diff --git a/.github/workflows/install-test.yml b/.github/workflows/install-test.yml index 495f6523..57a28eef 100644 --- a/.github/workflows/install-test.yml +++ b/.github/workflows/install-test.yml @@ -13,6 +13,8 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get install -y libev-dev libuv1-dev - name: make gcc install run: make BUILD_TYPE=Release INSTALL_PREFIX=/tmp/install-gcc tests-install-gcc-native - name: make clang install diff --git a/3rdparty/libwebsockets/CMakeLists-implied-options.txt b/3rdparty/libwebsockets/CMakeLists-implied-options.txt index 1675c693..c8137af3 100644 --- a/3rdparty/libwebsockets/CMakeLists-implied-options.txt +++ b/3rdparty/libwebsockets/CMakeLists-implied-options.txt @@ -47,7 +47,7 @@ if (LWS_PLAT_OPTEE) set(LWS_WITH_UDP 0) endif() -if (LWS_PLAT_FREERTOS) +if (LWS_PLAT_FREERTOS OR (${CMAKE_SYSTEM_NAME} MATCHES "QNX")) message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") set(LWS_WITH_DIR OFF) set(LWS_WITH_LEJP_CONF OFF) @@ -101,6 +101,8 @@ if(LWS_WITH_DISTRO_RECOMMENDED) set(LWS_WITH_PLUGINS_BUILTIN 1) # selfcontained set(LWS_ROLE_RAW_PROXY 1) # selfcontained set(LWS_WITH_GENCRYPTO 1) # selfcontained / tls + set(LWS_WITH_CBOR 1) # selfcontained + set(LWS_WITH_COSE 1) # selfcontained set(LWS_WITH_JOSE 1) # selfcontained set(LWS_WITH_STRUCT_JSON 1) # selfcontained set(LWS_WITH_STRUCT_SQLITE3 1) # sqlite3 diff --git a/3rdparty/libwebsockets/CMakeLists.txt b/3rdparty/libwebsockets/CMakeLists.txt index b1576428..166d48a4 100644 --- a/3rdparty/libwebsockets/CMakeLists.txt +++ b/3rdparty/libwebsockets/CMakeLists.txt @@ -63,18 +63,39 @@ if (ESP_PLATFORM) endif() # it's at this point any toolchain file is brought in -project(libwebsockets C CXX) +project(libwebsockets C) +if (LWS_WITH_SECURE_STREAMS_CPP) + enable_language(CXX) +endif() include(CTest) if (ESP_PLATFORM) include_directories( - ${IDF_PATH}/components/freertos/port/xtensa/include/ - ${IDF_PATH}/components/hal/include - ${IDF_PATH}/components/soc/${CONFIG_IDF_TARGET}/include/ - ${IDF_PATH}/components/soc/include/ - ${IDF_PATH}/components/esp_hw_support/include - ${IDF_PATH}/components/hal/${CONFIG_IDF_TARGET}/include/ - ) + $ENV{IDF_PATH}/components/esp_hw_support/include/soc/ + $ENV{IDF_PATH}/components/freertos/include/ + $ENV{IDF_PATH}/components/freertos/esp_additions/include/ + $ENV{IDF_PATH}/components/freertos/esp_additions/include/freertos/ + $ENV{IDF_PATH}/components/freertos/FreeRTOS-Kernel/include/ + $ENV{IDF_PATH}/components/freertos/FreeRTOS-Kernel/portable/linux/include/ + $ENV{IDF_PATH}/components/xtensa/${CONFIG_IDF_TARGET}/include/ + $ENV{IDF_PATH}/components/freertos/include/esp_additions + $ENV{IDF_PATH}/components/hal/include + $ENV{IDF_PATH}/components/soc/${CONFIG_IDF_TARGET}/include/ + $ENV{IDF_PATH}/components/soc/include/ + $ENV{IDF_PATH}/components/esp_hw_support/include + $ENV{IDF_PATH}/components/hal/${CONFIG_IDF_TARGET}/include/ + ) + + if (CONFIG_IDF_TARGET_ARCH_RISCV) + include_directories( + $ENV{IDF_PATH}/components/freertos/port/riscv/include + $ENV{IDF_PATH}/components/riscv/include) + else() + include_directories( + $ENV{IDF_PATH}/components/freertos/port/xtensa/include + $ENV{IDF_PATH}/components/xtensa/include) + endif() + endif() @@ -139,6 +160,8 @@ option(LWS_WITH_SECURE_STREAMS_PROXY_API "Secure Streams support to work across 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) option(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4 "Secure Streams Auth support for AWS Sigv4" OFF) +option(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP "Secure Streams protocol buffer dump" OFF) +option(LWS_WITH_SS_DIRECT_PROTOCOL_STR "Secure Streams directly set/get metadata w/o policy" OFF) # # CTest options @@ -159,11 +182,12 @@ option(LWS_WITH_SSL "Include SSL support (defaults to OpenSSL or similar, mbedTL option(LWS_WITH_MBEDTLS "Use mbedTLS (>=2.0) replacement for OpenSSL. When setting this, you also may need to specify LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS" OFF) option(LWS_WITH_BORINGSSL "Use BoringSSL replacement for OpenSSL" OFF) option(LWS_WITH_CYASSL "Use CyaSSL replacement for OpenSSL. When setting this, you also need to specify LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS" OFF) -option(LWS_WITH_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF) +option(LWS_WITH_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also may need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF) option(LWS_SSL_CLIENT_USE_OS_CA_CERTS "SSL support should make use of the OS-installed CA root certs" ON) option(LWS_TLS_LOG_PLAINTEXT_RX "For debugging log the received plaintext as soon as decrypted" OFF) option(LWS_TLS_LOG_PLAINTEXT_TX "For debugging log the transmitted plaintext just before encryption" OFF) option(LWS_WITH_TLS_SESSIONS "Enable persistent, resumable TLS sessions" ON) +option(LWS_WITH_TLS_JIT_TRUST "Enable dynamically computing which trusted TLS CA is needed to be instantiated" OFF) # # Event library options (may select multiple, or none for default poll() @@ -195,7 +219,7 @@ option(LWS_WITH_STATIC "Build the static version of the library" ON) option(LWS_WITH_SHARED "Build the shared version of the library" ON) option(LWS_LINK_TESTAPPS_DYNAMIC "Link the test apps to the shared version of the library. Default is to link statically" OFF) option(LWS_STATIC_PIC "Build the static version of the library with position-independent code" OFF) -option(LWS_SUPPRESS_DEPRECATED_API_WARNINGS "Turn off complaints about, eg, openssl deprecated api usage" OFF) +option(LWS_SUPPRESS_DEPRECATED_API_WARNINGS "Turn off complaints about, eg, openssl 3 deprecated api usage" ON) # # Specific platforms @@ -210,11 +234,11 @@ option(LWS_PLAT_ANDROID "Android flavour of unix platform" OFF) # option(LWS_WITHOUT_CLIENT "Don't build the client part of the library" OFF) option(LWS_WITHOUT_SERVER "Don't build the server part of the library" OFF) -option(LWS_WITHOUT_TESTAPPS "Don't build the libwebsocket-test-apps" ON) -option(LWS_WITHOUT_TEST_SERVER "Don't build the test server" ON) -option(LWS_WITHOUT_TEST_SERVER_EXTPOLL "Don't build the test server version that uses external poll" ON) -option(LWS_WITHOUT_TEST_PING "Don't build the ping test application" ON) -option(LWS_WITHOUT_TEST_CLIENT "Don't build the client test application" ON) +option(LWS_WITHOUT_TESTAPPS "Don't build the libwebsocket-test-apps" OFF) +option(LWS_WITHOUT_TEST_SERVER "Don't build the test server" OFF) +option(LWS_WITHOUT_TEST_SERVER_EXTPOLL "Don't build the test server version that uses external poll" OFF) +option(LWS_WITHOUT_TEST_PING "Don't build the ping test application" OFF) +option(LWS_WITHOUT_TEST_CLIENT "Don't build the client test application" OFF) # # Extensions (permessage-deflate) # @@ -228,6 +252,8 @@ option(LWS_WITHOUT_BUILTIN_SHA1 "Don't build the lws sha-1 (eg, because openssl option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" ON) option(LWS_SSL_SERVER_WITH_ECDH_CERT "Include SSL server use ECDH certificate" OFF) option(LWS_WITH_LEJP "With the Lightweight JSON Parser" ON) +option(LWS_WITH_CBOR "With the Lightweight LECP CBOR Parser" OFF) +option(LWS_WITH_CBOR_FLOAT "Build floating point types if building CBOR LECP" ON) option(LWS_WITH_SQLITE3 "Require SQLITE3 support" OFF) option(LWS_WITH_STRUCT_JSON "Generic struct serialization to and from JSON" OFF) option(LWS_WITH_STRUCT_SQLITE3 "Generic struct serialization to and from SQLITE3" OFF) @@ -246,7 +272,8 @@ set(LWS_LOGGING_BITFIELD_CLEAR 0 CACHE STRING "Bitfield describing which log lev option(LWS_LOGS_TIMESTAMP "Timestamp at start of logs" ON) option(LWS_LOG_TAG_LIFECYCLE "Log tagged object lifecycle as NOTICE" ON) option(LWS_AVOID_SIGPIPE_IGN "Android 7+ reportedly needs this" OFF) -option(LWS_WITH_JOSE "JSON Web Signature / Encryption / Keys (RFC7515/6/) API" OFF) +option(LWS_WITH_JOSE "JOSE JSON Web Signature / Encryption / Keys (RFC7515/6/) API" OFF) +option(LWS_WITH_COSE "COSE CBOR Signature / Encryption / Keys (RFC8152) API" OFF) option(LWS_WITH_GENCRYPTO "Enable support for Generic Crypto apis independent of TLS backend" OFF) option(LWS_WITH_SELFTESTS "Selftests run at context creation" OFF) option(LWS_WITH_GCOV "Build with gcc gcov coverage instrumentation" OFF) @@ -255,13 +282,12 @@ option(LWS_REPRODUCIBLE "Build libwebsockets reproducible. It removes the build option(LWS_WITH_MINIMAL_EXAMPLES "Also build the normally standalone minimal examples, for QA" OFF) option(LWS_WITH_LWSAC "lwsac Chunk Allocation api" ON) 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_DISKCACHE "Hashed cache directory with lazy LRU deletion to size limit (unrelated to lws_cache_ttl)" OFF) option(LWS_WITH_ASAN "Build with gcc runtime sanitizer options enabled (needs libasan)" 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_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) @@ -275,6 +301,12 @@ option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include 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) option(LWS_WITH_CONMON "Collect introspectable connection latency stats on individual client connections" ON) +option(LWS_WITHOUT_EVENTFD "Force using pipe instead of eventfd" OFF) +if (UNIX OR WIN32) + option(LWS_WITH_CACHE_NSCOOKIEJAR "Build file-backed lws-cache-ttl that uses netscape cookie jar format (linux-only)" ON) +else() + option(LWS_WITH_CACHE_NSCOOKIEJAR "Build file-backed lws-cache-ttl that uses netscape cookie jar format (linux-only)" OFF) +endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") option(LWS_WITH_NETLINK "Monitor Netlink for Routing Table changes" ON) @@ -369,12 +401,16 @@ if(GIT_EXECUTABLE) message("Git commit hash: ${LWS_BUILD_HASH}") endif() +if ("${LWS_BUILD_HASH}" STREQUAL "") + set(LWS_BUILD_HASH "unknown") +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 "2") -set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "0") +set(CPACK_PACKAGE_VERSION_MINOR "3") +set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "2") set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) @@ -383,7 +419,7 @@ set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSIO 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 "18") +set(SOVERSION "19") if(NOT CPACK_GENERATOR) if(UNIX) set(CPACK_GENERATOR "TGZ") @@ -553,7 +589,14 @@ CHECK_FUNCTION_EXISTS(getgrgid_r LWS_HAVE_GETGRGID_R) CHECK_FUNCTION_EXISTS(getgrnam_r LWS_HAVE_GETGRNAM_R) CHECK_FUNCTION_EXISTS(getpwuid_r LWS_HAVE_GETPWUID_R) CHECK_FUNCTION_EXISTS(getpwnam_r LWS_HAVE_GETPWNAM_R) +CHECK_FUNCTION_EXISTS(timegm LWS_HAVE_TIMEGM) +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + if(CMAKE_OSX_DEPLOYMENT_TARGET LESS "10.12") + message("No clock_gettime found on macOS ${CMAKE_OSX_DEPLOYMENT_TARGET}. Disabling LWS_HAVE_CLOCK_GETTIME.") + set(LWS_HAVE_CLOCK_GETTIME 0) + endif() +endif() if (NOT LWS_HAVE_GETIFADDRS) if (LWS_WITHOUT_BUILTIN_GETIFADDRS) @@ -754,11 +797,19 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) # always warn all and generate debug info if (UNIX AND NOT LWS_PLAT_FREERTOS) - set(CMAKE_C_FLAGS "-Wall -Wconversion -Wsign-compare -Wstrict-aliasing ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) + set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wconversion -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() + if (PICO_SDK_PATH) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wconversion -Wsign-compare -Wstrict-aliasing -Wundef -nolibc") + endif() + + if (ESP_PLATFORM AND (CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S2 OR CONFIG_IDF_TARGET_ESP32S3)) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlongcalls") + endif() + if ("${DISABLE_WERROR}" STREQUAL "OFF") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") endif() @@ -800,6 +851,12 @@ if (MSVC) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) # Fail the build if any warnings add_compile_options(/W3 /WX) + # Unbreak MSVC broken preprocessor __VA_ARGS__ behaviour + if (MSVC_VERSION GREATER 1925) + add_compile_options(/Zc:preprocessor /wd5105) + else() + add_compile_options(/experimental:preprocessor /wd5105) + endif() endif(MSVC) if (MINGW) @@ -829,7 +886,7 @@ 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_INCLUDE_DIRS ${MINIZ_INCLUDE_DIR}) set(ZLIB_LIBRARIES ${MINIZ_LIBRARIES}) else() find_package(ZLIB REQUIRED) @@ -1017,6 +1074,9 @@ file(RELATIVE_PATH if (DEFINED REL_INCLUDE_DIR) set(LWS__INCLUDE_DIRS "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") endif() +if (DEFINED OPENSSL_INCLUDE_DIRS) + set(LWS__INCLUDE_DIRS "${LWS__INCLUDE_DIRS};${OPENSSL_INCLUDE_DIRS}") +endif() configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake diff --git a/3rdparty/libwebsockets/LICENSE b/3rdparty/libwebsockets/LICENSE index b3c9edbb..917f8dcf 100644 --- a/3rdparty/libwebsockets/LICENSE +++ b/3rdparty/libwebsockets/LICENSE @@ -6,10 +6,12 @@ them. Original liberal license retained: - - lib/misc/sha-1.c - 3-clause BSD license retained, link to original - - win32port/zlib - ZLIB license (see zlib.h) - - lib/tls/mbedtls/wrapper - Apache 2.0 (only built if linked against mbedtls) - - lib/misc/base64-decode.c - already MIT + - lib/misc/sha-1.c - 3-clause BSD license retained, link to original [BSD3] + - win32port/zlib - ZLIB license (see zlib.h) [ZLIB] + - lib/tls/mbedtls/wrapper - Apache 2.0 (only built if linked against mbedtls) [APACHE2] + lib/tls/mbedtls/mbedtls-extensions.c + - lib/misc/base64-decode.c - already MIT + - lib/misc/ieeehalfprecision.c - 2-clause BSD license retained [BSD2] Relicensed to MIT: @@ -32,7 +34,7 @@ we are very hot on cleaning and refactoring the codebase). The least painful and lowest risk way remains sending your changes and fixes upstream to us so you can easily use later releases and fixes. -MIT License applied to libwebsockets: +## MIT License applied to libwebsockets https://opensource.org/licenses/MIT @@ -54,3 +56,156 @@ https://opensource.org/licenses/MIT FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## BSD2 + +``` + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +``` + +## BSD3 + +For convenience, a copy of the license on `./lib/misc/sha-1.c`. In binary +distribution, this applies to builds with ws support enabled, and without +`LWS_WITHOUT_BUILTIN_SHA1` at cmake. + +``` +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH +``` + +## ZLIB + +For convenience, a copy of the license on zlib. In binary distribution, +this applies for win32 builds with internal zlib only. You can avoid +building any zlib usage or copy at all with `-DLWS_WITH_ZLIB=0` (the +default), and so avoid needing to observe the license for binary +distribution that doesn't include the related code. + +``` + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu +``` + + +## APACHE2 + +For convenience, a copy of the license on the mbedtls wrapper part. In binary +distribution, this applies only when building lws against mbedtls. + +The canonical license application to source files uses the URL reference, so the +whole is not reproduced here. + +``` +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +``` + +## CC0 + +For convenience,the full text of CC0 dedication found on the lws examples. +The intention of this is to dedicate the examples to the public domain, so +users can build off and modify them without any constraint. + +``` +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + moral rights retained by the original author(s) and/or performer(s); + publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + rights protecting the extraction, dissemination, use and reuse of data in a Work; + database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. +``` + diff --git a/3rdparty/libwebsockets/README.md b/3rdparty/libwebsockets/README.md index 2013f436..552603f3 100644 --- a/3rdparty/libwebsockets/README.md +++ b/3rdparty/libwebsockets/README.md @@ -8,442 +8,43 @@ lightweight, configurable, scalable and flexible way. It's easy to build and cross-build via cmake and is suitable for tasks from embedded RTOS through mass cloud serving. -[80 independent minimal examples](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples) for -various scenarios, CC0-licensed (public domain) for cut-and-paste, allow you to get started quickly. +It supports a lot of lightweight ancilliary implementations for things like JSON, +CBOR, JOSE, COSE, and supports OpenSSL and MbedTLS v2 and v3 out of the box for everything. +It's very gregarious when it comes to event loop sharing, supporting libuv, libevent, libev, +sdevent, glib and uloop, as well as custom event libs. -![overview](./doc-assets/lws-overview.png) - -News ----- - -## Transition from master branch to main branch - -"master" branch was just the default branch name from git originally, it was not selected -for lws to have any semantic value in itself. There's no problem changing it to the more -universally neutral "main" other than any explicit references spread around over the last -10 years to "master" breaking, which can be managed. - -As a first step, I updated my push scripts, that keep libwebsockets.org git and the github -mirror in sync, to push stuff on "master" also to "main" branch to establish it. If you -currently refer to "master" branch in lws for build or CI, you should switch to using -"main". - -For the next months the two should run in parallel and I'll move over references to -"master" in lws docs to use "main", eventually some point after the next release, -master will be deleted. - -In github, I changed its default branch for libwebsockets to "main", since main and -master are updated in lockstep currently, this should hopefully have limited impact. - -## 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 -at any given time. - -See the [changelog](https://libwebsockets.org/git/libwebsockets/tree/changelog) for -information on the huge amount of new features in this release, and additional information -below. - -``` - - NEW: Lws is now under the MIT license, see ./LICENSE for details - - - NEW: GLIB native event loop support, lws + gtk example - - - NEW: native lws MQTT client... supports client stream binding like h2 when - multiple logical connections are going to the same endpoint over MQTT, they - transparently and independently share the one connection + tls tunnel - - - NEW: "Secure Streams"... if you are making a device with client connections - to the internet or cloud, this allows separation of the communications - policy (endpoints, tls cert validation, protocols, etc) from the code, with - the goal you can combine streams, change protocols and cloud provision, and - reflect that in the device's JSON policy document without having to change - any code. - - - NEW: lws_system: New lightweight and efficient Asynchronous DNS resolver - implementation for both A and AAAA records, supports recursive (without - recursion in code) lookups, caching, and getaddrinfo() compatible results - scheme (from cache directly without per-consumer allocation). Able to - perform DNS lookups without introducing latency in the event loop. - - - NEW: lws_system: ntpclient implementation with interface for setting system - time via lws_system ops - - - NEW: lws_system: dhcpclient implementation - - - NEW: Connection validity tracking, autoproduce PING/PONG for protocols that - support it if not informed that the connection has passed data in both - directions recently enough - - - NEW: lws_retry: standardized exponential backoff and retry timing based - around backoff table and lws_sul - - - NEW: there are official public helpers for unaligned de/serialization of all - common types, see eh, lws_ser_wu16be() in include/libwebsockets/lws-misc.h - - - NEW: lws_tls_client_vhost_extra_cert_mem() api allows attaching extra certs - to a client vhost from DER in memory - - - NEW: lws_system: generic blobs support passing auth tokens, per-connection - client certs etc from platform into lws - - - NEW: public helpers to consume and produce ipv4/6 addresses in a clean way, - along with lws_sockaddr46 type now public. See eg, lws_sockaddr46-based - lws_sa46_parse_numeric_address(), lws_write_numeric_address() - in include/libwebsockets/lws-network-helper.h - - - Improved client redirect handling, h2 compatibility - - - NEW: lwsac: additional features for constant folding support (strings that - already are in the lwsac can be pointed to without copying again), backfill - (look for gaps in previous chunks that could take a new use size), and - lwsac_extend() so last use() can attempt to use more unallocated chunk space - - - NEW: lws_humanize: apis for reporting scalar quanties like 1234 as "1.234KB" - with the scaled symbol strings passed in by caller - - - NEW: freertos: support lws_cancel_service() by using UDP pair bound to lo, - since it doesn't have logical pipes - - - NEW: "esp32" plat, which implemented freertos plat compatibility on esp32, is - renamed to "freertos" plat, targeting esp32 and other freertos platforms - - - NEW: base64 has an additional api supporting stateful decode, where the input - is not all in the same place at the same time and can be processed - incrementally - - - NEW: lws ws proxy: support RFC8441 - - - NEW: lws_spawn_piped apis: generic support for vforking a process with child - wsis attached to its stdin, stdout and stderr via pipes. When processes are - reaped, a specified callback is triggered. Currently Linux + OSX. - - - NEW: lws_fsmount apis: Linux-only overlayfs mount and unmount management for - aggregating read-only layers with disposable, changeable upper layer fs - - - Improvements for RTOS / small build case bring the footprint of lws v4 below - that of v3.1 on ARM - - - lws_tokenize: flag specifying # should mark rest of line as comment - - - NEW: minimal example for integrating libasound / alsa via raw file - - - lws_struct: sqlite and json / lejp translation now usable - - -``` - -## Introducing Secure Streams client support - -Secure Streams is an optional layer above lws (`-DLWS_WITH_SECURE_STREAMS=1`) that -separates connectivity policy into a JSON document, which can be part of the -firmware or fetched at boot time. - -Code no longer deals with details like endpoint specification or tls cert stack used -to validate the remote server, it's all specified in JSON, eg, see -[this example](https://warmcat.com/policy/minimal-proxy.json). Even the protocol to use to talk to the -server, between h1, h2, ws or MQTT, is specified in the policy JSON and the code -itself just deals with payloads and optionally metadata, making it possible to -switch endpoints, update certs and even switch communication protocols by just -editing the JSON policy and leaving the code alone. +[100+ independent minimal examples](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples) for various scenarios, CC0-licensed +(public domain) for cut-and-paste, allow you to get started quickly. -Logical Secure Stream connections outlive any underlying lws connection, and support -"nailed-up" connection reacquisition and exponential backoff management. +[There are a lot of READMEs](https://libwebsockets.org/git/libwebsockets/tree/READMEs) on a variety of topics. -See [./lib/secure-streams/README.md](https://libwebsockets.org/git/libwebsockets/tree/lib/secure-streams/README.md) and the related minimal examples -for more details. +[We do a huge amount of CI testing per push](https://libwebsockets.org/sai/), currently 582 builds on 30 platforms. +[You can see the lws CI rack and read about how lws-based Sai is used to coordinate all the testing](https://warmcat.com/2021/08/21/Sai-CI.html). -## mqtt client support - -If you enable `-DLWS_ROLE_MQTT=1`, lws can now support QoS0 and QoS1 MQTT client -connections. See the examples at ./minimal-examples/mqtt-client - -## libglib native event loop support - -glib's event loop joins libuv, libevent and libev support in lws for both the -`lws_context` creating and owning the loop object for its lifetime, and for -an already-existing "foreign loop" where the `lws_context` is created, attaches, -detaches, and is destroyed without affecting the loop. - -This allows direct, lock-free integration of lws functionality with, eg, a GTK app's -existing `GMainLoop` / glib `g_main_loop`. Just select `-DLWS_WITH_GLIB=1` at cmake -time to enable. The -eventlib minimal examples also support --glib option to -select using the glib loop at runtime. - -There's also a gtk example that is built if lws cmake has `-DLWS_WITH_GTK=1`. - -## `lws_system` helper for attaching code to a single event loop from another thread - -`lws_system` ops struct now has a member that enables other threads (in the -same process) to request a callback they define from the lws event loop thread -context as soon as possible. From here, in the event loop thread context, -they can set up their lws functionality before returning and letting it -operate wholly from the lws event loop. The original thread calling the -api to request the callback returns immediately. - -## Improvements on tx credit - -H2 clients and servers can now modulate RX flow control on streams precisely, -ie, define the size of the first incoming data and hand out more tx credit -at timing of its choosing to throttle or completely quench the remote server -sending as it likes. - -The only RFC-compatible way to acheive this is set the initial tx credit to -0 and set it explicitly when sending the headers... client code can elect to -do this rather than automatically manage the credit by setting a new flag -LCCSCF_H2_MANUAL_RXFLOW and indicating the initial tx credit for that stream -in client connection info member manual_initial_tx_credit. A new public api -lws_wsi_tx_credit() allows dynamic get and add to local and estimated remote -peer credit for a connection. This api can be used without knowing if the -underlying connection is h2 or not. - -## `lws_system`: DHCP client - -DHCP client is now another network service that can be integrated into lws, with -`LWS_WITH_SYS_DHCP_CLIENT` at CMake. When enabled, the `lws_system` state -is held at `DHCP` until at least one registered network interface acquires a -usable set of DHCP information including ip, subnet mask, router / gateway -address and at least one DNS server. - -See the [api-test-dhcp](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/api-tests/api-test-dhcpc) Minimal Example for how to use. - -## UDP integration with `lws_retry` - -UDP support in lws has new helper that allow `lws_retry` to be applied for retry, -and the ability to synthesize rx and tx udp packetloss systemwide to confirm -retry strategies. Since multiple transactions may be in flight on one UDP -socket, the support relies on an `lws_sul` in the transaction object to manage -the transaction retries individually. - -See `READMEs/README.udp.md` for details. - -## `lws_system`: system state and notification handlers - -Lws now has the concept of systemwide state held in the context... this is to -manage that there may be multiple steps that need the network before it's possible -for the user code to operate normally. The steps defined are - -`CONTEXT_CREATED`, `INITIALIZED`, `IFACE_COLDPLUG`, `DHCP`, `TIME_VALID`, `POLICY_VALID`, -`REGISTERED`, `AUTH1`, `AUTH2`, `OPERATIONAL` and `POLICY_INVALID`. OPERATIONAL is the -state where user code can run normally. - -User and other parts of lws can hook notifier callbacks to receive and be able to -veto system state changes, either definitively or because they have been triggered -to perform a step asynchronously and will move the state on themselves when it -completes. - -By default just after context creation, lws attempts to move straight to OPERATIONAL. -If no notifier interecepts it, it will succeed to do that and operate in a -backwards-compatible way. Enabling various features like lws ntpclient also enable -notifiers that hold progress at the related state until their operation completes -successfully, eg, not able to enter `TIME_VALID` until ntpclient has the time. - -See `READMEs/README.lws_system.md` for details. - -## `lws_system`: HAL ops struct - -Lws allows you to define a standardized ops struct at context creation time so your -user code can get various information like device serial number without embedding -system-specific code throughout the user code. It can also perform some generic -functions like requesting a device reboot. - -See `READMEs/README.lws_system.md` for details. - -## `lws_system`: ntpclient - -Optional lws system service enabled by cmake `-DLWS_WITH_SYS_NTPCLIENT` intercepts -the `lws_system` `TIME_VALID` state and performs ntpclient to get the date and time -before entering `TIME_VALID`. This allows user code to validate tls certificates -correctly knowing the current date and time by the time it reached OPERATIONAL. - -## Connection Validity tracking - -Lws now allows you to apply a policy for how long a network connection may go -without seeing something on it that confirms it's still valid in the sense of -passing traffic cohernetly both ways. There's a global policy in the context -which defaults to 5m before it produces a PING if possible, and 5m10 before -the connection will be hung up, user code can override this in the context, -vhost (for server) and client connection info (for client). - -An api `lws_validity_confirmed(wsi)` is provided so user code can indicate -that it observed traffic that must mean the connection is passing traffic in -both directions to and from the peer. In the absence of these confirmations -lws will generate PINGs and take PONGs as the indication of validity. - -## `lws_system`: Async DNS support - -Master now provides optional Asynchronous (ie, nonblocking) recursive DNS resolving. -Enable with `-DLWS_WITH_SYS_ASYNC_DNS=1` at cmake. This provides a quite -sophisticated ipv4 + ipv6 capable resolver that autodetects the dns server on -several platforms and operates a UDP socket to its port 53 to produce and parse DNS -packets from the event loop. And of course, it's extremely compact. - -It broadly follows the getaddrinfo style api, but instead of creating the results -on the heap for each caller, it caches a single result according to the TTL and -then provides refcounted const pointers to the cached result to callers. While -there are references on the cached result it can't be reaped. - -See `READMEs/README.async-dns.md` for detailed information on how it works, along -with `api-tests/api-test-async-dns` minimal example. - -## Detailed Latency - -You can now opt to measure and store us-resolution statistics on effective -latencies for client operations, and easily spool them to a file in a -format suitable for gnuplot, or handle in your own callback. Enable -`-DLWS_WITH_DETAILED_LATENCY=1` in cmake to build it into lws. (NB 2021-01-12 -this has been replaced by the lws_metrics support) - -If you are concerned about operation latency or potential blocking from -user code, or behaviour under load, or latency variability on specific -platforms, you can get real numbers on your platform using this. - -Timings for all aspects of events on connections are recorded, including -the time needed for name resolution, setting up the connection, tls -negotiation on both client and server sides, and each read and write. - -See `READMEs/README.detailed-latency.md` for how to use it. - -## Client connection logic rewrite - -Lws now makes much better use of the DNS results for ipv4 and ipv6... it -will iterate through them automatically making the best use it can of what's -provided and attempting new connections for each potentially usable one in turn -before giving up on the whole client connection attempt. - -If ipv6 is disabled at cmake it can only use A / ipv4 records, but if ipv6 is -enabled, it tries both; if only ipv6 is enabled it promotes ipv4 to -::ffff:1.2.3.4 IPv4-in-IPv6 addresses. - -## New network helpers for ipv4 and ipv6 - -An internal union `lws_sockaddr46` that combines `struct sockaddr_in` and -`struct sockaddr_in6` is now public, and there are helpers that can parse (using -`lws_tokenize`) any valid numeric representation for ipv4 and ipv6 either -into byte arrays and lengths, or directly to and from `lws_sockaddr46`. - -## h2 long poll support +![overview](./doc-assets/lws-overview.png) -Lws now supports the convention that half-closing an h2 http stream may make -the stream 'immortal', in terms of not being bound by normal timeouts. For -the client side, there's an api that can be applied to the client stream to -make it transition to this "read-only" long poll mode. +News +---- -See `READMEs/README.h2-long-poll.md` for full details, including how to test -it with the minimal examples. +## v4.3 is released -## h1 client parser improvements +See the [changelog](https://libwebsockets.org/git/libwebsockets/tree/changelog) -H1 is not so simple to parse because the header length is not known until it -has been fully parsed. The next header, or http body may be directly coalesced -with the header as well. Lws has supported bulk h1 parsing from a buffer for a -long time, but on clientside due to interactions with http proxying it had -been stuck parsing the header bytewise out of the tls buffer. Now, -everything now bulk parses from a buffer and uses a buflist to pass leftovers -through the event loop cleanly. -## `lws_sul` time refactor +## Lws work retrospective -Just before v3.2 there was a big refactor about how lws handles time. It now -explicitly schedules anything that may happen in the future on a single, sorted -linked-list, at us resolution. When entering a poll wait (or returning to an -event lib loop) it checks the interval between now and the earliest event on the -list to figure out how long to wait if there are no network events. For the -event loop case, it sets a native event lib timer to enforce it. +The initial commit for lws will have been 11 years ago come Oct 28 2021, it's been a lot of work. +There are a total of 4.3K patches, touching 800KLOC cumulatively (this is not the size in the +repo, but over the years, how many source lines were changed by patches). -See `READMEs/README.lws_sul.md` for more details and a handy api where you can -schedule your own arbitrary callbacks using this system. +![overview](./doc-assets/work.png) -## Master is now MIT-licensed +Gratifyingly, it turns out over the years, ~15% of that was contributed by 404 contributors: that's not so bad. +Thanks a lot to everyone who has provided patches. -Libwebsockets is now under the MIT license. See ./LICENSE. +Today at least tens of millions of devices and product features rely on lws to +handle their communications including several from FAANG; Google now include lws +as part of Android sources. ## Support @@ -460,5 +61,5 @@ You can get the latest version of the library from git: - https://libwebsockets.org/git -Doxygen API docs for development: https://libwebsockets.org/lws-api-doc-master/html/index.html +Doxygen API docs for development: https://libwebsockets.org/lws-api-doc-main/html/index.html diff --git a/3rdparty/libwebsockets/READMEs/README.cbor-cose.md b/3rdparty/libwebsockets/READMEs/README.cbor-cose.md new file mode 100644 index 00000000..baa9d7df --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.cbor-cose.md @@ -0,0 +1,272 @@ +# RFC8152 COSE apis + +||| +|---|---|---| +|cmake| `LWS_WITH_COSE`| +|Header| ./include/libwebsockets/lws-cose.h| +|api-test| ./minimal-examples/api-tests/api-test-cose/| +|README| ./READMEs/README.cbor-cose.md + +COSE is the CBOR equivalent of the JOSE suite of crypto objects and operations. +You can represent public and private EC, RSA and SYMMETRIC keys, and sets of +keys of various types; import the logical keys to and from CBOR; and sign / +verify and encrypt / decrypt payloads using structured CBOR. Key generation is +also supported. + +|type|operations|algs| +|---|---|---| +|lws_cose_key_t|import, export, generation|EC / RSA / SYMMETRIC| +|cose_sign1|sign, validate|ES256/384/512, RS256/384/512| +|cose_sign|sign, validate|ES256/384/512, RS256/384/512| +|cose_mac0|sign, validate|HS256/HS256_64/384/512| +|cose_mac|validate only|HS256/HS256_64/384/512| + +The lws COSE support uses the lws gencrypto layer, which calls through to the +tls crypto library, and so works on both OpenSSL and mbedTLS the same. + +An increasing number of higher-level IETF specifications use COSE underneath. + +## cose_key and sets + +Lws provides an `lws_cose_key_t` object to contain a single key's metadata and +key material for EC, RSA and SYMMETRIC key types. + +There is a commandline tool wrapping the key dumping and generation apis +available at `./minimal-examples/crypto/lws-crypto-cose-key` + +### cose_key and sets import from CBOR and destroying + +``` +lws_cose_key_t * +lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb, + void *user, const uint8_t *in, size_t len); +void +lws_cose_key_destroy(lws_cose_key_t **ck); + +void +lws_cose_key_set_destroy(lws_dll2_owner_t *o); +``` + +To convert a single key, `pkey_set` should be NULL and the created key will be +returned, for a cose_key set, which is simply a CBOR array of cose_keys, it +should be a prepared (ie, zero'd down if nothing in it) lws_dll2_owner_t that +will contain the resulting list of `lws_cose_key_t` objects that were created. +In both cases the return is NULL if there was a fatal error and anything created +has been cleaned up, the return has no other meaning in the cose_key set case. + +`lws_cose_key_destroy()` destroys a single `lws_cose_key_t` and sets the +contents of the pointer to NULL, for cose_key sets you instead pass a pointer to +the owner object to `lws_cose_key_set_destroy()` to destroy all the keys in the +set in one step. + +cose_key has some confusions about type, kty and alg may be either ints, +representing well-known standardized key and alg types, or freeform strings. +We convert the well-known ints to their string representations at import, so +there can be no confusion later. + +### cose_key generation + +``` +lws_cose_key_t * +lws_cose_key_generate(struct lws_context *context, int cose_kty, int use_mask, + int bits, const char *curve, const char *kid); +``` + +This creates an `lws_cose_key_t`, generates a key (SYMMETRIC) or keypair into +it and returns a pointer to it. + +`cose_kty` is one of `LWSCOSE_WKKTV_OKP`, `LWSCOSE_WKKTV_EC2`, `LWSCOSE_WKKTV_RSA`, +or `LWSCOSE_WKKTV_SYMMETRIC`. `bits` is valid for RSA keys and for EC keys, +`curve` should be a well-known curve name, one of `P-256`, `P-384` and `P-521` +currently. `use_mask` is a bitfield made up of (1 << LWSCOSE_WKKO_...) set to +enable the usage on the key. + +### cose_key export to CBOR + +The export api uses the same CBOR write context as `lws_lec_printf()` uses to +emit the key into an output buffer. Like the CBOR output apis, it may return +`LWS_LECPCTX_RET_AGAIN` to indicate it filled the buffer and should be called +again to fill another buffer. `lws_lec_init()` should be used to prepare the +write context and `lws_lec_setbuf()` to reset the output buffer on subsequent +calls, exactly the same as the CBOR write apis. + +``` +enum lws_lec_pctx_ret +lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags); +``` + +`flags` may be 0 to only output the public key pieces, or `LWSJWKF_EXPORT_PRIVATE` +to output everything. + +## Signing and signature validation + +COSE specifies three kinds of signed object, `cose_sign1` which signs a payload +with a single algorithm and key, `cose_sign` which may sign a payload with +multiple algorithms and keys, and `countersign`. + +`cose_sign1` has the advantage it can be validated with a single pass through +the signed object; `cose_sign` unfortunately specifies the parameters of the +signatures after the payload and must be done with multiple passes through the +payload, for inline payloads, by caching it in heap. + +`cose_sign` and `cose_sign1` objects are supported by lws, Countersigned +objects are not yet supported. + +`cose_mac0` is supported using HMAC for signing and validation, `cose_mac` is +only supported for validation. + +There is a commandline tool wrapping the signing and validation apis +available at `./minimal-examples/crypto/lws-crypto-cose-sign` + +### Signature validation + +Signature validation does not have to be done synchronously, to facilitate this +first you create a validation context specifying the type (eg, `SIGTYPE_SINGLE`) +and a keyset of public keys the signature might use to validate (notice even a +single key is passed in an lws_dll2_owner_t keyset). + +Creation uses a public `lws_cose_validate_create_info_t` info struct + +``` +typedef struct lws_cose_validate_create_info { + struct lws_context *cx; + /**< REQUIRED: the lws context */ + lws_dll2_owner_t *keyset; + /**< REQUIRED: one or more cose_keys */ + + enum lws_cose_sig_types sigtype; + /**< 0 if a CBOR tag is in the sig, else one of SIGTYPE_MULTI, + * SIGTYPE_SINGLE, etc*/ + + lws_cose_validate_pay_cb_t pay_cb; + /**< optional: called back with unvalidated payload pieces */ + void *pay_opaque; + /**< optional: passed into pay_cb callback along with payload chunk */ + + lws_cose_sign_ext_pay_cb_t ext_cb; + /**< optional extra application data provision callback */ + void *ext_opaque; + /**< optional extra application data provision callback opaque */ + size_t ext_len; + /**< if we have extra app data, this must be set to the length of it */ +} lws_cose_validate_create_info_t; +``` + +``` +struct lws_cose_validate_context * +lws_cose_validate_create(const lws_cose_validate_create_info_t *info); + +void +lws_cose_validate_destroy(struct lws_cose_validate_context **cps); +``` + +after that as pieces of the signature CBOR become available, they can be +processed by the validation context + +``` +int +lws_cose_validate_chunk(struct lws_cose_validate_context *cps, + const uint8_t *in, size_t in_len, size_t *used_in); +``` + +The parsing of the signature yields a list of result objects indicating +information about each signature it encountered and whether it was validated or +not. The parsing itself only fails if there is an unrecoverable error, the +completion of parsing does not indicate validation, it may yield zero or more +result objects indicating the validation failed. + +``` +lws_dll2_owner_t * +lws_cose_validate_results(struct lws_cose_validate_context *cps); + +typedef struct { + lws_dll2_t list; + + const lws_cose_key_t *cose_key; + cose_param_t cose_alg; + + int result; /* 0 = validated */ + +} lws_cose_validate_res_t; +``` + +It's like this because for multiple signatures, we may only have keys for some +of them, and we may have different policies for validation that can only be +assessed as a whole, eg, we may inisit that signatures pass with specific +algorithms, or all signatures for specific keys must be present and pass. This +way user code can assess the situation after the signature parsing and make its +decision about overall validity according to its own policies. + +## Signing + +Signing is again done by creating a signing context using an info struct to pass +in the paramter (a `lws_cose_sign_create_info_t`). + +``` +#define LCSC_FL_ADD_CBOR_TAG (1 << 0) +#define LCSC_FL_ADD_CBOR_PREFER_MAC0 (1 << 1) + +typedef struct lws_cose_sign_create_info { + struct lws_context *cx; + /**< REQUIRED: the lws context */ + lws_dll2_owner_t *keyset; + /**< REQUIRED: one or more cose_keys */ + + lws_lec_pctx_t *lec; + /**< REQUIRED: the cbor output context to emit to, user must + * initialize with lws_lec_init() beforehand */ + + lws_cose_sign_ext_pay_cb_t ext_cb; + /**< optional extra application data provision callback */ + void *ext_opaque; + /**< optional extra application data provision callback opaque */ + size_t ext_len; + /**< if we have extra app data, this must be set to the length of it */ + + size_t inline_payload_len; + /**< REQUIRED: size of the inline payload we will provide */ + + int flags; + /**< bitmap of LCSC_FL_* */ + enum lws_cose_sig_types sigtype; + /**< 0, or sign type hint */ +} lws_cose_sign_create_info_t; +``` + +``` +struct lws_cose_sign_context * +lws_cose_sign_create(const lws_cose_sign_create_info_t *info); +``` + +After creating the signing context, you call `lws_cose_sign_add()` one or more +times to add algorithms and keys to sign with (since cose_sign allows multiple +recipients with the same payload signed in different ways). + +``` +int +lws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg, + const lws_cose_key_t *ck); +``` + +The payload does not have to be provided all at once and can be passed in chunk +by chunk over time via `lws_cose_sign_payload_chunk()`. + +Output is mediated via an lws CBOR output context provided in the info at +creation-time, it's only emitted during the `lws_cose_sign_payload_chunk()` +phase. If it returns `LWS_LECPCTX_RET_AGAIN`, you must call that api again +after using the CBOR output context data and resetting its buffer by +`lws_lec_setbuf()`, so it can continue to output. + +``` +enum lws_lec_pctx_ret +lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, + const uint8_t *in, size_t in_len); +``` + +Finally the signing context is destroyed. + +``` +void +lws_cose_sign_destroy(struct lws_cose_sign_context **csc); +``` + diff --git a/3rdparty/libwebsockets/READMEs/README.cbor-lecp.md b/3rdparty/libwebsockets/READMEs/README.cbor-lecp.md new file mode 100644 index 00000000..109dc0c8 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.cbor-lecp.md @@ -0,0 +1,344 @@ +# RFC8949 CBOR Stream Parsing and Writing + +||| +|---|---|---| +|cmake| `LWS_WITH_CBOR`, `LWS_WITH_CBOR_FLOAT`| +|Header| ./include/libwebsockets/lws-lecp.h| +|api-test| ./minimal-examples/api-tests/api-test-lecp/| +|test app| ./test-apps/test-lecp.c -> libwebsockets-test-lecp| + +LECP is the RFC8949 CBOR stream parsing counterpart to LEJP for JSON. + +## Features + + - Completely immune to input fragmentation, give it any size blocks of CBOR as + they become available; 1 byte, or 100K at a time give identical parsing + results + - Input chunks discarded as they are parsed, whole CBOR never needed in memory + - Nonrecursive, fixed stack usage of a few dozen bytes + - No heap allocations at all, just requires ~500 byte context usually on + caller stack + - Creates callbacks to a user-provided handler as members are parsed out + - No payload size limit, supports huge / endless strings or blobs bigger than + system memory + - Collates utf-8 text and blob payloads into a 250-byte chunk buffer for ease + of access + - Write apis don't use any heap allocations or recursion either + - Write apis use an explicit context with its own lifecycle, and printf style + vaargs including sized blobs, C strings, double, int, unsigned long etc + - Completely immune to output fragmentation, supports huge strings and blobs + into small buffers, api returns to indicates unfinished if it needs to be + called again to continue; 1 byte or 100K output buffer give same results + - Write apis completely fill available buffer and if unfinished, continues + into same or different buffer when called again with same args; no + requirement for subsequent calls to be done sequentially or even from same + function + +## Type limits + +CBOR allows negative integers of up to 64 bits, these do not fit into a `uint64_t`. +LECP has a union for numbers that includes the types `uint64_t` and `int64_t`, +but it does not separately handle negative integers. Only -2^63.. 2^64 -1 can +be handled by the C types, the oversize negative numbers wrap and should be +avoided. + +## Floating point support + +Floats are handled using the IEEE memory format, it means they can be parsed +from the CBOR without needing any floating point support in the build. If +floating point is available, you can also enable `LWS_WITH_CBOR_FLOAT` and +a `float` and `double` types are available in the number item union. Otherwise +these are handled as `ctx->item.u.u32` and `ctx->item.u.u64` union members. + +Half-float (16-bit) is defined in CBOR and always handled as a `uint16_t` +number union member `ctx->item.u.hf`. + +## Callback reasons + +The user callback does not have to handle any callbacks, it only needs to +process the data for the ones it is interested in. + +|Callback reason|CBOR structure|Associated data| +|---|---|---| +|`LECPCB_CONSTRUCTED`|Created the parse context|| +|`LECPCB_DESTRUCTED`|Destroyed the parse context|| +|`LECPCB_COMPLETE`|The parsing completed OK|| +|`LECPCB_FAILED`|The parsing failed|| +|`LECPCB_VAL_TRUE`|boolean true|| +|`LECPCB_VAL_FALSE`|boolean false|| +|`LECPCB_VAL_NULL`|explicit NULL|| +|`LECPCB_VAL_NUM_INT`|signed integer|`ctx->item.u.i64`| +|`LECPCB_VAL_STR_START`|A UTF-8 string is starting|| +|`LECPCB_VAL_STR_CHUNK`|The next string chunk|`ctx->npos` bytes in `ctx->buf`| +|`LECPCB_VAL_STR_END`|The last string chunk|`ctx->npos` bytes in `ctx->buf`| +|`LECPCB_ARRAY_START`|An array is starting|| +|`LECPCB_ARRAY_END`|An array has ended|| +|`LECPCB_OBJECT_START`|A CBOR map is starting|| +|`LECPCB_OBJECT_END`|A CBOR map has ended|| +|`LECPCB_TAG_START`|The following data has a tag index|`ctx->item.u.u64`| +|`LECPCB_TAG_END`|The end of the data referenced by the last tag|| +|`LECPCB_VAL_NUM_UINT`|Unsigned integer|`ctx->item.u.u64`| +|`LECPCB_VAL_UNDEFINED`|CBOR undefined|| +|`LECPCB_VAL_FLOAT16`|half-float available as host-endian `uint16_t`|`ctx->item.u.hf`| +|`LECPCB_VAL_FLOAT32`|`float` (`uint32_t` if no float support) available|`ctx->item.u.f`| +|`LECPCB_VAL_FLOAT64`|`double` (`uint64_t` if no float support) available|`ctx->item.u.d`| +|`LECPCB_VAL_SIMPLE`|CBOR simple|`ctx->item.u.u64`| +|`LECPCB_VAL_BLOB_START`|A binary blob is starting|| +|`LECPCB_VAL_BLOB_CHUNK`|The next blob chunk|`ctx->npos` bytes in `ctx->buf`| +|`LECPCB_VAL_BLOB_END`|The last blob chunk|`ctx->npos` bytes in `ctx->buf`| +|`LECPCB_ARRAY_ITEM_START`|A logical item in an array is starting| +|`LCEPDB_ARRAY_ITEM_END`|A logical item in an array has completed| + +## CBOR indeterminite lengths + +Indeterminite lengths are supported, but are concealed in the parser as far as +possible, the CBOR lengths or its indeterminacy are not exposed in the callback +interface at all, just chunks of data that may be the start, the middle, or the +end. + +## Handling CBOR UTF-8 strings and blobs + +When a string or blob is parsed, an advisory callback of `LECPCB_VAL_STR_START` or +`LECPCB_VAL_BLOB_START` occurs first. The `_STR_` callbacks indicate the +content is a CBOR UTF-8 string, `_BLOB_` indicates it is binary data. + +Strings or blobs may have indeterminite length, but if so, they are composed +of logical chunks which must have known lengths. When the `_START` callback +occurs, the logical length either of the whole string, or of the sub-chunk if +indeterminite length, can be found in `ctx->item.u.u64`. + +Payload is collated into `ctx->buf[]`, the valid length is in `ctx->npos`. + +For short strings or blobs where the length is known, the whole payload is +delivered in a single `LECPCB_VAL_STR_END` or `LECPCB_VAL_BLOB_END` callback. + +For payloads larger than the size of `ctx->buf[]`, `LECPCB_VAL_STR_CHUNK` or +`LECPCB_VAL_BLOB_CHUNK` callbacks occur delivering each sequential bufferload. +If the CBOR indicates the total length, the last chunk is delievered in a +`LECPCB_VAL_STR_END` or `LECPCB_VAL_BLOB_END`. + +If the CBOR indicates the string end after the chunk, a zero-length `..._END` +callback is provided. + +## Handling CBOR tags + +CBOR tags are exposed as `LECPCB_TAG_START` and `LECPCB_TAG_END` pairs, at +the `_START` callback the tag index is available in `ctx->item.u.u64`. + +## CBOR maps + +You can check if you are on the "key" part of a map "key:value" pair using the +helper api `lecp_parse_map_is_key(ctx)`. + +## Parsing paths + +LECP maintains a "parsing path" in `ctx->path` that represents the context of +the callback events. As a convenience, at LECP context creation time, you can +pass in an array of path strings you want to match on, and have any match +checkable in the callback using `ctx->path_match`, it's 0 if no active match, +or the match index from your path array starting from 1 for the first entry. + +|CBOR element|Representation in path| +|---|---| +|CBOR Array|`[]`| +|CBOR Map|`.`| +|CBOR Map entry key string|`keystring`| + +## Accessing raw CBOR subtrees + +Some CBOR usages like COSE require access to selected raw CBOR from the input +stream. `lecp_parse_report_raw(ctx, on)` lets you turn on and off buffering of +raw CBOR and reporting it in the parse callback with `LECPCB_LITERAL_CBOR` +callbacks. The callbacks mean the temp buffer `ctx->cbor[]` has `ctx->cbor_pos` +bytes of raw CBOR available in it. Callbacks are triggered when the buffer +fills, or reporting is turned off and the buffer has something in it. + +By turning the reporting on and off according to the outer CBOR parsing state, +it's possible to get exactly the raw CBOR subtree that's needed. + +Capturing and reporting the raw CBOR does not change that the same CBOR is being +passed to the parser as usual as well. + +## Comparison with LEJP (JSON parser) + +LECP is based on the same principles as LEJP and shares most of the callbacks. +The major differences: + + - LEJP value callbacks all appear in `ctx->buf[]`, ie, floating-point is + provided to the callback in ascii form like `"1.0"`. CBOR provides a more + strict typing system, and the different type values are provided either in + `ctx->buf[]` for blobs or utf-8 text strtings, or the `item.u` union for + converted types, with additional callback reasons specific to each type. + + - CBOR "maps" use `_OBJECT_START` and `_END` parsing callbacks around the + key / value pairs. LEJP has a special callback type `PAIR_NAME` for the + key string / integer, but in LECP these are provided as generic callbacks + dependent on type, ie, generic string callbacks or integer ones, and the + value part is represented according to whatever comes. + + +# Writing CBOR + +CBOR is written into a `lws_lec_pctx_t` object that has been initialized to +point to an output buffer of a specified size, using printf type formatting. + +Output is paused if the buffer fills, and the write api may be called again +later with the same context object, to resume emitting to the same or different +buffer. + +This allows bufferloads of encoded CBOR to be produced on demand, it's designed +to fit usage in WRITEABLE callbacks and Secure Streams tx() callbacks where the +buffer size for one packet is already fixed. + +CBOR array and map lengths are deduced from the format string, as is whether to +use indeterminite length formatting or not. For indeterminite text or binary +strings, a container of < > + +|Format|Arg(s)|Meaning| +|---|---|---| +|`123`||unsigned literal number| +|`-123`||signed literal number| +|`%u`|`unsigned int`|number| +|`%lu`|`unsigned long int`|number| +|`%llu`|`unsigned long long int`|number| +|`%d`|`signed int`|number| +|`%ld`|`signed long int`|number| +|`%lld`|`signed long long int`|number| +|`%f`|`double`|floating point number| +|`123(...)`||literal tag and scope| +|`%t(...)`|`unsigned int`|tag and scope| +|`%lt(...)`|`unsigned long int`|tag and scope| +|`%llt(...)`|`unsigned long long int`|tag and scope| +|`[...]`||Array (fixed len if `]` in same format string)| +|`{...}`||Map (fixed len if `}` in same format string)| +|``||Container for indeterminite text string frags| +|``||Container for indeterminite binary string frags| +|`'string'`||Literal text of known length| +|`%s`|`const char *`|NUL-terminated string| +|`%.*s`|`int`, `const char *`|length-specified string| +|`%.*b`|`int`, `const uint8_t *`|length-specified binary| +|`:`||separator between Map items (a:b)| +|`,`||separator between Map pairs or array items| + +Backslash is used as an escape in `'...'` literal strings, so `'\\'` represents +a string consisting of a single backslash, and `'\''` a string consisting of a +single single-quote. + +For integers, various natural C types are available, but in all cases, the +number is represented in CBOR using the smallest valid way based on its value, +the long or long-long modifiers just apply to the expected C type in the args. + +For floats, the C argument is always expected to be a `double` type following +C type promotion, but again it is represented in CBOR using the smallest valid +way based on value, half-floats are used for NaN / Infinity and where possible +for values like 0.0 and -1.0. + +## Examples + +### Literal ints + +``` + uint8_t buf[128]; + lws_lec_pctx_t cbw; + + lws_lec_init(&cbw, buf, sizeof(buf)); + lws_lec_printf(ctx, "-1"); +``` +||| +|---|---| +|Return| `LWS_LECPCTX_RET_FINISHED`| +|`ctx->used`|1| +|`buf[]`|20| + +### Dynamic ints + +``` + uint8_t buf[128]; + lws_lec_pctx_t cbw; + int n = -1; /* could be long */ + + lws_lec_init(&cbw, buf, sizeof(buf)); + lws_lec_printf(ctx, "%d", n); /* use %ld for long */ +``` +||| +|---|---| +|Return| `LWS_LECPCTX_RET_FINISHED`| +|`ctx->used`|1| +|`buf[]`|20| + +### Maps, arrays and dynamic ints + +``` + ... + int args[3] = { 1, 2, 3 }; + + lws_lec_printf(ctx, "{'a':%d,'b':[%d,%d]}", args[0], args[1], args[2]); +``` + +||| +|---|---| +|Return| `LWS_LECPCTX_RET_FINISHED`| +|`ctx->used`|9| +|`buf[]`|A2 61 61 01 61 62 82 02 03| + +### String longer than the buffer + +Using `%s` and the same string as an arg gives same results + +``` + uint8_t buf[16]; + lws_lec_pctx_t cbw; + + lws_lec_init(&cbw, buf, sizeof(buf)); + lws_lec_printf(ctx, "'A literal string > one buf'"); + /* not required to be in same function context or same buf, + * but the string must remain the same */ + lws_lec_setbuf(&cbw, buf, sizeof(buf)); + lws_lec_printf(ctx, "'A literal string > one buf'"); +``` + +First call + +||| +|---|---| +|Return| `LWS_LECPCTX_RET_AGAIN`| +|`ctx->used`|16| +|`buf[]`|78 1A 41 20 6C 69 74 65 72 61 6C 20 73 74 72 69| + +Second call + +||| +|---|---| +|Return| `LWS_LECPCTX_RET_FINISHED`| +|`ctx->used`|12| +|`buf[]`|6E 67 20 3E 20 6F 6E 65 20 62 75 66| + +### Binary blob longer than the buffer + +``` + uint8_t buf[16], blob[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }; + lws_lec_pctx_t cbw; + + lws_lec_init(&cbw, buf, sizeof(buf)); + lws_lec_printf(ctx, "%.*b", (int)sizeof(blob), blob); + /* not required to be in same function context or same buf, + * but the length and blob must remain the same */ + lws_lec_setbuf(&cbw, buf, sizeof(buf)); + lws_lec_printf(ctx, "%.*b", (int)sizeof(blob), blob); +``` + +First call + +||| +|---|---| +|Return| `LWS_LECPCTX_RET_AGAIN`| +|`ctx->used`|16| +|`buf[]`|52 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F| + +Second call + +||| +|---|---| +|Return| `LWS_LECPCTX_RET_FINISHED`| +|`ctx->used`|3| +|`buf[]`|10 11 12| diff --git a/3rdparty/libwebsockets/READMEs/README.coding.md b/3rdparty/libwebsockets/READMEs/README.coding.md index f0c7008e..d1143f56 100644 --- a/3rdparty/libwebsockets/READMEs/README.coding.md +++ b/3rdparty/libwebsockets/READMEs/README.coding.md @@ -183,28 +183,17 @@ loop wait (sleeping in `poll()` or `epoll()` or whatever). The rules above mean directly sending data on the connection from another thread is out of the question. -Therefore the two apis mentioned above that may be used from another thread are - - - For LWS using the default poll() event loop, `lws_callback_on_writable()` - - - For LWS using libuv/libev/libevent event loop, `lws_cancel_service()` - -If you are using the default poll() event loop, one "foreign thread" at a time may -call `lws_callback_on_writable()` directly for a wsi. You need to use your own -locking around that to serialize multiple thread access to it. - -If you implement LWS_CALLBACK_GET_THREAD_ID in protocols[0], then LWS will detect -when it has been called from a foreign thread and automatically use -`lws_cancel_service()` to additionally wake the service loop from its wait. - -For libuv/libev/libevent event loop, they cannot handle being called from other -threads. So there is a slightly different scheme, you may call `lws_cancel_service()` -to force the event loop to end immediately. This then broadcasts a callback (in the -service thread context) `LWS_CALLBACK_EVENT_WAIT_CANCELLED`, to all protocols on all -vhosts, where you can perform your own locking and walk a list of wsi that need -`lws_callback_on_writable()` calling on them. - -`lws_cancel_service()` is very cheap to call. +The only lws api that's safe to call from other thread contexts is `lws_cancel_service()`. +This will take a platform-specific action to wake the lws event loop thread wait, +either put a byte into a pipe2() the event loop is waiting on, or send a packet on +a UDP socket pair that the event loop waits on. When the wake is handled by the +lws event loop thread, it will broadcast a `LWS_CALLBACK_EVENT_WAIT_CANCELLED` +message to every vhost-protocol instantiation, so you can handle this callback, +usually lock a shared data region, and if you see you need to write, call +`lws_callback_on_writeable()` for the wsi(s) that need to write. + +There's no restriction on multiple threads calling `lws_cancel_service()`, it's +unconditionally safe due to how it is implemented underneath. 5) The obverse of this truism about the receiver being the boss is the case where we are receiving. If we get into a situation we actually can't usefully diff --git a/3rdparty/libwebsockets/READMEs/README.event-loops-intro.md b/3rdparty/libwebsockets/READMEs/README.event-loops-intro.md new file mode 100644 index 00000000..35b51610 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.event-loops-intro.md @@ -0,0 +1,285 @@ +# Considerations around Event Loops + +Much of the software we use is written around an **event loop**. Some examples + + - Chrome / Chromium, transmission, tmux, ntp SNTP... [libevent](https://libevent.org/) + - node.js / cjdns / Julia / cmake ... [libuv](https://archive.is/64pOt) + - Gstreamer, Gnome / GTK apps ... [glib](https://people.gnome.org/~desrt/glib-docs/glib-The-Main-Event-Loop.html) + - SystemD ... sdevent + - OpenWRT ... uloop + +Many applications roll their own event loop using poll() or epoll() or similar, +using the same techniques. Another set of apps use message dispatchers that +take the same approach, but are for cases that don't need to support sockets. +Event libraries provide crossplatform abstractions for this functoinality, and +provide the best backend for their event waits on the platform automagically. + +libwebsockets networking operations require an event loop, it provides a default +one for the platform (based on poll() for Unix) if needed, but also can natively +use any of the event loop libraries listed above, including "foreign" loops +already created and managed by the application. + +## What is an 'event loop'? + +Event loops have the following characteristics: + + - they have a **single thread**, therefore they do not require locking + - they are **not threadsafe** + - they require **nonblocking IO** + - they **sleep** while there are no events (aka the "event wait") + - if one or more event seen, they call back into user code to handle each in + turn and then return to the wait (ie, "loop") + +### They have a single thread + +By doing everything in turn on a single thread, there can be no possibility of +conflicting access to resources from different threads... if the single thread +is in callback A, it cannot be in two places at the same time and also in +callback B accessing the same thing: it can never run any other code +concurrently, only sequentially, by design. + +It means that all mutexes and other synchronization and locking can be +eliminated, along with the many kinds of bugs related to them. + +### They are not threadsafe + +Event loops mandate doing everything in a single thread. You cannot call their +apis from other threads, since there is no protection against reentrancy. + +Lws apis cannot be called safely from any thread other than the event loop one, +with the sole exception of `lws_cancel_service()`. + +### They have nonblocking IO + +With blocking IO, you have to create threads in order to block them to learn +when your IO could proceed. In an event loop, all descriptors are set to use +nonblocking mode, we only attempt to read or write when we have been informed by +an event that there is something to read, or it is possible to write. + +So sacrificial, blocking discrete IO threads are also eliminated, we just do +what we should do sequentially, when we get the event indicating that we should +do it. + +### They sleep while there are no events + +An OS "wait" of some kind is used to sleep the event loop thread until something +to do. There's an explicit wait on file descriptors that have pending read or +write, and also an implicit wait for the next scheduled event. Even if idle for +descriptor events, the event loop will wake and handle scheduled events at the +right time. + +In an idle system, the event loop stays in the wait and takes 0% CPU. + +### If one or more event, they handle them and then return to sleep + +As you can expect from "event loop", it is an infinite loop alternating between +sleeping in the event wait and sequentially servicing pending events, by calling +callbacks for each event on each object. + +The callbacks handle the event and then "return to the event loop". The state +of things in the loop itself is guaranteed to stay consistent while in a user +callback, until you return from the callback to the event loop, when socket +closes may be processed and lead to object destruction. + +Event libraries like libevent are operating the same way, once you start the +event loop, it sits in an inifinite loop in the library, calling back on events +until you "stop" or "break" the loop by calling apis. + +## Why are event libraries popular? + +Developers prefer an external library solution for the event loop because: + + - the quality is generally higher than self-rolled ones. Someone else is + maintaining it, a fulltime team in some cases. + - the event libraries are crossplatform, they will pick the most effective + event wait for the platform without the developer having to know the details. + For example most libs can conceal whether the platform is windows or unix, + and use native waits like epoll() or WSA accordingly. + - If your application uses a event library, it is possible to integrate very + cleanly with other libraries like lws that can use the same event library. + That is extremely messy or downright impossible to do with hand-rolled loops. + +Compared to just throwing threads on it + + - thread lifecycle has to be closely managed, threads must start and must be + brought to an end in a controlled way. Event loops may end and destroy + objects they control at any time a callback returns to the event loop. + + - threads may do things sequentially or genuinely concurrently, this requires + locking and careful management so only deterministic and expected things + happen at the user data. + + - threads do not scale well to, eg, serving tens of thousands of connections; + web servers use event loops. + +## Multiple codebases cooperating on one event loop + +The ideal situation is all your code operates via a single event loop thread. +For lws-only code, including lws_protocols callbacks, this is the normal state +of affairs. + +When there is other code that also needs to handle events, say already existing +application code, or code handling a protocol not supported by lws, there are a +few options to allow them to work together, which is "best" depends on the +details of what you're trying to do and what the existing code looks like. +In descending order of desirability: + +### 1) Use a common event library for both lws and application code + +This is the best choice for Linux-class devices. If you write your application +to use, eg, a libevent loop, then you only need to configure lws to also use +your libevent loop for them to be able to interoperate perfectly. Lws will +operate as a guest on this "foreign loop", and can cleanly create and destroy +its context on the loop without disturbing the loop. + +In addition, your application can merge and interoperate with any other +libevent-capable libraries the same way, and compared to hand-rolled loops, the +quality will be higher. + +### 2) Use lws native wsi semantics in the other code too + +Lws supports raw sockets and file fd abstractions inside the event loop. So if +your other code fits into that model, one way is to express your connections as +"RAW" wsis and handle them using lws_protocols callback semantics. + +This ties the application code to lws, but it has the advantage that the +resulting code is aware of the underlying event loop implementation and will +work no matter what it is. + +### 3) Make a custom lws event lib shim for your custom loop + +Lws provides an ops struct abstraction in order to integrate with event +libraries, you can find it in ./includes/libwebsockets/lws-eventlib-exports.h. + +Lws uses this interface to implement its own event library plugins, but you can +also use it to make your own customized event loop shim, in the case there is +too much written for your custom event loop to be practical to change it. + +In other words this is a way to write a customized event lib "plugin" and tell +the lws_context to use it at creation time. See [minimal-http-server.c](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c) + +### 4) Cooperate at thread level + +This is less desirable because it gives up on unifying the code to run from a +single thread, it means the codebases cannot call each other's apis directly. + +In this scheme the existing threads do their own thing, lock a shared +area of memory and list what they want done from the lws thread context, before +calling `lws_cancel_service()` to break the lws event wait. Lws will then +broadcast a `LWS_CALLBACK_EVENT_WAIT_CANCELLED` protocol callback, the handler +for which can lock the shared area and perform the requested operations from the +lws thread context. + +### 5) Glue the loops together to wait sequentially (don't do this) + +If you have two or more chunks of code with their own waits, it may be tempting +to have them wait sequentially in an outer event loop. (This is only possible +with the lws default loop and not the event library support, event libraries +have this loop inside their own `...run(loop)` apis.) + +``` + while (1) { + do_lws_wait(); /* interrupted at short intervals */ + do_app_wait(); /* interrupted at short intervals */ + } +``` + +This never works well, either: + + - the whole thing spins at 100% CPU when idle, or + + - the waits have timeouts where they sleep for short periods, but then the + latency to service on set of events is increased by the idle timeout period + of the wait for other set of events + +## Common Misunderstandings + +### "Real Men Use Threads" + +Sometimes you need threads or child processes. But typically, whatever you're +trying to do does not literally require threads. Threads are an architectural +choice that can go either way depending on the goal and the constraints. + +Any thread you add should have a clear reason to specifically be a thread and +not done on the event loop, without a new thread or the consequent locking (and +bugs). + +### But blocking IO is faster and simpler + +No, blocking IO has a lot of costs to conceal the event wait by blocking. + +For any IO that may wait, you must spawn an IO thread for it, purely to handle +the situation you get blocked in read() or write() for an arbitrary amount of +time. It buys you a simple story in one place, that you will proceed on the +thread if read() or write() has completed, but costs threads and locking to get +to that. + +Event loops dispense with the threads and locking, and still provide a simple +story, you will get called back when data arrives or you may send. + +Event loops can scale much better, a busy server with 50,000 connections active +does not have to pay the overhead of 50,000 threads and their competing for +locking. + +With blocked threads, the thread can do no useful work at all while it is stuck +waiting. With event loops the thread can service other events until something +happens on the fd. + +### Threads are inexpensive + +In the cases you really need threads, you must have them, or fork off another +process. But if you don't really need them, they bring with them a lot of +expense, some you may only notice when your code runs on constrained targets + + - threads have an OS-side footprint both as objects and in the scheduler + + - thread context switches are not slow on modern CPUs, but have side effects + like cache flushing + + - threads are designed to be blocked for arbitrary amounts of time if you use + blocking IO apis like write() or read(). Then how much concurrency is really + happening? Since blocked threads just go away silently, it is hard to know + when in fact your thread is almost always blocked and not doing useful work. + + - threads require their own stack, which is on embedded is typically suffering + from a dedicated worst-case allocation where the headroom is usually idle + + - locking must be handled, and missed locking or lock order bugs found + +### But... what about latency if only one thing happens at a time? + + - Typically, at CPU speeds, nothing is happening at any given time on most + systems, the event loop is spending most of its time in the event wait + asleep at 0% cpu. + + - The POSIX sockets layer is disjoint from the actual network device driver. + It means that once you hand off the packet to the networking stack, the POSIX + api just returns and leaves the rest of the scheduling, retries etc to the + networking stack and device, descriptor queuing is driven by interrupts in + the driver part completely unaffected by the event loop part. + + - Passing data around via POSIX apis between the user code and the networking + stack tends to return almost immediately since its onward path is managed + later in another, usually interrupt, context. + + - So long as enough packets-worth of data are in the network stack ready to be + handed to descriptors, actual throughput is completely insensitive to jitter + or latency at the application event loop + + - The network device itself is inherently serializing packets, it can only send + one thing at a time. The networking stack locking also introduces hidden + serialization by blocking multiple threads. + + - Many user systems are decoupled like the network stack and POSIX... the user + event loop and its latencies do not affect backend processes occurring in + interrupt or internal thread or other process contexts + +## Conclusion + +Event loops have been around for a very long time and are in wide use today due +to their advantages. Working with them successfully requires understand how to +use them and why they have the advantages and restrictions they do. + +The best results come from all the participants joining the same loop directly. +Using a common event library in the participating codebases allows completely +different code can call each other's apis safely without locking. diff --git a/3rdparty/libwebsockets/READMEs/README.fault-injection.md b/3rdparty/libwebsockets/READMEs/README.fault-injection.md index b7e3f307..78106794 100644 --- a/3rdparty/libwebsockets/READMEs/README.fault-injection.md +++ b/3rdparty/libwebsockets/READMEs/README.fault-injection.md @@ -232,15 +232,26 @@ matches an object, the fault will be injected every time. It's also possible to make the fault inject itself at a random probability, or in a cyclic pattern, by giving additional information in brackets, eg -|Syntax|Meaning| -|---|---| -|`wsi/thefault`|Inject the fault every time| -|`wsi/thefault(10%)`|Randomly inject the fault at 10% probability| -|`wsi/thefault(.............X.X)`|Inject the fault on the 14th and 16th try, every 16 tries| +|Syntax|Used with|Meaning| +|---|---|---| +|`wsi/thefault`|lws_fi()|Inject the fault every time| +|`wsi/thefault(10%)`|lws_fi()|Randomly inject the fault at 10% probability| +|`wsi/thefault(.............X.X)`|lws_fi()|Inject the fault on the 14th and 16th try, every 16 tries| +|`wsi/thefault2(123..456)`|lws_fi_range()|Pick a number between 123 and 456| You must quote the strings containing these symbols, since they may otherwise be interpreted by your shell. +The last example above does not decide whether to inject the fault via `lws_fi()` +like the others. Instead you can use it via `lws_fi_range()` as part of the +fault processing, on a secondary fault injection name. For example you may have +a fault `myfault` you use with `lws_fi()` to decide when to inject the fault, +and then a second, related fault name `myfault_delay` to allow you to add code +to delay the fault action by some random amount of ms within an externally- +given range. You can get a pseudo-random number within the externally-given +range by calling `lws_fi_range()` on `myfault_delay`, and control the whole +thing by giving, eg, `"myfault(10%),myfault_delay(123..456)"` + ## Well-known fault names in lws |Scope|Namespc|Name|Fault effect| @@ -262,6 +273,9 @@ interpreted by your shell. |context||`ctx_createfail_ss_pol1`|Fail context creation due to ss policy parse start failed (if policy enabled)| |context||`ctx_createfail_ss_pol2`|Fail context creation due to ss policy parse failed (if policy enabled)| |context||`ctx_createfail_ss_pol3`|Fail context creation due to ss policy set failed (if policy enabled)| +|context||`cache_createfail`|Fail `lws_cache` creation due to OOM| +|context||`cache_lookup_oom`|Fail `lws_cache` lookup due to OOM| +|vhost|`vh`|`vh_create_oom`|Fail vh creation on vh object alloc OOM| |vhost|`vh`|`vh_create_oom`|Fail vh creation on vh object alloc OOM| |vhost|`vh`|`vh_create_pcols_oom`|Fail vh creation at protocols alloc OOM| |vhost|`vh`|`vh_create_access_log_open_fail`|Fail vh creation due to unable to open access log (LWS_WITH_ACCESS_LOG)| @@ -293,7 +307,17 @@ interpreted by your shell. |ssproxy|`wsi`|`sspc_dsh_ss2p_oom`|Cause ss->proxy dsh allocation to fail| |ssproxy|`ss`|`ssproxy_onward_conn_fail`|Act as if proxy onward client connection failed immediately| |ssproxy|`ss`|`ssproxy_dsh_c2p_pay_oom`|Cause proxy's DSH alloc for C->P payload to fail| - +|ss|`ss`|`ss_create_smd`|SMD: ss creation smd registration fail| +|ss|`ss`|`ss_create_vhost`|Server: ss creation acts like no vhost matching typename (only for `!vhost`)| +|ss|`ss`|`ss_create_pcol`|Server: ss creation acts like no protocol given in policy| +|ss|`ss`|`ss_srv_vh_fail`|Server: ss creation acts like unable to create vhost| +|ss|`ss`|`ss_create_destroy_me`|ss creation acts like CREATING state returned DESTROY_ME| +|ss|`ss`|`ss_create_no_ts`|Static Policy: ss creation acts like no trust store| +|ss|`ss`|`ss_create_smd_1`|SMD: ss creation acts like CONNECTING said DESTROY_ME| +|ss|`ss`|`ss_create_smd_2`|SMD: ss creation acts like CONNECTED said DESTROY_ME| +|ss|`ss`|`ss_create_conn`|Nailed up: ss creation client connection fails with DESTROY_ME| +|wsi|`wsi`|`timedclose`|(see next) Cause wsi to close after some time| +|wsi|`wsi`|`timedclose_ms`|Range of ms for timedclose (eg, "timedclose_ms(10..250)"| ## Well-known namespace targets diff --git a/3rdparty/libwebsockets/READMEs/README.http-cache.md b/3rdparty/libwebsockets/READMEs/README.http-cache.md new file mode 100644 index 00000000..a1378362 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.http-cache.md @@ -0,0 +1,40 @@ +# Client http cookie storage, caching and application + +lws now has the option to store incoming cookies in a Netscape cookie jar file +persistently, and auto-apply relevant cookies to future outgoing requests. + +A L1 heap cache of recent cookies is maintained, along with LRU tracking and +removal of entries from cache and the cookie jar file according to their cookie +expiry time. + +The cookie handling is off by default per-connection for backwards compatibility +and to avoid unexpected tracking. + +## Enabling at build-time + +Make sure `-DLWS_WITH_CACHE_NSCOOKIEJAR=1` is enabled at cmake (it is on by +default now). + +## Configuring the cookie cache + +The cookie cache is managed through context creation info struct members. + +|member|function| +|---|---| +|`.http_nsc_filepath`|Filepath to store the cookie jar file at| +|`.http_nsc_heap_max_footprint`|0, or Max size in bytes for the L1 heap cache| +|`.http_nsc_heap_max_items`|0, or Max number of cookies allowed in L1 heap cache| +|`.http_nsc_heap_max_payload`|0, or Largest cookie we are willing to handle| + +## Enabling per-connection in lws + +To enable it on connections at lws level, add the flag `LCCSCF_CACHE_COOKIES` to +the client connection info struct `.ssl_connection` flags. + +## Enabling per-connection in Secure Streams policy + +To enable it on Secure Streams, in the streamtype policy add + +``` + "http_cookies": true +``` diff --git a/3rdparty/libwebsockets/READMEs/README.jit-trust.md b/3rdparty/libwebsockets/READMEs/README.jit-trust.md new file mode 100644 index 00000000..dfdd12b2 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.jit-trust.md @@ -0,0 +1,446 @@ +# JIT trust + +![JIT Trust logo](../doc-assets/jit-trust-logo.png) + +## Background + +Most systems using openssl rely on a system trust bundle that openssl was +compiled to load at library init. This is a bit expensive, since it +instantiates over 120 CA X.509 certs, but most modern Linux systems don't really +notice the permanent use of 1MB or so of heap from init, the advantage is client +connections have all the trusted root certs available in memory to perform +validation. + +![Using system trust bundles](../doc-assets/jit-trust-system-trust.png) + +For the kind of systems that choose mbedtls, they will typically either be +burdened by or not even have enough ram to take this approach. + +If the device only connects to endpoints that are signed by a specific +CA, you can just prepare the connection with the known trusted CA, that's +the approach the examples take. This method should still be used for critical +connections to the cloud, for example provide the necessary CA cert in the +Secure Streams policy, or at vhost creation time. + +![Using system trust bundles](../doc-assets/jit-trust-single-trust.png) + +However if you also have a browser type application that could connect anywhere, +but you don't have heap spare to preload all the CAs, you need something like +"JIT trust". + +## JIT trust overview + +The basic approach is to connect to the server to retrieve its certificates, +then study the certificates to determine the identity of the missing trusted +cert we should be trying to validate with. + +![JIT Trust overview](../doc-assets/jit-trust-overview.png) + +We attempt to get the trusted cert from some local or remote store, and retry +the connection having instantiated the missing CA cert as trusted for that +connection, if it is one that we do actually trust. If it lies about what CA it +needs to validate, or we do not trust the one it asks for, subsequent +connections will fail. + +If it asked for a trusted CA that we trust, and the relationship was valid, the +tls negotiation should then complete successfully, and we can cache the CA cert +and the host -> CA cert pre-trust requirement so future connections can work +first time. + +## Subject Key Id and Authority Key Id + +All of the certificates publish a unique-enough personal "Subject Key ID" or +SKID blob. These are typically 20-byte hashes based on the cert public key. + +When a server certificate is issued by the CA, an entry is made first in the +certificate noting the SKID of the certificate that will be used to sign it, +in an "Authority Key ID", or AKID, extension. The certificate is then signed by +the parent certificate private key to prove it was issued by the real owner of +the CA or intermediate certificate. + +![X.509 validation paths](../doc-assets/jit-trust-paths.png) + +Basically this AKID on a certificate is guiding the validator with +information about which certificate it claims is next in the chain of trust +leading back to a trusted CA. Lying about it doesn't help an attacker, +because we're only using the AKID to get the CA certificate and then try to do +the full signature check using it, if it's not really signed by the AKID cert it +told, or anything else wrong, the actual validation will just fail. + +A chain that terminates in a CA certificate is complete, and can undergo full +validation using the tls library. + +## Converting the Mozilla trust bundle for JIT trust + +Lws provides a bash script `./scripts/mozilla-trust-gen.sh` that can fetch the +latest Mozilla CA trust bundle for certs usable for tls validation, and convert +it to three different forms to allow maintaining the trust bundle in different +ways for different kinds of device to consume. + + - as a webroot directory, so you can server trusted DERs, with + symlink indexes to the CA certs by SKID and issuer/serial + + - as an atomic binary blob, currently about 143KB, with structure + at the start pointing to DER certs and indexes inside + + - a C-compiler friendly `uint8_t` array version of the blob, + so it can be compiled into .rodata directly if necessary. + +Currently there are 128 certs in the trust bundle, and the whole blob is about +143KB uncompressed. + +## Considerations about maintaining the trust blob + +Mozilla update their trust bundle at intervals, and there have been at least +three cases where they have removed or distrusted CAs from it by their own +decision, because they have issued dangerous certificates, (like one for `*` +that will validate anything at all). Certifacte owners may also revoke their +own certificates for any reason and issue replacements. + +The certs in the trust bundle expire, currently 10/128 will expire within 3 +years and 50/128 over the next 10 years. So new and replacement certificates +are also being added at intervals. + +Part of using the trust bundle is building in some way to update what is trusted +over the lifetime of the device, which may exceed 10 years. + +Depending on the device, it may not be any problem to keep the trust blob in the +firmware, and update the firmware ongoing every few months. So you could build +it into the firmware using the C array include file (the minimal example takes +this approach). + +Another device may have difficulty updating the firmware outside of emergencies, +it could keep the trust blob in a separate area and update it separately. +Having it as a single blob makes it easy to fetch and update. + +Finally constrained devices, say in ESP32 class, may not have space or desire +to store the trust blob in the device at all, it could query a remote server on +demand to check for any trusted CA matching a given AKID and retrieve and cache +it in volatile ram. This would use the webroot produced by the script, via tls +and a fixed CA cert outside this system. + +## Format of the JIT trust blob + +The trust blob layout is currently + +``` +00: 54 42 4c 42 Magic "TBLB" +04: 00 01 MSB-first trust blob layout version +06: XX XX MSB-first count of certificates +08: XX XX XX XX MSB-first trust blob generation unix time +0c: XX XX XX XX MSB-first offset from blob start of cert length table +10: XX XX XX XX MSB-first offset from blob start of SKID length table +14: XX XX XX XX MSB-first offset from blob start of SKID table +18: XX XX XX XX MSB-first total blob length + +1c: XX .. XX DER certs (start at +0x1c) + : XX .. XX DER cert length table (MSB-first 16-bit per cert) + : XX .. XX SKID length table (8-bit per cert) + : XX .. XX SKID table (variable per cert) +``` + +## Enabling JIT Trust + +``` +$ cmake .. -DLWS_WITH_TLS_JIT_TRUST=1 +``` + +## Minimal example for JIT Trust + +`minimal-examples/http-client/minimal-http-client-jit-trust` is built if JIT +Trust is enabled at cmake and `-DLWS_WITH_MINIMAL_EXAMPLES=1`. This is based on +minimal-http-client, except the loading of the system trust bundle is defeated, +so by default it does not trust anything and cannot complete any tls connection. +It includes the mozilla trust blob as a header file when built. + +It tries to do an http client connection twice, the first time fails but JIT +Trust determines which trusted CA cert is missing, retreives it from the trust +blob and creates the necessary temporary vhost with the correct CA cert(s) +trusted. On the next retry, the connection succeeds. + +## Processing of x509 AKID and SKIDs + +We study each x509 cert sent by the server in turn. We parse out the SKID and +AKID on each one and stash them (up to 4 deep). + +After the initial validation fails due to lack of any trusted CA, lws has +collected all the AKID and SKIDs that were in certs sent by the server. Since +these may be sent in any order, may be malicious, and may even contain the +(untrusted) root CA, they are sorted into a trust path using the AKID and SKID +relationships. + +To cover cross-signing and cases where the root cert(s) were wrongly sent by +a misconfigured server, all of the AKIDs in the stash are queried against the +trusted CA store. In cross-signing, multiple intermediates are provided with +the same SKID, that all match the server certificate AKID parent. Since we +might meet certificates that trust multiple valid CAs that can validate the +certificate, we support up to three CA certs imported. + +A user `lws_system_ops` handler performs the query, so it can consist of any +kind of backing store or remote lookup. Helpers are provided to query the JIT +trust mozilla blob, so the system helper is small in the typical case, just +calling lws helpers. + +The results (up to three CA certs to account for cross-signing scenarios) are +collected and a 1hr TTL cache entry made for the hostname and the SKIDs of the +matched CAs, if there is no existing JIT vhost with its tls context configured +with the needed trusted CAs, one is created. + +When the connection is retried, lws checks the cache for the hostname having +a binding to an existing JIT vhost, if that exists the connection proceeds +bound to that. If there is a cache entry but no JIT vhost, one is created using +the information in the cache entry. + +## Efficiency considerations + +From cold, the JIT Trust flow is + +1. A sacrificial connection is made to get the server certs +2. Query the JIT Trust database for AKIDs mentioned in the certs (this may be +done asynchronously) +3. Create a temporary vhost with the appropriate trusted certs enabled in it, + and add an entry in the cache for this hostname to the SKIDs of the CAs + enabled on this temporary vhost +4. Retry, querying the cache to bind the connection to the right temporary vhost + +An lws_cache in heap is maintained so step 1 can be skipped while hostname-> +SKID items exist in the cache. If the items expire or are evicted, it just +means we have to do step 1 again. + +For a short time, the vhost created in step 3 is allowed to exist when idle, ie +when no connections are actively using it. In the case the vhost exists and +the cache entry exists for the hostname, the connection can proceed successfully +right away without steps 1 through 3. + +## APIs related to JIT Trust + +Systems that support JIT trust define an `lws_system_ops` callback +that does whatever the system needs to do for attempting to acquire +a trusted cert with a specified SKID or issuer/serial. + +``` +int (*jit_trust_query)(struct lws_context *cx, const uint8_t *skid, size_t skid_len, void *got_opaque); +``` + +The ops handler doesn't have to find the trusted cert immediately before +returning, it is OK starting the process and later if successful calling a +helper `lws_tls_jit_trust_got_cert_cb()` with the `got_opaque` from the query. +This will cache the CA cert so it's available at the next connection retry for +preloading. + +An helper suitable for `ops->jit_trust_query` using trust blob lookup in .rodata +is provided in `lws_tls_jit_trust_blob_queury_skid()`, the callback above should +be called with its results as shown in the minimal example. + +## Runtime tuning for JIT Trust + +The context creation info struct has a couple of runtime-tunable settings +related to JIT Trust. + +`.jitt_cache_max_footprint`: default 0 means no limit, otherwise the hostname-> +SKID cache is kept below this many bytes in heap, by evicting LRU entries. + +`.vh_idle_grace_ms`: default 0 means 5000ms, otherwise sets the length of time +a JIT Trust vhost is allowed to exist when it has no connections using it. +Notice that, eg, h2 connections have their own grace period when they become +idle, to optimize reuse, this period does not start until any h2 network +connection bound to the vhost has really closed. + +## Considerations around http redirects + +HTTP redirects are transactions that tell the client to go somewhere else to +continue, typically a 301 response with a Location: header explaining where to +go. + +JIT Trust supports redirects to hosts with the same or different trust +requirements, each step in the redirect is treated as a new connection that will +fail, try to create a vhost with the right trust and work on the retry. + +Lws rejects by default protocol downgrades (https -> http) on redirects, the +example used a context option `LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS` to +override this. + +## Works out of the box on recent mbedtls and openssl + +No modifications are needed to either tls library. + +## Compatibility Testing + +A list of the top 100 sites each from the US and the ROW were combined to +produce 156 unqiue domain names [1] + +The Mbedtls build of JIT trust minimal example was run against each of these +doing a GET on path `/` and restricted to h1 (`--server xxx --h1`). In some +cases, the server at the base domain name is broken or down, as verified using +ssllabs.com as a second opinion. These domains only resolve properly using +`www.` prefix. + +In some cases the sites check the user agent and return a 4xx, these are taken +as success for this test, since there was no problem at the tls layer. + +|site|h1|h2|comment| +|---|---|---|---| +|adobe.com|✓|✓|| +|allegro.pl|✓|✓|| +|allrecipes.com|✓|✓|| +|amazon.co.jp|✓|✓|| +|amazon.com|✓|✓|| +|amazon.co.uk|✓|✓|| +|amazon.de|✓|✓|| +|amazon.fr|✓|✓|| +|amazon.in|✓|✓|| +|amazon.it|✓|✓|| +|aol.com|✓|✓|| +|apartments.com|✓|✓|| +|apple.com|✓|✓|| +|ar.wikipedia.org|✓|✓|| +|att.com|✓|✓|| +|bankofamerica.com|✓|✓|| +|bbc.com|✓|✓|| +|bbc.co.uk|✓|✓|| +|bestbuy.com|✕|✓|redirect-> `www.` then h1: timeout, h2: 403 forbidden... geolocated?| +|booking.com|✓|✓|| +|britannica.com|✓|✓|| +|bulbagarden.net|✓|✓|| +|businessinsider.com|✓|✓|| +|ca.gov|✓|✓|| +|caixa.gov.br|✕|✕|TLS trust works fine. Continuously redirects to self... sends set-cookie that we don't return yet| +|capitalone.com|✓|✓|| +|cbssports.com|✓|✓|| +|cdc.gov|✓|✓|| +|chase.com|✓|✓|| +|chrome.google.com|✓|✓|| +|cnbc.com|✓|✓|| +|cnet.com|✓|✓|| +|cnn.com|✓|✓|| +|cookpad.com|✓|✓|| +|costco.com|✕|✓|TLS trust works fine. But with or without `www.` server does not reply within 15s on h1, sends 403 OK on h2... Curl acts the same as we do, firefox works... geolocated?|| +|craigslist.org|✓|✓|| +|dailymotion.com|✓|✓|| +|de.wikipedia.org|✓|✓|| +|dictionary.com|✓|✓|| +|ebay.com|✓|✓|| +|ebay.co.uk|✓|✓|| +|en.wikipedia.org|✓|✓|| +|epicgames.com|✓|✓|| +|espn.com|✓|✓|| +|es.wikipedia.org|✓|✓|| +|etsy.com|✓|✓|| +|expedia.com|✓|✓|| +|facebook.com|✓|✓|| +|fandom.com|✓|✓|| +|fedex.com|✓|✓|| +|finance.yahoo.com|✓|✓|| +|www.foodnetwork.com|✓|✓|`www.` served correctly, base domain is misconfigured with expired cert, confirmed with ssllabs + curl| +|forbes.com|✓|✓|| +|foxnews.com|✓|✓|| +|fr.wikipedia.org|✓|✓|| +|gamepedia.com|✓|✓|| +|genius.com|✓|✓|| +|glassdoor.com|✓|✓|| +|globo.com|✓|✓|| +|google.com|✓|✓|| +|healthline.com|✓|✓|| +|homedepot.com|✓|✓|| +|hulu.com|✓|✓|| +|hurriyet.com.tr|✓|✓|| +|id.wikipedia.org|✓|✓|| +|ign.com|✓|✓|| +|ikea.com|✓|✓|`www.` served correctly, base domain is misconfigured with nonresponsive server, confirmed with ssllabs| +|ilovepdf.com|✓|✓|| +|imdb.com|✓|✓|| +|indeed.com|✓|✓|| +|indiatimes.com|✓|✓|| +|instagram.com|✓|✓|| +|investopedia.com|✓|✓|| +|irs.gov|✓|✓|| +|it.wikipedia.org|✓|✓|| +|ivi.ru|✓|✓|| +|ja.wikipedia.org|✓|✓|| +|kakaku.com|✓|✓|| +|khanacademy.org|✓|✓|| +|kinopoisk.ru|✓|✓|| +|leboncoin.fr|✓|✓|| +|linkedin.com|✓|✓|| +|live.com|✓|✓|| +|lowes.com|✓|✓|| +|macys.com|✕|✓|TLS trust works fine. Continuously redirects to self... `www.` same, curl acts same but OK if given -b -c, so akami cookie storage issue| +|mail.ru|✓|✓|| +|mail.yahoo.com|✓|✓|| +|mapquest.com|✓|✓|| +|mayoclinic.org|✓|✓|| +|medicalnewstoday.com|✓|✓|| +|mercadolivre.com.br|✓|✓|| +|merriam-webster.com|✓|✓|| +|microsoft.com|✓|✓|| +|msn.com|✓|✓|| +|namu.wiki|✓|✓|| +|nbcnews.com|✓|✓|| +|netflix.com|✓|✓|| +|nih.gov|✓|✓|| +|nl.wikipedia.org|✓|✓|| +|ny.gov|✓|✓|| +|nytimes.com|✓|✓|| +|ok.ru|✓|✓|| +|onet.pl|✓|| +|orange.fr|✓|✓|| +|paypal.com|✓|✓|| +|pinterest.com|✓|✓|| +|pixiv.net|✓|✓|| +|play.google.com|✓|✓|| +|pl.wikipedia.org|✓|✓|| +|www.programme-tv.net|✓|✓|OK with `www.`, without `www.` TLS trust works fine but server does not reply, same with curl| +|pt.wikipedia.org|✓|✓|| +|quizlet.com|✓|✓|| +|quora.com|✓|✓||| +|rakuten.co.jp|✓|✓|| +|realtor.com|✓|✓|| +|reddit.com|✓|✓|| +|reverso.net|✓|✓|| +|roblox.com|✓|✓|| +|rottentomatoes.com|✓|✓|| +|ru.wikipedia.org|✓|✓|| +|sahibinden.com|✓|✓|| +|smallpdf.com|✓|✓|| +|speedtest.net|✓|✓|| +|spotify.com|✓|✓|| +|steampowered.com|✓|✓|| +|target.com|✓|✓|| +|theguardian.com|✓|✓|| +|tripadvisor.com|✓|✓|| +|tr.wikipedia.org|✓|✓|| +|twitch.tv|✓|✓|| +|twitter.com|✓|✓|| +|uol.com.br|✓|✓|| +|ups.com|✓|✓|| +|urbandictionary.com|✓|✓|| +|usatoday.com|✓|✓|| +|usnews.com|✕|✓|TLS trust works fine. Needs `www.` else server doesn't respond in 15s, sends 403 on h2, Curl acts the same, geolocated?| +|usps.com|✓|✓|| +|verizon.com|✓|✓|| +|vk.com|✓|✓|| +|walmart.com|✓|✓|| +|washingtonpost.com|✓|✓|| +|weather.com|✓|✓|| +|webmd.com|✓|✓|| +|whatsapp.com|✓|✓|| +|wowhead.com|✓|✓|| +|wp.pl|✓|✓|| +|www.gov.uk|✓|✓|| +|xfinity.com|✓|✓|| +|yahoo.co.jp|✓|✓|| +|yahoo.com|✓|✓|| +|yandex.ru|✓|✓|| +|yellowpages.com|✓|✓|| +|yelp.com|✓|✓|| +|youtube.com|✓|✓|| +|zh.wikipedia.org|✓|✓|| +|zillow.com|✓|✓|| + +[1] +``` +wget -O- https://ahrefs.com/blog/most-visited-websites/ | grep most-visited-websites-us | \ + sed -E 's/class="column-2">/|/g' | tr '|' '\n' | \ + sed 's/<.*//g' | grep -v Domain | grep -v Josh | sort | uniq +``` + diff --git a/3rdparty/libwebsockets/READMEs/README.json-lejp.md b/3rdparty/libwebsockets/READMEs/README.json-lejp.md new file mode 100644 index 00000000..1471c17d --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.json-lejp.md @@ -0,0 +1,107 @@ +# LEJP JSON Stream Parser + +||| +|---|---|---| +|cmake| `LWS_WITH_LEJP`| +|Header| ./include/libwebsockets/lws-lejp.h| +|api-test| ./minimal-examples/api-tests/api-test-lejp/| +|test app| ./test-apps/test-lejp.c -> libwebsockets-test-lejp| + +LEJP is a lightweight JSON stream parser. + +The features are: + + - completely immune to input fragmentation, give it any size blocks of JSON as + they become available, 1 byte, or 100K at a time give identical parsing + results + - input chunks discarded as they are parsed, whole JSON never needed in memory + - nonrecursive, fixed stack usage of a few dozen bytes + - no heap allocations at all, just requires ~500 byte context usually on + caller stack + - creates callbacks to a user-provided handler as members are parsed out + - no payload size limit, supports huge / endless strings bigger than + system memory + - collates utf-8 text payloads into a 250-byte chunk buffer in the json parser + context object for ease of access + +## Type handling + +LEJP leaves all numbers in text form, they are signalled in different callbacks +according to int or float, but delivered as text strings in the first +`ctx->npos` chars of `ctx->buf`. + +For numeric types, you would typically use `atoi()` or similar to recover the +number as a host type. + +## Callback reasons + +The user callback does not have to handle any callbacks, it only needs to +process the data for the ones it is interested in. + +|Callback reason|JSON structure|Associated data| +|---|---|---| +|`LEJPCB_CONSTRUCTED`|Created the parse context|| +|`LEJPCB_DESTRUCTED`|Destroyed the parse context|| +|`LEJPCB_COMPLETE`|The parsing completed OK|| +|`LEJPCB_FAILED`|The parsing failed|| +|`LEJPCB_VAL_TRUE`|boolean true|| +|`LEJPCB_VAL_FALSE`|boolean false|| +|`LEJPCB_VAL_NULL`|explicit NULL|| +|`LEJPCB_PAIR_NAME`|The name part of a JSON `key: value` map pair|`ctx->buf`| +|`LEJPCB_VAL_STR_START`|A UTF-8 string is starting|| +|`LEJPCB_VAL_STR_CHUNK`|The next string chunk|`ctx->npos` bytes in `ctx->buf`| +|`LEJPCB_VAL_STR_END`|The last string chunk|`ctx->npos` bytes in `ctx->buf`| +|`LEJPCB_ARRAY_START`|An array is starting|| +|`LEJPCB_ARRAY_END`|An array has ended|| +|`LEJPCB_OBJECT_START`|A JSON object is starting|| +|`LEJPCB_OBJECT_END`|A JSON object has ended|| + +## Handling JSON UTF-8 strings + +When a string is parsed, an advisory callback of `LECPCB_VAL_STR_START` occurs +first. No payload is delivered with the START callback. + +Payload is collated into `ctx->buf[]`, the valid length is in `ctx->npos`. + +For short strings or blobs where the length is known, the whole payload is +delivered in a single `LECPCB_VAL_STR_END` callback. + +For payloads larger than the size of `ctx->buf[]`, `LECPCB_VAL_STR_CHUNK` +callbacks occur delivering each sequential bufferload. + +The last chunk (which may be zero length) is delievered by `LECPCB_VAL_STR_END`. + +## Parsing paths + +LEJP maintains a "parsing path" in `ctx->path` that represents the context of +the callback events. As a convenience, at LEJP context creation time, you can +pass in an array of path strings you want to match on, and have any match +checkable in the callback using `ctx->path_match`, it's 0 if no active match, +or the match index from your path array starting from 1 for the first entry. + +|CBOR element|Representation in path| +|---|---| +|JSON Array|`[]`| +|JSON Map|`.`| +|JSON Map entry key string|`keystring`| + + + +## Comparison with LECP (CBOR parser) + +LECP is based on the same principles as LEJP and shares most of the callbacks. +The major differences: + + - LEJP value callbacks all appear in `ctx->buf[]`, ie, floating-point is + provided to the callback in ascii form like `"1.0"`. CBOR provides a more + strict typing system, and the different type values are provided either in + `ctx->buf[]` for blobs or utf-8 text strtings, or the `item.u` union for + converted types, with additional callback reasons specific to each type. + + - CBOR "maps" use `_OBJECT_START` and `_END` parsing callbacks around the + key / value pairs. LEJP has a special callback type `PAIR_NAME` for the + key string / integer, but in LECP these are provided as generic callbacks + dependent on type, ie, generic string callbacks or integer ones, and the + value part is represented according to whatever comes. + + diff --git a/3rdparty/libwebsockets/READMEs/README.logging.md b/3rdparty/libwebsockets/READMEs/README.logging.md index 83a9a678..933a9208 100644 --- a/3rdparty/libwebsockets/READMEs/README.logging.md +++ b/3rdparty/libwebsockets/READMEs/README.logging.md @@ -2,9 +2,10 @@ # `lwsl_` logging apis -LWS provides logging arrangements that are not indirected through the -lws context, because logging may be needed before and after the context -existence. For that reason it's processwide. +LWS has traditionally provided logging arrangements that are not indirected +through the lws context, because logging may be needed before and after the +context existence. For that reason the original logging arrangements are +processwide. By default the logs are emitted on stdout, but this can be overridden using `lws_set_log_level()` and either syslog (provided by `lwsl_emit_syslog()`) @@ -100,6 +101,188 @@ is a wsi bound to the SS object from the first log to do the outgoing client act When user code wants to refer to a tagged object like a wsi or vhost, there are helpers that return a `const char *` containing the tag -`lws_wsi_tag(wsi)` -`lws_vh_tag(vh)` +|tag accessors| +|---| +|`lws_wsi_tag(wsi)`| +|`lws_vh_tag(vh)`| +|`lws_ss_tag(h)`| +# New logging context apis + +From v4.3 on lws additionally provides wrappers that issue logs into a +"log context" object, one of these is embedded in the lws_context, lws_vhost, +wsi, ss and sspc handles. These follow the same general approach as before, but +allow logs to be issued in "the context" of any of those objects, and to fall +back sanely if the object pointer is NULL. + +The traditional process scope logs and emit management remain available as +before, and if you do not set custom log contexts, the new log apis use the +processwide log context emit and mask as before too. + +Here's a summary of the differences: + +|Traditional process scope logs|New log context apis| +|---|---| +|Single processwide log context|Defaults to processwide, but object can use custom log contexts| +|Single processwide emit function|Emit function per log context| +|Single processwide log mask|log mask is in log context, objects can be bound to custom log contexts at creation time| +|Require trailing `\n` in format|Trailing `\n` added if not present| +|Manual `__func__`|`__func__` added in wrapper macros automatically| +|Manual tag addition|Object tag prepended automatically| +|No hierarchy|Log contexts may refer to parent log contexts, which may prepend to child logs| +|Macros per level (eg, `lwsl_err(...)`)|Macros per object type / level (eg, `lwsl_wsi_err(wsi, ...)`)| + +In addition to being able to control the emit function and log level for +individual log contexts, eg, for a particular wsi, the log functions understand +how to prepend object-specific information such as tags and `__func__` +automatically. They also do not need a trailing `\n` in the format string. So +the new context aware logs remove boilerplate from the logging calls while +making the log information more consistent. + +So comparing this kind of logging the processwide and log context aware ways: + +``` +[2021/06/25 09:39:34:7050] N: [669282|wsicli|4|GET/h1/libwebsockets.org|default]: _lws_generic_transaction_completed_active_conn: ... +``` + +|Type|Example code| +|---|---| +|Process scope apis|`lwsl_notice("%s: %s: mylog %d\n", __func__, lws_wsi_tag(wsi), n);`| +|New log context apis|`lwsl_wsi_notice(wsi, "mylog %d", n);`| + +The log context / object-aware apis do not replace the processwide logging but +augment it, and the new apis default to use the original processwide emit +function and log mask, so the behaviours are the same. The original processwide +log apis themselves are unchanged. + +At lws_context creation time, you can set the context info `.log_cx` to a user +defined log context which is inherited by objects created in that lws_context by +default. Vhost creation, wsi creation and ss / sspc creation all allow passing +a user log_cx to customize how logs for that object are handled. + +## Using the new logging apis + +This table describes the different ways to issue an ERROR verbosity log, it +works the same for info, notice, warn, etc. + +|Scope|Api example|Functionality| +|---|---|---| +|Old, Processwide|lwsl_err(...)|Traditional processwide error log| +|lws_context|lwsl_cx_err(context, ...)|error log bound to lws_context| +|lws_vhost|lwsl_vhost_err(vh, ...)|error log bound to lws_vhost| +|lws_wsi|lwsl_wsi_err(wsi, ...)|error log bound to wsi| +|lws_ss|lwsl_ss_err(handle, ...)|error log bound to secure stream| + +Similarly hexdumps can be bound to different log contexts + +|Scope|Api example|Functionality| +|---|---|---| +|Old, Processwide|lwsl_hexdump_err(...)|Traditional processwide error hexdump| +|lws_context|lwsl_hexdump_cx_err(context, ...)|error hexdump bound to lws_context| +|lws_vhost|lwsl_hexdump_vhost_err(vh, ...)|error hexdump bound to lws_vhost| +|lws_wsi|lwsl_hexdump_wsi_err(wsi, ...)|error hexdump bound to wsi| +|lws_ss|lwsl_hexdump_ss_err(handle, ...)|error hexdump bound to secure stream| + +## Creating and using custom log contexts + +The log context object is public, in `libwebsockets/lws-logs.h`, currently it +is like this + +``` +typedef void (*lws_log_emit_t)(int level, const char *line); +typedef void (*lws_log_emit_cx_t)(struct lws_log_cx *cx, int level, + const char *line, size_t len); +typedef void (*lws_log_prepend_cx_t)(struct lws_log_cx *cx, void *obj, + char **p, char *e); +typedef void (*lws_log_use_cx_t)(struct lws_log_cx *cx, int _new); +typedef struct lws_log_cx { + union { + lws_log_emit_t emit; /* legacy emit function */ + lws_log_emit_cx_t emit_cx; /* LLLF_LOG_CONTEXT_AWARE */ + } u; + lws_log_use_cx_t refcount_cb; + /**< NULL, or a function called after each change to .refcount below, + * this enables implementing side-effects like opening and closing + * log files when the first and last object binds / unbinds */ + lws_log_prepend_cx_t prepend; + /**< NULL, or a cb to optionally prepend a string to logs we are a + * parent of */ + struct lws_log_cx *parent; + /**< NULL, or points to log ctx we are a child of */ + void *opaque; + /**< ignored by lws, used to pass config to emit_cx, eg, filepath */ + void *stg; + /**< ignored by lws, may be used a storage by refcount_cb / emit_cx */ + uint32_t lll_flags; + /**< mask of log levels we want to emit in this context */ + int32_t refcount; + /**< refcount of objects bound to this log context */ +} lws_log_cx_t; +``` + +The emit function is a union because the traditional logs and the old emit +functions are also implemented using the new log contexts internally. For +new log context-aware code, you would use `.u.emit_cx` and set the flag +`LLLF_LOG_CONTEXT_AWARE` on `.lll_flags`. + +Lws also exports some common emit and refcount functions so you don't have to +reinvent the wheel + +|Dest|emit member|`.lll_flags`|emit|`.refcount_cb`|`.opaque`| +|---|---|---|---|---|---| +|stderr|`.u.emit`|-|`lwsl_emit_stderr`|NULL|NULL| +|file|`.u.emit_cx`|`LLLF_LOG_CONTEXT_AWARE`|`lws_log_emit_cx_file`|`lws_log_use_cx_file`|`(const char *)filepath`| + +For example, a custom log context that emits to a configurable file can be +declared like this (lws exports the needed helpers already) + +``` +static lws_log_cx_t my_log_cx = { + .lll_flags = LLLF_LOG_CONTEXT_AWARE | + LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER, + .refcount_cb = lws_log_use_cx_file, + .u.emit_cx = lws_log_emit_cx_file, + .opaque = "/tmp/mylogpath.log" /* also settable at runtime */ +}; +``` + +To bind the lws_context to this log context, set `log_cx` in the context +creation info struct + +``` + info.log_cx = &my_log_cx; +``` + +### Log context hierarchy + +Log contexts may also point to a parent log context... the top level log context +defines the emit function to be used, but parent log contexts are consulted by +calling their prepend function if any, to annotate logs with information from +parent levels. + +### Log context prepend function + +Logs contexts may define a "prepend" function callback, that knows how to +represent the object in a brief string to be prepended to other logs. For +example the wsi-aware log context layer knows how to provide the wsi tag +when called. + +Prepend functions should add `:` after their output, if any, since these +will appear before the start of other logs. + +### Log context opaque member + +The `.opaque` member is available for passing in configuration to the emit and +refcount_cb members. Lws does not use this itself at all. + +### Log context refcounting + +An expected use for custom log contexts is emitting to a specific file, and +then binding one or more objects to that log context. Since it's too expensive +to keep opening and closing the output file per log, it means we need to know +when we bind to the first object and unbind from the last, so we can keep the +file handle open. + +For this reason the log contexts have a refcount, and an opaque `void *stg` +availble for the emit and refounct_cb to use how they see fit, eg, for storing +the output log file descriptor. diff --git a/3rdparty/libwebsockets/READMEs/README.lws_cache.md b/3rdparty/libwebsockets/READMEs/README.lws_cache.md new file mode 100644 index 00000000..9a471c12 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.lws_cache.md @@ -0,0 +1,160 @@ +# lws_cache: Flexible single and multilevel caching + +lws_cache implements a single- or multi-level cache for generic payload items +that are **keyed by a unique string**. + +![lws_cache overview](../doc-assets/lws_cache-1.png) + +L1 cache is always stored on heap, but it may be hooked up to additional levels +of cache objects with different backing storage. The last level always contains +a complete set of cached items, earlier levels may be empty or contain a partial +set of objects. + +User code can define its own subclassed lws_cache objects with custom storage +formats and media, while being able to take advantage of a suitably-sized L1 +heap cache to minimize the cost of repeated access. + +![lws_cache overview](../doc-assets/lws_cache-2.png) + +You can find examples of how to create, use and destroy single and multilevel +caches in `minimal-examples/api-tests/api-test-lws_cache` + +## Cache size restriction, LRU and TTL + +The max heap footprint of its items and max number of items can be capped. LRU +tracking is performed so the least recently relevant items are evicted first. +It's also possible to limit the maximum size of any single payload. + +Time To Live (TTL) tracking is also performed automatically, so cached items +auto-expire if a non-zero TTL is provided when the object is created. A user +callback can be defined to get called when an item is about to be removed from +a particular cache level, in case any housekeeping needed. + +## Atomicity + +Items in L1 can be accessed in heap casually and reliably if the following is +borne in mind: + + - Any return to the event loop may perform removal of cache items due to TTL +expiry + + - Any operation that writes new items may evict items from non-last +cache levels which have limits to the footprint or item count to make room for +it, using LRU ordering. + +In short process cache results before returning to the event loop or writing +or removing items in the cache. + +## Cache creation + +Caches are created using an info struct `struct lws_cache_creation_info` +that should be zeroed down. Most members are optional and can be left at zero, +a pointer to the lws_context and a short cache name are mandatory. + +``` +struct lws_cache_ttl_lru * +lws_cache_create(const struct lws_cache_creation_info *info); +``` + +How caches work is defined by an "ops struct" that the cache is bound to at +creation time. `lws_cache_ops_heap` ops struct is provided by lws, you can +define your own to implement your own specialized cache level. See +`./include/libwebsockets/lws-cache-ttl.h` for the definition. + +## Cache destruction + +Created cache levels should be destroyed when you are finished with them. + +``` +void +lws_cache_destroy(struct lws_cache_ttl_lru **cache); +``` + +For L1, in heap, this frees any allocations. For other levels, eg, with file +storage for the items, this would close the file and leave any entries as they +are. + +## Writethrough + +``` +int +lws_cache_write_through(struct lws_cache_ttl_lru *cache, + const char *specific_key, const uint8_t *source, + size_t size, lws_usec_t expiry, void **ppay); +``` + +The combined caches are always accessed via the L1 cache, writing new items is +done at L1 and writes through to each cache layer immediately, so new items go +into the backing store without delay, but are available from heap for read. + +If existing keys are rewritten, the previous item of the same key is deleted +from all levels of the cache before writing the new one. + +## Removal + +Removal also is performed at all cache levels at once. + +``` +int +lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key); +``` + +internally earlier cache levels can evict cached items just at their level, but +this is triggered automatically and not by api. + +A wildcard key is supported, removing all items matching, eg "myitem*". + +## Get by key + +``` +int +lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key, + const void **pdata, size_t *psize); +``` + +Apis are provided to get the blob related to a specific key, if it exists at +any cache layer. Again this should use L1, it will bring a copy of the item +into L1 if one is not already there, so it can be accessed from heap. + +## Lookup with wildcards + +``` +int +lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key, + const void **pdata, size_t *psize); +``` + +lws_cache also supports **lookup** queries that contain wildcards or otherwise match +on multiple keys according to cache-specific rules. These queries do not return +a single item, instead they return lists of keys that match, in a blob of its +own that is also cached in L1. + +The user can walk the lookup results blob using a provided helper api + +``` +int +lws_cache_results_walk(lws_cache_results_t *walk_ctx); +``` + +After recovering each result key this way, the user code can use the _get api +to access the blob for each indiviudally. + +The lookup results themselves are cached in L1, any new key that matches the +wildcard lookup in any cached results, or any deletion of items with keys +matching the cached wildcard lookup invalidate the affected cached lookup +results so they will be regenerated next time. + +In the typical case after a lookup, at least for a while the lookup results blob +and all items mentioned in the lookup results will already be in L1 and cheaply +accessible. + +## Expunging + +An api is also provided to "expunge" or completely empty all cache levels and +corresponding backing stores. + +``` +int +lws_cache_expunge(struct lws_cache_ttl_lru *cache); +``` + diff --git a/3rdparty/libwebsockets/READMEs/README.lws_map.md b/3rdparty/libwebsockets/READMEs/README.lws_map.md new file mode 100644 index 00000000..7772d660 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.lws_map.md @@ -0,0 +1,117 @@ +# lws_map generic map abstraction + +||| +|---|---|---| +|cmake|core feature| +|Header| ./include/libwebsockets/lws-map.h| +|api-test| ./minimal-examples/api-tests/api-test-lws_map/| + +lws_map provides a robust abstraction for containing a collection of items that +map key objects to value objects, where both the key and value objects may +differ in size each time and have any type. + +Its one-level linked-list hashtables are useful up to hundreds or low thousands +of items in the map on may platforms. + +The map itself and the items inside it are opaque. + +## Creating and destroying the map + +The user should prepare a `lws_map_info_t` object, it's legal for it to be +all zeros to select defaults, an 8-way hashtable with item allocation from heap, +simple bytewise key comparison, and xor / shift key hashing. These are often +what you want simplifying construction. + +The info object allows user override of item allocator, freeing, key comparison +and object hashing, allowing custom objects to be keys if desired. + +Custom allocator / free implementations for using lwsac for item allocation are +provided to simplify that case. + +Just call `lws_map_create()` with the info struct to create the map, later it +and all its contents can be destroyed with `lws_map_destroy()`. The info struct +can go out of scope immediately after the create call. + +``` +lws_map_t * +lws_map_create(const lws_map_info_t *info); +void +lws_map_destroy(lws_map_t **pmap); +``` + +## Keys in lws_map + +Items are managed in the map by a key, this may be, eg, a string, but it also +can be an arbitrary object itself. If comparing keys takes more than a simple +bytewise comparison, the map creation info struct ._compare() operation should +be overridden with a user-supplied one that knows how to use the user's +custom key objects. + +Keys are not required to be the same length, so objects with variable size +overallocation can be used as keys. + +Keys and values are copied into allocations inside the map, the original objects +they are copied from may go out of scope after item creation assuming there are +no pointers to them copied in the objects themselves. + +## Adding items to a map + +The map's info._alloc allocator is used for creating items. By default that +just creates into the heap. + +If you create a new item with the same key as an existing one, the existing one +is destroyed before the new one is created. So there is only one item allowed +at a given key at a time. + +To allocate and create a new item containing the key and value, use +`lws_map_item_create()` + +``` +lws_map_item_t * +lws_map_item_create(lws_map_t *map, + const lws_map_key_t key, size_t keylen, + const lws_map_value_t value, size_t valuelen); +``` + +Eg, + +``` + if (!lws_map_item_create(map, (lws_map_key_t)&my_key, + sizeof(my_key), + (lws_map_value_t)"4567", 4)) + /* fail */ +``` + + +In the case the key is a string, there is a ..._ks wrapper to simplify usage + +``` + if (!lws_map_item_create_ks(map, "123", (lws_map_value_t)"4567", 4)) + /* fail */ +``` + +## Lookups in the map + +You can retreive a pointer to an item in the map with a give key using + +``` +lws_map_item_t * +lws_map_item_lookup(lws_map_t *map, const lws_map_key_t key, size_t keylen); +``` + +The item is opaque, but there are accessors + +|Accessor|Function| +|---|---| +|`lws_map_item_key(lws_map_item_t *_item)`|get a pointer to the item key| +|`lws_map_item_value(lws_map_item_t *_item)`|get a pointer to the item value| +|`lws_map_item_key_len(lws_map_item_t *_item)`|get the key length| +|`lws_map_item_value_len(lws_map_item_t *_item)`|get the value length| + +Again there is a ..._ks() helper to simplify C strings as keys + +``` + item = lws_map_item_lookup_ks(map, "abc"); + if (!item) + /* fail */ +``` diff --git a/3rdparty/libwebsockets/READMEs/README.lws_system.md b/3rdparty/libwebsockets/READMEs/README.lws_system.md index 05afa470..e1a91eea 100644 --- a/3rdparty/libwebsockets/READMEs/README.lws_system.md +++ b/3rdparty/libwebsockets/READMEs/README.lws_system.md @@ -207,6 +207,7 @@ The generic states defined are: |`LWS_SYSTATE_AUTH2`|Optional second access token for different services| |`LWS_SYSTATE_OPERATIONAL`|The system is ready for user code to work normally| |`LWS_SYSTATE_POLICY_INVALID`|All connections are being dropped because policy information is changing. It will transition back to `LWS_SYSTATE_INITIALIZED` and onward to `OPERATIONAL` again afterwards with the new policy| +|`LWS_SYSTATE_CONTEXT_DESTROYING`|Context is going down and smd with it| ### Inserting a notifier diff --git a/3rdparty/libwebsockets/READMEs/README.tcp_fastopen.md b/3rdparty/libwebsockets/READMEs/README.tcp_fastopen.md new file mode 100644 index 00000000..f9ca8eb3 --- /dev/null +++ b/3rdparty/libwebsockets/READMEs/README.tcp_fastopen.md @@ -0,0 +1,32 @@ +# `TCP_FASTOPEN` support in lws + +Lws supports enabling TCP_FASTOPEN oper-vhost for listen sockets. + +## Enabling per vhost serving + +Set the `info.fo_listen_queue` to nonzero at vhost creation. Different +platforms interpret this number differently, zero always disables it +but on Linux, the number is interpreted as a SYN queue length. + +On FreeBSD, OSX and Windows, the number is basically a bool, with the +extra restriction OSX and Windows only allows 0 or 1. + +## Enabling Linux for serving with TCP_FASTOPEN + +To configure the kernel for listening socket TCP_FASTOPEN, you need + +``` +# sysctl -w net.ipv4.tcp_fastopen=3 +``` + +## Enabling BSD for serving with TCP_FASTOPEN + +At least on FreeBSD, you need to set the net.inet.tcp.fastopen.enabled +sysctl to 1 + +## Enabling Windows for serving with TCP_FASTOPEN + +``` +> netsh int tcp set global fastopenfallback=disabled +> netsh int tcp show global +``` diff --git a/3rdparty/libwebsockets/READMEs/README.tls-sessions.md b/3rdparty/libwebsockets/READMEs/README.tls-sessions.md index 1c292094..5247555c 100644 --- a/3rdparty/libwebsockets/READMEs/README.tls-sessions.md +++ b/3rdparty/libwebsockets/READMEs/README.tls-sessions.md @@ -59,6 +59,20 @@ be treated with caution. Filling, expiring and consulting the session cache for client connections is performed automatically. +### tls library differences + +Mbedtls supports clientside session caching in lws, but it does not have a +session message arrival callback to synchronize updating the client session +cache like openssl does. + +Separately, the session cb in boringssl is reportedly nonfunctional at the +moment. + +To solve both cases, lws will schedule a check for the session at +500ms after +the tls negotiation completed, and for the case the connection doesn't last +500ms or the server is slow issuing the message, also attempt to update the +cache at the time the tls connection object is closing. + ### Session namespacing in lws Internally sessions are referred to by a vhostname.hostname.port tuple. diff --git a/3rdparty/libwebsockets/changelog b/3rdparty/libwebsockets/changelog index 5debeb60..e1f48306 100644 --- a/3rdparty/libwebsockets/changelog +++ b/3rdparty/libwebsockets/changelog @@ -1,6 +1,54 @@ Changelog --------- +v4.3.0 +====== + + - Add full CBOR stream parsing and writing support, with huge + amount of test vectors and resumable printf type write apis + See ./READMEs/README.cbor-lecp.md + - Add COSE key and signing / validation support with huge amount of + test vectors + cose_sign[1] ES256/384/512, RS256/384/512 + cose_mac0 HS256/384/512 + See ./READMEs/README.cbor-cose.md + - JIT Trust: for constrained devices, provides a way to determine the + trusted CA certs the peer requires, and instantiate just those. + This allows generic client browsing without the overhead of ~130 + x.509 CA certs in memory permanently. + See ./READMEs/README.jit-trust.md + - Add support for client Netscape cookie jar with caching + - Secure Streams: issue LWSSSCS_EVENT_WAIT_CANCELLED state() when + lws_cancel_service() called, so cross-thread events can be handled + in SS + - Actively assert() on attempt to destroy SS handles still active in + the call stack, use DESTROY_ME returns instead so caller can choose + how to handle it. + - Improved Client Connection Error report strings for tls errors + - SMP: Use a private fakewsi for PROTOCOL_INIT so pts cannot try to + use the same one concurrently + - MbedTLS v3 support for all release changes, as well as retaining + support for v2.x + - MQTT client: support QoS2 + - Event lib ops can now be set at context creation time directly, + bringing full event lib hooking to custom event loops. See + minimal-http-server-eventlib-custom + - Extra APIs to recover AKID and SKID from x.509 in mbedtls and openssl + - Improve http redirect to handle h2-> h2 cleanly + - IPv4+6 listen sockets on vhosts are now done with two separate + sockets bound individually to AF_INET and AF_INET6 addresses, + handled by the same vhost listen flow. + - Improved tls restriction handling + - Log contexts: allow objects to log into local logging contexts, by + lws_context, vhost, wsi and ss handle. Each context has its own + emit function and log level. See ./READMEs/README.logging.md + - Upgrade compiler checking to default to -Werror -Wall -Wextra + - Fault injection apis now also support pseudo-random number binding + within a specified range, eg, + --fault-injection "f1(10%),f1_delay(123..456)" + - Remove LWS_WITH_DEPRECATED_THINGS, remove master branch + - Interface binding now uses ipv6 scoring to select bind address + v4.2.0 ====== diff --git a/3rdparty/libwebsockets/cmake/FindOpenSSLbins.cmake b/3rdparty/libwebsockets/cmake/FindOpenSSLbins.cmake index 235962f2..4d5c37bd 100644 --- a/3rdparty/libwebsockets/cmake/FindOpenSSLbins.cmake +++ b/3rdparty/libwebsockets/cmake/FindOpenSSLbins.cmake @@ -44,7 +44,7 @@ if(OPENSSL_FOUND) 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}) + 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 "") diff --git a/3rdparty/libwebsockets/cmake/LwsCheckRequirements.cmake b/3rdparty/libwebsockets/cmake/LwsCheckRequirements.cmake index 76cf9e50..9fc76e69 100644 --- a/3rdparty/libwebsockets/cmake/LwsCheckRequirements.cmake +++ b/3rdparty/libwebsockets/cmake/LwsCheckRequirements.cmake @@ -4,6 +4,9 @@ # If we are being built externally, confirm installed lws was configured to # support reqconfig, else error out with a helpful message about the problem. # + +include(CheckIncludeFile) + MACRO(require_lws_config reqconfig _val result) if (DEFINED ${reqconfig}) @@ -22,6 +25,9 @@ MACRO(require_lws_config reqconfig _val result) set(SAME 0) endif() + string(COMPARE EQUAL "${result}" requirements _cmp) + + # we go in the first clause if in-tree if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) if (${_val}) message("${SAMP}: skipping as lws being built without ${reqconfig}") @@ -45,7 +51,7 @@ MACRO(require_lws_config reqconfig _val result) set(MET 0) endif() endif() - if (NOT MET) + if (NOT MET AND _cmp) if (${_val}) message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") else() @@ -69,7 +75,9 @@ MACRO(require_pthreads result) if (WIN32) set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) else() - set(PTHREAD_LIB pthread) + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "QNX") + set(PTHREAD_LIB pthread) + endif() endif() endif() ENDMACRO() diff --git a/3rdparty/libwebsockets/cmake/libwebsockets-config.cmake.in b/3rdparty/libwebsockets/cmake/libwebsockets-config.cmake.in index 49482ca1..8ba97e6f 100644 --- a/3rdparty/libwebsockets/cmake/libwebsockets-config.cmake.in +++ b/3rdparty/libwebsockets/cmake/libwebsockets-config.cmake.in @@ -1,14 +1,14 @@ # - Config file for lws # It defines the following variables -# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar +# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for lws # LIBWEBSOCKETS_LIBRARIES - libraries to link against # Get the path of the current file. get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +list(APPEND CMAKE_MODULE_PATH ${libwebsockets_DIR}) -# Set the include directories. -set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@") +set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@" "@LWS_PUBLIC_INCLUDES@") # Include the project Targets file, this contains definitions for IMPORTED targets. include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) @@ -17,8 +17,20 @@ include(${LWS_CMAKE_DIR}/LwsCheckRequirements.cmake) # IMPORTED targets from LibwebsocketsTargets.cmake set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) +# These are additional include paths you will need +foreach(item "${LIBWEBSOCKETS_INCLUDE_DIRS}") + include_directories(${item}) + set(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}" ${item}) +endforeach() + # 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() +# Move boilerplate for consuming cmake files into here + +include(CheckIncludeFile) +include(CheckCSourceCompiles) +set(requirements 1) + diff --git a/3rdparty/libwebsockets/cmake/lws_config.h.in b/3rdparty/libwebsockets/cmake/lws_config.h.in index a7fcfca9..f3f4a9d7 100644 --- a/3rdparty/libwebsockets/cmake/lws_config.h.in +++ b/3rdparty/libwebsockets/cmake/lws_config.h.in @@ -47,7 +47,10 @@ #cmakedefine LWS_HAVE_EVP_aes_192_cfb128 #cmakedefine LWS_HAVE_EVP_aes_256_cfb8 #cmakedefine LWS_HAVE_EVP_aes_256_cfb128 +#cmakedefine LWS_HAVE_EVP_aes_128_ofb #cmakedefine LWS_HAVE_EVP_aes_128_xts +#cmakedefine LWS_HAVE_EVP_aes_128_ctr +#cmakedefine LWS_HAVE_EVP_aes_128_ecb #cmakedefine LWS_HAVE_EVP_PKEY_new_raw_private_key #cmakedefine LWS_HAVE_EXECVPE #cmakedefine LWS_HAVE_LOCALTIME_R @@ -72,9 +75,13 @@ #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_ca_chain #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_own_cert #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_authmode +#cmakedefine LWS_HAVE_mbedtls_ssl_set_verify +#cmakedefine LWS_HAVE_mbedtls_x509_crt_parse_file #cmakedefine LWS_HAVE_MBEDTLS_NET_SOCKETS +#cmakedefine LWS_HAVE_MBEDTLS_AUTH_KEY_ID #cmakedefine LWS_HAVE_NEW_UV_VERSION_H #cmakedefine LWS_HAVE_OPENSSL_ECDH_H +#cmakedefine LWS_HAVE_OPENSSL_STACK #cmakedefine LWS_HAVE_PIPE2 #cmakedefine LWS_HAVE_EVENTFD #cmakedefine LWS_HAVE_PTHREAD_H @@ -95,6 +102,7 @@ #cmakedefine LWS_HAVE__STAT32I64 #cmakedefine LWS_HAVE_STDINT_H #cmakedefine LWS_HAVE_SYS_CAPABILITY_H +#cmakedefine LWS_HAVE_TIMEGM #cmakedefine LWS_HAVE_TLS_CLIENT_METHOD #cmakedefine LWS_HAVE_TLSV1_2_CLIENT_METHOD #cmakedefine LWS_HAVE_SUSECONDS_T @@ -137,6 +145,7 @@ #cmakedefine LWS_WITH_BORINGSSL #cmakedefine LWS_WITH_CGI #cmakedefine LWS_WITH_CONMON +#cmakedefine LWS_WITH_COSE #cmakedefine LWS_WITH_CUSTOM_HEADERS #cmakedefine LWS_WITH_DEPRECATED_LWS_DLL #cmakedefine LWS_WITH_DETAILED_LATENCY @@ -162,6 +171,8 @@ #cmakedefine LWS_WITH_HTTP_UNCOMMON_HEADERS #cmakedefine LWS_WITH_IPV6 #cmakedefine LWS_WITH_JOSE +#cmakedefine LWS_WITH_CBOR +#cmakedefine LWS_WITH_CBOR_FLOAT #cmakedefine LWS_WITH_LEJP #cmakedefine LWS_WITH_LIBEV #cmakedefine LWS_WITH_LIBEVENT @@ -174,6 +185,7 @@ #cmakedefine LWS_WITH_NETLINK #cmakedefine LWS_WITH_NETWORK #cmakedefine LWS_WITH_NO_LOGS +#cmakedefine LWS_WITH_CACHE_NSCOOKIEJAR #cmakedefine LWS_WITH_CLIENT #cmakedefine LWS_WITHOUT_EXTENSIONS #cmakedefine LWS_WITH_SERVER @@ -191,6 +203,8 @@ #cmakedefine LWS_WITH_SECURE_STREAMS_PROXY_API #cmakedefine LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY #cmakedefine LWS_WITH_SECURE_STREAMS_AUTH_SIGV4 +#cmakedefine LWS_WITH_SECURE_STREAMS_BUFFER_DUMP +#cmakedefine LWS_WITH_SS_DIRECT_PROTOCOL_STR #cmakedefine LWS_WITH_SELFTESTS #cmakedefine LWS_WITH_SEQUENCER #cmakedefine LWS_WITH_SERVER_STATUS @@ -210,6 +224,7 @@ #cmakedefine LWS_WITH_SYS_STATE #cmakedefine LWS_WITH_THREADPOOL #cmakedefine LWS_WITH_TLS +#cmakedefine LWS_WITH_TLS_JIT_TRUST #cmakedefine LWS_WITH_TLS_SESSIONS #cmakedefine LWS_WITH_UDP #cmakedefine LWS_WITH_ULOOP diff --git a/3rdparty/libwebsockets/contrib/cross-aarch64-qnx.cmake b/3rdparty/libwebsockets/contrib/cross-aarch64-qnx.cmake new file mode 100644 index 00000000..404d1d98 --- /dev/null +++ b/3rdparty/libwebsockets/contrib/cross-aarch64-qnx.cmake @@ -0,0 +1,50 @@ +# +# CMake Toolchain file for crosscompiling aarch64 for QNX. +# +# This can be used when running cmake in the following way: +# cd build/ +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-aarch64-qnx.cmake +# + +# adapt to your toolchain path +set(CROSS_PATH /var/toolchain/qnx5.4/host/linux/x86_64/usr) + +# Target operating system name. +set(CMAKE_SYSTEM_NAME QNX) +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +# Name of C compiler. +set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/ntoaarch64-gcc") +set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/ntoaarch64-g++") + +set(CMAKE_C_FLAGS "-Wno-error") +set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") + +# +# 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() + +# 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 --git a/3rdparty/libwebsockets/doc-assets/jit-trust-logo.png b/3rdparty/libwebsockets/doc-assets/jit-trust-logo.png new file mode 100644 index 00000000..86f7a0af Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/jit-trust-logo.png differ diff --git a/3rdparty/libwebsockets/doc-assets/jit-trust-overview.png b/3rdparty/libwebsockets/doc-assets/jit-trust-overview.png new file mode 100644 index 00000000..1250693b Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/jit-trust-overview.png differ diff --git a/3rdparty/libwebsockets/doc-assets/jit-trust-paths.png b/3rdparty/libwebsockets/doc-assets/jit-trust-paths.png new file mode 100644 index 00000000..395d883d Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/jit-trust-paths.png differ diff --git a/3rdparty/libwebsockets/doc-assets/jit-trust-single-trust.png b/3rdparty/libwebsockets/doc-assets/jit-trust-single-trust.png new file mode 100644 index 00000000..67758c51 Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/jit-trust-single-trust.png differ diff --git a/3rdparty/libwebsockets/doc-assets/jit-trust-system-trust.png b/3rdparty/libwebsockets/doc-assets/jit-trust-system-trust.png new file mode 100644 index 00000000..be2b99be Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/jit-trust-system-trust.png differ diff --git a/3rdparty/libwebsockets/doc-assets/lws_cache-1.png b/3rdparty/libwebsockets/doc-assets/lws_cache-1.png new file mode 100644 index 00000000..260677d8 Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/lws_cache-1.png differ diff --git a/3rdparty/libwebsockets/doc-assets/lws_cache-2.png b/3rdparty/libwebsockets/doc-assets/lws_cache-2.png new file mode 100644 index 00000000..ab69c3dc Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/lws_cache-2.png differ diff --git a/3rdparty/libwebsockets/doc-assets/work.png b/3rdparty/libwebsockets/doc-assets/work.png new file mode 100644 index 00000000..37b38011 Binary files /dev/null and b/3rdparty/libwebsockets/doc-assets/work.png differ diff --git a/3rdparty/libwebsockets/include/libwebsockets.h b/3rdparty/libwebsockets/include/libwebsockets.h index 72151617..8fb98c34 100644 --- a/3rdparty/libwebsockets/include/libwebsockets.h +++ b/3rdparty/libwebsockets/include/libwebsockets.h @@ -125,7 +125,11 @@ typedef int suseconds_t; #define LWS_EXTERN #endif +#if defined(__MINGW32__) +#define LWS_INVALID_FILE -1 +#else #define LWS_INVALID_FILE INVALID_HANDLE_VALUE +#endif #define LWS_SOCK_INVALID (INVALID_SOCKET) #define LWS_O_RDONLY _O_RDONLY #define LWS_O_WRONLY _O_WRONLY @@ -287,6 +291,18 @@ typedef int suseconds_t; #include #include #include +#include + +#if !defined(MBEDTLS_PRIVATE) +#define MBEDTLS_PRIVATE(_q) _q +#endif + +#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR == 0) +#define MBEDTLS_PRIVATE_V30_ONLY(_q) MBEDTLS_PRIVATE(_q) +#else +#define MBEDTLS_PRIVATE_V30_ONLY(_q) _q +#endif + #endif #else #include @@ -378,8 +394,12 @@ struct lws; #if defined(_WIN32) #if !defined(LWS_WIN32_HANDLE_TYPES) typedef SOCKET lws_sockfd_type; +#if defined(__MINGW32__) +typedef int lws_filefd_type; +#else typedef HANDLE lws_filefd_type; #endif +#endif #define lws_pollfd pollfd @@ -566,8 +586,11 @@ struct lws_vhost; struct lws; #include +#include + #include #include +#include #if defined(LWS_WITH_SYS_SMD) #include #endif @@ -608,7 +631,11 @@ struct lws; #if defined(LWS_WITH_FILE_OPS) #include #endif +#include + #include +#include +#include #include #include #include @@ -638,7 +665,6 @@ struct lws; #include #endif -#include #include #include #include diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-cache-ttl.h b/3rdparty/libwebsockets/include/libwebsockets/lws-cache-ttl.h new file mode 100644 index 00000000..9942dc7d --- /dev/null +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-cache-ttl.h @@ -0,0 +1,348 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 lws_cache_ttl Cache supporting expiry + * ##Cache supporting expiry + * + * These apis let you quickly and reliably implement caches of named objects, + * that have a "destroy-by date" and cache limits that will be observed. + * + * You can instantiate as many caches as you need. The first one must be an + * L1 / heap cache type, it can have parents and grandparents of other types + * which are accessible why writing / looking up and getting from the L1 cache. + * The outer "cache" layer may persistently store items to a backing store. + * + * Allocated object memory is entirely for the use of user code, up to the + * requested size. + * + * The key name for the listed objects may be any string chosen by the user, + * there is no special length limit as it is also allocated. + * + * Both expiry and LRU orderings are kept so it is easy to find out usage + * ordering and when the next object that will expire. + * + * Cached objects may be destroyed any time you go around the event loop, when + * you allocate new objects (to keep the whole cache under the specified limit), + * or when their expiry time arrives. So you shouldn't keep copies of pointers + * to cached objects after returning to the event loop. + */ +///@{ + + +struct lws_cache_ttl_lru; + +/** + * lws_cache_write_through() - add a new cache item object in all layers + * + * \param cache: the existing cache to allocate the object in + * \param specific_key: a key string that identifies the item in the cache + * \param source: optional payload for the cached item, NULL means caller will + * write the payload + * \param size: the size of the object to allocate + * \param expiry: the usec time that the object will autodestroy + * \param ppay: NULL, or a pointer to a void * to be set to the L1 payload + * + * If an item with the key already exists, it is destroyed before allocating a + * new one. + * + * Returns 0 if successful. The written entry will be scheduled to be auto- + * destroyed when \p expiry occurs. + * + * Adding or removing cache items may cause invalidation of cached queries. + */ +LWS_VISIBLE LWS_EXTERN int /* only valid until return to event loop */ +lws_cache_write_through(struct lws_cache_ttl_lru *cache, + const char *specific_key, const uint8_t *source, + size_t size, lws_usec_t expiry, void **ppay); + +typedef struct lws_cache_match { + lws_dll2_t list; + lws_usec_t expiry; + /* earliest expiry amongst results */ + size_t payload_size; + /**< the payload is not attached here. This is a hint about what + * (*get)() will return for this tag name. + */ + size_t tag_size; + + /* tag name + NUL is overcommitted */ +} lws_cache_match_t; + +/** + * lws_cache_heap_lookup() - get a list of matching items + * + * \param cache: the cache to search for the key + * \param wildcard_key: the item key string, may contain wildcards + * \param pdata: pointer to pointer to be set to the serialized result list + * \param psize: pointer to size_t to receive length of serialized result list + * + * This finds all unique items in the final cache that match search_key, which + * may contain wildcards. It does not return the payloads for matching items, + * just a list of specific tags in the that match. + * + * If successful, results are provided in a serialized list format, in no + * particular order, each result has the following fields + * + * - BE32: payload size in bytes (payload itself is not included) + * - BE32: specific tag name length in bytes + * - chars: tag name with terminating NUL + * + * These serialized results are themselves cached in L1 cache (only) and the + * result pointers are set pointing into that. If the results are still in L1 + * cache next time this api is called, the results will be returned directly + * from that without repeating the expensive lookup on the backup store. That + * is why the results are provided in serialized form. + * + * The cached results list expiry is set to the earliest expiry of any listed + * item. Additionally any cached results are invalidated on addition or + * deletion (update is done as addition + deletion) of any item that would + * match the results' original wildcard_key. For the typical case new items + * are rare compared to lookups, this is efficient. + * + * Lookup matching does not itself affect LRU or cache status of the result + * itsems. Typically user code will get the lookup results, and then perform + * get operations on each item in its desired order, that will bring the items + * to the head of the LRU list and occupy L1 cache. + * + * Returns 0 if proceeded alright, or nonzero if error. If there was an error, + * any partial results set has been deallocated cleanly before returning. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key, + const void **pdata, size_t *psize); + +/** + * lws_cache_item_get() - bring a specific item into L1 and get payload info + * + * \param cache: the cache to search for the key + * \param specific_key: the key string of the item to get + * \param pdata: pointer to a void * to be set to the payload in L1 cache + * \param psize: pointer to a size_t to be set to the payload size + * + * If the cache still has an item matching the key string, it will be destroyed. + * + * Adding or removing cache items may cause invalidation of cached queries. + * + * Notice the cache payload is a blob of the given size. If you are storing + * strings, there is no NUL termination unless you stored them with it. + * + * Returns 0 if successful. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key, + const void **pdata, size_t *psize); + +/** + * lws_cache_item_remove() - remove item from all cache levels + * + * \param cache: the cache to search for the key + * \param wildcard_key: the item key string + * + * Removes any copy of any item matching the \p wildcard_key from any cache + * level in one step. + * + * Adding or removing cache items may cause invalidation of cached queries + * that could refer to the removed item. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key); + +/** + * lws_cache_footprint() - query the amount of storage used by the cache layer + * + * \param cache: cache to query + * + * Returns number of payload bytes stored in cache currently + */ +LWS_VISIBLE LWS_EXTERN uint64_t +lws_cache_footprint(struct lws_cache_ttl_lru *cache); + +/** + * lws_cache_debug_dump() - if built in debug mode dump cache contents to log + * + * \param cache: cache to dump + * + * If lws was built in debug mode, dump cache to log, otherwise a NOP. + */ +LWS_VISIBLE LWS_EXTERN void +lws_cache_debug_dump(struct lws_cache_ttl_lru *cache); + +typedef struct lws_cache_results { + const uint8_t *ptr; /* set before using walk api */ + size_t size; /* set before using walk api */ + + size_t payload_len; + size_t tag_len; + const uint8_t *tag; +} lws_cache_results_t; + +/** + * lws_cache_results_walk() - parse next result + * + * \param walk_ctx: the context of the results blob to walk + * + * Caller must initialize \p walk_ctx.ptr and \p walk_ctx.size before calling. + * These are set to the results returned from a _lookup api call. + * + * The call returns 0 if the struct elements have been set to a result, or 1 + * if there where no more results in the blob to walk. + * + * If successful, after the call \p payload_len is set to the length of the + * payload related to this result key (the payload itself is not present), + * \p tag_len is set to the length of the result key name, and \p tag is set + * to the result tag name, with a terminating NUL. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_results_walk(lws_cache_results_t *walk_ctx); + +typedef void (*lws_cache_item_destroy_cb)(void *item, size_t size); +struct lws_cache_creation_info { + struct lws_context *cx; + /**< Mandatory: the lws_context */ + const char *name; + /**< Mandatory: short cache name */ + lws_cache_item_destroy_cb cb; + /**< NULL, or a callback that can hook cache item destory */ + struct lws_cache_ttl_lru *parent; + /**< NULL, or next cache level */ + const struct lws_cache_ops *ops; + /**< NULL for default, heap-based ops, else custom cache storage and + * query implementation */ + + union { + struct { + const char *filepath; + /**< the filepath to store items in */ + } nscookiejar; + } u; + /**< these are extra configuration for specific cache types */ + + size_t max_footprint; + /**< 0, or the max heap allocation allowed before destroying + * lru items to keep it under the limit */ + size_t max_items; + /**< 0, or the max number of items allowed in the cache before + * destroying lru items to keep it under the limit */ + size_t max_payload; + /**< 0, or the max allowed payload size for one item */ + int tsi; + /**< 0 unless using SMP, then tsi to bind sul to */ +}; + +struct lws_cache_ops { + struct lws_cache_ttl_lru * + (*create)(const struct lws_cache_creation_info *info); + /**< create an instance of the cache type specified in info */ + + void + (*destroy)(struct lws_cache_ttl_lru **_cache); + /**< destroy the logical cache instance pointed to by *_cache, doesn't + * affect any NV backing storage */ + + int + (*expunge)(struct lws_cache_ttl_lru *cache); + /**< completely delete any backing storage related to the cache + * instance, eg, delete the backing file */ + + int + (*write)(struct lws_cache_ttl_lru *cache, const char *specific_key, + const uint8_t *source, size_t size, lws_usec_t expiry, + void **ppvoid); + /**< create an entry in the cache level according to the given info */ + int + (*tag_match)(struct lws_cache_ttl_lru *cache, const char *wc, + const char *tag, char lookup_rules); + /**< Just tell us if tag would match wildcard, using whatever special + * rules the backing store might use for tag matching. 0 indicates + * it is a match on wildcard, nonzero means does not match. + */ + int + (*lookup)(struct lws_cache_ttl_lru *cache, const char *wildcard_key, + lws_dll2_owner_t *results_owner); + /**+ add keys for search_key matches not already listed in the results + * owner */ + int + (*invalidate)(struct lws_cache_ttl_lru *cache, const char *wildcard_key); + /**< remove matching item(s) from cache level */ + + int + (*get)(struct lws_cache_ttl_lru *cache, const char *specific_key, + const void **pdata, size_t *psize); + /**< if it has the item, fills L1 with item. updates LRU, and returns + * pointer to payload in L1 */ + + void + (*debug_dump)(struct lws_cache_ttl_lru *cache); + /**< Helper to dump the whole cache contents to log, useful for debug */ +}; + +/** + * lws_cache_create() - create an empty cache you can allocate items in + * + * \param info: a struct describing the cache to create + * + * Create an empty cache you can allocate items in. The cache will be kept + * below the max_footprint and max_items limits if they are nonzero, by + * destroying least-recently-used items until it remains below the limits. + * + * Items will auto-destroy when their expiry time is reached. + * + * When items are destroyed from the cache, if \p cb is non-NULL, it will be + * called back with the item pointer after it has been removed from the cache, + * but before it is deallocated and destroyed. + * + * context and tsi are used when scheduling expiry callbacks + */ +LWS_VISIBLE LWS_EXTERN struct lws_cache_ttl_lru * +lws_cache_create(const struct lws_cache_creation_info *info); + +/** + * lws_cache_destroy() - destroy a previously created cache + * + * \param cache: pointer to the cache + * + * Everything in the cache is destroyed, then the cache itself is destroyed, + * and *cache set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_cache_destroy(struct lws_cache_ttl_lru **cache); + +/** + * lws_cache_expunge() - destroy all items in cache and parents + * + * \param cache: pointer to the cache + * + * Everything in the cache and parents is destroyed, leaving it empty. + * If the cache has a backing store, it is deleted. + * + * Returns 0 if no problems reported at any cache layer, else nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_expunge(struct lws_cache_ttl_lru *cache); + +LWS_VISIBLE extern const struct lws_cache_ops lws_cache_ops_heap, + lws_cache_ops_nscookiejar; + +///@} + diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-callbacks.h b/3rdparty/libwebsockets/include/libwebsockets/lws-callbacks.h index 7a782622..fd36f7c7 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-callbacks.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-callbacks.h @@ -878,8 +878,18 @@ enum lws_callback_reasons { * close the wsi. */ LWS_CALLBACK_MQTT_RESEND = 210, - /**< In QoS1, this callback is generated instead of the _ACK one if - * we timed out waiting for a PUBACK and we must resend the message. + /**< In QoS1 or QoS2, this callback is generated instead of the _ACK one + * if we timed out waiting for a PUBACK or a PUBREC, and we must resend + * the message. Return nonzero to close the wsi. + */ + LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT = 211, + /**< When a UNSUBSCRIBE is sent, this callback is generated instead of + * the _UNSUBSCRIBED one if we timed out waiting for a UNSUBACK. + * Return nonzero to close the wsi. + */ + LWS_CALLBACK_MQTT_SHADOW_TIMEOUT = 212, + /**< When a Device Shadow is sent, this callback is generated if we + * timed out waiting for a response from AWS IoT. * Return nonzero to close the wsi. */ diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-client.h b/3rdparty/libwebsockets/include/libwebsockets/lws-client.h index 38de8976..bb5f2d03 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-client.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-client.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -93,6 +93,12 @@ enum lws_client_connect_ssl_connection_flags { LCCSCF_CONMON = (1 << 28), /**< If LWS_WITH_CONMON enabled for build, keeps a copy of the * getaddrinfo results so they can be queried subsequently */ + LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS = (1 << 29), + /**< By default lws rejects https redirecting to http. Set this + * flag on the client connection to allow it. */ + LCCSCF_CACHE_COOKIES = (1 << 30), + /**< If built with -DLWS_WITH_CACHE_NSCOOKIEJAR, store and reapply + * http cookies in a Netscape Cookie Jar on this connection */ }; /** struct lws_client_connect_info - parameters to connect with when using @@ -108,7 +114,8 @@ struct lws_client_connect_info { int ssl_connection; /**< 0, or a combination of LCCSCF_ flags */ const char *path; - /**< uri path */ + /**< URI path. Prefix with + for a UNIX socket. (+@ for + * a Linux abstract-namespace socket) */ const char *host; /**< content of host header */ const char *origin; @@ -216,12 +223,18 @@ struct lws_client_connect_info { * connection, allows targeting by "wsi=XXX/..." if you give XXX here. */ - uint16_t keep_warm_secs; + 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. */ + lws_log_cx_t *log_cx; + /**< NULL to use lws_context log context, else a pointer to a log + * context template to take a copy of for this wsi. Used to isolate + * wsi-specific logs into their own stream or file. + */ + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * @@ -300,6 +313,7 @@ lws_http_client_read(struct lws *wsi, char **buf, int *len); * \param wsi: client connection * * Returns the last server response code, eg, 200 for client http connections. + * If there is no valid response, it will return 0. * * You should capture this during the LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP * callback, because after that the memory reserved for storing the related diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-conmon.h b/3rdparty/libwebsockets/include/libwebsockets/lws-conmon.h index 2e25f8c3..12a0eec7 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-conmon.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-conmon.h @@ -31,7 +31,7 @@ */ ///@{ -/* enough for 4191us, or just over an hour */ +/* enough for 4191s, or just over an hour */ typedef uint32_t lws_conmon_interval_us_t; /* @@ -44,18 +44,56 @@ typedef uint32_t lws_conmon_interval_us_t; * { * "peer": "46.105.127.147", * "dns_us": 1234, + * "dns_disp": 1, * "sockconn_us": 1234, * "tls_us": 1234, * "txn_resp_us": 1234, - * "dns":["46.105.127.147", "2001:41d0:2:ee93::1"] + * "dns":["46.105.127.147", "2001:41d0:2:ee93::1"], + * "prot_specific": { + * "protocol": "http", + * "resp": 200 + * } * } + * + * The indexes in "dns_disp" are declared in lws_conmon_dns_disposition_t + * below. + * + * "prot_specific" may not be present if the protocol doesn't have anything + * to report or is not supported. */ +typedef enum lws_conmon_pcol { + LWSCONMON_PCOL_NONE, + LWSCONMON_PCOL_HTTP, /* .protocol_specific.http is valid */ +} lws_conmon_pcol_t; + +typedef enum lws_conmon_dns_disposition { + LWSCONMON_DNS_NONE, + /**< did not attempt DNS */ + LWSCONMON_DNS_OK = 1, + /**< DNS lookup did give results */ + LWSCONMON_DNS_SERVER_UNREACHABLE = 2, + /**< DNS server was not reachable */ + LWSCONMON_DNS_NO_RESULT = 3 + /**< DNS server replied but nothing usable */ +} lws_conmon_dns_disposition_t; + struct lws_conmon { lws_sockaddr46 peer46; /**< The peer we actually connected to, if any. .peer46.sa4.sa_family * is either 0 if invalid, or the AF_ */ + union { + struct { + int response; + /**< h1 http response code */ + } http; + } protocol_specific; + /**< possibly-present protocol-specific additional information. This + * is only valid for the first transaction after connection and does + * not capture results for persistent or muxed connections like ws + * messages, mqtt messages, or h2 streams */ + struct addrinfo *dns_results_copy; /**< NULL, or Allocated copy of dns results, owned by this object and * freed when object destroyed. @@ -72,7 +110,15 @@ struct lws_conmon { /**< 0 if no tls, or us taken to establish the tls tunnel */ lws_conmon_interval_us_t ciu_txn_resp; /**< 0, or if the protocol supports transactions, the interval between - * sending the transaction request and starting to receive the resp */ + * sending the initial transaction request and starting to receive the + * response */ + + lws_conmon_pcol_t pcol; + /**< indicates which extra protocol_specific info member is valid, + * if any */ + + lws_conmon_dns_disposition_t dns_disposition; + /**< indicates general disposition of DNS request */ }; /** diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-context-vhost.h b/3rdparty/libwebsockets/include/libwebsockets/lws-context-vhost.h index ee7d57da..b3de140b 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-context-vhost.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-context-vhost.h @@ -453,6 +453,8 @@ struct lws_context_creation_info { int simultaneous_ssl_restriction; /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions * possible.*/ + int simultaneous_ssl_handshake_restriction; + /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL handshakes ongoing */ 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 @@ -536,6 +538,17 @@ struct lws_context_creation_info { * implementation for the one provided by provided_ssl_ctx. * Libwebsockets no longer is responsible for freeing the context * if this option is selected. */ +#else /* WITH_MBEDTLS */ + const char *mbedtls_client_preload_filepath; + /**< CONTEXT: If NULL, no effect. Otherwise it should point to a + * filepath where every created client SSL_CTX is preloaded from the + * system trust bundle. + * + * This sets a processwide variable that affects all contexts. + * + * Requires that the mbedtls provides mbedtls_x509_crt_parse_file(), + * else disabled. + */ #endif #endif @@ -621,7 +634,10 @@ struct lws_context_creation_info { 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. */ + * Host: header and / or SNI name for SSL. + * CONTEXT: NULL, or the name to associate with the context for + * context-specific logging + */ #if defined(LWS_WITH_PLUGINS) const char * const *plugin_dirs; /**< CONTEXT: NULL, or NULL-terminated array of directories to @@ -843,16 +859,60 @@ struct lws_context_creation_info { #if defined(LWS_WITH_SYS_METRICS) const struct lws_metric_policy *metrics_policies; - /**< non-SS policy metrics policies */ + /**< CONTEXT: non-SS policy metrics policies */ const char *metrics_prefix; - /**< prefix for this context's metrics, used to distinguish metrics - * pooled from different processes / applications, so, eg what would - * be "cpu.svc" if this is NULL becomes "myapp.cpu.svc" is this is + /**< CONTEXT: prefix for this context's metrics, used to distinguish + * metrics pooled from different processes / applications, so, eg what + * would be "cpu.svc" if this is NULL becomes "myapp.cpu.svc" is this is * set to "myapp". Policies are applied using the name with the prefix, * if present. */ #endif + int fo_listen_queue; + /**< VHOST: 0 = no TCP_FASTOPEN, nonzero = enable TCP_FASTOPEN if the + * platform supports it, with the given queue length for the listen + * socket. + */ + + const struct lws_plugin_evlib *event_lib_custom; + /**< CONTEXT: If non-NULL, override event library selection so it uses + * this custom event library implementation, instead of default internal + * loop. Don't set any other event lib context creation flags in that + * case. it will be used automatically. This is useful for integration + * where an existing application is using its own handrolled event loop + * instead of an event library, it provides a way to allow lws to use + * the custom event loop natively as if it were an "event library". + */ + +#if defined(LWS_WITH_TLS_JIT_TRUST) + size_t jitt_cache_max_footprint; + /**< CONTEXT: 0 for no limit, else max bytes used by JIT Trust cache... + * LRU items are evicted to keep under this limit */ + int vh_idle_grace_ms; + /**< CONTEXT: 0 for default of 5000ms, or number of ms JIT Trust vhosts + * are allowed to live without active connections using them. */ +#endif + + lws_log_cx_t *log_cx; + /**< CONTEXT: NULL to use the default, process-scope logging context, + * else a specific logging context to associate with this context */ + +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + const char *http_nsc_filepath; + /**< CONTEXT: Filepath to use for http netscape cookiejar file */ + + size_t http_nsc_heap_max_footprint; + /**< CONTEXT: 0, or limit in bytes for heap usage of memory cookie + * cache */ + size_t http_nsc_heap_max_items; + /**< CONTEXT: 0, or the max number of items allowed in the cookie cache + * before destroying lru items to keep it under the limit */ + size_t http_nsc_heap_max_payload; + /**< CONTEXT: 0, or the maximum size of a single cookie we are able to + * handle */ +#endif + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * @@ -1265,13 +1325,7 @@ struct lws_http_mount { /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility - * - * The below is to ensure later library versions with new - * members added above will see 0 (default) even if the app - * was not built against the newer headers. */ - - void *_unused[2]; /**< dummy */ }; ///@} diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-cose.h b/3rdparty/libwebsockets/include/libwebsockets/lws-cose.h new file mode 100644 index 00000000..1ea67915 --- /dev/null +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-cose.h @@ -0,0 +1,511 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 cose COSE apis + * ##COSE related functions + * \ingroup lwsaoi + * + * COSE RFC 8152 relates to signed and encrypted CBOR + */ +//@{ + +enum { + /* RFC8152: Table 2: Common Header Parameters + * https://www.iana.org/assignments/cose/cose.xhtml#header-parameters + */ + + LWSCOSE_WKL_ALG = 1, /* int / tstr */ + LWSCOSE_WKL_CRIT, /* [+ label ] */ + LWSCOSE_WKL_CONTENT_TYPE, /* tstr / uint */ + LWSCOSE_WKL_KID, /* bstr */ + LWSCOSE_WKL_IV, /* bstr */ + LWSCOSE_WKL_IV_PARTIAL, /* bstr */ + LWSCOSE_WKL_COUNTERSIG, /* COSE sig(s) */ + LWSCOSE_WKL_COUNTERSIG0 = 9, /* bstr */ + LWSCOSE_WKL_KID_CONTEXT, /* bstr */ + LWSCOSE_WKL_CUPH_NONCE = 256, /* bstr */ + LWSCOSE_WKL_CUPH_OWNER_PUBKEY = 257, /* array */ + + /* RFC8152: Table 3: key map labels */ + + LWSCOSE_WKK_KTY = 1, /* int / tstr */ + LWSCOSE_WKK_KID, /* bstr */ + LWSCOSE_WKK_ALG, /* int / tstr */ + LWSCOSE_WKK_KEY_OPS, /* [ + (int / tstr) ] */ + LWSCOSE_WKK_BASE_IV, /* bstr */ + + /* RFC8152: Table 4: Key Operation Values */ + + LWSCOSE_WKKO_SIGN = 1, + LWSCOSE_WKKO_VERIFY, + LWSCOSE_WKKO_ENCRYPT, + LWSCOSE_WKKO_DECRYPT, + LWSCOSE_WKKO_WRAP_KEY, + LWSCOSE_WKKO_UNWRAP_KEY, + LWSCOSE_WKKO_DERIVE_KEY, + LWSCOSE_WKKO_DERIVE_BITS, + LWSCOSE_WKKO_MAC_CREATE, + LWSCOSE_WKKO_MAC_VERIFY, + + /* RFC8152: Table 5: ECDSA algs */ + + LWSCOSE_WKAECDSA_ALG_ES256 = -7, + LWSCOSE_WKAECDSA_ALG_ES384 = -35, + LWSCOSE_WKAECDSA_ALG_ES512 = -36, + + /* RFC8152: Table 6: EDDSA algs */ + + LWSCOSE_WKAEDDSA_ALG_EDDSA = -8, + + /* RFC8152: Table 7: HMAC algs */ + + LWSCOSE_WKAHMAC_256_64 = 4, + LWSCOSE_WKAHMAC_256_256, + LWSCOSE_WKAHMAC_384_384, + LWSCOSE_WKAHMAC_512_512, + + /* RFC8152: Table 8: AES algs */ + + LWSCOSE_WKAAES_128_64 = 14, + LWSCOSE_WKAAES_256_64, + LWSCOSE_WKAAES_128_128 = 25, + LWSCOSE_WKAAES_256_128, + + /* RFC8152: Table 9: AES GCM algs */ + + LWSCOSE_WKAAESGCM_128 = 1, + LWSCOSE_WKAAESGCM_192, + LWSCOSE_WKAAESGCM_256, + + /* RFC8152: Table 10: AES CCM algs */ + + LWSCOSE_WKAAESCCM_16_64_128 = 10, + LWSCOSE_WKAAESCCM_16_64_256, + LWSCOSE_WKAAESCCM_64_64_128, + LWSCOSE_WKAAESCCM_64_64_256, + LWSCOSE_WKAAESCCM_16_128_128, + LWSCOSE_WKAAESCCM_16_128_256, + LWSCOSE_WKAAESCCM_64_128_128, + LWSCOSE_WKAAESCCM_64_128_256, + + /* RFC8152: Table 11: CHACHA20 / Poly1305 */ + + LWSCOSE_WKACHACHA_POLY1305 = 24, + + /* RFC8152: Table 13: HKDF param */ + + LWSCOSE_WKAPHKDF_SALT = -20, + + /* RFC8152: Table 14: Context Algorithm Parameters */ + + LWSCOSE_WKAPCTX_PARTY_U_IDENTITY = -21, + LWSCOSE_WKAPCTX_PARTY_U_NONCE = -22, + LWSCOSE_WKAPCTX_PARTY_U_OTHER = -23, + LWSCOSE_WKAPCTX_PARTY_V_IDENTITY = -24, + LWSCOSE_WKAPCTX_PARTY_V_NONCE = -25, + LWSCOSE_WKAPCTX_PARTY_V_OTHER = -26, + + /* RFC8152: Table 15: Direct key */ + + LWSCOSE_WKK_DIRECT_CEK = -6, + + /* RFC8152: Table 16: Direct key with KDF */ + + LWSCOSE_WKK_DIRECT_HKDF_SHA_256 = -10, + LWSCOSE_WKK_DIRECT_HKDF_SHA_512 = -11, + LWSCOSE_WKK_DIRECT_HKDF_AES_128 = -12, + LWSCOSE_WKK_DIRECT_HKDF_AES_256 = -13, + + /* RFC8152: Table 17: AES Key Wrap Algorithm Values */ + + LWSCOSE_WKK_DIRECT_HKDFKW_SHA_256 = -3, + LWSCOSE_WKK_DIRECT_HKDFKW_SHA_512 = -4, + LWSCOSE_WKK_DIRECT_HKDFKW_AES_128 = -5, + + /* RFC8152: Table 18: ECDH Algorithm Values */ + + LWSCOSE_WKAECDH_ALG_ES_HKDF_256 = -25, + LWSCOSE_WKAECDH_ALG_ES_HKDF_512 = -26, + LWSCOSE_WKAECDH_ALG_SS_HKDF_256 = -27, + LWSCOSE_WKAECDH_ALG_SS_HKDF_512 = -28, + + /* RFC8152: Table 19: ECDH Algorithm Parameters */ + + LWSCOSE_WKAPECDH_EPHEMERAL_KEY = -1, + LWSCOSE_WKAPECDH_STATIC_KEY = -2, + LWSCOSE_WKAPECDH_STATIC_KEY_ID = -3, + + /* RFC8152: Table 20: ECDH Algorithm Parameters with key wrap */ + + LWSCOSE_WKAPECDH_ES_A128KW = -29, + LWSCOSE_WKAPECDH_ES_A192KW = -30, + LWSCOSE_WKAPECDH_ES_A256KW = -31, + LWSCOSE_WKAPECDH_SS_A128KW = -32, + LWSCOSE_WKAPECDH_SS_A192KW = -33, + LWSCOSE_WKAPECDH_SS_A256KW = -34, + + /* RFC8152: Table 21: Key Type Values + * https://www.iana.org/assignments/cose/cose.xhtml#key-type + */ + + LWSCOSE_WKKTV_OKP = 1, + LWSCOSE_WKKTV_EC2 = 2, + LWSCOSE_WKKTV_RSA = 3, + LWSCOSE_WKKTV_SYMMETRIC = 4, + LWSCOSE_WKKTV_HSS_LMS = 5, + LWSCOSE_WKKTV_WALNUTDSA = 6, + + + /* RFC8152: Table 22: Elliptic Curves + * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves + */ + + LWSCOSE_WKEC_P256 = 1, + LWSCOSE_WKEC_P384, + LWSCOSE_WKEC_P521, + LWSCOSE_WKEC_X25519, + LWSCOSE_WKEC_X448, + LWSCOSE_WKEC_ED25519, + LWSCOSE_WKEC_ED448, + LWSCOSE_WKEC_SECP256K1, + + /* RFC8152: Table 23: EC Key Parameters */ + + LWSCOSE_WKECKP_CRV = -1, + LWSCOSE_WKECKP_X = -2, + LWSCOSE_WKECKP_Y = -3, + LWSCOSE_WKECKP_D = -4, + + /* RFC8152: Table 24: Octet Key Pair (OKP) Parameters */ + + LWSCOSE_WKOKP_CRV = -1, + LWSCOSE_WKOKP_X = -2, + LWSCOSE_WKOKP_D = -4, + + /* Additional from + * https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters + */ + + LWSCOSE_WKKPRSA_N = -1, + LWSCOSE_WKKPRSA_E = -2, + LWSCOSE_WKKPRSA_D = -3, + LWSCOSE_WKKPRSA_P = -4, + LWSCOSE_WKKPRSA_Q = -5, + LWSCOSE_WKKPRSA_DP = -6, + LWSCOSE_WKKPRSA_DQ = -7, + LWSCOSE_WKKPRSA_QINV = -8, + LWSCOSE_WKKPRSA_OTHER = -9, + LWSCOSE_WKKPRSA_RI = -10, + LWSCOSE_WKKPRSA_DI = -11, + LWSCOSE_WKKPRSA_TI = -12, + + /* RFC8152: Table 25: Symmetric Key Parameters */ + + LWSCOSE_WKSYMKP_KEY_VALUE = 4, + + /* RFC8152: Table 26: CoAP Content-Formats for COSE */ + + LWSCOAP_CONTENTFORMAT_COSE_SIGN = 98, + LWSCOAP_CONTENTFORMAT_COSE_SIGN1 = 18, + LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT = 96, + LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT0 = 16, + LWSCOAP_CONTENTFORMAT_COSE_MAC = 97, + LWSCOAP_CONTENTFORMAT_COSE_MAC0 = 17, + LWSCOAP_CONTENTFORMAT_COSE_KEY = 101, + LWSCOAP_CONTENTFORMAT_COSE_KEY_SET = 102, + + /* RFC8152: Table 27: Header Parameter for CounterSignature0 */ + + LWSCOSE_WKL_COUNTERSIGNATURE0 = 9, /* bstr */ + + /* RFC8812: Table 1: RSASSA-PKCS1-v1_5 Algorithm Values */ + + LWSCOSE_WKARSA_ALG_RS256 = -257, /* + SHA-256 */ + LWSCOSE_WKARSA_ALG_RS384 = -258, /* + SHA-384 */ + LWSCOSE_WKARSA_ALG_RS512 = -259, /* + SHA-512 */ +}; + +enum enum_cose_key_meta_tok { + COSEKEY_META_KTY, + COSEKEY_META_KID, + COSEKEY_META_KEY_OPS, + COSEKEY_META_BASE_IV, + COSEKEY_META_ALG, + + LWS_COUNT_COSE_KEY_ELEMENTS +}; + +typedef int64_t cose_param_t; + +LWS_VISIBLE LWS_EXTERN const char * +lws_cose_alg_to_name(cose_param_t alg); + +LWS_VISIBLE LWS_EXTERN cose_param_t +lws_cose_name_to_alg(const char *name); + +/* + * cose_key + */ + +typedef struct lws_cose_key { + /* key data elements */ + struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT]; + /* generic meta key elements, like KID */ + struct lws_gencrypto_keyelem meta[LWS_COUNT_COSE_KEY_ELEMENTS]; + lws_dll2_t list; /* used when part of a set */ + int gencrypto_kty; /**< one of LWS_GENCRYPTO_KTY_ */ + cose_param_t kty; + cose_param_t cose_alg; + cose_param_t cose_curve; + char private_key; /* nonzero = has private key elements */ +} lws_cose_key_t; + +typedef int (*lws_cose_key_import_callback)(struct lws_cose_key *s, void *user); + +/** lws_cose_jwk_import() - Create an lws_cose_key_t object from cose_key CBOR + * + * \param pkey_set: NULL, or a pointer to an lws_dll2_owner_t for a cose_key set + * \param cb: callback for each jwk-processed key, or NULL if importing a single + * key with no parent "keys" JSON + * \param user: pointer to be passed to the callback, otherwise ignored by lws. + * NULL if importing a single key with no parent "keys" JSON + * \param in: a single cose_key + * \param len: the length of the cose_key in bytes + * + * Creates a single lws_cose_key_t if \p pkey_set is NULL or if the incoming + * CBOR doesn't start with an array, otherwise expects a CBOR array containing + * zero or more cose_key CBOR, and adds each to the \p pkey_set + * lws_dll2_owner_t struct. Created lws_cose_key_t are filled with data from + * the COSE representation and can be used with other COSE crypto ops. + */ +LWS_VISIBLE LWS_EXTERN lws_cose_key_t * +lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb, + void *user, const uint8_t *in, size_t len); + +/** lws_cose_key_export() - Create cose_key CBOR from an lws_cose_key_t + * + * \param ck: the lws_cose_key_t to export to CBOR + * \param ctx: the CBOR writing context (same as for lws_lec_printf()) + * \param flags: 0 to export only public elements, or LWSJWKF_EXPORT_PRIVATE + * + * Creates an lws_jwk struct filled with data from the COSE representation. + */ +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags); + +/** + * lws_cose_key_generate() - generate a fresh key + * + * \param context: the lws_context used to get random + * \param cose_kty: one of LWSCOSE_WKKTV_ indicating the well-known key type + * \param use_mask: 0, or a bitfield where (1 << LWSCOSE_WKKO_...) set means valid for use + * \param bits: key bits for RSA + * \param curve: for EC keys, one of "P-256", "P-384" or "P-521" currently + * \param kid: string describing the key, or NULL + * + * Create an lws_cose_key_t of the specified type and return it + */ +LWS_VISIBLE LWS_EXTERN lws_cose_key_t * +lws_cose_key_generate(struct lws_context *context, cose_param_t cose_kty, + int use_mask, int bits, const char *curve, + const uint8_t *kid, size_t kl); + +LWS_VISIBLE LWS_EXTERN lws_cose_key_t * +lws_cose_key_from_set(lws_dll2_owner_t *set, const uint8_t *kid, size_t kl); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_key_destroy(lws_cose_key_t **ck); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_key_set_destroy(lws_dll2_owner_t *o); + +/* only available in _DEBUG build */ + +LWS_VISIBLE LWS_EXTERN void +lws_cose_key_dump(const lws_cose_key_t *ck); + +/* + * cose_sign + */ + +struct lws_cose_validate_context; + + +enum lws_cose_sig_types { + SIGTYPE_UNKNOWN, + SIGTYPE_MULTI, + SIGTYPE_SINGLE, + SIGTYPE_COUNTERSIGNED, /* not yet supported */ + SIGTYPE_MAC, /* only supported for validation */ + SIGTYPE_MAC0, +}; + +/* a list of these result objects is the output of the validation process */ + +typedef struct { + lws_dll2_t list; + + const lws_cose_key_t *cose_key; + cose_param_t cose_alg; + + int result; /* 0 = validated */ + +} lws_cose_validate_res_t; + +enum { + LCOSESIGEXTCB_RET_FINISHED, + LCOSESIGEXTCB_RET_AGAIN, + LCOSESIGEXTCB_RET_ERROR = -1 +}; + +typedef struct { + struct lws_cose_validate_context *cps; + const uint8_t *ext; + size_t xl; +} lws_cose_sig_ext_pay_t; + +typedef int (*lws_cose_sign_ext_pay_cb_t)(lws_cose_sig_ext_pay_t *x); +typedef int (*lws_cose_validate_pay_cb_t)(struct lws_cose_validate_context *cps, + void *opaque, const uint8_t *paychunk, + size_t paychunk_len); + +typedef struct lws_cose_validate_create_info { + struct lws_context *cx; + /**< REQUIRED: the lws context */ + lws_dll2_owner_t *keyset; + /**< REQUIRED: one or more cose_keys */ + + enum lws_cose_sig_types sigtype; + /**< 0 if a CBOR tag is in the sig, else one of SIGTYPE_MULTI, + * SIGTYPE_SINGLE, etc*/ + + lws_cose_validate_pay_cb_t pay_cb; + /**< optional: called back with unvalidated payload pieces */ + void *pay_opaque; + /**< optional: passed into pay_cb callback along with payload chunk */ + + lws_cose_sign_ext_pay_cb_t ext_cb; + /**< optional extra application data provision callback */ + void *ext_opaque; + /**< optional extra application data provision callback opaque */ + size_t ext_len; + /**< if we have extra app data, this must be set to the length of it */ +} lws_cose_validate_create_info_t; + +/** + * lws_cose_validate_create() - create a signature validation context + * + * \param info: struct describing the validation context to create + * + * Creates a signature validation context set up as described in \p info. + * + * You can then pass the signature cbor chunks to it using + * lws_cose_validate_chunk(), finialize and get the results list using + * lws_cose_validate_results() and destroy with lws_cose_validate_destroy(). + */ +LWS_VISIBLE LWS_EXTERN struct lws_cose_validate_context * +lws_cose_validate_create(const lws_cose_validate_create_info_t *info); + +/** + * lws_cose_validate_chunk() - passes chunks of CBOR into the signature validator + * + * \param cps: the validation context + * \param in: the chunk of CBOR (does not have to be logically complete) + * \param in_len: number of bytes available at \p in + * + * Parses signature CBOR to produce a list of result objects. + * + * + */ +LWS_VISIBLE LWS_EXTERN int +lws_cose_validate_chunk(struct lws_cose_validate_context *cps, + const uint8_t *in, size_t in_len, size_t *used_in); + +LWS_VISIBLE LWS_EXTERN lws_dll2_owner_t * +lws_cose_validate_results(struct lws_cose_validate_context *cps); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_validate_destroy(struct lws_cose_validate_context **cps); + +struct lws_cose_sign_context; + +#define LCSC_FL_ADD_CBOR_TAG (1 << 0) +#define LCSC_FL_ADD_CBOR_PREFER_MAC0 (1 << 1) + +typedef struct lws_cose_sign_create_info { + struct lws_context *cx; + /**< REQUIRED: the lws context */ + lws_dll2_owner_t *keyset; + /**< REQUIRED: one or more cose_keys */ + + lws_lec_pctx_t *lec; + /**< REQUIRED: the cbor output context to emit to, user must + * initialize with lws_lec_init() beforehand */ + + lws_cose_sign_ext_pay_cb_t ext_cb; + /**< optional extra application data provision callback */ + void *ext_opaque; + /**< optional extra application data provision callback opaque */ + size_t ext_len; + /**< if we have extra app data, this must be set to the length of it */ + + size_t inline_payload_len; + /**< REQUIRED: size of the inline payload we will provide */ + + int flags; + /**< bitmap of LCSC_FL_* */ + enum lws_cose_sig_types sigtype; + /**< 0, or sign type hint */ +} lws_cose_sign_create_info_t; + +/** + * lws_cose_sign_create() - Create a signing context + * + * \param info: a structure describing the signing context you want to create + * + * This allocates and returns a signing context created according to what is in + * the \p info parameter. + * + * \p info must be prepared with the lws_context, a keyset to use, a CBOR + * output context, and the inline payload length. + * + * Returns NULL on failure or the created signing context ready to add alg(s) + * to. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_cose_sign_context * +lws_cose_sign_create(const lws_cose_sign_create_info_t *info); + +LWS_VISIBLE LWS_EXTERN int +lws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg, + const lws_cose_key_t *ck); + +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, + const uint8_t *in, size_t in_len); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_sign_destroy(struct lws_cose_sign_context **csc); + +//@} diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-dll2.h b/3rdparty/libwebsockets/include/libwebsockets/lws-dll2.h index 478aa434..14f0fcd4 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-dll2.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-dll2.h @@ -228,9 +228,11 @@ lws_dll2_add_tail(struct lws_dll2 *d, struct lws_dll2_owner *owner); LWS_VISIBLE LWS_EXTERN void lws_dll2_remove(struct lws_dll2 *d); +typedef int (*lws_dll2_foreach_cb_t)(struct lws_dll2 *d, void *user); + LWS_VISIBLE LWS_EXTERN int lws_dll2_foreach_safe(struct lws_dll2_owner *owner, void *user, - int (*cb)(struct lws_dll2 *d, void *user)); + lws_dll2_foreach_cb_t cb); LWS_VISIBLE LWS_EXTERN void lws_dll2_clear(struct lws_dll2 *d); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-eventlib-exports.h b/3rdparty/libwebsockets/include/libwebsockets/lws-eventlib-exports.h index 87c4085b..5d01caa9 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-eventlib-exports.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-eventlib-exports.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2020 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -22,10 +22,70 @@ * IN THE SOFTWARE. * * These are exports needed by event lib plugins. - * - * You should consider these opaque for normal user code. */ +enum lws_event_lib_ops_flags { + LELOF_ISPOLL = (1 >> 0), + LELOF_DESTROY_FINAL = (1 >> 1), +}; + +enum { + LWS_EV_READ = (1 << 0), + LWS_EV_WRITE = (1 << 1), + LWS_EV_START = (1 << 2), + LWS_EV_STOP = (1 << 3), +}; + +struct lws_event_loop_ops { + const char *name; + /* event loop-specific context init during context creation */ + int (*init_context)(struct lws_context *context, + const struct lws_context_creation_info *info); + /* called during lws_destroy_context */ + int (*destroy_context1)(struct lws_context *context); + /* called during lws_destroy_context2 */ + int (*destroy_context2)(struct lws_context *context); + /* init vhost listening wsi */ + int (*init_vhost_listen_wsi)(struct lws *wsi); + /* init the event loop for a pt */ + int (*init_pt)(struct lws_context *context, void *_loop, int tsi); + /* called at end of first phase of close_free_wsi() */ + int (*wsi_logical_close)(struct lws *wsi); + /* return nonzero if client connect not allowed */ + int (*check_client_connect_ok)(struct lws *wsi); + /* close handle manually */ + void (*close_handle_manually)(struct lws *wsi); + /* event loop accept processing */ + int (*sock_accept)(struct lws *wsi); + /* control wsi active events */ + void (*io)(struct lws *wsi, unsigned int flags); + /* run the event loop for a pt */ + void (*run_pt)(struct lws_context *context, int tsi); + /* called before pt is destroyed */ + void (*destroy_pt)(struct lws_context *context, int tsi); + /* called just before wsi is freed */ + void (*destroy_wsi)(struct lws *wsi); + /* return nonzero if caller thread is not loop service thread */ + int (*foreign_thread)(struct lws_context *context, int tsi); + + uint8_t flags; + + uint16_t evlib_size_ctx; + uint16_t evlib_size_pt; + uint16_t evlib_size_vh; + uint16_t evlib_size_wsi; +}; + +LWS_VISIBLE LWS_EXTERN void * +lws_evlib_wsi_to_evlib_pt(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void * +lws_evlib_tsi_to_evlib_pt(struct lws_context *ctx, int tsi); + + /* + * You should consider these opaque for normal user code. + */ + LWS_VISIBLE LWS_EXTERN void * lws_realloc(void *ptr, size_t size, const char *reason); @@ -36,6 +96,10 @@ LWS_VISIBLE LWS_EXTERN void lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *caller); +LWS_VISIBLE LWS_EXTERN int +lws_vhost_foreach_listen_wsi(struct lws_context *cx, void *arg, + lws_dll2_foreach_cb_t cb); + struct lws_context_per_thread; LWS_VISIBLE LWS_EXTERN void lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-fault-injection.h b/3rdparty/libwebsockets/include/libwebsockets/lws-fault-injection.h index 6f8e1aa8..e9133763 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-fault-injection.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-fault-injection.h @@ -72,6 +72,7 @@ enum { LWSFI_PROBABILISTIC, /* .pre % chance of injection */ LWSFI_PATTERN, /* use .count bits in .pattern after .pre */ LWSFI_PATTERN_ALLOC, /* as _PATTERN, but .pattern is malloc'd */ + LWSFI_RANGE /* pick a number between pre and count */ }; typedef struct lws_fi { @@ -108,6 +109,27 @@ typedef struct lws_fi_ctx { LWS_VISIBLE LWS_EXTERN int lws_fi(const lws_fi_ctx_t *fic, const char *fi_name); +/** + * lws_fi_range() - get a random number from a range + * + * \param fic: fault injection tracking context + * \param fi_name: name of fault injection + * \param result: points to uint64_t to be set to the result + * + * This lets you get a random number from an externally-set range, set using a + * fault injection syntax like "myfault(123..456)". That will cause us to + * return a number between those two inclusive, from the seeded PRNG. + * + * This is useful when you used lws_fi() with its own fault name to decide + * whether to inject the fault, and then the code to cause the fault needs + * additional constrained pseudo-random fuzzing for, eg, delays before issuing + * the fault. + * + * Returns 0 if \p *result is set, else nonzero for failure. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fi_range(const lws_fi_ctx_t *fic, const char *name, uint64_t *result); + /** * lws_fi_add() - add an allocated copy of fault injection to a context * diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-gencrypto.h b/3rdparty/libwebsockets/include/libwebsockets/lws-gencrypto.h index 644ce892..00182310 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-gencrypto.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-gencrypto.h @@ -59,6 +59,13 @@ enum lws_gencrypto_rsa_tok { LWS_GENCRYPTO_RSA_KEYEL_DQ, LWS_GENCRYPTO_RSA_KEYEL_QI, + /* we don't actively use these if given, but may come from COSE */ + + LWS_GENCRYPTO_RSA_KEYEL_OTHER, + LWS_GENCRYPTO_RSA_KEYEL_RI, + LWS_GENCRYPTO_RSA_KEYEL_DI, + LWS_GENCRYPTO_RSA_KEYEL_TI, + LWS_GENCRYPTO_RSA_KEYEL_COUNT }; @@ -89,10 +96,10 @@ enum lws_gencrypto_aes_tok { * type. */ -struct lws_gencrypto_keyelem { +typedef struct lws_gencrypto_keyelem { uint8_t *buf; uint32_t len; -}; +} lws_gc_elem_t; /** diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-genec.h b/3rdparty/libwebsockets/include/libwebsockets/lws-genec.h index ee62abe3..5ae1d2f7 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-genec.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-genec.h @@ -147,7 +147,7 @@ lws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name, */ LWS_VISIBLE LWS_EXTERN int lws_genecdsa_set_key(struct lws_genec_ctx *ctx, - struct lws_gencrypto_keyelem *el); + const struct lws_gencrypto_keyelem *el); /** lws_genecdsa_hash_sig_verify_jws() - Verifies a JWS ECDSA signature on a given hash * @@ -184,7 +184,7 @@ lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, * \param sig: pointer to buffer to take signature * \param sig_len: length of the buffer (must be >= length of key N) * - * Returns <0 for error, or 0 for success. + * Returns <0 for error, or >=0 for success. * * This creates a JWS ECDSA signature for a hash you already computed and provide. * diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-genhash.h b/3rdparty/libwebsockets/include/libwebsockets/lws-genhash.h index 8407d2f0..f27c3b91 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-genhash.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-genhash.h @@ -93,7 +93,8 @@ struct lws_genhmac_ctx { * * \param type: one of LWS_GENHASH_TYPE_... * - * Returns number of bytes in this type of hash + * Returns number of bytes in this type of hash, if the hash type is unknown, it + * will return 0. */ LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT lws_genhash_size(enum lws_genhash_types type); @@ -102,7 +103,8 @@ lws_genhash_size(enum lws_genhash_types type); * * \param type: one of LWS_GENHASH_TYPE_... * - * Returns number of bytes in this type of hmac + * Returns number of bytes in this type of hmac, if the hmac type is unknown, it + * will return 0. */ LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT lws_genhmac_size(enum lws_genhmac_types type); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-genrsa.h b/3rdparty/libwebsockets/include/libwebsockets/lws-genrsa.h index 744a4843..3f230312 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-genrsa.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-genrsa.h @@ -74,7 +74,8 @@ struct lws_genrsa_ctx { * This and related APIs operate identically with OpenSSL or mbedTLS backends. */ LWS_VISIBLE LWS_EXTERN int -lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, +lws_genrsa_create(struct lws_genrsa_ctx *ctx, + const struct lws_gencrypto_keyelem *el, struct lws_context *context, enum enum_genrsa_mode mode, enum lws_genhash_types oaep_hashid); @@ -215,7 +216,7 @@ lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in, * \param sig: pointer to buffer to take signature * \param sig_len: length of the buffer (must be >= length of key N) * - * Returns <0 for error, or 0 for success. + * Returns <0 for error, or \p sig_len for success. * * This creates an RSA signature for a hash you already computed and provide. * You should have created the hash before calling this by iterating over the diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-http.h b/3rdparty/libwebsockets/include/libwebsockets/lws-http.h index d1ecacf8..85767589 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-http.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-http.h @@ -494,6 +494,26 @@ LWS_VISIBLE LWS_EXTERN int lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, int nlen); +typedef void (*lws_hdr_custom_fe_cb_t)(const char *name, int nlen, void *opaque); +/** + * lws_hdr_custom_name_foreach() - Iterate the custom header names + * + * \param wsi: websocket connection + * \param cb: callback for each custom header name + * \param opaque: ignored by lws except to pass to callback + * + * Lws knows about 100 common http headers, and parses them into indexes when + * it recognizes them. When it meets a header that it doesn't know, it stores + * the name and value directly, and you can look them up using + * lws_hdr_custom_length() and lws_hdr_custom_copy(). + * + * This api returns -1 on error else 0. Use lws_hdr_custom_copy() to get the + * values of headers. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by + * default) to use this api. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb, void *opaque); + /** * lws_get_urlarg_by_name_safe() - get copy and return length of y for x=y urlargs * @@ -514,8 +534,6 @@ lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, * * Use this in place of lws_get_urlarg_by_name() that does not return an * explicit length. - * - * Use lws_get_urlarg_by_name_safe() instead of this, which returns the length. */ LWS_VISIBLE LWS_EXTERN int lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len); @@ -846,7 +864,7 @@ lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, * lws_http_transaction_completed() - wait for new http transaction or close * \param wsi: websocket connection * - * Returns 1 if the HTTP connection must close now + * Returns nonzero if the HTTP connection must close now * Returns 0 and resets connection to wait for new HTTP header / * transaction if possible */ diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-jose.h b/3rdparty/libwebsockets/include/libwebsockets/lws-jose.h index 247d02c6..c780c0e2 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-jose.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-jose.h @@ -189,7 +189,8 @@ lws_gencrypto_jwe_enc_to_definition(const char *enc, * \param temp: parent-owned buffer to "allocate" elements into * \param temp_len: amount of space available in temp * - * returns the amount of temp used, or -1 for error + * returns 0 for success, or -1 for error + * *\p temp_len is updated to reflect the amount of \p temp used if successful. */ LWS_VISIBLE LWS_EXTERN int lws_jws_parse_jose(struct lws_jose *jose, @@ -204,7 +205,8 @@ lws_jws_parse_jose(struct lws_jose *jose, * \param temp: parent-owned buffer to "allocate" elements into * \param temp_len: amount of space available in temp * - * returns the amount of temp used, or -1 for error + * returns 0 for success, or -1 for error + * *\p temp_len is updated to reflect the amount of \p temp used if successful. */ LWS_VISIBLE LWS_EXTERN int lws_jwe_parse_jose(struct lws_jose *jose, diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-jwk.h b/3rdparty/libwebsockets/include/libwebsockets/lws-jwk.h index ab4aff59..a2205d2e 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-jwk.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-jwk.h @@ -52,7 +52,7 @@ struct lws_jwk { struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT]; /* generic meta key elements, like KID */ struct lws_gencrypto_keyelem meta[LWS_COUNT_JWK_ELEMENTS]; - int kty; /**< one of LWS_JWK_ */ + int kty; /**< one of LWS_GENCRYPTO_KTY_ */ char private_key; /* nonzero = has private key elements */ }; @@ -64,6 +64,8 @@ struct lws_jwk_parse_state { lws_jwk_key_import_callback per_key_cb; void *user; int pos; + int cose_state; + int seen; unsigned short possible; }; @@ -191,7 +193,7 @@ lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32); * \param in: string to copy * \param len: length of string to copy * - * Returns 0 for OK or -1 for failure + * Returns 0 for OK or nonzero for failure */ LWS_VISIBLE LWS_EXTERN int lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx, @@ -209,7 +211,7 @@ lws_jwk_dump(struct lws_jwk *jwk); * \param bits: for OCT and RSA keys, the number of bits * \param curve: for EC keys, the name of the curve * - * Returns 0 for OK or -1 for failure + * Returns 0 for OK or nonzero for failure */ LWS_VISIBLE int lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk, diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-jws.h b/3rdparty/libwebsockets/include/libwebsockets/lws-jws.h index 0ad4714b..f15d503c 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-jws.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-jws.h @@ -111,7 +111,7 @@ lws_jws_destroy(struct lws_jws *jws); * in a map... it'll make a temp b64 version needed for comparison. See below * for other variants. * - * Returns 0 on match. + * Returns 0 on match, else nonzero. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sig_confirm_compact(struct lws_jws_map *map, struct lws_jwk *jwk, @@ -139,7 +139,7 @@ lws_jws_sig_confirm_compact_b64_map(struct lws_jws_map *map_b64, * (jose.payload.hdr.sig) as an aggregated string... it'll make a temp plain * version needed for comparison. * - * Returns 0 on match. + * Returns 0 on match, else nonzero. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sig_confirm_compact_b64(const char *in, size_t len, @@ -163,7 +163,7 @@ lws_jws_sig_confirm_compact_b64(const char *in, size_t len, * will end up with both maps, and can use this api version, saving needlessly * regenerating any temp map. * - * Returns 0 on match. + * Returns 0 on match, else nonzero. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */ @@ -187,7 +187,9 @@ lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */ * case \p b64_hdr may be NULL, and only the payload will be hashed before * signing. * - * Returns the length of the encoded signature written to \p b64_sig, or -1. + * If successful, returns the length of the encoded signature written to + * \p b64_sig. If the jose signing type is unknown, 0 is returned. Otherwise + * -1 indicates failure. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sign_from_b64(struct lws_jose *jose, struct lws_jws *jws, char *b64_sig, @@ -556,7 +558,7 @@ struct lws_jwt_sign_set_cookie { }; /** - * lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie + * lws_jwt_sign_token_set_http_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 diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-lecp.h b/3rdparty/libwebsockets/include/libwebsockets/lws-lecp.h new file mode 100644 index 00000000..8133e4b1 --- /dev/null +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-lecp.h @@ -0,0 +1,539 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 lecp CBOR parser + * ##CBOR parsing related functions + * \ingroup lwsapi + * + * LECP is an extremely lightweight CBOR stream parser included in lws. It + * is aligned in approach with the LEJP JSON stream parser, with some additional + * things needed for CBOR. + */ +//@{ + +#ifndef LECP_MAX_PARSING_STACK_DEPTH +#define LECP_MAX_PARSING_STACK_DEPTH 5 +#endif +#ifndef LECP_MAX_DEPTH +#define LECP_MAX_DEPTH 12 +#endif +#ifndef LECP_MAX_INDEX_DEPTH +#define LECP_MAX_INDEX_DEPTH 8 +#endif +#ifndef LECP_MAX_PATH +#define LECP_MAX_PATH 128 +#endif +#ifndef LECP_STRING_CHUNK +/* must be >= 30 to assemble floats */ +#define LECP_STRING_CHUNK 254 +#endif + +#define LECP_FLAG_CB_IS_VALUE 64 + +/* + * CBOR initial byte 3 x MSB bits are these + */ + +enum { + LWS_CBOR_MAJTYP_UINT = 0 << 5, + LWS_CBOR_MAJTYP_INT_NEG = 1 << 5, + LWS_CBOR_MAJTYP_BSTR = 2 << 5, + LWS_CBOR_MAJTYP_TSTR = 3 << 5, + LWS_CBOR_MAJTYP_ARRAY = 4 << 5, + LWS_CBOR_MAJTYP_MAP = 5 << 5, + LWS_CBOR_MAJTYP_TAG = 6 << 5, + LWS_CBOR_MAJTYP_FLOAT = 7 << 5, /* also BREAK */ + + LWS_CBOR_MAJTYP_MASK = 7 << 5, + + /* + * For the low 5 bits of the opcode, 0-23 are literals, unless it's + * FLOAT. + * + * 24 = 1 byte; 25 = 2..., 26 = 4... and 27 = 8 bytes following literal. + */ + LWS_CBOR_1 = 24, + LWS_CBOR_2 = 25, + LWS_CBOR_4 = 26, + LWS_CBOR_8 = 27, + + LWS_CBOR_RESERVED = 28, + + LWS_CBOR_SUBMASK = 0x1f, + + /* + * Major type 7 discriminators in low 5 bits + * 0 - 23 is SIMPLE implicit value (like, eg, LWS_CBOR_SWK_TRUE) + */ + LWS_CBOR_SWK_FALSE = 20, + LWS_CBOR_SWK_TRUE = 21, + LWS_CBOR_SWK_NULL = 22, + LWS_CBOR_SWK_UNDEFINED = 23, + + LWS_CBOR_M7_SUBTYP_SIMPLE_X8 = 24, /* simple with additional byte */ + LWS_CBOR_M7_SUBTYP_FLOAT16 = 25, + LWS_CBOR_M7_SUBTYP_FLOAT32 = 26, + LWS_CBOR_M7_SUBTYP_FLOAT64 = 27, + LWS_CBOR_M7_BREAK = 31, + +/* 28, 29, 30 are illegal. + * + * 31 is illegal for UINT, INT_NEG, and TAG; + * for BSTR, TSTR, ARRAY and MAP it means "indefinite length", ie, + * it's made up of an endless amount of determinite-length + * fragments terminated with a BREAK (FLOAT | 31) instead of the + * next determinite-length fragment. The second framing level + * means no need for escapes for BREAK in the data. + */ + + LWS_CBOR_INDETERMINITE = 31, + +/* + * Well-known tags + */ + + LWS_CBOR_WKTAG_DATETIME_STD = 0, /* text */ + LWS_CBOR_WKTAG_DATETIME_EPOCH = 1, /* int or float */ + LWS_CBOR_WKTAG_BIGNUM_UNSIGNED = 2, /* byte string */ + LWS_CBOR_WKTAG_BIGNUM_NEGATIVE = 3, /* byte string */ + LWS_CBOR_WKTAG_DECIMAL_FRAC = 4, /* array */ + LWS_CBOR_WKTAG_BIGFLOAT = 5, /* array */ + + LWS_CBOR_WKTAG_COSE_ENC0 = 16, + LWS_CBOR_WKTAG_COSE_MAC0 = 17, + LWS_CBOR_WKTAG_COSE_SIGN1 = 18, + + LWS_CBOR_WKTAG_TO_B64U = 21, /* any */ + LWS_CBOR_WKTAG_TO_B64 = 22, /* any */ + LWS_CBOR_WKTAG_TO_B16 = 23, /* any */ + LWS_CBOR_WKTAG_CBOR = 24, /* byte string */ + + LWS_CBOR_WKTAG_URI = 32, /* text string */ + LWS_CBOR_WKTAG_B64U = 33, /* text string */ + LWS_CBOR_WKTAG_B64 = 34, /* text string */ + LWS_CBOR_WKTAG_MIME = 36, /* text string */ + + LWS_CBOR_WKTAG_COSE_ENC = 96, + LWS_CBOR_WKTAG_COSE_MAC = 97, + LWS_CBOR_WKTAG_COSE_SIGN = 98, + + LWS_CBOR_WKTAG_SELFDESCCBOR = 55799 +}; + +enum lecp_callbacks { + LECPCB_CONSTRUCTED = 0, + LECPCB_DESTRUCTED = 1, + + LECPCB_COMPLETE = 3, + LECPCB_FAILED = 4, + + LECPCB_PAIR_NAME = 5, + + LECPCB_VAL_TRUE = LECP_FLAG_CB_IS_VALUE | 6, + LECPCB_VAL_FALSE = LECP_FLAG_CB_IS_VALUE | 7, + LECPCB_VAL_NULL = LECP_FLAG_CB_IS_VALUE | 8, + LECPCB_VAL_NUM_INT = LECP_FLAG_CB_IS_VALUE | 9, + LECPCB_VAL_RESERVED = LECP_FLAG_CB_IS_VALUE | 10, + LECPCB_VAL_STR_START = 11, /* notice handle separately */ + LECPCB_VAL_STR_CHUNK = LECP_FLAG_CB_IS_VALUE | 12, + LECPCB_VAL_STR_END = LECP_FLAG_CB_IS_VALUE | 13, + + LECPCB_ARRAY_START = 14, + LECPCB_ARRAY_END = 15, + + LECPCB_OBJECT_START = 16, + LECPCB_OBJECT_END = 17, + + LECPCB_TAG_START = 18, + LECPCB_TAG_END = 19, + + LECPCB_VAL_NUM_UINT = LECP_FLAG_CB_IS_VALUE | 20, + LECPCB_VAL_UNDEFINED = LECP_FLAG_CB_IS_VALUE | 21, + LECPCB_VAL_FLOAT16 = LECP_FLAG_CB_IS_VALUE | 22, + LECPCB_VAL_FLOAT32 = LECP_FLAG_CB_IS_VALUE | 23, + LECPCB_VAL_FLOAT64 = LECP_FLAG_CB_IS_VALUE | 24, + + LECPCB_VAL_SIMPLE = LECP_FLAG_CB_IS_VALUE | 25, + + LECPCB_VAL_BLOB_START = 26, /* notice handle separately */ + LECPCB_VAL_BLOB_CHUNK = LECP_FLAG_CB_IS_VALUE | 27, + LECPCB_VAL_BLOB_END = LECP_FLAG_CB_IS_VALUE | 28, + + LECPCB_ARRAY_ITEM_START = 29, + LECPCB_ARRAY_ITEM_END = 30, + + LECPCB_LITERAL_CBOR = 31, +}; + +enum lecp_reasons { + LECP_CONTINUE = -1, + LECP_REJECT_BAD_CODING = -2, + LECP_REJECT_UNKNOWN = -3, + LECP_REJECT_CALLBACK = -4, + LECP_STACK_OVERFLOW = -5, +}; + + +struct lecp_item { + union { + uint64_t u64; + int64_t i64; + + uint64_t u32; + + uint16_t hf; +#if defined(LWS_WITH_CBOR_FLOAT) + float f; + double d; +#else + uint32_t f; + uint64_t d; +#endif + } u; + uint8_t opcode; +}; + +struct lecp_ctx; +typedef signed char (*lecp_callback)(struct lecp_ctx *ctx, char reason); + +struct _lecp_stack { + char s; /* lejp_state stack*/ + uint8_t p; /* path length */ + char i; /* index array length */ + char indet; /* indeterminite */ + char intermediate; /* in middle of string */ + + char pop_iss; + uint64_t tag; + uint64_t collect_rem; + uint32_t ordinal; + uint8_t opcode; + uint8_t send_new_array_item; + uint8_t barrier; +}; + +struct _lecp_parsing_stack { + void *user; /* private to the stack level */ + lecp_callback cb; + const char * const *paths; + uint8_t count_paths; + uint8_t ppos; + uint8_t path_match; +}; + +struct lecp_ctx { + + /* sorted by type for most compact alignment + * + * pointers + */ + void *user; + uint8_t *collect_tgt; + + /* arrays */ + + struct _lecp_parsing_stack pst[LECP_MAX_PARSING_STACK_DEPTH]; + struct _lecp_stack st[LECP_MAX_DEPTH]; + uint16_t i[LECP_MAX_INDEX_DEPTH]; /* index array */ + uint16_t wild[LECP_MAX_INDEX_DEPTH]; /* index array */ + char path[LECP_MAX_PATH]; + uint8_t cbor[64]; /* literal cbor capture */ + + struct lecp_item item; + + + /* size_t */ + + size_t path_stride; /* 0 means default ptr size, else + * stride... allows paths to be + * provided composed inside a + * larger user struct instead of a + * duplicated array */ + size_t used_in; /* bytes of input consumed */ + + /* short */ + + uint16_t uni; + + /* char */ + + uint8_t npos; + uint8_t dcount; + uint8_t f; + uint8_t sp; /* stack head */ + uint8_t ipos; /* index stack depth */ + uint8_t count_paths; + uint8_t path_match; + uint8_t path_match_len; + uint8_t wildcount; + uint8_t pst_sp; /* parsing stack head */ + uint8_t outer_array; + uint8_t cbor_pos; + uint8_t literal_cbor_report; + char present; /* temp for cb reason to use */ + + uint8_t be; /* big endian */ + + /* at end so we can memset the rest of it */ + + char buf[LECP_STRING_CHUNK + 1]; +}; + +enum lws_lec_pctx_ret { + LWS_LECPCTX_RET_FINISHED = 0, + LWS_LECPCTX_RET_AGAIN, /* call again to continue writing buffer */ + LWS_LECPCTX_RET_FAIL /* something broken, eg, format string */ +}; + +enum cbp_state { + CBPS_IDLE, + CBPS_PC1, + CBPS_PC2, + CBPS_PC3, + + CBPS_STRING_BODY, + + CBPS_NUM_LIT, + + CBPS_STRING_LIT, + + CBPS_CONTYPE, +}; + +typedef struct lws_lec_pctx { + uint8_t stack[16]; + uint8_t vaa[16]; + uint8_t indet[16]; + uint8_t scratch[24]; + uint8_t *start; /* the beginning of the out buf */ + uint8_t *buf; /* cur pos in output buf */ + uint8_t *end; /* the end of the output buf */ + + const uint8_t *ongoing_src; + uint64_t ongoing_len; + uint64_t ongoing_done; + + struct lecp_item item; + + size_t used; /* number of bytes valid from start */ + + int opaque[4]; /* ignored by lws, caller may use */ + + enum cbp_state state; + unsigned int fmt_pos; + uint8_t sp; + uint8_t scratch_len; + uint8_t escflag; + uint8_t _long; + uint8_t vaa_pos; + uint8_t dotstar; +} lws_lec_pctx_t; + +LWS_VISIBLE LWS_EXTERN void +lws_lec_int(lws_lec_pctx_t *ctx, uint8_t opcode, uint8_t indet, uint64_t num); + +LWS_VISIBLE LWS_EXTERN int +lws_lec_scratch(lws_lec_pctx_t *ctx); + +/* + * lws_lec_init() - prepare a cbor writing context + * + * \param ctx: the cbor writing context to prepare + * \param buf: the output buffer start + * \param len: the amount of the output buffer we can use + * + * Prepares a cbor writing context so that les_lec_printf can be used to + * write into it. + */ +LWS_VISIBLE LWS_EXTERN void +lws_lec_init(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len); + +/* + * lws_lec_setbuf() - update the output buffer for an initialized cbor writing ctx + * + * \param ctx: the cbor writing context to prepare + * \param buf: the output buffer start + * \param len: the amount of the output buffer we can use + * + * Leaves the cbor writing context state as it is, but resets the output buffer + * it writes into as given in \p buf and \p len + */ +LWS_VISIBLE LWS_EXTERN void +lws_lec_setbuf(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len); + +/* + * lws_lec_vsprintf() - write into a cbor writing context + * + * \param ctx: the cbor writing context to prepare + * \param format: a printf style argument map + * \param args: the va args + * + * CBOR-aware vsprintf which pauses output when it fills the output buffer. You + * can call it again with the same args and same lws_lex_pctx to resume filling + * + * Returns either LWS_LECPCTX_RET_FINISHED if we have nothing left over that we + * want to put in the buffer, or LWS_LECPCTX_RET_AGAIN if the function should + * be called again with the same arguments (perhaps into a different output + * buffer) to continue emitting output from where it left off. + * + * If LWS_LECPCTX_RET_AGAIN is returned, lws_lec_setbuf() must be used on the + * context to reset or change the output buffer before calling again. + * + * The number of bytes placed in the output buffer is available in ctx->used. + * + * \p format is a printf-type format string that is specialized for CBOR + * generation. It understands the following specifiers + * + * |`123`||unsigned literal number| + * |`-123`||signed literal number| + * |`%u`|`unsigned int`|number| + * |`%lu`|`unsigned long int`|number| + * |`%llu`|`unsigned long long int`|number| + * |`%d`|`signed int`|number| + * |`%ld`|`signed long int`|number| + * |`%lld`|`signed long long int`|number| + * |`%f`|`double`|floating point number| + * |`123(...)`||literal tag and scope| + * |`%t(...)`|`unsigned int`|tag and scope| + * |`%lt(...)`|`unsigned long int`|tag and scope| + * |`%llt(...)`|`unsigned long long int`|tag and scope| + * |`[...]`||Array (fixed len if `]` in same format string)| + * |`{...}`||Map (fixed len if `}` in same format string)| + * |``||Container for indeterminite text string frags| + * |``||Container for indeterminite binary string frags| + * |`'string'`||Literal text of known length| + * |`%s`|`const char *`|NUL-terminated string| + * |`%.*s`|`int`, `const char *`|length-specified string| + * |`%.*b`|`int`, `const uint8_t *`|length-specified binary| + * |`:`||separator between Map items (a:b)| + * |`,`||separator between Map pairs or array items| + * + * See READMEs/README.cbor-lecp.md for more details. + */ +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_lec_vsprintf(lws_lec_pctx_t *ctx, const char *format, va_list args); + +/* + * lws_lec_printf() - write into a cbor writing context + * + * \param ctx: the cbor writing context to prepare + * \param format: a printf style argument map + * \param ...: format args + * + * See lws_lec_vsprintf() for format details. This is the most common way + * to format the CBOR output. + * + * See READMEs/README.cbor-lecp.md for more details. + */ +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_lec_printf(lws_lec_pctx_t *ctx, const char *format, ...); + +/** + * lecp_construct() - Construct an LECP parser context + * + * \param ctx: the parser context object to be initialized + * \param cb: the user callback to receive the parsing events + * \param user: an opaque user pointer available at \p cb + * \param paths: an optional array of parsing paths + * \param paths_count: how many paths in \p paths + * + * Prepares an LECP parser context for parsing. + */ +LWS_VISIBLE LWS_EXTERN void +lecp_construct(struct lecp_ctx *ctx, lecp_callback cb, void *user, + const char * const *paths, unsigned char paths_count); + +/** + * lecp_destruct() - Destroys an LECP parser context + * + * \param ctx: the parser context object to be destroyed + */ +LWS_VISIBLE LWS_EXTERN void +lecp_destruct(struct lecp_ctx *ctx); + +/** + * lecp_parse() - parses a chunk of input CBOR + * + * \p ctx: the parsing context + * \p cbor: the start of the chunk of CBOR + * \p len: the number of bytes of CBOR available at \p cbor + * + * Returns LECP_CONTINUE if more input needed, one of enum lecp_reasons for a + * fatal error, else 0 for successful parsing completion. + * + * On success or _CONTINUE, ctx->used_in is set to the number of input bytes + * consumed. + */ +LWS_VISIBLE LWS_EXTERN int +lecp_parse(struct lecp_ctx *ctx, const uint8_t *cbor, size_t len); + +LWS_VISIBLE LWS_EXTERN void +lecp_change_callback(struct lecp_ctx *ctx, lecp_callback cb); + +LWS_VISIBLE LWS_EXTERN const char * +lecp_error_to_string(int e); + +/** + * lecp_parse_report_raw() - turn cbor raw reporting on and off + * + * \param ctx: the lecp context + * \param on: 0 to disable (defaults disabled), 1 to enable + * + * For cose_sign, it needs access to raw cbor subtrees for the hash input. + * This api causes LECPCB_LITERAL_CBOR parse callbacks when there are + * ctx->cbor_pos bytes of raw cbor available in ctx->cbor[]. the callbacks + * occur when the ctx->cbor[] buffer fills or if it holds anything when this + * spi is used to stop the reports. + * + * The same CBOR that is being captured continues to be passed for parsing. + */ +LWS_VISIBLE LWS_EXTERN void +lecp_parse_report_raw(struct lecp_ctx *ctx, int on); + +/** + * lecp_parse_map_is_key() - return nonzero if we're in a map and this is a key + * + * \param ctx: the lwcp context + * + * Checks if the current value is a key in a map, ie, that you are on a "key" in + * a list of "{key: value}" pairs. Zero means you're either not in a map or not + * on the key part, and nonzero means you are in a map and on a key part. + */ +LWS_VISIBLE LWS_EXTERN int +lecp_parse_map_is_key(struct lecp_ctx *ctx); + +LWS_VISIBLE LWS_EXTERN int +lecp_parse_subtree(struct lecp_ctx *ctx, const uint8_t *in, size_t len); + +/* + * Helpers for half-float + */ + +LWS_VISIBLE LWS_EXTERN void +lws_singles2halfp(uint16_t *hp, uint32_t x); + +LWS_VISIBLE LWS_EXTERN void +lws_halfp2singles(uint32_t *xp, uint16_t h); + +//@} diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-lejp.h b/3rdparty/libwebsockets/include/libwebsockets/lws-lejp.h index 6ea6d3dc..f9f50270 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-lejp.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-lejp.h @@ -193,26 +193,26 @@ typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason); #endif enum num_flags { - LEJP_SEEN_MINUS = (1 << 0), - LEJP_SEEN_POINT = (1 << 1), - LEJP_SEEN_POST_POINT = (1 << 2), - LEJP_SEEN_EXP = (1 << 3) + LEJP_SEEN_MINUS = (1 << 0), + LEJP_SEEN_POINT = (1 << 1), + LEJP_SEEN_POST_POINT = (1 << 2), + LEJP_SEEN_EXP = (1 << 3) }; struct _lejp_stack { - char s; /* lejp_state stack*/ - char p; /* path length */ - char i; /* index array length */ - char b; /* user bitfield */ + char s; /* lejp_state stack*/ + char p; /* path length */ + char i; /* index array length */ + char b; /* user bitfield */ }; struct _lejp_parsing_stack { - void *user; /* private to the stack level */ - signed char (*callback)(struct lejp_ctx *ctx, char reason); - const char * const *paths; - uint8_t count_paths; - uint8_t ppos; - uint8_t path_match; + void *user; /* private to the stack level */ + signed char (*callback)(struct lejp_ctx *ctx, char reason); + const char * const *paths; + uint8_t count_paths; + uint8_t ppos; + uint8_t path_match; }; struct lejp_ctx { diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-logs.h b/3rdparty/libwebsockets/include/libwebsockets/lws-logs.h index 3a3c8924..795ba55c 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-logs.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-logs.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -31,23 +31,83 @@ * * Log categories may be individually filtered bitwise, and directed to built-in * sinks for syslog-compatible logging, or a user-defined function. + * + * Traditional logs use a single, processwide logging context. New style log + * apis (lws_xxx_cx()) can pass the logging context to use in. */ ///@{ -#define LLL_ERR (1 << 0) -#define LLL_WARN (1 << 1) -#define LLL_NOTICE (1 << 2) -#define LLL_INFO (1 << 3) -#define LLL_DEBUG (1 << 4) -#define LLL_PARSER (1 << 5) -#define LLL_HEADER (1 << 6) -#define LLL_EXT (1 << 7) -#define LLL_CLIENT (1 << 8) -#define LLL_LATENCY (1 << 9) -#define LLL_USER (1 << 10) -#define LLL_THREAD (1 << 11) - -#define LLL_COUNT (12) /* set to count of valid flags */ +#define LLL_ERR (1 << 0) +#define LLL_WARN (1 << 1) +#define LLL_NOTICE (1 << 2) +#define LLL_INFO (1 << 3) +#define LLL_DEBUG (1 << 4) +#define LLL_PARSER (1 << 5) +#define LLL_HEADER (1 << 6) +#define LLL_EXT (1 << 7) +#define LLL_CLIENT (1 << 8) +#define LLL_LATENCY (1 << 9) +#define LLL_USER (1 << 10) +#define LLL_THREAD (1 << 11) + +#define LLL_COUNT (12) /* set to count of valid flags */ + +#define LLLF_SECRECY_PII (1 << 16) + /**< contains Personally Identifiable Information */ +#define LLLF_SECRECY_BEARER (1 << 17) + /**< possession of this data allows impersonation */ + +#define LLLF_LOG_TIMESTAMP (1 << 18) + /**< set to prepend logs with timestamp */ + +#define LLLF_LOG_CONTEXT_AWARE (1 << 30) +/**< set if the context uses an emit function that takes the logctx, auto- + * applied when setting emit using lws_set_log_level_cx() api */ + +struct lws_log_cx; + +typedef void (*lws_log_emit_t)(int level, const char *line); +typedef void (*lws_log_emit_cx_t)(struct lws_log_cx *cx, int level, + const char *line, size_t len); +typedef void (*lws_log_prepend_cx_t)(struct lws_log_cx *cx, void *obj, + char **p, char *e); +typedef void (*lws_log_use_cx_t)(struct lws_log_cx *cx, int _new); + +/* + * This is the logging context + */ + +typedef struct lws_log_cx { + union { + lws_log_emit_t emit; /* legacy emit function */ + lws_log_emit_cx_t emit_cx; /* LLLF_LOG_CONTEXT_AWARE */ + } u; + +#if LWS_MAX_SMP > 1 + pthread_mutex_t refcount_lock; +#endif + + lws_log_use_cx_t refcount_cb; + /**< NULL, or a function called after each change to .refcount below, + * this enables implementing side-effects like opening and closing + * log files when the first and last object binds / unbinds */ + lws_log_prepend_cx_t prepend; + /**< NULL, or a cb to optionally prepend a string to logs we are a + * parent of */ + struct lws_log_cx *parent; + /**< NULL, or points to log ctx we are a child of */ + void *opaque; + /**< ignored by lws, used to pass config to emit_cx, eg, filepath */ + void *stg; + /**< ignored by lws, may be used a storage by refcount_cb / emit_cx */ + uint32_t lll_flags; + /**< mask of log levels we want to emit in this context */ + int32_t refcount; + /**< refcount of objects bound to this log context */ +#if LWS_MAX_SMP > 1 + char inited; +#endif +} lws_log_cx_t; /** * lwsl_timestamp: generate logging timestamp string @@ -64,10 +124,84 @@ lwsl_timestamp(int level, char *p, size_t len); #if defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK) #define _lws_log(aaa, ...) SMSG(__VA_ARGS__) #else -LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...) LWS_FORMAT(2); -LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl); +LWS_VISIBLE LWS_EXTERN void +_lws_log(int filter, const char *format, ...) LWS_FORMAT(2); +LWS_VISIBLE LWS_EXTERN void +_lws_logv(int filter, const char *format, va_list vl); +#endif + +struct lws_vhost; +struct lws; + +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_context_get_cx(struct lws_context *cx); +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_vhost_get_cx(struct lws_vhost *vh); +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_wsi_get_cx(struct lws *wsi); +#if defined(LWS_WITH_SECURE_STREAMS) +struct lws_ss_handle; +struct lws_sspc_handle; +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_ss_get_cx(struct lws_ss_handle *ss); +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_sspc_get_cx(struct lws_sspc_handle *ss); +#endif + +LWS_VISIBLE LWS_EXTERN void +lws_log_emit_cx_file(struct lws_log_cx *cx, int level, const char *line, + size_t len); + +LWS_VISIBLE LWS_EXTERN void +lws_log_use_cx_file(struct lws_log_cx *cx, int _new); + +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_context(struct lws_log_cx *cx, void *obj, char **p, char *e); +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_vhost(struct lws_log_cx *cx, void *obj, char **p, char *e); +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e); +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_ss(struct lws_log_cx *cx, void *obj, char **p, char *e); +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e); #endif +LWS_VISIBLE LWS_EXTERN void +_lws_log_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int filter, const char *_fun, const char *format, ...) LWS_FORMAT(6); + +#define lwsl_cx(_c, _fil, ...) \ + _lws_log_cx(lwsl_context_get_cx(_c), lws_log_prepend_context, \ + _c, _fil, __func__, __VA_ARGS__) +#define lwsl_vhost(_v, _fil, ...) \ + _lws_log_cx(lwsl_vhost_get_cx(_v), lws_log_prepend_vhost, _v, \ + _fil, __func__, __VA_ARGS__) +#define lwsl_wsi(_w, _fil, ...) \ + _lws_log_cx(lwsl_wsi_get_cx(_w), lws_log_prepend_wsi, _w, \ + _fil, __func__, __VA_ARGS__) +#define lwsl_ss(_h, _fil, ...) \ + _lws_log_cx(lwsl_ss_get_cx(_h), lws_log_prepend_ss, _h, \ + _fil, __func__, __VA_ARGS__) + +#define lwsl_hexdump_context(_c, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_context_get_cx(_c), \ + lws_log_prepend_context, \ + _c, _fil, _buf, _len) +#define lwsl_hexdump_vhost(_v, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_vhost_get_cx(_v), \ + lws_log_prepend_vhost, \ + _v, _fil, _buf, _len) +#define lwsl_hexdump_wsi(_w, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_wsi_get_cx(_w), \ + lws_log_prepend_wsi, \ + _w, _fil, _buf, _len) +#define lwsl_hexdump_ss(_h, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_ss_get_cx(_h), \ + lws_log_prepend_ss, \ + _h, _fil, _buf, _len) + /* * Figure out which logs to build in or not */ @@ -120,6 +254,10 @@ LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl * depending on what was computed */ +/* + * Process scope logs + */ + #if (_LWS_ENABLED_LOGS & LLL_ERR) #define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__) #else @@ -192,13 +330,344 @@ LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl #define lwsl_user(...) do {} while(0) #endif - #define lwsl_hexdump_err(...) lwsl_hexdump_level(LLL_ERR, __VA_ARGS__) #define lwsl_hexdump_warn(...) lwsl_hexdump_level(LLL_WARN, __VA_ARGS__) #define lwsl_hexdump_notice(...) lwsl_hexdump_level(LLL_NOTICE, __VA_ARGS__) #define lwsl_hexdump_info(...) lwsl_hexdump_level(LLL_INFO, __VA_ARGS__) #define lwsl_hexdump_debug(...) lwsl_hexdump_level(LLL_DEBUG, __VA_ARGS__) +/* + * lws_context scope logs + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_cx_err(_c, ...) lwsl_cx(_c, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_cx_err(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_cx_warn(_c, ...) lwsl_cx(_c, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_cx_warn(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_cx_notice(_c, ...) lwsl_cx(_c, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_cx_notice(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_cx_info(_c, ...) lwsl_cx(_c, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_cx_info(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_cx_debug(_c, ...) lwsl_cx(_c, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_cx_debug(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_cx_parser(_c, ...) lwsl_cx(_c, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_cx_parser(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_cx_header(_c, ...) lwsl_cx(_c, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_cx_header(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_cx_ext(_c, ...) lwsl_cx(_c, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_cx_ext(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_cx_client(_c, ...) lwsl_cx(_c, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_cx_client(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_cx_latency(_c, ...) lwsl_cx(_c, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_cx_latency(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_cx_thread(_c, ...) lwsl_cx(_c, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_cx_thread(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_cx_user(_c, ...) lwsl_cx(_c, LLL_USER, __VA_ARGS__) +#else +#define lwsl_cx_user(_c, ...) do {} while(0) +#endif + +#define lwsl_hexdump_cx_err(_c, ...) lwsl_hexdump_context(_c, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_cx_warn(_c, ...) lwsl_hexdump_context(_c, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_cx_notice(_c, ...) lwsl_hexdump_context(_c, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_cx_info(_c, ...) lwsl_hexdump_context(_c, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_cx_debug(_c, ...) lwsl_hexdump_context(_c, LLL_DEBUG, __VA_ARGS__) + +/* + * lws_vhost + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_vhost_err(_v, ...) lwsl_vhost(_v, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_vhost_err(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_vhost_warn(_v, ...) lwsl_vhost(_v, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_vhost_warn(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_vhost_notice(_v, ...) lwsl_vhost(_v, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_vhost_notice(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_vhost_info(_v, ...) lwsl_vhost(_v, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_vhost_info(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_vhost_debug(_v, ...) lwsl_vhost(_v, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_vhost_debug(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_vhost_parser(_v, ...) lwsl_vhost(_v, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_vhost_parser(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_vhost_header(_v, ...) lwsl_vhost(_v, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_vhost_header(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_vhost_ext(_v, ...) lwsl_vhost(_v, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_vhost_ext(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_vhost_client(_v, ...) lwsl_vhost(_v, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_vhost_client(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_vhost_latency(_v, ...) lwsl_vhost(_v, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_vhost_latency(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_vhost_thread(_v, ...) lwsl_vhost(_v, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_vhost_thread(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_vhost_user(_v, ...) lwsl_vhost(_v, LLL_USER, __VA_ARGS__) +#else +#define lwsl_vhost_user(_v, ...) do {} while(0) +#endif + +#define lwsl_hexdump_vhost_err(_v, ...) lwsl_hexdump_vhost(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_vhost_warn(_v, ...) lwsl_hexdump_vhost(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_vhost_notice(_v, ...) lwsl_hexdump_vhost(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_vhost_info(_v, ...) lwsl_hexdump_vhost(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_vhost_debug(_v, ...) lwsl_hexdump_vhost(_v, LLL_DEBUG, __VA_ARGS__) + + +/* + * lws_wsi + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_wsi_err(_w, ...) lwsl_wsi(_w, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_wsi_err(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_wsi_warn(_w, ...) lwsl_wsi(_w, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_wsi_warn(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_wsi_notice(_w, ...) lwsl_wsi(_w, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_wsi_notice(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_wsi_info(_w, ...) lwsl_wsi(_w, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_wsi_info(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_wsi_debug(_w, ...) lwsl_wsi(_w, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_wsi_debug(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_wsi_parser(_w, ...) lwsl_wsi(_w, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_wsi_parser(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_wsi_header(_w, ...) lwsl_wsi(_w, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_wsi_header(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_wsi_ext(_w, ...) lwsl_wsi(_w, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_wsi_ext(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_wsi_client(_w, ...) lwsl_wsi(_w, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_wsi_client(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_wsi_latency(_w, ...) lwsl_wsi(_w, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_wsi_latency(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_wsi_thread(_w, ...) lwsl_wsi(_w, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_wsi_thread(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_wsi_user(_w, ...) lwsl_wsi(_w, LLL_USER, __VA_ARGS__) +#else +#define lwsl_wsi_user(_w, ...) do {} while(0) +#endif + +#define lwsl_hexdump_wsi_err(_v, ...) lwsl_hexdump_wsi(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_wsi_warn(_v, ...) lwsl_hexdump_wsi(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_wsi_notice(_v, ...) lwsl_hexdump_wsi(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_wsi_info(_v, ...) lwsl_hexdump_wsi(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_wsi_debug(_v, ...) lwsl_hexdump_wsi(_v, LLL_DEBUG, __VA_ARGS__) + + +/* + * lwsl_ss + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_ss_err(_w, ...) lwsl_ss(_w, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_ss_err(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_ss_warn(_w, ...) lwsl_ss(_w, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_ss_warn(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_ss_notice(_w, ...) lwsl_ss(_w, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_ss_notice(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_ss_info(_w, ...) lwsl_ss(_w, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_ss_info(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_ss_debug(_w, ...) lwsl_ss(_w, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_ss_debug(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_ss_parser(_w, ...) lwsl_ss(_w, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_ss_parser(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_ss_header(_w, ...) lwsl_ss(_w, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_ss_header(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_ss_ext(_w, ...) lwsl_ss(_w, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_ss_ext(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_ss_client(_w, ...) lwsl_ss(_w, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_ss_client(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_ss_latency(_w, ...) lwsl_ss(_w, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_ss_latency(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_ss_thread(_w, ...) lwsl_ss(_w, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_ss_thread(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_ss_user(_w, ...) lwsl_ss(_w, LLL_USER, __VA_ARGS__) +#else +#define lwsl_ss_user(_w, ...) do {} while(0) +#endif + +#define lwsl_hexdump_ss_err(_v, ...) lwsl_hexdump_ss(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_ss_warn(_v, ...) lwsl_hexdump_ss(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_ss_notice(_v, ...) lwsl_hexdump_ss(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_ss_info(_v, ...) lwsl_hexdump_ss(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_ss_debug(_v, ...) lwsl_hexdump_ss(_v, LLL_DEBUG, __VA_ARGS__) + + + /** * lwsl_hexdump_level() - helper to hexdump a buffer at a selected debug level * @@ -212,6 +681,10 @@ LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl LWS_VISIBLE LWS_EXTERN void lwsl_hexdump_level(int level, const void *vbuf, size_t len); +LWS_VISIBLE LWS_EXTERN void +lwsl_hexdump_level_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int hexdump_level, const void *vbuf, size_t len); + /** * lwsl_hexdump() - helper to hexdump a buffer (DEBUG builds only) * @@ -241,13 +714,20 @@ static LWS_INLINE int lws_is_be(void) { * function to perform log string emission instead of * the default stderr one. * - * log level defaults to "err", "warn" and "notice" contexts enabled and - * emission on stderr. If stderr is a tty (according to isatty()) then - * the output is coloured according to the log level using ANSI escapes. + * log level defaults to "err", "warn" and "notice" contexts enabled and + * emission on stderr. If stderr is a tty (according to isatty()) then + * the output is coloured according to the log level using ANSI escapes. + * + * You can set the default security level for logging using the + * secrecy_and_log_level() macro to set the \p level parameter, eg + * + * lws_set_log_level(secrecy_and_log_level(LWS_SECRECY_PII, LLL_ERR | LLL_WARN), + * my_emit_function); + * + * Normally you can just leave it at the default. */ LWS_VISIBLE LWS_EXTERN void -lws_set_log_level(int level, - void (*log_emit_function)(int level, const char *line)); +lws_set_log_level(int level, lws_log_emit_t log_emit_function); /** * lwsl_emit_syslog() - helper log emit function writes to system log @@ -308,4 +788,7 @@ struct lws; LWS_VISIBLE LWS_EXTERN const char * lws_wsi_tag(struct lws *wsi); +LWS_VISIBLE LWS_EXTERN void +lwsl_refcount_cx(lws_log_cx_t *cx, int _new); + ///@} diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-map.h b/3rdparty/libwebsockets/include/libwebsockets/lws-map.h new file mode 100644 index 00000000..cf2368a0 --- /dev/null +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-map.h @@ -0,0 +1,188 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 lws_map generic map apis + * ##Generic map structures and apis + * \ingroup lwsapi + * + * lws_map + * + * Discrete owner object represents the whole map, created with key-specific + * ops for hashing the key to a uint32_t and comparing two keys. Owns a list + * of hash tables whose size / modulo it set at creation time. + * + * Items in the map are contained in a lws_map_item_t that is indexed in a + * hash table. + * + * It's difficult to make a single compact map abstraction that fits all cases, + * this is useful to the extent you have the memory to trade off the number of + * hashtables needed for the amount of items and the lookup latency limit for + * your application, typically for hundreds or low thousands of items. + */ +//@{ + +typedef struct lws_map lws_map_t; +struct lws_map_item; + +typedef void * lws_map_key_t; +typedef void * lws_map_value_t; +typedef uint32_t lws_map_hash_t; + +typedef lws_map_hash_t (*lws_map_hash_from_key_t)(const lws_map_key_t key, + size_t kl); +typedef int (*lws_map_compare_key_t)(const lws_map_key_t key1, size_t kl1, + const lws_map_value_t key2, size_t kl2); +typedef void * (*lws_map_alloc_t)(struct lws_map *mo, size_t x); +typedef void (*lws_map_free_t)(void *); + +/* + * Creation parameters for the map, copied into the map owner + */ + +typedef struct lws_map_info { + lws_map_hash_from_key_t _hash; + lws_map_compare_key_t _compare; + lws_map_alloc_t _alloc; /* NULL = lws_malloc */ + lws_map_free_t _free; /* NULL = lws_free */ + + void *opaque; + /**< &lwsac if using lwsac allocator */ + void *aux; + /**< chunk size if using lwsac allocator */ + /**< this can be used by the alloc handler, eg for lws_ac */ + size_t modulo; + /**< number of hashed owner lists to create */ +} lws_map_info_t; + +LWS_VISIBLE LWS_EXTERN const void * +lws_map_item_key(struct lws_map_item *_item); +LWS_VISIBLE LWS_EXTERN const void * +lws_map_item_value(struct lws_map_item *_item); +LWS_VISIBLE LWS_EXTERN size_t +lws_map_item_key_len(struct lws_map_item *_item); +LWS_VISIBLE LWS_EXTERN size_t +lws_map_item_value_len(struct lws_map_item *_item); + +/* + * Helpers for C string keys case + */ + +#define lws_map_item_create_ks(_map, _str, _v, _vl) \ + lws_map_item_create(_map, (const lws_map_key_t)_str, \ + strlen(_str), (const lws_map_value_t)_v, \ + _vl) +#define lws_map_item_lookup_ks(_map, _str) \ + lws_map_item_lookup(_map, (const lws_map_key_t)_str, strlen(_str)) + +/** + * lws_map_create() - create a map object and hashtables on heap + * + * \param info: description of map to create + * + * Creates a map object on heap, using lws_malloc(). + * + * \p info may be all zeros inside, if so, modulo defaults to 8, and the + * operation callbacks default to using lws_malloc() / _free() for item alloc, + * a default xor / shift based hash and simple linear memory key compare. + * + * For less typical use-cases, the provided \p info members can be tuned to + * control how the allocation of mapped items is done, lws provides two exports + * lws_map_alloc_lwsac() and lws_map_free_lwsac() that can be used for _alloc + * and _free to have items allocated inside an lwsac. + * + * The map itself is created on the heap directly, the info._alloc() op is only + * used when creating items. + * + * keys have individual memory sizes and do not need to all be the same length. + */ +LWS_VISIBLE LWS_EXTERN lws_map_t * +lws_map_create(const lws_map_info_t *info); + +/* + * helpers that can be used for info._alloc and info._free if using lwsac + * allocation for items, set info.opaque to point to the lwsac pointer, and + * aux to (void *)chunksize, or leave zero / NULL for the default + */ + +LWS_VISIBLE LWS_EXTERN void * +lws_map_alloc_lwsac(struct lws_map *map, size_t x); + +LWS_VISIBLE LWS_EXTERN void +lws_map_free_lwsac(void *v); + +/** + * lws_map_destroy() - deallocate all items and free map + * + * \param pmap: pointer to pointer map object to deallocate + * + * Frees all items in the map, using info._free(), and then frees the map + * from heap directly. \p *pmap is set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_map_destroy(lws_map_t **pmap); + +/** + * lws_map_item_create() - allocate and map an item into an existing map + * + * \param map: the map to add items into + * \param key: the key, may be any kind of object + * \param keylen: the length of the key in bytes + * \param value: the value, may be any kind of object + * \param valuelen: the length of value + * + * Allocates space for the item, key and value using the map allocator, and + * if non-NULL, copies the key and value into the item. + * + * If an item with the same key exists, it is removed and destroyed before + * creating and adding the new one. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_map_item * +lws_map_item_create(lws_map_t *map, + const lws_map_key_t key, size_t keylen, + const lws_map_value_t value, size_t valuelen); + +/** + * lws_map_item_destroy() - remove item from map and free + * + * \param item: the item in the map to remove and free + */ +LWS_VISIBLE LWS_EXTERN void +lws_map_item_destroy(struct lws_map_item *item); + +/** + * lws_map_item_lookup() - look for a item with the given key in the map + * + * \param map: the map + * \param key: the key to look for + * \param keylen: the length of the key to look for + * + * Searches for the key in the map, using the map's key hash and key compare + * functions. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_map_item * +lws_map_item_lookup(lws_map_t *map, const lws_map_key_t key, size_t keylen); + +//@} diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-misc.h b/3rdparty/libwebsockets/include/libwebsockets/lws-misc.h index 17a4b3bd..c6dc4397 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-misc.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-misc.h @@ -817,6 +817,25 @@ lws_is_ssl(struct lws *wsi); LWS_VISIBLE LWS_EXTERN int lws_is_cgi(struct lws *wsi); +/** + * lws_tls_jit_trust_blob_queury_skid() - walk jit trust blob for skid + * + * \param _blob: the start of the blob in memory + * \param blen: the length of the blob in memory + * \param skid: the SKID we are looking for + * \param skid_len: the length of the SKID we are looking for + * \param prpder: result pointer to receive a pointer to the matching DER + * \param prder_len: result pointer to receive matching DER length + * + * Helper to scan a JIT Trust blob in memory for a trusted CA cert matching + * a given SKID. Returns 0 if found and *prpder and *prder_len are set, else + * nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_jit_trust_blob_queury_skid(const void *_blob, size_t blen, + const uint8_t *skid, size_t skid_len, + const uint8_t **prpder, size_t *prder_len); + /** * lws_open() - platform-specific wrapper for open that prepares the fd * diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-mqtt.h b/3rdparty/libwebsockets/include/libwebsockets/lws-mqtt.h index ff0ebb8a..cbf8b363 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-mqtt.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-mqtt.h @@ -3,20 +3,23 @@ * * Copyright (C) 2010 - 2021 Andy Green * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation: - * version 2.1 of the License. + * 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: * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * 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. * * included from libwebsockets.h */ @@ -39,6 +42,29 @@ typedef struct lws_mqtt_str_st lws_mqtt_str_t; #define LWS_MQTT_RANDOM_CIDLEN 23 /* 3.1.3.1-5: Server MUST... between 1 and 23 chars... */ +#define LWS_MQTT_SHADOW_MAX_THING_LEN 128 +#define LWS_MQTT_SHADOW_MAX_SHADOW_LEN 64 +#define LWS_MQTT_SHADOW_UPDATE_STR "/update" +#define LWS_MQTT_SHADOW_DELETE_STR "/delete" +#define LWS_MQTT_SHADOW_GET_STR "/get" +#define LWS_MQTT_SHADOW_RESP_ACCEPTED_STR "/accepted" +#define LWS_MQTT_SHADOW_RESP_REJECTED_STR "/rejected" +#define LWS_MQTT_SHADOW_RESP_DELTA_STR "/delta" +#define LWS_MQTT_SHADOW_RESP_DOCUMENT_STR "/documents" +#define LWS_MQTT_SHADOW_UPDATE_ACCEPTED_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR +#define LWS_MQTT_SHADOW_UPDATE_REJECTED_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR +#define LWS_MQTT_SHADOW_UPDATE_DELTA_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_DELTA_STR +#define LWS_MQTT_SHADOW_UPDATE_DOCUMENT_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_DOCUMENT_STR +#define LWS_MQTT_SHADOW_DELETE_ACCEPTED_STR LWS_MQTT_SHADOW_DELETE_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR +#define LWS_MQTT_SHADOW_DELETE_REJECTED_STR LWS_MQTT_SHADOW_DELETE_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR +#define LWS_MQTT_SHADOW_GET_ACCEPTED_STR LWS_MQTT_SHADOW_GET_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR +#define LWS_MQTT_SHADOW_GET_REJECTED_STR LWS_MQTT_SHADOW_GET_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR +#define LWS_MQTT_SHADOW_PREFIX_FORMAT "$aws/things/%s" +#define LWS_MQTT_SHADOW_NAMED_SHADOW_TOPIC_FORMAT LWS_MQTT_SHADOW_PREFIX_FORMAT "/shadow/name/%s%s" +#define LWS_MQTT_SHADOW_UNNAMED_SHADOW_TOPIC_FORMAT LWS_MQTT_SHADOW_PREFIX_FORMAT "/shadow%s" +#define LWS_MQTT_SHADOW_UNNAMED_TOPIC_MATCH "$aws/things/+/shadow/+" +#define LWS_MQTT_SHADOW_NAMED_TOPIC_MATCH "$aws/things/+/shadow/name/+/+" + typedef enum { QOS0, QOS1, @@ -67,8 +93,14 @@ typedef struct lws_mqtt_client_connect_param_s { uint16_t keep_alive; /* MQTT keep alive interval in seconds */ - uint8_t clean_start; /* MQTT clean + uint8_t clean_start:1; /* MQTT clean session */ + uint8_t client_id_nofree:1; + /**< do not free the client id */ + uint8_t username_nofree:1; + /**< do not free the username */ + uint8_t password_nofree:1; + /**< do not free the password */ struct { const char *topic; const char *message; @@ -76,6 +108,13 @@ typedef struct lws_mqtt_client_connect_param_s { uint8_t retain; } will_param; /* MQTT LWT parameters */ + struct { + const char *topic; + const char *message; + lws_mqtt_qos_levels_t qos; + uint8_t retain; + } birth_param; /* MQTT Birth + parameters */ const char *username; const char *password; uint8_t aws_iot; @@ -98,6 +137,7 @@ typedef struct lws_mqtt_publish_param_s { 0 */ uint8_t dup:1; /* Retried PUBLISH, for QoS > 0 */ + uint8_t retain:1; /* Retained message */ } lws_mqtt_publish_param_t; typedef struct topic_elem { @@ -140,6 +180,10 @@ typedef enum { /* flags from byte 8 of C_TO_S CONNECT */ typedef enum { + LMQCFT_USERNAME_NOFREE = (1 << 10), + LMQCFT_PASSWORD_NOFREE = (1 << 9), + LMQCFT_CLIENT_ID_NOFREE = (1 << 8), + /* only the low 8 are standardized and go out in the protocol */ LMQCFT_USERNAME = (1 << 7), LMQCFT_PASSWORD = (1 << 6), LMQCFT_WILL_RETAIN = (1 << 5), diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-network-helper.h b/3rdparty/libwebsockets/include/libwebsockets/lws-network-helper.h index 4ad16bef..09308b8b 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-network-helper.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-network-helper.h @@ -33,7 +33,8 @@ #include #endif -typedef uint8_t lws_route_uidx_t; +/* cope with large amounts of route information */ +typedef uint16_t lws_route_uidx_t; typedef struct lws_dns_score { uint8_t precedence; @@ -223,8 +224,9 @@ lws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46); * \param len: max size of text buffer * * Converts an array of network-ordered byte address elements to a textual - * representation of the numeric address, like "1.2.3.4" or "::1". Return 0 - * if OK else < 0. ipv6 only supported with LWS_IPV6=1 at cmake. + * representation of the numeric address, like "1.2.3.4" or "::1". Returns the + * number of chars written into buf, else < 0. ipv6 only supported with + * LWS_IPV6=1 at cmake. */ LWS_VISIBLE LWS_EXTERN int lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len); @@ -237,8 +239,9 @@ lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len); * \param len: max size of text buffer * * Converts the ipv4 or ipv6 address in an lws_sockaddr46 to a textual - * representation of the numeric address, like "1.2.3.4" or "::1". Return 0 - * if OK else < 0. ipv6 only supported with LWS_IPV6=1 at cmake. + * representation of the numeric address, like "1.2.3.4" or "::1". Returns the + * number of chars written into buf, else < 0. ipv6 only supported with + * LWS_IPV6=1 at cmake. */ LWS_VISIBLE LWS_EXTERN int lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-protocols-plugins.h b/3rdparty/libwebsockets/include/libwebsockets/lws-protocols-plugins.h index ec9d8d8c..66240c96 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-protocols-plugins.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-protocols-plugins.h @@ -86,6 +86,8 @@ struct lws_protocols { * This is part of the ABI, don't needlessly break compatibility */ }; +#define LWS_PROTOCOL_LIST_TERM { NULL, NULL, 0, 0, 0, NULL, 0 } + /** * lws_vhost_name_to_protocol() - get vhost's protocol object from its name * diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-client.h b/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-client.h index eac12e79..4d24cbae 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-client.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-client.h @@ -40,6 +40,8 @@ * lws_sspc_ in one step by #define LWS_SS_USE_SSPC before including */ +struct lws_sspc_handle; + #if defined(LWS_SS_USE_SSPC) #define lws_ss_handle lws_sspc_handle #define lws_ss_create lws_sspc_create @@ -62,10 +64,112 @@ #define lws_smd_ss_rx_forward lws_smd_sspc_rx_forward #define lws_ss_tag lws_sspc_tag #define _lws_fi_user_ss_fi _lws_fi_user_sspc_fi +#define lwsl_ss_get_cx lwsl_sspc_get_cx + +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e); + +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_sspc_get_cx(struct lws_sspc_handle *ss); + +#undef lwsl_ss +#define lwsl_ss lwsl_sspc + +#undef lwsl_hexdump_ss +#define lwsl_hexdump_ss lwsl_hexdump_sspc #endif +#define lwsl_sspc(_h, _fil, ...) \ + _lws_log_cx(lwsl_sspc_get_cx(_h), lws_log_prepend_sspc, _h, \ + _fil, __func__, __VA_ARGS__) + +#define lwsl_hexdump_sspc(_h, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_sspc_get_cx(_h), \ + lws_log_prepend_sspc, \ + _h, _fil, _buf, _len) + +/* + * lwsl_sspc + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_sspc_err(_w, ...) lwsl_sspc(_w, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_sspc_err(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_sspc_warn(_w, ...) lwsl_sspc(_w, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_sspc_warn(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_sspc_notice(_w, ...) lwsl_sspc(_w, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_sspc_notice(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_sspc_info(_w, ...) lwsl_sspc(_w, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_sspc_info(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_sspc_debug(_w, ...) lwsl_sspc(_w, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_sspc_debug(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_sspc_parser(_w, ...) lwsl_sspc(_w, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_sspc_parser(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_sspc_header(_w, ...) lwsl_sspc(_w, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_sspc_header(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_sspc_ext(_w, ...) lwsl_sspc(_w, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_sspc_ext(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_sspc_client(_w, ...) lwsl_sspc(_w, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_sspc_client(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_sspc_latency(_w, ...) lwsl_sspc(_w, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_sspc_latency(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_sspc_thread(_w, ...) lwsl_sspc(_w, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_sspc_thread(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_sspc_user(_w, ...) lwsl_sspc(_w, LLL_USER, __VA_ARGS__) +#else +#define lwsl_sspc_user(_w, ...) do {} while(0) +#endif + +#define lwsl_hexdump_sspc_err(_v, ...) lwsl_hexdump_sspc(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_sspc_warn(_v, ...) lwsl_hexdump_sspc(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_sspc_notice(_v, ...) lwsl_hexdump_sspc(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_sspc_info(_v, ...) lwsl_hexdump_sspc(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_sspc_debug(_v, ...) lwsl_hexdump_sspc(_v, LLL_DEBUG, __VA_ARGS__) -struct lws_sspc_handle; LWS_VISIBLE LWS_EXTERN int lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, @@ -119,8 +223,7 @@ lws_sspc_request_tx_len(struct lws_sspc_handle *h, unsigned long len); * * \param h: secure streams handle * - * Starts the connection process for the secure stream. Returns 0 if OK or - * nonzero if we have already failed. + * Starts the connection process for the secure stream. Returns 0. */ LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_sspc_client_connect(struct lws_sspc_handle *h); @@ -188,7 +291,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h); * when the policy is using h1 is interpreted to add h1 headers of the given * name with the value of the metadata on the left. * - * Return 0 if OK. + * Return 0 if OK, or nonzero if failed. */ LWS_VISIBLE LWS_EXTERN int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-policy.h b/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-policy.h index 55587e12..2c81f9fd 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-policy.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams-policy.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2021 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 @@ -158,6 +158,13 @@ enum { /**< stream is not critical and should be handled as cheap as poss */ LWSSSPOLF_PERF = (1 << 22), /**< capture and report performace information */ + LWSSSPOLF_DIRECT_PROTO_STR = (1 << 23), + /**< metadata as direct protocol string, e.g. http header */ + LWSSSPOLF_HTTP_CACHE_COOKIES = (1 << 24), + /**< Record http cookies and pass them back on future requests */ + LWSSSPOLF_PRIORITIZE_READS = (1 << 25), + /**< prioritize clearing reads at expense of writes */ + }; typedef struct lws_ss_trust_store { @@ -197,6 +204,9 @@ typedef struct lws_ss_metadata { uint8_t value_length; /* only valid if set by policy */ uint8_t value_is_http_token; /* valid if set by policy */ +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + uint8_t name_on_lws_heap:1; /* proxy metatadata does this */ +#endif uint8_t value_on_lws_heap:1; /* proxy + rx metadata does this */ #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) uint8_t pending_onward:1; @@ -302,12 +312,18 @@ typedef struct lws_ss_policy { const char *will_topic; const char *will_message; + const char *birth_topic; + const char *birth_message; + uint16_t keep_alive; uint8_t qos; uint8_t clean_start; uint8_t will_qos; uint8_t will_retain; + uint8_t birth_qos; + uint8_t birth_retain; uint8_t aws_iot; + uint8_t retain; } mqtt; diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams.h b/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams.h index 0aa79ec5..8157c700 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-secure-streams.h @@ -217,6 +217,15 @@ typedef enum { LWSSSCS_SERVER_TXN, LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */ + LWSSSCS_EVENT_WAIT_CANCELLED, /* somebody called lws_cancel_service */ + + LWSSSCS_UPSTREAM_LINK_RETRY, /* if we are being proxied over some + * intermediate link, this transient + * state may be sent to indicate we are + * waiting to establish that link before + * creation can proceed.. ack is the + * number of ms we have been trying */ + LWSSSCS_SINK_JOIN, /* sinks get this when a new source * stream joins the sink */ LWSSSCS_SINK_PART, /* sinks get this when a new source @@ -345,6 +354,11 @@ typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack); +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) +typedef void (*lws_ss_buffer_dump_cb)(void *userobj, const uint8_t *buf, + size_t len, int done); +#endif + struct lws_ss_policy; typedef struct lws_ss_info { @@ -377,6 +391,10 @@ typedef struct lws_ss_info { /**< 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. */ +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) + lws_ss_buffer_dump_cb dump; + /**< cb to record needed protocol buffer data*/ +#endif 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 @@ -436,7 +454,7 @@ typedef struct lws_ss_info { * formats, \p ppayload_fmt is set to point to the name of the needed payload * format from the policy database if non-NULL. */ -LWS_VISIBLE LWS_EXTERN int +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, struct lws_ss_handle **ppss, struct lws_sequencer *seq_owner, const char **ppayload_fmt); @@ -460,9 +478,9 @@ lws_ss_destroy(struct lws_ss_handle **ppss); * write on this stream, the \p *tx callback will occur with an empty buffer for * the stream owner to fill in. * - * Returns 0 or LWSSSSRET_SS_HANDLE_DESTROYED + * Returns 0 or LWSSSSRET_DESTROY_ME */ -LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_request_tx(struct lws_ss_handle *pss); /** @@ -478,7 +496,7 @@ lws_ss_request_tx(struct lws_ss_handle *pss); * 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 lws_ss_state_return_t +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); /** @@ -494,7 +512,7 @@ lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); * LWSSSSRET_OK means the connection is ongoing. * */ -LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_client_connect(struct lws_ss_handle *h); /** diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-service.h b/3rdparty/libwebsockets/include/libwebsockets/lws-service.h index 2f597b31..73e498a7 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-service.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-service.h @@ -59,7 +59,7 @@ lws_service(struct lws_context *context, int timeout_ms); * \param tsi: Thread service index, starting at 0 * * Same as lws_service(), but for a specific thread service index. Only needed - * if you are spawning multiple service threads. + * if you are spawning multiple service threads that operate on the same lws_context. */ LWS_VISIBLE LWS_EXTERN int lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-system.h b/3rdparty/libwebsockets/include/libwebsockets/lws-system.h index 5d57a1f7..07900e02 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-system.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-system.h @@ -139,6 +139,7 @@ typedef enum { /* keep system_state_names[] in sync in context.c */ * drop everything done with old * policy, switch to new then enter * LWS_SYSTATE_POLICY_VALID */ + LWS_SYSTATE_CONTEXT_DESTROYING, /* Context is being destroyed */ } lws_system_states_t; /* Captive Portal Detect -related */ @@ -154,6 +155,11 @@ typedef enum { typedef void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque); struct lws_attach_item; +LWS_EXTERN LWS_VISIBLE int +lws_tls_jit_trust_got_cert_cb(struct lws_context *cx, void *got_opaque, + const uint8_t *skid, size_t skid_len, + const uint8_t *der, size_t der_len); + typedef struct lws_system_ops { int (*reboot)(void); int (*set_clock)(lws_usec_t us); @@ -186,6 +192,15 @@ typedef struct lws_system_ops { * held in \p mdata... return 0 to leave the metric object as it is, * or nonzero to reset it. */ + int (*jit_trust_query)(struct lws_context *cx, const uint8_t *skid, + size_t skid_len, void *got_opaque); + /**< user defined trust store search, if we do trust a cert with SKID + * matching skid / skid_len, then it should get hold of the DER for the + * matching root CA and call + * lws_tls_jit_trust_got_cert_cb(..., got_opaque) before cleaning up and + * returning. The DER should be destroyed if in heap before returning. + */ + uint32_t wake_latency_us; /**< time taken for this device to wake from suspend, in us */ diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-timeout-timer.h b/3rdparty/libwebsockets/include/libwebsockets/lws-timeout-timer.h index 6fd6a0e9..102a25fc 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-timeout-timer.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-timeout-timer.h @@ -150,64 +150,6 @@ lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us); 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 - * - * \param vh: the vhost to call back - * \param protocol: the protocol to call back - * \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. - * - * Returns 0 if OK or 1 on OOM. - * - * In the multithreaded service case, the callback will occur in the same - * service thread context as the call to this api that requested it. If it is - * called from a non-service thread, tsi 0 will handle it. - */ -LWS_VISIBLE LWS_EXTERN int -lws_timed_callback_vh_protocol(struct lws_vhost *vh, - const struct lws_protocols *prot, - int reason, int secs) -LWS_WARN_DEPRECATED; - -/* - * lws_timed_callback_vh_protocol_us() - calls back a protocol on a vhost after - * the specified delay in us - * - * \param vh: the vhost to call back - * \param protocol: the protocol to call back - * \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. - * - * Returns 0 if OK or 1 on OOM. - * - * In the multithreaded service case, the callback will occur in the same - * service thread context as the call to this api that requested it. If it is - * called from a non-service thread, tsi 0 will handle it. - */ -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_WARN_DEPRECATED; - -#endif - struct lws_sorted_usec_list; typedef void (*sul_cb_t)(struct lws_sorted_usec_list *sul); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-tokenize.h b/3rdparty/libwebsockets/include/libwebsockets/lws-tokenize.h index 9af6c597..66b34b41 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-tokenize.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-tokenize.h @@ -259,11 +259,14 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, * lws_strcmp_wildcard() - strcmp but the first arg can have wildcards * * \p wildcard: a string that may contain zero to three *, and may lack a NUL - * \p len: length of the wildcard string + * \p wlen: length of the wildcard string * \p check: string to test to see if it matches wildcard + * \p clen: length of check string * - * Exactly like strcmp, but supports patterns like "a*", "a*b", "a*b*" etc - * where a and b are arbitrary substrings + * Like strcmp, but supports patterns like "a*", "a*b", "a*b*" etc + * where a and b are arbitrary substrings. Both the wc and check strings need + * not be NUL terminated, but are specified by lengths. */ LWS_VISIBLE LWS_EXTERN int -lws_strcmp_wildcard(const char *wildcard, size_t len, const char *check); +lws_strcmp_wildcard(const char *wildcard, size_t wlen, const char *check, + size_t clen); diff --git a/3rdparty/libwebsockets/include/libwebsockets/lws-x509.h b/3rdparty/libwebsockets/include/libwebsockets/lws-x509.h index 55b66009..e60d6d16 100644 --- a/3rdparty/libwebsockets/include/libwebsockets/lws-x509.h +++ b/3rdparty/libwebsockets/include/libwebsockets/lws-x509.h @@ -47,6 +47,14 @@ enum lws_tls_cert_info { * -1 is returned and the size will be returned in buf->ns.len. * If the certificate cannot be found -1 is returned and 0 in * buf->ns.len. */ + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID, + /**< If the cert has one, the key ID responsible for the signature */ + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER, + /**< If the cert has one, the issuer responsible for the signature */ + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL, + /**< If the cert has one, serial number responsible for the signature */ + LWS_TLS_CERT_INFO_SUBJECT_KEY_ID, + /**< If the cert has one, the cert's subject key ID */ }; union lws_tls_cert_info_results { @@ -98,7 +106,7 @@ lws_x509_create(struct lws_x509_cert **x509); * IMPORTANT for compatibility with mbedtls, the last used byte of \p pem * must be '\0' and the \p len must include it. * - * Returns 0 if all went OK. + * Returns 0 if all went OK, or nonzero for failure. */ LWS_VISIBLE LWS_EXTERN int lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len); @@ -140,6 +148,7 @@ lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, * lws_x509_jwk_privkey_pem() - Copy a private key PEM into a jwk that has the * public part already * + * \param cx: lws_context (for random) * \param jwk: pointer to the jwk to initialize and set to the public key * \param pem: pointer to PEM private key in memory * \param len: length of PEM private key in memory @@ -155,8 +164,8 @@ lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, * The caller should take care to zero down passphrase if used. */ LWS_VISIBLE LWS_EXTERN int -lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, - const char *passphrase); +lws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk, + void *pem, size_t len, const char *passphrase); /** * lws_x509_destroy() - Destroy a previously allocated lws_x509_cert object @@ -183,8 +192,8 @@ lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type, * lws_tls_peer_cert_info() lets you get hold of information from the peer * certificate. * - * Return 0 if there is a result in \p buf, or -1 indicating there was no cert - * or another problem. + * Return 0 if there is a result in \p buf, or nonzero indicating there was no + * cert, or another problem. * * This function works the same no matter if the TLS backend is OpenSSL or * mbedTLS. @@ -204,8 +213,8 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, * lws_tls_vhost_cert_info() lets you get hold of information from the vhost * certificate. * - * Return 0 if there is a result in \p buf, or -1 indicating there was no cert - * or another problem. + * Return 0 if there is a result in \p buf, or nonzero indicating there was no + * cert, or another problem. * * This function works the same no matter if the TLS backend is OpenSSL or * mbedTLS. @@ -223,8 +232,8 @@ lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, * \param san_b: second SAN written into the certificate * * - * Returns 0 if created and attached to the vhost. Returns -1 if problems and - * frees all allocations before returning. + * Returns 0 if created and attached to the vhost. Returns nonzero if problems, + * and frees all allocations before returning. * * On success, any allocations are destroyed at vhost destruction automatically. */ diff --git a/3rdparty/libwebsockets/lib/CMakeLists.txt b/3rdparty/libwebsockets/lib/CMakeLists.txt index bff9e4c8..19dc0cf6 100644 --- a/3rdparty/libwebsockets/lib/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/CMakeLists.txt @@ -38,42 +38,46 @@ set(LWS_LIB_INCLUDES "") 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 ) + list(APPEND LWS_ESP_IDF_DIRS + $ENV{IDF_PATH}/components/freertos/include + $ENV{IDF_PATH}/components/esp_hw_support/include/soc/ + $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 ) + + include_directories(${LWS_ESP_IDF_DIRS}) + + list(APPEND CMAKE_REQUIRED_INCLUDES ${LWS_ESP_IDF_DIRS}) endif() + else() if (LWS_PLAT_OPTEE) @@ -117,7 +121,7 @@ CHECK_C_SOURCE_COMPILES(" # after kernel 2.6.37 CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT) - +set(LWS_PUBLIC_INCLUDES "") if (LWS_WITH_TLS) add_subdir_include_dirs(tls) endif() @@ -146,6 +150,10 @@ endif() if (LWS_WITH_JOSE) add_subdir_include_dirs(jose) endif() +if (LWS_WITH_COSE) + add_subdir_include_dirs(cose) +endif() + if (LWS_WITH_SECURE_STREAMS) add_subdir_include_dirs(secure-streams) @@ -168,14 +176,16 @@ if (LWS_WITH_STATIC) ) target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) target_compile_definitions(websockets PRIVATE LWS_BUILDING_STATIC) + target_include_directories(websockets PUBLIC ${LWS_PUBLIC_INCLUDES}) + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) - #if (WIN32) + 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() endif() @@ -194,6 +204,8 @@ if (LWS_WITH_SHARED) ) target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) target_compile_definitions(websockets_shared PRIVATE LWS_BUILDING_SHARED) + target_include_directories(websockets_shared PUBLIC ${LWS_PUBLIC_INCLUDES}) + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) # We want the shared lib to be named "libwebsockets" # not "libwebsocket_shared". @@ -280,7 +292,7 @@ install(TARGETS ${LWS_LIBRARIES} set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE) -if (UNIX) +if (UNIX OR MINGW) # figure out pkfcfg required libs here @@ -328,7 +340,7 @@ 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: -L\${libdir} -l:libwebsockets${CMAKE_STATIC_LIBRARY_SUFFIX} Libs.private: Cflags: -I\${includedir} " @@ -342,7 +354,7 @@ endif() install(FILES "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" DESTINATION lib${LIB_SUFFIX}/pkgconfig) -endif(UNIX) +endif(UNIX OR MINGW) # Keep explicit parent scope exports at end @@ -375,3 +387,4 @@ 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 --git a/3rdparty/libwebsockets/lib/abstract/protocols/smtp/smtp-sequencer.c b/3rdparty/libwebsockets/lib/abstract/protocols/smtp/smtp-sequencer.c index 4b745aab..24d8f44f 100644 --- a/3rdparty/libwebsockets/lib/abstract/protocols/smtp/smtp-sequencer.c +++ b/3rdparty/libwebsockets/lib/abstract/protocols/smtp/smtp-sequencer.c @@ -3,20 +3,23 @@ * * Copyright (C) 2016-2019 Andy Green * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation: - * version 2.1 of the License. + * 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: * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * 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 sequencer sits above the abstract protocol, and manages queueing, * retrying mail transmission, and retry limits. diff --git a/3rdparty/libwebsockets/lib/core-net/adopt.c b/3rdparty/libwebsockets/lib/core-net/adopt.c index a5fb8b43..579f4bfe 100644 --- a/3rdparty/libwebsockets/lib/core-net/adopt.c +++ b/3rdparty/libwebsockets/lib/core-net/adopt.c @@ -31,7 +31,7 @@ lws_get_idlest_tsi(struct lws_context *context) int n = 0, hit = -1; for (; n < context->count_threads; n++) { - lwsl_debug("%s: %d %d\n", __func__, context->pt[n].fds_count, + lwsl_cx_debug(context, "%d %d\n", context->pt[n].fds_count, context->fd_limit_per_thread - 1); if ((unsigned int)context->pt[n].fds_count != context->fd_limit_per_thread - 1 && @@ -54,19 +54,22 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi, const char *de n = lws_get_idlest_tsi(vhost->context); if (n < 0) { - lwsl_err("no space for new conn\n"); + lwsl_vhost_err(vhost, "no space for new conn"); return NULL; } lws_context_lock(vhost->context, __func__); - new_wsi = __lws_wsi_create_with_role(vhost->context, n, NULL); + new_wsi = __lws_wsi_create_with_role(vhost->context, n, NULL, + vhost->lc.log_cx); lws_context_unlock(vhost->context); if (new_wsi == NULL) { - lwsl_err("Out of memory for new connection\n"); + lwsl_vhost_err(vhost, "OOM"); return NULL; } - __lws_lc_tag(&vhost->context->lcg[ + lws_wsi_fault_timedclose(new_wsi); + + __lws_lc_tag(vhost->context, &vhost->context->lcg[ #if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) strcmp(desc, "adopted") ? LWSLCG_WSI_MUX : #endif @@ -74,8 +77,8 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi, const char *de new_wsi->wsistate |= LWSIFR_SERVER; new_wsi->tsi = (char)n; - lwsl_debug("%s joining vhost %s, tsi %d\n", new_wsi->lc.gutag, - vhost->name, new_wsi->tsi); + lwsl_wsi_debug(new_wsi, "joining vh %s, tsi %d", + vhost->name, new_wsi->tsi); lws_vhost_bind_wsi(vhost, new_wsi); new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; @@ -119,7 +122,7 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, const char *vh_prot_name, struct lws *parent, void *opaque, const char *fi_wsi_name) { - struct lws_context *context = vh->context; + struct lws_context *context; struct lws_context_per_thread *pt; struct lws *new_wsi; int n; @@ -130,6 +133,11 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, * we initialize it, it may become "live" concurrently unexpectedly... */ + if (!vh) + return NULL; + + context = vh->context; + lws_context_assert_lock_held(vh->context); n = -1; @@ -163,12 +171,12 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, new_wsi->a.protocol = lws_vhost_name_to_protocol(new_wsi->a.vhost, vh_prot_name); if (!new_wsi->a.protocol) { - lwsl_err("Protocol %s not enabled on vhost %s\n", - vh_prot_name, new_wsi->a.vhost->name); + lwsl_vhost_err(new_wsi->a.vhost, "Protocol %s not enabled", + vh_prot_name); goto bail; } if (lws_ensure_user_space(new_wsi)) { - lwsl_notice("OOM trying to get user_space\n"); + lwsl_wsi_notice(new_wsi, "OOM"); goto bail; } } @@ -178,13 +186,14 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, type &= (unsigned int)~LWS_ADOPT_ALLOW_SSL; if (lws_role_call_adoption_bind(new_wsi, (int)type, vh_prot_name)) { - lwsl_err("%s: no role for desc type 0x%x\n", __func__, type); + lwsl_wsi_err(new_wsi, "no role for desc type 0x%x", type); goto bail; } #if defined(LWS_WITH_SERVER) - if (new_wsi->role_ops) + if (new_wsi->role_ops) { lws_metrics_tag_wsi_add(new_wsi, "role", new_wsi->role_ops->name); + } #endif lws_pt_unlock(pt); @@ -202,7 +211,7 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, return new_wsi; bail: - lwsl_notice("%s: exiting on bail\n", __func__); + lwsl_wsi_notice(new_wsi, "exiting on bail"); if (parent) parent->child_list = new_wsi->sibling_list; if (new_wsi->user_space) @@ -269,7 +278,7 @@ lws_adopt_ss_server_accept(struct lws *new_wsi) 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__); + lwsl_wsi_err(new_wsi, "accept ss creation failed"); goto fail1; } @@ -285,8 +294,9 @@ lws_adopt_ss_server_accept(struct lws *new_wsi) /* indicate wsi should invalidate any ss link to it on close */ new_wsi->for_ss = 1; - // lwsl_notice("%s: opaq %p, role %s\n", __func__, - // new_wsi->a.opaque_user_data, new_wsi->role_ops->name); + // lwsl_wsi_notice(new_wsi, "%s: opaq %p, role %s", + // new_wsi->a.opaque_user_data, + // new_wsi->role_ops->name); h->policy = new_wsi->a.vhost->ss_handle->policy; @@ -301,8 +311,7 @@ lws_adopt_ss_server_accept(struct lws *new_wsi) !!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_RELIABILITY)) | (LCCSCF_IP_LOW_COST * !!(h->policy->flags & LWSSSPOLF_ATTR_LOW_COST)))) - lwsl_warn("%s: %s: unable to set ip options\n", - __func__, new_wsi->lc.gutag); + lwsl_wsi_warn(new_wsi, "unable to set ip options"); /* * add us to the list of clients that came in from the server @@ -352,16 +361,15 @@ lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, if (type & LWS_ADOPT_SOCKET) { if (lws_plat_set_nonblocking(fd.sockfd)) { - lwsl_err("%s: unable to set sockfd %d nonblocking\n", - __func__, fd.sockfd); + lwsl_wsi_err(new_wsi, "unable to set sockfd %d nonblocking", + fd.sockfd); goto fail; } } #if !defined(WIN32) else if (lws_plat_set_nonblocking(fd.filefd)) { - lwsl_err("%s: unable to set filefd nonblocking\n", - __func__); + lwsl_wsi_err(new_wsi, "unable to set filefd nonblocking"); goto fail; } #endif @@ -400,7 +408,7 @@ lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, lws_pt_lock(pt, __func__); if (__insert_wsi_socket_into_fds(new_wsi->a.context, new_wsi)) { lws_pt_unlock(pt); - lwsl_err("%s: fail inserting socket\n", __func__); + lwsl_wsi_err(new_wsi, "fail inserting socket"); goto fail; } lws_pt_unlock(pt); @@ -408,7 +416,7 @@ lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, #if defined(LWS_WITH_SERVER) else if (lws_server_socket_service_ssl(new_wsi, fd.sockfd, 0)) { - lwsl_info("%s: fail ssl negotiation\n", __func__); + lwsl_wsi_info(new_wsi, "fail ssl negotiation"); goto fail; } @@ -441,8 +449,7 @@ lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, * (here) and h2 (at __lws_wsi_server_new()) */ - lwsl_info("%s: %s, vhost %s\n", __func__, new_wsi->lc.gutag, - new_wsi->a.vhost->lc.gutag); + lwsl_wsi_info(new_wsi, "vhost %s", new_wsi->a.vhost->lc.gutag); if (lws_adopt_ss_server_accept(new_wsi)) goto fail; @@ -840,12 +847,16 @@ lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, lws_snprintf(buf, sizeof(buf), "%u", port); n = getaddrinfo(ads, buf, &h, &r); if (n) { + +#if (_LWS_ENABLED_LOGS & LLL_INFO) #if !defined(LWS_PLAT_FREERTOS) lwsl_info("%s: getaddrinfo error: %s\n", __func__, gai_strerror(n)); #else + lwsl_info("%s: getaddrinfo error: %s\n", __func__, strerror(n)); +#endif #endif //freeaddrinfo(r); goto bail1; diff --git a/3rdparty/libwebsockets/lib/core-net/client/client.c b/3rdparty/libwebsockets/lib/core-net/client/client.c index ef7df9d3..e3bc6d59 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/client.c +++ b/3rdparty/libwebsockets/lib/core-net/client/client.c @@ -53,7 +53,7 @@ lws_set_proxy(struct lws_vhost *vhost, const char *proxy) sizeof vhost->proxy_basic_auth_token) < 0) goto auth_too_long; - lwsl_info(" Proxy auth in use\n"); + lwsl_vhost_info(vhost, " Proxy auth in use"); #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) proxy = p + 1; @@ -88,7 +88,7 @@ lws_set_proxy(struct lws_vhost *vhost, const char *proxy) p = strchr(vhost->http.http_proxy_address, ']'); if (!p) { - lwsl_err("%s: malformed proxy '%s'\n", __func__, proxy); + lwsl_vhost_err(vhost, "malformed proxy '%s'", proxy); return -1; } @@ -98,7 +98,7 @@ lws_set_proxy(struct lws_vhost *vhost, const char *proxy) p = strchr(p, ':'); if (!p && !vhost->http.http_proxy_port) { - lwsl_err("http_proxy needs to be ads:port\n"); + lwsl_vhost_err(vhost, "http_proxy needs to be ads:port"); return -1; } @@ -107,14 +107,14 @@ lws_set_proxy(struct lws_vhost *vhost, const char *proxy) vhost->http.http_proxy_port = (unsigned int)atoi(p + 1); } - lwsl_info(" Proxy %s:%u\n", vhost->http.http_proxy_address, - vhost->http.http_proxy_port); + lwsl_vhost_info(vhost, " Proxy %s:%u", vhost->http.http_proxy_address, + vhost->http.http_proxy_port); #endif return 0; auth_too_long: - lwsl_err("proxy auth too long\n"); + lwsl_vhost_err(vhost, "proxy auth too long"); return -1; } diff --git a/3rdparty/libwebsockets/lib/core-net/client/conmon.c b/3rdparty/libwebsockets/lib/core-net/client/conmon.c index 6e252134..21f67c96 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/conmon.c +++ b/3rdparty/libwebsockets/lib/core-net/client/conmon.c @@ -91,23 +91,25 @@ lws_conmon_append_copy_new_dns_results(struct lws *wsi, * No we don't already have a copy of this one, let's * allocate and append it then */ - size_t al = sizeof(struct addrinfo) + cai->ai_addrlen; + size_t al = sizeof(struct addrinfo) + + (size_t)cai->ai_addrlen; size_t cl = cai->ai_canonname ? strlen(cai->ai_canonname) + 1 : 0; - ai = lws_malloc(al + cl, __func__); + ai = lws_malloc(al + cl + 1, __func__); if (!ai) { - lwsl_warn("%s: OOM\n", __func__); + lwsl_wsi_warn(wsi, "OOM"); return 1; } *ai = *cai; ai->ai_addr = (struct sockaddr *)&ai[1]; - memcpy(ai->ai_addr, cai->ai_addr, cai->ai_addrlen); + memcpy(ai->ai_addr, cai->ai_addr, (size_t)cai->ai_addrlen); if (cl) { ai->ai_canonname = ((char *)ai->ai_addr) + cai->ai_addrlen; - memcpy(ai->ai_canonname, cai->ai_canonname, cl + 1); + memcpy(ai->ai_canonname, cai->ai_canonname, + cl + 1); } ai->ai_next = wsi->conmon.dns_results_copy; wsi->conmon.dns_results_copy = ai; diff --git a/3rdparty/libwebsockets/lib/core-net/client/connect.c b/3rdparty/libwebsockets/lib/core-net/client/connect.c index 4c632b50..23c4c367 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/connect.c +++ b/3rdparty/libwebsockets/lib/core-net/client/connect.c @@ -41,7 +41,7 @@ lws_http_client_connect_via_info2(struct lws *wsi) struct client_info_stash *stash = wsi->stash; int n; - lwsl_debug("%s: %s (stash %p)\n", __func__, lws_lc_tag(&wsi->lc), stash); + lwsl_wsi_debug(wsi, "stash %p", stash); if (!stash) return wsi; @@ -60,7 +60,7 @@ lws_http_client_connect_via_info2(struct lws *wsi) for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames); n++) if (hnames[n] && stash->cis[n] && lws_hdr_simple_create(wsi, hnames[n], stash->cis[n])) - goto bail1; + goto bail; #if defined(LWS_WITH_SOCKS5) if (!wsi->a.vhost->socks_proxy_port) @@ -70,15 +70,60 @@ lws_http_client_connect_via_info2(struct lws *wsi) no_ah: return lws_client_connect_2_dnsreq(wsi); -bail1: +bail: #if defined(LWS_WITH_SOCKS5) if (!wsi->a.vhost->socks_proxy_port) lws_free_set_NULL(wsi->stash); #endif + lws_free_set_NULL(wsi->stash); + return NULL; } +int +lws_client_stash_create(struct lws *wsi, const char **cisin) +{ + size_t size; + char *pc; + int n; + + size = sizeof(*wsi->stash) + 1; + + /* + * Let's overallocate the stash object with space for all the args + * in one hit. + */ + for (n = 0; n < CIS_COUNT; n++) + if (cisin[n]) + size += strlen(cisin[n]) + 1; + + if (wsi->stash) + lws_free_set_NULL(wsi->stash); + + wsi->stash = lws_malloc(size, "client stash"); + if (!wsi->stash) + return 1; + + /* all the pointers default to NULL, but no need to zero the args */ + memset(wsi->stash, 0, sizeof(*wsi->stash)); + + pc = (char *)&wsi->stash[1]; + + for (n = 0; n < CIS_COUNT; n++) + if (cisin[n]) { + size_t mm; + wsi->stash->cis[n] = pc; + if (n == CIS_PATH && cisin[n][0] != '/') + *pc++ = '/'; + mm = strlen(cisin[n]) + 1; + memcpy(pc, cisin[n], mm); + pc += mm; + } + + return 0; +} + struct lws * lws_client_connect_via_info(const struct lws_client_connect_info *i) { @@ -86,14 +131,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) struct lws *wsi, *safe = NULL; const struct lws_protocols *p; const char *cisin[CIS_COUNT]; - struct lws_vhost *vh, *v; - int -#if LWS_MAX_SMP > 1 - tid = 0, -#endif - n, tsi = 0; - size_t size; - char *pc; + struct lws_vhost *vh; + int tsi; if (i->context->requested_stop_internal_loops) return NULL; @@ -114,41 +153,35 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) * PHASE 1: if SMP, find out the tsi related to current service thread */ -#if LWS_MAX_SMP > 1 - - for (n = 0; n < i->context->count_threads; n++) - if (i->context->pt[n].service_tid == tid) { - lwsl_info("%s: client binds to caller tsi %d\n", - __func__, n); - tsi = n; - - break; - } - - /* - * this binding is sort of provisional, since when we try to insert - * into the pt fds, there may be no space and it will fail - */ - -#endif + tsi = lws_pthread_self_to_tsi(i->context); + assert(tsi >= 0); /* PHASE 2: create a bare wsi */ - wsi = __lws_wsi_create_with_role(i->context, tsi, NULL); + wsi = __lws_wsi_create_with_role(i->context, tsi, NULL, i->log_cx); lws_context_unlock(i->context); if (wsi == NULL) - goto bail; + return NULL; vh = i->vhost; if (!vh) { - vh = i->context->vhost_list; - - if (!vh) { /* coverity */ - lwsl_err("%s: no vhost\n", __func__); - goto bail; +#if defined(LWS_WITH_TLS_JIT_TRUST) + if (lws_tls_jit_trust_vhost_bind(i->context, i->address, &vh)) +#endif + { + vh = lws_get_vhost_by_name(i->context, "default"); + if (!vh) { + + vh = i->context->vhost_list; + + if (!vh) { /* coverity */ + lwsl_cx_err(i->context, "no vhost"); + goto bail; + } + if (!strcmp(vh->name, "system")) + vh = vh->vhost_next; + } } - if (!strcmp(vh->name, "system")) - vh = vh->vhost_next; } #if defined(LWS_WITH_SECURE_STREAMS) @@ -188,6 +221,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) #endif #endif + lws_wsi_fault_timedclose(wsi); + /* * Until we exit, we can report connection failure directly to the * caller without needing to call through to protocol CONNECTION_ERROR. @@ -212,36 +247,19 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (i->ssl_connection & LCCSCF_WAKE_SUSPEND__VALIDITY) wsi->conn_validity_wakesuspend = 1; - if (!i->vhost) { - v = i->context->vhost_list; - - if (!v) { /* coverity */ - lwsl_err("%s: no vhost\n", __func__); - goto bail; - } - if (!strcmp(v->name, "system")) - v = v->vhost_next; - } else - v = i->vhost; - - lws_vhost_bind_wsi(v, wsi); + lws_vhost_bind_wsi(vh, wsi); #if defined(LWS_WITH_SYS_FAULT_INJECTION) /* additionally inerit from vhost we bound to */ - lws_fi_inherit_copy(&wsi->fic, &v->fic, "wsi", i->fi_wsi_name); + lws_fi_inherit_copy(&wsi->fic, &vh->fic, "wsi", i->fi_wsi_name); #endif if (!wsi->a.vhost) { - lwsl_err("%s: No vhost in the context\n", __func__); + lwsl_wsi_err(wsi, "No vhost in the context"); goto bail; } -#if LWS_MAX_SMP > 1 - tid = wsi->a.vhost->protocols[0].callback(wsi, - LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); -#endif - /* * PHASE 3: Choose an initial role for the wsi and do role-specific init * @@ -250,11 +268,11 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) */ if (lws_role_call_client_bind(wsi, i) < 0) { - lwsl_err("%s: unable to bind to role\n", __func__); + lwsl_wsi_err(wsi, "unable to bind to role"); goto bail; } - lwsl_info("%s: role binding to %s\n", __func__, wsi->role_ops->name); + lwsl_wsi_info(wsi, "role binding to %s", wsi->role_ops->name); /* * PHASE 4: fill up the wsi with stuff from the connect_info as far as @@ -290,16 +308,16 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) } if (local) { - lwsl_info("%s: vh %s protocol binding to %s\n", __func__, + lwsl_wsi_info(wsi, "vh %s protocol binding to %s\n", 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_info("%s: unknown protocol %s\n", __func__, local); + lwsl_wsi_info(wsi, "unknown protocol %s", local); - lwsl_info("%s: %s: %s %s entry\n", - __func__, lws_wsi_tag(wsi), wsi->role_ops->name, + lwsl_wsi_info(wsi, "%s: %s %s entry", + lws_wsi_tag(wsi), wsi->role_ops->name, wsi->a.protocol ? wsi->a.protocol->name : "none"); } @@ -317,7 +335,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) wsi->tls.use_ssl = (unsigned int)i->ssl_connection; #else if (i->ssl_connection & LCCSCF_USE_SSL) { - lwsl_err("%s: lws not configured for tls\n", __func__); + lwsl_wsi_err(wsi, "lws not configured for tls"); goto bail; } #endif @@ -342,23 +360,13 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) cisin[CIS_IFACE] = i->iface; cisin[CIS_ALPN] = i->alpn; - size = sizeof(*wsi->stash); - - /* - * Let's overallocate the stash object with space for all the args - * in one hit. - */ - for (n = 0; n < CIS_COUNT; n++) - if (cisin[n]) - size += strlen(cisin[n]) + 1; + if (lws_client_stash_create(wsi, cisin)) + goto bail; - wsi->stash = lws_malloc(size, "client stash"); - if (!wsi->stash) { - lwsl_err("%s: OOM\n", __func__); - goto bail1; - } - /* all the pointers default to NULL, but no need to zero the args */ - memset(wsi->stash, 0, sizeof(*wsi->stash)); +#if defined(LWS_WITH_TLS) + if (i->alpn) + lws_strncpy(wsi->alpn, i->alpn, sizeof(wsi->alpn)); +#endif wsi->a.opaque_user_data = wsi->stash->opaque_user_data = i->opaque_user_data; @@ -371,7 +379,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) * LCCSCF_SECSTREAM_PROXY_LINK : client SSPC link to proxy * LCCSCF_SECSTREAM_PROXY_ONWARD: proxy's onward connection */ - __lws_lc_tag(&i->context->lcg[ + __lws_lc_tag(i->context, &i->context->lcg[ #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) i->ssl_connection & LCCSCF_SECSTREAM_PROXY_LINK ? LWSLCG_WSI_SSP_CLIENT : #if defined(LWS_WITH_SERVER) @@ -394,23 +402,12 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) lws_ss_tag(((lws_ss_handle_t *)i->opaque_user_data))); } else #endif - __lws_lc_tag(&i->context->lcg[LWSLCG_WSI_CLIENT], &wsi->lc, - "%s/%s/%s", i->method ? i->method : "WS", - wsi->role_ops->name, i->address); + __lws_lc_tag(i->context, &i->context->lcg[LWSLCG_WSI_CLIENT], &wsi->lc, + "%s/%s/%s/%s", i->method ? i->method : "WS", + wsi->role_ops->name ? wsi->role_ops->name : "novh", vh->name, i->address); lws_metrics_tag_wsi_add(wsi, "vh", wsi->a.vhost->name); - pc = (char *)&wsi->stash[1]; - - for (n = 0; n < CIS_COUNT; n++) - if (cisin[n]) { - size_t mm; - wsi->stash->cis[n] = pc; - mm = strlen(cisin[n]) + 1; - memcpy(pc, cisin[n], mm); - pc += mm; - } - /* * at this point user callbacks like * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER will be interested to @@ -419,8 +416,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) */ if (i->parent_wsi) { - lwsl_info("%s: created child %p of parent %p\n", __func__, - wsi, i->parent_wsi); + lwsl_wsi_info(wsi, "created as child %s", + lws_wsi_tag(i->parent_wsi)); wsi->parent = i->parent_wsi; safe = wsi->sibling_list = i->parent_wsi->child_list; i->parent_wsi->child_list = wsi; @@ -436,11 +433,9 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) int n = lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_client_bind). client_bind(wsi, NULL); - if (n && i->parent_wsi) { + if (n && i->parent_wsi) /* unpick from parent */ - i->parent_wsi->child_list = safe; - } if (n < 0) /* we didn't survive, wsi is freed */ @@ -456,6 +451,10 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (i->pwsi) *i->pwsi = wsi; + if (!wsi->a.protocol) + /* we must have one protocol or another bound by this point */ + goto bail; + /* PHASE 8: notify protocol with role-specific connected callback */ /* raw socket per se doesn't want this... raw socket proxy wants it... */ @@ -463,8 +462,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (wsi->role_ops != &role_ops_raw_skt || (i->local_protocol_name && !strcmp(i->local_protocol_name, "raw-proxy"))) { - lwsl_debug("%s: %s: adoption cb %d to %s %s\n", __func__, - lws_wsi_tag(wsi), wsi->role_ops->adoption_cb[0], + lwsl_wsi_debug(wsi, "adoption cb %d to %s %s", + wsi->role_ops->adoption_cb[0], wsi->role_ops->name, wsi->a.protocol->name); wsi->a.protocol->callback(wsi, wsi->role_ops->adoption_cb[0], @@ -528,7 +527,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) #if defined(LWS_WITH_TLS) bail3: - lwsl_info("%s: tls start fail\n", __func__); + lwsl_wsi_info(wsi, "tls start fail"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "tls start fail"); if (i->pwsi) @@ -537,21 +536,19 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) return NULL; #endif -bail1: - lws_free_set_NULL(wsi->stash); - bail: +#if defined(LWS_WITH_TLS) + if (wsi->tls.ssl) + lws_tls_restrict_return(wsi); +#endif + + lws_free_set_NULL(wsi->stash); lws_fi_destroy(&wsi->fic); lws_free(wsi); #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 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 --git a/3rdparty/libwebsockets/lib/core-net/client/connect2.c b/3rdparty/libwebsockets/lib/core-net/client/connect2.c index 7aa308a2..0ccb3cb5 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/connect2.c +++ b/3rdparty/libwebsockets/lib/core-net/client/connect2.c @@ -93,20 +93,24 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result) || n == EAI_AGAIN #endif ) { -#if defined(LWS_WITH_SECURE_STREAMS) - -#endif wsi->dns_reachability = 1; lws_metrics_caliper_report(cal, METRES_NOGO); #if defined(LWS_WITH_SYS_METRICS) lws_snprintf(buckname, sizeof(buckname), "dns=\"unreachable %d\"", n); lws_metrics_hist_bump_priv_wsi(wsi, mth_conn_failures, buckname); #endif - lwsl_debug("%s: asking to recheck CPD in 1s\n", __func__); + +#if defined(LWS_WITH_CONMON) + wsi->conmon.dns_disposition = LWSCONMON_DNS_SERVER_UNREACHABLE; +#endif + +#if 0 + lwsl_wsi_debug(wsi, "asking to recheck CPD in 1s"); lws_system_cpd_start_defer(wsi->a.context, LWS_US_PER_SEC); +#endif } - lwsl_info("%s: getaddrinfo '%s' says %d\n", __func__, ads, n); + lwsl_wsi_info(wsi, "getaddrinfo '%s' says %d", ads, n); #if defined(LWS_WITH_SYS_METRICS) if (n < 0) { @@ -114,6 +118,10 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result) lws_metrics_hist_bump_priv_wsi(wsi, mth_conn_failures, buckname); } #endif +#if defined(LWS_WITH_CONMON) + wsi->conmon.dns_disposition = n < 0 ? LWSCONMON_DNS_NO_RESULT : + LWSCONMON_DNS_OK; +#endif lws_metrics_caliper_report(cal, n >= 0 ? METRES_GO : METRES_NOGO); @@ -121,11 +129,15 @@ lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result) } #endif +#if !defined(LWS_WITH_SYS_ASYNC_DNS) && defined(EAI_NONAME) +static const char * const dns_nxdomain = "DNS NXDOMAIN"; +#endif + struct lws * lws_client_connect_2_dnsreq(struct lws *wsi) { struct addrinfo *result = NULL; - const char *meth = NULL, *ads; + const char *meth = NULL; #if defined(LWS_WITH_IPV6) struct sockaddr_in addr; const char *iface; @@ -136,11 +148,25 @@ lws_client_connect_2_dnsreq(struct lws *wsi) if (lwsi_state(wsi) == LRS_WAITING_DNS || lwsi_state(wsi) == LRS_WAITING_CONNECT) { - lwsl_info("%s: LRS_WAITING_DNS / CONNECT\n", __func__); + lwsl_wsi_info(wsi, "LRS_WAITING_DNS / CONNECT"); return wsi; } + /* + * clients who will create their own fresh connection keep a copy of + * the hostname they originally connected to, in case other connections + * want to use it too + */ + + if (!wsi->cli_hostname_copy) { + const char *pa = lws_wsi_client_stash_item(wsi, CIS_HOST, + _WSI_TOKEN_CLIENT_PEER_ADDRESS); + + if (pa) + wsi->cli_hostname_copy = lws_strdup(pa); + } + /* * The first job is figure out if we want to pipeline on or just join * an existing "active connection" to the same place @@ -148,11 +174,15 @@ lws_client_connect_2_dnsreq(struct lws *wsi) meth = lws_wsi_client_stash_item(wsi, CIS_METHOD, _WSI_TOKEN_CLIENT_METHOD); + /* consult active connections to find out disposition */ + + adsin = lws_wsi_client_stash_item(wsi, CIS_ADDRESS, + _WSI_TOKEN_CLIENT_PEER_ADDRESS); /* we only pipeline connections that said it was okay */ if (!wsi->client_pipeline) { - lwsl_debug("%s: new conn on no pipeline flag\n", __func__); + lwsl_wsi_debug(wsi, "new conn on no pipeline flag"); goto solo; } @@ -164,11 +194,6 @@ lws_client_connect_2_dnsreq(struct lws *wsi) strcmp(meth, "UDP") && strcmp(meth, "MQTT")) goto solo; - /* consult active connections to find out disposition */ - - adsin = lws_wsi_client_stash_item(wsi, CIS_ADDRESS, - _WSI_TOKEN_CLIENT_PEER_ADDRESS); - if (!adsin) /* * This cannot happen since user code must provide the client @@ -180,7 +205,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) case ACTIVE_CONNS_SOLO: break; case ACTIVE_CONNS_MUXED: - lwsl_notice("%s: ACTIVE_CONNS_MUXED\n", __func__); + lwsl_wsi_notice(wsi, "ACTIVE_CONNS_MUXED"); if (lwsi_role_h2(wsi)) { if (wsi->a.protocol->callback(wsi, @@ -195,8 +220,9 @@ lws_client_connect_2_dnsreq(struct lws *wsi) return wsi; case ACTIVE_CONNS_QUEUED: - lwsl_debug("%s: ACTIVE_CONNS_QUEUED st 0x%x: \n", __func__, - lwsi_state(wsi)); + lwsl_wsi_debug(wsi, "ACTIVE_CONNS_QUEUED st 0x%x: ", + lwsi_state(wsi)); + if (lwsi_state(wsi) == LRS_UNCONNECTED) { if (lwsi_role_h2(w)) lwsi_set_state(wsi, @@ -210,26 +236,6 @@ lws_client_connect_2_dnsreq(struct lws *wsi) solo: - /* - * clients who will create their own fresh connection keep a copy of - * the hostname they originally connected to, in case other connections - * want to use it too - */ - - if (!wsi->cli_hostname_copy) { - if (wsi->stash && wsi->stash->cis[CIS_HOST]) - wsi->cli_hostname_copy = - lws_strdup(wsi->stash->cis[CIS_HOST]); -#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) - else { - char *pa = lws_hdr_simple_ptr(wsi, - _WSI_TOKEN_CLIENT_PEER_ADDRESS); - if (pa) - wsi->cli_hostname_copy = lws_strdup(pa); - } -#endif - } - /* * If we made our own connection, and we're doing a method that can * take a pipeline, we are an "active client connection". @@ -245,7 +251,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) lws_dll2_is_detached(&wsi->dll_cli_active_conns)) { lws_context_lock(wsi->a.context, __func__); lws_vhost_lock(wsi->a.vhost); - lwsl_info("%s: adding active conn %s\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "adding as active conn"); /* caution... we will have to unpick this on oom4 path */ lws_dll2_add_head(&wsi->dll_cli_active_conns, &wsi->a.vhost->dll_cli_active_conns_owner); @@ -253,24 +259,19 @@ lws_client_connect_2_dnsreq(struct lws *wsi) lws_context_unlock(wsi->a.context); } - /* - * unix socket destination? - */ - - if (wsi->stash) - ads = wsi->stash->cis[CIS_ADDRESS]; - else - ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS); - /* * Since address must be given at client creation, should not be * possible, but necessary to satisfy coverity */ - if (!ads) + if (!adsin) return NULL; #if defined(LWS_WITH_UNIX_SOCK) - if (*ads == '+') { + /* + * unix socket destination? + */ + + if (*adsin == '+') { wsi->unix_skt = 1; n = 0; goto next_step; @@ -289,7 +290,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) if (wsi->ipv6 && iface && inet_pton(AF_INET, iface, &addr.sin_addr) == 1) { - lwsl_notice("%s: client connection forced to IPv4\n", __func__); + lwsl_wsi_notice(wsi, "client connection forced to IPv4"); wsi->ipv6 = 0; } #endif @@ -302,7 +303,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) * Priority 1: connect to http proxy */ if (wsi->a.vhost->http.http_proxy_port) { - ads = wsi->a.vhost->http.http_proxy_address; + adsin = wsi->a.vhost->http.http_proxy_address; port = (int)wsi->a.vhost->http.http_proxy_port; #else if (0) { @@ -313,8 +314,8 @@ lws_client_connect_2_dnsreq(struct lws *wsi) /* Priority 2: Connect to SOCK5 Proxy */ } else if (wsi->a.vhost->socks_proxy_port) { - lwsl_client("Sending SOCKS Greeting\n"); - ads = wsi->a.vhost->socks_proxy_address; + lwsl_wsi_client(wsi, "Sending SOCKS Greeting"); + adsin = wsi->a.vhost->socks_proxy_address; port = (int)wsi->a.vhost->socks_proxy_port; #endif } else { @@ -331,7 +332,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) */ lwsi_set_state(wsi, LRS_WAITING_DNS); - lwsl_info("%s: %s: lookup %s:%u\n", __func__, wsi->lc.gutag, ads, port); + lwsl_wsi_info(wsi, "lookup %s:%u", adsin, port); wsi->conn_port = (uint16_t)port; #if !defined(LWS_WITH_SYS_ASYNC_DNS) @@ -340,7 +341,21 @@ lws_client_connect_2_dnsreq(struct lws *wsi) /* * blocking dns resolution */ - n = lws_getaddrinfo46(wsi, ads, &result); + n = lws_getaddrinfo46(wsi, adsin, &result); +#if defined(EAI_NONAME) + if (n == EAI_NONAME) { + /* + * The DNS server responded with NXDOMAIN... even + * though this is still in the client creation call, + * we need to make a CCE, otherwise there won't be + * any user indication of what went wrong + */ + wsi->client_suppress_CONNECTION_ERROR = 0; + lws_inform_client_conn_fail(wsi, (void *)dns_nxdomain, + strlen(dns_nxdomain)); + goto failed1; + } +#endif } #else /* this is either FAILED, CONTINUING, or already called connect_4 */ @@ -348,7 +363,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) if (lws_fi(&wsi->fic, "dnsfail")) return lws_client_connect_3_connect(wsi, NULL, NULL, -4, NULL); else - n = lws_async_dns_query(wsi->a.context, wsi->tsi, ads, + n = lws_async_dns_query(wsi->a.context, wsi->tsi, adsin, LWS_ADNS_RECORD_A, lws_client_connect_3_connect, wsi, NULL); @@ -364,7 +379,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) #if defined(LWS_WITH_UNIX_SOCK) next_step: #endif - return lws_client_connect_3_connect(wsi, ads, result, n, NULL); + return lws_client_connect_3_connect(wsi, adsin, result, n, NULL); //#if defined(LWS_WITH_SYS_ASYNC_DNS) failed1: diff --git a/3rdparty/libwebsockets/lib/core-net/client/connect3.c b/3rdparty/libwebsockets/lib/core-net/client/connect3.c index 1a7f9f97..b7523303 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/connect3.c +++ b/3rdparty/libwebsockets/lib/core-net/client/connect3.c @@ -35,7 +35,7 @@ lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul) * connection before giving up on it and retrying. */ - lwsl_info("%s: connect wait timeout has fired\n", __func__); + lwsl_wsi_info(wsi, "connect wait timeout has fired"); lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL); } @@ -51,9 +51,9 @@ lws_client_dns_retry_timeout(lws_sorted_usec_list_t *sul) * isn't officially used until we connected somewhere. */ - lwsl_info("%s: dns retry\n", __func__); + lwsl_wsi_info(wsi, "dns retry"); if (!lws_client_connect_2_dnsreq(wsi)) - lwsl_notice("%s: DNS lookup failed\n", __func__); + lwsl_wsi_notice(wsi, "DNS lookup failed"); } /* @@ -71,11 +71,13 @@ typedef enum { } lcccr_t; static lcccr_t -lws_client_connect_check(struct lws *wsi) +lws_client_connect_check(struct lws *wsi, int *real_errno) { - int e = 0; int en = 0; +#if !defined(WIN32) + int e; socklen_t sl = sizeof(e); +#endif (void)en; @@ -84,26 +86,26 @@ lws_client_connect_check(struct lws *wsi) * condition, the connect definitively failed. */ - if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR, -#if defined(WIN32) - (char *) -#endif - &e, &sl)) { +#if !defined(WIN32) + if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR, &e, &sl)) { en = LWS_ERRNO; if (!e) { - lwsl_debug("%s: getsockopt check: conn OK errno %d\n", - __func__, en); + lwsl_wsi_debug(wsi, "getsockopt: conn OK errno %d", en); return LCCCR_CONNECTED; } - lwsl_notice("%s: getsockopt fd %d says err %d\n", __func__, - wsi->desc.sockfd, e); + lwsl_wsi_notice(wsi, "getsockopt fd %d says e %d", + wsi->desc.sockfd, e); + + *real_errno = e; + + return LCCCR_FAILED; } -#if defined(WIN32) +#else - if (!connect(wsi->desc.sockfd, NULL, 0)) + if (!connect(wsi->desc.sockfd, (const struct sockaddr *)&wsi->sa46_peer.sa4, 0)) return LCCCR_CONNECTED; en = LWS_ERRNO; @@ -114,18 +116,19 @@ lws_client_connect_check(struct lws *wsi) if (en == WSAEALREADY) { /* reset the POLLOUT wait */ if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) - lwsl_notice("pollfd failed\n"); + lwsl_wsi_notice(wsi, "pollfd failed"); } if (!en || en == WSAEINVAL || en == WSAEWOULDBLOCK || en == WSAEALREADY) { - lwsl_debug("%s: errno %d\n", __func__, en); + lwsl_wsi_debug(wsi, "errno %d", en); return LCCCR_CONTINUE; } #endif - lwsl_notice("%s: connect check take as FAILED: errno %d\n", __func__, en); + lwsl_wsi_notice(wsi, "connect check FAILED: %d", + *real_errno || en); return LCCCR_FAILED; } @@ -145,16 +148,17 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, struct sockaddr_un sau; #endif struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + const char *cce = "Unable to connect", *iface; const struct sockaddr *psa = NULL; uint16_t port = wsi->conn_port; - const char *cce, *iface; lws_dns_sort_t *curr; ssize_t plen = 0; lws_dll2_t *d; + char dcce[48]; #if defined(LWS_WITH_SYS_FAULT_INJECTION) int cfail; #endif - int m; + int m, af = 0; /* * If we come here with result set, we need to convert getaddrinfo @@ -182,6 +186,10 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, result = NULL; } +#if defined(LWS_WITH_UNIX_SOCK) + memset(&sau, 0, sizeof(sau)); +#endif + /* * async dns calls back here for everybody who cares when it gets a * result... but if we are piggybacking, we do not want to connect @@ -195,7 +203,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, !wsi->dns_sorted_list.count && /* there's no results */ !lws_socket_is_valid(wsi->desc.sockfd) && /* no attempt ongoing */ !wsi->speculative_connect_owner.count /* no spec attempt */ ) { - lwsl_notice("%s: dns lookup failed %d\n", __func__, n); + lwsl_wsi_notice(wsi, "dns lookup failed %d", n); /* * DNS lookup itself failed... let's try again until we @@ -226,7 +234,15 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, /* no dns results and no ongoing timeout for one */ goto connect_to; - switch (lws_client_connect_check(wsi)) { + /* + * If the connection failed, the OS-level errno may be + * something like EINPROGRESS rather than the actual problem + * that prevented a connection. This value will represent the + * “real†problem that we should report to the caller. + */ + int real_errno = 0; + + switch (lws_client_connect_check(wsi, &real_errno)) { case LCCCR_CONNECTED: /* * Oh, it has happened... @@ -235,23 +251,28 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, case LCCCR_CONTINUE: return NULL; default: - lwsl_debug("%s: getsockopt check: conn fail: errno %d\n", - __func__, LWS_ERRNO); + if (!real_errno) + real_errno = LWS_ERRNO; + lws_snprintf(dcce, sizeof(dcce), "conn fail: %d", + real_errno); + + cce = dcce; + lwsl_wsi_debug(wsi, "%s", dcce); lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); goto try_next_dns_result_fds; } } #if defined(LWS_WITH_UNIX_SOCK) + if (ads && *ads == '+') { ads++; memset(&wsi->sa46_peer, 0, sizeof(wsi->sa46_peer)); - memset(&sau, 0, sizeof(sau)); - sau.sun_family = AF_UNIX; + af = sau.sun_family = AF_UNIX; strncpy(sau.sun_path, ads, sizeof(sau.sun_path)); sau.sun_path[sizeof(sau.sun_path) - 1] = '\0'; - lwsl_info("%s: Unix skt: %s\n", __func__, ads); + lwsl_wsi_info(wsi, "Unix skt: %s", ads); if (sau.sun_path[0] == '@') sau.sun_path[0] = '\0'; @@ -262,7 +283,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, #if defined(LWS_WITH_SYS_ASYNC_DNS) if (n == LADNS_RET_FAILED) { - lwsl_notice("%s: adns failed %s\n", __func__, ads); + lwsl_wsi_notice(wsi, "adns failed %s", ads); /* * Caller that is giving us LADNS_RET_FAILED will deal * with cleanup @@ -280,6 +301,8 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, next_dns_result: + cce = "Unable to connect"; + if (!wsi->dns_sorted_list.count) goto failed1; @@ -295,7 +318,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, wsi->sa46_peer = curr->dest; #if defined(LWS_WITH_NETLINK) wsi->peer_route_uidx = curr->uidx; - lwsl_info("%s: peer_route_uidx %d\n", __func__, wsi->peer_route_uidx); + lwsl_wsi_info(wsi, "peer_route_uidx %d", wsi->peer_route_uidx); #endif lws_free(curr); @@ -324,15 +347,25 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, } #if defined(LWS_WITH_UNIX_SOCK) - if (wsi->unix_skt) + af = 0; + if (wsi->unix_skt) { + af = AF_UNIX; wsi->desc.sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + } else #endif + { + af = wsi->sa46_peer.sa4.sin_family; wsi->desc.sockfd = socket(wsi->sa46_peer.sa4.sin_family, SOCK_STREAM, 0); + } if (!lws_socket_is_valid(wsi->desc.sockfd)) { - lwsl_warn("Unable to open socket\n"); + lws_snprintf(dcce, sizeof(dcce), + "conn fail: skt creation: errno %d", + LWS_ERRNO); + cce = dcce; + lwsl_wsi_warn(wsi, "%s", dcce); goto try_next_dns_result; } @@ -342,25 +375,36 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, #else 0)) { #endif - lwsl_err("Failed to set wsi socket options\n"); + lws_snprintf(dcce, sizeof(dcce), + "conn fail: skt options: errno %d", + LWS_ERRNO); + cce = dcce; + lwsl_wsi_warn(wsi, "%s", dcce); goto try_next_dns_result_closesock; } /* apply requested socket options */ if (lws_plat_set_socket_options_ip(wsi->desc.sockfd, wsi->c_pri, wsi->flags)) - lwsl_warn("%s: %s: unable to set ip options\n", - __func__, wsi->lc.gutag); + lwsl_wsi_warn(wsi, "unable to set ip options"); - lwsl_debug("%s: %s: WAITING_CONNECT\n", __func__, wsi->lc.gutag); + lwsl_wsi_debug(wsi, "WAITING_CONNECT"); lwsi_set_state(wsi, LRS_WAITING_CONNECT); if (wsi->a.context->event_loop_ops->sock_accept) - if (wsi->a.context->event_loop_ops->sock_accept(wsi)) + if (wsi->a.context->event_loop_ops->sock_accept(wsi)) { + lws_snprintf(dcce, sizeof(dcce), + "conn fail: sock accept"); + cce = dcce; + lwsl_wsi_warn(wsi, "%s", dcce); goto try_next_dns_result_closesock; + } lws_pt_lock(pt, __func__); if (__insert_wsi_socket_into_fds(wsi->a.context, wsi)) { + lws_snprintf(dcce, sizeof(dcce), + "conn fail: insert fd"); + cce = dcce; lws_pt_unlock(pt); goto try_next_dns_result_closesock; } @@ -377,8 +421,12 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, * and anything else we have done. */ - if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lws_snprintf(dcce, sizeof(dcce), + "conn fail: change pollfd"); + cce = dcce; goto try_next_dns_result_fds; + } if (!wsi->a.protocol) wsi->a.protocol = &wsi->a.vhost->protocols[0]; @@ -391,9 +439,13 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, if (iface && *iface) { m = lws_socket_bind(wsi->a.vhost, wsi, wsi->desc.sockfd, - 0, iface, wsi->ipv6); - if (m < 0) + 0, iface, af); + if (m < 0) { + lws_snprintf(dcce, sizeof(dcce), + "conn fail: socket bind"); + cce = dcce; goto try_next_dns_result_fds; + } } } @@ -430,8 +482,9 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, */ #if defined(LWS_WITH_SYS_METRICS) - if (wsi->cal_conn.mt) + if (wsi->cal_conn.mt) { lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); + } lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mt_conn_tcp); #endif @@ -441,7 +494,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_CONNECTING, wsi->user_space, (void *)(intptr_t)wsi->desc.sockfd, 0)) { - lwsl_info("%s: CONNECTION CB closed\n", __func__); + lwsl_wsi_info(wsi, "CONNECTION CB closed"); goto failed1; } @@ -452,7 +505,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, else #endif m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, - (unsigned int)n); + (socklen_t)n); #if defined(LWS_WITH_CONMON) wsi->conmon_datum = lws_now_usecs(); @@ -475,7 +528,8 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, errno_copy = 999; #endif - lwsl_debug("%s: connect: errno: %d\n", __func__, errno_copy); + lwsl_wsi_debug(wsi, "connect: fd %d errno: %d", + wsi->desc.sockfd, errno_copy); if (errno_copy && errno_copy != LWS_EALREADY && @@ -507,10 +561,19 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, lws_sa46_write_numeric_address(&wsi->sa46_peer, nads, sizeof(nads)); + lws_snprintf(dcce, sizeof(dcce), + "conn fail: errno %d: %s:%d", + errno_copy, nads, port); + cce = dcce; + wsi->sa46_peer.sa4.sin_family = 0; - lwsl_info("%s: Connect failed: %s port %d (errno %d)\n", - __func__, nads, port, errno_copy); + lwsl_wsi_info(wsi, "%s", cce); #if defined(LWS_WITH_UNIX_SOCK) + } else { + lws_snprintf(dcce, sizeof(dcce), + "conn fail: errno %d: UDS %s", + errno_copy, ads); + cce = dcce; } #endif #endif @@ -576,7 +639,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, #endif lws_sa46_write_numeric_address(&wsi->sa46_local, buf, sizeof(buf)); - lwsl_info("%s: %s: source ads %s\n", __func__, wsi->lc.gutag, buf); + lwsl_wsi_info(wsi, "source ads %s", buf); #endif } #endif @@ -590,7 +653,8 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE, wsi->user_space, NULL, 0); - lwsl_debug("%s: going into connect_4\n", __func__); + lwsl_wsi_debug(wsi, "going into connect_4"); + return lws_client_connect_4_established(wsi, NULL, plen); oom4: @@ -635,7 +699,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, /* * It looks like the sul_connect_timeout fired */ - lwsl_info("%s: abandoning connect due to timeout\n", __func__); + lwsl_wsi_info(wsi, "abandoning connect due to timeout"); try_next_dns_result_fds: lws_pt_lock(pt, __func__); @@ -655,7 +719,6 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, goto next_dns_result; lws_addrinfo_clean(wsi); - cce = "Unable to connect"; lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); failed1: diff --git a/3rdparty/libwebsockets/lib/core-net/client/connect4.c b/3rdparty/libwebsockets/lib/core-net/client/connect4.c index 89611202..c34d2253 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/connect4.c +++ b/3rdparty/libwebsockets/lib/core-net/client/connect4.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2020 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -62,7 +62,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, if (!cpa) goto failed; - lwsl_info("%s: going via proxy\n", __func__); + lwsl_wsi_info(wsi, "going via proxy"); plen = lws_snprintf((char *)pt->serv_buf, 256, "CONNECT %s:%u HTTP/1.1\x0d\x0a" @@ -95,10 +95,11 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, goto failed; wsi->c_port = (uint16_t)wsi->a.vhost->http.http_proxy_port; - n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, (unsigned int)plen, + n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, + (unsigned int)plen, MSG_NOSIGNAL); if (n < 0) { - lwsl_debug("ERROR writing to proxy socket\n"); + lwsl_wsi_debug(wsi, "ERROR writing to proxy socket"); cce = "proxy write failed"; goto failed; } @@ -157,18 +158,22 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, */ lws_callback_on_writable(wsi_piggyback); - lwsl_info("%s: %s: waiting to send hdrs (par state 0x%x)\n", - __func__, wsi->lc.gutag, lwsi_state(wsi_piggyback)); + lwsl_wsi_info(wsi, "waiting to send hdrs (par state 0x%x)", + lwsi_state(wsi_piggyback)); } else { - lwsl_info("%s: %s: %s %s client created own conn " - "(raw %d) vh %sm st 0x%x\n", - __func__, wsi->lc.gutag, wsi->role_ops->name, - wsi->a.protocol->name, rawish, wsi->a.vhost->name, - lwsi_state(wsi)); + lwsl_wsi_info(wsi, "%s %s client created own conn " + "(raw %d) vh %s st 0x%x", + wsi->role_ops->name, wsi->a.protocol->name, rawish, + wsi->a.vhost->name, lwsi_state(wsi)); /* we are making our own connection */ - if (!rawish) { + if (!rawish +#if defined(LWS_WITH_TLS) + // && (!(wsi->tls.use_ssl & LCCSCF_USE_SSL) || wsi->tls.ssl) +#endif + ) { + if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2) lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); } else { @@ -183,20 +188,22 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { int result; + //lwsi_set_state(wsi, LRS_WAITING_SSL); + /* * 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: + lwsl_wsi_debug(wsi, "create_tls RETRY"); return wsi; default: + lwsl_wsi_debug(wsi, "create_tls FAIL"); goto failed; } @@ -207,9 +214,9 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, * LRS_H2_WAITING_TO_SEND_HEADERS already. */ - lwsl_notice("%s: %s: " - "tls established st 0x%x\n", - __func__, wsi->lc.gutag, lwsi_state(wsi)); + lwsl_wsi_notice(wsi, "tls established st 0x%x, " + "client_h2_alpn %d", lwsi_state(wsi), + wsi->client_h2_alpn); if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS) @@ -217,7 +224,13 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, LRS_H1C_ISSUE_HANDSHAKE2); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, - (int)wsi->a.context->timeout_secs); + (int)wsi->a.context->timeout_secs); +#if 0 + /* ensure pollin enabled */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) + lwsl_wsi_notice(wsi, + "unable to set POLLIN"); +#endif goto provoke_service; } @@ -230,9 +243,10 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, if (m) { n = user_callback_handle_rxflow( wsi->a.protocol->callback, wsi, - (enum lws_callback_reasons)m, wsi->user_space, NULL, 0); + (enum lws_callback_reasons)m, + wsi->user_space, NULL, 0); if (n < 0) { - lwsl_info("RAW_PROXY_CLI_ADOPT err\n"); + lwsl_wsi_info(wsi, "RAW_PROXY_CLI_ADOPT err"); goto failed; } } @@ -240,15 +254,14 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, /* service.c pollout processing wants this */ wsi->hdr_parsing_completed = 1; #if defined(LWS_ROLE_MQTT) - if (!strcmp(meth, "MQTT")) { + if (meth && !strcmp(meth, "MQTT")) { #if defined(LWS_WITH_TLS) if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { lwsi_set_state(wsi, LRS_WAITING_SSL); return wsi; } #endif - lwsl_info("%s: settings LRS_MQTTC_IDLE\n", - __func__); + lwsl_wsi_info(wsi, "settings LRS_MQTTC_IDLE"); lwsi_set_state(wsi, LRS_MQTTC_IDLE); /* @@ -265,8 +278,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, pfd.events = LWS_POLLIN; pfd.revents = LWS_POLLOUT; - lwsl_info("%s: going to service fd\n", - __func__); + lwsl_wsi_info(wsi, "going to service fd"); n = lws_service_fd(wsi->a.context, &pfd); if (n < 0) { cce = "first service failed"; @@ -278,7 +290,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, return wsi; } #endif - lwsl_info("%s: setting ESTABLISHED\n", __func__); + lwsl_wsi_info(wsi, "setting ESTABLISHED"); lwsi_set_state(wsi, LRS_ESTABLISHED); return wsi; @@ -320,7 +332,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, failed: lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); - lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2"); + lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect4"); return NULL; } diff --git a/3rdparty/libwebsockets/lib/core-net/client/sort-dns.c b/3rdparty/libwebsockets/lib/core-net/client/sort-dns.c index e802909a..db105c52 100644 --- a/3rdparty/libwebsockets/lib/core-net/client/sort-dns.c +++ b/3rdparty/libwebsockets/lib/core-net/client/sort-dns.c @@ -406,7 +406,7 @@ lws_sort_dns_dcomp(const lws_dns_sort_t *da, const lws_dns_sort_t *db) */ scopea = lws_ipv6_unicast_scope(to_v6_sa(&da->dest)); - scopeb = lws_ipv6_unicast_scope(to_v6_sa(&db)); + scopeb = lws_ipv6_unicast_scope(to_v6_sa(&db->dest)); scope_srca = lws_ipv6_unicast_scope(to_v6_sa(&da->source)); scope_srcb = lws_ipv6_unicast_scope(to_v6_sa(&db->source)); @@ -564,7 +564,7 @@ lws_sort_dns_dump(struct lws *wsi) (void)n; /* nologs */ if (!lws_dll2_get_head(&wsi->dns_sorted_list)) - lwsl_notice("%s: empty\n", __func__); + lwsl_wsi_notice(wsi, "empty"); lws_start_foreach_dll(struct lws_dll2 *, d, lws_dll2_get_head(&wsi->dns_sorted_list)) { @@ -574,9 +574,9 @@ lws_sort_dns_dump(struct lws *wsi) lws_sa46_write_numeric_address(&s->dest, dest, sizeof(dest)); lws_sa46_write_numeric_address(&s->gateway, gw, sizeof(gw)); - lwsl_info("%s: %d: (%d)%s, gw (%d)%s, idi: %d, " - "lbl: %d, prec: %d\n", - __func__, n++, s->dest.sa4.sin_family, dest, + lwsl_wsi_info(wsi, "%d: (%d)%s, gw (%d)%s, idi: %d, " + "lbl: %d, prec: %d", n++, + s->dest.sa4.sin_family, dest, s->gateway.sa4.sin_family, gw, s->if_idx, s->score.label, s->score.precedence); @@ -593,7 +593,7 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result) #endif const struct addrinfo *ai = result; - lwsl_info("%s: sort_dns: %p\n", __func__, result); + lwsl_wsi_info(wsi, "sort_dns: %p", result); /* * We're going to take the dns results and produce our own linked-list @@ -623,24 +623,20 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result) * Only transfer address families we can cope with */ if ((int)ai->ai_addrlen > (int)sizeof(lws_sockaddr46) || - (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)) { - lwsl_info("%s: skip %d %d %d\n", __func__, - ai->ai_family, (int)ai->ai_addrlen, - (int)sizeof(lws_sockaddr46)); + (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)) goto next; - } ds = lws_zalloc(sizeof(*ds), __func__); if (!ds) return 1; - memcpy(&ds->dest, ai->ai_addr, ai->ai_addrlen); + memcpy(&ds->dest, ai->ai_addr, (size_t)ai->ai_addrlen); ds->dest.sa4.sin_family = (sa_family_t)ai->ai_family; lws_sa46_write_numeric_address(&ds->dest, afip, sizeof(afip)); - lwsl_info("%s: unsorted entry (af %d) %s\n", __func__, - ds->dest.sa4.sin_family, afip); + lwsl_wsi_info(wsi, "unsorted entry (af %d) %s", + ds->dest.sa4.sin_family, afip); #if defined(LWS_WITH_NETLINK) @@ -655,8 +651,8 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result) estr = _lws_route_est_outgoing(pt, &ds->dest); if (!estr) { lws_free(ds); - lwsl_notice("%s: %s has no route out\n", - __func__, afip); + lwsl_wsi_notice(wsi, "%s has no route out\n", + afip); /* * There's no outbound route for this, it's * unusable, so don't add it to the list @@ -701,7 +697,7 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result) * promote v4 -> v6 address using ::ffff:xx:yy */ - lwsl_info("%s: promoting v4->v6\n", __func__); + lwsl_wsi_info(wsi, "promoting v4->v6"); lws_sa46_4to6(&ds->dest, (uint8_t *)&ds->dest.sa4.sin_addr, 0); diff --git a/3rdparty/libwebsockets/lib/core-net/close.c b/3rdparty/libwebsockets/lib/core-net/close.c index fce5bb2d..a8dd7209 100644 --- a/3rdparty/libwebsockets/lib/core-net/close.c +++ b/3rdparty/libwebsockets/lib/core-net/close.c @@ -123,6 +123,8 @@ __lws_reset_wsi(struct lws *wsi) #if defined(LWS_WITH_CLIENT) lws_dll2_remove(&wsi->dll2_cli_txn_queue); lws_dll2_remove(&wsi->dll_cli_active_conns); + if (wsi->cli_hostname_copy) + lws_free_set_NULL(wsi->cli_hostname_copy); #endif #if defined(LWS_WITH_SYS_ASYNC_DNS) @@ -134,8 +136,10 @@ __lws_reset_wsi(struct lws *wsi) lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body); #endif - if (wsi->a.vhost && wsi->a.vhost->lserv_wsi == wsi) - wsi->a.vhost->lserv_wsi = NULL; +#if defined(LWS_WITH_SERVER) + lws_dll2_remove(&wsi->listen_list); +#endif + #if defined(LWS_WITH_CLIENT) if (wsi->a.vhost) lws_dll2_remove(&wsi->dll_cli_active_conns); @@ -143,7 +147,7 @@ __lws_reset_wsi(struct lws *wsi) __lws_same_vh_protocol_remove(wsi); #if defined(LWS_WITH_CLIENT) - lws_free_set_NULL(wsi->stash); + //lws_free_set_NULL(wsi->stash); lws_free_set_NULL(wsi->cli_hostname_copy); #endif @@ -166,6 +170,34 @@ __lws_reset_wsi(struct lws *wsi) #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) __lws_header_table_detach(wsi, 0); #endif + +#if defined(LWS_ROLE_H2) + /* + * Let's try to clean out the h2-ness of the wsi + */ + + memset(&wsi->h2, 0, sizeof(wsi->h2)); + + wsi->hdr_parsing_completed = wsi->mux_substream = + wsi->upgraded_to_http2 = wsi->mux_stream_immortal = + wsi->h2_acked_settings = wsi->seen_nonpseudoheader = + wsi->socket_is_permanently_unusable = wsi->favoured_pollin = + wsi->already_did_cce = wsi->told_user_closed = + wsi->waiting_to_send_close_frame = wsi->close_needs_ack = + wsi->parent_pending_cb_on_writable = wsi->seen_zero_length_recv = + wsi->close_when_buffered_out_drained = wsi->could_have_pending = 0; +#endif + +#if defined(LWS_WITH_CLIENT) + wsi->do_ws = wsi->chunked = wsi->client_rx_avail = + wsi->client_http_body_pending = wsi->transaction_from_pipeline_queue = + wsi->keepalive_active = wsi->keepalive_rejected = + wsi->redirected_to_get = wsi->client_pipeline = wsi->client_h2_alpn = + wsi->client_mux_substream = wsi->client_mux_migrated = + wsi->tls_session_reused = wsi->perf_done = 0; + + wsi->immortal_substream_count = 0; +#endif } /* req cx lock */ @@ -182,37 +214,56 @@ __lws_free_wsi(struct lws *wsi) #if defined(LWS_WITH_SECURE_STREAMS) if (wsi->for_ss) { - /* - * Make certain it is disconnected from the ss by now - */ - 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; +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + if (wsi->client_bound_sspc) { + lws_sspc_handle_t *h = (lws_sspc_handle_t *) + wsi->a.opaque_user_data; + if (h) { + h->cwsi = NULL; + wsi->a.opaque_user_data = NULL; + } + } else +#endif + { + /* + * Make certain it is disconnected from the ss by now + */ + 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 + vh = wsi->a.vhost; + __lws_reset_wsi(wsi); __lws_wsi_remove_from_sul(wsi); - vh = wsi->a.vhost; + if (vh) + /* this may destroy vh */ + __lws_vhost_unbind_wsi(wsi); /* req cx + vh lock */ + +#if defined(LWS_WITH_CLIENT) + if (wsi->stash) + lws_free_set_NULL(wsi->stash); +#endif if (wsi->a.context->event_loop_ops->destroy_wsi) wsi->a.context->event_loop_ops->destroy_wsi(wsi); - if (vh) - __lws_vhost_unbind_wsi(wsi); /* req cx + vh lock */ - - lwsl_debug("%s: %s, tsi fds count %d\n", __func__, - lws_wsi_tag(wsi), + lwsl_wsi_debug(wsi, "tsi fds count %d\n", 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_sul_debug_zombies(wsi->a.context, wsi, sizeof(*wsi), __func__); - __lws_lc_untag(&wsi->lc); + __lws_lc_untag(wsi->a.context, &wsi->lc); lws_free(wsi); } @@ -230,8 +281,8 @@ lws_remove_child_from_any_parent(struct lws *wsi) pwsi = &wsi->parent->child_list; while (*pwsi) { if (*pwsi == wsi) { - lwsl_info("%s: detach %s from parent %s\n", __func__, - lws_wsi_tag(wsi), lws_wsi_tag(wsi->parent)); + lwsl_wsi_info(wsi, "detach from parent %s", + lws_wsi_tag(wsi->parent)); if (wsi->parent->a.protocol) wsi->parent->a.protocol->callback(wsi, @@ -245,7 +296,7 @@ lws_remove_child_from_any_parent(struct lws *wsi) pwsi = &(*pwsi)->sibling_list; } if (!seen) - lwsl_err("%s: failed to detach from parent\n", __func__); + lwsl_wsi_err(wsi, "failed to detach from parent"); wsi->parent = NULL; } @@ -289,7 +340,7 @@ lws_addrinfo_clean(struct lws *wsi) #endif } -/* requires cx lock */ +/* requires cx and pt lock */ void __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, @@ -301,20 +352,22 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, struct lws *wsi1, *wsi2; int n, ccb; - lwsl_info("%s: %s: caller: %s\n", __func__, lws_wsi_tag(wsi), caller); - if (!wsi) return; + lwsl_wsi_info(wsi, "caller: %s", caller); + lws_access_log(wsi); - if (!lws_dll2_is_detached(&wsi->dll_buflist)) { - lwsl_info("%s: %s: going down with stuff in buflist\n", - __func__, lws_wsi_tag(wsi)); } + if (!lws_dll2_is_detached(&wsi->dll_buflist)) + lwsl_wsi_info(wsi, "going down with stuff in buflist"); context = wsi->a.context; pt = &context->pt[(int)wsi->tsi]; + if (pt->pipe_wsi == wsi) + pt->pipe_wsi = NULL; + #if defined(LWS_WITH_SYS_METRICS) && \ (defined(LWS_WITH_CLIENT) || defined(LWS_WITH_SERVER)) /* wsi level: only reports if dangling caliper */ @@ -339,6 +392,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, #if defined(LWS_WITH_CLIENT) lws_free_set_NULL(wsi->cli_hostname_copy); + wsi->client_mux_substream_was = wsi->client_mux_substream; lws_addrinfo_clean(wsi); #endif @@ -407,7 +461,8 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, #endif #if defined(LWS_WITH_CLIENT) - lws_free_set_NULL(wsi->stash); + if (!wsi->close_is_redirect) + lws_free_set_NULL(wsi->stash); #endif if (wsi->role_ops == &role_ops_raw_skt) { @@ -448,7 +503,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, lws_callback_on_writable(wsi); return; } - lwsl_info("%s: %s: end LRS_FLUSHING_BEFORE_CLOSE\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, " end LRS_FLUSHING_BEFORE_CLOSE"); goto just_kill_connection; default: if (lws_has_buffered_out(wsi) @@ -457,7 +512,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, wsi->http.comp_ctx.may_have_more #endif ) { - lwsl_info("%s: %s: LRS_FLUSHING_BEFORE_CLOSE\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "LRS_FLUSHING_BEFORE_CLOSE"); lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE); __lws_set_timeout(wsi, PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE, 5); @@ -495,15 +550,19 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_close_via_role_protocol) && lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_close_via_role_protocol). close_via_role_protocol(wsi, reason)) { - lwsl_info("%s: clsoe_via_role took over: %s (sockfd %d)\n", __func__, - lws_wsi_tag(wsi), wsi->desc.sockfd); + lwsl_wsi_info(wsi, "close_via_role took over (sockfd %d)", + wsi->desc.sockfd); return; } just_kill_connection: - lwsl_debug("%s: real just_kill_connection A: %s (sockfd %d)\n", __func__, - lws_wsi_tag(wsi), wsi->desc.sockfd); + lwsl_wsi_debug(wsi, "real just_kill_connection A: (sockfd %d)", + wsi->desc.sockfd); + +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) + lws_threadpool_wsi_closing(wsi); +#endif #if defined(LWS_WITH_FILE_OPS) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)) if (lwsi_role_http(wsi) && lwsi_role_server(wsi) && @@ -561,11 +620,12 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, #endif lwsi_state(wsi) == LRS_WAITING_DNS || lwsi_state(wsi) == LRS_WAITING_CONNECT) && - !wsi->already_did_cce && wsi->a.protocol) { + !wsi->already_did_cce && wsi->a.protocol && + !wsi->close_is_redirect) { static const char _reason[] = "closed before established"; - lwsl_debug("%s: closing in unestablished state 0x%x\n", - __func__, lwsi_state(wsi)); + lwsl_wsi_debug(wsi, "closing in unestablished state 0x%x", + lwsi_state(wsi)); wsi->socket_is_permanently_unusable = 1; lws_inform_client_conn_fail(wsi, @@ -610,7 +670,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, } } if (n) - lwsl_debug("closing: shutdown (state 0x%x) ret %d\n", + lwsl_wsi_debug(wsi, "closing: shutdown (state 0x%x) ret %d", lwsi_state(wsi), LWS_ERRNO); /* @@ -620,6 +680,9 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, #if !defined(_WIN32_WCE) && !defined(LWS_PLAT_FREERTOS) /* libuv: no event available to guarantee completion */ if (!wsi->socket_is_permanently_unusable && +#if defined(LWS_WITH_CLIENT) + !wsi->close_is_redirect && +#endif lws_socket_is_valid(wsi->desc.sockfd) && lwsi_state(wsi) != LRS_SHUTDOWN && (context->event_loop_ops->flags & LELOF_ISPOLL)) { @@ -633,8 +696,8 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, #endif } - lwsl_info("%s: real just_kill_connection: %s (sockfd %d)\n", __func__, - lws_wsi_tag(wsi), wsi->desc.sockfd); + lwsl_wsi_info(wsi, "real just_kill_connection: sockfd %d\n", + wsi->desc.sockfd); #ifdef LWS_WITH_HUBBUB if (wsi->http.rw) { @@ -692,11 +755,11 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, /* * He's a guy who go started with dns, but failed or is * caught with a shutdown before he got the result. We have - * to issue him a close cb + * to issclient_mux_substream_wasue him a close cb */ ccb = 1; - lwsl_info("%s: %s: cce=%d\n", __func__, lws_wsi_tag(wsi), ccb); + lwsl_wsi_info(wsi, "cce=%d", ccb); pro = wsi->a.protocol; @@ -708,12 +771,17 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, ccb = 0; #if defined(LWS_WITH_CLIENT) - if (!ccb && (lwsi_state_PRE_CLOSE(wsi) & LWSIFS_NOT_EST) && + if (!wsi->close_is_redirect && !ccb && + (lwsi_state_PRE_CLOSE(wsi) & LWSIFS_NOT_EST) && lwsi_role_client(wsi)) { lws_inform_client_conn_fail(wsi, "Closed before conn", 18); } #endif - if (ccb) { + if (ccb +#if defined(LWS_WITH_CLIENT) + && !wsi->close_is_redirect +#endif + ) { if (!wsi->a.protocol && wsi->a.vhost && wsi->a.vhost->protocols) pro = &wsi->a.vhost->protocols[0]; @@ -729,9 +797,9 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, async_close: #endif -#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER) +#if defined(LWS_WITH_SECURE_STREAMS) if (wsi->for_ss) { - lwsl_debug("%s: for_ss\n", __func__); + lwsl_wsi_debug(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 @@ -812,11 +880,10 @@ __lws_close_free_wsi_final(struct lws *wsi) if (!wsi->shadow && lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) { - lwsl_debug("%s: wsi %s: fd %d\n", __func__, lws_wsi_tag(wsi), - wsi->desc.sockfd); + lwsl_wsi_debug(wsi, "fd %d", wsi->desc.sockfd); n = compatible_close(wsi->desc.sockfd); if (n) - lwsl_debug("closing: close ret %d\n", LWS_ERRNO); + lwsl_wsi_debug(wsi, "closing: close ret %d", LWS_ERRNO); __remove_wsi_socket_from_fds(wsi); if (lws_socket_is_valid(wsi->desc.sockfd)) @@ -827,10 +894,93 @@ __lws_close_free_wsi_final(struct lws *wsi) #endif sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd); + } - wsi->desc.sockfd = LWS_SOCK_INVALID; + /* ... if we're closing the cancel pipe, account for it */ + + { + struct lws_context_per_thread *pt = + &wsi->a.context->pt[(int)wsi->tsi]; + + if (pt->pipe_wsi == wsi) + pt->pipe_wsi = NULL; + if (pt->dummy_pipe_fds[0] == wsi->desc.sockfd) + pt->dummy_pipe_fds[0] = LWS_SOCK_INVALID; } + wsi->desc.sockfd = LWS_SOCK_INVALID; + +#if defined(LWS_WITH_CLIENT) + lws_free_set_NULL(wsi->cli_hostname_copy); + if (wsi->close_is_redirect) { + + wsi->close_is_redirect = 0; + + lwsl_wsi_info(wsi, "picking up redirection"); + + lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, + &role_ops_h1); + +#if defined(LWS_WITH_HTTP2) + if (wsi->client_mux_substream_was) + wsi->h2.END_STREAM = wsi->h2.END_HEADERS = 0; +#endif +#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) + if (wsi->mux.parent_wsi) { + lws_wsi_mux_sibling_disconnect(wsi); + wsi->mux.parent_wsi = NULL; + } +#endif + +#if defined(LWS_WITH_TLS) + memset(&wsi->tls, 0, sizeof(wsi->tls)); +#endif + + // wsi->a.protocol = NULL; + if (wsi->a.protocol) + lws_bind_protocol(wsi, wsi->a.protocol, "client_reset"); + wsi->pending_timeout = NO_PENDING_TIMEOUT; + wsi->hdr_parsing_completed = 0; + +#if defined(LWS_WITH_TLS) + if (wsi->stash->cis[CIS_ALPN]) + lws_strncpy(wsi->alpn, wsi->stash->cis[CIS_ALPN], + sizeof(wsi->alpn)); +#endif + + if (lws_header_table_attach(wsi, 0)) { + lwsl_wsi_err(wsi, "failed to get ah"); + return; + } +// } + //_lws_header_table_reset(wsi->http.ah); + +#if defined(LWS_WITH_TLS) + wsi->tls.use_ssl = (unsigned int)wsi->flags; +#endif + +#if defined(LWS_WITH_TLS_JIT_TRUST) + if (wsi->stash && wsi->stash->cis[CIS_ADDRESS]) { + struct lws_vhost *vh = NULL; + lws_tls_jit_trust_vhost_bind(wsi->a.context, + wsi->stash->cis[CIS_ADDRESS], + &vh); + if (vh) { + if (!vh->count_bound_wsi && vh->grace_after_unref) { + lwsl_wsi_info(wsi, "%s in use\n", + vh->lc.gutag); + lws_sul_cancel(&vh->sul_unref); + } + vh->count_bound_wsi++; + wsi->a.vhost = vh; + } + } +#endif + + return; + } +#endif + /* outermost destroy notification for wsi (user_space still intact) */ if (wsi->a.vhost) wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, diff --git a/3rdparty/libwebsockets/lib/core-net/dummy-callback.c b/3rdparty/libwebsockets/lib/core-net/dummy-callback.c index c474ec4b..d36000fa 100644 --- a/3rdparty/libwebsockets/lib/core-net/dummy-callback.c +++ b/3rdparty/libwebsockets/lib/core-net/dummy-callback.c @@ -35,22 +35,22 @@ proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp, int n = lws_hdr_total_length(par, (enum lws_token_indexes)index); if (n < 1) { - lwsl_debug("%s: no index %d:\n", __func__, index); + lwsl_wsi_debug(wsi, "no index %d:", index); return 0; } if (lws_hdr_copy(par, (char *)temp, temp_len, (enum lws_token_indexes)index) < 0) { - lwsl_notice("%s: unable to copy par hdr idx %d (len %d)\n", - __func__, index, n); + lwsl_wsi_notice(wsi, "unable to copy par hdr idx %d (len %d)", + index, n); return -1; } - lwsl_debug("%s: index %d: %s\n", __func__, index, (char *)temp); + lwsl_wsi_debug(wsi, "index %d: %s", index, (char *)temp); if (lws_add_http_header_by_token(wsi, (enum lws_token_indexes)index, temp, n, p, end)) { - lwsl_notice("%s: unable to append par hdr idx %d (len %d)\n", - __func__, index, n); + lwsl_wsi_notice(wsi, "unable to append par hdr idx %d (len %d)", + index, n); return -1; } @@ -69,29 +69,28 @@ stream_close(struct lws *wsi) if (wsi->mux_substream) { if (lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0, - LWS_WRITE_HTTP_FINAL) < 0) { - lwsl_info("%s: COMPL_CLIENT_HTTP: h2 fin wr failed\n", - __func__); + LWS_WRITE_HTTP_FINAL) < 0) + goto bail; - return -1; - } - } else { - *out++ = '0'; - *out++ = '\x0d'; - *out++ = '\x0a'; - *out++ = '\x0d'; - *out++ = '\x0a'; - - if (lws_write(wsi, (unsigned char *)buf + LWS_PRE, 5, - LWS_WRITE_HTTP_FINAL) < 0) { - lwsl_err("%s: COMPL_CLIENT_HTTP: " - "h2 final write failed\n", __func__); - - return -1; - } + return 0; } + *out++ = '0'; + *out++ = '\x0d'; + *out++ = '\x0a'; + *out++ = '\x0d'; + *out++ = '\x0a'; + + if (lws_write(wsi, (unsigned char *)buf + LWS_PRE, 5, + LWS_WRITE_HTTP_FINAL) < 0) + goto bail; + return 0; + +bail: + lwsl_wsi_info(wsi, "h2 fin wr failed"); + + return -1; } #endif @@ -127,7 +126,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, #if defined(LWS_WITH_HTTP2) if (wsi->parent->mux_substream) - lwsl_info("%s: proxied h2 -> h1 ws established\n", __func__); + lwsl_wsi_info(wsi, "proxied h2 -> h1 ws established"); #endif break; @@ -136,7 +135,8 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: case LWS_CALLBACK_CLIENT_CLOSED: - lwsl_info("%s: client closed: parent %s\n", __func__, lws_wsi_tag(wsi->parent)); + lwsl_wsi_info(wsi, "client closed: parent %s", + lws_wsi_tag(wsi->parent)); if (wsi->parent) lws_set_timeout(wsi->parent, 1, LWS_TO_KILL_ASYNC); break; @@ -160,8 +160,8 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_RECEIVE: wsi->parent->ws->proxy_buffered += len; if (wsi->parent->ws->proxy_buffered > 10 * 1024 * 1024) { - lwsl_err("%s: proxied ws connection excessive buffering: dropping\n", - __func__); + lwsl_wsi_err(wsi, "proxied ws connection " + "excessive buffering: dropping"); return -1; } pkt = lws_zalloc(sizeof(*pkt) + LWS_PRE + len, __func__); @@ -204,7 +204,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, return 1; case LWS_CALLBACK_CLOSED: - lwsl_info("%s: closed\n", __func__); + lwsl_wsi_info(wsi, "closed"); return -1; case LWS_CALLBACK_RECEIVE: @@ -294,7 +294,9 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_HTTP_BODY_COMPLETION: #if defined(LWS_WITH_HTTP_PROXY) if (wsi->child_list) { - lwsl_info("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION: %d\n", __func__, (int)len); + lwsl_wsi_info(wsi, "HTTP_BODY_COMPLETION: %d", + (int)len); + lws_callback_on_writable(wsi->child_list); break; } #endif @@ -312,9 +314,11 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, #if defined(LWS_WITH_HTTP_PROXY) case LWS_CALLBACK_HTTP_BODY: if (wsi->child_list) { - 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) + lwsl_wsi_info(wsi, "HTTP_BODY: stashing %d", (int)len); + if (lws_buflist_append_segment( + &wsi->http.buflist_post_body, in, len) < 0) return -1; + lws_client_http_body_pending(wsi->child_list, 1); lws_callback_on_writable(wsi->child_list); } break; @@ -327,7 +331,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, LWS_CB_REASON_AUX_BF__CGI)) { n = lws_cgi_write_split_stdout_headers(wsi); if (n < 0) { - lwsl_debug("AUX_BF__CGI forcing close\n"); + lwsl_wsi_debug(wsi, "AUX_BF__CGI forcing close"); return -1; } if (!n && wsi->http.cgi && wsi->http.cgi->lsp && @@ -342,7 +346,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, wsi->reason_bf &= (char)~LWS_CB_REASON_AUX_BF__CGI; if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) { - lwsl_info("%s: txn over\n", __func__); + lwsl_wsi_info(wsi, "txn over"); return -1; } @@ -353,7 +357,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, (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"); + lwsl_wsi_debug(wsi, "wr chunk term and exiting"); lws_write(wsi, (unsigned char *)buf + LWS_PRE, 5, LWS_WRITE_HTTP); } else @@ -371,24 +375,25 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY_HEADERS) { - wsi->reason_bf &= (char)~LWS_CB_REASON_AUX_BF__PROXY_HEADERS; + wsi->reason_bf &= + (char)~LWS_CB_REASON_AUX_BF__PROXY_HEADERS; n = LWS_WRITE_HTTP_HEADERS; if (!wsi->http.prh_content_length) n |= LWS_WRITE_H2_STREAM_END; - lwsl_debug("%s: %s: issuing proxy headers: clen %d\n", - __func__, lws_wsi_tag(wsi), + lwsl_wsi_debug(wsi, "issuing proxy headers: clen %d", (int)wsi->http.prh_content_length); n = lws_write(wsi, wsi->http.pending_return_headers + LWS_PRE, - wsi->http.pending_return_headers_len, (enum lws_write_protocol)n); + wsi->http.pending_return_headers_len, + (enum lws_write_protocol)n); lws_free_set_NULL(wsi->http.pending_return_headers); if (n < 0) { - lwsl_err("%s: EST_CLIENT_HTTP: write failed\n", - __func__); + lwsl_wsi_err(wsi, "EST_CLIENT_HTTP: wr failed"); + return -1; } @@ -413,8 +418,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, /* this causes LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ */ if (lws_http_client_read(lws_get_child(wsi), &px, &lenx) < 0) { - lwsl_info("%s: LWS_CB_REASON_AUX_BF__PROXY: " - "client closed\n", __func__); + lwsl_wsi_info(wsi, "LWS_CB_REASON_AUX_BF__PROXY: " + "client closed"); stream_close(wsi); @@ -424,8 +429,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, } if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY_TRANS_END) { - lwsl_info("%s: LWS_CB_REASON_AUX_BF__PROXY_TRANS_END\n", - __func__); + lwsl_wsi_info(wsi, "PROXY_TRANS_END"); wsi->reason_bf &= (char)~LWS_CB_REASON_AUX_BF__PROXY_TRANS_END; @@ -455,7 +459,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, if (wsi->http.proxy_parent_chunked) { if (len > sizeof(buf) - LWS_PRE - 16) { - lwsl_err("oversize buf %d %d\n", (int)len, + lwsl_wsi_err(wsi, "oversize buf %d %d", (int)len, (int)sizeof(buf) - LWS_PRE - 16); return -1; } @@ -546,7 +550,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, if (!parent->mux_substream && !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { - lwsl_debug("downstream parent chunked\n"); + lwsl_wsi_debug(wsi, "downstream parent chunked"); if (lws_add_http_header_by_token(parent, WSI_TOKEN_HTTP_TRANSFER_ENCODING, (unsigned char *)"chunked", 7, &p, end)) @@ -576,8 +580,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, parent->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY_HEADERS; - lwsl_debug("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: " - "prepared %d headers (len %d)\n", __func__, + lwsl_wsi_debug(wsi, "ESTABLISHED_CLIENT_HTTP: " + "prepared %d headers (len %d)", lws_http_client_http_response(wsi), (int)parent->http.prh_content_length); @@ -592,9 +596,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, break; } case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - lwsl_info("%s: COMPLETED_CLIENT_HTTP: %s (parent %s)\n", - __func__, lws_wsi_tag(wsi), - lws_wsi_tag(lws_get_parent(wsi))); + lwsl_wsi_info(wsi, "COMPLETED_CLIENT_HTTP: (parent %s)", + lws_wsi_tag(lws_get_parent(wsi))); if (!lws_get_parent(wsi)) break; lws_get_parent(wsi)->reason_bf |= @@ -606,7 +609,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, if (!lws_get_parent(wsi)) break; // lwsl_err("%s: LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", __func__); - lws_set_timeout(lws_get_parent(wsi), (enum pending_timeout)LWS_TO_KILL_ASYNC, + lws_set_timeout(lws_get_parent(wsi), + (enum pending_timeout)LWS_TO_KILL_ASYNC, (int)PENDING_TIMEOUT_KILLED_BY_PROXY_CLIENT_CLOSE); break; @@ -675,28 +679,30 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, if (buf[n - 1] != '\n') buf[n++] = '\n'; buf[n] = '\0'; - lwsl_notice("CGI-stderr: %s\n", buf); + lwsl_wsi_notice(wsi, "CGI-stderr: %s", buf); } break; } break; case LWS_CALLBACK_CGI_TERMINATED: - lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: %d %" PRIu64 "\n", + if (wsi->http.cgi) { + lwsl_wsi_debug(wsi, "CGI_TERMINATED: %d %" PRIu64, wsi->http.cgi->explicitly_chunked, (uint64_t)wsi->http.cgi->content_length); - if (!(wsi->http.cgi->explicitly_chunked && wsi->mux_substream) && - !wsi->http.cgi->content_length) { - /* send terminating chunk */ - lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: ending\n"); - wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END; - lws_callback_on_writable(wsi); - lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3); - break; - } - if (wsi->mux_substream && !wsi->cgi_stdout_zero_length) - lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0, + if (!(wsi->http.cgi->explicitly_chunked && wsi->mux_substream) && + !wsi->http.cgi->content_length) { + /* send terminating chunk */ + lwsl_wsi_debug(wsi, "LWS_CALLBACK_CGI_TERMINATED: ending"); + wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END; + lws_callback_on_writable(wsi); + lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3); + break; + } + if (wsi->mux_substream && !wsi->cgi_stdout_zero_length) + lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0, LWS_WRITE_HTTP_FINAL); + } #if defined(LWS_WITH_SERVER) if (lws_http_transaction_completed(wsi)) return -1; @@ -717,15 +723,14 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, /* gzip handling */ if (!wsi->http.cgi->gzip_init) { - lwsl_info("inflating gzip\n"); + lwsl_wsi_info(wsi, "inflating gzip"); memset(&wsi->http.cgi->inflate, 0, sizeof(wsi->http.cgi->inflate)); if (inflateInit2(&wsi->http.cgi->inflate, 16 + 15) != Z_OK) { - lwsl_err("%s: iniflateInit failed\n", - __func__); + lwsl_wsi_err(wsi, "iniflateInit fail"); return -1; } @@ -752,7 +757,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, case Z_MEM_ERROR: inflateEnd(&wsi->http.cgi->inflate); wsi->http.cgi->gzip_init = 0; - lwsl_err("zlib error inflate %d\n", n); + lwsl_wsi_err(wsi, "zlib err inflate %d", n); return -1; } @@ -768,12 +773,15 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, if (written != (int)( sizeof(wsi->http.cgi->inflate_buf) - wsi->http.cgi->inflate.avail_out)) { - lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: " - "sent %d only %d went", n, args->len); + lwsl_wsi_notice(wsi, + "CGI_STDIN_DATA: " + "sent %d only %d went", + n, args->len); } if (n == Z_STREAM_END) { - lwsl_err("gzip inflate end\n"); + lwsl_wsi_err(wsi, + "gzip inflate end"); inflateEnd(&wsi->http.cgi->inflate); wsi->http.cgi->gzip_init = 0; break; @@ -794,10 +802,10 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, n = (int)write(n, args->data, (unsigned int)args->len); // lwsl_hexdump_notice(args->data, args->len); if (n < args->len) - lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: " + lwsl_wsi_notice(wsi, "CGI_STDIN_DATA: " "sent %d only %d went", n, args->len); - lwsl_info("%s: proxied %d bytes\n", __func__, n); + lwsl_wsi_info(wsi, "proxied %d bytes", n); if (wsi->http.cgi->post_in_expected && args->stdwsi[LWS_STDIN] && args->stdwsi[LWS_STDIN]->desc.filefd > 0) { @@ -814,10 +822,9 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, * if no content-length)... */ - lwsl_info("%s: expected POST in end: " - "closing stdin wsi %s, fd %d\n", - __func__, lws_wsi_tag(siwsi), - siwsi->desc.sockfd); + lwsl_wsi_info(siwsi, "expected POST in end: " + "closing stdin fd %d", + siwsi->desc.sockfd); /* * We don't want the child / parent relationship @@ -839,8 +846,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, si = in; (void)si; - lwsl_notice("LWS_CALLBACK_SSL_INFO: where: 0x%x, ret: 0x%x\n", - si->where, si->ret); + lwsl_wsi_notice(wsi, "SSL_INFO: where: 0x%x, ret: 0x%x", + si->where, si->ret); break; #if LWS_MAX_SMP > 1 diff --git a/3rdparty/libwebsockets/lib/core-net/lws-dsh.c b/3rdparty/libwebsockets/lib/core-net/lws-dsh.c index 7a6c505a..fc332ae0 100644 --- a/3rdparty/libwebsockets/lib/core-net/lws-dsh.c +++ b/3rdparty/libwebsockets/lib/core-net/lws-dsh.c @@ -120,125 +120,16 @@ search_best_free(struct lws_dll2 *d, void *user) return 0; } -static int -try_foreign(struct lws_dll2 *d, void *user) -{ - struct lws_dsh_search *s = (struct lws_dsh_search *)user; - lws_dsh_t *dsh1 = lws_container_of(d, lws_dsh_t, list); - - if (dsh1 == s->already_checked) - return 0; - - if (dsh1->being_destroyed) - return 0; - - if (dsh1->count_kinds < s->kind + 1) - return 0; - - lwsl_debug("%s: actual try_foreign: dsh %p (free list size %d)\n", - __func__, dsh1, dsh1->oha[0].owner.count); - - s->this_dsh = dsh1; - if (lws_dll2_foreach_safe(&dsh1->oha[0].owner, s, search_best_free)) - return 1; - - return 0; -} - -static int -free_foreign(struct lws_dll2 *d, void *user) -{ - lws_dsh_obj_t *obj = lws_container_of(d, lws_dsh_obj_t, list); - lws_dsh_t *dsh = (lws_dsh_t *)user; - void *p = (void *)&obj[1]; - - if (obj->dsh != dsh) - lws_dsh_free(&p); - - return 0; -} - -static int -evict2(struct lws_dll2 *d, void *user) -{ - lws_dsh_obj_t *obj = lws_container_of(d, lws_dsh_obj_t, list); - lws_dsh_t *dsh = (lws_dsh_t *)user; - void *p; - - if (obj->dsh != dsh) - return 0; - - /* - * If we are here, it means obj is a live object that is allocated on - * the dsh being destroyed, from a different dsh. We need to migrate - * the object to a dsh that isn't being destroyed. - */ - - lwsl_debug("%s: migrating object size %zu\n", __func__, obj->size); - - if (_lws_dsh_alloc_tail(dsh, 0, (void *)&obj[1], obj->size, NULL, 0, &obj->list)) { - lwsl_notice("%s: failed to migrate object\n", __func__); - /* - * only thing we can do is drop the logical object - */ - p = (uint8_t *)&obj[1]; - lws_dsh_free(&p); - } - - return 0; -} - -static int -evict1(struct lws_dll2 *d, void *user) -{ - lws_dsh_t *dsh1 = lws_container_of(d, lws_dsh_t, list); - lws_dsh_t *dsh = (lws_dsh_t *)user; - int n; - - if (dsh1->being_destroyed) - return 0; - - /* - * For every dsh that's not being destroyed, send every object to - * evict2 for checking. - */ - - lwsl_debug("%s: checking dsh %p\n", __func__, dsh1); - - for (n = 1; n < dsh1->count_kinds; n++) { - lws_dll2_describe(&dsh1->oha[n].owner, "check dsh1"); - lws_dll2_foreach_safe(&dsh1->oha[n].owner, dsh, evict2); - } - - return 0; -} - void lws_dsh_destroy(lws_dsh_t **pdsh) { lws_dsh_t *dsh = *pdsh; - int n; if (!dsh) return; - lwsl_debug("%s: destroying dsh %p\n", __func__, dsh); - dsh->being_destroyed = 1; - /* we need to explicitly free any of our allocations in foreign dsh */ - - for (n = 1; n < dsh->count_kinds; n++) - lws_dll2_foreach_safe(&dsh->oha[n].owner, dsh, free_foreign); - - /* - * We need to have anybody else with allocations in us evict them - * and make a copy in a buffer that isn't being destroyed - */ - - if (dsh->list.owner) - lws_dll2_foreach_safe(dsh->list.owner, dsh, evict1); - lws_dll2_remove(&dsh->list); /* everything else is in one heap allocation */ @@ -280,19 +171,9 @@ _lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, lws_dll2_foreach_safe(&dsh->oha[0].owner, &s, search_best_free); if (!s.best) { - /* - * Let's see if any other buffer has room - */ - s.already_checked = dsh; - - if (dsh && dsh->list.owner) - lws_dll2_foreach_safe(dsh->list.owner, &s, try_foreign); + lwsl_notice("%s: no buffer has space\n", __func__); - if (!s.best) { - lwsl_notice("%s: no buffer has space\n", __func__); - - return 1; - } + return 1; } /* anything coming out of here must be aligned */ diff --git a/3rdparty/libwebsockets/lib/core-net/network.c b/3rdparty/libwebsockets/lib/core-net/network.c index 866ff3c3..4ba98a1f 100644 --- a/3rdparty/libwebsockets/lib/core-net/network.c +++ b/3rdparty/libwebsockets/lib/core-net/network.c @@ -58,7 +58,7 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name, if (!lws_plat_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ads)->sin6_addr, rip, (socklen_t)rip_len)) { - lwsl_err("inet_ntop: %s", strerror(LWS_ERRNO)); + lwsl_vhost_err(vh, "inet_ntop: %s", strerror(LWS_ERRNO)); return -1; } @@ -67,7 +67,13 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name, memmove(rip, rip + 7, strlen(rip) - 6); getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in6), - name, (socklen_t)name_len, NULL, 0, 0); + name, +#if defined(__ANDROID__) + (size_t)name_len, +#else + (socklen_t)name_len, +#endif + NULL, 0, 0); return 0; } else @@ -81,7 +87,13 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name, #if !defined(LWS_PLAT_FREERTOS) if (getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in), - name, (unsigned int)name_len, NULL, 0, 0)) + name, +#if defined(__ANDROID__) + (size_t)name_len, +#else + (socklen_t)name_len, +#endif + NULL, 0, 0)) return -1; #endif @@ -165,7 +177,7 @@ lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name, } if (getpeername(fd, p, &len) < 0) { - lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO)); + lwsl_wsi_warn(wsi, "getpeername: %s", strerror(LWS_ERRNO)); goto bail; } @@ -194,7 +206,7 @@ lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name, int lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, lws_sockfd_type sockfd, int port, const char *iface, - int ipv6_allowed) + int af) { #ifdef LWS_WITH_UNIX_SOCK struct sockaddr_un serv_unix; @@ -206,7 +218,7 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, #ifndef LWS_PLAT_OPTEE socklen_t len = sizeof(struct sockaddr_storage); #endif - int n; + int n = 0; #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) int m; #endif @@ -219,15 +231,16 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, if (wsi) psin = (struct sockaddr_storage *)&wsi->sa46_local; + switch (af) { #if defined(LWS_WITH_UNIX_SOCK) - if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) { + case AF_UNIX: v = (struct sockaddr *)&serv_unix; memset(&serv_unix, 0, sizeof(serv_unix)); serv_unix.sun_family = AF_UNIX; if (!iface) return LWS_ITOSA_NOT_EXIST; if (sizeof(serv_unix.sun_path) <= strlen(iface)) { - lwsl_err("\"%s\" too long for UNIX domain socket\n", + lwsl_wsi_err(wsi, "\"%s\" too long for UNIX domain socket", iface); return LWS_ITOSA_NOT_EXIST; } @@ -239,35 +252,37 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, unlink(serv_unix.sun_path); // lwsl_hexdump_notice(v, n); - - } else + break; #endif #if defined(LWS_WITH_IPV6) && !defined(LWS_PLAT_FREERTOS) - if (ipv6_allowed && LWS_IPV6_ENABLED(vhost)) { + case AF_INET6: v = (struct sockaddr *)&serv_addr6; n = sizeof(struct sockaddr_in6); + memset(&serv_addr6, 0, sizeof(serv_addr6)); + serv_addr6.sin6_family = AF_INET6; if (iface) { m = interface_to_sa(vhost, iface, (struct sockaddr_in *)v, (unsigned int)n, 1); if (m == LWS_ITOSA_NOT_USABLE) { - lwsl_info("%s: netif %s: Not usable\n", - __func__, iface); + lwsl_wsi_info(wsi, "netif %s: Not usable", + iface); return m; } if (m == LWS_ITOSA_NOT_EXIST) { - lwsl_info("%s: netif %s: Does not exist\n", - __func__, iface); + lwsl_wsi_info(wsi, "netif %s: Does not exist", + iface); return m; } - serv_addr6.sin6_scope_id = (unsigned int)lws_get_addr_scope(iface); + serv_addr6.sin6_scope_id = (unsigned int)htonl((uint32_t) + lws_get_addr_scope(wsi, iface)); } - serv_addr6.sin6_family = AF_INET6; serv_addr6.sin6_port = (uint16_t)htons((uint16_t)port); - } else + break; #endif - { + + case AF_INET: v = (struct sockaddr *)&serv_addr4; n = sizeof(serv_addr4); memset(&serv_addr4, 0, sizeof(serv_addr4)); @@ -279,19 +294,22 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, m = interface_to_sa(vhost, iface, (struct sockaddr_in *)v, (unsigned int)n, 0); if (m == LWS_ITOSA_NOT_USABLE) { - lwsl_info("%s: netif %s: Not usable\n", - __func__, iface); + lwsl_wsi_info(wsi, "netif %s: Not usable", + iface); return m; } if (m == LWS_ITOSA_NOT_EXIST) { - lwsl_info("%s: netif %s: Does not exist\n", - __func__, iface); + lwsl_wsi_info(wsi, "netif %s: Does not exist", + iface); return m; } } #endif serv_addr4.sin_port = htons((uint16_t)(unsigned int)port); - } /* ipv4 */ + break; + default: + return -1; + } /* switch */ /* just checking for the interface extant */ if (sockfd == LWS_SOCK_INVALID) @@ -299,17 +317,18 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, n = bind(sockfd, v, (socklen_t)n); #ifdef LWS_WITH_UNIX_SOCK - if (n < 0 && LWS_UNIX_SOCK_ENABLED(vhost)) { - lwsl_err("ERROR on binding fd %d to \"%s\" (%d %d)\n", - sockfd, iface, n, LWS_ERRNO); + if (n < 0 && af == AF_UNIX) { + lwsl_wsi_err(wsi, "ERROR on binding fd %d to \"%s\" (%d %d)", + sockfd, iface, n, LWS_ERRNO); + return LWS_ITOSA_NOT_EXIST; } else #endif if (n < 0) { int _lws_errno = LWS_ERRNO; - lwsl_err("ERROR on binding fd %d to port %d (%d %d)\n", - sockfd, port, n, _lws_errno); + lwsl_wsi_err(wsi, "ERROR on binding fd %d to port %d (%d %d)", + sockfd, port, n, _lws_errno); /* if something already listening, tell caller to fail permanently */ @@ -322,33 +341,33 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, } #if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) - if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) { + if (af == AF_UNIX) { uid_t uid = vhost->context->uid; gid_t gid = vhost->context->gid; if (vhost->unix_socket_perms) { if (lws_plat_user_colon_group_to_ids( vhost->unix_socket_perms, &uid, &gid)) { - lwsl_err("%s: Failed to translate %s\n", - __func__, vhost->unix_socket_perms); + lwsl_wsi_err(wsi, "Failed to translate %s", + vhost->unix_socket_perms); return LWS_ITOSA_NOT_EXIST; } } if (iface && iface[0] != '@' && uid && gid) { if (chown(iface, uid, gid)) { - lwsl_err("%s: failed to set %s perms %u:%u\n", - __func__, iface, - (unsigned int)uid, (unsigned int)gid); + lwsl_wsi_err(wsi, "failed to set %s perms %u:%u", + 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, iface, - (unsigned int)uid, (unsigned int)gid); + lwsl_wsi_notice(wsi, "vh %s unix skt %s perms %u:%u", + vhost->name, iface, + (unsigned int)uid, + (unsigned int)gid); if (chmod(iface, 0660)) { - lwsl_err("%s: failed to set %s to 0600 mode\n", - __func__, iface); + lwsl_wsi_err(wsi, "0600 mode on %s fail", iface); return LWS_ITOSA_NOT_EXIST; } @@ -358,7 +377,7 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, #ifndef LWS_PLAT_OPTEE if (getsockname(sockfd, (struct sockaddr *)psin, &len) == -1) - lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO)); + lwsl_wsi_warn(wsi, "getsockname: %s", strerror(LWS_ERRNO)); else #endif #if defined(LWS_WITH_IPV6) @@ -378,8 +397,7 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, lws_sa46_write_numeric_address((lws_sockaddr46 *)psin, buf, sizeof(buf)); - lwsl_notice("%s: %s: source ads %s\n", __func__, - wsi ? wsi->lc.gutag : "nowsi", buf); + lwsl_vhost_notice(vhost, "source ads %s", buf); } return port; @@ -399,11 +417,13 @@ lws_retry_get_delay_ms(struct lws_context *context, *conceal = 0; if (retry) { - if (*ctry < retry->retry_ms_table_count) - ms = retry->retry_ms_table[*ctry]; - else - ms = retry->retry_ms_table[ - retry->retry_ms_table_count - 1]; + if (retry->retry_ms_table_count) { + if (*ctry < retry->retry_ms_table_count) + ms = retry->retry_ms_table[*ctry]; + else + ms = retry->retry_ms_table[ + retry->retry_ms_table_count - 1]; + } /* if no percent given, use the default 30% */ if (retry->jitter_percent) @@ -435,8 +455,7 @@ lws_retry_sul_schedule(struct lws_context *context, int tid, if (!conceal) return 1; - lwsl_info("%s: sul %p: scheduling retry in %dms\n", __func__, sul, - (int)ms); + lwsl_cx_info(context, "sul %p: scheduling retry in %dms", sul, (int)ms); lws_sul_schedule(context, tid, sul, cb, (int64_t)(ms * 1000)); @@ -483,7 +502,7 @@ lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul, #if defined(LWS_WITH_IPV6) unsigned long -lws_get_addr_scope(const char *ifname_or_ipaddr) +lws_get_addr_scope(struct lws *wsi, const char *ifname_or_ipaddr) { unsigned long scope; char ip[NI_MAXHOST]; @@ -524,10 +543,8 @@ lws_get_addr_scope(const char *ifname_or_ipaddr) continue; ip[0] = '\0'; - getnameinfo(addr->ifa_addr, - sizeof(struct sockaddr_in6), - ip, sizeof(ip), - NULL, 0, NI_NUMERICHOST); + getnameinfo(addr->ifa_addr, sizeof(struct sockaddr_in6), + ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); i = 0; while (ip[i]) @@ -544,27 +561,22 @@ lws_get_addr_scope(const char *ifname_or_ipaddr) freeifaddrs(addrs); #else - for (i = 0; i < 5; i++) - { + for (i = 0; i < 5; i++) { ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, NULL, addrs, &size); - if ((ret == NO_ERROR) || (ret == ERROR_NO_DATA)) { + if (ret == NO_ERROR || ret == ERROR_NO_DATA) break; - } else if (ret == ERROR_BUFFER_OVERFLOW) - { - if (addrs) - free(addrs); - addrs = (IP_ADAPTER_ADDRESSES *)malloc(size); - } else - { - if (addrs) - { - free(addrs); - addrs = NULL; - } - lwsl_err("Failed to get IPv6 address table (%d)", ret); + + if (addrs) + free(addrs); + + if (ret != ERROR_BUFFER_OVERFLOW) { + addrs = NULL; + lwsl_wsi_err(wsi, "Get IPv6 ads table fail (%d)", ret); break; } + + addrs = (IP_ADAPTER_ADDRESSES *)malloc(size); } if ((ret == NO_ERROR) && (addrs)) { diff --git a/3rdparty/libwebsockets/lib/core-net/output.c b/3rdparty/libwebsockets/lib/core-net/output.c index a8ff396a..911688e4 100644 --- a/3rdparty/libwebsockets/lib/core-net/output.c +++ b/3rdparty/libwebsockets/lib/core-net/output.c @@ -44,20 +44,6 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) * read. */ - /* - * Detect if we got called twice without going through the - * event loop to handle pending. Since that guarantees extending any - * existing buflist_out it's inefficient. - */ - if (0 && buf && wsi->could_have_pending) { - lwsl_hexdump_level(LLL_INFO, buf, len); - lwsl_info("** %s: vh: %s, prot: %s, role %s: " - "Inefficient back-to-back write of %lu detected...\n", - lws_wsi_tag(wsi), lws_vh_tag(wsi->a.vhost), - wsi->a.protocol->name, wsi->role_ops->name, - (unsigned long)len); - } - /* just ignore sends after we cleared the truncation buffer */ if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE && !lws_has_buffered_out(wsi) @@ -68,9 +54,8 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) return (int)len; if (buf && lws_has_buffered_out(wsi)) { - lwsl_info("** %s: vh: %s, prot: %s, incr buflist_out by %lu\n", - lws_wsi_tag(wsi), lws_vh_tag(wsi->a.vhost), - wsi->a.protocol->name, (unsigned long)len); + lwsl_wsi_info(wsi, "** prot: %s, incr buflist_out by %lu", + wsi->a.protocol->name, (unsigned long)len); /* * already buflist ahead of this, add it on the tail of the @@ -91,14 +76,14 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) len = lws_buflist_next_segment_len(&wsi->buflist_out, &buf); real_len = len; - lwsl_debug("%s: draining %d\n", __func__, (int)len); + lwsl_wsi_debug(wsi, "draining %d", (int)len); } if (!len || !buf) return 0; if (!wsi->mux_substream && !lws_socket_is_valid(wsi->desc.sockfd)) - lwsl_err("%s: %s invalid sock\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_err(wsi, "invalid sock"); /* limit sending */ if (wsi->a.protocol->tx_packet_size) @@ -119,7 +104,7 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) else m = (unsigned int)lws_ssl_capable_write(wsi, buf, n); - lwsl_info("%s: ssl_capable_write (%d) says %d\n", __func__, n, m); + lwsl_wsi_info(wsi, "ssl_capable_write (%d) says %d", n, m); /* something got written, it can have been truncated now */ wsi->could_have_pending = 1; @@ -149,19 +134,17 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) */ if (lws_has_buffered_out(wsi)) { if (m) { - lwsl_info("%s partial adv %d (vs %ld)\n", - lws_wsi_tag(wsi), m, (long)real_len); + lwsl_wsi_info(wsi, "partial adv %d (vs %ld)", + m, (long)real_len); lws_buflist_use_segment(&wsi->buflist_out, m); } if (!lws_has_buffered_out(wsi)) { - lwsl_info("%s: %s: buflist_out flushed\n", - __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "buflist_out flushed"); m = (unsigned int)real_len; if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) { - lwsl_info("*%s signalling to close now\n", - lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "*signalling to close now"); return -1; /* retry closing now */ } @@ -173,9 +156,8 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) #if defined(LWS_WITH_SERVER) if (wsi->http.deferred_transaction_completed) { - lwsl_notice("%s: partial completed, doing " - "deferred transaction completed\n", - __func__); + lwsl_wsi_notice(wsi, "partial completed, doing " + "deferred transaction completed"); wsi->http.deferred_transaction_completed = 0; return lws_http_transaction_completed(wsi) ? -1 : (int)real_len; @@ -209,8 +191,8 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) * buffering the unsent remainder on it. * (it will get first priority next time the socket is writable). */ - lwsl_debug("%s new partial sent %d from %lu total\n", lws_wsi_tag(wsi), - m, (unsigned long)real_len); + lwsl_wsi_debug(wsi, "new partial sent %d from %lu total", + m, (unsigned long)real_len); if (lws_buflist_append_segment(&wsi->buflist_out, buf + m, real_len - m) < 0) @@ -235,8 +217,8 @@ lws_write(struct lws *wsi, unsigned char *buf, size_t len, int m; if ((int)len < 0) { - lwsl_err("%s: suspicious len int %d, ulong %lu\n", __func__, - (int)len, (unsigned long)len); + lwsl_wsi_err(wsi, "suspicious len int %d, ulong %lu", + (int)len, (unsigned long)len); return -1; } @@ -317,8 +299,7 @@ lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, size_t len) lws_metric_event(wsi->a.vhost->mt_traffic_rx, METRES_NOGO, 0u); #endif - lwsl_info("%s: error on reading from skt : %d, errno %d\n", - __func__, n, en); + lwsl_wsi_info(wsi, "error on reading from skt : %d, errno %d", n, en); return LWS_SSL_CAPABLE_ERROR; } @@ -386,8 +367,8 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, size_t len) return LWS_SSL_CAPABLE_MORE_SERVICE; } - lwsl_debug("ERROR writing len %d to skt fd %d err %d / errno %d\n", - (int)(ssize_t)len, wsi->desc.sockfd, n, LWS_ERRNO); + lwsl_wsi_debug(wsi, "ERROR writing len %d to skt fd %d err %d / errno %d", + (int)(ssize_t)len, wsi->desc.sockfd, n, LWS_ERRNO); return LWS_SSL_CAPABLE_ERROR; } diff --git a/3rdparty/libwebsockets/lib/core-net/pollfd.c b/3rdparty/libwebsockets/lib/core-net/pollfd.c index 80f445f7..dea85aec 100644 --- a/3rdparty/libwebsockets/lib/core-net/pollfd.c +++ b/3rdparty/libwebsockets/lib/core-net/pollfd.c @@ -61,7 +61,7 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa) * to cancel service */ - lwsl_debug("%s: using leave_pollout_active\n", __func__); + lwsl_wsi_debug(wsi, "using leave_pollout_active"); return 0; } @@ -147,8 +147,8 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa) pfd = &pt->fds[wsi->position_in_fds_table]; pa->fd = wsi->desc.sockfd; - lwsl_debug("%s: %s: fd %d events %d -> %d\n", __func__, lws_wsi_tag(wsi), - pa->fd, pfd->events, (pfd->events & ~_and) | _or); + lwsl_wsi_debug(wsi, "fd %d events %d -> %d", pa->fd, pfd->events, + (pfd->events & ~_and) | _or); pa->prev_events = pfd->events; pa->events = pfd->events = (short)((pfd->events & ~_and) | _or); @@ -196,7 +196,7 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa) if (pa_events) { if (lws_plat_change_pollfd(context, wsi, pfd)) { - lwsl_info("%s failed\n", __func__); + lwsl_wsi_info(wsi, "failed"); ret = -1; goto bail; } @@ -230,14 +230,15 @@ lws_accept_modulation(struct lws_context *context, struct lws_pollargs pa1; while (vh) { - if (vh->lserv_wsi) { - if (allow) - _lws_change_pollfd(vh->lserv_wsi, - 0, LWS_POLLIN, &pa1); - else - _lws_change_pollfd(vh->lserv_wsi, - LWS_POLLIN, 0, &pa1); - } + lws_start_foreach_dll(struct lws_dll2 *, d, + lws_dll2_get_head(&vh->listen_wsi)) { + struct lws *wsi = lws_container_of(d, struct lws, + listen_list); + + _lws_change_pollfd(wsi, allow ? 0 : LWS_POLLIN, + allow ? LWS_POLLIN : 0, &pa1); + } lws_end_foreach_dll(d); + vh = vh->vhost_next; } } @@ -249,12 +250,12 @@ __dump_fds(struct lws_context_per_thread *pt, const char *s) { unsigned int n; - lwsl_warn("%s: fds_count %u, %s\n", __func__, pt->fds_count, s); + lwsl_cx_warn(pt->context, "fds_count %u, %s", pt->fds_count, s); for (n = 0; n < pt->fds_count; n++) { struct lws *wsi = wsi_from_fd(pt->context, pt->fds[n].fd); - lwsl_warn(" %d: fd %d, wsi %s, pos_in_fds: %d\n", + lwsl_cx_warn(pt->context, " %d: fd %d, wsi %s, pos_in_fds: %d", n + 1, pt->fds[n].fd, lws_wsi_tag(wsi), wsi ? wsi->position_in_fds_table : -1); } @@ -276,19 +277,19 @@ __insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi) lws_pt_assert_lock_held(pt); - lwsl_debug("%s: %s: tsi=%d, sock=%d, pos-in-fds=%d\n", - __func__, lws_wsi_tag(wsi), wsi->tsi, wsi->desc.sockfd, pt->fds_count); + lwsl_wsi_debug(wsi, "tsi=%d, sock=%d, pos-in-fds=%d", + wsi->tsi, wsi->desc.sockfd, pt->fds_count); if ((unsigned int)pt->fds_count >= context->fd_limit_per_thread) { - lwsl_err("Too many fds (%d vs %d)\n", context->max_fds, - context->fd_limit_per_thread ); + lwsl_cx_err(context, "Too many fds (%d vs %d)", context->max_fds, + context->fd_limit_per_thread); return 1; } #if !defined(_WIN32) if (!wsi->a.context->max_fds_unrelated_to_ulimit && wsi->desc.sockfd - lws_plat_socket_offset() >= (int)context->max_fds) { - lwsl_err("Socket fd %d is too high (%d) offset %d\n", + lwsl_cx_err(context, "Socket fd %d is too high (%d) offset %d", wsi->desc.sockfd, context->max_fds, lws_plat_socket_offset()); return 1; @@ -371,8 +372,9 @@ __remove_wsi_socket_from_fds(struct lws *wsi) #if !defined(_WIN32) if (!wsi->a.context->max_fds_unrelated_to_ulimit && wsi->desc.sockfd - lws_plat_socket_offset() > (int)context->max_fds) { - lwsl_err("fd %d too high (%d)\n", wsi->desc.sockfd, - context->max_fds); + lwsl_wsi_err(wsi, "fd %d too high (%d)", + wsi->desc.sockfd, + context->max_fds); return 1; } @@ -393,9 +395,8 @@ __remove_wsi_socket_from_fds(struct lws *wsi) 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, - LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE | - LWS_EV_PREPARE_DELETION); + context->event_loop_ops->io(wsi, LWS_EV_STOP | LWS_EV_READ | + LWS_EV_WRITE); /* lwsl_notice("%s: wsi=%s, skt=%d, fds pos=%d, end guy pos=%d, endfd=%d\n", __func__, lws_wsi_tag(wsi), wsi->desc.sockfd, wsi->position_in_fds_table, @@ -426,9 +427,10 @@ __remove_wsi_socket_from_fds(struct lws *wsi) * deletion guy's old one */ end_wsi = wsi_from_fd(context, v); if (!end_wsi) { - lwsl_err("no wsi for fd %d pos %d, " - "pt->fds_count=%d\n", - (int)pt->fds[m].fd, m, pt->fds_count); + lwsl_wsi_err(wsi, "no wsi for fd %d pos %d, " + "pt->fds_count=%d", + (int)pt->fds[m].fd, m, + pt->fds_count); // assert(0); } else end_wsi->position_in_fds_table = m; @@ -436,15 +438,17 @@ __remove_wsi_socket_from_fds(struct lws *wsi) /* removed wsi has no position any more */ wsi->position_in_fds_table = LWS_NO_FDS_POS; - } #if defined(LWS_WITH_EXTERNAL_POLL) - /* remove also from external POLL support via protocol 0 */ - 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; + /* remove also from external POLL support via protocol 0 */ + 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 + } #if defined(LWS_WITH_SERVER) if (!context->being_destroyed && @@ -529,21 +533,16 @@ lws_callback_on_writable(struct lws *wsi) int q = lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_callback_on_writable). callback_on_writable(wsi); - //lwsl_notice("%s: rops_cow says %d\n", __func__, q); if (q) return 1; w = lws_get_network_wsi(wsi); } else - if (w->position_in_fds_table == LWS_NO_FDS_POS) { - lwsl_debug("%s: failed to find socket %d\n", __func__, - wsi->desc.sockfd); + lwsl_wsi_debug(wsi, "failed to find socket %d", + wsi->desc.sockfd); return -1; } - // lwsl_notice("%s: marking for POLLOUT %s (%s)\n", __func__, - // lws_wsi_tag(w), lws_wsi_tag(wsi)); - if (__lws_change_pollfd(w, 0, LWS_POLLOUT)) return -1; @@ -608,9 +607,10 @@ lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost, if (protocol < vhost->protocols || protocol >= (vhost->protocols + vhost->count_protocols)) { - lwsl_err("%s: protocol %p is not from vhost %p (%p - %p)\n", - __func__, protocol, vhost->protocols, vhost, - (vhost->protocols + vhost->count_protocols)); + lwsl_vhost_err((struct lws_vhost *)vhost, + "protocol %p is not from vhost %p (%p - %p)", + protocol, vhost->protocols, vhost, + (vhost->protocols + vhost->count_protocols)); return -1; } diff --git a/3rdparty/libwebsockets/lib/core-net/private-lib-core-net.h b/3rdparty/libwebsockets/lib/core-net/private-lib-core-net.h index fc3491d0..0b3561f7 100644 --- a/3rdparty/libwebsockets/lib/core-net/private-lib-core-net.h +++ b/3rdparty/libwebsockets/lib/core-net/private-lib-core-net.h @@ -182,15 +182,6 @@ struct lws_peer { }; #endif -enum { - LWS_EV_READ = (1 << 0), - LWS_EV_WRITE = (1 << 1), - LWS_EV_START = (1 << 2), - LWS_EV_STOP = (1 << 3), - - LWS_EV_PREPARE_DELETION = (1u << 31), -}; - #ifdef LWS_WITH_IPV6 #define LWS_IPV6_ENABLED(vh) \ (!lws_check_opt(vh->context->options, LWS_SERVER_OPTION_DISABLE_IPV6) && \ @@ -247,23 +238,9 @@ struct client_info_stash { #define LWS_H2_FRAME_HEADER_LENGTH 9 - lws_usec_t __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; - lws_sorted_usec_list_t sul; - const struct lws_protocols *protocol; - struct lws_vhost *vhost; /* only used for pending processing */ - int reason; - int tsi_req; -}; - -#endif - /* * lws_async_dns */ @@ -379,9 +356,7 @@ struct lws_context_per_thread { #endif /* --- event library based members --- */ -#if defined(LWS_WITH_EVENT_LIBS) void *evlib_pt; /* overallocated */ -#endif /* --- */ @@ -484,11 +459,16 @@ struct lws_vhost { const lws_retry_bo_t *retry_policy; +#if defined(LWS_WITH_TLS_JIT_TRUST) + lws_sorted_usec_list_t sul_unref; /* grace period after idle */ +#endif + #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; + lws_dll2_owner_t listen_wsi; + const char *name; const char *iface; const char *listen_accept_role; @@ -515,9 +495,6 @@ struct lws_vhost { 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; @@ -535,6 +512,7 @@ struct lws_vhost { int keepalive_timeout; int timeout_secs_ah_idle; int connect_timeout_secs; + int fo_listen_queue; int count_bound_wsi; @@ -546,8 +524,8 @@ struct lws_vhost { uint32_t tls_session_cache_max; #endif -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) - int8_t ss_refcount; +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) + int8_t ss_refcount; /**< refcount of number of ss connections with streamtypes using this * trust store */ #endif @@ -556,6 +534,10 @@ struct lws_vhost { uint8_t created_vhost_protocols:1; uint8_t being_destroyed:1; uint8_t from_ss_policy:1; +#if defined(LWS_WITH_TLS_JIT_TRUST) + uint8_t grace_after_unref:1; + /* grace time / autodelete aoplies to us */ +#endif unsigned char default_protocol_index; unsigned char raw_protocol_index; @@ -681,6 +663,9 @@ struct lws { struct lws_dll2 adns; /* on adns list of guys to tell result */ lws_async_dns_cb_t adns_cb; /* callback with result */ #endif +#if defined(LWS_WITH_SERVER) + struct lws_dll2 listen_list; +#endif #if defined(LWS_WITH_CLIENT) struct lws_dll2 dll_cli_active_conns; struct lws_dll2 dll2_cli_txn_queue; @@ -697,8 +682,10 @@ struct lws { #endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) - lws_fi_ctx_t fic; + lws_fi_ctx_t fic; /**< Fault Injection ctx for the wsi, hierarchy wsi->vhost->context */ + lws_sorted_usec_list_t sul_fault_timedclose; + /**< used to inject a fault that closes the wsi after a random time */ #endif #if defined(LWS_WITH_SYS_METRICS) @@ -717,7 +704,9 @@ struct lws { struct lws_sequencer *seq; /* associated sequencer if any */ const lws_retry_bo_t *retry_policy; -#if defined(LWS_WITH_THREADPOOL) + lws_log_cx_t *log_cx; + +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) lws_dll2_owner_t tp_task_owner; /* struct lws_threadpool_task */ #endif @@ -745,6 +734,7 @@ struct lws { #if defined(LWS_WITH_TLS) struct lws_lws_tls tls; + char alpn[24]; #endif lws_sock_file_fd_type desc; /* .filefd / .sockfd */ @@ -762,6 +752,8 @@ struct lws { #endif unsigned int cache_secs; + short bugcatcher; + unsigned int hdr_parsing_completed:1; unsigned int mux_substream:1; unsigned int upgraded_to_http2:1; @@ -816,6 +808,9 @@ struct lws { unsigned int client_bound_sspc:1; unsigned int client_proxy_onward:1; #endif + unsigned int tls_borrowed:1; + unsigned int tls_borrowed_hs:1; + unsigned int tls_read_wanted_write:1; #ifdef LWS_WITH_ACCESS_LOG unsigned int access_log_pending:1; @@ -840,6 +835,8 @@ struct lws { * this activity, and will report the failure */ unsigned int tls_session_reused:1; unsigned int perf_done:1; + unsigned int close_is_redirect:1; + unsigned int client_mux_substream_was:1; #endif #ifdef _WIN32 @@ -872,6 +869,7 @@ struct lws { uint8_t sys_tls_client_cert; uint8_t c_pri; #endif + uint8_t af; #if defined(LWS_WITH_CGI) || defined(LWS_WITH_CLIENT) char reason_bf; /* internal writeable callback reason bitfield */ #endif @@ -952,9 +950,16 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, lws_sockfd_type sockfd, int port, const char *iface, int ipv6_allowed); +#if defined(LWS_WITH_SYS_FAULT_INJECTION) +void +lws_wsi_fault_timedclose(struct lws *wsi); +#else +#define lws_wsi_fault_timedclose(_w) +#endif + #if defined(LWS_WITH_IPV6) unsigned long -lws_get_addr_scope(const char *ipaddr); +lws_get_addr_scope(struct lws *wsi, const char *ipaddr); #endif void @@ -1113,8 +1118,8 @@ lws_rxflow_cache(struct lws *wsi, unsigned char *buf, size_t n, size_t len); int lws_service_flag_pending(struct lws_context *context, int tsi); -static LWS_INLINE int -lws_has_buffered_out(struct lws *wsi) { return !!wsi->buflist_out; } +int +lws_has_buffered_out(struct lws *wsi); int LWS_WARN_UNUSED_RESULT lws_ws_client_rx_sm(struct lws *wsi, unsigned char c); @@ -1194,11 +1199,6 @@ lws_destroy_event_pipe(struct lws *wsi); int lws_socks5c_generate_msg(struct lws *wsi, enum socks_msg_type type, ssize_t *msg_len); -#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); @@ -1233,7 +1233,8 @@ lws_http_client_connect_via_info2(struct lws *wsi); struct lws * __lws_wsi_create_with_role(struct lws_context *context, int tsi, - const struct lws_role_ops *ops); + const struct lws_role_ops *ops, + lws_log_cx_t *log_cx_template); int lws_wsi_inject_to_loop(struct lws_context_per_thread *pt, struct lws *wsi); @@ -1354,6 +1355,9 @@ __lws_same_vh_protocol_remove(struct lws *wsi); void lws_same_vh_protocol_insert(struct lws *wsi, int n); +int +lws_client_stash_create(struct lws *wsi, const char **cisin); + void lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt); @@ -1364,14 +1368,14 @@ int _lws_route_pt_close_unroutable(struct lws_context_per_thread *pt); void -_lws_routing_entry_dump(lws_route_t *rou); +_lws_routing_entry_dump(struct lws_context *cx, lws_route_t *rou); void _lws_routing_table_dump(struct lws_context *cx); #define LRR_IGNORE_PRI (1 << 0) #define LRR_MATCH_SRC (1 << 1) -#define LRR_JUST_CHECK (1 << 2) +#define LRR_MATCH_DST (1 << 2) lws_route_t * _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flags); @@ -1424,9 +1428,19 @@ hubbub_error html_parser_cb(const hubbub_token *token, void *pw); #endif +#if defined(_DEBUG) +void +lws_service_assert_loop_thread(struct lws_context *cx, int tsi); +#else +#define lws_service_assert_loop_thread(_cx, _tsi) +#endif + int lws_threadpool_tsi_context(struct lws_context *context, int tsi); +void +lws_threadpool_wsi_closing(struct lws *wsi); + void __lws_wsi_remove_from_sul(struct lws *wsi); @@ -1524,6 +1538,9 @@ lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us); void __lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh); +int +lws_vhost_compare_listen(struct lws_vhost *v1, struct lws_vhost *v2); + void lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni); diff --git a/3rdparty/libwebsockets/lib/core-net/route.c b/3rdparty/libwebsockets/lib/core-net/route.c index efe08ba1..c9fdc2ba 100644 --- a/3rdparty/libwebsockets/lib/core-net/route.c +++ b/3rdparty/libwebsockets/lib/core-net/route.c @@ -35,42 +35,48 @@ void -_lws_routing_entry_dump(lws_route_t *rou) +_lws_routing_entry_dump(struct lws_context *cx, lws_route_t *rou) { char sa[48], fin[192], *end = &fin[sizeof(fin)]; - int n = 0; + char *it = fin; + int n; + + fin[0] = '\0'; if (rou->dest.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->dest, sa, sizeof(sa)); - n += lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), + n = lws_snprintf(it, lws_ptr_diff_size_t(end, it), "dst: %s/%d, ", sa, rou->dest_len); + it = it + n; } if (rou->src.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->src, sa, sizeof(sa)); - n += lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), + n = lws_snprintf(it, lws_ptr_diff_size_t(end, it), "src: %s/%d, ", sa, rou->src_len); + it = it + n; } if (rou->gateway.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->gateway, sa, sizeof(sa)); - n += lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), + n = lws_snprintf(it, lws_ptr_diff_size_t(end, it), "gw: %s, ", sa); + it = it + n; } - lwsl_info(" %s ifidx: %d, pri: %d, proto: %d\n", fin, + lwsl_cx_info(cx, " %s ifidx: %d, pri: %d, proto: %d\n", fin, rou->if_idx, rou->priority, rou->proto); } void _lws_routing_table_dump(struct lws_context *cx) { - lwsl_info("%s\n", __func__); + lwsl_cx_info(cx, "\n"); lws_start_foreach_dll(struct lws_dll2 *, d, lws_dll2_get_head(&cx->routing_table)) { lws_route_t *rou = lws_container_of(d, lws_route_t, list); - _lws_routing_entry_dump(rou); + _lws_routing_entry_dump(cx, rou); } lws_end_foreach_dll(d); } #endif @@ -97,11 +103,15 @@ _lws_routing_table_dump(struct lws_context *cx) lws_route_uidx_t _lws_route_get_uidx(struct lws_context *cx) { + lws_route_uidx_t ou; + if (!cx->route_uidx) cx->route_uidx++; - while (1) { - char again = 0; + ou = cx->route_uidx; + + do { + uint8_t again = 0; /* Anybody in the table already uses the pt's next uidx? */ @@ -114,17 +124,18 @@ _lws_route_get_uidx(struct lws_context *cx) cx->route_uidx++; if (!cx->route_uidx) cx->route_uidx++; - if (again) { + if (cx->route_uidx == ou) { assert(0); /* we have filled up the 8-bit uidx space? */ return 0; } again = 1; + break; } } lws_end_foreach_dll(d); if (!again) return cx->route_uidx++; - } + } while (1); } lws_route_t * @@ -135,7 +146,7 @@ _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flag lws_route_t *rou = lws_container_of(d, lws_route_t, list); if ((!(flags & LRR_MATCH_SRC) || !lws_sa46_compare_ads(&robj->src, &rou->src)) && - ((flags & LRR_MATCH_SRC) || !lws_sa46_compare_ads(&robj->dest, &rou->dest)) && + (!(flags & LRR_MATCH_DST) || !lws_sa46_compare_ads(&robj->dest, &rou->dest)) && (!robj->gateway.sa4.sin_family || !lws_sa46_compare_ads(&robj->gateway, &rou->gateway)) && robj->dest_len <= rou->dest_len && @@ -143,9 +154,7 @@ _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flag ((flags & LRR_IGNORE_PRI) || robj->priority == rou->priority) ) { - if (flags & LRR_JUST_CHECK) - return rou; - lwsl_info("%s: deleting route\n", __func__); + lwsl_cx_info(pt->context, "deleting route"); _lws_route_pt_close_route_users(pt, robj->uidx); lws_dll2_remove(&rou->list); lws_free(rou); @@ -196,7 +205,7 @@ _lws_route_est_outgoing(struct lws_context_per_thread *pt, int best_gw_priority = INT_MAX; if (!dest->sa4.sin_family) { - lwsl_notice("%s: dest has 0 AF\n", __func__); + lwsl_cx_notice(pt->context, "dest has 0 AF"); /* leave it alone */ return NULL; } @@ -223,9 +232,9 @@ _lws_route_est_outgoing(struct lws_context_per_thread *pt, */ return rou; - lwsl_debug("%s: dest af %d, rou gw af %d, pri %d\n", __func__, - dest->sa4.sin_family, rou->gateway.sa4.sin_family, - rou->priority); + lwsl_cx_debug(pt->context, "dest af %d, rou gw af %d, pri %d", + dest->sa4.sin_family, rou->gateway.sa4.sin_family, + rou->priority); if (rou->gateway.sa4.sin_family && @@ -241,7 +250,7 @@ _lws_route_est_outgoing(struct lws_context_per_thread *pt, (dest->sa4.sin_family == AF_INET && rou->gateway.sa4.sin_family == AF_INET6)) && rou->priority < best_gw_priority) { - lwsl_info("%s: gw hit\n", __func__); + lwsl_cx_info(pt->context, "gw hit"); best_gw_priority = rou->priority; best_gw = rou; } @@ -254,7 +263,7 @@ _lws_route_est_outgoing(struct lws_context_per_thread *pt, * gw route for dest. */ - lwsl_info("%s: returning %p\n", __func__, best_gw); + lwsl_cx_info(pt->context, "returning %p", best_gw); return best_gw; } @@ -305,7 +314,7 @@ _lws_route_check_wsi(struct lws *wsi) if (!_lws_route_est_outgoing(pt, &wsi->sa46_peer)) { /* no way to talk to the peer */ - lwsl_notice("%s: %s: dest route gone\n", __func__, wsi->lc.gutag); + lwsl_wsi_notice(wsi, "dest route gone"); return 1; } @@ -321,13 +330,12 @@ _lws_route_check_wsi(struct lws *wsi) lws_sa46_write_numeric_address(&wsi->sa46_local, buf, sizeof(buf)); - lwsl_notice("%s: %s: source %s gone\n", __func__, - wsi->lc.gutag, buf); + lwsl_wsi_notice(wsi, "source %s gone", buf); return 1; } - lwsl_debug("%s: %s: source + dest OK\n", __func__, wsi->lc.gutag); + lwsl_wsi_debug(wsi, "source + dest OK"); return 0; } @@ -338,11 +346,15 @@ _lws_route_pt_close_unroutable(struct lws_context_per_thread *pt) struct lws *wsi; unsigned int n; - if (!pt->context->nl_initial_done || - pt->context->mgr_system.state < LWS_SYSTATE_IFACE_COLDPLUG) + if (!pt->context->nl_initial_done +#if defined(LWS_WITH_SYS_STATE) + || + pt->context->mgr_system.state < LWS_SYSTATE_IFACE_COLDPLUG +#endif + ) return 0; - lwsl_debug("%s\n", __func__); + lwsl_cx_debug(pt->context, "in"); #if defined(_DEBUG) _lws_routing_table_dump(pt->context); #endif @@ -353,7 +365,7 @@ _lws_route_pt_close_unroutable(struct lws_context_per_thread *pt) continue; if (_lws_route_check_wsi(wsi)) { - lwsl_info("%s: culling wsi %s\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "culling wsi"); lws_wsi_close(wsi, LWS_TO_KILL_ASYNC); } } @@ -363,7 +375,7 @@ _lws_route_pt_close_unroutable(struct lws_context_per_thread *pt) int _lws_route_pt_close_route_users(struct lws_context_per_thread *pt, - lws_route_uidx_t uidx) + lws_route_uidx_t uidx) { struct lws *wsi; unsigned int n; @@ -371,7 +383,7 @@ _lws_route_pt_close_route_users(struct lws_context_per_thread *pt, if (!uidx) return 0; - lwsl_info("%s: closing users of route %d\n", __func__, uidx); + lwsl_cx_info(pt->context, "closing users of route %d", uidx); for (n = 0; n < pt->fds_count; n++) { wsi = wsi_from_fd(pt->context, pt->fds[n].fd); @@ -385,7 +397,7 @@ _lws_route_pt_close_route_users(struct lws_context_per_thread *pt, #endif wsi->sa46_peer.sa4.sin_family && wsi->peer_route_uidx == uidx) { - lwsl_notice("%s: culling wsi %s\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_notice(wsi, "culling wsi"); lws_wsi_close(wsi, LWS_TO_KILL_ASYNC); } } diff --git a/3rdparty/libwebsockets/lib/core-net/service.c b/3rdparty/libwebsockets/lib/core-net/service.c index 6737f40b..02e4c05e 100644 --- a/3rdparty/libwebsockets/lib/core-net/service.c +++ b/3rdparty/libwebsockets/lib/core-net/service.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -24,6 +24,27 @@ #include "private-lib-core.h" +#if defined(_DEBUG) +void +lws_service_assert_loop_thread(struct lws_context *cx, int tsi) +{ + if (!cx->event_loop_ops->foreign_thread) + /* we can't judge it */ + return; + + if (!cx->event_loop_ops->foreign_thread(cx, tsi)) + /* OK */ + return; + + /* + * Lws apis are NOT THREADSAFE with the sole exception of + * lws_cancel_service(). If you look at the assert backtrace, you + * should see you're illegally calling an lws api from another thread. + */ + assert(0); +} +#endif + int lws_callback_as_writeable(struct lws *wsi) { @@ -43,8 +64,6 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) volatile struct lws *vwsi = (volatile struct lws *)wsi; int n; - // lwsl_notice("%s: %s\n", __func__, lws_wsi_tag(wsi)); - if (wsi->socket_is_permanently_unusable) return 0; @@ -69,9 +88,8 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) */ if (lws_has_buffered_out(wsi)) { - //lwsl_notice("%s: completing partial\n", __func__); if (lws_issue_raw(wsi, NULL, 0) < 0) { - lwsl_info("%s signalling to close\n", __func__); + lwsl_wsi_info(wsi, "signalling to close"); goto bail_die; } /* leave POLLOUT active either way */ @@ -89,15 +107,14 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) wsi->http.comp_ctx.may_have_more) { enum lws_write_protocol wp = LWS_WRITE_HTTP; - lwsl_info("%s: completing comp partial (buflist_comp %p, may %d)\n", - __func__, wsi->http.comp_ctx.buflist_comp, - wsi->http.comp_ctx.may_have_more - ); + lwsl_wsi_info(wsi, "compl comp partial (buflist_comp %p, may %d)", + wsi->http.comp_ctx.buflist_comp, + wsi->http.comp_ctx.may_have_more); if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol) && lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol). write_role_protocol(wsi, NULL, 0, &wp) < 0) { - lwsl_info("%s signalling to close\n", __func__); + lwsl_wsi_info(wsi, "signalling to close"); goto bail_die; } lws_callback_on_writable(wsi); @@ -115,7 +132,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) /* also one shot */ if (pollfd) if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { - lwsl_info("failed at set pollfd\n"); + lwsl_wsi_info(wsi, "failed at set pollfd"); return 1; } goto user_service_go_again; @@ -149,7 +166,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) if (!eff) { if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { - lwsl_info("failed at set pollfd\n"); + lwsl_wsi_info(wsi, "failed at set pollfd"); goto bail_die; } } @@ -162,9 +179,9 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) * got set inbetween sampling eff and clearing * handling_pollout, force POLLOUT on */ - lwsl_debug("leave_pollout_active\n"); + lwsl_wsi_debug(wsi, "leave_pollout_active"); if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) { - lwsl_info("failed at set pollfd\n"); + lwsl_wsi_info(wsi, "failed at set pollfd"); goto bail_die; } } @@ -194,9 +211,8 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) goto bail_ok; } - lwsl_debug("%s: %s: non mux: wsistate 0x%lx, ops %s\n", __func__, - lws_wsi_tag(wsi), - (unsigned long)wsi->wsistate, wsi->role_ops->name); + lwsl_wsi_debug(wsi, "non mux: wsistate 0x%lx, ops %s", + (unsigned long)wsi->wsistate, wsi->role_ops->name); vwsi = (volatile struct lws *)wsi; vwsi->leave_pollout_active = 0; @@ -249,8 +265,8 @@ lws_rxflow_cache(struct lws *wsi, unsigned char *buf, size_t n, size_t len) */ lws_buflist_use_segment(&wsi->buflist, blen - len); - lwsl_debug("%s: trim existing rxflow %d -> %d\n", - __func__, (int)blen, (int)len); + lwsl_wsi_debug(wsi, "trim existing rxflow %d -> %d", + (int)blen, (int)len); return LWSRXFC_TRIMMED; } @@ -259,13 +275,13 @@ lws_rxflow_cache(struct lws *wsi, unsigned char *buf, size_t n, size_t len) /* a new rxflow, buffer it and warn caller */ - lwsl_debug("%s: rxflow append %d\n", __func__, (int)(len - n)); + lwsl_wsi_debug(wsi, "rxflow append %d", (int)(len - n)); m = lws_buflist_append_segment(&wsi->buflist, buf + n, len - n); if (m < 0) return LWSRXFC_ERROR; if (m) { - lwsl_debug("%s: added %s to rxflow list\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_debug(wsi, "added to rxflow list");; if (lws_dll2_is_detached(&wsi->dll_buflist)) lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner); } @@ -299,14 +315,22 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi) pt = &context->pt[tsi]; -#if defined(LWS_WITH_EXTERNAL_POLL) - { - lws_usec_t u = __lws_sul_service_ripe(pt->pt_sul_owner, + if (pt->evlib_pt) { + lws_usec_t u; + + lws_pt_lock(pt, __func__); /* -------------- pt { */ + + 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; + /* + * We will come back with 0 if nothing to do at the moment, or + * the number of us until something to do + */ + if (u && u < (lws_usec_t)timeout_ms * (lws_usec_t)1000) + timeout_ms = (int)(u / 1000); + + lws_pt_unlock(pt); } -#endif /* * Figure out if we really want to wait in poll()... we only need to @@ -394,8 +418,7 @@ lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi, ebuf->token = ep; ebuf->len = n = lws_ssl_capable_read(wsi, ep, (size_t)e); - lwsl_debug("%s: %s: %s: ssl_capable_read %d\n", __func__, - lws_wsi_tag(wsi), hint, ebuf->len); + lwsl_wsi_debug(wsi, "%s: ssl_capable_read %d", hint, ebuf->len); if (!bns && /* only acknowledge error when we handled buflist content */ n == LWS_SSL_CAPABLE_ERROR) { @@ -452,10 +475,6 @@ lws_buflist_aware_finished_consuming(struct lws *wsi, struct lws_tokens *ebuf, 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, - // buffered, (size_t)used, (size_t)ebuf->len); - // lws_buflist_describe(&wsi->buflist, wsi, __func__); - /* it's in the buflist; we didn't use any */ if (!used && buffered) @@ -463,14 +482,13 @@ lws_buflist_aware_finished_consuming(struct lws *wsi, struct lws_tokens *ebuf, if (used && buffered) { if (wsi->buflist) { - m = (int)lws_buflist_use_segment(&wsi->buflist, (size_t)used); - // lwsl_notice("%s: used %d, next %d\n", __func__, used, m); - // lws_buflist_describe(&wsi->buflist, wsi, __func__); + m = (int)lws_buflist_use_segment(&wsi->buflist, + (size_t)used); if (m) return 0; } - lwsl_info("%s: removed %p from dll_buflist\n", __func__, wsi); + lwsl_wsi_info(wsi, "removed from dll_buflist"); lws_dll2_remove(&wsi->dll_buflist); return 0; @@ -479,21 +497,17 @@ lws_buflist_aware_finished_consuming(struct lws *wsi, struct lws_tokens *ebuf, /* any remainder goes on the buflist */ if (used < ebuf->len && ebuf->len >= 0 && used >= 0) { - // lwsl_notice("%s %s bac appending %d\n", __func__, hint, - // ebuf->len - used); m = lws_buflist_append_segment(&wsi->buflist, ebuf->token + used, (unsigned int)(ebuf->len - used)); if (m < 0) return 1; /* OOM */ if (m) { - lwsl_debug("%s: added %s to rxflow list\n", - __func__, lws_wsi_tag(wsi)); + lwsl_wsi_debug(wsi, "added to rxflow list"); if (lws_dll2_is_detached(&wsi->dll_buflist)) lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner); } - // lws_buflist_describe(&wsi->buflist, wsi, __func__); } return 0; @@ -522,9 +536,9 @@ lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt) pfd.revents = LWS_POLLIN; pfd.fd = -1; - lwsl_debug("%s: rxflow processing: %s fc=%d, 0x%lx\n", __func__, - lws_wsi_tag(wsi), lws_is_flowcontrolled(wsi), - (unsigned long)wsi->wsistate); + lwsl_wsi_debug(wsi, "rxflow processing: fc=%d, 0x%lx", + lws_is_flowcontrolled(wsi), + (unsigned long)wsi->wsistate); if (!lws_is_flowcontrolled(wsi) && lwsi_state(wsi) != LRS_DEFERRING_ACTION) { @@ -626,6 +640,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, { struct lws_context_per_thread *pt; struct lws *wsi; + char cow = 0; if (!context || context->service_no_longer_possible) return -1; @@ -686,8 +701,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, * so acknowledge the wsi is done */ - lwsl_debug("Session Socket %s (fd=%d) dead\n", - lws_wsi_tag(wsi), pollfd->fd); + lwsl_wsi_debug(wsi, "Session Socket %d dead", + pollfd->fd); goto close_and_handled; } @@ -721,6 +736,22 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, } } #endif + + if ((pollfd->revents & LWS_POLLOUT) == LWS_POLLOUT && + wsi->tls_read_wanted_write) { + /* + * If this wsi has a pending WANT_WRITE from SSL_read(), it has + * asked for a callback on writeable so it can retry the read. + * + * Let's consume the POLLOUT by turning it into a POLLIIN, and + * setting a flag to request a new writeable + */ + wsi->tls_read_wanted_write = 0; + pollfd->revents &= ~(LWS_POLLOUT); + pollfd->revents |= LWS_POLLIN; + cow = 1; + } + wsi->could_have_pending = 0; /* clear back-to-back write detection */ pt->inside_lws_service = 1; @@ -743,7 +774,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, //lwsl_notice("%s: %s pollin says please close me\n", __func__, // wsi->role_ops->name); close_and_handled: - lwsl_debug("%s: %s: Close and handled\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_debug(wsi, "Close and handled"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "close_and_handled"); #if defined(_DEBUG) && defined(LWS_WITH_LIBUV) @@ -771,6 +802,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, handled: #endif pollfd->revents = 0; + if (cow) + lws_callback_on_writable(wsi); pt->inside_lws_service = 0; return 0; diff --git a/3rdparty/libwebsockets/lib/core-net/socks5-client.c b/3rdparty/libwebsockets/lib/core-net/socks5-client.c index f0db8f8c..4d7572a1 100644 --- a/3rdparty/libwebsockets/lib/core-net/socks5-client.c +++ b/3rdparty/libwebsockets/lib/core-net/socks5-client.c @@ -41,22 +41,22 @@ lws_set_socks(struct lws_vhost *vhost, const char *socks) p_at = strrchr(socks, '@'); if (p_at) { /* auth is around */ - if ((unsigned int)(p_at - socks) > (sizeof(user) - + sizeof(password) - 2)) { - lwsl_err("Socks auth too long\n"); + if (lws_ptr_diff_size_t(p_at, socks) > (sizeof(user) + + sizeof(password) - 2)) { + lwsl_vhost_err(vhost, "auth too long"); goto bail; } p_colon = strchr(socks, ':'); if (p_colon) { - if ((unsigned int)(p_colon - socks) > (sizeof(user) - - 1) ) { - lwsl_err("Socks user too long\n"); + if (lws_ptr_diff_size_t(p_colon, socks) > + sizeof(user) - 1) { + lwsl_vhost_err(vhost, "user too long"); goto bail; } - if ((unsigned int)(p_at - p_colon) > (sizeof(password) - - 1) ) { - lwsl_err("Socks password too long\n"); + if (lws_ptr_diff_size_t(p_at, p_colon) > + sizeof(password) - 1) { + lwsl_vhost_err(vhost, "pw too long"); goto bail; } @@ -66,8 +66,9 @@ lws_set_socks(struct lws_vhost *vhost, const char *socks) lws_ptr_diff_size_t(p_at, (p_colon + 1)) + 1); } - lwsl_info(" Socks auth, user: %s, password: %s\n", - vhost->socks_user, vhost->socks_password ); + lwsl_vhost_info(vhost, " Socks auth, user: %s, password: %s", + vhost->socks_user, + vhost->socks_password); socks = p_at + 1; } @@ -77,17 +78,19 @@ lws_set_socks(struct lws_vhost *vhost, const char *socks) p_colon = strchr(vhost->socks_proxy_address, ':'); if (!p_colon && !vhost->socks_proxy_port) { - lwsl_err("socks_proxy needs to be address:port\n"); + lwsl_vhost_err(vhost, "socks_proxy needs to be address:port"); + return -1; - } else { - if (p_colon) { - *p_colon = '\0'; - vhost->socks_proxy_port = (unsigned int)atoi(p_colon + 1); - } } - lwsl_debug("%s: Connections via Socks5 %s:%u\n", __func__, - vhost->socks_proxy_address, vhost->socks_proxy_port); + if (p_colon) { + *p_colon = '\0'; + vhost->socks_proxy_port = (unsigned int)atoi(p_colon + 1); + } + + lwsl_vhost_debug(vhost, "Connections via Socks5 %s:%u", + vhost->socks_proxy_address, + vhost->socks_proxy_port); return 0; @@ -233,9 +236,9 @@ lws_socks5c_greet(struct lws *wsi, const char **pcce) } // lwsl_hexdump_notice(pt->serv_buf, plen); n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, (size_t)plen, - MSG_NOSIGNAL); + MSG_NOSIGNAL); if (n < 0) { - lwsl_debug("ERROR writing socks greeting\n"); + lwsl_wsi_debug(wsi, "ERROR writing socks greeting"); *pcce = "socks write failed"; return -1; } @@ -260,20 +263,19 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, /* handle proxy hung up on us */ if (pollfd->revents & LWS_POLLHUP) { - lwsl_warn("SOCKS conn %s (fd=%d) dead\n", - lws_wsi_tag(wsi), pollfd->fd); + lwsl_wsi_warn(wsi, "SOCKS fd=%d dead", pollfd->fd); *pcce = "socks conn dead"; return LW5CHS_RET_BAIL3; } - n = (int)recv(wsi->desc.sockfd, pt->serv_buf, + n = (int)recv(wsi->desc.sockfd, (void *)pt->serv_buf, wsi->a.context->pt_serv_buf_size, 0); if (n < 0) { if (LWS_ERRNO == LWS_EAGAIN) { - lwsl_debug("SOCKS read EAGAIN, retrying\n"); + lwsl_wsi_debug(wsi, "SOCKS read EAGAIN, retrying"); return LW5CHS_RET_RET0; } - lwsl_err("ERROR reading from SOCKS socket\n"); + lwsl_wsi_err(wsi, "ERROR reading from SOCKS socket"); *pcce = "socks recv fail"; return LW5CHS_RET_BAIL3; } @@ -287,11 +289,10 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, goto socks_reply_fail; if (pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH) { - lwsl_client("SOCKS GR: No Auth Method\n"); + lwsl_wsi_client(wsi, "SOCKS GR: No Auth Method"); if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_CONNECT, &len)) { - lwsl_err("%s: failed to generate connect msg\n", - __func__); + lwsl_wsi_err(wsi, "generate connect msg fail"); goto socks_send_msg_fail; } conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY; @@ -301,7 +302,7 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, } if (pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD) { - lwsl_client("SOCKS GR: User/Pw Method\n"); + lwsl_wsi_client(wsi, "SOCKS GR: User/Pw Method"); if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_USERNAME_PASSWORD, &len)) @@ -319,7 +320,7 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, SOCKS_SUBNEGOTIATION_STATUS_SUCCESS) goto socks_reply_fail; - lwsl_client("SOCKS password OK, sending connect\n"); + lwsl_wsi_client(wsi, "SOCKS password OK, sending connect"); if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_CONNECT, &len)) { socks_send_msg_fail: *pcce = "socks gen msg fail"; @@ -330,10 +331,10 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY; socks_send: // lwsl_hexdump_notice(pt->serv_buf, len); - n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, (size_t)len, - MSG_NOSIGNAL); + n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, + (size_t)len, MSG_NOSIGNAL); if (n < 0) { - lwsl_debug("ERROR writing to socks proxy\n"); + lwsl_wsi_debug(wsi, "ERROR writing to socks proxy"); *pcce = "socks write fail"; return LW5CHS_RET_BAIL3; } @@ -344,8 +345,8 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, break; socks_reply_fail: - lwsl_err("%s: socks reply: v%d, err %d\n", __func__, - pt->serv_buf[0], pt->serv_buf[1]); + lwsl_wsi_err(wsi, "socks reply: v%d, err %d", + pt->serv_buf[0], pt->serv_buf[1]); *pcce = "socks reply fail"; return LW5CHS_RET_BAIL3; @@ -354,7 +355,7 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, pt->serv_buf[1] != SOCKS_REQUEST_REPLY_SUCCESS) goto socks_reply_fail; - lwsl_client("%s: socks connect OK\n", __func__); + lwsl_wsi_client(wsi, "socks connect OK"); #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (lwsi_role_http(wsi) && diff --git a/3rdparty/libwebsockets/lib/core-net/sorted-usec-list.c b/3rdparty/libwebsockets/lib/core-net/sorted-usec-list.c index 16ff617f..d9af0f11 100644 --- a/3rdparty/libwebsockets/lib/core-net/sorted-usec-list.c +++ b/3rdparty/libwebsockets/lib/core-net/sorted-usec-list.c @@ -81,6 +81,8 @@ lws_sul2_schedule(struct lws_context *context, int tsi, int flags, lws_pt_assert_lock_held(pt); + assert(sul->cb); + __lws_sul_insert( &pt->pt_sul_owner[!!(flags & LWSSULLI_WAKE_IF_SUSPENDED)], sul); } @@ -144,6 +146,12 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow) /* his moment has come... remove him from his owning list */ + if (!hit->cb) { + lwsl_err("%s: sul with NULL callback (did not cancel on destory?)\n", __func__); + + return 0; + } + lws_dll2_remove(&hit->list); hit->us = 0; @@ -272,6 +280,8 @@ lws_sul_schedule(struct lws_context *ctx, int tsi, lws_sorted_usec_list_t *sul, { struct lws_context_per_thread *_pt = &ctx->pt[tsi]; + assert(_cb); + lws_pt_lock(_pt, __func__); if (_us == (lws_usec_t)LWS_SET_TIMER_USEC_CANCEL) @@ -292,6 +302,8 @@ lws_sul_schedule_wakesuspend(struct lws_context *ctx, int tsi, { struct lws_context_per_thread *_pt = &ctx->pt[tsi]; + assert(_cb); + lws_pt_lock(_pt, __func__); if (_us == (lws_usec_t)LWS_SET_TIMER_USEC_CANCEL) @@ -334,16 +346,23 @@ lws_sul_debug_zombies(struct lws_context *ctx, void *po, size_t len, lws_container_of(p, lws_sorted_usec_list_t, list); + if (!po) { + lwsl_cx_err(ctx, "%s", + destroy_description); + /* just sanity check the list */ + assert(sul->cb); + } + /* * Is the sul resident inside the object that is * indicated as being deleted? */ - if ((void *)sul >= po && + if (po && + (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, + lwsl_cx_err(ctx, "ERROR: Zombie Sul " + "(on list %d) %s, cb %p\n", m, destroy_description, sul->cb); /* * This assert fires if you have left diff --git a/3rdparty/libwebsockets/lib/core-net/state.c b/3rdparty/libwebsockets/lib/core-net/state.c index 2063f06b..8eabce2b 100644 --- a/3rdparty/libwebsockets/lib/core-net/state.c +++ b/3rdparty/libwebsockets/lib/core-net/state.c @@ -74,10 +74,10 @@ _report(lws_state_manager_t *mgr, int a, int b) /* a dependency took responsibility for retry */ #if (_LWS_ENABLED_LOGS & LLL_INFO) - lwsl_info("%s: %s: %s: rejected '%s' -> '%s'\n", - __func__, mgr->name, l->name, - _systnm(mgr, a, temp8), - _systnm(mgr, b, temp8)); + lwsl_cx_info(mgr->context, "%s: %s: rejected '%s' -> '%s'", + mgr->name, l->name, + _systnm(mgr, a, temp8), + _systnm(mgr, b, temp8)); #endif return 1; @@ -99,7 +99,8 @@ _lws_state_transition(lws_state_manager_t *mgr, int target) return 1; #if (_LWS_ENABLED_LOGS & LLL_DEBUG) - lwsl_debug("%s: %s: changed %d '%s' -> %d '%s'\n", __func__, mgr->name, + if (mgr->context) + lwsl_cx_debug(mgr->context, "%s: changed %d '%s' -> %d '%s'", mgr->name, mgr->state, _systnm(mgr, mgr->state, temp8), target, _systnm(mgr, target, temp8)); #endif @@ -110,7 +111,7 @@ _lws_state_transition(lws_state_manager_t *mgr, int target) _report(mgr, target, target); #if defined(LWS_WITH_SYS_SMD) - if (mgr->smd_class) + if (mgr->smd_class && mgr->context) (void)lws_smd_msg_printf(mgr->context, mgr->smd_class, "{\"state\":\"%s\"}", mgr->state_names[target]); @@ -135,7 +136,7 @@ lws_state_transition_steps(lws_state_manager_t *mgr, int target) n = _lws_state_transition(mgr, mgr->state + 1); #if (_LWS_ENABLED_LOGS & LLL_INFO) - lwsl_info("%s: %s -> %s\n", __func__, _systnm(mgr, i, temp8), + lwsl_cx_info(mgr->context, "%s -> %s", _systnm(mgr, i, temp8), _systnm(mgr, mgr->state, temp8)); #endif diff --git a/3rdparty/libwebsockets/lib/core-net/vhost.c b/3rdparty/libwebsockets/lib/core-net/vhost.c index ec5349e0..298bf01e 100644 --- a/3rdparty/libwebsockets/lib/core-net/vhost.c +++ b/3rdparty/libwebsockets/lib/core-net/vhost.c @@ -117,7 +117,7 @@ lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn) return 0; #if !defined(LWS_ESP_PLATFORM) - lwsl_info("%s: '%s'\n", __func__, alpn); + lwsl_wsi_info(wsi, "'%s'", alpn); #endif LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) @@ -153,8 +153,11 @@ lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot) prot = wsi->a.vhost->listen_accept_protocol; if (!role) - lwsl_err("%s: can't find role '%s'\n", __func__, - wsi->a.vhost->listen_accept_role); + lwsl_wsi_err(wsi, "can't find role '%s'", + wsi->a.vhost->listen_accept_role); + + if (!strcmp(wsi->a.vhost->listen_accept_role, "raw-proxy")) + type |= LWS_ADOPT_FLAG_RAW_PROXY; if (role && lws_rops_fidx(role, LWS_ROPS_adoption_bind)) { n = (lws_rops_func_fidx(role, LWS_ROPS_adoption_bind)). @@ -166,13 +169,13 @@ lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot) } if (type & _LWS_ADOPT_FINISH) { - lwsl_debug("%s: leaving bound to role %s\n", __func__, - wsi->role_ops->name); + lwsl_wsi_debug(wsi, "leaving bound to role %s", + wsi->role_ops->name); return 0; } - lwsl_warn("%s: adoption bind to role '%s', " - "protocol '%s', type 0x%x, failed\n", __func__, + lwsl_wsi_warn(wsi, "adoption bind to role '%s', " + "protocol '%s', type 0x%x, failed", wsi->a.vhost->listen_accept_role, prot, type); } @@ -197,7 +200,7 @@ lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot) #if defined(LWS_ROLE_RAW_FILE) - lwsl_notice("%s: falling back to raw file role bind\n", __func__); + lwsl_wsi_notice(wsi, "falling back to raw file role bind"); /* fall back to raw file role if, eg, h1 not configured */ @@ -244,7 +247,7 @@ lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, { int n = 0; - if (!vhost || !prot) + if (!vhost || !prot || !vhost->protocols || !prot->name) return NULL; /* allocate the vh priv array only on demand */ @@ -252,6 +255,7 @@ lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, vhost->protocol_vh_privs = (void **)lws_zalloc( (size_t)vhost->count_protocols * sizeof(void *), "protocol_vh_privs"); + if (!vhost->protocol_vh_privs) return NULL; } @@ -261,12 +265,17 @@ lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, if (n == vhost->count_protocols) { n = 0; - while (n < vhost->count_protocols && - strcmp(vhost->protocols[n].name, prot->name)) + while (n < vhost->count_protocols) { + if (vhost->protocols[n].name && + !strcmp(vhost->protocols[n].name, prot->name)) + break; n++; + } - if (n == vhost->count_protocols) + if (n == vhost->count_protocols) { + lwsl_vhost_err(vhost, "unknown protocol %p", prot); return NULL; + } } vhost->protocol_vh_privs[n] = lws_zalloc((size_t)size, "vh priv"); @@ -279,7 +288,8 @@ lws_protocol_vh_priv_get(struct lws_vhost *vhost, { int n = 0; - if (!vhost || !vhost->protocol_vh_privs || !prot) + if (!vhost || !vhost->protocols || + !vhost->protocol_vh_privs || !prot || !prot->name) return NULL; while (n < vhost->count_protocols && &vhost->protocols[n] != prot) @@ -287,12 +297,15 @@ lws_protocol_vh_priv_get(struct lws_vhost *vhost, if (n == vhost->count_protocols) { n = 0; - while (n < vhost->count_protocols && - strcmp(vhost->protocols[n].name, prot->name)) + while (n < vhost->count_protocols) { + if (vhost->protocols[n].name && + !strcmp(vhost->protocols[n].name, prot->name)) + break; n++; + } if (n == vhost->count_protocols) { - lwsl_err("%s: unknown protocol %p\n", __func__, prot); + lwsl_vhost_err(vhost, "unknown protocol %p", prot); return NULL; } } @@ -340,7 +353,7 @@ lws_vhd_find_by_pvo(struct lws_context *cx, const char *protname, return vh->protocol_vh_privs[n]; } } else - lwsl_notice("%s: no privs yet on %s\n", __func__, lws_vh_tag(vh)); + lwsl_vhost_notice(vh, "no privs yet"); vh = vh->vhost_next; } @@ -368,17 +381,25 @@ int lws_protocol_init_vhost(struct lws_vhost *vh, int *any) { const struct lws_protocol_vhost_options *pvo, *pvo1; - lws_fakewsi_def_plwsa(&vh->context->pt[0]); int n; +#if defined(LWS_PLAT_FREERTOS) + struct lws_a _lwsa, *lwsa = &_lwsa; + + memset(&_lwsa, 0, sizeof(_lwsa)); +#else + struct lws _lws; + struct lws_a *lwsa = &_lws.a; - lws_fakewsi_prep_plwsa_ctx(vh->context); + memset(&_lws, 0, sizeof(_lws)); +#endif - plwsa->vhost = vh; + lwsa->context = vh->context; + lwsa->vhost = vh; /* initialize supported protocols on this vhost */ for (n = 0; n < vh->count_protocols; n++) { - plwsa->protocol = &vh->protocols[n]; + lwsa->protocol = &vh->protocols[n]; if (!vh->protocols[n].name) continue; pvo = lws_vhost_protocol_options(vh, vh->protocols[n].name); @@ -391,42 +412,34 @@ lws_protocol_init_vhost(struct lws_vhost *vh, int *any) pvo = pvo1->options; while (pvo) { - lwsl_debug( - " vhost \"%s\", " - "protocol \"%s\", " - "option \"%s\"\n", - vh->name, - vh->protocols[n].name, - pvo->name); + lwsl_vhost_debug(vh, "protocol \"%s\", " + "option \"%s\"", + vh->protocols[n].name, + pvo->name); if (!strcmp(pvo->name, "default")) { - lwsl_info("Setting default " - "protocol for vh %s to %s\n", - vh->name, - vh->protocols[n].name); + lwsl_vhost_info(vh, "Setting default " + "protocol to %s", + vh->protocols[n].name); vh->default_protocol_index = (unsigned char)n; } if (!strcmp(pvo->name, "raw")) { - lwsl_info("Setting raw " - "protocol for vh %s to %s\n", - vh->name, - vh->protocols[n].name); + lwsl_vhost_info(vh, "Setting raw " + "protocol to %s", + vh->protocols[n].name); vh->raw_protocol_index = (unsigned char)n; } pvo = pvo->next; } } else - lwsl_debug("%s: not instantiating %s.%s\n", - __func__, vh->name, vh->protocols[n].name); + lwsl_vhost_debug(vh, "not instantiating %s", + vh->protocols[n].name); #if defined(LWS_WITH_TLS) if (any) *any |= !!vh->tls.ssl_ctx; #endif - plwsa->vhost = vh; - plwsa->protocol = &vh->protocols[n]; - pvo = lws_vhost_protocol_options(vh, vh->protocols[n].name); /* @@ -437,18 +450,35 @@ lws_protocol_init_vhost(struct lws_vhost *vh, int *any) * prepared in case the protocol handler wants to touch them */ - if (pvo || !vh->pvo) { - lwsl_info("%s: init %s.%s\n", __func__, vh->name, + if (pvo +#if !defined(LWS_WITH_PLUGINS) + /* + * with plugins, you have to explicitly + * instantiate them per-vhost with pvos. + * + * Without plugins, not setting the vhost pvo + * list at creation enables all the protocols + * by default, for backwards compatibility + */ + || !vh->pvo +#endif + ) { + lwsl_vhost_info(vh, "init %s.%s", vh->name, vh->protocols[n].name); - if (vh->protocols[n].callback((struct lws *)plwsa, + if (vh->protocols[n].callback((struct lws *)lwsa, LWS_CALLBACK_PROTOCOL_INIT, NULL, - (void *)(pvo ? pvo->options : NULL), 0)) { +#if !defined(LWS_WITH_PLUGINS) + (void *)(pvo ? pvo->options : NULL), +#else + (void *)pvo->options, +#endif + 0)) { if (vh->protocol_vh_privs && vh->protocol_vh_privs[n]) { lws_free(vh->protocol_vh_privs[n]); vh->protocol_vh_privs[n] = NULL; } - lwsl_err("%s: protocol %s failed init\n", - __func__, vh->protocols[n].name); + lwsl_vhost_err(vh, "protocol %s failed init", + vh->protocols[n].name); return 1; } @@ -475,7 +505,7 @@ lws_protocol_init(struct lws_context *context) context->doing_protocol_init = 1; - lwsl_info("%s\n", __func__); + lwsl_cx_info(context, "\n"); while (vh) { @@ -485,7 +515,7 @@ lws_protocol_init(struct lws_context *context) goto next; if (lws_protocol_init_vhost(vh, &any)) { - lwsl_warn("%s: init vhost %s failed\n", __func__, vh->name); + lwsl_vhost_warn(vh, "init vhost %s failed", vh->name); r = -1; } next: @@ -495,7 +525,7 @@ lws_protocol_init(struct lws_context *context) context->doing_protocol_init = 0; if (r) - lwsl_warn("%s: some protocols did not init\n", __func__); + lwsl_cx_warn(context, "some protocols did not init"); if (!context->protocol_init_done) { @@ -552,6 +582,7 @@ lws_create_vhost(struct lws_context *context, #endif struct lws_protocols *lwsp; int m, f = !info->pvo, fx = 0, abs_pcol_count = 0, sec_pcol_count = 0; + const char *name = "default"; char buf[96]; char *p; #if defined(LWS_WITH_SYS_ASYNC_DNS) @@ -559,10 +590,13 @@ lws_create_vhost(struct lws_context *context, #endif int n; + if (info->vhost_name) + name = info->vhost_name; + if (lws_fi(&info->fic, "vh_create_oom")) vh = NULL; else - vh = lws_zalloc(sizeof(*vh) + vh = lws_zalloc(sizeof(*vh) + strlen(name) + 1 #if defined(LWS_WITH_EVENT_LIBS) + context->event_loop_ops->evlib_size_vh #endif @@ -570,9 +604,19 @@ lws_create_vhost(struct lws_context *context, if (!vh) goto early_bail; + if (info->log_cx) + vh->lc.log_cx = info->log_cx; + else + vh->lc.log_cx = &log_cx; + #if defined(LWS_WITH_EVENT_LIBS) vh->evlib_vh = (void *)&vh[1]; + vh->name = (const char *)vh->evlib_vh + + context->event_loop_ops->evlib_size_vh; +#else + vh->name = (const char *)&vh[1]; #endif + memcpy((char *)vh->name, name, strlen(name) + 1); #if LWS_MAX_SMP > 1 lws_mutex_refcount_init(&vh->mr); @@ -582,10 +626,6 @@ lws_create_vhost(struct lws_context *context, pcols = &protocols_dummy[0]; vh->context = context; - if (!info->vhost_name) - vh->name = "default"; - else - vh->name = info->vhost_name; { char *end = buf + sizeof(buf) - 1; p = buf; @@ -597,8 +637,8 @@ lws_create_vhost(struct lws_context *context, p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "|%u", info->port); } - __lws_lc_tag(&context->lcg[LWSLCG_VHOST], &vh->lc, "%s|%s|%d", buf, - info->iface ? info->iface : "", info->port); + __lws_lc_tag(context, &context->lcg[LWSLCG_VHOST], &vh->lc, "%s|%s|%d", + buf, info->iface ? info->iface : "", info->port); #if defined(LWS_WITH_SYS_FAULT_INJECTION) vh->fic.name = "vh"; @@ -619,7 +659,7 @@ lws_create_vhost(struct lws_context *context, #endif if (lws_check_opt(info->options, LWS_SERVER_OPTION_ONLY_RAW)) - lwsl_info("%s set to only support RAW\n", vh->name); + lwsl_vhost_info(vh, "set to only support RAW"); vh->iface = info->iface; #if !defined(LWS_PLAT_FREERTOS) && !defined(OPTEE_TA) && !defined(WIN32) @@ -654,15 +694,16 @@ lws_create_vhost(struct lws_context *context, vh->count_protocols++) ; - vh->options = info->options; - vh->pvo = info->pvo; - vh->headers = info->headers; - vh->user = info->user; - vh->finalize = info->finalize; - vh->finalize_arg = info->finalize_arg; - vh->listen_accept_role = info->listen_accept_role; - vh->listen_accept_protocol = info->listen_accept_protocol; - vh->unix_socket_perms = info->unix_socket_perms; + vh->options = info->options; + vh->pvo = info->pvo; + vh->headers = info->headers; + vh->user = info->user; + vh->finalize = info->finalize; + vh->finalize_arg = info->finalize_arg; + vh->listen_accept_role = info->listen_accept_role; + vh->listen_accept_protocol = info->listen_accept_protocol; + vh->unix_socket_perms = info->unix_socket_perms; + vh->fo_listen_queue = info->fo_listen_queue; LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) if (lws_rops_fidx(ar, LWS_ROPS_init_vhost) && @@ -853,7 +894,7 @@ lws_create_vhost(struct lws_context *context, #ifdef LWS_WITH_UNIX_SOCK if (LWS_UNIX_SOCK_ENABLED(vh)) { - lwsl_info("Creating Vhost '%s' path \"%s\", %d protocols\n", + lwsl_vhost_info(vh, "Creating '%s' path \"%s\", %d protocols", vh->name, vh->iface, vh->count_protocols); } else #endif @@ -869,14 +910,14 @@ lws_create_vhost(struct lws_context *context, lws_snprintf(buf, sizeof(buf), "port %u", info->port); break; } - lwsl_info("Creating Vhost '%s' %s, %d protocols, IPv6 %s\n", + lwsl_vhost_info(vh, "Creating Vhost '%s' %s, %d protocols, IPv6 %s", vh->name, buf, vh->count_protocols, LWS_IPV6_ENABLED(vh) ? "on" : "off"); } mounts = info->mounts; while (mounts) { (void)mount_protocols[0]; - lwsl_info(" mounting %s%s to %s\n", + lwsl_vhost_info(vh, " mounting %s%s to %s", mount_protocols[mounts->origin_protocol], mounts->origin ? mounts->origin : "none", mounts->mountpoint); @@ -927,7 +968,7 @@ lws_create_vhost(struct lws_context *context, vh->ka_probes = info->ka_probes; if (vh->options & LWS_SERVER_OPTION_STS) - lwsl_notice(" STS enabled\n"); + lwsl_vhost_notice(vh, " STS enabled"); #ifdef LWS_WITH_ACCESS_LOG if (info->log_filepath) { @@ -937,28 +978,28 @@ lws_create_vhost(struct lws_context *context, vh->log_fd = lws_open(info->log_filepath, O_CREAT | O_APPEND | O_RDWR, 0600); if (vh->log_fd == (int)LWS_INVALID_FILE) { - lwsl_err("unable to open log filepath %s\n", - info->log_filepath); + lwsl_vhost_err(vh, "unable to open log filepath %s", + info->log_filepath); goto bail; } #ifndef WIN32 if (context->uid != (uid_t)-1) if (chown(info->log_filepath, context->uid, context->gid) == -1) - lwsl_err("unable to chown log file %s\n", - info->log_filepath); + lwsl_vhost_err(vh, "unable to chown log file %s", + info->log_filepath); #endif } else vh->log_fd = (int)LWS_INVALID_FILE; #endif if (lws_fi(&vh->fic, "vh_create_ssl_srv") || lws_context_init_server_ssl(info, vh)) { - lwsl_err("%s: lws_context_init_server_ssl failed\n", __func__); + lwsl_vhost_err(vh, "lws_context_init_server_ssl failed"); goto bail1; } if (lws_fi(&vh->fic, "vh_create_ssl_cli") || lws_context_init_client_ssl(info, vh)) { - lwsl_err("%s: lws_context_init_client_ssl failed\n", __func__); + lwsl_vhost_err(vh, "lws_context_init_client_ssl failed"); goto bail1; } #if defined(LWS_WITH_SERVER) @@ -969,7 +1010,7 @@ lws_create_vhost(struct lws_context *context, n = _lws_vhost_init_server(info, vh); lws_context_unlock(context); if (n < 0) { - lwsl_err("init server failed\n"); + lwsl_vhost_err(vh, "init server failed\n"); goto bail1; } #endif @@ -996,7 +1037,7 @@ lws_create_vhost(struct lws_context *context, if (context->protocol_init_done) if (lws_fi(&vh->fic, "vh_create_protocol_init") || lws_protocol_init(context)) { - lwsl_err("%s: lws_protocol_init failed\n", __func__); + lwsl_vhost_err(vh, "lws_protocol_init failed"); goto bail1; } @@ -1008,7 +1049,7 @@ lws_create_vhost(struct lws_context *context, return NULL; bail: - __lws_lc_untag(&vh->lc); + __lws_lc_untag(vh->context, &vh->lc); lws_fi_destroy(&vh->fic); lws_free(vh); @@ -1045,7 +1086,7 @@ lws_cancel_service(struct lws_context *context) if (context->service_no_longer_possible) return; - lwsl_debug("%s\n", __func__); + lwsl_cx_debug(context, "\n"); for (m = 0; m < context->count_threads; m++) { if (pt->pipe_wsi) @@ -1077,11 +1118,13 @@ __lws_create_event_pipes(struct lws_context *context) if (pt->pipe_wsi) return 0; - wsi = __lws_wsi_create_with_role(context, n, &role_ops_pipe); + wsi = __lws_wsi_create_with_role(context, n, &role_ops_pipe, + NULL); if (!wsi) return 1; - __lws_lc_tag(&context->lcg[LWSLCG_WSI], &wsi->lc, "pipe"); + __lws_lc_tag(context, &context->lcg[LWSLCG_WSI], &wsi->lc, + "pipe"); wsi->event_pipe = 1; pt->pipe_wsi = wsi; @@ -1097,7 +1140,7 @@ __lws_create_event_pipes(struct lws_context *context) */ wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0]; - lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd); + // lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd); if (lws_wsi_inject_to_loop(pt, wsi)) goto bail; @@ -1116,7 +1159,7 @@ lws_destroy_event_pipe(struct lws *wsi) { int n; - lwsl_info("%s\n", __func__); + lwsl_wsi_info(wsi, "in"); n = lws_wsi_extract_from_loop(wsi); lws_plat_pipe_close(wsi); @@ -1165,7 +1208,7 @@ __lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh) if (w->tsi == tsi) { - lwsl_debug("%s: closing aso\n", __func__); + lwsl_vhost_debug(vh, "closing aso"); lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS, "awaiting skt"); } @@ -1183,8 +1226,8 @@ __lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh) if (wsi && wsi->tsi == tsi && wsi->a.vhost == vh) { - lwsl_debug("%s: pt %d: closing wsi %p: role %s\n", - __func__, tsi, wsi, wsi->role_ops->name); + lwsl_wsi_debug(wsi, "pt %d: closin, role %s", tsi, + wsi->role_ops->name); lws_wsi_close(wsi, LWS_TO_KILL_ASYNC); @@ -1200,6 +1243,38 @@ __lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh) #endif } +#if defined(LWS_WITH_NETWORK) + +/* returns nonzero if v1 and v2 can share listen sockets */ +int +lws_vhost_compare_listen(struct lws_vhost *v1, struct lws_vhost *v2) +{ + return ((!v1->iface && !v2->iface) || + (v1->iface && v2->iface && !strcmp(v1->iface, v2->iface))) && + v1->listen_port == v2->listen_port; +} + +/* helper to interate every listen socket on any vhost and call cb on it */ +int +lws_vhost_foreach_listen_wsi(struct lws_context *cx, void *arg, + lws_dll2_foreach_cb_t cb) +{ + struct lws_vhost *v = cx->vhost_list; + int n; + + while (v) { + + n = lws_dll2_foreach_safe(&v->listen_wsi, arg, cb); + if (n) + return n; + + v = v->vhost_next; + } + + return 0; +} + +#endif /* * Mark the vhost as being destroyed, so things trying to use it abort. @@ -1211,14 +1286,23 @@ void lws_vhost_destroy1(struct lws_vhost *vh) { struct lws_context *context = vh->context; + int n; - lwsl_info("%s\n", __func__); + lwsl_vhost_info(vh, "\n"); lws_context_lock(context, "vhost destroy 1"); /* ---------- context { */ if (vh->being_destroyed) goto out; + /* + * let's lock all the pts, to enforce pt->vh order... pt is refcounted + * so it's OK if we acquire it later inside this + */ + + for (n = 0; n < context->count_threads; n++) + lws_pt_lock((&context->pt[n]), __func__); + lws_vhost_lock(vh); /* -------------- vh { */ #if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_WITH_TLS) @@ -1229,12 +1313,12 @@ lws_vhost_destroy1(struct lws_vhost *vh) lws_dll2_add_tail(&vh->vh_being_destroyed_list, &context->owner_vh_being_destroyed); -#if defined(LWS_WITH_NETWORK) +#if defined(LWS_WITH_NETWORK) && defined(LWS_WITH_SERVER) /* * PHASE 1: take down or reassign any listen wsi * - * Are there other vhosts that are piggybacking on our listen socket? - * If so we need to hand the listen socket off to one of the others + * Are there other vhosts that are piggybacking on our listen sockets? + * If so we need to hand each listen socket off to one of the others * so it will remain open. * * If not, close the listen socket now. @@ -1243,15 +1327,21 @@ lws_vhost_destroy1(struct lws_vhost *vh) * immediately performed. */ - if (vh->lserv_wsi) { + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head(&vh->listen_wsi)) { + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + /* + * For each of our listen sockets, check every other vhost to + * see if another vhost should be given our listen socket. + * + * ipv4 and ipv6 sockets will both match and be migrated. + */ + lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) { - if (v != vh && - !v->being_destroyed && - v->listen_port == vh->listen_port && - ((!v->iface && !vh->iface) || - (v->iface && vh->iface && - !strcmp(v->iface, vh->iface)))) { + if (v != vh && !v->being_destroyed && + lws_vhost_compare_listen(v, vh)) { /* * this can only be a listen wsi, which is * restricted... it has no protocol or other @@ -1260,39 +1350,58 @@ lws_vhost_destroy1(struct lws_vhost *vh) * iface + port, but is not closing. */ - lwsl_notice("%s: listen skt migrate %s -> %s\n", - __func__, lws_vh_tag(vh), - lws_vh_tag(v)); + lwsl_vhost_notice(vh, "listen skt migrate -> %s", + lws_vh_tag(v)); - assert(v->lserv_wsi == NULL); - v->lserv_wsi = vh->lserv_wsi; - - if (v->lserv_wsi) { - /* req cx + vh lock */ - __lws_vhost_unbind_wsi(vh->lserv_wsi); - lws_vhost_bind_wsi(v, v->lserv_wsi); - vh->lserv_wsi = NULL; - } + lws_dll2_remove(&wsi->listen_list); + lws_dll2_add_tail(&wsi->listen_list, + &v->listen_wsi); + /* req cx + vh lock */ + /* + * If the vhost sees it's being destroyed and + * in the unbind the number of wsis bound to + * it falls to zero, it will destroy the + * vhost opportunistically before we can + * complete the transfer. Add a fake wsi + * bind temporarily to disallow this... + */ + v->count_bound_wsi++; + __lws_vhost_unbind_wsi(wsi); + lws_vhost_bind_wsi(v, wsi); + /* + * ... remove the fake wsi bind + */ + v->count_bound_wsi--; break; } } lws_end_foreach_ll(v, vhost_next); - if (vh->lserv_wsi) { - /* - * we didn't pass it off to another vhost on the same - * listen port... let's close it next time around the - * event loop without waiting for the logical destroy - * of the vhost itself - */ - lws_set_timeout(vh->lserv_wsi, 1, LWS_TO_KILL_ASYNC); - vh->lserv_wsi = NULL; - } - } + } lws_end_foreach_dll_safe(d, d1); + + /* + * If any listen wsi left we couldn't pass to other vhosts, close them + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head(&vh->listen_wsi)) { + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + lws_dll2_remove(&wsi->listen_list); + lws_wsi_close(wsi, LWS_TO_KILL_ASYNC); + + } lws_end_foreach_dll_safe(d, d1); + +#endif +#if defined(LWS_WITH_TLS_JIT_TRUST) + lws_sul_cancel(&vh->sul_unref); #endif lws_vhost_unlock(vh); /* } vh -------------- */ + for (n = 0; n < context->count_threads; n++) + lws_pt_unlock((&context->pt[n])); + out: lws_context_unlock(context); /* --------------------------- context { */ } @@ -1328,14 +1437,6 @@ __lws_vhost_destroy2(struct lws_vhost *vh) // lwsl_info("%s: %s\n", __func__, vh->name); -#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 */ @@ -1349,7 +1450,7 @@ __lws_vhost_destroy2(struct lws_vhost *vh) while (n < vh->count_protocols) { wsi.a.protocol = protocol; - lwsl_debug("%s: protocol destroy\n", __func__); + lwsl_vhost_debug(vh, "protocol destroy"); if (protocol->callback) protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY, @@ -1436,14 +1537,14 @@ __lws_vhost_destroy2(struct lws_vhost *vh) #endif #if LWS_MAX_SMP > 1 - lws_mutex_refcount_destroy(&context->mr); + lws_mutex_refcount_destroy(&vh->mr); #endif #if defined(LWS_WITH_UNIX_SOCK) if (LWS_UNIX_SOCK_ENABLED(vh)) { n = unlink(vh->iface); if (n) - lwsl_info("Closing unix socket %s: errno %d\n", + lwsl_vhost_info(vh, "Closing unix socket %s: errno %d\n", vh->iface, errno); } #endif @@ -1474,8 +1575,11 @@ __lws_vhost_destroy2(struct lws_vhost *vh) #if defined(LWS_WITH_SYS_FAULT_INJECTION) lws_fi_destroy(&vh->fic); #endif +#if defined(LWS_WITH_TLS_JIT_TRUST) + lws_sul_cancel(&vh->sul_unref); +#endif - __lws_lc_untag(&vh->lc); + __lws_lc_untag(vh->context, &vh->lc); memset(vh, 0, sizeof(*vh)); lws_free(vh); @@ -1520,7 +1624,7 @@ lws_vhost_destroy(struct lws_vhost *vh) /* start async closure of all wsi on this pt thread attached to vh */ __lws_vhost_destroy_pt_wsi_dieback_start(vh); - lwsl_info("%s: count_bound_wsi %d\n", __func__, vh->count_bound_wsi); + lwsl_vhost_info(vh, "count_bound_wsi %d", vh->count_bound_wsi); /* if there are none, finalize now since no further chance */ if (!vh->count_bound_wsi) { @@ -1561,44 +1665,40 @@ lws_get_vhost_listen_port(struct lws_vhost *vhost) #if defined(LWS_WITH_SERVER) void -lws_context_deprecate(struct lws_context *context, lws_reload_func cb) +lws_context_deprecate(struct lws_context *cx, lws_reload_func cb) { - struct lws_vhost *vh = context->vhost_list, *vh1; + struct lws_vhost *vh = cx->vhost_list; /* - * "deprecation" means disable the context from accepting any new + * "deprecation" means disable the cx from accepting any new * connections and free up listen sockets to be used by a replacement - * context. + * cx. * - * Otherwise the deprecated context remains operational, until its + * Otherwise the deprecated cx remains operational, until its * number of connected sockets falls to zero, when it is deleted. + * + * So, for each vhost, close his listen sockets */ - /* for each vhost, close his listen socket */ - while (vh) { - struct lws *wsi = vh->lserv_wsi; - if (wsi) { + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head(&vh->listen_wsi)) { + struct lws *wsi = lws_container_of(d, struct lws, + listen_list); + wsi->socket_is_permanently_unusable = 1; - lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "ctx deprecate"); - 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. - */ - vh1 = context->vhost_list; - while (vh1) { - if (vh1->lserv_wsi == wsi) - vh1->lserv_wsi = NULL; - vh1 = vh1->vhost_next; - } - } + lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, + __func__); + cx->deprecation_pending_listen_close_count++; + + } lws_end_foreach_dll_safe(d, d1); + vh = vh->vhost_next; } - context->deprecated = 1; - context->deprecation_cb = cb; + cx->deprecated = 1; + cx->deprecation_cb = cb; } #endif @@ -1680,9 +1780,11 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) struct lws *w = lws_container_of(d, struct lws, dll_cli_active_conns); - lwsl_debug("%s: check %s %s %s %s %d %d\n", __func__, - lws_wsi_tag(wsi), lws_wsi_tag(w), - adsin, w->cli_hostname_copy, wsi->c_port, w->c_port); + lwsl_wsi_debug(wsi, "check %s %s %s %d %d", + lws_wsi_tag(w), adsin, + w->cli_hostname_copy ? w->cli_hostname_copy : + "null", + wsi->c_port, w->c_port); if (w != wsi && /* @@ -1714,8 +1816,7 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) * connection that it doesn't support pipelining... */ if (w->keepalive_rejected) { - lwsl_notice("defeating pipelining due to no " - "keepalive on server\n"); + lwsl_wsi_notice(w, "defeating pipelining"); goto solo; } @@ -1729,13 +1830,11 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) lwsi_state(w) == LRS_ESTABLISHED || lwsi_state(w) == LRS_IDLING)) { - lwsl_notice("%s: just join h2 directly 0x%x\n", - __func__, lwsi_state(w)); + lwsl_wsi_notice(w, "just join h2 directly 0x%x", + lwsi_state(w)); - if (lwsi_state(w) == LRS_IDLING) { - // lwsi_set_state(w, LRS_ESTABLISHED); + if (lwsi_state(w) == LRS_IDLING) _lws_generic_transaction_completed_active_conn(&w, 0); - } //lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2); @@ -1760,7 +1859,7 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) lwsi_state(w) == LRS_ESTABLISHED) { if (lws_wsi_mqtt_adopt(w, wsi)) { - lwsl_notice("%s: join mqtt directly\n", __func__); + lwsl_wsi_notice(w, "join mqtt directly"); lws_dll2_remove(&wsi->dll2_cli_txn_queue); wsi->client_mux_substream = 1; @@ -1778,9 +1877,9 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) * to get there or fail. */ - lwsl_notice("%s: apply %s to txn queue on %s state 0x%lx\n", - __func__, lws_wsi_tag(wsi), lws_wsi_tag(w), - (unsigned long)w->wsistate); + lwsl_wsi_notice(wsi, "apply txn queue %s, state 0x%lx", + lws_wsi_tag(w), + (unsigned long)w->wsistate); /* * ...let's add ourselves to his transaction queue... * we are adding ourselves at the TAIL @@ -1788,10 +1887,8 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) lws_dll2_add_tail(&wsi->dll2_cli_txn_queue, &w->dll2_cli_txn_queue_owner); - if (lwsi_state(w) == LRS_IDLING) { - // lwsi_set_state(w, LRS_ESTABLISHED); + if (lwsi_state(w) == LRS_IDLING) _lws_generic_transaction_completed_active_conn(&w, 0); - } /* * For eg, h1 next we'd pipeline our headers out on him, @@ -1824,3 +1921,21 @@ lws_vh_tag(struct lws_vhost *vh) { return lws_lc_tag(&vh->lc); } + +struct lws_log_cx * +lwsl_vhost_get_cx(struct lws_vhost *vh) +{ + if (!vh) + return NULL; + + return vh->lc.log_cx; +} + +void +lws_log_prepend_vhost(struct lws_log_cx *cx, void *obj, char **p, char *e) +{ + struct lws_vhost *vh = (struct lws_vhost *)obj; + + *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", + lws_vh_tag(vh)); +} diff --git a/3rdparty/libwebsockets/lib/core-net/wsi-timeout.c b/3rdparty/libwebsockets/lib/core-net/wsi-timeout.c index 19da524f..b72f134f 100644 --- a/3rdparty/libwebsockets/lib/core-net/wsi-timeout.c +++ b/3rdparty/libwebsockets/lib/core-net/wsi-timeout.c @@ -27,16 +27,12 @@ void __lws_wsi_remove_from_sul(struct lws *wsi) { - //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); - - // lws_dll2_describe(&pt->pt_sul_owner, "pre-remove"); - lws_dll2_remove(&wsi->sul_timeout.list); - lws_dll2_remove(&wsi->sul_hrtimer.list); - lws_dll2_remove(&wsi->sul_validity.list); - // lws_dll2_describe(&pt->pt_sul_owner, "post-remove"); + lws_sul_cancel(&wsi->sul_timeout); + lws_sul_cancel(&wsi->sul_hrtimer); + lws_sul_cancel(&wsi->sul_validity); +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_sul_cancel(&wsi->sul_fault_timedclose); +#endif } /* @@ -86,19 +82,18 @@ lws_sul_wsitimeout_cb(lws_sorted_usec_list_t *sul) // if (wsi->pending_timeout != PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE) #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (wsi->pending_timeout != PENDING_TIMEOUT_USER_OK) - lwsl_info("%s: %s: TIMEDOUT WAITING on %d " - "(did hdr %d, ah %p, wl %d)\n", __func__, - lws_wsi_tag(wsi), wsi->pending_timeout, - wsi->hdr_parsing_completed, wsi->http.ah, - pt->http.ah_wait_list_length); + lwsl_wsi_info(wsi, "TIMEDOUT WAITING %d, dhdr %d, ah %p, wl %d", + wsi->pending_timeout, + wsi->hdr_parsing_completed, wsi->http.ah, + pt->http.ah_wait_list_length); #if defined(LWS_WITH_CGI) if (wsi->http.cgi) - lwsl_notice("CGI timeout: %s\n", wsi->http.cgi->summary); + lwsl_wsi_notice(wsi, "CGI timeout: %s", wsi->http.cgi->summary); #endif #else if (wsi->pending_timeout != PENDING_TIMEOUT_USER_OK) - lwsl_info("%s: %s: TIMEDOUT WAITING on %d ", __func__, - lws_wsi_tag(wsi), wsi->pending_timeout); + lwsl_wsi_info(wsi, "TIMEDOUT WAITING on %d ", + wsi->pending_timeout); #endif /* cgi timeout */ if (wsi->pending_timeout != PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE) @@ -114,6 +109,9 @@ lws_sul_wsitimeout_cb(lws_sorted_usec_list_t *sul) if (lwsi_state(wsi) == LRS_WAITING_SSL) lws_inform_client_conn_fail(wsi, (void *)"Timed out waiting SSL", 21); + if (lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY) + lws_inform_client_conn_fail(wsi, + (void *)"Timed out waiting server reply", 30); #endif lws_context_lock(cx, __func__); @@ -133,8 +131,7 @@ __lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) &wsi->sul_timeout, ((lws_usec_t)secs) * LWS_US_PER_SEC); - lwsl_debug("%s: %s: %d secs, reason %d\n", __func__, lws_wsi_tag(wsi), - secs, reason); + lwsl_wsi_debug(wsi, "%d secs, reason %d\n", secs, reason); wsi->pending_timeout = (char)reason; } @@ -153,7 +150,7 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) goto bail; if (secs == LWS_TO_KILL_SYNC) { - lwsl_debug("%s: TO_KILL_SYNC %s\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_debug(wsi, "TO_KILL_SYNC"); lws_context_unlock(pt->context); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "to sync kill"); @@ -165,7 +162,7 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) // assert(!secs || !wsi->mux_stream_immortal); if (secs && wsi->mux_stream_immortal) - lwsl_err("%s: on immortal stream %d %d\n", __func__, reason, secs); + lwsl_wsi_err(wsi, "on immortal stream %d %d", reason, secs); lws_pt_lock(pt, __func__); __lws_set_timeout(wsi, reason, secs); @@ -191,104 +188,13 @@ lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us) __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], &wsi->sul_timeout, us); - lwsl_notice("%s: %s: %llu us, reason %d\n", __func__, lws_wsi_tag(wsi), - (unsigned long long)us, reason); + lwsl_wsi_notice(wsi, "%llu us, reason %d", + (unsigned long long)us, reason); wsi->pending_timeout = (char)reason; lws_pt_unlock(pt); } -#if defined(LWS_WITH_DEPRECATED_THINGS) - -/* requires context + vh lock */ - -int -__lws_timed_callback_remove(struct lws_vhost *vh, struct lws_timed_vh_protocol *p) -{ - lws_start_foreach_llp_safe(struct lws_timed_vh_protocol **, pt, - vh->timed_vh_protocol_list, next) { - if (*pt == p) { - *pt = p->next; - lws_dll2_remove(&p->sul.list); - lws_free(p); - - return 0; - } - } lws_end_foreach_llp_safe(pt); - - return 1; -} - -void -lws_sul_timed_callback_vh_protocol_cb(lws_sorted_usec_list_t *sul) -{ - struct lws_timed_vh_protocol *tvp = lws_container_of(sul, - struct lws_timed_vh_protocol, sul); - lws_fakewsi_def_plwsa(&tvp->vhost->context->pt[0]); - - 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: %s, protocol %s, reason %d\n", __func__, - lws_vh_tag(tvp->vhost), tvp->protocol->name, tvp->reason); - - tvp->protocol->callback((struct lws *)plwsa, tvp->reason, NULL, NULL, 0); - - __lws_timed_callback_remove(tvp->vhost, tvp); -} - -int -lws_timed_callback_vh_protocol_us(struct lws_vhost *vh, - const struct lws_protocols *prot, int reason, - lws_usec_t us) -{ - struct lws_timed_vh_protocol *p = (struct lws_timed_vh_protocol *) - lws_malloc(sizeof(*p), "timed_vh"); - - if (!p) - return 1; - - memset(p, 0, sizeof(*p)); - - p->tsi_req = lws_pthread_self_to_tsi(vh->context); - if (p->tsi_req < 0) /* not called from a service thread --> tsi 0 */ - p->tsi_req = 0; - - lws_context_lock(vh->context, __func__); /* context ----------------- */ - - p->protocol = prot; - p->reason = reason; - p->vhost = vh; - - p->sul.cb = lws_sul_timed_callback_vh_protocol_cb; - /* list is always at the very top of the sul */ - __lws_sul_insert(&vh->context->pt[p->tsi_req].pt_sul_owner, - (lws_sorted_usec_list_t *)&p->sul.list, us); - - // lwsl_notice("%s: %s.%s %d\n", __func__, vh->name, prot->name, secs); - - lws_vhost_lock(vh); /* vhost ---------------------------------------- */ - p->next = vh->timed_vh_protocol_list; - vh->timed_vh_protocol_list = p; - lws_vhost_unlock(vh); /* -------------------------------------- vhost */ - - lws_context_unlock(vh->context); /* ------------------------- context */ - - return 0; -} - -int -lws_timed_callback_vh_protocol(struct lws_vhost *vh, - const struct lws_protocols *prot, int reason, - int secs) -{ - return lws_timed_callback_vh_protocol_us(vh, prot, reason, - ((lws_usec_t)secs) * LWS_US_PER_SEC); -} - -#endif - static void lws_validity_cb(lws_sorted_usec_list_t *sul) { @@ -299,15 +205,22 @@ lws_validity_cb(lws_sorted_usec_list_t *sul) /* one of either the ping or hangup validity threshold was crossed */ if (wsi->validity_hup) { - lwsl_info("%s: %s: validity too old\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "validity too old"); + struct lws_context *cx = wsi->a.context; + struct lws_context_per_thread *pt = &cx->pt[(int)wsi->tsi]; + + lws_context_lock(cx, __func__); + lws_pt_lock(pt, __func__); __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "validity timeout"); + lws_pt_unlock(pt); + lws_context_unlock(cx); return; } /* schedule a protocol-dependent ping */ - lwsl_info("%s: %s: scheduling validity check\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_info(wsi, "scheduling validity check"); if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_issue_keepalive)) lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_issue_keepalive). @@ -348,11 +261,10 @@ _lws_validity_confirmed_role(struct lws *wsi) wsi->validity_hup = rbo->secs_since_valid_ping >= rbo->secs_since_valid_hangup; - lwsl_info("%s: %s: setting validity timer %ds (hup %d)\n", - __func__, lws_wsi_tag(wsi), - wsi->validity_hup ? rbo->secs_since_valid_hangup : + lwsl_wsi_info(wsi, "setting validity timer %ds (hup %d)", + wsi->validity_hup ? rbo->secs_since_valid_hangup : rbo->secs_since_valid_ping, - wsi->validity_hup); + wsi->validity_hup); __lws_sul_insert_us(&pt->pt_sul_owner[!!wsi->conn_validity_wakesuspend], &wsi->sul_validity, diff --git a/3rdparty/libwebsockets/lib/core-net/wsi.c b/3rdparty/libwebsockets/lib/core-net/wsi.c index 85f5b6c7..978d1e80 100644 --- a/3rdparty/libwebsockets/lib/core-net/wsi.c +++ b/3rdparty/libwebsockets/lib/core-net/wsi.c @@ -37,30 +37,50 @@ void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role) { wsi->wsistate = (wsi->wsistate & (~LWSI_ROLE_MASK)) | role; - lwsl_debug("lwsi_set_role(%s, 0x%lx)\n", lws_wsi_tag(wsi), - (unsigned long)wsi->wsistate); + lwsl_wsi_debug(wsi, "state 0x%lx", (unsigned long)wsi->wsistate); } void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs) { - wsi->wsistate = (wsi->wsistate & (unsigned int)(~LRS_MASK)) | lrs; + lws_wsi_state_t old = wsi->wsistate; - lwsl_debug("lwsi_set_state(%s, 0x%lx)\n", lws_wsi_tag(wsi), - (unsigned long)wsi->wsistate); + wsi->wsistate = (old & (unsigned int)(~LRS_MASK)) | lrs; + + lwsl_wsi_debug(wsi, "lwsi_set_state 0x%lx -> 0x%lx", + (unsigned long)old, (unsigned long)wsi->wsistate); } #endif +void +lws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e) +{ + struct lws *wsi = (struct lws *)obj; + + *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", + lws_wsi_tag(wsi)); +} + void lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi) { if (wsi->a.vhost == vh) return; + lws_context_lock(vh->context, __func__); /* ---------- context { */ wsi->a.vhost = vh; + +#if defined(LWS_WITH_TLS_JIT_TRUST) + if (!vh->count_bound_wsi && vh->grace_after_unref) { + lwsl_wsi_info(wsi, "in use"); + lws_sul_cancel(&vh->sul_unref); + } +#endif + vh->count_bound_wsi++; lws_context_unlock(vh->context); /* } context ---------- */ - lwsl_debug("%s: vh %s: wsi %s/%s, count_bound_wsi %d\n", __func__, + + lwsl_wsi_debug(wsi, "vh %s: wsi %s/%s, count_bound_wsi %d\n", vh->name, wsi->role_ops ? wsi->role_ops->name : "none", wsi->a.protocol ? wsi->a.protocol->name : "none", vh->count_bound_wsi); @@ -72,20 +92,29 @@ lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi) void __lws_vhost_unbind_wsi(struct lws *wsi) { - if (!wsi->a.vhost) - return; + struct lws_vhost *vh = wsi->a.vhost; + + if (!vh) + return; lws_context_assert_lock_held(wsi->a.context); - lws_vhost_lock(wsi->a.vhost); + lws_vhost_lock(vh); - 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->a.vhost->name, wsi->a.vhost->count_bound_wsi); + assert(vh->count_bound_wsi > 0); + vh->count_bound_wsi--; + +#if defined(LWS_WITH_TLS_JIT_TRUST) + if (!vh->count_bound_wsi && vh->grace_after_unref) + lws_tls_jit_trust_vh_start_grace(vh); +#endif - if (!wsi->a.vhost->count_bound_wsi && - wsi->a.vhost->being_destroyed) { + lwsl_wsi_debug(wsi, "vh %s: count_bound_wsi %d", + vh->name, vh->count_bound_wsi); + + lws_vhost_unlock(vh); + + if (!vh->count_bound_wsi && vh->being_destroyed) /* * We have closed all wsi that were bound to this vhost * by any pt: nothing can be servicing any wsi belonging @@ -93,13 +122,8 @@ __lws_vhost_unbind_wsi(struct lws *wsi) * * Finalize the vh destruction... must drop vh lock */ - lws_vhost_unlock(wsi->a.vhost); - __lws_vhost_destroy2(wsi->a.vhost); - wsi->a.vhost = NULL; - return; - } + __lws_vhost_destroy2(vh); - lws_vhost_unlock(wsi->a.vhost); wsi->a.vhost = NULL; } @@ -161,6 +185,22 @@ lws_callback_all_protocol(struct lws_context *context, return 0; } +void * +lws_evlib_wsi_to_evlib_pt(struct lws *wsi) +{ + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + + return pt->evlib_pt; +} + +void * +lws_evlib_tsi_to_evlib_pt(struct lws_context *cx, int tsi) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; + + return pt->evlib_pt; +} + int lws_callback_all_protocol_vhost_args(struct lws_vhost *vh, const struct lws_protocols *protocol, int reason, @@ -206,13 +246,49 @@ lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, size_t len) return 0; } +#if defined(LWS_WITH_SYS_FAULT_INJECTION) +/* + * We want to inject a fault that makes it feel like the peer hung up on us, + * or we were otherwise cut off. + */ +void +lws_wsi_fault_timedclose_cb(lws_sorted_usec_list_t *s) +{ + struct lws *wsi = lws_container_of(s, struct lws, sul_fault_timedclose); + + lwsl_wsi_warn(wsi, "force-closing"); + lws_wsi_close(wsi, LWS_TO_KILL_ASYNC); +} +#endif + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) +void +lws_wsi_fault_timedclose(struct lws *wsi) +{ + uint64_t u; + + if (!lws_fi(&wsi->fic, "timedclose")) + return; + + if (lws_fi_range(&wsi->fic, "timedclose_ms", &u)) + return; + + lwsl_wsi_warn(wsi, "injecting close in %ums", (unsigned int)u); + lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_fault_timedclose, + lws_wsi_fault_timedclose_cb, + (lws_usec_t)(u * 1000ull)); +} +#endif + + /* * We need the context lock */ struct lws * __lws_wsi_create_with_role(struct lws_context *context, int tsi, - const struct lws_role_ops *ops) + const struct lws_role_ops *ops, + lws_log_cx_t *log_cx_template) { size_t s = sizeof(struct lws); struct lws *wsi; @@ -228,10 +304,15 @@ __lws_wsi_create_with_role(struct lws_context *context, int tsi, wsi = lws_zalloc(s, __func__); if (!wsi) { - lwsl_err("%s: Out of mem\n", __func__); + lwsl_cx_err(context, "OOM"); return NULL; } + if (log_cx_template) + wsi->lc.log_cx = log_cx_template; + else + wsi->lc.log_cx = context->log_cx; + #if defined(LWS_WITH_EVENT_LIBS) wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi); #endif @@ -244,9 +325,6 @@ __lws_wsi_create_with_role(struct lws_context *context, int tsi, wsi->desc.sockfd = LWS_SOCK_INVALID; wsi->position_in_fds_table = LWS_NO_FDS_POS; -// lwsl_debug("%s: tsi %d: role: %s\n", __func__, tsi, -// ops ? ops->name : "none"); - #if defined(LWS_WITH_SYS_FAULT_INJECTION) lws_xos_init(&wsi->fic.xos, lws_xos(&context->fic.xos)); #endif @@ -345,7 +423,7 @@ lws_rx_flow_control(struct lws *wsi, int _enable) lwsi_role_h2_ENCAPSULATION(wsi)) return 0; // !!! - lwsl_info("%s: %s 0x%x\n", __func__, lws_wsi_tag(wsi), _enable); + lwsl_wsi_info(wsi, "0x%x", _enable); if (!(_enable & LWS_RXFLOW_REASON_APPLIES)) { /* @@ -372,9 +450,8 @@ lws_rx_flow_control(struct lws *wsi, int _enable) wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | (!wsi->rxflow_bitmap); - lwsl_info("%s: %s: bitmap 0x%x: en 0x%x, ch 0x%x\n", __func__, - lws_wsi_tag(wsi), - wsi->rxflow_bitmap, en, wsi->rxflow_change_to); + lwsl_wsi_info(wsi, "bitmap 0x%x: en 0x%x, ch 0x%x", + wsi->rxflow_bitmap, en, wsi->rxflow_change_to); if (_enable & LWS_RXFLOW_REASON_FLAG_PROCESS_NOW || !wsi->rxflow_will_be_applied) { @@ -459,16 +536,16 @@ __lws_rx_flow_control(struct lws *wsi) wsi->rxflow_change_to &= (~LWS_RXFLOW_PENDING_CHANGE) & 3; - lwsl_info("rxflow: %s change_to %d\n", lws_wsi_tag(wsi), - wsi->rxflow_change_to & LWS_RXFLOW_ALLOW); + lwsl_wsi_info(wsi, "rxflow: change_to %d", + wsi->rxflow_change_to & LWS_RXFLOW_ALLOW); /* adjust the pollfd for this wsi */ if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) { - lwsl_info("%s: reenable POLLIN\n", __func__); + lwsl_wsi_info(wsi, "reenable POLLIN"); // lws_buflist_describe(&wsi->buflist, NULL, __func__); if (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_info("%s: fail\n", __func__); + lwsl_wsi_info(wsi, "fail"); return -1; } } else @@ -498,14 +575,13 @@ lws_ensure_user_space(struct lws *wsi) wsi->user_space = lws_zalloc( wsi->a.protocol->per_session_data_size, "user space"); if (wsi->user_space == NULL) { - lwsl_err("%s: OOM\n", __func__); + lwsl_wsi_err(wsi, "OOM"); return 1; } } else - lwsl_debug("%s: %s protocol pss %lu, user_space=%p\n", __func__, - lws_wsi_tag(wsi), - (long)wsi->a.protocol->per_session_data_size, - wsi->user_space); + lwsl_wsi_debug(wsi, "protocol pss %lu, user_space=%p", + (long)wsi->a.protocol->per_session_data_size, + wsi->user_space); return 0; } @@ -546,6 +622,24 @@ lws_get_ssl(struct lws *wsi) } #endif +int +lws_has_buffered_out(struct lws *wsi) +{ + if (wsi->buflist_out) + return 1; + +#if defined(LWS_ROLE_H2) + { + struct lws *nwsi = lws_get_network_wsi(wsi); + + if (nwsi->buflist_out) + return 1; + } +#endif + + return 0; +} + int lws_partial_buffered(struct lws *wsi) { @@ -575,8 +669,8 @@ lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state, #if (_LWS_ENABLED_LOGS & LLL_DEBUG) if (wsi->role_ops) name = wsi->role_ops->name; - lwsl_debug("%s: %s: wsistate 0x%lx, ops %s\n", __func__, - lws_wsi_tag(wsi), (unsigned long)wsi->wsistate, name); + lwsl_wsi_debug(wsi, "wsistate 0x%lx, ops %s", + (unsigned long)wsi->wsistate, name); #endif } @@ -921,6 +1015,15 @@ lws_get_context(const struct lws *wsi) return wsi->a.context; } +struct lws_log_cx * +lwsl_wsi_get_cx(struct lws *wsi) +{ + if (!wsi) + return NULL; + + return wsi->lc.log_cx; +} + #if defined(LWS_WITH_CLIENT) int _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_lock) @@ -957,7 +1060,7 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l * Nothing pipelined... we should hang around a bit * in case something turns up... otherwise we'll close */ - lwsl_info("%s: nothing pipelined waiting\n", __func__); + lwsl_wsi_info(wsi, "nothing pipelined waiting"); lwsi_set_state(wsi, LRS_IDLING); lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, @@ -1033,8 +1136,10 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l /* take over his copy of his endpoint as an active connection */ - wnew->cli_hostname_copy = wsi->cli_hostname_copy; - wsi->cli_hostname_copy = NULL; + if (!wnew->cli_hostname_copy && wsi->cli_hostname_copy) { + wnew->cli_hostname_copy = wsi->cli_hostname_copy; + wsi->cli_hostname_copy = NULL; + } wnew->keep_warm_secs = wsi->keep_warm_secs; /* @@ -1074,8 +1179,7 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l /* after the first one, they can only be coming from the queue */ wnew->transaction_from_pipeline_queue = 1; - lwsl_notice("%s: pipeline queue passed %s on to queued %s\n", - __func__, lws_wsi_tag(wsi), lws_wsi_tag(wnew)); + lwsl_wsi_notice(wsi, " pipeline queue passed -> %s", lws_wsi_tag(wnew)); *_wsi = wnew; /* inform caller we swapped */ @@ -1095,8 +1199,8 @@ lws_raw_transaction_completed(struct lws *wsi) * Defer the close until the last part of the partial is sent. * */ - lwsl_debug("%s: %s: deferring due to partial\n", __func__, - lws_wsi_tag(wsi)); + + lwsl_wsi_debug(wsi, "deferring due to partial"); wsi->close_when_buffered_out_drained = 1; lws_callback_on_writable(wsi); @@ -1175,8 +1279,8 @@ lws_http_close_immortal(struct lws *wsi) wsi->mux_stream_immortal = 0; nwsi = lws_get_network_wsi(wsi); - lwsl_debug("%s: %s %s %d\n", __func__, lws_wsi_tag(wsi), lws_wsi_tag(nwsi), - nwsi->immortal_substream_count); + lwsl_wsi_debug(wsi, "%s (%d)", lws_wsi_tag(nwsi), + nwsi->immortal_substream_count); assert(nwsi->immortal_substream_count); nwsi->immortal_substream_count--; if (!nwsi->immortal_substream_count) @@ -1201,16 +1305,20 @@ lws_mux_mark_immortal(struct lws *wsi) && !wsi->client_mux_substream #endif ) { - lwsl_err("%s: not h2 substream\n", __func__); + lwsl_wsi_err(wsi, "not mux substream"); return; } + if (wsi->mux_stream_immortal) + /* only need to handle it once per child wsi */ + return; + nwsi = lws_get_network_wsi(wsi); if (!nwsi) return; - lwsl_debug("%s: %s %s %d\n", __func__, lws_wsi_tag(wsi), lws_wsi_tag(nwsi), - nwsi->immortal_substream_count); + lwsl_wsi_debug(wsi, "%s (%d)\n", lws_wsi_tag(nwsi), + nwsi->immortal_substream_count); wsi->mux_stream_immortal = 1; assert(nwsi->immortal_substream_count < 255); /* largest count */ @@ -1219,21 +1327,6 @@ lws_mux_mark_immortal(struct lws *wsi) lws_set_timeout(nwsi, NO_PENDING_TIMEOUT, 0); } -int -lws_tls_session_is_reused(struct lws *wsi) -{ -#if defined(LWS_WITH_CLIENT) - struct lws *nwsi = lws_get_network_wsi(wsi); - - if (!nwsi) - return 0; - - return nwsi->tls_session_reused; -#else - return 0; -#endif -} - int lws_http_mark_sse(struct lws *wsi) { @@ -1272,8 +1365,8 @@ lws_wsi_client_stash_item(struct lws *wsi, int stash_idx, int hdr_idx) void lws_wsi_mux_insert(struct lws *wsi, struct lws *parent_wsi, unsigned int sid) { - lwsl_info("%s: %s, par %s: assign sid %d (curr %d)\n", __func__, - lws_wsi_tag(wsi), lws_wsi_tag(parent_wsi), sid, wsi->mux.my_sid); + lwsl_wsi_info(wsi, "par %s: assign sid %d (curr %d)", + lws_wsi_tag(parent_wsi), sid, wsi->mux.my_sid); if (wsi->mux.my_sid && wsi->mux.my_sid != (unsigned int)sid) assert(0); @@ -1311,9 +1404,9 @@ lws_wsi_mux_dump_children(struct lws *wsi) lws_start_foreach_llp(struct lws **, w, wsi->mux.parent_wsi->mux.child_list) { - lwsl_info(" \\---- child %s %s\n", - (*w)->role_ops ? (*w)->role_ops->name : "?", - lws_wsi_tag(*w)); + lwsl_wsi_info(wsi, " \\---- child %s %s\n", + (*w)->role_ops ? (*w)->role_ops->name : "?", + lws_wsi_tag(*w)); assert(*w != (*w)->mux.sibling_list); } lws_end_foreach_llp(w, mux.sibling_list); #endif @@ -1330,7 +1423,7 @@ lws_wsi_mux_close_children(struct lws *wsi, int reason) w = &wsi->mux.child_list; while (*w) { - lwsl_info(" closing child %s\n", lws_wsi_tag(*w)); + lwsl_wsi_info((*w), " closing child"); /* disconnect from siblings */ wsi2 = (*w)->mux.sibling_list; assert (wsi2 != *w); @@ -1355,8 +1448,8 @@ lws_wsi_mux_sibling_disconnect(struct lws *wsi) wsi2 = (*w)->mux.sibling_list; (*w)->mux.sibling_list = NULL; *w = wsi2; - lwsl_debug(" %s disentangled from sibling %s\n", - lws_wsi_tag(wsi), lws_wsi_tag(wsi2)); + lwsl_wsi_debug(wsi, " disentangled from sibling %s", + lws_wsi_tag(wsi2)); break; } } lws_end_foreach_llp(w, mux.sibling_list); @@ -1374,9 +1467,9 @@ lws_wsi_mux_dump_waiting_children(struct lws *wsi) wsi = wsi->mux.child_list; while (wsi) { - lwsl_info(" %c %s: sid %u: 0x%x %s %s\n", + lwsl_wsi_info(wsi, " %c sid %u: 0x%x %s %s", wsi->mux.requested_POLLOUT ? '*' : ' ', - lws_wsi_tag(wsi), wsi->mux.my_sid, lwsi_state(wsi), + wsi->mux.my_sid, lwsi_state(wsi), wsi->role_ops->name, wsi->a.protocol ? wsi->a.protocol->name : "noprotocol"); @@ -1396,8 +1489,8 @@ lws_wsi_mux_mark_parents_needing_writeable(struct lws *wsi) wsi2 = wsi; while (wsi2) { wsi2->mux.requested_POLLOUT = 1; - lwsl_info("%s: mark: %s, sid %u, pending writable\n", - __func__, lws_wsi_tag(wsi2), wsi2->mux.my_sid); + lwsl_wsi_info(wsi2, "sid %u, pending writable", + wsi2->mux.my_sid); wsi2 = wsi2->mux.parent_wsi; } @@ -1411,8 +1504,7 @@ lws_wsi_mux_move_child_to_tail(struct lws **wsi2) while (w) { if (!w->mux.sibling_list) { /* w is the current last */ - lwsl_debug("w=%s, *wsi2 = %s\n", lws_wsi_tag(w), - lws_wsi_tag(*wsi2)); + lwsl_wsi_debug(w, "*wsi2 = %s\n", lws_wsi_tag(*wsi2)); if (w == *wsi2) /* we are already last */ break; @@ -1548,8 +1640,7 @@ lws_wsi_mux_apply_queue(struct lws *wsi) #if defined(LWS_ROLE_H2) if (lwsi_role_http(wsi) && lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS) { - lwsl_info("%s: cli pipeq %s to be h2\n", __func__, - lws_wsi_tag(w)); + lwsl_wsi_info(w, "cli pipeq to be h2"); lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2); @@ -1564,8 +1655,7 @@ lws_wsi_mux_apply_queue(struct lws *wsi) #if defined(LWS_ROLE_MQTT) if (lwsi_role_mqtt(wsi) && lwsi_state(wsi) == LRS_ESTABLISHED) { - lwsl_info("%s: cli pipeq %s to be mqtt\n", __func__, - lws_wsi_tag(w)); + lwsl_wsi_info(w, "cli pipeq to be mqtt\n"); /* remove ourselves from client queue */ lws_dll2_remove(&w->dll2_cli_txn_queue); diff --git a/3rdparty/libwebsockets/lib/core/CMakeLists.txt b/3rdparty/libwebsockets/lib/core/CMakeLists.txt index 75bec6c3..dc647942 100644 --- a/3rdparty/libwebsockets/lib/core/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/core/CMakeLists.txt @@ -29,6 +29,7 @@ list(APPEND SOURCES core/buflist.c core/context.c core/lws_dll2.c + core/lws_map.c core/libwebsockets.c core/logs.c ) diff --git a/3rdparty/libwebsockets/lib/core/context.c b/3rdparty/libwebsockets/lib/core/context.c index 162a1bce..af818ebe 100644 --- a/3rdparty/libwebsockets/lib/core/context.c +++ b/3rdparty/libwebsockets/lib/core/context.c @@ -30,6 +30,10 @@ static const char *library_version = LWS_LIBRARY_VERSION; +#if defined(LWS_WITH_MBEDTLS) +extern const char *mbedtls_client_preload_filepath; +#endif + #if defined(LWS_HAVE_SYS_RESOURCE_H) /* for setrlimit */ #include @@ -71,7 +75,8 @@ static const char * system_state_names[] = { "AUTH1", "AUTH2", "OPERATIONAL", - "POLICY_INVALID" + "POLICY_INVALID", + "DESTROYING" }; @@ -130,8 +135,10 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, * us to OPERATIONAL */ - if (target == LWS_SYSTATE_IFACE_COLDPLUG && !context->nl_initial_done) { - lwsl_info("%s: waiting for netlink coldplug\n", __func__); + if (target == LWS_SYSTATE_IFACE_COLDPLUG && + context->netlink && + !context->nl_initial_done) { + lwsl_cx_info(context, "waiting for netlink coldplug"); return 1; } @@ -152,8 +159,8 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, 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__); + lwsl_cx_info(context, + "AUTH1 state triggering api.amazon.com auth"); /* * Start trying to acquire it if it's not already in progress * returns nonzero if we determine it's not needed @@ -191,7 +198,7 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, if (context->hss_fetch_policy) return 1; - lwsl_debug("%s: starting policy fetch\n", __func__); + lwsl_cx_debug(context, "starting policy fetch"); /* * Start trying to acquire it if it's not already in progress * returns nonzero if we determine it's not needed @@ -215,7 +222,7 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, if (target != LWS_SYSTATE_POLICY_VALID) return 0; - lwsl_info("%s: doing protocol init on POLICY_VALID\n", __func__); + lwsl_cx_info(context, "doing protocol init on POLICY_VALID\n"); return lws_protocol_init(context); } @@ -380,6 +387,9 @@ lws_create_context(const struct lws_context_creation_info *info) unsigned short count_threads = 1; uint8_t *u; uint16_t us_wait_resolution = 0; +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + struct lws_cache_creation_info ci; +#endif #if defined(__ANDROID__) struct rlimit rt; @@ -406,6 +416,7 @@ lws_create_context(const struct lws_context_creation_info *info) char fatal_exit_defer = 0; #endif + if (lws_fi(&info->fic, "ctx_createfail1")) goto early_bail; @@ -422,8 +433,6 @@ lws_create_context(const struct lws_context_creation_info *info) #endif } - lwsl_notice("LWS: %s, loglevel %d\n", library_version, log_level); - #if defined(LWS_WITH_IPV6) && !defined(LWS_WITH_NO_LOGS) if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6)) s = "IPV6-on"; @@ -431,8 +440,6 @@ lws_create_context(const struct lws_context_creation_info *info) s = "IPV6-off"; #endif - lwsl_notice("%s%s\n", opts_str, s); - if (lws_plat_context_early_init()) goto early_bail; @@ -452,8 +459,12 @@ lws_create_context(const struct lws_context_creation_info *info) size += (count_threads * sizeof(struct lws)); #endif + if (info->event_lib_custom) { + plev = info->event_lib_custom; + us_wait_resolution = 0; + } #if defined(LWS_WITH_POLL) - { + else { extern const lws_plugin_evlib_t evlib_poll; plev = &evlib_poll; #if !defined(LWS_PLAT_FREERTOS) @@ -587,8 +598,6 @@ lws_create_context(const struct lws_context_creation_info *info) #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"); @@ -596,13 +605,25 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_SYS_FAULT_INJECTION) lws_free(context); #endif - lwsl_err("No memory for lws_context\n"); + lwsl_err("OOM"); goto early_bail; } #if defined(LWS_WITH_NETWORK) context->event_loop_ops = plev->ops; context->us_wait_resolution = us_wait_resolution; +#if defined(LWS_WITH_TLS_JIT_TRUST) + { + struct lws_cache_creation_info ci; + + memset(&ci, 0, sizeof(ci)); + ci.cx = context; + ci.ops = &lws_cache_ops_heap; + ci.name = "jitt"; + ci.max_footprint = info->jitt_cache_max_footprint; + context->trust_cache = lws_cache_create(&ci); + } +#endif #endif #if defined(LWS_WITH_EVENT_LIBS) /* at the very end */ @@ -619,8 +640,20 @@ lws_create_context(const struct lws_context_creation_info *info) context->username = info->username; context->groupname = info->groupname; #endif + context->name = info->vhost_name; + if (info->log_cx) + context->log_cx = info->log_cx; + else + context->log_cx = &log_cx; + lwsl_refcount_cx(context->log_cx, 1); + context->system_ops = info->system_ops; context->pt_serv_buf_size = (unsigned int)s1; + context->protocols_copy = info->protocols; +#if defined(LWS_WITH_TLS_JIT_TRUST) + context->vh_idle_grace_ms = info->vh_idle_grace_ms ? + info->vh_idle_grace_ms : 5000; +#endif #if defined(LWS_WITH_SYS_FAULT_INJECTION) context->fic.name = "ctx"; @@ -640,12 +673,12 @@ lws_create_context(const struct lws_context_creation_info *info) #else 2000000; #endif - context->smd_queue_depth = info->smd_queue_depth ? + context->smd_queue_depth = (uint16_t)(info->smd_queue_depth ? info->smd_queue_depth : #if defined(LWS_PLAT_FREERTOS) - 20; + 20); #else - 40; + 40); #endif #endif @@ -655,7 +688,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->lcg[LWSLCG_WSI_SERVER].tag_prefix = "wsisrv"; /* adopted */ #if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) - context->lcg[LWSLCG_WSI_MUX].tag_prefix = "mux", /* a mux child wsi */ + context->lcg[LWSLCG_WSI_MUX].tag_prefix = "mux"; /* a mux child wsi */ #endif #if defined(LWS_WITH_CLIENT) @@ -749,6 +782,11 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ + lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); +#if defined(LWS_WITH_NETWORK) + lwsl_cx_info(context, "Event loop: %s", plev->ops->name); +#endif + /* * Proxy group */ @@ -779,8 +817,8 @@ lws_create_context(const struct lws_context_creation_info *info) context->ss_proxy_port = info->ss_proxy_port; context->ss_proxy_address = info->ss_proxy_address; 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, + lwsl_cx_notice(context, "ss proxy bind '%s', port %d, ads '%s'", + context->ss_proxy_bind, context->ss_proxy_port, context->ss_proxy_address); #endif @@ -790,7 +828,7 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_ROLE_WS) && defined(LWS_WITHOUT_EXTENSIONS) if (info->extensions) - lwsl_warn("%s: LWS_WITHOUT_EXTENSIONS but extensions ptr set\n", __func__); + lwsl_cx_warn(context, "WITHOUT_EXTENSIONS but exts ptr set"); #endif #endif /* network */ @@ -811,6 +849,8 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) #if defined(LWS_WITH_MBEDTLS) context->tls_ops = &tls_ops_mbedtls; + + mbedtls_client_preload_filepath = info->mbedtls_client_preload_filepath; #else context->tls_ops = &tls_ops_openssl; #endif @@ -875,6 +915,8 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) context->simultaneous_ssl_restriction = info->simultaneous_ssl_restriction; + context->simultaneous_ssl_handshake_restriction = + info->simultaneous_ssl_handshake_restriction; #endif context->options = info->options; @@ -897,13 +939,14 @@ lws_create_context(const struct lws_context_creation_info *info) #ifndef LWS_NO_DAEMONIZE if (pid_daemon) { context->started_with_parent = pid_daemon; - lwsl_info(" Started with daemon pid %u\n", (unsigned int)pid_daemon); + lwsl_cx_info(context, " Started with daemon pid %u", + (unsigned int)pid_daemon); } #endif #if defined(__ANDROID__) n = getrlimit(RLIMIT_NOFILE, &rt); if (n == -1) { - lwsl_err("Get RLIMIT_NOFILE failed!\n"); + lwsl_cx_err(context, "Get RLIMIT_NOFILE failed!"); goto free_context_fail2; } @@ -918,8 +961,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->max_fds = 2560; if (l > 10000000) - lwsl_warn("%s: unreasonable ulimit -n workaround\n", - __func__); + lwsl_cx_warn(context, "unreasonable ulimit -n workaround"); else if (l != -1l) context->max_fds = (unsigned int)l; @@ -927,8 +969,7 @@ lws_create_context(const struct lws_context_creation_info *info) #endif if ((int)context->max_fds < 0 || lws_fi(&context->fic, "ctx_createfail_maxfds")) { - lwsl_err("%s: problem getting process max files\n", - __func__); + lwsl_cx_err(context, "problem getting process max files"); goto free_context_fail2; } @@ -1018,7 +1059,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (!lws_smd_register(context, context, 0, LWSSMDCL_NETWORK, lws_system_smd_cb)) { - lwsl_err("%s: early smd register failed\n", __func__); + lwsl_cx_err(context, "early smd register failed"); } /* user smd participant */ @@ -1027,7 +1068,7 @@ lws_create_context(const struct lws_context_creation_info *info) !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__); + lwsl_cx_err(context, "early smd register failed"); } #endif @@ -1076,10 +1117,8 @@ lws_create_context(const struct lws_context_creation_info *info) 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; @@ -1099,7 +1138,7 @@ lws_create_context(const struct lws_context_creation_info *info) } if (!info->ka_interval && info->ka_time > 0) { - lwsl_err("info->ka_interval can't be 0 if ka_time used\n"); + lwsl_cx_err(context, "info->ka_interval can't be 0 if ka_time used"); goto free_context_fail; } @@ -1131,13 +1170,13 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_SYS_FAULT_INJECTION) lws_free(context->pt[0].fds); #endif - lwsl_err("OOM allocating %d fds\n", context->max_fds); + lwsl_cx_err(context, "OOM allocating %d fds\n", context->max_fds); goto free_context_fail; } #endif - lwsl_info(" ctx: %5luB (%ld ctx + pt(%ld thr x %d)), " - "pt-fds: %d, fdmap: %d\n", + lwsl_cx_info(context, "ctx: %5luB (%ld ctx + pt(%ld thr x %d)), " + "pt-fds: %d, fdmap: %d", (long)sizeof(struct lws_context) + (context->count_threads * context->pt_serv_buf_size), (long)sizeof(struct lws_context), @@ -1146,7 +1185,7 @@ lws_create_context(const struct lws_context_creation_info *info) 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", + lwsl_cx_info(context, " http: ah_data: %u, ah: %lu, max count %u", context->max_http_header_data, (long)sizeof(struct allocated_headers), context->max_http_header_pool); @@ -1216,7 +1255,7 @@ lws_create_context(const struct lws_context_creation_info *info) } #endif - lws_context_init_ssl_library(info); + lws_context_init_ssl_library(context, info); context->user_space = info->user; @@ -1277,8 +1316,7 @@ lws_create_context(const struct lws_context_creation_info *info) else vh = lws_create_vhost(context, &ii); if (!vh) { - lwsl_err("%s: failed to create system vhost\n", - __func__); + lwsl_cx_err(context, "failed to create system vhost"); goto bail_libuv_aware; } @@ -1286,7 +1324,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (lws_protocol_init_vhost(vh, NULL) || lws_fi(&context->fic, "ctx_createfail_sys_vh_init")) { - lwsl_err("%s: failed to init system vhost\n", __func__); + lwsl_cx_err(context, "failed to init system vhost"); goto bail_libuv_aware; } #if defined(LWS_WITH_SYS_ASYNC_DNS) @@ -1333,7 +1371,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) { if (!lws_create_vhost(context, info) || lws_fi(&context->fic, "ctx_createfail_def_vh")) { - lwsl_err("Failed to create default vhost\n"); + lwsl_cx_err(context, "Failed to create default vhost"); #if defined(LWS_WITH_PEER_LIMITS) lws_free_set_NULL(context->pl_hash_table); @@ -1342,6 +1380,34 @@ lws_create_context(const struct lws_context_creation_info *info) } } +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + if (info->http_nsc_filepath) { + memset(&ci, 0, sizeof(ci)); + + ci.cx = context; + ci.ops = &lws_cache_ops_nscookiejar; + ci.name = "NSC"; + ci.u.nscookiejar.filepath = info->http_nsc_filepath; + + context->nsc = lws_cache_create(&ci); + if (!context->nsc) + goto bail; + + ci.ops = &lws_cache_ops_heap; + ci.name = "L1"; + ci.parent = context->nsc; + ci.max_footprint = info->http_nsc_heap_max_footprint; + ci.max_items = info->http_nsc_heap_max_items; + ci.max_payload = info->http_nsc_heap_max_payload; + + context->l1 = lws_cache_create(&ci); + if (!context->l1) { + lwsl_cx_err(context, "Failed to init cookiejar"); + goto bail; + } + } +#endif + #if defined(LWS_WITH_SECURE_STREAMS) #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) @@ -1372,27 +1438,26 @@ lws_create_context(const struct lws_context_creation_info *info) if (lws_ss_policy_set(context, "hardcoded") || lws_fi(&context->fic, "ctx_createfail_ss_pol3")) { - lwsl_err("%s: policy set failed\n", __func__); + lwsl_cx_err(context, "policy set failed"); goto bail_libuv_aware; } - } else + } #else if (context->pss_policies) { /* user code set the policy objects directly, no parsing step */ if (lws_ss_policy_set(context, "hardcoded") || lws_fi(&context->fic, "ctx_createfail_ss_pol3")) { - lwsl_err("%s: policy set failed\n", __func__); + lwsl_cx_err(context, "policy set failed"); goto bail_libuv_aware; } - } //else + } #endif - // lws_create_vhost(context, info); #endif lws_context_init_extensions(info, context); - lwsl_info(" mem: per-conn: %5lu bytes + protocol rx buf\n", + lwsl_cx_info(context, " mem: per-conn: %5lu bytes + protocol rx buf", (unsigned long)sizeof(struct lws)); /* @@ -1430,28 +1495,6 @@ lws_create_context(const struct lws_context_creation_info *info) return NULL; -#if 0 -#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); - - lws_free_set_NULL(context->pt[0].fds); - lws_plat_context_late_destroy(context); - lws_free_set_NULL(context); - - return NULL; -#endif -#endif - #if defined(LWS_WITH_NETWORK) bail: lws_fi_destroy(&info->fic); @@ -1470,7 +1513,8 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_NETWORK) fail_event_libs: - lwsl_err("Requested event library support not configured\n"); + if (context) + lwsl_cx_err(context, "Requested event library support not configured"); #endif #if defined(LWS_WITH_NETWORK) @@ -1489,7 +1533,10 @@ lws_create_context(const struct lws_context_creation_info *info) lws_fi_destroy(&context->fic); } lws_fi_destroy(&info->fic); - lws_free(context); + if (context) { + lwsl_refcount_cx(context->log_cx, -1); + lws_free(context); + } return NULL; } @@ -1543,7 +1590,7 @@ lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) return; #if !defined(LWS_WITH_NO_LOGS) - lwsl_notice("%s: setting CPD result %s\n", __func__, cname[result]); + lwsl_cx_notice(cx, "setting CPD result %s", cname[result]); #endif cx->captive_portal_detect = (uint8_t)result; @@ -1623,11 +1670,25 @@ lws_pt_destroy(struct lws_context_per_thread *pt) vpt->foreign_pfd_list = NULL; lws_pt_lock(pt, __func__); + if (pt->pipe_wsi) { lws_destroy_event_pipe(pt->pipe_wsi); pt->pipe_wsi = NULL; } + if (pt->dummy_pipe_fds[0] +#if !defined(WIN32) + && (int)pt->dummy_pipe_fds[0] != -1 +#endif + ) { + struct lws wsi; + + memset(&wsi, 0, sizeof(wsi)); + wsi.a.context = pt->context; + wsi.tsi = (char)pt->tid; + lws_plat_pipe_close(&wsi); + } + #if defined(LWS_WITH_SECURE_STREAMS) lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll); @@ -1711,7 +1772,7 @@ lws_context_destroy(struct lws_context *context) lws_context_lock(context, __func__); context->inside_context_destroy = 1; - lwsl_info("%s: destroy_state %d\n", __func__, context->destroy_state); + lwsl_cx_info(context, "destroy_state %d", context->destroy_state); switch (context->destroy_state) { case LWSCD_NO_DESTROY: @@ -1719,7 +1780,7 @@ lws_context_destroy(struct lws_context *context) * We're getting started */ - lwsl_info("%s: starting context destroy flow\n", __func__); + lwsl_cx_info(context, "starting context destroy flow"); context->being_destroyed = 1; #if defined(LWS_WITH_NETWORK) @@ -1737,7 +1798,7 @@ lws_context_destroy(struct lws_context *context) vh = context->vhost_list; while (vh) { - lwsl_info("%s: vh %s start close\n", __func__, vh->name); + lwsl_vhost_info(vh, "start close"); vh1 = vh->vhost_next; lws_vhost_destroy1(vh); vh = vh1; @@ -1788,8 +1849,9 @@ lws_context_destroy(struct lws_context *context) if (wsi) { - lwsl_debug("%s: pt %d: closing wsi %p: role %s\n", - __func__, n, wsi, wsi->role_ops->name); + lwsl_cx_debug(context, + "pt %d: closing wsi %p: role %s", + n, wsi, wsi->role_ops->name); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY, @@ -1814,8 +1876,8 @@ lws_context_destroy(struct lws_context *context) */ if (context->event_loop_ops->destroy_pt) { - lwsl_info("%s: calling evlib destroy_pt %d\n", - __func__, n); + lwsl_cx_info(context, + "calling evlib destroy_pt %d\n", n); context->event_loop_ops->destroy_pt(context, n); } @@ -1827,7 +1889,7 @@ lws_context_destroy(struct lws_context *context) if (deferred_pt) { context->destroy_state = LWSCD_PT_WAS_DEFERRED; - lwsl_notice("%s: destroy from inside service\n", __func__); + lwsl_cx_notice(context, "destroy from inside service"); lws_cancel_service(context); goto bail; } @@ -1855,8 +1917,7 @@ lws_context_destroy(struct lws_context *context) #if defined(LWS_WITH_NETWORK) if (context->event_loop_ops->destroy_context1) { - lwsl_info("%s: do evlib destroy_context1 and wait\n", - __func__); + lwsl_cx_info(context, "do evlib destroy_context1 and wait"); context->event_loop_ops->destroy_context1(context); goto bail; @@ -1867,7 +1928,7 @@ lws_context_destroy(struct lws_context *context) * now ourselves... */ - lwsl_info("%s: manually destroying pts\n", __func__); + lwsl_cx_info(context, "manually destroying pts"); pt = context->pt; for (n = 0; n < context->count_threads; n++, pt++) { @@ -1886,8 +1947,7 @@ lws_context_destroy(struct lws_context *context) !context->pt[n].event_loop_pt_unused) alive++; - lwsl_info("%s: PT_WAIT_ALL_DESTROYED: %d alive\n", __func__, - alive); + lwsl_cx_info(context, "PT_WAIT_ALL_DESTROYED: %d alive", alive); if (alive) break; @@ -1931,7 +1991,7 @@ lws_context_destroy(struct lws_context *context) vh = context->vhost_list; while (vh) { vh1 = vh->vhost_next; - // lwsl_debug("%s: vh %s destroy2\n", __func__, vh->name); + // lwsl_vhost_debug(vh, "vh %s destroy2", vh->name); __lws_vhost_destroy2(vh); vh = vh1; } @@ -1941,8 +2001,6 @@ lws_context_destroy(struct lws_context *context) while (context->vhost_pending_destruction_list) /* removes itself from list */ __lws_vhost_destroy2(context->vhost_pending_destruction_list); - - lwsl_debug("%p: post pdl\n", __func__); #endif #if defined(LWS_WITH_NETWORK) @@ -1951,15 +2009,18 @@ lws_context_destroy(struct lws_context *context) lws_plat_context_late_destroy(context); #if defined(LWS_WITH_PEER_LIMITS) - for (nu = 0; nu < context->pl_hash_elements; nu++) { - lws_start_foreach_llp(struct lws_peer **, peer, - context->pl_hash_table[nu]) { - struct lws_peer *df = *peer; - *peer = df->next; - lws_free(df); - continue; - } lws_end_foreach_llp(peer, next); - } + if (context->pl_hash_table) + for (nu = 0; nu < context->pl_hash_elements; nu++) { + if (!context->pl_hash_table[nu]) + continue; + lws_start_foreach_llp(struct lws_peer **, peer, + context->pl_hash_table[nu]) { + struct lws_peer *df = *peer; + *peer = df->next; + lws_free(df); + continue; + } lws_end_foreach_llp(peer, next); + } lws_free(context->pl_hash_table); #endif @@ -1989,7 +2050,7 @@ lws_context_destroy(struct lws_context *context) while (pt->http.ah_list) _lws_destroy_ah(pt, pt->http.ah_list); #endif - lwsl_info("%s: pt destroy %d\n", __func__, n); + lwsl_cx_info(context, "pt destroy %d", n); lws_pt_destroy(pt); } #endif /* NETWORK */ @@ -2001,18 +2062,20 @@ lws_context_destroy(struct lws_context *context) if (context->pt[0].event_loop_foreign && context->event_loop_ops->destroy_context1) { - lwsl_info("%s: leaving final context destruction" - " for final call\n", __func__); + lwsl_cx_info(context, + "leaving final context destruction" + " for final call"); goto bail; } if (context->event_loop_ops->destroy_context1 && !context->pt[0].event_loop_foreign) { - lwsl_notice("%s: waiting for internal loop exit\n", __func__); + lwsl_cx_notice(context, "waiting for internal loop exit"); goto bail; } #endif + /* fallthru */ case LWSCD_FINALIZATION: @@ -2025,7 +2088,10 @@ lws_context_destroy(struct lws_context *context) #if defined(LWS_WITH_NETWORK) if (context->event_loop_ops->destroy_context2) context->event_loop_ops->destroy_context2(context); - +#if defined(LWS_WITH_SYS_STATE) + lws_state_transition_steps(&context->mgr_system, + LWS_SYSTATE_CONTEXT_DESTROYING); +#endif /* * finalize destroy of pt and things hanging off it */ @@ -2053,7 +2119,7 @@ lws_context_destroy(struct lws_context *context) pt->destroy_self = 0; pt->is_destroyed = 1; - lwsl_info("%s: pt %d fully destroyed\n", __func__, + lwsl_cx_info(context, "pt %d fully destroyed", (int)(pt - pt->context->pt)); } @@ -2063,6 +2129,16 @@ lws_context_destroy(struct lws_context *context) * clean up the context and things hanging off it */ +#if defined(LWS_WITH_TLS_JIT_TRUST) + lws_cache_destroy(&context->trust_cache); + lws_tls_jit_trust_inflight_destroy_all(context); +#endif + +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + lws_cache_destroy(&context->nsc); + lws_cache_destroy(&context->l1); +#endif + #if defined(LWS_WITH_SYS_SMD) _lws_smd_destroy(context); #endif @@ -2137,8 +2213,9 @@ lws_context_destroy(struct lws_context *context) lws_fi_destroy(&context->fic); #endif + lwsl_refcount_cx(context->log_cx, -1); + lws_free(context); - lwsl_debug("%s: ctx %p freed\n", __func__, context); if (pcontext_finalize) *pcontext_finalize = NULL; @@ -2149,7 +2226,7 @@ lws_context_destroy(struct lws_context *context) #if defined(LWS_WITH_NETWORK) bail: #endif - lwsl_info("%s: leaving\n", __func__); + lwsl_cx_info(context, "leaving"); context->inside_context_destroy = 0; lws_context_unlock(context); } @@ -2171,3 +2248,22 @@ lws_system_context_from_system_mgr(lws_state_manager_t *mgr) #endif } #endif + +void +lws_log_prepend_context(struct lws_log_cx *cx, void *obj, char **p, char *e) +{ + struct lws_context *lcx = (struct lws_context *)obj; + + if (lcx->name) + *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", + lcx->name); +} + +struct lws_log_cx * +lwsl_context_get_cx(struct lws_context *cx) +{ + if (!cx) + return NULL; + + return cx->log_cx; +} diff --git a/3rdparty/libwebsockets/lib/core/libwebsockets.c b/3rdparty/libwebsockets/lib/core/libwebsockets.c index 4def8563..1c66e8b8 100644 --- a/3rdparty/libwebsockets/lib/core/libwebsockets.c +++ b/3rdparty/libwebsockets/lib/core/libwebsockets.c @@ -209,8 +209,18 @@ int lws_open(const char *__file, int __oflag, ...) || ((__oflag & O_TMPFILE) == O_TMPFILE) #endif ) +#if defined(WIN32) /* last arg is really a mode_t. But windows... */ n = open(__file, __oflag, va_arg(ap, uint32_t)); +#else + /* ... and some other toolchains... + * + * error: second argument to 'va_arg' is of promotable type 'mode_t' + * (aka 'unsigned short'); this va_arg has undefined behavior because + * arguments will be promoted to 'int' + */ + n = open(__file, __oflag, (mode_t)va_arg(ap, unsigned int)); +#endif else n = open(__file, __oflag); va_end(ap); @@ -234,6 +244,10 @@ lws_pthread_self_to_tsi(struct lws_context *context) struct lws_context_per_thread *pt = &context->pt[0]; int n; + /* case that we have SMP build, but don't use it */ + if (context->count_threads == 1) + return 0; + for (n = 0; n < context->count_threads; n++) { if (pthread_equal(ps, pt->self)) return n; @@ -1165,9 +1179,11 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, } int -lws_strcmp_wildcard(const char *wildcard, size_t len, const char *check) +lws_strcmp_wildcard(const char *wildcard, size_t wlen, const char *check, + size_t clen) { - const char *match[3], *wc[3], *wc_end = wildcard + len; + const char *match[3], *wc[3], *wc_end = wildcard + wlen, + *cend = check + clen; int sp = 0; do { @@ -1236,9 +1252,13 @@ lws_strcmp_wildcard(const char *wildcard, size_t len, const char *check) /* we're looking for a post-* match... keep looking... */ - } while (*check); + } while (check < cend); + + /* + * We reached the end of check, if also at end of wildcard we're OK + */ - return !!*wildcard; + return wildcard != wc_end; } #if LWS_MAX_SMP > 1 diff --git a/3rdparty/libwebsockets/lib/core/logs.c b/3rdparty/libwebsockets/lib/core/logs.c index 9d8a7338..27b7b9fa 100644 --- a/3rdparty/libwebsockets/lib/core/logs.c +++ b/3rdparty/libwebsockets/lib/core/logs.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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,14 +32,15 @@ void lwsl_emit_optee(int level, const char *line); #endif -int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE; -static void (*lwsl_emit)(int level, const char *line) -#ifndef LWS_PLAT_OPTEE - = lwsl_emit_stderr +lws_log_cx_t log_cx = { +#if !defined(LWS_PLAT_OPTEE) + .u.emit = lwsl_emit_stderr, #else - = lwsl_emit_optee; + .u.emit = lwsl_emit_optee, #endif - ; + .lll_flags = LLL_ERR | LLL_WARN | LLL_NOTICE, +}; + #if !defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NO_LOGS) static const char * log_level_names ="EWNIDPHXCLUT??"; #endif @@ -49,8 +50,8 @@ static const char * log_level_names ="EWNIDPHXCLUT??"; */ void -__lws_lc_tag(lws_lifecycle_group_t *grp, lws_lifecycle_t *lc, - const char *format, ...) +__lws_lc_tag(struct lws_context *context, lws_lifecycle_group_t *grp, + lws_lifecycle_t *lc, const char *format, ...) { va_list ap; int n = 1; @@ -96,11 +97,13 @@ __lws_lc_tag(lws_lifecycle_group_t *grp, lws_lifecycle_t *lc, lc->gutag[0] = '['; #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) /* ie, will have getpid if set */ - n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - (unsigned int)n - 1u, - "%u|", getpid()); + n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - + (unsigned int)n - 1u, "%u|", getpid()); #endif - n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - (unsigned int)n - 1u, - "%s|%lx|", grp->tag_prefix, (unsigned long)grp->ordinal++); + n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - + (unsigned int)n - 1u, "%s|%lx|", + grp->tag_prefix, + (unsigned long)grp->ordinal++); va_start(ap, format); n += vsnprintf(&lc->gutag[n], sizeof(lc->gutag) - (unsigned int)n - @@ -118,8 +121,10 @@ __lws_lc_tag(lws_lifecycle_group_t *grp, lws_lifecycle_t *lc, lc->us_creation = (uint64_t)lws_now_usecs(); lws_dll2_add_tail(&lc->list, &grp->owner); + lwsl_refcount_cx(lc->log_cx, 1); + #if defined(LWS_LOG_TAG_LIFECYCLE) - lwsl_notice(" ++ %s (%d)\n", lc->gutag, (int)grp->owner.count); + lwsl_cx_notice(context, " ++ %s (%d)", lc->gutag, (int)grp->owner.count); #endif } @@ -141,8 +146,8 @@ __lws_lc_tag_append(lws_lifecycle_t *lc, const char *app) if (n && lc->gutag[n - 1] == ']') n--; - n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - 2u - (unsigned int)n, - "|%s]", app); + n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - 2u - + (unsigned int)n, "|%s]", app); if ((unsigned int)n >= sizeof(lc->gutag) - 2u) { lc->gutag[sizeof(lc->gutag) - 2] = ']'; @@ -155,33 +160,37 @@ __lws_lc_tag_append(lws_lifecycle_t *lc, const char *app) */ void -__lws_lc_untag(lws_lifecycle_t *lc) +__lws_lc_untag(struct lws_context *context, lws_lifecycle_t *lc) { //lws_lifecycle_group_t *grp; char buf[24]; if (!lc->gutag[0]) { /* we never tagged this object... */ - lwsl_err("%s: %s never tagged\n", __func__, lc->gutag); + lwsl_cx_err(context, "%s never tagged", lc->gutag); assert(0); return; } if (!lc->list.owner) { /* we already untagged this object... */ - lwsl_err("%s: %s untagged twice\n", __func__, lc->gutag); + lwsl_cx_err(context, "%s untagged twice", lc->gutag); assert(0); return; } //grp = lws_container_of(lc->list.owner, lws_lifecycle_group_t, owner); - lws_humanize(buf, sizeof(buf), (uint64_t)lws_now_usecs() - lc->us_creation, - humanize_schema_us); + lws_humanize(buf, sizeof(buf), + (uint64_t)lws_now_usecs() - lc->us_creation, + humanize_schema_us); #if defined(LWS_LOG_TAG_LIFECYCLE) - lwsl_notice(" -- %s (%d) %s\n", lc->gutag, (int)lc->list.owner->count - 1, buf); + lwsl_cx_notice(context, " -- %s (%d) %s", lc->gutag, + (int)lc->list.owner->count - 1, buf); #endif lws_dll2_remove(&lc->list); + + lwsl_refcount_cx(lc->log_cx, -1); } const char * @@ -191,7 +200,6 @@ lws_lc_tag(lws_lifecycle_t *lc) } -#if defined(LWS_LOGS_TIMESTAMP) int lwsl_timestamp(int level, char *p, size_t len) { @@ -207,7 +215,8 @@ lwsl_timestamp(int level, char *p, size_t len) gettimeofday(&tv, NULL); o_now = tv.tv_sec; - now = ((unsigned long long)tv.tv_sec * 10000) + (unsigned int)(tv.tv_usec / 100); + now = ((unsigned long long)tv.tv_sec * 10000) + + (unsigned int)(tv.tv_usec / 100); #if defined(LWS_HAVE_LOCALTIME_R) ptm = localtime_r(&o_now, &tm); @@ -233,6 +242,16 @@ lwsl_timestamp(int level, char *p, size_t len) n = lws_snprintf(p, len, "[%llu:%04d] %c: ", (unsigned long long) now / 10000, (int)(now % 10000), log_level_names[n]); + +#if defined(LWS_PLAT_FREERTOS) + n += lws_snprintf(p + n, len - n, "%6u: ", +#if defined(LWS_AMAZON_RTOS) + (unsigned int)xPortGetFreeHeapSize()); +#else + (unsigned int)esp_get_free_heap_size()); +#endif +#endif + return n; } #else @@ -241,7 +260,6 @@ lwsl_timestamp(int level, char *p, size_t len) return 0; } -#endif #ifndef LWS_PLAT_OPTEE static const char * const colours[] = { @@ -262,20 +280,13 @@ static const char * const colours[] = { static char tty; static void -_lwsl_emit_stderr(int level, const char *line, int ts) +_lwsl_emit_stderr(int level, const char *line) { - char buf[50]; int n, m = LWS_ARRAY_SIZE(colours) - 1; if (!tty) tty = (char)(isatty(2) | 2); - buf[0] = '\0'; -#if defined(LWS_LOGS_TIMESTAMP) - if (ts) - lwsl_timestamp(level, buf, sizeof(buf)); -#endif - if (tty == 3) { n = 1 << (LWS_ARRAY_SIZE(colours) - 1); while (n) { @@ -284,27 +295,76 @@ _lwsl_emit_stderr(int level, const char *line, int ts) m--; n >>= 1; } - fprintf(stderr, "%c%s%s%s%c[0m", 27, colours[m], buf, line, 27); + fprintf(stderr, "%c%s%s%c[0m", 27, colours[m], line, 27); } else - fprintf(stderr, "%s%s", buf, line); + fprintf(stderr, "%s", line); } void lwsl_emit_stderr(int level, const char *line) { - _lwsl_emit_stderr(level, line, 1); + _lwsl_emit_stderr(level, line); } void lwsl_emit_stderr_notimestamp(int level, const char *line) { - _lwsl_emit_stderr(level, line, 0); + _lwsl_emit_stderr(level, line); +} + +#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) + +/* + * Helper to emit to a file + */ + +void +lws_log_emit_cx_file(struct lws_log_cx *cx, int level, const char *line, + size_t len) +{ + int fd = (int)(intptr_t)cx->stg; + + if (fd >= 0) + if (write(fd, line, (unsigned int)len) != (ssize_t)len) + fprintf(stderr, "Unable to write log to file\n"); +} + +/* + * Helper to use a .refcount_cb to store logs in a file + */ + +void +lws_log_use_cx_file(struct lws_log_cx *cx, int _new) +{ + int fd; + + if (_new > 0 && cx->refcount == 1) { + fd = open((const char *)cx->opaque, + LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600); + if (fd < 0) + fprintf(stderr, "Unable to open log %s: errno %d\n", + (const char *)cx->opaque, errno); + cx->stg = (void *)(intptr_t)fd; + + return; + } + + fd = (int)(intptr_t)cx->stg; + + if (_new <= 0 && cx->refcount == 0 && fd >= 0) { + close(fd); + cx->stg = (void *)(intptr_t)-1; + } } #endif +#endif + #if !(defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)) -void _lws_logv(int filter, const char *format, va_list vl) +void +__lws_logv(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int filter, const char *_fun, const char *format, va_list vl) { #if LWS_MAX_SMP == 1 && !defined(LWS_WITH_THREADPOOL) /* this is incompatible with multithreaded logging */ @@ -312,25 +372,103 @@ void _lws_logv(int filter, const char *format, va_list vl) #else char buf[1024]; #endif - int n; + char *p = buf, *end = p + sizeof(buf) - 1; + lws_log_cx_t *cxp; + int n, back = 0; + + /* + * We need to handle NULL wsi etc at the wrappers as gracefully as + * possible + */ + + if (!cx) { + lws_strncpy(p, "NULL log cx: ", sizeof(buf) - 1); + p += 13; + /* use the processwide one for lack of anything better */ + cx = &log_cx; + } - if (!(log_level & filter)) + cxp = cx; + + if (!(cx->lll_flags & (uint32_t)filter)) + /* + * logs may be produced and built in to the code but disabled + * at runtime + */ return; - n = vsnprintf(buf, sizeof(buf) - 1, format, vl); - (void)n; - /* vnsprintf returns what it would have written, even if truncated */ - if (n > (int)sizeof(buf) - 1) { - n = sizeof(buf) - 5; - buf[n++] = '.'; - buf[n++] = '.'; - buf[n++] = '.'; - buf[n++] = '\n'; - buf[n] = '\0'; +#if !defined(LWS_LOGS_TIMESTAMP) + if (cx->lll_flags & LLLF_LOG_TIMESTAMP) +#endif + { + buf[0] = '\0'; + lwsl_timestamp(filter, buf, sizeof(buf)); + p += strlen(buf); } - if (n > 0) - buf[n] = '\0'; - lwsl_emit(filter, buf); + + /* + * prepend parent log ctx content first + * top level cx also gets an opportunity to prepend + */ + + while (cxp->parent) { + cxp = cxp->parent; + back++; + } + + do { + int b = back; + + cxp = cx; + while (b--) + cxp = cxp->parent; + if (cxp->prepend) + cxp->prepend(cxp, NULL, &p, end); + + back--; + } while (back > 0); + + if (prep) + prep(cxp, obj, &p, end); + + if (_fun) + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s: ", _fun); + + /* + * The actual log content + */ + + n = vsnprintf(p, lws_ptr_diff_size_t(end, p), format, vl); + + /* vnsprintf returns what it would have written, even if truncated */ + if (p + n > end - 2) { + p = end - 5; + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + *p++ = '\n'; + *p++ = '\0'; + } else + if (n > 0) { + p += n; + if (p[-1] != '\n') + *p++ = '\n'; + *p = '\0'; + } + + /* + * The actual emit + */ + + if (cx->lll_flags & LLLF_LOG_CONTEXT_AWARE) + cx->u.emit_cx(cx, filter, buf, lws_ptr_diff_size_t(p, buf)); + else + cx->u.emit(filter, buf); +} + +void _lws_logv(int filter, const char *format, va_list vl) +{ + __lws_logv(&log_cx, NULL, NULL, filter, NULL, format, vl); } void _lws_log(int filter, const char *format, ...) @@ -338,42 +476,102 @@ void _lws_log(int filter, const char *format, ...) va_list ap; va_start(ap, format); - _lws_logv(filter, format, ap); + __lws_logv(&log_cx, NULL, NULL, filter, NULL, format, ap); + va_end(ap); +} + +void _lws_log_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int filter, const char *_fun, const char *format, ...) +{ + va_list ap; + + if (!cx) + cx = &log_cx; + + va_start(ap, format); + __lws_logv(cx, prep, obj, filter, _fun, format, ap); va_end(ap); } #endif -void lws_set_log_level(int level, void (*func)(int level, const char *line)) + +void +lws_set_log_level(int flags, lws_log_emit_t func) { - log_level = level; + log_cx.lll_flags = (uint32_t)(flags & (~LLLF_LOG_CONTEXT_AWARE)); + if (func) - lwsl_emit = func; + log_cx.u.emit = func; } int lwsl_visible(int level) { - return log_level & level; + return !!(log_cx.lll_flags & (uint32_t)level); +} + +int lwsl_visible_cx(lws_log_cx_t *cx, int level) +{ + return !!(cx->lll_flags & (uint32_t)level); } void -lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len) +lwsl_refcount_cx(lws_log_cx_t *cx, int _new) +{ +#if LWS_MAX_SMP > 1 + volatile lws_log_cx_t *vcx = (volatile lws_log_cx_t *)cx; +#endif + + if (!cx) + return; + +#if LWS_MAX_SMP > 1 + if (!vcx->inited) { + vcx->inited = 1; + lws_pthread_mutex_init(&cx->refcount_lock); + vcx->inited = 2; + } + while (vcx->inited != 2) + ; + lws_pthread_mutex_lock(&cx->refcount_lock); +#endif + + if (_new > 0) + cx->refcount++; + else { + assert(cx->refcount); + cx->refcount--; + } + + if (cx->refcount_cb) + cx->refcount_cb(cx, _new); + +#if LWS_MAX_SMP > 1 + lws_pthread_mutex_unlock(&cx->refcount_lock); +#endif +} + +void +lwsl_hexdump_level_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int hexdump_level, const void *vbuf, size_t len) { unsigned char *buf = (unsigned char *)vbuf; unsigned int n; - if (!lwsl_visible(hexdump_level)) + if (!lwsl_visible_cx(cx, hexdump_level)) return; if (!len) { - _lws_log(hexdump_level, "(hexdump: zero length)\n"); + _lws_log_cx(cx, prep, obj, hexdump_level, NULL, + "(hexdump: zero length)\n"); return; } if (!vbuf) { - _lws_log(hexdump_level, "(hexdump: NULL ptr)\n"); + _lws_log_cx(cx, prep, obj, hexdump_level, NULL, + "(hexdump: NULL ptr)\n"); return; } - _lws_log(hexdump_level, "\n"); + _lws_log_cx(cx, prep, obj, hexdump_level, NULL, "\n"); for (n = 0; n < len;) { unsigned int start = n, m; @@ -399,11 +597,17 @@ lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len) *p++ = '\n'; *p = '\0'; - _lws_log(hexdump_level, "%s", line); + _lws_log_cx(cx, prep, obj, hexdump_level, NULL, "%s", line); (void)line; } - _lws_log(hexdump_level, "\n"); + _lws_log_cx(cx, prep, obj, hexdump_level, NULL, "\n"); +} + +void +lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len) +{ + lwsl_hexdump_level_cx(&log_cx, NULL, NULL, hexdump_level, vbuf, len); } void diff --git a/3rdparty/libwebsockets/lib/core/lws_map.c b/3rdparty/libwebsockets/lib/core/lws_map.c new file mode 100644 index 00000000..d149d867 --- /dev/null +++ b/3rdparty/libwebsockets/lib/core/lws_map.c @@ -0,0 +1,266 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 struct lws_map_hashtable { + struct lws_map *map_owner; /* so items can find map */ + lws_dll2_owner_t ho; +} lws_map_hashtable_t; + +typedef struct lws_map { + lws_map_info_t info; + + /* array of info.modulo x lws_map_hashtable_t overallocated */ +} lws_map_t; + +typedef struct lws_map_item { + lws_dll2_t list; /* owned by hashtable */ + + size_t keylen; + size_t valuelen; + + /* key then value is overallocated */ +} lws_map_item_t; + +/* + * lwsac-aware allocator + */ + +void * +lws_map_alloc_lwsac(struct lws_map *map, size_t x) +{ + return lwsac_use((struct lwsac **)map->info.opaque, x, + (size_t)map->info.aux); +} + +void +lws_map_free_lwsac(void *v) +{ +} + +/* + * Default allocation / free if none given in info + */ + +void * +lws_map_alloc_lws_malloc(struct lws_map *mo, size_t x) +{ + return lws_malloc(x, __func__); +} + +void +lws_map_free_lws_free(void *v) +{ + lws_free(v); +} + +/* + * This just needs to approximate a flat distribution, it's not related to + * security at all. + */ + +lws_map_hash_t +lws_map_hash_from_key_default(const lws_map_key_t key, size_t kl) +{ + lws_map_hash_t h = 0x12345678; + const uint8_t *u = (const uint8_t *)key; + + while (kl--) + h = ((((h << 7) | (h >> 25)) + 0xa1b2c3d4) ^ (*u++)) ^ h; + + return h; +} + +int +lws_map_compare_key_default(const lws_map_key_t key1, size_t kl1, + const lws_map_value_t key2, size_t kl2) +{ + if (kl1 != kl2) + return 1; + + return memcmp(key1, key2, kl1); +} + +lws_map_t * +lws_map_create(const lws_map_info_t *info) +{ + lws_map_t *map; + lws_map_alloc_t a = info->_alloc; + size_t modulo = info->modulo; + lws_map_hashtable_t *ht; + size_t size; + + if (!a) + a = lws_map_alloc_lws_malloc; + + if (!modulo) + modulo = 8; + + size = sizeof(*map) + (modulo * sizeof(lws_map_hashtable_t)); + map = lws_malloc(size, __func__); + if (!map) + return NULL; + + memset(map, 0, size); + + map->info = *info; + + map->info._alloc = a; + map->info.modulo = modulo; + if (!info->_free) + map->info._free = lws_map_free_lws_free; + if (!info->_hash) + map->info._hash = lws_map_hash_from_key_default; + if (!info->_compare) + map->info._compare = lws_map_compare_key_default; + + ht = (lws_map_hashtable_t *)&map[1]; + while (modulo--) + ht[modulo].map_owner = map; + + return map; +} + +static int +ho_free_item(struct lws_dll2 *d, void *user) +{ + lws_map_item_t *i = lws_container_of(d, lws_map_item_t, list); + + lws_map_item_destroy(i); + + return 0; +} + +void +lws_map_destroy(lws_map_t **pmap) +{ + lws_map_hashtable_t *ht; + lws_map_t *map = *pmap; + + if (!map) + return; + + /* empty out all the hashtables */ + + ht = (lws_map_hashtable_t *)&(map[1]); + while (map->info.modulo--) { + lws_dll2_foreach_safe(&ht->ho, ht, ho_free_item); + ht++; + } + + /* free the map itself */ + + lws_free_set_NULL(*pmap); +} + +lws_map_item_t * +lws_map_item_create(lws_map_t *map, + const lws_map_key_t key, size_t keylen, + const lws_map_value_t value, size_t valuelen) +{ + lws_map_hashtable_t *ht; + lws_map_item_t *item; + lws_map_hash_t h; + size_t hti; + uint8_t *u; + + item = lws_map_item_lookup(map, key, keylen); + if (item) + lws_map_item_destroy(item); + + item = map->info._alloc(map, sizeof(*item) + keylen + valuelen); + if (!item) + return NULL; + + lws_dll2_clear(&item->list); + item->keylen = keylen; + item->valuelen = valuelen; + + u = (uint8_t *)&item[1]; + memcpy(u, key, keylen); + u += keylen; + if (value) + memcpy(u, value, valuelen); + + h = map->info._hash(key, keylen); + + hti = h % map->info.modulo; + ht = (lws_map_hashtable_t *)&map[1]; + + lws_dll2_add_head(&item->list, &ht[hti].ho); + + return item; +} + +void +lws_map_item_destroy(lws_map_item_t *item) +{ + lws_map_hashtable_t *ht = lws_container_of(item->list.owner, + lws_map_hashtable_t, ho); + + lws_dll2_remove(&item->list); + ht->map_owner->info._free(item); +} + +lws_map_item_t * +lws_map_item_lookup(lws_map_t *map, const lws_map_key_t key, size_t keylen) +{ + lws_map_hash_t h = map->info._hash(key, keylen); + lws_map_hashtable_t *ht = (lws_map_hashtable_t *)&map[1]; + + lws_start_foreach_dll(struct lws_dll2 *, p, + ht[h % map->info.modulo].ho.head) { + lws_map_item_t *i = lws_container_of(p, lws_map_item_t, list); + + if (!map->info._compare(key, keylen, &i[1], i->keylen)) + return i; + } lws_end_foreach_dll(p); + + return NULL; +} + +const void * +lws_map_item_key(lws_map_item_t *_item) +{ + return ((void *)&_item[1]); +} + +const void * +lws_map_item_value(lws_map_item_t *_item) +{ + return (void *)(((uint8_t *)&_item[1]) + _item->keylen); +} + +size_t +lws_map_item_key_len(lws_map_item_t *_item) +{ + return _item->keylen; +} + +size_t +lws_map_item_value_len(lws_map_item_t *_item) +{ + return _item->valuelen; +} diff --git a/3rdparty/libwebsockets/lib/core/private-lib-core.h b/3rdparty/libwebsockets/lib/core/private-lib-core.h index ab822175..6cdc91cf 100644 --- a/3rdparty/libwebsockets/lib/core/private-lib-core.h +++ b/3rdparty/libwebsockets/lib/core/private-lib-core.h @@ -195,21 +195,24 @@ typedef struct lws_lifecycle { #endif lws_dll2_t list; /* group list membership */ uint64_t us_creation; /* creation timestamp */ + lws_log_cx_t *log_cx; } lws_lifecycle_t; void -__lws_lc_tag(lws_lifecycle_group_t *grp, lws_lifecycle_t *lc, - const char *format, ...); +__lws_lc_tag(struct lws_context *cx, lws_lifecycle_group_t *grp, + lws_lifecycle_t *lc, const char *format, ...); void __lws_lc_tag_append(lws_lifecycle_t *lc, const char *app); void -__lws_lc_untag(lws_lifecycle_t *lc); +__lws_lc_untag(struct lws_context *cx, lws_lifecycle_t *lc); const char * lws_lc_tag(lws_lifecycle_t *lc); +extern lws_log_cx_t log_cx; + /* * Generic bidi tx credit management */ @@ -445,6 +448,8 @@ struct lws_context { lws_lifecycle_group_t lcg[LWSLCG_COUNT]; + const struct lws_protocols *protocols_copy; + #if defined(LWS_WITH_NETLINK) lws_sorted_usec_list_t sul_nl_coldplug; /* process can only have one netlink socket, have to do it in ctx */ @@ -514,6 +519,12 @@ struct lws_context { #if defined(LWS_WITH_TLS) struct lws_context_tls tls; +#if defined (LWS_WITH_TLS_JIT_TRUST) + lws_dll2_owner_t jit_inflight; + /* ongoing sync or async jit trust lookups */ + struct lws_cache_ttl_lru *trust_cache; + /* caches host -> truncated trust SKID mappings */ +#endif #endif #if defined(LWS_WITH_DRIVERS) lws_netdevs_t netdevs; @@ -528,6 +539,9 @@ struct lws_context { /**< Toplevel Fault Injection ctx */ #endif +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + struct lws_cache_ttl_lru *l1, *nsc; +#endif #if defined(LWS_WITH_SYS_NTPCLIENT) void *ntpclient_priv; @@ -589,6 +603,9 @@ struct lws_context { #endif /* NETWORK */ + lws_log_cx_t *log_cx; + const char *name; + #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) const char *ss_proxy_bind; const char *ss_proxy_address; @@ -603,12 +620,12 @@ struct lws_context { const char *username, *groupname; #endif -#if defined(LWS_AMAZON_RTOS) && defined(LWS_WITH_MBEDTLS) +#if defined(LWS_WITH_MBEDTLS) mbedtls_entropy_context mec; mbedtls_ctr_drbg_context mcdc; #endif -#if defined(LWS_WITH_THREADPOOL) +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) struct lws_threadpool *tp_list_head; #endif @@ -685,6 +702,11 @@ struct lws_context { unsigned int max_http_header_pool; int simultaneous_ssl_restriction; int simultaneous_ssl; + int simultaneous_ssl_handshake_restriction; + int simultaneous_ssl_handshake; +#if defined(LWS_WITH_TLS_JIT_TRUST) + int vh_idle_grace_ms; +#endif #if defined(LWS_WITH_PEER_LIMITS) uint32_t pl_hash_elements; /* protected by context->lock */ uint32_t count_peers; /* protected by context->lock */ @@ -700,6 +722,8 @@ struct lws_context { lws_route_uidx_t route_uidx; #endif + char tls_gate_accepts; + unsigned int deprecated:1; unsigned int inside_context_destroy:1; unsigned int being_destroyed:1; @@ -744,6 +768,13 @@ lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max); void lws_vhost_destroy1(struct lws_vhost *vh); +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) +int +lws_parse_set_cookie(struct lws *wsi); + +int +lws_cookie_send_cookies(struct lws *wsi, char **pp, char *end); +#endif #if defined(LWS_PLAT_FREERTOS) int @@ -766,8 +797,6 @@ struct lws_buflist { char * lws_strdup(const char *s); -extern int log_level; - int lws_b64_selftest(void); @@ -794,7 +823,7 @@ void lwsl_emit_stderr(int level, const char *line); #define lws_ssl_SSL_CTX_destroy(_a) #define lws_ssl_remove_wsi_from_buffered_list(_a) #define __lws_ssl_remove_wsi_from_buffered_list(_a) - #define lws_context_init_ssl_library(_a) + #define lws_context_init_ssl_library(_a, _b) #define lws_context_deinit_ssl_library(_a) #define lws_tls_check_all_cert_lifetimes(_a) #define lws_tls_acme_sni_cert_destroy(_a) @@ -856,6 +885,9 @@ lws_vhost_protocol_options(struct lws_vhost *vh, const char *name); const struct lws_http_mount * lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len); +#ifdef LWS_WITH_HTTP2 +int lws_wsi_is_h2(struct lws *wsi); +#endif /* * custom allocator */ @@ -921,6 +953,15 @@ lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len); int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount); +int +lws_lec_scratch(lws_lec_pctx_t *ctx); +void +lws_lec_signed(lws_lec_pctx_t *ctx, int64_t num); + +int +lws_cose_key_checks(const lws_cose_key_t *key, int64_t kty, int64_t alg, + int key_op, const char *crv); + void lws_msleep(unsigned int); void diff --git a/3rdparty/libwebsockets/lib/cose/CMakeLists.txt b/3rdparty/libwebsockets/lib/cose/CMakeLists.txt new file mode 100644 index 00000000..c96e3db3 --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# 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_COSE) + list(APPEND SOURCES + cose/cose_key.c + cose/cose_validate.c + cose/cose_validate_alg.c + cose/cose_sign.c + cose/cose_sign_alg.c + ) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/3rdparty/libwebsockets/lib/cose/cose_key.c b/3rdparty/libwebsockets/lib/cose/cose_key.c new file mode 100644 index 00000000..66247cbc --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/cose_key.c @@ -0,0 +1,1188 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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. + * + * cose_key code + */ + +#include "private-lib-core.h" +//#include "private-lib-jose.h" + +#define lwsl_cose lwsl_notice +#define lwsl_hexdump_cose lwsl_hexdump_notice + +// #define VERBOSE 1 + +struct lws_cose_key_parse_state { + struct lws_cose_key *ck; + /**< single key created here if pkey_set is NULL */ + char buf[(8192 / 8) + 1]; + /**< enough for 8Kb key, only needed during parse */ + lws_cose_key_import_callback per_key_cb; + lws_dll2_owner_t *pkey_set; + /**< if non-NULL, expects a [ key set ], else single key */ + void *user; + size_t pos; + int cose_state; + cose_param_t seen[16]; + int seen_count; + int gencrypto_eidx; + int meta_idx; + unsigned short possible; +}; + +/* + * A COSE key representation is a CBOR map with a specified structure. The + * keys are + * + * LWSCOSE_WKK_KTY MUST int / tstr + * LWSCOSE_WKK_KID OPT bstr + * LWSCOSE_WKK_ALG OPT int / tstr + * LWSCOSE_WKK_KEY_OPS OPT [ + (int / tstr) ] + * LWSCOSE_WKK_BASE_IV OPT bstr + */ + +#if defined(_DEBUG) + +static const char *meta_names[] = { + "kty", "kid", "use", "key_ops", "base_iv", "alg" +}; + +static const char *oct_names[] = { + "k" +}; + +static const char *rsa_names[] = { + "e", "n", "d", "p", "q", "dp", "dq", "qi", "other", "ri", "di", "ti" +}; + +static const char *ec_names[] = { + "crv", "x", "d", "y", +}; + +void +lws_cose_key_dump(const struct lws_cose_key *ck) +{ + const char **enames; + char hex[2048]; + int elems; + int n; + + (void)enames; + (void)meta_names; + + switch (ck->gencrypto_kty) { + + case LWS_GENCRYPTO_KTY_OCT: + elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT; + enames = oct_names; + break; + case LWS_GENCRYPTO_KTY_RSA: + elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT; + enames = rsa_names; + break; + case LWS_GENCRYPTO_KTY_EC: + elems = LWS_GENCRYPTO_EC_KEYEL_COUNT; + enames = ec_names; + break; + + default: + lwsl_err("%s: jwk %p: unknown type\n", __func__, ck); + + return; + } + + lwsl_cose("%s: cose_key %p, kty: %lld (gc %d)\n", __func__, ck, + (long long)ck->kty, ck->gencrypto_kty); + + for (n = 0; n < LWS_COUNT_COSE_KEY_ELEMENTS; n++) { + if (ck->meta[n].buf) { + lws_hex_from_byte_array(ck->meta[n].buf, ck->meta[n].len, + hex, sizeof(hex)); + lwsl_cose(" meta: %s: %s\n", meta_names[n], hex); + } + } + + for (n = 0; n < elems; n++) { + if (ck->e[n].buf) { + lws_hex_from_byte_array(ck->e[n].buf, ck->e[n].len, + hex, sizeof(hex)); + lwsl_cose(" e: %s: %s\n", enames[n], hex); + } + } +} +#endif + +static const char * const kty_strings[] = { NULL, + "OKP", "EC2", "RSA", "SYMMETRIC", "HSS_LMS", "WALNUTDSA" +}; + +int +lws_cose_key_checks(const lws_cose_key_t *key, int64_t kty, cose_param_t alg, + int key_op, const char *crv) +{ + const struct lws_gencrypto_keyelem *ke; + + /* + * we ourselves have to have a very clear idea what we need, even if + * matches are optional in the key itself + */ + assert(key); + assert(kty); + assert(alg); + assert(key_op); + assert((kty != LWSCOSE_WKKTV_OKP && kty != LWSCOSE_WKKTV_EC2) || crv); + + /* RFC8152 8.1: + * + * The 'kty' field MUST be present, and it MUST be '...'. + * + * But kty can come as an int or a string, but we convert well-known + * kty ints to the corresponding string representation at key import + */ + if (!kty || kty >= (int)LWS_ARRAY_SIZE(kty_strings)) { + /* we don't understand it */ + lwsl_notice("%s: unknown kty %d\n", __func__, (int)kty); + goto bail; + } + + ke = &key->meta[COSEKEY_META_KTY]; + if (ke->buf && (strlen(kty_strings[kty]) != ke->len || + memcmp(kty_strings[kty], ke->buf, ke->len))) { + lwsl_notice("%s: key is of wrong kty\n", __func__); + lwsl_hexdump_notice(ke->buf, ke->len); + goto bail; + } + + /* ... + * If the 'alg' field is present, it MUST match the ... signature + * algorithm being used. + * + * We attempt to convert key alg text representations to a well-known + * index, if we can't, then we don't know the alg anyway and should fail + * it + */ + + if (!key->cose_alg && key->meta[COSEKEY_META_ALG].buf) { + lwsl_notice("%s: alg fail 1\n", __func__); + goto bail; + } + + if (key->cose_alg && /* accept it being absent altogether */ + key->cose_alg != alg) { + lwsl_notice("%s: alg fail 2\n", __func__); + + goto bail; + } + + /* ... + * If the 'key_ops' field is present, it MUST include 'sign' / 'verify' + * when creating /verifying an ... signature. + */ + + ke = &key->meta[COSEKEY_META_KEY_OPS]; + if (ke->buf && ke->len) { + uint32_t n; + + for (n = 0; n < ke->len; n++) + if (ke->buf[n] == key_op) + break; + + if (n == ke->len) + goto bail; + } + + /* + * If it's related to EC, check there is a curve associated with the + * key, and check it is what we expect + */ + + if (kty == LWSCOSE_WKKTV_OKP || kty == LWSCOSE_WKKTV_EC2) { + ke = &key->e[LWS_GENCRYPTO_EC_KEYEL_CRV]; + + if (!ke->buf) + goto bail; + if (ke->len != strlen(crv)) + goto bail; + if (memcmp(ke->buf, crv, ke->len)) + goto bail; + } + + /* We're willing to use this key for this operation */ + + return 0; + +bail: + lwsl_notice("%s: key rejected\n", __func__); + + return 1; +} + + +static int +lws_ck_set_el(struct lws_gencrypto_keyelem *e, char *in, size_t len) +{ + e->buf = lws_malloc(len + 1, "ck"); + if (!e->buf) + return -1; + + memcpy(e->buf, in, len); + e->buf[len] = '\0'; + e->len = (uint32_t)len; + + return 0; +} + +static struct { + const char *curve; + cose_param_t cose_id; +} cose_curves[] = { + { "P-256", LWSCOSE_WKEC_P256 }, + { "P-384", LWSCOSE_WKEC_P384 }, + { "P-521", LWSCOSE_WKEC_P521 }, + { "X25519", LWSCOSE_WKEC_X25519 }, + { "X448", LWSCOSE_WKEC_X448 }, + { "ED25519", LWSCOSE_WKEC_ED25519 }, + { "ED448", LWSCOSE_WKEC_ED448 }, + { "SECP256K1", LWSCOSE_WKEC_SECP256K1 }, +}; + +/* 0 means failed */ + +static cose_param_t +lws_cose_curve_name_to_id(const char *curve) +{ + int n; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(cose_curves); n++) + if (!strcmp(cose_curves[n].curve, curve)) + return cose_curves[n].cose_id; + + return 0; +} + +static const char * +lws_cose_curve_id_to_name(cose_param_t id) +{ + int n; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(cose_curves); n++) + if (cose_curves[n].cose_id == id) + return cose_curves[n].curve; + + return 0; +} + +static const char * const wk_algs[] = { + "ES256", "ES384", "ES512" +}; +static signed char wk_alg_indexes[] = { + LWSCOSE_WKAECDSA_ALG_ES256, + LWSCOSE_WKAECDSA_ALG_ES384, + LWSCOSE_WKAECDSA_ALG_ES512, +}; + +static signed char +cb_cose_key(struct lecp_ctx *ctx, char reason) +{ + struct lws_cose_key_parse_state *cps = + (struct lws_cose_key_parse_state *)ctx->user; + struct lws_gencrypto_keyelem *ke = NULL; + const char *p; + int n; + +#if defined(VERBOSE) + lwsl_notice("%s: reason %d, path %s, ord %u, ppos %d\n", __func__, + reason & 0x3f, + ctx->path, ctx->st[ctx->sp - 1].ordinal, + ctx->pst[ctx->pst_sp].ppos); +#endif + + switch (reason) { + case LECPCB_OBJECT_START: + if (cps->ck) + break; + goto ak; + case LECPCB_ARRAY_ITEM_START: + if (cps->pkey_set && ctx->pst[ctx->pst_sp].ppos == 2) { + ak: + cps->ck = lws_zalloc(sizeof(*cps->ck), __func__); + if (!cps->ck) + goto bail; + cps->cose_state = 0; + cps->meta_idx = -1; + cps->gencrypto_eidx = -1; + cps->seen_count = 0; + + if (cps->pkey_set) + lws_dll2_add_tail(&cps->ck->list, cps->pkey_set); + } + break; + case LECPCB_ARRAY_ITEM_END: + if (cps->pkey_set && ctx->pst[ctx->pst_sp].ppos == 2) { + if (cps->per_key_cb) + cps->per_key_cb(cps->ck, cps->user); + } + break; + case LECPCB_TAG_START: + if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_KEY) { + lwsl_warn("%s: unexpected tag\n", __func__); + goto bail; + } + break; + + case LECPCB_VAL_NUM_INT: + case LECPCB_VAL_NUM_UINT: + if (!ctx->sp) { + lwsl_warn("%s: unexpected uint %d, ppos %d\n", + __func__, ctx->sp, ctx->pst[ctx->sp].ppos); + goto bail; + } + + if (!lecp_parse_map_is_key(ctx)) { + const char *kty_str; + + /* value part of map */ + + switch (cps->cose_state) { + case LWSCOSE_WKK_KTY: + assert(cps->ck); + cps->ck->kty = (int)ctx->item.u.u64; + + /* convert the cose key type to gencrypto one */ + switch (ctx->item.u.u64) { + case LWSCOSE_WKKTV_OKP: + cps->ck->gencrypto_kty = + LWS_GENCRYPTO_KTY_EC; + kty_str = "OKP"; + break; + case LWSCOSE_WKKTV_EC2: + kty_str = "EC2"; + cps->ck->gencrypto_kty = + LWS_GENCRYPTO_KTY_EC; + break; + case LWSCOSE_WKKTV_RSA: + kty_str = "RSA"; + cps->ck->gencrypto_kty = + LWS_GENCRYPTO_KTY_RSA; + break; + case LWSCOSE_WKKTV_SYMMETRIC: + kty_str = "SYMMETRIC"; + cps->ck->gencrypto_kty = + LWS_GENCRYPTO_KTY_OCT; + break; + // case LWSCOSE_WKKTV_HSS_LMS: + // case LWSCOSE_WKKTV_WALNUTDSA: + default: + lwsl_warn("%s: unknown kty\n", __func__); + goto bail; + } + + /* store the string version of the key type */ + + ke = &cps->ck->meta[COSEKEY_META_KTY]; + ke->len = (uint32_t)strlen(kty_str); + ke->buf = lws_malloc(ke->len + 1, __func__); + if (!ke->buf) + goto bail; + memcpy(ke->buf, kty_str, ke->len + 1); + break; + case LWSCOSE_WKK_ALG: + /* + * He can tie the key to a cose alg code + */ + cps->ck->cose_alg = (int)ctx->item.u.u64; + break; + case LWSCOSE_WKK_KEY_OPS: + if (!cps->pkey_set && + (ctx->pst[ctx->sp].ppos != 3 || + strcmp(ctx->path, ".[]"))) { + lwsl_warn("%s: unexpected kops\n", + __func__); + goto bail; + } + if (cps->pkey_set && + (ctx->pst[ctx->sp].ppos != 5 || + strcmp(ctx->path, "[].[]"))) { + lwsl_warn("%s: unexpected kops\n", + __func__); + goto bail; + } + break; + case LWSCOSE_WKOKP_CRV: + cps->ck->cose_curve = (int)ctx->item.u.u64; + p = lws_cose_curve_id_to_name(cps->ck->cose_curve); + if (p) { + ke = &cps->ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV]; + ke->len = (uint32_t)strlen(p); + ke->buf = lws_malloc(ke->len + 1, __func__); + if (!ke->buf) + goto bail; + memcpy(ke->buf, p, ke->len); + ke->buf[ke->len] = '\0'; + } + break; + default: + lwsl_warn("%s: uint not allowed in state %d\n", + __func__, cps->cose_state); + /* int not allowed in this state */ + goto bail; + } + + cps->cose_state = 0; + break; + } + + /* key part of map pair */ + + /* + * Disallow any of these coming more than once + */ + cps->cose_state = (int)ctx->item.u.u64; + for (n = 0 ; n < cps->seen_count; n++) + if (cps->seen[n] == cps->cose_state) { + /* dupe */ + lwsl_warn("%s: duplicate map name %d\n", + __func__, cps->cose_state); + goto bail; + } + + if (cps->seen_count >= (int)LWS_ARRAY_SIZE(cps->seen)) + goto bail; + cps->seen[cps->seen_count++] = cps->cose_state; + + cps->meta_idx = -1; + switch ((int)ctx->item.u.u64) { + case LWSCOSE_WKK_KTY: + cps->meta_idx = COSEKEY_META_KTY; + break; + case LWSCOSE_WKK_KID: + cps->meta_idx = COSEKEY_META_KID; + break; + case LWSCOSE_WKK_ALG: + cps->meta_idx = COSEKEY_META_ALG; + break; + case LWSCOSE_WKK_KEY_OPS: + cps->meta_idx = COSEKEY_META_KEY_OPS; + break; + case LWSCOSE_WKK_BASE_IV: + cps->meta_idx = COSEKEY_META_BASE_IV; + break; + + default: + cps->gencrypto_eidx = -1; + + switch (cps->ck->kty) { + case LWSCOSE_WKKTV_OKP: + switch ((int)ctx->item.u.u64) { + case LWSCOSE_WKOKP_CRV: + cps->cose_state = LWSCOSE_WKOKP_CRV; + break; + case LWSCOSE_WKOKP_X: + cps->gencrypto_eidx = + LWS_GENCRYPTO_EC_KEYEL_X; + break; + case LWSCOSE_WKOKP_D: + cps->gencrypto_eidx = + LWS_GENCRYPTO_EC_KEYEL_D; + break; + default: + goto bail; + } + break; + case LWSCOSE_WKKTV_EC2: + switch ((int)ctx->item.u.u64) { + case LWSCOSE_WKECKP_CRV: + cps->cose_state = LWSCOSE_WKOKP_CRV; + break; + case LWSCOSE_WKECKP_X: + cps->gencrypto_eidx = + LWS_GENCRYPTO_EC_KEYEL_X; + break; + case LWSCOSE_WKECKP_Y: + cps->gencrypto_eidx = + LWS_GENCRYPTO_EC_KEYEL_Y; + break; + case LWSCOSE_WKECKP_D: + cps->gencrypto_eidx = + LWS_GENCRYPTO_EC_KEYEL_D; + break; + default: + goto bail; + } + break; + case LWSCOSE_WKKTV_RSA: + switch ((int)ctx->item.u.u64) { + case LWSCOSE_WKKPRSA_N: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_N; + break; + case LWSCOSE_WKKPRSA_E: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_E; + break; + case LWSCOSE_WKKPRSA_D: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_D; + break; + case LWSCOSE_WKKPRSA_P: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_P; + break; + case LWSCOSE_WKKPRSA_Q: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_Q; + break; + case LWSCOSE_WKKPRSA_DP: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_DP; + break; + case LWSCOSE_WKKPRSA_DQ: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_DQ; + break; + case LWSCOSE_WKKPRSA_QINV: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_QI; + break; + case LWSCOSE_WKKPRSA_OTHER: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_OTHER; + break; + case LWSCOSE_WKKPRSA_RI: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_RI; + break; + case LWSCOSE_WKKPRSA_DI: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_DI; + break; + case LWSCOSE_WKKPRSA_TI: + cps->gencrypto_eidx = + LWS_GENCRYPTO_RSA_KEYEL_TI; + break; + default: + goto bail; + } + break; + case LWSCOSE_WKKTV_SYMMETRIC: + if (ctx->item.u.i64 != -1 && + ctx->item.u.u64 != LWSCOSE_WKSYMKP_KEY_VALUE) + goto bail; + + cps->gencrypto_eidx = LWS_GENCRYPTO_OCT_KEYEL_K; + break; + default: + lwsl_warn("%s: unknown kty\n", __func__); + goto bail; + } + break; + } + break; + + case LECPCB_VAL_BLOB_START: + if (!ctx->sp || !(ctx->st[ctx->sp - 1].ordinal & 1)) { + lwsl_warn("%s: unexpected blob\n", __func__); + goto bail; + } + + if (cps->cose_state == COSEKEY_META_KID) + break; + + /* + * Validate the association of the blob now, collect it into + * the temp buf in cps and then alloc and copy it into the + * related key element when it's at the end and the size known + */ + + cps->pos = 0; + if (cps->gencrypto_eidx >= 0) { + if (cps->ck->e[cps->gencrypto_eidx].buf) { + lwsl_warn("%s: e[%d] set twice %d\n", __func__, + cps->gencrypto_eidx, + cps->ck->e[cps->gencrypto_eidx].len); + /* key elements must only come at most once */ + goto bail; + } + break; + } + if (cps->meta_idx >= 0) + break; + + goto bail; + + case LECPCB_VAL_BLOB_CHUNK: + case LECPCB_VAL_BLOB_END: + if (cps->pos + ctx->npos > sizeof(cps->buf)) { + lwsl_warn("%s: oversize blob\n", __func__); + goto bail; + } + memcpy(cps->buf + cps->pos, ctx->buf, ctx->npos); + cps->pos += ctx->npos; + + if (reason == LECPCB_VAL_BLOB_CHUNK) + break; + + /* we have the key element data, let's make the ck element */ + if (cps->gencrypto_eidx >= 0) { + + if (cps->ck->e[cps->gencrypto_eidx].buf) + break; + + lws_ck_set_el(&cps->ck->e[cps->gencrypto_eidx], + (char *)cps->buf, cps->pos); + cps->gencrypto_eidx = -1; + break; + } + + + if (cps->meta_idx >= 0) { + lws_ck_set_el(&cps->ck->meta[cps->meta_idx], + (char *)cps->buf, cps->pos); + cps->meta_idx = -1; + } + cps->pos = 0; + break; + case LECPCB_VAL_STR_END: + if (cps->cose_state == LWSCOSE_WKOKP_CRV) { + cps->ck->cose_curve = lws_cose_curve_name_to_id(ctx->buf); + ke = &cps->ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV]; + ke->len = ctx->npos; + ke->buf = lws_malloc(ctx->npos, __func__); + if (!ke->buf) + goto bail; + memcpy(ke->buf, ctx->buf, ctx->npos); + } + + if (!lecp_parse_map_is_key(ctx) && + cps->cose_state == LWSCOSE_WKK_ALG) { + size_t n; + + for (n = 0; n < LWS_ARRAY_SIZE(wk_algs); n++) + if (ctx->npos == strlen(wk_algs[n]) && + !memcmp(ctx->buf, wk_algs[n], ctx->npos)) { + cps->ck->cose_alg = wk_alg_indexes[n]; + break; + } + + if (n == LWS_ARRAY_SIZE(wk_algs)) + /* key is for an alg we don't understand */ + lwsl_warn("%s: key for unknown alg %.*s\n", + __func__, (int)ctx->npos, ctx->buf); + + ke = &cps->ck->meta[COSEKEY_META_ALG]; + ke->len = ctx->npos; + ke->buf = lws_malloc(ctx->npos, __func__); + if (!ke->buf) + goto bail; + memcpy(ke->buf, ctx->buf, ctx->npos); + } + + break; + } + + return 0; + +bail: + lwsl_warn("%s: bail\n", __func__); + lws_cose_key_destroy(&cps->ck); + + if (cps->pkey_set) { + lws_cose_key_set_destroy(cps->pkey_set); + cps->pkey_set = NULL; + } + + return -1; +} + +void +lws_cose_key_destroy_elements(struct lws_gencrypto_keyelem *el, int m) +{ + int n; + + if (!el) + return; + + for (n = 0; n < m; n++) + if (el[n].buf) { + /* wipe all key material when it goes out of scope */ + lws_explicit_bzero(el[n].buf, el[n].len); + lws_free_set_NULL(el[n].buf); + el[n].len = 0; + } +} + +void +lws_cose_key_destroy(struct lws_cose_key **pck) +{ + struct lws_cose_key *ck = *pck; + + if (!ck) + return; + + lws_dll2_remove(&ck->list); + + lws_cose_key_destroy_elements(ck->e, LWS_ARRAY_SIZE(ck->e)); + lws_cose_key_destroy_elements(ck->meta, LWS_ARRAY_SIZE(ck->meta)); + + lws_free_set_NULL(*pck); +} + +static int +lws_cose_key_set_memb_remove(struct lws_dll2 *d, void *user) +{ + lws_cose_key_t *ck = lws_container_of(d, lws_cose_key_t, list); + + lws_dll2_remove(d); + lws_cose_key_destroy(&ck); + + return 0; +} + +void +lws_cose_key_set_destroy(lws_dll2_owner_t *o) +{ + lws_dll2_foreach_safe(o, NULL, lws_cose_key_set_memb_remove); +} + +lws_cose_key_t * +lws_cose_key_from_set(lws_dll2_owner_t *set, const uint8_t *kid, size_t kl) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(set)) { + lws_cose_key_t *ck = lws_container_of(p, lws_cose_key_t, list); + struct lws_gencrypto_keyelem *ke = &ck->meta[COSEKEY_META_KID]; + + if (!kid) /* always the first then */ + return ck; + + if (ke->buf && ke->len == (uint32_t)kl && + !memcmp(ke->buf, kid, ke->len)) + return ck; + + } lws_end_foreach_dll(p); + + return NULL; +} + +lws_cose_key_t * +lws_cose_key_generate(struct lws_context *context, cose_param_t cose_kty, + int use_mask, int bits, const char *curve, + const uint8_t *kid, size_t kl) +{ + struct lws_gencrypto_keyelem *ke; + lws_cose_key_t *ck; + size_t sn; + int n; + + ck = lws_zalloc(sizeof(*ck), __func__); + if (!ck) + return NULL; + + ck->kty = cose_kty; + ck->private_key = 1; + + if (use_mask & 0xfffe) { + int count = 0; + + for (n = 1; n < 15; n++) + if (use_mask & (1 << n)) + count++; + ke = &ck->meta[COSEKEY_META_KEY_OPS]; + ke->buf = lws_malloc((size_t)count, __func__); + if (!ke->buf) + goto fail; + ke->len = (uint32_t)count; + count = 0; + for (n = 1; n < 15; n++) + if (use_mask & (1 << n)) + ke->buf[count++] = (uint8_t)n; + } + + if (kid) { + ke = &ck->meta[COSEKEY_META_KID]; + ke->buf = lws_malloc(kl, __func__); + ke->len = (uint32_t)kl; + memcpy(ke->buf, kid, ke->len); + } + + switch (cose_kty) { + case LWSCOSE_WKKTV_RSA: + { + struct lws_genrsa_ctx ctx; + + memset(&ctx, 0, sizeof(ctx)); + ck->gencrypto_kty = LWS_GENCRYPTO_KTY_RSA; + + lwsl_notice("%s: generating %d bit RSA key\n", + __func__, bits); + n = lws_genrsa_new_keypair(context, &ctx, + LGRSAM_PKCS1_1_5, + ck->e, bits); + lws_genrsa_destroy(&ctx); + if (n) { + lwsl_err("%s: problem generating RSA key\n", + __func__); + goto fail; + } + } + break; + case LWSCOSE_WKKTV_SYMMETRIC: + + ck->gencrypto_kty = LWS_GENCRYPTO_KTY_OCT; + sn = (unsigned int)lws_gencrypto_bits_to_bytes(bits); + ke = &ck->e[LWS_GENCRYPTO_OCT_KEYEL_K]; + ke->buf = lws_malloc(sn, "oct"); + if (!ke->buf) + goto fail; + ke->len = (uint32_t)sn; + if (lws_get_random(context, ke->buf, sn) != sn) { + lwsl_err("%s: problem getting random\n", __func__); + goto fail; + } + break; + + case LWSCOSE_WKKTV_OKP: + case LWSCOSE_WKKTV_EC2: + { + struct lws_genec_ctx ctx; + + ck->gencrypto_kty = LWS_GENCRYPTO_KTY_EC; + + if (!curve) { + lwsl_err("%s: must have a named curve\n", __func__); + + goto fail; + } + + if (lws_genecdsa_create(&ctx, context, NULL)) + goto fail; + + ctx.genec_alg = LEGENEC_ECDSA; + lwsl_notice("%s: generating ECDSA key on curve %s\n", __func__, + curve); + + n = lws_genecdsa_new_keypair(&ctx, curve, ck->e); + lws_genec_destroy(&ctx); + if (n) { + lwsl_err("%s: problem generating ECDSA key\n", __func__); + goto fail; + } + /* trim the trailing NUL */ + ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve); + } + break; + + default: + lwsl_err("%s: unknown kty\n", __func__); + goto fail; + } + + return ck; + +fail: + lws_free_set_NULL(ck); + + return NULL; +} + +struct lws_cose_key * +lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb, + void *user, const uint8_t *in, size_t len) +{ + struct lws_cose_key_parse_state cps; + struct lecp_ctx ctx; + int m; + + memset(&cps, 0, sizeof(cps)); + + cps.per_key_cb = cb; + cps.user = user; + cps.pkey_set = pkey_set; + cps.gencrypto_eidx = -1; + + lecp_construct(&ctx, cb_cose_key, &cps, NULL, 0); + m = lecp_parse(&ctx, in, len); + lecp_destruct(&ctx); + + if (m < 0) { + lwsl_notice("%s: parse got %d\n", __func__, m); + if (cps.pkey_set) + lws_cose_key_set_destroy(cps.pkey_set); + + return NULL; + } + + switch (cps.ck->gencrypto_kty) { + case LWS_GENCRYPTO_KTY_UNKNOWN: + lwsl_notice("%s: missing or unknown ktys\n", __func__); + goto bail; + default: + break; + } + + return cps.ck; + +bail: + lws_cose_key_destroy(&cps.ck); + return NULL; +} + +/* gencrypto element orering -> cose key parameters */ + +static const signed char ckp[3][12] = { + { /* LWS_GENCRYPTO_KTY_OCT (1) */ + /* LWS_GENCRYPTO_OCT_KEYEL_K */ LWSCOSE_WKSYMKP_KEY_VALUE, + }, + { /* LWS_GENCRYPTO_KTY_RSA (2) */ + /* LWS_GENCRYPTO_RSA_KEYEL_E */ LWSCOSE_WKKPRSA_E, + /* LWS_GENCRYPTO_RSA_KEYEL_N */ LWSCOSE_WKKPRSA_N, + /* LWS_GENCRYPTO_RSA_KEYEL_D */ LWSCOSE_WKKPRSA_D, + /* LWS_GENCRYPTO_RSA_KEYEL_P */ LWSCOSE_WKKPRSA_P, + /* LWS_GENCRYPTO_RSA_KEYEL_Q */ LWSCOSE_WKKPRSA_Q, + /* LWS_GENCRYPTO_RSA_KEYEL_DP */ LWSCOSE_WKKPRSA_DP, + /* LWS_GENCRYPTO_RSA_KEYEL_DQ */ LWSCOSE_WKKPRSA_DQ, + /* LWS_GENCRYPTO_RSA_KEYEL_QT */ LWSCOSE_WKKPRSA_QINV, + /* LWS_GENCRYPTO_RSA_KEYEL_OTHER */ LWSCOSE_WKKPRSA_OTHER, + /* LWS_GENCRYPTO_RSA_KEYEL_RI */ LWSCOSE_WKKPRSA_RI, + /* LWS_GENCRYPTO_RSA_KEYEL_DI */ LWSCOSE_WKKPRSA_DI, + /* LWS_GENCRYPTO_RSA_KEYEL_TI */ LWSCOSE_WKKPRSA_TI, + }, + { /* LWS_GENCRYPTO_KTY_EC (3) */ + /* LWS_GENCRYPTO_EC_KEYEL_CRV */ LWSCOSE_WKECKP_CRV, + /* LWS_GENCRYPTO_EC_KEYEL_X */ LWSCOSE_WKECKP_X, + /* LWS_GENCRYPTO_EC_KEYEL_D */ LWSCOSE_WKECKP_D, + /* LWS_GENCRYPTO_EC_KEYEL_Y */ LWSCOSE_WKECKP_Y, + } +}; + +enum lws_lec_pctx_ret +lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags) +{ + cose_param_t pa = 0; + int n; + + if (!ctx->opaque[0]) { + + ctx->opaque[0] = 1; /* map pair count */ + ctx->opaque[1] = 1; /* element index */ + ctx->opaque[2] = 0; /* public mask */ + ctx->opaque[3] = 0; /* doing AGAIN */ + + switch (ck->gencrypto_kty) { + case LWS_GENCRYPTO_KTY_OCT: + /* nothing to differentiate */ + ctx->opaque[2] = 1 << LWS_GENCRYPTO_OCT_KEYEL_K; + break; + case LWS_GENCRYPTO_KTY_RSA: + ctx->opaque[2] = 1 << LWS_GENCRYPTO_RSA_KEYEL_E; + break; + case LWS_GENCRYPTO_KTY_EC: + ctx->opaque[2] = (1 << LWS_GENCRYPTO_EC_KEYEL_X) | + (1 << LWS_GENCRYPTO_EC_KEYEL_Y); + break; + default: + goto fail; + } + + if (flags & LWSJWKF_EXPORT_PRIVATE) + ctx->opaque[2] = 0xffff; + + /* + * We first need to find out how many CBOR map pairs we are + * planning to create, so we can set a fixed length map of the + * right size. + */ + + for (n = 0; n < (int)LWS_ARRAY_SIZE(ck->e); n++) + if ((ctx->opaque[2] & (1 << n)) && ck->e[n].buf) + ctx->opaque[0]++; + + /* + * We always issue kty, others may be + * + * KID / ALG / KEY_OPS / BASE_IV + */ + + if (ck->meta[COSEKEY_META_KID].buf) + ctx->opaque[0]++; + if (ck->meta[COSEKEY_META_ALG].buf) + ctx->opaque[0]++; + if (ck->meta[COSEKEY_META_KEY_OPS].buf) + ctx->opaque[0]++; + if (ck->meta[COSEKEY_META_BASE_IV].buf) + ctx->opaque[0]++; + + lws_lec_int(ctx, LWS_CBOR_MAJTYP_MAP, 0, (uint64_t)ctx->opaque[0]); + lws_lec_signed(ctx, LWSCOSE_WKK_KTY); + lws_lec_signed(ctx, (int64_t)ck->kty); + + if (ck->gencrypto_kty == LWS_GENCRYPTO_KTY_EC) { + struct lws_gencrypto_keyelem *ke = + &ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV]; + + if (!ke->buf || + ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV].len > 10) { + lwsl_err("%s: no curve type\n", __func__); + goto fail; + } + + pa = lws_cose_curve_name_to_id((const char *)ke->buf); + lws_lec_signed(ctx, LWSCOSE_WKECKP_CRV); + if (pa) + lws_lec_signed(ctx, pa); + else + lws_lec_printf(ctx, "%.*s", + (int)ke->len, ke->buf); + } + + + ctx->opaque[1] = COSEKEY_META_KID; + } + + /* + * Start from the second key meta, then do any elements that are set + */ + + while (ctx->buf != ctx->end) { + struct lws_gencrypto_keyelem *ke = NULL; + int cose_key_param = 0; + + if (lws_lec_scratch(ctx)) + break; + + if (ctx->opaque[1] == LWS_ARRAY_SIZE(ck->e) + + LWS_COUNT_COSE_KEY_ELEMENTS) + break; + + if (ctx->opaque[1] >= LWS_COUNT_COSE_KEY_ELEMENTS) { + n = ctx->opaque[1] - LWS_COUNT_COSE_KEY_ELEMENTS; + + if (ck->gencrypto_kty != LWS_GENCRYPTO_KTY_EC || + n != LWS_GENCRYPTO_EC_KEYEL_CRV) { + /* we didn't already encode his curve */ + + if ((ctx->opaque[2] & (1 << n)) && + ck->e[n].buf && ck->e[n].len) { + ke = &ck->e[n]; + cose_key_param = ckp[ck->gencrypto_kty - 1][n]; + } + } + } else + + switch (ctx->opaque[1]) { + + case COSEKEY_META_KID: /* bstr */ + if (ck->meta[COSEKEY_META_KID].buf) { + ke = &ck->meta[COSEKEY_META_KID]; + cose_key_param = LWSCOSE_WKK_KID; + // lwsl_hexdump_notice(ke->buf, ke->len); + } + break; + + case COSEKEY_META_ALG: /* int, tstr */ + if (ck->meta[COSEKEY_META_ALG].buf) { + ke = &ck->meta[COSEKEY_META_ALG]; + cose_key_param = LWSCOSE_WKK_ALG; + } + break; + + case COSEKEY_META_KEY_OPS: /* [ int ] */ + if (!ck->meta[COSEKEY_META_KEY_OPS].buf) + break; + ke = &ck->meta[COSEKEY_META_KEY_OPS]; + + n = (int)ke->len; + if (n > 10) + n = 10; + + /* + * We copy this array into scratch by hand now we + * made sure it will fit, we will never need AGAIN + */ + + lws_lec_signed(ctx, LWSCOSE_WKK_KEY_OPS); + lws_lec_int(ctx, LWS_CBOR_MAJTYP_ARRAY, 0, (uint64_t)n); + memcpy(&ctx->scratch[ctx->scratch_len], ke->buf, + (size_t)n); + ctx->scratch_len = (uint8_t)(ctx->scratch_len + (uint8_t)n); + ke = NULL; + break; + + case COSEKEY_META_BASE_IV: /* bstr */ + if (ck->meta[COSEKEY_META_BASE_IV].buf) { + ke = &ck->meta[COSEKEY_META_BASE_IV]; + cose_key_param = LWSCOSE_WKK_BASE_IV; + } + break; + + default: + break; + } + + if (ke && ke->buf && ke->len) { + + if (!ctx->opaque[3]) + lws_lec_signed(ctx, cose_key_param); + + /* binary string or text string? */ + if (ctx->opaque[1] == COSEKEY_META_KID || + ctx->opaque[1] == COSEKEY_META_BASE_IV || + ctx->opaque[1] >= LWS_COUNT_COSE_KEY_ELEMENTS) + n = (int)lws_lec_printf(ctx, "%.*b", + (int)ke->len, ke->buf); + else + n = (int)lws_lec_printf(ctx, "%.*s", + (int)ke->len, ke->buf); + + switch (n) { + case LWS_LECPCTX_RET_AGAIN: + ctx->opaque[3] = 1; + /* dump what we have and come back */ + continue; + case LWS_LECPCTX_RET_FAIL: + goto fail; + case LWS_LECPCTX_RET_FINISHED: + break; + } + } + + /* move on if we finished that guy */ + ctx->opaque[1]++; + ctx->opaque[3] = 0; + } + + ctx->used = lws_ptr_diff_size_t(ctx->buf, ctx->start); + + if (ctx->buf == ctx->end || ctx->scratch_len) + return LWS_LECPCTX_RET_AGAIN; + + ctx->opaque[0] = 0; + + return LWS_LECPCTX_RET_FINISHED; + +fail: + lwsl_notice("%s: failed\n", __func__); + + ctx->opaque[0] = 0; + + return LWS_LECPCTX_RET_FAIL; +} diff --git a/3rdparty/libwebsockets/lib/cose/cose_sign.c b/3rdparty/libwebsockets/lib/cose/cose_sign.c new file mode 100644 index 00000000..7c624de5 --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/cose_sign.c @@ -0,0 +1,543 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 "private-lib-cose.h" + +struct lws_cose_sign_context * +lws_cose_sign_create(const lws_cose_sign_create_info_t *info) +{ + struct lws_cose_sign_context *csc; + + /* you have to have prepared a cbor output context for us to use */ + assert(info->lec); + /* you have to provide at least one key in a cose_keyset */ + assert(info->keyset); + /* you have to provide an lws_context (for crypto random) */ + assert(info->cx); + + if (info->sigtype == SIGTYPE_MAC) { + lwsl_err("%s: only mac0 supported for signing\n", __func__); + return NULL; + } + + csc = lws_zalloc(sizeof(*csc), __func__); + if (!csc) + return NULL; + + csc->info = *info; + + return csc; +} + +int +lws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg, + const lws_cose_key_t *ck) +{ + lws_cose_sig_alg_t *si = lws_cose_sign_alg_create(csc->info.cx, ck, alg, + LWSCOSE_WKKO_SIGN); + + if (!si) + return 1; + + lws_dll2_add_tail(&si->list, &csc->algs); + + return 0; +} + +static signed char cose_tags[] = { + 0, + LWSCOAP_CONTENTFORMAT_COSE_SIGN, + LWSCOAP_CONTENTFORMAT_COSE_SIGN1, + LWSCOAP_CONTENTFORMAT_COSE_SIGN, + LWSCOAP_CONTENTFORMAT_COSE_MAC, + LWSCOAP_CONTENTFORMAT_COSE_MAC0 +}; + +static void +lws_cose_sign_hashing(struct lws_cose_sign_context *csc, + const uint8_t *in, size_t in_len) +{ + //lwsl_hexdump_warn(in, in_len); + + assert(in_len); + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(&csc->algs)) { + lws_cose_sig_alg_t *alg = lws_container_of(p, + lws_cose_sig_alg_t, list); + + if (lws_cose_sign_alg_hash(alg, in, in_len)) + alg->failed = 1; + } lws_end_foreach_dll_safe(p, tp); +} + +/* + * These chunks may be payload or application AAD being emitted into the + * signed object somewhere else. But we do not emit them ourselves here + * (since other non-emitted things are also hashed by us) and so can always + * deal with the whole in_len in one step. + */ + +enum lws_lec_pctx_ret +lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, + const uint8_t *in, size_t in_len) +{ + uint8_t lbuf[MAX_BLOBBED_PARAMS], lb[9]; + const struct lws_gencrypto_keyelem *ke; + enum lws_lec_pctx_ret ret; + lws_lec_pctx_t lec, lec1; + lws_cose_sig_alg_t *alg; + uint8_t c; + size_t s; + + switch (csc->tli) { + case ST_UNKNOWN: + /* + * We need to figure out what signing structure we need to use, + * given the algorithms that are in it. So let's have a look + * and decide. + */ + + if (!csc->algs.count) { + lwsl_err("%s: must add at least one signature\n", __func__); + return 1; + } + + csc->type = SIGTYPE_MULTI; + alg = lws_container_of(csc->algs.head, lws_cose_sig_alg_t, list); + + switch (alg->cose_alg) { + case LWSCOSE_WKAHMAC_256_64: + case LWSCOSE_WKAHMAC_256_256: + case LWSCOSE_WKAHMAC_384_384: + case LWSCOSE_WKAHMAC_512_512: +// if (csc->info.sigtype == SIGTYPE_MAC0) + csc->type = SIGTYPE_MAC0; +// else +// csc->type = SIGTYPE_MAC; + break; + } + + if (csc->algs.count == 1) { + if (!csc->info.sigtype && csc->type == SIGTYPE_MAC) { + if (csc->info.flags & LCSC_FL_ADD_CBOR_PREFER_MAC0) + csc->type = SIGTYPE_MAC0; + } else + if (!csc->info.sigtype || + csc->info.sigtype == SIGTYPE_SINGLE) /* ie, if no hint */ + csc->type = SIGTYPE_SINGLE; + } + + lwsl_notice("%s: decided on type %d\n", __func__, csc->type); + + /* + * Start emitting the appropriate tag if that's requested + */ + + if (csc->info.flags & LCSC_FL_ADD_CBOR_TAG) { + ret = lws_lec_printf(csc->info.lec, "%t(", + cose_tags[csc->type]); + + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + } + + /* The */ + c = 0; + switch (csc->type) { + case SIGTYPE_MAC0: + case SIGTYPE_MULTI: + case SIGTYPE_SINGLE: + c = 0x84; + break; + case SIGTYPE_MAC: + c = 0x85; + break; + default: + break; + } + + /* The outer array */ + csc->info.lec->scratch[csc->info.lec->scratch_len++] = c; + + /* + * Then, let's start hashing with the sigtype constant part + */ + + lws_cose_sign_hashing(csc, sig_mctx[csc->type], + sig_mctx_len[csc->type]); + + csc->tli = ST_OUTER_PROTECTED; + csc->subsequent = 0; + + /* fallthru */ + + case ST_OUTER_PROTECTED: + + /* + * We need to list and emit any outer protected data as a map + * into its own buffer, then emit that into the output as a bstr + */ + + switch (csc->type) { + case SIGTYPE_SINGLE: + case SIGTYPE_MAC0: + alg = lws_container_of(csc->algs.head, + lws_cose_sig_alg_t, list); + + lws_lec_init(&lec, lbuf, sizeof(lbuf)); + + /* we know it will fit... but coverity doesn't */ + ret = lws_lec_printf(&lec, "{1:%lld}", + (long long)alg->cose_alg); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + + lws_lec_scratch(&lec); + + if (!csc->subsequent) { + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, + lec.used); + lws_cose_sign_hashing(csc, lec1.scratch, + lec1.scratch_len); + lws_cose_sign_hashing(csc, lec.start, lec.used); + ret = lws_lec_printf(csc->info.lec, "%.*b", + (int)lec.used, lec.start); + + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + csc->subsequent = 1; + } + break; + case SIGTYPE_MAC: + case SIGTYPE_MULTI: + lws_lec_init(&lec, lbuf, sizeof(lbuf)); + lws_lec_int(&lec, LWS_CBOR_MAJTYP_BSTR, 0, 0); + lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_BSTR, 0, 0); + lws_lec_scratch(&lec); + lec.used = lws_ptr_diff_size_t(lec.buf, lec.start); + lws_cose_sign_hashing(csc, lec.start, + lec.used); + break; + default: + lec.used = 0; + break; + } + + csc->tli = ST_OUTER_UNPROTECTED; + + /* fallthru */ + + case ST_OUTER_UNPROTECTED: + + /* + * We need to list and emit any outer unprotected data, as + * an inline cbor map + */ + + switch (csc->type) { + case SIGTYPE_SINGLE: + case SIGTYPE_MAC0: + alg = lws_container_of(csc->algs.head, + lws_cose_sig_alg_t, list); + ke = &alg->cose_key->meta[COSEKEY_META_KID]; + if (ke->len) { + ret = lws_lec_printf(csc->info.lec, "{%d:%.*b}", + LWSCOSE_WKL_KID, + (int)ke->len, ke->buf); + + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + } + /* hack for no extra data */ + + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 0); + lws_cose_sign_hashing(csc, lec1.scratch, + lec1.scratch_len); + break; + case SIGTYPE_MAC: + case SIGTYPE_MULTI: + + lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_BSTR, 0, 0); + + /* + * For cose-sign, we need to feed each sig alg its alg- + * specific protected data into the hash before letting + * all the hashes see the payload + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(&csc->algs)) { + alg = lws_container_of(p, lws_cose_sig_alg_t, list); + + lws_lec_init(&lec, lbuf, sizeof(lbuf)); + + /* we know it will fit... but coverity doesn't... */ + ret = lws_lec_printf(&lec, "{1:%lld}", + (long long)alg->cose_alg); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, + lec.used); + + // lwsl_hexdump_warn(lec1.scratch, lec1.scratch_len); + // lwsl_hexdump_warn(lec.start, lec.used); + if (lws_cose_sign_alg_hash(alg, lec1.scratch, + lec1.scratch_len)) + alg->failed = 1; + if (lws_cose_sign_alg_hash(alg, lec.start, + lec.used)) + alg->failed = 1; + + } lws_end_foreach_dll_safe(p, tp); + + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 0); + lws_cose_sign_hashing(csc, lec1.scratch, + lec1.scratch_len); + + break; + default: + ret = lws_lec_printf(csc->info.lec, "{}"); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + break; + } + + csc->tli = ST_OUTER_PAYLOAD; + csc->subsequent = 0; + + /* Prepare the payload BSTR */ + + lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_BSTR, 0, + csc->info.inline_payload_len); + + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, + csc->info.inline_payload_len); + lws_cose_sign_hashing(csc, lec1.scratch, + lec1.scratch_len); + + lws_lec_scratch(csc->info.lec); + + csc->rem_pay = csc->info.inline_payload_len; + + /* fallthru */ + + case ST_OUTER_PAYLOAD: + + if (csc->along) { + in += csc->along; + in_len -= csc->along; + } + + lws_lec_scratch(csc->info.lec); + + if (csc->rem_pay) { + + lws_cose_sign_hashing(csc, in, in_len); + + /* + * in / in_len is the payload chunk + */ + + s = lws_ptr_diff_size_t(csc->info.lec->end, + csc->info.lec->buf); + if (s > (size_t)csc->rem_pay) + s = (size_t)csc->rem_pay; + if (s > in_len) + s = in_len; + + memcpy(csc->info.lec->buf, in, s); + csc->info.lec->buf += s; + csc->info.lec->used = lws_ptr_diff_size_t( + csc->info.lec->buf, + csc->info.lec->start); + csc->rem_pay -= s; + + csc->along = s; + + return LWS_LECPCTX_RET_AGAIN; + } + + /* finished with rem_pay */ + + if (csc->type == SIGTYPE_MULTI) { + + csc->alg = lws_container_of(csc->algs.head, + lws_cose_sig_alg_t, list); + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_ARRAY, 0, + csc->algs.count); + lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_ARRAY, 0, + csc->algs.count); + csc->tli = ST_INNER_PROTECTED; + goto inner_protected; + } + csc->tli = ST_OUTER_SIGN1_SIGNATURE; + csc->along = 0; + + /* fallthru */ + + case ST_OUTER_SIGN1_SIGNATURE: + + alg = lws_container_of(lws_dll2_get_head(&csc->algs), + lws_cose_sig_alg_t, list); + + if (!alg->completed) + lws_cose_sign_alg_complete(alg); + if (alg->failed) + return LWS_LECPCTX_RET_FAIL; + + ret = lws_lec_printf(csc->info.lec, "%.*b", + (int)alg->rhash_len, alg->rhash); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + + if (csc->type == SIGTYPE_MAC) { + csc->alg = lws_container_of(csc->algs.head, + lws_cose_sig_alg_t, list); + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_ARRAY, 0, + csc->algs.count); + lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_ARRAY, 0, + csc->algs.count); + csc->tli = ST_INNER_PROTECTED; + goto inner_protected; + } + + break; + + case ST_INNER_PROTECTED: +inner_protected: + + /* + * We need to list and emit any outer protected data as a map + * into its own buffer, then emit that into the output as a bstr + */ + + switch (csc->type) { + case SIGTYPE_MAC: + case SIGTYPE_MULTI: + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_ARRAY, 0, 3); + + lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_ARRAY, 0, 3); + + lws_lec_init(&lec, lbuf, sizeof(lbuf)); + + /* we know it will fit */ + lws_lec_printf(&lec, "{1:%lld}", + (long long)csc->alg->cose_alg); + + lws_lec_init(&lec1, lb, sizeof(lb)); + lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, + lec.used); + if (lws_lec_printf(csc->info.lec, "{1:%lld}", + (long long)csc->alg->cose_alg) != LWS_LECPCTX_RET_FINISHED) + /* coverity */ + return 0; + break; + default: + lec.used = 0; + break; + } + + + csc->tli = ST_INNER_UNPROTECTED; + + /* fallthru */ + + case ST_INNER_UNPROTECTED: + + switch (csc->type) { + case SIGTYPE_MULTI: + alg = lws_container_of(csc->algs.head, + lws_cose_sig_alg_t, list); + ke = &alg->cose_key->meta[COSEKEY_META_KID]; + if (ke->len) { + ret = lws_lec_printf(csc->info.lec, "{%d:%.*b}", + LWSCOSE_WKL_KID, + (int)ke->len, ke->buf); + + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + } + break; + default: + ret = lws_lec_printf(csc->info.lec, "{}"); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + break; + } + + lws_cose_sign_alg_complete(csc->alg); + if (csc->alg->failed) + return LWS_LECPCTX_RET_FAIL; + csc->tli = ST_INNER_SIGNATURE; + + /* fallthru */ + + case ST_INNER_SIGNATURE: + + ret = lws_lec_printf(csc->info.lec, "%.*b", + (int)csc->alg->rhash_len, csc->alg->rhash); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + + if (csc->alg->list.next) { + csc->alg = (lws_cose_sig_alg_t *)csc->alg->list.next; + csc->tli = ST_INNER_PROTECTED; + } + break; + + } + + return 0; +} + +void +lws_cose_sign_destroy(struct lws_cose_sign_context **_csc) +{ + struct lws_cose_sign_context *csc = *_csc; + + if (!csc) + return; + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(&csc->algs)) { + lws_cose_sig_alg_t *alg = lws_container_of(p, + lws_cose_sig_alg_t, list); + + lws_dll2_remove(p); + lws_cose_sign_alg_destroy(&alg); + } lws_end_foreach_dll_safe(p, tp); + + lws_free_set_NULL(*_csc); +} diff --git a/3rdparty/libwebsockets/lib/cose/cose_sign_alg.c b/3rdparty/libwebsockets/lib/cose/cose_sign_alg.c new file mode 100644 index 00000000..71d52454 --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/cose_sign_alg.c @@ -0,0 +1,271 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 "private-lib-cose.h" + +lws_cose_sig_alg_t * +lws_cose_sign_alg_create(struct lws_context *cx, const lws_cose_key_t *ck, + cose_param_t cose_alg, int op) +{ + lws_cose_sig_alg_t *alg = lws_zalloc(sizeof(*alg), __func__); + const struct lws_gencrypto_keyelem *ke; + enum lws_genhmac_types ghm; + enum lws_genhash_types gh; + const char *crv; + + if (!alg) + return NULL; + + alg->cose_alg = cose_alg; + alg->cose_key = ck; + + switch (cose_alg) { + + /* ECDSA algs */ + + case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ + crv = "P-256"; + gh = LWS_GENHASH_TYPE_SHA256; + alg->keybits = 256; + goto ecdsa; + case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ + crv = "P-384"; + gh = LWS_GENHASH_TYPE_SHA384; + alg->keybits = 384; + goto ecdsa; + case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ + crv = "P-521"; + gh = LWS_GENHASH_TYPE_SHA512; + alg->keybits = 521; +ecdsa: + + /* the key is good for this? */ + + if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_EC2, cose_alg, + op, crv)) + goto bail_ecdsa; + + if (lws_genhash_init(&alg->hash_ctx, gh)) + goto bail_ecdsa; + + if (lws_genecdsa_create(&alg->u.ecdsactx, cx, lws_ec_curves)) { + lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", + __func__); + goto bail_ecdsa1; + } + + if (lws_genecdsa_set_key(&alg->u.ecdsactx, ck->e)) { + lwsl_notice("%s: ec key import fail\n", __func__); + goto bail_ecdsa2; + } + + break; + + /* HMAC algs */ + + case LWSCOSE_WKAHMAC_256_64: + ghm = LWS_GENHMAC_TYPE_SHA256; + alg->keybits = 64; + goto hmac; + case LWSCOSE_WKAHMAC_256_256: + ghm = LWS_GENHMAC_TYPE_SHA256; + alg->keybits = 256; + goto hmac; + case LWSCOSE_WKAHMAC_384_384: + ghm = LWS_GENHMAC_TYPE_SHA384; + alg->keybits = 384; + goto hmac; + case LWSCOSE_WKAHMAC_512_512: + ghm = LWS_GENHMAC_TYPE_SHA512; + alg->keybits = 512; + +hmac: + if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_SYMMETRIC, + cose_alg, op, NULL)) + goto bail_hmac; + + ke = &ck->e[LWS_GENCRYPTO_OCT_KEYEL_K]; + if (lws_genhmac_init(&alg->u.hmacctx, ghm, ke->buf, ke->len)) + goto bail_hmac; + + break; + + /* RSASSA algs */ + + case LWSCOSE_WKARSA_ALG_RS256: + gh = LWS_GENHASH_TYPE_SHA256; + goto rsassa; + + case LWSCOSE_WKARSA_ALG_RS384: + gh = LWS_GENHASH_TYPE_SHA384; + goto rsassa; + + case LWSCOSE_WKARSA_ALG_RS512: + gh = LWS_GENHASH_TYPE_SHA512; + +rsassa: + if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_RSA, cose_alg, + op, NULL)) + goto bail_hmac; + + alg->keybits = (int)ck->e[LWS_GENCRYPTO_RSA_KEYEL_N].len * 8; + + if (lws_genhash_init(&alg->hash_ctx, gh)) + goto bail_hmac; + + if (lws_genrsa_create(&alg->u.rsactx, ck->e, cx, + LGRSAM_PKCS1_1_5, gh)) { + lwsl_notice("%s: lws_genrsa_create fail\n", __func__); + goto bail_hmac; + } + break; + + default: + lwsl_warn("%s: unsupported alg %lld\n", __func__, + (long long)cose_alg); + goto bail_hmac; + } + + return alg; + +bail_ecdsa2: + lws_genec_destroy(&alg->u.ecdsactx); +bail_ecdsa1: + lws_genhash_destroy(&alg->hash_ctx, NULL); +bail_ecdsa: + lws_free(alg); + + return NULL; + +bail_hmac: + lws_free(alg); + + return NULL; +} + +int +lws_cose_sign_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len) +{ +#if defined(VERBOSE) + lwsl_hexdump_warn(in, in_len); +#endif + + switch (alg->cose_alg) { + + case LWSCOSE_WKAHMAC_256_64: + case LWSCOSE_WKAHMAC_256_256: + case LWSCOSE_WKAHMAC_384_384: + case LWSCOSE_WKAHMAC_512_512: + return lws_genhmac_update(&alg->u.hmacctx, in, in_len); + } + + /* EC, rsa are just making the hash before signing */ + + return lws_genhash_update(&alg->hash_ctx, in, in_len); +} + +/* + * We fill up alg-> rhash and rhash_len with the results, and destroy the + * crypto pieces cleanly. Call lws_cose_sign_alg_destroy() afterwards to + * clean up the alg itself. + */ + +void +lws_cose_sign_alg_complete(lws_cose_sig_alg_t *alg) +{ + uint8_t digest[LWS_GENHASH_LARGEST]; + unsigned int bytes; + uint8_t htype; + size_t hs; + + if (alg->completed) + return; + + switch (alg->cose_alg) { + case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ + case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ + case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ + hs = lws_genhash_size(alg->hash_ctx.type); + bytes = (unsigned int)lws_gencrypto_bits_to_bytes(alg->keybits); + lws_genhash_destroy(&alg->hash_ctx, digest); + alg->rhash_len = 0; + lwsl_notice("alg keybits %d hs %d\n", (int)alg->keybits, (int)hs); + if (!alg->failed && + lws_genecdsa_hash_sign_jws(&alg->u.ecdsactx, digest, + alg->hash_ctx.type, + (int)alg->keybits, alg->rhash, + 2u * bytes) >= 0) + alg->rhash_len = (int)(2 * bytes); + else + alg->failed = 1; + + lws_genec_destroy(&alg->u.ecdsactx); + break; + + case LWSCOSE_WKAHMAC_256_64: + case LWSCOSE_WKAHMAC_256_256: + case LWSCOSE_WKAHMAC_384_384: + case LWSCOSE_WKAHMAC_512_512: + alg->rhash_len = (int)lws_genhmac_size(alg->u.hmacctx.type); + if (alg->cose_alg == LWSCOSE_WKAHMAC_256_64) + alg->rhash_len = 8; + + if (lws_genhmac_destroy(&alg->u.hmacctx, alg->rhash)) { + lwsl_err("%s: destroy failed\n", __func__); + break; + } + break; + + case LWSCOSE_WKARSA_ALG_RS256: + case LWSCOSE_WKARSA_ALG_RS384: + case LWSCOSE_WKARSA_ALG_RS512: + bytes = (unsigned int)lws_gencrypto_bits_to_bytes(alg->keybits); + htype = alg->hash_ctx.type; + + if (!lws_genhash_destroy(&alg->hash_ctx, digest) && + !alg->failed && + lws_genrsa_hash_sign(&alg->u.rsactx, digest, htype, + alg->rhash, bytes) >= 0) + alg->rhash_len = (int)bytes; + else + lwsl_err("%s: lws_genrsa_hash_sign\n", __func__); + + lws_genrsa_destroy(&alg->u.rsactx); + break; + + default: + break; + } + + alg->completed = 1; +} + +void +lws_cose_sign_alg_destroy(lws_cose_sig_alg_t **_alg) +{ + lws_dll2_remove(&(*_alg)->list); + lws_cose_sign_alg_complete(*_alg); + lws_free_set_NULL(*_alg); +} diff --git a/3rdparty/libwebsockets/lib/cose/cose_validate.c b/3rdparty/libwebsockets/lib/cose/cose_validate.c new file mode 100644 index 00000000..1b9f3f3e --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/cose_validate.c @@ -0,0 +1,1051 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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. + * + * cose_sign handling + * + * Validation: + * + * - we put all our pieces and results in an lwsac in the parse state object + * + * - we collect pieces needed for sig validation into lwsac elements + * + * - we go through each signature making discrete results in the lwsac for + * the user code to assess + */ + +#include "private-lib-core.h" +#include "private-lib-cose.h" + +const uint8_t *sig_mctx[] = { (uint8_t *)"", + (uint8_t *)"\x85\x69""Signature", + (uint8_t *)"\x84\x6a""Signature1", + (uint8_t *)"\x85\x6f""CounterSignature", + (uint8_t *)"\x84\x63""MAC", + (uint8_t *)"\x84\x64""MAC0", +}; +uint8_t sig_mctx_len[] = { 0, 11, 12, 17, 5, 6 }; + +struct alg_names { + const char *name; + cose_param_t alg; +} alg_names[] = { + { "ES256", LWSCOSE_WKAECDSA_ALG_ES256 }, + { "ES384", LWSCOSE_WKAECDSA_ALG_ES384 }, + { "ES512", LWSCOSE_WKAECDSA_ALG_ES512 }, + { "HS256_64", LWSCOSE_WKAHMAC_256_64 }, + { "HS256", LWSCOSE_WKAHMAC_256_256 }, + { "HS384", LWSCOSE_WKAHMAC_384_384 }, + { "HS512", LWSCOSE_WKAHMAC_512_512 }, + { "RS256", LWSCOSE_WKARSA_ALG_RS256 }, + { "RS384", LWSCOSE_WKARSA_ALG_RS384 }, + { "RS512", LWSCOSE_WKARSA_ALG_RS512 }, +}; + +/* + * The Sig_structure plaintext is new temp CBOR made up from pieces from the + * cose_sign, cose_signature, and payload in a specific order + * + * tstr context string + * bstr 0-len or protected body headers + * bstr (Missing for sign1) 0-len or protected signer headers + * bstr 0-len or protected application part + * bstr the payload + * + * We are getting CBOR with an optional outer tag and then an array of exactly + * 4 items in a fixed order + * + * [ + * protected headers: bstr containing a map (captured as CBOR in cps->ph[]) + * unprotected: map: for sign1, eg, the alg (!?), the kid + * payload: bstr + * if sign: signatures: [ cose_signature struct array, + * each is a 3-element array + * [ + * protected: bstr containing a map: (eg, the alg) (captured as CBOR) + * unprotected: map: (eg, the kid) + * signature: bstr + * ] + * if sign1: bstr containing signature + * ] + * + * The last signatures field may be an array of signatures, or a single + * cose_signature object for cose_sign1. + * + * For cose_sign1, we know the signature alg before the payload and can do it + * in a single pass. But for sign, we do not know the signature algs until + * after the payload, which is an unfortunate oversight in cose_sign, meaning we + * cannot hash the payload one or more ways in a single pass. + */ + +#if defined(VERBOSE) +const char *cose_sections[] = { + "ST_UNKNOWN", + + "ST_OUTER_PROTECTED", + "ST_OUTER_UNPROTECTED", + "ST_OUTER_PAYLOAD", + "ST_OUTER_SIGN1_SIGNATURE", + + "ST_OUTER_SIGN_SIGARRAY", + + "ST_OUTER_MACTAG", + + "ST_INNER_PROTECTED", + "ST_INNER_UNPROTECTED", + "ST_INNER_SIGNATURE", + + "ST_INNER_EXCESS", +}; +#endif + +const char * +lws_cose_alg_to_name(cose_param_t alg) +{ + size_t n; + + for (n = 0; n < LWS_ARRAY_SIZE(alg_names); n++) + if (alg_names[n].alg == alg) + return alg_names[n].name; + + return "unknown_alg"; +} + +cose_param_t +lws_cose_name_to_alg(const char *name) +{ + size_t n; + + for (n = 0; n < LWS_ARRAY_SIZE(alg_names); n++) + if (!strcmp(alg_names[n].name, name)) + return alg_names[n].alg; + + return 0; +} + +static size_t +bstr_len(uint8_t *t, size_t buflen, uint8_t opcode, uint64_t len) +{ + uint8_t *ot = t; + + if (buflen < 9) + return 0; + + if (len < 24) { + *t = (uint8_t)(opcode | len); + + return 1; + } + if (len < 256) { + *t++ = opcode | LWS_CBOR_1; + goto b; + } + if (len < 65536) { + *t++ = opcode | LWS_CBOR_2; + goto b1; + } + if (len < 0xffffffffu) { + *t++ = opcode | LWS_CBOR_4; + goto b2; + } + + *t++ = opcode | LWS_CBOR_8; + + *t++ = (uint8_t)(len >> 56); + *t++ = (uint8_t)(len >> 48); + *t++ = (uint8_t)(len >> 40); + *t++ = (uint8_t)(len >> 32); + +b2: + *t++ = (uint8_t)(len >> 24); + *t++ = (uint8_t)(len >> 16); +b1: + *t++ = (uint8_t)(len >> 8); +b: + *t++ = (uint8_t)len; + + return lws_ptr_diff_size_t(t, ot); +} + +static int +apply_external(struct lws_cose_validate_context *cps) +{ + lws_cose_sig_alg_t *alg; + uint8_t t[9]; + + alg = lws_container_of(cps->algs.head, lws_cose_sig_alg_t, list); + if (!alg) + /* expected if no key */ + return 0; + + /* get the external payload first, if any indicated */ + + if (cps->info.ext_len) { + lws_cose_sig_ext_pay_t ex; + size_t s; + + s = bstr_len(t, sizeof(t), LWS_CBOR_MAJTYP_BSTR, + cps->info.ext_len); + if (lws_cose_val_alg_hash(alg, t, s)) + return 1; + + memset(&ex, 0, sizeof(ex)); + ex.cps = cps; + + do { + int n; + + ex.xl = 0; + n = cps->info.ext_cb(&ex); + + if (ex.xl && + lws_cose_val_alg_hash(alg, ex.ext, ex.xl)) + return 1; + + if (n == LCOSESIGEXTCB_RET_ERROR) + return 1; + + if (n == LCOSESIGEXTCB_RET_FINISHED) + break; + } while (1); + } + + return 0; +} + +static int +create_alg(struct lecp_ctx *ctx, struct lws_cose_validate_context *cps) +{ + lws_cose_validate_param_stack_t *sl = &cps->st[cps->sp], *sl0 = &cps->st[0]; + lws_cose_validate_res_t *res; + lws_cose_sig_alg_t *alg; + lws_cose_key_t *ck; + uint8_t *p; + size_t s; + + /* with sign1, we can hash the payload in a + * single pass */ + + ck = lws_cose_key_from_set(cps->info.keyset, sl->kid.buf, sl->kid.len); + if (!ck) { + lwsl_notice("%s: no key\n", __func__); + lwsl_hexdump_notice(sl->kid.buf, sl->kid.len); + goto no_key_or_alg; + } + + // lwsl_notice("%s: cps->alg %d\n", __func__, (int)cps->alg); + + alg = lws_cose_val_alg_create(cps->info.cx, ck, cps->st[0].alg, + LWSCOSE_WKKO_VERIFY); + if (!alg) { + lwsl_info("%s: no alg\n", __func__); + +no_key_or_alg: + /* + * We can't create the alg then, so we can't normally + * create a result object. Create one especially for this + * case and continue on + */ + + res = lws_zalloc(sizeof(*res), __func__); + if (res) { + res->result = -1001; + + lws_dll2_add_tail(&res->list, &cps->results); + } + + return 0; + } + + lws_dll2_add_tail(&alg->list, &cps->algs); + + /* + * Hash step 1: The first hash content depends on + * sign/sign1/csign/mac/mac0 constant bstr + */ + + if (lws_cose_val_alg_hash(alg, sig_mctx[cps->info.sigtype], + sig_mctx_len[cps->info.sigtype])) + goto bail; + + /* + * Hash step 2: A zero-length bstr, or a copy of the + * OUTER protected headers + * + * A zero-entry map alone becomes a zero- + * length bstr + */ + + if (sl0->ph_pos[0] < 2) { + /* nothing to speak of */ + sl0->ph[0][0] = LWS_CBOR_MAJTYP_BSTR; + p = &sl0->ph[0][0]; + s = 1; + } else { + if (sl0->ph_pos[0] < 24) { + sl0->ph[0][2] = (uint8_t) + (LWS_CBOR_MAJTYP_BSTR | sl0->ph_pos[0]); + p = &sl0->ph[0][2]; + s = (size_t)sl0->ph_pos[0] + 1; + } else { + sl0->ph[0][1] = LWS_CBOR_MAJTYP_BSTR | + LWS_CBOR_1; + sl0->ph[0][2] = (uint8_t)sl0->ph_pos[0]; + p = &sl0->ph[0][1]; + s = (size_t)sl0->ph_pos[0] + 2; + } + } + + if (lws_cose_val_alg_hash(alg, p, s)) + goto bail; + + /* + * Hash step 3: Protected signer headers (Elided for sign1) + */ + + if (cps->info.sigtype == SIGTYPE_MULTI) { + if (sl->ph_pos[2] < 2) { + /* nothing to speak of */ + sl->ph[2][0] = LWS_CBOR_MAJTYP_BSTR; + p = &sl->ph[2][0]; + s = 1; + } else { + if (sl->ph_pos[2] < 24) { + sl->ph[2][2] = (uint8_t) + (LWS_CBOR_MAJTYP_BSTR | sl->ph_pos[2]); + p = &sl->ph[2][2]; + s = (size_t)sl->ph_pos[2] + 1; + } else { + sl->ph[2][1] = LWS_CBOR_MAJTYP_BSTR | + LWS_CBOR_1; + sl->ph[2][2] = (uint8_t)sl->ph_pos[2]; + p = &sl->ph[2][1]; + s = (size_t)sl->ph_pos[2] + 2; + } + } + + if (lws_cose_val_alg_hash(alg, p, s)) + goto bail; + } + + /* Hash step 4: bstr for applictation protected pieces + * empty for now + */ + + if (!cps->info.ext_len) { /* ie, if no app data */ + uint8_t u = LWS_CBOR_MAJTYP_BSTR; + if (lws_cose_val_alg_hash(alg, &u, 1)) + goto bail; + } + + /* + * The final part is the payload in its own bstr, as + * we get it if sign1, else replayed from a cache in heap + */ + + if (cps->info.sigtype == SIGTYPE_SINGLE) + return 0; + + if (!cps->payload_stash) { + lwsl_notice("%s: no payload stash\n", __func__); + goto bail; + } + + apply_external(cps); + + if (lws_cose_val_alg_hash(alg, cps->payload_stash, cps->payload_pos)) + goto bail; +lwsl_notice("a %d\n", (int)cps->sig_agg_pos); + + lws_cose_val_alg_destroy(cps, &alg, (const uint8_t *)cps->sig_agg, + cps->sig_agg_pos); + + return 0; + +bail: + return 1; +} + +#if defined(VERBOSE) +static const char * const reason_names[] = { + "LECPCB_CONSTRUCTED", + "LECPCB_DESTRUCTED", + "LECPCB_START", + "LECPCB_COMPLETE", + "LECPCB_FAILED", + "LECPCB_PAIR_NAME", + "LECPCB_VAL_TRUE", + "LECPCB_VAL_FALSE", + "LECPCB_VAL_NULL", + "LECPCB_VAL_NUM_INT", + "LECPCB_VAL_RESERVED", /* float in lejp */ + "LECPCB_VAL_STR_START", + "LECPCB_VAL_STR_CHUNK", + "LECPCB_VAL_STR_END", + "LECPCB_ARRAY_START", + "LECPCB_ARRAY_END", + "LECPCB_OBJECT_START", + "LECPCB_OBJECT_END", + "LECPCB_TAG_START", + "LECPCB_TAG_END", + "LECPCB_VAL_NUM_UINT", + "LECPCB_VAL_UNDEFINED", + "LECPCB_VAL_FLOAT16", + "LECPCB_VAL_FLOAT32", + "LECPCB_VAL_FLOAT64", + "LECPCB_VAL_SIMPLE", + "LECPCB_VAL_BLOB_START", + "LECPCB_VAL_BLOB_CHUNK", + "LECPCB_VAL_BLOB_END", + "LECPCB_ARRAY_ITEM_START", + "LECPCB_ARRAY_ITEM_END", + "LECPCB_LITERAL_CBOR" +}; +#endif + +static int +ph_index(struct lws_cose_validate_context *cps) +{ + switch (cps->tli) { + case ST_OUTER_PROTECTED: + return 0; + case ST_OUTER_UNPROTECTED: + return 1; + case ST_INNER_PROTECTED: + return 2; + case ST_INNER_UNPROTECTED: + return 3; + } + + assert(0); + return 0; +} + +static signed char +cb_cose_sig(struct lecp_ctx *ctx, char reason) +{ + struct lws_cose_validate_context *cps = + (struct lws_cose_validate_context *)ctx->user; + lws_cose_validate_param_stack_t *sl; + struct lws_gencrypto_keyelem *ke; + lws_cose_sig_alg_t *alg; + uint8_t t[9]; + size_t s; + int hi; + +#if defined(VERBOSE) + lwsl_notice("%s: %s, tli %s, sub %d, ppos %d, sp %d\n", __func__, + reason_names[reason & 0x1f], cose_sections[cps->tli], + cps->sub, ctx->pst[ctx->pst_sp].ppos, cps->sp); +#endif + + switch (reason) { + case LECPCB_CONSTRUCTED: + break; + + case LECPCB_TAG_START: + + lwsl_notice("%s: tag sigtype %d\n", __func__, cps->info.sigtype); + + switch (cps->info.sigtype) { + default: + assert(0); + break; + case SIGTYPE_UNKNOWN: + /* it means use the tag value to set the type */ + switch (ctx->item.u.u64) { + case LWSCOAP_CONTENTFORMAT_COSE_SIGN: + cps->info.sigtype = SIGTYPE_MULTI; + break; + case LWSCOAP_CONTENTFORMAT_COSE_SIGN1: + cps->info.sigtype = SIGTYPE_SINGLE; + break; +// case LWSCOAP_CONTENTFORMAT_COSE_SIGN__: +// cps->info.sigtype = SIGTYPE_COUNTERSIGNED; +// break; + case LWSCOAP_CONTENTFORMAT_COSE_MAC0: + cps->info.sigtype = SIGTYPE_MAC0; + break; + case LWSCOAP_CONTENTFORMAT_COSE_MAC: + cps->info.sigtype = SIGTYPE_MAC; + break; + default: + goto unexpected_tag; + } + break; + case SIGTYPE_MULTI: + if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_SIGN) + goto unexpected_tag; + break; + case SIGTYPE_SINGLE: + if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_SIGN1) + goto unexpected_tag; + break; + case SIGTYPE_COUNTERSIGNED: + if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_SIGN) + goto unexpected_tag; + break; + case SIGTYPE_MAC0: + if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_MAC0) + goto unexpected_tag; + break; + case SIGTYPE_MAC: + if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_MAC) { +unexpected_tag: + lwsl_warn("%s: unexpected tag %d\n", __func__, + (int)ctx->item.u.u64); + goto bail; + } + break; + } + + cps->depth++; + break; + + case LECPCB_ARRAY_ITEM_START: + + if (cps->sub) + break; + + if (ctx->pst[ctx->pst_sp].ppos == 4 || + ctx->pst[ctx->pst_sp].ppos == 6) { + switch (cps->tli) { + case ST_INNER_UNPROTECTED: + case ST_INNER_PROTECTED: + hi = ph_index(cps); + sl = &cps->st[cps->sp]; + sl->ph_pos[hi] = 0; + lecp_parse_report_raw(ctx, 1); + break; + default: + break; + } + break; + } + + if (ctx->pst[ctx->pst_sp].ppos != 2) + break; + + switch (cps->tli) { + case ST_OUTER_UNPROTECTED: + case ST_OUTER_PROTECTED: + /* + * Holy type confusion, Batman... this is a CBOR bstr + * containing valid CBOR that must also be parsed as + * part of the containing array... we need to collect + * it anyway since it is part of the signing plaintext + * in bstr form, let's get it and then parse it at the + * END of the bstr. + */ + lecp_parse_report_raw(ctx, 1); + break; + + case ST_OUTER_PAYLOAD: + if (cps->info.sigtype != SIGTYPE_SINGLE) + break; + + if (create_alg(ctx, cps)) + goto bail; + + break; + + case ST_OUTER_SIGN_SIGARRAY: + cps->tli = ST_INNER_PROTECTED; + break; + } + break; + + case LECPCB_ARRAY_ITEM_END: + + if (cps->sub) + break; + + if (ctx->pst[ctx->pst_sp].ppos == 2) { + sl = &cps->st[cps->sp]; + switch (cps->tli) { + case ST_OUTER_UNPROTECTED: + break; + /* fallthru */ + case ST_OUTER_PROTECTED: + lecp_parse_report_raw(ctx, 0); + + hi = ph_index(cps); + + if (!sl->ph_pos[hi] || cps->sub) + break; + + cps->sub = 1; + s = (size_t)sl->ph_pos[hi]; + + if (lecp_parse_subtree(&cps->ctx, + sl->ph[hi] + 3, s) != + LECP_CONTINUE) + goto bail; + cps->sub = 0; + break; + + case ST_OUTER_PAYLOAD: + switch (cps->info.sigtype) { + case SIGTYPE_MULTI: + cps->tli = ST_OUTER_SIGN_SIGARRAY - 1; + break; + case SIGTYPE_MAC: + case SIGTYPE_MAC0: + cps->tli = ST_OUTER_MACTAG - 1; + break; + case SIGTYPE_COUNTERSIGNED: + break; + default: + break; + } + break; + + case ST_OUTER_SIGN1_SIGNATURE: + case ST_OUTER_MACTAG: + cps->sp++; + cps->tli = ST_INNER_PROTECTED - 1; + break; + + case ST_INNER_UNPROTECTED: + lwsl_notice("ST_INNER_UNPROTECTED end\n"); + break; + case ST_INNER_PROTECTED: + lwsl_notice("ST_INNER_PROTECTED end\n"); + break; + + case ST_INNER_EXCESS: + case ST_OUTER_SIGN_SIGARRAY: + cps->tli--; /* so no change */ + break; + } + if (!cps->sub) + cps->tli++; + } + + if (ctx->pst[ctx->pst_sp].ppos >= 4) { + uint8_t *p; + uint8_t u; + size_t s1; + + switch (cps->tli) { + case ST_INNER_UNPROTECTED: + case ST_INNER_PROTECTED: + + hi = ph_index(cps); + sl = &cps->st[cps->sp]; + p = sl->ph[hi] + 3; + lecp_parse_report_raw(ctx, 0); + + if (!sl->ph_pos[hi] || cps->sub) { + if (!cps->sub) + cps->tli++; + break; + } + + cps->sub = 1; + s = (size_t)sl->ph_pos[hi]; + + /* + * somehow the raw captures the + * initial BSTR container length, + * let's strip it + */ + + u = (*p) & LWS_CBOR_SUBMASK; + if (((*p) & LWS_CBOR_MAJTYP_MASK) == + LWS_CBOR_MAJTYP_BSTR) { + s1 = 1; + if (u == LWS_CBOR_1) + s1 = 2; + else if (u == LWS_CBOR_2) + s1 = 3; + else if (u == LWS_CBOR_4) + s1 = 5; + else if (u == LWS_CBOR_8) + s1 = 9; + + if (s1 > s) + goto bail; + + sl->ph_pos[hi] = (int) + (sl->ph_pos[hi] - (ssize_t)s1); + s = s - s1; + memmove(p, p + s1, s); + } + + if (lecp_parse_subtree(&cps->ctx, p, s) != + LECP_CONTINUE) + goto bail; + + cps->sub = 0; + + if (!cps->sub) + cps->tli++; + break; + + case ST_INNER_SIGNATURE: + if (cps->info.sigtype == SIGTYPE_MAC) { + // lwsl_err("Y: alg %d\n", (int)cps->alg); + if (create_alg(ctx, cps)) + goto bail; + } + cps->tli++; + break; + default: + break; + } + } + + break; + + case LECPCB_VAL_NUM_INT: + case LECPCB_VAL_NUM_UINT: + switch (cps->tli) { + case ST_INNER_PROTECTED: + case ST_INNER_UNPROTECTED: + case ST_INNER_SIGNATURE: + case ST_OUTER_PROTECTED: + case ST_OUTER_UNPROTECTED: + if (lecp_parse_map_is_key(ctx)) { + cps->map_key = ctx->item.u.i64; + // lwsl_notice("%s: key %d\n", __func__, (int)cps->map_key); + break; + } + + // lwsl_notice("%s: key %d val %d\n", __func__, (int)cps->map_key, (int)ctx->item.u.i64); + + if (cps->map_key == LWSCOSE_WKL_ALG) { + sl = &cps->st[cps->sp]; + cps->map_key = 0; + if (cps->tli == ST_INNER_PROTECTED || + cps->tli == ST_INNER_UNPROTECTED || + cps->tli == ST_INNER_SIGNATURE) { + sl->alg = ctx->item.u.i64; + if (!cps->st[0].alg) + cps->st[0].alg = sl->alg; + } else + sl->alg = ctx->item.u.i64; + break; + } + break; + } + break; + + case LECPCB_VAL_STR_END: + switch (cps->tli) { + case ST_OUTER_UNPROTECTED: + break; + } + break; + + case LECPCB_VAL_BLOB_START: + + lwsl_notice("%s: blob size %d\n", __func__, (int)ctx->item.u.u64); + + if (cps->tli == ST_OUTER_SIGN1_SIGNATURE || + cps->tli == ST_INNER_SIGNATURE) { + if (ctx->item.u.u64 > sizeof(cps->sig_agg)) + goto bail; + cps->sig_agg_pos = 0; + break; + } + + if (cps->tli != ST_OUTER_PAYLOAD) + break; + + if (apply_external(cps)) { + lwsl_notice("%s: ext\n", __func__); + goto bail; + } + + s = bstr_len(t, sizeof(t), LWS_CBOR_MAJTYP_BSTR, + ctx->item.u.u64); + + if (cps->info.sigtype == SIGTYPE_SINGLE) { + alg = lws_container_of(cps->algs.head, + lws_cose_sig_alg_t, list); + if (!alg) + /* expected if no key */ + break; + if (lws_cose_val_alg_hash(alg, t, s)) { + lwsl_notice("%s: hash failed\n", __func__); + goto bail; + } + + break; + } + + cps->payload_stash_size = (size_t)(ctx->item.u.u64 + s); + cps->payload_stash = lws_malloc(cps->payload_stash_size, + __func__); + if (!cps->payload_stash) { + lwsl_notice("%s: oom\n", __func__); + goto bail; + } + + memcpy(cps->payload_stash, t, s); + cps->payload_pos = s; + + break; + + case LECPCB_VAL_BLOB_CHUNK: + switch (cps->tli) { + case ST_OUTER_PAYLOAD: + + if (cps->info.pay_cb && ctx->npos) + cps->info.pay_cb(cps, cps->info.pay_opaque, + (uint8_t *)ctx->buf, ctx->npos); + + if (cps->payload_stash) { + if (cps->payload_pos + ctx->npos > + cps->payload_stash_size) + goto bail; + memcpy(cps->payload_stash + cps->payload_pos, + ctx->buf, ctx->npos); + cps->payload_pos += ctx->npos; + break; + } + alg = lws_container_of(cps->algs.head, + lws_cose_sig_alg_t, list); + if (!alg) + /* expected if no key */ + break; + if (ctx->npos && + lws_cose_val_alg_hash(alg, (uint8_t *)ctx->buf, + ctx->npos)) { + lwsl_notice("%s: chunk fail\n", __func__); + goto bail; + } + break; + case ST_INNER_SIGNATURE: + case ST_OUTER_SIGN1_SIGNATURE: + /* the sig is big compared to ctx->buf... we need to + * stash it then */ + memcpy(cps->sig_agg + cps->sig_agg_pos, ctx->buf, + ctx->npos); + cps->sig_agg_pos = cps->sig_agg_pos + ctx->npos; + break; + } + break; + + case LECPCB_VAL_BLOB_END: + switch (cps->tli) { + + case ST_INNER_SIGNATURE: + if (cps->info.sigtype == SIGTYPE_MULTI) { + memcpy(cps->sig_agg + cps->sig_agg_pos, ctx->buf, + ctx->npos); + cps->sig_agg_pos = cps->sig_agg_pos + ctx->npos; + // lwsl_err("Y: alg %d\n", (int)cps->alg); + if (create_alg(ctx, cps)) + goto bail; + break; + } + if (cps->info.sigtype != SIGTYPE_MAC) + break; + /* fallthru */ + case ST_OUTER_PROTECTED: + case ST_OUTER_UNPROTECTED: + case ST_INNER_PROTECTED: + case ST_INNER_UNPROTECTED: + if (cps->map_key == LWSCOSE_WKL_KID) { + sl = &cps->st[cps->sp]; + ke = &sl->kid; + if (ke->buf) + lws_free(ke->buf); + ke->buf = lws_malloc(ctx->npos, __func__); + if (!ke->buf) + goto bail; + ke->len = ctx->npos; + memcpy(ke->buf, ctx->buf, ctx->npos); + cps->map_key = 0; + } + break; + + case ST_OUTER_PAYLOAD: + if (cps->info.pay_cb && ctx->npos) + cps->info.pay_cb(cps, cps->info.pay_opaque, + (uint8_t *)ctx->buf, ctx->npos); + if (cps->payload_stash) { + if (cps->payload_pos + ctx->npos > + cps->payload_stash_size) + goto bail; + memcpy(cps->payload_stash + cps->payload_pos, + ctx->buf, ctx->npos); + cps->payload_pos += ctx->npos; + break; + } + alg = lws_container_of(cps->algs.head, + lws_cose_sig_alg_t, list); + if (!alg) + /* expected if no key */ + break; + + if (ctx->npos && + lws_cose_val_alg_hash(alg, (uint8_t *)ctx->buf, + ctx->npos)) + goto bail; + break; + + case ST_OUTER_SIGN1_SIGNATURE: + if (cps->info.sigtype == SIGTYPE_MULTI) + break; + + memcpy(cps->sig_agg + cps->sig_agg_pos, ctx->buf, + ctx->npos); + cps->sig_agg_pos += ctx->npos; + + alg = lws_container_of(cps->algs.head, + lws_cose_sig_alg_t, list); + lwsl_notice("b\n"); + if (alg) + lws_cose_val_alg_destroy(cps, &alg, + cps->sig_agg, + cps->sig_agg_pos); + break; + + case ST_OUTER_MACTAG: + if (cps->mac_pos + ctx->npos > sizeof(cps->mac)) + goto bail; + memcpy(cps->mac + cps->mac_pos, ctx->buf, ctx->npos); + cps->mac_pos += ctx->npos; + + if (cps->info.sigtype == SIGTYPE_MAC0) { + if (create_alg(ctx, cps)) + goto bail; + } + + break; + } + break; + + case LECPCB_LITERAL_CBOR: + /* only used for protected headers */ + switch (cps->tli) { + case ST_INNER_PROTECTED: + case ST_OUTER_PROTECTED: + case ST_INNER_UNPROTECTED: + case ST_OUTER_UNPROTECTED: + sl = &cps->st[cps->sp]; + hi = ph_index(cps); + if (sl->ph_pos[hi] + 3 + ctx->cbor_pos > + (int)sizeof(sl->ph[hi]) - 3) + /* more protected cbor than we can handle */ + goto bail; + memcpy(sl->ph[hi] + 3 + sl->ph_pos[hi], ctx->cbor, + ctx->cbor_pos); + sl->ph_pos[hi] += ctx->cbor_pos; + break; + } + } + + return 0; + +bail: + + return -1; +} + +struct lws_cose_validate_context * +lws_cose_validate_create(const lws_cose_validate_create_info_t *info) +{ + struct lws_cose_validate_context *cps; + + /* you have to provide at least one key in a cose_keyset */ + assert(info->keyset); + /* you have to provide an lws_context (for crypto random) */ + assert(info->cx); + + cps = lws_zalloc(sizeof(*cps), __func__); + if (!cps) + return NULL; + + cps->info = *info; + cps->tli = ST_OUTER_PROTECTED; + + lecp_construct(&cps->ctx, cb_cose_sig, cps, NULL, 0); + + return cps; +} + +int +lws_cose_validate_chunk(struct lws_cose_validate_context *cps, + const uint8_t *in, size_t in_len, size_t *used_in) +{ + int n; + + n = lecp_parse(&cps->ctx, in, in_len); + if (used_in) + *used_in = cps->ctx.used_in; + + if (n == LECP_CONTINUE) + return LECP_CONTINUE; + + lecp_destruct(&cps->ctx); + + return n; +} + +lws_dll2_owner_t * +lws_cose_validate_results(struct lws_cose_validate_context *cps) +{ + return &cps->results; +} + +void +lws_cose_validate_destroy(struct lws_cose_validate_context **_cps) +{ + struct lws_cose_validate_context *cps = *_cps; + + if (!cps) + return; + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(&cps->algs)) { + lws_cose_sig_alg_t *alg = lws_container_of(p, + lws_cose_sig_alg_t, list); + + lws_dll2_remove(p); + lws_cose_val_alg_destroy(cps, &alg, NULL, 0); + } lws_end_foreach_dll_safe(p, tp); + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(&cps->results)) { + lws_cose_validate_res_t *res = lws_container_of(p, + lws_cose_validate_res_t, list); + + lws_dll2_remove(p); + lws_free(res); + } lws_end_foreach_dll_safe(p, tp); + + lws_free_set_NULL(cps->payload_stash); + + lwsac_free(&cps->ac); + + while (cps->sp >= 0) { + if (cps->st[cps->sp].kid.buf) + lws_free(cps->st[cps->sp].kid.buf); + cps->sp--; + } + + lws_free_set_NULL(*_cps); +} diff --git a/3rdparty/libwebsockets/lib/cose/cose_validate_alg.c b/3rdparty/libwebsockets/lib/cose/cose_validate_alg.c new file mode 100644 index 00000000..9f2e888e --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/cose_validate_alg.c @@ -0,0 +1,274 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 "private-lib-cose.h" + +lws_cose_sig_alg_t * +lws_cose_val_alg_create(struct lws_context *cx, lws_cose_key_t *ck, + cose_param_t cose_alg, int op) +{ + lws_cose_sig_alg_t *alg = lws_zalloc(sizeof(*alg), __func__); + struct lws_gencrypto_keyelem *ke; + enum lws_genhmac_types ghm; + enum lws_genhash_types gh; + const char *crv; + + if (!alg) + return NULL; + + alg->cose_alg = cose_alg; + alg->cose_key = ck; + + switch (cose_alg) { + + /* ECDSA algs */ + + case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ + crv = "P-256"; + gh = LWS_GENHASH_TYPE_SHA256; + alg->keybits = 256; + goto ecdsa; + case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ + crv = "P-384"; + gh = LWS_GENHASH_TYPE_SHA384; + alg->keybits = 384; + goto ecdsa; + case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ + crv = "P-521"; + gh = LWS_GENHASH_TYPE_SHA512; + alg->keybits = 521; +ecdsa: + + /* the key is good for this? */ + + if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_EC2, cose_alg, + op, crv)) + goto bail_ecdsa; + + if (lws_genhash_init(&alg->hash_ctx, gh)) + goto bail_ecdsa; + + if (lws_genecdsa_create(&alg->u.ecdsactx, cx, lws_ec_curves)) { + lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", + __func__); + goto bail_ecdsa1; + } + + if (lws_genecdsa_set_key(&alg->u.ecdsactx, ck->e)) { + lwsl_notice("%s: ec key import fail\n", __func__); + goto bail_ecdsa2; + } + + break; + + /* HMAC algs */ + + case LWSCOSE_WKAHMAC_256_64: + ghm = LWS_GENHMAC_TYPE_SHA256; + alg->keybits = 64; + goto hmac; + case LWSCOSE_WKAHMAC_256_256: + ghm = LWS_GENHMAC_TYPE_SHA256; + alg->keybits = 256; + goto hmac; + case LWSCOSE_WKAHMAC_384_384: + ghm = LWS_GENHMAC_TYPE_SHA384; + alg->keybits = 384; + goto hmac; + case LWSCOSE_WKAHMAC_512_512: + ghm = LWS_GENHMAC_TYPE_SHA512; + alg->keybits = 512; + +hmac: + if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_SYMMETRIC, + cose_alg, op, NULL)) + goto bail_hmac; + + ke = &ck->e[LWS_GENCRYPTO_OCT_KEYEL_K]; + if (lws_genhmac_init(&alg->u.hmacctx, ghm, ke->buf, ke->len)) + goto bail_hmac; + + break; + + /* RSASSA algs */ + + case LWSCOSE_WKARSA_ALG_RS256: + gh = LWS_GENHASH_TYPE_SHA256; + goto rsassa; + + case LWSCOSE_WKARSA_ALG_RS384: + gh = LWS_GENHASH_TYPE_SHA384; + goto rsassa; + + case LWSCOSE_WKARSA_ALG_RS512: + gh = LWS_GENHASH_TYPE_SHA512; + +rsassa: + if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_RSA, cose_alg, + op, NULL)) + goto bail_hmac; + alg->keybits = (int)ck->e[LWS_GENCRYPTO_RSA_KEYEL_N].len * 8; + + if (lws_genhash_init(&alg->hash_ctx, gh)) + goto bail_ecdsa; + + if (lws_genrsa_create(&alg->u.rsactx, ck->e, cx, + LGRSAM_PKCS1_1_5, gh)) { + lwsl_notice("%s: lws_genrsa_create fail\n", __func__); + goto bail_ecdsa1; + } + break; + + default: + lwsl_warn("%s: unsupported alg %lld\n", __func__, + (long long)cose_alg); + goto bail_hmac; + } + + return alg; + +bail_ecdsa2: + lws_genec_destroy(&alg->u.ecdsactx); +bail_ecdsa1: + lws_genhash_destroy(&alg->hash_ctx, NULL); +bail_ecdsa: + lws_free(alg); + + lwsl_notice("%s: failed\n", __func__); + + return NULL; + +bail_hmac: + lws_free(alg); + + return NULL; +} + +int +lws_cose_val_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len) +{ +#if defined(VERBOSE) + lwsl_hexdump_warn(in, in_len); +#endif + + switch (alg->cose_alg) { + case LWSCOSE_WKAHMAC_256_64: + case LWSCOSE_WKAHMAC_256_256: + case LWSCOSE_WKAHMAC_384_384: + case LWSCOSE_WKAHMAC_512_512: + return lws_genhmac_update(&alg->u.hmacctx, in, in_len); + } + + return lws_genhash_update(&alg->hash_ctx, in, in_len); +} + +void +lws_cose_val_alg_destroy(struct lws_cose_validate_context *cps, + lws_cose_sig_alg_t **_alg, const uint8_t *against, + size_t against_len) +{ + uint8_t digest[LWS_GENHASH_LARGEST]; + lws_cose_sig_alg_t *alg = *_alg; + lws_cose_validate_res_t *res; + size_t hs, shs; + int keybits; + uint8_t ht; + + lws_dll2_remove(&alg->list); + ht = alg->hash_ctx.type; + keybits = alg->keybits; + + res = lws_zalloc(sizeof(*res), __func__); + if (res) { + + res->cose_key = alg->cose_key; + res->cose_alg = alg->cose_alg; + res->result = -999; + + lws_dll2_add_tail(&res->list, &cps->results); + } + + switch (alg->cose_alg) { + case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ + case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ + case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ + hs = lws_genhash_size(alg->hash_ctx.type); + lws_genhash_destroy(&alg->hash_ctx, digest); + + lwsl_notice("%d %d %d\n", (int)hs, (int)keybits, (int)against_len); + + if (res && against) + res->result = lws_genecdsa_hash_sig_verify_jws( + &alg->u.ecdsactx, digest, ht, + keybits, against, against_len); + lws_genec_destroy(&alg->u.ecdsactx); + break; + + case LWSCOSE_WKAHMAC_256_64: + case LWSCOSE_WKAHMAC_256_256: + case LWSCOSE_WKAHMAC_384_384: + case LWSCOSE_WKAHMAC_512_512: + shs = hs = lws_genhmac_size(alg->u.hmacctx.type); + if (alg->cose_alg == LWSCOSE_WKAHMAC_256_64) + shs = 8; + + if (lws_genhmac_destroy(&alg->u.hmacctx, digest)) { + lwsl_err("%s: destroy failed\n", __func__); + break; + } + + if (cps->mac_pos != shs) { + lwsl_warn("%s: mac wrong size\n", __func__); + /* we can't compare it, leave it at fail */ + break; + } + if (res && against) { + res->result = lws_timingsafe_bcmp(digest, cps->mac, + (uint32_t)shs); + if (res->result) + lwsl_warn("%s: hash mismatch\n", __func__); + } + break; + + case LWSCOSE_WKARSA_ALG_RS256: + case LWSCOSE_WKARSA_ALG_RS384: + case LWSCOSE_WKARSA_ALG_RS512: + + if (!lws_genhash_destroy(&alg->hash_ctx, digest) && + !alg->failed && + lws_genrsa_hash_sig_verify(&alg->u.rsactx, digest, + alg->hash_ctx.type, + against, against_len) >= 0) { + if (res) + res->result = 0; + } else + lwsl_err("%s: lws_genrsa_hash_verify\n", __func__); + + lws_genrsa_destroy(&alg->u.rsactx); + break; + } + + lws_free_set_NULL(*_alg); +} diff --git a/3rdparty/libwebsockets/lib/cose/private-lib-cose.h b/3rdparty/libwebsockets/lib/cose/private-lib-cose.h new file mode 100644 index 00000000..97cc2656 --- /dev/null +++ b/3rdparty/libwebsockets/lib/cose/private-lib-cose.h @@ -0,0 +1,148 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 VERBOSE + +#define MAX_BLOBBED_PARAMS 96 /* largest bstr-encoded params */ + +enum { + ST_UNKNOWN, + + ST_OUTER_PROTECTED, + ST_OUTER_UNPROTECTED, + ST_OUTER_PAYLOAD, + ST_OUTER_SIGN1_SIGNATURE, + + ST_OUTER_SIGN_SIGARRAY, + + ST_OUTER_MACTAG, + + ST_INNER_PROTECTED, + ST_INNER_UNPROTECTED, + ST_INNER_SIGNATURE, + + ST_INNER_EXCESS, +}; + +typedef struct lws_cose_sig_alg { + lws_dll2_t list; + uint8_t rhash[512]; + const lws_cose_key_t *cose_key; + struct lws_genhash_ctx hash_ctx; + union { + struct lws_genec_ctx ecdsactx; + struct lws_genrsa_ctx rsactx; + struct lws_genhmac_ctx hmacctx; + } u; + cose_param_t cose_alg; + int keybits; + int rhash_len; + + char failed; + char completed; +} lws_cose_sig_alg_t; + +typedef struct lws_cose_validate_param_stack { + uint8_t ph[4][MAX_BLOBBED_PARAMS]; + int ph_pos[4]; + struct lws_gencrypto_keyelem kid; + cose_param_t alg; +} lws_cose_validate_param_stack_t; + +struct lws_cose_validate_context { + lws_cose_validate_create_info_t info; + uint8_t mac[LWS_GENHASH_LARGEST]; + uint8_t sig_agg[512]; + lws_cose_validate_param_stack_t st[3]; + lws_dll2_owner_t algs; + lws_dll2_owner_t results; + uint8_t *payload_stash; + struct lwsac *ac; + struct lecp_ctx ctx; + void *user; + + size_t payload_pos; + size_t payload_stash_size; + + int seen; + int depth; + + int outer; + size_t mac_pos; + size_t sig_agg_pos; + + cose_param_t map_key; /* parsing temp before val */ + + int tli; /* toplevel item */ + int sp; + + uint8_t sub; +}; + +struct lws_cose_sign_context { + lws_cose_sign_create_info_t info; + + lws_dll2_owner_t algs; + lws_cose_sig_alg_t *alg; + + size_t rem_pay; + enum lws_cose_sig_types type; /* computed */ + int flags; + + size_t along; + + int tli; + + char subsequent; +}; + +extern const uint8_t *sig_mctx[]; +extern uint8_t sig_mctx_len[]; +extern const char *cose_sections[]; + +lws_cose_sig_alg_t * +lws_cose_val_alg_create(struct lws_context *cx, lws_cose_key_t *ck, + cose_param_t cose_alg, int op); + +int +lws_cose_val_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len); + +void +lws_cose_val_alg_destroy(struct lws_cose_validate_context *cps, + lws_cose_sig_alg_t **_alg, const uint8_t *against, + size_t against_len); + +lws_cose_sig_alg_t * +lws_cose_sign_alg_create(struct lws_context *cx, const lws_cose_key_t *ck, + cose_param_t cose_alg, int op); + +int +lws_cose_sign_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len); + +void +lws_cose_sign_alg_complete(lws_cose_sig_alg_t *alg); + +void +lws_cose_sign_alg_destroy(lws_cose_sig_alg_t **_alg); + diff --git a/3rdparty/libwebsockets/lib/drivers/button/lws-button.c b/3rdparty/libwebsockets/lib/drivers/button/lws-button.c index e937db6f..43456fb5 100644 --- a/3rdparty/libwebsockets/lib/drivers/button/lws-button.c +++ b/3rdparty/libwebsockets/lib/drivers/button/lws-button.c @@ -471,8 +471,8 @@ lws_button_controller_destroy(struct lws_button_state *bcs) 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); + LWS_PLAT_TIMER_DELETE(bcs->timer); + LWS_PLAT_TIMER_DELETE(bcs->timer_mon); #endif lws_free(bcs); diff --git a/3rdparty/libwebsockets/lib/drivers/led/led-gpio.c b/3rdparty/libwebsockets/lib/drivers/led/led-gpio.c index 664a120c..382c3e63 100644 --- a/3rdparty/libwebsockets/lib/drivers/led/led-gpio.c +++ b/3rdparty/libwebsockets/lib/drivers/led/led-gpio.c @@ -81,7 +81,7 @@ void lws_led_gpio_destroy(struct lws_led_state *lcs) { #if defined(LWS_PLAT_TIMER_DELETE) - LWS_PLAT_TIMER_DELETE(&lcs->timer); + LWS_PLAT_TIMER_DELETE(lcs->timer); #endif lws_free(lcs); } diff --git a/3rdparty/libwebsockets/lib/event-libs/glib/glib.c b/3rdparty/libwebsockets/lib/event-libs/glib/glib.c index 8ff3703a..14c779e1 100644 --- a/3rdparty/libwebsockets/lib/event-libs/glib/glib.c +++ b/3rdparty/libwebsockets/lib/event-libs/glib/glib.c @@ -132,8 +132,8 @@ lws_glib_dispatch(GSource *src, GSourceFunc x, gpointer userData) eventfd.events = eventfd.revents; eventfd.fd = sub->wsi->desc.sockfd; - lwsl_debug("%s: %s: fd %d, events %d\n", __func__, lws_wsi_tag(sub->wsi), - eventfd.fd, eventfd.revents); + lwsl_wsi_debug(sub->wsi, "fd %d, events %d", + eventfd.fd, eventfd.revents); pt = &sub->wsi->a.context->pt[(int)sub->wsi->tsi]; if (pt->is_destroyed) @@ -293,12 +293,21 @@ elops_accept_glib(struct lws *wsi) return 0; } +static int +elops_listen_init_glib(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + elops_accept_glib(wsi); + + return 0; +} + static int 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; if (!loop) @@ -307,24 +316,14 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi) context->pt[tsi].event_loop_foreign = 1; if (!loop) { - lwsl_err("%s: creating glib loop failed\n", __func__); + lwsl_cx_err(context, "creating glib loop failed"); return -1; } ptpr->loop = loop; - /* - * Initialize all events with the listening sockets - * and register a callback for read operations - */ - - while (vh) { - if (vh->lserv_wsi) - elops_accept_glib(vh->lserv_wsi); - - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_glib); lws_glib_set_idle(pt); @@ -378,8 +377,8 @@ elops_io_glib(struct lws *wsi, unsigned int flags) wsipr->w_read.actual_events = (uint8_t)cond; - lwsl_debug("%s: %s, fd %d, 0x%x/0x%x\n", __func__, lws_wsi_tag(wsi), - wsi->desc.sockfd, flags, (int)cond); + lwsl_wsi_debug(wsi, "fd %d, 0x%x/0x%x", wsi->desc.sockfd, + flags, (int)cond); g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag, cond); @@ -420,25 +419,26 @@ elops_destroy_wsi_glib(struct lws *wsi) wsi_to_subclass(wsi) = NULL; } +static int +elops_listen_destroy_glib(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + elops_destroy_wsi_glib(wsi); + + return 0; +} + static void 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)) return; - /* - * Free all events with the listening sockets - */ - while (vh) { - if (vh->lserv_wsi) - elops_destroy_wsi_glib(vh->lserv_wsi); - - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_glib); lws_gs_destroy(ptpr->idle); lws_gs_destroy(ptpr->hrtimer); @@ -490,6 +490,7 @@ static const struct lws_event_loop_ops event_loop_ops_glib = { /* run_pt */ elops_run_pt_glib, /* destroy_pt */ elops_destroy_pt_glib, /* destroy wsi */ elops_destroy_wsi_glib, + /* foreign_thread */ NULL, /* flags */ LELOF_DESTROY_FINAL, diff --git a/3rdparty/libwebsockets/lib/event-libs/glib/private-lib-event-libs-glib.h b/3rdparty/libwebsockets/lib/event-libs/glib/private-lib-event-libs-glib.h index cd976f89..10d9b0c6 100644 --- a/3rdparty/libwebsockets/lib/event-libs/glib/private-lib-event-libs-glib.h +++ b/3rdparty/libwebsockets/lib/event-libs/glib/private-lib-event-libs-glib.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2020 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -22,13 +22,7 @@ * IN THE SOFTWARE. */ -#if defined(LWS_WITH_GLIB) -#if defined(__APPLE__) #include -#else -#include -#endif -#endif /* LWS_WITH_GLIB */ typedef struct lws_glib_tag { GSource *gs; diff --git a/3rdparty/libwebsockets/lib/event-libs/libev/libev.c b/3rdparty/libwebsockets/lib/event-libs/libev/libev.c index a8583b8f..4bdede78 100644 --- a/3rdparty/libwebsockets/lib/event-libs/libev/libev.c +++ b/3rdparty/libwebsockets/lib/event-libs/libev/libev.c @@ -133,6 +133,27 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents) ev_break(loop, EVBREAK_ALL); } +static int +elops_listen_init_ev(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct lws_context *context = (struct lws_context *)user; + struct lws_context_per_thread *pt = &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); + struct lws_vhost *vh = wsi->a.vhost; + + 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, wsi->desc.sockfd, EV_READ); + ev_io_start(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher); + + return 0; +} + static int elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) { @@ -140,12 +161,11 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) 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; unsigned int backend; int status = 0; - lwsl_info("%s: loop %p\n", __func__, _loop); + lwsl_cx_info(context, "loop %p", _loop); ptpr->pt = pt; @@ -155,33 +175,14 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) context->pt[tsi].event_loop_foreign = 1; if (!loop) { - lwsl_err("%s: creating event base failed\n", __func__); + lwsl_cx_err(context, "creating event base failed"); return -1; } ptpr->io_loop = loop; - /* - * Initialize the accept w_accept with all the listening sockets - * and register a callback for read operations - */ - while (vh) { - if (vh->lserv_wsi) { - struct lws_wsi_eventlibs_libev *w = - wsi_to_priv_ev(vh->lserv_wsi); - - 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; - } + lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_ev); /* Register the signal watcher unless it's a foreign loop */ if (!context->pt[tsi].event_loop_foreign) { @@ -225,7 +226,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) break; } - lwsl_info(" libev backend: %s\n", backend_name); + lwsl_cx_info(context, " libev backend: %s", backend_name); (void)backend_name; ev_timer_init(&ptpr->hrtimer, lws_ev_hrtimer_cb, 0, 0); @@ -236,19 +237,27 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) return status; } +static int +elops_listen_destroy_ev(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct lws_context *context = (struct lws_context *)user; + struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; + struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt); + struct lws_vhost *vh = wsi->a.vhost; + + ev_io_stop(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher); + + return 0; +} + static void 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(ptpr->io_loop, - &vh_to_priv_ev(vh)->w_accept.watcher); - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_ev); /* static assets */ @@ -279,8 +288,6 @@ 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 @@ -302,9 +309,9 @@ elops_io_ev(struct lws *wsi, unsigned int flags) struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt); struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi); - lwsl_debug("%s: %s %s flags 0x%x %p %d\n", __func__, - lws_wsi_tag(wsi), wsi->role_ops->name, flags, - ptpr->io_loop, pt->is_destroyed); + lwsl_wsi_debug(wsi, "%s flags 0x%x %p %d", wsi->role_ops->name, flags, + ptpr->io_loop, + pt->is_destroyed); if (!ptpr->io_loop || pt->is_destroyed) return; @@ -342,8 +349,6 @@ elops_destroy_context2_ev(struct lws_context *context) struct lws_pt_eventlibs_libev *ptpr; int n, m; - lwsl_debug("%s\n", __func__); - for (n = 0; n < context->count_threads; n++) { int budget = 1000; @@ -423,6 +428,7 @@ static const struct lws_event_loop_ops event_loop_ops_ev = { /* run_pt */ elops_run_pt_ev, /* destroy_pt */ elops_destroy_pt_ev, /* destroy wsi */ elops_destroy_wsi_ev, + /* foreign_thread */ NULL, /* flags */ 0, diff --git a/3rdparty/libwebsockets/lib/event-libs/libevent/libevent.c b/3rdparty/libwebsockets/lib/event-libs/libevent/libevent.c index e9240a09..b7b310ca 100644 --- a/3rdparty/libwebsockets/lib/event-libs/libevent/libevent.c +++ b/3rdparty/libwebsockets/lib/event-libs/libevent/libevent.c @@ -83,8 +83,6 @@ lws_event_idle_timer_cb(evutil_socket_t fd, short event, void *p) } } - lwsl_debug("%s: wait\n", __func__); - /* account for hrtimer */ lws_pt_lock(pt, __func__); @@ -147,7 +145,7 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx) lws_service_fd_tsi(context, &eventfd, wsi->tsi); if (pt->destroy_self) { - lwsl_notice("%s: pt destroy self coming true\n", __func__); + lwsl_cx_notice(context, "pt destroy self coming true"); lws_context_destroy(pt->context); return; } @@ -175,15 +173,33 @@ lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx) event_base_loopbreak(pt_to_priv_event(pt)->io_loop); } +static int +elops_listen_init_event(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct lws_context *context = (struct lws_context *)user; + struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; + struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt); + struct lws_io_watcher_libevent *w_read = + &(wsi_to_priv_event(wsi)->w_read); + + w_read->context = context; + w_read->watcher = event_new(ptpr->io_loop, wsi->desc.sockfd, + (EV_READ | EV_PERSIST), lws_event_cb, w_read); + event_add(w_read->watcher, NULL); + w_read->set = 1; + + return 0; +} + 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); + lwsl_cx_info(context, "loop %p", _loop); if (!loop) loop = event_base_new(); @@ -191,33 +207,14 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi) context->pt[tsi].event_loop_foreign = 1; if (!loop) { - lwsl_err("%s: creating event base failed\n", __func__); + lwsl_cx_err(context, "creating event base failed"); return -1; } ptpr->io_loop = loop; - /* - * Initialize all events with the listening sockets - * and register a callback for read operations - */ - - while (vh) { - if (vh->lserv_wsi) { - 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, - w_read); - event_add(w_read->watcher, NULL); - w_read->set = 1; - } - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_event); /* static event loop objects */ @@ -334,33 +331,30 @@ elops_run_pt_event(struct lws_context *context, int tsi) pt_to_priv_event(&context->pt[tsi])->io_loop); } +static int +elops_listen_destroy_event(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct lws_wsi_eventlibs_libevent *w = wsi_to_priv_event(wsi); + + event_free(w->w_read.watcher); + w->w_read.watcher = NULL; + event_free(w->w_write.watcher); + w->w_write.watcher = NULL; + + return 0; +} + 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 (!ptpr->io_loop) return; - /* - * Free all events with the listening sockets - */ - while (vh) { - if (vh->lserv_wsi) { - 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; - } + lws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_event); event_free(ptpr->hrtimer); event_free(ptpr->idle_timer); @@ -371,7 +365,7 @@ elops_destroy_pt_event(struct lws_context *context, int tsi) 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__); + lwsl_cx_notice(context, "set to exit loop"); } } @@ -453,8 +447,6 @@ elops_destroy_context2_event(struct lws_context *context) struct lws_pt_eventlibs_libevent *ptpr; int n, m; - lwsl_debug("%s: in\n", __func__); - for (n = 0; n < context->count_threads; n++) { int budget = 1000; @@ -473,21 +465,13 @@ elops_destroy_context2_event(struct lws_context *context) while (budget-- && (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(ptpr->io_loop, stderr); - } else - lwsl_debug("%s: %d: everything closed OK\n", __func__, n); -#endif - lwsl_err("%s: event_base_free\n", __func__); + + lwsl_cx_info(context, "event_base_free"); + event_base_free(ptpr->io_loop); ptpr->io_loop = NULL; } - lwsl_debug("%s: out\n", __func__); - return 0; } @@ -506,6 +490,7 @@ static const struct lws_event_loop_ops event_loop_ops_event = { /* run_pt */ elops_run_pt_event, /* destroy_pt */ elops_destroy_pt_event, /* destroy wsi */ elops_destroy_wsi_event, + /* foreign_thread */ NULL, /* flags */ 0, diff --git a/3rdparty/libwebsockets/lib/event-libs/libuv/libuv.c b/3rdparty/libwebsockets/lib/event-libs/libuv/libuv.c index 7a5bc56b..dad371aa 100644 --- a/3rdparty/libwebsockets/lib/event-libs/libuv/libuv.c +++ b/3rdparty/libwebsockets/lib/event-libs/libuv/libuv.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -95,6 +95,7 @@ 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->a.context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; + struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); struct lws_pollfd eventfd; lws_context_lock(pt->context, __func__); @@ -103,6 +104,12 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents) if (pt->is_destroyed) goto bail; + if (!ptpriv->thread_valid) { + /* record the thread id that gave us our first event */ + ptpriv->uv_thread = uv_thread_self(); + ptpriv->thread_valid = 1; + } + #if defined(WIN32) || defined(_WIN32) eventfd.fd = watcher->socket; #else @@ -144,7 +151,7 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents) return; } - uv_idle_start(&pt_to_priv_uv(pt)->idle, lws_uv_idle); + uv_idle_start(&ptpriv->idle, lws_uv_idle); return; bail: @@ -161,10 +168,8 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents) static void lws_libuv_stop(struct lws_context *context) { - lwsl_err("%s\n", __func__); - if (context->requested_stop_internal_loops) { - lwsl_err("%s: ignoring\n", __func__); + lwsl_cx_err(context, "ignoring"); return; } @@ -184,7 +189,8 @@ lws_uv_signal_handler(uv_signal_t *watcher, int signum) return; } - lwsl_err("internal signal handler caught signal %d\n", signum); + lwsl_cx_err(pt->context, "internal signal handler caught signal %d", + signum); lws_libuv_stop(pt->context); } @@ -193,7 +199,7 @@ lws_uv_finalize_pt(struct lws_context_per_thread *pt) { pt->event_loop_pt_unused = 1; - lwsl_info("%s: thr %d\n", __func__, (int)(pt - pt->context->pt)); + lwsl_cx_info(pt->context, "thr %d", (int)(pt - pt->context->pt)); lws_context_lock(pt->context, __func__); @@ -204,7 +210,7 @@ lws_uv_finalize_pt(struct lws_context_per_thread *pt) * eventually, we emptied all the pts... */ - lwsl_debug("%s: all pts down now\n", __func__); + lwsl_cx_debug(pt->context, "all pts down now"); /* protocols may have initialized libuv objects */ @@ -215,8 +221,7 @@ lws_uv_finalize_pt(struct lws_context_per_thread *pt) if (!pt->count_event_loop_static_asset_handles && pt->event_loop_foreign) { - lwsl_info("%s: resuming context_destroy\n", - __func__); + lwsl_cx_info(pt->context, "resuming context_destroy"); lws_context_unlock(pt->context); lws_context_destroy(pt->context); /* @@ -227,8 +232,8 @@ lws_uv_finalize_pt(struct lws_context_per_thread *pt) return 1; } } else - lwsl_debug("%s: still %d undestroyed\n", __func__, - pt->context->undestroyed_threads); + lwsl_cx_debug(pt->context, "still %d undestroyed", + pt->context->undestroyed_threads); lws_context_unlock(pt->context); @@ -259,11 +264,11 @@ lws_uv_close_cb_sa(uv_handle_t *handle) int tsi = (int)(pt - &context->pt[0]); #endif - lwsl_info("%s: thr %d: sa left %d: dyn left: %d (rk %d)\n", __func__, - tsi, - pt->count_event_loop_static_asset_handles - 1, - ptpriv->extant_handles, - context->requested_stop_internal_loops); + lwsl_cx_info(context, "thr %d: sa left %d: dyn left: %d (rk %d)", + tsi, + pt->count_event_loop_static_asset_handles - 1, + ptpriv->extant_handles, + context->requested_stop_internal_loops); /* any static assets left? */ @@ -285,16 +290,14 @@ lws_uv_close_cb_sa(uv_handle_t *handle) * Stop the loop so we can get out of here. */ - lwsl_info("%s: thr %d: seen final static handle gone\n", __func__, tsi); + lwsl_cx_info(context, "thr %d: seen final static handle gone", tsi); - if (!pt->event_loop_foreign) { - lwsl_info("%s: calling lws_context_destroy2\n", __func__); + if (!pt->event_loop_foreign) lws_context_destroy(context); - } lws_uv_finalize_pt(pt); - lwsl_info("%s: all done\n", __func__); + lwsl_cx_info(context, "all done"); } /* @@ -381,8 +384,7 @@ elops_destroy_context1_uv(struct lws_context *context) UV_RUN_NOWAIT))) ; if (m) - lwsl_info("%s: tsi %d: not all closed\n", - __func__, n); + lwsl_cx_info(context, "tsi %d: unclosed", n); } } @@ -422,16 +424,18 @@ static int elops_wsi_logical_close_uv(struct lws *wsi) { if (!lws_socket_is_valid(wsi->desc.sockfd) && - wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file")) + wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file") && + !wsi_to_priv_uv(wsi)->w_read.pwatcher) return 0; if (wsi->listener || wsi->event_pipe) { - lwsl_debug("%s: %s: %d %d stop listener / pipe poll\n", - __func__, lws_wsi_tag(wsi), wsi->listener, wsi->event_pipe); + lwsl_wsi_debug(wsi, "%d %d stop listener / pipe poll", + wsi->listener, + wsi->event_pipe); 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: %s\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_debug(wsi, "lws_libuv_closehandle"); /* * libuv has to do his own close handle processing asynchronously */ @@ -444,7 +448,7 @@ static int elops_check_client_connect_ok_uv(struct lws *wsi) { if (lws_libuv_check_watcher_active(wsi)) { - lwsl_warn("Waiting for libuv watcher to close\n"); + lwsl_wsi_warn(wsi, "Waiting for libuv watcher to close"); return 1; } @@ -455,6 +459,7 @@ static void lws_libuv_closewsi_m(uv_handle_t* handle) { lws_sockfd_type sockfd = (lws_sockfd_type)(lws_intptr_t)handle->data; + lwsl_debug("%s: sockfd %d\n", __func__, sockfd); compatible_close(sockfd); lws_free(handle); @@ -465,7 +470,7 @@ elops_close_handle_manually_uv(struct lws *wsi) { uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher; - lwsl_debug("%s: lws_libuv_closehandle: %s\n", __func__, lws_wsi_tag(wsi)); + lwsl_wsi_debug(wsi, "lws_libuv_closehandle"); /* * the "manual" variant only closes the handle itself and the @@ -491,7 +496,13 @@ elops_accept_uv(struct lws *wsi) struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read; + int n; + if (!ptpriv->thread_valid) { + /* record the thread id that gave us our first event */ + ptpriv->uv_thread = uv_thread_self(); + ptpriv->thread_valid = 1; + } w_read->context = wsi->a.context; @@ -500,21 +511,28 @@ elops_accept_uv(struct lws *wsi) return -1; if (wsi->role_ops->file_handle) - uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, + n = 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_to_priv_uv(pt)->io_loop, + n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, wsi->desc.sockfd); + if (n) { + lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n, + (void *)(lws_intptr_t)wsi->desc.sockfd); + lws_free(w_read->pwatcher); + w_read->pwatcher = NULL; + return -1; + } + ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; ptpriv->extant_handles++; - lwsl_debug("%s: thr %d: %s sa left %d: dyn left: %d\n", __func__, - (int)(pt - &pt->context->pt[0]), - lws_wsi_tag(wsi), - pt->count_event_loop_static_asset_handles, - ptpriv->extant_handles); + lwsl_wsi_debug(wsi, "thr %d: sa left %d: dyn left: %d", + (int)(pt - &pt->context->pt[0]), + pt->count_event_loop_static_asset_handles, + ptpriv->extant_handles); return 0; } @@ -526,23 +544,23 @@ elops_io_uv(struct lws *wsi, unsigned int flags) 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: %s: %d\n", __func__, lws_wsi_tag(wsi), flags); + lwsl_wsi_debug(wsi, "%d", flags); /* w->context is set after the loop is initialized */ if (!pt_to_priv_uv(pt)->io_loop || !w->context) { - lwsl_info("%s: no io loop yet\n", __func__); + lwsl_wsi_info(wsi, "no io loop yet"); return; } if (!((flags & (LWS_EV_START | LWS_EV_STOP)) && (flags & (LWS_EV_READ | LWS_EV_WRITE)))) { - lwsl_err("%s: assert: flags %d", __func__, flags); + lwsl_wsi_err(wsi, "assert: flags %d", flags); assert(0); } if (!w->pwatcher || wsi->told_event_loop_closed) { - lwsl_info("%s: no watcher\n", __func__); + lwsl_wsi_info(wsi, "no watcher"); return; } @@ -601,19 +619,18 @@ elops_init_vhost_listen_wsi_uv(struct lws *wsi) 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); + lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n, + (void *)(lws_intptr_t)wsi->desc.sockfd); return -1; } ptpriv->extant_handles++; - lwsl_debug("%s: thr %d: %s sa left %d: dyn left: %d\n", __func__, - (int)(pt - &pt->context->pt[0]), - lws_wsi_tag(wsi), - pt->count_event_loop_static_asset_handles, - ptpriv->extant_handles); + lwsl_wsi_debug(wsi, "thr %d: sa left %d: dyn left: %d", + (int)(pt - &pt->context->pt[0]), + pt->count_event_loop_static_asset_handles, + ptpriv->extant_handles); ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; @@ -651,7 +668,7 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi) } pt->event_loop_destroy_processing_done = 1; - lwsl_debug("%s: %d\n", __func__, tsi); + // lwsl_cx_debug(context, "%d", tsi); if (!pt->event_loop_foreign) { @@ -668,7 +685,7 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi) lws_uv_close_cb_sa); } } else - lwsl_debug("%s: not closing pt signals\n", __func__); + lwsl_cx_debug(context, "not closing pt signals"); 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); @@ -677,6 +694,17 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi) uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->idle, lws_uv_close_cb_sa); } +static int +elops_listen_init_uv(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + if (elops_init_vhost_listen_wsi_uv(wsi) == -1) + return -1; + + return 0; +} + /* * This needs to be called after vhosts have been defined. * @@ -689,7 +717,6 @@ 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; @@ -699,18 +726,18 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi) if (!loop) { loop = lws_malloc(sizeof(*loop), "libuv loop"); if (!loop) { - lwsl_err("OOM\n"); + lwsl_cx_err(context, "OOM"); return -1; } - #if UV_VERSION_MAJOR > 0 +#if UV_VERSION_MAJOR > 0 uv_loop_init(loop); - #else - lwsl_err("This libuv is too old to work...\n"); +#else + lwsl_cx_err(context, "This libuv is too old to work..."); return 1; - #endif +#endif pt->event_loop_foreign = 0; } else { - lwsl_notice(" Using foreign event loop...\n"); + lwsl_cx_notice(context, " Using foreign event loop..."); pt->event_loop_foreign = 1; } @@ -745,11 +772,7 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi) * We have to do it here because the uv loop(s) are not * initialized until after context creation. */ - while (vh) { - if (elops_init_vhost_listen_wsi_uv(vh->lserv_wsi) == -1) - return -1; - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_uv); if (!first) return status; @@ -771,7 +794,7 @@ lws_libuv_closewsi(uv_handle_t* handle) int lspd = 0; #endif - lwsl_notice("%s: %s\n", __func__, lws_wsi_tag(wsi)); + // lwsl_wsi_notice(wsi, "in"); lws_context_lock(context, __func__); @@ -791,12 +814,11 @@ lws_libuv_closewsi(uv_handle_t* handle) lws_pt_lock(pt, __func__); - lwsl_notice("%s: thr %d: %s sa left %d: dyn left: %d (rk %d)\n", __func__, - (int)(pt - &pt->context->pt[0]), - lws_wsi_tag(wsi), - pt->count_event_loop_static_asset_handles, - ptpriv->extant_handles - 1, - context->requested_stop_internal_loops); + lwsl_wsi_info(wsi, "thr %d: sa left %d: dyn left: %d (rk %d)", + (int)(pt - &pt->context->pt[0]), + pt->count_event_loop_static_asset_handles, + ptpriv->extant_handles - 1, + context->requested_stop_internal_loops); __lws_close_free_wsi_final(wsi); assert(ptpriv->extant_handles); @@ -808,7 +830,7 @@ lws_libuv_closewsi(uv_handle_t* handle) #if defined(LWS_WITH_SERVER) if (lspd == 2 && context->deprecation_cb) { - lwsl_notice("calling deprecation callback\n"); + lwsl_cx_notice(context, "calling deprecation callback"); context->deprecation_cb(); } #endif @@ -843,12 +865,10 @@ lws_libuv_closehandle(struct lws *wsi) if (!w_read->pwatcher) return; - if (wsi->told_event_loop_closed) { - // assert(0); + if (wsi->told_event_loop_closed) return; - } - lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(wsi)); +// lwsl_wsi_debug(wsi, "in"); wsi->told_event_loop_closed = 1; @@ -866,6 +886,27 @@ lws_libuv_closehandle(struct lws *wsi) uv_close(handle, lws_libuv_closewsi); } +static int +elops_foreign_thread_uv(struct lws_context *cx, int tsi) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; + struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); + uv_thread_t th = uv_thread_self(); + + if (!ptpriv->thread_valid) + /* + * We can't judge it until we get the first event from the loop + */ + return 0; + + /* + * This is the same thread that gave us the first event on this loop? + * Return 0 if so. + */ + + return !uv_thread_equal(&th, &ptpriv->uv_thread); +} + static const struct lws_event_loop_ops event_loop_ops_uv = { /* name */ "libuv", /* init_context */ elops_init_context_uv, @@ -881,6 +922,7 @@ static const struct lws_event_loop_ops event_loop_ops_uv = { /* run_pt */ elops_run_pt_uv, /* destroy_pt */ elops_destroy_pt_uv, /* destroy wsi */ NULL, + /* foreign_thread */ elops_foreign_thread_uv, /* flags */ 0, diff --git a/3rdparty/libwebsockets/lib/event-libs/libuv/private-lib-event-libs-libuv.h b/3rdparty/libwebsockets/lib/event-libs/libuv/private-lib-event-libs-libuv.h index e2625900..48715110 100644 --- a/3rdparty/libwebsockets/lib/event-libs/libuv/private-lib-event-libs-libuv.h +++ b/3rdparty/libwebsockets/lib/event-libs/libuv/private-lib-event-libs-libuv.h @@ -52,27 +52,32 @@ struct lws_signal_watcher_libuv { }; 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; + uv_loop_t *io_loop; + struct lws_context_per_thread *pt; + uv_signal_t signals[8]; + uv_timer_t sultimer; + uv_idle_t idle; + + uv_thread_t uv_thread; + struct lws_signal_watcher_libuv w_sigint; - int extant_handles; + int extant_handles; + + char thread_valid; }; struct lws_context_eventlibs_libuv { - uv_loop_t loop; + uv_loop_t loop; }; struct lws_io_watcher_libuv { - uv_poll_t *pwatcher; - struct lws_context *context; - uint8_t actual_events; + uv_poll_t *pwatcher; + struct lws_context *context; + uint8_t actual_events; }; struct lws_wsi_eventlibs_libuv { - struct lws_io_watcher_libuv w_read; + struct lws_io_watcher_libuv w_read; }; uv_loop_t * diff --git a/3rdparty/libwebsockets/lib/event-libs/poll/poll.c b/3rdparty/libwebsockets/lib/event-libs/poll/poll.c index f3685bf2..aa45dc53 100644 --- a/3rdparty/libwebsockets/lib/event-libs/poll/poll.c +++ b/3rdparty/libwebsockets/lib/event-libs/poll/poll.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -25,28 +25,29 @@ #include #include "private-lib-event-libs-poll.h" +static int +elops_foreign_thread_poll(struct lws_context *cx, int tsi) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; + volatile struct lws_context_per_thread *vpt = + (volatile struct lws_context_per_thread *)pt; + + /* + * To avoid mandating a specific threading library, we can check + * probabilistically by seeing if the lws default wait is still asleep + * at the time we are checking, if it is then we cannot be being called + * by the event loop loop thread. + */ + + return vpt->inside_poll; +} + struct lws_event_loop_ops event_loop_ops_poll = { - /* name */ "poll", - /* init_context */ NULL, - /* destroy_context1 */ NULL, - /* destroy_context2 */ NULL, - /* init_vhost_listen_wsi */ NULL, - /* init_pt */ NULL, - /* wsi_logical_close */ NULL, - /* check_client_connect_ok */ NULL, - /* close_handle_manually */ NULL, - /* accept */ NULL, - /* io */ NULL, - /* run */ NULL, - /* destroy_pt */ NULL, - /* destroy wsi */ NULL, - - /* flags */ LELOF_ISPOLL, - - /* evlib_size_ctx */ 0, - /* evlib_size_pt */ 0, - /* evlib_size_vh */ 0, - /* evlib_size_wsi */ 0, + .name = "poll", + + .foreign_thread = elops_foreign_thread_poll, + + .flags = LELOF_ISPOLL, }; const lws_plugin_evlib_t evlib_poll = { diff --git a/3rdparty/libwebsockets/lib/event-libs/private-lib-event-libs.h b/3rdparty/libwebsockets/lib/event-libs/private-lib-event-libs.h index 3c249498..5cc0b751 100644 --- a/3rdparty/libwebsockets/lib/event-libs/private-lib-event-libs.h +++ b/3rdparty/libwebsockets/lib/event-libs/private-lib-event-libs.h @@ -24,45 +24,4 @@ * This is included from private-lib-core.h */ -enum lws_event_lib_ops_flags { - LELOF_ISPOLL = (1 >> 0), - LELOF_DESTROY_FINAL = (1 >> 1), -}; -struct lws_event_loop_ops { - const char *name; - /* event loop-specific context init during context creation */ - int (*init_context)(struct lws_context *context, - const struct lws_context_creation_info *info); - /* called during lws_destroy_context */ - int (*destroy_context1)(struct lws_context *context); - /* called during lws_destroy_context2 */ - int (*destroy_context2)(struct lws_context *context); - /* init vhost listening wsi */ - int (*init_vhost_listen_wsi)(struct lws *wsi); - /* init the event loop for a pt */ - int (*init_pt)(struct lws_context *context, void *_loop, int tsi); - /* called at end of first phase of close_free_wsi() */ - int (*wsi_logical_close)(struct lws *wsi); - /* return nonzero if client connect not allowed */ - int (*check_client_connect_ok)(struct lws *wsi); - /* close handle manually */ - void (*close_handle_manually)(struct lws *wsi); - /* event loop accept processing */ - int (*sock_accept)(struct lws *wsi); - /* control wsi active events */ - void (*io)(struct lws *wsi, unsigned int flags); - /* run the event loop for a pt */ - void (*run_pt)(struct lws_context *context, int tsi); - /* called before pt is destroyed */ - void (*destroy_pt)(struct lws_context *context, int tsi); - /* called just before wsi is freed */ - void (*destroy_wsi)(struct lws *wsi); - - uint8_t flags; - - uint16_t evlib_size_ctx; - uint16_t evlib_size_pt; - uint16_t evlib_size_vh; - uint16_t evlib_size_wsi; -}; diff --git a/3rdparty/libwebsockets/lib/event-libs/sdevent/sdevent.c b/3rdparty/libwebsockets/lib/event-libs/sdevent/sdevent.c index a8939586..0c7ddaec 100644 --- a/3rdparty/libwebsockets/lib/event-libs/sdevent/sdevent.c +++ b/3rdparty/libwebsockets/lib/event-libs/sdevent/sdevent.c @@ -170,7 +170,7 @@ io_sd(struct lws *wsi, unsigned int flags) // assert that the requested flags do not contain anything unexpected if (!((flags & (LWS_EV_START | LWS_EV_STOP)) && (flags & (LWS_EV_READ | LWS_EV_WRITE)))) { - lwsl_err("%s: assert: flags %d", __func__, flags); + lwsl_wsi_err(wsi, "assert: flags %d", flags); assert(0); } @@ -231,22 +231,32 @@ init_vhost_listen_wsi_sd(struct lws *wsi) return 0; } +static int +elops_listen_init_sdevent(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + if (init_vhost_listen_wsi_sd(wsi) == -1) + return -1; + + return 0; +} + static int init_pt_sd(struct lws_context *context, void *_loop, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt); struct sd_event *loop = (struct sd_event *)_loop; - struct lws_vhost *vh; - int first = 1; // we are the first that create and initialize the loop + int first = 1; /* first to create and initialize the loop */ ptpriv->pt = pt; - // make sure we have an event loop + /* make sure we have an event loop */ if (!ptpriv->io_loop) { if (!loop) { if (sd_event_default(&loop) < 0) { - lwsl_err("%s: sd_event_default failed\n", __func__); + lwsl_cx_err(context, "sd_event_default failed"); return -1; } @@ -257,7 +267,6 @@ init_pt_sd(struct lws_context *context, void *_loop, int tsi) } ptpriv->io_loop = loop; - } else /* * If the loop was initialized before, we do not need to @@ -265,12 +274,7 @@ init_pt_sd(struct lws_context *context, void *_loop, int tsi) */ first = 0; - // initialize accept/read for vhosts - // Note: default vhost usually not included here - for (vh = context->vhost_list; vh; vh = vh->vhost_next) - /* call lws_event_loop_ops->init_vhost_listen_wsi */ - if (init_vhost_listen_wsi_sd(vh->lserv_wsi) == -1) - return -1; + lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_sdevent); if (first) { @@ -361,16 +365,23 @@ run_pt_sd(struct lws_context *context, int tsi) sd_event_run(ptpriv->io_loop, (uint64_t) -1); } +static int +elops_listen_destroy_sdevent(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + + wsi_logical_close_sd(wsi); + + return 0; +} + static void destroy_pt_sd(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt); - struct lws_vhost *vh; - for (vh = context->vhost_list; vh; vh = vh->vhost_next) - if (vh->lserv_wsi) - wsi_logical_close_sd(vh->lserv_wsi); + lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_sdevent); if (ptpriv->sultimer) { sd_event_source_set_enabled(ptpriv->sultimer, @@ -390,7 +401,6 @@ destroy_pt_sd(struct lws_context *context, int tsi) sd_event_unref(ptpriv->io_loop); ptpriv->io_loop = NULL; } - } const struct lws_event_loop_ops event_loop_ops_sdevent = { diff --git a/3rdparty/libwebsockets/lib/event-libs/uloop/uloop.c b/3rdparty/libwebsockets/lib/event-libs/uloop/uloop.c index 00ed5373..be9046c7 100644 --- a/3rdparty/libwebsockets/lib/event-libs/uloop/uloop.c +++ b/3rdparty/libwebsockets/lib/event-libs/uloop/uloop.c @@ -121,7 +121,7 @@ lws_uloop_cb(struct uloop_fd *ufd, unsigned int revents) lws_service_fd_tsi(context, &eventfd, wu->wsi->tsi); if (pt->destroy_self) { - lwsl_notice("%s: pt destroy self coming true\n", __func__); + lwsl_cx_notice(context, "pt destroy self coming true"); lws_context_destroy(pt->context); return; } @@ -132,33 +132,30 @@ lws_uloop_cb(struct uloop_fd *ufd, unsigned int revents) uloop_timeout_set(&pt_to_priv_uloop(pt)->idle_timer, 1); } +static int +elops_listen_init_uloop(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); + + wu->wsi = wsi; + wu->fd.fd = wsi->desc.sockfd; + wu->fd.cb = lws_uloop_cb; + uloop_fd_add(&wu->fd, ULOOP_READ); + wu->actual_events = ULOOP_READ; + + return 0; +} + static int elops_init_pt_uloop(struct lws_context *context, void *v, int tsi) { - struct lws_vhost *vh = context->vhost_list; struct lws_context_per_thread *pt = &context->pt[tsi]; struct lws_pt_eventlibs_uloop *ptpr = pt_to_priv_uloop(pt); ptpr->pt = pt; - /* - * Initialize all events with the listening sockets - * and register a callback for read operations - */ - - while (vh) { - if (vh->lserv_wsi) { - struct lws_wsi_eventlibs_uloop *wu = - wsi_to_priv_uloop(vh->lserv_wsi); - wu->wsi = vh->lserv_wsi; - wu->fd.fd = vh->lserv_wsi->desc.sockfd; - wu->fd.cb = lws_uloop_cb; - uloop_fd_add(&wu->fd, ULOOP_READ); - wu->actual_events = ULOOP_READ; - } - - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_uloop); /* static event loop objects */ @@ -217,20 +214,24 @@ elops_run_pt_uloop(struct lws_context *context, int tsi) uloop_run(); } +static int +elops_listen_destroy_uloop(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); + + uloop_fd_delete(&wu->fd); + + return 0; +} + static void elops_destroy_pt_uloop(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; struct lws_pt_eventlibs_uloop *ptpr = pt_to_priv_uloop(pt); - struct lws_vhost *vh; - - vh = context->vhost_list; - while (vh) { - if (vh->lserv_wsi) - uloop_fd_delete(&wsi_to_priv_uloop(vh->lserv_wsi)->fd); - vh = vh->vhost_next; - } + lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_uloop); uloop_timeout_cancel(&ptpr->hrtimer); uloop_timeout_cancel(&ptpr->idle_timer); @@ -295,6 +296,7 @@ static const struct lws_event_loop_ops event_loop_ops_uloop = { /* run_pt */ elops_run_pt_uloop, /* destroy_pt */ elops_destroy_pt_uloop, /* destroy wsi */ elops_destroy_wsi_uloop, + /* foreign_thread */ NULL, /* flags */ 0, diff --git a/3rdparty/libwebsockets/lib/jose/CMakeLists.txt b/3rdparty/libwebsockets/lib/jose/CMakeLists.txt index 2634f52c..161744ef 100644 --- a/3rdparty/libwebsockets/lib/jose/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/jose/CMakeLists.txt @@ -26,8 +26,9 @@ include_directories(. ./jwe ./jws ./jwk) if (LWS_WITH_JOSE) list(APPEND SOURCES - jose/jwk/jwk.c jose/jws/jose.c + jose/jwk/jwk.c + jose/jwk/jose_key.c jose/jws/jws.c jose/jwe/jwe.c jose/jwe/enc/aescbc.c diff --git a/3rdparty/libwebsockets/lib/jose/jwk/jose_key.c b/3rdparty/libwebsockets/lib/jose/jwk/jose_key.c new file mode 100644 index 00000000..2d754d91 --- /dev/null +++ b/3rdparty/libwebsockets/lib/jose/jwk/jose_key.c @@ -0,0 +1,649 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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. + * + * JOSE-specific JWK code + */ + +#include "private-lib-core.h" +#include "private-lib-jose.h" + +#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT) +#include +#endif + +static const char * const kty_names[] = { + "unknown", /* LWS_GENCRYPTO_KTY_UNKNOWN */ + "oct", /* LWS_GENCRYPTO_KTY_OCT */ + "RSA", /* LWS_GENCRYPTO_KTY_RSA */ + "EC" /* LWS_GENCRYPTO_KTY_EC */ +}; + +/* + * These are the entire legal token set for names in jwk. + * + * The first version is used to parse a detached single jwk that don't have any + * parent JSON context. The second version is used to parse full jwk objects + * that has a "keys": [ ] array containing the keys. + */ + +const char * const jwk_tok[] = { + "keys[]", /* dummy */ + "e", "n", "d", "p", "q", "dp", "dq", "qi", /* RSA */ + "kty", /* generic */ + "k", /* symmetric key data */ + "crv", "x", "y", /* EC (also "D") */ + "kid", /* generic */ + "use" /* mutually exclusive with "key_ops" */, + "key_ops" /* mutually exclusive with "use" */, + "x5c", /* generic */ + "alg" /* generic */ +}, * const jwk_outer_tok[] = { + "keys[]", + "keys[].e", "keys[].n", "keys[].d", "keys[].p", "keys[].q", "keys[].dp", + "keys[].dq", "keys[].qi", + + "keys[].kty", "keys[].k", /* generic */ + "keys[].crv", "keys[].x", "keys[].y", /* EC (also "D") */ + "keys[].kid", "keys[].use" /* mutually exclusive with "key_ops" */, + "keys[].key_ops", /* mutually exclusive with "use" */ + "keys[].x5c", "keys[].alg" +}; + +static unsigned short tok_map[] = { + F_RSA | F_EC | F_OCT | F_META | 0xff, + F_RSA | F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_E, + F_RSA | F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_N, + F_RSA | F_EC | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_D, + F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_P, + F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_Q, + F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_DP, + F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_DQ, + F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_QI, + + F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY, + F_OCT | F_B64U | F_M | LWS_GENCRYPTO_OCT_KEYEL_K, + + F_EC | F_M | LWS_GENCRYPTO_EC_KEYEL_CRV, + F_EC | F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_X, + F_EC | F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_Y, + + F_RSA | F_EC | F_OCT | F_META | JWK_META_KID, + F_RSA | F_EC | F_OCT | F_META | JWK_META_USE, + + F_RSA | F_EC | F_OCT | F_META | JWK_META_KEY_OPS, + F_RSA | F_EC | F_OCT | F_META | F_B64 | JWK_META_X5C, + F_RSA | F_EC | F_OCT | F_META | JWK_META_ALG, +}; + +struct lexico { + const char *name; + int idx; + char meta; +} lexico_ec[] = { + { "alg", JWK_META_ALG, 1 }, + { "crv", LWS_GENCRYPTO_EC_KEYEL_CRV, 0 }, + { "d", LWS_GENCRYPTO_EC_KEYEL_D, 2 | 0 }, + { "key_ops", JWK_META_KEY_OPS, 1 }, + { "kid", JWK_META_KID, 1 }, + { "kty", JWK_META_KTY, 1 }, + { "use", JWK_META_USE, 1 }, + { "x", LWS_GENCRYPTO_EC_KEYEL_X, 0 }, + { "x5c", JWK_META_X5C, 1 }, + { "y", LWS_GENCRYPTO_EC_KEYEL_Y, 0 } +}, lexico_oct[] = { + { "alg", JWK_META_ALG, 1 }, + { "k", LWS_GENCRYPTO_OCT_KEYEL_K, 0 }, + { "key_ops", JWK_META_KEY_OPS, 1 }, + { "kid", JWK_META_KID, 1 }, + { "kty", JWK_META_KTY, 1 }, + { "use", JWK_META_USE, 1 }, + { "x5c", JWK_META_X5C, 1 } +}, lexico_rsa[] = { + { "alg", JWK_META_ALG, 1 }, + { "d", LWS_GENCRYPTO_RSA_KEYEL_D, 2 | 0 }, + { "dp", LWS_GENCRYPTO_RSA_KEYEL_DP, 2 | 0 }, + { "dq", LWS_GENCRYPTO_RSA_KEYEL_DQ, 2 | 0 }, + { "e", LWS_GENCRYPTO_RSA_KEYEL_E, 0 }, + { "key_ops", JWK_META_KEY_OPS, 1 }, + { "kid", JWK_META_KID, 1 }, + { "kty", JWK_META_KTY, 1 }, + { "n", LWS_GENCRYPTO_RSA_KEYEL_N, 0 }, + { "p", LWS_GENCRYPTO_RSA_KEYEL_P, 2 | 0 }, + { "q", LWS_GENCRYPTO_RSA_KEYEL_Q, 2 | 0 }, + { "qi", LWS_GENCRYPTO_RSA_KEYEL_QI, 2 | 0 }, + { "use", JWK_META_USE, 1 }, + { "x5c", JWK_META_X5C, 1 } +}; + +static int +_lws_jwk_set_el_jwk_b64(struct lws_gencrypto_keyelem *e, char *in, int len) +{ + size_t dec_size = (unsigned int)lws_base64_size(len); + int n; + + e->buf = lws_malloc(dec_size, "jwk"); + if (!e->buf) + return -1; + + /* same decoder accepts both url or original styles */ + + n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1); + if (n < 0) + return -1; + e->len = (uint32_t)n; + + return 0; +} + +static int +_lws_jwk_set_el_jwk_b64u(struct lws_gencrypto_keyelem *e, char *in, int len) +{ + size_t dec_size = (size_t)lws_base64_size(len); + int n; + + e->buf = lws_malloc(dec_size, "jwk"); + if (!e->buf) + return -1; + + /* same decoder accepts both url or original styles */ + + n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1); + if (n < 0) + return -1; + e->len = (uint32_t)n; + + return 0; +} + + +signed char +cb_jwk(struct lejp_ctx *ctx, char reason) +{ + struct lws_jwk_parse_state *jps = (struct lws_jwk_parse_state *)ctx->user; + struct lws_jwk *jwk = jps->jwk; + unsigned int idx, n; + unsigned short poss; + char dotstar[64]; + + if (reason == LEJPCB_VAL_STR_START) + jps->pos = 0; + + if (reason == LEJPCB_OBJECT_START && ctx->path_match == 0 + 1) + /* + * new keys[] member is starting + * + * Until we see some JSON names, it could be anything... + * there is no requirement for kty to be given first and eg, + * ACME specifies the keys must be ordered in lexographic + * order - where kty is not first. + */ + jps->possible = F_RSA | F_EC | F_OCT; + + if (reason == LEJPCB_OBJECT_END && ctx->path_match == 0 + 1) { + /* we completed parsing a key */ + if (jps->per_key_cb && jps->possible) { + if (jps->per_key_cb(jps->jwk, jps->user)) { + + lwsl_notice("%s: user cb halts import\n", + __func__); + + return -2; + } + + /* clear it down */ + lws_jwk_destroy(jps->jwk); + jps->possible = 0; + } + } + + if (reason == LEJPCB_COMPLETE) { + + /* + * Now we saw the whole jwk and know the key type, let'jwk insist + * that as a whole, it must be consistent and complete. + * + * The tracking of ->possible bits from even before we know the + * kty already makes certain we cannot have key element members + * defined that are inconsistent with the key type. + */ + + for (n = 0; n < LWS_ARRAY_SIZE(tok_map); n++) + /* + * All mandataory elements for the key type + * must be present + */ + if ((tok_map[n] & jps->possible) && ( + ((tok_map[n] & (F_M | F_META)) == (F_M | F_META) && + !jwk->meta[tok_map[n] & 0xff].buf) || + ((tok_map[n] & (F_M | F_META)) == F_M && + !jwk->e[tok_map[n] & 0xff].buf))) { + lwsl_notice("%s: missing %s\n", __func__, + jwk_tok[n]); + return -3; + } + + /* + * When the key may be public or public + private, ensure the + * intra-key members related to that are consistent. + * + * Only RSA keys need extra care, since EC keys are already + * confirmed by making CRV, X and Y mandatory and only D + * (the singular private part) optional. For RSA, N and E are + * also already known to be present using mandatory checking. + */ + + /* + * If a private key, it must have all D, P and Q. Public key + * must have none of them. + */ + if (jwk->kty == LWS_GENCRYPTO_KTY_RSA && + !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) && + (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) && + (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf)) || + (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf && + jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf && + jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf)) + ) { + lwsl_notice("%s: RSA requires D, P and Q for private\n", + __func__); + return -3; + } + + /* + * If the precomputed private key terms appear, they must all + * appear together. + */ + if (jwk->kty == LWS_GENCRYPTO_KTY_RSA && + !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf) && + (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) && + (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf)) || + (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf && + jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf && + jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf)) + ) { + lwsl_notice("%s: RSA DP, DQ, QI must all appear " + "or none\n", __func__); + return -3; + } + + /* + * The precomputed private key terms must not appear without + * the private key itself also appearing. + */ + if (jwk->kty == LWS_GENCRYPTO_KTY_RSA && + !jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf && + jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) { + lwsl_notice("%s: RSA DP, DQ, QI can appear only with " + "private key\n", __func__); + return -3; + } + + if ((jwk->kty == LWS_GENCRYPTO_KTY_RSA || + jwk->kty == LWS_GENCRYPTO_KTY_EC) && + jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) + jwk->private_key = 1; + } + + if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) + return 0; + + if (ctx->path_match == 0 + 1) + return 0; + + idx = tok_map[ctx->path_match - 1]; + if ((idx & 0xff) == 0xff) + return 0; + + switch (idx) { + /* note: kty is not necessarily first... we have to keep track of + * what could match given which element names have already been + * seen. Once kty comes, we confirm it'jwk still possible (ie, it'jwk + * not trying to tell us that it'jwk RSA now when we saw a "crv" + * earlier) and then reduce the possibilities to just the one that + * kty told. */ + case F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY: + + if (ctx->npos == 3 && !strncmp(ctx->buf, "oct", 3)) { + if (!(jps->possible & F_OCT)) + goto elements_mismatch; + jwk->kty = LWS_GENCRYPTO_KTY_OCT; + jps->possible = F_OCT; + goto cont; + } + if (ctx->npos == 3 && !strncmp(ctx->buf, "RSA", 3)) { + if (!(jps->possible & F_RSA)) + goto elements_mismatch; + jwk->kty = LWS_GENCRYPTO_KTY_RSA; + jps->possible = F_RSA; + goto cont; + } + if (ctx->npos == 2 && !strncmp(ctx->buf, "EC", 2)) { + if (!(jps->possible & F_EC)) + goto elements_mismatch; + jwk->kty = LWS_GENCRYPTO_KTY_EC; + jps->possible = F_EC; + goto cont; + } + lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); + lwsl_err("%s: Unknown KTY '%s'\n", __func__, dotstar); + return -1; + + default: +cont: + if (jps->pos + ctx->npos >= (int)sizeof(jps->b64)) + goto bail; + + memcpy(jps->b64 + jps->pos, ctx->buf, ctx->npos); + jps->pos += ctx->npos; + + if (reason == LEJPCB_VAL_STR_CHUNK) + return 0; + + /* chunking has been collated */ + + poss = idx & (F_RSA | F_EC | F_OCT); + jps->possible &= poss; + if (!jps->possible) + goto elements_mismatch; + + if (idx & F_META) { + if (_lws_jwk_set_el_jwk(&jwk->meta[idx & 0x7f], + jps->b64, (unsigned int)jps->pos) < 0) + goto bail; + + break; + } + + if (idx & F_B64U) { + /* key data... do the base64 decode as needed */ + if (_lws_jwk_set_el_jwk_b64u(&jwk->e[idx & 0x7f], + jps->b64, jps->pos) < 0) + goto bail; + + if (jwk->e[idx & 0x7f].len > + LWS_JWE_LIMIT_KEY_ELEMENT_BYTES) { + lwsl_notice("%s: oversize keydata\n", __func__); + goto bail; + } + + return 0; + } + + if (idx & F_B64) { + + /* cert data... do non-urlcoded base64 decode */ + if (_lws_jwk_set_el_jwk_b64(&jwk->e[idx & 0x7f], + jps->b64, jps->pos) < 0) + goto bail; + return 0; + } + + if (_lws_jwk_set_el_jwk(&jwk->e[idx & 0x7f], + jps->b64, (unsigned int)jps->pos) < 0) + goto bail; + break; + } + + return 0; + +elements_mismatch: + lwsl_err("%s: jwk elements mismatch\n", __func__); + +bail: + lwsl_err("%s: element failed\n", __func__); + + return -1; +} + +int +lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user, + const char *in, size_t len) +{ + struct lejp_ctx jctx; + struct lws_jwk_parse_state jps; + int m; + + lws_jwk_init_jps(&jps, jwk, cb, user); + + lejp_construct(&jctx, cb_jwk, &jps, cb ? jwk_outer_tok: jwk_tok, + LWS_ARRAY_SIZE(jwk_tok)); + + m = lejp_parse(&jctx, (uint8_t *)in, (int)len); + lejp_destruct(&jctx); + + if (m < 0) { + lwsl_notice("%s: parse got %d\n", __func__, m); + lws_jwk_destroy(jwk); + return -1; + } + + switch (jwk->kty) { + case LWS_GENCRYPTO_KTY_UNKNOWN: + lwsl_notice("%s: missing or unknown kty\n", __func__); + lws_jwk_destroy(jwk); + return -1; + default: + break; + } + + return 0; +} + + +int +lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) +{ + char *start = p, *end = &p[*len - 1]; + int n, m, limit, first = 1, asym = 0; + struct lexico *l; + + /* RFC7638 lexicographic order requires + * RSA: e -> kty -> n + * oct: k -> kty + * + * ie, meta and key data elements appear interleaved in name alpha order + */ + + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{"); + + switch (jwk->kty) { + case LWS_GENCRYPTO_KTY_OCT: + l = lexico_oct; + limit = LWS_ARRAY_SIZE(lexico_oct); + break; + case LWS_GENCRYPTO_KTY_RSA: + l = lexico_rsa; + limit = LWS_ARRAY_SIZE(lexico_rsa); + asym = 1; + break; + case LWS_GENCRYPTO_KTY_EC: + l = lexico_ec; + limit = LWS_ARRAY_SIZE(lexico_ec); + asym = 1; + break; + default: + return -1; + } + + for (n = 0; n < limit; n++) { + const char *q, *q_end; + char tok[12]; + int pos = 0, f = 1; + + if ((l->meta & 1) && (jwk->meta[l->idx].buf || + l->idx == (int)JWK_META_KTY)) { + + switch (l->idx) { + case JWK_META_KTY: + if (!first) + *p++ = ','; + first = 0; + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"%s\"", + l->name, kty_names[jwk->kty]); + break; + case JWK_META_KEY_OPS: + if (!first) + *p++ = ','; + first = 0; + q = (const char *)jwk->meta[l->idx].buf; + q_end = q + jwk->meta[l->idx].len; + + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + "\"%s\":[", l->name); + /* + * For the public version, usages that + * require the private part must be + * snipped + */ + + while (q < q_end) { + if (*q != ' ' && pos < (int)sizeof(tok) - 1) { + tok[pos++] = *q++; + if (q != q_end) + continue; + } + tok[pos] = '\0'; + pos = 0; + if ((flags & LWSJWKF_EXPORT_PRIVATE) || + !asym || (strcmp(tok, "sign") && + strcmp(tok, "encrypt"))) { + if (!f) + *p++ = ','; + f = 0; + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + "\"%s\"", tok); + } + q++; + } + + *p++ = ']'; + + break; + + default: + /* both sig and enc require asym private key */ + if (!(flags & LWSJWKF_EXPORT_PRIVATE) && + asym && l->idx == (int)JWK_META_USE) + break; + if (!first) + *p++ = ','; + first = 0; + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"", + l->name); + lws_strnncpy(p, (const char *)jwk->meta[l->idx].buf, + jwk->meta[l->idx].len, end - p); + p += strlen(p); + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\""); + break; + } + } + + if ((!(l->meta & 1)) && jwk->e[l->idx].buf && + ((flags & LWSJWKF_EXPORT_PRIVATE) || !(l->meta & 2))) { + if (!first) + *p++ = ','; + first = 0; + + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"", l->name); + + if (jwk->kty == LWS_GENCRYPTO_KTY_EC && + l->idx == (int)LWS_GENCRYPTO_EC_KEYEL_CRV) { + lws_strnncpy(p, + (const char *)jwk->e[l->idx].buf, + jwk->e[l->idx].len, end - p); + m = (int)strlen(p); + } else + m = lws_jws_base64_enc( + (const char *)jwk->e[l->idx].buf, + jwk->e[l->idx].len, p, lws_ptr_diff_size_t(end, p) - 4); + if (m < 0) { + lwsl_notice("%s: enc failed\n", __func__); + return -1; + } + p += m; + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\""); + } + + l++; + } + + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n"); + + *len -= lws_ptr_diff(p, start); + + return lws_ptr_diff(p, start); +} + +int +lws_jwk_load(struct lws_jwk *jwk, const char *filename, + lws_jwk_key_import_callback cb, void *user) +{ + unsigned int buflen = 4096; + char *buf = lws_malloc(buflen, "jwk-load"); + int n; + + if (!buf) + return -1; + + n = lws_plat_read_file(filename, buf, buflen); + if (n < 0) + goto bail; + + n = lws_jwk_import(jwk, cb, user, buf, (unsigned int)n); + lws_free(buf); + + return n; +bail: + lws_free(buf); + + return -1; +} + +int +lws_jwk_save(struct lws_jwk *jwk, const char *filename) +{ + int buflen = 4096; + char *buf = lws_malloc((unsigned int)buflen, "jwk-save"); + int n, m; + + if (!buf) + return -1; + + n = lws_jwk_export(jwk, LWSJWKF_EXPORT_PRIVATE, buf, &buflen); + if (n < 0) + goto bail; + + m = lws_plat_write_file(filename, buf, (size_t)n); + + lws_free(buf); + if (m) + return -1; + + return 0; + +bail: + lws_free(buf); + + return -1; +} diff --git a/3rdparty/libwebsockets/lib/jose/jwk/jwk.c b/3rdparty/libwebsockets/lib/jose/jwk/jwk.c index 592d5a28..d0befd82 100644 --- a/3rdparty/libwebsockets/lib/jose/jwk/jwk.c +++ b/3rdparty/libwebsockets/lib/jose/jwk/jwk.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -20,133 +20,17 @@ * 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. + * + * Shared JWK handling that's the same whether JOSE or COSE */ #include "private-lib-core.h" #include "private-lib-jose.h" -#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT) -#include -#endif - -static const char * const kty_names[] = { - "unknown", /* LWS_GENCRYPTO_KTY_UNKNOWN */ - "oct", /* LWS_GENCRYPTO_KTY_OCT */ - "RSA", /* LWS_GENCRYPTO_KTY_RSA */ - "EC" /* LWS_GENCRYPTO_KTY_EC */ -}; - -/* - * These are the entire legal token set for names in jwk. - * - * The first version is used to parse a detached single jwk that don't have any - * parent JSON context. The second version is used to parse full jwk objects - * that has a "keys": [ ] array containing the keys. - */ - -static const char * const jwk_tok[] = { - "keys[]", /* dummy */ - "e", "n", "d", "p", "q", "dp", "dq", "qi", /* RSA */ - "kty", /* generic */ - "k", /* symmetric key data */ - "crv", "x", "y", /* EC (also "D") */ - "kid", /* generic */ - "use" /* mutually exclusive with "key_ops" */, - "key_ops" /* mutually exclusive with "use" */, - "x5c", /* generic */ - "alg" /* generic */ -}, * const jwk_outer_tok[] = { - "keys[]", - "keys[].e", "keys[].n", "keys[].d", "keys[].p", "keys[].q", "keys[].dp", - "keys[].dq", "keys[].qi", - - "keys[].kty", "keys[].k", /* generic */ - "keys[].crv", "keys[].x", "keys[].y", /* EC (also "D") */ - "keys[].kid", "keys[].use" /* mutually exclusive with "key_ops" */, - "keys[].key_ops", /* mutually exclusive with "use" */ - "keys[].x5c", "keys[].alg" -}; - -/* information about each token declared above */ - -#define F_M (1 << 9) /* Mandatory for key type */ -#define F_B64 (1 << 10) /* Base64 coded octets */ -#define F_B64U (1 << 11) /* Base64 Url coded octets */ -#define F_META (1 << 12) /* JWK key metainformation */ -#define F_RSA (1 << 13) /* RSA key */ -#define F_EC (1 << 14) /* Elliptic curve key */ -#define F_OCT (1 << 15) /* octet key */ - -static unsigned short tok_map[] = { - F_RSA | F_EC | F_OCT | F_META | 0xff, - F_RSA | F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_E, - F_RSA | F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_N, - F_RSA | F_EC | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_D, - F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_P, - F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_Q, - F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_DP, - F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_DQ, - F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_QI, - - F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY, - F_OCT | F_B64U | F_M | LWS_GENCRYPTO_OCT_KEYEL_K, - - F_EC | F_M | LWS_GENCRYPTO_EC_KEYEL_CRV, - F_EC | F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_X, - F_EC | F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_Y, - - F_RSA | F_EC | F_OCT | F_META | JWK_META_KID, - F_RSA | F_EC | F_OCT | F_META | JWK_META_USE, - - F_RSA | F_EC | F_OCT | F_META | JWK_META_KEY_OPS, - F_RSA | F_EC | F_OCT | F_META | F_B64 | JWK_META_X5C, - F_RSA | F_EC | F_OCT | F_META | JWK_META_ALG, -}; - static const char *meta_names[] = { "kty", "kid", "use", "key_ops", "x5c", "alg" }; -struct lexico { - const char *name; - int idx; - char meta; -} lexico_ec[] = { - { "alg", JWK_META_ALG, 1 }, - { "crv", LWS_GENCRYPTO_EC_KEYEL_CRV, 0 }, - { "d", LWS_GENCRYPTO_EC_KEYEL_D, 2 | 0 }, - { "key_ops", JWK_META_KEY_OPS, 1 }, - { "kid", JWK_META_KID, 1 }, - { "kty", JWK_META_KTY, 1 }, - { "use", JWK_META_USE, 1 }, - { "x", LWS_GENCRYPTO_EC_KEYEL_X, 0 }, - { "x5c", JWK_META_X5C, 1 }, - { "y", LWS_GENCRYPTO_EC_KEYEL_Y, 0 } -}, lexico_oct[] = { - { "alg", JWK_META_ALG, 1 }, - { "k", LWS_GENCRYPTO_OCT_KEYEL_K, 0 }, - { "key_ops", JWK_META_KEY_OPS, 1 }, - { "kid", JWK_META_KID, 1 }, - { "kty", JWK_META_KTY, 1 }, - { "use", JWK_META_USE, 1 }, - { "x5c", JWK_META_X5C, 1 } -}, lexico_rsa[] = { - { "alg", JWK_META_ALG, 1 }, - { "d", LWS_GENCRYPTO_RSA_KEYEL_D, 2 | 0 }, - { "dp", LWS_GENCRYPTO_RSA_KEYEL_DP, 2 | 0 }, - { "dq", LWS_GENCRYPTO_RSA_KEYEL_DQ, 2 | 0 }, - { "e", LWS_GENCRYPTO_RSA_KEYEL_E, 0 }, - { "key_ops", JWK_META_KEY_OPS, 1 }, - { "kid", JWK_META_KID, 1 }, - { "kty", JWK_META_KTY, 1 }, - { "n", LWS_GENCRYPTO_RSA_KEYEL_N, 0 }, - { "p", LWS_GENCRYPTO_RSA_KEYEL_P, 2 | 0 }, - { "q", LWS_GENCRYPTO_RSA_KEYEL_Q, 2 | 0 }, - { "qi", LWS_GENCRYPTO_RSA_KEYEL_QI, 2 | 0 }, - { "use", JWK_META_USE, 1 }, - { "x5c", JWK_META_X5C, 1 } -}; - static const char meta_b64[] = { 0, 0, 0, 0, 1, 0 }; static const char *oct_names[] = { @@ -221,7 +105,7 @@ lws_jwk_dump(struct lws_jwk *jwk) return 0; } -static int +int _lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem *e, char *in, size_t len) { e->buf = lws_malloc(len + 1, "jwk"); @@ -235,46 +119,6 @@ _lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem *e, char *in, size_t len) return 0; } -static int -_lws_jwk_set_el_jwk_b64(struct lws_gencrypto_keyelem *e, char *in, int len) -{ - size_t dec_size = (unsigned int)lws_base64_size(len); - int n; - - e->buf = lws_malloc(dec_size, "jwk"); - if (!e->buf) - return -1; - - /* same decoder accepts both url or original styles */ - - n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1); - if (n < 0) - return -1; - e->len = (uint32_t)n; - - return 0; -} - -static int -_lws_jwk_set_el_jwk_b64u(struct lws_gencrypto_keyelem *e, char *in, int len) -{ - size_t dec_size = (size_t)lws_base64_size(len); - int n; - - e->buf = lws_malloc(dec_size, "jwk"); - if (!e->buf) - return -1; - - /* same decoder accepts both url or original styles */ - - n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1); - if (n < 0) - return -1; - e->len = (uint32_t)n; - - return 0; -} - void lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m) { @@ -296,261 +140,21 @@ lws_jwk_destroy(struct lws_jwk *jwk) lws_jwk_destroy_elements(jwk->meta, LWS_ARRAY_SIZE(jwk->meta)); } -static signed char -cb_jwk(struct lejp_ctx *ctx, char reason) -{ - struct lws_jwk_parse_state *jps = (struct lws_jwk_parse_state *)ctx->user; - struct lws_jwk *jwk = jps->jwk; - unsigned int idx, n; - unsigned short poss; - char dotstar[64]; - - if (reason == LEJPCB_VAL_STR_START) - jps->pos = 0; - - if (reason == LEJPCB_OBJECT_START && ctx->path_match == 0 + 1) - /* - * new keys[] member is starting - * - * Until we see some JSON names, it could be anything... - * there is no requirement for kty to be given first and eg, - * ACME specifies the keys must be ordered in lexographic - * order - where kty is not first. - */ - jps->possible = F_RSA | F_EC | F_OCT; - - if (reason == LEJPCB_OBJECT_END && ctx->path_match == 0 + 1) { - /* we completed parsing a key */ - if (jps->per_key_cb && jps->possible) { - if (jps->per_key_cb(jps->jwk, jps->user)) { - - lwsl_notice("%s: user cb halts import\n", - __func__); - - return -2; - } - - /* clear it down */ - lws_jwk_destroy(jps->jwk); - jps->possible = 0; - } - } - - if (reason == LEJPCB_COMPLETE) { - - /* - * Now we saw the whole jwk and know the key type, let'jwk insist - * that as a whole, it must be consistent and complete. - * - * The tracking of ->possible bits from even before we know the - * kty already makes certain we cannot have key element members - * defined that are inconsistent with the key type. - */ - - for (n = 0; n < LWS_ARRAY_SIZE(tok_map); n++) - /* - * All mandataory elements for the key type - * must be present - */ - if ((tok_map[n] & jps->possible) && ( - ((tok_map[n] & (F_M | F_META)) == (F_M | F_META) && - !jwk->meta[tok_map[n] & 0xff].buf) || - ((tok_map[n] & (F_M | F_META)) == F_M && - !jwk->e[tok_map[n] & 0xff].buf))) { - lwsl_notice("%s: missing %s\n", __func__, - jwk_tok[n]); - return -3; - } - - /* - * When the key may be public or public + private, ensure the - * intra-key members related to that are consistent. - * - * Only RSA keys need extra care, since EC keys are already - * confirmed by making CRV, X and Y mandatory and only D - * (the singular private part) optional. For RSA, N and E are - * also already known to be present using mandatory checking. - */ - - /* - * If a private key, it must have all D, P and Q. Public key - * must have none of them. - */ - if (jwk->kty == LWS_GENCRYPTO_KTY_RSA && - !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) && - (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) && - (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf)) || - (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf && - jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf && - jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf)) - ) { - lwsl_notice("%s: RSA requires D, P and Q for private\n", - __func__); - return -3; - } - - /* - * If the precomputed private key terms appear, they must all - * appear together. - */ - if (jwk->kty == LWS_GENCRYPTO_KTY_RSA && - !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf) && - (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) && - (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf)) || - (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf && - jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf && - jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf)) - ) { - lwsl_notice("%s: RSA DP, DQ, QI must all appear " - "or none\n", __func__); - return -3; - } - - /* - * The precomputed private key terms must not appear without - * the private key itself also appearing. - */ - if (jwk->kty == LWS_GENCRYPTO_KTY_RSA && - !jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf && - jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) { - lwsl_notice("%s: RSA DP, DQ, QI can appear only with " - "private key\n", __func__); - return -3; - } - - if ((jwk->kty == LWS_GENCRYPTO_KTY_RSA || - jwk->kty == LWS_GENCRYPTO_KTY_EC) && - jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) - jwk->private_key = 1; - } - - if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) - return 0; - - if (ctx->path_match == 0 + 1) - return 0; - - idx = tok_map[ctx->path_match - 1]; - if ((idx & 0xff) == 0xff) - return 0; - - switch (idx) { - /* note: kty is not necessarily first... we have to keep track of - * what could match given which element names have already been - * seen. Once kty comes, we confirm it'jwk still possible (ie, it'jwk - * not trying to tell us that it'jwk RSA now when we saw a "crv" - * earlier) and then reduce the possibilities to just the one that - * kty told. */ - case F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY: - - if (ctx->npos == 3 && !strncmp(ctx->buf, "oct", 3)) { - if (!(jps->possible & F_OCT)) - goto elements_mismatch; - jwk->kty = LWS_GENCRYPTO_KTY_OCT; - jps->possible = F_OCT; - goto cont; - } - if (ctx->npos == 3 && !strncmp(ctx->buf, "RSA", 3)) { - if (!(jps->possible & F_RSA)) - goto elements_mismatch; - jwk->kty = LWS_GENCRYPTO_KTY_RSA; - jps->possible = F_RSA; - goto cont; - } - if (ctx->npos == 2 && !strncmp(ctx->buf, "EC", 2)) { - if (!(jps->possible & F_EC)) - goto elements_mismatch; - jwk->kty = LWS_GENCRYPTO_KTY_EC; - jps->possible = F_EC; - goto cont; - } - lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); - lwsl_err("%s: Unknown KTY '%s'\n", __func__, dotstar); - return -1; - - default: -cont: - if (jps->pos + ctx->npos >= (int)sizeof(jps->b64)) - goto bail; - - memcpy(jps->b64 + jps->pos, ctx->buf, ctx->npos); - jps->pos += ctx->npos; - - if (reason == LEJPCB_VAL_STR_CHUNK) - return 0; - - /* chunking has been collated */ - - poss = idx & (F_RSA | F_EC | F_OCT); - jps->possible &= poss; - if (!jps->possible) - goto elements_mismatch; - - if (idx & F_META) { - if (_lws_jwk_set_el_jwk(&jwk->meta[idx & 0x7f], - jps->b64, (unsigned int)jps->pos) < 0) - goto bail; - - break; - } - - if (idx & F_B64U) { - /* key data... do the base64 decode as needed */ - if (_lws_jwk_set_el_jwk_b64u(&jwk->e[idx & 0x7f], - jps->b64, jps->pos) < 0) - goto bail; - - if (jwk->e[idx & 0x7f].len > - LWS_JWE_LIMIT_KEY_ELEMENT_BYTES) { - lwsl_notice("%s: oversize keydata\n", __func__); - goto bail; - } - - return 0; - } - - if (idx & F_B64) { - - /* cert data... do non-urlcoded base64 decode */ - if (_lws_jwk_set_el_jwk_b64(&jwk->e[idx & 0x7f], - jps->b64, jps->pos) < 0) - goto bail; - return 0; - } - - if (_lws_jwk_set_el_jwk(&jwk->e[idx & 0x7f], - jps->b64, (unsigned int)jps->pos) < 0) - goto bail; - break; - } - - return 0; - -elements_mismatch: - lwsl_err("%s: jwk elements mismatch\n", __func__); - -bail: - lwsl_err("%s: element failed\n", __func__); - - return -1; -} - void -lws_jwk_init_jps(struct lejp_ctx *jctx, struct lws_jwk_parse_state *jps, +lws_jwk_init_jps(struct lws_jwk_parse_state *jps, struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user) { if (jwk) memset(jwk, 0, sizeof(*jwk)); - jps->jwk = jwk; - jps->possible = F_RSA | F_EC | F_OCT; - jps->per_key_cb = cb; - jps->user = user; - jps->pos = 0; - - lejp_construct(jctx, cb_jwk, jps, cb ? jwk_outer_tok: jwk_tok, - LWS_ARRAY_SIZE(jwk_tok)); + jps->jwk = jwk; + jps->possible = F_RSA | F_EC | F_OCT; + jps->per_key_cb = cb; + jps->user = user; + jps->pos = 0; + jps->seen = 0; + jps->cose_state = 0; } int @@ -600,6 +204,8 @@ lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk, case LWS_GENCRYPTO_KTY_OCT: sn = (unsigned int)lws_gencrypto_bits_to_bytes(bits); jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf = lws_malloc(sn, "oct"); + if (!jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf) + return 1; 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) { @@ -641,183 +247,6 @@ lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk, return 0; } -int -lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user, - const char *in, size_t len) -{ - struct lejp_ctx jctx; - struct lws_jwk_parse_state jps; - int m; - - lws_jwk_init_jps(&jctx, &jps, jwk, cb, user); - - m = lejp_parse(&jctx, (uint8_t *)in, (int)len); - lejp_destruct(&jctx); - - if (m < 0) { - lwsl_notice("%s: parse got %d\n", __func__, m); - lws_jwk_destroy(jwk); - return -1; - } - - switch (jwk->kty) { - case LWS_GENCRYPTO_KTY_UNKNOWN: - lwsl_notice("%s: missing or unknown kyt\n", __func__); - lws_jwk_destroy(jwk); - return -1; - default: - break; - } - - return 0; -} - - -int -lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) -{ - char *start = p, *end = &p[*len - 1]; - int n, m, limit, first = 1, asym = 0; - struct lexico *l; - - /* RFC7638 lexicographic order requires - * RSA: e -> kty -> n - * oct: k -> kty - * - * ie, meta and key data elements appear interleaved in name alpha order - */ - - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{"); - - switch (jwk->kty) { - case LWS_GENCRYPTO_KTY_OCT: - l = lexico_oct; - limit = LWS_ARRAY_SIZE(lexico_oct); - break; - case LWS_GENCRYPTO_KTY_RSA: - l = lexico_rsa; - limit = LWS_ARRAY_SIZE(lexico_rsa); - asym = 1; - break; - case LWS_GENCRYPTO_KTY_EC: - l = lexico_ec; - limit = LWS_ARRAY_SIZE(lexico_ec); - asym = 1; - break; - default: - return -1; - } - - for (n = 0; n < limit; n++) { - const char *q, *q_end; - char tok[12]; - int pos = 0, f = 1; - - if ((l->meta & 1) && (jwk->meta[l->idx].buf || - l->idx == (int)JWK_META_KTY)) { - - switch (l->idx) { - case JWK_META_KTY: - if (!first) - *p++ = ','; - first = 0; - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"%s\"", - l->name, kty_names[jwk->kty]); - break; - case JWK_META_KEY_OPS: - if (!first) - *p++ = ','; - first = 0; - q = (const char *)jwk->meta[l->idx].buf; - q_end = q + jwk->meta[l->idx].len; - - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), - "\"%s\":[", l->name); - /* - * For the public version, usages that - * require the private part must be - * snipped - */ - - while (q < q_end) { - if (*q != ' ' && pos < (int)sizeof(tok) - 1) { - tok[pos++] = *q++; - if (q != q_end) - continue; - } - tok[pos] = '\0'; - pos = 0; - if ((flags & LWSJWKF_EXPORT_PRIVATE) || - !asym || (strcmp(tok, "sign") && - strcmp(tok, "encrypt"))) { - if (!f) - *p++ = ','; - f = 0; - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), - "\"%s\"", tok); - } - q++; - } - - *p++ = ']'; - - break; - - default: - /* both sig and enc require asym private key */ - if (!(flags & LWSJWKF_EXPORT_PRIVATE) && - asym && l->idx == (int)JWK_META_USE) - break; - if (!first) - *p++ = ','; - first = 0; - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"", - l->name); - lws_strnncpy(p, (const char *)jwk->meta[l->idx].buf, - jwk->meta[l->idx].len, end - p); - p += strlen(p); - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\""); - break; - } - } - - if ((!(l->meta & 1)) && jwk->e[l->idx].buf && - ((flags & LWSJWKF_EXPORT_PRIVATE) || !(l->meta & 2))) { - if (!first) - *p++ = ','; - first = 0; - - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"", l->name); - - if (jwk->kty == LWS_GENCRYPTO_KTY_EC && - l->idx == (int)LWS_GENCRYPTO_EC_KEYEL_CRV) { - lws_strnncpy(p, - (const char *)jwk->e[l->idx].buf, - jwk->e[l->idx].len, end - p); - m = (int)strlen(p); - } else - m = lws_jws_base64_enc( - (const char *)jwk->e[l->idx].buf, - jwk->e[l->idx].len, p, lws_ptr_diff_size_t(end, p) - 4); - if (m < 0) { - lwsl_notice("%s: enc failed\n", __func__); - return -1; - } - p += m; - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\""); - } - - l++; - } - - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), - (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n"); - - *len -= lws_ptr_diff(p, start); - - return lws_ptr_diff(p, start); -} - int lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32) { @@ -866,55 +295,3 @@ lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx, return 0; } -int -lws_jwk_load(struct lws_jwk *jwk, const char *filename, - lws_jwk_key_import_callback cb, void *user) -{ - unsigned int buflen = 4096; - char *buf = lws_malloc(buflen, "jwk-load"); - int n; - - if (!buf) - return -1; - - n = lws_plat_read_file(filename, buf, buflen); - if (n < 0) - goto bail; - - n = lws_jwk_import(jwk, cb, user, buf, (unsigned int)n); - lws_free(buf); - - return n; -bail: - lws_free(buf); - - return -1; -} - -int -lws_jwk_save(struct lws_jwk *jwk, const char *filename) -{ - int buflen = 4096; - char *buf = lws_malloc((unsigned int)buflen, "jwk-save"); - int n, m; - - if (!buf) - return -1; - - n = lws_jwk_export(jwk, LWSJWKF_EXPORT_PRIVATE, buf, &buflen); - if (n < 0) - goto bail; - - m = lws_plat_write_file(filename, buf, (size_t)n); - - lws_free(buf); - if (m) - return -1; - - return 0; - -bail: - lws_free(buf); - - return -1; -} diff --git a/3rdparty/libwebsockets/lib/jose/jws/jose.c b/3rdparty/libwebsockets/lib/jose/jws/jose.c index c9fdf588..4007865b 100644 --- a/3rdparty/libwebsockets/lib/jose/jws/jose.c +++ b/3rdparty/libwebsockets/lib/jose/jws/jose.c @@ -404,7 +404,6 @@ lws_jose_destroy(struct lws_jose *jose) lws_jose_recip_destroy(&jose->recipient[n]); } - static int lws_jose_parse(struct lws_jose *jose, const uint8_t *buf, int n, char *temp, int *temp_len, int is_jwe) @@ -413,11 +412,14 @@ lws_jose_parse(struct lws_jose *jose, const uint8_t *buf, int n, struct jose_cb_args args; int m; - if (is_jwe) + if (is_jwe) { /* prepare a context for JOSE epk ephemeral jwk parsing */ - lws_jwk_init_jps(&args.jwk_jctx, &args.jps, + lws_jwk_init_jps(&args.jps, &jose->recipient[jose->recipients].jwk_ephemeral, NULL, NULL); + lejp_construct(&args.jwk_jctx, cb_jwk, &args.jps, + jwk_tok, LWS_ARRAY_SIZE(jwk_tok)); + } args.is_jwe = (unsigned int)is_jwe; args.temp = temp; diff --git a/3rdparty/libwebsockets/lib/jose/private-lib-jose.h b/3rdparty/libwebsockets/lib/jose/private-lib-jose.h index d5ed26df..c6508d3b 100644 --- a/3rdparty/libwebsockets/lib/jose/private-lib-jose.h +++ b/3rdparty/libwebsockets/lib/jose/private-lib-jose.h @@ -22,14 +22,32 @@ * IN THE SOFTWARE. */ +/* information about each token declared above */ + +#define F_M (1 << 9) /* Mandatory for key type */ +#define F_B64 (1 << 10) /* Base64 coded octets */ +#define F_B64U (1 << 11) /* Base64 Url coded octets */ +#define F_META (1 << 12) /* JWK key metainformation */ +#define F_RSA (1 << 13) /* RSA key */ +#define F_EC (1 << 14) /* Elliptic curve key */ +#define F_OCT (1 << 15) /* octet key */ + void lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m); +int +lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, + char *out, size_t out_len); + +int +_lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem *e, char *in, size_t len); + void -lws_jwk_init_jps(struct lejp_ctx *jctx, struct lws_jwk_parse_state *jps, +lws_jwk_init_jps(struct lws_jwk_parse_state *jps, struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user); -int -lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, - char *out, size_t out_len); +signed char +cb_jwk(struct lejp_ctx *ctx, char reason); + +extern const char * const jwk_tok[19], * const jwk_outer_tok[19]; diff --git a/3rdparty/libwebsockets/lib/misc/CMakeLists.txt b/3rdparty/libwebsockets/lib/misc/CMakeLists.txt index cd040aa5..337367aa 100644 --- a/3rdparty/libwebsockets/lib/misc/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/misc/CMakeLists.txt @@ -36,12 +36,27 @@ list(APPEND SOURCES misc/prng.c misc/lws-ring.c) +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + misc/cache-ttl/lws-cache-ttl.c + misc/cache-ttl/heap.c + ) + + if (LWS_WITH_CACHE_NSCOOKIEJAR) + list(APPEND SOURCES + misc/cache-ttl/file.c) + endif() + +endif() + if (LWS_WITH_FTS) list(APPEND SOURCES misc/fts/trie.c misc/fts/trie-fd.c) endif() +# this is an older, standalone hashed disk cache +# implementation unrelated to lws-cache-ttl if (LWS_WITH_DISKCACHE) list(APPEND SOURCES misc/diskcache.c) @@ -95,6 +110,12 @@ if (LWS_WITH_LEJP) list(APPEND SOURCES misc/lejp.c) endif() +if (LWS_WITH_CBOR) + list(APPEND SOURCES + misc/lecp.c + misc/ieeehalfprecision.c) +endif() + if (UNIX) if (NOT LWS_HAVE_GETIFADDRS) diff --git a/3rdparty/libwebsockets/lib/misc/base64-decode.c b/3rdparty/libwebsockets/lib/misc/base64-decode.c index f8e8e49a..9d18b33f 100644 --- a/3rdparty/libwebsockets/lib/misc/base64-decode.c +++ b/3rdparty/libwebsockets/lib/misc/base64-decode.c @@ -72,9 +72,9 @@ _lws_b64_encode_string(const char *encode, const char *in, int in_len, *out++ = encode[triple[0] >> 2]; *out++ = encode[(((triple[0] & 0x03) << 4) & 0x30) | (((triple[1] & 0xf0) >> 4) & 0x0f)]; - *out++ = (len > 1 ? encode[(((triple[1] & 0x0f) << 2) & 0x3c) | + *out++ = (char)(len > 1 ? encode[(((triple[1] & 0x0f) << 2) & 0x3c) | (((triple[2] & 0xc0) >> 6) & 3)] : '='); - *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '='); + *out++ = (char)(len > 2 ? encode[triple[2] & 0x3f] : '='); done += 4; } diff --git a/3rdparty/libwebsockets/lib/misc/cache-ttl/file.c b/3rdparty/libwebsockets/lib/misc/cache-ttl/file.c new file mode 100644 index 00000000..3307faf8 --- /dev/null +++ b/3rdparty/libwebsockets/lib/misc/cache-ttl/file.c @@ -0,0 +1,960 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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. + * + * Implements a cache backing store compatible with netscape cookies.txt format + * There is one entry per "line", and fields are tab-delimited + * + * We need to know the format here, because while the unique cookie tag consists + * of "hostname|urlpath|cookiename", that does not appear like that in the file; + * we have to go parse the fields and synthesize the corresponding tag. + * + * We rely on all the fields except the cookie value fitting in a 256 byte + * buffer, and allow eating multiple buffers to get a huge cookie values. + * + * Because the cookie file is a device-wide asset, although lws will change it + * from the lws thread without conflict, there may be other processes that will + * change it by removal and regenerating the file asynchronously. For that + * reason, file handles are opened fresh each time we want to use the file, so + * we always get the latest version. + * + * When updating the file ourselves, we use a lockfile to ensure our process + * has exclusive access. + * + * + * Tag Matching rules + * + * There are three kinds of tag matching rules + * + * 1) specific - tag strigs must be the same + * 2) wilcard - tags matched using optional wildcards + * 3) wildcard + lookup - wildcard, but path part matches using cookie scope rules + * + */ + +#include +#include "private-lib-misc-cache-ttl.h" + +typedef enum nsc_iterator_ret { + NIR_CONTINUE = 0, + NIR_FINISH_OK = 1, + NIR_FINISH_ERROR = -1 +} nsc_iterator_ret_t; + +typedef enum cbreason { + LCN_SOL = (1 << 0), + LCN_EOL = (1 << 1) +} cbreason_t; + +typedef int (*nsc_cb_t)(lws_cache_nscookiejar_t *cache, void *opaque, int flags, + const char *buf, size_t size); + +static void +expiry_cb(lws_sorted_usec_list_t *sul); + +static int +nsc_backing_open_lock(lws_cache_nscookiejar_t *cache, int mode, const char *par) +{ + int sanity = 50; + char lock[128]; + int fd_lock, fd; + + lwsl_debug("%s: %s\n", __func__, par); + + lws_snprintf(lock, sizeof(lock), "%s.LCK", + cache->cache.info.u.nscookiejar.filepath); + + do { + fd_lock = open(lock, LWS_O_CREAT | O_EXCL, 0600); + if (fd_lock >= 0) { + close(fd_lock); + break; + } + + if (!sanity--) { + lwsl_warn("%s: unable to lock %s: errno %d\n", __func__, + lock, errno); + return -1; + } + +#if defined(WIN32) + Sleep(100); +#else + usleep(100000); +#endif + } while (1); + + fd = open(cache->cache.info.u.nscookiejar.filepath, + LWS_O_CREAT | mode, 0600); + + if (fd == -1) { + lwsl_warn("%s: unable to open or create %s\n", __func__, + cache->cache.info.u.nscookiejar.filepath); + unlink(lock); + } + + return fd; +} + +static void +nsc_backing_close_unlock(lws_cache_nscookiejar_t *cache, int fd) +{ + char lock[128]; + + lwsl_debug("%s\n", __func__); + + lws_snprintf(lock, sizeof(lock), "%s.LCK", + cache->cache.info.u.nscookiejar.filepath); + if (fd >= 0) + close(fd); + unlink(lock); +} + +/* + * We're going to call the callback with chunks of the file with flags + * indicating we're giving it the start of a line and / or giving it the end + * of a line. + * + * It's like this because the cookie value may be huge (and to a lesser extent + * the path may also be big). + * + * If it's the start of a line (flags on the cb has LCN_SOL), then the buffer + * contains up to the first 256 chars of the line, it's enough to match with. + * + * We cannot hold the file open inbetweentimes, since other processes may + * regenerate it, so we need to bind to a new inode. We open it with an + * exclusive flock() so other processes can't replace conflicting changes + * while we also write changes, without having to wait and see our changes. + */ + +static int +nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd, + nsc_cb_t cb, void *opaque) +{ + int m = 0, n = 0, e, r = LCN_SOL, ignore = 0, ret = 0; + char temp[256], eof = 0; + + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) + return -1; + + do { /* for as many buffers in the file */ + + int n1; + + lwsl_debug("%s: n %d, m %d\n", __func__, n, m); + +read: + n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n); + + lwsl_debug("%s: n1 %d\n", __func__, n1); + + if (n1 <= 0) { + eof = 1; + if (m == n) + continue; + } else + n += n1; + + while (m < n) { + + m++; + + if (temp[m - 1] != '\n') + continue; + + /* ie, we hit EOL */ + + if (temp[0] == '#') + /* lines starting with # are comments */ + e = 0; + else + e = cb(cache, opaque, r | LCN_EOL, temp, + (size_t)m - 1); + r = LCN_SOL; + ignore = 0; + /* + * Move back remainder and prefill the gap that opened + * up: we want to pass enough in the start chunk so the + * cb can classify it even if it can't get all the + * value part in one go + */ + memmove(temp, temp + m, (size_t)(n - m)); + n -= m; + m = 0; + + if (e) { + ret = e; + goto bail; + } + + goto read; + } + + if (m) { + /* we ran out of buffer */ + if (ignore || (r == LCN_SOL && n && temp[0] == '#')) { + e = 0; + ignore = 1; + } else { + e = cb(cache, opaque, + r | (n == m && eof ? LCN_EOL : 0), + temp, (size_t)m); + + m = 0; + n = 0; + } + + if (e) { + /* + * We have to call off the whole thing if any + * step, eg, OOMs + */ + ret = e; + goto bail; + } + r = 0; + } + + } while (!eof || n != m); + + ret = 0; + +bail: + + return ret; +} + +/* + * lookup() just handles wildcard resolution, it doesn't deal with moving the + * hits to L1. That has to be done individually by non-wildcard names. + */ + +enum { + NSC_COL_HOST = 0, /* wc idx 0 */ + NSC_COL_PATH = 2, /* wc idx 1 */ + NSC_COL_EXPIRY = 4, + NSC_COL_NAME = 5, /* wc idx 2 */ + + NSC_COL_COUNT = 6 +}; + +/* + * This performs the specialized wildcard that knows about cookie path match + * rules. + * + * To defeat the lookup path matching, lie to it about idx being NSC_COL_PATH + */ + +static int +nsc_match(const char *wc, size_t wc_len, const char *col, size_t col_len, + int idx) +{ + size_t n = 0; + + if (idx != NSC_COL_PATH) + return lws_strcmp_wildcard(wc, wc_len, col, col_len); + + /* + * Cookie path match is special, if we lookup on a path like /my/path, + * we must match on cookie paths for every dir level including /, so + * match on /, /my, and /my/path. But we must not match on /m or + * /my/pa etc. If we lookup on /, we must not match /my/path + * + * Let's go through wc checking at / and for every complete subpath if + * it is an explicit match + */ + + if (!strcmp(col, wc)) + return 0; /* exact hit */ + + while (n <= wc_len) { + if (n == wc_len || wc[n] == '/') { + if (n && col_len <= n && !strncmp(wc, col, n)) + return 0; /* hit */ + + if (n != wc_len && col_len <= n + 1 && + !strncmp(wc, col, n + 1)) /* check for trailing / */ + return 0; /* hit */ + } + n++; + } + + return 1; /* fail */ +} + +static const uint8_t nsc_cols[] = { NSC_COL_HOST, NSC_COL_PATH, NSC_COL_NAME }; + +static int +lws_cache_nscookiejar_tag_match(struct lws_cache_ttl_lru *cache, + const char *wc, const char *tag, char lookup) +{ + const char *wc_end = wc + strlen(wc), *tag_end = tag + strlen(tag), + *start_wc, *start_tag; + int n = 0; + + lwsl_cache("%s: '%s' vs '%s'\n", __func__, wc, tag); + + /* + * Given a well-formed host|path|name tag and a wildcard term, + * make the determination if the tag matches the wildcard or not, + * using lookup rules that apply at this cache level. + */ + + while (n < 3) { + start_wc = wc; + while (wc < wc_end && *wc != LWSCTAG_SEP) + wc++; + + start_tag = tag; + while (tag < tag_end && *tag != LWSCTAG_SEP) + tag++; + + lwsl_cache("%s: '%.*s' vs '%.*s'\n", __func__, + lws_ptr_diff(wc, start_wc), start_wc, + lws_ptr_diff(tag, start_tag), start_tag); + if (nsc_match(start_wc, lws_ptr_diff_size_t(wc, start_wc), + start_tag, lws_ptr_diff_size_t(tag, start_tag), + lookup ? nsc_cols[n] : NSC_COL_HOST)) { + lwsl_cache("%s: fail\n", __func__); + return 1; + } + + if (wc < wc_end) + wc++; + if (tag < tag_end) + tag++; + + n++; + } + + lwsl_cache("%s: hit\n", __func__); + + return 0; /* match */ +} + +/* + * Converts the start of a cookie file line into a tag + */ + +static int +nsc_line_to_tag(const char *buf, size_t size, char *tag, size_t max_tag, + lws_usec_t *pexpiry) +{ + int n, idx = 0, tl = 0; + lws_usec_t expiry = 0; + size_t bn = 0; + char col[64]; + + if (size < 3) + return 1; + + while (bn < size && idx <= NSC_COL_NAME) { + + n = 0; + while (bn < size && n < (int)sizeof(col) - 1 && + buf[bn] != '\t') + col[n++] = buf[bn++]; + col[n] = '\0'; + if (buf[bn] == '\t') + bn++; + + switch (idx) { + case NSC_COL_EXPIRY: + expiry = (lws_usec_t)((unsigned long long)atoll(col) * + (lws_usec_t)LWS_US_PER_SEC); + break; + + case NSC_COL_HOST: + case NSC_COL_PATH: + case NSC_COL_NAME: + + /* + * As we match the pieces of the wildcard, + * compose the matches into a specific tag + */ + + if (tl + n + 2 > (int)max_tag) + return 1; + if (tl) + tag[tl++] = LWSCTAG_SEP; + memcpy(tag + tl, col, (size_t)n); + tl += n; + tag[tl] = '\0'; + break; + default: + break; + } + + idx++; + } + + if (pexpiry) + *pexpiry = expiry; + + lwsl_info("%s: %.*s: tag '%s'\n", __func__, (int)size, buf, tag); + + return 0; +} + +struct nsc_lookup_ctx { + const char *wildcard_key; + lws_dll2_owner_t *results_owner; + lws_cache_match_t *match; /* current match if any */ + size_t wklen; +}; + + +static int +nsc_lookup_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags, + const char *buf, size_t size) +{ + struct nsc_lookup_ctx *ctx = (struct nsc_lookup_ctx *)opaque; + lws_usec_t expiry; + char tag[200]; + int tl; + + if (!(flags & LCN_SOL)) { + if (ctx->match) + ctx->match->payload_size += size; + + return NIR_CONTINUE; + } + + /* + * There should be enough in buf to match or reject it... let's + * synthesize a tag from the text "line" and then check the tags for + * a match + */ + + ctx->match = NULL; /* new SOL means stop tracking payload len */ + + if (nsc_line_to_tag(buf, size, tag, sizeof(tag), &expiry)) + return NIR_CONTINUE; + + if (lws_cache_nscookiejar_tag_match(&cache->cache, + ctx->wildcard_key, tag, 1)) + return NIR_CONTINUE; + + tl = (int)strlen(tag); + + /* + * ... it looks like a match then... create new match + * object with the specific tag, and add it to the owner list + */ + + ctx->match = lws_fi(&cache->cache.info.cx->fic, "cache_lookup_oom") ? NULL : + lws_malloc(sizeof(*ctx->match) + (unsigned int)tl + 1u, + __func__); + if (!ctx->match) + /* caller of lookup will clean results list on fail */ + return NIR_FINISH_ERROR; + + ctx->match->payload_size = size; + ctx->match->tag_size = (size_t)tl; + ctx->match->expiry = expiry; + + memset(&ctx->match->list, 0, sizeof(ctx->match->list)); + memcpy(&ctx->match[1], tag, (size_t)tl + 1u); + lws_dll2_add_tail(&ctx->match->list, ctx->results_owner); + + return NIR_CONTINUE; +} + +static int +lws_cache_nscookiejar_lookup(struct lws_cache_ttl_lru *_c, + const char *wildcard_key, + lws_dll2_owner_t *results_owner) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c; + struct nsc_lookup_ctx ctx; + int ret, fd; + + fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__); + if (fd < 0) + return 1; + + ctx.wildcard_key = wildcard_key; + ctx.results_owner = results_owner; + ctx.wklen = strlen(wildcard_key); + ctx.match = 0; + + ret = nscookiejar_iterate(cache, fd, nsc_lookup_cb, &ctx); + /* + * The cb can fail, eg, with OOM, making the whole lookup + * invalid and returning fail. Caller will clean + * results_owner on fail. + */ + nsc_backing_close_unlock(cache, fd); + + return ret == NIR_FINISH_ERROR; +} + +/* + * It's pretty horrible having to implement add or remove individual items by + * file regeneration, but if we don't want to keep it all in heap, and we want + * this cookie jar format, that is what we are into. + * + * Allow to optionally add a "line", optionally wildcard delete tags, and always + * delete expired entries. + * + * Although we can rely on the lws thread to be doing this, multiple processes + * may be using the cookie jar and can tread on each other. So we use flock() + * (linux only) to get exclusive access while we are processing this. + * + * We leave the existing file alone and generate a new one alongside it, with a + * fixed name.tmp format so it can't leak, if that went OK then we unlink the + * old and rename the new. + */ + +struct nsc_regen_ctx { + const char *wildcard_key_delete; + const void *add_data; + lws_usec_t curr; + size_t add_size; + int fdt; + char drop; +}; + +/* only used by nsc_regen() */ + +static int +nsc_regen_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags, + const char *buf, size_t size) +{ + struct nsc_regen_ctx *ctx = (struct nsc_regen_ctx *)opaque; + char tag[256]; + lws_usec_t expiry; + + if (flags & LCN_SOL) { + + ctx->drop = 0; + + if (nsc_line_to_tag(buf, size, tag, sizeof(tag), &expiry)) + /* filter it out if it is unparseable */ + goto drop; + + /* routinely track the earliest expiry */ + + if (!cache->earliest_expiry || + (expiry && cache->earliest_expiry > expiry)) + cache->earliest_expiry = expiry; + + if (expiry && expiry < ctx->curr) + /* routinely strip anything beyond its expiry */ + goto drop; + + if (ctx->wildcard_key_delete) + lwsl_cache("%s: %s vs %s\n", __func__, + tag, ctx->wildcard_key_delete); + if (ctx->wildcard_key_delete && + !lws_cache_nscookiejar_tag_match(&cache->cache, + ctx->wildcard_key_delete, + tag, 0)) { + lwsl_cache("%s: %s matches wc delete %s\n", __func__, + tag, ctx->wildcard_key_delete); + goto drop; + } + } + + if (ctx->drop) + return 0; + + cache->cache.current_footprint += (uint64_t)size; + + if (write(ctx->fdt, buf, /*msvc*/(unsigned int)size) != (ssize_t)size) + return NIR_FINISH_ERROR; + + if (flags & LCN_EOL) + if ((size_t)write(ctx->fdt, "\n", 1) != 1) + return NIR_FINISH_ERROR; + + return 0; + +drop: + ctx->drop = 1; + + return NIR_CONTINUE; +} + +static int +nsc_regen(lws_cache_nscookiejar_t *cache, const char *wc_delete, + const void *pay, size_t pay_size) +{ + struct nsc_regen_ctx ctx; + char filepath[128]; + int fd, ret = 1; + + fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__); + if (fd < 0) + return 1; + + lws_snprintf(filepath, sizeof(filepath), "%s.tmp", + cache->cache.info.u.nscookiejar.filepath); + unlink(filepath); + + if (lws_fi(&cache->cache.info.cx->fic, "cache_regen_temp_open")) + goto bail; + + ctx.fdt = open(filepath, LWS_O_CREAT | LWS_O_WRONLY, 0600); + if (ctx.fdt < 0) + goto bail; + + /* magic header */ + + if (lws_fi(&cache->cache.info.cx->fic, "cache_regen_temp_write") || + /* other consumers insist to see this at start of cookie jar */ + write(ctx.fdt, "# Netscape HTTP Cookie File\n", 28) != 28) + goto bail1; + + /* if we are adding something, put it first */ + + if (pay && + write(ctx.fdt, pay, /*msvc*/(unsigned int)pay_size) != + (ssize_t)pay_size) + goto bail1; + if (pay && write(ctx.fdt, "\n", 1u) != (ssize_t)1) + goto bail1; + + cache->cache.current_footprint = 0; + + ctx.wildcard_key_delete = wc_delete; + ctx.add_data = pay; + ctx.add_size = pay_size; + ctx.curr = lws_now_usecs(); + ctx.drop = 0; + + cache->earliest_expiry = 0; + + if (lws_fi(&cache->cache.info.cx->fic, "cache_regen_iter_fail") || + nscookiejar_iterate(cache, fd, nsc_regen_cb, &ctx)) + goto bail1; + + close(ctx.fdt); + ctx.fdt = -1; + + if (unlink(cache->cache.info.u.nscookiejar.filepath) == -1) + lwsl_info("%s: unlink %s failed\n", __func__, + cache->cache.info.u.nscookiejar.filepath); + if (rename(filepath, cache->cache.info.u.nscookiejar.filepath) == -1) + lwsl_info("%s: rename %s failed\n", __func__, + cache->cache.info.u.nscookiejar.filepath); + + if (cache->earliest_expiry) + lws_cache_schedule(&cache->cache, expiry_cb, + cache->earliest_expiry); + + ret = 0; + goto bail; + +bail1: + if (ctx.fdt >= 0) + close(ctx.fdt); +bail: + unlink(filepath); + + nsc_backing_close_unlock(cache, fd); + + return ret; +} + +static void +expiry_cb(lws_sorted_usec_list_t *sul) +{ + lws_cache_nscookiejar_t *cache = lws_container_of(sul, + lws_cache_nscookiejar_t, cache.sul); + + /* + * regen the cookie jar without changes, so expired are removed and + * new earliest expired computed + */ + if (nsc_regen(cache, NULL, NULL, 0)) + return; + + if (cache->earliest_expiry) + lws_cache_schedule(&cache->cache, expiry_cb, + cache->earliest_expiry); +} + + +/* specific_key and expiry are ignored, since it must be encoded in payload */ + +static int +lws_cache_nscookiejar_write(struct lws_cache_ttl_lru *_c, + const char *specific_key, const uint8_t *source, + size_t size, lws_usec_t expiry, void **ppvoid) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c; + char tag[128]; + + lwsl_cache("%s: %s: len %d\n", __func__, _c->info.name, (int)size); + + assert(source); + + if (nsc_line_to_tag((const char *)source, size, tag, sizeof(tag), NULL)) + return 1; + + if (ppvoid) + *ppvoid = NULL; + + if (nsc_regen(cache, tag, source, size)) { + lwsl_err("%s: regen failed\n", __func__); + + return 1; + } + + return 0; +} + +struct nsc_get_ctx { + struct lws_buflist *buflist; + const char *specific_key; + const void **pdata; + size_t *psize; + lws_cache_ttl_lru_t *l1; + lws_usec_t expiry; +}; + +/* + * We're looking for a specific key, if found, we want to make an entry for it + * in L1 and return information about that + */ + +static int +nsc_get_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags, + const char *buf, size_t size) +{ + struct nsc_get_ctx *ctx = (struct nsc_get_ctx *)opaque; + char tag[200]; + uint8_t *q; + + if (ctx->buflist) + goto collect; + + if (!(flags & LCN_SOL)) + return NIR_CONTINUE; + + if (nsc_line_to_tag(buf, size, tag, sizeof(tag), &ctx->expiry)) { + lwsl_err("%s: can't get tag\n", __func__); + return NIR_CONTINUE; + } + + lwsl_cache("%s: %s %s\n", __func__, ctx->specific_key, tag); + + if (strcmp(ctx->specific_key, tag)) { + lwsl_cache("%s: no match\n", __func__); + return NIR_CONTINUE; + } + + /* it's a match */ + + lwsl_cache("%s: IS match\n", __func__); + + if (!(flags & LCN_EOL)) + goto collect; + + /* it all fit in the buffer, let's create it in L1 now */ + + *ctx->psize = size; + if (ctx->l1->info.ops->write(ctx->l1, + ctx->specific_key, (const uint8_t *)buf, + size, ctx->expiry, (void **)ctx->pdata)) + return NIR_FINISH_ERROR; + + return NIR_FINISH_OK; + +collect: + /* + * it's bigger than one buffer-load, we have to stash what we're getting + * on a buflist and create it when we have it all + */ + + if (lws_buflist_append_segment(&ctx->buflist, (const uint8_t *)buf, + size)) + goto cleanup; + + if (!(flags & LCN_EOL)) + return NIR_CONTINUE; + + /* we have all the payload, create the L1 entry without payload yet */ + + *ctx->psize = size; + if (ctx->l1->info.ops->write(ctx->l1, ctx->specific_key, NULL, + lws_buflist_total_len(&ctx->buflist), + ctx->expiry, (void **)&q)) + goto cleanup; + *ctx->pdata = q; + + /* dump the buflist into the L1 cache entry */ + + do { + uint8_t *p; + size_t len = lws_buflist_next_segment_len(&ctx->buflist, &p); + + memcpy(q, p, len); + q += len; + + lws_buflist_use_segment(&ctx->buflist, len); + } while (ctx->buflist); + + return NIR_FINISH_OK; + +cleanup: + lws_buflist_destroy_all_segments(&ctx->buflist); + + return NIR_FINISH_ERROR; +} + +static int +lws_cache_nscookiejar_get(struct lws_cache_ttl_lru *_c, + const char *specific_key, const void **pdata, + size_t *psize) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c; + struct nsc_get_ctx ctx; + int ret, fd; + + fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__); + if (fd < 0) + return 1; + + /* get a pointer to l1 */ + ctx.l1 = &cache->cache; + while (ctx.l1->child) + ctx.l1 = ctx.l1->child; + + ctx.pdata = pdata; + ctx.psize = psize; + ctx.specific_key = specific_key; + ctx.buflist = NULL; + ctx.expiry = 0; + + ret = nscookiejar_iterate(cache, fd, nsc_get_cb, &ctx); + + nsc_backing_close_unlock(cache, fd); + + return ret != NIR_FINISH_OK; +} + +static int +lws_cache_nscookiejar_invalidate(struct lws_cache_ttl_lru *_c, + const char *wc_key) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c; + + return nsc_regen(cache, wc_key, NULL, 0); +} + +static struct lws_cache_ttl_lru * +lws_cache_nscookiejar_create(const struct lws_cache_creation_info *info) +{ + lws_cache_nscookiejar_t *cache; + + cache = lws_fi(&info->cx->fic, "cache_createfail") ? NULL : + lws_zalloc(sizeof(*cache), __func__); + if (!cache) + return NULL; + + cache->cache.info = *info; + + /* + * We need to scan the file, if it exists, and find the earliest + * expiry while cleaning out any expired entries + */ + expiry_cb(&cache->cache.sul); + + lwsl_notice("%s: create %s\n", __func__, info->name ? info->name : "?"); + + return (struct lws_cache_ttl_lru *)cache; +} + +static int +lws_cache_nscookiejar_expunge(struct lws_cache_ttl_lru *_c) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c; + int r; + + if (!cache) + return 0; + + r = unlink(cache->cache.info.u.nscookiejar.filepath); + if (r) + lwsl_warn("%s: failed to unlink %s\n", __func__, + cache->cache.info.u.nscookiejar.filepath); + + return r; +} + +static void +lws_cache_nscookiejar_destroy(struct lws_cache_ttl_lru **_pc) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)*_pc; + + if (!cache) + return; + + lws_sul_cancel(&cache->cache.sul); + + lws_free_set_NULL(*_pc); +} + +#if defined(_DEBUG) + +static int +nsc_dump_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags, + const char *buf, size_t size) +{ + lwsl_hexdump_cache(buf, size); + + return 0; +} + +static void +lws_cache_nscookiejar_debug_dump(struct lws_cache_ttl_lru *_c) +{ + lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c; + int fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__); + + if (fd < 0) + return; + + lwsl_cache("%s: %s\n", __func__, _c->info.name); + + nscookiejar_iterate(cache, fd, nsc_dump_cb, NULL); + + nsc_backing_close_unlock(cache, fd); +} +#endif + +const struct lws_cache_ops lws_cache_ops_nscookiejar = { + .create = lws_cache_nscookiejar_create, + .destroy = lws_cache_nscookiejar_destroy, + .expunge = lws_cache_nscookiejar_expunge, + + .write = lws_cache_nscookiejar_write, + .tag_match = lws_cache_nscookiejar_tag_match, + .lookup = lws_cache_nscookiejar_lookup, + .invalidate = lws_cache_nscookiejar_invalidate, + .get = lws_cache_nscookiejar_get, +#if defined(_DEBUG) + .debug_dump = lws_cache_nscookiejar_debug_dump, +#endif +}; diff --git a/3rdparty/libwebsockets/lib/misc/cache-ttl/heap.c b/3rdparty/libwebsockets/lib/misc/cache-ttl/heap.c new file mode 100644 index 00000000..4fc16923 --- /dev/null +++ b/3rdparty/libwebsockets/lib/misc/cache-ttl/heap.c @@ -0,0 +1,608 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 "private-lib-misc-cache-ttl.h" + +#if defined(write) +#undef write +#endif + +static void +update_sul(lws_cache_ttl_lru_t_heap_t *cache); + +static int +lws_cache_heap_invalidate(struct lws_cache_ttl_lru *_c, const char *key); + +static int +sort_expiry(const lws_dll2_t *a, const lws_dll2_t *b) +{ + const lws_cache_ttl_item_heap_t + *c = lws_container_of(a, lws_cache_ttl_item_heap_t, list_expiry), + *d = lws_container_of(b, lws_cache_ttl_item_heap_t, list_expiry); + + if (c->expiry > d->expiry) + return 1; + if (c->expiry < d->expiry) + return -1; + + return 0; +} + +static void +_lws_cache_heap_item_destroy(lws_cache_ttl_lru_t_heap_t *cache, + lws_cache_ttl_item_heap_t *item) +{ + lwsl_cache("%s: %s (%s)\n", __func__, cache->cache.info.name, + (const char *)&item[1] + item->size); + + lws_dll2_remove(&item->list_expiry); + lws_dll2_remove(&item->list_lru); + + cache->cache.current_footprint -= item->size; + + update_sul(cache); + + if (cache->cache.info.cb) + cache->cache.info.cb((void *)((uint8_t *)&item[1]), item->size); + + lws_free(item); +} + +static void +lws_cache_heap_item_destroy(lws_cache_ttl_lru_t_heap_t *cache, + lws_cache_ttl_item_heap_t *item, int parent_too) +{ + struct lws_cache_ttl_lru *backing = &cache->cache; + const char *tag = ((const char *)&item[1]) + item->size; + + /* + * We're destroying a normal item? + */ + + if (*tag == META_ITEM_LEADING) + /* no, nothing to check here then */ + goto post; + + if (backing->info.parent) + backing = backing->info.parent; + + /* + * We need to check any cached meta-results from lookups that + * include this normal item, and if any, invalidate the meta-results + * since they have to be recalculated before being used again. + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + cache->items_lru.head) { + lws_cache_ttl_item_heap_t *i = lws_container_of(d, + lws_cache_ttl_item_heap_t, + list_lru); + const char *iname = ((const char *)&item[1]) + item->size; + uint8_t *pay = (uint8_t *)&item[1], *end = pay + item->size; + + if (*iname == META_ITEM_LEADING) { + size_t taglen = strlen(iname); + + /* + * If the item about to be destroyed makes an + * appearance on the meta results list, we must kill + * the meta result item to force recalc next time + */ + + while (pay < end) { + uint32_t tlen = lws_ser_ru32be(pay + 4); + + if (tlen == taglen && + !strcmp((const char *)pay + 8, iname)) { +#if defined(_DEBUG) + /* + * Sanity check that the item tag is + * really a match for that meta results + * item + */ + + assert (!backing->info.ops->tag_match( + backing, iname + 1, tag, 1)); +#endif + _lws_cache_heap_item_destroy(cache, i); + break; + } + pay += 8 + tlen + 1; + } + +#if defined(_DEBUG) + /* + * Sanity check that the item tag really isn't a match + * for that meta results item + */ + + assert (backing->info.ops->tag_match(backing, iname + 1, + tag, 1)); +#endif + } + + } lws_end_foreach_dll_safe(d, d1); + +post: + _lws_cache_heap_item_destroy(cache, item); +} + +static void +lws_cache_item_evict_lru(lws_cache_ttl_lru_t_heap_t *cache) +{ + lws_cache_ttl_item_heap_t *ei; + + if (!cache->items_lru.head) + return; + + ei = lws_container_of(cache->items_lru.head, + lws_cache_ttl_item_heap_t, list_lru); + + lws_cache_heap_item_destroy(cache, ei, 0); +} + +/* + * We need to weed out expired entries in the backing file + */ + +static void +expiry_cb(lws_sorted_usec_list_t *sul) +{ + lws_cache_ttl_lru_t_heap_t *cache = lws_container_of(sul, + lws_cache_ttl_lru_t_heap_t, cache.sul); + lws_usec_t now = lws_now_usecs(); + + lwsl_cache("%s: %s\n", __func__, cache->cache.info.name); + + while (cache->items_expiry.head) { + lws_cache_ttl_item_heap_t *item; + + item = lws_container_of(cache->items_expiry.head, + lws_cache_ttl_item_heap_t, list_expiry); + + if (item->expiry > now) + return; + + lws_cache_heap_item_destroy(cache, item, 1); + } +} + +/* + * Let's figure out what the earliest next expiry is + */ + +static int +earliest_expiry(lws_cache_ttl_lru_t_heap_t *cache, lws_usec_t *pearliest) +{ + lws_cache_ttl_item_heap_t *item; + + if (!cache->items_expiry.head) + return 1; + + item = lws_container_of(cache->items_expiry.head, + lws_cache_ttl_item_heap_t, list_expiry); + + *pearliest = item->expiry; + + return 0; +} + +static void +update_sul(lws_cache_ttl_lru_t_heap_t *cache) +{ + lws_usec_t earliest; + + /* weed out any newly-expired */ + expiry_cb(&cache->cache.sul); + + /* figure out the next soonest expiring item */ + if (earliest_expiry(cache, &earliest)) { + lws_sul_cancel(&cache->cache.sul); + return; + } + + lwsl_debug("%s: setting exp %llu\n", __func__, + (unsigned long long)earliest); + + if (earliest) + lws_cache_schedule(&cache->cache, expiry_cb, earliest); +} + +static lws_cache_ttl_item_heap_t * +lws_cache_heap_specific(lws_cache_ttl_lru_t_heap_t *cache, + const char *specific_key) +{ + lws_start_foreach_dll(struct lws_dll2 *, d, cache->items_lru.head) { + lws_cache_ttl_item_heap_t *item = lws_container_of(d, + lws_cache_ttl_item_heap_t, + list_lru); + const char *iname = ((const char *)&item[1]) + item->size; + + if (!strcmp(specific_key, iname)) + return item; + + } lws_end_foreach_dll(d); + + return NULL; +} + +static int +lws_cache_heap_tag_match(struct lws_cache_ttl_lru *cache, const char *wc, + const char *tag, char lookup_rules) +{ + return lws_strcmp_wildcard(wc, strlen(wc), tag, strlen(tag)); +} + +static int +lws_cache_heap_lookup(struct lws_cache_ttl_lru *_c, const char *wildcard_key, + lws_dll2_owner_t *results_owner) +{ + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; + size_t sklen = strlen(wildcard_key); + + lws_start_foreach_dll(struct lws_dll2 *, d, cache->items_lru.head) { + lws_cache_ttl_item_heap_t *item = lws_container_of(d, + lws_cache_ttl_item_heap_t, + list_lru); + const char *iname = ((const char *)&item[1]) + item->size; + + if (!lws_strcmp_wildcard(wildcard_key, sklen, iname, + strlen(iname))) { + size_t ilen = strlen(iname); + lws_cache_match_t *m; + char hit = 0; + + /* + * It musn't already be on the list from an earlier + * cache level + */ + + lws_start_foreach_dll(struct lws_dll2 *, e, + results_owner->head) { + lws_cache_match_t *i = lws_container_of(e, + lws_cache_match_t, list); + if (i->tag_size == ilen && + !strcmp(iname, ((const char *)&i[1]))) { + hit = 1; + break; + } + } lws_end_foreach_dll(e); + + if (!hit) { + + /* + * it's unique, instantiate a record for it + */ + + m = lws_fi(&_c->info.cx->fic, + "cache_lookup_oom") ? NULL : + lws_malloc(sizeof(*m) + ilen + 1, + __func__); + if (!m) { + lws_cache_clear_matches(results_owner); + return 1; + } + + memset(&m->list, 0, sizeof(m->list)); + m->tag_size = ilen; + memcpy(&m[1], iname, ilen + 1); + + lws_dll2_add_tail(&m->list, results_owner); + } + } + + } lws_end_foreach_dll(d); + + return 0; +} + +static int +lws_cache_heap_write(struct lws_cache_ttl_lru *_c, const char *specific_key, + const uint8_t *source, size_t size, lws_usec_t expiry, + void **ppvoid) +{ + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; + struct lws_cache_ttl_lru *backing = _c; + lws_cache_ttl_item_heap_t *item, *ei; + size_t kl = strlen(specific_key); + char *p; + + lwsl_cache("%s: %s: len %d\n", __func__, _c->info.name, (int)size); + + /* + * Is this new tag going to invalidate any existing cached meta-results? + * + * If so, let's destroy any of those first to recover the heap + */ + + if (backing->info.parent) + backing = backing->info.parent; + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + cache->items_lru.head) { + lws_cache_ttl_item_heap_t *i = lws_container_of(d, + lws_cache_ttl_item_heap_t, + list_lru); + const char *iname = ((const char *)&i[1]) + i->size; + + if (*iname == META_ITEM_LEADING) { + + /* + * If the item about to be added would match any cached + * results from before it was added, we have to + * invalidate them. To check this, we have to use the + * matching rules at the backing store level + */ + + if (!strcmp(iname + 1, specific_key)) + _lws_cache_heap_item_destroy(cache, i); + } + + } lws_end_foreach_dll_safe(d, d1); + + + /* + * Keep us under the limit if possible... note this will always allow + * caching a single large item even if it is above the limits + */ + + while ((cache->cache.info.max_footprint && + cache->cache.current_footprint + size > + cache->cache.info.max_footprint) || + (cache->cache.info.max_items && + cache->items_lru.count + 1 > cache->cache.info.max_items)) + lws_cache_item_evict_lru(cache); + + /* remove any existing entry of the same key */ + + lws_cache_heap_invalidate(&cache->cache, specific_key); + + item = lws_fi(&_c->info.cx->fic, "cache_write_oom") ? NULL : + lws_malloc(sizeof(*item) + kl + 1u + size, __func__); + if (!item) + return 1; + + cache->cache.current_footprint += item->size; + + /* only need to zero down our item object */ + memset(item, 0, sizeof(*item)); + + p = (char *)&item[1]; + if (ppvoid) + *ppvoid = p; + + /* copy the payload into place */ + if (source) + memcpy(p, source, size); + + /* copy the key string into place, with terminating NUL */ + memcpy(p + size, specific_key, kl + 1); + + item->expiry = expiry; + item->key_len = kl; + item->size = size; + + if (expiry) { + /* adding to expiry is optional, on nonzero expiry */ + lws_dll2_add_sorted(&item->list_expiry, &cache->items_expiry, + sort_expiry); + ei = lws_container_of(cache->items_expiry.head, + lws_cache_ttl_item_heap_t, list_expiry); + lwsl_debug("%s: setting exp %llu\n", __func__, + (unsigned long long)ei->expiry); + lws_cache_schedule(&cache->cache, expiry_cb, ei->expiry); + } + + /* always add outselves to head of lru list */ + lws_dll2_add_head(&item->list_lru, &cache->items_lru); + + return 0; +} + +static int +lws_cache_heap_get(struct lws_cache_ttl_lru *_c, const char *specific_key, + const void **pdata, size_t *psize) +{ + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; + lws_cache_ttl_item_heap_t *item; + + item = lws_cache_heap_specific(cache, specific_key); + if (!item) + return 1; + + /* we are using it, move it to lru head */ + lws_dll2_remove(&item->list_lru); + lws_dll2_add_head(&item->list_lru, &cache->items_lru); + + if (pdata) { + *pdata = (const void *)&item[1]; + *psize = item->size; + } + + return 0; +} + +static int +lws_cache_heap_invalidate(struct lws_cache_ttl_lru *_c, const char *specific_key) +{ + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; + struct lws_cache_ttl_lru *backing = _c; + lws_cache_ttl_item_heap_t *item; + const void *user; + size_t size; + + if (lws_cache_heap_get(_c, specific_key, &user, &size)) + return 0; + + if (backing->info.parent) + backing = backing->info.parent; + + item = (lws_cache_ttl_item_heap_t *)(((uint8_t *)user) - sizeof(*item)); + + /* + * We must invalidate any cached results that would have included this + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + cache->items_lru.head) { + lws_cache_ttl_item_heap_t *i = lws_container_of(d, + lws_cache_ttl_item_heap_t, + list_lru); + const char *iname = ((const char *)&i[1]) + i->size; + + if (*iname == META_ITEM_LEADING) { + + /* + * If the item about to be added would match any cached + * results from before it was added, we have to + * invalidate them. To check this, we have to use the + * matching rules at the backing store level + */ + + if (!backing->info.ops->tag_match(backing, iname + 1, + specific_key, 1)) + _lws_cache_heap_item_destroy(cache, i); + } + + } lws_end_foreach_dll_safe(d, d1); + + lws_cache_heap_item_destroy(cache, item, 0); + + return 0; +} + +static struct lws_cache_ttl_lru * +lws_cache_heap_create(const struct lws_cache_creation_info *info) +{ + lws_cache_ttl_lru_t_heap_t *cache; + + assert(info->cx); + assert(info->name); + + cache = lws_fi(&info->cx->fic, "cache_createfail") ? NULL : + lws_zalloc(sizeof(*cache), __func__); + if (!cache) + return NULL; + + cache->cache.info = *info; + if (info->parent) + info->parent->child = &cache->cache; + + // lwsl_cache("%s: create %s\n", __func__, info->name); + + return (struct lws_cache_ttl_lru *)cache; +} + +static int +destroy_dll(struct lws_dll2 *d, void *user) +{ + lws_cache_ttl_lru_t *_c = (struct lws_cache_ttl_lru *)user; + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; + lws_cache_ttl_item_heap_t *item = + lws_container_of(d, lws_cache_ttl_item_heap_t, list_lru); + + lws_cache_heap_item_destroy(cache, item, 0); + + return 0; +} + +static int +lws_cache_heap_expunge(struct lws_cache_ttl_lru *_c) +{ + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; + + lws_dll2_foreach_safe(&cache->items_lru, cache, destroy_dll); + + return 0; +} + +static void +lws_cache_heap_destroy(struct lws_cache_ttl_lru **_cache) +{ + lws_cache_ttl_lru_t *c = *_cache; + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)c; + + if (!cache) + return; + + lws_sul_cancel(&c->sul); + + lws_dll2_foreach_safe(&cache->items_lru, cache, destroy_dll); + + lws_free_set_NULL(*_cache); +} + +#if defined(_DEBUG) +static int +dump_dll(struct lws_dll2 *d, void *user) +{ + lws_cache_ttl_item_heap_t *item = + lws_container_of(d, lws_cache_ttl_item_heap_t, list_lru); + + lwsl_cache(" %s: size %d, exp %llu\n", + (const char *)&item[1] + item->size, + (int)item->size, (unsigned long long)item->expiry); + + lwsl_hexdump_cache((const char *)&item[1], item->size); + + return 0; +} + +static void +lws_cache_heap_debug_dump(struct lws_cache_ttl_lru *_c) +{ + lws_cache_ttl_lru_t_heap_t *cache = (lws_cache_ttl_lru_t_heap_t *)_c; +#if !defined(LWS_WITH_NO_LOGS) + lws_cache_ttl_item_heap_t *item = NULL; + + lws_dll2_t *d = cache->items_expiry.head; + + if (d) + item = lws_container_of(d, lws_cache_ttl_item_heap_t, + list_expiry); + + lwsl_cache("%s: %s: items %d, earliest %llu\n", __func__, + cache->cache.info.name, (int)cache->items_lru.count, + item ? (unsigned long long)item->expiry : 0ull); +#endif + + lws_dll2_foreach_safe(&cache->items_lru, cache, dump_dll); +} +#endif + +const struct lws_cache_ops lws_cache_ops_heap = { + .create = lws_cache_heap_create, + .destroy = lws_cache_heap_destroy, + .expunge = lws_cache_heap_expunge, + + .write = lws_cache_heap_write, + .tag_match = lws_cache_heap_tag_match, + .lookup = lws_cache_heap_lookup, + .invalidate = lws_cache_heap_invalidate, + .get = lws_cache_heap_get, +#if defined(_DEBUG) + .debug_dump = lws_cache_heap_debug_dump, +#endif +}; diff --git a/3rdparty/libwebsockets/lib/misc/cache-ttl/lws-cache-ttl.c b/3rdparty/libwebsockets/lib/misc/cache-ttl/lws-cache-ttl.c new file mode 100644 index 00000000..0bc80ab5 --- /dev/null +++ b/3rdparty/libwebsockets/lib/misc/cache-ttl/lws-cache-ttl.c @@ -0,0 +1,300 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 "private-lib-misc-cache-ttl.h" + +#include + +#if defined(write) +#undef write +#endif + +void +lws_cache_clear_matches(lws_dll2_owner_t *results_owner) +{ + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, results_owner->head) { + lws_cache_match_t *item = lws_container_of(d, lws_cache_match_t, + list); + lws_dll2_remove(d); + lws_free(item); + } lws_end_foreach_dll_safe(d, d1); +} + +void +lws_cache_schedule(struct lws_cache_ttl_lru *cache, sul_cb_t cb, lws_usec_t e) +{ + lwsl_cache("%s: %s schedule %llu\n", __func__, cache->info.name, + (unsigned long long)e); + + lws_sul_schedule(cache->info.cx, cache->info.tsi, &cache->sul, cb, + e - lws_now_usecs()); +} + +int +lws_cache_write_through(struct lws_cache_ttl_lru *cache, + const char *specific_key, const uint8_t *source, + size_t size, lws_usec_t expiry, void **ppay) +{ + struct lws_cache_ttl_lru *levels[LWS_CACHE_MAX_LEVELS], *c = cache; + int n = 0, r = 0; + + lws_cache_item_remove(cache, specific_key); + + /* starting from L1 */ + + do { + levels[n++] = c; + c = c->info.parent; + } while (c && n < (int)LWS_ARRAY_SIZE(levels)); + + /* starting from outermost cache level */ + + while (n) { + n--; + r = levels[n]->info.ops->write(levels[n], specific_key, + source, size, expiry, ppay); + } + + return r; +} + +/* + * We want to make a list of unique keys that exist at any cache level + * matching a wildcard search key. + * + * If L1 has a cached version though, we will just use that. + */ + +int +lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key, + const void **pdata, size_t *psize) +{ + struct lws_cache_ttl_lru *l1 = cache; + lws_dll2_owner_t results_owner; + lws_usec_t expiry = 0; + char meta_key[128]; + uint8_t *p, *temp; + size_t sum = 0; + int n; + + memset(&results_owner, 0, sizeof(results_owner)); + meta_key[0] = META_ITEM_LEADING; + lws_strncpy(&meta_key[1], wildcard_key, sizeof(meta_key) - 2); + + /* + * If we have a cached result set in L1 already, return that + */ + + if (!l1->info.ops->get(l1, meta_key, pdata, psize)) + return 0; + + /* + * No, we have to do the actual lookup work in the backing store layer + * to get results for this... + */ + + while (cache->info.parent) + cache = cache->info.parent; + + if (cache->info.ops->lookup(cache, wildcard_key, &results_owner)) { + /* eg, OOM */ + + lwsl_cache("%s: bs lookup fail\n", __func__); + + lws_cache_clear_matches(&results_owner); + return 1; + } + + /* + * Scan the results, we want to know how big a payload it needs in + * the cache, and we want to know the earliest expiry of any of the + * component parts, so the meta cache entry for these results can be + * expired when any of the results would expire. + */ + + lws_start_foreach_dll(struct lws_dll2 *, d, results_owner.head) { + lws_cache_match_t *m = lws_container_of(d, lws_cache_match_t, + list); + sum += 8; /* payload size, name length */ + sum += m->tag_size + 1; + + if (m->expiry && (!expiry || expiry < m->expiry)) + expiry = m->expiry; + + } lws_end_foreach_dll(d); + + lwsl_cache("%s: results %d, size %d\n", __func__, + (int)results_owner.count, (int)sum); + + temp = lws_malloc(sum, __func__); + if (!temp) { + lws_cache_clear_matches(&results_owner); + return 1; + } + + /* + * Fill temp with the serialized results + */ + + p = temp; + lws_start_foreach_dll(struct lws_dll2 *, d, results_owner.head) { + lws_cache_match_t *m = lws_container_of(d, lws_cache_match_t, + list); + + /* we don't copy the payload in, but take note of its size */ + lws_ser_wu32be(p, (uint32_t)m->payload_size); + p += 4; + /* length of the tag name (there is an uncounted NUL after) */ + lws_ser_wu32be(p, (uint32_t)m->tag_size); + p += 4; + + /* then the tag name, plus the extra NUL */ + memcpy(p, &m[1], m->tag_size + 1); + p += m->tag_size + 1; + + } lws_end_foreach_dll(d); + + lws_cache_clear_matches(&results_owner); + + /* + * Create the right amount of space for an L1 record of these results, + * with its expiry set to the earliest of the results, and copy it in + * from temp + */ + + n = l1->info.ops->write(l1, meta_key, temp, sum, expiry, (void **)&p); + /* done with temp */ + lws_free(temp); + + if (n) + return 1; + + /* point to the results in L1 */ + + *pdata = p; + *psize = sum; + + return 0; +} + +int +lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key, + const void **pdata, size_t *psize) +{ + while (cache) { + if (!cache->info.ops->get(cache, specific_key, pdata, psize)) { + lwsl_cache("%s: hit\n", __func__); + return 0; + } + + cache = cache->info.parent; + } + + return 1; +} + +int +lws_cache_expunge(struct lws_cache_ttl_lru *cache) +{ + int ret = 0; + + while (cache) { + ret |= cache->info.ops->expunge(cache); + + cache = cache->info.parent; + } + + return ret; +} + +int +lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key) +{ + while (cache) { + if (cache->info.ops->invalidate(cache, wildcard_key)) + return 1; + + cache = cache->info.parent; + } + + return 0; +} + +uint64_t +lws_cache_footprint(struct lws_cache_ttl_lru *cache) +{ + return cache->current_footprint; +} + +void +lws_cache_debug_dump(struct lws_cache_ttl_lru *cache) +{ +#if defined(_DEBUG) + if (cache->info.ops->debug_dump) + cache->info.ops->debug_dump(cache); +#endif +} + +int +lws_cache_results_walk(lws_cache_results_t *walk_ctx) +{ + if (!walk_ctx->size) + return 1; + + walk_ctx->payload_len = lws_ser_ru32be(walk_ctx->ptr); + walk_ctx->tag_len = lws_ser_ru32be(walk_ctx->ptr + 4); + walk_ctx->tag = walk_ctx->ptr + 8; + + walk_ctx->ptr += walk_ctx->tag_len + 1 + 8; + walk_ctx->size -= walk_ctx->tag_len + 1 + 8; + + return 0; +} + +struct lws_cache_ttl_lru * +lws_cache_create(const struct lws_cache_creation_info *info) +{ + assert(info); + assert(info->ops); + assert(info->name); + assert(info->ops->create); + + return info->ops->create(info); +} + +void +lws_cache_destroy(struct lws_cache_ttl_lru **_cache) +{ + lws_cache_ttl_lru_t *cache = *_cache; + + if (!cache) + return; + + assert(cache->info.ops->destroy); + + lws_sul_cancel(&cache->sul); + + cache->info.ops->destroy(_cache); +} diff --git a/3rdparty/libwebsockets/lib/misc/cache-ttl/private-lib-misc-cache-ttl.h b/3rdparty/libwebsockets/lib/misc/cache-ttl/private-lib-misc-cache-ttl.h new file mode 100644 index 00000000..9ff356de --- /dev/null +++ b/3rdparty/libwebsockets/lib/misc/cache-ttl/private-lib-misc-cache-ttl.h @@ -0,0 +1,98 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 lwsl_cache lwsl_debug +#define lwsl_hexdump_cache lwsl_hexdump_debug + +#define LWS_CACHE_MAX_LEVELS 3 + +/* + * If we need structure inside the cache tag names, use this character as a + * separator + */ +#define LWSCTAG_SEP '|' + +/* + * Our synthetic cache result items all have tags starting with this char + */ +#define META_ITEM_LEADING '!' + +typedef struct lws_cache_ttl_item_heap { + lws_dll2_t list_expiry; + lws_dll2_t list_lru; + + lws_usec_t expiry; + size_t key_len; + size_t size; + + /* + * len + key_len + 1 bytes of data overcommitted, user object first + * so it is well-aligned, then the NUL-terminated key name + */ +} lws_cache_ttl_item_heap_t; + +/* this is a "base class", all cache implementations have one at the start */ + +typedef struct lws_cache_ttl_lru { + struct lws_cache_creation_info info; + lws_sorted_usec_list_t sul; + struct lws_cache_ttl_lru *child; + uint64_t current_footprint; +} lws_cache_ttl_lru_t; + +/* + * The heap-backed cache uses lws_dll2 linked-lists to track items that are + * in it. + */ + +typedef struct lws_cache_ttl_lru_heap { + lws_cache_ttl_lru_t cache; + + lws_dll2_owner_t items_expiry; + lws_dll2_owner_t items_lru; +} lws_cache_ttl_lru_t_heap_t; + +/* + * We want to be able to work with a large file-backed implementation even on + * devices that don't have heap to track what is in it. It means if lookups + * reach this cache layer, we will be scanning a potentially large file. + * + * L1 caching of lookups (including null result list) reduces the expense of + * this on average. We keep a copy of the last computed earliest expiry. + * + * We can't keep an open file handle here. Because other processes may change + * the cookie file by deleting and replacing it, we have to open it fresh each + * time. + */ +typedef struct lws_cache_nscookiejar { + lws_cache_ttl_lru_t cache; + + lws_usec_t earliest_expiry; +} lws_cache_nscookiejar_t; + +void +lws_cache_clear_matches(lws_dll2_owner_t *results_owner); + +void +lws_cache_schedule(struct lws_cache_ttl_lru *cache, sul_cb_t cb, lws_usec_t e); diff --git a/3rdparty/libwebsockets/lib/misc/getifaddrs.c b/3rdparty/libwebsockets/lib/misc/getifaddrs.c index 15e3eaf2..125088e2 100644 --- a/3rdparty/libwebsockets/lib/misc/getifaddrs.c +++ b/3rdparty/libwebsockets/lib/misc/getifaddrs.c @@ -90,7 +90,11 @@ getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags, ret = ENOMEM; goto error_out; } - ifconf.ifc_len = buf_size; +#if defined(__QNX__) + ifconf.ifc_len = (short)(int)buf_size; +#else + ifconf.ifc_len = (int)buf_size; +#endif ifconf.ifc_buf = buf; /* @@ -141,7 +145,7 @@ getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags, (*end)->ifa_next = NULL; (*end)->ifa_name = strdup(ifr->ifr_name); - (*end)->ifa_flags = ifreq.ifr_flags; + (*end)->ifa_flags = (unsigned int)ifreq.ifr_flags; (*end)->ifa_addr = lws_malloc(salen, "getifaddrs"); memcpy((*end)->ifa_addr, sa, salen); (*end)->ifa_netmask = NULL; diff --git a/3rdparty/libwebsockets/lib/misc/ieeehalfprecision.c b/3rdparty/libwebsockets/lib/misc/ieeehalfprecision.c new file mode 100644 index 00000000..075eb1d1 --- /dev/null +++ b/3rdparty/libwebsockets/lib/misc/ieeehalfprecision.c @@ -0,0 +1,228 @@ +/****************************************************************************** + * + * Filename: ieeehalfprecision.c + * Programmer: James Tursa + * Version: 1.0 + * Date: March 3, 2009 + * Copyright: (c) 2009 by James Tursa, All Rights Reserved + * + * This code uses the BSD License: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * This file contains C code to convert between IEEE double, single, and half + * precision floating point formats. The intended use is for standalone C code + * that does not rely on MATLAB mex.h. The bit pattern for the half precision + * floating point format is stored in a 16-bit unsigned int variable. The half + * precision bit pattern definition is: + * + * 1 bit sign bit + * 5 bits exponent, biased by 15 + * 10 bits mantissa, hidden leading bit, normalized to 1.0 + * + * Special floating point bit patterns recognized and supported: + * + * All exponent bits zero: + * - If all mantissa bits are zero, then number is zero (possibly signed) + * - Otherwise, number is a denormalized bit pattern + * + * All exponent bits set to 1: + * - If all mantissa bits are zero, then number is +Infinity or -Infinity + * - Otherwise, number is NaN (Not a Number) + * + * For the denormalized cases, note that 2^(-24) is the smallest number that can + * be represented in half precision exactly. 2^(-25) will convert to 2^(-24) + * because of the rounding algorithm used, and 2^(-26) is too small and + * underflows to zero. + * + ******************************************************************************/ + +/* + changes by K. Rogovin: + - changed macros UINT16_TYPE, etc to types from stdint.h + (i.e. UINT16_TYPE-->uint16_t, INT16_TYPE-->int16_t, etc) + + - removed double conversion routines. + + - changed run time checks of endianness to compile time macro. + + - removed return value from routines + + - changed source parameter type from * to const * + + - changed pointer types from void ot uint16_t and uint32_t + */ + +/* + * andy@warmcat.com: + * + * - clean style and indenting + * - convert to single operation + * - export as lws_ + */ + +#include +#include + +void +lws_singles2halfp(uint16_t *hp, uint32_t x) +{ + uint32_t xs, xe, xm; + uint16_t hs, he, hm; + int hes; + + if (!(x & 0x7FFFFFFFu)) { + /* Signed zero */ + *hp = (uint16_t)(x >> 16); + + return; + } + + xs = x & 0x80000000u; // Pick off sign bit + xe = x & 0x7F800000u; // Pick off exponent bits + xm = x & 0x007FFFFFu; // Pick off mantissa bits + + if (xe == 0) { // Denormal will underflow, return a signed zero + *hp = (uint16_t) (xs >> 16); + return; + } + + if (xe == 0x7F800000u) { // Inf or NaN (all the exponent bits are set) + if (!xm) { // If mantissa is zero ... + *hp = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf + return; + } + + *hp = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set + + return; + } + + /* Normalized number */ + + hs = (uint16_t) (xs >> 16); // Sign bit + /* Exponent unbias the single, then bias the halfp */ + hes = ((int)(xe >> 23)) - 127 + 15; + + if (hes >= 0x1F) { // Overflow + *hp = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf + return; + } + + if (hes <= 0) { // Underflow + if ((14 - hes) > 24) + /* + * Mantissa shifted all the way off & no + * rounding possibility + */ + hm = (uint16_t) 0u; // Set mantissa to zero + else { + xm |= 0x00800000u; // Add the hidden leading bit + hm = (uint16_t) (xm >> (14 - hes)); // Mantissa + if ((xm >> (13 - hes)) & 1u) // Check for rounding + /* Round, might overflow into exp bit, + * but this is OK */ + hm = (uint16_t)(hm + 1u); + } + /* Combine sign bit and mantissa bits, biased exponent is 0 */ + *hp = hs | hm; + + return; + } + + he = (uint16_t)(hes << 10); // Exponent + hm = (uint16_t)(xm >> 13); // Mantissa + + if (xm & 0x00001000u) // Check for rounding + /* Round, might overflow to inf, this is OK */ + *hp = (uint16_t)((hs | he | hm) + (uint16_t)1u); + else + *hp = hs | he | hm; // No rounding +} + +void +lws_halfp2singles(uint32_t *xp, uint16_t h) +{ + uint16_t hs, he, hm; + uint32_t xs, xe, xm; + int32_t xes; + int e; + + if (!(h & 0x7FFFu)) { // Signed zero + *xp = ((uint32_t)h) << 16; // Return the signed zero + + return; + } + + hs = h & 0x8000u; // Pick off sign bit + he = h & 0x7C00u; // Pick off exponent bits + hm = h & 0x03FFu; // Pick off mantissa bits + + if (!he) { // Denormal will convert to normalized + e = -1; + + /* figure out how much extra to adjust the exponent */ + do { + e++; + hm = (uint16_t)(hm << 1); + /* Shift until leading bit overflows into exponent */ + } while (!(hm & 0x0400u)); + + xs = ((uint32_t) hs) << 16; // Sign bit + + /* Exponent unbias the halfp, then bias the single */ + xes = ((int32_t)(he >> 10)) - 15 + 127 - e; + xe = (uint32_t)(xes << 23); // Exponent + xm = ((uint32_t)(hm & 0x03FFu)) << 13; // Mantissa + + *xp = xs | xe | xm; + + return; + } + + if (he == 0x7C00u) { /* Inf or NaN (all the exponent bits are set) */ + if (!hm) { /* If mantissa is zero ... + * Signed Inf + */ + *xp = (((uint32_t)hs) << 16) | ((uint32_t)0x7F800000u); + + return; + } + + /* ... NaN, only 1st mantissa bit set */ + *xp = (uint32_t)0xFFC00000u; + + return; + } + + /* Normalized number */ + + xs = ((uint32_t)hs) << 16; // Sign bit + /* Exponent unbias the halfp, then bias the single */ + xes = ((int32_t)(he >> 10)) - 15 + 127; + xe = (uint32_t)(xes << 23); // Exponent + xm = ((uint32_t)hm) << 13; // Mantissa + + /* Combine sign bit, exponent bits, and mantissa bits */ + *xp = xs | xe | xm; +} diff --git a/3rdparty/libwebsockets/lib/misc/lecp.c b/3rdparty/libwebsockets/lib/misc/lecp.c new file mode 100644 index 00000000..4783241a --- /dev/null +++ b/3rdparty/libwebsockets/lib/misc/lecp.c @@ -0,0 +1,1686 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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. + * + * Stream parser for RFC8949 CBOR + */ + +#include "private-lib-core.h" +#include +#include + +#if defined(LWS_WITH_CBOR_FLOAT) +#include +#endif + +#define lwsl_lecp lwsl_debug + +static const char * const parser_errs[] = { + "", + "", + "Bad CBOR coding", + "Unknown", + "Parser callback errored (see earlier error)", + "Overflow" +}; + +enum lecp_states { + LECP_OPC, + LECP_COLLECT, + LECP_SIMPLEX8, + LECP_COLLATE, + LECP_ONLY_SAME +}; + +void +lecp_construct(struct lecp_ctx *ctx, lecp_callback cb, void *user, + const char * const *paths, unsigned char count_paths) +{ + uint16_t x = 0x1234; + + memset(ctx, 0, sizeof(*ctx) - sizeof(ctx->buf)); + + ctx->user = user; + ctx->pst[0].cb = cb; + ctx->pst[0].paths = paths; + ctx->pst[0].count_paths = count_paths; + ctx->be = *((uint8_t *)&x) == 0x12; + + ctx->st[0].s = LECP_OPC; + + ctx->pst[0].cb(ctx, LECPCB_CONSTRUCTED); +} + +void +lecp_destruct(struct lecp_ctx *ctx) +{ + /* no allocations... just let callback know what it happening */ + if (ctx->pst[0].cb) + ctx->pst[0].cb(ctx, LECPCB_DESTRUCTED); +} + +void +lecp_change_callback(struct lecp_ctx *ctx, lecp_callback cb) +{ + ctx->pst[0].cb(ctx, LECPCB_DESTRUCTED); + ctx->pst[0].cb = cb; + ctx->pst[0].cb(ctx, LECPCB_CONSTRUCTED); +} + + +const char * +lecp_error_to_string(int e) +{ + if (e > 0) + e = 0; + else + e = -e; + + if (e >= (int)LWS_ARRAY_SIZE(parser_errs)) + return "Unknown error"; + + return parser_errs[e]; +} + +static void +ex(struct lecp_ctx *ctx, void *_start, size_t len) +{ + struct _lecp_stack *st = &ctx->st[ctx->sp]; + uint8_t *start = (uint8_t *)_start; + + st->s = LECP_COLLECT; + st->collect_rem = (uint8_t)len; + + if (ctx->be) + ctx->collect_tgt = start; + else + ctx->collect_tgt = start + len - 1; +} + +static void +lecp_check_path_match(struct lecp_ctx *ctx) +{ + const char *p, *q; + size_t s = sizeof(char *); + int n; + + if (ctx->path_stride) + s = ctx->path_stride; + + /* we only need to check if a match is not active */ + for (n = 0; !ctx->path_match && + n < ctx->pst[ctx->pst_sp].count_paths; n++) { + ctx->wildcount = 0; + p = ctx->path; + + q = *((char **)(((char *)ctx->pst[ctx->pst_sp].paths) + + ((unsigned int)n * s))); + + while (*p && *q) { + if (*q != '*') { + if (*p != *q) + break; + p++; + q++; + continue; + } + ctx->wild[ctx->wildcount++] = + (uint16_t)lws_ptr_diff_size_t(p, ctx->path); + q++; + /* + * if * has something after it, match to . + * if ends with *, eat everything. + * This implies match sequences must be ordered like + * x.*.* + * x.* + * if both options are possible + */ + while (*p && (*p != '.' || !*q)) + p++; + } + if (*p || *q) + continue; + + ctx->path_match = (uint8_t)(n + 1); + ctx->path_match_len = ctx->pst[ctx->pst_sp].ppos; + return; + } + + if (!ctx->path_match) + ctx->wildcount = 0; +} + +int +lecp_push(struct lecp_ctx *ctx, char s_start, char s_end, char state) +{ + struct _lecp_stack *st = &ctx->st[ctx->sp]; + + if (ctx->sp + 1 == LWS_ARRAY_SIZE(ctx->st)) + return LECP_STACK_OVERFLOW; + + if (s_start && ctx->pst[ctx->pst_sp].cb(ctx, s_start)) + return LECP_REJECT_CALLBACK; + + lwsl_lecp("%s: pushing from sp %d, parent " + "(opc %d, indet %d, collect_rem %d)\n", + __func__, ctx->sp, st->opcode >> 5, st->indet, + (int)st->collect_rem); + + + st->pop_iss = s_end; /* issue this when we pop back here */ + ctx->st[ctx->sp + 1] = *st; + ctx->sp++; + st++; + + st->s = state; + st->collect_rem = 0; + st->intermediate = 0; + st->indet = 0; + st->ordinal = 0; + st->send_new_array_item = 0; + st->barrier = 0; + + return 0; +} + +int +lecp_pop(struct lecp_ctx *ctx) +{ + struct _lecp_stack *st; + + assert(ctx->sp); + ctx->sp--; + + st = &ctx->st[ctx->sp]; + + if (st->pop_iss == LECPCB_ARRAY_END) { + assert(ctx->ipos); + ctx->ipos--; + } + + ctx->pst[ctx->pst_sp].ppos = st->p; + ctx->path[st->p] = '\0'; + lecp_check_path_match(ctx); + + lwsl_lecp("%s: popping to sp %d, parent " + "(opc %d, indet %d, collect_rem %d)\n", + __func__, ctx->sp, st->opcode >> 5, st->indet, + (int)st->collect_rem); + + if (st->pop_iss && ctx->pst[ctx->pst_sp].cb(ctx, st->pop_iss)) + return LECP_REJECT_CALLBACK; + + return 0; +} + +static struct _lecp_stack * +lwcp_st_parent(struct lecp_ctx *ctx) +{ + assert(ctx->sp); + + return &ctx->st[ctx->sp - 1]; +} + +int +lwcp_completed(struct lecp_ctx *ctx, char indet) +{ + int r, il = ctx->ipos; + + ctx->st[ctx->sp].s = LECP_OPC; + + while (ctx->sp && !ctx->st[ctx->sp].barrier) { + struct _lecp_stack *parent = lwcp_st_parent(ctx); + + lwsl_lecp("%s: sp %d, parent " + "(opc %d, indet %d, collect_rem %d)\n", + __func__, ctx->sp, parent->opcode >> 5, parent->indet, + (int)parent->collect_rem); + + parent->ordinal++; + if (parent->opcode == LWS_CBOR_MAJTYP_ARRAY) { + assert(il); + il--; + ctx->i[il]++; + if (!parent->send_new_array_item) { + if (ctx->pst[ctx->pst_sp].cb(ctx, + LECPCB_ARRAY_ITEM_END)) + return LECP_REJECT_CALLBACK; + parent->send_new_array_item = 1; + } + } + + if (!indet && parent->indet) { + lwsl_lecp("%s: abandoning walk as parent needs indet\n", __func__); + break; + } + + if (!parent->indet && parent->collect_rem) { + parent->collect_rem--; + lwsl_lecp("%s: sp %d, parent (opc %d, indet %d, collect_rem -> %d)\n", + __func__, ctx->sp, parent->opcode >> 5, parent->indet, (int)parent->collect_rem); + + if (parent->collect_rem) { + /* more items to come */ + if (parent->opcode == LWS_CBOR_MAJTYP_ARRAY) + parent->send_new_array_item = 1; + break; + } + } + + lwsl_lecp("%s: parent (opc %d) collect_rem became zero\n", __func__, parent->opcode >> 5); + + ctx->st[ctx->sp - 1].s = LECP_OPC; + r = lecp_pop(ctx); + if (r) + return r; + indet = 0; + } + + return 0; +} + +static int +lwcp_is_indet_string(struct lecp_ctx *ctx) +{ + if (ctx->st[ctx->sp].indet) + return 1; + + if (!ctx->sp) + return 0; + + if (lwcp_st_parent(ctx)->opcode != LWS_CBOR_MAJTYP_BSTR && + lwcp_st_parent(ctx)->opcode != LWS_CBOR_MAJTYP_TSTR) + return 0; + + if (ctx->st[ctx->sp - 1].indet) + return 1; + + return 0; +} + +static int +report_raw_cbor(struct lecp_ctx *ctx) +{ + struct _lecp_parsing_stack *pst = &ctx->pst[ctx->pst_sp]; + + if (!ctx->cbor_pos) + return 0; + + if (pst->cb(ctx, LECPCB_LITERAL_CBOR)) + return 1; + + ctx->cbor_pos = 0; + + return 0; +} + +void +lecp_parse_report_raw(struct lecp_ctx *ctx, int on) +{ + ctx->literal_cbor_report = (uint8_t)on; + report_raw_cbor(ctx); +} + +int +lecp_parse_map_is_key(struct lecp_ctx *ctx) +{ + return lwcp_st_parent(ctx)->opcode == LWS_CBOR_MAJTYP_MAP && + !(lwcp_st_parent(ctx)->ordinal & 1); +} + +int +lecp_parse_subtree(struct lecp_ctx *ctx, const uint8_t *in, size_t len) +{ + struct _lecp_stack *st = &ctx->st[++ctx->sp]; + int n; + + st->s = 0; + st->collect_rem = 0; + st->intermediate = 0; + st->indet = 0; + st->ordinal = 0; + st->send_new_array_item = 0; + st->barrier = 1; + + n = lecp_parse(ctx, in, len); + ctx->sp--; + + return n; +} + +int +lecp_parse(struct lecp_ctx *ctx, const uint8_t *cbor, size_t len) +{ + size_t olen = len; + int ret; + + while (len--) { + struct _lecp_parsing_stack *pst = &ctx->pst[ctx->pst_sp]; + struct _lecp_stack *st = &ctx->st[ctx->sp]; + uint8_t c, sm, o; + char to; + + c = *cbor++; + + /* + * for, eg, cose_sign, we sometimes need to collect subtrees of + * raw CBOR. Report buffers of it via the callback if we filled + * the buffer, or we stopped collecting. + */ + + if (ctx->literal_cbor_report) { + ctx->cbor[ctx->cbor_pos++] = c; + if (ctx->cbor_pos == sizeof(ctx->cbor) && + report_raw_cbor(ctx)) + goto reject_callback; + } + + switch (st->s) { + /* + * We're getting the nex opcode + */ + case LECP_OPC: + st->opcode = ctx->item.opcode = c & LWS_CBOR_MAJTYP_MASK; + sm = c & LWS_CBOR_SUBMASK; + to = 0; + + lwsl_lecp("%s: %d: OPC %d|%d\n", __func__, ctx->sp, + c >> 5, sm); + + if (c != 0xff && ctx->sp && + ctx->st[ctx->sp - 1].send_new_array_item) { + ctx->st[ctx->sp - 1].send_new_array_item = 0; + if (ctx->pst[ctx->pst_sp].cb(ctx, + LECPCB_ARRAY_ITEM_START)) + goto reject_callback; + } + + switch (st->opcode) { + case LWS_CBOR_MAJTYP_UINT: + ctx->present = LECPCB_VAL_NUM_UINT; + if (sm < LWS_CBOR_1) { + ctx->item.u.i64 = (int64_t)sm; + goto issue; + } + goto i2; + + case LWS_CBOR_MAJTYP_INT_NEG: + ctx->present = LECPCB_VAL_NUM_INT; + if (sm < 24) { + ctx->item.u.i64 = (-1ll) - (int64_t)sm; + goto issue; + } +i2: + if (sm >= LWS_CBOR_RESERVED) + goto bad_coding; + ctx->item.u.u64 = 0; + o = (uint8_t)(1 << (sm - LWS_CBOR_1)); + ex(ctx, (uint8_t *)&ctx->item.u.u64, o); + break; + + case LWS_CBOR_MAJTYP_BSTR: + to = LECPCB_VAL_BLOB_END - LECPCB_VAL_STR_END; + + /* fallthru */ + + case LWS_CBOR_MAJTYP_TSTR: + /* + * The first thing is the string length, it's + * going to either be a byte count for the + * string or the indefinite length marker + * followed by determinite-length chunks of the + * same MAJTYP + */ + + ctx->npos = 0; + ctx->buf[0] = '\0'; + + if (!sm) { + if ((!ctx->sp || (ctx->sp && + !ctx->st[ctx->sp - 1].intermediate)) && + pst->cb(ctx, (char)(LECPCB_VAL_STR_START + to))) + goto reject_callback; + + if (pst->cb(ctx, (char)(LECPCB_VAL_STR_END + to))) + goto reject_callback; + lwcp_completed(ctx, 0); + break; + } + + if (sm < LWS_CBOR_1) { + ctx->item.u.u64 = (uint64_t)sm; + if ((!ctx->sp || (ctx->sp && + !ctx->st[ctx->sp - 1].intermediate)) && + pst->cb(ctx, (char)(LECPCB_VAL_STR_START + to))) + goto reject_callback; + + st->indet = 0; + st->collect_rem = sm; + st->s = LECP_COLLATE; + break; + } + + if (sm < LWS_CBOR_RESERVED) + goto i2; + + if (sm != LWS_CBOR_INDETERMINITE) + goto bad_coding; + + if ((!ctx->sp || (ctx->sp && + !ctx->st[ctx->sp - 1].intermediate)) && + pst->cb(ctx, (char)(LECPCB_VAL_STR_START + to))) + goto reject_callback; + + st->indet = 1; + + st->p = pst->ppos; + lecp_push(ctx, 0, (char)(LECPCB_VAL_STR_END + to), + LECP_ONLY_SAME); + break; + + case LWS_CBOR_MAJTYP_ARRAY: + ctx->npos = 0; + ctx->buf[0] = '\0'; + + if (pst->ppos + 3u >= sizeof(ctx->path)) + goto reject_overflow; + + st->p = pst->ppos; + ctx->path[pst->ppos++] = '['; + ctx->path[pst->ppos++] = ']'; + ctx->path[pst->ppos] = '\0'; + + lecp_check_path_match(ctx); + + if (ctx->ipos + 1u >= LWS_ARRAY_SIZE(ctx->i)) + goto reject_overflow; + + ctx->i[ctx->ipos++] = 0; + + if (pst->cb(ctx, LECPCB_ARRAY_START)) + goto reject_callback; + + if (!sm) { + if (pst->cb(ctx, LECPCB_ARRAY_END)) + goto reject_callback; + pst->ppos = st->p; + ctx->path[pst->ppos] = '\0'; + ctx->ipos--; + lecp_check_path_match(ctx); + lwcp_completed(ctx, 0); + break; + } + + ctx->st[ctx->sp].send_new_array_item = 1; + + if (sm < LWS_CBOR_1) { + st->indet = 0; + st->collect_rem = sm; + goto push_a; + } + + if (sm < LWS_CBOR_RESERVED) + goto i2; + + if (sm != LWS_CBOR_INDETERMINITE) + goto bad_coding; + + st->indet = 1; +push_a: + lecp_push(ctx, 0, LECPCB_ARRAY_END, LECP_OPC); + break; + + case LWS_CBOR_MAJTYP_MAP: + ctx->npos = 0; + ctx->buf[0] = '\0'; + + if (pst->ppos + 1u >= sizeof(ctx->path)) + goto reject_overflow; + + st->p = pst->ppos; + ctx->path[pst->ppos++] = '.'; + ctx->path[pst->ppos] = '\0'; + + lecp_check_path_match(ctx); + + if (pst->cb(ctx, LECPCB_OBJECT_START)) + goto reject_callback; + + if (!sm) { + if (pst->cb(ctx, LECPCB_OBJECT_END)) + goto reject_callback; + pst->ppos = st->p; + ctx->path[pst->ppos] = '\0'; + lecp_check_path_match(ctx); + lwcp_completed(ctx, 0); + break; + } + if (sm < LWS_CBOR_1) { + st->indet = 0; + st->collect_rem = (uint64_t)(sm * 2); + goto push_m; + } + + if (sm < LWS_CBOR_RESERVED) + goto i2; + + if (sm != LWS_CBOR_INDETERMINITE) + goto bad_coding; + + st->indet = 1; +push_m: + lecp_push(ctx, 0, LECPCB_OBJECT_END, LECP_OPC); + break; + + case LWS_CBOR_MAJTYP_TAG: + /* tag has one or another kind of int first */ + if (sm < LWS_CBOR_1) { + /* + * We have a literal tag number, push + * to decode the tag body + */ + ctx->item.u.u64 = st->tag = (uint64_t)sm; + goto start_tag_enclosure; + } + /* + * We have to do more stuff to get the tag + * number... + */ + goto i2; + + case LWS_CBOR_MAJTYP_FLOAT: + /* + * This can also be a bunch of specials as well + * as sizes of float... + */ + sm = c & LWS_CBOR_SUBMASK; + + switch (sm) { + case LWS_CBOR_SWK_FALSE: + ctx->present = LECPCB_VAL_FALSE; + goto issue; + + case LWS_CBOR_SWK_TRUE: + ctx->present = LECPCB_VAL_TRUE; + goto issue; + + case LWS_CBOR_SWK_NULL: + ctx->present = LECPCB_VAL_NULL; + goto issue; + + case LWS_CBOR_SWK_UNDEFINED: + ctx->present = LECPCB_VAL_UNDEFINED; + goto issue; + + case LWS_CBOR_M7_SUBTYP_SIMPLE_X8: + st->s = LECP_SIMPLEX8; + break; + + case LWS_CBOR_M7_SUBTYP_FLOAT16: + ctx->present = LECPCB_VAL_FLOAT16; + ex(ctx, &ctx->item.u.hf, 2); + break; + + case LWS_CBOR_M7_SUBTYP_FLOAT32: + ctx->present = LECPCB_VAL_FLOAT32; + ex(ctx, &ctx->item.u.f, 4); + break; + + case LWS_CBOR_M7_SUBTYP_FLOAT64: + ctx->present = LECPCB_VAL_FLOAT64; + ex(ctx, &ctx->item.u.d, 8); + break; + + case LWS_CBOR_M7_BREAK: + if (!ctx->sp || + !ctx->st[ctx->sp - 1].indet) + goto bad_coding; + + lwcp_completed(ctx, 1); + break; + + default: + /* handle as simple */ + ctx->item.u.u64 = (uint64_t)sm; + if (pst->cb(ctx, LECPCB_VAL_SIMPLE)) + goto reject_callback; + break; + } + break; + } + break; + + /* + * We're collecting int / float pieces + */ + case LECP_COLLECT: + if (ctx->be) + *ctx->collect_tgt++ = c; + else + *ctx->collect_tgt-- = c; + + if (--st->collect_rem) + break; + + /* + * We collected whatever it was... + */ + + ctx->npos = 0; + ctx->buf[0] = '\0'; + + switch (st->opcode) { + case LWS_CBOR_MAJTYP_BSTR: + case LWS_CBOR_MAJTYP_TSTR: + st->collect_rem = ctx->item.u.u64; + if ((!ctx->sp || (ctx->sp && + !ctx->st[ctx->sp - 1].intermediate)) && + pst->cb(ctx, (char)((st->opcode == + LWS_CBOR_MAJTYP_TSTR) ? + LECPCB_VAL_STR_START : + LECPCB_VAL_BLOB_START))) + goto reject_callback; + st->s = LECP_COLLATE; + break; + + case LWS_CBOR_MAJTYP_ARRAY: + st->collect_rem = ctx->item.u.u64; + lecp_push(ctx, 0, LECPCB_ARRAY_END, LECP_OPC); + break; + + case LWS_CBOR_MAJTYP_MAP: + st->collect_rem = ctx->item.u.u64 * 2; + lecp_push(ctx, 0, LECPCB_OBJECT_END, LECP_OPC); + break; + + case LWS_CBOR_MAJTYP_TAG: + st->tag = ctx->item.u.u64; + goto start_tag_enclosure; + + default: + /* + * ... then issue what we collected as a + * literal + */ + + if (st->opcode == LWS_CBOR_MAJTYP_INT_NEG) + ctx->item.u.i64 = (-1ll) - ctx->item.u.i64; + + goto issue; + } + break; + + case LECP_SIMPLEX8: + /* + * Extended SIMPLE byte for 7|24 opcode, no uses + * for it in RFC8949 + */ + if (c <= LWS_CBOR_INDETERMINITE) + /* + * Duplication of implicit simple values is + * denied by RFC8949 3.3 + */ + goto bad_coding; + + ctx->item.u.u64 = (uint64_t)c; + if (pst->cb(ctx, LECPCB_VAL_SIMPLE)) + goto reject_callback; + + lwcp_completed(ctx, 0); + break; + + case LECP_COLLATE: + /* + * let's grab b/t string content into the context + * buffer, and issue chunks from there + */ + + ctx->buf[ctx->npos++] = (char)c; + if (st->collect_rem) + st->collect_rem--; + + /* spill at chunk boundaries, or if we filled the buf */ + if (ctx->npos != sizeof(ctx->buf) - 1 && + st->collect_rem) + break; + + /* spill */ + ctx->buf[ctx->npos] = '\0'; + + /* if it's a map name, deal with the path */ + if (ctx->sp && lecp_parse_map_is_key(ctx)) { + if (lwcp_st_parent(ctx)->ordinal) + pst->ppos = st->p; + st->p = pst->ppos; + if (pst->ppos + ctx->npos > sizeof(ctx->path)) + goto reject_overflow; + memcpy(&ctx->path[pst->ppos], ctx->buf, + (size_t)(ctx->npos + 1)); + pst->ppos = (uint8_t)(pst->ppos + ctx->npos); + lecp_check_path_match(ctx); + } + + to = 0; + if (ctx->item.opcode == LWS_CBOR_MAJTYP_BSTR) + to = LECPCB_VAL_BLOB_END - LECPCB_VAL_STR_END; + + o = (uint8_t)(LECPCB_VAL_STR_END + to); + c = (st->collect_rem /* more to come at this layer */ || + /* we or direct parent is indeterminite */ + lwcp_is_indet_string(ctx)); + + if (ctx->sp) + ctx->st[ctx->sp - 1].intermediate = !!c; + if (c) + o--; + + if (pst->cb(ctx, (char)o)) + goto reject_callback; + ctx->npos = 0; + ctx->buf[0] = '\0'; + + if (ctx->sp && lwcp_st_parent(ctx)->indet) + st->s = LECP_OPC; + if (o == LECPCB_VAL_STR_END + to) + lwcp_completed(ctx, 0); + + break; + + case LECP_ONLY_SAME: + /* + * deterministic sized chunks same MAJTYP as parent + * level only (BSTR and TSTR frags inside interderminite + * BSTR or TSTR) + * + * Clean end when we see M7|31 + */ + if (!ctx->sp) { + /* + * We should only come here by pushing on stack + */ + assert(0); + return LECP_STACK_OVERFLOW; + } + + if (c == (LWS_CBOR_MAJTYP_FLOAT | LWS_CBOR_M7_BREAK)) { + /* if's the end of an interdetminite list */ + if (!ctx->sp || !ctx->st[ctx->sp - 1].indet) + /* + * Can't have a break without an + * indeterminite parent + */ + goto bad_coding; + + if (lwcp_completed(ctx, 1)) + goto reject_callback; + break; + } + + if (st->opcode != lwcp_st_parent(ctx)->opcode) + /* + * Fragments have to be of the same type as the + * outer opcode + */ + goto bad_coding; + + sm = c & LWS_CBOR_SUBMASK; + + if (sm == LWS_CBOR_INDETERMINITE) + /* indeterminite length frags not allowed */ + goto bad_coding; + + if (sm < LWS_CBOR_1) { + st->indet = 0; + st->collect_rem = (uint64_t)sm; + st->s = LECP_COLLATE; + break; + } + + if (sm >= LWS_CBOR_RESERVED) + goto bad_coding; + + goto i2; + + default: + assert(0); + return -1; + } + + continue; + +start_tag_enclosure: + st->p = pst->ppos; + ret = lecp_push(ctx, LECPCB_TAG_START, LECPCB_TAG_END, LECP_OPC); + if (ret) + return ret; + + continue; + +issue: + if (ctx->item.opcode == LWS_CBOR_MAJTYP_TAG) { + st->tag = ctx->item.u.u64; + goto start_tag_enclosure; + } + + /* we are just a number */ + + if (pst->cb(ctx, ctx->present)) + goto reject_callback; + + lwcp_completed(ctx, 0); + + } + + ctx->used_in = olen - len; + + if (!ctx->sp && ctx->st[0].s == LECP_OPC) + return 0; + + return LECP_CONTINUE; + +reject_overflow: + ret = LECP_STACK_OVERFLOW; + goto reject; + +bad_coding: + ret = LECP_REJECT_BAD_CODING; + goto reject; + +reject_callback: + ret = LECP_REJECT_CALLBACK; + +reject: + ctx->pst[ctx->pst_sp].cb(ctx, LECPCB_FAILED); + + return ret; +} + + + +void +lws_lec_init(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->start = ctx->buf = buf; + ctx->end = ctx->start + len; + ctx->fmt_pos = 0; +} + +void +lws_lec_setbuf(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len) +{ + ctx->start = ctx->buf = buf; + ctx->end = ctx->start + len; + ctx->used = 0; + ctx->vaa_pos = 0; +} + +enum lws_lec_pctx_ret +lws_lec_printf(lws_lec_pctx_t *ctx, const char *format, ...) +{ + enum lws_lec_pctx_ret r; + va_list ap; + + va_start(ap, format); + r = lws_lec_vsprintf(ctx, format, ap); + va_end(ap); + + return r; +} + +/* + * Report how many next-level elements inbetween fmt[0] and the matching + * closure, eg, [] returns 0, [123] would return 1, [123,456] returns 2, and + * [123,{'a':[123,456]}] returns 2. Counts for { } maps are in pairs, ie, + * {'a':1, 'b': 2} returns 2 + * + * If there is no closure in the string it returns -1 + * + * We use this to figure out if we should use indeterminite lengths or specific + * lengths for items in the format string + */ + +#define bump(_r) count[sp]++ +//; lwsl_notice("%s: count[%d] -> %d\n", _r, sp, count[sp]) + +static int +format_scan(const char *fmt) +{ + char stack[12], literal = 0, numeric = 0; + int count[12], sp = 0, pc = 0, swallow = 0; + + literal = *fmt == '\''; + stack[sp] = *fmt++; + count[sp] = 0; + +// lwsl_notice("%s: start %s\n", __func__, fmt - 1); + + while (*fmt) { + +// lwsl_notice("%s: %c %d %d\n", __func__, *fmt, sp, literal); + + if (swallow) { + swallow--; + fmt++; + continue; + } + + if (numeric) { + if (*fmt >= '0' && *fmt <= '9') + fmt++; + numeric = 0; + if (*fmt != '(') + bump("a"); + } + + if (literal) { + if (*fmt == '\\' && fmt[1]) { + fmt += 2; + continue; + } + if (*fmt == '\'') { + literal = 0; + if (!sp && stack[sp] == '\'') + return count[sp]; + + if (sp) + sp--; + fmt++; + continue; + } + + bump("b"); + fmt++; + continue; + } + + if (*fmt == '\'') { + bump("c"); + sp++; + literal = 1; + fmt++; + continue; + } + + switch (pc) { + case 1: + if (*fmt == '.') { + pc++; + fmt++; + continue; + } + if (*fmt == 'l') { + pc++; + fmt++; + continue; + } + /* fallthru */ + case 2: + if (*fmt == '*') { + pc++; + fmt++; + continue; + } + if (*fmt == 'l') { + pc++; + fmt++; + continue; + } + /* fallthru */ + case 3: + bump("pc"); + pc = 0; + fmt++; + continue; + } + + switch (*fmt) { + + case '<': + swallow = 1; + /* fallthru */ + case '[': + case '(': + case '{': + if (sp == sizeof(stack)) + return -2; + + bump("d"); + sp++; + stack[sp] = *fmt; + count[sp] = 0; + break; + case ' ': + break; + case ',': + //count[sp]++; + break; + case ':': + if (stack[sp] != '{') + goto mismatch; + //count[sp]++; + break; + case '%': + pc = 1; + break; + case ']': + if (stack[sp] != '[') + goto mismatch; + goto pop; + case ')': + if (stack[sp] != '(') + goto mismatch; + goto pop; + case '}': + if (stack[sp] != '{') + goto mismatch; + goto pop; + case '>': + if (stack[sp] != '<') + goto mismatch; +pop: + if (sp) { + sp--; + break; + } + + if (stack[0] == '{') { + /* args have to come in pairs */ + if (count[0] & 1) { + lwsl_err("%s: odd map args %d %s\n", + __func__, count[0], fmt); + return -2; + } + // lwsl_notice("%s: return %d pairs\n", __func__, count[0] >> 1); + /* report how many pairs */ + return count[0] >> 1; + } + + // lwsl_notice("%s: return %d items\n", __func__, count[0]); + + return count[0]; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + numeric = 1; + + break; + + default: + bump("e"); + break; + } + fmt++; + } + + return -1; + +mismatch: + lwsl_err("%s: format mismatch %c %c\n", __func__, stack[sp], *fmt); + + return -2; +} + +void +lws_lec_signed(lws_lec_pctx_t *ctx, int64_t num) +{ + if (num < 0) + lws_lec_int(ctx, LWS_CBOR_MAJTYP_INT_NEG, 0, + (uint64_t)(-1ll - num)); + else + lws_lec_int(ctx, LWS_CBOR_MAJTYP_UINT, 0, (uint64_t)num); +} + +void +lws_lec_int(lws_lec_pctx_t *ctx, uint8_t opcode, uint8_t indet, uint64_t num) +{ + uint8_t hint = 0; + unsigned int n; + + if (indet) { + ctx->scratch[ctx->scratch_len++] = (uint8_t)(opcode | + LWS_CBOR_INDETERMINITE); + return; + } + + if ((opcode & LWS_CBOR_MAJTYP_MASK) == LWS_CBOR_MAJTYP_FLOAT) { + hint = opcode & LWS_CBOR_SUBMASK; + switch (hint) { + case LWS_CBOR_M7_SUBTYP_FLOAT16: + num <<= 48; + break; + case LWS_CBOR_M7_SUBTYP_FLOAT32: + num <<= 32; + break; + } + } else { + + if (num < LWS_CBOR_1) { + ctx->scratch[ctx->scratch_len++] = (uint8_t)(opcode | num); + return; + } + + if (!(num & (uint64_t)(~0xffull))) { + hint = LWS_CBOR_1; + num <<= 56; + } else + if (!(num & (uint64_t)(~0xffffull))) { + hint = LWS_CBOR_2; + num <<= 48; + } else + if (!(num & (uint64_t)(~0xffffffffull))) { + hint = LWS_CBOR_4; + num <<= 32; + } + else + hint = LWS_CBOR_8; + } + + ctx->scratch[ctx->scratch_len++] = (uint8_t)(opcode | hint); + n = 1u << (hint - LWS_CBOR_1); + while (n--) { + ctx->scratch[ctx->scratch_len++] = (uint8_t)(num >> 56); + num <<= 8; + } +} + +enum { + NATTYPE_INT, + NATTYPE_LONG, + NATTYPE_LONG_LONG, + NATTYPE_PTR, + NATTYPE_DOUBLE, +}; + +int +lws_lec_scratch(lws_lec_pctx_t *ctx) +{ + size_t s; + + if (!ctx->scratch_len) + return 0; + + s = lws_ptr_diff_size_t(ctx->end, ctx->buf); + if (s > (size_t)ctx->scratch_len) + s = (size_t)ctx->scratch_len; + + memcpy(ctx->buf, ctx->scratch, s); + ctx->buf += s; + ctx->scratch_len = (uint8_t)(ctx->scratch_len - (uint8_t)s); + + return ctx->buf == ctx->end; +} + +enum lws_lec_pctx_ret +lws_lec_vsprintf(lws_lec_pctx_t *ctx, const char *fmt, va_list args) +{ + size_t fl = strlen(fmt); + uint64_t u64; + int64_t i64; +#if defined(LWS_WITH_CBOR_FLOAT) + double dbl; +#endif + size_t s; + char c; + int n; + + /* + * We might be being called after the first time, since we had to emit + * output buffer(s) before we could move on in the format string. For + * this case, reposition ourselves at the vaarg we got to from the last + * call. + */ + + for (n = 0; n < ctx->vaa_pos; n++) { + + switch (ctx->vaa[n]) { + case NATTYPE_INT: + (void)va_arg(args, int); + break; + case NATTYPE_LONG: + (void)va_arg(args, long); + break; + case NATTYPE_LONG_LONG: + (void)va_arg(args, long long); + break; + case NATTYPE_PTR: + (void)va_arg(args, const char *); + break; + case NATTYPE_DOUBLE: + (void)va_arg(args, double); + break; + } + if (ctx->state == CBPS_STRING_BODY) + /* + * when copying out text or binary strings, we reload + * the %s or %.*s pointer on subsequent calls, in case + * it was on the stack. The length and contents should + * not change between calls, but it's OK if the source + * address does. + */ + ctx->ongoing_src = va_arg(args, uint8_t *); + } + + while (ctx->buf != ctx->end) { + + /* + * We write small things into the context scratch array, then + * copy that into the output buffer fragmenting as needed. Next + * time we will finish emptying the scratch into the output + * buffer preferentially. + * + * Then we don't otherwise have to handle fragmentations in + * order to exactly fill the output buffer, simplifying + * everything else. + */ + + if (lws_lec_scratch(ctx)) + break; + + if (ctx->fmt_pos >= fl) { + if (ctx->state == CBPS_IDLE) + break; + c = 0; + } else + c = fmt[ctx->fmt_pos]; + + // lwsl_notice("%s: %d %d %c\n", __func__, ctx->state, ctx->sp, c); + + switch (ctx->state) { + case CBPS_IDLE: + ctx->scratch_len = 0; + switch (c) { + case '[': + n = format_scan(&fmt[ctx->fmt_pos]); + if (n == -2) + return LWS_LECPCTX_RET_FAIL; + lws_lec_int(ctx, LWS_CBOR_MAJTYP_ARRAY, n == -1, + (uint64_t)n); + goto stack_push; + case '{': + n = format_scan(&fmt[ctx->fmt_pos]); + if (n == -2) + return LWS_LECPCTX_RET_FAIL; + lws_lec_int(ctx, LWS_CBOR_MAJTYP_MAP, n == -1, + (uint64_t)n); + goto stack_push; + case '(': + /* must be preceded by a number */ + goto fail; + + case '<': /* state = CBPS_CONTYPE; + break; + + case ']': + if (!ctx->sp || ctx->stack[ctx->sp - 1] != '[') + return LWS_LECPCTX_RET_FAIL; + ctx->sp--; + break; + case '}': + if (!ctx->sp || ctx->stack[ctx->sp - 1] != '{') + return LWS_LECPCTX_RET_FAIL; + ctx->sp--; + break; + case ')': + if (!ctx->sp || ctx->stack[ctx->sp - 1] != '(') { + lwsl_notice("bad tag end %d %c\n", + ctx->sp, ctx->stack[ctx->sp - 1]); + goto fail; + } + ctx->sp--; + break; + case '>': + if (!ctx->sp || ctx->stack[ctx->sp - 1] != '<') + return LWS_LECPCTX_RET_FAIL; + ctx->scratch[ctx->scratch_len++] = + (uint8_t)(LWS_CBOR_MAJTYP_FLOAT | + LWS_CBOR_M7_BREAK); + ctx->sp--; + break; + case '\'': + n = format_scan(&fmt[ctx->fmt_pos]); + // lwsl_notice("%s: quote fs %d\n", __func__, n); + if (n < 0) + return LWS_LECPCTX_RET_FAIL; + lws_lec_int(ctx, LWS_CBOR_MAJTYP_TSTR, 0, + (uint64_t)n); + ctx->state = CBPS_STRING_LIT; + break; + case '%': + if (ctx->vaa_pos >= sizeof(ctx->vaa) - 1) { + lwsl_err("%s: too many %%\n", __func__); + goto fail; + } + ctx->_long = 0; + ctx->dotstar = 0; + ctx->state = CBPS_PC1; + break; + case ':': + break; + case ',': + break; + case '-': + ctx->item.opcode = LWS_CBOR_MAJTYP_INT_NEG; + ctx->item.u.i64 = 0; + ctx->state = CBPS_NUM_LIT; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + ctx->item.opcode = LWS_CBOR_MAJTYP_UINT; + ctx->item.u.u64 = (uint64_t)(c - '0'); + ctx->state = CBPS_NUM_LIT; + break; + } + break; + case CBPS_PC1: + if (c == 'l') { + ctx->_long++; + ctx->state = CBPS_PC2; + break; + } + if (c == '.') { + ctx->dotstar++; + ctx->state = CBPS_PC2; + break; + } + /* fallthru */ + + case CBPS_PC2: + if (c == 'l') { + ctx->_long++; + ctx->state = CBPS_PC3; + break; + } + if (c == '*') { + ctx->dotstar++; + ctx->state = CBPS_PC3; + break; + } + /* fallthru */ + + case CBPS_PC3: + switch (c) { + case 'd': + switch (ctx->_long) { + case 0: + i64 = (int64_t)va_arg(args, int); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT; + break; + case 1: + i64 = (int64_t)va_arg(args, long); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG; + break; + case 2: + i64 = (int64_t)va_arg(args, long long); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG_LONG; + break; + } + if (i64 < 0) + lws_lec_int(ctx, + LWS_CBOR_MAJTYP_INT_NEG, 0, + (uint64_t)(-1ll - i64)); + else + lws_lec_int(ctx, + LWS_CBOR_MAJTYP_UINT, 0, + (uint64_t)i64); + break; + case 'u': + switch (ctx->_long) { + case 0: + u64 = (uint64_t)va_arg(args, unsigned int); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT; + break; + case 1: + u64 = (uint64_t)va_arg(args, unsigned long); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG; + break; + case 2: + u64 = (uint64_t)va_arg(args, unsigned long long); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG_LONG; + break; + } + lws_lec_int(ctx, LWS_CBOR_MAJTYP_UINT, 0, u64); + break; + case 's': /* text string */ + ctx->ongoing_done = 0; + if (ctx->dotstar == 2) { + ctx->ongoing_len = (uint64_t)va_arg(args, int); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT; + } + /* vaa for ptr done at end of body copy */ + ctx->ongoing_src = va_arg(args, uint8_t *); + if (ctx->dotstar != 2) + ctx->ongoing_len = (uint64_t)strlen( + (const char *)ctx->ongoing_src); + lws_lec_int(ctx, LWS_CBOR_MAJTYP_TSTR, 0, ctx->ongoing_len); + ctx->state = CBPS_STRING_BODY; + ctx->fmt_pos++; + continue; + case 'b': /* binary string (%.*b only) */ + if (ctx->dotstar != 2) + goto fail; + ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT; + ctx->ongoing_done = 0; + ctx->ongoing_len = (uint64_t)va_arg(args, int); + /* vaa for ptr done at end of body copy */ + ctx->ongoing_src = va_arg(args, uint8_t *); + lws_lec_int(ctx, LWS_CBOR_MAJTYP_BSTR, 0, ctx->ongoing_len); + ctx->state = CBPS_STRING_BODY; + ctx->fmt_pos++; + continue; + case 't': /* dynamic tag */ + switch (ctx->_long) { + case 0: + ctx->item.u.u64 = (uint64_t)va_arg(args, int); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_INT; + break; + case 1: + ctx->item.u.u64 = (uint64_t)va_arg(args, long); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG; + break; + case 2: + ctx->item.u.u64 = (uint64_t)va_arg(args, long long); + ctx->vaa[ctx->vaa_pos++] = NATTYPE_LONG_LONG; + break; + } + ctx->item.opcode = LWS_CBOR_MAJTYP_UINT; + ctx->fmt_pos++; + if (ctx->fmt_pos >= fl) + continue; + c = fmt[ctx->fmt_pos]; + if (c != '(') + goto fail; + goto tag_body; +#if defined(LWS_WITH_CBOR_FLOAT) + case 'f': /* floating point double */ + dbl = va_arg(args, double); + + if (dbl == (float)dbl) { + uint16_t hf; + union { + uint32_t ui; + float f; + } u1, u2; + + u1.f = (float)dbl; + lws_singles2halfp(&hf, u1.ui); + lws_halfp2singles(&u2.ui, hf); + + if ((isinf(u1.f) && isinf(u2.f)) || + (isnan(u1.f) && isnan(u2.f)) || + u1.f == u2.f) { + lws_lec_int(ctx, + LWS_CBOR_MAJTYP_FLOAT | + LWS_CBOR_M7_SUBTYP_FLOAT16, + 0, hf); + break; + } + /* do it as 32-bit float */ + lws_lec_int(ctx, + LWS_CBOR_MAJTYP_FLOAT | + LWS_CBOR_M7_SUBTYP_FLOAT32, + 0, u1.ui); + break; + } + + /* do it as 64-bit double */ + + { + union { + uint64_t ui; + double f; + } u3; + + u3.f = dbl; + lws_lec_int(ctx, + LWS_CBOR_MAJTYP_FLOAT | + LWS_CBOR_M7_SUBTYP_FLOAT64, + 0, u3.ui); + } + break; +#else + case 'f': + lwsl_err("%s: no FP support\n", __func__); + goto fail; +#endif + } + ctx->state = CBPS_IDLE; + break; + + case CBPS_STRING_BODY: + s = lws_ptr_diff_size_t(ctx->end, ctx->buf); + if (s > (size_t)(ctx->ongoing_len - ctx->ongoing_done)) + s = (size_t)(ctx->ongoing_len - ctx->ongoing_done); + memcpy(ctx->buf, ctx->ongoing_src + ctx->ongoing_done, s); + ctx->buf += s; + ctx->ongoing_done += s; + if (ctx->ongoing_len == ctx->ongoing_done) { + /* vaa for ptr */ + ctx->vaa[ctx->vaa_pos++] = NATTYPE_PTR; + ctx->state = CBPS_IDLE; + } + continue; + + case CBPS_NUM_LIT: + if (c >= '0' && c <= '9') { + ctx->item.u.u64 = (ctx->item.u.u64 * 10) + + (uint64_t)(c - '0'); + break; + } + + if (ctx->item.opcode == LWS_CBOR_MAJTYP_INT_NEG) + ctx->item.u.i64--; + + if (c == '(') { /* tag qualifier */ +tag_body: + n = format_scan(&fmt[ctx->fmt_pos]); + if (n == -2) + goto fail; + /* + * inteterminite length not possible for tag, + * take it to mean that the closure is in a + * later format string + */ + + lws_lec_int(ctx, LWS_CBOR_MAJTYP_TAG, 0, + ctx->item.u.u64); + +stack_push: + if (ctx->sp >= sizeof(ctx->stack)) + return LWS_LECPCTX_RET_FAIL; + ctx->stack[ctx->sp] = (uint8_t)c; + ctx->indet[ctx->sp++] = (uint8_t)(n == -1); + // lwsl_notice("%s: pushed %c\n", __func__, c); + ctx->state = CBPS_IDLE; + break; + } + + lws_lec_int(ctx, ctx->item.opcode, 0, ctx->item.u.u64); + + ctx->state = CBPS_IDLE; + /* deal with the terminating char fresh */ + continue; + + case CBPS_STRING_LIT: + if (!ctx->escflag && c == '\\') { + ctx->escflag = 1; + break; + } + if (!ctx->escflag && c == '\'') { + ctx->state = CBPS_IDLE; + break; + } + + *ctx->buf++ = (uint8_t)c; + ctx->escflag = 0; + + break; + + case CBPS_CONTYPE: + if (c != 't' && c != 'b') + return LWS_LECPCTX_RET_FAIL; + + lws_lec_int(ctx, c == 't' ? LWS_CBOR_MAJTYP_TSTR : + LWS_CBOR_MAJTYP_BSTR, 1, 0); + c = '<'; + n = 0; + goto stack_push; + } + + ctx->fmt_pos++; + } + + ctx->used = lws_ptr_diff_size_t(ctx->buf, ctx->start); + // lwsl_notice("%s: ctx->used %d\n", __func__, (int)ctx->used); + + if (ctx->buf == ctx->end || ctx->scratch_len) + return LWS_LECPCTX_RET_AGAIN; + + ctx->fmt_pos = 0; + ctx->vaa_pos = 0; + + return LWS_LECPCTX_RET_FINISHED; + +fail: + lwsl_notice("%s: failed\n", __func__); + + ctx->fmt_pos = 0; + + return LWS_LECPCTX_RET_FAIL; +} diff --git a/3rdparty/libwebsockets/lib/misc/lejp.c b/3rdparty/libwebsockets/lib/misc/lejp.c index ee84734f..b898c6f9 100644 --- a/3rdparty/libwebsockets/lib/misc/lejp.c +++ b/3rdparty/libwebsockets/lib/misc/lejp.c @@ -107,7 +107,7 @@ void lejp_destruct(struct lejp_ctx *ctx) { /* no allocations... just let callback know what it happening */ - if (ctx->pst[0].callback) + if (ctx && ctx->pst[0].callback) ctx->pst[0].callback(ctx, LEJPCB_DESTRUCTED); } @@ -160,7 +160,7 @@ lejp_check_path_match(struct lejp_ctx *ctx) p = ctx->path; q = *((char **)(((char *)ctx->pst[ctx->pst_sp].paths) + ((unsigned int)n * s))); - +//lwsl_notice("%s: %s %s\n", __func__, p, q); while (*p && *q) { if (*q != '*') { if (*p != *q) @@ -468,6 +468,9 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) /* push */ ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END; c = LEJP_MP_VALUE; + if (ctx->pst[ctx->pst_sp].ppos + 3u >= + sizeof(ctx->path)) + goto reject; 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'; @@ -881,3 +884,4 @@ lejp_error_to_string(int e) return parser_errs[e]; } + diff --git a/3rdparty/libwebsockets/lib/misc/lws-struct-lejp.c b/3rdparty/libwebsockets/lib/misc/lws-struct-lejp.c index 081b0cef..efb81c89 100644 --- a/3rdparty/libwebsockets/lib/misc/lws-struct-lejp.c +++ b/3rdparty/libwebsockets/lib/misc/lws-struct-lejp.c @@ -270,12 +270,20 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) lwsl_info("%s: created '%s' object size %d\n", __func__, pmap->colname, (int)pmap->aux); - if (pmap->type == LSMT_LIST) { + switch (pmap->type) { + case LSMT_LIST: list = (struct lws_dll2 *) ((char *)ctx->pst[ctx->pst_sp].user + pmap->ofs_clist); lws_dll2_add_tail(list, owner); + break; + case LSMT_CHILD_PTR: + *((void **)owner) = ctx->pst[ctx->pst_sp].user; + break; + default: + assert(0); + break; } } diff --git a/3rdparty/libwebsockets/lib/misc/threadpool/threadpool.c b/3rdparty/libwebsockets/lib/misc/threadpool/threadpool.c index dd310b82..40df5ba4 100644 --- a/3rdparty/libwebsockets/lib/misc/threadpool/threadpool.c +++ b/3rdparty/libwebsockets/lib/misc/threadpool/threadpool.c @@ -426,13 +426,13 @@ lws_threadpool_worker_sync(struct lws_pool *pool, } /* - * So tries times this is the maximum time between SYNC asking + * So "tries" times this is the maximum time between SYNC asking * for a callback on writable and actually getting it we are * willing to sit still for. * * If it is exceeded, we will stop the task. */ - abstime.tv_sec = time(NULL) + 2; + abstime.tv_sec = time(NULL) + 3; abstime.tv_nsec = 0; task->wanted_writeable_cb = 1; @@ -462,8 +462,9 @@ lws_threadpool_worker_sync(struct lws_pool *pool, __func__, pool->tp->name, task, task->name, lws_wsi_tag(task_to_wsi(task))); - state_transition(task, LWS_TP_STATUS_STOPPING); - goto done; + pthread_mutex_unlock(&pool->lock); /* ----------------- - pool unlock */ + lws_threadpool_dequeue_task(task); + return 1; /* destroyed task */ } continue; @@ -605,7 +606,10 @@ lws_threadpool_worker(void *d) } /* block until writable acknowledges */ then = lws_now_usecs(); - lws_threadpool_worker_sync(pool, task); + if (lws_threadpool_worker_sync(pool, task)) { + lwsl_notice("%s: Sync failed\n", __func__); + goto doneski; + } us_accrue(&task->acc_syncing, then); break; case LWS_TP_RETURN_FINISHED: @@ -1162,6 +1166,22 @@ lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user, } #endif +static int +disassociate_wsi(struct lws_threadpool_task *task, + void *user) +{ + task->args.wsi = NULL; + lws_dll2_remove(&task->list); + + return 0; +} + +void +lws_threadpool_wsi_closing(struct lws *wsi) +{ + lws_threadpool_foreach_task_wsi(wsi, NULL, disassociate_wsi); +} + struct lws_threadpool_task * lws_threadpool_get_task_wsi(struct lws *wsi) { diff --git a/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c b/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c index 729fa216..c9300e07 100644 --- a/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c +++ b/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c @@ -309,7 +309,7 @@ _event_handler_wifi(void *arg, esp_event_base_t event_base, int32_t event_id, lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, "{\"type\":\"priv\",\"if\":\"%s\",\"ev\":%d}", - wnd->inst.name, event_id); + wnd->inst.name, (int)event_id); break; default: return; diff --git a/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/pwm-esp32.c b/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/pwm-esp32.c index a13e10b3..1950f2d1 100644 --- a/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/pwm-esp32.c +++ b/3rdparty/libwebsockets/lib/plat/freertos/esp32/drivers/pwm-esp32.c @@ -26,8 +26,10 @@ #include "soc/ledc_reg.h" #include "driver/ledc.h" +#define _LEDC_HIGH_SPEED_MODE 0 + static const ledc_timer_config_t tc = { - .speed_mode = LEDC_HIGH_SPEED_MODE, + .speed_mode = _LEDC_HIGH_SPEED_MODE, .duty_resolution = LEDC_TIMER_13_BIT, .timer_num = LEDC_TIMER_0, .freq_hz = 5000, @@ -40,7 +42,7 @@ 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, + .speed_mode = _LEDC_HIGH_SPEED_MODE, .timer_sel = LEDC_TIMER_0, }; size_t n; @@ -51,8 +53,8 @@ lws_pwm_plat_init(const struct lws_pwm_ops *lo) 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); + ledc_set_duty(_LEDC_HIGH_SPEED_MODE, lc.channel, 0); + ledc_update_duty(_LEDC_HIGH_SPEED_MODE, lc.channel); } return 0; @@ -68,9 +70,9 @@ lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, 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 + + 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 + + ledc_update_duty(_LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + lo->pwm_map[n].index); return; } diff --git a/3rdparty/libwebsockets/lib/plat/freertos/freertos-service.c b/3rdparty/libwebsockets/lib/plat/freertos/freertos-service.c index 1bea562a..795e3828 100644 --- a/3rdparty/libwebsockets/lib/plat/freertos/freertos-service.c +++ b/3rdparty/libwebsockets/lib/plat/freertos/freertos-service.c @@ -40,6 +40,7 @@ lws_plat_service(struct lws_context *context, int timeout_ms) int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { + volatile struct lws_context_per_thread *vpt; struct lws_context_per_thread *pt; lws_usec_t timeout_us; int n = -1, m, c, a = 0; @@ -50,6 +51,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) return 1; pt = &context->pt[tsi]; + vpt = (volatile struct lws_context_per_thread *)pt; { unsigned long m = lws_now_secs(); @@ -99,9 +101,15 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* * is there anybody with pending stuff that needs service forcing? */ +#if !defined(LWS_AMAZON_RTOS) +again: +#endif + n = 0; if (lws_service_adjust_timeout(context, 1, tsi)) { - +#if defined(LWS_AMAZON_RTOS) again: +#endif /* LWS_AMAZON_RTOS */ + a = 0; if (timeout_us) { lws_usec_t us; @@ -138,7 +146,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) FD_SET(pt->fds[n].fd, &errfds); } + vpt->inside_poll = 1; + lws_memory_barrier(); n = select(max_fd + 1, &readfds, &writefds, &errfds, ptv); + vpt->inside_poll = 0; + lws_memory_barrier(); n = 0; for (m = 0; m < (int)pt->fds_count; m++) { @@ -179,15 +191,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) a = 1; m = lws_service_flag_pending(context, tsi); - if (m) - c = -1; /* unknown limit */ - else - if (n < 0) { - if (LWS_ERRNO != LWS_EINTR) - return -1; - return 0; - } else - c = n; + c = m ? -1 : n; /* any socket with events to service? */ for (n = 0; n < (int)pt->fds_count && c; n++) { diff --git a/3rdparty/libwebsockets/lib/plat/freertos/private-lib-plat-freertos.h b/3rdparty/libwebsockets/lib/plat/freertos/private-lib-plat-freertos.h index 48f11372..67b83997 100644 --- a/3rdparty/libwebsockets/lib/plat/freertos/private-lib-plat-freertos.h +++ b/3rdparty/libwebsockets/lib/plat/freertos/private-lib-plat-freertos.h @@ -59,11 +59,15 @@ gai_strerror(int); #include "FreeRTOS_IP.h" #endif #include "timers.h" +#if defined(LWS_ESP_PLATFORM) #include +#endif #include #else #include "freertos/timers.h" +#if defined(LWS_ESP_PLATFORM) #include +#endif #include #include #endif @@ -76,7 +80,7 @@ gai_strerror(int); 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_lock(x) (!xSemaphoreTake(x, portMAX_DELAY)) /*0 = OK */ #define lws_mutex_unlock(x) xSemaphoreGive(x) #include @@ -94,6 +98,7 @@ typedef SemaphoreHandle_t lws_mutex_t; #define LWS_ENOTCONN ENOTCONN #define LWS_EWOULDBLOCK EWOULDBLOCK #define LWS_EADDRINUSE EADDRINUSE + #define LWS_ECONNABORTED ECONNABORTED #define lws_set_blocking_send(wsi) diff --git a/3rdparty/libwebsockets/lib/plat/unix/CMakeLists.txt b/3rdparty/libwebsockets/lib/plat/unix/CMakeLists.txt index 59558c4f..b27bbb67 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/plat/unix/CMakeLists.txt @@ -78,7 +78,7 @@ if (HAIKU) list(APPEND LIB_LIST_AT_END network) endif() -IF (CMAKE_SYSTEM_NAME STREQUAL Linux) +IF (CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT LWS_WITHOUT_EVENTFD) CHECK_FUNCTION_EXISTS(eventfd_read LWS_HAVE_EVENTFD) endif() diff --git a/3rdparty/libwebsockets/lib/plat/unix/android/android-resolv.c b/3rdparty/libwebsockets/lib/plat/unix/android/android-resolv.c index d28fb9cc..3ae38d5c 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/android/android-resolv.c +++ b/3rdparty/libwebsockets/lib/plat/unix/android/android-resolv.c @@ -38,13 +38,13 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) return LADNS_CONF_SERVER_UNKNOWN; for (n = 0; n < 4; n++) { - i[n] = atoi(d); + i[n] = (uint8_t)atoi(d); p = strchr(d, '.'); if (n != 3 && !p) return LADNS_CONF_SERVER_UNKNOWN; } - ip32 = (i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3]; + ip32 = (uint32_t) ((i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3]); n = ip32 == sa46->sa4.sin_addr.s_addr; sa46->sa4.sin_family = AF_INET; sa46->sa4.sin_addr.s_addr = ip32; diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-caps.c b/3rdparty/libwebsockets/lib/plat/unix/unix-caps.c index 054e3d13..2f38854d 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-caps.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-caps.c @@ -125,11 +125,11 @@ lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop) g = getgrnam(context->groupname); if (g) { #endif - lwsl_info("%s: group %s -> gid %u\n", __func__, + lwsl_cx_info(context, "group %s -> gid %u", context->groupname, g->gr_gid); context->gid = g->gr_gid; } else { - lwsl_err("%s: unknown groupname '%s'\n", __func__, + lwsl_cx_err(context, "unknown groupname '%s'", context->groupname); return 1; @@ -150,10 +150,10 @@ lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop) #endif context->uid = p->pw_uid; - lwsl_info("%s: username %s -> uid %u\n", __func__, + lwsl_cx_info(context, "username %s -> uid %u", context->username, (unsigned int)p->pw_uid); } else { - lwsl_err("%s: unknown username %s\n", __func__, + lwsl_cx_err(context, "unknown username %s", context->username); return 1; @@ -175,23 +175,22 @@ lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop) g = getgrgid(context->gid); if (!g) { #endif - lwsl_err("%s: cannot find name for gid %d\n", - __func__, context->gid); + lwsl_cx_err(context, "cannot find name for gid %d", + context->gid); return 1; } if (setgid(context->gid)) { - lwsl_err("%s: setgid: %s failed\n", __func__, - strerror(LWS_ERRNO)); + lwsl_cx_err(context, "setgid: %s failed", + strerror(LWS_ERRNO)); return 1; } - lwsl_notice("%s: effective group '%s'\n", __func__, - g->gr_name); + lwsl_cx_notice(context, "effective group '%s'", g->gr_name); } else - lwsl_info("%s: not changing group\n", __func__); + lwsl_cx_info(context, "not changing group"); /* if he gave us the uid or we have it from the username, set it */ @@ -206,8 +205,8 @@ lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop) p = getpwuid(context->uid); if (!p) { #endif - lwsl_err("%s: getpwuid: unable to find uid %d\n", - __func__, context->uid); + lwsl_cx_err(context, "getpwuid: unable to find uid %d", + context->uid); return 1; } @@ -224,13 +223,13 @@ lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop) return 1; if (setuid(context->uid)) { - lwsl_err("%s: setuid: %s failed\n", __func__, - strerror(LWS_ERRNO)); + lwsl_cx_err(context, "setuid: %s failed", + strerror(LWS_ERRNO)); return 1; } else - lwsl_notice("%s: effective user '%s'\n", - __func__, p->pw_name); + lwsl_cx_notice(context, "effective user '%s'", + p->pw_name); #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) _lws_plat_apply_caps(CAP_EFFECTIVE, context->caps, @@ -239,12 +238,12 @@ lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop) if (context->count_caps) { int n; for (n = 0; n < context->count_caps; n++) - lwsl_notice(" RETAINING CAP %d\n", + lwsl_cx_notice(context, " RETAINING CAP %d", (int)context->caps[n]); } #endif } else - lwsl_info("%s: not changing user\n", __func__); + lwsl_cx_info(context, "not changing user"); return 0; } diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-fds.c b/3rdparty/libwebsockets/lib/plat/unix/unix-fds.c index ec457664..d6cd64d2 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-fds.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-fds.c @@ -192,9 +192,7 @@ delete_from_fd(const struct lws_context *context, int fd) while (p != done && (!*p || (*p)->desc.sockfd != fd)) p++; - if (p == done) - lwsl_debug("%s: fd %d not found\n", __func__, fd); - else + if (p != done) *p = NULL; #if defined(_DEBUG) diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-file.c b/3rdparty/libwebsockets/lib/plat/unix/unix-file.c index c71c0d1e..81cbb222 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-file.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-file.c @@ -155,11 +155,11 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, *amount = 0; return -1; } - fop_fd->pos += (size_t)n; + fop_fd->pos = (lws_filepos_t)(fop_fd->pos + (lws_filepos_t)n); lwsl_debug("%s: read %ld of req %ld, pos %ld, len %ld\n", __func__, (long)n, (long)len, (long)fop_fd->pos, (long)fop_fd->len); - *amount = (size_t)n; + *amount = (lws_filepos_t)n; return 0; } @@ -176,8 +176,8 @@ _lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, return -1; } - fop_fd->pos += (size_t)n; - *amount = (size_t)n; + fop_fd->pos = (lws_filepos_t)(fop_fd->pos + (lws_filepos_t)n); + *amount = (lws_filepos_t)n; return 0; } diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-init.c b/3rdparty/libwebsockets/lib/plat/unix/unix-init.c index 64cec8a5..46f072f9 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-init.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-init.c @@ -131,12 +131,39 @@ lws_plat_init(struct lws_context *context, context->max_fds, "lws_lookup"); if (!context->lws_lookup) { - lwsl_err("%s: OOM on alloc lws_lookup array for %d conn\n", - __func__, context->max_fds); + lwsl_cx_err(context, "OOM on alloc lws_lookup array for %d conn", + context->max_fds); return 1; } - lwsl_info(" mem: platform fd map: %5lu B\n", +#if defined(LWS_WITH_MBEDTLS) + { + int n; + + /* initialize platform random through mbedtls */ + mbedtls_entropy_init(&context->mec); + mbedtls_ctr_drbg_init(&context->mcdc); + + n = mbedtls_ctr_drbg_seed(&context->mcdc, mbedtls_entropy_func, + &context->mec, NULL, 0); + if (n) + lwsl_err("%s: mbedtls_ctr_drbg_seed() returned 0x%x\n", + __func__, n); +#if 0 + else { + uint8_t rtest[16]; + lwsl_notice("%s: started drbg\n", __func__); + if (mbedtls_ctr_drbg_random(&context->mcdc, rtest, + sizeof(rtest))) + lwsl_err("%s: get random failed\n", __func__); + else + lwsl_hexdump_notice(rtest, sizeof(rtest)); + } +#endif + } +#endif + + lwsl_cx_info(context, " mem: platform fd map: %5lu B", (unsigned long)(sizeof(struct lws *) * context->max_fds)); #endif #if defined(LWS_WITH_FILE_OPS) diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-misc.c b/3rdparty/libwebsockets/lib/plat/unix/unix-misc.c index 8dcaaa94..fce5e429 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-misc.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-misc.c @@ -127,9 +127,12 @@ lws_plat_ntpclient_config(struct lws_context *context) 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, + lws_system_blob_t *blob = lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0); + if (!blob) + return 0; + + lws_system_blob_direct_set(blob, (const uint8_t *)ntpsrv, strlen(ntpsrv)); return 1; } diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-pipe.c b/3rdparty/libwebsockets/lib/plat/unix/unix-pipe.c index b4470975..ad04acbb 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-pipe.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-pipe.c @@ -31,18 +31,34 @@ int lws_plat_pipe_create(struct lws *wsi) { struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + int n; #if defined(LWS_HAVE_EVENTFD) 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; + n = pt->dummy_pipe_fds[0] < 0 ? -1 : 0; + goto set; #elif defined(LWS_HAVE_PIPE2) - return pipe2(pt->dummy_pipe_fds, O_NONBLOCK); + n = pipe2(pt->dummy_pipe_fds, O_NONBLOCK); #else - return pipe(pt->dummy_pipe_fds); + n = pipe(pt->dummy_pipe_fds); #endif + +#if defined(LWS_HAVE_EVENTFD) +set: +#endif + if (n >= 0) { + if (fcntl(pt->dummy_pipe_fds[0], F_SETFL, O_NONBLOCK) < 0) + n = -1; + else if (pt->dummy_pipe_fds[1] >= 0) { + if (fcntl(pt->dummy_pipe_fds[1], F_SETFL, O_NONBLOCK) < 0) + n = -1; + } + } + + return n; } int diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-sockets.c b/3rdparty/libwebsockets/lib/plat/unix/unix-sockets.c index f8b5db92..2c1b9569 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-sockets.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-sockets.c @@ -216,23 +216,35 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) { int optval = (int)pri, ret = 0, n; socklen_t optlen = sizeof(optval); -#if !defined(LWS_WITH_NO_LOGS) +#if (_LWS_ENABLED_LOGS & LLL_WARN) int en; #endif +#if 0 +#if defined(TCP_FASTOPEN_CONNECT) + optval = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, (void *)&optval, + sizeof(optval))) + lwsl_warn("%s: FASTOPEN_CONNECT failed\n", __func__); + optval = (int)pri; +#endif +#endif + #if !defined(__APPLE__) && \ !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && \ !defined(__NetBSD__) && \ !defined(__OpenBSD__) && \ !defined(__sun) && \ - !defined(__HAIKU__) + !defined(__HAIKU__) && \ + !defined(__CYGWIN__) && \ + !defined(__QNX__) /* the BSDs don't have SO_PRIORITY */ if (pri) { /* 0 is the default already */ if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (const void *)&optval, optlen) < 0) { -#if !defined(LWS_WITH_NO_LOGS) +#if (_LWS_ENABLED_LOGS & LLL_WARN) en = errno; lwsl_warn("%s: unable to set socket pri %d: errno %d\n", __func__, (int)pri, en); @@ -266,6 +278,14 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) /* cast a struct sockaddr_in6 * into addr for ipv6 */ +enum { + IP_SCORE_NONE, + IP_SCORE_NONNATIVE, + IP_SCORE_IPV6_SCOPE_BASE, + /* ipv6 scopes */ + IP_SCORE_GLOBAL_NATIVE = 18 +}; + int lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, size_t addrlen) @@ -274,8 +294,11 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, struct ifaddrs *ifr; struct ifaddrs *ifc; -#ifdef LWS_WITH_IPV6 +#if defined(LWS_WITH_IPV6) struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; + unsigned long sco = IP_SCORE_NONE; + unsigned long ts; + const uint8_t *p; #endif if (getifaddrs(&ifr)) { @@ -283,7 +306,7 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, return LWS_ITOSA_USABLE; } - for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) { + for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) { if (!ifc->ifa_addr || !ifc->ifa_name) continue; @@ -298,13 +321,19 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, #if defined(AF_PACKET) case AF_PACKET: /* interface exists but is not usable */ - rc = LWS_ITOSA_NOT_USABLE; + if (rc == LWS_ITOSA_NOT_EXIST) + rc = LWS_ITOSA_NOT_USABLE; continue; #endif case AF_INET: -#ifdef LWS_WITH_IPV6 +#if defined(LWS_WITH_IPV6) if (ipv6) { + /* any existing solution is better than this */ + if (sco != IP_SCORE_NONE) + break; + sco = IP_SCORE_NONNATIVE; + rc = LWS_ITOSA_USABLE; /* map IPv4 to IPv6 */ memset((char *)&addr6->sin6_addr, 0, sizeof(struct in6_addr)); @@ -314,37 +343,44 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr, sizeof(struct in_addr)); lwsl_debug("%s: uplevelling ipv4 bind to ipv6\n", __func__); - } else + break; + } + + sco = IP_SCORE_GLOBAL_NATIVE; #endif - memcpy(addr, - (struct sockaddr_in *)ifc->ifa_addr, + rc = LWS_ITOSA_USABLE; + memcpy(addr, (struct sockaddr_in *)ifc->ifa_addr, sizeof(struct sockaddr_in)); break; -#ifdef LWS_WITH_IPV6 +#if defined(LWS_WITH_IPV6) case AF_INET6: + p = (const uint8_t *) + &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr; + ts = IP_SCORE_IPV6_SCOPE_BASE; + if (p[0] == 0xff) + ts = (unsigned long)(IP_SCORE_IPV6_SCOPE_BASE + (p[1] & 0xf)); + + if (sco >= ts) + break; + + sco = ts; + rc = LWS_ITOSA_USABLE; + memcpy(&addr6->sin6_addr, - &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, + &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, sizeof(struct in6_addr)); break; #endif default: - continue; + break; } - rc = LWS_ITOSA_USABLE; } freeifaddrs(ifr); - if (rc) { - /* check if bind to IP address */ -#ifdef LWS_WITH_IPV6 - if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) - rc = LWS_ITOSA_USABLE; - else -#endif - if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1) - rc = LWS_ITOSA_USABLE; - } + if (rc && + !lws_sa46_parse_numeric_address(ifname, (lws_sockaddr46 *)addr)) + rc = LWS_ITOSA_USABLE; return rc; } @@ -553,7 +589,7 @@ lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) int lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) { - int fd = ((mbedtls_net_context *) ctx)->fd; + int fd = ((mbedtls_net_context *) ctx)->MBEDTLS_PRIVATE_V30_ONLY(fd); int ret; if (fd < 0) @@ -578,7 +614,7 @@ 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) { - int fd = ((mbedtls_net_context *) ctx)->fd; + int fd = ((mbedtls_net_context *) ctx)->MBEDTLS_PRIVATE_V30_ONLY(fd); int ret; if (fd < 0) diff --git a/3rdparty/libwebsockets/lib/plat/unix/unix-spawn.c b/3rdparty/libwebsockets/lib/plat/unix/unix-spawn.c index af831809..1c68d45b 100644 --- a/3rdparty/libwebsockets/lib/plat/unix/unix-spawn.c +++ b/3rdparty/libwebsockets/lib/plat/unix/unix-spawn.c @@ -83,7 +83,7 @@ lws_create_stdwsi(struct lws_context *context, int tsi, } lws_context_lock(context, __func__); - new_wsi = __lws_wsi_create_with_role(context, tsi, ops); + new_wsi = __lws_wsi_create_with_role(context, tsi, ops, NULL); lws_context_unlock(context); if (new_wsi == NULL) { lwsl_err("Out of memory for new connection\n"); @@ -382,8 +382,8 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) goto bail2; } - __lws_lc_tag(&i->vh->context->lcg[LWSLCG_WSI], &lsp->stdwsi[n]->lc, - "nspawn-stdwsi-%d", n); + __lws_lc_tag(i->vh->context, &i->vh->context->lcg[LWSLCG_WSI], + &lsp->stdwsi[n]->lc, "nspawn-stdwsi-%d", n); lsp->stdwsi[n]->lsp_channel = (uint8_t)n; lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]); diff --git a/3rdparty/libwebsockets/lib/plat/windows/private-lib-plat-windows.h b/3rdparty/libwebsockets/lib/plat/windows/private-lib-plat-windows.h index beb5f544..18d87ac2 100644 --- a/3rdparty/libwebsockets/lib/plat/windows/private-lib-plat-windows.h +++ b/3rdparty/libwebsockets/lib/plat/windows/private-lib-plat-windows.h @@ -155,7 +155,11 @@ struct lws_fd_hashtable { #endif typedef SOCKET lws_sockfd_type; +#if defined(__MINGW32__) +typedef int lws_filefd_type; +#else typedef HANDLE lws_filefd_type; +#endif #define LWS_WIN32_HANDLE_TYPES LWS_EXTERN struct lws * diff --git a/3rdparty/libwebsockets/lib/plat/windows/windows-file.c b/3rdparty/libwebsockets/lib/plat/windows/windows-file.c index 5e2625ad..27b0a9cc 100644 --- a/3rdparty/libwebsockets/lib/plat/windows/windows-file.c +++ b/3rdparty/libwebsockets/lib/plat/windows/windows-file.c @@ -50,7 +50,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } - if (ret == LWS_INVALID_FILE) + if (ret == NULL) goto bail; fop_fd = malloc(sizeof(*fop_fd)); @@ -58,8 +58,13 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, goto bail; fop_fd->fops = fops; +#if defined(__MINGW32__) + /* we use filesystem_priv */ + fop_fd->fd = (int)(intptr_t)ret; +#else fop_fd->fd = ret; - fop_fd->filesystem_priv = NULL; /* we don't use it */ +#endif + fop_fd->filesystem_priv = ret; fop_fd->flags = *flags; fop_fd->len = GetFileSize(ret, NULL); if(GetFileSizeEx(ret, &llFileSize)) @@ -76,7 +81,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, int _lws_plat_file_close(lws_fop_fd_t *fop_fd) { - HANDLE fd = (*fop_fd)->fd; + HANDLE fd = (*fop_fd)->filesystem_priv; free(*fop_fd); *fop_fd = NULL; @@ -92,7 +97,23 @@ _lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset) LARGE_INTEGER l; l.QuadPart = offset; - return SetFilePointerEx((HANDLE)fop_fd->fd, l, NULL, FILE_CURRENT); + if (!SetFilePointerEx((HANDLE)fop_fd->filesystem_priv, l, NULL, FILE_CURRENT)) + { + lwsl_err("error seeking from cur %ld, offset %ld\n", (long)fop_fd->pos, (long)offset); + return -1; + } + + LARGE_INTEGER zero; + zero.QuadPart = 0; + LARGE_INTEGER newPos; + if (!SetFilePointerEx((HANDLE)fop_fd->filesystem_priv, zero, &newPos, FILE_CURRENT)) + { + lwsl_err("error seeking from cur %ld, offset %ld\n", (long)fop_fd->pos, (long)offset); + return -1; + } + fop_fd->pos = newPos.QuadPart; + + return newPos.QuadPart; } int @@ -101,7 +122,7 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, { DWORD _amount; - if (!ReadFile((HANDLE)fop_fd->fd, buf, (DWORD)len, &_amount, NULL)) { + if (!ReadFile((HANDLE)fop_fd->filesystem_priv, buf, (DWORD)len, &_amount, NULL)) { *amount = 0; return 1; @@ -119,7 +140,7 @@ _lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, { DWORD _amount; - if (!WriteFile((HANDLE)fop_fd->fd, buf, (DWORD)len, &_amount, NULL)) { + if (!WriteFile((HANDLE)fop_fd->filesystem_priv, buf, (DWORD)len, &_amount, NULL)) { *amount = 0; return 1; diff --git a/3rdparty/libwebsockets/lib/plat/windows/windows-init.c b/3rdparty/libwebsockets/lib/plat/windows/windows-init.c index f60c8bfe..00190c71 100644 --- a/3rdparty/libwebsockets/lib/plat/windows/windows-init.c +++ b/3rdparty/libwebsockets/lib/plat/windows/windows-init.c @@ -77,6 +77,33 @@ lws_plat_init(struct lws_context *context, struct lws_context_per_thread *pt = &context->pt[0]; int i, n = context->count_threads; +#if defined(LWS_WITH_MBEDTLS) + { + int n; + + /* initialize platform random through mbedtls */ + mbedtls_entropy_init(&context->mec); + mbedtls_ctr_drbg_init(&context->mcdc); + + n = mbedtls_ctr_drbg_seed(&context->mcdc, mbedtls_entropy_func, + &context->mec, NULL, 0); + if (n) + lwsl_err("%s: mbedtls_ctr_drbg_seed() returned 0x%x\n", + __func__, n); +#if 0 + else { + uint8_t rtest[16]; + lwsl_notice("%s: started drbg\n", __func__); + if (mbedtls_ctr_drbg_random(&context->mcdc, rtest, + sizeof(rtest))) + lwsl_err("%s: get random failed\n", __func__); + else + lwsl_hexdump_notice(rtest, sizeof(rtest)); + } +#endif + } +#endif + for (i = 0; i < FD_HASHTABLE_MODULUS; i++) { context->fd_hashtable[i].wsi = lws_zalloc(sizeof(struct lws*) * context->max_fds, @@ -117,7 +144,7 @@ lws_plat_context_late_destroy(struct lws_context *context) #ifdef LWS_WITH_PLUGINS if (context->plugin_list) - lws_plugins_destroy(&context->plugin_list); + lws_plugins_destroy(&context->plugin_list, NULL, NULL); #endif for (n = 0; n < FD_HASHTABLE_MODULUS; n++) { diff --git a/3rdparty/libwebsockets/lib/plat/windows/windows-plugins.c b/3rdparty/libwebsockets/lib/plat/windows/windows-plugins.c index b2153d67..313d58ff 100644 --- a/3rdparty/libwebsockets/lib/plat/windows/windows-plugins.c +++ b/3rdparty/libwebsockets/lib/plat/windows/windows-plugins.c @@ -66,7 +66,7 @@ lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, 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); + __func__, path, libpath, lib.errmsg); goto bail; } @@ -123,7 +123,9 @@ lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, int lws_plat_destroy_dl(struct lws_plugin *p) { - return uv_dlclose(&p->u.lib); + uv_dlclose(&p->u.lib); + + return 0; } #endif diff --git a/3rdparty/libwebsockets/lib/plat/windows/windows-sockets.c b/3rdparty/libwebsockets/lib/plat/windows/windows-sockets.c index 8fa4b458..b0e15dd1 100644 --- a/3rdparty/libwebsockets/lib/plat/windows/windows-sockets.c +++ b/3rdparty/libwebsockets/lib/plat/windows/windows-sockets.c @@ -25,6 +25,7 @@ #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS #endif +#define MBEDTLS_ALLOW_PRIVATE_ACCESS #include "private-lib-core.h" #if defined(LWS_WITH_MBEDTLS) @@ -200,6 +201,9 @@ lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) } #endif + if (context->event_loop_ops->io) + context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ); + pt->fds[pt->fds_count++].revents = 0; lws_plat_change_pollfd(context, wsi, &pt->fds[pt->fds_count - 1]); @@ -241,6 +245,8 @@ lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi, return 0; } +#if defined(LWS_WITH_TLS) + int lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) { @@ -398,6 +404,8 @@ lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) return 0; } +#endif + const char * lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { @@ -551,19 +559,22 @@ int lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) { int fd = ((mbedtls_net_context *) ctx)->fd; - int ret; + int ret, en; if (fd < 0) return MBEDTLS_ERR_NET_INVALID_CONTEXT; - ret = write(fd, buf, (unsigned int)len); + ret = send(fd, (const char *)buf, (unsigned int)len, 0); if (ret >= 0) return ret; - if (errno == EAGAIN || errno == EWOULDBLOCK) + en = LWS_ERRNO; + if (en == EAGAIN || en == EWOULDBLOCK) return MBEDTLS_ERR_SSL_WANT_WRITE; - if (WSAGetLastError() == WSAECONNRESET ) + ret = WSAGetLastError(); + lwsl_notice("%s: errno %d, GLE %d\n", __func__, en, ret); + if (ret == WSAECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); return MBEDTLS_ERR_NET_SEND_FAILED; @@ -573,19 +584,23 @@ int lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) { int fd = ((mbedtls_net_context *) ctx)->fd; - int ret; + int ret, en; if (fd < 0) return MBEDTLS_ERR_NET_INVALID_CONTEXT; - ret = (int)read(fd, buf, (unsigned int)len); + ret = (int)recv(fd, (char *)buf, (unsigned int)len, 0); if (ret >= 0) return ret; - if (errno == EAGAIN || errno == EWOULDBLOCK) + en = LWS_ERRNO; + if (en == EAGAIN || en == EWOULDBLOCK) return MBEDTLS_ERR_SSL_WANT_READ; - if (WSAGetLastError() == WSAECONNRESET) + ret = WSAGetLastError(); + lwsl_notice("%s: errno %d, GLE %d\n", __func__, en, ret); + + if (ret == WSAECONNRESET) return MBEDTLS_ERR_NET_CONN_RESET; return MBEDTLS_ERR_NET_RECV_FAILED; diff --git a/3rdparty/libwebsockets/lib/plat/windows/windows-spawn.c b/3rdparty/libwebsockets/lib/plat/windows/windows-spawn.c index 10eb5d18..a7c0322e 100644 --- a/3rdparty/libwebsockets/lib/plat/windows/windows-spawn.c +++ b/3rdparty/libwebsockets/lib/plat/windows/windows-spawn.c @@ -78,7 +78,7 @@ lws_create_basic_wsi(struct lws_context *context, int tsi, } lws_context_lock(context, __func__); - new_wsi = __lws_wsi_create_with_role(context, tsi, ops); + new_wsi = __lws_wsi_create_with_role(context, tsi, ops, NULL); lws_context_unlock(context); if (new_wsi == NULL) { lwsl_err("Out of memory for new connection\n"); @@ -415,8 +415,8 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) goto bail2; } - __lws_lc_tag(&i->vh->context->lcg[LWSLCG_WSI], &lsp->stdwsi[n]->lc, - "nspawn-stdwsi-%d", n); + __lws_lc_tag(i->vh->context, &i->vh->context->lcg[LWSLCG_WSI], + &lsp->stdwsi[n]->lc, "nspawn-stdwsi-%d", n); lsp->stdwsi[n]->lsp_channel = n; lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]); diff --git a/3rdparty/libwebsockets/lib/roles/cgi/cgi-server.c b/3rdparty/libwebsockets/lib/roles/cgi/cgi-server.c index 60b956f0..a6f04fa1 100644 --- a/3rdparty/libwebsockets/lib/roles/cgi/cgi-server.c +++ b/3rdparty/libwebsockets/lib/roles/cgi/cgi-server.c @@ -78,8 +78,6 @@ lws_cgi_grace(lws_sorted_usec_list_t *sul) /* act on the reap cb from earlier */ - lwsl_info("%s: %s\n", __func__, lws_wsi_tag(cgi->wsi)); - if (!cgi->wsi->http.cgi->post_in_expected) cgi->wsi->http.cgi->cgi_transaction_over = 1; @@ -97,14 +95,16 @@ lws_cgi_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si, * The cgi has come to an end, by itself or with a signal... */ - lwsl_info("%s: %s post_in_expected %d\n", __func__, lws_wsi_tag(wsi), - (int)wsi->http.cgi->post_in_expected); + if (wsi->http.cgi) + lwsl_wsi_info(wsi, "post_in_expected %d", + (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, + if (wsi->http.cgi) + lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->http.cgi->sul_grace, lws_cgi_grace, 1 * LWS_US_PER_SEC); } @@ -126,7 +126,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, wsi->http.cgi = lws_zalloc(sizeof(*wsi->http.cgi), "new cgi"); if (!wsi->http.cgi) { - lwsl_err("%s: OOM\n", __func__); + lwsl_wsi_err(wsi, "OOM"); return -1; } @@ -144,7 +144,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, wsi->hdr_state = LCHS_HEADER; /* add us to the pt list of active cgis */ - lwsl_debug("%s: adding cgi %p to list\n", __func__, wsi->http.cgi); + lwsl_wsi_debug(wsi, "adding cgi %p to list", wsi->http.cgi); cgi->cgi_list = pt->http.cgi_list; pt->http.cgi_list = cgi; @@ -477,8 +477,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) */ switch (wsi->hdr_state) { case LHCS_RESPONSE: - lwsl_debug("LHCS_RESPONSE: issuing response %d\n", - wsi->http.cgi->response_code); + lwsl_wsi_debug(wsi, "LHCS_RESPONSE: iss response %d", + wsi->http.cgi->response_code); if (lws_add_http_header_status(wsi, (unsigned int)wsi->http.cgi->response_code, &p, end)) @@ -605,7 +605,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) if (n > 512) n = 512; - lwsl_debug("LHCS_DUMP_HEADERS: %d\n", n); + lwsl_wsi_debug(wsi, "LHCS_DUMP_HEADERS: %d", n); cmd = LWS_WRITE_HTTP_HEADERS_CONTINUATION; if (wsi->http.cgi->headers_dumped + n != @@ -618,7 +618,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) (unsigned char *)wsi->http.cgi->headers_dumped, (unsigned int)n, (enum lws_write_protocol)cmd); if (m < 0) { - lwsl_debug("%s: write says %d\n", __func__, m); + lwsl_wsi_debug(wsi, "write says %d", m); return -1; } wsi->http.cgi->headers_dumped += n; @@ -626,12 +626,12 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) wsi->http.cgi->headers_pos) { wsi->hdr_state = LHCS_PAYLOAD; lws_free_set_NULL(wsi->http.cgi->headers_buf); - lwsl_debug("%s: freed cgi headers\n", __func__); + lwsl_wsi_debug(wsi, "freed cgi headers"); if (wsi->http.cgi->post_in_expected) { - lwsl_info("%s: post data still expected, " - "asking for writeable\n", - __func__); + lwsl_wsi_info(wsi, "post data still " + "expected, asking " + "for writeable"); lws_callback_on_writable(wsi); } @@ -656,11 +656,11 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) wsi->http.cgi->headers_buf = lws_malloc((unsigned int)n + LWS_PRE, "cgi hdr buf"); if (!wsi->http.cgi->headers_buf) { - lwsl_err("OOM\n"); + lwsl_wsi_err(wsi, "OOM"); return -1; } - lwsl_debug("allocated cgi hdrs\n"); + lwsl_wsi_debug(wsi, "allocated cgi hdrs"); wsi->http.cgi->headers_start = wsi->http.cgi->headers_buf + LWS_PRE; wsi->http.cgi->headers_pos = wsi->http.cgi->headers_start; @@ -680,7 +680,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) n = (int)read(n, &c, 1); if (n < 0) { if (errno != EAGAIN) { - lwsl_debug("%s: read says %d\n", __func__, n); + lwsl_wsi_debug(wsi, "read says %d", n); return -1; } else @@ -688,7 +688,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) if (wsi->http.cgi->headers_pos >= wsi->http.cgi->headers_end - 4) { - lwsl_notice("CGI hdrs > buf size\n"); + lwsl_wsi_notice(wsi, "CGI hdrs > buf size"); return -1; } @@ -696,8 +696,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) if (!n) goto agin; - lwsl_debug("-- 0x%02X %c %d %d\n", (unsigned char)c, c, - wsi->http.cgi->match[1], wsi->hdr_state); + lwsl_wsi_debug(wsi, "-- 0x%02X %c %d %d", (unsigned char)c, c, + wsi->http.cgi->match[1], wsi->hdr_state); if (!c) return -1; switch (wsi->hdr_state) { @@ -721,8 +721,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) case SIGNIFICANT_HDR_STATUS: wsi->http.cgi->response_code = atoi(wsi->http.cgi->l); - lwsl_debug("Status set to %d\n", - wsi->http.cgi->response_code); + lwsl_wsi_debug(wsi, "Status set to %d", + wsi->http.cgi->response_code); break; default: break; @@ -751,7 +751,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) !significant_hdr[SIGNIFICANT_HDR_TRANSFER_ENCODING] [wsi->http.cgi->match[ SIGNIFICANT_HDR_TRANSFER_ENCODING]]) { - lwsl_info("cgi produced chunked\n"); + lwsl_wsi_info(wsi, "cgi produced chunked"); wsi->http.cgi->explicitly_chunked = 1; } @@ -759,7 +759,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) if (wsi->hdr_state != LCHS_HEADER && !significant_hdr[SIGNIFICANT_HDR_LOCATION][ wsi->http.cgi->match[SIGNIFICANT_HDR_LOCATION]]) { - lwsl_debug("CGI: Location hdr seen\n"); + lwsl_wsi_debug(wsi, "CGI: Location hdr seen"); wsi->http.cgi->response_code = 302; } break; @@ -770,8 +770,8 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) break; } /* we got \r[^\n]... it's unreasonable */ - lwsl_debug("%s: funny CRLF 0x%02X\n", __func__, - (unsigned char)c); + lwsl_wsi_debug(wsi, "funny CRLF 0x%02X", + (unsigned char)c); return -1; case LCHS_CR2: @@ -790,7 +790,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) case LCHS_SINGLE_0A: m = wsi->hdr_state; if (c == '\x0a') { - lwsl_debug("Content-Length: %lld\n", + lwsl_wsi_debug(wsi, "Content-Length: %lld", (unsigned long long) wsi->http.cgi->content_length); wsi->hdr_state = LHCS_RESPONSE; @@ -831,7 +831,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) n = (int)read(n, start, sizeof(buf) - LWS_PRE); if (n < 0 && errno != EAGAIN) { - lwsl_debug("%s: stdout read says %d\n", __func__, n); + lwsl_wsi_debug(wsi, "stdout read says %d", n); return -1; } if (n > 0) { @@ -869,7 +869,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) m = lws_write(wsi, (unsigned char *)start, (unsigned int)n, (enum lws_write_protocol)cmd); //lwsl_notice("write %d\n", m); if (m < 0) { - lwsl_debug("%s: stdout write says %d\n", __func__, m); + lwsl_wsi_debug(wsi, "stdout write says %d\n", m); return -1; } wsi->http.cgi->content_length_seen += (unsigned int)n; @@ -878,7 +878,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) if (!wsi->mux_substream && m) { uint8_t term[LWS_PRE + 6]; - lwsl_info("%s: sent trailer\n", __func__); + lwsl_wsi_info(wsi, "sent trailer"); memcpy(term + LWS_PRE, (uint8_t *)"0\x0d\x0a\x0d\x0a", 5); if (lws_write(wsi, term + LWS_PRE, 5, @@ -891,7 +891,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) } if (wsi->cgi_stdout_zero_length) { - lwsl_debug("%s: stdout is POLLHUP'd\n", __func__); + lwsl_wsi_debug(wsi, "stdout is POLLHUP'd"); if (wsi->mux_substream) m = lws_write(wsi, (unsigned char *)start, 0, LWS_WRITE_HTTP_FINAL); @@ -909,9 +909,7 @@ lws_cgi_kill(struct lws *wsi) { struct lws_cgi_args args; pid_t pid; - int n, m; - - lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(wsi)); + int n, m = 0; if (!wsi->http.cgi || !wsi->http.cgi->lsp) return 0; @@ -923,7 +921,8 @@ lws_cgi_kill(struct lws *wsi) /* that has invalidated and NULL'd wsi->http.cgi->lsp */ if (pid != -1) { - m = wsi->http.cgi->being_closed; + if (wsi->http.cgi) + m = wsi->http.cgi->being_closed; n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_CGI_TERMINATED, wsi->user_space, (void *)&args, @@ -946,7 +945,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) n = waitpid(-1, &status, WNOHANG); if (n <= 0) continue; - lwsl_debug("%s: observed PID %d terminated\n", __func__, n); + lwsl_cx_debug(pt->context, "observed PID %d terminated", n); pcgi = &pt->http.cgi_list; @@ -968,9 +967,8 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) continue; if (cgi->content_length) { - lwsl_debug("%s: %s: expected content " - "length seen: %lld\n", __func__, - lws_wsi_tag(cgi->wsi), + lwsl_cx_debug(pt->context, "expected content " + "length seen: %lld", (unsigned long long)cgi->content_length_seen); } @@ -982,8 +980,6 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) * and close him if he's not already closing */ if (n == cgi->lsp->child_pid) { - lwsl_debug("%s: found PID %d on cgi list\n", - __func__, n); if (!cgi->content_length) { /* @@ -1004,11 +1000,9 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) cgi = NULL; } /* if not found on the cgi list, as he's one of ours, reap */ - if (!cgi) { - lwsl_debug("%s: reading PID %d although no cgi match\n", - __func__, n); + if (!cgi) waitpid(n, &status, WNOHANG); - } + } pcgi = &pt->http.cgi_list; @@ -1039,9 +1033,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) continue; if (cgi->content_length) - lwsl_debug("%s: %s: expected " - "content len seen: %lld\n", __func__, - lws_wsi_tag(cgi->wsi), + lwsl_wsi_debug(cgi->wsi, "expected cont len seen: %lld", (unsigned long long)cgi->content_length_seen); /* reap it */ @@ -1057,8 +1049,8 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) continue; } finish_him: - lwsl_debug("%s: found PID %d on cgi list\n", - __func__, cgi->lsp->child_pid); + lwsl_cx_debug(pt->context, "found PID %d on cgi list", + cgi->lsp->child_pid); /* defeat kill() */ cgi->lsp->child_pid = 0; @@ -1087,7 +1079,7 @@ lws_cgi_remove_and_kill(struct lws *wsi) struct lws_cgi **pcgi = &pt->http.cgi_list; /* remove us from the cgi list */ - lwsl_debug("%s: remove cgi %p from list\n", __func__, wsi->http.cgi); + while (*pcgi) { if (*pcgi == wsi->http.cgi) { /* drop us from the pt cgi list */ @@ -1096,10 +1088,9 @@ lws_cgi_remove_and_kill(struct lws *wsi) } pcgi = &(*pcgi)->cgi_list; } - if (wsi->http.cgi->headers_buf) { - lwsl_debug("%s: close: freed cgi headers\n", __func__); + if (wsi->http.cgi->headers_buf) lws_free_set_NULL(wsi->http.cgi->headers_buf); - } + /* we have a cgi going, we must kill it */ wsi->http.cgi->being_closed = 1; lws_cgi_kill(wsi); diff --git a/3rdparty/libwebsockets/lib/roles/cgi/ops-cgi.c b/3rdparty/libwebsockets/lib/roles/cgi/ops-cgi.c index 1b1c0014..d0dfc3cf 100644 --- a/3rdparty/libwebsockets/lib/roles/cgi/ops-cgi.c +++ b/3rdparty/libwebsockets/lib/roles/cgi/ops-cgi.c @@ -42,27 +42,24 @@ rops_handle_POLLIN_cgi(struct lws_context_per_thread *pt, struct lws *wsi, if (wsi->lsp_channel == LWS_STDIN && lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { - lwsl_info("failed at set pollfd\n"); + lwsl_wsi_info(wsi, "failed at set pollfd"); return LWS_HPI_RET_WSI_ALREADY_DIED; } if (!wsi->parent) { - lwsl_debug("%s: stdwsi content with parent\n", - __func__); + lwsl_wsi_debug(wsi, "stdwsi content with parent"); return LWS_HPI_RET_HANDLED; } if (!wsi->parent->http.cgi) { - lwsl_notice("%s: stdwsi content with deleted cgi object\n", - __func__); + lwsl_wsi_notice(wsi, "stdwsi content with deleted cgi object"); return LWS_HPI_RET_HANDLED; } if (!wsi->parent->http.cgi->lsp) { - lwsl_notice("%s: stdwsi content with reaped lsp\n", - __func__); + lwsl_wsi_notice(wsi, "stdwsi content with reaped lsp"); return LWS_HPI_RET_HANDLED; } @@ -71,8 +68,8 @@ rops_handle_POLLIN_cgi(struct lws_context_per_thread *pt, struct lws *wsi, args.stdwsi = &wsi->parent->http.cgi->lsp->stdwsi[0]; args.hdr_state = (enum lws_cgi_hdr_state)wsi->hdr_state; - lwsl_debug("CGI LWS_STDOUT %p wsistate 0x%x\n", - wsi->parent, wsi->wsistate); + lwsl_wsi_debug(wsi, "CGI LWS_STDOUT %p wsistate 0x%x", + wsi->parent, wsi->wsistate); if (user_callback_handle_rxflow(wsi->parent->a.protocol->callback, wsi->parent, LWS_CALLBACK_CGI, diff --git a/3rdparty/libwebsockets/lib/roles/dbus/dbus.c b/3rdparty/libwebsockets/lib/roles/dbus/dbus.c index e8e58078..34457925 100644 --- a/3rdparty/libwebsockets/lib/roles/dbus/dbus.c +++ b/3rdparty/libwebsockets/lib/roles/dbus/dbus.c @@ -72,7 +72,8 @@ __lws_shadow_wsi(struct lws_dbus_ctx *ctx, DBusWatch *w, int fd, int create_ok) lws_vhost_assert_lock_held(wsi->a.vhost); /* requires context lock */ - wsi = __lws_wsi_create_with_role(ctx->vh->context, ctx->tsi, NULL); + wsi = __lws_wsi_create_with_role(ctx->vh->context, ctx->tsi, NULL, + ctx->vh->lc.log_cx); if (wsi == NULL) { lwsl_err("Out of mem\n"); return NULL; @@ -87,7 +88,8 @@ __lws_shadow_wsi(struct lws_dbus_ctx *ctx, DBusWatch *w, int fd, int create_ok) wsi->opaque_parent_data = ctx; ctx->w[0] = w; - __lws_lc_tag(&ctx->vh->context->lcg[LWSLCG_WSI], &wsi->lc, "dbus|%s", ctx->vh->name); + __lws_lc_tag(ctx->vh->context, &ctx->vh->context->lcg[LWSLCG_WSI], + &wsi->lc, "dbus|%s", ctx->vh->name); lws_vhost_bind_wsi(ctx->vh, wsi); if (__insert_wsi_socket_into_fds(ctx->vh->context, wsi)) { diff --git a/3rdparty/libwebsockets/lib/roles/h1/ops-h1.c b/3rdparty/libwebsockets/lib/roles/h1/ops-h1.c index a6e53e40..769490fe 100644 --- a/3rdparty/libwebsockets/lib/roles/h1/ops-h1.c +++ b/3rdparty/libwebsockets/lib/roles/h1/ops-h1.c @@ -292,9 +292,11 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len) // assert(0); /* fallthru */ + case LRS_WAITING_CONNECT: /* observed on warmcat.com */ + break; + default: lwsl_err("%s: Unhandled state %d\n", __func__, lwsi_state(wsi)); - assert(0); goto bail; } @@ -367,6 +369,7 @@ lws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) if ((lwsi_state(wsi) == LRS_ESTABLISHED || lwsi_state(wsi) == LRS_ISSUING_FILE || lwsi_state(wsi) == LRS_HEADERS || + lwsi_state(wsi) == LRS_DOING_TRANSACTION || /* at least, SSE */ lwsi_state(wsi) == LRS_DISCARD_BODY || lwsi_state(wsi) == LRS_BODY)) { @@ -632,6 +635,11 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi, lwsl_debug("%s: %s: wsistate 0x%x\n", __func__, lws_wsi_tag(wsi), (unsigned int)wsi->wsistate); + + if (pollfd->revents & LWS_POLLHUP && + !lws_buflist_total_len(&wsi->buflist)) + return LWS_HPI_RET_PLEASE_CLOSE_ME; + n = lws_h1_server_socket_service(wsi, pollfd); if (n != LWS_HPI_RET_HANDLED) return n; @@ -705,7 +713,9 @@ static int rops_handle_POLLOUT_h1(struct lws *wsi) { - if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY) { + + if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY || + lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY) { #if defined(LWS_WITH_HTTP_PROXY) if (wsi->http.proxy_clientside) { unsigned char *buf, prebuf[LWS_PRE + 1024]; @@ -717,7 +727,6 @@ rops_handle_POLLOUT_h1(struct lws *wsi) len = sizeof(prebuf) - LWS_PRE; if (len) { - memcpy(prebuf + LWS_PRE, buf, len); lwsl_debug("%s: %s: proxying body %d %d %d %d %d\n", @@ -736,23 +745,28 @@ rops_handle_POLLOUT_h1(struct lws *wsi) } lws_buflist_use_segment(&wsi->parent->http.buflist_post_body, len); + } - if (wsi->parent->http.buflist_post_body) + if (wsi->parent->http.buflist_post_body) { lws_callback_on_writable(wsi); - else { + return LWS_HP_RET_DROP_POLLOUT; + } + + lwsl_wsi_err(wsi, "nothing to send"); #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) - /* prepare ourselves to do the parsing */ - wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART; - wsi->http.ah->lextable_pos = 0; + /* prepare ourselves to do the parsing */ + wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART; + wsi->http.ah->lextable_pos = 0; #if defined(LWS_WITH_CUSTOM_HEADERS) - wsi->http.ah->unk_pos = 0; + wsi->http.ah->unk_pos = 0; #endif #endif - lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY); - lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, - (int)wsi->a.context->timeout_secs); - } + lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY); + lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, + (int)wsi->a.context->timeout_secs); + + return LWS_HP_RET_DROP_POLLOUT; } #endif return LWS_HP_RET_USER_SERVICE; diff --git a/3rdparty/libwebsockets/lib/roles/h2/hpack.c b/3rdparty/libwebsockets/lib/roles/h2/hpack.c index 68629e6f..f6aefd34 100644 --- a/3rdparty/libwebsockets/lib/roles/h2/hpack.c +++ b/3rdparty/libwebsockets/lib/roles/h2/hpack.c @@ -1398,11 +1398,15 @@ int lws_add_http2_header_by_name(struct lws *wsi, const unsigned char *name, #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); + if (value) { + 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); + } else { + lwsl_err("%s: %p dummy copy %s (len %d)\n", __func__, *p, name, length); + } #endif len = (int)strlen((char *)name); @@ -1436,7 +1440,8 @@ int lws_add_http2_header_by_name(struct lws *wsi, const unsigned char *name, if (lws_h2_num(7, (unsigned long)length, p, end)) return 1; - memcpy(*p, value, (unsigned int)length); + if (value) + memcpy(*p, value, (unsigned int)length); *p += length; return 0; diff --git a/3rdparty/libwebsockets/lib/roles/h2/http2.c b/3rdparty/libwebsockets/lib/roles/h2/http2.c index be28537d..58e7c107 100644 --- a/3rdparty/libwebsockets/lib/roles/h2/http2.c +++ b/3rdparty/libwebsockets/lib/roles/h2/http2.c @@ -267,8 +267,9 @@ __lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi, } #if defined(LWS_WITH_SERVER) - if (lwsi_role_server(parent_wsi)) + if (lwsi_role_server(parent_wsi)) { lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mth_srv); + } #endif h2n->highest_sid_opened = sid; @@ -395,12 +396,17 @@ lws_h2_issue_preface(struct lws *wsi) return 1; } + if (h2n->sent_preface) + return 1; + lwsl_debug("%s: %s: fd %d\n", __func__, lws_wsi_tag(wsi), (int)wsi->desc.sockfd); if (lws_issue_raw(wsi, (uint8_t *)preface, strlen(preface)) != (int)strlen(preface)) return 1; + h2n->sent_preface = 1; + lws_role_transition(wsi, LWSIFR_CLIENT, LRS_H2_WAITING_TO_SEND_HEADERS, &role_ops_h2); @@ -425,6 +431,12 @@ lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pps) struct lws *nwsi = lws_get_network_wsi(wsi); struct lws_h2_netconn *h2n = nwsi->h2.h2n; + if (!h2n) { + lwsl_warn("%s: null h2n\n", __func__); + lws_free(pps); + return; + } + pps->next = h2n->pps; h2n->pps = pps; lws_rx_flow_control(wsi, LWS_RXFLOW_REASON_APPLIES_DISABLE | @@ -1510,6 +1522,18 @@ lws_h2_parse_end_of_frame(struct lws *wsi) #endif #endif /* CLIENT */ +#if defined(LWS_WITH_SECURE_STREAMS) + if (wsi->for_ss) { + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + h2n->swsi->for_ss = 1; + wsi->for_ss = 0; + + if (h->wsi == wsi) + h->wsi = h2n->swsi; + } +#endif + h2n->swsi->a.protocol = wsi->a.protocol; if (h2n->swsi->user_space && !h2n->swsi->user_space_externally_allocated) @@ -1522,6 +1546,11 @@ lws_h2_parse_end_of_frame(struct lws *wsi) h2n->swsi->txc.manual_initial_tx_credit = wsi->txc.manual_initial_tx_credit; +#if defined(LWS_WITH_TLS) + lws_strncpy(h2n->swsi->alpn, wsi->alpn, + sizeof(wsi->alpn)); +#endif + wsi->user_space = NULL; if (h2n->swsi->http.ah) @@ -1619,8 +1648,17 @@ lws_h2_parse_end_of_frame(struct lws *wsi) #if defined(LWS_WITH_CLIENT) if (h2n->swsi->client_mux_substream && lws_client_interpret_server_handshake(h2n->swsi)) { - lwsl_info("%s: cli int serv hs closed it\n", __func__); - break; + /* + * This is more complicated than it looks, one exit from + * interpret_server_handshake() is to do a close that + * turns into a redirect. + * + * In that case, the wsi survives having being reset + * and detached from any h2 identity. We need to get + * our parents out from touching it any more + */ + lwsl_info("%s: cli int serv hs closed, or redir\n", __func__); + return 2; } #endif @@ -2020,7 +2058,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, 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); + //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length); goto frame_end; } @@ -2155,16 +2193,22 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, __func__, lws_wsi_tag(h2n->swsi)); } + /* + * in + length may cover multiple frames, we + * can only consider the length of the DATA + * in front of us + */ + if (lws_hdr_total_length(h2n->swsi, WSI_TOKEN_HTTP_CONTENT_LENGTH) && h2n->swsi->http.rx_content_length && h2n->swsi->http.rx_content_remain < - lws_ptr_diff_size_t(iend, in) + 1 - 9 && /* last */ + h2n->length && /* last */ h2n->inside < h2n->length) { lwsl_warn("%s: %lu %lu %lu %lu\n", __func__, (unsigned long)h2n->swsi->http.rx_content_remain, - (unsigned long)(lws_ptr_diff_size_t(iend, in) + 1 - 9), + (unsigned long)(lws_ptr_diff_size_t(iend, in) + 1), (unsigned long)h2n->inside, (unsigned long)h2n->length); /* unread data in frame */ @@ -2217,10 +2261,9 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, goto close_swsi_and_return; } - break; + goto do_windows; } #endif - if (lwsi_state(h2n->swsi) == LRS_DEFERRING_ACTION) { m = lws_buflist_append_segment( &h2n->swsi->buflist, in - 1, (unsigned int)n); @@ -2299,7 +2342,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, * fast as we can take it */ - m = n; //(2 * h2n->length) + 65536; + m = n + 65536; /* update both the stream and nwsi */ @@ -2360,7 +2403,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, 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); + //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length); h2n->count++; break; @@ -2384,7 +2427,13 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, /* * end of frame just happened */ - if (lws_h2_parse_end_of_frame(wsi)) + n = lws_h2_parse_end_of_frame(wsi); + if (n == 2) { + *inused = (lws_filepos_t)lws_ptr_diff_size_t(in, oldin); + + return 2; + } + if (n) goto fail; break; @@ -2430,7 +2479,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, 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); + //lwsl_debug("%s: consuming for ignored %u %u\n", __func__, (unsigned int)h2n->count, (unsigned int)h2n->length); h2n->count++; } break; @@ -2468,6 +2517,7 @@ lws_h2_client_handshake(struct lws *wsi) char *meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD), *uri = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI), *simp; struct lws *nwsi = lws_get_network_wsi(wsi); + const char *path = "/"; int n, m; /* * The identifier of a newly established stream MUST be numerically @@ -2505,6 +2555,8 @@ lws_h2_client_handshake(struct lws *wsi) if (!meth) meth = "GET"; + /* h2 pseudoheaders must be in a bunch at the start */ + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_METHOD, (unsigned char *)meth, @@ -2517,31 +2569,49 @@ lws_h2_client_handshake(struct lws *wsi) &p, end)) goto fail_length; + n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI); + if (n) + path = uri; + else + if (wsi->stash && wsi->stash->cis[CIS_PATH]) { + path = wsi->stash->cis[CIS_PATH]; + n = (int)strlen(path); + } else + n = 1; + + if (n > 1 && path[0] == '/' && path[1] == '/') { + path++; + n--; + } + if (n && lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_PATH, - (unsigned char *)uri, n, &p, end)) + (unsigned char *)path, n, &p, end)) goto fail_length; - n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_ORIGIN); - simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN); + n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_HOST); + simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST); + if (!n && wsi->stash && wsi->stash->cis[CIS_ADDRESS]) { + n = (int)strlen(wsi->stash->cis[CIS_ADDRESS]); + simp = wsi->stash->cis[CIS_ADDRESS]; + } + +// n = lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_ORIGIN); +// simp = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN); +#if 0 if (n && simp && lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_AUTHORITY, (unsigned char *)simp, n, &p, end)) goto fail_length; +#endif - 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 && + if (/*!wsi->client_h2_alpn && */n && simp && lws_add_http_header_by_token(wsi, WSI_TOKEN_HOST, (unsigned char *)simp, n, &p, end)) goto fail_length; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_USER_AGENT, - (unsigned char *)"lwsss", 5, - &p, end)) - goto fail_length; if (wsi->flags & LCCSCF_HTTP_MULTIPART_MIME) { p1 = lws_http_multipart_headers(wsi, p); @@ -2560,6 +2630,11 @@ lws_h2_client_handshake(struct lws *wsi) /* give userland a chance to append, eg, cookies */ +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + if (wsi->flags & LCCSCF_CACHE_COOKIES) + lws_cookie_send_cookies(wsi, (char **)&p, (char *)end); +#endif + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, wsi->user_space, &p, lws_ptr_diff_size_t(end, p) - 12)) diff --git a/3rdparty/libwebsockets/lib/roles/h2/ops-h2.c b/3rdparty/libwebsockets/lib/roles/h2/ops-h2.c index cc442f8e..0f76d171 100644 --- a/3rdparty/libwebsockets/lib/roles/h2/ops-h2.c +++ b/3rdparty/libwebsockets/lib/roles/h2/ops-h2.c @@ -113,8 +113,20 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, } #endif - lwsl_info("%s: wsistate 0x%x, pollout %d\n", __func__, - (unsigned int)wsi->wsistate, pollfd->revents & LWS_POLLOUT); + lwsl_info("%s: %s wsistate 0x%x, events %d, revents %d, pollout %d\n", __func__, + wsi->lc.gutag, (unsigned int)wsi->wsistate, + pollfd->events, pollfd->revents, + pollfd->revents & LWS_POLLOUT); + + /* !!! */ + if (wsi->wsistate == 0x10000013) { + wsi->bugcatcher++; + if (wsi->bugcatcher == 250) { + lwsl_err("%s: BUGCATCHER\n", __func__); + return LWS_HPI_RET_PLEASE_CLOSE_ME; + } + } else + wsi->bugcatcher = 0; /* * something went wrong with parsing the handshake, and @@ -170,7 +182,9 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, if (wsi->mux_substream || wsi->upgraded_to_http2) { wsi1 = lws_get_network_wsi(wsi); - if (wsi1 && lws_has_buffered_out(wsi1)) + if (wsi1 && lws_has_buffered_out(wsi1)) { + + lwsl_info("%s: has buffered out\n", __func__); /* * We cannot deal with any kind of new RX * because we are dealing with a partial send @@ -178,6 +192,7 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, * expect to be able to send) */ return LWS_HPI_RET_HANDLED; + } } read: @@ -205,8 +220,11 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, !(pollfd->revents & pollfd->events & LWS_POLLIN)) return LWS_HPI_RET_HANDLED; + /* We have something to read... */ + if (!(lwsi_role_client(wsi) && (lwsi_state(wsi) != LRS_ESTABLISHED && + // lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2 && lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) { ebuf.token = pt->serv_buf; @@ -228,7 +246,8 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, // lwsl_notice("%s: Actual RX %d\n", __func__, ebuf.len); // if (ebuf.len > 0) // lwsl_hexdump_notice(ebuf.token, ebuf.len); - } + } else + lwsl_info("%s: skipped read\n", __func__); if (ebuf.len < 0) return LWS_HPI_RET_PLEASE_CLOSE_ME; @@ -484,9 +503,9 @@ rops_write_role_protocol_h2(struct lws *wsi, unsigned char *buf, size_t len, } if (base == LWS_WRITE_HTTP_FINAL || ((*wp) & LWS_WRITE_H2_STREAM_END)) { - lwsl_info("%s: %s: setting END_STREAM\n", __func__, - lws_wsi_tag(wsi)); flags |= LWS_H2_FLAG_END_STREAM; + lwsl_info("%s: %s: setting END_STREAM, 0x%x\n", __func__, + lws_wsi_tag(wsi), flags); wsi->h2.send_END_STREAM = 1; } @@ -559,7 +578,9 @@ rops_pt_init_destroy_h2(struct lws_context *context, const struct lws_context_creation_info *info, struct lws_context_per_thread *pt, int destroy) { - context->set = lws_h2_stock_settings; + /* if not already set by plat, use lws default SETTINGS */ + if (!context->set.s[0]) + context->set = lws_h2_stock_settings; /* * We only want to do this once... we will do it if we are built @@ -776,9 +797,9 @@ static int lws_h2_bind_for_post_before_action(struct lws *wsi) { const struct lws_http_mount *hit; + int uri_len = 0, methidx; char *uri_ptr = NULL; uint8_t *buffered; - int uri_len = 0; const char *p; size_t blen; @@ -816,6 +837,9 @@ lws_h2_bind_for_post_before_action(struct lws *wsi) if (hit->protocol) name = hit->protocol; + else + if (hit->origin_protocol == LWSMPRO_FILE) + return 0; pp = lws_vhost_name_to_protocol(wsi->a.vhost, name); if (!pp) { @@ -826,7 +850,10 @@ lws_h2_bind_for_post_before_action(struct lws *wsi) if (lws_bind_protocol(wsi, pp, __func__)) return 1; } - if (lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len) >= 0) + + methidx = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len); + + if (methidx >= 0) if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP, wsi->user_space, hit ? uri_ptr + @@ -836,6 +863,10 @@ lws_h2_bind_for_post_before_action(struct lws *wsi) uri_len))) return 1; +#if defined(LWS_WITH_ACCESS_LOG) + lws_prepare_access_log_info(wsi, uri_ptr, uri_len, methidx); +#endif + lwsl_info("%s: setting LRS_BODY from 0x%x (%s)\n", __func__, (int)wsi->wsistate, wsi->a.protocol->name); @@ -1156,7 +1187,7 @@ rops_perform_user_POLLOUT_h2(struct lws *wsi) * then logically close ourself */ - if ((lwsi_role_ws(w) && w->ws->ping_pending_flag) || + if ((lwsi_role_ws(w) && w->ws->pong_pending_flag) || (lwsi_state(w) == LRS_RETURNED_CLOSE && w->ws->payload_is_close)) { @@ -1164,13 +1195,13 @@ rops_perform_user_POLLOUT_h2(struct lws *wsi) write_type = LWS_WRITE_CLOSE | LWS_WRITE_H2_STREAM_END; - n = lws_write(w, &w->ws->ping_payload_buf[LWS_PRE], - w->ws->ping_payload_len, (enum lws_write_protocol)write_type); + n = lws_write(w, &w->ws->pong_payload_buf[LWS_PRE], + w->ws->pong_payload_len, (enum lws_write_protocol)write_type); if (n < 0) return -1; /* well he is sent, mark him done */ - w->ws->ping_pending_flag = 0; + w->ws->pong_pending_flag = 0; if (w->ws->payload_is_close) { /* oh... a close frame... then we are done */ lwsl_debug("Ack'd peer's close packet\n"); @@ -1278,8 +1309,9 @@ rops_alpn_negotiated_h2(struct lws *wsi, const char *alpn) /* HTTP2 union */ - lws_hpack_dynamic_size(wsi, - (int)wsi->h2.h2n->our_set.s[H2SET_HEADER_TABLE_SIZE]); + if (lws_hpack_dynamic_size(wsi, + (int)wsi->h2.h2n->our_set.s[H2SET_HEADER_TABLE_SIZE])) + return 1; wsi->txc.tx_cr = 65535; lwsl_info("%s: %s: configured for h2\n", __func__, lws_wsi_tag(wsi)); diff --git a/3rdparty/libwebsockets/lib/roles/h2/private-lib-roles-h2.h b/3rdparty/libwebsockets/lib/roles/h2/private-lib-roles-h2.h index 9bce1d9c..98b2aea4 100644 --- a/3rdparty/libwebsockets/lib/roles/h2/private-lib-roles-h2.h +++ b/3rdparty/libwebsockets/lib/roles/h2/private-lib-roles-h2.h @@ -272,6 +272,7 @@ struct lws_h2_netconn { unsigned int is_first_header_char:1; unsigned int zero_huff_padding:1; unsigned int last_action_dyntable_resize:1; + unsigned int sent_preface:1; uint32_t hdr_idx; uint32_t hpack_len; diff --git a/3rdparty/libwebsockets/lib/roles/http/CMakeLists.txt b/3rdparty/libwebsockets/lib/roles/http/CMakeLists.txt index 706823ab..01ad79b9 100644 --- a/3rdparty/libwebsockets/lib/roles/http/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/roles/http/CMakeLists.txt @@ -35,13 +35,18 @@ list(APPEND SOURCES roles/http/header.c roles/http/date.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_CACHE_NSCOOKIEJAR AND LWS_WITH_CLIENT) + list(APPEND SOURCES + roles/http/cookie.c) +endif() + if (LWS_WITH_HTTP_PROXY AND LWS_WITH_HUBBUB) list(APPEND SOURCES roles/http/server/rewrite.c) diff --git a/3rdparty/libwebsockets/lib/roles/http/client/client-http.c b/3rdparty/libwebsockets/lib/roles/http/client/client-http.c index 8730ee61..7dce8500 100644 --- a/3rdparty/libwebsockets/lib/roles/http/client/client-http.c +++ b/3rdparty/libwebsockets/lib/roles/http/client/client-http.c @@ -143,10 +143,12 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); - /* fallthrough */ + /* fallthru */ #endif + /* dummy fallthru to satisfy compiler */ + /* fallthru */ case LRS_H1C_ISSUE_HANDSHAKE: lwsl_debug("%s: LRS_H1C_ISSUE_HANDSHAKE\n", __func__); @@ -217,7 +219,9 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) #endif #if defined (LWS_WITH_HTTP2) - if (wsi->client_h2_alpn && lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2) { + if (wsi->client_h2_alpn //&& + //lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2 + ) { /* * We connected to the server and set up tls and * negotiated "h2" or connected as clear text @@ -227,16 +231,18 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) * now, not an h1 client connection. */ -#if defined(LWS_WITH_TLS) - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) - lws_tls_server_conn_alpn(wsi); -#endif + lwsl_info("%s: doing h2 hello path\n", __func__); - /* send the H2 preface to legitimize the connection */ - if (lws_h2_issue_preface(wsi)) { - cce = "error sending h2 preface"; - goto bail3; - } + /* + * send the H2 preface to legitimize the connection + * + * transitions us to LRS_H2_WAITING_TO_SEND_HEADERS + */ + if (wsi->client_h2_alpn) + if (lws_h2_issue_preface(wsi)) { + cce = "error sending h2 preface"; + goto bail3; + } // lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, @@ -296,7 +302,8 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) if (wsi->flags & LCCSCF_HTTP_X_WWW_FORM_URLENCODED) lws_callback_on_writable(wsi); #if defined(LWS_WITH_HTTP_PROXY) - if (wsi->http.proxy_clientside) + if (wsi->http.proxy_clientside && wsi->parent && + wsi->parent->http.buflist_post_body) lws_callback_on_writable(wsi); #endif /* user code must ask for writable callback */ @@ -327,10 +334,9 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) case LRS_ISSUE_HTTP_BODY: #if defined(LWS_WITH_HTTP_PROXY) - if (wsi->http.proxy_clientside) { + if (wsi->http.proxy_clientside && wsi->parent && + wsi->parent->http.buflist_post_body) lws_callback_on_writable(wsi); - break; - } #endif if (wsi->client_http_body_pending || lws_has_buffered_out(wsi)) { //lws_set_timeout(wsi, @@ -419,6 +425,21 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) } m = eb.len - n; +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) + do { + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + if (!h) + break; + + if (h->info.dump) { + h->info.dump(ss_to_userobj(h), + (const uint8_t *)eb.token, + (size_t)m, + (wsi->http.ah->parser_state == + WSI_PARSING_COMPLETE) ? 1 : 0); + } + } while (0); +#endif if (lws_buflist_aware_finished_consuming(wsi, &eb, m, buffered, __func__)) @@ -576,6 +597,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) struct lws *nwsi = lws_get_network_wsi(wsi); char *p = NULL, *q, *simp; char new_path[300]; + void *opaque; // lws_free_set_NULL(wsi->stash); @@ -613,6 +635,13 @@ lws_client_interpret_server_handshake(struct lws *wsi) ah->http_response = 0; } +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + + if ((wsi->flags & LCCSCF_CACHE_COOKIES) && + lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_SET_COOKIE)) + lws_parse_set_cookie(wsi); + +#endif /* * well, what the server sent looked reasonable for syntax. * Now let's confirm it sent all the necessary headers @@ -677,6 +706,27 @@ lws_client_interpret_server_handshake(struct lws *wsi) goto bail3; } +#if defined(LWS_WITH_CONMON) + if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) { + wsi->conmon.pcol = LWSCONMON_PCOL_HTTP; + wsi->conmon.protocol_specific.http.response = n; + } + +#if defined(LWS_WITH_SECURE_STREAMS) + if (wsi->for_ss +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + && !wsi->client_bound_sspc +#endif + ) { + + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (h) + lws_conmon_ss_json(h); + } +#endif +#endif + /* let's let the user code know, if he cares */ if (wsi->a.protocol->callback(wsi, @@ -756,7 +806,8 @@ lws_client_interpret_server_handshake(struct lws *wsi) } #if defined(LWS_WITH_TLS) - if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl) { + if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl && + !(wsi->flags & LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS)) { cce = "HS: Redirect attempted SSL downgrade"; goto bail3; } @@ -768,23 +819,24 @@ lws_client_interpret_server_handshake(struct lws *wsi) } if (!lws_client_reset(&wsi, ssl, ads, port, path, ads, 1)) { - /* - * There are two ways to fail out with NULL return... - * simple, early problem where the wsi is intact, or - * we went through with the reconnect attempt and the - * wsi is already closed. In the latter case, the wsi - * has been set to NULL additionally. - */ lwsl_err("Redirect failed\n"); cce = "HS: Redirect failed"; - /* coverity[reverse_inull] */ - if (wsi) - goto bail3; - - /* wsi has closed */ - return 1; + goto bail3; } - return 0; + + /* + * We are redirecting, let's close in order to extricate + * ourselves from the current wsi usage, eg, h2 mux cleanly. + * + * We will notice close_is_redirect and switch to redirect + * flow late in the close action. + */ + + opaque = wsi->a.opaque_user_data; + lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "redir"); + wsi->a.opaque_user_data = opaque; + + return -1; } /* if h1 KA is allowed, enable the queued pipeline guys */ @@ -1078,7 +1130,7 @@ char * lws_generate_client_handshake(struct lws *wsi, char *pkt) { const char *meth, *pp = lws_hdr_simple_ptr(wsi, - _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); + _WSI_TOKEN_CLIENT_SENT_PROTOCOLS), *path; char *p = pkt, *p1, *end = p + wsi->a.context->pt_serv_buf_size; meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD); @@ -1131,9 +1183,17 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) * Sec-WebSocket-Version: 4 */ + path = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI); + if (!path) { + if (wsi->stash && wsi->stash->cis[CIS_PATH] && + wsi->stash->cis[CIS_PATH][0]) + path = wsi->stash->cis[CIS_PATH]; + else + path = "/"; + } + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), - "%s %s HTTP/1.1\x0d\x0a", meth, - lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI)); + "%s %s HTTP/1.1\x0d\x0a", meth, path); p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "Pragma: no-cache\x0d\x0a" @@ -1152,7 +1212,9 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) _WSI_TOKEN_CLIENT_ORIGIN)); else p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), - "Origin: http://%s\x0d\x0a", + "Origin: %s://%s\x0d\x0a", + wsi->flags & LCCSCF_USE_SSL ? + "https" : "http", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)); } @@ -1202,6 +1264,11 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) /* give userland a chance to append, eg, cookies */ +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + if (wsi->flags & LCCSCF_CACHE_COOKIES) + lws_cookie_send_cookies(wsi, &p, end); +#endif + if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, wsi->user_space, &p, @@ -1507,8 +1574,7 @@ static uint8_t hnames2[] = { _WSI_TOKEN_CLIENT_ORIGIN, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, _WSI_TOKEN_CLIENT_METHOD, - _WSI_TOKEN_CLIENT_IFACE, - _WSI_TOKEN_CLIENT_ALPN + _WSI_TOKEN_CLIENT_IFACE }; /** @@ -1529,9 +1595,9 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, #if defined(LWS_ROLE_WS) struct _lws_websocket_related *ws; #endif - char *stash, *p; + const char *cisin[CIS_COUNT]; struct lws *wsi; - size_t size = 0; + size_t o; int n; if (!pwsi) @@ -1543,7 +1609,7 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, lwsl_debug("%s: %s: redir %d: %s\n", __func__, lws_wsi_tag(wsi), wsi->redirects, address); - if (wsi->redirects == 3) { + if (wsi->redirects == 4) { lwsl_err("%s: Too many redirects\n", __func__); return NULL; } @@ -1554,51 +1620,23 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, * but leave our wsi extant and still bound to whatever vhost it was */ - for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++) - size += (unsigned int)lws_hdr_total_length(wsi, hnames2[n]) + 1u; - - if (size < (size_t)lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI) + 1) - size = (unsigned int)lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_URI) + 1u; - - /* - * The incoming address and host can be from inside the existing ah - * we are going to detach and reattch - */ - - size += strlen(path) + 1 + strlen(address) + 1 + strlen(host) + 1 + 1; + o = path[0] == '/' && path[1] == '/'; - p = stash = lws_malloc(size, __func__); - if (!stash) - return NULL; + memset((char *)cisin, 0, sizeof(cisin)); - /* - * _WSI_TOKEN_CLIENT_ORIGIN, - * _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, - * _WSI_TOKEN_CLIENT_METHOD, - * _WSI_TOKEN_CLIENT_IFACE, - * _WSI_TOKEN_CLIENT_ALPN - * address - * host - * path - */ + cisin[CIS_ADDRESS] = address; + cisin[CIS_PATH] = path + o; + cisin[CIS_HOST] = host; for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++) - if (lws_hdr_total_length(wsi, hnames2[n]) && - lws_hdr_simple_ptr(wsi, hnames2[n])) { - memcpy(p, lws_hdr_simple_ptr(wsi, hnames2[n]), (size_t)( - lws_hdr_total_length(wsi, hnames2[n]) + 1)); - p += (size_t)(lws_hdr_total_length(wsi, hnames2[n]) + 1); - } else - *p++ = '\0'; + cisin[n + 3] = lws_hdr_simple_ptr(wsi, hnames2[n]); + +#if defined(LWS_WITH_TLS) + cisin[CIS_ALPN] = wsi->alpn; +#endif - memcpy(p, address, strlen(address) + (size_t)1); - address = p; - p += strlen(address) + 1; - memcpy(p, host, strlen(host) + (size_t)1); - host = p; - p += strlen(host) + 1; - memcpy(p, path, strlen(path) + (size_t)1); - path = p; + if (lws_client_stash_create(wsi, cisin)) + return NULL; if (!port) { lwsl_info("%s: forcing port 443\n", __func__); @@ -1607,8 +1645,20 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, ssl = 1; } - lwsl_info("redirect ads='%s', port=%d, path='%s', ssl = %d, pifds %d\n", - address, port, path, ssl, wsi->position_in_fds_table); + wsi->c_port = (uint16_t)port; + + wsi->flags = (wsi->flags & (~LCCSCF_USE_SSL)) | + (ssl ? LCCSCF_USE_SSL : 0); + + if (!cisin[CIS_ALPN] || !cisin[CIS_ALPN][0]) +#if defined(LWS_ROLE_H2) + cisin[CIS_ALPN] = "h2,http/1.1"; +#else + cisin[CIS_ALPN] = "http/1.1"; +#endif + + lwsl_notice("%s: REDIRECT %s:%d, path='%s', ssl = %d, alpn='%s'\n", + __func__, address, port, path, ssl, cisin[CIS_ALPN]); lws_pt_lock(pt, __func__); __remove_wsi_socket_from_fds(wsi); @@ -1620,6 +1670,14 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, wsi->ws = NULL; } #endif + + /* + * After this point we can't trust the incoming strings like address, + * path any more, since they may have been pointing into the old ah. + * + * We must use the copies in the wsi->stash instead if we want them. + */ + __lws_reset_wsi(wsi); /* detaches ah here */ #if defined(LWS_ROLE_WS) if (weak) @@ -1627,102 +1685,11 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, #endif wsi->client_pipeline = 1; - /* close the connection by hand */ - -#if defined(LWS_WITH_TLS) - lws_ssl_close(wsi); -#endif - - if (wsi->role_ops && - lws_rops_fidx(wsi->role_ops, LWS_ROPS_close_kill_connection)) - lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_close_kill_connection). - close_kill_connection(wsi, 1); - - if (wsi->a.context->event_loop_ops->close_handle_manually) - wsi->a.context->event_loop_ops->close_handle_manually(wsi); - else - if (wsi->desc.sockfd != LWS_SOCK_INVALID) - compatible_close(wsi->desc.sockfd); - -#if defined(LWS_WITH_TLS) - if (!ssl) - wsi->tls.use_ssl &= (unsigned int)~LCCSCF_USE_SSL; - else - wsi->tls.use_ssl |= LCCSCF_USE_SSL; -#else - if (ssl) { - lwsl_err("%s: not configured for ssl\n", __func__); - goto bail; - } -#endif - - if (wsi->a.protocol && wsi->role_ops && wsi->protocol_bind_balance) { - wsi->a.protocol->callback(wsi, - wsi->role_ops->protocol_unbind_cb[ - !!lwsi_role_server(wsi)], - wsi->user_space, (void *)__func__, 0); - - wsi->protocol_bind_balance = 0; - } - - wsi->desc.sockfd = LWS_SOCK_INVALID; - lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1); -// wsi->a.protocol = NULL; - if (wsi->a.protocol) - lws_bind_protocol(wsi, wsi->a.protocol, "client_reset"); - wsi->pending_timeout = NO_PENDING_TIMEOUT; - wsi->c_port = (uint16_t)port; - wsi->hdr_parsing_completed = 0; - - if (lws_header_table_attach(wsi, 0)) { - lwsl_err("%s: failed to get ah\n", __func__); - goto bail; - } - //_lws_header_table_reset(wsi->http.ah); - - if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address)) - goto bail; - - if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host)) - goto bail; - /* - * _WSI_TOKEN_CLIENT_ORIGIN, - * _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, - * _WSI_TOKEN_CLIENT_METHOD, - * _WSI_TOKEN_CLIENT_IFACE, - * _WSI_TOKEN_CLIENT_ALPN - * address - * host - * path + * Will complete at close flow */ - p = stash; - for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames2); n++) { - if (lws_hdr_simple_create(wsi, hnames2[n], p)) - goto bail; - p += lws_hdr_total_length(wsi, hnames2[n]) + 1; - } - - stash[0] = '/'; - memmove(&stash[1], path, size - 1 < strlen(path) + 1 ? - size - 1 : strlen(path) + (size_t)1); - if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash)) - goto bail; - - lws_free_set_NULL(stash); - -#if defined(LWS_WITH_HTTP2) - if (wsi->client_mux_substream) - wsi->h2.END_STREAM = wsi->h2.END_HEADERS = 0; -#endif - - *pwsi = lws_client_connect_2_dnsreq(wsi); + wsi->close_is_redirect = 1; return *pwsi; - -bail: - lws_free_set_NULL(stash); - - return NULL; } diff --git a/3rdparty/libwebsockets/lib/roles/http/compression/stream.c b/3rdparty/libwebsockets/lib/roles/http/compression/stream.c index 9898b76f..d4c72aa4 100644 --- a/3rdparty/libwebsockets/lib/roles/http/compression/stream.c +++ b/3rdparty/libwebsockets/lib/roles/http/compression/stream.c @@ -65,7 +65,7 @@ lws_http_compression_apply(struct lws *wsi, const char *name, for (n = 0; n < LWS_ARRAY_SIZE(lcs_available); n++) { /* if name is non-NULL, choose only that compression method */ - if (name && !strcmp(lcs_available[n]->encoding_name, name)) + if (name && strcmp(lcs_available[n]->encoding_name, name)) continue; /* * If we're the server, confirm that the client told us he could diff --git a/3rdparty/libwebsockets/lib/roles/http/cookie.c b/3rdparty/libwebsockets/lib/roles/http/cookie.c new file mode 100644 index 00000000..1860e87d --- /dev/null +++ b/3rdparty/libwebsockets/lib/roles/http/cookie.c @@ -0,0 +1,735 @@ + +#include +#include "private-lib-core.h" + +//#define LWS_COOKIE_DEBUG + +#if defined(LWS_COOKIE_DEBUG) + #define lwsl_cookie lwsl_notice +#else + #define lwsl_cookie lwsl_debug +#endif + +#define LWS_COOKIE_MAX_CACHE_NAME_LEN 128 + +#define lws_tolower(_c) (((_c) >= 'A' && (_c) <= 'Z') ? \ + (char)((_c) + 'a' - 'A') : \ + (char)(_c)) + +#define LWS_COOKIE_NSC_FORMAT "%.*s\t"\ + "%s\t"\ + "%.*s\t"\ + "%s\t"\ + "%llu\t"\ + "%.*s\t"\ + "%.*s" + +static const char *const mon = "janfebmaraprnayjunjulaugsepoctnovdec"; + +enum lws_cookie_nsc_f { + LWSC_NSC_DOMAIN, + LWSC_NSC_HOSTONLY, + LWSC_NSC_PATH, + LWSC_NSC_SECURE, + LWSC_NSC_EXPIRES, + LWSC_NSC_NAME, + LWSC_NSC_VALUE, + + LWSC_NSC_COUNT, +}; + +enum lws_cookie_elements { + CE_DOMAIN, + CE_PATH, + CE_EXPIRES, + CE_MAXAGE, + CE_NAME, + CE_VALUE, + + CE_HOSTONLY, /* these are bool, NULL = 0, non-NULL = 1 */ + CE_SECURE, + + CE_COUNT +}; + +struct lws_cookie { + const char *f[CE_COUNT]; + size_t l[CE_COUNT]; + + unsigned int httponly:1; +}; + +static int +lws_cookie_parse_date(const char *d, size_t len, time_t *t) +{ + struct tm date; + int offset = 0, i; + + memset(&date, 0, sizeof(date)); + + while (len) { + if (isalnum((int)*d)) { + offset++; + goto next; + } + switch (offset) { + case 2: + if (*d == ':' && len >= 6) { + date.tm_hour = atoi(d - 2); + if (date.tm_hour < 0 || date.tm_hour > 23) + return -1; + date.tm_min = atoi(d + 1); + if (date.tm_min < 0 || date.tm_min > 60) + return -1; + date.tm_sec = atoi(d + 4); + if (date.tm_sec < 0 || date.tm_sec > 61) + /* leap second */ + return -1; + + d += 6; + len -= 6; + offset = 0; + continue; + } + + if (!date.tm_mday) { + date.tm_mday = atoi(d - 2); + if (date.tm_mday < 1 || date.tm_mday > 31) + return -1; + goto next2; + } + + if (!date.tm_year) { + date.tm_year = atoi(d - 2); + if (date.tm_year < 0 || date.tm_year > 99) + return -1; + if (date.tm_year < 70) + date.tm_year += 100; + } + goto next2; + + case 3: + for (i = 0; i < 36; i += 3) { + if (lws_tolower(*(d - 3)) == mon[i] && + lws_tolower(*(d - 2)) == mon[i + 1] && + lws_tolower(*(d - 1)) == mon[i + 2]) { + date.tm_mon = i / 3; + break; + } + } + goto next2; + + case 4: + if (!date.tm_year) { + date.tm_year = atoi(d - 4); + if (date.tm_year < 1601) + return -1; + date.tm_year -= 1900; + } + goto next2; + + default: + goto next2; + } + +next2: + offset = 0; +next: + d++; + len--; + } + + *t = mktime(&date); + + if (*t < 0) + return -1; + + return 0; +} + +static void +lws_cookie_rm_sws(const char **buf_p, size_t *len_p) +{ + const char *buf; + size_t len; + + if (!buf_p || !*buf_p || !len_p || !*len_p) { + lwsl_err("%s: false parameter\n", __func__); + return; + } + + buf = *buf_p; + len = *len_p; + while (buf[0] == ' ' && len > 0) { + buf++; + len--; + } + while (buf[len - 1] == ' ' && len > 0) + len--; + + *buf_p = buf; + *len_p = len; +} + +static int +is_iprefix(const char *h, size_t hl, const char *n, size_t nl) +{ + if (!h || !n || nl > hl) + return 0; + + while (nl) { + nl--; + if (lws_tolower(h[nl]) != lws_tolower(n[nl])) + return 0; + } + return 1; +} + +static int +lws_cookie_compile_cache_name(char *buf, size_t buf_len, struct lws_cookie *c) +{ + if (!buf || !c->f[CE_DOMAIN] || !c->f[CE_PATH] || !c->f[CE_NAME] || + c->l[CE_DOMAIN] + c->l[CE_PATH] + c->l[CE_NAME] + 6 > buf_len) + return -1; + + memcpy(buf, c->f[CE_DOMAIN], c->l[CE_DOMAIN]); + buf += c->l[CE_DOMAIN]; + *buf++ = '|'; + + memcpy(buf, c->f[CE_PATH], c->l[CE_PATH]); + buf += c->l[CE_PATH]; + *buf++ = '|'; + + memcpy(buf, c->f[CE_NAME], c->l[CE_NAME]); + buf += c->l[CE_NAME]; + *buf = '\0'; + + return 0; +} + +static int +lws_cookie_parse_nsc(struct lws_cookie *c, const char *b, size_t l) +{ + enum lws_cookie_nsc_f state = LWSC_NSC_DOMAIN; + size_t n = 0; + + if (!c || !b || l < 13) + return -1; + + memset(c, 0, sizeof(*c)); + lwsl_cookie("%s: parsing (%.*s) \n", __func__, (int)l, b); + + while (l) { + l--; + if (b[n] != '\t' && l) { + n++; + continue; + } + switch (state) { + case LWSC_NSC_DOMAIN: + c->f[CE_DOMAIN] = b; + c->l[CE_DOMAIN] = n; + break; + case LWSC_NSC_PATH: + c->f[CE_PATH] = b; + c->l[CE_PATH] = n; + break; + case LWSC_NSC_EXPIRES: + c->f[CE_EXPIRES] = b; + c->l[CE_EXPIRES] = n; + break; + case LWSC_NSC_NAME: + c->f[CE_NAME] = b; + c->l[CE_NAME] = n; + break; + + case LWSC_NSC_HOSTONLY: + if (b[0] == 'T') { + c->f[CE_HOSTONLY] = b; + c->l[CE_HOSTONLY] = 1; + } + break; + case LWSC_NSC_SECURE: + if (b[0] == 'T') { + c->f[CE_SECURE] = b; + c->l[CE_SECURE] = 1; + } + break; + + case LWSC_NSC_VALUE: + c->f[CE_VALUE] = b; + c->l[CE_VALUE] = n + 1; + + for (n = 0; n < LWS_ARRAY_SIZE(c->f); n++) + lwsl_cookie("%s: %d: %.*s\n", __func__, + (int)n, (int)c->l[n], c->f[n]); + + return 0; + default: + return -1; + } + + b += n + 1; + n = 0; + state++; + } + + return -1; +} + +static int +lws_cookie_write_nsc(struct lws *wsi, struct lws_cookie *c) +{ + char cache_name[LWS_COOKIE_MAX_CACHE_NAME_LEN]; + const char *ads, *path; + struct lws_cache_ttl_lru *l1; + struct client_info_stash *stash; + char *cookie_string = NULL, *dl; + /* 6 tabs + 20 for max time_t + 2 * TRUE/FALSE + null */ + size_t size = 6 + 20 + 10 + 1; + time_t expires = 0; + int ret = 0; + + if (!wsi || !c) + return -1; + + l1 = wsi->a.context->l1; + if (!l1 || !wsi->a.context->nsc) + return -1; + + stash = wsi->stash ? wsi->stash : lws_get_network_wsi(wsi)->stash; + if (stash) { + ads = stash->cis[CIS_ADDRESS]; + path = stash->cis[CIS_PATH]; + } else { + ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS); + path = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI); + } + if (!ads || !path) + return -1; + + if (!c->f[CE_NAME] || !c->f[CE_VALUE]) { + lwsl_err("%s: malformed c\n", __func__); + + return -1; + } + + if (!c->f[CE_EXPIRES]) { + /* + * Currently we just take the approach to reject session cookies + */ + lwsl_warn("%s: reject session cookies\n", __func__); + + return 0; + } + + if (!c->f[CE_DOMAIN]) { + c->f[CE_HOSTONLY] = "T"; + c->l[CE_HOSTONLY] = 1; + c->f[CE_DOMAIN] = ads; + c->l[CE_DOMAIN] = strlen(ads); + } + + if (!c->f[CE_PATH]) { + c->f[CE_PATH] = path; + c->l[CE_PATH] = strlen(path); + dl = memchr(c->f[CE_PATH], '?', c->l[CE_PATH]); + if (dl) + c->l[CE_PATH] = (size_t)(dl - c->f[CE_PATH]); + } + + if (lws_cookie_compile_cache_name(cache_name, sizeof(cache_name), c)) + return -1; + + if (c->f[CE_EXPIRES] && + lws_cookie_parse_date(c->f[CE_EXPIRES], c->l[CE_EXPIRES], &expires)) { + lwsl_err("%s: can't parse date %.*s\n", __func__, + (int)c->l[CE_EXPIRES], c->f[CE_EXPIRES]); + return -1; + } + + size += c->l[CE_NAME] + c->l[CE_VALUE] + c->l[CE_DOMAIN] + c->l[CE_PATH]; + cookie_string = (char *)lws_malloc(size, __func__); + if (!cookie_string) { + lwsl_err("%s: OOM\n",__func__); + + return -1; + } + + lws_snprintf(cookie_string, size, LWS_COOKIE_NSC_FORMAT, + (int)c->l[CE_DOMAIN], c->f[CE_DOMAIN], + c->f[CE_HOSTONLY] ? "TRUE" : "FALSE", + (int)c->l[CE_PATH], c->f[CE_PATH], + c->f[CE_SECURE] ? "TRUE" : "FALSE", + (unsigned long long)expires, + (int)c->l[CE_NAME], c->f[CE_NAME], + (int)c->l[CE_VALUE], c->f[CE_VALUE]); + + lwsl_cookie("%s: name %s\n", __func__, cache_name); + lwsl_cookie("%s: c %s\n", __func__, cookie_string); + + if (lws_cache_write_through(l1, cache_name, + (const uint8_t *)cookie_string, + strlen(cookie_string), + (lws_usec_t)((unsigned long long)expires * + (lws_usec_t)LWS_US_PER_SEC), NULL)) { + ret = -1; + goto exit; + } + +#if defined(LWS_COOKIE_DEBUG) + char *po; + if (lws_cache_item_get(l1, cache_name, (const void **)&po, &size) || + size != strlen(cookie_string) || memcmp(po, cookie_string, size)) { + lwsl_err("%s: L1 '%s' missing\n", __func__, cache_name); + } + + if (lws_cache_item_get(wsi->a.context->nsc, cache_name, + (const void **)&po, &size) || + size != strlen(cookie_string) || + memcmp(po, cookie_string, size)) { + lwsl_err("%s: NSC '%s' missing, size %llu, po %s\n", __func__, + cache_name, (unsigned long long)size, po); + } +#endif + +exit: + lws_free(cookie_string); + + return ret; +} + +static int +lws_cookie_attach_cookies(struct lws *wsi, char *buf, char *end) +{ + const char *domain, *path, *dl_domain, *dl_path, *po; + char cache_name[LWS_COOKIE_MAX_CACHE_NAME_LEN]; + size_t domain_len, path_len, size, ret = 0; + struct lws_cache_ttl_lru *l1; + struct client_info_stash *stash; + lws_cache_results_t cr; + struct lws_cookie c; + int hostdomain = 1; + char *p, *p1; + + if (!wsi) + return -1; + + stash = wsi->stash ? wsi->stash : lws_get_network_wsi(wsi)->stash; + if (!stash || !stash->cis[CIS_ADDRESS] || + !stash->cis[CIS_PATH]) + return -1; + + l1 = wsi->a.context->l1; + if (!l1 || !wsi->a.context->nsc){ + lwsl_err("%s:no cookiejar\n", __func__); + return -1; + } + + memset(&c, 0, sizeof(c)); + + domain = stash->cis[CIS_ADDRESS]; + path = stash->cis[CIS_PATH]; + + if (!domain || !path) + return -1; + + path_len = strlen(path); + + /* remove query string if exist */ + dl_path = memchr(path, '?', path_len); + if (dl_path) + path_len = lws_ptr_diff_size_t(dl_path, path); + + /* remove last slash if exist */ + if (path_len != 1 && path[path_len - 1] == '/') + path_len--; + + if (!path_len) + return -1; + + lwsl_cookie("%s: path %.*s len %d\n", __func__, (int)path_len, path, (int)path_len); + + /* when dest buf is not provided, we only return size of cookie string */ + if (!buf || !end) + p = NULL; + else + p = buf; + + /* iterate through domain and path levels to find matching cookies */ + dl_domain = domain; + while (dl_domain) { + domain_len = strlen(domain); + dl_domain = memchr(domain, '.', domain_len); + /* don't match top level domain */ + if (!dl_domain) + break; + + if (domain_len + path_len + 6 > sizeof(cache_name)) + return -1; + + /* compile key string "[domain]|[path]|*"" */ + p1 = cache_name; + memcpy(p1, domain, domain_len); + p1 += domain_len; + *p1 = '|'; + p1++; + memcpy(p1, path, path_len); + p1 += path_len; + *p1 = '|'; + p1++; + *p1 = '*'; + p1++; + *p1 = '\0'; + + lwsl_cookie("%s: looking for %s\n", __func__, cache_name); + + if (!lws_cache_lookup(l1, cache_name, + (const void **)&cr.ptr, &cr.size)) { + + while (!lws_cache_results_walk(&cr)) { + lwsl_cookie(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + if (lws_cache_item_get(l1, (const char *)cr.tag, + (const void **)&po, &size) || + lws_cookie_parse_nsc(&c, po, size)) { + lwsl_err("%s: failed to get c '%s'\n", + __func__, cr.tag); + break; + } + + if (c.f[CE_HOSTONLY] && !hostdomain){ + lwsl_cookie("%s: not sending this\n", + __func__); + continue; + } + + if (p) { + if (ret) { + *p = ';'; + p++; + *p = ' '; + p++; + } + + memcpy(p, c.f[CE_NAME], c.l[CE_NAME]); + p += c.l[CE_NAME]; + *p = '='; + p++; + memcpy(p, c.f[CE_VALUE], c.l[CE_VALUE]); + p += c.l[CE_VALUE]; + } + + if (ret) + ret += 2; + ret += c.l[CE_NAME] + 1 + c.l[CE_VALUE]; + + } + } + + domain = dl_domain + 1; + hostdomain = 0; + } + + lwsl_notice("%s: c len (%d)\n", __func__, (int)ret); + + return (int)ret; +} + +static struct { + const char *const name; + uint8_t len; +} cft[] = { + { "domain=", 7 }, + { "path=", 5 }, + { "expires=", 8 }, + { "max-age=", 8 }, + { "httponly", 8 }, + { "secure", 6 } +}; + +int +lws_parse_set_cookie(struct lws *wsi) +{ + char *tk_head, *tk_end, *buf_head, *buf_end, *cookiep, *dl; + struct lws_cache_ttl_lru *l1; + struct lws_cookie c; + size_t fl; + int f, n; + + if (!wsi) + return -1; + + l1 = wsi->a.context->l1; + if (!l1) + return -1; + + f = wsi->http.ah->frag_index[WSI_TOKEN_HTTP_SET_COOKIE]; + + while (f) { + cookiep = wsi->http.ah->data + wsi->http.ah->frags[f].offset; + fl = wsi->http.ah->frags[f].len; + f = wsi->http.ah->frags[f].nfrag; + + if (!cookiep || !fl) + continue; + +#if defined(LWS_COOKIE_DEBUG) + lwsl_notice("%s:parsing: %.*s\n", __func__, (int)fl, cookiep); +#endif + + buf_head = cookiep; + buf_end = cookiep + fl - 1; + memset(&c, 0, sizeof(struct lws_cookie)); + + do { + tk_head = buf_head; + tk_end = memchr(buf_head, ';', + (size_t)(buf_end - buf_head + 1)); + if (!tk_end) { + tk_end = buf_end; + buf_head = buf_end; + } else { + buf_head = tk_end + 1; + tk_end--; + } + + if (c.f[CE_NAME]) + goto parse_av; + + /* + * find name value, remove leading trailing + * WS and DQ for value + */ + + dl = memchr(tk_head, '=', lws_ptr_diff_size_t(tk_end, + tk_head + 1)); + if (!dl || dl == tk_head) + return -1; + + c.f[CE_NAME] = tk_head; + c.l[CE_NAME] = lws_ptr_diff_size_t(dl, tk_head); + lws_cookie_rm_sws(&c.f[CE_NAME], &c.l[CE_NAME]); + + if (!c.l[CE_NAME]) + return -1; + + lwsl_cookie("%s: c name l %d v:%.*s\n", __func__, + (int)c.l[CE_NAME], + (int)c.l[CE_NAME], c.f[CE_NAME]); + c.f[CE_VALUE] = dl + 1; + c.l[CE_VALUE] = lws_ptr_diff_size_t(tk_end, + c.f[CE_VALUE]) + 1; + + lws_cookie_rm_sws(&c.f[CE_VALUE], &c.l[CE_VALUE]); + if (c.l[CE_VALUE] >= 2 && c.f[CE_VALUE][0] == '\"') { + c.f[CE_VALUE]++; + c.l[CE_VALUE] -= 2; + } + lwsl_cookie("%s: c value l %d v:%.*s\n", __func__, + (int)c.l[CE_VALUE], (int)c.l[CE_VALUE], + c.f[CE_VALUE]); + continue; + +parse_av: + while (*tk_head == ' ') { + if (tk_head == tk_end) + return -1; + + tk_head++; + } + + for (n = 0; n < (int)LWS_ARRAY_SIZE(cft); n++) { + if (lws_tolower(*tk_head) != cft[n].name[0]) + continue; + + if (!is_iprefix(tk_head, + lws_ptr_diff_size_t(tk_end, + tk_head) + 1, + cft[n].name, cft[n].len)) + continue; + + if (n == 4 || n == 5) { + c.f[n] = "T"; + c.l[n] = 1; + break; + } + + c.f[n] = tk_head + cft[n].len; + c.l[n] = lws_ptr_diff_size_t(tk_end, c.f[n]) + 1; + lws_cookie_rm_sws(&c.f[n], &c.l[n]); + + if (n == CE_DOMAIN && c.l[0] && + c.f[n][0] == '.'){ + c.f[n]++; + c.l[n]--; + } + + lwsl_cookie("%s: %s l %d v:%.*s\n", __func__, + cft[n].name, (int)c.l[n], + (int)c.l[n], c.f[n]); + break; + } + + } while (tk_end != buf_end); + + if (lws_cookie_write_nsc(wsi, &c)) + lwsl_err("%s:failed to write nsc\n", __func__); + } + + return 0; +} + +int +lws_cookie_send_cookies(struct lws *wsi, char **pp, char *end) +{ + char *p; + int size; + + if (!wsi || !pp || !(*pp) || !end) + return -1; + + size = lws_cookie_attach_cookies(wsi, NULL, NULL); + + if (!size) + return 0; + if (size < 0) { + lwsl_err("%s:failed to get cookie string size\n", __func__); + return -1; + } + + lwsl_notice("%s: size %d\n", __func__, size); + +#if defined(LWS_COOKIE_DEBUG) + char *p_dbg = *pp; +#endif + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COOKIE, NULL, size, + (unsigned char **)pp, (unsigned char *)end)) + return -1; + +#if defined(LWS_COOKIE_DEBUG) + lwsl_notice("%s: dummy copy (%.*s) \n", __func__, (int)(*pp - p_dbg), p_dbg); +#endif + + +#ifdef LWS_WITH_HTTP2 + if (lws_wsi_is_h2(wsi)) + p = *pp - size; + else +#endif + p = *pp - size - 2; + + if (lws_cookie_attach_cookies(wsi, p, p + size) <= 0) { + lwsl_err("%s:failed to attach cookies\n", __func__); + return -1; + } + +#if defined(LWS_COOKIE_DEBUG) + lwsl_notice("%s: real copy (%.*s) total len %d\n", __func__, (int)(*pp - p_dbg), p_dbg, (int)(*pp - p_dbg)); + lwsl_hexdump_notice(p_dbg, (size_t)(*pp - p_dbg)); +#endif + + return 0; +} diff --git a/3rdparty/libwebsockets/lib/roles/http/date.c b/3rdparty/libwebsockets/lib/roles/http/date.c index 0b0012b6..6ac42ba9 100644 --- a/3rdparty/libwebsockets/lib/roles/http/date.c +++ b/3rdparty/libwebsockets/lib/roles/http/date.c @@ -139,7 +139,16 @@ lws_http_date_parse_unix(const char *b, size_t len, time_t *t) if (lws_http_date_parse(b, len, &tm)) return -1; +#if defined(WIN32) + *t = _mkgmtime(&tm); +#else +#if defined(LWS_HAVE_TIMEGM) + *t = timegm(&tm); +#else + /* this is a poor fallback since it uses localtime zone */ *t = mktime(&tm); +#endif +#endif return (int)*t == -1 ? -1 : 0; } diff --git a/3rdparty/libwebsockets/lib/roles/http/header.c b/3rdparty/libwebsockets/lib/roles/http/header.c index 83983a57..032bf6bd 100644 --- a/3rdparty/libwebsockets/lib/roles/http/header.c +++ b/3rdparty/libwebsockets/lib/roles/http/header.c @@ -52,7 +52,7 @@ lws_http_string_to_known_header(const char *s, size_t slen) } #ifdef LWS_WITH_HTTP2 -static int +int lws_wsi_is_h2(struct lws *wsi) { return wsi->upgraded_to_http2 || @@ -78,16 +78,22 @@ lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name, (void)wsi; #endif if (name) { - while (*p < end && *name) + char has_colon = 0; + while (*p < end && *name) { + has_colon = has_colon || *name == ':'; *((*p)++) = *name++; - if (*p == end) + } + if (*p + (has_colon ? 1 : 2) >= end) return 1; + if (!has_colon) + *((*p)++) = ':'; *((*p)++) = ' '; } if (*p + length + 3 >= end) return 1; - memcpy(*p, value, (unsigned int)length); + if (value) + memcpy(*p, value, (unsigned int)length); *p += length; *((*p)++) = '\x0d'; *((*p)++) = '\x0a'; diff --git a/3rdparty/libwebsockets/lib/roles/http/parsers.c b/3rdparty/libwebsockets/lib/roles/http/parsers.c index cb405fd7..220f9cf8 100644 --- a/3rdparty/libwebsockets/lib/roles/http/parsers.c +++ b/3rdparty/libwebsockets/lib/roles/http/parsers.c @@ -490,8 +490,8 @@ int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h) len += wsi->http.ah->frags[n].len; n = wsi->http.ah->frags[n].nfrag; - if (n && h != WSI_TOKEN_HTTP_COOKIE) - ++len; + if (n) + len++; } while (n); @@ -532,9 +532,7 @@ int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len, int lws_hdr_copy(struct lws *wsi, char *dst, int len, enum lws_token_indexes h) { - int toklen = lws_hdr_total_length(wsi, h); - int n; - int comma; + int toklen = lws_hdr_total_length(wsi, h), n, comma; *dst = '\0'; if (!toklen) @@ -547,17 +545,16 @@ int lws_hdr_copy(struct lws *wsi, char *dst, int len, return -1; n = wsi->http.ah->frag_index[h]; - if (h == WSI_TOKEN_HTTP_URI_ARGS) - lwsl_err("%s: WSI_TOKEN_HTTP_URI_ARGS start frag %d\n", __func__, n); - - if (!n) return 0; do { comma = (wsi->http.ah->frags[n].nfrag) ? 1 : 0; if (h == WSI_TOKEN_HTTP_URI_ARGS) - lwsl_notice("%s: WSI_TOKEN_HTTP_URI_ARGS '%.*s'\n", __func__, (int)wsi->http.ah->frags[n].len, &wsi->http.ah->data[wsi->http.ah->frags[n].offset]); + lwsl_notice("%s: WSI_TOKEN_HTTP_URI_ARGS '%.*s'\n", + __func__, (int)wsi->http.ah->frags[n].len, + &wsi->http.ah->data[ + wsi->http.ah->frags[n].offset]); if (wsi->http.ah->frags[n].len + comma >= len) { lwsl_notice("blowout len\n"); @@ -569,14 +566,22 @@ int lws_hdr_copy(struct lws *wsi, char *dst, int len, len -= wsi->http.ah->frags[n].len; n = wsi->http.ah->frags[n].nfrag; + /* + * Note if you change this logic, take care about updating len + * and make sure lws_hdr_total_length() gives the same resulting + * length + */ + if (comma) { - if (h == WSI_TOKEN_HTTP_COOKIE || h == WSI_TOKEN_HTTP_SET_COOKIE) + if (h == WSI_TOKEN_HTTP_COOKIE || + h == WSI_TOKEN_HTTP_SET_COOKIE) *dst++ = ';'; else if (h == WSI_TOKEN_HTTP_URI_ARGS) *dst++ = '&'; else *dst++ = ','; + len--; } } while (n); @@ -646,6 +651,31 @@ lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, return -1; } + +int +lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb, + void *custom) +{ + ah_data_idx_t ll; + + if (!wsi->http.ah || wsi->mux_substream) + return -1; + + ll = wsi->http.ah->unk_ll_head; + + while (ll) { + if (ll >= wsi->http.ah->data_length) + return -1; + + cb(&wsi->http.ah->data[ll + UHO_NAME], + lws_ser_ru16be((uint8_t *)&wsi->http.ah->data[ll + UHO_NLEN]), + custom); + + ll = lws_ser_ru32be((uint8_t *)&wsi->http.ah->data[ll + UHO_LL]); + } + + return 0; +} #endif char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h) @@ -1562,7 +1592,7 @@ lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, p += bl; n -= (int)bl; - while (n-- > (int)bl) { + while (n-- > 0) { if (*p == '=' && !memcmp(p - bl, name, (unsigned int)bl)) { p++; while (*p != ';' && n-- && max) { diff --git a/3rdparty/libwebsockets/lib/roles/http/server/access-log.c b/3rdparty/libwebsockets/lib/roles/http/server/access-log.c index 98b13284..15520193 100644 --- a/3rdparty/libwebsockets/lib/roles/http/server/access-log.c +++ b/3rdparty/libwebsockets/lib/roles/http/server/access-log.c @@ -96,7 +96,7 @@ lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int uri_len, int met nwsi = lws_get_network_wsi(wsi); - if (wsi->sa46_peer.sa4.sin_family) + if (nwsi->sa46_peer.sa4.sin_family) lws_sa46_write_numeric_address(&nwsi->sa46_peer, ta, sizeof(ta)); else strncpy(ta, "unknown", sizeof(ta)); diff --git a/3rdparty/libwebsockets/lib/roles/http/server/lejp-conf.c b/3rdparty/libwebsockets/lib/roles/http/server/lejp-conf.c index 6970c19b..0f979cf2 100644 --- a/3rdparty/libwebsockets/lib/roles/http/server/lejp-conf.c +++ b/3rdparty/libwebsockets/lib/roles/http/server/lejp-conf.c @@ -71,7 +71,6 @@ enum lejp_global_paths { static const char * const paths_vhosts[] = { "vhosts[]", - "vhosts[].mounts[]", "vhosts[].name", "vhosts[].port", "vhosts[].interface", @@ -89,13 +88,17 @@ static const char * const paths_vhosts[] = { "vhosts[].mounts[].auth-mask", "vhosts[].mounts[].cgi-timeout", "vhosts[].mounts[].cgi-env[].*", + "vhosts[].mounts[].cgi-env[]", "vhosts[].mounts[].cache-max-age", "vhosts[].mounts[].cache-reuse", "vhosts[].mounts[].cache-revalidate", "vhosts[].mounts[].basic-auth", "vhosts[].mounts[].cache-intermediaries", "vhosts[].mounts[].extra-mimetypes.*", + "vhosts[].mounts[].extra-mimetypes", "vhosts[].mounts[].interpret.*", + "vhosts[].mounts[].interpret", + "vhosts[].mounts[]", "vhosts[].ws-protocols[].*.*", "vhosts[].ws-protocols[].*", "vhosts[].ws-protocols[]", @@ -108,6 +111,7 @@ static const char * const paths_vhosts[] = { "vhosts[].ssl-option-set", "vhosts[].ssl-option-clear", "vhosts[].mounts[].pmo[].*", + "vhosts[].mounts[].pmo[]", "vhosts[].headers[].*", "vhosts[].headers[]", "vhosts[].client-ssl-key", @@ -119,6 +123,7 @@ static const char * const paths_vhosts[] = { "vhosts[].ignore-missing-cert", "vhosts[].error-document-404", "vhosts[].alpn", + "vhosts[].fo-listen-queue", "vhosts[].ssl-client-option-set", "vhosts[].ssl-client-option-clear", "vhosts[].tls13-ciphers", @@ -139,7 +144,6 @@ static const char * const paths_vhosts[] = { enum lejp_vhost_paths { LEJPVP, - LEJPVP_MOUNTS, LEJPVP_NAME, LEJPVP_PORT, LEJPVP_INTERFACE, @@ -157,13 +161,19 @@ enum lejp_vhost_paths { LEJPVP_DEFAULT_AUTH_MASK, LEJPVP_CGI_TIMEOUT, LEJPVP_CGI_ENV, + LEJPVP_CGI_ENV_base, LEJPVP_MOUNT_CACHE_MAX_AGE, LEJPVP_MOUNT_CACHE_REUSE, LEJPVP_MOUNT_CACHE_REVALIDATE, LEJPVP_MOUNT_BASIC_AUTH, LEJPVP_MOUNT_CACHE_INTERMEDIARIES, LEJPVP_MOUNT_EXTRA_MIMETYPES, + LEJPVP_MOUNT_EXTRA_MIMETYPES_base, LEJPVP_MOUNT_INTERPRET, + LEJPVP_MOUNT_INTERPRET_base, + + LEJPVP_MOUNTS, + LEJPVP_PROTOCOL_NAME_OPT, LEJPVP_PROTOCOL_NAME, LEJPVP_PROTOCOL, @@ -176,6 +186,7 @@ enum lejp_vhost_paths { LEJPVP_SSL_OPTION_SET, LEJPVP_SSL_OPTION_CLEAR, LEJPVP_PMO, + LEJPVP_PM_baseO, LEJPVP_HEADERS_NAME, LEJPVP_HEADERS, LEJPVP_CLIENT_SSL_KEY, @@ -187,6 +198,7 @@ enum lejp_vhost_paths { LEJPVP_IGNORE_MISSING_CERT, LEJPVP_ERROR_DOCUMENT_404, LEJPVP_ALPN, + LWJPVP_FO_LISTEN_QUEUE, LEJPVP_SSL_CLIENT_OPTION_SET, LEJPVP_SSL_CLIENT_OPTION_CLEAR, LEJPVP_TLS13_CIPHERS, @@ -693,6 +705,9 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) case LEJPVP_CGI_TIMEOUT: a->m.cgi_timeout = atoi(ctx->buf); return 0; + case LWJPVP_FO_LISTEN_QUEUE: + a->info->fo_listen_queue = atoi(ctx->buf); + return 0; case LEJPVP_KEEPALIVE_TIMEOUT: a->info->keepalive_timeout = atoi(ctx->buf); return 0; @@ -932,6 +947,8 @@ lwsws_get_config(void *user, const char *f, const char * const *paths, struct lejp_ctx ctx; int n, m = 0, fd; + memset(&ctx, 0, sizeof(ctx)); + fd = lws_open(f, O_RDONLY); if (fd < 0) { lwsl_err("Cannot open %s\n", f); diff --git a/3rdparty/libwebsockets/lib/roles/http/server/lws-spa.c b/3rdparty/libwebsockets/lib/roles/http/server/lws-spa.c index 61d6d40d..a39c6613 100644 --- a/3rdparty/libwebsockets/lib/roles/http/server/lws-spa.c +++ b/3rdparty/libwebsockets/lib/roles/http/server/lws-spa.c @@ -439,11 +439,11 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, case MT_IGNORE3: if (*in == '\x0d') s->state = MT_IGNORE1; - if (*in == '-') { + else if (*in == '-') { s->state = MT_COMPLETED; s->wsi->http.rx_content_remain = 0; } - in++; + else in++; break; case MT_COMPLETED: break; diff --git a/3rdparty/libwebsockets/lib/roles/http/server/server.c b/3rdparty/libwebsockets/lib/roles/http/server/server.c index b05e949e..c98bf0d6 100644 --- a/3rdparty/libwebsockets/lib/roles/http/server/server.c +++ b/3rdparty/libwebsockets/lib/roles/http/server/server.c @@ -24,6 +24,10 @@ #include "private-lib-core.h" +#if !defined(SOL_TCP) && defined(IPPROTO_TCP) +#define SOL_TCP IPPROTO_TCP +#endif + const char * const method_names[] = { "GET", "POST", #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) @@ -48,73 +52,84 @@ static const char * const intermediates[] = { "private", "public" }; */ #if defined(LWS_WITH_SERVER) + +struct vh_sock_args { + const struct lws_context_creation_info *info; + struct lws_vhost *vhost; + int af; +}; + + +static int +check_extant(struct lws_dll2 *d, void *user) +{ + struct lws *wsi = lws_container_of(d, struct lws, listen_list); + struct vh_sock_args *a = (struct vh_sock_args *)user; + + if (!lws_vhost_compare_listen(wsi->a.vhost, a->vhost)) + return 0; + + if (wsi->af != a ->af) + return 0; + + lwsl_notice(" using listen skt from vhost %s\n", wsi->a.vhost->name); + + return 1; +} + +/* + * Creates a single listen socket of a specific AF + */ + int -_lws_vhost_init_server(const struct lws_context_creation_info *info, - struct lws_vhost *vhost) +_lws_vhost_init_server_af(struct vh_sock_args *a) { + struct lws_context *cx = a->vhost->context; struct lws_context_per_thread *pt; int n, opt = 1, limit = 1; lws_sockfd_type sockfd; - struct lws_vhost *vh; struct lws *wsi; int m = 0, is; +#if defined(LWS_WITH_IPV6) + int value = 1; +#endif (void)method_names; (void)opt; - if (info) { - vhost->iface = info->iface; - vhost->listen_port = info->port; - } - - /* set up our external listening socket we serve on */ + lwsl_info("%s: af %d\n", __func__, (int)a->af); - if (vhost->listen_port == CONTEXT_PORT_NO_LISTEN || - vhost->listen_port == CONTEXT_PORT_NO_LISTEN_SERVER) + if (lws_vhost_foreach_listen_wsi(a->vhost->context, a, check_extant)) return 0; - vh = vhost->context->vhost_list; - while (vh) { - if (vh->listen_port == vhost->listen_port) { - if (((!vhost->iface && !vh->iface) || - (vhost->iface && vh->iface && - !strcmp(vhost->iface, vh->iface))) && - vh->lserv_wsi - ) { - lwsl_notice(" using listen skt from vhost %s\n", - vh->name); - return 0; - } - } - vh = vh->vhost_next; - } +deal: + + if (a->vhost->iface) { - if (vhost->iface) { /* * let's check before we do anything else about the disposition * of the interface he wants to bind to... */ - is = lws_socket_bind(vhost, NULL, LWS_SOCK_INVALID, - vhost->listen_port, vhost->iface, 1); + is = lws_socket_bind(a->vhost, NULL, LWS_SOCK_INVALID, + a->vhost->listen_port, a->vhost->iface, + a->af); lwsl_debug("initial if check says %d\n", is); if (is == LWS_ITOSA_BUSY) /* treat as fatal */ return -1; -deal: - lws_start_foreach_llp(struct lws_vhost **, pv, - vhost->context->no_listener_vhost_list) { - if (is >= LWS_ITOSA_USABLE && *pv == vhost) { + cx->no_listener_vhost_list) { + if (is >= LWS_ITOSA_USABLE && *pv == a->vhost) { /* on the list and shouldn't be: remove it */ lwsl_debug("deferred iface: removing vh %s\n", (*pv)->name); - *pv = vhost->no_listener_vhost_list; - vhost->no_listener_vhost_list = NULL; + *pv = a->vhost->no_listener_vhost_list; + a->vhost->no_listener_vhost_list = NULL; goto done_list; } - if (is < LWS_ITOSA_USABLE && *pv == vhost) + if (is < LWS_ITOSA_USABLE && *pv == a->vhost) goto done_list; } lws_end_foreach_llp(pv, no_listener_vhost_list); @@ -124,10 +139,11 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, /* ... but needs to be: so add it */ - lwsl_debug("deferred iface: adding vh %s\n", vhost->name); - vhost->no_listener_vhost_list = - vhost->context->no_listener_vhost_list; - vhost->context->no_listener_vhost_list = vhost; + lwsl_debug("deferred iface: adding vh %s\n", + a->vhost->name); + a->vhost->no_listener_vhost_list = + cx->no_listener_vhost_list; + cx->no_listener_vhost_list = a->vhost; } done_list: @@ -137,66 +153,61 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, break; case LWS_ITOSA_NOT_EXIST: /* can't add it */ - if (info) /* first time */ - lwsl_err("VH %s: iface %s port %d DOESN'T EXIST\n", - vhost->name, vhost->iface, vhost->listen_port); - else + if (!a->info) return -1; - return (info->options & LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND) == - LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND? + + /* first time */ + lwsl_err("%s: VH %s: iface %s port %d DOESN'T EXIST\n", + __func__, a->vhost->name, a->vhost->iface, + a->vhost->listen_port); + + return (a->info->options & + LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND) == + LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND ? -1 : 1; + case LWS_ITOSA_NOT_USABLE: /* can't add it */ - if (info) /* first time */ - lwsl_err("VH %s: iface %s port %d NOT USABLE\n", - vhost->name, vhost->iface, vhost->listen_port); - else + if (!a->info) /* first time */ return -1; - return (info->options & LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND) == - LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND? + + lwsl_err("%s: VH %s: iface %s port %d NOT USABLE\n", + __func__, a->vhost->name, a->vhost->iface, + a->vhost->listen_port); + + return (a->info->options & + LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND) == + LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND ? -1 : 1; } } (void)n; #if defined(__linux__) -#ifdef LWS_WITH_UNIX_SOCK /* - * A Unix domain sockets cannot be bound for several times, even if we set - * the SO_REUSE* options on. - * However, fortunately, each thread is able to independently listen when - * running on a reasonably new Linux kernel. So we can safely assume - * creating just one listening socket for a multi-threaded environment won't - * fail in most cases. + * A Unix domain sockets cannot be bound multiple times, even if we + * set the SO_REUSE* options on. + * + * However on recent linux, each thread is able to independently listen. + * + * So we can assume creating just one listening socket for a multi- + * threaded environment will typically work. */ - if (!LWS_UNIX_SOCK_ENABLED(vhost)) -#endif - limit = vhost->context->count_threads; + if (a->af != AF_UNIX) + limit = cx->count_threads; #endif for (m = 0; m < limit; m++) { - if (lws_fi(&vhost->fic, "listenskt")) { - sockfd = LWS_SOCK_INVALID; - } else { - -#ifdef LWS_WITH_UNIX_SOCK - if (LWS_UNIX_SOCK_ENABLED(vhost)) - sockfd = socket(AF_UNIX, SOCK_STREAM, 0); - else -#endif -#ifdef LWS_WITH_IPV6 - if (LWS_IPV6_ENABLED(vhost)) - sockfd = socket(AF_INET6, SOCK_STREAM, 0); - else -#endif - sockfd = socket(AF_INET, SOCK_STREAM, 0); - } + sockfd = lws_fi(&a->vhost->fic, "listenskt") ? + LWS_SOCK_INVALID : + socket(a->af, SOCK_STREAM, 0); if (sockfd == LWS_SOCK_INVALID) { lwsl_err("ERROR opening socket\n"); return 1; } + #if !defined(LWS_PLAT_FREERTOS) #if (defined(WIN32) || defined(_WIN32)) && defined(SO_EXCLUSIVEADDRUSE) /* @@ -206,7 +217,7 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, * * for lws, to match Linux, we default to exclusive listen */ - if (!lws_check_opt(vhost->options, + if (!lws_check_opt(a->vhost->options, LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE)) { if (setsockopt(sockfd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const void *)&opt, sizeof(opt)) < 0) { @@ -228,15 +239,17 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, } #if defined(LWS_WITH_IPV6) && defined(IPV6_V6ONLY) - if (LWS_IPV6_ENABLED(vhost) && - vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY) { - int value = (vhost->options & - LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE) ? 1 : 0; - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, - (const void*)&value, sizeof(value)) < 0) { - compatible_close(sockfd); - return -1; - } + /* + * If we have an ipv6 listen socket, it only accepts ipv6. + * + * There will be a separate ipv4 listen socket if that's + * enabled. + */ + if (a->af == AF_INET6 && + setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, + (const void*)&value, sizeof(value)) < 0) { + compatible_close(sockfd); + return -1; } #endif @@ -245,10 +258,10 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, #if LWS_MAX_SMP > 1 n = 1; #else - n = lws_check_opt(vhost->options, + n = lws_check_opt(a->vhost->options, LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE); #endif - if (n && vhost->context->count_threads > 1) + if (n || cx->count_threads > 1) /* ... also implied by threads > 1 */ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const void *)&opt, sizeof(opt)) < 0) { compatible_close(sockfd); @@ -256,10 +269,12 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, } #endif #endif - lws_plat_set_socket_options(vhost, sockfd, 0); + lws_plat_set_socket_options(a->vhost, sockfd, 0); + + is = lws_socket_bind(a->vhost, NULL, sockfd, + a->vhost->listen_port, + a->vhost->iface, a->af); - is = lws_socket_bind(vhost, NULL, sockfd, vhost->listen_port, - vhost->iface, 1); if (is == LWS_ITOSA_BUSY) { /* treat as fatal */ compatible_close(sockfd); @@ -275,75 +290,105 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, if (is < 0) { lwsl_info("%s: lws_socket_bind says %d\n", __func__, is); compatible_close(sockfd); - goto deal; + if (a->vhost->iface) + goto deal; + return -1; } /* * Create the listen wsi and customize it */ - lws_context_lock(vhost->context, __func__); - wsi = __lws_wsi_create_with_role(vhost->context, m, &role_ops_listen); - lws_context_unlock(vhost->context); + lws_context_lock(cx, __func__); + wsi = __lws_wsi_create_with_role(cx, m, &role_ops_listen, NULL); + lws_context_unlock(cx); if (wsi == NULL) { lwsl_err("Out of mem\n"); goto bail; } + wsi->af = (uint8_t)a->af; + #ifdef LWS_WITH_UNIX_SOCK - if (!LWS_UNIX_SOCK_ENABLED(vhost)) + if (!LWS_UNIX_SOCK_ENABLED(a->vhost)) #endif { wsi->unix_skt = 1; - vhost->listen_port = is; + a->vhost->listen_port = is; lwsl_debug("%s: lws_socket_bind says %d\n", __func__, is); } wsi->desc.sockfd = sockfd; - wsi->a.protocol = vhost->protocols; - lws_vhost_bind_wsi(vhost, wsi); + wsi->a.protocol = a->vhost->protocols; + lws_vhost_bind_wsi(a->vhost, wsi); wsi->listener = 1; 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]; + pt = &cx->pt[m]; lws_pt_lock(pt, __func__); - if (__insert_wsi_socket_into_fds(vhost->context, wsi)) { + if (__insert_wsi_socket_into_fds(cx, wsi)) { lwsl_notice("inserting wsi socket into fds failed\n"); lws_pt_unlock(pt); goto bail; } - vhost->lserv_wsi = wsi; + lws_dll2_add_tail(&wsi->listen_list, &a->vhost->listen_wsi); lws_pt_unlock(pt); +#if defined(WIN32) && defined(TCP_FASTOPEN) + if (a->vhost->fo_listen_queue) { + int optval = 1; + if (setsockopt(wsi->desc.sockfd, IPPROTO_TCP, + TCP_FASTOPEN, + (const char*)&optval, sizeof(optval)) < 0) { + int error = LWS_ERRNO; + lwsl_warn("%s: TCP_NODELAY failed with error %d\n", + __func__, error); + } + } +#else +#if defined(TCP_FASTOPEN) + if (a->vhost->fo_listen_queue) { + int qlen = a->vhost->fo_listen_queue; + + if (setsockopt(wsi->desc.sockfd, SOL_TCP, TCP_FASTOPEN, + &qlen, sizeof(qlen))) + lwsl_warn("%s: TCP_FASTOPEN failed\n", __func__); + } +#endif +#endif + n = listen(wsi->desc.sockfd, LWS_SOMAXCONN); if (n < 0) { lwsl_err("listen failed with error %d\n", LWS_ERRNO); - vhost->lserv_wsi = NULL; + lws_dll2_remove(&wsi->listen_list); __remove_wsi_socket_from_fds(wsi); goto bail; } if (wsi) - __lws_lc_tag(&vhost->context->lcg[LWSLCG_WSI], - &wsi->lc, "listen|%s|%s|%d", vhost->name, - vhost->iface ? vhost->iface : "", - (int)vhost->listen_port); + __lws_lc_tag(a->vhost->context, + &a->vhost->context->lcg[LWSLCG_WSI], + &wsi->lc, "listen|%s|%s|%d", + a->vhost->name, + a->vhost->iface ? a->vhost->iface : "", + (int)a->vhost->listen_port); } /* for each thread able to independently listen */ - if (!lws_check_opt(vhost->context->options, - LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) { + if (!lws_check_opt(cx->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) { #ifdef LWS_WITH_UNIX_SOCK - if (LWS_UNIX_SOCK_ENABLED(vhost)) - lwsl_info(" Listening on \"%s\"\n", vhost->iface); + if (a->af == AF_UNIX) + lwsl_info(" Listening on \"%s\"\n", a->vhost->iface); else #endif - lwsl_info(" Listening on port %d\n", vhost->listen_port); + lwsl_info(" Listening on %s:%d\n", + a->vhost->iface, + a->vhost->listen_port); } // info->port = vhost->listen_port; @@ -355,6 +400,102 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, return -1; } + + +int +_lws_vhost_init_server(const struct lws_context_creation_info *info, + struct lws_vhost *vhost) +{ + struct vh_sock_args a; + + a.info = info; + a.vhost = vhost; + + if (info) { + vhost->iface = info->iface; + vhost->listen_port = info->port; + } + + /* set up our external listening socket we serve on */ + + if (vhost->listen_port == CONTEXT_PORT_NO_LISTEN || + vhost->listen_port == CONTEXT_PORT_NO_LISTEN_SERVER) + return 0; + + /* + * Let's figure out what AF(s) we want this vhost to listen on. + * + * We want AF_UNIX alone if that's what's told + */ + +#if defined(LWS_WITH_UNIX_SOCK) + /* + * If unix socket, ask for that and we are done + */ + if (LWS_UNIX_SOCK_ENABLED(vhost)) { + a.af = AF_UNIX; + goto single; + } +#endif + + /* + * We may support both ipv4 and ipv6, but get a numeric vhost listen + * iface that is unambiguously ipv4 or ipv6, meaning we can only listen + * for the related AF then. + */ + + if (vhost->iface) { + uint8_t buf[16]; + int q; + + q = lws_parse_numeric_address(vhost->iface, buf, sizeof(buf)); + + if (q == 4) { + a.af = AF_INET; + goto single; + } + + if (q == 16) { +#if defined(LWS_WITH_IPV6) + if (LWS_IPV6_ENABLED(vhost)) { + a.af = AF_INET6; + goto single; + } +#endif + lwsl_err("%s: ipv6 not supported on %s\n", __func__, + vhost->name); + return 1; + } + } + + /* + * ... if we make it here, we would want to listen on AF_INET and + * AF_INET6 unless one or the other is forbidden + */ + +#if defined(LWS_WITH_IPV6) + if (!(LWS_IPV6_ENABLED(vhost) && + (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY) && + (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE))) { +#endif + a.af = AF_INET; + if (_lws_vhost_init_server_af(&a)) + return 1; + +#if defined(LWS_WITH_IPV6) + } + if (LWS_IPV6_ENABLED(vhost)) { + a.af = AF_INET6; + goto single; + } +#endif + + return 0; + +single: + return _lws_vhost_init_server_af(&a); +} + #endif struct lws_vhost * @@ -579,9 +720,13 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin, } #else #if defined(LWS_HAVE__STAT32I64) - if (_stat32i64(path, &st)) { - lwsl_info("unable to stat %s\n", path); - goto notfound; + { + WCHAR buf[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, buf, LWS_ARRAY_SIZE(buf)); + if (_wstat32i64(buf, &st)) { + lwsl_info("unable to stat %s\n", path); + goto notfound; + } } #else if (stat(path, &st)) { @@ -1103,10 +1248,13 @@ int lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, char *uri_ptr, char ws) { - char ads[96], rpath[256], host[96], *pcolon, *pslash, unix_skt = 0; + char ads[96], host[96], *pcolon, *pslash, unix_skt = 0; struct lws_client_connect_info i; struct lws *cwsi; int n, na; + unsigned int max_http_header_data = wsi->a.context->max_http_header_data > 256 ? + wsi->a.context->max_http_header_data : 256; + char *rpath = NULL; #if defined(LWS_ROLE_WS) if (ws) @@ -1173,7 +1321,13 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, if (pcolon) i.port = atoi(pcolon + 1); - n = lws_snprintf(rpath, sizeof(rpath) - 1, "/%s/%s", + rpath = lws_malloc(max_http_header_data, __func__); + if (!rpath) + return -1; + + /* rpath needs cleaning after this... ---> */ + + n = lws_snprintf(rpath, max_http_header_data - 1, "/%s/%s", pslash + 1, uri_ptr + hit->mountpoint_len) - 1; lws_clean_url(rpath); n = (int)strlen(rpath); @@ -1190,17 +1344,17 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, p = rpath + n; - if (na >= (int)sizeof(rpath) - n - 2) { + if (na >= (int)max_http_header_data - n - 2) { lwsl_info("%s: query string %d longer " "than we can handle\n", __func__, na); - + lws_free(rpath); return -1; } *p++ = '?'; budg = lws_hdr_copy(wsi, p, - (int)(&rpath[sizeof(rpath) - 1] - p), + (int)(&rpath[max_http_header_data - 1] - p), WSI_TOKEN_HTTP_URI_ARGS); if (budg > 0) p += budg; @@ -1224,9 +1378,8 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, #endif { n = lws_hdr_total_length(wsi, WSI_TOKEN_HOST); - if (n > 0) { + if (n > 0) i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST); - } } #if 0 @@ -1248,6 +1401,36 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, #endif ) i.method = "POST"; + else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PUT_URI) +#if defined(LWS_WITH_HTTP2) + || ( + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) && + !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), "put") + ) +#endif + ) + i.method = "PUT"; + else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PATCH_URI) +#if defined(LWS_WITH_HTTP2) + || ( + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) && + !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), "patch") + ) +#endif + ) + i.method = "PATCH"; + else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_DELETE_URI) +#if defined(LWS_WITH_HTTP2) + || ( + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) && + !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), "delete") + ) +#endif + ) + i.method = "DELETE"; else i.method = "GET"; } @@ -1290,9 +1473,10 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, "The server is temporarily unable to service " "your request due to maintenance downtime or " "capacity problems. Please try again later."); - + lws_free(rpath); return 1; } + lws_free(rpath); lwsl_info("%s: setting proxy clientside on %s (parent %s)\n", __func__, lws_wsi_tag(cwsi), lws_wsi_tag(lws_get_parent(cwsi))); @@ -1902,15 +2086,15 @@ lws_confirm_host_header(struct lws *wsi) port = 443; #endif - lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_DOT_NONTERM /* server.com */| - LWS_TOKENIZE_F_NO_FLOATS /* 1.server.com */| - LWS_TOKENIZE_F_MINUS_NONTERM /* a-b.com */); n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_HOST); if (n <= 0) { lwsl_info("%s: missing or oversize host header\n", __func__); return 1; } ts.len = (size_t)n; + lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_DOT_NONTERM /* server.com */| + LWS_TOKENIZE_F_NO_FLOATS /* 1.server.com */| + LWS_TOKENIZE_F_MINUS_NONTERM /* a-b.com */); if (lws_tokenize(&ts) != LWS_TOKZE_TOKEN) goto bad_format; @@ -2292,8 +2476,9 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) lws_h2_settings(wsi, &wsi->h2.h2n->peer_set, (uint8_t *)tbuf, n); - lws_hpack_dynamic_size(wsi, (int)wsi->h2.h2n->peer_set.s[ - H2SET_HEADER_TABLE_SIZE]); + if (lws_hpack_dynamic_size(wsi, (int)wsi->h2.h2n->peer_set.s[ + H2SET_HEADER_TABLE_SIZE])) + return 1; strcpy(tbuf, "HTTP/1.1 101 Switching Protocols\x0d\x0a" "Connection: Upgrade\x0d\x0a" @@ -2845,6 +3030,9 @@ int lws_serve_http_file_fragment(struct lws *wsi) unsigned char *p, *pstart; #if defined(LWS_WITH_RANGES) unsigned char finished = 0; +#endif +#if defined(LWS_ROLE_H2) + struct lws *nwsi; #endif int n, m; @@ -2926,8 +3114,20 @@ int lws_serve_http_file_fragment(struct lws *wsi) } #endif - poss = context->pt_serv_buf_size - (unsigned int)n - - LWS_H2_FRAME_HEADER_LENGTH; + poss = context->pt_serv_buf_size; + +#if defined(LWS_ROLE_H2) + /* + * If it's h2, restrict any lump that we are sending to the + * max h2 frame size the peer indicated he could handle in + * his SETTINGS + */ + nwsi = lws_get_network_wsi(wsi); + if (nwsi->h2.h2n && + poss > (lws_filepos_t)nwsi->h2.h2n->peer_set.s[H2SET_MAX_FRAME_SIZE]) + poss = (lws_filepos_t)nwsi->h2.h2n->peer_set.s[H2SET_MAX_FRAME_SIZE]; +#endif + poss = poss - (lws_filepos_t)(n + LWS_H2_FRAME_HEADER_LENGTH); if (wsi->http.tx_content_length) if (poss > wsi->http.tx_content_remain) @@ -3135,7 +3335,8 @@ lws_server_get_canonical_hostname(struct lws_context *context, lws_strncpy((char *)context->canonical_hostname, "unknown", sizeof(context->canonical_hostname)); - lwsl_info(" canonical_hostname = %s\n", context->canonical_hostname); + lwsl_cx_info(context, " canonical_hostname = %s\n", + context->canonical_hostname); #else (void)context; #endif diff --git a/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt-handshake.c b/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt-handshake.c index ab9cec79..ffdf262d 100644 --- a/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt-handshake.c +++ b/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt-handshake.c @@ -77,7 +77,7 @@ lws_mqtt_client_send_connect(struct lws *wsi) *p++ = 'T'; *p++ = 'T'; *p++ = MQTT_VER_3_1_1; - *p++ = c->conn_flags; + *p++ = (uint8_t)c->conn_flags; lws_ser_wu16be(p, c->keep_alive_secs); p += 2; @@ -176,3 +176,25 @@ lws_mqtt_client_send_connect(struct lws *wsi) return wsi; } + +struct lws * +lws_mqtt_client_send_disconnect(struct lws *wsi) +{ + uint8_t b[256 + LWS_PRE], *start = b + LWS_PRE, *p = start; + + /* 1. Fixed Headers */ + if (lws_mqtt_fill_fixed_header(p++, LMQCP_DISCONNECT, 0, 0, 0)) + { + lwsl_err("%s: Failled to fill fixed header\n", __func__); + return NULL; + } + *p++ = 0; + if (lws_write(wsi, (unsigned char *)&b[LWS_PRE], lws_ptr_diff_size_t(p, start), + LWS_WRITE_BINARY) != lws_ptr_diff(p, start)) { + lwsl_err("%s: write failed\n", __func__); + + return NULL; + } + + return wsi; +} diff --git a/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt.c b/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt.c index 5ad4471a..5324286e 100644 --- a/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt.c +++ b/3rdparty/libwebsockets/lib/roles/mqtt/client/client-mqtt.c @@ -120,7 +120,15 @@ lws_create_client_mqtt_object(const struct lws_client_connect_info *i, if (cp->clean_start || !(cp->client_id && cp->client_id[0])) c->conn_flags = LMQCFT_CLEAN_START; - lws_free((void *)cp->client_id); + if (cp->client_id_nofree) + c->conn_flags |= LMQCFT_CLIENT_ID_NOFREE; + if (cp->username_nofree) + c->conn_flags |= LMQCFT_USERNAME_NOFREE; + if (cp->password_nofree) + c->conn_flags |= LMQCFT_PASSWORD_NOFREE; + + if (!(c->conn_flags & LMQCFT_CLIENT_ID_NOFREE)) + lws_free((void *)cp->client_id); c->keep_alive_secs = cp->keep_alive; c->aws_iot = cp->aws_iot; @@ -138,8 +146,8 @@ lws_create_client_mqtt_object(const struct lws_client_connect_info *i, if (!c->will.message) goto oom2; } - c->conn_flags = (uint8_t)(unsigned int)(c->conn_flags | ((cp->will_param.qos << 3) & LMQCFT_WILL_QOS_MASK)); - c->conn_flags |= (uint8_t)((!!cp->will_param.retain) * LMQCFT_WILL_RETAIN); + c->conn_flags = (uint16_t)(unsigned int)(c->conn_flags | ((cp->will_param.qos << 3) & LMQCFT_WILL_QOS_MASK)); + c->conn_flags |= (uint16_t)((!!cp->will_param.retain) * LMQCFT_WILL_RETAIN); } if (cp->username && @@ -148,14 +156,16 @@ lws_create_client_mqtt_object(const struct lws_client_connect_info *i, if (!c->username) goto oom3; c->conn_flags |= LMQCFT_USERNAME; - lws_free((void *)cp->username); + if (!(c->conn_flags & LMQCFT_USERNAME_NOFREE)) + lws_free((void *)cp->username); if (cp->password) { c->password = lws_mqtt_str_create_cstr_dup(cp->password, 0); if (!c->password) goto oom4; c->conn_flags |= LMQCFT_PASSWORD; - lws_free((void *)cp->password); + if (!(c->conn_flags & LMQCFT_PASSWORD_NOFREE)) + lws_free((void *)cp->password); } } diff --git a/3rdparty/libwebsockets/lib/roles/mqtt/mqtt.c b/3rdparty/libwebsockets/lib/roles/mqtt/mqtt.c index 9ec43096..aaac84b8 100644 --- a/3rdparty/libwebsockets/lib/roles/mqtt/mqtt.c +++ b/3rdparty/libwebsockets/lib/roles/mqtt/mqtt.c @@ -214,13 +214,6 @@ static const uint8_t map_flags[] = { LMQCP_LUT_FLAG_PACKET_ID_NONE | 0x00, }; -void -lws_mqttc_state_transition(lws_mqttc_t *c, lwsgs_mqtt_states_t s) -{ - lwsl_debug("%s: ep %p: state %d -> %d\n", __func__, c, c->estate, s); - c->estate = s; -} - static int lws_mqtt_pconsume(lws_mqtt_parser_t *par, int consumed) { @@ -277,74 +270,6 @@ lws_mqtt_set_client_established(struct lws *wsi) return 0; } - -static lws_mqtt_match_topic_return_t -lws_mqtt_is_topic_matched(const char* sub, const char* pub) -{ - const char *ppos = pub, *spos = sub; - - if (!ppos || !spos) { - return LMMTR_TOPIC_MATCH_ERROR; - } - - while (*spos) { - if (*ppos == '#' || *ppos == '+') { - lwsl_err("%s: PUBLISH to wildcard " - "topic \"%s\" not supported\n", - __func__, pub); - return LMMTR_TOPIC_MATCH_ERROR; - } - /* foo/+/bar == foo/xyz/bar ? */ - if (*spos == '+') { - /* Skip ahead */ - while (*ppos != '\0' && *ppos != '/') { - ppos++; - } - } else if (*spos == '#') { - return LMMTR_TOPIC_MATCH; - } else { - if (*ppos == '\0') { - /* foo/bar == foo/bar/# ? */ - if (!strncmp(spos, "/#", 2)) - return LMMTR_TOPIC_MATCH; - return LMMTR_TOPIC_NOMATCH; - /* Non-matching character */ - } else if (*ppos != *spos) { - return LMMTR_TOPIC_NOMATCH; - } - ppos++; - } - spos++; - } - - if (*spos == '\0' && *ppos == '\0') - return LMMTR_TOPIC_MATCH; - - return LMMTR_TOPIC_NOMATCH; -} - -lws_mqtt_subs_t* lws_mqtt_find_sub(struct _lws_mqtt_related* mqtt, - const char* ptopic) { - lws_mqtt_subs_t *s = mqtt->subs_head; - - while (s) { - /* SUB topic == PUB topic ? */ - /* foo/bar/xyz == foo/bar/xyz ? */ - if (!s->wildcard) { - if (!strcmp((const char*)s->topic, ptopic)) - return s; - } else { - if (lws_mqtt_is_topic_matched( - s->topic, ptopic) == LMMTR_TOPIC_MATCH) - return s; - } - - s = s->next; - } - - return NULL; -} - static lws_mqtt_validate_topic_return_t lws_mqtt_validate_topic(const char *topic, size_t topiclen, uint8_t awsiot) { @@ -429,10 +354,8 @@ lws_mqtt_create_sub(struct _lws_mqtt_related *mqtt, const char *topic) __func__); return NULL; } - if (flag == LMVTR_VALID_WILDCARD) - mysub->wildcard = 1; - else if (flag == LMVTR_VALID_SHADOW) - mysub->shadow = 1; + mysub->wildcard = (flag == LMVTR_VALID_WILDCARD); + mysub->shadow = (flag == LMVTR_VALID_SHADOW); break; default: @@ -479,6 +402,126 @@ lws_mqtt_client_remove_subs(struct _lws_mqtt_related *mqtt) return 1; } +/* + * This fires if the wsi did a PUBLISH under QoS1 or QoS2, but no PUBACK or + * PUBREC came before the timeout period + */ + +static void +lws_mqtt_publish_resend(struct lws_sorted_usec_list *sul) +{ + struct _lws_mqtt_related *mqtt = lws_container_of(sul, + struct _lws_mqtt_related, sul_qos_puback_pubrec_wait); + + lwsl_notice("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); + + 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); +} + +static void +lws_mqtt_unsuback_timeout(struct lws_sorted_usec_list *sul) +{ + struct _lws_mqtt_related *mqtt = lws_container_of(sul, + struct _lws_mqtt_related, sul_unsuback_wait); + + lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); + + if (mqtt->wsi->a.protocol->callback(mqtt->wsi, + LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT, + mqtt->wsi->user_space, NULL, 0)) + lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); +} + +static void +lws_mqtt_shadow_timeout(struct lws_sorted_usec_list *sul) +{ + struct _lws_mqtt_related *mqtt = lws_container_of(sul, + struct _lws_mqtt_related, sul_shadow_wait); + + lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); + + if (mqtt->wsi->a.protocol->callback(mqtt->wsi, + LWS_CALLBACK_MQTT_SHADOW_TIMEOUT, + mqtt->wsi->user_space, NULL, 0)) + lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); +} + +void +lws_mqttc_state_transition(lws_mqttc_t *c, lwsgs_mqtt_states_t s) +{ + lwsl_debug("%s: ep %p: state %d -> %d\n", __func__, c, c->estate, s); + c->estate = s; +} + +lws_mqtt_match_topic_return_t +lws_mqtt_is_topic_matched(const char* sub, const char* pub) +{ + const char *ppos = pub, *spos = sub; + + if (!ppos || !spos) { + return LMMTR_TOPIC_MATCH_ERROR; + } + + while (*spos) { + if (*ppos == '#' || *ppos == '+') { + lwsl_err("%s: PUBLISH to wildcard " + "topic \"%s\" not supported\n", + __func__, pub); + return LMMTR_TOPIC_MATCH_ERROR; + } + /* foo/+/bar == foo/xyz/bar ? */ + if (*spos == '+') { + /* Skip ahead */ + while (*ppos != '\0' && *ppos != '/') { + ppos++; + } + } else if (*spos == '#') { + return LMMTR_TOPIC_MATCH; + } else { + if (*ppos == '\0') { + /* foo/bar == foo/bar/# ? */ + if (!strncmp(spos, "/#", 2)) + return LMMTR_TOPIC_MATCH; + return LMMTR_TOPIC_NOMATCH; + /* Non-matching character */ + } else if (*ppos != *spos) { + return LMMTR_TOPIC_NOMATCH; + } + ppos++; + } + spos++; + } + + if (*spos == '\0' && *ppos == '\0') + return LMMTR_TOPIC_MATCH; + + return LMMTR_TOPIC_NOMATCH; +} + +lws_mqtt_subs_t* lws_mqtt_find_sub(struct _lws_mqtt_related* mqtt, + const char* ptopic) { + lws_mqtt_subs_t *s = mqtt->subs_head; + + while (s) { + /* SUB topic == PUB topic ? */ + /* foo/bar/xyz == foo/bar/xyz ? */ + if (!s->wildcard) { + if (!strcmp((const char*)s->topic, ptopic)) + return s; + } else { + if (lws_mqtt_is_topic_matched( + s->topic, ptopic) == LMMTR_TOPIC_MATCH) + return s; + } + + s = s->next; + } + + return NULL; +} + int _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, const uint8_t *buf, size_t len) @@ -655,6 +698,114 @@ _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, } break; + /* PUBREC */ + case LMQCPP_PUBREC_PACKET: + lwsl_debug("%s: received PUBREC pkt\n", __func__); + lws_mqtt_vbi_init(&par->vbit); + switch (lws_mqtt_vbi_r(&par->vbit, &buf, &len)) { + case LMSPR_NEED_MORE: + break; + case LMSPR_COMPLETED: + par->cpkt_remlen = par->vbit.value; + lwsl_debug("%s: PUBREC pkt len = %d\n", + __func__, (int)par->cpkt_remlen); + if (par->cpkt_remlen < 2) + goto send_protocol_error_and_close; + par->state = LMQCPP_PUBREC_VH_PKT_ID; + break; + default: + lwsl_notice("%s: pubrec bad vbi\n", __func__); + goto send_protocol_error_and_close; + } + break; + + case LMQCPP_PUBREC_VH_PKT_ID: + if (len < 2) { + lwsl_notice("%s: len breakage 3\n", __func__); + return -1; + } + + par->cpkt_id = lws_ser_ru16be(buf); + wsi->mqtt->ack_pkt_id = par->cpkt_id; + buf += 2; + len -= 2; + par->cpkt_remlen -= 2; + par->n = 0; + + goto cmd_completion; + + /* PUBREL */ + case LMQCPP_PUBREL_PACKET: + lwsl_debug("%s: received PUBREL pkt\n", __func__); + lws_mqtt_vbi_init(&par->vbit); + switch (lws_mqtt_vbi_r(&par->vbit, &buf, &len)) { + case LMSPR_NEED_MORE: + break; + case LMSPR_COMPLETED: + par->cpkt_remlen = par->vbit.value; + lwsl_debug("%s: PUBREL pkt len = %d\n", + __func__, (int)par->cpkt_remlen); + if (par->cpkt_remlen < 2) + goto send_protocol_error_and_close; + par->state = LMQCPP_PUBREL_VH_PKT_ID; + break; + default: + lwsl_err("%s: pubrel bad vbi\n", __func__); + goto send_protocol_error_and_close; + } + break; + + case LMQCPP_PUBREL_VH_PKT_ID: + if (len < 2) { + lwsl_notice("%s: len breakage 3\n", __func__); + return -1; + } + + par->cpkt_id = lws_ser_ru16be(buf); + wsi->mqtt->ack_pkt_id = par->cpkt_id; + buf += 2; + len -= 2; + par->cpkt_remlen -= 2; + par->n = 0; + + goto cmd_completion; + + /* PUBCOMP */ + case LMQCPP_PUBCOMP_PACKET: + lwsl_debug("%s: received PUBCOMP pkt\n", __func__); + lws_mqtt_vbi_init(&par->vbit); + switch (lws_mqtt_vbi_r(&par->vbit, &buf, &len)) { + case LMSPR_NEED_MORE: + break; + case LMSPR_COMPLETED: + par->cpkt_remlen = par->vbit.value; + lwsl_debug("%s: PUBCOMP pkt len = %d\n", + __func__, (int)par->cpkt_remlen); + if (par->cpkt_remlen < 2) + goto send_protocol_error_and_close; + par->state = LMQCPP_PUBCOMP_VH_PKT_ID; + break; + default: + lwsl_err("%s: pubcmp bad vbi\n", __func__); + goto send_protocol_error_and_close; + } + break; + + case LMQCPP_PUBCOMP_VH_PKT_ID: + if (len < 2) { + lwsl_notice("%s: len breakage 3\n", __func__); + return -1; + } + + par->cpkt_id = lws_ser_ru16be(buf); + wsi->mqtt->ack_pkt_id = par->cpkt_id; + buf += 2; + len -= 2; + par->cpkt_remlen -= 2; + par->n = 0; + + goto cmd_completion; + case LMQCPP_PUBLISH_PACKET: if (lwsi_role_client(wsi) && wsi->mqtt->inside_subscribe) { lwsl_notice("%s: Topic rx before subscribing\n", @@ -769,7 +920,7 @@ _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, par->cpkt_id = lws_ser_ru16be(buf); buf += 2; len -= 2; - wsi->mqtt->ack_pkt_id = par->cpkt_id; + wsi->mqtt->peer_ack_pkt_id = par->cpkt_id; lwsl_debug("%s: Packet ID %d\n", __func__, (int)par->cpkt_id); par->state = LMQCPP_PAYLOAD; @@ -1214,6 +1365,93 @@ _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, return 0; + case LMQCP_PUBREC: + lwsl_err("%s: cmd_completion: PUBREC\n", + __func__); + /* + * Figure out which child asked for this + */ + n = 0; + lws_start_foreach_ll(struct lws *, w, + wsi->mux.child_list) { + if (w->mqtt->unacked_publish && + w->mqtt->ack_pkt_id == par->cpkt_id) { + char requested_close = 0; + + w->mqtt->unacked_publish = 0; + w->mqtt->unacked_pubrel = 1; + + if (user_callback_handle_rxflow( + w->a.protocol->callback, + w, LWS_CALLBACK_MQTT_ACK, + w->user_space, NULL, 0) < 0) { + lwsl_info("%s: MQTT_ACK requests close\n", + __func__); + requested_close = 1; + } + n = 1; + + /* + * We got an assertive PUBREC, + * no need for timeout wait + * any more + */ + lws_sul_cancel(&w->mqtt-> + sul_qos_puback_pubrec_wait); + + if (requested_close) { + __lws_close_free_wsi(w, + 0, "ack cb"); + break; + } + + break; + } + } lws_end_foreach_ll(w, mux.sibling_list); + + if (!n) { + lwsl_err("%s: unsolicited PUBREC\n", + __func__); + return -1; + } + wsi->mqtt->send_pubrel = 1; + lws_callback_on_writable(wsi); + break; + + case LMQCP_PUBCOMP: + lwsl_err("%s: cmd_completion: PUBCOMP\n", + __func__); + n = 0; + lws_start_foreach_ll(struct lws *, w, + wsi->mux.child_list) { + if (w->mqtt->unacked_pubrel > 0 && + w->mqtt->ack_pkt_id == par->cpkt_id) { + w->mqtt->unacked_pubrel = 0; + n = 1; + } + } lws_end_foreach_ll(w, mux.sibling_list); + + if (!n) { + lwsl_err("%s: unsolicited PUBCOMP\n", + __func__); + return -1; + } + + /* + * If we published something and PUBCOMP arrived, + * our connection is definitely working in both + * directions at the moment. + */ + lws_validity_confirmed(wsi); + break; + + case LMQCP_PUBREL: + lwsl_err("%s: cmd_completion: PUBREL\n", + __func__); + wsi->mqtt->send_pubcomp = 1; + lws_callback_on_writable(wsi); + break; + case LMQCP_PUBACK: lwsl_info("%s: cmd_completion: PUBACK\n", __func__); @@ -1245,7 +1483,7 @@ _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, * no need for ACK timeout wait * any more */ - lws_sul_cancel(&w->mqtt->sul_qos1_puback_wait); + lws_sul_cancel(&w->mqtt->sul_qos_puback_pubrec_wait); if (requested_close) { __lws_close_free_wsi(w, @@ -1356,6 +1594,7 @@ _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, } n = 1; + lws_sul_cancel(&w->mqtt->sul_unsuback_wait); if (requested_close) { __lws_close_free_wsi(w, 0, "unsub ack cb"); @@ -1440,10 +1679,14 @@ _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, break; } - /* For QOS>0, send out PUBACK */ - if (pub->qos) { + if (pub->qos == 1) { + /* For QOS = 1, send out PUBACK */ wsi->mqtt->send_puback = 1; lws_callback_on_writable(wsi); + } else if (pub->qos == 2) { + /* For QOS = 2, send out PUBREC */ + wsi->mqtt->send_pubrec = 1; + lws_callback_on_writable(wsi); } par->payload_consumed = 0; @@ -1710,24 +1953,6 @@ lws_mqtt_fill_fixed_header(uint8_t *p, lws_mqtt_control_packet_t ctrl_pkt_type, return 0; } -/* - * This fires if the wsi did a PUBLISH under QoS1, but no PUBACK came before - * the timeout period - */ - -static void -lws_mqtt_publish_resend(struct lws_sorted_usec_list *sul) -{ - struct _lws_mqtt_related *mqtt = lws_container_of(sul, - struct _lws_mqtt_related, sul_qos1_puback_wait); - - lwsl_notice("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); - - 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); -} - int lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, const void *buf, uint32_t len, int is_complete) @@ -1770,7 +1995,7 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, * payload (if any) */ if (lws_mqtt_fill_fixed_header(p++, LMQCP_PUBLISH, - 0, pub->qos, 0)) { + pub->dup, pub->qos, pub->retain)) { lwsl_err("%s: Failed to fill fixed header\n", __func__); return 1; } @@ -1815,7 +2040,9 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, /* Packet ID */ if (pub->qos != QOS0) { p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); - wsi->mqtt->ack_pkt_id = pub->packet_id = ++nwsi->mqtt->pkt_id; + if (!pub->dup) + nwsi->mqtt->pkt_id++; + wsi->mqtt->ack_pkt_id = pub->packet_id = nwsi->mqtt->pkt_id; lwsl_debug("%s: pkt_id = %d\n", __func__, (int)wsi->mqtt->ack_pkt_id); lws_ser_wu16be(p, pub->packet_id); @@ -1824,17 +2051,12 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, return 1; } } - /* - * A non-empty Payload is expected and a chunk - * is present - */ - if (pub->payload_len && len) { - p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); - memcpy(p, buf, len); - if (lws_mqtt_str_advance(&mqtt_vh_payload, (int)len)) - return 1; - p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); - } + + p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); + memcpy(p, buf, len); + if (lws_mqtt_str_advance(&mqtt_vh_payload, (int)len)) + return 1; + p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); if (!is_complete) nwsi->mqtt->inside_payload = wsi->mqtt->inside_payload = 1; @@ -1874,16 +2096,22 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, lwsl_err("%s: ACK callback exited\n", __func__); return 1; } - - return 0; + } else if (pub->qos == QOS1 || pub->qos == QOS2) { + /* For QoS1 or QoS2, if no PUBACK or PUBREC coming after 3s, + * we must RETRY the publish + */ + wsi->mqtt->sul_qos_puback_pubrec_wait.cb = lws_mqtt_publish_resend; + __lws_sul_insert_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], + &wsi->mqtt->sul_qos_puback_pubrec_wait, + 3 * LWS_USEC_PER_SEC); } - /* 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_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], - &wsi->mqtt->sul_qos1_puback_wait, - 3 * LWS_USEC_PER_SEC); + if (wsi->mqtt->inside_shadow) { + wsi->mqtt->sul_shadow_wait.cb = lws_mqtt_shadow_timeout; + __lws_sul_insert_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], + &wsi->mqtt->sul_shadow_wait, + 60 * LWS_USEC_PER_SEC); + } return 0; } @@ -2009,6 +2237,8 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) (int)sub->packet_id); lws_ser_wu16be(p, wsi->mqtt->ack_pkt_id); + nwsi->mqtt->client.aws_iot = wsi->mqtt->client.aws_iot; + if (lws_mqtt_str_advance(&mqtt_vh_payload, 2)) return 1; @@ -2059,6 +2289,9 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) return 1; } + if (wsi->mqtt->inside_resume_session) + return 0; + if (lws_write(nwsi, start, lws_ptr_diff_size_t(p, start), LWS_WRITE_BINARY) != lws_ptr_diff(p, start)) return 1; @@ -2151,8 +2384,10 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, wsi->mqtt->sub_size = (uint16_t)rem_len; +#if defined(_DEBUG) lwsl_debug("%s: Number of topics = %d, Remaining len = %d\n", __func__, (int)tops, (int)rem_len); +#endif p += lws_mqtt_vbi_encode(rem_len, p); @@ -2172,6 +2407,8 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, (int)wsi->mqtt->ack_pkt_id); lws_ser_wu16be(p, wsi->mqtt->ack_pkt_id); + nwsi->mqtt->client.aws_iot = wsi->mqtt->client.aws_iot; + if (lws_mqtt_str_advance(&mqtt_vh_payload, 2)) return 1; @@ -2214,6 +2451,11 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, wsi->mqtt->inside_unsubscribe = 1; + wsi->mqtt->sul_unsuback_wait.cb = lws_mqtt_unsuback_timeout; + __lws_sul_insert_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], + &wsi->mqtt->sul_unsuback_wait, + 3 * LWS_USEC_PER_SEC); + return 0; } diff --git a/3rdparty/libwebsockets/lib/roles/mqtt/ops-mqtt.c b/3rdparty/libwebsockets/lib/roles/mqtt/ops-mqtt.c index 6b812d26..ceac2f57 100644 --- a/3rdparty/libwebsockets/lib/roles/mqtt/ops-mqtt.c +++ b/3rdparty/libwebsockets/lib/roles/mqtt/ops-mqtt.c @@ -302,6 +302,40 @@ rops_handle_POLLOUT_mqtt(struct lws *wsi) return LWS_HP_RET_BAIL_OK; } #endif + if (wsi->mqtt && !wsi->mqtt->inside_payload && + (wsi->mqtt->send_pubrec || wsi->mqtt->send_pubrel || + wsi->mqtt->send_pubcomp)) { + uint8_t buf[LWS_PRE + 4]; + /* Remaining len = 2 */ + buf[LWS_PRE + 1] = 2; + if (wsi->mqtt->send_pubrec) { + lwsl_notice("%s: issuing PUBREC for pkt id: %d\n", + __func__, wsi->mqtt->peer_ack_pkt_id); + buf[LWS_PRE] = LMQCP_PUBREC << 4 | 0x2; + /* Packet ID */ + lws_ser_wu16be(&buf[LWS_PRE + 2], + wsi->mqtt->peer_ack_pkt_id); + wsi->mqtt->send_pubrec = 0; + } else if (wsi->mqtt->send_pubrel) { + lwsl_notice("%s: issuing PUBREL for pkt id: %d\n", + __func__, wsi->mqtt->ack_pkt_id); + buf[LWS_PRE] = LMQCP_PUBREL << 4 | 0x2; + lws_ser_wu16be(&buf[LWS_PRE + 2], + wsi->mqtt->ack_pkt_id); + wsi->mqtt->send_pubrel = 0; + } else { + lwsl_notice("%s: issuing PUBCOMP for pkt id: %d\n", + __func__, wsi->mqtt->peer_ack_pkt_id); + buf[LWS_PRE] = LMQCP_PUBCOMP << 4 | 0x2; + lws_ser_wu16be(&buf[LWS_PRE + 2], + wsi->mqtt->peer_ack_pkt_id); + wsi->mqtt->send_pubcomp = 0; + } + if (lws_write(wsi, (uint8_t *)&buf[LWS_PRE], 4, + LWS_WRITE_BINARY) != 4) + return LWS_HP_RET_BAIL_DIE; + return LWS_HP_RET_BAIL_OK; + } wsi = lws_get_network_wsi(wsi); @@ -313,6 +347,9 @@ rops_handle_POLLOUT_mqtt(struct lws *wsi) return LWS_HP_RET_DROP_POLLOUT; } + if (!wsi->mqtt) + return LWS_HP_RET_BAIL_DIE; + lws_wsi_mux_dump_waiting_children(wsi); do { @@ -358,7 +395,7 @@ rops_handle_POLLOUT_mqtt(struct lws *wsi) /* Remaining len = 2 */ buf[LWS_PRE + 1] = 2; /* Packet ID */ - lws_ser_wu16be(&buf[LWS_PRE + 2], wsi->mqtt->ack_pkt_id); + lws_ser_wu16be(&buf[LWS_PRE + 2], wsi->mqtt->peer_ack_pkt_id); if (lws_write(wsi, (uint8_t *)&buf[LWS_PRE], 4, LWS_WRITE_BINARY) != 4) @@ -421,7 +458,7 @@ rops_close_role_mqtt(struct lws_context_per_thread *pt, struct lws *wsi) c = &wsi->mqtt->client; - lws_sul_cancel(&wsi->mqtt->sul_qos1_puback_wait); + lws_sul_cancel(&wsi->mqtt->sul_qos_puback_pubrec_wait); lws_mqtt_str_free(&c->username); lws_mqtt_str_free(&c->password); diff --git a/3rdparty/libwebsockets/lib/roles/mqtt/private-lib-roles-mqtt.h b/3rdparty/libwebsockets/lib/roles/mqtt/private-lib-roles-mqtt.h index 6383ead2..dc46a936 100644 --- a/3rdparty/libwebsockets/lib/roles/mqtt/private-lib-roles-mqtt.h +++ b/3rdparty/libwebsockets/lib/roles/mqtt/private-lib-roles-mqtt.h @@ -45,6 +45,7 @@ extern struct lws_role_ops role_ops_mqtt; #define LWS_MQTT_RESPONSE_TIMEOUT (3 * LWS_US_PER_SEC) #define LWS_MQTT_RETRY_CEILING (60 * LWS_US_PER_SEC) +#define LWS_MQTT_MAX_PUBLISH_RETRY (3) typedef enum { LMSPR_COMPLETED = 0, @@ -156,6 +157,15 @@ typedef enum { LMQCPP_PUBACK_VH_PKT_ID, LMQCPP_PUBACK_PROPERTIES_LEN_VBI, + LMQCPP_PUBREC_PACKET = LMQCP_PUBREC << 4, + LMQCPP_PUBREC_VH_PKT_ID, + + LMQCPP_PUBREL_PACKET = LMQCP_PUBREL << 4, + LMQCPP_PUBREL_VH_PKT_ID, + + LMQCPP_PUBCOMP_PACKET = LMQCP_PUBCOMP << 4, + LMQCPP_PUBCOMP_VH_PKT_ID, + LMQCPP_SUBACK_PACKET = LMQCP_STOC_SUBACK << 4, LMQCPP_SUBACK_VH_PKT_ID, LMQCPP_SUBACK_PAYLOAD, @@ -337,18 +347,23 @@ typedef struct lws_mqttc { uint8_t retain; } will; uint16_t keep_alive_secs; - uint8_t conn_flags; + uint16_t conn_flags; uint8_t aws_iot; } lws_mqttc_t; struct _lws_mqtt_related { lws_mqttc_t client; + lws_sorted_usec_list_t sul_qos_puback_pubrec_wait; /* QoS1 puback or QoS2 pubrec wait TO */ lws_sorted_usec_list_t sul_qos1_puback_wait; /* QoS1 puback wait TO */ + lws_sorted_usec_list_t sul_unsuback_wait; /* unsuback wait TO */ + lws_sorted_usec_list_t sul_qos2_pubrec_wait; /* QoS2 pubrec wait TO */ + lws_sorted_usec_list_t sul_shadow_wait; /* Device Shadow wait TO */ struct lws *wsi; /**< so sul can use lws_container_of */ lws_mqtt_subs_t *subs_head; /**< Linked-list of heap-allocated subscription objects */ void *rx_cpkt_param; uint16_t pkt_id; uint16_t ack_pkt_id; + uint16_t peer_ack_pkt_id; uint16_t sub_size; #if defined(LWS_WITH_CLIENT) @@ -358,10 +373,20 @@ struct _lws_mqtt_related { uint8_t inside_payload:1; uint8_t inside_subscribe:1; uint8_t inside_unsubscribe:1; + uint8_t inside_birth:1; + uint8_t inside_resume_session:1; uint8_t send_puback:1; + uint8_t send_pubrel:1; + uint8_t send_pubrec:1; + uint8_t send_pubcomp:1; uint8_t unacked_publish:1; + uint8_t unacked_pubrel:1; uint8_t done_subscribe:1; + uint8_t done_birth:1; + uint8_t inside_shadow:1; + uint8_t done_shadow_subscribe:1; + uint8_t send_shadow_unsubscribe:1; }; /* @@ -403,6 +428,9 @@ lws_create_client_mqtt_object(const struct lws_client_connect_info *i, struct lws * lws_mqtt_client_send_connect(struct lws *wsi); +struct lws * +lws_mqtt_client_send_disconnect(struct lws *wsi); + int lws_mqtt_fill_fixed_header(uint8_t *p, lws_mqtt_control_packet_t ctrl_pkt_type, uint8_t dup, lws_mqtt_qos_levels_t qos, @@ -414,5 +442,8 @@ lws_wsi_mqtt_adopt(struct lws *parent_wsi, struct lws *wsi); lws_mqtt_subs_t * lws_mqtt_find_sub(struct _lws_mqtt_related *mqtt, const char *topic); +lws_mqtt_match_topic_return_t +lws_mqtt_is_topic_matched(const char* sub, const char* pub); + #endif /* _PRIVATE_LIB_ROLES_MQTT */ diff --git a/3rdparty/libwebsockets/lib/roles/netlink/ops-netlink.c b/3rdparty/libwebsockets/lib/roles/netlink/ops-netlink.c index 338e17b2..fa3bf29a 100644 --- a/3rdparty/libwebsockets/lib/roles/netlink/ops-netlink.c +++ b/3rdparty/libwebsockets/lib/roles/netlink/ops-netlink.c @@ -41,7 +41,7 @@ #define RTA_ALIGNTO 4U //#define lwsl_netlink lwsl_notice -#define lwsl_netlink lwsl_info +#define lwsl_cx_netlink lwsl_cx_info static void lws_netlink_coldplug_done_cb(lws_sorted_usec_list_t *sul) @@ -49,9 +49,10 @@ lws_netlink_coldplug_done_cb(lws_sorted_usec_list_t *sul) struct lws_context *ctx = lws_container_of(sul, struct lws_context, sul_nl_coldplug); ctx->nl_initial_done = 1; - +#if defined(LWS_WITH_SYS_STATE) /* if nothing is there to intercept anything, go all the way */ lws_state_transition_steps(&ctx->mgr_system, LWS_SYSTATE_OPERATIONAL); +#endif } static int @@ -78,18 +79,6 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, if (!(pollfd->revents & LWS_POLLIN)) return LWS_HPI_RET_HANDLED; - if (!cx->nl_initial_done && pt == &cx->pt[0]) { - /* - * While netlink info still coming, keep moving the timer for - * calling it "done" to +100ms until after it stops coming - */ - lws_context_lock(cx, __func__); - lws_sul_schedule(cx, 0, &cx->sul_nl_coldplug, - lws_netlink_coldplug_done_cb, - 100 * LWS_US_PER_MS); - lws_context_unlock(cx); - } - memset(&msg, 0, sizeof(msg)); iov.iov_base = (void *)s; @@ -103,7 +92,7 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, n = (unsigned int)recvmsg(wsi->desc.sockfd, &msg, 0); if ((int)n < 0) { - lwsl_notice("%s: recvmsg failed\n", __func__); + lwsl_cx_notice(cx, "recvmsg failed"); return LWS_HPI_RET_PLEASE_CLOSE_ME; } @@ -125,10 +114,9 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, struct ifinfomsg *ifi; struct rtattr *attribute; - lws_sockaddr46 *sa46; unsigned int len; - lwsl_netlink("%s: RTM %d\n", __func__, h->nlmsg_type); + lwsl_cx_netlink(cx, "RTM %d", h->nlmsg_type); memset(&robj, 0, sizeof(robj)); robj.if_idx = -1; @@ -151,34 +139,21 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, /* loop over all attributes for the NEWLINK message */ for (attribute = IFLA_RTA(ifi); RTA_OK(attribute, len); attribute = RTA_NEXT(attribute, len)) { - lwsl_netlink("%s: if attr %d\n", __func__, + lwsl_cx_netlink(cx, "if attr %d", (int)attribute->rta_type); switch(attribute->rta_type) { case IFLA_IFNAME: - lwsl_netlink("NETLINK ifidx %d : %s\n", + lwsl_cx_netlink(cx, "NETLINK ifidx %d : %s", ifi->ifi_index, (char *)RTA_DATA(attribute)); break; - case RTA_SRC: - sa46 = (lws_sockaddr46 *)RTA_DATA(attribute); - if (sa46->sa4.sin_family == 0xffff) { - lwsl_netlink("%s: down %d\n", - __func__, - ifi->ifi_index); - lws_pt_lock(pt, __func__); - _lws_route_table_ifdown(pt, - ifi->ifi_index); - _lws_route_pt_close_unroutable(pt); - lws_pt_unlock(pt); - } - break; default: break; } /* switch */ } /* for loop */ - lwsl_netlink("%s: NEWLINK ifi_index %d, flags 0x%x\n", - __func__, ifi->ifi_index, ifi->ifi_flags); + lwsl_cx_netlink(cx, "NEWLINK ifi_index %d, flags 0x%x", + ifi->ifi_index, ifi->ifi_flags); /* * Despite "New"link this is actually telling us there @@ -190,8 +165,8 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, * Interface is down, so scrub all routes that * applied to it */ - lwsl_netlink("%s: NEWLINK: ifdown %d\n", - __func__, ifi->ifi_index); + lwsl_cx_netlink(cx, "NEWLINK: ifdown %d", + ifi->ifi_index); lws_pt_lock(pt, __func__); _lws_route_table_ifdown(pt, ifi->ifi_index); lws_pt_unlock(pt); @@ -214,15 +189,20 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, ra = (struct rtattr *)IFA_RTA(ifam); ra_len = (unsigned int)IFA_PAYLOAD(h); - lwsl_netlink("%s: %s\n", __func__, + lwsl_cx_netlink(cx, "%s", h->nlmsg_type == RTM_NEWADDR ? "NEWADDR" : "DELADDR"); - break; + + /* + * almost nothing interesting within IFA_* attributes: + * so skip it and goto to the second half + */ + goto second_half; case RTM_NEWROUTE: case RTM_DELROUTE: - lwsl_netlink("%s: %s\n", __func__, + lwsl_cx_netlink(cx, "%s", h->nlmsg_type == RTM_NEWROUTE ? "NEWROUTE" : "DELROUTE"); @@ -233,23 +213,23 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, case RTM_DELNEIGH: case RTM_NEWNEIGH: - lwsl_netlink("%s: %s\n", __func__, - h->nlmsg_type == RTM_NEWNEIGH ? "NEWNEIGH" : - "DELNEIGH"); + lwsl_cx_netlink(cx, "%s", h->nlmsg_type == + RTM_NEWNEIGH ? "NEWNEIGH" : + "DELNEIGH"); #if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG) nd = (struct ndmsg *)rm; - lwsl_netlink("%s: fam %u, ifidx %u, flags 0x%x\n", - __func__, nd->ndm_family, nd->ndm_ifindex, + lwsl_cx_netlink(cx, "fam %u, ifidx %u, flags 0x%x", + nd->ndm_family, nd->ndm_ifindex, nd->ndm_flags); #endif ra = (struct rtattr *)RTM_RTA(rm); ra_len = (unsigned int)RTM_PAYLOAD(h); for ( ; RTA_OK(ra, ra_len); ra = RTA_NEXT(ra, ra_len)) { - lwsl_netlink("%s: atr %d\n", __func__, ra->rta_type); + lwsl_cx_netlink(cx, "atr %d", ra->rta_type); switch (ra->rta_type) { case NDA_DST: - lwsl_netlink("%s: dst len %d\n", - __func__, ra->rta_len); + lwsl_cx_netlink(cx, "dst len %d", + ra->rta_len); break; } } @@ -259,13 +239,14 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, continue; default: - lwsl_netlink("%s: *** Unknown RTM_%d\n", __func__, + lwsl_cx_netlink(cx, "*** Unknown RTM_%d", h->nlmsg_type); continue; } /* switch */ robj.proto = rm->rtm_protocol; + // iterate over route attributes for ( ; RTA_OK(ra, ra_len); ra = RTA_NEXT(ra, ra_len)) { // lwsl_netlink("%s: atr %d\n", __func__, ra->rta_type); switch (ra->rta_type) { @@ -275,14 +256,23 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, rm->rtm_family); robj.src_len = rm->rtm_src_len; lws_sa46_write_numeric_address(&robj.src, buf, sizeof(buf)); - lwsl_netlink("%s: RTA_SRC: %s\n", __func__, buf); + lwsl_cx_netlink(cx, "RTA_SRC: %s", buf); break; case RTA_DST: + /* check if is local addr -> considering it as src addr too */ + if (rm->rtm_type == RTN_LOCAL && + ((rm->rtm_family == AF_INET && rm->rtm_dst_len == 32) || + (rm->rtm_family == AF_INET6 && rm->rtm_dst_len == 128))) { + lws_sa46_copy_address(&robj.src, RTA_DATA(ra), + rm->rtm_family); + lwsl_cx_netlink(cx, "Local addr: RTA_DST -> added to RTA_SRC"); + } + lws_sa46_copy_address(&robj.dest, RTA_DATA(ra), rm->rtm_family); robj.dest_len = rm->rtm_dst_len; lws_sa46_write_numeric_address(&robj.dest, buf, sizeof(buf)); - lwsl_netlink("%s: RTA_DST: %s\n", __func__, buf); + lwsl_cx_netlink(cx, "RTA_DST: %s", buf); break; case RTA_GATEWAY: lws_sa46_copy_address(&robj.gateway, @@ -294,11 +284,8 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, break; case RTA_IIF: /* int: input interface index */ case RTA_OIF: /* int: output interface index */ - if (h->nlmsg_type != RTM_NEWADDR && - h->nlmsg_type != RTM_DELADDR) { - robj.if_idx = *(int *)RTA_DATA(ra); - lwsl_netlink("%s: ifidx %d\n", __func__, robj.if_idx); - } + robj.if_idx = *(int *)RTA_DATA(ra); + lwsl_cx_netlink(cx, "ifidx %d", robj.if_idx); break; case RTA_PRIORITY: /* int: priority of route */ p = RTA_DATA(ra); @@ -315,8 +302,8 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, break; default: - lwsl_info("%s: unknown attr type %d\n", - __func__, ra->rta_type); + lwsl_cx_info(cx, "unknown attr type %d", + ra->rta_type); break; } } /* for */ @@ -324,15 +311,14 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, /* * the second half, once all the attributes were collected */ - - +second_half: switch (h->nlmsg_type) { case RTM_DELROUTE: /* * This will also take down wsi marked as using it */ - lwsl_netlink("%s: DELROUTE: if_idx %d\n", __func__, + lwsl_cx_netlink(cx, "DELROUTE: if_idx %d", robj.if_idx); lws_pt_lock(pt, __func__); _lws_route_remove(pt, &robj, 0); @@ -341,7 +327,7 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, case RTM_NEWROUTE: - lwsl_netlink("%s: NEWROUTE rtm_type %d\n", __func__, + lwsl_cx_netlink(cx, "NEWROUTE rtm_type %d", rm->rtm_type); /* @@ -360,9 +346,9 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, goto ana; case RTM_DELADDR: - lwsl_notice("%s: DELADDR\n", __func__); + lwsl_cx_notice(cx, "DELADDR"); #if defined(_DEBUG) - _lws_routing_entry_dump(&robj); + _lws_routing_entry_dump(cx, &robj); #endif lws_pt_lock(pt, __func__); _lws_route_remove(pt, &robj, LRR_MATCH_SRC | LRR_IGNORE_PRI); @@ -372,7 +358,7 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, case RTM_NEWADDR: - lwsl_netlink("%s: NEWADDR\n", __func__); + lwsl_cx_netlink(cx, "NEWADDR"); ana: /* @@ -385,9 +371,8 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, lws_pt_lock(pt, __func__); /* returns zero on match already in table */ - rmat = _lws_route_remove(pt, &robj, LRR_MATCH_SRC | - LRR_JUST_CHECK | - LRR_IGNORE_PRI); + rmat = _lws_route_remove(pt, &robj, h->nlmsg_type == RTM_NEWROUTE ? + LRR_MATCH_DST : LRR_MATCH_SRC | LRR_IGNORE_PRI); lws_pt_unlock(pt); if (rmat) { @@ -397,7 +382,7 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, rou = lws_malloc(sizeof(*rou), __func__); if (!rou) { - lwsl_err("%s: oom\n", __func__); + lwsl_cx_err(cx, "oom"); return LWS_HPI_RET_HANDLED; } @@ -412,7 +397,8 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, rou->uidx = _lws_route_get_uidx(cx); lws_dll2_add_tail(&rou->list, &cx->routing_table); - lwsl_info("%s: route list size %u\n", __func__, cx->routing_table.count); + lwsl_cx_info(cx, "route list size %u", + cx->routing_table.count); _lws_route_pt_close_unroutable(pt); @@ -462,6 +448,20 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, } #endif + if (!cx->nl_initial_done && + pt == &cx->pt[0] && + cx->routing_table.count) { + /* + * While netlink info still coming, keep moving the timer for + * calling it "done" to +100ms until after it stops coming + */ + lws_context_lock(cx, __func__); + lws_sul_schedule(cx, 0, &cx->sul_nl_coldplug, + lws_netlink_coldplug_done_cb, + 100 * LWS_US_PER_MS); + lws_context_unlock(cx); + } + return LWS_HPI_RET_HANDLED; } @@ -480,7 +480,7 @@ rops_pt_init_destroy_netlink(struct lws_context *context, struct msghdr msg; struct iovec iov; struct lws *wsi; - int n; + int n, ret = 1; if (destroy) { @@ -500,7 +500,7 @@ rops_pt_init_destroy_netlink(struct lws_context *context, /* we can only have one netlink socket */ return 0; - lwsl_info("%s: creating netlink skt\n", __func__); + lwsl_cx_info(context, "creating netlink skt"); /* * We want a netlink socket per pt as well @@ -508,33 +508,35 @@ rops_pt_init_destroy_netlink(struct lws_context *context, lws_context_lock(context, __func__); wsi = __lws_wsi_create_with_role(context, (int)(pt - &context->pt[0]), - &role_ops_netlink); + &role_ops_netlink, NULL); lws_context_unlock(context); if (!wsi) goto bail; wsi->desc.sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (wsi->desc.sockfd == LWS_SOCK_INVALID) { - lwsl_err("%s: unable to open netlink\n", __func__); + lwsl_cx_err(context, "unable to open netlink"); goto bail1; } - __lws_lc_tag(&context->lcg[LWSLCG_VHOST], &wsi->lc, "netlink"); + lws_plat_set_nonblocking(wsi->desc.sockfd); + + __lws_lc_tag(context, &context->lcg[LWSLCG_VHOST], &wsi->lc, + "netlink"); memset(&sanl, 0, sizeof(sanl)); sanl.nl_family = AF_NETLINK; sanl.nl_pid = (uint32_t)getpid(); - sanl.nl_groups = (1 << (RTNLGRP_LINK - 1)) | - (1 << (RTNLGRP_IPV4_ROUTE - 1)) | - (1 << (RTNLGRP_IPV4_IFADDR - 1)) + sanl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR #if defined(LWS_WITH_IPV6) - | (1 << (RTNLGRP_IPV6_ROUTE - 1)) | - (1 << (RTNLGRP_IPV6_IFADDR - 1)) + | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR #endif ; - if (bind(wsi->desc.sockfd, (struct sockaddr*)&sanl, sizeof(sanl)) < 0) { - lwsl_err("%s: netlink bind failed\n", __func__); + if (lws_fi(&context->fic, "netlink_bind") || + bind(wsi->desc.sockfd, (struct sockaddr*)&sanl, sizeof(sanl)) < 0) { + lwsl_cx_warn(context, "netlink bind failed"); + ret = 0; /* some systems deny access, just ignore */ goto bail2; } @@ -577,30 +579,28 @@ rops_pt_init_destroy_netlink(struct lws_context *context, n = (int)sendmsg(wsi->desc.sockfd, (struct msghdr *)&msg, 0); if (n < 0) { - lwsl_notice("%s: rt dump req failed... permissions? errno %d\n", - __func__, LWS_ERRNO); + lwsl_cx_notice(context, "rt dump req failed... permissions? errno %d", + LWS_ERRNO); } /* - * Responses are going to come asynchronously, since we can't process - * DNS lookups properly until we collected the initial netlink responses - * let's set a timer that will let us advance from lws_system - * LWS_SYSTATE_IFACE_COLDPLUG + * Responses are going to come asynchronously, let's block moving + * off state IFACE_COLDPLUG until we have had them. This is important + * since if we don't hold there, when we do get the responses we may + * cull any ongoing connections as unroutable otherwise */ - lwsl_debug("%s: starting netlink coldplug wait\n", __func__); - lws_sul_schedule(context, 0, &context->sul_nl_coldplug, - lws_netlink_coldplug_done_cb, 450 * LWS_US_PER_MS); + lwsl_cx_debug(context, "starting netlink coldplug wait"); return 0; bail2: - __lws_lc_untag(&wsi->lc); + __lws_lc_untag(wsi->a.context, &wsi->lc); compatible_close(wsi->desc.sockfd); bail1: lws_free(wsi); bail: - return 1; + return ret; } static const lws_rops_t rops_table_netlink[] = { diff --git a/3rdparty/libwebsockets/lib/roles/pipe/ops-pipe.c b/3rdparty/libwebsockets/lib/roles/pipe/ops-pipe.c index a55827c6..ad54a04f 100644 --- a/3rdparty/libwebsockets/lib/roles/pipe/ops-pipe.c +++ b/3rdparty/libwebsockets/lib/roles/pipe/ops-pipe.c @@ -60,7 +60,7 @@ rops_handle_POLLIN_pipe(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_PLEASE_CLOSE_ME; #endif -#if defined(LWS_WITH_THREADPOOL) +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) /* * threadpools that need to call for on_writable callbacks do it by * marking the task as needing one for its wsi, then cancelling service. @@ -93,6 +93,13 @@ rops_handle_POLLIN_pipe(struct lws_context_per_thread *pt, struct lws *wsi, } lws_end_foreach_dll_safe(d, d1); } +#endif + +#if defined(LWS_WITH_SECURE_STREAMS) + lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_cancel_notify_dll); +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) && defined(LWS_WITH_CLIENT) + lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_cancel_notify_dll); +#endif #endif /* diff --git a/3rdparty/libwebsockets/lib/roles/raw-file/ops-raw-file.c b/3rdparty/libwebsockets/lib/roles/raw-file/ops-raw-file.c index 2b60be52..0f753272 100644 --- a/3rdparty/libwebsockets/lib/roles/raw-file/ops-raw-file.c +++ b/3rdparty/libwebsockets/lib/roles/raw-file/ops-raw-file.c @@ -31,11 +31,11 @@ rops_handle_POLLIN_raw_file(struct lws_context_per_thread *pt, struct lws *wsi, int n; if (pollfd->revents & LWS_POLLOUT) { - n = lws_callback_as_writeable(wsi); if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { - lwsl_info("failed at set pollfd\n"); + lwsl_wsi_info(wsi, "failed at set pollfd"); return LWS_HPI_RET_WSI_ALREADY_DIED; } + n = lws_callback_as_writeable(wsi); if (n) return LWS_HPI_RET_PLEASE_CLOSE_ME; } @@ -44,7 +44,7 @@ rops_handle_POLLIN_raw_file(struct lws_context_per_thread *pt, struct lws *wsi, 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"); + lwsl_wsi_debug(wsi, "raw rx callback closed it"); return LWS_HPI_RET_PLEASE_CLOSE_ME; } } diff --git a/3rdparty/libwebsockets/lib/roles/raw-proxy/ops-raw-proxy.c b/3rdparty/libwebsockets/lib/roles/raw-proxy/ops-raw-proxy.c index 93e5cb5e..cac95a6d 100644 --- a/3rdparty/libwebsockets/lib/roles/raw-proxy/ops-raw-proxy.c +++ b/3rdparty/libwebsockets/lib/roles/raw-proxy/ops-raw-proxy.c @@ -48,6 +48,9 @@ rops_handle_POLLIN_raw_proxy(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_HANDLED; } + if (lwsi_state(wsi) == LRS_WAITING_CONNECT) + goto try_pollout; + if ((pollfd->revents & pollfd->events & LWS_POLLIN) && /* any tunnel has to have been established... */ lwsi_state(wsi) != LRS_SSL_ACK_PENDING && diff --git a/3rdparty/libwebsockets/lib/roles/raw-skt/ops-raw-skt.c b/3rdparty/libwebsockets/lib/roles/raw-skt/ops-raw-skt.c index ff01fd3f..453c64e7 100644 --- a/3rdparty/libwebsockets/lib/roles/raw-skt/ops-raw-skt.c +++ b/3rdparty/libwebsockets/lib/roles/raw-skt/ops-raw-skt.c @@ -24,6 +24,57 @@ #include +#if defined(LWS_WITH_CLIENT) +static int +lws_raw_skt_connect(struct lws *wsi) +{ + int n; +#if defined(LWS_WITH_TLS) + const char *cce = NULL; + char ccebuf[128]; + +#if !defined(LWS_WITH_SYS_ASYNC_DNS) + switch (lws_client_create_tls(wsi, &cce, 1)) { +#else + switch (lws_client_create_tls(wsi, &cce, 0)) { +#endif + case CCTLS_RETURN_ERROR: + lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); + return -1; + case CCTLS_RETURN_RETRY: + return 0; + case CCTLS_RETURN_DONE: + break; + } + + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + n = lws_ssl_client_connect2(wsi, ccebuf, sizeof(ccebuf)); + if (n < 0) { + lws_inform_client_conn_fail(wsi, (void *)ccebuf, + strlen(ccebuf)); + + return -1; + } + if (n != 1) + return 0; /* wait */ + } +#endif + + n = user_callback_handle_rxflow(wsi->a.protocol->callback, + wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)], + wsi->user_space, NULL, 0); + if (n) { + lws_inform_client_conn_fail(wsi, (void *)"user", 4); + return 1; + } + + lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); + lwsi_set_state(wsi, LRS_ESTABLISHED); + + return 1; /* success */ +} +#endif + static int rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, struct lws_pollfd *pollfd) @@ -55,8 +106,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, #if defined(LWS_WITH_SERVER) if (!lwsi_role_client(wsi) && lwsi_state(wsi) != LRS_ESTABLISHED) { - lwsl_debug("%s: %s: wsistate 0x%x\n", __func__, lws_wsi_tag(wsi), - (int)wsi->wsistate); + lwsl_wsi_debug(wsi, "wsistate 0x%x\n", (int)wsi->wsistate); if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, @@ -72,8 +122,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, !(wsi->favoured_pollin && (pollfd->revents & pollfd->events & LWS_POLLOUT))) { - lwsl_debug("%s: POLLIN: %s, state 0x%x\n", __func__, - lws_wsi_tag(wsi), lwsi_state(wsi)); + lwsl_wsi_debug(wsi, "POLLIN: state 0x%x", lwsi_state(wsi)); switch (lwsi_state(wsi)) { @@ -84,6 +133,14 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, case LRS_WAITING_CONNECT: goto nope; + case LRS_WAITING_SSL: +#if defined(LWS_WITH_CLIENT) + n = lws_raw_skt_connect(wsi); + if (n < 0) + goto fail; +#endif + break; + #if defined(LWS_WITH_SOCKS5) /* SOCKS Greeting Reply */ @@ -122,7 +179,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, case 0: if (wsi->unix_skt) break; - lwsl_info("%s: read 0 len\n", __func__); + lwsl_wsi_info(wsi, "read 0 len"); wsi->seen_zero_length_recv = 1; if (lws_change_pollfd(wsi, LWS_POLLIN, 0)) goto fail; @@ -156,7 +213,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, post_rx: #endif if (n < 0) { - lwsl_info("LWS_CALLBACK_RAW_RX_fail\n"); + lwsl_wsi_info(wsi, "LWS_CALLBACK_RAW_RX_fail"); goto fail; } @@ -179,16 +236,21 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_HANDLED; #if defined(LWS_WITH_CLIENT) - if (lwsi_state(wsi) == LRS_WAITING_CONNECT && - !lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL)) + if (lwsi_state(wsi) == LRS_WAITING_CONNECT) { + if (!lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL)) return LWS_HPI_RET_WSI_ALREADY_DIED; + + if (lws_raw_skt_connect(wsi) < 0) + goto fail; + } #endif + if (lwsi_state(wsi) == LRS_WAITING_SSL) + return LWS_HPI_RET_HANDLED; + /* one shot */ - if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { - lwsl_notice("%s a\n", __func__); + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) goto fail; - } /* clear back-to-back write detection */ wsi->could_have_pending = 0; diff --git a/3rdparty/libwebsockets/lib/roles/ws/client-parser-ws.c b/3rdparty/libwebsockets/lib/roles/ws/client-parser-ws.c index b578f0f2..f569532e 100644 --- a/3rdparty/libwebsockets/lib/roles/ws/client-parser-ws.c +++ b/3rdparty/libwebsockets/lib/roles/ws/client-parser-ws.c @@ -51,7 +51,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) lws_remove_wsi_from_draining_ext_list(wsi); rx_draining_ext = 1; - lwsl_debug("%s: doing draining flow\n", __func__); + lwsl_wsi_debug(wsi, "doing draining flow"); goto drain_extension; } @@ -100,7 +100,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; case LWSWSOPC_CONTINUATION: if (!wsi->ws->continuation_possible) { - lwsl_info("disordered continuation\n"); + lwsl_wsi_info(wsi, "disordered continuation"); return -1; } wsi->ws->first_fragment = 0; @@ -119,7 +119,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case 0xd: case 0xe: case 0xf: - lwsl_info("illegal opcode\n"); + lwsl_wsi_info(wsi, "illegal opcode"); return -1; default: wsi->ws->defeat_check_utf8 = 1; @@ -132,17 +132,17 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) !wsi->ws->count_act_ext && #endif wsi->ws->rsv) { - lwsl_info("illegal rsv bits set\n"); + lwsl_wsi_info(wsi, "illegal rsv bits set"); return -1; } wsi->ws->final = !!((c >> 7) & 1); - lwsl_ext("%s: This RX frame Final %d\n", __func__, + lwsl_wsi_ext(wsi, " This RX frame Final %d", wsi->ws->final); if (wsi->ws->owed_a_fin && (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME || wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) { - lwsl_info("hey you owed us a FIN\n"); + lwsl_wsi_info(wsi, "hey you owed us a FIN"); return -1; } if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) { @@ -151,7 +151,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) } if ((wsi->ws->opcode & 8) && !wsi->ws->final) { - lwsl_info("control msg can't be fragmented\n"); + lwsl_wsi_info(wsi, "control msg can't be fragmented"); return -1; } if (!wsi->ws->final) @@ -168,7 +168,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; default: - lwsl_err("unknown spec version %02d\n", + lwsl_wsi_err(wsi, "unknown spec version %02d", wsi->ws->ietf_spec_revision); break; } @@ -177,6 +177,8 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case LWS_RXPS_04_FRAME_HDR_LEN: wsi->ws->this_frame_masked = !!(c & 0x80); + if (wsi->ws->this_frame_masked) + goto server_cannot_mask; switch (c & 0x7f) { case 126: @@ -231,7 +233,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case LWS_RXPS_04_FRAME_HDR_LEN64_8: if (c & 0x80) { - lwsl_warn("b63 of length must be zero\n"); + lwsl_wsi_warn(wsi, "b63 of length must be zero"); /* kill the connection */ return -1; } @@ -350,8 +352,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) if (--wsi->ws->rx_packet_length == 0) { /* spill because we have the whole frame */ wsi->lws_rx_parse_state = LWS_RXPS_NEW; - lwsl_debug("%s: spilling as we have the whole frame\n", - __func__); + lwsl_wsi_debug(wsi, "spilling as we have the whole frame"); goto spill; } @@ -369,8 +370,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) /* spill because we filled our rx buffer */ - lwsl_debug("%s: spilling as we filled our rx buffer\n", - __func__); + lwsl_wsi_debug(wsi, "spilling as we filled our rx buffer"); spill: handled = 0; @@ -396,11 +396,11 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) * fine he has told us he is closing too, let's * finish our close */ - lwsl_parser("seen server's close ack\n"); + lwsl_wsi_parser(wsi, "seen server's close ack"); return -1; } - lwsl_parser("client sees server close len = %d\n", + lwsl_wsi_parser(wsi, "client sees server close len = %d", (int)wsi->ws->rx_ubuf_head); if (wsi->ws->rx_ubuf_head >= 2) { close_code = (unsigned short)((pp[0] << 8) | pp[1]); @@ -426,8 +426,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) wsi->ws->close_in_ping_buffer_len = (uint8_t)wsi->ws->rx_ubuf_head; - lwsl_info("%s: scheduling return close as ack\n", - __func__); + lwsl_wsi_info(wsi, "scheduling return close as ack"); __lws_change_pollfd(wsi, LWS_POLLIN, 0); lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3); wsi->waiting_to_send_close_frame = 1; @@ -438,35 +437,35 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; case LWSWSOPC_PING: - lwsl_info("received %d byte ping, sending pong\n", + lwsl_wsi_info(wsi, "received %d byte ping, sending pong", (int)wsi->ws->rx_ubuf_head); /* he set a close reason on this guy, ignore PING */ if (wsi->ws->close_in_ping_buffer_len) goto ping_drop; - if (wsi->ws->ping_pending_flag) { + if (wsi->ws->pong_pending_flag) { /* - * there is already a pending ping payload + * there is already a pending pong payload * we should just log and drop */ - lwsl_parser("DROP PING since one pending\n"); + lwsl_wsi_parser(wsi, "DROP PING since one pending"); goto ping_drop; } /* control packets can only be < 128 bytes long */ if (wsi->ws->rx_ubuf_head > 128 - 3) { - lwsl_parser("DROP PING payload too large\n"); + lwsl_wsi_parser(wsi, "DROP PING payload too large"); goto ping_drop; } /* stash the pong payload */ - memcpy(wsi->ws->ping_payload_buf + LWS_PRE, + memcpy(wsi->ws->pong_payload_buf + LWS_PRE, &wsi->ws->rx_ubuf[LWS_PRE], wsi->ws->rx_ubuf_head); - wsi->ws->ping_payload_len = (uint8_t)wsi->ws->rx_ubuf_head; - wsi->ws->ping_pending_flag = 1; + wsi->ws->pong_payload_len = (uint8_t)wsi->ws->rx_ubuf_head; + wsi->ws->pong_pending_flag = 1; /* get it sent as soon as possible */ lws_callback_on_writable(wsi); @@ -476,8 +475,8 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; case LWSWSOPC_PONG: - lwsl_info("%s: %s received pong\n", __func__, lws_wsi_tag(wsi)); - lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE], + lwsl_wsi_info(wsi, "Received pong"); + lwsl_hexdump_wsi_debug(wsi, &wsi->ws->rx_ubuf[LWS_PRE], wsi->ws->rx_ubuf_head); lws_validity_confirmed(wsi); @@ -492,7 +491,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) default: /* not handled or failed */ - lwsl_ext("Unhandled ext opc 0x%x\n", wsi->ws->opcode); + lwsl_wsi_ext(wsi, "Unhandled ext opc 0x%x", wsi->ws->opcode); wsi->ws->rx_ubuf_head = 0; return -1; @@ -522,26 +521,26 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) pmdrx.eb_out = pmdrx.eb_in; - lwsl_debug("%s: starting disbursal of %d deframed rx\n", - __func__, (int)wsi->ws->rx_ubuf_head); + lwsl_wsi_debug(wsi, "starting disbursal of %d deframed rx", + (int)wsi->ws->rx_ubuf_head); #if !defined(LWS_WITHOUT_EXTENSIONS) drain_extension: #endif do { - // lwsl_notice("%s: pmdrx.eb_in.len: %d\n", __func__, + // lwsl_wsi_notice("pmdrx.eb_in.len: %d", // (int)pmdrx.eb_in.len); n = PMDR_DID_NOTHING; #if !defined(LWS_WITHOUT_EXTENSIONS) - lwsl_ext("%s: +++ passing %d %p to ext\n", __func__, + lwsl_wsi_ext(wsi, "+++ passing %d %p to ext", pmdrx.eb_in.len, pmdrx.eb_in.token); n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &pmdrx, 0); - lwsl_ext("Ext RX returned %d\n", n); + lwsl_wsi_ext(wsi, "Ext RX returned %d", n); if (n < 0) { wsi->socket_is_permanently_unusable = 1; return -1; @@ -550,23 +549,21 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) /* ie, not PMDR_NOTHING_WE_SHOULD_DO */ break; #endif - lwsl_ext("%s: post inflate ebuf in len %d / out len %d\n", - __func__, pmdrx.eb_in.len, pmdrx.eb_out.len); + lwsl_wsi_ext(wsi, "post inflate ebuf in len %d / out len %d", + pmdrx.eb_in.len, pmdrx.eb_out.len); #if !defined(LWS_WITHOUT_EXTENSIONS) if (rx_draining_ext && !pmdrx.eb_out.len) { - lwsl_debug(" --- ending drain on 0 read result\n"); + lwsl_wsi_debug(wsi, " --- ending drain on 0 read result"); goto already_done; } if (n == PMDR_HAS_PENDING) { /* 1 means stuff to drain */ /* extension had more... main loop will come back */ - lwsl_ext("%s: adding to draining ext list\n", - __func__); + lwsl_wsi_ext(wsi, "adding to draining ext list"); lws_add_wsi_to_draining_ext_list(wsi); } else { - lwsl_ext("%s: removing from draining ext list\n", - __func__); + lwsl_wsi_ext(wsi, "removing from draining ext list"); lws_remove_wsi_from_draining_ext_list(wsi); } rx_draining_ext = wsi->ws->rx_draining_ext; @@ -591,13 +588,13 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) && (n == PMDR_EMPTY_FINAL || n == PMDR_UNKNOWN) #endif ) { - lwsl_info("FINAL utf8 error\n"); + lwsl_wsi_info(wsi, "FINAL utf8 error"); lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD, (uint8_t *)"partial utf8", 12); utf8_fail: - lwsl_info("utf8 error\n"); - lwsl_hexdump_info(pmdrx.eb_out.token, + lwsl_wsi_info(wsi, "utf8 error"); + lwsl_hexdump_wsi_info(wsi, pmdrx.eb_out.token, (unsigned int)pmdrx.eb_out.len); return -1; @@ -617,7 +614,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) goto already_done; if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG) - lwsl_info("Client doing pong callback\n"); + lwsl_wsi_info(wsi, "Client doing pong callback"); #if !defined(LWS_WITHOUT_EXTENSIONS) if (n == PMDR_HAS_PENDING) @@ -652,8 +649,8 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) wsi->ws->first_fragment = 0; - lwsl_debug("%s: bulk ws rx: inp used %d, output %d\n", - __func__, (int)wsi->ws->rx_ubuf_head, + lwsl_wsi_debug(wsi, "bulk ws rx: inp used %d, output %d", + (int)wsi->ws->rx_ubuf_head, (int)pmdrx.eb_out.len); /* if user code wants to close, let caller know */ @@ -670,14 +667,24 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) wsi->ws->rx_ubuf_head = 0; break; default: - lwsl_err("client rx illegal state\n"); + lwsl_wsi_err(wsi, "client rx illegal state"); return 1; } return 0; illegal_ctl_length: - lwsl_warn("Control frame asking for extended length is illegal\n"); + lwsl_wsi_warn(wsi, "Control frame asking for extended length is illegal"); + + /* kill the connection */ + return -1; + +server_cannot_mask: + lws_close_reason(wsi, + LWS_CLOSE_STATUS_PROTOCOL_ERR, + (uint8_t *)"srv mask", 8); + + lwsl_wsi_warn(wsi, "Server must not mask"); /* kill the connection */ return -1; diff --git a/3rdparty/libwebsockets/lib/roles/ws/client-ws.c b/3rdparty/libwebsockets/lib/roles/ws/client-ws.c index 7a795b61..bc2a8468 100644 --- a/3rdparty/libwebsockets/lib/roles/ws/client-ws.c +++ b/3rdparty/libwebsockets/lib/roles/ws/client-ws.c @@ -51,7 +51,7 @@ lws_create_client_ws_object(const struct lws_client_connect_info *i, /* allocate the ws struct for the wsi */ wsi->ws = lws_zalloc(sizeof(*wsi->ws), "client ws struct"); if (!wsi->ws) { - lwsl_notice("OOM\n"); + lwsl_wsi_notice(wsi, "OOM"); return 1; } @@ -77,14 +77,14 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) !lwsi_role_client(wsi)) return 0; - lwsl_debug("%s: hs client feels it has %d in\n", __func__, (int)len); + lwsl_wsi_debug(wsi, "hs client feels it has %d in", (int)len); while (len) { /* * we were accepting input but now we stopped doing so */ if (lws_is_flowcontrolled(wsi)) { - lwsl_debug("%s: caching %ld\n", __func__, (long)len); + lwsl_wsi_debug(wsi, "caching %ld", (long)len); /* * Since we cached the remaining available input, we * can say we "consumed" it. @@ -103,8 +103,7 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) * 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", - __func__); + lwsl_wsi_info(wsi, "trimming inside rxflow cache"); *buf = bufin; } else *buf += len; @@ -115,7 +114,7 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) if (wsi->ws->rx_draining_ext) { int m; - lwsl_info("%s: draining ext\n", __func__); + lwsl_wsi_info(wsi, "draining ext"); if (lwsi_role_client(wsi)) m = lws_ws_client_rx_sm(wsi, 0); else @@ -131,13 +130,13 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) */ if (lws_ws_client_rx_sm(wsi, *(*buf)++)) { - lwsl_info("%s: client_rx_sm exited, DROPPING %d\n", - __func__, (int)len); + lwsl_wsi_info(wsi, "client_rx_sm exited, DROPPING %d", + (int)len); return -1; } len--; } - // lwsl_notice("%s: finished with %ld\n", __func__, (long)len); + // lwsl_wsi_notice(wsi, "finished with %ld", (long)len); return 0; } @@ -157,7 +156,7 @@ lws_generate_client_ws_handshake(struct lws *wsi, char *p, const char *conn1) * create the random key */ if (lws_get_random(wsi->a.context, hash, 16) != 16) { - lwsl_err("Unable to read from random dev %s\n", + lwsl_wsi_err(wsi, "Unable to read from random dev %s", SYSTEM_RANDOM_FILEPATH); return NULL; } @@ -252,44 +251,40 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) #endif if (wsi->client_mux_substream) {/* !!! client ws-over-h2 not there yet */ - lwsl_warn("%s: client ws-over-h2 upgrade not supported yet\n", - __func__); + lwsl_wsi_warn(wsi, "client ws-over-h2 upgrade not supported yet"); *cce = "HS: h2 / ws upgrade unsupported"; goto bail3; } if (wsi->http.ah->http_response == 401) { - lwsl_warn( - "lws_client_handshake: got bad HTTP response '%d'\n", - wsi->http.ah->http_response); + lwsl_wsi_warn(wsi, "got bad HTTP response '%d'", + wsi->http.ah->http_response); *cce = "HS: ws upgrade unauthorized"; goto bail3; } if (wsi->http.ah->http_response != 101) { - lwsl_warn( - "lws_client_handshake: got bad HTTP response '%d'\n", - wsi->http.ah->http_response); + lwsl_wsi_warn(wsi, "got bad HTTP response '%d'", + wsi->http.ah->http_response); *cce = "HS: ws upgrade response not 101"; goto bail3; } if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) { - lwsl_info("no ACCEPT\n"); + lwsl_wsi_info(wsi, "no ACCEPT"); *cce = "HS: ACCEPT missing"; goto bail3; } p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE); if (!p) { - lwsl_info("no UPGRADE\n"); + lwsl_wsi_info(wsi, "no UPGRADE"); *cce = "HS: UPGRADE missing"; goto bail3; } strtolower(p); if (strcmp(p, "websocket")) { - lwsl_warn( - "lws_client_handshake: got bad Upgrade header '%s'\n", p); + lwsl_wsi_warn(wsi, "got bad Upgrade header '%s'", p); *cce = "HS: Upgrade to something other than websocket"; goto bail3; } @@ -316,8 +311,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) default: /* includes ENDED found by the tokenizer itself */ bad_conn_format: - lwsl_info("%s: malfored connection '%s'\n", - __func__, buf); + lwsl_wsi_info(wsi, "malformed connection '%s'", buf); *cce = "HS: UPGRADE malformed"; goto bail3; } @@ -325,10 +319,10 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); #if defined(_DEBUG) - if (!pc) { - lwsl_parser("lws_client_int_s_hs: no protocol list\n"); - } else - lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc); + if (!pc) + lwsl_wsi_parser(wsi, "lws_client_int_s_hs: no protocol list"); + else + lwsl_wsi_parser(wsi, "lws_client_int_s_hs: protocol list '%s'", pc); #endif /* @@ -338,7 +332,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL); if (!len) { - lwsl_info("%s: WSI_TOKEN_PROTOCOL is null\n", __func__); + lwsl_wsi_info(wsi, "WSI_TOKEN_PROTOCOL is null"); /* * no protocol name to work from, if we don't already have one * default to first protocol @@ -372,7 +366,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } if (!okay) { - lwsl_info("%s: got bad protocol %s\n", __func__, p); + lwsl_wsi_info(wsi, "got bad protocol %s", p); *cce = "HS: PROTOCOL malformed"; goto bail2; } @@ -404,7 +398,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) 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); + lwsl_wsi_info(wsi, "fail protocol %s", p); *cce = "HS: Cannot match protocol"; goto bail2; } @@ -423,16 +417,17 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) if (!wsi->a.vhost->protocols[n].callback) { if (wsi->a.protocol) - lwsl_err("Failed to match protocol %s\n", + lwsl_wsi_err(wsi, "Failed to match protocol %s", wsi->a.protocol->name); else - lwsl_err("No protocol on client\n"); + lwsl_wsi_err(wsi, "No protocol on client"); *cce = "ws protocol no match"; goto bail2; } } - lwsl_debug("Selected protocol %s\n", wsi->a.protocol->name); + lwsl_wsi_debug(wsi, "Selected protocol %s", wsi->a.protocol ? + wsi->a.protocol->name : "no pcol"); check_extensions: /* @@ -449,7 +444,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) /* instantiate the accepted extensions */ if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) { - lwsl_ext("no client extensions allowed by server\n"); + lwsl_wsi_ext(wsi, "no client extensions allowed by server"); goto check_accept; } @@ -460,7 +455,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) if (lws_hdr_copy(wsi, sb, (int)context->pt_serv_buf_size, WSI_TOKEN_EXTENSIONS) < 0) { - lwsl_warn("ext list from server failed to copy\n"); + lwsl_wsi_warn(wsi, "ext list from server failed to copy"); *cce = "HS: EXT: list too big"; goto bail2; } @@ -499,7 +494,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) /* check we actually support it */ - lwsl_notice("checking client ext %s\n", ext_name); + lwsl_wsi_notice(wsi, "checking client ext %s", ext_name); n = 0; ext = wsi->a.vhost->ws.extensions; @@ -510,7 +505,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } n = 1; - lwsl_notice("instantiating client ext %s\n", ext_name); + lwsl_wsi_notice(wsi, "instantiating client ext %s", ext_name); /* instantiate the extension on this conn */ @@ -523,7 +518,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) (void *)&wsi->ws->act_ext_user[ wsi->ws->count_act_ext], (void *)&opts, 0)) { - lwsl_info(" ext %s failed construction\n", + lwsl_wsi_info(wsi, " ext %s failed construction", ext_name); ext++; continue; @@ -548,8 +543,8 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) wsi->ws->count_act_ext], opts, ext_name, (int)strlen(ext_name))) { - lwsl_err("%s: unable to parse user defaults '%s'", - __func__, ext_name); + lwsl_wsi_err(wsi, "unable to parse user defaults '%s'", + ext_name); *cce = "HS: EXT: failed parsing defaults"; goto bail2; } @@ -561,8 +556,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) wsi->ws->act_ext_user[ wsi->ws->count_act_ext], opts, a, lws_ptr_diff(c, a))) { - lwsl_err("%s: unable to parse remote def '%s'", - __func__, a); + lwsl_wsi_err(wsi, "unable to parse remote def '%s'", a); *cce = "HS: EXT: failed parsing options"; goto bail2; } @@ -571,8 +565,8 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) LWS_EXT_CB_OPTION_CONFIRM, wsi->ws->act_ext_user[wsi->ws->count_act_ext], NULL, 0)) { - lwsl_err("%s: ext %s rejects server options %s", - __func__, ext->name, a); + lwsl_wsi_err(wsi, "ext %s rejects server options %s", + ext->name, a); *cce = "HS: EXT: Rejects server options"; goto bail2; } @@ -583,7 +577,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } if (n == 0) { - lwsl_warn("Unknown ext '%s'!\n", ext_name); + lwsl_wsi_warn(wsi, "Unknown ext '%s'!", ext_name); *cce = "HS: EXT: unknown ext"; goto bail2; } @@ -601,7 +595,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT); if (strcmp(p, wsi->http.ah->initial_handshake_hash_base64)) { - lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p, + lwsl_wsi_warn(wsi, "lws_client_int_s_hs: accept '%s' wrong vs '%s'", p, wsi->http.ah->initial_handshake_hash_base64); *cce = "HS: Accept hash wrong"; goto bail2; @@ -609,7 +603,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) /* allocate the per-connection user memory (if any) */ if (lws_ensure_user_space(wsi)) { - lwsl_err("Problem allocating wsi user mem\n"); + lwsl_wsi_err(wsi, "Problem allocating wsi user mem"); *cce = "HS: OOM"; goto bail2; } @@ -648,13 +642,13 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) wsi->ws->rx_ubuf = lws_malloc((unsigned int)n + 4 /* 0x0000ffff zlib */, "client frame buffer"); if (!wsi->ws->rx_ubuf) { - lwsl_err("Out of Mem allocating rx buffer %d\n", n); + lwsl_wsi_err(wsi, "OOM allocating rx buffer %d", n); *cce = "HS: OOM"; goto bail2; } wsi->ws->rx_ubuf_alloc = (unsigned int)n; - lwsl_debug("handshake OK for protocol %s\n", wsi->a.protocol->name); + lwsl_wsi_debug(wsi, "handshake OK for protocol %s", wsi->a.protocol->name); /* call him back to inform him he is up */ diff --git a/3rdparty/libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c b/3rdparty/libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c index c442f7c1..79c70ea9 100644 --- a/3rdparty/libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c +++ b/3rdparty/libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c @@ -62,7 +62,7 @@ lws_extension_pmdeflate_restrict_args(struct lws *wsi, if (extra < priv->args[PMD_RX_BUF_PWR2]) { priv->args[PMD_RX_BUF_PWR2] = (unsigned char)extra; - lwsl_info(" Capping pmd rx to %d\n", 1 << extra); + lwsl_wsi_info(wsi, " Capping pmd rx to %d", 1 << extra); } } @@ -89,8 +89,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, oa = in; if (!oa->option_name) break; - lwsl_ext("%s: named option set: %s\n", __func__, - oa->option_name); + lwsl_wsi_ext(wsi, "named option set: %s", oa->option_name); for (n = 0; n < (int)LWS_ARRAY_SIZE(lws_ext_pm_deflate_options); n++) if (!strcmp(lws_ext_pm_deflate_options[n].name, @@ -105,7 +104,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, case LWS_EXT_CB_OPTION_SET: oa = in; - lwsl_ext("%s: option set: idx %d, %s, len %d\n", __func__, + lwsl_wsi_ext(wsi, "option set: idx %d, %s, len %d", oa->option_index, oa->start, oa->len); if (oa->start) priv->args[oa->option_index] = (unsigned char)atoi(oa->start); @@ -134,8 +133,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, 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", + lwsl_wsi_info(wsi, " permessage-deflate requires the protocol " + "(%s) to have an RX buffer >= 128", wsi->a.protocol->name); return -1; } @@ -143,7 +142,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, /* fill in **user */ priv = lws_zalloc(sizeof(*priv), "pmd priv"); *((void **)user) = priv; - lwsl_ext("%s: LWS_EXT_CB_*CONSTRUCT\n", __func__); + lwsl_wsi_ext(wsi, "LWS_EXT_CB_*CONSTRUCT"); memset(priv, 0, sizeof(*priv)); /* fill in pointer to options list */ @@ -173,7 +172,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, break; case LWS_EXT_CB_DESTROY: - lwsl_ext("%s: LWS_EXT_CB_DESTROY\n", __func__); + lwsl_wsi_ext(wsi, "LWS_EXT_CB_DESTROY"); lws_free(priv->buf_rx_inflated); lws_free(priv->buf_tx_deflated); if (priv->rx_init) @@ -189,8 +188,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, /* * ie, we are INFLATING */ - lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n", - __func__, pmdrx->eb_in.len, priv->rx.avail_in); + lwsl_wsi_ext(wsi, " LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d", + pmdrx->eb_in.len, priv->rx.avail_in); /* * If this frame is not marked as compressed, @@ -216,8 +215,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pmdrx->eb_out.len = 0; - lwsl_ext("%s: LWS_EXT_CB_PAYLOAD_RX: in %d, " - "existing avail in %d, pkt fin: %d\n", __func__, + lwsl_wsi_ext(wsi, "LWS_EXT_CB_PAYLOAD_RX: in %d, " + "existing avail in %d, pkt fin: %d", pmdrx->eb_in.len, priv->rx.avail_in, wsi->ws->final); /* if needed, initialize the inflator */ @@ -225,7 +224,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (!priv->rx_init) { if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) { - lwsl_err("%s: iniflateInit failed\n", __func__); + lwsl_wsi_err(wsi, "iniflateInit failed"); return PMDR_FAILED; } priv->rx_init = 1; @@ -235,7 +234,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, (1 << priv->args[PMD_RX_BUF_PWR2])), "pmd rx inflate buf"); if (!priv->buf_rx_inflated) { - lwsl_err("%s: OOM\n", __func__); + lwsl_wsi_err(wsi, "OOM"); return PMDR_FAILED; } } @@ -248,8 +247,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (priv->rx.avail_in && pmdrx->eb_in.token && pmdrx->eb_in.len) { - lwsl_warn("%s: priv->rx.avail_in %d while getting new in\n", - __func__, priv->rx.avail_in); + lwsl_wsi_warn(wsi, "priv->rx.avail_in %d while getting new in", + priv->rx.avail_in); // assert(0); } #endif @@ -277,7 +276,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, wsi->ws->final && !wsi->ws->rx_packet_length && wsi->ws->pmd_trailer_application) { - lwsl_ext("%s: trailer apply 1\n", __func__); + lwsl_wsi_ext(wsi, "trailer apply 1"); was_fin = 1; wsi->ws->pmd_trailer_application = 0; priv->rx.next_in = trail; @@ -293,15 +292,15 @@ lws_extension_callback_pm_deflate(struct lws_context *context, return PMDR_DID_NOTHING; n = inflate(&priv->rx, was_fin ? Z_SYNC_FLUSH : Z_NO_FLUSH); - lwsl_ext("inflate ret %d, avi %d, avo %d, wsifinal %d\n", n, + lwsl_wsi_ext(wsi, "inflate ret %d, avi %d, avo %d, wsifinal %d", n, priv->rx.avail_in, priv->rx.avail_out, wsi->ws->final); switch (n) { case Z_NEED_DICT: case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: - lwsl_err("%s: zlib error inflate %d: \"%s\"\n", - __func__, n, priv->rx.msg); + lwsl_wsi_err(wsi, "zlib error inflate %d: \"%s\"", + n, priv->rx.msg); return PMDR_FAILED; } @@ -313,7 +312,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, ((unsigned int)pmdrx->eb_in.len - (unsigned int)priv->rx.avail_in); pmdrx->eb_in.len = (int)priv->rx.avail_in; - lwsl_debug("%s: %d %d %d %d %d\n", __func__, + lwsl_wsi_debug(wsi, "%d %d %d %d %d", priv->rx.avail_in, wsi->ws->final, (int)wsi->ws->rx_packet_length, @@ -325,7 +324,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, !wsi->ws->rx_packet_length && !was_fin && wsi->ws->pmd_trailer_application) { - lwsl_ext("%s: RX trailer apply 2\n", __func__); + lwsl_wsi_ext(wsi, "RX trailer apply 2"); /* we overallocated just for this situation where * we might issue something */ @@ -336,14 +335,14 @@ lws_extension_callback_pm_deflate(struct lws_context *context, priv->rx.next_in = trail; priv->rx.avail_in = sizeof(trail); n = inflate(&priv->rx, Z_SYNC_FLUSH); - lwsl_ext("RX trailer infl ret %d, avi %d, avo %d\n", + lwsl_wsi_ext(wsi, "RX trailer infl ret %d, avi %d, avo %d", n, priv->rx.avail_in, priv->rx.avail_out); switch (n) { case Z_NEED_DICT: case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: - lwsl_info("zlib error inflate %d: %s\n", + lwsl_wsi_info(wsi, "zlib error inflate %d: %s", n, priv->rx.msg); return -1; } @@ -355,16 +354,16 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pmdrx->eb_out.token); priv->count_rx_between_fin = priv->count_rx_between_fin + (size_t)pmdrx->eb_out.len; - lwsl_ext(" %s: RX leaving with new effbuff len %d, " - "rx.avail_in=%d, TOTAL RX since FIN %lu\n", - __func__, pmdrx->eb_out.len, priv->rx.avail_in, + lwsl_wsi_ext(wsi, " RX leaving with new effbuff len %d, " + "rx.avail_in=%d, TOTAL RX since FIN %lu", + pmdrx->eb_out.len, priv->rx.avail_in, (unsigned long)priv->count_rx_between_fin); if (was_fin) { - lwsl_ext("%s: was_fin\n", __func__); + lwsl_wsi_ext(wsi, "was_fin"); priv->count_rx_between_fin = 0; if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) { - lwsl_ext("PMD_SERVER_NO_CONTEXT_TAKEOVER\n"); + lwsl_wsi_ext(wsi, "PMD_SERVER_NO_CONTEXT_TAKEOVER"); (void)inflateEnd(&priv->rx); priv->rx_init = 0; } @@ -393,7 +392,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, priv->args[PMD_MEM_LEVEL], Z_DEFAULT_STRATEGY); if (n != Z_OK) { - lwsl_ext("inflateInit2 failed %d\n", n); + lwsl_wsi_ext(wsi, "inflateInit2 failed %d", n); return PMDR_FAILED; } priv->tx_init = 1; @@ -404,7 +403,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, (1 << priv->args[PMD_TX_BUF_PWR2])), "pmd tx deflate buf"); if (!priv->buf_tx_deflated) { - lwsl_err("%s: OOM\n", __func__); + lwsl_wsi_err(wsi, "OOM"); return PMDR_FAILED; } @@ -415,8 +414,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, assert(!priv->tx.avail_in); priv->count_tx_between_fin = priv->count_tx_between_fin + (size_t)pmdrx->eb_in.len; - lwsl_ext("%s: TX: eb_in length %d, " - "TOTAL TX since FIN: %d\n", __func__, + lwsl_wsi_ext(wsi, "TX: eb_in length %d, " + "TOTAL TX since FIN: %d", pmdrx->eb_in.len, (int)priv->count_tx_between_fin); priv->tx.next_in = (unsigned char *)pmdrx->eb_in.token; @@ -433,7 +432,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pen = pen | (unsigned int)penbits; if (!priv->tx.avail_in && (len & LWS_WRITE_NO_FIN)) { - lwsl_ext("%s: no available in, pen: %u\n", __func__, pen); + lwsl_wsi_ext(wsi, "no available in, pen: %u", pen); if (!pen) return PMDR_DID_NOTHING; @@ -441,20 +440,20 @@ lws_extension_callback_pm_deflate(struct lws_context *context, m = Z_NO_FLUSH; if (!(len & LWS_WRITE_NO_FIN)) { - lwsl_ext("%s: deflate with SYNC_FLUSH, pkt len %d\n", - __func__, (int)wsi->ws->rx_packet_length); + lwsl_wsi_ext(wsi, "deflate with SYNC_FLUSH, pkt len %d", + (int)wsi->ws->rx_packet_length); m = Z_SYNC_FLUSH; } n = deflate(&priv->tx, m); if (n == Z_STREAM_ERROR) { - lwsl_notice("%s: Z_STREAM_ERROR\n", __func__); + lwsl_wsi_notice(wsi, "Z_STREAM_ERROR"); return PMDR_FAILED; } pen = (!priv->tx.avail_out) && n != Z_STREAM_END; - lwsl_ext("%s: deflate ret %d, len 0x%x\n", __func__, n, + lwsl_wsi_ext(wsi, "deflate ret %d, len 0x%x", n, (unsigned int)len); if ((len & 0xf) == LWS_WRITE_TEXT) @@ -467,8 +466,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (m == Z_SYNC_FLUSH && !(len & LWS_WRITE_NO_FIN) && !pen && pmdrx->eb_out.len < 4) { - lwsl_err("%s: FAIL want to trim out length %d\n", - __func__, (int)pmdrx->eb_out.len); + lwsl_wsi_err(wsi, "FAIL want to trim out length %d", + (int)pmdrx->eb_out.len); assert(0); } @@ -476,7 +475,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, m == Z_SYNC_FLUSH && !pen && pmdrx->eb_out.len >= 4) { - // lwsl_err("%s: Trimming 4 from end of write\n", __func__); + // lwsl_wsi_err(wsi, "Trimming 4 from end of write"); priv->tx.next_out -= 4; priv->tx.avail_out += 4; priv->count_tx_between_fin = 0; @@ -500,8 +499,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pmdrx->eb_out.len = lws_ptr_diff(priv->tx.next_out, pmdrx->eb_out.token); - lwsl_ext(" TX rewritten with new eb_in len %d, " - "eb_out len %d, deflatePending %d\n", + lwsl_wsi_ext(wsi, " TX rewritten with new eb_in len %d, " + "eb_out len %d, deflatePending %d", pmdrx->eb_in.len, pmdrx->eb_out.len, pen); if (pmdrx->eb_in.len || pen) @@ -538,13 +537,13 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (n == LWSWSOPC_TEXT_FRAME || n == LWSWSOPC_BINARY_FRAME) *pmdrx->eb_in.token |= 0x40; - lwsl_ext("%s: PRESEND compressed: ws frame 0x%02X, len %d\n", - __func__, ((*pmdrx->eb_in.token) & 0xff), + lwsl_wsi_ext(wsi, "PRESEND compressed: ws frame 0x%02X, len %d", + ((*pmdrx->eb_in.token) & 0xff), pmdrx->eb_in.len); if (((*pmdrx->eb_in.token) & 0x80) && /* fin */ priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) { - lwsl_debug("PMD_CLIENT_NO_CONTEXT_TAKEOVER\n"); + lwsl_wsi_debug(wsi, "PMD_CLIENT_NO_CONTEXT_TAKEOVER"); (void)deflateEnd(&priv->tx); priv->tx_init = 0; } diff --git a/3rdparty/libwebsockets/lib/roles/ws/ext/extension.c b/3rdparty/libwebsockets/lib/roles/ws/ext/extension.c index 38fd2995..dd6539b7 100644 --- a/3rdparty/libwebsockets/lib/roles/ws/ext/extension.c +++ b/3rdparty/libwebsockets/lib/roles/ws/ext/extension.c @@ -30,7 +30,7 @@ void lws_context_init_extensions(const struct lws_context_creation_info *info, struct lws_context *context) { - lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE); + lwsl_cx_info(context, " LWS_MAX_EXTENSIONS_ACTIVE: %u", LWS_MAX_EXTENSIONS_ACTIVE); } enum lws_ext_option_parser_states { @@ -56,7 +56,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, while (opts[count_options].name) count_options++; while (len) { - lwsl_ext("'%c' %d", *in, leap); + lwsl_wsi_ext(wsi, "'%c' %d", *in, leap); switch (leap) { case LEAPS_SEEK_NAME: if (*in == ' ') @@ -83,12 +83,12 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, n++; continue; } - lwsl_ext(" m=%d, n=%d, w=%d\n", m, n, w); + lwsl_wsi_ext(wsi, " m=%d, n=%d, w=%d", m, n, w); if (*in == opts[n].name[w]) { if (!opts[n].name[w + 1]) { oa.option_index = (int)n; - lwsl_ext("hit %d\n", + lwsl_wsi_ext(wsi, "hit %d", oa.option_index); leap = LEAPS_SEEK_VAL; if (len == 1) @@ -98,7 +98,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, } else { match_map &= (unsigned int)~(1 << n); if (!match_map) { - lwsl_ext("empty match map\n"); + lwsl_wsi_ext(wsi, "empty match map"); return -1; } } @@ -200,7 +200,7 @@ int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len) lws_get_context(wsi), wsi->ws->active_extensions[n], wsi, (enum lws_extension_callback_reasons)reason, wsi->ws->act_ext_user[n], arg, (size_t)len); if (m < 0) { - lwsl_ext("Ext '%s' failed to handle callback %d!\n", + lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!", wsi->ws->active_extensions[n]->name, reason); return -1; } @@ -229,7 +229,7 @@ int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, m = ext->callback(context, ext, wsi, (enum lws_extension_callback_reasons)reason, (void *)(lws_intptr_t)n, arg, (size_t)len); if (m < 0) { - lwsl_ext("Ext '%s' failed to handle callback %d!\n", + lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!", wsi->ws->active_extensions[n]->name, reason); return -1; } @@ -284,7 +284,7 @@ lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) if (ebuf.len) { n = lws_issue_raw(wsi, ebuf.token, (size_t)ebuf.len); if (n < 0) { - lwsl_info("closing from ext access\n"); + lwsl_wsi_info(wsi, "closing from ext access"); return -1; } @@ -292,8 +292,7 @@ lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) if (wsi->ws->clean_buffer) len = (size_t)n; - lwsl_ext("%s: written %d bytes to client\n", - __func__, n); + lwsl_wsi_ext(wsi, "written %d bytes to client", n); } /* no extension has more to spill? Then we can go */ @@ -315,7 +314,7 @@ lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) /* no we could add more, lets's do that */ continue; - lwsl_debug("choked\n"); + lwsl_wsi_debug(wsi, "choked"); /* * Yes, he's choked. Don't spill the rest now get a callback diff --git a/3rdparty/libwebsockets/lib/roles/ws/ops-ws.c b/3rdparty/libwebsockets/lib/roles/ws/ops-ws.c index 08299ca6..37fbd34d 100644 --- a/3rdparty/libwebsockets/lib/roles/ws/ops-ws.c +++ b/3rdparty/libwebsockets/lib/roles/ws/ops-ws.c @@ -512,9 +512,9 @@ lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c) lwsl_info("received %d byte ping, sending pong\n", (int)wsi->ws->rx_ubuf_head); - if (wsi->ws->ping_pending_flag) { + if (wsi->ws->pong_pending_flag) { /* - * there is already a pending ping payload + * there is already a pending pong payload * we should just log and drop */ lwsl_parser("DROP PING since one pending\n"); @@ -528,12 +528,12 @@ lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c) } /* stash the pong payload */ - memcpy(wsi->ws->ping_payload_buf + LWS_PRE, + memcpy(wsi->ws->pong_payload_buf + LWS_PRE, &wsi->ws->rx_ubuf[LWS_PRE], wsi->ws->rx_ubuf_head); - wsi->ws->ping_payload_len = (uint8_t)wsi->ws->rx_ubuf_head; - wsi->ws->ping_pending_flag = 1; + wsi->ws->pong_payload_len = (uint8_t)wsi->ws->rx_ubuf_head; + wsi->ws->pong_pending_flag = 1; /* get it sent as soon as possible */ lws_callback_on_writable(wsi); @@ -943,7 +943,7 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi, unsigned int pending = 0; struct lws_tokens ebuf; char buffered = 0; - int n = 0, m; + int n = 0, m, sanity = 10; #if defined(LWS_WITH_HTTP2) struct lws *wsi1; #endif @@ -1223,7 +1223,14 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi, else pending = pending > wsi->a.context->pt_serv_buf_size ? wsi->a.context->pt_serv_buf_size : pending; - goto read; + if (--sanity) + goto read; + else + /* + * Something has gone wrong, we are spinning... + * let's bail on this connection + */ + return LWS_HPI_RET_PLEASE_CLOSE_ME; } if (buffered && /* were draining, now nothing left */ @@ -1287,7 +1294,7 @@ int rops_handle_POLLOUT_ws(struct lws *wsi) /* else, the send failed and we should just hang up */ - if ((lwsi_role_ws(wsi) && wsi->ws->ping_pending_flag) || + if ((lwsi_role_ws(wsi) && wsi->ws->pong_pending_flag) || (lwsi_state(wsi) == LRS_RETURNED_CLOSE && wsi->ws->payload_is_close)) { @@ -1296,20 +1303,20 @@ int rops_handle_POLLOUT_ws(struct lws *wsi) else { if (wsi->wsistate_pre_close) { /* we started close flow, forget pong */ - wsi->ws->ping_pending_flag = 0; + wsi->ws->pong_pending_flag = 0; return LWS_HP_RET_BAIL_OK; } lwsl_info("issuing pong %d on %s\n", - wsi->ws->ping_payload_len, lws_wsi_tag(wsi)); + wsi->ws->pong_payload_len, lws_wsi_tag(wsi)); } - n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE], - wsi->ws->ping_payload_len, (enum lws_write_protocol)write_type); + n = lws_write(wsi, &wsi->ws->pong_payload_buf[LWS_PRE], + wsi->ws->pong_payload_len, (enum lws_write_protocol)write_type); if (n < 0) return LWS_HP_RET_BAIL_DIE; /* well he is sent, mark him done */ - wsi->ws->ping_pending_flag = 0; + wsi->ws->pong_pending_flag = 0; if (wsi->ws->payload_is_close) { // assert(0); /* oh... a close frame was it... then we are done */ @@ -1558,8 +1565,8 @@ rops_close_role_ws(struct lws_context_per_thread *pt, struct lws *wsi) #endif lws_free_set_NULL(wsi->ws->rx_ubuf); - wsi->ws->ping_payload_len = 0; - wsi->ws->ping_pending_flag = 0; + wsi->ws->pong_payload_len = 0; + wsi->ws->pong_pending_flag = 0; /* deallocate any active extension contexts */ diff --git a/3rdparty/libwebsockets/lib/roles/ws/private-lib-roles-ws.h b/3rdparty/libwebsockets/lib/roles/ws/private-lib-roles-ws.h index 09d5b212..d0b08707 100644 --- a/3rdparty/libwebsockets/lib/roles/ws/private-lib-roles-ws.h +++ b/3rdparty/libwebsockets/lib/roles/ws/private-lib-roles-ws.h @@ -87,6 +87,8 @@ struct lws_pt_role_ws { }; #endif +#define PAYLOAD_BUF_SIZE 128 - 3 + LWS_PRE + struct _lws_websocket_related { unsigned char *rx_ubuf; #if !defined(LWS_WITHOUT_EXTENSIONS) @@ -103,7 +105,8 @@ struct _lws_websocket_related { #endif /* Also used for close content... control opcode == < 128 */ - uint8_t ping_payload_buf[128 - 3 + LWS_PRE]; + uint8_t ping_payload_buf[PAYLOAD_BUF_SIZE]; + uint8_t pong_payload_buf[PAYLOAD_BUF_SIZE]; unsigned int final:1; unsigned int frame_is_binary:1; @@ -112,7 +115,7 @@ struct _lws_websocket_related { unsigned int inside_frame:1; /* next write will be more of frame */ unsigned int clean_buffer:1; /* buffer not rewritten by extension */ unsigned int payload_is_close:1; /* process as PONG, but it is close */ - unsigned int ping_pending_flag:1; + unsigned int pong_pending_flag:1; unsigned int continuation_possible:1; unsigned int owed_a_fin:1; unsigned int check_utf8:1; @@ -134,7 +137,7 @@ struct _lws_websocket_related { uint32_t rx_ubuf_head; uint32_t rx_ubuf_alloc; - uint8_t ping_payload_len; + uint8_t pong_payload_len; uint8_t mask_idx; uint8_t opcode; uint8_t rsv; diff --git a/3rdparty/libwebsockets/lib/secure-streams/README.md b/3rdparty/libwebsockets/lib/secure-streams/README.md index ffad3e7b..5d707aed 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/README.md +++ b/3rdparty/libwebsockets/lib/secure-streams/README.md @@ -185,7 +185,7 @@ An array of ms delays for each retry in turn The number of retries to conceal from higher layers before giving errors. If this is larger than the number of times in the backoff array, then the last time -is used for the extra delays +is used for the extra delays. 65535 means never stop trying. ### `jitterpc` @@ -371,17 +371,26 @@ for the normal payloads, as they can appear inside normal payload messages. The name of the trust store described in the `trust_stores` section to apply to validate the remote server cert. +If missing and tls is enabled on the streamtype, then validation is +attempted using the OS trust store, otherwise the connection fails. + ### `use_auth` Indicate that the streamtype should use the named auth type from the `auth` array in the policy ### `aws_region` + Indicate which metadata should be used to set aws region for certain streamtype ### `aws_service` + Indicate which metadata should be used to set aws service for certain streamtype +### `direct_proto_str` + +If set to `true`, application can use `lws_ss_set_metadata()` to directly set protocol related string and use `lws_ss_get_metadata` to fetch certain protocol related string. Please note that currently HTTP header is the supported protocol string. The `name` parameter is the name of HTTP header name (**with ':'**, e.g. `"Content-Type:"`) and `value` is the header's value. `LWS_WITH_SS_DIRECT_PROTOCOL_STR` flag needs to be configured during compilation for this. Currently it's only work for non-proxy case. + ### `server_cert` **SERVER ONLY**: subject to change... the name of the x.509 cert that is the @@ -612,6 +621,10 @@ The `content-type` to mark up the multipart mime section with if present Indicate the data is sent in `x-www-form-urlencoded` form +### `http_cookies` + +This streamtype should store and bring out http cookies from the peer. + ### `rideshare` For special cases where one logically separate stream travels with another when using this @@ -629,6 +642,11 @@ protocol. Eg, a single multipart mime transaction carries content from two or m Use if the ws messages are binary +### `ws_prioritize_reads` + +Set `true` if the event loop should prioritize keeping up with input at the +potential expense of output latency. + ## MQTT transport ### `mqtt_topic` @@ -643,6 +661,10 @@ Set the topic this streamtype subscribes to Set the QOS level for this streamtype +### `mqtt_retain` + +Set to true if this streamtype should use MQTT's "retain" feature. + ### `mqtt_keep_alive` 16-bit number representing MQTT keep alive for the stream. diff --git a/3rdparty/libwebsockets/lib/secure-streams/policy-common.c b/3rdparty/libwebsockets/lib/secure-streams/policy-common.c index 9899b41d..a98abaea 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/policy-common.c +++ b/3rdparty/libwebsockets/lib/secure-streams/policy-common.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2021 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 @@ -85,12 +85,33 @@ lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, { lws_ss_metadata_t *omd = lws_ss_get_handle_metadata(h, name); - if (!omd) { - lwsl_info("%s: unknown metadata %s\n", __func__, name); - return 1; + lws_service_assert_loop_thread(h->context, h->tsi); + + if (omd) + return _lws_ss_set_metadata(omd, name, value, len); + +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + if (h->policy->flags & LWSSSPOLF_DIRECT_PROTO_STR) { + omd = lws_ss_get_handle_instant_metadata(h, name); + if (!omd) { + omd = lws_zalloc(sizeof(*omd), "imetadata"); + if (!omd) { + lwsl_err("%s OOM\n", __func__); + return 1; + } + omd->name = name; + omd->next = h->instant_metadata; + h->instant_metadata = omd; + } + omd->value__may_own_heap = (void *)value; + omd->length = len; + + return 0; } +#endif - return _lws_ss_set_metadata(omd, name, value, len); + lwsl_info("%s: unknown metadata %s\n", __func__, name); + return 1; } int @@ -128,6 +149,8 @@ lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name, { lws_ss_metadata_t *omd = lws_ss_get_handle_metadata(h, name); + lws_service_assert_loop_thread(h->context, h->tsi); + if (!omd) { lwsl_info("%s: unknown metadata %s\n", __func__, name); return 1; @@ -141,16 +164,58 @@ lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, const void **value, size_t *len) { lws_ss_metadata_t *omd = lws_ss_get_handle_metadata(h, name); +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + int n; +#endif - if (!omd) { - lwsl_info("%s: unknown metadata %s\n", __func__, name); - return 1; + lws_service_assert_loop_thread(h->context, h->tsi); + + if (omd) { + *value = omd->value__may_own_heap; + *len = omd->length; + + return 0; } +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + if (!(h->policy->flags & LWSSSPOLF_DIRECT_PROTO_STR) || !h->wsi) + goto bail; + + n = lws_http_string_to_known_header(name, strlen(name)); + if (n != LWS_HTTP_NO_KNOWN_HEADER) { + *len = (size_t)lws_hdr_total_length(h->wsi, n); + if (!*len) + goto bail; + *value = lws_hdr_simple_ptr(h->wsi, n); + if (!*value) + goto bail; - *value = omd->value__may_own_heap; - *len = omd->length; + return 0; + } +#if defined(LWS_WITH_CUSTOM_HEADERS) + n = lws_hdr_custom_length(h->wsi, (const char *)name, + (int)strlen(name)); + if (n <= 0) + goto bail; + *value = lwsac_use(&h->imd_ac, (size_t)(n+1), (size_t)(n+1)); + if (!*value) { + lwsl_err("%s ac OOM\n", __func__); + return 1; + } + if (lws_hdr_custom_copy(h->wsi, (char *)(*value), n+1, name, + (int)strlen(name))) { + /* waste n+1 bytes until ss is destryed */ + goto bail; + } + *len = (size_t)n; return 0; +#endif + +bail: +#endif + lwsl_info("%s: unknown metadata %s\n", __func__, name); + + return 1; } lws_ss_metadata_t * @@ -158,6 +223,8 @@ lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) { int n; + lws_service_assert_loop_thread(h->context, h->tsi); + for (n = 0; n < h->policy->metadata_count; n++) if (!strcmp(name, h->metadata[n].name)) return &h->metadata[n]; @@ -165,6 +232,24 @@ lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) return NULL; } +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) +lws_ss_metadata_t * +lws_ss_get_handle_instant_metadata(struct lws_ss_handle *h, const char *name) +{ + lws_ss_metadata_t *imd = h->instant_metadata; + + while (imd) { + if (!strcmp(name, imd->name)) + return imd; + imd = imd->next; + } + + return NULL; +} + +#endif + + lws_ss_metadata_t * lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name) { @@ -282,7 +367,7 @@ lws_ss_policy_ref_trust_store(struct lws_context *context, } accepted: -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) if (doref) v->ss_refcount++; #endif @@ -290,7 +375,7 @@ lws_ss_policy_ref_trust_store(struct lws_context *context, return v; } -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) int lws_ss_policy_unref_trust_store(struct lws_context *context, const lws_ss_policy_t *pol) @@ -335,6 +420,9 @@ lws_ss_policy_set(struct lws_context *context, const char *name) * policy that's laid out in args->ac */ + if (!args) + return 1; + lejp_destruct(&args->jctx); if (context->ac_policy) { diff --git a/3rdparty/libwebsockets/lib/secure-streams/policy-json.c b/3rdparty/libwebsockets/lib/secure-streams/policy-json.c index dc0b6439..e230ce5e 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/policy-json.c +++ b/3rdparty/libwebsockets/lib/secure-streams/policy-json.c @@ -64,6 +64,7 @@ static const char * const lejp_tokens_policy[] = { "s[].*.attr_high_reliability", "s[].*.attr_low_cost", "s[].*.long_poll", + "s[].*.ws_prioritize_reads", "s[].*.retry", "s[].*.timeout_ms", "s[].*.perf", @@ -98,6 +99,7 @@ static const char * const lejp_tokens_policy[] = { "s[].*.http_mime_content_type", "s[].*.http_www_form_urlencoded", "s[].*.http_expect", + "s[].*.http_cookies", "s[].*.http_fail_redirect", "s[].*.http_multipart_ss_in", "s[].*.ws_subprotocol", @@ -109,17 +111,23 @@ static const char * const lejp_tokens_policy[] = { "s[].*.mqtt_topic", "s[].*.mqtt_subscribe", "s[].*.mqtt_qos", + "s[].*.mqtt_retain", "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[].*.mqtt_birth_topic", + "s[].*.mqtt_birth_message", + "s[].*.mqtt_birth_qos", + "s[].*.mqtt_birth_retain", "s[].*.aws_iot", "s[].*.swake_validity", "s[].*.use_auth", "s[].*.aws_region", "s[].*.aws_service", + "s[].*.direct_proto_str", "s[].*", "auth[].name", "auth[].type", @@ -165,6 +173,7 @@ typedef enum { LSSPPT_ATTR_HIGH_RELIABILITY, LSSPPT_ATTR_LOW_COST, LSSPPT_LONG_POLL, + LSSPPT_PRIORITIZE_READS, LSSPPT_RETRYPTR, LSSPPT_DEFAULT_TIMEOUT_MS, LSSPPT_PERF, @@ -198,6 +207,7 @@ typedef enum { LSSPPT_HTTP_MULTIPART_CONTENT_TYPE, LSSPPT_HTTP_WWW_FORM_URLENCODED, LSSPPT_HTTP_EXPECT, + LSSPPT_HTTP_COOKIES, LSSPPT_HTTP_FAIL_REDIRECT, LSSPPT_HTTP_MULTIPART_SS_IN, LSSPPT_WS_SUBPROTOCOL, @@ -209,17 +219,23 @@ typedef enum { LSSPPT_MQTT_TOPIC, LSSPPT_MQTT_SUBSCRIBE, LSSPPT_MQTT_QOS, + LSSPPT_MQTT_RETAIN, LSSPPT_MQTT_KEEPALIVE, LSSPPT_MQTT_CLEAN_START, LSSPPT_MQTT_WILL_TOPIC, LSSPPT_MQTT_WILL_MESSAGE, LSSPPT_MQTT_WILL_QOS, LSSPPT_MQTT_WILL_RETAIN, + LSSPPT_MQTT_BIRTH_TOPIC, + LSSPPT_MQTT_BIRTH_MESSAGE, + LSSPPT_MQTT_BIRTH_QOS, + LSSPPT_MQTT_BIRTH_RETAIN, LSSPPT_MQTT_AWS_IOT, LSSPPT_SWAKE_VALIDITY, LSSPPT_USE_AUTH, LSSPPT_AWS_REGION, LSSPPT_AWS_SERVICE, + LSSPPT_DIRECT_PROTO_STR, LSSPPT_STREAMTYPES, LSSPPT_AUTH_NAME, LSSPPT_AUTH_TYPE, @@ -754,6 +770,11 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LONG_POLL; break; + case LSSPPT_PRIORITIZE_READS: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_PRIORITIZE_READS; + break; + case LSSPPT_HTTP_WWW_FORM_URLENCODED: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->flags |= @@ -769,6 +790,11 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_ALLOW_REDIRECTS; break; + case LSSPPT_HTTP_COOKIES: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_HTTP_CACHE_COOKIES; + break; case LSSPPT_HTTP_MULTIPART_SS_IN: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->flags |= @@ -996,6 +1022,11 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.mqtt.qos = (uint8_t)atoi(ctx->buf); break; + case LSSPPT_MQTT_RETAIN: + a->curr[LTY_POLICY].p->u.mqtt.retain = + reason == LEJPCB_VAL_TRUE; + break; + case LSSPPT_MQTT_KEEPALIVE: a->curr[LTY_POLICY].p->u.mqtt.keep_alive = (uint16_t)atoi(ctx->buf); break; @@ -1019,12 +1050,33 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.mqtt.will_retain = reason == LEJPCB_VAL_TRUE; break; + case LSSPPT_MQTT_BIRTH_TOPIC: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.birth_topic; + goto string2; + + case LSSPPT_MQTT_BIRTH_MESSAGE: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.birth_message; + goto string2; + + case LSSPPT_MQTT_BIRTH_QOS: + a->curr[LTY_POLICY].p->u.mqtt.birth_qos = (uint8_t)atoi(ctx->buf); + break; + case LSSPPT_MQTT_BIRTH_RETAIN: + a->curr[LTY_POLICY].p->u.mqtt.birth_retain = + reason == LEJPCB_VAL_TRUE; + break; case LSSPPT_MQTT_AWS_IOT: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->u.mqtt.aws_iot = reason == LEJPCB_VAL_TRUE; break; #endif + case LSSPPT_DIRECT_PROTO_STR: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_DIRECT_PROTO_STR; + break; + case LSSPPT_PROTOCOL: a->curr[LTY_POLICY].p->protocol = 0xff; @@ -1130,10 +1182,16 @@ lws_ss_policy_parse_abandon(struct lws_context *context) * 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; - } + lws_free((void *)x->ca_der); + x->ca_der = NULL; + + x = x->next; + } + + x = context->server_der_list; + while (x) { + lws_free((void *)x->ca_der); + x->ca_der = NULL; x = x->next; } @@ -1142,6 +1200,8 @@ lws_ss_policy_parse_abandon(struct lws_context *context) lwsac_free(&args->ac); lws_free_set_NULL(context->pol_args); + context->server_der_list = NULL; + return 0; } @@ -1154,7 +1214,7 @@ lws_ss_policy_parse_file(struct lws_context *cx, const char *filepath) int n, m, fd = lws_open(filepath, LWS_O_RDONLY); if (fd < 0) - return -1; + return LEJP_REJECT_UNKNOWN; do { n = (int)read(fd, buf, sizeof(buf)); @@ -1193,12 +1253,11 @@ lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) int m; #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) - if (!args->jctx.line && buf[0] != '{') { - puts((const char *)buf); + if (args->jctx.line < 2 && buf[0] != '{' && !args->parse_data) return lws_ss_policy_parse_file(context, (const char *)buf); - } #endif + args->parse_data = 1; m = lejp_parse(&args->jctx, buf, (int)len); if (m == LEJP_CONTINUE || m >= 0) return m; diff --git a/3rdparty/libwebsockets/lib/secure-streams/private-lib-secure-streams.h b/3rdparty/libwebsockets/lib/secure-streams/private-lib-secure-streams.h index 9bf6f310..cc2fc4cf 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/private-lib-secure-streams.h +++ b/3rdparty/libwebsockets/lib/secure-streams/private-lib-secure-streams.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2021 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 @@ -39,6 +39,7 @@ typedef enum { SSSEQ_CONNECTED, } lws_ss_seq_state_t; +struct conn; /** * lws_ss_handle_t: publicly-opaque secure stream object implementation @@ -70,13 +71,20 @@ typedef struct lws_ss_handle { struct lws_sequencer *seq; /**< owning sequencer if any */ struct lws *wsi; /**< the stream wsi if any */ + struct conn *conn_if_sspc_onw; + #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; +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + lws_ss_metadata_t *instant_metadata; /**< for set instant metadata */ + struct lwsac *imd_ac; /**< for get custom header */ +#endif const lws_ss_policy_t *rideshare; + struct lws_ss_handle *h_in_svc; #if defined(LWS_WITH_CONMON) char *conmon_json; @@ -139,10 +147,15 @@ typedef struct lws_ss_handle { lws_mqtt_topic_elem_t topic_qos; lws_mqtt_topic_elem_t sub_top; lws_mqtt_subscribe_param_t sub_info; + lws_mqtt_subscribe_param_t shadow_sub; /* allocation that must be destroyed with conn */ void *heap_baggage; const char *subscribe_to; size_t subscribe_to_len; + struct lws_buflist *buflist_unacked; + uint32_t unacked_size; + uint8_t retry_count; + uint8_t send_unacked:1; } mqtt; #endif #if defined(LWS_WITH_SYS_SMD) @@ -157,6 +170,8 @@ typedef struct lws_ss_handle { lws_ss_constate_t connstate;/**< public connection state */ lws_ss_seq_state_t seqstate; /**< private connection state */ + lws_ss_state_return_t pending_ret; /**< holds desired disposition + * for ss during CCE */ #if defined(LWS_WITH_SERVER) int txn_resp; @@ -181,6 +196,9 @@ typedef struct lws_ss_handle { uint8_t destroying:1; uint8_t ss_dangling_connected:1; uint8_t proxy_onward:1; /* opaque is conn */ + uint8_t inside_connect:1; /* set if we are currently + * creating the onward + * connect */ } lws_ss_handle_t; /* connection helper that doesn't need to hang around after connection starts */ @@ -310,7 +328,14 @@ typedef struct lws_sspc_handle { struct lws_dsh *dsh; struct lws_context *context; + struct lws_sspc_handle *h_in_svc; + /* + * Used to detect illegal lws_sspc_destroy() calls while still + * being serviced + */ + lws_usec_t us_earliest_write_req; + lws_usec_t us_start_upstream; unsigned long writeable_len; @@ -381,6 +406,8 @@ struct policy_cb_args { int count; char pending_respmap; + + uint8_t parse_data:1; }; #if defined(LWS_WITH_SYS_SMD) @@ -412,9 +439,6 @@ int lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack); -void -lws_ss_serialize_state_transition(lws_ss_conn_states_t *state, int new_state); - const lws_ss_policy_t * lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype); @@ -464,6 +488,11 @@ lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name); lws_ss_metadata_t * lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index); +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) +lws_ss_metadata_t * +lws_ss_get_handle_instant_metadata(struct lws_ss_handle *h, const char *name); +#endif + lws_ss_metadata_t * lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name); @@ -482,6 +511,9 @@ _lws_ss_alloc_set_metadata(lws_ss_metadata_t *omd, const char *name, lws_ss_state_return_t _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw); +lws_ss_state_return_t +_lws_ss_request_tx(lws_ss_handle_t *h); + int __lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size); @@ -497,10 +529,24 @@ int lws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate, lws_ss_constate_t cs); +int +lws_ss_check_next_state_ss(lws_ss_handle_t *ss, uint8_t *prevstate, + lws_ss_constate_t cs); + +int +lws_ss_check_next_state_sspc(lws_sspc_handle_t *ss, uint8_t *prevstate, + lws_ss_constate_t cs); + void lws_proxy_clean_conn_ss(struct lws *wsi); -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +int +lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user); + +int +lws_sspc_cancel_notify_dll(struct lws_dll2 *d, void *user); + +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) int lws_ss_policy_unref_trust_store(struct lws_context *context, const lws_ss_policy_t *pol); @@ -514,6 +560,13 @@ int lws_ss_apply_sigv4(struct lws *wsi, struct lws_ss_handle *h, unsigned char **p, unsigned char *end); #endif +#if defined(_DEBUG) +void +lws_ss_assert_extant(struct lws_context *cx, int tsi, struct lws_ss_handle *h); +#else +#define lws_ss_assert_extant(_a, _b, _c) +#endif + typedef int (* const secstream_protocol_connect_munge_t)(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct); diff --git a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h1.c b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h1.c index da982c7a..d9ffe852 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h1.c +++ b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h1.c @@ -271,6 +271,39 @@ lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, } +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) +static int +lws_apply_instant_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, + uint8_t **pp, uint8_t *end) +{ + lws_ss_metadata_t *imd = h->instant_metadata; + + while (imd) { + if (imd->name && imd->value__may_own_heap) { + lwsl_debug("%s add header %s %s %d\n", __func__, + imd->name, + (char *)imd->value__may_own_heap, + (int)imd->length); + if (lws_add_http_header_by_name(wsi, + (const unsigned char *)imd->name, + (const unsigned char *)imd->value__may_own_heap, + (int)imd->length, pp, end)) + return -1; + + /* it's possible user set content-length directly */ + if (!strncmp(imd->name, + "content-length", 14) && + atoi(imd->value__may_own_heap)) + lws_client_http_body_pending(wsi, 1); + + } + + imd = imd->next; + } + + return 0; +} +#endif /* * Check if any metadata headers present in the server headers, and record * them into the associated metadata item if so. @@ -293,7 +326,7 @@ lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) const char *cp = lws_hdr_simple_ptr(wsi, polmd->value_is_http_token); omd = lws_ss_get_handle_metadata(h, polmd->name); - if (!omd) + if (!omd || !cp) return 1; assert(!strcmp(omd->name, polmd->name)); @@ -363,14 +396,16 @@ lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) omd = lws_ss_get_handle_metadata(h, polmd->name); + if (omd) { - _lws_ss_set_metadata(omd, - polmd->name, p, (size_t)n); - omd->value_on_lws_heap = 1; + _lws_ss_set_metadata(omd, + polmd->name, p, (size_t)n); + omd->value_on_lws_heap = 1; #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) - omd->pending_onward = 1; + omd->pending_onward = 1; #endif + } } } #endif @@ -415,22 +450,45 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_err("%s: CCE with no ss handle %s\n", __func__, lws_wsi_tag(wsi)); break; } + + lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); + assert(h->policy); +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); +#endif lws_metrics_caliper_report_hist(h->cal_txn, wsi); lwsl_info("%s: %s CLIENT_CONNECTION_ERROR: %s\n", __func__, h->lc.gutag, in ? (const char *)in : "none"); - /* already disconnected, no action for DISCONNECT_ME */ - r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); - if (r) - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + if (h->ss_dangling_connected) { + /* 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_CAN_DESTROY_HANDLE(r, wsi, &h); + } else { + /* already disconnected, no action for DISCONNECT_ME */ + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r) { + if (h->inside_connect) { + h->pending_ret = r; + break; + } + + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } + } h->wsi = NULL; r = lws_ss_backoff(h); - if (r != LWSSSSRET_OK) + if (r != LWSSSSRET_OK) { + if (h->inside_connect) { + h->pending_ret = r; + break; + } return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } break; case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: @@ -451,13 +509,25 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_sul_cancel(&h->sul_timeout); + lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); + +#if defined(LWS_WITH_CONMON) + if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) { + wsi->conmon.pcol = LWSCONMON_PCOL_HTTP; + wsi->conmon.protocol_specific.http.response = + (int)lws_http_client_http_response(wsi); + } + lws_conmon_ss_json(h); +#endif lws_metrics_caliper_report_hist(h->cal_txn, wsi); //lwsl_notice("%s: %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", // __func__, wsi->lc.gutag); h->wsi = NULL; + h->hanging_som = 0; + h->subseq = 0; #if defined(LWS_WITH_SERVER) lws_pt_lock(pt, __func__); @@ -485,13 +555,24 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, } break; - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: if (!h) return -1; + lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); + h->wsi = wsi; /* since we accept the wsi is bound to the SS, + * ensure the SS feels the same way about the wsi */ + +#if defined(LWS_WITH_CONMON) + if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) { + wsi->conmon.pcol = LWSCONMON_PCOL_HTTP; + wsi->conmon.protocol_specific.http.response = + (int)lws_http_client_http_response(wsi); + } + lws_conmon_ss_json(h); +#endif status = (int)lws_http_client_http_response(wsi); lwsl_info("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: %d\n", __func__, status); @@ -571,9 +652,12 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_sul_cancel(&h->sul); if (h->prev_ss_state != LWSSSCS_CONNECTED) { - r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); - if (r != LWSSSSRET_OK) - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + wsi->client_suppress_CONNECTION_ERROR = 1; + if (h->prev_ss_state != LWSSSCS_CONNECTED) { + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } } /* @@ -715,6 +799,13 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (lws_apply_metadata(h, wsi, buf, p, end)) return -1; +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + if (h->policy->flags & LWSSSPOLF_DIRECT_PROTO_STR) { + if (lws_apply_instant_metadata(h, wsi, buf, p, end)) + return -1; + } +#endif + #if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) if (h->policy->auth && h->policy->auth->type && !strcmp(h->policy->auth->type, "sigv4")) { @@ -742,9 +833,12 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, !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_CAN_DESTROY_HANDLE(r, wsi, &h); + wsi->client_suppress_CONNECTION_ERROR = 1; + if (h->prev_ss_state != LWSSSCS_CONNECTED) { + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } } break; @@ -772,6 +866,8 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, // lwsl_notice("%s: HTTP_READ: client side sent len %d fl 0x%x\n", // __func__, (int)len, (int)f); + h->wsi = wsi; /* since we accept the wsi is bound to the SS, + * ensure the SS feels the same way about the wsi */ r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); @@ -801,6 +897,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (h->hanging_som) { h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); h->hanging_som = 0; + h->subseq = 0; } wsi->http.writeable_len = h->writeable_len = 0; @@ -827,7 +924,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: if (!h || !h->info.tx) { - lwsl_notice("%s: %s no handle / tx\n", __func__, h->lc.gutag); + lwsl_notice("%s: no handle / tx\n", __func__); return 0; } @@ -960,7 +1057,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!h) return -1; - lwsl_notice("%s: LWS_CALLBACK_HTTP\n", __func__); + lwsl_info("%s: LWS_CALLBACK_HTTP\n", __func__); { h->txn_resp_set = 0; @@ -975,7 +1072,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, WSI_TOKEN_HTTP_COLON_METHOD), (unsigned int)m)) return -1; m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH); - if (lws_ss_alloc_set_metadata(h, "path", + if (m && lws_ss_alloc_set_metadata(h, "path", lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH), (unsigned int)m)) return -1; @@ -1011,14 +1108,19 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, */ lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL); #endif - r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); - if (r) - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + wsi->client_suppress_CONNECTION_ERROR = 1; + if (h->prev_ss_state != LWSSSCS_CONNECTED) { + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } } r = lws_ss_event_helper(h, LWSSSCS_SERVER_TXN); if (r) - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, + wsi, &h); + return 0; #endif @@ -1032,8 +1134,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, const struct lws_protocols protocol_secstream_h1 = { "lws-secstream-h1", secstream_h1, - 0, - 0, + 0, 0, 0, NULL, 0 }; /* @@ -1073,6 +1174,9 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED; #endif + if (h->policy->flags & LWSSSPOLF_HTTP_CACHE_COOKIES) + i->ssl_connection |= LCCSCF_CACHE_COOKIES; + /* protocol aux is the path part */ i->path = buf; @@ -1098,5 +1202,5 @@ const struct ss_pcols ss_pcol_h1 = { "http/1.1", &protocol_secstream_h1, secstream_connect_munge_h1, - NULL + NULL, NULL }; diff --git a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h2.c b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h2.c index 533cd639..910067ab 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h2.c +++ b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-h2.c @@ -52,7 +52,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, */ lwsl_info("%s: reporting initial tx cr from server %d\n", __func__, wsi->txc.tx_cr); - ss_proxy_onward_txcr((void *)&h[1], wsi->txc.tx_cr); + ss_proxy_onward_txcr((void *)(h + 1), wsi->txc.tx_cr); } #endif @@ -66,8 +66,13 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, return n; case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - if (lws_get_network_wsi(wsi) == wsi) + /* + * Only allow the wsi that the handle believes is representing + * him to report closure up to h1 + */ + if (!h || h->wsi != wsi) return 0; + break; case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: @@ -79,8 +84,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, r = 0; if (h->hanging_som) 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; lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ if (h->hanging_som && r == LWSSSSRET_DESTROY_ME) @@ -102,7 +106,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) if (h->being_serialized) /* we are the proxy-side SS for a remote client */ - ss_proxy_onward_txcr((void *)&h[1], (int)len); + ss_proxy_onward_txcr((void *)(h + 1), (int)len); #endif break; @@ -116,8 +120,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, const struct lws_protocols protocol_secstream_h2 = { "lws-secstream-h2", secstream_h2, - 0, - 0, + 0, 0, 0, NULL, 0 }; /* @@ -155,6 +158,9 @@ secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED) i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED; + if (h->policy->flags & LWSSSPOLF_HTTP_CACHE_COOKIES) + i->ssl_connection |= LCCSCF_CACHE_COOKIES; + i->ssl_connection |= LCCSCF_PIPELINE; i->alpn = "h2"; diff --git a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c index a5319028..8698bee4 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c +++ b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2021 Andy Green + * Copyright (C) 2019 - 2022 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 @@ -24,17 +24,476 @@ #include +static void +secstream_mqtt_cleanup(lws_ss_handle_t *h) +{ + uint32_t i; + + if (h->u.mqtt.heap_baggage) { + lws_free(h->u.mqtt.heap_baggage); + h->u.mqtt.heap_baggage = NULL; + } + + if (h->u.mqtt.sub_info.topic) { + for (i = 0; i < h->u.mqtt.sub_info.num_topics; i++) { + if (h->u.mqtt.sub_info.topic[i].name) { + lws_free((void*)h->u.mqtt.sub_info.topic[i].name); + h->u.mqtt.sub_info.topic[i].name = NULL; + } + } + lws_free(h->u.mqtt.sub_info.topic); + h->u.mqtt.sub_info.topic = NULL; + } + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); +} + +static int +secstream_mqtt_subscribe(struct lws *wsi) +{ + size_t used_in, used_out, topic_limit; + lws_strexp_t exp; + char* expbuf; + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (!h || !h->policy) + return -1; + + if (h->policy->u.mqtt.aws_iot) + topic_limit = LWS_MQTT_MAX_AWSIOT_TOPICLEN; + else + topic_limit = LWS_MQTT_MAX_TOPICLEN; + + if (!h->policy->u.mqtt.subscribe || wsi->mqtt->done_subscribe) + return 0; + + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, NULL, + topic_limit); + /* + * Expand with no output first to calculate the size of + * expanded string then, allocate new buffer and expand + * again with the buffer + */ + if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, + strlen(h->policy->u.mqtt.subscribe), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err( + "%s, failed to expand MQTT subscribe" + " topic with no output\n", + __func__); + return 1; + } + + expbuf = lws_malloc(used_out + 1, __func__); + if (!expbuf) { + lwsl_err( + "%s, failed to allocate MQTT subscribe" + "topic", + __func__); + return 1; + } + + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, expbuf, + used_out + 1); + + if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, + strlen(h->policy->u.mqtt.subscribe), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand MQTT subscribe topic\n", + __func__); + lws_free(expbuf); + return 1; + } + lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); + h->u.mqtt.sub_top.name = expbuf; + + /* + * The policy says to subscribe to something, and we + * haven't done it yet. Do it using the pre-prepared + * string-substituted version of the policy string. + */ + + lwsl_notice("%s: subscribing %s\n", __func__, + h->u.mqtt.sub_top.name); + + 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; + h->u.mqtt.sub_info.topic = &h->u.mqtt.sub_top; + h->u.mqtt.sub_info.topic = + lws_malloc(sizeof(lws_mqtt_topic_elem_t), __func__); + h->u.mqtt.sub_info.topic[0].name = lws_strdup(expbuf); + h->u.mqtt.sub_info.topic[0].qos = h->policy->u.mqtt.qos; + + if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.sub_info)) { + lwsl_notice("%s: unable to subscribe", __func__); + lws_free(expbuf); + h->u.mqtt.sub_top.name = NULL; + return -1; + } + lws_free(expbuf); + h->u.mqtt.sub_top.name = NULL; + + /* Expect a SUBACK */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); + return -1; + } + return 0; +} + +static int +secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buf_len, + uint32_t payload_len, const char* topic, + lws_mqtt_qos_levels_t qos, uint8_t retain, uint8_t dup, + int f) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + size_t used_in, used_out, topic_limit; + lws_strexp_t exp; + char *expbuf; + lws_mqtt_publish_param_t mqpp; + + if (h->policy->u.mqtt.aws_iot) + topic_limit = LWS_MQTT_MAX_AWSIOT_TOPICLEN; + else + topic_limit = LWS_MQTT_MAX_TOPICLEN; + + memset(&mqpp, 0, sizeof(mqpp)); + + lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, NULL, + topic_limit); + + if (lws_strexp_expand(&exp, topic, strlen(topic), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand MQTT publish" + " topic with no output\n", __func__); + return 1; + } + expbuf = lws_malloc(used_out + 1, __func__); + if (!expbuf) { + lwsl_err("%s, failed to allocate MQTT publish topic", + __func__); + return 1; + } + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, expbuf, + used_out + 1); + + if (lws_strexp_expand(&exp, topic, strlen(topic), &used_in, + &used_out) != LSTRX_DONE) { + lws_free(expbuf); + return 1; + } + lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); + mqpp.topic = (char *)expbuf; + + mqpp.topic_len = (uint16_t)strlen(mqpp.topic); + mqpp.packet_id = (uint16_t)(h->txord - 1); + mqpp.qos = qos; + mqpp.retain = !!retain; + mqpp.payload = buf; + mqpp.dup = !!dup; + if (payload_len) + mqpp.payload_len = payload_len; + else + mqpp.payload_len = (uint32_t)buf_len; + + lwsl_notice("%s: payload len %d\n", __func__, + (int)mqpp.payload_len); + + if (lws_mqtt_client_send_publish(wsi, &mqpp, + (const char *)buf, + (uint32_t)buf_len, + f & LWSSS_FLAG_EOM)) { + lwsl_notice("%s: failed to publish\n", __func__); + lws_free(expbuf); + return -1; + } + lws_free(expbuf); + + if ((mqpp.qos == QOS1 || mqpp.qos == QOS2) && buf_len > 0) { + if (lws_buflist_append_segment(&h->u.mqtt.buflist_unacked, + buf, buf_len) < 0) { + lwsl_notice("%s: failed to store unacked\n", __func__); + return -1; + } + } + + return 0; +} + +static int +secstream_mqtt_birth(struct lws *wsi, uint8_t *buf, size_t buflen) { + lws_strexp_t exp; + size_t used_in, used_out = 0; + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (h->policy->u.mqtt.birth_message) { + lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, + (char *)buf, buflen); + if (lws_strexp_expand(&exp, h->policy->u.mqtt.birth_message, + strlen(h->policy->u.mqtt.birth_message), + &used_in, &used_out) != LSTRX_DONE) { + return 1; + } + } + wsi->mqtt->inside_birth = 1; + return secstream_mqtt_publish(wsi, buf, + used_out, 0, h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_qos, + h->policy->u.mqtt.birth_retain, 0, + LWSSS_FLAG_EOM); +} + +static int +secstream_mqtt_resend(struct lws *wsi, uint8_t *buf) { + uint8_t *buffered; + size_t len; + int f = 0, r; + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + len = lws_buflist_next_segment_len(&h->u.mqtt.buflist_unacked, + &buffered); + + if (h->u.mqtt.unacked_size <= len) + f |= LWSSS_FLAG_EOM; + + if (!len) { + /* when the message does not have payload */ + buffered = buf; + } else { + h->u.mqtt.unacked_size -= (uint32_t)len; + } + + if (wsi->mqtt->inside_birth) { + r = secstream_mqtt_publish(wsi, buffered, len, 0, + h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_qos, + h->policy->u.mqtt.birth_retain, + 1, f); + } else { + r = secstream_mqtt_publish(wsi, buffered, len, + (uint32_t)h->writeable_len, + h->policy->u.mqtt.topic, + h->policy->u.mqtt.qos, + h->policy->u.mqtt.retain, 1, f); + } + if (len) + lws_buflist_use_segment(&h->u.mqtt.buflist_unacked, len); + + if (r) { + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); + h->u.mqtt.retry_count = h->u.mqtt.send_unacked = 0; + + if (wsi->mqtt->inside_birth) { + lwsl_err("%s: %s: failed to send Birth\n", __func__, + lws_ss_tag(h)); + return -1; + } else { + r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } + } + return 0; +} + +static char * +expand_metadata(lws_ss_handle_t *h, const char* str, const char* post, size_t max_len) +{ + lws_strexp_t exp; + char *expbuf = NULL; + size_t used_in = 0, used_out = 0, post_len = 0; + + memset(&exp, 0, sizeof(exp)); + + if (post) + post_len = strlen(post); + + if (post_len > max_len) + return NULL; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, NULL, + max_len - post_len); + + if (lws_strexp_expand(&exp, str, strlen(str), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand %s", __func__, str); + + return NULL; + } + + expbuf = lws_malloc(used_out + 1 + post_len, __func__); + if (!expbuf) { + lwsl_err("%s, failed to allocate str_exp for %s", __func__, str); + + return NULL; + } + + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, expbuf, + used_out + 1 + post_len); + + if (lws_strexp_expand(&exp, str, strlen(str), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand str_exp %s\n", __func__, str); + lws_free(expbuf); + + return NULL; + } + if (post) + strcat(expbuf, post); + + return expbuf; +} + +static lws_mqtt_match_topic_return_t +secstream_mqtt_is_shadow_matched(struct lws *wsi, const char *topic) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + const char *match[] = { LWS_MQTT_SHADOW_UNNAMED_TOPIC_MATCH, + LWS_MQTT_SHADOW_NAMED_TOPIC_MATCH }; + char *expbuf = NULL; + unsigned int i = 0; + lws_mqtt_match_topic_return_t ret = LMMTR_TOPIC_NOMATCH; + + if (!topic) + return LMMTR_TOPIC_MATCH_ERROR; + + expbuf = expand_metadata(h, topic, NULL, LWS_MQTT_MAX_AWSIOT_TOPICLEN); + if (!expbuf) { + lwsl_wsi_warn(wsi, "Failed to expand Shadow topic"); + + return LMMTR_TOPIC_MATCH_ERROR; + } + for (i = 0; i < (sizeof(match) / sizeof(match[0])); i++) { + if (lws_mqtt_is_topic_matched( + match[i], expbuf) == LMMTR_TOPIC_MATCH) { + ret = LMMTR_TOPIC_MATCH; + break; + } + } + lws_free(expbuf); + + return ret; +} + +static void +secstream_mqtt_shadow_cleanup(struct lws *wsi) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + uint32_t i = 0; + + for (i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) + lws_free((void *)h->u.mqtt.shadow_sub.topic[i].name); + + h->u.mqtt.shadow_sub.num_topics = 0; + + if (h->u.mqtt.shadow_sub.topic) { + lws_free(h->u.mqtt.shadow_sub.topic); + h->u.mqtt.shadow_sub.topic = NULL; + } +} + +static lws_ss_state_return_t +secstream_mqtt_shadow_unsubscribe(struct lws *wsi) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (h->u.mqtt.shadow_sub.num_topics == 0) { + wsi->mqtt->send_shadow_unsubscribe = 0; + wsi->mqtt->inside_shadow = 0; + wsi->mqtt->done_shadow_subscribe = 0; + + return LWSSSSRET_OK; + } + + if (lws_mqtt_client_send_unsubcribe(wsi, &h->u.mqtt.shadow_sub)) { + lwsl_wsi_err(wsi, "Failed to send MQTT unsubsribe"); + + return LWSSSSRET_DISCONNECT_ME; + } + /* Expect a UNSUBACK */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lwsl_wsi_err(wsi, "Unable to set LWS_POLLIN"); + + return LWSSSSRET_DISCONNECT_ME; + } + wsi->mqtt->send_shadow_unsubscribe = 0; + + return LWSSSSRET_OK; +} + +static int +secstream_mqtt_shadow_subscribe(struct lws *wsi) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + char* expbuf = NULL; + const char *suffixes[] = { LWS_MQTT_SHADOW_RESP_ACCEPTED_STR, + LWS_MQTT_SHADOW_RESP_REJECTED_STR }; + unsigned int i, suffixes_len = sizeof(suffixes) / sizeof(suffixes[0]); + + if (!h->policy->u.mqtt.topic || wsi->mqtt->inside_shadow) + return 0; + + if (h->u.mqtt.shadow_sub.num_topics > 0) + secstream_mqtt_shadow_cleanup(wsi); + + memset(&h->u.mqtt.shadow_sub, 0, sizeof(lws_mqtt_subscribe_param_t)); + h->u.mqtt.shadow_sub.topic = lws_malloc( + sizeof(lws_mqtt_topic_elem_t) * suffixes_len, __func__); + if (!h->u.mqtt.shadow_sub.topic) { + lwsl_ss_err(h, "Failed to allocate Shadow topics"); + return -1; + } + h->u.mqtt.shadow_sub.num_topics = suffixes_len; + for (i = 0; i < suffixes_len; i++) { + expbuf = expand_metadata(h, h->policy->u.mqtt.topic, suffixes[i], + LWS_MQTT_MAX_AWSIOT_TOPICLEN); + if (!expbuf) { + lwsl_ss_err(h, "Failed to allocate Shadow topic"); + secstream_mqtt_shadow_cleanup(wsi); + + return -1; + } + h->u.mqtt.shadow_sub.topic[i].name = expbuf; + h->u.mqtt.shadow_sub.topic[i].qos = h->policy->u.mqtt.qos; + } + h->u.mqtt.shadow_sub.packet_id = (uint16_t)(h->txord - 1); + + if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.shadow_sub)) { + lwsl_wsi_notice(wsi, "Unable to subscribe Shadow topics"); + + return 0; + } + + /* Expect a SUBACK */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); + return -1; + } + wsi->mqtt->inside_shadow = 1; + + return 0; +} + static int secstream_mqtt(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); - lws_mqtt_publish_param_t mqpp, *pmqpp; + size_t used_in = 0, used_out = 0, topic_len = 0; + lws_mqtt_publish_param_t *pmqpp = NULL; + lws_ss_state_return_t r = LWSSSSRET_OK; uint8_t buf[LWS_PRE + 1400]; - lws_ss_state_return_t r; - size_t buflen; + size_t buflen = sizeof(buf) - LWS_PRE; + lws_ss_metadata_t *omd = NULL; + char *sub_topic = NULL; + lws_strexp_t exp; int f = 0; + memset(buf, 0, sizeof(buf)); + memset(&exp, 0, sizeof(exp)); + switch (reason) { /* because we are protocols[0] ... */ @@ -44,15 +503,14 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!h) break; +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); +#endif r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); h->wsi = NULL; - if (h->u.mqtt.heap_baggage) { - lws_free(h->u.mqtt.heap_baggage); - h->u.mqtt.heap_baggage = NULL; - } + secstream_mqtt_cleanup(h); if (r == LWSSSSRET_DESTROY_ME) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); @@ -67,9 +525,9 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!h) break; lws_sul_cancel(&h->sul_timeout); - +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); - +#endif if (h->ss_dangling_connected) r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); else @@ -78,10 +536,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_set_opaque_user_data(h->wsi, NULL); h->wsi = NULL; - if (h->u.mqtt.heap_baggage) { - lws_free(h->u.mqtt.heap_baggage); - h->u.mqtt.heap_baggage = NULL; - } + secstream_mqtt_cleanup(h); if (r) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); @@ -102,13 +557,60 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->wsi = wsi; h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - /* - * If a subscribe is pending on the stream, then make - * sure the SUBSCRIBE is done before signaling the - * user application. - */ - if (h->policy->u.mqtt.subscribe && - !wsi->mqtt->done_subscribe) { + + if (h->policy->u.mqtt.birth_topic && + !wsi->mqtt->done_birth) { + struct lws *nwsi = lws_get_network_wsi(wsi); + lws_start_foreach_ll(struct lws *, w, nwsi->mux.child_list) { + if (w != wsi && + (w->mqtt->done_birth || w->mqtt->inside_birth)) { + /* + * If any Birth was sent out or + * is pending on other stream, + * skip sending Birth. + */ + wsi->mqtt->done_birth = 1; + break; + } + } lws_end_foreach_ll(w, mux.sibling_list); + } + + if (!h->policy->u.mqtt.subscribe || + !h->policy->u.mqtt.subscribe[0]) { + /* + * If subscribe is empty in the policy, then, + * skip sending SUBSCRIBE and signal the user + * application. + */ + wsi->mqtt->done_subscribe = 1; + } else if (!h->policy->u.mqtt.clean_start && + wsi->mqtt->session_resumed) { + wsi->mqtt->inside_resume_session = 1; + /* + * If the previous session is resumed and Server has + * stored session, then, do not subscribe. + */ + if (!secstream_mqtt_subscribe(wsi)) + wsi->mqtt->done_subscribe = 1; + wsi->mqtt->inside_resume_session = 0; + } else if (h->policy->u.mqtt.subscribe && + !wsi->mqtt->done_subscribe) { + /* + * If a subscribe is pending on the stream, then make + * sure the SUBSCRIBE is done before signaling the + * user application. + */ + lws_callback_on_writable(wsi); + break; + } + + if (h->policy->u.mqtt.birth_topic && + !wsi->mqtt->done_birth) { + /* + * If a Birth is pending on the stream, then make + * sure the Birth is done before signaling the + * user application. + */ lws_callback_on_writable(wsi); break; } @@ -141,24 +643,95 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->subseq = 1; + if (wsi->mqtt->inside_shadow) { + /* + * When Shadow is used, the stream receives multiple + * topics including Shadow response, set received + * topic on the metadata + */ + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, + NULL, (size_t)-1); + + if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, + strlen(h->policy->u.mqtt.subscribe), + &used_in, &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand subscribe topic", + __func__); + return -1; + } + omd = lws_ss_get_handle_metadata(h, exp.name); + + if (!omd) { + lwsl_err("%s, failed to find metadata for subscribe", + __func__); + return -1; + } + sub_topic = omd->value__may_own_heap; + topic_len = omd->length; + + _lws_ss_set_metadata(omd, exp.name, + (const void *)pmqpp->topic, + pmqpp->topic_len); + } + r = h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, len, f); + + if (wsi->mqtt->inside_shadow) + _lws_ss_set_metadata(omd, exp.name, &sub_topic, + topic_len); + if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + if (wsi->mqtt->inside_shadow) { + size_t acc_n = strlen(LWS_MQTT_SHADOW_RESP_ACCEPTED_STR); + size_t rej_n = strlen(LWS_MQTT_SHADOW_RESP_REJECTED_STR); + uint32_t i; + + for (i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { + /* + * received response ('/accepted' or 'rejected') + * and clean up Shadow operation + */ + if (strncmp(h->u.mqtt.shadow_sub.topic[i].name, + pmqpp->topic, pmqpp->topic_len) || + (strlen(pmqpp->topic) < acc_n || + strlen(pmqpp->topic) < rej_n)) + continue; + + if (!strcmp(pmqpp->topic + + (strlen(pmqpp->topic) - acc_n), + LWS_MQTT_SHADOW_RESP_ACCEPTED_STR) || + !strcmp(pmqpp->topic + + (strlen(pmqpp->topic) - rej_n), + LWS_MQTT_SHADOW_RESP_REJECTED_STR)) { + lws_sul_cancel(&wsi->mqtt->sul_shadow_wait); + wsi->mqtt->send_shadow_unsubscribe = 1; + lws_callback_on_writable(wsi); + + return 0; + } + } + } return 0; /* don't passthru */ case LWS_CALLBACK_MQTT_SUBSCRIBED: + if (wsi->mqtt->inside_shadow) { + wsi->mqtt->done_shadow_subscribe = 1; + lws_callback_on_writable(wsi); + + return 0; + } /* - * Stream demanded a subscribe while connecting, once + * Stream demanded a subscribe without a Birth while connecting, once * done notify CONNECTED event to the application. */ - if (wsi->mqtt->done_subscribe == 0) { + if (!wsi->mqtt->done_subscribe && !h->policy->u.mqtt.birth_topic) { lws_sul_cancel(&h->sul); r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); if (r != LWSSSSRET_OK) - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, - wsi, &h); + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); } wsi->mqtt->done_subscribe = 1; lws_callback_on_writable(wsi); @@ -166,17 +739,61 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_ACK: lws_sul_cancel(&h->sul_timeout); + if (h->u.mqtt.send_unacked) { + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); + h->u.mqtt.retry_count = h->u.mqtt.send_unacked = 0; + } + + if (wsi->mqtt->inside_birth) { + /* + * Skip LWSSSCS_QOS_ACK_REMOTE for a Birth, notify + * CONNECTED event to the application. + */ + wsi->mqtt->inside_birth = 0; + wsi->mqtt->done_birth = 1; + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + lws_callback_on_writable(wsi); + break; + } r = lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); break; + case LWS_CALLBACK_MQTT_RESEND: + lws_sul_cancel(&h->sul_timeout); + if (h->u.mqtt.retry_count++ < LWS_MQTT_MAX_PUBLISH_RETRY) { + h->u.mqtt.unacked_size = + (uint32_t)lws_buflist_total_len(&h->u.mqtt.buflist_unacked); + if (h->u.mqtt.unacked_size) { + lwsl_notice("%s: %s: resend unacked message (%d/%d) \n", + __func__, lws_ss_tag(h), + h->u.mqtt.retry_count, + LWS_MQTT_MAX_PUBLISH_RETRY); + h->u.mqtt.send_unacked = 1; + lws_callback_on_writable(wsi); + break; + } + } + + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); + h->u.mqtt.retry_count = h->u.mqtt.send_unacked = 0; + + if (wsi->mqtt->inside_birth) { + lwsl_err("%s: %s: failed to send Birth\n", __func__, + lws_ss_tag(h)); + return -1; + } + + r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + break; + case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: { - size_t used_in, used_out, topic_limit; - lws_strexp_t exp; - char *expbuf; - if (!h || !h->info.tx) return 0; lwsl_notice("%s: %s: WRITEABLE\n", __func__, lws_ss_tag(h)); @@ -185,148 +802,114 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_warn("%s: seqstate %d\n", __func__, h->seqstate); break; } - if (h->policy->u.mqtt.aws_iot) - topic_limit = LWS_MQTT_MAX_AWSIOT_TOPICLEN; - else - topic_limit = LWS_MQTT_MAX_TOPICLEN; - if (h->policy->u.mqtt.subscribe && - !wsi->mqtt->done_subscribe) { - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, - NULL, topic_limit); - /* - * Expand with no output first to calculate the size of - * expanded string then, allocate new buffer and expand - * again with the buffer - */ - if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, - strlen(h->policy->u.mqtt.subscribe), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s, failed to expand MQTT subscribe" - " topic with no output\n", __func__); - return 1; - } + if (!wsi->mqtt->done_subscribe && h->policy->u.mqtt.subscribe) + return secstream_mqtt_subscribe(wsi); - expbuf = lws_malloc(used_out + 1, __func__); - if (!expbuf) { - lwsl_err("%s, failed to allocate MQTT subscribe" - "topic", __func__); - return 1; - } + if (h->u.mqtt.send_unacked) + return secstream_mqtt_resend(wsi, buf + LWS_PRE); - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, - expbuf, used_out); + if (!wsi->mqtt->done_birth && h->policy->u.mqtt.birth_topic) + return secstream_mqtt_birth(wsi, buf + LWS_PRE, buflen); - if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, - strlen(h->policy->u.mqtt.subscribe), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s, failed to expand MQTT subscribe topic\n", - __func__); - lws_free(expbuf); - return 1; + if (h->policy->u.mqtt.aws_iot) { + if (secstream_mqtt_is_shadow_matched(wsi, + h->policy->u.mqtt.topic) == LMMTR_TOPIC_MATCH) { + if (!wsi->mqtt->done_shadow_subscribe) + return secstream_mqtt_shadow_subscribe(wsi); + if (wsi->mqtt->send_shadow_unsubscribe) + return secstream_mqtt_shadow_unsubscribe(wsi); } - lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); - h->u.mqtt.sub_top.name = expbuf; - - /* - * The policy says to subscribe to something, and we - * haven't done it yet. Do it using the pre-prepared - * string-substituted version of the policy string. - */ - - lwsl_notice("%s: subscribing %s\n", __func__, - h->u.mqtt.sub_top.name); + } - 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; - h->u.mqtt.sub_info.topic = &h->u.mqtt.sub_top; + r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f); - if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.sub_info)) { - lwsl_notice("%s: unable to subscribe", __func__); - lws_free(expbuf); - h->u.mqtt.sub_top.name = NULL; - return -1; - } - lws_free(expbuf); - h->u.mqtt.sub_top.name = NULL; - /* Expect a SUBACK */ - if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); - return -1; + if (r == LWSSSSRET_TX_DONT_SEND) { + if (wsi->mqtt->done_shadow_subscribe) { + return secstream_mqtt_shadow_unsubscribe(wsi); } - return 0; } - - buflen = sizeof(buf) - LWS_PRE; - 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_DISCONNECT_ME) { + lws_mqtt_subscribe_param_t lmsp; + if (h->u.mqtt.sub_info.num_topics) { + lmsp.num_topics = h->u.mqtt.sub_info.num_topics; + lmsp.topic = h->u.mqtt.sub_info.topic; + lmsp.packet_id = (uint16_t)(h->txord - 1); + if (lws_mqtt_client_send_unsubcribe(wsi, + &lmsp)) { + lwsl_err("%s, failed to send" + " MQTT unsubsribe", __func__); + return -1; + } + return 0; + } + } if (r < 0) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); - memset(&mqpp, 0, sizeof(mqpp)); - /* this is the string-substituted h->policy->u.mqtt.topic */ - mqpp.topic = (char *)h->u.mqtt.topic_qos.name; - lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, NULL, - topic_limit); - - if (lws_strexp_expand(&exp, h->policy->u.mqtt.topic, - strlen(h->policy->u.mqtt.topic), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s, failed to expand MQTT publish" - " topic with no output\n", __func__); - return 1; - } - expbuf = lws_malloc(used_out + 1, __func__); - if (!expbuf) { - lwsl_err("%s, failed to allocate MQTT publish topic", - __func__); - return 1; + if (secstream_mqtt_publish(wsi, buf + LWS_PRE, buflen, + (uint32_t)h->writeable_len, + h->policy->u.mqtt.topic, + h->policy->u.mqtt.qos, + h->policy->u.mqtt.retain, 0, f) != 0) { + r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); } + return 0; + } - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, expbuf, - used_out); + case LWS_CALLBACK_MQTT_UNSUBSCRIBED: + { + struct lws *nwsi = lws_get_network_wsi(wsi); - if (lws_strexp_expand(&exp, h->policy->u.mqtt.topic, - strlen(h->policy->u.mqtt.topic), &used_in, - &used_out) != LSTRX_DONE) { - lws_free(expbuf); - return 1; + if (wsi->mqtt->inside_shadow) { + secstream_mqtt_shadow_cleanup(wsi); + wsi->mqtt->inside_shadow = 0; + wsi->mqtt->done_shadow_subscribe = 0; + break; } - lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); - mqpp.topic = (char *)expbuf; - - mqpp.topic_len = (uint16_t)strlen(mqpp.topic); - mqpp.packet_id = (uint16_t)(h->txord - 1); - mqpp.payload = buf + LWS_PRE; - if (h->writeable_len) - mqpp.payload_len = (uint32_t)h->writeable_len; - else - mqpp.payload_len = (uint32_t)buflen; + if (nwsi && (nwsi->mux.child_count == 1)) + lws_mqtt_client_send_disconnect(nwsi); + return -1; + } - lwsl_notice("%s: payload len %d\n", __func__, - (int)mqpp.payload_len); + case LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT: + if (!wsi->mqtt) + return -1; - mqpp.qos = h->policy->u.mqtt.qos; + if (wsi->mqtt->inside_shadow) { + secstream_mqtt_shadow_cleanup(wsi); + wsi->mqtt->inside_shadow = 0; + wsi->mqtt->done_shadow_subscribe = 0; + lwsl_warn("%s: %s: Unsubscribe (Shadow) timeout.\n", + __func__, lws_ss_tag(h)); + break; + } - if (lws_mqtt_client_send_publish(wsi, &mqpp, - (const char *)buf + LWS_PRE, - (uint32_t)buflen, - f & LWSSS_FLAG_EOM)) { - lwsl_notice("%s: failed to publish\n", __func__); - lws_free(expbuf); + if (wsi->mqtt->inside_unsubscribe) { + lwsl_warn("%s: %s: Unsubscribe timeout.\n", __func__, + lws_ss_tag(h)); + return -1; + } + break; + case LWS_CALLBACK_MQTT_SHADOW_TIMEOUT: + if (!wsi->mqtt) return -1; + + if (wsi->mqtt->inside_shadow) { + lwsl_warn("%s: %s: Shadow timeout.\n", __func__, + lws_ss_tag(h)); + wsi->mqtt->send_shadow_unsubscribe = 1; + lws_callback_on_writable(wsi); } - lws_free(expbuf); + break; - return 0; - } default: break; } @@ -337,8 +920,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, const struct lws_protocols protocol_secstream_mqtt = { "lws-secstream-mqtt", secstream_mqtt, - 0, - 0, + 0, 0, 0, NULL, 0 }; /* * Munge connect info according to protocol-specific considerations... this @@ -355,7 +937,9 @@ enum { SSCMM_STRSUB_WILL_TOPIC, SSCMM_STRSUB_WILL_MESSAGE, SSCMM_STRSUB_SUBSCRIBE, - SSCMM_STRSUB_TOPIC + SSCMM_STRSUB_TOPIC, + SSCMM_STRSUB_BIRTH_TOPIC, + SSCMM_STRSUB_BIRTH_MESSAGE }; static int @@ -363,16 +947,18 @@ 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] = { + const char *sources[6] = { /* 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 + h->policy->u.mqtt.topic, + h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_message }; - size_t used_in, olen[4] = { 0, 0, 0, 0 }, tot = 0; + size_t used_in, olen[6] = { 0, 0, 0, 0, 0, 0 }, tot = 0; lws_strexp_t exp; - char *ps[4]; + char *ps[6]; uint8_t *p = NULL; int n = -1; size_t blen; @@ -390,6 +976,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, return -1; } p = (uint8_t *)lws_zalloc(blen+1, __func__); + if (!p) + return -1; n = lws_system_blob_get(b, p, &blen, 0); if (n) { ct->ccp.client_id = NULL; @@ -409,6 +997,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, /* If LWS_SYSBLOB_TYPE_MQTT_USERNAME is set */ if (b && (blen = lws_system_blob_get_size(b))) { p = (uint8_t *)lws_zalloc(blen+1, __func__); + if (!p) + return -1; n = lws_system_blob_get(b, p, &blen, 0); if (n) { ct->ccp.username = NULL; @@ -425,6 +1015,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, /* If LWS_SYSBLOB_TYPE_MQTT_PASSWORD is set */ if (b && (blen = lws_system_blob_get_size(b))) { p = (uint8_t *)lws_zalloc(blen+1, __func__); + if (!p) + return -1; n = lws_system_blob_get(b, p, &blen, 0); if (n) { ct->ccp.password = NULL; @@ -436,9 +1028,11 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, } ct->ccp.keep_alive = h->policy->u.mqtt.keep_alive; - ct->ccp.clean_start = h->policy->u.mqtt.clean_start; + ct->ccp.clean_start = (h->policy->u.mqtt.clean_start & 1u); ct->ccp.will_param.qos = h->policy->u.mqtt.will_qos; ct->ccp.will_param.retain = h->policy->u.mqtt.will_retain; + ct->ccp.birth_param.qos = h->policy->u.mqtt.birth_qos; + ct->ccp.birth_param.retain = h->policy->u.mqtt.birth_retain; ct->ccp.aws_iot = h->policy->u.mqtt.aws_iot; h->u.mqtt.topic_qos.qos = h->policy->u.mqtt.qos; @@ -459,6 +1053,9 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, */ for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { + if (!sources[n]) + continue; + 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]), @@ -488,6 +1085,10 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, (char *)p, (size_t)-1); + if (!sources[n]) { + ps[n] = NULL; + continue; + } ps[n] = (char *)p; if (lws_strexp_expand(&exp, sources[n], strlen(sources[n]), &used_in, &olen[n]) != LSTRX_DONE) @@ -506,6 +1107,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, 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]; + ct->ccp.birth_param.topic = ps[SSCMM_STRSUB_BIRTH_TOPIC]; + ct->ccp.birth_param.message = ps[SSCMM_STRSUB_BIRTH_MESSAGE]; i->method = "MQTT"; i->mqtt_cp = &ct->ccp; @@ -522,5 +1125,6 @@ const struct ss_pcols ss_pcol_mqtt = { "MQTT", "x-amzn-mqtt-ca", //"mqtt/3.1.1", &protocol_secstream_mqtt, - secstream_connect_munge_mqtt + secstream_connect_munge_mqtt, + NULL, NULL }; diff --git a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-raw.c b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-raw.c index b11a74bc..76b11ea1 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-raw.c +++ b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-raw.c @@ -48,7 +48,9 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_info("%s: %s, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, lws_ss_tag(h), h->policy->streamtype, in ? (char *)in : "(null)"); +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); +#endif r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); if (r == LWSSSSRET_DESTROY_ME) @@ -64,7 +66,9 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; lws_sul_cancel(&h->sul_timeout); +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); +#endif lwsl_info("%s: %s, %s RAW_CLOSE\n", __func__, lws_ss_tag(h), h->policy ? h->policy->streamtype : "no policy"); @@ -177,6 +181,7 @@ const struct lws_protocols protocol_secstream_raw = { secstream_raw, 0, 0, + 0, NULL, 0 }; const struct ss_pcols ss_pcol_raw = { @@ -184,5 +189,5 @@ const struct ss_pcols ss_pcol_raw = { "", &protocol_secstream_raw, secstream_connect_munge_raw, - NULL + NULL, NULL }; diff --git a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-ws.c b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-ws.c index d7b04c09..eed62c5b 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-ws.c +++ b/3rdparty/libwebsockets/lib/secure-streams/protocols/ss-ws.c @@ -46,7 +46,9 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!h) break; +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); +#endif r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); if (r == LWSSSSRET_DESTROY_ME) @@ -64,7 +66,9 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; lws_sul_cancel(&h->sul_timeout); +#if defined(LWS_WITH_CONMON) lws_conmon_ss_json(h); +#endif r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); if (r == LWSSSSRET_DESTROY_ME) @@ -186,8 +190,7 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, const struct lws_protocols protocol_secstream_ws = { "lws-secstream-ws", secstream_ws, - 0, - 0, + 0, 0, 0, NULL, 0 }; /* * Munge connect info according to protocol-specific considerations... this @@ -209,8 +212,6 @@ secstream_connect_munge_ws(lws_ss_handle_t *h, char *buf, size_t len, size_t used_in, used_out; lws_strexp_t exp; - lwsl_notice("%s\n", __func__); - /* i.path on entry is used to override the policy urlpath if not "" */ if (i->path[0]) @@ -219,6 +220,12 @@ secstream_connect_munge_ws(lws_ss_handle_t *h, char *buf, size_t len, if (!pbasis) return 0; + if (h->policy->flags & LWSSSPOLF_HTTP_CACHE_COOKIES) + i->ssl_connection |= LCCSCF_CACHE_COOKIES; + + if (h->policy->flags & LWSSSPOLF_PRIORITIZE_READS) + i->ssl_connection |= LCCSCF_PRIORITIZE_READS; + /* protocol aux is the path part ; ws subprotocol name */ i->path = buf; @@ -232,11 +239,11 @@ secstream_connect_munge_ws(lws_ss_handle_t *h, char *buf, size_t len, i->protocol = h->policy->u.http.u.ws.subprotocol; - lwsl_notice("%s: url %s, ws subprotocol %s\n", __func__, buf, i->protocol); + lwsl_ss_info(h, "url %s, ws subprotocol %s", buf, i->protocol); return 0; } const struct ss_pcols ss_pcol_ws = { - "ws", "http/1.1", &protocol_secstream_ws, secstream_connect_munge_ws + "ws", "http/1.1", &protocol_secstream_ws, secstream_connect_munge_ws, 0, 0 }; diff --git a/3rdparty/libwebsockets/lib/secure-streams/secure-streams-client.c b/3rdparty/libwebsockets/lib/secure-streams/secure-streams-client.c index 9c877fad..075cf965 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/secure-streams-client.c +++ b/3rdparty/libwebsockets/lib/secure-streams/secure-streams-client.c @@ -19,20 +19,75 @@ */ #include +extern const uint32_t ss_state_txn_validity[17]; + +int +lws_ss_check_next_state_sspc(lws_sspc_handle_t *ss, uint8_t *prevstate, + lws_ss_constate_t cs) +{ + if (cs >= LWSSSCS_USER_BASE || cs == LWSSSCS_EVENT_WAIT_CANCELLED) + /* + * we can't judge user or transient states, leave the old state + * and just wave them through + */ + return 0; + + if (cs >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { + /* we don't recognize this state as usable */ + lwsl_sspc_err(ss, "bad new state %u", cs); + assert(0); + return 1; + } + + if (*prevstate >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { + /* existing state is broken */ + lwsl_sspc_err(ss, "bad existing state %u", + (unsigned int)*prevstate); + assert(0); + return 1; + } + + if (ss_state_txn_validity[*prevstate] & (1u << cs)) { + + lwsl_sspc_notice(ss, "%s -> %s", + lws_ss_state_name((int)*prevstate), + lws_ss_state_name((int)cs)); + + /* this is explicitly allowed, update old state to new */ + *prevstate = (uint8_t)cs; + + return 0; + } + + lwsl_sspc_err(ss, "transition from %s -> %s is illegal", + lws_ss_state_name((int)*prevstate), + lws_ss_state_name((int)cs)); + + assert(0); + + return 1; +} + lws_ss_state_return_t lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs, lws_ss_tx_ordinal_t flags) { + lws_ss_state_return_t ret; + if (!h) return LWSSSSRET_OK; - if (lws_ss_check_next_state(&h->lc, &h->prev_ss_state, cs)) + if (lws_ss_check_next_state_sspc(h, &h->prev_ss_state, cs)) return LWSSSSRET_DESTROY_ME; if (!h->ssi.state) return LWSSSSRET_OK; - return h->ssi.state((void *)((uint8_t *)&h[1]), NULL, cs, flags); + h->h_in_svc = h; + ret = h->ssi.state((void *)((uint8_t *)(h + 1)), NULL, cs, flags); + h->h_in_svc = NULL; + + return ret; } static void @@ -94,17 +149,18 @@ lws_sspc_sul_retry_cb(lws_sorted_usec_list_t *sul) return; } - lwsl_notice("%s: %s\n", __func__, h->cwsi->lc.gutag); + lwsl_sspc_notice(h, "%s", h->cwsi->lc.gutag); } static int -lws_sspc_serialize_metadata(lws_sspc_metadata_t *md, uint8_t *p, uint8_t *end) +lws_sspc_serialize_metadata(lws_sspc_handle_t *h, lws_sspc_metadata_t *md, + uint8_t *p, uint8_t *end) { int n, txc; if (md->name[0] == '\0') { - lwsl_info("%s: sending tx credit update %d\n", __func__, + lwsl_info("sending tx credit update %d\n", md->tx_cr_adjust); p[0] = LWSSS_SER_TXPRE_TXCR_UPDATE; @@ -115,7 +171,7 @@ lws_sspc_serialize_metadata(lws_sspc_metadata_t *md, uint8_t *p, uint8_t *end) } else { - lwsl_info("%s: sending metadata\n", __func__); + lwsl_sspc_info(h, "sending metadata"); p[0] = LWSSS_SER_TXPRE_METADATA; txc = (int)strlen(md->name); @@ -145,22 +201,28 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, { lws_sspc_handle_t *h = (lws_sspc_handle_t *)lws_get_opaque_user_data(wsi); size_t pktsize = wsi->a.context->max_http_header_data; - void *m = (void *)((uint8_t *)&h[1]); + void *m = (void *)((uint8_t *)(h + 1)); uint8_t *pkt = NULL, *p = NULL, *end = NULL; + lws_ss_state_return_t r; + uint64_t interval; const uint8_t *cp; uint8_t s[64]; lws_usec_t us; int flags, n; switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: - break; - case LWS_CALLBACK_PROTOCOL_DESTROY: + case LWS_CALLBACK_CONNECTING: + /* + * In our particular case, we want CCEs even inside the + * initial connect loop time + */ + wsi->client_suppress_CONNECTION_ERROR = 0; break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_warn("%s: CONNECTION_ERROR\n", __func__); + lwsl_warn("%s: CCE: %s\n", __func__, + in ? (const char *)in : "null"); #if defined(LWS_WITH_SYS_METRICS) /* * If any hanging caliper measurement, dump it, and free any tags @@ -171,12 +233,23 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, h->cwsi = NULL; lws_sul_schedule(h->context, 0, &h->sul_retry, lws_sspc_sul_retry_cb, LWS_US_PER_SEC); + if (h->ssi.state) { + interval = (uint64_t)(lws_now_usecs() - h->us_start_upstream) / + LWS_US_PER_MS; + if (interval > 0xffffffffull) + interval = 0xffffffffull; + r = h->ssi.state(lws_sspc_to_user_object(h), NULL, + LWSSSCS_UPSTREAM_LINK_RETRY, + (uint32_t)interval); + if (r == LWSSSSRET_DESTROY_ME) + lws_sspc_destroy(&h); + } break; case LWS_CALLBACK_RAW_CONNECTED: if (!h || lws_fi(&h->fic, "sspc_fail_on_linkup")) return -1; - lwsl_info("%s: CONNECTED (%s)\n", __func__, h->ssi.streamtype); + lwsl_sspc_info(h, "CONNECTED (%s)", h->ssi.streamtype); h->state = LPCSCLI_SENDING_INITIAL_TX; /* @@ -190,37 +263,49 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, */ lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, 3); lws_callback_on_writable(wsi); + h->us_start_upstream = 0; break; case LWS_CALLBACK_RAW_CLOSE: /* * our ss proxy Unix Domain socket has closed... */ - lwsl_info("%s: LWS_CALLBACK_RAW_CLOSE: %s proxy conn down, sspc h %s\n", - __func__, lws_wsi_tag(wsi), lws_sspc_tag(h)); - if (h) { - lws_dsh_destroy(&h->dsh); - if (h->ss_dangling_connected && h->ssi.state) { - lwsl_notice("%s: setting _DISCONNECTED\n", __func__); - h->ss_dangling_connected = 0; - h->prev_ss_state = LWSSSCS_DISCONNECTED; - h->ssi.state(ss_to_userobj(h), NULL, LWSSSCS_DISCONNECTED, 0); + if (!h) { + lwsl_info("%s: no sspc on client proxy link close", __func__); + break; + } + lwsl_sspc_info(h, "LWS_CALLBACK_RAW_CLOSE: proxy conn down, wsi %s", + lws_wsi_tag(wsi)); + + lws_dsh_destroy(&h->dsh); + if (h->ss_dangling_connected && h->ssi.state) { + + lwsl_sspc_notice(h, "setting _DISCONNECTED"); + h->ss_dangling_connected = 0; + h->prev_ss_state = LWSSSCS_DISCONNECTED; + r = h->ssi.state(ss_to_userobj(h), NULL, + LWSSSCS_DISCONNECTED, 0); + if (r == LWSSSSRET_DESTROY_ME) { + h->cwsi = NULL; + lws_set_opaque_user_data(wsi, NULL); + lws_sspc_destroy(&h); + break; } - 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); - } else - lwsl_info("%s: no sspc on client proxy link close\n", __func__); + } + + 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) { lwsl_info("%s: rx when client ss destroyed\n", __func__); @@ -228,8 +313,10 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, return -1; } + lwsl_sspc_info(h, "%s: RAW_RX: rx %d\n", __func__, (int)len); + if (!len) { - lwsl_notice("%s: RAW_RX: zero len\n", __func__); + lwsl_sspc_notice(h, "RAW_RX: zero len"); return -1; } @@ -250,11 +337,11 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, case LWSSSSRET_OK: break; case LWSSSSRET_DISCONNECT_ME: - lwsl_notice("%s: proxlicent RX ended with DISCONNECT_ME\n", + lwsl_info("%s: proxlicent RX ended with DISCONNECT_ME\n", __func__); return -1; case LWSSSSRET_DESTROY_ME: - lwsl_notice("%s: proxlicent RX ended with DESTROY_ME\n", + lwsl_info("%s: proxlicent RX ended with DESTROY_ME\n", __func__); lws_set_opaque_user_data(wsi, NULL); lws_sspc_destroy(&h); @@ -276,8 +363,8 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, if (!h) break; - lwsl_debug("%s: WRITEABLE %s, state %d\n", __func__, - wsi->lc.gutag, h->state); + lwsl_sspc_debug(h, "WRITEABLE %s, state %d", + wsi->lc.gutag, h->state); /* * Management of ss timeout can happen any time and doesn't @@ -349,18 +436,18 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, cp = p = pkt + LWS_PRE; end = p + pktsize; - n = lws_sspc_serialize_metadata(md, p, end); + n = lws_sspc_serialize_metadata(h, md, p, end); if (n < 0) goto metadata_hangup; - lwsl_debug("%s: (local_conn) metadata\n", __func__); + lwsl_sspc_debug(h, "(local_conn) metadata"); 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); + lwsl_sspc_debug(h, "(local_conn) PAYLOAD_LENGTH_HINT %u", + (unsigned int)h->writeable_len); s[0] = LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT; lws_ser_wu16be(&s[1], 4); lws_ser_wu32be(&s[3], (uint32_t)h->writeable_len); @@ -370,12 +457,12 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, } if (h->conn_req_state >= LWSSSPC_ONW_ONGOING) { - lwsl_info("%s: conn_req_state %d\n", __func__, + lwsl_sspc_info(h, "conn_req_state %d", h->conn_req_state); break; } - lwsl_info("%s: (local_conn) onward connect\n", __func__); + lwsl_sspc_info(h, "(local_conn) onward connect"); h->conn_req_state = LWSSSPC_ONW_ONGOING; @@ -407,7 +494,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, lws_dll2_get_tail(&h->metadata_owner), lws_sspc_metadata_t, list); - n = lws_sspc_serialize_metadata(md, p, end); + n = lws_sspc_serialize_metadata(h, md, p, end); if (n < 0) goto metadata_hangup; @@ -415,8 +502,8 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, } if (h->pending_writeable_len) { - lwsl_info("%s: PAYLOAD_LENGTH_HINT %u\n", - __func__, (unsigned int)h->writeable_len); + lwsl_sspc_info(h, "PAYLOAD_LENGTH_HINT %u", + (unsigned int)h->writeable_len); s[0] = LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT; lws_ser_wu16be(&s[1], 4); lws_ser_wu32be(&s[3], (uint32_t)h->writeable_len); @@ -427,8 +514,8 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, /* we can't write anything if we don't have credit */ if (!h->ignore_txc && h->txc.tx_cr <= 0) { - lwsl_info("%s: WRITEABLE / OPERATIONAL:" - " lack credit (%d)\n", __func__, + lwsl_sspc_info(h, "WRITEABLE / OPERATIONAL:" + " lack credit (%d)", h->txc.tx_cr); // break; } @@ -490,7 +577,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, else n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW); if (n < 0) { - lwsl_notice("%s: WRITEABLE: %d\n", __func__, n); + lwsl_sspc_notice(h, "WRITEABLE: %d", n); goto hangup; } @@ -505,7 +592,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, return lws_callback_http_dummy(wsi, reason, user, in, len); metadata_hangup: - lwsl_err("%s: metadata too large\n", __func__); + lwsl_sspc_err(h, "metadata too large"); hangup: lws_free(pkt); @@ -538,6 +625,8 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, uint8_t *ua; char *p; + lws_service_assert_loop_thread(context, tsi); + /* allocate the handle (including ssi), the user alloc, * and the streamname */ @@ -547,6 +636,8 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, return 1; memset(h, 0, sizeof(*h)); + h->lc.log_cx = context->log_cx; + #if defined(LWS_WITH_SYS_FAULT_INJECTION) h->fic.name = "sspc"; lws_xos_init(&h->fic.xos, lws_xos(&context->fic.xos)); @@ -566,15 +657,17 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, return 1; } - __lws_lc_tag(&context->lcg[LWSLCG_SSP_CLIENT], &h->lc, ssi->streamtype); + __lws_lc_tag(context, &context->lcg[LWSLCG_SSP_CLIENT], &h->lc, + ssi->streamtype); memcpy(&h->ssi, ssi, sizeof(*ssi)); - ua = (uint8_t *)&h[1]; + ua = (uint8_t *)(h + 1); memset(ua, 0, ssi->user_alloc); p = (char *)ua + ssi->user_alloc; memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1); h->ssi.streamtype = (const char *)p; h->context = context; + h->us_start_upstream = lws_now_usecs(); if (!ssi->manual_initial_tx_credit) h->txc.peer_tx_cr_est = 500000000; @@ -632,12 +725,18 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) { lws_sspc_handle_t *h; - lwsl_debug("%s\n", __func__); - if (!*ph) return; h = *ph; + if (h == h->h_in_svc) { + lwsl_err("%s: illegal destroy, return LWSSSSRET_DESTROY_ME instead\n", + __func__); + assert(0); + return; + } + + lws_service_assert_loop_thread(h->context, 0); if (h->destroying) return; @@ -690,7 +789,13 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) lws_sul_cancel(&h->sul_retry); - __lws_lc_untag(&h->lc); + + /* confirm no sul left scheduled in handle or user allocation object */ + lws_sul_debug_zombies(h->context, h, sizeof(*h) + h->ssi.user_alloc, + __func__); + + __lws_lc_untag(h->context, &h->lc); + free(h); } @@ -700,6 +805,8 @@ lws_sspc_request_tx(lws_sspc_handle_t *h) if (!h || !h->cwsi) return LWSSSSRET_OK; + lws_service_assert_loop_thread(h->context, 0); + if (!h->us_earliest_write_req) h->us_earliest_write_req = lws_now_usecs(); @@ -741,8 +848,9 @@ lws_sspc_request_tx_len(lws_sspc_handle_t *h, unsigned long len) if (!h) return LWSSSSRET_OK; - lwsl_notice("%s: setting %s writeable_len %u\n", __func__, h->lc.gutag, - (unsigned int)len); + lws_service_assert_loop_thread(h->context, 0); + + lwsl_sspc_notice(h, "setting writeable_len %u", (unsigned int)len); h->writeable_len = len; h->pending_writeable_len = 1; @@ -770,6 +878,8 @@ lws_sspc_client_connect(lws_sspc_handle_t *h) if (!h || h->state == LPCSCLI_OPERATIONAL) return 0; + lws_service_assert_loop_thread(h->context, 0); + assert(h->state == LPCSCLI_LOCAL_CONNECTED); if (h->state == LPCSCLI_LOCAL_CONNECTED && h->conn_req_state == LWSSSPC_ONW_NONE) @@ -794,7 +904,8 @@ lws_sspc_rideshare(struct lws_sspc_handle *h) */ if (h->parser.rideshare[0]) { - lwsl_info("%s: parser %s\n", __func__, h->parser.rideshare); + lwsl_sspc_info(h, "parser %s", h->parser.rideshare); + return h->parser.rideshare; } @@ -803,7 +914,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h) */ if (h->rideshare_list[0]) { - lwsl_info("%s: tx list %s\n", __func__, + lwsl_sspc_info(h, "tx list %s", &h->rideshare_list[h->rideshare_ofs[h->rsidx]]); return &h->rideshare_list[h->rideshare_ofs[h->rsidx]]; } @@ -812,7 +923,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h) * ... otherwise default to our stream type name */ - lwsl_info("%s: def %s\n", __func__, h->ssi.streamtype); + lwsl_sspc_info(h, "def %s\n", h->ssi.streamtype); return h->ssi.streamtype; } @@ -823,6 +934,8 @@ _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, { lws_sspc_metadata_t *md; + lws_service_assert_loop_thread(h->context, 0); + /* * Are we replacing a pending metadata of the same name? It's not * efficient to do this but user code can do what it likes... let's @@ -852,7 +965,7 @@ _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, else md = lws_malloc(sizeof(*md) + len, "set metadata"); if (!md) { - lwsl_err("%s: OOM\n", __func__); + lwsl_sspc_err(h, "OOM"); return 1; } @@ -870,10 +983,10 @@ _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, lws_dll2_add_tail(&md->list, &h->metadata_owner); if (len) { - lwsl_info("%s: set metadata %s\n", __func__, name); - lwsl_hexdump_info(value, len); + lwsl_sspc_info(h, "set metadata %s", name); + lwsl_hexdump_sspc_info(h, value, len); } else - lwsl_info("%s: serializing tx cr adj %d\n", __func__, + lwsl_sspc_info(h, "serializing tx cr adj %d", (int)tx_cr_adjust); if (h->cwsi) @@ -902,6 +1015,8 @@ lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name, * the same name first */ + lws_service_assert_loop_thread(h->context, 0); + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, lws_dll2_get_head(&h->metadata_owner_rx)) { md = lws_container_of(d, @@ -922,19 +1037,22 @@ lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name, int lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t bump) { - lwsl_notice("%s: %d\n", __func__, bump); + lws_service_assert_loop_thread(h->context, 0); + lwsl_sspc_notice(h, "%d\n", bump); return _lws_sspc_set_metadata(h, "", NULL, 0, (int)bump); } int lws_sspc_get_est_peer_tx_credit(struct lws_sspc_handle *h) { + lws_service_assert_loop_thread(h->context, 0); return h->txc.peer_tx_cr_est; } void lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms) { + lws_service_assert_loop_thread(h->context, 0); if (!h->cwsi) /* we can't fulfil it */ return; @@ -952,7 +1070,7 @@ lws_sspc_cancel_timeout(struct lws_sspc_handle *h) void * lws_sspc_to_user_object(struct lws_sspc_handle *h) { - return (void *)&h[1]; + return (void *)(h + 1); } void @@ -978,3 +1096,14 @@ lws_sspc_tag(struct lws_sspc_handle *h) return "[null sspc]"; return lws_lc_tag(&h->lc); } + +int +lws_sspc_cancel_notify_dll(struct lws_dll2 *d, void *user) +{ + lws_sspc_handle_t *h = lws_container_of(d, lws_sspc_handle_t, client_list); + + lws_sspc_event_helper(h, LWSSSCS_EVENT_WAIT_CANCELLED, 0); + + return 0; +} + diff --git a/3rdparty/libwebsockets/lib/secure-streams/secure-streams-process.c b/3rdparty/libwebsockets/lib/secure-streams/secure-streams-process.c index 9edd7a63..552e1d12 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/secure-streams-process.c +++ b/3rdparty/libwebsockets/lib/secure-streams/secure-streams-process.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2021 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 @@ -68,13 +68,12 @@ void lws_proxy_clean_conn_ss(struct lws *wsi) { #if 0 - struct conn *conn; + lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data; + struct conn *conn = h->conn_if_sspc_onw; if (!wsi) return; - conn = (struct conn *)wsi->a.opaque_user_data; - if (conn && conn->ss) conn->ss->wsi = NULL; #endif @@ -208,7 +207,7 @@ ss_proxy_onward_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, /* ... there's more we want to send? */ if (!lws_dsh_get_head(m->conn->dsh, KIND_C_TO_P, (void **)&p, &si)) - lws_ss_request_tx(m->conn->ss); + _lws_ss_request_tx(m->conn->ss); if (!*len && !*flags) /* we don't actually want to send anything */ @@ -488,6 +487,7 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, ssi.state = ss_proxy_onward_state; ssi.flags = 0; + // coverity[uninit_use_in_call] n = lws_ss_deserialize_parse(&conn->parser, lws_get_context(wsi), conn->dsh, in, len, &conn->state, conn, &conn->ss, &ssi, 0); @@ -609,6 +609,7 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, * priority 2 */ +#if defined(LWS_WITH_CONMON) if (conn->ss->conmon_json) { unsigned int xlen = conn->ss->conmon_len; @@ -626,7 +627,7 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, pay = 0; goto again; } - +#endif /* * if no fresh rx metadata, just pass through incoming * dsh diff --git a/3rdparty/libwebsockets/lib/secure-streams/secure-streams-serialize.c b/3rdparty/libwebsockets/lib/secure-streams/secure-streams-serialize.c index 571e6714..53a9ed81 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/secure-streams-serialize.c +++ b/3rdparty/libwebsockets/lib/secure-streams/secure-streams-serialize.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2021 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 @@ -108,11 +108,31 @@ static const char *sn[] = { }; #endif +struct lws_log_cx * +lwsl_sspc_get_cx(struct lws_sspc_handle *sspc) +{ + if (!sspc) + return NULL; + + return sspc->lc.log_cx; +} + + void -lws_ss_serialize_state_transition(lws_ss_conn_states_t *state, int new_state) +lws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e) +{ + struct lws_sspc_handle *h = (struct lws_sspc_handle *)obj; + + *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", + lws_sspc_tag(h)); +} + +static void +lws_ss_serialize_state_transition(lws_sspc_handle_t *h, + lws_ss_conn_states_t *state, int new_state) { #if defined(_DEBUG) - lwsl_info("%s: %s -> %s\n", __func__, sn[*state], sn[new_state]); + lwsl_sspc_info(h, "%s -> %s", sn[*state], sn[new_state]); #endif *state = (lws_ss_conn_states_t)new_state; } @@ -226,33 +246,6 @@ lws_ss_deserialize_tx_payload(struct lws_dsh *dsh, struct lws *wsi, *flags = (int)lws_ser_ru32be(&p[3]); -#if 0 - if (wsi && wsi->a.context->detailed_latency_cb) { - /* - * use the proxied latency information to compute the client - * and our delays, and apply to wsi. - * - * + 7 u32 us held at client before written - * +11 u32 us taken for transit to proxy - * +15 u64 ustime when proxy got packet from client - */ - lws_usec_t us = lws_now_usecs(); - - wsi->detlat.acc_size = wsi->detlat.req_size = si - 23; - wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] = - lws_ser_ru32be(&p[7]); - wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_WRITE_TO_PROXY_RX] = - lws_ser_ru32be(&p[11]); - wsi->detlat.latencies[LAT_DUR_PROXY_RX_TO_ONWARD_TX] = - us - lws_ser_ru64be(&p[15]); - - wsi->detlat.latencies[LAT_DUR_USERCB] = 0; - } -#endif - - // lwsl_user("%s: len %d, flags: %d\n", __func__, (int)*len, *flags); - // lwsl_hexdump_info(buf, *len); - lws_dsh_free((void **)&p); return 0; @@ -270,6 +263,9 @@ lws_ss_serialize_state(struct lws *wsi, struct lws_dsh *dsh, lws_ss_constate_t s uint8_t pre[12]; int n = 4; + if (state == LWSSSCS_EVENT_WAIT_CANCELLED) + return 0; + lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name((int)state), (unsigned int)ack); @@ -366,6 +362,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, lws_ss_conn_states_t *state, void *parconn, lws_ss_handle_t **pss, lws_ss_info_t *ssi, char client) { + lws_ss_state_return_t r; lws_ss_metadata_t *pm; lws_sspc_handle_t *h; uint8_t pre[23]; @@ -375,6 +372,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, int n; while (len--) { + switch (par->ps) { case RPAR_TYPE: par->type = *cp++; @@ -405,7 +403,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (client) goto hangup; par->ps = RPAR_TYPE; - lwsl_notice("%s: DESTROYING\n", __func__); + lwsl_cx_notice(context, "DESTROYING"); goto hangup; case LWSSS_SER_TXPRE_ONWARD_CONNECT: @@ -416,7 +414,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, goto hangup; par->ps = RPAR_TYPE; - lwsl_notice("%s: ONWARD_CONNECT\n", __func__); + lwsl_cx_notice(context, "ONWARD_CONNECT"); /* * Shrug it off if we are already connecting or @@ -542,8 +540,8 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, break; default: - lwsl_notice("%s: bad type 0x%x\n", __func__, - par->type); + lwsl_cx_notice(context, "bad type 0x%x", + par->type); goto hangup; } break; @@ -711,6 +709,8 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, us = lws_now_usecs(); if (!client) { + lws_ss_handle_t *hss; + /* * Proxy - we received some serialized tx from * the client. @@ -721,8 +721,9 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, * additionally */ - lwsl_info("%s: C2P RX: len %d\n", __func__, - (int)n); + hss = proxy_pss_to_ss_h(pss); + if (hss) + lwsl_ss_info(hss, "C2P RX: len %d", (int)n); p = pre; pre[0] = LWSSS_SER_TXPRE_TX_PAYLOAD; @@ -735,19 +736,17 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, /* time used later to find proxy hold time */ lws_ser_wu64be(&p[15], (uint64_t)us); - if ((proxy_pss_to_ss_h(pss) && - lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_dsh_c2p_pay_oom")) || + if ((hss && + lws_fi(&hss->fic, "ssproxy_dsh_c2p_pay_oom")) || lws_dsh_alloc_tail(dsh, KIND_C_TO_P, pre, 23, cp, (unsigned int)n)) { - lwsl_err("%s: unable to alloc in dsh 3\n", - __func__); + lwsl_ss_err(hss, "unable to alloc in dsh 3"); return LWSSSSRET_DISCONNECT_ME; } - if (proxy_pss_to_ss_h(pss)) - lws_ss_request_tx( - proxy_pss_to_ss_h(pss)); + if (hss) + _lws_ss_request_tx(hss); } else { /* @@ -756,16 +755,17 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, * Pass whatever payload we have to ss user */ - lwsl_info("%s: P2C RX: len %d\n", __func__, - (int)n); - h = lws_container_of(par, lws_sspc_handle_t, parser); h->txc.peer_tx_cr_est -= n; - if (client_pss_to_sspc_h(pss, ssi)) { + lwsl_sspc_info(h, "P2C RX: len %d", (int)n); + + if (ssi->rx && client_pss_to_sspc_h(pss, ssi)) { /* we still have an sspc handle */ - int ret = ssi->rx(client_pss_to_userdata(pss), + int ret; + + ret = ssi->rx(client_pss_to_userdata(pss), (uint8_t *)cp, (unsigned int)n, (int)flags); if (client_pss_to_sspc_h(pss, ssi) && @@ -921,7 +921,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, __func__, par->temp32, proxy_pss_to_ss_h(pss)->wsi-> txc.peer_tx_cr_est); - lws_ss_request_tx(proxy_pss_to_ss_h(pss)); + _lws_ss_request_tx(proxy_pss_to_ss_h(pss)); } else #endif lwsl_info("%s: dropping TXCR\n", __func__); @@ -1004,11 +1004,14 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, 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), - (unsigned long)par->temp32); - par->ps = RPAR_TYPE; + + if (proxy_pss_to_ss_h(pss)) { + r = lws_ss_request_tx_len(proxy_pss_to_ss_h(pss), + (unsigned long)par->temp32); + if (r == LWSSSSRET_DESTROY_ME) + goto hangup; + } break; case RPAR_METADATA_NAMELEN: @@ -1071,6 +1074,11 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, lwsl_err("%s: OOM\n", __func__); goto hangup; } + + if (!h) + /* coverity */ + goto hangup; + memset(md, 0, sizeof(lws_sspc_metadata_t)); lws_strncpy(md->name, par->metadata_name, @@ -1095,6 +1103,11 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (!proxy_pss_to_ss_h(pss)) goto hangup; + if (!proxy_pss_to_ss_h(pss)->policy) { + lwsl_err("%s: null policy\n", __func__); + goto hangup; + } + /* * This is the policy's metadata list for the given * name @@ -1113,25 +1126,28 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, proxy_pss_to_ss_h(pss), par->metadata_name); - if (par->ssmd->value_on_lws_heap) - lws_free_set_NULL(par->ssmd->value__may_own_heap); - par->ssmd->value_on_lws_heap = 0; + if (par->ssmd) { - if (proxy_pss_to_ss_h(pss) && - lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_rx_metadata_oom")) - par->ssmd->value__may_own_heap = NULL; - else - par->ssmd->value__may_own_heap = - lws_malloc((unsigned int)par->rem + 1, "metadata"); + if (par->ssmd->value_on_lws_heap) + lws_free_set_NULL(par->ssmd->value__may_own_heap); + par->ssmd->value_on_lws_heap = 0; - if (!par->ssmd->value__may_own_heap) { - lwsl_err("%s: OOM mdv\n", __func__); - goto hangup; + if (proxy_pss_to_ss_h(pss) && + lws_fi(&proxy_pss_to_ss_h(pss)->fic, "ssproxy_rx_metadata_oom")) + par->ssmd->value__may_own_heap = NULL; + else + par->ssmd->value__may_own_heap = + lws_malloc((unsigned int)par->rem + 1, "metadata"); + + if (!par->ssmd->value__may_own_heap) { + lwsl_err("%s: OOM mdv\n", __func__); + goto hangup; + } + par->ssmd->length = par->rem; + ((uint8_t *)par->ssmd->value__may_own_heap)[par->rem] = '\0'; + /* mark it as needing cleanup */ + par->ssmd->value_on_lws_heap = 1; } - par->ssmd->length = par->rem; - ((uint8_t *)par->ssmd->value__may_own_heap)[par->rem] = '\0'; - /* mark it as needing cleanup */ - par->ssmd->value_on_lws_heap = 1; par->ctr = 0; break; @@ -1140,21 +1156,39 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (client) { *par->rxmetaval++ = *cp++; - } else + } else { + + if (!par->ssmd) { + /* we don't recognize the name */ + + cp++; + + if (--par->rem) + break; + + par->ps = RPAR_TYPE; + break; + } + ((uint8_t *)(par->ssmd->value__may_own_heap))[par->ctr++] = *cp++; + } if (--par->rem) break; /* we think we got all the value */ - if (client) - lwsl_notice("%s: RX METADATA %s\n", __func__, - par->metadata_name); - else { - lwsl_info("%s: RPAR_METADATA_VALUE for %s (len %d)\n", - __func__, par->ssmd->name, - (int)par->ssmd->length); - lwsl_hexdump_info(par->ssmd->value__may_own_heap, par->ssmd->length); + if (client) { + h = lws_container_of(par, lws_sspc_handle_t, parser); + lwsl_sspc_notice(h, "RX METADATA %s", + par->metadata_name); + } else { + lwsl_ss_info(proxy_pss_to_ss_h(pss), + "RPAR_METADATA_VALUE for %s (len %d)", + par->ssmd->name, + (int)par->ssmd->length); + lwsl_hexdump_ss_info(proxy_pss_to_ss_h(pss), + par->ssmd->value__may_own_heap, + par->ssmd->length); } par->ps = RPAR_TYPE; break; @@ -1267,14 +1301,15 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (++par->ctr < 4) break; - /* * Client (par->temp32 == dsh alloc) */ - lws_ss_serialize_state_transition(state, - LPCSCLI_LOCAL_CONNECTED); h = lws_container_of(par, lws_sspc_handle_t, parser); + + lws_ss_serialize_state_transition(h, state, + LPCSCLI_LOCAL_CONNECTED); + lws_set_timeout(h->cwsi, NO_PENDING_TIMEOUT, 0); if (h->dsh) @@ -1308,8 +1343,9 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, #endif if (!h->creating_cb_done) { - if (lws_ss_check_next_state(&h->lc, &h->prev_ss_state, - LWSSSCS_CREATING)) + if (lws_ss_check_next_state_sspc(h, + &h->prev_ss_state, + LWSSSCS_CREATING)) return LWSSSSRET_DESTROY_ME; h->prev_ss_state = (uint8_t)LWSSSCS_CREATING; h->creating_cb_done = 1; @@ -1334,8 +1370,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (!h->dsh) goto hangup; - if (h->cwsi) - lws_callback_on_writable(h->cwsi); + lws_callback_on_writable(h->cwsi); par->rsl_pos = 0; par->rsl_idx = 0; @@ -1398,7 +1433,8 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, * Client received a proxied state change */ - if (!client_pss_to_sspc_h(pss, ssi)) + h = client_pss_to_sspc_h(pss, ssi); + if (!h) /* * Since we're being informed we need to have * a stream to inform. Assume whatever set this @@ -1410,25 +1446,25 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, case LWSSSCS_DISCONNECTED: case LWSSSCS_UNREACHABLE: case LWSSSCS_AUTH_FAILED: - lws_ss_serialize_state_transition(state, + lws_ss_serialize_state_transition(h, state, LPCSCLI_LOCAL_CONNECTED); - client_pss_to_sspc_h(pss, ssi)->conn_req_state = - LWSSSPC_ONW_NONE; + h->conn_req_state = LWSSSPC_ONW_NONE; break; + case LWSSSCS_CONNECTED: - lwsl_info("%s: CONNECTED %s\n", __func__, - ssi->streamtype); + lwsl_sspc_info(h, "CONNECTED %s", + 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, - LPCSCLI_OPERATIONAL); - client_pss_to_sspc_h(pss, ssi)->conn_req_state = - LWSSSPC_ONW_CONN; + lws_ss_serialize_state_transition(h, state, + LPCSCLI_OPERATIONAL); + + h->conn_req_state = LWSSSPC_ONW_CONN; break; case LWSSSCS_TIMEOUT: break; @@ -1440,8 +1476,8 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, goto hangup; #if defined(_DEBUG) - lwsl_info("%s: forwarding proxied state %s\n", - __func__, lws_ss_state_name(par->ctr)); + lwsl_sspc_info(h, "forwarding proxied state %s", + lws_ss_state_name(par->ctr)); #endif if (par->ctr == LWSSSCS_CREATING) { @@ -1467,15 +1503,17 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (cs == LWSSSCS_DISCONNECTED) h->ss_dangling_connected = 0; - if (lws_ss_check_next_state(&h->lc, + if (lws_ss_check_next_state_sspc(h, &h->prev_ss_state, cs)) return LWSSSSRET_DESTROY_ME; if (cs < LWSSSCS_USER_BASE) h->prev_ss_state = (uint8_t)cs; + h->h_in_svc = h; n = ssi->state(client_pss_to_userdata(pss), NULL, cs, par->flags); + h->h_in_svc = NULL; switch (n) { case LWSSSSRET_OK: break; @@ -1498,7 +1536,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, hangup: - lwsl_notice("%s: hangup\n", __func__); + lwsl_cx_notice(context, "hangup"); return LWSSSSRET_DISCONNECT_ME; } diff --git a/3rdparty/libwebsockets/lib/secure-streams/secure-streams.c b/3rdparty/libwebsockets/lib/secure-streams/secure-streams.c index 52a86be8..911f7132 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/secure-streams.c +++ b/3rdparty/libwebsockets/lib/secure-streams/secure-streams.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2021 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 @@ -67,6 +67,8 @@ static const char *state_names[] = { "LWSSSCS_TIMEOUT", "LWSSSCS_SERVER_TXN", "LWSSSCS_SERVER_UPGRADE", + "LWSSSCS_EVENT_WAIT_CANCELLED", + "LWSSSCS_UPSTREAM_LINK_RETRY", }; /* @@ -78,7 +80,7 @@ static const char *state_names[] = { * (because we will assert if we have bugs that do it) */ -static const uint32_t ss_state_txn_validity[] = { +const uint32_t ss_state_txn_validity[] = { /* if we was last in this state... we can legally go to these states */ @@ -86,6 +88,7 @@ static const uint32_t ss_state_txn_validity[] = { (1 << LWSSSCS_DESTROYING), [LWSSSCS_CREATING] = (1 << LWSSSCS_CONNECTING) | + (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_POLL) | (1 << LWSSSCS_SERVER_UPGRADE) | (1 << LWSSSCS_DESTROYING), @@ -125,6 +128,7 @@ static const uint32_t ss_state_txn_validity[] = { (1 << LWSSSCS_CONNECTING) | (1 << LWSSSCS_CONNECTED) | (1 << LWSSSCS_TIMEOUT) | + (1 << LWSSSCS_POLL) | (1 << LWSSSCS_DISCONNECTED) | /* proxy retry */ (1 << LWSSSCS_DESTROYING), @@ -132,6 +136,7 @@ static const uint32_t ss_state_txn_validity[] = { [LWSSSCS_POLL] = (1 << LWSSSCS_CONNECTING) | (1 << LWSSSCS_TIMEOUT) | + (1 << LWSSSCS_ALL_RETRIES_FAILED) | (1 << LWSSSCS_DESTROYING), [LWSSSCS_ALL_RETRIES_FAILED] = (1 << LWSSSCS_CONNECTING) | @@ -142,11 +147,16 @@ static const uint32_t ss_state_txn_validity[] = { (1 << LWSSSCS_TIMEOUT) | #if defined(LWS_ROLE_MQTT) (1 << LWSSSCS_QOS_ACK_REMOTE) | + (1 << LWSSSCS_QOS_NACK_REMOTE) | #endif (1 << LWSSSCS_DESTROYING), [LWSSSCS_QOS_NACK_REMOTE] = (1 << LWSSSCS_DISCONNECTED) | (1 << LWSSSCS_TIMEOUT) | +#if defined(LWS_ROLE_MQTT) + (1 << LWSSSCS_QOS_ACK_REMOTE) | + (1 << LWSSSCS_QOS_NACK_REMOTE) | +#endif (1 << LWSSSCS_DESTROYING), [LWSSSCS_QOS_ACK_LOCAL] = (1 << LWSSSCS_DISCONNECTED) | @@ -212,12 +222,14 @@ lws_conmon_ss_json(lws_ss_handle_t *h) buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "{\"peer\":\"%s\"," "\"dns_us\":%u," + "\"dns_disp\":%u," "\"sockconn_us\":%u," "\"tls_us\":%u," - "\"txn_resp_us:%u," + "\"txn_resp_us\":%u," "\"dns\":[", ads, (unsigned int)cm.ciu_dns, + (unsigned int)cm.dns_disposition, (unsigned int)cm.ciu_sockconn, (unsigned int)cm.ciu_tls, (unsigned int)cm.ciu_txn_resp); @@ -231,7 +243,19 @@ lws_conmon_ss_json(lws_ss_handle_t *h) ai = ai->ai_next; } - buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "]}"); + buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "]"); + + switch (cm.pcol) { + case LWSCONMON_PCOL_HTTP: + buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), + ",\"prot_specific\":{\"protocol\":\"http\",\"resp\":%u}", + (unsigned int)cm.protocol_specific.http.response); + break; + default: + break; + } + + buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "}"); /* * This destroys the DNS list in the lws_conmon that we took @@ -259,7 +283,7 @@ lws_conmon_ss_json(lws_ss_handle_t *h) */ if (h->info.rx) - ret = h->info.rx(h, (uint8_t *)h->conmon_json, + ret = h->info.rx(ss_to_userobj(h), (uint8_t *)h->conmon_json, (unsigned int)h->conmon_len, (int)(LWSSS_FLAG_SOM | LWSSS_FLAG_EOM | LWSSS_FLAG_PERF_JSON)); @@ -274,10 +298,13 @@ int lws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate, lws_ss_constate_t cs) { - if (cs >= LWSSSCS_USER_BASE) + if (cs >= LWSSSCS_USER_BASE || + cs == LWSSSCS_EVENT_WAIT_CANCELLED || + cs == LWSSSCS_SERVER_TXN || + cs == LWSSSCS_UPSTREAM_LINK_RETRY) /* - * we can't judge user states, leave the old state and - * just wave them through + * we can't judge user or transient states, leave the old state + * and just wave them through */ return 0; @@ -317,6 +344,55 @@ lws_ss_check_next_state(lws_lifecycle_t *lc, uint8_t *prevstate, return 1; } +int +lws_ss_check_next_state_ss(lws_ss_handle_t *ss, uint8_t *prevstate, + lws_ss_constate_t cs) +{ + if (cs >= LWSSSCS_USER_BASE || + cs == LWSSSCS_EVENT_WAIT_CANCELLED || + cs == LWSSSCS_UPSTREAM_LINK_RETRY) + /* + * we can't judge user or transient states, leave the old state + * and just wave them through + */ + return 0; + + if (cs >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { + /* we don't recognize this state as usable */ + lwsl_ss_err(ss, "bad new state %u", cs); + assert(0); + return 1; + } + + if (*prevstate >= LWS_ARRAY_SIZE(ss_state_txn_validity)) { + /* existing state is broken */ + lwsl_ss_err(ss, "bad existing state %u", + (unsigned int)*prevstate); + assert(0); + return 1; + } + + if (ss_state_txn_validity[*prevstate] & (1u << cs)) { + + lwsl_ss_notice(ss, "%s -> %s", + lws_ss_state_name((int)*prevstate), + lws_ss_state_name((int)cs)); + + /* this is explicitly allowed, update old state to new */ + *prevstate = (uint8_t)cs; + + return 0; + } + + lwsl_ss_err(ss, "transition from %s -> %s is illegal", + lws_ss_state_name((int)*prevstate), + lws_ss_state_name((int)cs)); + + assert(0); + + return 1; +} + const char * lws_ss_state_name(int state) { @@ -337,7 +413,7 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) if (!h) return LWSSSSRET_OK; - if (lws_ss_check_next_state(&h->lc, &h->prev_ss_state, cs)) + if (lws_ss_check_next_state_ss(h, &h->prev_ss_state, cs)) return LWSSSSRET_DESTROY_ME; if (cs == LWSSSCS_CONNECTED) @@ -356,9 +432,11 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) #endif if (h->info.state) { + h->h_in_svc = h; r = h->info.state(ss_to_userobj(h), NULL, cs, cs == LWSSSCS_UNREACHABLE && h->wsi && h->wsi->dns_reachability); + h->h_in_svc = NULL; #if defined(LWS_WITH_SERVER) if ((h->info.flags & LWSSSINFLAGS_ACCEPTED) && cs == LWSSSCS_DISCONNECTED) @@ -403,7 +481,7 @@ lws_ss_timeout_sul_check_cb(lws_sorted_usec_list_t *sul) /* we want to retry... */ h->seqstate = SSSEQ_DO_RETRY; - r = lws_ss_request_tx(h); + r = _lws_ss_request_tx(h); _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, NULL, &h); } @@ -423,7 +501,14 @@ lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, return LSTRX_FATAL_NAME_UNKNOWN; } + if (!hmd) + return LSTRX_FILLED_OUT; + replace = hmd->value__may_own_heap; + + if (!replace) + return LSTRX_DONE; + total = hmd->length; budget = olen - *pos; @@ -461,6 +546,8 @@ _lws_ss_backoff(lws_ss_handle_t *h, lws_usec_t us_override) uint64_t ms; char conceal; + lws_service_assert_loop_thread(h->context, h->tsi); + if (h->seqstate == SSSEQ_RECONNECT_WAIT) return LWSSSSRET_OK; @@ -520,6 +607,8 @@ lws_smd_ss_cb(void *opaque, lws_smd_class_t _class, lws_ss_handle_t *h = (lws_ss_handle_t *)opaque; uint8_t *p = (uint8_t *)buf - LWS_SMD_SS_RX_HEADER_LEN; + lws_service_assert_loop_thread(h->context, h->tsi); + /* * When configured with SS enabled, lws over-allocates * LWS_SMD_SS_RX_HEADER_LEN bytes behind the payload of the queued @@ -531,7 +620,7 @@ lws_smd_ss_cb(void *opaque, lws_smd_class_t _class, lws_ser_wu64be(p + 8, (uint64_t)timestamp); if (h->info.rx) - h->info.rx((void *)&h[1], p, len + LWS_SMD_SS_RX_HEADER_LEN, + h->info.rx((void *)(h + 1), p, len + LWS_SMD_SS_RX_HEADER_LEN, LWSSS_FLAG_SOM | LWSSS_FLAG_EOM); return 0; @@ -546,10 +635,12 @@ lws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) lws_smd_class_t _class; int flags = 0, n; + lws_service_assert_loop_thread(h->context, h->tsi); + if (!h->info.tx) return; - n = h->info.tx(&h[1], h->txord++, buf, &len, &flags); + n = h->info.tx((h + 1), h->txord++, buf, &len, &flags); if (n) /* nonzero return means don't want to send anything */ return; @@ -589,6 +680,8 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) lws_strexp_t exp; struct lws *wsi; + lws_service_assert_loop_thread(h->context, h->tsi); + if (!h->policy) { lwsl_err("%s: ss with no policy\n", __func__); @@ -721,7 +814,7 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) if (conn_if_sspc_onw) { i.ssl_connection |= LCCSCF_SECSTREAM_PROXY_ONWARD; - // i.opaque_user_data = conn_if_sspc_onw; + h->conn_if_sspc_onw = conn_if_sspc_onw; } @@ -779,7 +872,9 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) if (!h->cal_txn.mt) lws_metrics_caliper_bind(h->cal_txn, h->context->mth_ss_conn); - lws_metrics_tag_add(&h->cal_txn.mtags_owner, "ss", h->policy->streamtype); + if (h->policy->streamtype) + lws_metrics_tag_add(&h->cal_txn.mtags_owner, "ss", + h->policy->streamtype); #endif h->txn_ok = 0; @@ -789,7 +884,10 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) return r; } + h->inside_connect = 1; + h->pending_ret = LWSSSSRET_OK; wsi = lws_client_connect_via_info(&i); + h->inside_connect = 0; lws_free(path); if (!wsi) { /* @@ -797,13 +895,23 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) * having to go around the event loop */ - r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); - if (r) - return r; + if (h->pending_ret) + return h->pending_ret; - r = lws_ss_backoff(h); - if (r) - return r; + if (h->prev_ss_state != LWSSSCS_UNREACHABLE && + h->prev_ss_state != LWSSSCS_ALL_RETRIES_FAILED) { + /* + * blocking DNS failure can get to unreachable via + * CCE, and unreachable can get to ALL_RETRIES_FAILED + */ + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r) + return r; + + r = lws_ss_backoff(h); + if (r) + return r; + } return LWSSSSRET_TX_DONT_SEND; } @@ -814,7 +922,13 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) lws_ss_state_return_t lws_ss_client_connect(lws_ss_handle_t *h) { - return _lws_ss_client_connect(h, 0, 0); + lws_ss_state_return_t r; + + lws_service_assert_loop_thread(h->context, h->tsi); + + r = _lws_ss_client_connect(h, 0, 0); + + return r; } /* @@ -840,6 +954,8 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, char *p; int n; + lws_service_assert_loop_thread(context, tsi); + #if defined(LWS_WITH_SECURE_STREAMS_CPP) pol = ssi->policy; if (!pol) { @@ -868,7 +984,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, pol = lws_ss_policy_lookup(context, ssi->streamtype); #endif if (!pol) { - lwsl_info("%s: unknown stream type %s\n", __func__, + lwsl_cx_info(context, "unknown stream type %s", ssi->streamtype); return 1; } @@ -930,14 +1046,18 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, if (!h) return 2; + h->lc.log_cx = context->log_cx; + if (ssi->sss_protocol_version) - __lws_lc_tag(&context->lcg[LWSLCG_WSI_SS_CLIENT], &h->lc, "%s|v%u|%u", + __lws_lc_tag(context, &context->lcg[LWSLCG_WSI_SS_CLIENT], + &h->lc, "%s|v%u|%u", ssi->streamtype ? ssi->streamtype : "nostreamtype", (unsigned int)ssi->sss_protocol_version, (unsigned int)ssi->client_pid); else - __lws_lc_tag(&context->lcg[LWSLCG_WSI_SS_CLIENT], &h->lc, "%s", - ssi->streamtype ? ssi->streamtype : "nostreamtype"); + __lws_lc_tag(context, &context->lcg[LWSLCG_WSI_SS_CLIENT], + &h->lc, "%s", + ssi->streamtype ? ssi->streamtype : "nostreamtype"); #if defined(LWS_WITH_SYS_FAULT_INJECTION) h->fic.name = "ss"; @@ -958,7 +1078,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, h->proxy_onward = 1; /* start of overallocated area */ - p = (char *)&h[1]; + p = (char *)(h + 1); /* set the handle pointer in the user data struct */ v = (void **)(p + ssi->handle_offset); @@ -985,7 +1105,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, h->metadata = (lws_ss_metadata_t *)p; p += pol->metadata_count * sizeof(lws_ss_metadata_t); - lwsl_info("%s: %s metadata count %d\n", __func__, + lwsl_cx_info(context, "%s metadata count %d", pol->streamtype, pol->metadata_count); } @@ -1040,9 +1160,9 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, h->u.smd.smd_peer = lws_smd_register(context, h, 0, (lws_smd_class_t)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__); + if (!h->u.smd.smd_peer || lws_fi(&h->fic, "ss_create_smd")) + goto fail_creation; + lwsl_cx_info(context, "registered SS SMD"); } #endif @@ -1052,7 +1172,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, struct lws_context_creation_info i; struct lws_vhost *vho = NULL; - lwsl_info("%s: creating server\n", __func__); + lwsl_cx_info(context, "creating server"); if (h->policy->endpoint && h->policy->endpoint[0] == '!') { @@ -1065,10 +1185,10 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, vho = lws_get_vhost_by_name(context, &h->policy->endpoint[1]); - if (!vho) { + if (!vho || lws_fi(&h->fic, "ss_create_vhost")) { lwsl_err("%s: no vhost %s\n", __func__, &h->policy->endpoint[1]); - goto late_bail; + goto fail_creation; } goto extant; @@ -1090,9 +1210,10 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, i.options |= LWS_SERVER_OPTION_UNIX_SOCK; } - if (!ss_pcols[h->policy->protocol]) { + if (!ss_pcols[h->policy->protocol] || + lws_fi(&h->fic, "ss_create_pcol")) { lwsl_err("%s: unsupp protocol", __func__); - goto late_bail; + goto fail_creation; } *ppp++ = ss_pcols[h->policy->protocol]->protocol; @@ -1121,12 +1242,13 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, } #endif - - if (!lws_fi(&ssi->fic, "ss_srv_vh_fail")) + if (!lws_fi(&h->fic, "ss_srv_vh_fail")) vho = lws_create_vhost(context, &i); + else + vho = NULL; if (!vho) { - lwsl_err("%s: failed to create vh", __func__); - goto late_bail; + lwsl_cx_err(context, "failed to create vh"); + goto fail_creation; } extant: @@ -1138,11 +1260,12 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, vho->ss_handle = h; r = lws_ss_event_helper(h, LWSSSCS_CREATING); - lwsl_info("%s: CREATING returned status %d\n", __func__, (int)r); - if (r == LWSSSSRET_DESTROY_ME) - goto late_bail; + lwsl_cx_info(context, "CREATING returned status %d", (int)r); + if (r == LWSSSSRET_DESTROY_ME || + lws_fi(&h->fic, "ss_create_destroy_me")) + goto fail_creation; - lwsl_notice("%s: created server %s\n", __func__, + lwsl_cx_notice(context, "created server %s", h->policy->streamtype); return 0; @@ -1161,45 +1284,36 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, * to the ss connect code instead. */ - if (!lws_ss_policy_ref_trust_store(context, h->policy, 1 /* do the ref */)) { + if (!lws_ss_policy_ref_trust_store(context, h->policy, 1 /* do the ref */) || + lws_fi(&h->fic, "ss_create_no_ts")) { + lwsl_err("%s: unable to get vhost / trust store\n", __func__); + goto fail_creation; + } +#else +#if defined(LWS_WITH_SECURE_STREAMS_CPP) + if (!ssi->streamtype && + !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; + goto fail_creation; } #endif - - r = lws_ss_event_helper(h, LWSSSCS_CREATING); - lwsl_info("%s: CREATING returned status %d\n", __func__, (int)r); - if (r == LWSSSSRET_DESTROY_ME) { - -#if defined(LWS_WITH_SERVER) || defined(LWS_WITH_SYS_SMD) -late_bail: #endif - if (ppss) - *ppss = NULL; - - lws_pt_lock(pt, __func__); - lws_dll2_remove(&h->list); - lws_pt_unlock(pt); - - lws_fi_destroy(&h->fic); - __lws_lc_untag(&h->lc); - lws_free(h); - - return 1; - } + r = lws_ss_event_helper(h, LWSSSCS_CREATING); + lwsl_ss_info(h, "CREATING returned status %d", (int)r); + if (r == LWSSSSRET_DESTROY_ME || + lws_fi(&h->fic, "ss_create_destroy_me")) + goto fail_creation; #if defined(LWS_WITH_SYS_SMD) if (!(ssi->flags & LWSSSINFLAGS_PROXIED) && pol == &pol_smd) { - lws_ss_state_return_t r; - r = lws_ss_event_helper(h, LWSSSCS_CONNECTING); - if (r) - return r; + if (r || lws_fi(&h->fic, "ss_create_smd_1")) + goto fail_creation; r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); - if (r) - return r; + if (r || lws_fi(&h->fic, "ss_create_smd_2")) + goto fail_creation; } #endif @@ -1210,29 +1324,39 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, //(ssi->flags & LWSSSINFLAGS_PROXIED)) ) #endif - )) - switch (_lws_ss_client_connect(h, 0, 0)) { + )) { + r = _lws_ss_client_connect(h, 0, 0); + if (lws_fi(&h->fic, "ss_create_conn")) + r = LWSSSSRET_DESTROY_ME; + switch (r) { case LWSSSSRET_OK: break; case LWSSSSRET_TX_DONT_SEND: case LWSSSSRET_DISCONNECT_ME: - if (lws_ss_backoff(h) == LWSSSSRET_DESTROY_ME) { - lws_ss_destroy(&h); - return 1; - } + if (lws_ss_backoff(h) == LWSSSSRET_DESTROY_ME) + goto fail_creation; break; case LWSSSSRET_DESTROY_ME: - lws_ss_destroy(&h); - return 1; + goto fail_creation; } + } return 0; + +fail_creation: + + if (ppss) + *ppss = NULL; + + lws_ss_destroy(&h); + + return 1; } void * lws_ss_to_user_object(struct lws_ss_handle *h) { - return (void *)&h[1]; + return (void *)(h + 1); } void @@ -1248,6 +1372,15 @@ lws_ss_destroy(lws_ss_handle_t **ppss) if (!h) return; + lws_service_assert_loop_thread(h->context, h->tsi); + + if (h == h->h_in_svc) { + lwsl_err("%s: illegal destroy, return LWSSSSRET_DESTROY_ME instead\n", + __func__); + assert(0); + return; + } + if (h->destroying) { lwsl_info("%s: reentrant destroy\n", __func__); return; @@ -1300,14 +1433,23 @@ lws_ss_destroy(lws_ss_handle_t **ppss) */ #if defined(LWS_WITH_SERVER) - if (h->policy->flags & LWSSSPOLF_SERVER) + if (h->policy && (h->policy->flags & LWSSSPOLF_SERVER)) v = lws_get_vhost_by_name(h->context, h->policy->streamtype); #endif - if (h->ss_dangling_connected) - (void)lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + /* + * Since we also come here to unpick create, it's possible we failed + * the creation before issuing any states, even CREATING. We should + * only issue cleanup states on destroy if we previously got as far as + * issuing CREATING. + */ - (void)lws_ss_event_helper(h, LWSSSCS_DESTROYING); + if (h->prev_ss_state) { + if (h->ss_dangling_connected) + (void)lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + + (void)lws_ss_event_helper(h, LWSSSCS_DESTROYING); + } lws_pt_unlock(pt); @@ -1318,9 +1460,31 @@ lws_ss_destroy(lws_ss_handle_t **ppss) lwsl_info("%s: pmd %p\n", __func__, pmd); if (pmd->value_on_lws_heap) lws_free_set_NULL(pmd->value__may_own_heap); + pmd = pmd->next; } +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + { + + lws_ss_metadata_t *imd; + + pmd = h->instant_metadata; + + while (pmd) { + imd = pmd; + pmd = pmd->next; + + lwsl_info("%s: instant md %p\n", __func__, imd); + lws_free(imd); + } + h->instant_metadata = NULL; + + if (h->imd_ac) + lwsac_free(&h->imd_ac); + } +#endif + lws_sul_cancel(&h->sul); #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) @@ -1335,8 +1499,13 @@ lws_ss_destroy(lws_ss_handle_t **ppss) * to the ss connect code instead. */ - - lws_ss_policy_unref_trust_store(h->context, h->policy); + if (h->policy) + lws_ss_policy_unref_trust_store(h->context, h->policy); +#else +#if defined(LWS_WITH_SECURE_STREAMS_CPP) + if (!h->info.streamtype || !*(h->info.streamtype)) + lws_ss_policy_unref_trust_store(h->context, h->policy); +#endif #endif #if defined(LWS_WITH_SERVER) @@ -1366,7 +1535,10 @@ lws_ss_destroy(lws_ss_handle_t **ppss) lws_sul_debug_zombies(h->context, h, sizeof(*h) + h->info.user_alloc, __func__); - __lws_lc_untag(&h->lc); + __lws_lc_untag(h->context, &h->lc); + + lws_explicit_bzero((void *)h, sizeof(*h) + h->info.user_alloc); + lws_free_set_NULL(h); } @@ -1397,14 +1569,32 @@ lws_ss_request_tx(lws_ss_handle_t *h) { lws_ss_state_return_t r; + r = _lws_ss_request_tx(h); + + return r; +} + +lws_ss_state_return_t +_lws_ss_request_tx(lws_ss_handle_t *h) +{ + lws_ss_state_return_t r; + // lwsl_notice("%s: h %p, wsi %p\n", __func__, h, h->wsi); + lws_service_assert_loop_thread(h->context, h->tsi); + if (h->wsi) { lws_callback_on_writable(h->wsi); return LWSSSSRET_OK; } + if (!h->policy) { + /* avoid crash */ + lwsl_err("%s: null policy\n", __func__); + return LWSSSSRET_OK; + } + if (h->policy->flags & LWSSSPOLF_SERVER) return LWSSSSRET_OK; @@ -1433,9 +1623,12 @@ lws_ss_request_tx(lws_ss_handle_t *h) return LWSSSSRET_OK; h->seqstate = SSSEQ_TRY_CONNECT; - r = lws_ss_event_helper(h, LWSSSCS_POLL); - if (r) - return r; + if (h->prev_ss_state != LWSSSCS_POLL) { /* possible if we were created + * before we could action it */ + r = lws_ss_event_helper(h, LWSSSCS_POLL); + if (r) + return r; + } /* * Retries operate via lws_ss_request_tx(), explicitly ask for a @@ -1454,7 +1647,9 @@ lws_ss_request_tx(lws_ss_handle_t *h) lws_ss_state_return_t lws_ss_request_tx_len(lws_ss_handle_t *h, unsigned long len) { - if (h->wsi && + lws_service_assert_loop_thread(h->context, h->tsi); + + if (h->wsi && h->policy && (h->policy->protocol == LWSSSP_H1 || h->policy->protocol == LWSSSP_H2 || h->policy->protocol == LWSSSP_WS)) @@ -1481,6 +1676,17 @@ lws_ss_destroy_dll(struct lws_dll2 *d, void *user) return 0; } +int +lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user) +{ + lws_ss_handle_t *h = lws_container_of(d, lws_ss_handle_t, list); + + if (lws_ss_event_helper(h, LWSSSCS_EVENT_WAIT_CANCELLED)) + lwsl_warn("%s: cancel event ignores return\n", __func__); + + return 0; +} + struct lws_sequencer * lws_ss_get_sequencer(lws_ss_handle_t *h) { @@ -1507,6 +1713,8 @@ lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t bump) { const struct ss_pcols *ssp; + lws_service_assert_loop_thread(h->context, h->tsi); + ssp = ss_pcols[(int)h->policy->protocol]; if (h->wsi && ssp && ssp->tx_cr_add) @@ -1520,6 +1728,8 @@ lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h) { const struct ss_pcols *ssp; + lws_service_assert_loop_thread(h->context, h->tsi); + ssp = ss_pcols[(int)h->policy->protocol]; if (h->wsi && ssp && ssp->tx_cr_add) @@ -1544,10 +1754,8 @@ lws_ss_to_cb(lws_sorted_usec_list_t *sul) if (r != LWSSSSRET_DISCONNECT_ME && r != LWSSSSRET_DESTROY_ME) return; - if (!h->wsi) - return; - - lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); + if (h->wsi) + lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, h->wsi, &h); } @@ -1555,6 +1763,8 @@ lws_ss_to_cb(lws_sorted_usec_list_t *sul) void lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms) { + lws_service_assert_loop_thread(h->context, h->tsi); + if (!timeout_ms && !h->policy->timeout_ms) return; @@ -1566,6 +1776,7 @@ lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms) void lws_ss_cancel_timeout(struct lws_ss_handle *h) { + lws_service_assert_loop_thread(h->context, h->tsi); lws_sul_cancel(&h->sul_timeout); } @@ -1594,3 +1805,44 @@ lws_ss_tag(struct lws_ss_handle *h) return "[null ss]"; return lws_lc_tag(&h->lc); } + +struct lws_log_cx * +lwsl_ss_get_cx(struct lws_ss_handle *ss) +{ + if (!ss) + return NULL; + + return ss->lc.log_cx; +} + +void +lws_log_prepend_ss(struct lws_log_cx *cx, void *obj, char **p, char *e) +{ + struct lws_ss_handle *h = (struct lws_ss_handle *)obj; + + *p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ", + lws_ss_tag(h)); +} + +#if defined(_DEBUG) +void +lws_ss_assert_extant(struct lws_context *cx, int tsi, struct lws_ss_handle *h) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, pt->ss_owner.head) { + struct lws_ss_handle *h1 = lws_container_of(d, + struct lws_ss_handle, list); + + if (h == h1) + return; /* okay */ + + } lws_end_foreach_dll_safe(d, d1); + + /* + * The ss handle is not listed in the pt ss handle owner... + */ + + assert(0); +} +#endif diff --git a/3rdparty/libwebsockets/lib/secure-streams/system/auth-api.amazon.com/auth.c b/3rdparty/libwebsockets/lib/secure-streams/system/auth-api.amazon.com/auth.c index 5351cc00..af297d8b 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/system/auth-api.amazon.com/auth.c +++ b/3rdparty/libwebsockets/lib/secure-streams/system/auth-api.amazon.com/auth.c @@ -220,16 +220,15 @@ ss_api_amazon_auth_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - if (lws_ss_set_metadata(m->ss, "ctype", "application/json", 16)) - return LWSSSSRET_DESTROY_ME; + //if (lws_ss_set_metadata(m->ss, "ctype", "application/json", 16)) + // return LWSSSSRET_DESTROY_ME; /* fallthru */ case LWSSSCS_CONNECTING: 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; + return lws_ss_request_tx_len(m->ss, (unsigned long)s); case LWSSSCS_DISCONNECTED: /* diff --git a/3rdparty/libwebsockets/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c b/3rdparty/libwebsockets/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c index 04900f07..4de54bfc 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c +++ b/3rdparty/libwebsockets/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c @@ -41,14 +41,13 @@ ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, 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((int)state), + lwsl_ss_info(m->ss, "%s, ord 0x%x\n", lws_ss_state_name((int)state), (unsigned int)ack); switch (state) { case LWSSSCS_CREATING: lws_ss_start_timeout(m->ss, 3 * LWS_US_PER_SEC); - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); case LWSSSCS_QOS_ACK_REMOTE: lws_system_cpd_set(cx, LWS_CPD_INTERNET_OK); @@ -85,12 +84,12 @@ int lws_ss_sys_cpd(struct lws_context *cx) { if (cx->ss_cpd) { - lwsl_notice("%s: CPD already ongoing\n", __func__); + lwsl_cx_notice(cx, "CPD already ongoing"); return 0; } if (lws_ss_create(cx, 0, &ssi_cpd, cx, &cx->ss_cpd, NULL, NULL)) { - lwsl_info("%s: Create stream failed (policy?)\n", __func__); + lwsl_cx_info(cx, "Create stream failed (policy?)"); return 1; } diff --git a/3rdparty/libwebsockets/lib/secure-streams/system/fetch-policy/fetch-policy.c b/3rdparty/libwebsockets/lib/secure-streams/system/fetch-policy/fetch-policy.c index 237d2dbe..ee4b139a 100644 --- a/3rdparty/libwebsockets/lib/secure-streams/system/fetch-policy/fetch-policy.c +++ b/3rdparty/libwebsockets/lib/secure-streams/system/fetch-policy/fetch-policy.c @@ -102,8 +102,8 @@ ss_fetch_policy_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); + case LWSSSCS_CONNECTING: break; diff --git a/3rdparty/libwebsockets/lib/system/async-dns/async-dns-parse.c b/3rdparty/libwebsockets/lib/system/async-dns/async-dns-parse.c index cc9693ab..bdfe2050 100644 --- a/3rdparty/libwebsockets/lib/system/async-dns/async-dns-parse.c +++ b/3rdparty/libwebsockets/lib/system/async-dns/async-dns-parse.c @@ -81,7 +81,8 @@ lws_adns_parse_label(const uint8_t *pkt, int len, const uint8_t *ls, int budget, return -1; } - if (ll > budget) { + + if (ls + ll > ols + budget) { lwsl_notice("%s: label too long %d vs %d\n", __func__, ll, budget); return -1; @@ -603,7 +604,7 @@ lws_adns_parse_udp(lws_async_dns_t *dns, const uint8_t *pkt, size_t len) lwsl_info("%s: create cache entry for %s, %zu\n", __func__, nm, est - sizeof(lws_adns_cache_t)); - c = lws_malloc(est, "async-dns-entry"); + c = lws_malloc(est + 1, "async-dns-entry"); if (!c) { lwsl_err("%s: OOM %zu\n", __func__, est); goto fail_out; diff --git a/3rdparty/libwebsockets/lib/system/async-dns/async-dns.c b/3rdparty/libwebsockets/lib/system/async-dns/async-dns.c index c46c8f34..e722214f 100644 --- a/3rdparty/libwebsockets/lib/system/async-dns/async-dns.c +++ b/3rdparty/libwebsockets/lib/system/async-dns/async-dns.c @@ -92,8 +92,8 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) lws_dll2_remove(d); if (c && c->results) { - lwsl_debug("%s: q: %p, c: %p, refcount %d -> %d\n", - __func__, q, c, c->refcount, c->refcount + 1); + lwsl_wsi_debug(w, "q: %p, c: %p, refcount %d -> %d", + q, c, c->refcount, c->refcount + 1); c->refcount++; } lws_set_timeout(w, NO_PENDING_TIMEOUT, 0); @@ -111,8 +111,8 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) if (q->standalone_cb) { if (c && c->results) { - lwsl_debug("%s: q: %p, c: %p, refcount %d -> %d\n", - __func__, q, c, c->refcount, c->refcount + 1); + lwsl_wsi_debug(q->dns ? q->dns->wsi : NULL, "q: %p, c: %p, refcount %d -> %d", + q, c, c->refcount, c->refcount + 1); c->refcount++; } @@ -130,7 +130,7 @@ lws_async_dns_sul_cb_retry(struct lws_sorted_usec_list *sul) { lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, sul); - lwsl_info("%s\n", __func__); + lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, "in"); lws_adns_dump(q->dns); if (q->dns && q->dns->wsi) { @@ -177,7 +177,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) lws_retry_sul_schedule_retry_wsi(wsi, &q->sul, lws_async_dns_sul_cb_retry, &q->retry)) { /* we have reached the end of our concealed retries */ - lwsl_info("%s: failing query\n", __func__); + lwsl_wsi_info(wsi, "failing query"); /* * our policy is to force reloading the dns server info * if our connection ever timed out, in case it or the @@ -206,7 +206,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) q->asked = 1; #endif - lwsl_info("%s: %s, which %d\n", __func__, name, which); + lwsl_wsi_info(wsi, "%s, which %d", name, which); /* we hack b0 of the tid to be 0 = A, 1 = AAAA */ @@ -237,7 +237,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) if (p + 6 >= e) { assert(0); - lwsl_err("%s: name too big\n", __func__); + lwsl_wsi_err(wsi, "name too big"); goto qfail; } @@ -252,14 +252,14 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) m = lws_write(wsi, pkt + LWS_PRE, (unsigned int)n, 0); if (m != n) { - lwsl_notice("%s: dns write failed %d %d errno %d\n", __func__, + lwsl_wsi_notice(wsi, "dns write failed %d %d errno %d", m, n, errno); goto qfail; } #if defined(LWS_WITH_IPV6) if (!q->responded && q->sent[0] != q->sent[1]) { - lwsl_debug("%s: request writeable for ipv6\n", __func__); + lwsl_wsi_debug(wsi, "request writeable for ipv6"); lws_callback_on_writable(wsi); } #endif @@ -267,14 +267,14 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) return; qfail: - lwsl_warn("%s: failing query doing NULL completion\n", __func__); + lwsl_wsi_warn(wsi, "failing query doing NULL completion"); /* * in ipv6 case, we made a cache entry for the first response but * evidently the second response didn't come in time, purge the * incomplete cache entry */ if (q->firstcache) { - lwsl_debug("%s: destroy firstcache\n", __func__); + lwsl_wsi_debug(wsi, "destroy firstcache"); lws_adns_cache_destroy(q->firstcache); q->firstcache = NULL; } @@ -293,21 +293,21 @@ callback_async_dns(struct lws *wsi, enum lws_callback_reasons reason, /* callbacks related to raw socket descriptor */ case LWS_CALLBACK_RAW_ADOPT: - //lwsl_user("LWS_CALLBACK_RAW_ADOPT\n"); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_ADOPT"); break; case LWS_CALLBACK_RAW_CLOSE: - //lwsl_user("LWS_CALLBACK_RAW_CLOSE\n"); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_CLOSE"); break; case LWS_CALLBACK_RAW_RX: - //lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); - // lwsl_hexdump_level(LLL_NOTICE, in, len); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_RX (%d)", (int)len); + // lwsl_hexdump_wsi_notice(wsi, in, len); lws_adns_parse_udp(dns, in, len); break; case LWS_CALLBACK_RAW_WRITEABLE: - //lwsl_user("LWS_CALLBACK_RAW_WRITEABLE\n"); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_WRITEABLE"); lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, dns->waiting.head) { lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, @@ -327,7 +327,7 @@ callback_async_dns(struct lws *wsi, enum lws_callback_reasons reason, } struct lws_protocols lws_async_dns_protocol = { - "lws-async-dns", callback_async_dns, 0, 0 + "lws-async-dns", callback_async_dns, 0, 0, 0, NULL, 0 }; int @@ -341,7 +341,7 @@ lws_async_dns_init(struct lws_context *context) return 0; if (!context->vhost_list) { /* coverity... system vhost always present */ - lwsl_err("%s: no system vhost\n", __func__); + lwsl_cx_err(context, "no system vhost"); return 1; } @@ -354,7 +354,7 @@ lws_async_dns_init(struct lws_context *context) n = lws_plat_asyncdns_init(context, &dns->sa46); if (n < 0) { - lwsl_warn("%s: no valid dns server, retry\n", __func__); + lwsl_cx_warn(context, "no valid dns server, retry"); return 1; } @@ -373,7 +373,7 @@ lws_async_dns_init(struct lws_context *context) lws_async_dns_protocol.name, NULL, NULL, NULL, &retry_policy, "asyncdns"); if (!dns->wsi) { - lwsl_err("%s: foreign socket adoption failed\n", __func__); + lwsl_cx_err(context, "foreign socket adoption failed"); return 1; } @@ -398,7 +398,7 @@ lws_adns_get_cache(lws_async_dns_t *dns, const char *name) lws_dll2_get_head(&dns->cached)) { c = lws_container_of(d, lws_adns_cache_t, list); - // lwsl_notice("%s vs %s (inc %d)\n", name, c->name, c->incomplete); + // lwsl_wsi_notice(dns->wsi, "%s vs %s (inc %d)", name, c->name, c->incomplete); if (!c->incomplete && !strcasecmp(name, c->name)) { /* Keep sorted by LRU: move to the head */ @@ -421,15 +421,15 @@ lws_adns_dump(lws_async_dns_t *dns) if (!dns) return; - lwsl_info("%s: ADNS cache %u entries\n", __func__, + lwsl_wsi_info(dns->wsi, "ADNS cache %u entries", (unsigned int)dns->cached.count); lws_start_foreach_dll(struct lws_dll2 *, d, lws_dll2_get_head(&dns->cached)) { c = lws_container_of(d, lws_adns_cache_t, list); - lwsl_info("%s: cache: '%s', exp: %lldus, incomp %d, " - "fl 0x%x, refc %d, res %p\n", __func__, c->name, + lwsl_wsi_info(dns->wsi, "cache: '%s', exp: %lldus, incomp %d, " + "fl 0x%x, refc %d, res %p\n", c->name, (long long)(c->sul.us - lws_now_usecs()), c->incomplete, c->flags, c->refcount, c->results); } lws_end_foreach_dll(d); @@ -438,8 +438,8 @@ lws_adns_dump(lws_async_dns_t *dns) lws_dll2_get_head(&dns->waiting)) { lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); - lwsl_info("%s: q: '%s', sent %d, resp %d\n", - __func__, (const char *)&q[1], q->sent[0], + lwsl_wsi_info(dns->wsi, "q: '%s', sent %d, resp %d", + (const char *)&q[1], q->sent[0], q->responded); } lws_end_foreach_dll(d); } @@ -482,7 +482,7 @@ sul_cb_write(struct lws_sorted_usec_list *sul) * the query and everyone riding on it... */ - lwsl_info("%s: failing\n", __func__); + lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, "failing"); lws_adns_dump(q->dns); lws_async_dns_complete(q, NULL); /* no cache to relate to */ @@ -531,8 +531,8 @@ lws_async_dns_trim_cache(lws_async_dns_t *dns) c1 = lws_container_of(lws_dll2_get_tail(&dns->cached), lws_adns_cache_t, list); if (c1->refcount) - lwsl_info("%s: acache %p: refcount %d on purge\n", - __func__, c1, c1->refcount); + lwsl_wsi_info(dns->wsi, "acache %p: refcount %d on purge", + c1, c1->refcount); else lws_adns_cache_destroy(c1); } @@ -553,8 +553,8 @@ lws_async_dns_deinit(lws_async_dns_t *dns) lws_dll2_foreach_safe(&dns->cached, NULL, cache_clean); if (dns->wsi && !dns->dns_server_connected) { - lwsl_notice("%s: late free of incomplete dns wsi\n", __func__); - __lws_lc_untag(&dns->wsi->lc); + lwsl_wsi_notice(dns->wsi, "late free of incomplete dns wsi"); + __lws_lc_untag(dns->wsi->a.context, &dns->wsi->lc); #if defined(LWS_WITH_SYS_METRICS) lws_metrics_tags_destroy(&dns->wsi->cal_conn.mtags_owner); #endif @@ -634,7 +634,7 @@ lws_async_dns_get_new_tid(struct lws_context *context, lws_adns_q_t *q) } while (budget--); - lwsl_err("%s: unable to get unique tid\n", __func__); + lwsl_cx_err(context, "unable to get unique tid"); return -1; } @@ -660,12 +660,12 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, char *p; int m; - lwsl_info("%s: entry %s\n", __func__, name); + lwsl_cx_info(context, "entry %s", name); lws_adns_dump(dns); #if !defined(LWS_WITH_IPV6) if (qtype == LWS_ADNS_RECORD_AAAA) { - lwsl_err("%s: ipv6 not enabled\n", __func__); + lwsl_cx_err(context, "ipv6 not enabled"); goto failed; } #endif @@ -688,7 +688,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, if (wsi) { if (!lws_dll2_is_detached(&wsi->adns)) { - lwsl_err("%s: %s already bound to query %p\n", __func__, + lwsl_cx_err(context, "%s already bound to query %p", lws_wsi_tag(wsi), wsi->adns.owner); goto failed; } @@ -699,7 +699,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, c = lws_adns_get_cache(dns, name); if (c) { - lwsl_info("%s: %s: using cached, c->results %p\n", __func__, + lwsl_cx_info(context, "%s: using cached, c->results %p", name, c->results); m = c->results ? LADNS_RET_FOUND : LADNS_RET_FAILED; if (c->results) @@ -714,7 +714,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, return m; } else - lwsl_info("%s: %s uncached\n", __func__, name); + lwsl_cx_info(context, "%s uncached", name); #if defined(LWS_WITH_SYS_METRICS) lws_metric_event(context->mt_adns_cache, METRES_NOGO, 0); @@ -799,7 +799,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, if (!context->async_dns.dns_server_set && lws_async_dns_init(context)) { - lwsl_notice("%s: init failed\n", __func__); + lwsl_cx_notice(context, "init failed"); goto failed; } @@ -807,7 +807,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, q = lws_adns_get_query(dns, qtype, &dns->waiting, 0, name); if (q) { - lwsl_debug("%s: dns piggybacking: %d:%s\n", __func__, + lwsl_cx_debug(context, "dns piggybacking: %d:%s", qtype, name); if (wsi) lws_dll2_add_head(&wsi->adns, &q->wsi_adns); @@ -847,7 +847,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, q->qtype = (uint16_t)qtype; if (lws_async_dns_get_new_tid(context, q)) { - lwsl_err("%s: tid fail\n", __func__); + lwsl_cx_err(context, "tid fail"); goto failed; } @@ -890,13 +890,13 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, q->go_nogo = METRES_NOGO; /* caliper is reported in lws_adns_q_destroy */ - lwsl_info("%s: created new query: %s\n", __func__, name); + lwsl_cx_info(context, "created new query: %s", name); lws_adns_dump(dns); return LADNS_RET_CONTINUING; failed: - lwsl_notice("%s: failed\n", __func__); + lwsl_cx_notice(context, "failed"); if (!cb(wsi, NULL, NULL, LADNS_RET_FAILED, opaque)) return LADNS_RET_FAILED_WSI_CLOSED; diff --git a/3rdparty/libwebsockets/lib/system/dhcpclient/dhcpc4.c b/3rdparty/libwebsockets/lib/system/dhcpclient/dhcpc4.c index 33c8494f..d7f91997 100644 --- a/3rdparty/libwebsockets/lib/system/dhcpclient/dhcpc4.c +++ b/3rdparty/libwebsockets/lib/system/dhcpclient/dhcpc4.c @@ -282,7 +282,7 @@ callback_dhcpc4(struct lws *wsi, enum lws_callback_reasons reason, void *user, } struct lws_protocols lws_system_protocol_dhcpc4 = - { "lws-dhcp4client", callback_dhcpc4, 0, 128, }; + { "lws-dhcp4client", callback_dhcpc4, 0, 128, 0, NULL, 0 }; void lws_dhcpc4_retry_conn(struct lws_sorted_usec_list *sul) diff --git a/3rdparty/libwebsockets/lib/system/fault-injection/fault-injection.c b/3rdparty/libwebsockets/lib/system/fault-injection/fault-injection.c index 57082cc5..70c2a9f9 100644 --- a/3rdparty/libwebsockets/lib/system/fault-injection/fault-injection.c +++ b/3rdparty/libwebsockets/lib/system/fault-injection/fault-injection.c @@ -88,6 +88,30 @@ lws_fi(const lws_fi_ctx_t *fic, const char *name) return 1; } +int +lws_fi_range(const lws_fi_ctx_t *fic, const char *name, uint64_t *result) +{ + lws_fi_priv_t *pv; + uint64_t d; + + pv = lws_fi_lookup(fic, name); + + if (!pv) + return 1; + + if (pv->fi.type != LWSFI_RANGE) { + lwsl_err("%s: fault %s is not a 123..456 range\n", + __func__, name); + return 1; + } + + d = pv->fi.count - pv->fi.pre; + + *result = pv->fi.pre + (lws_xos((lws_xos_t *)&fic->xos) % d); + + return 0; +} + int _lws_fi_user_wsi_fi(struct lws *wsi, const char *name) { @@ -240,20 +264,30 @@ lws_fi_destroy(const lws_fi_ctx_t *fic) } lws_end_foreach_dll_safe(p, p1); } +/* + * We want to support these kinds of qualifier + * + * myfault true always + * myfault(10%) true 10% of the time + * myfault(....X X) true when X + * myfault2(20..3000) pick a number between 20 and 3000 + */ + enum { PARSE_NAME, PARSE_WHEN, PARSE_PC, - PARSE_ENDBR + PARSE_ENDBR, + PARSE_COMMA }; void lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers) { + int state = PARSE_NAME, m; struct lws_tokenize ts; lws_fi_t fi; char nm[64]; - int state = PARSE_NAME; /* * Go through the comma-separated list of faults @@ -284,17 +318,20 @@ lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers) memset(&fi, 0, sizeof(fi)); - lws_strnncpy(nm, ts.token, ts.token_len, sizeof(nm)); + lws_strnncpy(nm, ts.token, ts.token_len, + sizeof(nm)); fi.name = nm; fi.type = LWSFI_ALWAYS; - lwsl_notice("%s: name %.*s\n", __func__, (int)ts.token_len, ts.token); + lwsl_notice("%s: name %.*s\n", __func__, + (int)ts.token_len, ts.token); /* added later, potentially after (when) */ break; } if (state == PARSE_WHEN) { - /* it's either numeric or a pattern */ + /* it's either numeric (then % or ..num2), or + * .X pattern */ lwsl_notice("%s: when\n", __func__); @@ -306,7 +343,8 @@ lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers) * pattern... we need to allocate it */ fi.type = LWSFI_PATTERN_ALLOC; - pat = lws_zalloc((ts.token_len >> 3) + 1, __func__); + pat = lws_zalloc((ts.token_len >> 3) + 1, + __func__); if (!pat) return; fi.pattern = pat; @@ -315,16 +353,50 @@ lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers) for (n = 0; n < ts.token_len; n++) if (ts.token[n] == 'X') pat[n >> 3] = (uint8_t)( - pat[n >> 3] | (1 << (n & 7))); + pat[n >> 3] | + (1 << (n & 7))); + + lwsl_hexdump_notice(pat, + (ts.token_len >> 3) + 1); + + state = PARSE_ENDBR; + break; + } + + fi.pre = (uint64_t)atoll(ts.token); + + for (m = 0; m < (int)ts.token_len - 1; m++) + if (ts.token[m] < '0' || + ts.token[m] > '9') + break; - lwsl_hexdump_notice(pat, (ts.token_len >> 3) + 1); + /* + * We can understand num% or num..num + */ + if (m != (int)ts.token_len && + ts.token[m] == '.' && + ts.token[m + 1] == '.') { + fi.count = (uint64_t)atoll( + &ts.token[m + 2]); + fi.type = LWSFI_RANGE; state = PARSE_ENDBR; + + if (fi.pre >= fi.count) { + lwsl_err("%s: range must have " + "smaller first!\n", + __func__); + } + + lwsl_notice("%s: range %llx .." + "%llx\n", __func__, + (unsigned long long)fi.pre, + (unsigned long long)fi.count); break; } - fi.pre = (uint64_t)atoi(ts.token); - lwsl_notice("%s: prob %d%%\n", __func__, (int)fi.pre); + lwsl_notice("%s: prob %d%%\n", __func__, + (int)fi.pre); fi.type = LWSFI_PROBABILISTIC; state = PARSE_PC; break; diff --git a/3rdparty/libwebsockets/lib/system/metrics/metrics.c b/3rdparty/libwebsockets/lib/system/metrics/metrics.c index f906bcd4..1a978cca 100644 --- a/3rdparty/libwebsockets/lib/system/metrics/metrics.c +++ b/3rdparty/libwebsockets/lib/system/metrics/metrics.c @@ -68,7 +68,7 @@ lws_metrics_tag_add(lws_dll2_owner_t *owner, const char *name, const char *val) int lws_metrics_tag_wsi_add(struct lws *wsi, const char *name, const char *val) { - __lws_lc_tag(NULL, &wsi->lc, "|%s", val); + __lws_lc_tag(wsi->a.context, NULL, &wsi->lc, "|%s", val); return lws_metrics_tag_add(&wsi->cal_conn.mtags_owner, name, val); } @@ -77,15 +77,15 @@ lws_metrics_tag_wsi_add(struct lws *wsi, const char *name, const char *val) int lws_metrics_tag_ss_add(struct lws_ss_handle *ss, const char *name, const char *val) { - __lws_lc_tag(NULL, &ss->lc, "|%s", val); + __lws_lc_tag(ss->context, NULL, &ss->lc, "|%s", val); return lws_metrics_tag_add(&ss->cal_txn.mtags_owner, name, val); } -#if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) int lws_metrics_tag_sspc_add(struct lws_sspc_handle *sspc, const char *name, const char *val) { - __lws_lc_tag(NULL, &sspc->lc, "|%s", val); + __lws_lc_tag(sspc->context, NULL, &sspc->lc, "|%s", val); return lws_metrics_tag_add(&sspc->cal_txn.mtags_owner, name, val); } #endif @@ -263,7 +263,8 @@ lws_metrics_check_in_policy(const char *polstring, const char *name) ts.e = (int8_t)lws_tokenize(&ts); if (ts.e == LWS_TOKZE_TOKEN) { - if (!lws_strcmp_wildcard(ts.token, ts.token_len, name)) + if (!lws_strcmp_wildcard(ts.token, ts.token_len, name, + strlen(name))) /* yes, we are mentioned in this guy's policy */ return 0; } @@ -436,11 +437,13 @@ int lws_metric_destroy(lws_metric_t **pmt, int keep) { lws_metric_t *mt = *pmt; - lws_metric_pub_t *pub = lws_metrics_priv_to_pub(mt); + lws_metric_pub_t *pub; if (!mt) return 0; + pub = lws_metrics_priv_to_pub(mt); + lws_dll2_remove(&mt->list); if (keep) { @@ -606,11 +609,13 @@ lws_metrics_hist_bump_describe_wsi(struct lws *wsi, lws_metric_pub_t *pub, h->ssi.streamtype); } else if (wsi->client_proxy_onward) { - struct conn *conn = (struct conn *)wsi->a.opaque_user_data; + lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data; + struct conn *conn = h->conn_if_sspc_onw; if (conn && conn->ss) - p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "ss=\"%s\",", - conn->ss->info.streamtype); + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + "ss=\"%s\",", + conn->ss->info.streamtype); } else #endif if (wsi->for_ss) { diff --git a/3rdparty/libwebsockets/lib/system/ntpclient/ntpclient.c b/3rdparty/libwebsockets/lib/system/ntpclient/ntpclient.c index bc5a9615..b7ea660b 100644 --- a/3rdparty/libwebsockets/lib/system/ntpclient/ntpclient.c +++ b/3rdparty/libwebsockets/lib/system/ntpclient/ntpclient.c @@ -306,5 +306,5 @@ lws_ntpc_trigger(struct lws_context *ctx) } struct lws_protocols lws_system_protocol_ntpc = - { "lws-ntpclient", callback_ntpc, 0, 128, }; + { "lws-ntpclient", callback_ntpc, 0, 128, 0, NULL, 0 }; diff --git a/3rdparty/libwebsockets/lib/system/smd/private-lib-system-smd.h b/3rdparty/libwebsockets/lib/system/smd/private-lib-system-smd.h index e7916574..452ba15a 100644 --- a/3rdparty/libwebsockets/lib/system/smd/private-lib-system-smd.h +++ b/3rdparty/libwebsockets/lib/system/smd/private-lib-system-smd.h @@ -53,6 +53,7 @@ typedef struct lws_smd_peer { #endif lws_smd_notification_cb_t cb; /* LSMDT_ */ + struct lws_context *ctx; void *opaque; /* NULL, or next message we will handle */ @@ -91,5 +92,3 @@ lws_smd_msg_distribute(struct lws_context *ctx); int _lws_smd_destroy(struct lws_context *ctx); -int -_lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc); diff --git a/3rdparty/libwebsockets/lib/system/smd/smd.c b/3rdparty/libwebsockets/lib/system/smd/smd.c index 76307016..13ccadb4 100644 --- a/3rdparty/libwebsockets/lib/system/smd/smd.c +++ b/3rdparty/libwebsockets/lib/system/smd/smd.c @@ -43,8 +43,8 @@ lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len) /* 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); + lwsl_cx_info(ctx, "rejecting class 0x%x as no participant wants", + (unsigned int)_class); return NULL; } @@ -159,7 +159,7 @@ _lws_smd_class_mask_union(lws_smd_t *smd) /* Call with message lock held */ static void -_lws_smd_msg_destroy(lws_smd_t *smd, lws_smd_msg_t *msg) +_lws_smd_msg_destroy(struct lws_context *cx, lws_smd_t *smd, lws_smd_msg_t *msg) { /* * We think we gave the message to everyone and can destroy it. @@ -171,9 +171,8 @@ _lws_smd_msg_destroy(lws_smd_t *smd, lws_smd_msg_t *msg) lws_smd_peer_t *xpr = lws_container_of(p, lws_smd_peer_t, list); if (xpr->tail == msg) { - lwsl_err("%s: peer %p has msg %p " - "we are about to destroy as tail\n", - __func__, xpr, msg); + lwsl_cx_err(cx, "peer %p has msg %p " + "we are about to destroy as tail", xpr, msg); #if !defined(LWS_PLAT_FREERTOS) assert(0); #endif @@ -185,7 +184,7 @@ _lws_smd_msg_destroy(lws_smd_t *smd, lws_smd_msg_t *msg) * We have fully delivered the message now, it * can be unlinked and destroyed */ - lwsl_info("%s: destroy msg %p\n", __func__, msg); + lwsl_cx_info(cx, "destroy msg %p", msg); lws_dll2_remove(&msg->list); lws_free(msg); } @@ -201,19 +200,25 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg)); if (ctx->smd.owner_messages.count >= ctx->smd_queue_depth) { - lwsl_warn("%s: rejecting message on queue depth %d\n", - __func__, (int)ctx->smd.owner_messages.count); + lwsl_cx_warn(ctx, "rejecting message on queue depth %d", + (int)ctx->smd.owner_messages.count); /* reject the message due to max queue depth reached */ return 1; } - if (!ctx->smd.delivering) - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + if (!ctx->smd.delivering && + lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */ + return 1; /* For Coverity */ + + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */ + goto bail; msg->refcount = (uint16_t)_lws_smd_msg_assess_peers_interested( &ctx->smd, msg, exc); if (!msg->refcount) { /* possible, condsidering exc and no other participants */ + lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */ + lws_free(msg); if (!ctx->smd.delivering) lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ @@ -225,7 +230,6 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) /* let's add him on the queue... */ - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++++++++++ messages */ lws_dll2_add_tail(&msg->list, &ctx->smd.owner_messages); /* @@ -253,6 +257,7 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */ +bail: if (!ctx->smd.delivering) lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ @@ -347,7 +352,7 @@ lws_smd_ss_msg_printf(const char *tag, uint8_t *buf, size_t *len, *len = LWS_SMD_SS_RX_HEADER_LEN + (unsigned int)n; - lwsl_info("%s: %s send cl 0x%x, len %u\n", __func__, tag, _class, + lwsl_info("%s: %s send cl 0x%x, len %u\n", __func__, tag, (unsigned int)_class, (unsigned int)n); return 0; @@ -415,7 +420,7 @@ _lws_smd_ss_rx_forward(struct lws_context *ctx, const char *tag, } lwsl_info("%s: %s send cl 0x%x, len %u, ts %llu\n", __func__, - tag, _class, msg->length, + tag, (unsigned int)_class, msg->length, (unsigned long long)msg->timestamp); return 0; @@ -456,7 +461,8 @@ _lws_smd_peer_destroy(lws_smd_peer_t *pr) lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, owner_peers); - lws_mutex_lock(smd->lock_messages); /* +++++++++ messages */ + if (lws_mutex_lock(smd->lock_messages)) /* +++++++++ messages */ + return; /* For Coverity */ lws_dll2_remove(&pr->list); @@ -472,7 +478,7 @@ _lws_smd_peer_destroy(lws_smd_peer_t *pr) if (_lws_smd_msg_peer_interested_in_msg(pr, pr->tail)) { if (!--pr->tail->refcount) - _lws_smd_msg_destroy(smd, pr->tail); + _lws_smd_msg_destroy(pr->ctx, smd, pr->tail); } pr->tail = m1; @@ -528,8 +534,8 @@ _lws_smd_msg_deliver_peer(struct lws_context *ctx, lws_smd_peer_t *pr) msg = lws_container_of(pr->tail, lws_smd_msg_t, list); - lwsl_smd("%s: deliver cl 0x%x, len %d, refc %d, to peer %p\n", - __func__, (unsigned int)msg->_class, (int)msg->length, + lwsl_cx_info(ctx, "deliver cl 0x%x, len %d, refc %d, to peer %p", + (unsigned int)msg->_class, (int)msg->length, (int)msg->refcount, pr); pr->cb(pr->opaque, msg->_class, msg->timestamp, @@ -547,9 +553,11 @@ _lws_smd_msg_deliver_peer(struct lws_context *ctx, lws_smd_peer_t *pr) /* tail message has to actually be of interest to the peer */ assert(!pr->tail || (pr->tail->_class & pr->_class_filter)); - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++ messages */ + return 1; /* For Coverity */ + if (!--msg->refcount) - _lws_smd_msg_destroy(&ctx->smd, msg); + _lws_smd_msg_destroy(ctx, &ctx->smd, msg); lws_mutex_unlock(ctx->smd.lock_messages); /* messages ------- */ return !!pr->tail; @@ -574,7 +582,8 @@ lws_smd_msg_distribute(struct lws_context *ctx) do { more = 0; - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + if (lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */ + return 1; /* For Coverity */ lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, ctx->smd.owner_peers.head) { @@ -604,15 +613,23 @@ lws_smd_register(struct lws_context *ctx, void *opaque, int flags, pr->cb = cb; pr->opaque = opaque; pr->_class_filter = _class_filter; + pr->ctx = ctx; - if (!ctx->smd.delivering) - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + if (!ctx->smd.delivering && + lws_mutex_lock(ctx->smd.lock_peers)) { /* +++++++++++++++ peers */ + lws_free(pr); + return NULL; /* For Coverity */ + } /* * Let's lock the message list before adding this peer... because... */ - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_messages)) { /* +++++++++ messages */ + lws_free(pr); + pr = NULL; + goto bail1; /* For Coverity */ + } lws_dll2_add_tail(&pr->list, &ctx->smd.owner_peers); @@ -639,9 +656,10 @@ lws_smd_register(struct lws_context *ctx, void *opaque, int flags, lws_mutex_unlock(ctx->smd.lock_messages); /* messages ------- */ - lwsl_info("%s: peer %p (count %u) registered\n", __func__, pr, + lwsl_cx_info(ctx, "peer %p (count %u) registered", pr, (unsigned int)ctx->smd.owner_peers.count); +bail1: if (!ctx->smd.delivering) lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ @@ -653,10 +671,13 @@ 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 */ - lwsl_notice("%s: destroying peer %p\n", __func__, pr); + if (!smd->delivering && + lws_mutex_lock(smd->lock_peers)) /* +++++++++++++++++++ peers */ + return; /* For Coverity */ + lwsl_cx_notice(pr->ctx, "destroying peer %p", pr); _lws_smd_peer_destroy(pr); - lws_mutex_unlock(smd->lock_peers); /* ------------------------- peers */ + if (!smd->delivering) + lws_mutex_unlock(smd->lock_peers); /* ----------------- peers */ } int @@ -677,16 +698,18 @@ lws_smd_message_pending(struct lws_context *ctx) * have been hanging around too long */ - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++++++++++ peers */ - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++++++++++ peers */ + return 1; /* For Coverity */ + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */ + goto bail; /* For Coverity */ 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); if ((lws_now_usecs() - msg->timestamp) > ctx->smd_ttl_us) { - lwsl_warn("%s: timing out queued message %p\n", - __func__, msg); + lwsl_cx_warn(ctx, "timing out queued message %p", + msg); /* * We're forcibly yanking this guy, we can expect that @@ -711,7 +734,7 @@ lws_smd_message_pending(struct lws_context *ctx) * when destroying the message now. */ - _lws_smd_msg_destroy(&ctx->smd, msg); + _lws_smd_msg_destroy(ctx, &ctx->smd, msg); } } lws_end_foreach_dll_safe(p, p1); diff --git a/3rdparty/libwebsockets/lib/tls/CMakeLists.txt b/3rdparty/libwebsockets/lib/tls/CMakeLists.txt index 78e9dab1..fb9a75fe 100644 --- a/3rdparty/libwebsockets/lib/tls/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/tls/CMakeLists.txt @@ -69,6 +69,9 @@ endif() if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") + include (FindPkgConfig) + PKG_SEARCH_MODULE(LWS_WOLFSSL wolfssl) + 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.") @@ -117,15 +120,24 @@ if (LWS_WITH_SSL) list(APPEND SOURCES tls/tls-sessions.c) endif() + if (LWS_WITH_TLS_JIT_TRUST) + list(APPEND SOURCES + tls/tls-jit-trust.c) + endif() if (LWS_WITH_MBEDTLS) list(APPEND SOURCES tls/mbedtls/mbedtls-tls.c + tls/mbedtls/mbedtls-extensions.c tls/mbedtls/mbedtls-x509.c) if (LWS_WITH_NETWORK) list(APPEND SOURCES tls/mbedtls/mbedtls-ssl.c) endif() + if (LWS_WITH_TLS_JIT_TRUST) + list(APPEND SOURCES + tls/mbedtls/mbedtls-extensions.c) + endif() if (LWS_WITH_TLS_SESSIONS) list(APPEND SOURCES tls/mbedtls/mbedtls-session.c) @@ -208,12 +220,14 @@ if (LWS_WITH_SSL) if (LWS_WITH_CYASSL) foreach(inc ${WOLFSSL_INCLUDE_DIRS}) set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl) - include_directories("${inc}" "${inc}/cyassl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${inc}" "${inc}/cyassl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endforeach() else() foreach(inc ${WOLFSSL_INCLUDE_DIRS}) set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl) - include_directories("${inc}" "${inc}/wolfssl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${inc}" "${inc}/wolfssl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endforeach() endif() set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) @@ -231,7 +245,8 @@ if (LWS_WITH_SSL) message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") foreach(inc ${MBEDTLS_INCLUDE_DIRS}) - include_directories("${inc}" "${inc}/mbedtls") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${inc}" "${inc}/mbedtls") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endforeach() list(INSERT LIB_LIST 0 "${MBEDTLS_LIBRARIES}") @@ -242,6 +257,10 @@ if (LWS_WITH_SSL) endif() if (NOT chose_ssl) + if (OPENSSL_FOUND AND "${OPENSSL_INCLUDE_DIRS}" STREQUAL "") + set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") + endif() + if (NOT OPENSSL_FOUND AND NOT LWS_WITH_BORINGSSL) # TODO: Add support for STATIC also. if (NOT LWS_PLAT_FREERTOS) @@ -260,23 +279,24 @@ if (LWS_WITH_SSL) 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) + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${OPENSSL_INCLUDE_DIRS}") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) + endif() + 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(LWS_WITH_SSL) @@ -308,7 +328,7 @@ endif() 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_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) @@ -318,6 +338,12 @@ CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8 PARENT_ 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}EVP_aes_128_ofb LWS_HAVE_EVP_aes_128_ofb PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_ecb LWS_HAVE_EVP_aes_128_ecb PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_ctr LWS_HAVE_EVP_aes_128_ctr 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) @@ -335,14 +361,15 @@ if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) # 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) +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { OPENSSL_STACK *x = NULL; return !x; } \n" LWS_HAVE_OPENSSL_STACK) 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) +CHECK_SYMBOL_EXISTS(${VARIA}SSL_CTX_load_verify_file LWS_HAVE_SSL_CTX_load_verify_file PARENT_SCOPE) +CHECK_SYMBOL_EXISTS(${VARIA}SSL_CTX_load_verify_dir LWS_HAVE_SSL_CTX_load_verify_dir PARENT_SCOPE) endif() if (LWS_WITH_MBEDTLS) @@ -352,16 +379,38 @@ if (LWS_WITH_MBEDTLS) 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 + set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${MBEDTLS_INCLUDE_DIRS}) + + if (ESP_PLATFORM) + # we know we should have things + set(LWS_HAVE_MBEDTLS_AUTH_KEY_ID 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_conf_sni 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_set_hs_ca_chain 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_set_hs_own_cert 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_set_hs_authmode 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_net_init 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_x509_crt_parse_file 1 CACHE BOOL x) # some embedded may lack filesystem + set(LWS_HAVE_mbedtls_md_setup 1 CACHE BOOL x) # not on xenial 2.2 + set(LWS_HAVE_mbedtls_rsa_complete 1 CACHE BOOL x) # not on xenial 2.2 + set(LWS_HAVE_mbedtls_internal_aes_encrypt 1 CACHE BOOL x) # not on xenial 2.2 + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_set_verify; return !!v; }\n" LWS_HAVE_mbedtls_ssl_set_verify) + CHECK_SYMBOL_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_x509_crt_parse_file LWS_HAVE_mbedtls_x509_crt_parse_file PARENT_SCOPE) # some embedded may lack filesystem + 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 + endif() 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) diff --git a/3rdparty/libwebsockets/lib/tls/lws-gencrypto-common.c b/3rdparty/libwebsockets/lib/tls/lws-gencrypto-common.c index 917a5f12..7b32872d 100644 --- a/3rdparty/libwebsockets/lib/tls/lws-gencrypto-common.c +++ b/3rdparty/libwebsockets/lib/tls/lws-gencrypto-common.c @@ -460,7 +460,7 @@ static const struct lws_jose_jwe_alg lws_gencrypto_jwe_alg_map[] = { }, /* list terminator */ - { 0, 0, 0, 0, NULL, NULL } + { 0, 0, 0, 0, NULL, NULL, 0, 0, 0 } }; /* diff --git a/3rdparty/libwebsockets/lib/tls/lws-genec-common.c b/3rdparty/libwebsockets/lib/tls/lws-genec-common.c index 0ea3fb02..8b5d30b7 100644 --- a/3rdparty/libwebsockets/lib/tls/lws-genec-common.c +++ b/3rdparty/libwebsockets/lib/tls/lws-genec-common.c @@ -94,7 +94,7 @@ lws_genec_confirm_curve_allowed_by_tls_id(const char *allowed, int id, } } while (e > 0); - lwsl_err("%s: unsupported curve group nid %d\n", __func__, n); + lwsl_err("%s: unsupported curve group nid %d\n", __func__, id); return -1; } diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/CMakeLists.txt b/3rdparty/libwebsockets/lib/tls/mbedtls/CMakeLists.txt index adfbbbd7..e3415172 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/CMakeLists.txt +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/CMakeLists.txt @@ -105,13 +105,16 @@ include_directories(wrapper/include wrapper/include/internal) endif() if (LWS_MBEDTLS_LIBRARIES) set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) + set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES} PARENT_SCOPE) endif() if (LWS_MBEDTLS_INCLUDE_DIRS) set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) + set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS} PARENT_SCOPE) endif() set(USE_MBEDTLS 1 PARENT_SCOPE) if (DEFINED MBEDTLS_INCLUDE_DIRS) include_directories(${MBEDTLS_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${MBEDTLS_INCLUDE_DIRS}) endif() if (DEFINED MBEDTLS_LIBRARIES) diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genaes.c b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genaes.c index 0bde745c..f6a4ebd9 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genaes.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genaes.c @@ -131,10 +131,20 @@ lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, int lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen) { +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + size_t last_len = 0; + uint8_t last[16]; +#endif int n; if (ctx->mode == LWS_GAESM_GCM) { +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + n = mbedtls_gcm_finish(&ctx->u.ctx_gcm, last, sizeof(last), + &last_len, tag, tlen); +#else n = mbedtls_gcm_finish(&ctx->u.ctx_gcm, tag, tlen); +#endif + if (n) lwsl_notice("%s: mbedtls_gcm_finish: -0x%x\n", __func__, -n); @@ -388,9 +398,18 @@ lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, * additional data len: len */ +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + n = mbedtls_gcm_starts(&ctx->u.ctx_gcm, (int)ctx->op, + iv_or_nonce_ctr_or_data_unit_16, + *nc_or_iv_off); + if (!n) + n = mbedtls_gcm_update_ad(&ctx->u.ctx_gcm, + in, len); +#else n = mbedtls_gcm_starts(&ctx->u.ctx_gcm, (int)ctx->op, iv_or_nonce_ctr_or_data_unit_16, *nc_or_iv_off, in, len); +#endif if (n) { lwsl_notice("%s: mbedtls_gcm_starts: -0x%x\n", __func__, -n); @@ -400,7 +419,15 @@ lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, break; } +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + { + size_t al; + + n = mbedtls_gcm_update(&ctx->u.ctx_gcm, in, len, out, len, &al); + } +#else n = mbedtls_gcm_update(&ctx->u.ctx_gcm, len, in, out); +#endif if (n) { lwsl_notice("%s: mbedtls_gcm_update: -0x%x\n", __func__, -n); diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genec.c b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genec.c index ef95c316..bae22e9f 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genec.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genec.c @@ -27,6 +27,15 @@ #include "private-lib-core.h" #include "private-lib-tls-mbedtls.h" +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 +#define ECDHCTX(_c, _ins) _c->u.ctx_ecdh->MBEDTLS_PRIVATE(ctx).\ + MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(_ins) +#define ECDSACTX(_c, _ins) _c->u.ctx_ecdsa->MBEDTLS_PRIVATE(_ins) +#else +#define ECDHCTX(_c, _ins) _c->u.ctx_ecdh->_ins +#define ECDSACTX(_c, _ins) _c->u.ctx_ecdsa->_ins +#endif + const struct lws_ec_curves lws_ec_curves[] = { /* * These are the curves we are willing to use by default... @@ -44,7 +53,7 @@ const struct lws_ec_curves lws_ec_curves[] = { static int lws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, - struct lws_gencrypto_keyelem *el) + const struct lws_gencrypto_keyelem *el) { const struct lws_ec_curves *curve; mbedtls_ecp_keypair kp; @@ -76,7 +85,8 @@ lws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, return -23; mbedtls_ecp_keypair_init(&kp); - if (mbedtls_ecp_group_load(&kp.grp, (mbedtls_ecp_group_id)curve->tls_lib_nid)) + if (mbedtls_ecp_group_load(&kp.MBEDTLS_PRIVATE(grp), + (mbedtls_ecp_group_id)curve->tls_lib_nid)) goto bail1; ctx->has_private = !!el[LWS_GENCRYPTO_EC_KEYEL_D].len; @@ -84,21 +94,24 @@ lws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, /* d (the private key) is directly an mpi */ if (ctx->has_private && - mbedtls_mpi_read_binary(&kp.d, el[LWS_GENCRYPTO_EC_KEYEL_D].buf, + mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(d), + el[LWS_GENCRYPTO_EC_KEYEL_D].buf, el[LWS_GENCRYPTO_EC_KEYEL_D].len)) goto bail1; - mbedtls_ecp_set_zero(&kp.Q); + mbedtls_ecp_set_zero(&kp.MBEDTLS_PRIVATE(Q)); - if (mbedtls_mpi_read_binary(&kp.Q.X, el[LWS_GENCRYPTO_EC_KEYEL_X].buf, + if (mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), + el[LWS_GENCRYPTO_EC_KEYEL_X].buf, el[LWS_GENCRYPTO_EC_KEYEL_X].len)) goto bail1; - if (mbedtls_mpi_read_binary(&kp.Q.Y, el[LWS_GENCRYPTO_EC_KEYEL_Y].buf, + if (mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), + el[LWS_GENCRYPTO_EC_KEYEL_Y].buf, el[LWS_GENCRYPTO_EC_KEYEL_Y].len)) goto bail1; - mbedtls_mpi_lset(&kp.Q.Z, 1); + mbedtls_mpi_lset(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1); switch (ctx->genec_alg) { case LEGENEC_ECDH: @@ -107,11 +120,11 @@ lws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, goto bail1; /* verify the key is consistent with the claimed curve */ if (ctx->has_private && - mbedtls_ecp_check_privkey(&ctx->u.ctx_ecdh->grp, - &ctx->u.ctx_ecdh->d)) + mbedtls_ecp_check_privkey(&ECDHCTX(ctx, grp), + &ECDHCTX(ctx, d))) goto bail1; - if (mbedtls_ecp_check_pubkey(&ctx->u.ctx_ecdh->grp, - &ctx->u.ctx_ecdh->Q)) + if (mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), + &ECDHCTX(ctx, Q))) goto bail1; break; case LEGENEC_ECDSA: @@ -119,11 +132,11 @@ lws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, goto bail1; /* verify the key is consistent with the claimed curve */ if (ctx->has_private && - mbedtls_ecp_check_privkey(&ctx->u.ctx_ecdsa->grp, - &ctx->u.ctx_ecdsa->d)) + mbedtls_ecp_check_privkey(&ECDSACTX(ctx, grp), + &ECDSACTX(ctx, d))) goto bail1; - if (mbedtls_ecp_check_pubkey(&ctx->u.ctx_ecdsa->grp, - &ctx->u.ctx_ecdsa->Q)) + if (mbedtls_ecp_check_pubkey(&ECDSACTX(ctx, grp), + &ECDSACTX(ctx, Q))) goto bail1; break; default: @@ -189,7 +202,7 @@ lws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el, int lws_genecdsa_set_key(struct lws_genec_ctx *ctx, - struct lws_gencrypto_keyelem *el) + const struct lws_gencrypto_keyelem *el) { if (ctx->genec_alg != LEGENEC_ECDSA) return -1; @@ -265,9 +278,9 @@ lws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, * lws_gencrypto_keyelem, so they can be serialized, used in jwk etc */ - mpi[0] = &kp->Q.X; - mpi[1] = &kp->d; - mpi[2] = &kp->Q.Y; + mpi[0] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); + mpi[1] = &kp->MBEDTLS_PRIVATE(d); + mpi[2] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1; el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf = @@ -339,9 +352,9 @@ lws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name, kp = (mbedtls_ecp_keypair *)ctx->u.ctx_ecdsa; - mpi[0] = &kp->Q.X; - mpi[1] = &kp->d; - mpi[2] = &kp->Q.Y; + mpi[0] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); + mpi[1] = &kp->MBEDTLS_PRIVATE(d); + mpi[2] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1; el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf = @@ -412,8 +425,8 @@ lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, mbedtls_mpi_init(&mpi_r); mbedtls_mpi_init(&mpi_s); - n = mbedtls_ecdsa_sign(&ctx->u.ctx_ecdsa->grp, &mpi_r, &mpi_s, - &ctx->u.ctx_ecdsa->d, in, hlen, + n = mbedtls_ecdsa_sign(&ECDSACTX(ctx, grp), &mpi_r, &mpi_s, + &ECDSACTX(ctx, d), in, hlen, lws_gencrypto_mbedtls_rngf, ctx->context); if (n) { lwsl_err("%s: mbedtls_ecdsa_sign failed: -0x%x\n", @@ -476,8 +489,8 @@ lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, if (mbedtls_mpi_read_binary(&mpi_s, sig + keybytes, (unsigned int)keybytes)) goto bail1; - n = mbedtls_ecdsa_verify(&ctx->u.ctx_ecdsa->grp, in, hlen, - &ctx->u.ctx_ecdsa->Q, &mpi_r, &mpi_s); + n = mbedtls_ecdsa_verify(&ECDSACTX(ctx, grp), in, hlen, + &ECDSACTX(ctx, Q), &mpi_r, &mpi_s); mbedtls_mpi_free(&mpi_s); mbedtls_mpi_free(&mpi_r); @@ -504,8 +517,8 @@ lws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss, { int n; size_t st; - if (mbedtls_ecp_check_pubkey(&ctx->u.ctx_ecdh->grp, &ctx->u.ctx_ecdh->Q) || - mbedtls_ecp_check_pubkey(&ctx->u.ctx_ecdh->grp, &ctx->u.ctx_ecdh->Qp)) { + if (mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), &ECDHCTX(ctx, Q)) || + mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), &ECDHCTX(ctx, Qp))) { lwsl_err("%s: both sides must be set up\n", __func__); return -1; diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genhash.c b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genhash.c index 8f578a95..c9ea3669 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genhash.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genhash.c @@ -27,7 +27,22 @@ #include "libwebsockets.h" #include -#if (MBEDTLS_VERSION_NUMBER >= 0x02070000) +#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define mbedtls_md5_starts_ret mbedtls_md5_starts +#define mbedtls_md5_update_ret mbedtls_md5_update +#define mbedtls_md5_finish_ret mbedtls_md5_finish +#define mbedtls_sha1_finish_ret mbedtls_sha1_finish +#define mbedtls_sha1_update_ret mbedtls_sha1_update +#define mbedtls_sha1_starts_ret mbedtls_sha1_starts +#define mbedtls_sha256_starts_ret mbedtls_sha256_starts +#define mbedtls_sha256_update_ret mbedtls_sha256_update +#define mbedtls_sha256_finish_ret mbedtls_sha256_finish +#define mbedtls_sha512_starts_ret mbedtls_sha512_starts +#define mbedtls_sha512_update_ret mbedtls_sha512_update +#define mbedtls_sha512_finish_ret mbedtls_sha512_finish +#endif + +#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x02070000) /* * We have the _ret variants available, check the return codes on everything diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genrsa.c b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genrsa.c index e5d9ba0a..292b1ac1 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genrsa.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/lws-genrsa.c @@ -41,7 +41,8 @@ lws_genrsa_destroy_elements(struct lws_gencrypto_keyelem *el) static int mode_map[] = { MBEDTLS_RSA_PKCS_V15, MBEDTLS_RSA_PKCS_V21 }; int -lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, +lws_genrsa_create(struct lws_genrsa_ctx *ctx, + const struct lws_gencrypto_keyelem *el, struct lws_context *context, enum enum_genrsa_mode mode, enum lws_genhash_types oaep_hashid) { @@ -56,18 +57,29 @@ lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, if (mode >= LGRSAM_COUNT) return -1; +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 mbedtls_rsa_init(ctx->ctx, mode_map[mode], 0); +#else + mbedtls_rsa_init(ctx->ctx); + mbedtls_rsa_set_padding(ctx->ctx, mode_map[mode], 0); +#endif - ctx->ctx->padding = mode_map[mode]; - ctx->ctx->hash_id = (int)lws_gencrypto_mbedtls_hash_to_MD_TYPE(oaep_hashid); + ctx->ctx->MBEDTLS_PRIVATE(padding) = mode_map[mode]; + ctx->ctx->MBEDTLS_PRIVATE(hash_id) = + (int)lws_gencrypto_mbedtls_hash_to_MD_TYPE(oaep_hashid); { int n; mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT] = { - &ctx->ctx->E, &ctx->ctx->N, &ctx->ctx->D, &ctx->ctx->P, - &ctx->ctx->Q, &ctx->ctx->DP, &ctx->ctx->DQ, - &ctx->ctx->QP, + &ctx->ctx->MBEDTLS_PRIVATE(E), + &ctx->ctx->MBEDTLS_PRIVATE(N), + &ctx->ctx->MBEDTLS_PRIVATE(D), + &ctx->ctx->MBEDTLS_PRIVATE(P), + &ctx->ctx->MBEDTLS_PRIVATE(Q), + &ctx->ctx->MBEDTLS_PRIVATE(DP), + &ctx->ctx->MBEDTLS_PRIVATE(DQ), + &ctx->ctx->MBEDTLS_PRIVATE(QP), }; for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++) @@ -100,7 +112,7 @@ lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, } } - ctx->ctx->len = el[LWS_GENCRYPTO_RSA_KEYEL_N].len; + ctx->ctx->MBEDTLS_PRIVATE(len) = el[LWS_GENCRYPTO_RSA_KEYEL_N].len; return 0; } @@ -132,7 +144,12 @@ lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx, if (mode >= LGRSAM_COUNT) return -1; +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 mbedtls_rsa_init(ctx->ctx, mode_map[mode], 0); +#else + mbedtls_rsa_init(ctx->ctx); + mbedtls_rsa_set_padding(ctx->ctx, mode_map[mode], 0); +#endif n = mbedtls_rsa_gen_key(ctx->ctx, _rngf, context, (unsigned int)bits, 65537); if (n) { @@ -142,13 +159,18 @@ lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx, { mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT] = { - &ctx->ctx->E, &ctx->ctx->N, &ctx->ctx->D, &ctx->ctx->P, - &ctx->ctx->Q, &ctx->ctx->DP, &ctx->ctx->DQ, - &ctx->ctx->QP, + &ctx->ctx->MBEDTLS_PRIVATE(E), + &ctx->ctx->MBEDTLS_PRIVATE(N), + &ctx->ctx->MBEDTLS_PRIVATE(D), + &ctx->ctx->MBEDTLS_PRIVATE(P), + &ctx->ctx->MBEDTLS_PRIVATE(Q), + &ctx->ctx->MBEDTLS_PRIVATE(DP), + &ctx->ctx->MBEDTLS_PRIVATE(DQ), + &ctx->ctx->MBEDTLS_PRIVATE(QP), }; for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++) - if (mbedtls_mpi_size(mpi[n])) { + if (mpi[n] && mbedtls_mpi_size(mpi[n])) { el[n].buf = lws_malloc( mbedtls_mpi_size(mpi[n]), "genrsakey"); if (!el[n].buf) @@ -179,7 +201,7 @@ lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, size_t olen = 0; int n; - ctx->ctx->len = in_len; + ctx->ctx->MBEDTLS_PRIVATE(len) = in_len; #if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); @@ -189,14 +211,18 @@ lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, case LGRSAM_PKCS1_1_5: n = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PUBLIC, +#endif &olen, in, out, out_max); break; case LGRSAM_PKCS1_OAEP_PSS: n = mbedtls_rsa_rsaes_oaep_decrypt(ctx->ctx, _rngf, ctx->context, - MBEDTLS_RSA_PUBLIC, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 + MBEDTLS_RSA_PUBLIC, +#endif NULL, 0, &olen, in, out, out_max); break; @@ -219,7 +245,7 @@ lws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, size_t olen = 0; int n; - ctx->ctx->len = in_len; + ctx->ctx->MBEDTLS_PRIVATE(len) = in_len; #if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); @@ -229,14 +255,18 @@ lws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, case LGRSAM_PKCS1_1_5: n = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PRIVATE, +#endif &olen, in, out, out_max); break; case LGRSAM_PKCS1_OAEP_PSS: n = mbedtls_rsa_rsaes_oaep_decrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PRIVATE, +#endif NULL, 0, &olen, in, out, out_max); break; @@ -266,13 +296,17 @@ lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, case LGRSAM_PKCS1_1_5: n = mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PUBLIC, +#endif in_len, in, out); break; case LGRSAM_PKCS1_OAEP_PSS: n = mbedtls_rsa_rsaes_oaep_encrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PUBLIC, +#endif NULL, 0, in_len, in, out); break; @@ -286,7 +320,7 @@ lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, return -1; } - return (int)mbedtls_mpi_size(&ctx->ctx->N); + return (int)mbedtls_mpi_size(&ctx->ctx->MBEDTLS_PRIVATE(N)); } int @@ -303,13 +337,17 @@ lws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, case LGRSAM_PKCS1_1_5: n = mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PRIVATE, +#endif in_len, in, out); break; case LGRSAM_PKCS1_OAEP_PSS: n = mbedtls_rsa_rsaes_oaep_encrypt(ctx->ctx, _rngf, ctx->context, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PRIVATE, +#endif NULL, 0, in_len, in, out); break; @@ -323,7 +361,7 @@ lws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, return -1; } - return (int)mbedtls_mpi_size(&ctx->ctx->N); + return (int)mbedtls_mpi_size(&ctx->ctx->MBEDTLS_PRIVATE(N)); } int @@ -342,20 +380,30 @@ lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in, switch(ctx->mode) { case LGRSAM_PKCS1_1_5: - n = mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx->ctx, NULL, NULL, + n = mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx->ctx, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 + NULL, NULL, MBEDTLS_RSA_PUBLIC, - (mbedtls_md_type_t)h, 0, in, sig); +#endif + (mbedtls_md_type_t)h, + (unsigned int)lws_genhash_size(hash_type), + in, sig); break; case LGRSAM_PKCS1_OAEP_PSS: - n = mbedtls_rsa_rsassa_pss_verify(ctx->ctx, NULL, NULL, + n = mbedtls_rsa_rsassa_pss_verify(ctx->ctx, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 + NULL, NULL, MBEDTLS_RSA_PUBLIC, - (mbedtls_md_type_t)h, 0, in, sig); +#endif + (mbedtls_md_type_t)h, + (unsigned int)lws_genhash_size(hash_type), + in, sig); break; default: return -1; } if (n < 0) { - lwsl_notice("%s: -0x%x\n", __func__, -n); + lwsl_notice("%s: (mode %d) -0x%x\n", __func__, ctx->mode, -n); return -1; } @@ -381,19 +429,31 @@ lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in, * The "sig" buffer must be as large as the size of ctx->N * (eg. 128 bytes if RSA-1024 is used). */ - if (sig_len < ctx->ctx->len) + if (sig_len < ctx->ctx->MBEDTLS_PRIVATE(len)) return -1; switch(ctx->mode) { case LGRSAM_PKCS1_1_5: - n = mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx->ctx, NULL, NULL, + n = mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx->ctx, + mbedtls_ctr_drbg_random, + &ctx->context->mcdc, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PRIVATE, - (mbedtls_md_type_t)h, 0, in, sig); +#endif + (mbedtls_md_type_t)h, + (unsigned int)lws_genhash_size(hash_type), + in, sig); break; case LGRSAM_PKCS1_OAEP_PSS: - n = mbedtls_rsa_rsassa_pss_sign(ctx->ctx, NULL, NULL, + n = mbedtls_rsa_rsassa_pss_sign(ctx->ctx, + mbedtls_ctr_drbg_random, + &ctx->context->mcdc, +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 MBEDTLS_RSA_PRIVATE, - (mbedtls_md_type_t)h, 0, in, sig); +#endif + (mbedtls_md_type_t)h, + (unsigned int)lws_genhash_size(hash_type), + in, sig); break; default: return -1; @@ -405,7 +465,7 @@ lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in, return -1; } - return (int)ctx->ctx->len; + return (int)ctx->ctx->MBEDTLS_PRIVATE(len); } int @@ -414,9 +474,14 @@ lws_genrsa_render_pkey_asn1(struct lws_genrsa_ctx *ctx, int _private, { uint8_t *p = pkey_asn1, *totlen, *end = pkey_asn1 + pkey_asn1_len - 1; mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT] = { - &ctx->ctx->N, &ctx->ctx->E, &ctx->ctx->D, &ctx->ctx->P, - &ctx->ctx->Q, &ctx->ctx->DP, &ctx->ctx->DQ, - &ctx->ctx->QP, + &ctx->ctx->MBEDTLS_PRIVATE(N), + &ctx->ctx->MBEDTLS_PRIVATE(E), + &ctx->ctx->MBEDTLS_PRIVATE(D), + &ctx->ctx->MBEDTLS_PRIVATE(P), + &ctx->ctx->MBEDTLS_PRIVATE(Q), + &ctx->ctx->MBEDTLS_PRIVATE(DP), + &ctx->ctx->MBEDTLS_PRIVATE(DQ), + &ctx->ctx->MBEDTLS_PRIVATE(QP), }; int n; diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-client.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-client.c index 8f315f75..187e8605 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-client.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-client.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2020 Andy Green + * Copyright (C) 2010 - 2021 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 @@ -25,18 +25,56 @@ #include "private-lib-core.h" #include "private-lib-tls-mbedtls.h" +#if defined(LWS_WITH_TLS_JIT_TRUST) + +/* + * We get called for each peer certificate that was provided in turn. + * + * Our job is just to collect the AKID and SKIDs into ssl->kid_chain, and walk + * later at verification result time if it failed. + * + * None of these should be trusted, even if a misconfigured server sends us + * his root CA. + */ + static int -OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) +lws_mbedtls_client_verify_callback(SSL *ssl, mbedtls_x509_crt *x509) { + union lws_tls_cert_info_results ci; + + /* we reached the max we can hold? */ + + if (ssl->kid_chain.count == LWS_ARRAY_SIZE(ssl->kid_chain.akid)) + return 0; + + /* if not, stash the SKID and AKID into the next kid slot */ + + if (!lws_tls_mbedtls_cert_info(x509, LWS_TLS_CERT_INFO_SUBJECT_KEY_ID, + &ci, 0)) + lws_tls_kid_copy(&ci, + &ssl->kid_chain.skid[ssl->kid_chain.count]); + + if (!lws_tls_mbedtls_cert_info(x509, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID, + &ci, 0)) + lws_tls_kid_copy(&ci, + &ssl->kid_chain.akid[ssl->kid_chain.count]); + + ssl->kid_chain.count++; + + // lwsl_notice("%s: %u\n", __func__, ssl->kid_chain.count); + return 0; } +#endif + int lws_ssl_client_bio_create(struct lws *wsi) { char hostname[128], *p; const char *alpn_comma = wsi->a.context->tls.alpn_default; struct alpn_ctx protos; + int fl = SSL_VERIFY_PEER; if (wsi->stash) lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname)); @@ -80,36 +118,53 @@ lws_ssl_client_bio_create(struct lws *wsi) /* Enable automatic hostname checks */ // X509_VERIFY_PARAM_set_hostflags(param, // X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); - X509_VERIFY_PARAM_set1_host(param, hostname, 0); + lwsl_info("%s: setting hostname %s\n", __func__, hostname); + if (X509_VERIFY_PARAM_set1_host(param, hostname, 0) != 1) + return -1; } 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)); - alpn_comma = wsi->stash->cis[CIS_ALPN]; + lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], + sizeof(hostname)); + if (wsi->stash->cis[CIS_ALPN]) + alpn_comma = wsi->stash->cis[CIS_ALPN]; } else { if (lws_hdr_copy(wsi, hostname, sizeof(hostname), _WSI_TOKEN_CLIENT_ALPN) > 0) alpn_comma = hostname; } - lwsl_info("%s: %s: client conn sending ALPN list '%s'\n", - __func__, lws_wsi_tag(wsi), alpn_comma); - protos.len = (uint8_t)lws_alpn_comma_to_openssl(alpn_comma, protos.data, sizeof(protos.data) - 1); + lwsl_info("%s: %s: client conn sending ALPN list '%s' (protos.len %d)\n", + __func__, lws_wsi_tag(wsi), alpn_comma, protos.len); + /* with mbedtls, protos is not pointed to after exit from this call */ SSL_set_alpn_select_cb(wsi->tls.ssl, &protos); + if (wsi->flags & LCCSCF_ALLOW_SELFSIGNED) { + lwsl_notice("%s: allowing selfsigned\n", __func__); + fl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + } + + if (wsi->flags & LCCSCF_ALLOW_INSECURE) + fl = SSL_VERIFY_NONE; + /* * use server name indication (SNI), if supported, * when establishing connection */ +#if defined(LWS_WITH_TLS_JIT_TRUST) SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER, - OpenSSL_client_verify_callback); + lws_mbedtls_client_verify_callback); + (void)fl; +#else + SSL_set_verify(wsi->tls.ssl, fl, NULL); +#endif SSL_set_fd(wsi->tls.ssl, (int)wsi->desc.sockfd); @@ -195,16 +250,13 @@ enum lws_ssl_capable_status lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) { int m, n = SSL_connect(wsi->tls.ssl), en; - const unsigned char *prot; - unsigned int len; if (n == 1) { - SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len); - lws_role_call_alpn_negotiated(wsi, (const char *)prot); + lws_tls_server_conn_alpn(wsi); #if defined(LWS_WITH_TLS_SESSIONS) lws_tls_session_new_mbedtls(wsi); #endif - lwsl_info("client connect OK\n"); + lwsl_info("%s: client connect OK\n", __func__); return LWS_SSL_CAPABLE_DONE; } @@ -220,7 +272,8 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE; - if (m == SSL_ERROR_SYSCALL && !en) + if (m == SSL_ERROR_SYSCALL && !en && n >= 0) /* otherwise we miss explicit failures and spin + * in hs state 17 until timeout... */ return LWS_SSL_CAPABLE_MORE_SERVICE; lws_snprintf(errbuf, elen, "mbedtls connect %d %d %d", n, m, en); @@ -294,6 +347,10 @@ lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len) return 0; } +#if defined(LWS_WITH_TLS_JIT_TRUST) + if (n == X509_V_ERR_INVALID_CA) + lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.ssl->kid_chain); +#endif lws_snprintf(ebuf, ebuf_len, "server's cert didn't look good, %s (use_ssl 0x%x) X509_V_ERR = %d: %s\n", type, (unsigned int)wsi->tls.use_ssl, n, @@ -340,7 +397,7 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } /* create context */ - vh->tls.ssl_client_ctx = SSL_CTX_new(method); + vh->tls.ssl_client_ctx = SSL_CTX_new(method, &vh->context->mcdc); if (!vh->tls.ssl_client_ctx) { error = (unsigned long)ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", @@ -363,7 +420,8 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, } vh->tls.x509_client_CA = d2i_X509(NULL, buf, (long)len); free(buf); - lwsl_info("Loading client CA for verification %s\n", ca_filepath); + + lwsl_info("Loading vh %s client CA for verification %s\n", vh->name, ca_filepath); #endif } else { vh->tls.x509_client_CA = d2i_X509(NULL, (uint8_t*)ca_mem, (long)ca_mem_len); @@ -400,9 +458,6 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, buf[amount++] = '\0'; - SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, - buf, (long)amount); - n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, (int)amount, buf); lws_free(buf); @@ -417,8 +472,6 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, #endif } else if (cert_mem && cert_mem_len) { /* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */ - SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, - cert_mem, (long)cert_mem_len - 1); n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, (int)cert_mem_len, cert_mem); if (n < 1) { @@ -431,6 +484,47 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, __func__, cert_mem_len); } + if (private_key_filepath) { +#if !defined(LWS_PLAT_OPTEE) + + uint8_t *buf; + lws_filepos_t amount; + + lwsl_notice("%s: doing private key filepath %s\n", __func__, + private_key_filepath); + if (alloc_file(vh->context, private_key_filepath, &buf, &amount)) + return 1; + + buf[amount++] = '\0'; + + n = SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, + buf, (long)amount); + + lws_free(buf); + if (n < 1) { + lwsl_err("problem %d getting private key '%s'\n", n, + private_key_filepath); + lws_tls_err_describe_clear(); + return 1; + } + + lwsl_notice("Loaded private key %s\n", private_key_filepath); +#endif + } else if (key_mem && key_mem_len) { + /* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */ + n = SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, + key_mem, (long)key_mem_len - 1); + + if (n < 1) { + lwsl_err("%s: (mbedtls) problem interpreting private key\n", + __func__); + lws_tls_err_describe_clear(); + return 1; + } + lwsl_info("%s: using mem private key %d\n", + __func__, key_mem_len); + + } return 0; } diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-extensions.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-extensions.c new file mode 100644 index 00000000..bf275eef --- /dev/null +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-extensions.c @@ -0,0 +1,512 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2022 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 additional apis that belong in mbedtls but do not yet exist there. + * Alternaives are provided for lws to use that understand additional standard + * v3 tls extensions. Error results are simplified to lws style. + * + * This file includes code taken from mbedtls and modified, and from an as of + * 2021-06-11 unaccepted-upstream patch for mbedtls contributed by Gábor Tóth + * . Gabor has graciously allowed use of his patch with more + * liberal terms but to not complicate matters I provide it here under the same + * Apache 2.0 terms as the mbedtls pieces. + * + * Those original pieces are licensed Apache-2.0 as follows + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "private-lib-core.h" +#include "private-lib-tls-mbedtls.h" +#include +#include + +/* + * This section from mbedtls oid.c + */ + +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +#define LWS_MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define LWS_MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ + +#define LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) + +#define LWS_MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define LWS_MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER + +#define LWS_MBEDTLS_X509_SAN_OTHER_NAME 0 +#define LWS_MBEDTLS_X509_SAN_RFC822_NAME 1 +#define LWS_MBEDTLS_X509_SAN_DNS_NAME 2 + +#define LWS_MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define LWS_MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +static const oid_x509_ext_t oid_x509_ext[] = { + { {ADD_LEN( LWS_MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + "id-ce-subjectKeyIdentifier", + "Subject Key Identifier" }, + LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, + }, + { {ADD_LEN( LWS_MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + "id-ce-authorityKeyIdentifier", + "Authority Key Identifier" }, + LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, + }, + { { NULL, 0, NULL, NULL }, 0 }, +}; + +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->MBEDTLS_PRIVATE(asn1) != NULL ) { \ + if( cur->MBEDTLS_PRIVATE(asn1_len) == oid->MBEDTLS_PRIVATE_V30_ONLY(len) && \ + memcmp( cur->MBEDTLS_PRIVATE(asn1), oid->MBEDTLS_PRIVATE_V30_ONLY(p), oid->MBEDTLS_PRIVATE_V30_ONLY(len) ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } + + +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if (!data) return 1; \ + *ATTR1 = data->ATTR1; \ + return 0; \ +} + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(lws_mbedtls_oid_get_x509_ext_type, + oid_x509_ext_t, x509_ext, int, ext_type) + +typedef struct lws_mbedtls_x509_san_other_name +{ + /** + * The type_id is an OID as deifned in RFC 5280. + * To check the value of the type id, you should use + * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. + */ + mbedtls_x509_buf type_id; /**< The type id. */ + union + { + /** + * From RFC 4108 section 5: + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + */ + struct + { + mbedtls_x509_buf oid; /**< The object identifier. */ + mbedtls_x509_buf val; /**< The named value. */ + } + hardware_module_name; + } + value; +} +lws_mbedtls_x509_san_other_name; + + +typedef struct lws_mbedtls_x509_subject_alternative_name +{ + int type; /**< The SAN type, value of LWS_MBEDTLS_X509_SAN_XXX. */ + union { + lws_mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */ + mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */ + } + san; /**< A union of the supported SAN types */ +} +lws_mbedtls_x509_subject_alternative_name; + +static int +x509_get_skid(uint8_t **p, const uint8_t *end, mbedtls_x509_buf *skid) +{ + int ret = 1; + size_t len = 0u; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (ret) + return ret; + + skid->MBEDTLS_PRIVATE_V30_ONLY(len) = len; + skid->MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OCTET_STRING; + skid->MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + *p += len; + + return *p != end; +} + +/* + * Names may have multiple allocated segments in a linked-list, when the mbedtls + * api mbedtls_x509_get_name() fails, it doesn't clean up any already-allocated + * segments, wrongly leaving it to the caller to handle. This helper takes care + * of the missing cleaning for allocation error path. + * + * name.next must be set to NULL by user code before calling ...get_name(..., + * &name), since not every error exit sets it and it will contain garbage if + * defined on stack as is usual. + */ + +static void +lws_x509_clean_name(mbedtls_x509_name *name) +{ + mbedtls_x509_name *n1; + + if (!name) + return; + + n1 = name->MBEDTLS_PRIVATE_V30_ONLY(next); + + while (n1) { + name = n1->MBEDTLS_PRIVATE_V30_ONLY(next); + free(n1); + n1 = name; + } +} + +static int +lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf, + lws_mbedtls_x509_subject_alternative_name *name) +{ + // mbedtls_x509_name_other_name other_name; + uint8_t *bufferPointer, **p, *end; + mbedtls_x509_name rfc822Name; + int ret; + + switch (name_buf->MBEDTLS_PRIVATE_V30_ONLY(tag) & + (LWS_MBEDTLS_ASN1_TAG_CLASS_MASK | + LWS_MBEDTLS_ASN1_TAG_VALUE_MASK)) { + +#if 0 + case MBEDTLS_ASN1_CONTEXT_SPECIFIC | LWS_MBEDTLS_X509_SAN_OTHER_NAME: + ret = x509_get_other_name( name_buf, &other_name ); + if (ret) + return ret; + + memset(name, 0, sizeof(*name)); + name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME; + memcpy(&name->name.other_name, &other_name, sizeof(other_name)); + return 0; +#endif + case MBEDTLS_ASN1_SEQUENCE | LWS_MBEDTLS_X509_SAN_RFC822_NAME: + + bufferPointer = name_buf->MBEDTLS_PRIVATE_V30_ONLY(p); + p = &bufferPointer; + end = name_buf->MBEDTLS_PRIVATE_V30_ONLY(p) + + name_buf->MBEDTLS_PRIVATE_V30_ONLY(len); + + /* The leading ASN1 tag and length has been processed. + * Stepping back with 2 bytes, because mbedtls_x509_get_name + * expects the beginning of the SET tag */ + *p = *p - 2; + + rfc822Name.MBEDTLS_PRIVATE_V30_ONLY(next) = NULL; + ret = mbedtls_x509_get_name( p, end, &rfc822Name ); + if (ret) { + lws_x509_clean_name(&rfc822Name); + return ret; + } + + memset(name, 0, sizeof(*name)); + name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME; + memcpy(&name->san.other_name, + &rfc822Name, sizeof(rfc822Name)); + return 0; + + case MBEDTLS_ASN1_CONTEXT_SPECIFIC | LWS_MBEDTLS_X509_SAN_DNS_NAME: + memset(name, 0, sizeof(*name)); + name->type = LWS_MBEDTLS_X509_SAN_DNS_NAME; + + memcpy(&name->san.unstructured_name, + name_buf, sizeof(*name_buf) ); + return 0; + + default: + return 1; + } + + return 1; +} + +static int +lws_x509_get_general_names(uint8_t **p, const uint8_t *end, + mbedtls_x509_sequence *name ) +{ + mbedtls_asn1_sequence *cur = name; + mbedtls_asn1_buf *buf; + size_t len, tag_len; + unsigned char tag; + int r; + + /* Get main sequence tag */ + r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (r) + return r; + + if (*p + len != end) + return 1; + + while (*p < end) { + lws_mbedtls_x509_subject_alternative_name dnb; + memset(&dnb, 0, sizeof(dnb)); + + tag = **p; + (*p)++; + + r = mbedtls_asn1_get_len(p, end, &tag_len); + if (r) + return r; + + /* Tag shall be CONTEXT_SPECIFIC or SET */ + if ((tag & LWS_MBEDTLS_ASN1_TAG_CLASS_MASK) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC && + (tag & (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) + return 1; + + /* + * Check that the name is structured correctly. + */ + r = lws_mbedtls_x509_parse_general_name( + &cur->MBEDTLS_PRIVATE_V30_ONLY(buf), &dnb); + /* + * In case the extension is malformed, return an error, + * and clear the allocated sequences. + */ + if (r && r != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { + mbedtls_x509_sequence *seq_cur = name->MBEDTLS_PRIVATE_V30_ONLY(next); + mbedtls_x509_sequence *seq_prv; + + while( seq_cur != NULL ) { + seq_prv = seq_cur; + seq_cur = seq_cur->MBEDTLS_PRIVATE_V30_ONLY(next); + lws_explicit_bzero(seq_prv, sizeof(*seq_cur)); + lws_free(seq_prv); + } + + name->MBEDTLS_PRIVATE_V30_ONLY(next) = NULL; + + return r; + } + + /* Allocate and assign next pointer */ + if (cur->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p)) { + if (cur->MBEDTLS_PRIVATE_V30_ONLY(next)) + return 1; + + cur->MBEDTLS_PRIVATE_V30_ONLY(next) = + lws_zalloc(sizeof(*cur), __func__); + + if (!cur->MBEDTLS_PRIVATE_V30_ONLY(next)) + return 1; + + cur = cur->MBEDTLS_PRIVATE_V30_ONLY(next); + } + + buf = &(cur->MBEDTLS_PRIVATE_V30_ONLY(buf)); + buf->MBEDTLS_PRIVATE_V30_ONLY(tag) = tag; + buf->MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + buf->MBEDTLS_PRIVATE_V30_ONLY(len) = tag_len; + + *p += buf->MBEDTLS_PRIVATE_V30_ONLY(len); + } + + /* Set final sequence entry's next pointer to NULL */ + cur->MBEDTLS_PRIVATE_V30_ONLY(next) = NULL; + + return *p != end; +} + +static int +x509_get_akid(uint8_t **p, uint8_t *end, lws_mbedtls_x509_authority *akid) +{ + size_t len = 0u; + int r; + + r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (r) + return r; + + r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (!r) { + akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(len) = len; + akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OCTET_STRING; + + *p += len; + } + + if (*p < end) { + /* Getting authorityCertIssuer using the required specific + * class tag [1] */ + r = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 1 ); + if (!r) { + /* Getting directoryName using the required specific + * class tag [4] */ + r = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 4); + if (r) + return(r); + + /* "end" also includes the CertSerialNumber field + * so "len" shall be used */ + r = lws_x509_get_general_names(p, (*p + len), + &akid->authorityCertIssuer); + } + } + + if (*p < end) { + r = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_INTEGER ); + if (r) + return r; + + akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(len) = len; + akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OCTET_STRING; + *p += len; + } + + return *p != end; +} + +/* + * Work around lack of this in mbedtls... we don't need to do sanity checks + * sanity checks because they will be done at x509 validation time + */ + +int +lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid, + lws_mbedtls_x509_authority *akid) +{ + uint8_t *p = crt->MBEDTLS_PRIVATE_V30_ONLY(v3_ext).MBEDTLS_PRIVATE_V30_ONLY(p), + *end_ext_data, *end_ext_octet; + const uint8_t *end = p + crt->MBEDTLS_PRIVATE_V30_ONLY(v3_ext).MBEDTLS_PRIVATE_V30_ONLY(len); + size_t len; + int r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (r) + return r; + + while (p < end) { + mbedtls_x509_buf extn_oid = { 0, 0, NULL }; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + r = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (r) + return r; + + end_ext_data = p + len; + + /* Get extension ID */ + r = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.MBEDTLS_PRIVATE_V30_ONLY(len), + MBEDTLS_ASN1_OID); + if (r) + return r; + + extn_oid.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OID; + extn_oid.MBEDTLS_PRIVATE_V30_ONLY(p) = p; + p += extn_oid.MBEDTLS_PRIVATE_V30_ONLY(len); + + /* Get optional critical */ + r = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical); + if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) + return r; + + /* Data should be octet string type */ + r = mbedtls_asn1_get_tag(&p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING); + if (r) + return r; + + end_ext_octet = p + len; + + if (end_ext_octet != end_ext_data) + return 1; + + r = lws_mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); + if (r) { + p = end_ext_octet; + continue; + } + + switch (ext_type) { + case LWS_MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER: + /* Parse subject key identifier */ + r = x509_get_skid(&p, end_ext_data, skid); + if (r) + return r; + break; + + case LWS_MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER: + /* Parse authority key identifier */ + r = x509_get_akid(&p, end_ext_octet, akid); + if (r) + return r; + break; + + default: + p = end_ext_octet; + } + } + + return 0; +} diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-server.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-server.c index f8bf0abb..ca703c5a 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-server.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-server.c @@ -38,15 +38,7 @@ lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) return 0; } - /* - * The wrapper has this messed-up mapping: - * - * else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) - * mode = MBEDTLS_SSL_VERIFY_OPTIONAL; - * - * ie the meaning is inverted. So where we should test for ! we don't - */ - if (lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) + if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) verify_options = SSL_VERIFY_FAIL_IF_NO_PEER_CERT; lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name, @@ -198,7 +190,7 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, lws_filepos_t flen; int n; - vhost->tls.ssl_ctx = SSL_CTX_new(method); /* create context */ + vhost->tls.ssl_ctx = SSL_CTX_new(method, &vhost->context->mcdc); /* create context */ if (!vhost->tls.ssl_ctx) { lwsl_err("problem creating ssl context\n"); return 1; @@ -279,7 +271,9 @@ int #endif lws_tls_server_abort_connection(struct lws *wsi) { - __lws_tls_shutdown(wsi); + if (wsi->tls.use_ssl) + __lws_tls_shutdown(wsi); + SSL_free(wsi->tls.ssl); return 0; diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-session.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-session.c index 1450e34f..a774ffb6 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-session.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-session.c @@ -110,6 +110,21 @@ lws_tls_reuse_session(struct lws *wsi) lws_context_unlock(wsi->a.context); /* } cx -------------- */ } +int +lws_tls_session_is_reused(struct lws *wsi) +{ +#if defined(LWS_WITH_CLIENT) + struct lws *nwsi = lws_get_network_wsi(wsi); + + if (!nwsi) + return 0; + + return nwsi->tls_session_reused; +#else + return 0; +#endif +} + static int lws_tls_session_destroy_dll(struct lws_dll2 *d, void *user) { @@ -204,9 +219,11 @@ lws_tls_session_new_mbedtls(struct lws *wsi) memset(ts, 0, sizeof(*ts)); memcpy(&ts[1], buf, nl + 1); - if (mbedtls_ssl_get_session(msc, &ts->session)) + if (mbedtls_ssl_get_session(msc, &ts->session)) { + lws_free(ts); /* no joy for whatever reason */ goto bail; + } lws_dll2_add_tail(&ts->list, &vh->tls_sessions); @@ -253,6 +270,28 @@ lws_tls_session_new_mbedtls(struct lws *wsi) return 0; } +#if defined(LWS_TLS_SYNTHESIZE_CB) + +/* + * On openssl, there is an async cb coming when the server issues the session + * information on the link, so we can pick it up and update the cache at the + * right time. + * + * On mbedtls and some version at least of borning ssl, this cb is either not + * part of the tls library apis or fails to arrive. + */ + +void +lws_sess_cache_synth_cb(lws_sorted_usec_list_t *sul) +{ + struct lws_lws_tls *tls = lws_container_of(sul, struct lws_lws_tls, + sul_cb_synth); + struct lws *wsi = lws_container_of(tls, struct lws, tls); + + lws_tls_session_new_mbedtls(wsi); +} +#endif + void lws_tls_session_cache(struct lws_vhost *vh, uint32_t ttl) { diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-ssl.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-ssl.c index 24048064..5fe92205 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-ssl.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-ssl.c @@ -75,6 +75,11 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) /* If the socket isn't connected anymore, bail out. */ goto do_err1; +#if defined(LWS_PLAT_FREERTOS) + if (errno == LWS_ECONNABORTED) + goto do_err1; +#endif + if (m == SSL_ERROR_ZERO_RETURN || m == SSL_ERROR_SYSCALL) goto do_err; @@ -85,8 +90,10 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) return LWS_SSL_CAPABLE_MORE_SERVICE; } if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { - lwsl_debug("%s: WANT_WRITE\n", __func__); + lwsl_info("%s: WANT_WRITE\n", __func__); lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); + wsi->tls_read_wanted_write = 1; + lws_callback_on_writable(wsi); return LWS_SSL_CAPABLE_MORE_SERVICE; } @@ -108,7 +115,7 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) * 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); + lwsl_hexdump_notice(buf, (size_t)n); #endif #if defined(LWS_WITH_SYS_METRICS) @@ -255,6 +262,15 @@ lws_ssl_close(struct lws *wsi) SSL_set_info_callback(wsi->tls.ssl, NULL); #endif +#if defined(LWS_TLS_SYNTHESIZE_CB) + lws_sul_cancel(&wsi->tls.sul_cb_synth); + /* + * ... check the session in case it did not live long enough to get + * the scheduled callback to sample it + */ + lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth); +#endif + n = SSL_get_fd(wsi->tls.ssl); if (!wsi->socket_is_permanently_unusable) SSL_shutdown(wsi->tls.ssl); @@ -262,7 +278,7 @@ lws_ssl_close(struct lws *wsi) SSL_free(wsi->tls.ssl); wsi->tls.ssl = NULL; - lws_tls_restrict_return(wsi->a.context); + lws_tls_restrict_return(wsi); return 1; /* handled */ } diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-tls.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-tls.c index 6da053d0..6ae4039a 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-tls.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-tls.c @@ -31,13 +31,14 @@ lws_tls_err_describe_clear(void) } int -lws_context_init_ssl_library(const struct lws_context_creation_info *info) +lws_context_init_ssl_library(struct lws_context *cx, + const struct lws_context_creation_info *info) { - lwsl_info(" Compiled with MbedTLS support\n"); + lwsl_info(" Compiled with MbedTLS support"); if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) lwsl_info(" SSL disabled: no " - "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n"); + "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT"); return 0; } diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-x509.c b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-x509.c index cead9755..8b0ccd3f 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-x509.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/mbedtls-x509.c @@ -49,17 +49,17 @@ lws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime) { struct tm t; - if (!xtime || !xtime->year || xtime->year < 0) + if (!xtime || !xtime->MBEDTLS_PRIVATE_V30_ONLY(year) || xtime->MBEDTLS_PRIVATE_V30_ONLY(year) < 0) return (time_t)(long long)-1; memset(&t, 0, sizeof(t)); - t.tm_year = xtime->year - 1900; - t.tm_mon = xtime->mon - 1; /* mbedtls months are 1+, tm are 0+ */ - t.tm_mday = xtime->day - 1; /* mbedtls days are 1+, tm are 0+ */ - t.tm_hour = xtime->hour; - t.tm_min = xtime->min; - t.tm_sec = xtime->sec; + t.tm_year = xtime->MBEDTLS_PRIVATE_V30_ONLY(year) - 1900; + t.tm_mon = xtime->MBEDTLS_PRIVATE_V30_ONLY(mon) - 1; /* mbedtls months are 1+, tm are 0+ */ + t.tm_mday = xtime->MBEDTLS_PRIVATE_V30_ONLY(day) - 1; /* mbedtls days are 1+, tm are 0+ */ + t.tm_hour = xtime->MBEDTLS_PRIVATE_V30_ONLY(hour); + t.tm_min = xtime->MBEDTLS_PRIVATE_V30_ONLY(min); + t.tm_sec = xtime->MBEDTLS_PRIVATE_V30_ONLY(sec); t.tm_isdst = -1; return mktime(&t); @@ -69,53 +69,65 @@ static int lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name, union lws_tls_cert_info_results *buf, size_t len) { + int r = -1; + + buf->ns.len = 0; + while (name) { - if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) { + /* + if (MBEDTLS_OID_CMP(type, &name->oid)) { name = name->next; continue; } - - if (len - 1 < name->val.len) - return -1; - - memcpy(&buf->ns.name[0], name->val.p, name->val.len); - buf->ns.name[name->val.len] = '\0'; - buf->ns.len = (int)name->val.len; - - return 0; +*/ + lws_strnncpy(&buf->ns.name[buf->ns.len], + (const char *)name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(p), + name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(len), + len - (size_t)buf->ns.len); + buf->ns.len = (int)strlen(buf->ns.name); + + r = 0; + name = name->MBEDTLS_PRIVATE_V30_ONLY(next); } - return -1; + return r; } -static int + +int lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, union lws_tls_cert_info_results *buf, size_t len) { + mbedtls_x509_buf skid; + lws_mbedtls_x509_authority akid; + if (!x509) return -1; + if (!len) + len = sizeof(buf->ns.name); + switch (type) { case LWS_TLS_CERT_INFO_VALIDITY_FROM: - buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_from); + buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_from)); if (buf->time == (time_t)(long long)-1) return -1; break; case LWS_TLS_CERT_INFO_VALIDITY_TO: - buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_to); + buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_to)); if (buf->time == (time_t)(long long)-1) return -1; break; case LWS_TLS_CERT_INFO_COMMON_NAME: - return lws_tls_mbedtls_get_x509_name(&x509->subject, buf, len); + return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(subject), buf, len); case LWS_TLS_CERT_INFO_ISSUER_NAME: - return lws_tls_mbedtls_get_x509_name(&x509->issuer, buf, len); + return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(issuer), buf, len); case LWS_TLS_CERT_INFO_USAGE: - buf->usage = x509->key_usage; + buf->usage = x509->MBEDTLS_PRIVATE(key_usage); break; case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY: @@ -123,16 +135,16 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, char *p = buf->ns.name; size_t r = len, u; - switch (mbedtls_pk_get_type(&x509->pk)) { + switch (mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))) { case MBEDTLS_PK_RSA: { - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->pk); + mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->MBEDTLS_PRIVATE_V30_ONLY(pk)); - if (mbedtls_mpi_write_string(&rsa->N, 16, p, r, &u)) + if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(N), 16, p, r, &u)) return -1; r -= u; p += u; - if (mbedtls_mpi_write_string(&rsa->E, 16, p, r, &u)) + if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(E), 16, p, r, &u)) return -1; p += u; @@ -141,17 +153,17 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, } case MBEDTLS_PK_ECKEY: { - mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->pk); + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->MBEDTLS_PRIVATE_V30_ONLY(pk)); - if (mbedtls_mpi_write_string(&ecp->Q.X, 16, p, r, &u)) + if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16, p, r, &u)) return -1; r -= u; p += u; - if (mbedtls_mpi_write_string(&ecp->Q.Y, 16, p, r, &u)) + if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16, p, r, &u)) return -1; r -= u; p += u; - if (mbedtls_mpi_write_string(&ecp->Q.Z, 16, p, r, &u)) + if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16, p, r, &u)) return -1; p += u; buf->ns.len = lws_ptr_diff(p, buf->ns.name); @@ -160,7 +172,7 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, default: lwsl_notice("%s: x509 has unsupported pubkey type %d\n", __func__, - mbedtls_pk_get_type(&x509->pk)); + mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))); return -1; } @@ -168,18 +180,92 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, } case LWS_TLS_CERT_INFO_DER_RAW: - buf->ns.len = (int)x509->raw.len; + buf->ns.len = (int)x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len); - if (len < x509->raw.len) + if (len < x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len)) /* * The buffer is too small and the attempt failed, but * the required object length is in buf->ns.len */ return -1; - memcpy(buf->ns.name, x509->raw.p, x509->raw.len); + memcpy(buf->ns.name, x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(p), + x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len)); + break; + + case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID: + + memset(&akid, 0, sizeof(akid)); + memset(&skid, 0, sizeof(skid)); + + lws_x509_get_crt_ext(x509, &skid, &akid); + if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) + return 1; + buf->ns.len = (int)akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(len); + if (!akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) || + len < (size_t)buf->ns.len) + return -1; + memcpy(buf->ns.name, akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); break; + case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: { + mbedtls_x509_sequence * ip; + + memset(&akid, 0, sizeof(akid)); + memset(&skid, 0, sizeof(skid)); + + lws_x509_get_crt_ext(x509, &skid, &akid); + + ip = &akid.authorityCertIssuer; + + buf->ns.len = 0; + + while (ip) { + if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING || + !ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p) || + ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) < 9 || + len < (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9u) + break; + + memcpy(buf->ns.name + buf->ns.len, ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p), + (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9); + buf->ns.len = buf->ns.len + (int)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9; + + ip = ip->MBEDTLS_PRIVATE_V30_ONLY(next); + } + break; + } + case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL: + + memset(&akid, 0, sizeof(akid)); + memset(&skid, 0, sizeof(skid)); + + lws_x509_get_crt_ext(x509, &skid, &akid); + + if (akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) + return 1; + buf->ns.len = (int)akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(len); + if (!akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) || + len < (size_t)buf->ns.len) + return -1; + memcpy(buf->ns.name, akid.authorityCertSerialNumber. + MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); + break; + + case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID: + + memset(&akid, 0, sizeof(akid)); + memset(&skid, 0, sizeof(skid)); + + lws_x509_get_crt_ext(x509, &skid, &akid); + + if (skid.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) + return 1; + buf->ns.len = (int)skid.MBEDTLS_PRIVATE_V30_ONLY(len); + if (len < (size_t)buf->ns.len) + return -1; + memcpy(buf->ns.name, skid.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); + break; default: return -1; } @@ -293,7 +379,8 @@ int lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, const char *curves, int rsa_min_bits) { - int kt = (int)mbedtls_pk_get_type(&x509->cert.pk), n, count = 0, ret = -1; + int kt = (int)mbedtls_pk_get_type(&x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)), + n, count = 0, ret = -1; mbedtls_rsa_context *rsactx; mbedtls_ecp_keypair *ecpctx; mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT]; @@ -304,31 +391,31 @@ lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, case MBEDTLS_PK_RSA: lwsl_notice("%s: RSA key\n", __func__); jwk->kty = LWS_GENCRYPTO_KTY_RSA; - rsactx = mbedtls_pk_rsa(x509->cert.pk); - - mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->E; - mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->N; - mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D; - mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P; - mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q; - mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->DP; - mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->DQ; - mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->QP; - - count = LWS_GENCRYPTO_RSA_KEYEL_COUNT; + rsactx = mbedtls_pk_rsa(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)); + + mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->MBEDTLS_PRIVATE(E); + mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->MBEDTLS_PRIVATE(N); + mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->MBEDTLS_PRIVATE(D); + mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->MBEDTLS_PRIVATE(P); + mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->MBEDTLS_PRIVATE(Q); + mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->MBEDTLS_PRIVATE(DP); + mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->MBEDTLS_PRIVATE(DQ); + mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->MBEDTLS_PRIVATE(QP); + + count = LWS_GENCRYPTO_RSA_KEYEL_QI + 1; n = LWS_GENCRYPTO_RSA_KEYEL_E; break; case MBEDTLS_PK_ECKEY: lwsl_notice("%s: EC key\n", __func__); jwk->kty = LWS_GENCRYPTO_KTY_EC; - ecpctx = mbedtls_pk_ec(x509->cert.pk); - mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->Q.X; - mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d; - mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->Q.Y; + ecpctx = mbedtls_pk_ec(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)); + mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); + mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d); + mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); if (lws_genec_confirm_curve_allowed_by_tls_id(curves, - (int)ecpctx->grp.id, jwk)) + (int)ecpctx->MBEDTLS_PRIVATE(grp).id, jwk)) /* already logged */ goto bail; @@ -363,8 +450,8 @@ lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, } int -lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, - const char *passphrase) +lws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk, + void *pem, size_t len, const char *passphrase) { mbedtls_rsa_context *rsactx; mbedtls_ecp_keypair *ecpctx; @@ -377,7 +464,11 @@ lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, n = 0; if (passphrase) n = (int)strlen(passphrase); - n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, (unsigned int)n); + n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, (unsigned int)n +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + , mbedtls_ctr_drbg_random, &cx->mcdc +#endif + ); if (n) { lwsl_err("%s: parse PEM key failed: -0x%x\n", __func__, -n); @@ -392,9 +483,9 @@ lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, goto bail; } rsactx = mbedtls_pk_rsa(pk); - mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D; - mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P; - mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q; + mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->MBEDTLS_PRIVATE(D); + mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->MBEDTLS_PRIVATE(P); + mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->MBEDTLS_PRIVATE(Q); n = LWS_GENCRYPTO_RSA_KEYEL_D; count = LWS_GENCRYPTO_RSA_KEYEL_Q + 1; break; @@ -404,7 +495,7 @@ lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, goto bail; } ecpctx = mbedtls_pk_ec(pk); - mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d; + mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d); n = LWS_GENCRYPTO_EC_KEYEL_D; count = n + 1; break; diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/private-lib-tls-mbedtls.h b/3rdparty/libwebsockets/lib/tls/mbedtls/private-lib-tls-mbedtls.h index 56ceee00..162d9726 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/private-lib-tls-mbedtls.h +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/private-lib-tls-mbedtls.h @@ -31,6 +31,16 @@ struct lws_x509_cert { mbedtls_x509_crt cert; /* has a .next for linked-list / chain */ }; +typedef struct lws_mbedtls_x509_authority +{ + mbedtls_x509_buf keyIdentifier; + mbedtls_x509_sequence authorityCertIssuer; + mbedtls_x509_buf authorityCertSerialNumber; + mbedtls_x509_buf raw; +} +lws_mbedtls_x509_authority; + + mbedtls_md_type_t lws_gencrypto_mbedtls_hash_to_MD_TYPE(enum lws_genhash_types hash_type); @@ -39,3 +49,11 @@ lws_gencrypto_mbedtls_rngf(void *context, unsigned char *buf, size_t len); int lws_tls_session_new_mbedtls(struct lws *wsi); + +int +lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, + union lws_tls_cert_info_results *buf, size_t len); + +int +lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid, + lws_mbedtls_x509_authority *akid); diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h index 86cf31ad..ab344f4d 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h @@ -28,7 +28,7 @@ * * @return certification object point */ -CERT *__ssl_cert_new(CERT *ic); +CERT *__ssl_cert_new(CERT *ic, void *rngctx); /** * @brief create a certification object include private key object @@ -37,7 +37,7 @@ CERT *__ssl_cert_new(CERT *ic); * * @return certification object point */ -CERT* ssl_cert_new(void); +CERT* ssl_cert_new(void *rngctx); /** * @brief free a certification object diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h index e790fcc9..edb74467 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h @@ -28,7 +28,7 @@ * * @return new private key object point */ -EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk); +EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk, void *rngctx); /** * @brief create a private key object @@ -37,7 +37,7 @@ EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk); * * @return private key object point */ -EVP_PKEY* EVP_PKEY_new(void); +EVP_PKEY* EVP_PKEY_new(void *rngctx); /** * @brief load a character key context into system context. If '*a' is pointed to the @@ -53,7 +53,7 @@ EVP_PKEY* EVP_PKEY_new(void); EVP_PKEY* d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, - long length); + long length, void *rngctx); /** * @brief free a private key object diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_types.h b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_types.h index 045fc7d1..564a94d8 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_types.h +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_types.h @@ -31,6 +31,10 @@ #include "ssl_code.h" +#include + +#include "private-jit-trust.h" + typedef void SSL_CIPHER; typedef void X509_STORE_CTX; @@ -183,7 +187,7 @@ struct ssl_ctx_st int verify_mode; - int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx); + int (*default_verify_callback) (SSL *, mbedtls_x509_crt *); long session_timeout; @@ -192,6 +196,8 @@ struct ssl_ctx_st int read_buffer_len; X509_VERIFY_PARAM param; + + void *rngctx; }; struct ssl_st @@ -223,7 +229,11 @@ struct ssl_st int verify_mode; - int (*verify_callback) (int ok, X509_STORE_CTX *ctx); + int (*verify_callback) (SSL *, mbedtls_x509_crt *); + +#if defined(LWS_WITH_TLS_JIT_TRUST) + lws_tls_kid_chain_t kid_chain; +#endif int rwstate; int interrupted_remaining_write; @@ -292,7 +302,7 @@ struct x509_method_st { struct pkey_method_st { - int (*pkey_new)(EVP_PKEY *pkey, EVP_PKEY *m_pkey); + int (*pkey_new)(EVP_PKEY *pkey, EVP_PKEY *m_pkey, void *rngctx); void (*pkey_free)(EVP_PKEY *pkey); diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/openssl/ssl.h b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/openssl/ssl.h index 59f7d6a3..ea5f5aba 100755 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/openssl/ssl.h +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/openssl/ssl.h @@ -60,7 +60,7 @@ * * @return the context point */ -SSL_CTX* SSL_CTX_new(const SSL_METHOD *method); +SSL_CTX* SSL_CTX_new(const SSL_METHOD *method, void *rngctx); /** * @brief free a SSL context @@ -708,7 +708,7 @@ int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); * * @return none */ -void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *)); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *)); /** * @brief set the SSL verifying of the SSL context @@ -719,7 +719,7 @@ void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509 * * @return none */ -void SSL_set_verify(SSL *s, int mode, int (*verify_callback)(int, X509_STORE_CTX *)); +void SSL_set_verify(SSL *s, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *)); /** * @brief set the SSL verify depth of the SSL context @@ -739,7 +739,7 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); * * @return verifying result */ -int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx); +int verify_callback(SSL *, mbedtls_x509_crt *); /** * @brief set the session timeout time diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h index cbbe3aa3..874d2d11 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h @@ -48,7 +48,7 @@ int x509_pm_new(X509 *x, X509 *m_x); void x509_pm_free(X509 *x); int x509_pm_load(X509 *x, const unsigned char *buffer, int len); -int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pk); +int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pk, void *rngctx); void pkey_pm_free(EVP_PKEY *pk); int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len); diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_cert.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_cert.c index 5c608125..dab197c5 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_cert.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_cert.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "private-lib-core.h" + #include "ssl_cert.h" #include "ssl_pkey.h" #include "ssl_x509.h" @@ -21,7 +23,7 @@ /** * @brief create a certification object according to input certification */ -CERT *__ssl_cert_new(CERT *ic) +CERT *__ssl_cert_new(CERT *ic, void *rngctx) { CERT *cert; @@ -42,7 +44,7 @@ CERT *__ssl_cert_new(CERT *ic) ix = NULL; } - cert->pkey = __EVP_PKEY_new(ipk); + cert->pkey = __EVP_PKEY_new(ipk, rngctx); if (!cert->pkey) { SSL_DEBUG(SSL_CERT_ERROR_LEVEL, "__EVP_PKEY_new() return NULL"); goto pkey_err; @@ -67,9 +69,9 @@ CERT *__ssl_cert_new(CERT *ic) /** * @brief create a certification object include private key object */ -CERT *ssl_cert_new(void) +CERT *ssl_cert_new(void *rngctx) { - return __ssl_cert_new(NULL); + return __ssl_cert_new(NULL, rngctx); } /** diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_lib.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_lib.c index a3220d69..d751d78c 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_lib.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_lib.c @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. + +#include "private-lib-core.h" + #include "ssl_lib.h" #include "ssl_pkey.h" #include "ssl_x509.h" @@ -19,8 +22,6 @@ #include "ssl_dbg.h" #include "ssl_port.h" -#include "private-lib-core.h" - char * lws_strncpy(char *dest, const char *src, size_t size); @@ -179,14 +180,19 @@ OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl) return state; } +const char *mbedtls_client_preload_filepath; + /** * @brief create a SSL context */ -SSL_CTX* SSL_CTX_new(const SSL_METHOD *method) +SSL_CTX* SSL_CTX_new(const SSL_METHOD *method, void *rngctx) { SSL_CTX *ctx; CERT *cert; X509 *client_ca; +#if defined(LWS_HAVE_mbedtls_x509_crt_parse_file) + int n; +#endif if (!method) { SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no no_method"); @@ -199,7 +205,7 @@ SSL_CTX* SSL_CTX_new(const SSL_METHOD *method) goto failed1; } - cert = ssl_cert_new(); + cert = ssl_cert_new(rngctx); if (!cert) { SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "ssl_cert_new() return NULL"); goto failed2; @@ -214,9 +220,24 @@ SSL_CTX* SSL_CTX_new(const SSL_METHOD *method) ctx->method = method; ctx->client_CA = client_ca; ctx->cert = cert; + ctx->rngctx = rngctx; ctx->version = method->version; +#if defined(LWS_HAVE_mbedtls_x509_crt_parse_file) + if (mbedtls_client_preload_filepath) { + mbedtls_x509_crt **px = (mbedtls_x509_crt **)ctx->client_CA->x509_pm; + + *px = malloc(sizeof(**px)); + mbedtls_x509_crt_init(*px); + n = mbedtls_x509_crt_parse_file(*px, mbedtls_client_preload_filepath); + if (n < 0) + lwsl_err("%s: unable to load cert bundle 0x%x\n", __func__, -n); + else + lwsl_info("%s: loaded cert bundle %d\n", __func__, n); + } +#endif + return ctx; failed3: @@ -296,7 +317,7 @@ SSL *SSL_new(SSL_CTX *ctx) goto failed2; } - ssl->cert = __ssl_cert_new(ctx->cert); + ssl->cert = __ssl_cert_new(ctx->cert, ctx->rngctx); if (!ssl->cert) { SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "__ssl_cert_new() return NULL"); goto failed3; @@ -1059,7 +1080,7 @@ void SSL_set_verify_depth(SSL *ssl, int depth) /** * @brief set the SSL context verifying of the SSL context */ -void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *)) +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *)) { SSL_ASSERT3(ctx); @@ -1070,7 +1091,7 @@ void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509 /** * @brief set the SSL verifying of the SSL context */ -void SSL_set_verify(SSL *ssl, int mode, int (*verify_callback)(int, X509_STORE_CTX *)) +void SSL_set_verify(SSL *ssl, int mode, int (*verify_callback)(SSL *, mbedtls_x509_crt *)) { SSL_ASSERT3(ssl); diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_methods.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_methods.c index 56e2c12c..bfa9c9be 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_methods.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_methods.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "private-lib-core.h" + #include "ssl_methods.h" #include "ssl_pm.h" diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_pkey.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_pkey.c index 7c92b699..18436a25 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_pkey.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_pkey.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "private-lib-core.h" + #include "ssl_pkey.h" #include "ssl_methods.h" #include "ssl_dbg.h" @@ -20,7 +22,7 @@ /** * @brief create a private key object according to input private key */ -EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk) +EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk, void *rngctx) { int ret; EVP_PKEY *pkey; @@ -37,7 +39,7 @@ EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk) pkey->method = EVP_PKEY_method(); } - ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk); + ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk, rngctx); if (ret) { SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(new) return %d", ret); goto failed; @@ -54,9 +56,9 @@ EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk) /** * @brief create a private key object */ -EVP_PKEY* EVP_PKEY_new(void) +EVP_PKEY* EVP_PKEY_new(void *rngctx) { - return __EVP_PKEY_new(NULL); + return __EVP_PKEY_new(NULL, rngctx); } /** @@ -78,7 +80,7 @@ void EVP_PKEY_free(EVP_PKEY *pkey) EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, - long length) + long length, void *rngctx) { int m = 0; int ret; @@ -91,7 +93,7 @@ EVP_PKEY *d2i_PrivateKey(int type, if (a && *a) { pkey = *a; } else { - pkey = EVP_PKEY_new();; + pkey = EVP_PKEY_new(rngctx); if (!pkey) { SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL"); goto failed1; @@ -165,7 +167,7 @@ int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, int ret; EVP_PKEY *pk; - pk = d2i_PrivateKey(0, NULL, &d, len); + pk = d2i_PrivateKey(0, NULL, &d, len, ctx->rngctx); if (!pk) { SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL"); goto failed1; @@ -194,7 +196,7 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, int ret; EVP_PKEY *pk; - pk = d2i_PrivateKey(0, NULL, &d, len); + pk = d2i_PrivateKey(0, NULL, &d, len, ssl->ctx->rngctx); if (!pk) { SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL"); goto failed1; diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_stack.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_stack.c index da836daf..78634c4b 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_stack.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_stack.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "private-lib-core.h" + #include "ssl_stack.h" #include "ssl_dbg.h" #include "ssl_port.h" diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_x509.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_x509.c index 933ee57d..7d8bbfff 100644 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_x509.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_x509.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "private-lib-core.h" + #include "ssl_x509.h" #include "ssl_methods.h" #include "ssl_dbg.h" diff --git a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index c73ba084..e8a0cb2d 100755 --- a/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/3rdparty/libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "private-lib-core.h" + #include "ssl_pm.h" #include "ssl_port.h" #include "ssl_dbg.h" @@ -27,9 +29,7 @@ #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" -#include "mbedtls/certs.h" -#include "private-lib-core.h" #define X509_INFO_STRING_LENGTH 8192 @@ -63,6 +63,8 @@ struct pkey_pm mbedtls_pk_context *pkey; mbedtls_pk_context *ex_pkey; + + void *rngctx; }; unsigned int max_content_len; @@ -96,6 +98,17 @@ static void ssl_platform_debug(void *ctx, int level, } //#endif +static int +lws_mbedtls_f_vrfy(void *opaque, mbedtls_x509_crt *x509, int state, uint32_t *pflags) +{ + struct ssl_pm *ssl_pm = (struct ssl_pm *)opaque; + + if (ssl_pm->owner->verify_callback) + (ssl_pm->owner->verify_callback)(ssl_pm->owner, x509); + + return 0; +} + /** * @brief create SSL low-level object */ @@ -134,6 +147,12 @@ int ssl_pm_new(SSL *ssl) mbedtls_entropy_init(&ssl_pm->entropy); mbedtls_ssl_init(&ssl_pm->ssl); +#if defined(LWS_HAVE_mbedtls_ssl_set_verify) + mbedtls_ssl_set_verify(&ssl_pm->ssl, lws_mbedtls_f_vrfy, ssl_pm); +#else + mbedtls_ssl_conf_verify(&ssl_pm->conf, lws_mbedtls_f_vrfy, ssl_pm); +#endif + ret = mbedtls_ctr_drbg_seed(&ssl_pm->ctr_drbg, mbedtls_entropy_func, &ssl_pm->entropy, pers, pers_len); if (ret) { lwsl_notice("%s: mbedtls_ctr_drbg_seed() return -0x%x", __func__, -ret); @@ -156,17 +175,15 @@ int ssl_pm_new(SSL *ssl) if (TLS1_2_VERSION == ssl->version) version = MBEDTLS_SSL_MINOR_VERSION_3; else if (TLS1_1_VERSION == ssl->version) - version = MBEDTLS_SSL_MINOR_VERSION_2; - else if (TLS1_VERSION == ssl->version) - version = MBEDTLS_SSL_MINOR_VERSION_1; + version = 2; else - version = MBEDTLS_SSL_MINOR_VERSION_0; + version = 1; mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version); mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version); } else { mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); - mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); + mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, 1); } mbedtls_ssl_conf_rng(&ssl_pm->conf, mbedtls_ctr_drbg_random, &ssl_pm->ctr_drbg); @@ -225,16 +242,16 @@ void ssl_pm_free(SSL *ssl) */ static int ssl_pm_reload_crt(SSL *ssl) { - int ret; - int mode; - struct ssl_pm *ssl_pm = ssl->ssl_pm; struct x509_pm *ca_pm = (struct x509_pm *)ssl->client_CA->x509_pm; + struct ssl_pm *ssl_pm = ssl->ssl_pm; + int ret = 0; + int mode; struct pkey_pm *pkey_pm = (struct pkey_pm *)ssl->cert->pkey->pkey_pm; struct x509_pm *crt_pm = (struct x509_pm *)ssl->cert->x509->x509_pm; if (ssl->verify_mode == SSL_VERIFY_PEER) - mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + mode = MBEDTLS_SSL_VERIFY_REQUIRED; else if (ssl->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) mode = MBEDTLS_SSL_VERIFY_OPTIONAL; else if (ssl->verify_mode == SSL_VERIFY_CLIENT_ONCE) @@ -244,19 +261,15 @@ static int ssl_pm_reload_crt(SSL *ssl) mbedtls_ssl_conf_authmode(&ssl_pm->conf, mode); - if (ca_pm->x509_crt) { + if (ca_pm->x509_crt) mbedtls_ssl_conf_ca_chain(&ssl_pm->conf, ca_pm->x509_crt, NULL); - } else if (ca_pm->ex_crt) { + else if (ca_pm->ex_crt) mbedtls_ssl_conf_ca_chain(&ssl_pm->conf, ca_pm->ex_crt, NULL); - } - if (crt_pm->x509_crt && pkey_pm->pkey) { + if (crt_pm->x509_crt && pkey_pm->pkey) ret = mbedtls_ssl_conf_own_cert(&ssl_pm->conf, crt_pm->x509_crt, pkey_pm->pkey); - } else if (crt_pm->ex_crt && pkey_pm->ex_pkey) { + else if (crt_pm->ex_crt && pkey_pm->ex_pkey) ret = mbedtls_ssl_conf_own_cert(&ssl_pm->conf, crt_pm->ex_crt, pkey_pm->ex_pkey); - } else { - ret = 0; - } if (ret) { SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_conf_own_cert() return -0x%x", -ret); @@ -274,10 +287,10 @@ static int mbedtls_handshake( mbedtls_ssl_context *ssl ) { int ret = 0; - while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { + while (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake_step(ssl); - lwsl_info("%s: ssl ret -%x state %d\n", __func__, -ret, ssl->state); + lwsl_info("%s: ssl ret -%x state %d\n", __func__, -ret, ssl->MBEDTLS_PRIVATE(state)); if (ret != 0) break; @@ -304,7 +317,7 @@ int ssl_pm_handshake(SSL *ssl) return 0; } - if (ssl_pm->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + if (ssl_pm->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { ssl_speed_up_enter(); /* mbedtls return codes @@ -336,6 +349,7 @@ int ssl_pm_handshake(SSL *ssl) } if (errno == 11) { + lwsl_info("%s: ambiguous EAGAIN taken as WANT_READ\n", __func__); ssl->err = ret == MBEDTLS_ERR_SSL_WANT_READ; return 0; @@ -410,7 +424,11 @@ int ssl_pm_read(SSL *ssl, void *buffer, int len) // lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret); SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret); if (ret == MBEDTLS_ERR_NET_CONN_RESET || +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */ +#else ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */ +#endif ssl->err = SSL_ERROR_SYSCALL; ret = -1; } @@ -481,14 +499,13 @@ void ssl_pm_set_fd(SSL *ssl, int fd, int mode) { struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - ssl_pm->fd.fd = fd; + ssl_pm->fd.MBEDTLS_PRIVATE_V30_ONLY(fd) = fd; } int ssl_pm_get_fd(const SSL *ssl, int mode) { struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - - return ssl_pm->fd.fd; + return ssl_pm->fd.MBEDTLS_PRIVATE_V30_ONLY(fd); } OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) @@ -497,7 +514,7 @@ OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - switch (ssl_pm->ssl.state) + switch (ssl_pm->ssl.MBEDTLS_PRIVATE(state)) { case MBEDTLS_SSL_CLIENT_HELLO: state = TLS_ST_CW_CLNT_HELLO; @@ -642,7 +659,7 @@ int x509_pm_load(X509 *x, const unsigned char *buffer, int len) struct x509_pm *x509_pm = (struct x509_pm *)x->x509_pm; if (!x509_pm->x509_crt) { - x509_pm->x509_crt = ssl_mem_malloc(sizeof(mbedtls_x509_crt)); + x509_pm->x509_crt = ssl_mem_malloc(sizeof(mbedtls_x509_crt) + 80); if (!x509_pm->x509_crt) { SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (x509_pm->x509_crt)"); goto no_mem; @@ -680,7 +697,7 @@ int x509_pm_load(X509 *x, const unsigned char *buffer, int len) return -1; } -int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pkey) +int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pkey, void *rngctx) { struct pkey_pm *pkey_pm; @@ -689,6 +706,7 @@ int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pkey) return -1; pk->pkey_pm = pkey_pm; + pkey_pm->rngctx = rngctx; if (m_pkey) { struct pkey_pm *m_pkey_pm = (struct pkey_pm *)m_pkey->pkey_pm; @@ -742,7 +760,12 @@ int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len) mbedtls_pk_init(pkey_pm->pkey); +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 + ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len + 1, NULL, 0, + mbedtls_ctr_drbg_random, pkey_pm->rngctx); +#else ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len + 1, NULL, 0); +#endif ssl_mem_free(load_buf); if (ret) { @@ -850,6 +873,8 @@ void _ssl_set_alpn_list(const SSL *ssl) return; if (mbedtls_ssl_conf_alpn_protocols(&((struct ssl_pm *)(ssl->ssl_pm))->conf, ssl->ctx->alpn_protos)) fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols failed\n"); +#else + fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols absent\n"); #endif } @@ -864,6 +889,9 @@ void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, *len = (unsigned int)strlen(alp); else *len = 0; +#else + fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols absent\n"); + *len = 0; #endif } @@ -934,13 +962,14 @@ void SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) if (ssl->cert) ssl_cert_free(ssl->cert); ssl->ctx = ctx; - ssl->cert = __ssl_cert_new(ctx->cert); + ssl->cert = __ssl_cert_new(ctx->cert, ctx->rngctx); #if defined(LWS_HAVE_mbedtls_ssl_set_hs_authmode) + if (ctx->verify_mode == SSL_VERIFY_PEER) - mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + mode = MBEDTLS_SSL_VERIFY_REQUIRED; else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) - mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + mode = MBEDTLS_SSL_VERIFY_REQUIRED; else if (ctx->verify_mode == SSL_VERIFY_CLIENT_ONCE) mode = MBEDTLS_SSL_VERIFY_UNSET; else diff --git a/3rdparty/libwebsockets/lib/tls/openssl/lws-genaes.c b/3rdparty/libwebsockets/lib/tls/openssl/lws-genaes.c index bc4d7d82..fa0fe806 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/lws-genaes.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/lws-genaes.c @@ -79,19 +79,27 @@ lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, ctx->cipher = EVP_aes_128_cfb8(); break; #endif +#if defined(LWS_HAVE_EVP_aes_128_ctr) case LWS_GAESM_CTR: ctx->cipher = EVP_aes_128_ctr(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_ecb) case LWS_GAESM_ECB: ctx->cipher = EVP_aes_128_ecb(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_ofb) case LWS_GAESM_OFB: ctx->cipher = EVP_aes_128_ofb(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_xts) case LWS_GAESM_XTS: lwsl_err("%s: AES XTS requires double-length key\n", __func__); break; +#endif case LWS_GAESM_GCM: ctx->cipher = EVP_aes_128_gcm(); break; @@ -126,18 +134,26 @@ lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, ctx->cipher = EVP_aes_192_cfb8(); break; #endif +#if defined(LWS_HAVE_EVP_aes_128_ctr) case LWS_GAESM_CTR: ctx->cipher = EVP_aes_192_ctr(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_ecb) case LWS_GAESM_ECB: ctx->cipher = EVP_aes_192_ecb(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_ofb) case LWS_GAESM_OFB: ctx->cipher = EVP_aes_192_ofb(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_xts) case LWS_GAESM_XTS: lwsl_err("%s: AES XTS 192 invalid\n", __func__); goto bail; +#endif case LWS_GAESM_GCM: ctx->cipher = EVP_aes_192_gcm(); break; @@ -172,15 +188,21 @@ lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, ctx->cipher = EVP_aes_256_cfb8(); break; #endif +#if defined(LWS_HAVE_EVP_aes_128_ctr) case LWS_GAESM_CTR: ctx->cipher = EVP_aes_256_ctr(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_ecb) case LWS_GAESM_ECB: ctx->cipher = EVP_aes_256_ecb(); break; +#endif +#if defined(LWS_HAVE_EVP_aes_128_ofb) case LWS_GAESM_OFB: ctx->cipher = EVP_aes_256_ofb(); break; +#endif #if defined(LWS_HAVE_EVP_aes_128_xts) case LWS_GAESM_XTS: ctx->cipher = EVP_aes_128_xts(); @@ -196,8 +218,10 @@ lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, case 512 / 8: switch (mode) { +#if defined(LWS_HAVE_EVP_aes_128_xts) case LWS_GAESM_XTS: ctx->cipher = EVP_aes_256_xts(); +#endif break; default: goto bail; diff --git a/3rdparty/libwebsockets/lib/tls/openssl/lws-genec.c b/3rdparty/libwebsockets/lib/tls/openssl/lws-genec.c index 5fd644d0..12830094 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/lws-genec.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/lws-genec.c @@ -34,11 +34,22 @@ #error "You probably need LWS_SUPPRESS_DEPRECATED_API_WARNINGS" #endif +#if defined(USE_WOLFSSL) +#include "openssl/ecdh.h" +#endif + /* * Care: many openssl apis return 1 for success. These are translated to the * lws convention of 0 for success. */ +#if defined(USE_WOLFSSL) +EVP_PKEY * EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *p) +{ + return p->pkey; +} +#endif + #if !defined(LWS_HAVE_ECDSA_SIG_set0) static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) @@ -66,9 +77,11 @@ ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { int i; +#if !defined(USE_WOLFSSL) BN_ULONG l; +#endif -#if !defined(LIBRESSL_VERSION_NUMBER) +#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_WOLFSSL) bn_check_top(a); #endif i = BN_num_bytes(a); @@ -78,10 +91,14 @@ int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) memset(to, 0, (size_t)(tolen - i)); to += tolen - i; } +#if defined(USE_WOLFSSL) + BN_bn2bin(a, to); +#else while (i--) { l = a->d[i / BN_BYTES]; *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; } +#endif return tolen; } #endif @@ -102,7 +119,8 @@ const struct lws_ec_curves lws_ec_curves[4] = { }; static int -lws_genec_eckey_import(int nid, EVP_PKEY *pkey, struct lws_gencrypto_keyelem *el) +lws_genec_eckey_import(int nid, EVP_PKEY *pkey, + const struct lws_gencrypto_keyelem *el) { EC_KEY *ec = EC_KEY_new_by_curve_name(nid); BIGNUM *bn_d, *bn_x, *bn_y; @@ -132,7 +150,22 @@ lws_genec_eckey_import(int nid, EVP_PKEY *pkey, struct lws_gencrypto_keyelem *el goto bail1; } + /* + * EC_KEY_set_public_key_affine_coordinates sets the public key for + * key based on its affine co-ordinates, i.e. it constructs an + * EC_POINT object based on the supplied x and y values and sets + * the public key to be this EC_POINT. It will also performs + * certain sanity checks on the key to confirm that it is valid. + */ + +#if defined(USE_WOLFSSL) + n = wolfSSL_EC_POINT_set_affine_coordinates_GFp(ec->group, + ec->pub_key, + bn_x, bn_y, + NULL); +#else n = EC_KEY_set_public_key_affine_coordinates(ec, bn_x, bn_y); +#endif BN_free(bn_x); BN_free(bn_y); if (n != 1) { @@ -160,10 +193,12 @@ lws_genec_eckey_import(int nid, EVP_PKEY *pkey, struct lws_gencrypto_keyelem *el /* explicitly confirm the key pieces are consistent */ +#if !defined(USE_WOLFSSL) if (EC_KEY_check_key(ec) != 1) { lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__); goto bail; } +#endif n = EVP_PKEY_assign_EC_KEY(pkey, ec); if (n != 1) { @@ -184,7 +219,8 @@ lws_genec_eckey_import(int nid, EVP_PKEY *pkey, struct lws_gencrypto_keyelem *el static int lws_genec_keypair_import(struct lws_genec_ctx *ctx, const struct lws_ec_curves *curve_table, - EVP_PKEY_CTX **pctx, struct lws_gencrypto_keyelem *el) + EVP_PKEY_CTX **pctx, + const struct lws_gencrypto_keyelem *el) { EVP_PKEY *pkey = NULL; const struct lws_ec_curves *curve; @@ -273,7 +309,7 @@ lws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el, int lws_genecdsa_set_key(struct lws_genec_ctx *ctx, - struct lws_gencrypto_keyelem *el) + const struct lws_gencrypto_keyelem *el) { if (ctx->genec_alg != LEGENEC_ECDSA) return -1; @@ -486,6 +522,7 @@ lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, uint8_t *sig, size_t sig_len) { int ret = -1, n, keybytes = lws_gencrypto_bits_to_bytes(keybits); + size_t hs = lws_genhash_size(hash_type); const BIGNUM *r = NULL, *s = NULL; ECDSA_SIG *ecdsasig; EC_KEY *eckey; @@ -498,9 +535,9 @@ lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, if (!ctx->has_private) return -1; - if ((int)sig_len < keybytes * 2) { + if ((int)sig_len != (int)(keybytes * 2)) { lwsl_notice("%s: sig buff %d < %d\n", __func__, - (int)sig_len, keybytes * 2); + (int)sig_len, (int)(hs * 2)); return -1; } @@ -525,7 +562,7 @@ lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, * 4. The resulting 64-octet sequence is the JWS Signature value. */ - ecdsasig = ECDSA_do_sign(in, (int)lws_genhash_size(hash_type), eckey); + ecdsasig = ECDSA_do_sign(in, (int)hs, eckey); EC_KEY_free(eckey); if (!ecdsasig) { lwsl_notice("%s: ECDSA_do_sign fail\n", __func__); @@ -567,8 +604,8 @@ lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, enum lws_genhash_types hash_type, int keybits, const uint8_t *sig, size_t sig_len) { - int ret = -1, n, keybytes = lws_gencrypto_bits_to_bytes(keybits), - hlen = (int)lws_genhash_size(hash_type); + int ret = -1, n, hlen = (int)lws_genhash_size(hash_type), + keybytes = lws_gencrypto_bits_to_bytes(keybits); ECDSA_SIG *ecsig = ECDSA_SIG_new(); BIGNUM *r = NULL, *s = NULL; EC_KEY *eckey; @@ -580,7 +617,7 @@ lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, goto bail; if ((int)sig_len != keybytes * 2) { - lwsl_err("%s: sig buf too small %d vs %d\n", __func__, + lwsl_err("%s: sig buf size %d vs %d\n", __func__, (int)sig_len, keybytes * 2); goto bail; } @@ -620,7 +657,7 @@ lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, n = ECDSA_do_verify(in, hlen, ecsig, eckey); EC_KEY_free(eckey); if (n != 1) { - lwsl_err("%s: ECDSA_do_verify fail\n", __func__); + lwsl_err("%s: ECDSA_do_verify fail, hlen %d\n", __func__, (int)hlen); lws_tls_err_describe_clear(); goto bail; } @@ -660,7 +697,12 @@ lws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss, len = (EC_GROUP_get_degree(EC_KEY_get0_group(eckey[LDHS_OURS])) + 7) / 8; if (len <= *ss_len) { - *ss_len = ECDH_compute_key(ss, (unsigned int)len, +#if defined(USE_WOLFSSL) + *ss_len = wolfSSL_ECDH_compute_key( +#else + *ss_len = ECDH_compute_key( +#endif + ss, (unsigned int)len, EC_KEY_get0_public_key(eckey[LDHS_THEIRS]), eckey[LDHS_OURS], NULL); ret = -(*ss_len < 0); diff --git a/3rdparty/libwebsockets/lib/tls/openssl/lws-genhash.c b/3rdparty/libwebsockets/lib/tls/openssl/lws-genhash.c index ba140e4c..5363bcba 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/lws-genhash.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/lws-genhash.c @@ -26,6 +26,7 @@ */ #include #include +#include /* * Care: many openssl apis return 1 for success. These are translated to the * lws convention of 0 for success. @@ -83,12 +84,16 @@ lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) unsigned int len; int ret = 0; + if (!ctx->mdctx) + return 0; + if (result) ret = EVP_DigestFinal_ex(ctx->mdctx, result, &len) != 1; (void)len; EVP_MD_CTX_destroy(ctx->mdctx); + ctx->mdctx = NULL; return ret; } @@ -217,8 +222,12 @@ int lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len) { #if defined(LWS_HAVE_HMAC_CTX_new) +#if defined(LIBRESSL_VERSION_NUMBER) if (HMAC_Update(ctx->ctx, in, len) != 1) #else + if (HMAC_Update(ctx->ctx, in, (int)len) != 1) +#endif +#else /* HMAC_CTX_new */ if (HMAC_Update(&ctx->ctx, in, len) != 1) #endif return -1; diff --git a/3rdparty/libwebsockets/lib/tls/openssl/lws-genrsa.c b/3rdparty/libwebsockets/lib/tls/openssl/lws-genrsa.c index ad8dbd54..985246c9 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/lws-genrsa.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/lws-genrsa.c @@ -77,7 +77,8 @@ rsa_pkey_wrap(struct lws_genrsa_ctx *ctx, RSA *rsa) } int -lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, +lws_genrsa_create(struct lws_genrsa_ctx *ctx, + const struct lws_gencrypto_keyelem *el, struct lws_context *context, enum enum_genrsa_mode mode, enum lws_genhash_types oaep_hashid) { @@ -111,7 +112,7 @@ lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, goto bail; } -#if defined(LWS_HAVE_RSA_SET0_KEY) +#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL) if (RSA_set0_key(ctx->rsa, ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_N], ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_E], ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_D]) != 1) { @@ -177,7 +178,7 @@ lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx, if (n != 1) goto cleanup_1; -#if defined(LWS_HAVE_RSA_SET0_KEY) +#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL) { const BIGNUM *mpi[5]; @@ -293,7 +294,8 @@ lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in, switch(ctx->mode) { case LGRSAM_PKCS1_1_5: - n = RSA_verify(n, in, (unsigned int)h, (uint8_t *)sig, (unsigned int)sig_len, ctx->rsa); + n = RSA_verify(n, in, (unsigned int)h, (uint8_t *)sig, + (unsigned int)sig_len, ctx->rsa); break; case LGRSAM_PKCS1_OAEP_PSS: md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type); @@ -363,7 +365,11 @@ lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in, goto bail; if (EVP_DigestSignInit(mdctx, NULL, md, NULL, +#if defined(USE_WOLFSSL) + ctx->ctx->pkey)) { +#else EVP_PKEY_CTX_get0_pkey(ctx->ctx))) { +#endif lwsl_err("%s: EVP_DigestSignInit failed\n", __func__); goto bail; diff --git a/3rdparty/libwebsockets/lib/tls/openssl/openssl-client.c b/3rdparty/libwebsockets/lib/tls/openssl/openssl-client.c index b315211c..6c8d5c1c 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/openssl-client.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/openssl-client.c @@ -25,8 +25,10 @@ #include "lws_config.h" #ifdef LWS_HAVE_X509_VERIFY_PARAM_set1_host /* Before glibc 2.10, strnlen required _GNU_SOURCE */ +#if !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif +#endif #include #include "private-lib-core.h" @@ -44,16 +46,56 @@ extern int openssl_websocket_private_data_index, #if !defined(USE_WOLFSSL) +#if 0 +#if defined(LWS_WITH_TLS_JIT_TRUST) + +/* + * Completion of sync or async JIT trust lookup + */ + +int +lws_tls_jit_trust_got_cert_cb(void *got_opaque, const uint8_t *der, + size_t der_len) +{ + X509 *x = d2i_X509(NULL, &der, (long)der_len); + /** !!! this is not safe for async atm */ + struct lws *wsi = (struct lws *)got_opaque; + X509_STORE *xs; + int ret = 0; + + if (!x) { + lwsl_err("%s: failed\n", __func__); + return 1; + } + + xs = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(wsi->tls.ssl)); + if (xs) { + if (X509_STORE_add_cert(xs, x) != 1) { + lwsl_warn("%s: unable to set trusted CA\n", __func__); + ret = 1; + } else + lwsl_notice("%s: added trusted CA to CTX for next time\n", + __func__); + } else + lwsl_warn("%s: couldn't get cert store\n", __func__); + + X509_free(x); + + return ret; +} +#endif +#endif + static int OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) { SSL *ssl; - int n; + int n, err = 0; struct lws *wsi; /* keep old behaviour accepting self-signed server certs */ if (!preverify_ok) { - int err = X509_STORE_CTX_get_error(x509_ctx); + err = X509_STORE_CTX_get_error(x509_ctx); if (err != X509_V_OK) { ssl = X509_STORE_CTX_get_ex_data(x509_ctx, @@ -106,6 +148,43 @@ OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) return 0; } +#if defined(LWS_WITH_TLS_JIT_TRUST) + if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) { + union lws_tls_cert_info_results ci; + STACK_OF(X509) *x509_stack; + + x509_stack = X509_STORE_CTX_get1_chain(x509_ctx); + if (x509_stack) { + + for (n = 0; n < OPENSSL_sk_num((const OPENSSL_STACK *)x509_stack) && + wsi->tls.kid_chain.count != + LWS_ARRAY_SIZE(wsi->tls.kid_chain.akid); n++) { + X509 *x509 = OPENSSL_sk_value((const OPENSSL_STACK *)x509_stack, n); + + if (!lws_tls_openssl_cert_info(x509, + LWS_TLS_CERT_INFO_SUBJECT_KEY_ID, + &ci, 0)) + lws_tls_kid_copy(&ci, + &wsi->tls.kid_chain.skid[ + wsi->tls.kid_chain.count]); + + if (!lws_tls_openssl_cert_info(x509, + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID, + &ci, 0)) + lws_tls_kid_copy(&ci, + &wsi->tls.kid_chain.akid[ + wsi->tls.kid_chain.count]); + + wsi->tls.kid_chain.count++; + } + + sk_X509_pop_free(x509_stack, X509_free); + } + + lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.kid_chain); + } +#endif + n = lws_get_context_protocol(wsi->a.context, 0).callback(wsi, LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION, x509_ctx, ssl, (unsigned int)preverify_ok); @@ -122,6 +201,9 @@ OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) int depth = X509_STORE_CTX_get_error_depth(x509_ctx); const char *msg = X509_verify_cert_error_string(err); + lws_strncpy(wsi->tls.err_helper, msg, + sizeof(wsi->tls.err_helper)); + lwsl_err("SSL error: %s (preverify_ok=%d;err=%d;" "depth=%d)\n", msg, preverify_ok, err, depth); @@ -148,7 +230,6 @@ OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) } #endif - int lws_ssl_client_bio_create(struct lws *wsi) { @@ -262,9 +343,9 @@ lws_ssl_client_bio_create(struct lws *wsi) strlen(hostname)); #endif #else -#ifdef WOLFSSL_SNI_HOST_NAME +#if defined(WOLFSSL_SNI_HOST_NAME) || defined(HAVE_SNI) wolfSSL_UseSNI(wsi->tls.ssl, WOLFSSL_SNI_HOST_NAME, hostname, - strlen(hostname)); + (unsigned short)strlen(hostname)); #endif #endif #else @@ -439,6 +520,7 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) #endif errno = 0; ERR_clear_error(); + wsi->tls.err_helper[0] = '\0'; n = SSL_connect(wsi->tls.ssl); en = errno; @@ -457,8 +539,9 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) } if (m == SSL_ERROR_SSL) { - n = lws_snprintf(errbuf, elen, "connect SSL err %d: ", m); - ERR_error_string_n((unsigned int)m, errbuf + n, (elen - (unsigned int)n)); + n = lws_snprintf(errbuf, elen, "tls: %s", wsi->tls.err_helper); + if (!wsi->tls.err_helper[0]) + ERR_error_string_n((unsigned int)m, errbuf + n, (elen - (unsigned int)n)); return LWS_SSL_CAPABLE_ERROR; } @@ -494,6 +577,12 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) lws_role_call_alpn_negotiated(wsi, (const char *)a); #endif +#if defined(LWS_TLS_SYNTHESIZE_CB) + lws_sul_schedule(wsi->a.context, wsi->tsi, + &wsi->tls.sul_cb_synth, + lws_sess_cache_synth_cb, 500 * LWS_US_PER_MS); +#endif + lwsl_info("client connect OK\n"); lws_openssl_describe_cipher(wsi); return LWS_SSL_CAPABLE_DONE; @@ -815,37 +904,67 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_RELEASE_BUFFERS); - if (info->ssl_client_options_set) - SSL_CTX_set_options(vh->tls.ssl_client_ctx, +#if !defined(USE_WOLFSSL) +#if defined(LWS_WITH_BORINGSSL) + uint32_t +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ + !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ + unsigned long +#else + long +#endif +#endif +#else + long +#endif + ssl_client_options_set_value = #if !defined(USE_WOLFSSL) #if defined(LWS_WITH_BORINGSSL) (uint32_t) #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ - (unsigned long) + (unsigned long) #else - (long) + (long) #endif #endif #endif - info->ssl_client_options_set); + info->ssl_client_options_set; + + if (info->ssl_client_options_set) + SSL_CTX_set_options(vh->tls.ssl_client_ctx, ssl_client_options_set_value); - /* SSL_clear_options introduced in 0.9.8m */ #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL) - if (info->ssl_client_options_clear) - SSL_CTX_clear_options(vh->tls.ssl_client_ctx, + + /* SSL_clear_options introduced in 0.9.8m */ +#if defined(LWS_WITH_BORINGSSL) + uint32_t +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ + !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ + unsigned long +#else + long +#endif +#endif + + ssl_client_options_clear_value = #if defined(LWS_WITH_BORINGSSL) (uint32_t) #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ - (unsigned long) + (unsigned long) #else - (long) + (long) #endif #endif - info->ssl_client_options_clear); + info->ssl_client_options_clear; + + if (info->ssl_client_options_clear) + SSL_CTX_clear_options(vh->tls.ssl_client_ctx, ssl_client_options_clear_value); #endif if (cipher_list) diff --git a/3rdparty/libwebsockets/lib/tls/openssl/openssl-server.c b/3rdparty/libwebsockets/lib/tls/openssl/openssl-server.c index 24f832e6..34a6ada2 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/openssl-server.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/openssl-server.c @@ -579,8 +579,20 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, __func__); } - if (info->ssl_options_set) - SSL_CTX_set_options(vhost->tls.ssl_ctx, +#if defined(USE_WOLFSSL) + long +#else +#if defined(LWS_WITH_BORINGSSL) + uint32_t +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ + unsigned long +#else + long +#endif +#endif +#endif + ssl_options_set_value = #if defined(USE_WOLFSSL) (long) #else @@ -588,32 +600,50 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, (uint32_t) #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ - (unsigned long) + (unsigned long) #else - (long) + (long) #endif #endif #endif - info->ssl_options_set); + info->ssl_options_set; + + if (info->ssl_options_set) + SSL_CTX_set_options(vhost->tls.ssl_ctx, ssl_options_set_value); -/* SSL_clear_options introduced in 0.9.8m */ #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL) - if (info->ssl_options_clear) - SSL_CTX_clear_options(vhost->tls.ssl_ctx, + +/* SSL_clear_options introduced in 0.9.8m */ #if defined(LWS_WITH_BORINGSSL) - (uint32_t) + uint32_t #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER)/* not documented by openssl */ - (unsigned long) + unsigned long #else - (long) + long #endif #endif - info->ssl_options_clear); + + ssl_options_clear_value = +#if defined(LWS_WITH_BORINGSSL) + (uint32_t) +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER)/* not documented by openssl */ + (unsigned long) +#else + (long) +#endif #endif + info->ssl_options_clear; + + if (info->ssl_options_clear) { + SSL_CTX_clear_options(vhost->tls.ssl_ctx, ssl_options_clear_value); + } lwsl_info(" SSL options 0x%lX\n", (unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx)); +#endif + if (!vhost->tls.use_ssl || (!info->ssl_cert_filepath && !info->server_ssl_cert_mem)) return 0; @@ -682,7 +712,8 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) int lws_tls_server_abort_connection(struct lws *wsi) { - SSL_shutdown(wsi->tls.ssl); + if (wsi->tls.use_ssl) + SSL_shutdown(wsi->tls.ssl); SSL_free(wsi->tls.ssl); return 0; diff --git a/3rdparty/libwebsockets/lib/tls/openssl/openssl-session.c b/3rdparty/libwebsockets/lib/tls/openssl/openssl-session.c index 2fdf3ff7..e27a8f38 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/openssl-session.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/openssl-session.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2021 Andy Green + * Copyright (C) 2010 - 2022 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 @@ -33,7 +33,12 @@ typedef struct lws_tls_session_cache_openssl { /* name is overallocated here */ } lws_tls_sco_t; -#define lwsl_tlssess lwsl_info +#define tlssess_loglevel LLL_INFO +#if (_LWS_ENABLED_LOGS & tlssess_loglevel) +#define lwsl_tlssess(...) _lws_log(tlssess_loglevel, __VA_ARGS__) +#else +#define lwsl_tlssess(...) +#endif static void __lws_tls_session_destroy(lws_tls_sco_t *ts) @@ -91,9 +96,22 @@ lws_tls_reuse_session(struct lws *wsi) } lwsl_tlssess("%s: %s\n", __func__, (const char *)&ts[1]); - wsi->tls_session_reused = 1; - SSL_set_session(wsi->tls.ssl, ts->session); + if (!SSL_set_session(wsi->tls.ssl, ts->session)) { + lwsl_err("%s: session not set for %s\n", __func__, tag); + goto bail; + } + +#if !defined(USE_WOLFSSL) + /* extend session lifetime */ + SSL_SESSION_set_time(ts->session, +#if defined(OPENSSL_IS_BORINGSSL) + (unsigned long) +#else + (long) +#endif + time(NULL)); +#endif /* keep our session list sorted in lru -> mru order */ @@ -105,6 +123,21 @@ lws_tls_reuse_session(struct lws *wsi) lws_context_unlock(wsi->a.context); /* } cx -------------- */ } +int +lws_tls_session_is_reused(struct lws *wsi) +{ +#if defined(LWS_WITH_CLIENT) + struct lws *nwsi = lws_get_network_wsi(wsi); + + if (!nwsi || !nwsi->tls.ssl) + return 0; + + return (int)SSL_session_reused(nwsi->tls.ssl); +#else + return 0; +#endif +} + static int lws_tls_session_destroy_dll(struct lws_dll2 *d, void *user) { @@ -129,7 +162,6 @@ lws_tls_session_expiry_cb(lws_sorted_usec_list_t *sul) struct lws_vhost *vh = lws_container_of(ts->list.owner, struct lws_vhost, tls_sessions); - lws_sul_cancel(&ts->sul_ttl); lws_context_lock(vh->context, __func__); /* -------------- cx { */ lws_vhost_lock(vh); /* -------------- vh { */ __lws_tls_session_destroy(ts); @@ -184,7 +216,7 @@ lws_tls_session_new_cb(SSL *ssl, SSL_SESSION *sess) struct lws_vhost *vh; lws_tls_sco_t *ts; long ttl; -#if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & tlssess_loglevel) const char *disposition = "reuse"; #endif @@ -220,7 +252,7 @@ lws_tls_session_new_cb(SSL *ssl, SSL_SESSION *sess) lws_tls_session_expiry_cb, ttl * LWS_US_PER_SEC); -#if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & tlssess_loglevel) disposition = "new"; #endif @@ -265,6 +297,47 @@ lws_tls_session_new_cb(SSL *ssl, SSL_SESSION *sess) return 0; } +#if defined(LWS_TLS_SYNTHESIZE_CB) + +/* + * On openssl, there is an async cb coming when the server issues the session + * information on the link, so we can pick it up and update the cache at the + * right time. + * + * On mbedtls and some version at least of borning ssl, this cb is either not + * part of the tls library apis or fails to arrive. + * + * This synthetic cb is called instead for those build cases, scheduled for + * +500ms after the tls negotiation completed. + */ + +void +lws_sess_cache_synth_cb(lws_sorted_usec_list_t *sul) +{ + struct lws_lws_tls *tls = lws_container_of(sul, struct lws_lws_tls, + sul_cb_synth); + struct lws *wsi = lws_container_of(tls, struct lws, tls); + SSL_SESSION *sess; + + if (lws_tls_session_is_reused(wsi)) + return; + + sess = SSL_get1_session(tls->ssl); + if (!sess) + return; + + if (!SSL_SESSION_is_resumable(sess) || /* not worth caching, or... */ + !lws_tls_session_new_cb(tls->ssl, sess)) { /* ...cb didn't keep it */ + /* + * For now the policy if no session message after the wait, + * is just let it be. Typically the session info is sent + * early. + */ + SSL_SESSION_free(sess); + } +} +#endif + void lws_tls_session_cache(struct lws_vhost *vh, uint32_t ttl) { @@ -348,7 +421,7 @@ lws_tls_session_dump_load(struct lws_vhost *vh, const char *host, uint16_t port, { struct lws_tls_session_dump d; lws_tls_sco_t *ts; - SSL_SESSION *sess; + SSL_SESSION *sess = NULL; /* allow it to "bail" early */ void *v; if (vh->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE) @@ -399,11 +472,7 @@ lws_tls_session_dump_load(struct lws_vhost *vh, const char *host, uint16_t port, goto bail; } -#if defined(LWS_HAVE_SSL_SESSION_up_ref) - SSL_SESSION_up_ref(sess); -#else - lwsl_err("%s: openssl is too old\n", __func__); -#endif + ts->session = sess; lwsl_tlssess("%s: session loaded OK\n", __func__); lws_vhost_unlock(vh); /* } vh -------------- */ diff --git a/3rdparty/libwebsockets/lib/tls/openssl/openssl-ssl.c b/3rdparty/libwebsockets/lib/tls/openssl/openssl-ssl.c index 562c352d..cf4d2b8c 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/openssl-ssl.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/openssl-ssl.c @@ -24,7 +24,6 @@ #include "private-lib-core.h" #include "private-lib-tls-openssl.h" -#include int openssl_websocket_private_data_index, openssl_SSL_CTX_private_data_index; @@ -57,12 +56,11 @@ int lws_ssl_get_error(struct lws *wsi, int n) return 99; m = SSL_get_error(wsi->tls.ssl, n); - lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, - errno); + lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, LWS_ERRNO); if (m == SSL_ERROR_SSL) lws_tls_err_describe_clear(); - // assert (errno != 9); + // assert (LWS_ERRNO != 9); return m; } @@ -207,7 +205,11 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) if (!wsi->tls.ssl) return lws_ssl_capable_read_no_ssl(wsi, buf, len); +#ifndef WIN32 errno = 0; +#else + WSASetLastError(0); +#endif ERR_clear_error(); n = SSL_read(wsi->tls.ssl, buf, (int)(ssize_t)len); #if defined(LWS_PLAT_FREERTOS) @@ -244,14 +246,14 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) */ if (n <= 0) { m = lws_ssl_get_error(wsi, n); - lwsl_debug("%s: ssl err %d errno %d\n", lws_wsi_tag(wsi), m, errno); + lwsl_debug("%s: ssl err %d errno %d\n", lws_wsi_tag(wsi), m, LWS_ERRNO); if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */ goto do_err; /* hm not retryable.. could be 0 size pkt or error */ if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL || - errno == LWS_ENOTCONN) { + LWS_ERRNO == LWS_ENOTCONN) { /* unclean, eg closed conn */ @@ -273,8 +275,10 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) return LWS_SSL_CAPABLE_MORE_SERVICE; } if (SSL_want_write(wsi->tls.ssl)) { - lwsl_debug("%s: WANT_WRITE\n", __func__); + lwsl_info("%s: WANT_WRITE\n", __func__); lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); + wsi->tls_read_wanted_write = 1; + lws_callback_on_writable(wsi); return LWS_SSL_CAPABLE_MORE_SERVICE; } @@ -449,6 +453,15 @@ lws_ssl_close(struct lws *wsi) SSL_set_info_callback(wsi->tls.ssl, NULL); #endif +#if defined(LWS_TLS_SYNTHESIZE_CB) + lws_sul_cancel(&wsi->tls.sul_cb_synth); + /* + * ... check the session in case it did not live long enough to get + * the scheduled callback to sample it + */ + lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth); +#endif + n = SSL_get_fd(wsi->tls.ssl); if (!wsi->socket_is_permanently_unusable) SSL_shutdown(wsi->tls.ssl); @@ -456,7 +469,7 @@ lws_ssl_close(struct lws *wsi) SSL_free(wsi->tls.ssl); wsi->tls.ssl = NULL; - lws_tls_restrict_return(wsi->a.context); + lws_tls_restrict_return(wsi); // lwsl_notice("%s: ssl restr %d, simul %d\n", __func__, // wsi->a.context->simultaneous_ssl_restriction, @@ -521,7 +534,11 @@ __lws_tls_shutdown(struct lws *wsi) { int n; +#ifndef WIN32 errno = 0; +#else + WSASetLastError(0); +#endif ERR_clear_error(); n = SSL_shutdown(wsi->tls.ssl); lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); diff --git a/3rdparty/libwebsockets/lib/tls/openssl/openssl-tls.c b/3rdparty/libwebsockets/lib/tls/openssl/openssl-tls.c index 435903f1..577acf35 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/openssl-tls.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/openssl-tls.c @@ -31,45 +31,6 @@ extern int openssl_websocket_private_data_index, static char openssl_ex_indexes_acquired; #endif -char* lws_ssl_get_error_string(int status, int ret, char *buf, size_t len) { - switch (status) { - case SSL_ERROR_NONE: - return lws_strncpy(buf, "SSL_ERROR_NONE", len); - case SSL_ERROR_ZERO_RETURN: - return lws_strncpy(buf, "SSL_ERROR_ZERO_RETURN", len); - case SSL_ERROR_WANT_READ: - return lws_strncpy(buf, "SSL_ERROR_WANT_READ", len); - case SSL_ERROR_WANT_WRITE: - return lws_strncpy(buf, "SSL_ERROR_WANT_WRITE", len); - case SSL_ERROR_WANT_CONNECT: - return lws_strncpy(buf, "SSL_ERROR_WANT_CONNECT", len); - case SSL_ERROR_WANT_ACCEPT: - return lws_strncpy(buf, "SSL_ERROR_WANT_ACCEPT", len); - case SSL_ERROR_WANT_X509_LOOKUP: - return lws_strncpy(buf, "SSL_ERROR_WANT_X509_LOOKUP", len); - case SSL_ERROR_SYSCALL: - switch (ret) { - case 0: - lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF"); - return buf; - case -1: -#ifndef LWS_PLAT_OPTEE - lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %s", - strerror(errno)); -#else - lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno); -#endif - return buf; - default: - return strncpy(buf, "SSL_ERROR_SYSCALL", len); - } - case SSL_ERROR_SSL: - return "SSL_ERROR_SSL"; - default: - return "SSL_ERROR_UNKNOWN"; - } -} - void lws_tls_err_describe_clear(void) { @@ -118,32 +79,32 @@ lws_openssl_thread_id(void) } #endif - int -lws_context_init_ssl_library(const struct lws_context_creation_info *info) +lws_context_init_ssl_library(struct lws_context *cx, + const struct lws_context_creation_info *info) { #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL - lwsl_info(" Compiled with CyaSSL support\n"); + lwsl_cx_info(cx, " Compiled with CyaSSL support"); #else - lwsl_info(" Compiled with wolfSSL support\n"); + lwsl_cx_info(cx, " Compiled with wolfSSL support"); #endif #else #if defined(LWS_WITH_BORINGSSL) - lwsl_info(" Compiled with BoringSSL support\n"); + lwsl_cx_info(cx, " Compiled with BoringSSL support"); #else - lwsl_info(" Compiled with OpenSSL support\n"); + lwsl_cx_info(cx, " Compiled with OpenSSL support"); #endif #endif if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { - lwsl_info(" SSL disabled: no " - "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n"); + lwsl_cx_info(cx, " SSL disabled: no " + "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT"); return 0; } /* basic openssl init */ - lwsl_info("Doing SSL library init\n"); + lwsl_cx_info(cx, "Doing SSL library init"); #if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_library_init(); diff --git a/3rdparty/libwebsockets/lib/tls/openssl/openssl-x509.c b/3rdparty/libwebsockets/lib/tls/openssl/openssl-x509.c index 6ba59b2b..dac4aa39 100644 --- a/3rdparty/libwebsockets/lib/tls/openssl/openssl-x509.c +++ b/3rdparty/libwebsockets/lib/tls/openssl/openssl-x509.c @@ -71,17 +71,33 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as) #endif } +#if defined(USE_WOLFSSL) +#define AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID +#endif + int lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type, union lws_tls_cert_info_results *buf, size_t len) { +#ifndef USE_WOLFSSL + const unsigned char *dp; + ASN1_OCTET_STRING *val; + AUTHORITY_KEYID *akid; + X509_EXTENSION *ext; + int tag, xclass, r = 1; + long xlen, loc; +#endif X509_NAME *xn; #if !defined(LWS_PLAT_OPTEE) char *p; #endif + buf->ns.len = 0; + if (!x509) return -1; + if (!len) + len = sizeof(buf->ns.name); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore) #define X509_get_notBefore(x) X509_getm_notBefore(x) @@ -180,6 +196,151 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type, return 0; } + +#ifndef USE_WOLFSSL + + case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID: + loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); + if (loc < 0) + return 1; + + ext = X509_get_ext(x509, (int)loc); + if (!ext) + return 1; +#ifndef USE_WOLFSSL + akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext); +#else + akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext); +#endif + if (!akid || !akid->keyid) + return 1; + val = akid->keyid; + dp = (const unsigned char *)val->data; + xlen = val->length; + + buf->ns.len = (int)xlen; + if (len < (size_t)buf->ns.len) + return -1; + + memcpy(buf->ns.name, dp, (size_t)buf->ns.len); + + AUTHORITY_KEYID_free(akid); + break; + + case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: + loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); + if (loc < 0) + return 1; + + ext = X509_get_ext(x509, (int)loc); + if (!ext) + return 1; + +#ifndef USE_WOLFSSL + akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext); +#else + akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext); +#endif + if (!akid || !akid->issuer) + return 1; + +#if defined(LWS_HAVE_OPENSSL_STACK) + { + const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext); + STACK_OF(CONF_VALUE) *cv; + int j; + + cv = i2v_GENERAL_NAMES((X509V3_EXT_METHOD*)method, akid->issuer, NULL); + if (!cv) + goto bail_ak; + + for (j = 0; j < OPENSSL_sk_num((const OPENSSL_STACK *)&cv); j++) { + CONF_VALUE *nval = OPENSSL_sk_value((const OPENSSL_STACK *)&cv, j); + size_t ln = (nval->name ? strlen(nval->name) : 0), + lv = (nval->value ? strlen(nval->value) : 0), + l = ln + lv; + + if (len > l) { + if (nval->name) + memcpy(buf->ns.name + buf->ns.len, nval->name, ln); + if (nval->value) + memcpy(buf->ns.name + buf->ns.len + ln, nval->value, lv); + buf->ns.len = (int)((size_t)buf->ns.len + l); + len -= l; + buf->ns.name[buf->ns.len] = '\0'; + + r = 0; + } + } + } + +bail_ak: +#endif + AUTHORITY_KEYID_free(akid); + + return r; + + case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL: + loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); + if (loc < 0) + return 1; + + ext = X509_get_ext(x509, (int)loc); + if (!ext) + return 1; + akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext); + if (!akid || !akid->serial) + return 1; + +#if 0 + // need to handle blobs, and ASN1_INTEGER_get_uint64 not + // available on older openssl + { + uint64_t res; + if (ASN1_INTEGER_get_uint64(&res, akid->serial) != 1) + break; + buf->ns.len = lws_snprintf(buf->ns.name, len, "%llu", + (unsigned long long)res); + } +#endif + break; + + case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID: + + loc = X509_get_ext_by_NID(x509, NID_subject_key_identifier, -1); + if (loc < 0) + return 1; + + ext = X509_get_ext(x509, (int)loc); + if (!ext) + return 1; + + val = X509_EXTENSION_get_data(ext); + if (!val) + return 1; + +#if defined(USE_WOLFSSL) + return 1; +#else + dp = (const unsigned char *)val->data; + + if (ASN1_get_object(&dp, &xlen, + &tag, &xclass, val->length) & 0x80) + return -1; + + if (tag != V_ASN1_OCTET_STRING) { + lwsl_notice("not octet string %d\n", (int)tag); + return 1; + } +#endif + buf->ns.len = (int)xlen; + if (len < (size_t)buf->ns.len) + return -1; + + memcpy(buf->ns.name, dp, (size_t)buf->ns.len); + break; +#endif + default: return -1; } @@ -502,8 +663,8 @@ lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u) } int -lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, - const char *passphrase) +lws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk, + void *pem, size_t len, const char *passphrase) { BIO* bio = BIO_new(BIO_s_mem()); BIGNUM *mpi, *dummy[6]; @@ -579,7 +740,7 @@ lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len, goto bail; } -#if defined(LWS_HAVE_RSA_SET0_KEY) +#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL) RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */ (const BIGNUM **)&dummy[1], /* e */ (const BIGNUM **)&mpi); /* d */ diff --git a/3rdparty/libwebsockets/lib/tls/private-jit-trust.h b/3rdparty/libwebsockets/lib/tls/private-jit-trust.h new file mode 100644 index 00000000..521c3a25 --- /dev/null +++ b/3rdparty/libwebsockets/lib/tls/private-jit-trust.h @@ -0,0 +1,149 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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 included from private-lib-core.h if LWS_WITH_TLS + * + * First-party trusted certs are handled outside of JIT Trust, eg, in SS policy. + * JIT Trust is used to validate arbitrary connections on demand, without + * needing a complete set of CAs in memory. + * + * Instantiated CA X509s are bound to dedicated SSL_CTX in their own dynamic + * vhosts for client connections to use, these are lazily culled when they have + * no remaining active connections using them. + * + * - check jit trust cache to see if hostname has vhost already + * - if so, use it + * - if not, check jit trust cache to see if we know the trusted kids list, + * - attempt connection + * - remote or local trust blob / store + */ + +#if !defined(__LWS_TLS_PRIVATE_JIT_TRUST_H__) +#define __LWS_TLS_PRIVATE_JIT_TRUST_H__ + +/* + * Refer to ./READMEs/README.jit-trust.md for blob layout specification + */ + +#define LWS_JIT_TRUST_MAGIC_BE 0x54424c42 + +enum { + LJT_OFS_32_COUNT_CERTS = 6, + LJT_OFS_32_DERLEN = 0x0c, + LJT_OFS_32_SKIDLEN = 0x10, + LJT_OFS_32_SKID = 0x14, + LJT_OFS_END = 0x18, + + LJT_OFS_DER = 0x1c, +}; + +typedef struct { + uint8_t kid[20]; + uint8_t kid_len; +} lws_tls_kid_t; + +typedef struct { + lws_tls_kid_t akid[4]; + lws_tls_kid_t skid[4]; + uint8_t count; +} lws_tls_kid_chain_t; + +/* + * This is used to manage ongoing jit trust lookups for a specific host. It + * collects results and any trusted DER certs until all of them have arrived, + * then caches the hostname -> trusted SKIDs mapping, and creates a vhost + + * SSL_CTX trusting the certs named after the trusted SKIDs. + * + * The cert copies and this inflight object are then freed. + * + * JIT Trust lookups may be async, there may be multiple lookups fired at one + * time, and these mappings are not actually related to a wsi lifetime, so these + * separate inflight tracking objects are needed. + * + * These objects only live until all the AKID lookups for the host that created + * them complete. + */ + +typedef struct { + lws_dll2_t list; + + lws_tls_kid_t kid[2]; /* SKID of the der if any */ + uint8_t *der[2]; /* temp allocated */ + + int ders; + + uint32_t tag; /* xor'd from start of SKIDs that + * that contributed certs, so we + * can name the vhost in a way that + * can be regenerated no matter + * the order of SKID results + */ + + short der_len[2]; + + char refcount; /* expected results left */ + + /* hostname overcommitted */ +} lws_tls_jit_inflight_t; + +/* + * These are the items in the jit trust cache, the cache tag is the hostname + * and it resolves to one of these if present. It describes 1 - 3 SKIDs + * of trusted CAs needed to validate that host, and a 32-bit tag that is + * the first 4 bytes of each valid SKID xor'd together, so you can find any + * existing vhost that already has the required trust (independent of the + * order they are checked in due to commutative xor). + */ + +typedef struct { + lws_tls_kid_t skids[3]; + int count_skids; + uint32_t xor_tag; +} lws_tls_jit_cache_item_t; + +union lws_tls_cert_info_results; + +void +lws_tls_kid_copy(union lws_tls_cert_info_results *ci, lws_tls_kid_t *kid); + +int +lws_tls_kid_cmp(const lws_tls_kid_t *a, const lws_tls_kid_t *b); + +int +lws_tls_jit_trust_sort_kids(struct lws *wsi, lws_tls_kid_chain_t *ch); + +void +lws_tls_jit_trust_inflight_destroy(lws_tls_jit_inflight_t *inf); + +void +lws_tls_jit_trust_inflight_destroy_all(struct lws_context *cx); + +int +lws_tls_jit_trust_vhost_bind(struct lws_context *cx, const char *address, + struct lws_vhost **pvh); + +void +lws_tls_jit_trust_vh_start_grace(struct lws_vhost *vh); + +#endif + diff --git a/3rdparty/libwebsockets/lib/tls/private-lib-tls.h b/3rdparty/libwebsockets/lib/tls/private-lib-tls.h index 3244c4ae..28203c58 100644 --- a/3rdparty/libwebsockets/lib/tls/private-lib-tls.h +++ b/3rdparty/libwebsockets/lib/tls/private-lib-tls.h @@ -30,6 +30,8 @@ #if defined(LWS_WITH_TLS) +#include "private-jit-trust.h" + #if defined(USE_WOLFSSL) #if defined(USE_OLD_CYASSL) #if defined(_WIN32) @@ -118,11 +120,19 @@ enum lws_tls_extant { #if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_WITH_CLIENT) && \ + (defined(LWS_WITH_MBEDTLS) || defined(OPENSSL_IS_BORINGSSL)) +#define LWS_TLS_SYNTHESIZE_CB 1 +#endif + int -lws_tls_restrict_borrow(struct lws_context *context); +lws_tls_restrict_borrow(struct lws *wsi); + +void +lws_tls_restrict_return(struct lws *wsi); void -lws_tls_restrict_return(struct lws_context *context); +lws_tls_restrict_return_handshake(struct lws *wsi); typedef SSL lws_tls_conn; typedef SSL_CTX lws_tls_ctx; @@ -134,7 +144,8 @@ typedef X509 lws_tls_x509; #endif int -lws_context_init_ssl_library(const struct lws_context_creation_info *info); +lws_context_init_ssl_library(struct lws_context *cx, + const struct lws_context_creation_info *info); void lws_context_deinit_ssl_library(struct lws_context *context); #define LWS_SSL_ENABLED(vh) (vh && vh->tls.use_ssl) @@ -163,8 +174,6 @@ int lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, const char *inbuf, lws_filepos_t inlen, uint8_t **buf, lws_filepos_t *amount); -char * -lws_ssl_get_error_string(int status, int ret, char *buf, size_t len); int lws_gencrypto_bits_to_bytes(int bits); diff --git a/3rdparty/libwebsockets/lib/tls/private-network.h b/3rdparty/libwebsockets/lib/tls/private-network.h index 26ff5b40..9c26f0b9 100644 --- a/3rdparty/libwebsockets/lib/tls/private-network.h +++ b/3rdparty/libwebsockets/lib/tls/private-network.h @@ -75,11 +75,19 @@ struct lws_vhost_tls { }; struct lws_lws_tls { - lws_tls_conn *ssl; - lws_tls_bio *client_bio; - struct lws_dll2 dll_pending_tls; - unsigned int use_ssl; - unsigned int redirect_to_https:1; + lws_tls_conn *ssl; + lws_tls_bio *client_bio; +#if defined(LWS_TLS_SYNTHESIZE_CB) + lws_sorted_usec_list_t sul_cb_synth; +#endif +#if !defined(LWS_WITH_MBEDTLS) && defined(LWS_WITH_TLS_JIT_TRUST) + /* mbedtls has this in the wrapper, since no wsi ptr at validation */ + lws_tls_kid_chain_t kid_chain; +#endif + struct lws_dll2 dll_pending_tls; + char err_helper[32]; + unsigned int use_ssl; + unsigned int redirect_to_https:1; }; @@ -94,6 +102,10 @@ lws_ssl_pending(struct lws *wsi); int LWS_WARN_UNUSED_RESULT lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd, char is_pollin); + +void +lws_sess_cache_synth_cb(lws_sorted_usec_list_t *sul); + int lws_ssl_close(struct lws *wsi); void diff --git a/3rdparty/libwebsockets/lib/tls/tls-client.c b/3rdparty/libwebsockets/lib/tls/tls-client.c index 9b5003f1..5b29923f 100644 --- a/3rdparty/libwebsockets/lib/tls/tls-client.c +++ b/3rdparty/libwebsockets/lib/tls/tls-client.c @@ -32,8 +32,10 @@ lws_ssl_client_connect1(struct lws *wsi, char *errbuf, size_t len) n = lws_tls_client_connect(wsi, errbuf, len); switch (n) { case LWS_SSL_CAPABLE_ERROR: + lws_tls_restrict_return_handshake(wsi); return -1; case LWS_SSL_CAPABLE_DONE: + lws_tls_restrict_return_handshake(wsi); lws_metrics_caliper_report(wsi->cal_conn, METRES_GO); #if defined(LWS_WITH_CONMON) wsi->conmon.ciu_tls = (lws_conmon_interval_us_t) @@ -63,6 +65,13 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, size_t len) switch (n) { case LWS_SSL_CAPABLE_ERROR: + lws_tls_restrict_return_handshake(wsi); + + if (lws_tls_client_confirm_peer_cert(wsi, errbuf, len)) { + lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); + return -1; + } + // lws_snprintf(errbuf, len, "client connect failed"); return -1; case LWS_SSL_CAPABLE_DONE: @@ -74,10 +83,12 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, size_t len) lwsi_set_state(wsi, LRS_WAITING_SSL); /* fallthru */ case LWS_SSL_CAPABLE_MORE_SERVICE: - return 0; + return 0; /* retry */ } } + lws_tls_restrict_return_handshake(wsi); + if (lws_tls_client_confirm_peer_cert(wsi, errbuf, len)) { lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); return -1; @@ -89,7 +100,7 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, size_t len) (lws_now_usecs() - wsi->conmon_datum); #endif - return 1; + return 1; /* connected */ } @@ -176,29 +187,28 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, int lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) { - /* we can retry this... just cook the SSL BIO the first time */ if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { int n; if (!wsi->tls.ssl) { - if (lws_ssl_client_bio_create(wsi) < 0) { - *pcce = "bio_create failed"; - return CCTLS_RETURN_ERROR; - } #if defined(LWS_WITH_TLS) if (!wsi->transaction_from_pipeline_queue && - lws_tls_restrict_borrow(wsi->a.context)) { + lws_tls_restrict_borrow(wsi)) { *pcce = "tls restriction limit"; return CCTLS_RETURN_ERROR; } #endif + if (lws_ssl_client_bio_create(wsi) < 0) { + *pcce = "bio_create failed"; + return CCTLS_RETURN_ERROR; + } } if (!do_c1) - return 0; + return CCTLS_RETURN_DONE; lws_metrics_caliper_report(wsi->cal_conn, METRES_GO); lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mt_conn_tls); @@ -211,39 +221,18 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) lwsl_debug("%s: lws_ssl_client_connect1: %d\n", __func__, n); if (!n) return CCTLS_RETURN_RETRY; /* caller should return 0 */ + if (n < 0) { *pcce = (const char *)wsi->a.context->pt[(int)wsi->tsi].serv_buf; lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); return CCTLS_RETURN_ERROR; } /* ...connect1 already handled caliper if SSL_accept done */ - } else - wsi->tls.ssl = NULL; -#if 0 -#if defined (LWS_WITH_HTTP2) - if (wsi->client_h2_alpn) { - /* - * We connected to the server and set up tls, and - * negotiated "h2". - * - * So this is it, we are an h2 nwsi client connection - * now, not an h1 client connection. - */ -#if defined(LWS_WITH_TLS) lws_tls_server_conn_alpn(wsi); -#endif - /* send the H2 preface to legitimize the connection */ - if (lws_h2_issue_preface(wsi)) { - *pcce = "error sending h2 preface"; - return CCTLS_RETURN_ERROR; - } - - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); - } -#endif -#endif + } else + wsi->tls.ssl = NULL; return CCTLS_RETURN_DONE; /* OK */ } diff --git a/3rdparty/libwebsockets/lib/tls/tls-jit-trust.c b/3rdparty/libwebsockets/lib/tls/tls-jit-trust.c new file mode 100644 index 00000000..f7802995 --- /dev/null +++ b/3rdparty/libwebsockets/lib/tls/tls-jit-trust.c @@ -0,0 +1,689 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 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" + +void +lws_tls_kid_copy(union lws_tls_cert_info_results *ci, lws_tls_kid_t *kid) +{ + + /* + * KIDs all seem to be 20 bytes / SHA1 or less. If we get one that + * is bigger, treat only the first 20 bytes as significant. + */ + + if ((size_t)ci->ns.len > sizeof(kid->kid)) + kid->kid_len = sizeof(kid->kid); + else + kid->kid_len = (uint8_t)ci->ns.len; + + memcpy(kid->kid, ci->ns.name, kid->kid_len); +} + +void +lws_tls_kid_copy_kid(lws_tls_kid_t *kid, const lws_tls_kid_t *src) +{ + int klen = sizeof(kid->kid); + + if (src->kid_len < klen) + klen = src->kid_len; + + kid->kid_len = (uint8_t)klen; + + memcpy(kid->kid, src->kid, (size_t)klen); +} + +int +lws_tls_kid_cmp(const lws_tls_kid_t *a, const lws_tls_kid_t *b) +{ + if (a->kid_len != b->kid_len) + return 1; + + return memcmp(a->kid, b->kid, a->kid_len); +} + +/* + * We have the SKID and AKID for every peer cert captured, but they may be + * in any order, and eg, falsely have sent the root CA, or an attacker may + * send unresolveable self-referencing loops of KIDs. + * + * Let's sort them into the SKID -> AKID hierarchy, so the last entry is the + * server cert and the first entry is the highest parent that the server sent. + * Normally the top one will be an intermediate, and its AKID is the ID of the + * root CA cert we would need to trust to validate the chain. + * + * It's not unknown the server is misconfigured to also send the root CA, if so + * the top slot's AKID is empty and we should look for its SKID in the trust + * blob. + * + * If we return 0, we succeeded and the AKID of ch[0] is the SKID we want to see + * try to import from the trust blob. + * + * If we return nonzero, we can't identify what we want and should abandon the + * connection. + */ + +int +lws_tls_jit_trust_sort_kids(struct lws *wsi, lws_tls_kid_chain_t *ch) +{ + size_t hl; + lws_tls_jit_inflight_t *inf; + int n, m, sanity = 10; + const char *host = wsi->cli_hostname_copy; + char more = 1; + + lwsl_info("%s\n", __func__); + + if (!host) { + if (wsi->stash && wsi->stash->cis[CIS_HOST]) + host = wsi->stash->cis[CIS_HOST]; +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + else + host = lws_hdr_simple_ptr(wsi, + _WSI_TOKEN_CLIENT_PEER_ADDRESS); + } +#endif + if (!host) + return 1; + + hl = strlen(host); + + /* something to work with? */ + + if (!ch->count) + return 1; + + /* do we need to sort? */ + + if (ch->count > 1) { + + /* okie... */ + + while (more) { + + if (!sanity--) + /* let's not get fooled into spinning */ + return 1; + + more = 0; + for (n = 0; n < ch->count - 1; n++) { + + if (!lws_tls_kid_cmp(&ch->skid[n], + &ch->akid[n + 1])) + /* next belongs with this one */ + continue; + + /* + * next doesn't belong with this one, let's + * try to figure out where this one does belong + * then + */ + + for (m = 0; m < ch->count; m++) { + if (n == m) + continue; + if (!lws_tls_kid_cmp(&ch->skid[n], + &ch->akid[m])) { + lws_tls_kid_t t; + + /* + * m references us, so we + * need to go one step above m, + * swap m and n + */ + + more = 1; + t = ch->akid[m]; + ch->akid[m] = ch->akid[n]; + ch->akid[n] = t; + t = ch->skid[m]; + ch->skid[m] = ch->skid[n]; + ch->skid[n] = t; + + break; + } + } + + if (more) + break; + } + } + + /* then we should be sorted */ + } + + for (n = 0; n < ch->count; n++) { + lwsl_info("%s: AKID[%d]\n", __func__, n); + lwsl_hexdump_info(ch->akid[n].kid, ch->akid[n].kid_len); + lwsl_info("%s: SKID[%d]\n", __func__, n); + lwsl_hexdump_info(ch->skid[n].kid, ch->skid[n].kid_len); + } + + /* to go further, user must provide a lookup helper */ + + if (!wsi->a.context->system_ops || + !wsi->a.context->system_ops->jit_trust_query) + return 1; + + /* + * If there's already a pending lookup for this host, let's bail and + * just wait for that to complete (since it will be done async if we + * can see it) + */ + + lws_start_foreach_dll(struct lws_dll2 *, d, + wsi->a.context->jit_inflight.head) { + inf = lws_container_of(d, lws_tls_jit_inflight_t, list); + + if (!strcmp((const char *)&inf[1], host)) + /* already being handled */ + return 1; + + } lws_end_foreach_dll(d); + + /* + * No... let's make an inflight entry for this host, then + */ + + inf = lws_zalloc(sizeof(*inf) + hl + 1, __func__); + if (!inf) + return 1; + + memcpy(&inf[1], host, hl + 1); + inf->refcount = (char)ch->count; + lws_dll2_add_tail(&inf->list, &wsi->a.context->jit_inflight); + + /* + * ...kid_chain[0] AKID should indicate the right CA SKID that we want. + * + * Because of cross-signing, we check all of them and accept we may get + * multiple (the inflight accepts up to 2) CAs needed. + */ + + for (n = 0; n < ch->count; n++) + wsi->a.context->system_ops->jit_trust_query(wsi->a.context, + ch->akid[n].kid, (size_t)ch->akid[n].kid_len, + (void *)inf); + + return 0; +} + +static void +tag_to_vh_name(char *result, size_t max, uint32_t tag) +{ + lws_snprintf(result, max, "jitt-%08X", tag); +} + +int +lws_tls_jit_trust_vhost_bind(struct lws_context *cx, const char *address, + struct lws_vhost **pvh) +{ + lws_tls_jit_cache_item_t *ci, jci; + lws_tls_jit_inflight_t *inf; + char vhtag[32]; + size_t size; + int n; + + if (lws_cache_item_get(cx->trust_cache, address, (const void **)&ci, + &size)) + /* + * There's no cached info, we have to start from scratch on + * this one + */ + return 1; + + /* gotten cache item may be evicted by jit_trust_query */ + jci = *ci; + + /* + * We have some trust cache information for this host already, it tells + * us the trusted CA SKIDs we found before, and the xor tag used to name + * the vhost configured for these trust CAs in its SSL_CTX. + * + * Let's check first if the correct prepared vhost already exists, if + * so, we can just bind to that and go. + */ + + tag_to_vh_name(vhtag, sizeof(vhtag), jci.xor_tag); + + *pvh = lws_get_vhost_by_name(cx, vhtag); + if (*pvh) { + lwsl_info("%s: %s -> existing %s\n", __func__, address, vhtag); + /* hit, let's just use that then */ + return 0; + } + + /* + * ... so, we know the SKIDs of the missing CAs, but we don't have the + * DERs for them, and so no configured vhost trusting them yet. We have + * had the DERs at some point, but we can't afford to cache them, so + * we will have to get them again. + * + * Let's make an inflight for this, it will create the vhost when it + * completes. If syncrhronous, then it will complete before we leave + * here, otherwise it will have a life of its own until all the + * queries use the cb to succeed or fail. + */ + + size = strlen(address); + inf = lws_zalloc(sizeof(*inf) + size + 1, __func__); + if (!inf) + return 1; + + memcpy(&inf[1], address, size + 1); + inf->refcount = (char)jci.count_skids; + lws_dll2_add_tail(&inf->list, &cx->jit_inflight); + + /* + * ...kid_chain[0] AKID should indicate the right CA SKID that we want. + * + * Because of cross-signing, we check all of them and accept we may get + * multiple (we can handle 3) CAs needed. + */ + + for (n = 0; n < jci.count_skids; n++) + cx->system_ops->jit_trust_query(cx, jci.skids[n].kid, + (size_t)jci.skids[n].kid_len, + (void *)inf); + + /* ... in case synchronous and it already finished the queries */ + + *pvh = lws_get_vhost_by_name(cx, vhtag); + if (*pvh) { + /* hit, let's just use that then */ + lwsl_info("%s: bind to created vhost %s\n", __func__, vhtag); + return 0; + } else + lwsl_err("%s: unable to bind to %s\n", __func__, vhtag); + + /* right now, nothing to offer */ + + return 1; +} + +void +lws_tls_jit_trust_inflight_destroy(lws_tls_jit_inflight_t *inf) +{ + int n; + + for (n = 0; n < inf->ders; n++) + lws_free_set_NULL(inf->der[n]); + lws_dll2_remove(&inf->list); + + lws_free(inf); +} + +static int +inflight_destroy(struct lws_dll2 *d, void *user) +{ + lws_tls_jit_inflight_t *inf; + + inf = lws_container_of(d, lws_tls_jit_inflight_t, list); + + lws_tls_jit_trust_inflight_destroy(inf); + + return 0; +} + +void +lws_tls_jit_trust_inflight_destroy_all(struct lws_context *cx) +{ + lws_dll2_foreach_safe(&cx->jit_inflight, cx, inflight_destroy); +} + +static void +unref_vh_grace_cb(lws_sorted_usec_list_t *sul) +{ + struct lws_vhost *vh = lws_container_of(sul, struct lws_vhost, + sul_unref); + + lwsl_info("%s: %s\n", __func__, vh->lc.gutag); + + lws_vhost_destroy(vh); +} + +void +lws_tls_jit_trust_vh_start_grace(struct lws_vhost *vh) +{ + lwsl_info("%s: %s: unused, grace %dms\n", __func__, vh->lc.gutag, + vh->context->vh_idle_grace_ms); + lws_sul_schedule(vh->context, 0, &vh->sul_unref, unref_vh_grace_cb, + (lws_usec_t)vh->context->vh_idle_grace_ms * + LWS_US_PER_MS); +} + +#if defined(_DEBUG) +static void +lws_tls_jit_trust_cert_info(const uint8_t *der, size_t der_len) +{ + struct lws_x509_cert *x; + union lws_tls_cert_info_results *u; + char p = 0, buf[192 + sizeof(*u)]; + + if (lws_x509_create(&x)) + return; + + if (!lws_x509_parse_from_pem(x, der, der_len)) { + + u = (union lws_tls_cert_info_results *)buf; + + if (!lws_x509_info(x, LWS_TLS_CERT_INFO_ISSUER_NAME, u, 192)) { + lwsl_info("ISS: %s\n", u->ns.name); + p = 1; + } + if (!lws_x509_info(x, LWS_TLS_CERT_INFO_COMMON_NAME, u, 192)) { + lwsl_info("CN: %s\n", u->ns.name); + p = 1; + } + + if (!p) { + lwsl_err("%s: unable to get any info\n", __func__); + lwsl_hexdump_err(der, der_len); + } + } else + lwsl_err("%s: unable to load DER\n", __func__); + + lws_x509_destroy(&x); +} +#endif + +/* + * This processes the JIT Trust lookup results independent of the tls backend. + */ + +int +lws_tls_jit_trust_got_cert_cb(struct lws_context *cx, void *got_opaque, + const uint8_t *skid, size_t skid_len, + const uint8_t *der, size_t der_len) +{ + lws_tls_jit_inflight_t *inf = (lws_tls_jit_inflight_t *)got_opaque; + struct lws_context_creation_info info; + lws_tls_jit_cache_item_t jci; + struct lws_vhost *v; + char vhtag[20]; + char hit = 0; + int n; + + /* + * Before anything else, check the inf is still valid. In the low + * probability but possible case it was reallocated to be a different + * inflight, that may cause different CA certs to apply to a connection, + * but since mbedtls will then validate the server cert using the wrong + * trusted CA, it will just cause temporary conn fail. + */ + + lws_start_foreach_dll(struct lws_dll2 *, e, cx->jit_inflight.head) { + lws_tls_jit_inflight_t *i = lws_container_of(e, + lws_tls_jit_inflight_t, list); + if (i == inf) { + hit = 1; + break; + } + + } lws_end_foreach_dll(e); + + if (!hit) + /* inf has already gone */ + return 1; + + inf->refcount--; + + if (skid_len >= 4) + inf->tag ^= *((uint32_t *)skid); + + if (der && inf->ders < (int)LWS_ARRAY_SIZE(inf->der) && inf->refcount) { + /* + * We have a trusted CA, but more results coming... stash it + * in heap. + */ + + inf->kid[inf->ders].kid_len = (uint8_t)((skid_len > + (uint8_t)sizeof(inf->kid[inf->ders].kid)) ? + sizeof(inf->kid[inf->ders].kid) : skid_len); + memcpy(inf->kid[inf->ders].kid, skid, + inf->kid[inf->ders].kid_len); + + inf->der[inf->ders] = lws_malloc(der_len, __func__); + if (!inf->der[inf->ders]) + return 1; + memcpy(inf->der[inf->ders], der, der_len); + inf->der_len[inf->ders] = (short)der_len; + inf->ders++; + + return 0; + } + + /* + * We accept up to three valid CA, and then end the inflight early. + * Any further pending results are dropped, since we got all we could + * use. Up to two valid CA would be held in the inflight and the other + * provided in the params. + * + * If we did not already fill up the inflight, keep waiting for any + * others expected + */ + + if (inf->refcount && inf->ders < (int)LWS_ARRAY_SIZE(inf->der)) + return 0; + + if (!der && !inf->ders) { + lwsl_warn("%s: no trusted CA certs matching\n", __func__); + + goto destroy_inf; + } + + tag_to_vh_name(vhtag, sizeof(vhtag), inf->tag); + + /* + * We have got at least one CA, it's all the CAs we're going to get, + * or that we can handle. So we have to process and drop the inf. + * + * First let's make a cache entry with a shortish ttl, mapping the + * hostname we were trying to connect to, to the SKIDs that actually + * had trust results. This may come in handy later when we want to + * connect to the same host again, but any vhost from before has been + * removed... we can just ask for the specific CAs to regenerate the + * vhost, without having to first fail the connection attempt to get the + * server cert. + * + * The cache entry can be evicted at any time, so it is selfcontained. + * If it's also lost, we start over with the initial failing connection + * to figure out what we need to make it work. + */ + + memset(&jci, 0, sizeof(jci)); + + jci.xor_tag = inf->tag; + + /* copy the SKIDs from the inflight and params into the cache item */ + + for (n = 0; n < (int)LWS_ARRAY_SIZE(inf->der); n++) + if (inf->kid[n].kid_len) + lws_tls_kid_copy_kid(&jci.skids[jci.count_skids++], + &inf->kid[n]); + + if (skid_len) { + if (skid_len > sizeof(inf->kid[0].kid)) + skid_len = sizeof(inf->kid[0].kid); + jci.skids[jci.count_skids].kid_len = (uint8_t)skid_len; + memcpy(jci.skids[jci.count_skids++].kid, skid, skid_len); + } + + lwsl_info("%s: adding cache mapping %s -> %s\n", __func__, + (const char *)&inf[1], vhtag); + + if (lws_cache_write_through(cx->trust_cache, (const char *)&inf[1], + (const uint8_t *)&jci, sizeof(jci), + lws_now_usecs() + (3600ll *LWS_US_PER_SEC), + NULL)) + lwsl_warn("%s: add to cache failed\n", __func__); + + /* is there already a vhost for this commutative-xor SKID trust? */ + + if (lws_get_vhost_by_name(cx, vhtag)) { + lwsl_info("%s: tag vhost %s already exists, skipping\n", + __func__, vhtag); + goto destroy_inf; + } + + /* + * We only end up here when we attempted a connection to this hostname. + * + * We have the identified CA trust DER(s) to hand, let's create the + * necessary vhost + prepared SSL_CTX for it to use on the retry, it + * will be used straight away if the retry comes before the idle vhost + * timeout. + * + * We also use this path in the case we have the cache entry but no + * matching vhost already existing, to create one. + */ + + memset(&info, 0, sizeof(info)); + info.vhost_name = vhtag; + info.port = CONTEXT_PORT_NO_LISTEN; + info.options = cx->options; + + /* + * We have to create the vhost with the first valid trusted DER... + * if we have a params one, use that so the rest are all from inflight + */ + + if (der) { + info.client_ssl_ca_mem = der; + info.client_ssl_ca_mem_len = (unsigned int)der_len; + n = 0; + } else { + info.client_ssl_ca_mem = inf->der[0]; + info.client_ssl_ca_mem_len = (unsigned int)inf->der_len[0]; + n = 1; + } + +#if defined(_DEBUG) + lws_tls_jit_trust_cert_info(info.client_ssl_ca_mem, + info.client_ssl_ca_mem_len); +#endif + + info.protocols = cx->protocols_copy; + + v = lws_create_vhost(cx, &info); + if (!v) + lwsl_err("%s: failed to create vh %s\n", __func__, vhtag); + + v->grace_after_unref = 1; + lws_tls_jit_trust_vh_start_grace(v); + + /* + * Do we need to add more trusted certs from inflight? + */ + + while (n < inf->ders) { + +#if defined(_DEBUG) + lws_tls_jit_trust_cert_info(inf->der[n], + (size_t)inf->der_len[n]); +#endif + + if (lws_tls_client_vhost_extra_cert_mem(v, inf->der[n], + (size_t)inf->der_len[n])) + lwsl_err("%s: add extra cert failed\n", __func__); + n++; + } + + lwsl_info("%s: created jitt %s -> vh %s\n", __func__, + (const char *)&inf[1], vhtag); + +destroy_inf: + lws_tls_jit_trust_inflight_destroy(inf); + + return 0; +} + +/* + * Refer to ./READMEs/README.jit-trust.md for blob layout specification + */ + +int +lws_tls_jit_trust_blob_queury_skid(const void *_blob, size_t blen, + const uint8_t *skid, size_t skid_len, + const uint8_t **prpder, size_t *prder_len) +{ + const uint8_t *pskidlen, *pskids, *pder, *blob = (uint8_t *)_blob; + const uint16_t *pderlen; + int certs; + + /* sanity check blob length and magic */ + + if (blen < 32768 || + lws_ser_ru32be(blob) != LWS_JIT_TRUST_MAGIC_BE || + lws_ser_ru32be(blob + LJT_OFS_END) != blen) { + lwsl_err("%s: blob not sane\n", __func__); + + return -1; + } + + if (!skid_len) + return 1; + + /* point into the various sub-tables */ + + certs = (int)lws_ser_ru16be(blob + LJT_OFS_32_COUNT_CERTS); + + pderlen = (uint16_t *)(blob + lws_ser_ru32be(blob + + LJT_OFS_32_DERLEN)); + pskidlen = blob + lws_ser_ru32be(blob + LJT_OFS_32_SKIDLEN); + pskids = blob + lws_ser_ru32be(blob + LJT_OFS_32_SKID); + pder = blob + LJT_OFS_DER; + + /* check each cert SKID in turn, return the DER if found */ + + while (certs--) { + + /* paranoia / sanity */ + + assert(pskids < blob + blen); + assert(pder < blob + blen); + assert(pskidlen < blob + blen); + assert((uint8_t *)pderlen < blob + blen); + + /* we will accept to match on truncated SKIDs */ + + if (*pskidlen >= skid_len && + !memcmp(skid, pskids, skid_len)) { + /* + * We found a trusted CA cert of the right SKID + */ + *prpder = pder; + *prder_len = lws_ser_ru16be((uint8_t *)pderlen); + + return 0; + } + + pder += lws_ser_ru16be((uint8_t *)pderlen); + pskids += *pskidlen; + pderlen++; + pskidlen++; + } + + return 1; +} diff --git a/3rdparty/libwebsockets/lib/tls/tls-network.c b/3rdparty/libwebsockets/lib/tls/tls-network.c index c90faa78..ef404aff 100644 --- a/3rdparty/libwebsockets/lib/tls/tls-network.c +++ b/3rdparty/libwebsockets/lib/tls/tls-network.c @@ -90,10 +90,10 @@ lws_tls_check_cert_lifetime(struct lws_vhost *v) return 1; life = (ir.time - now) / (24 * 3600); - lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name, + lwsl_vhost_notice(v, " vhost %s: cert expiry: %dd", v->name, (int)life); } else - lwsl_info(" vhost %s: no cert\n", v->name); + lwsl_vhost_info(v, " vhost %s: no cert", v->name); memset(&caa, 0, sizeof(caa)); caa.vh = v; @@ -151,7 +151,7 @@ lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert, if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) && (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) { - lwsl_notice("Ignoring missing %s or %s\n", cert, private_key); + lwsl_vhost_notice(vhost, "Ignoring missing %s or %s", cert, private_key); vhost->tls.skipped_certs = 1; return LWS_TLS_EXTANT_NO; @@ -188,14 +188,12 @@ lws_tls_cert_updated(struct lws_context *context, const char *certpath, mem_privkey, len_mem_privkey); if (v->tls.skipped_certs) - lwsl_notice("%s: vhost %s: cert unset\n", - __func__, v->name); + lwsl_vhost_notice(v, "vhost %s: cert unset", v->name); } } lws_end_foreach_ll(v, vhost_next); return 0; } -#endif int lws_gate_accepts(struct lws_context *context, int on) @@ -204,17 +202,29 @@ lws_gate_accepts(struct lws_context *context, int on) lwsl_notice("%s: on = %d\n", __func__, on); + if (context->tls_gate_accepts == (char)on) + return 0; + + context->tls_gate_accepts = (char)on; + while (v) { - if (v->tls.use_ssl && v->lserv_wsi && - lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on, - (LWS_POLLIN) * on)) - lwsl_notice("Unable to set accept POLLIN %d\n", on); + lws_start_foreach_dll(struct lws_dll2 *, d, + lws_dll2_get_head(&v->listen_wsi)) { + struct lws *wsi = lws_container_of(d, struct lws, + listen_list); + + if (v->tls.use_ssl && + lws_change_pollfd(wsi, on ? LWS_POLLIN : 0, + on ? 0 : LWS_POLLIN)) + lwsl_cx_notice(context, "Unable to set POLLIN %d", on); + } lws_end_foreach_dll(d); v = v->vhost_next; } return 0; } +#endif /* comma-separated alpn list, like "h2,http/1.1" to openssl alpn format */ diff --git a/3rdparty/libwebsockets/lib/tls/tls-server.c b/3rdparty/libwebsockets/lib/tls/tls-server.c index 887159fa..05055f7e 100644 --- a/3rdparty/libwebsockets/lib/tls/tls-server.c +++ b/3rdparty/libwebsockets/lib/tls/tls-server.c @@ -113,12 +113,12 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, if (vhost->tls.use_ssl) lws_context_init_alpn(vhost); - /* check certs once a day */ + /* check certs in a few seconds (after protocol init) and then once a day */ context->pt[0].sul_tls.cb = lws_sul_tls_cb; __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); + (lws_usec_t)5 * LWS_US_PER_SEC); return 0; } @@ -144,7 +144,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char f if (accept_fd == LWS_SOCK_INVALID) assert(0); - if (lws_tls_restrict_borrow(context)) { + if (lws_tls_restrict_borrow(wsi)) { lwsl_err("%s: failed on ssl restriction\n", __func__); return 1; } @@ -153,7 +153,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char f 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); + lws_tls_restrict_return(wsi); goto fail; } @@ -320,8 +320,10 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char f lwsl_info("SSL_accept says %d\n", n); switch (n) { case LWS_SSL_CAPABLE_DONE: + lws_tls_restrict_return_handshake(wsi); break; case LWS_SSL_CAPABLE_ERROR: + lws_tls_restrict_return_handshake(wsi); lwsl_info("%s: SSL_accept failed socket %u: %d\n", __func__, wsi->desc.sockfd, n); wsi->socket_is_permanently_unusable = 1; diff --git a/3rdparty/libwebsockets/lib/tls/tls-sessions.c b/3rdparty/libwebsockets/lib/tls/tls-sessions.c index 706e2da7..b1e90aa5 100644 --- a/3rdparty/libwebsockets/lib/tls/tls-sessions.c +++ b/3rdparty/libwebsockets/lib/tls/tls-sessions.c @@ -45,10 +45,8 @@ lws_tls_session_tag_from_wsi(struct lws *wsi, char *buf, size_t len) if (!wsi) return 1; - if (!wsi->stash) { - lwsl_warn("%s: wsi has no stash\n", __func__); + if (!wsi->stash) return 1; - } host = wsi->stash->cis[CIS_HOST]; if (!host) diff --git a/3rdparty/libwebsockets/lib/tls/tls.c b/3rdparty/libwebsockets/lib/tls/tls.c index b4b43f0e..29a7a5d5 100644 --- a/3rdparty/libwebsockets/lib/tls/tls.c +++ b/3rdparty/libwebsockets/lib/tls/tls.c @@ -46,40 +46,110 @@ alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, #endif int -lws_tls_restrict_borrow(struct lws_context *context) +lws_tls_restrict_borrow(struct lws *wsi) { - if (!context->simultaneous_ssl_restriction) - return 0; + struct lws_context *cx = wsi->a.context; - if (context->simultaneous_ssl >= context->simultaneous_ssl_restriction) { + if (cx->simultaneous_ssl_restriction && + cx->simultaneous_ssl >= cx->simultaneous_ssl_restriction) { lwsl_notice("%s: tls connection limit %d\n", __func__, - context->simultaneous_ssl); + cx->simultaneous_ssl); return 1; } - if (++context->simultaneous_ssl == context->simultaneous_ssl_restriction) - /* that was the last allowed SSL connection */ - lws_gate_accepts(context, 0); + if (cx->simultaneous_ssl_handshake_restriction && + cx->simultaneous_ssl_handshake >= + cx->simultaneous_ssl_handshake_restriction) { + lwsl_notice("%s: tls handshake limit %d\n", __func__, + cx->simultaneous_ssl); + return 1; + } + + cx->simultaneous_ssl++; + cx->simultaneous_ssl_handshake++; + wsi->tls_borrowed_hs = 1; + wsi->tls_borrowed = 1; lwsl_info("%s: %d -> %d\n", __func__, - context->simultaneous_ssl - 1, - context->simultaneous_ssl); + cx->simultaneous_ssl - 1, + cx->simultaneous_ssl); + + assert(!cx->simultaneous_ssl_restriction || + cx->simultaneous_ssl <= + cx->simultaneous_ssl_restriction); + assert(!cx->simultaneous_ssl_handshake_restriction || + cx->simultaneous_ssl_handshake <= + cx->simultaneous_ssl_handshake_restriction); + +#if defined(LWS_WITH_SERVER) + lws_gate_accepts(cx, + (cx->simultaneous_ssl_restriction && + cx->simultaneous_ssl == cx->simultaneous_ssl_restriction) || + (cx->simultaneous_ssl_handshake_restriction && + cx->simultaneous_ssl_handshake == cx->simultaneous_ssl_handshake_restriction)); +#endif return 0; } +static void +_lws_tls_restrict_return(struct lws *wsi) +{ +#if defined(LWS_WITH_SERVER) + struct lws_context *cx = wsi->a.context; + + assert(cx->simultaneous_ssl_handshake >= 0); + assert(cx->simultaneous_ssl >= 0); + + lws_gate_accepts(cx, + (cx->simultaneous_ssl_restriction && + cx->simultaneous_ssl == cx->simultaneous_ssl_restriction) || + (cx->simultaneous_ssl_handshake_restriction && + cx->simultaneous_ssl_handshake == cx->simultaneous_ssl_handshake_restriction)); +#endif +} + void -lws_tls_restrict_return(struct lws_context *context) +lws_tls_restrict_return_handshake(struct lws *wsi) { - if (context->simultaneous_ssl_restriction) { - if (context->simultaneous_ssl-- == - context->simultaneous_ssl_restriction) - /* we made space and can do an accept */ - lws_gate_accepts(context, 1); - lwsl_info("%s: %d -> %d\n", __func__, - context->simultaneous_ssl + 1, - context->simultaneous_ssl); - } + struct lws_context *cx = wsi->a.context; + + /* we're just returning the hs part */ + + if (!wsi->tls_borrowed_hs) + return; + + wsi->tls_borrowed_hs = 0; /* return it one time per wsi */ + cx->simultaneous_ssl_handshake--; + + lwsl_info("%s: %d -> %d\n", __func__, + cx->simultaneous_ssl_handshake + 1, + cx->simultaneous_ssl_handshake); + + _lws_tls_restrict_return(wsi); +} + +void +lws_tls_restrict_return(struct lws *wsi) +{ + struct lws_context *cx = wsi->a.context; + + if (!wsi->tls_borrowed) + return; + + wsi->tls_borrowed = 0; + cx->simultaneous_ssl--; + + lwsl_info("%s: %d -> %d\n", __func__, + cx->simultaneous_ssl + 1, + cx->simultaneous_ssl); + + /* We're returning everything, even if hs didn't complete */ + + if (wsi->tls_borrowed_hs) + lws_tls_restrict_return_handshake(wsi); + else + _lws_tls_restrict_return(wsi); } void @@ -94,6 +164,7 @@ lws_context_init_alpn(struct lws_vhost *vhost) lwsl_info(" Server '%s' advertising ALPN: %s\n", vhost->name, alpn_comma); + vhost->tls.alpn_ctx.len = (uint8_t)lws_alpn_comma_to_openssl(alpn_comma, vhost->tls.alpn_ctx.data, sizeof(vhost->tls.alpn_ctx.data) - 1); @@ -101,9 +172,9 @@ lws_context_init_alpn(struct lws_vhost *vhost) SSL_CTX_set_alpn_select_cb(vhost->tls.ssl_ctx, alpn_cb, &vhost->tls.alpn_ctx); #else - lwsl_err( - " HTTP2 / ALPN configured but not supported by OpenSSL 0x%lx\n", - OPENSSL_VERSION_NUMBER); + lwsl_err(" HTTP2 / ALPN configured " + "but not supported by OpenSSL 0x%lx\n", + OPENSSL_VERSION_NUMBER); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L } @@ -116,8 +187,12 @@ lws_tls_server_conn_alpn(struct lws *wsi) char cstr[10]; unsigned len; - if (!wsi->tls.ssl) + lwsl_info("%s\n", __func__); + + if (!wsi->tls.ssl) { + lwsl_err("%s: non-ssl\n", __func__); return 0; + } SSL_get0_alpn_selected(wsi->tls.ssl, &name, &len); if (!len) { @@ -131,10 +206,12 @@ lws_tls_server_conn_alpn(struct lws *wsi) memcpy(cstr, name, len); cstr[len] = '\0'; - lwsl_info("negotiated '%s' using ALPN\n", cstr); + lwsl_info("%s: negotiated '%s' using ALPN\n", __func__, cstr); wsi->tls.use_ssl |= LCCSCF_USE_SSL; return lws_role_call_alpn_negotiated(wsi, (const char *)cstr); +#else + lwsl_err("%s: openssl too old\n", __func__); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L return 0; @@ -196,7 +273,7 @@ int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, goto bail; } - m = ftell(f); + m = (ssize_t)ftell(f); if (m == -1l) { n = 1; goto bail; @@ -208,7 +285,7 @@ int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, goto bail; } - *buf = lws_malloc(s, "alloc_file"); + *buf = lws_malloc(s + 1, "alloc_file"); if (!*buf) { n = 2; goto bail; @@ -300,7 +377,6 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, p++; if (*p != '-') { - lwsl_err("b\n"); goto bail; } @@ -308,7 +384,6 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, p++; if (p >= end) { - lwsl_err("c\n"); goto bail; } @@ -321,10 +396,8 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, while (q > opem && *q != '\n') q--; - if (*q != '\n') { - lwsl_err("d\n"); + if (*q != '\n') goto bail; - } /* we can't write into the input buffer for mem, since it may be in RO * const segment @@ -332,7 +405,10 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, if (filename) *q = '\0'; - *amount = (unsigned int)lws_b64_decode_string_len((char *)p, lws_ptr_diff(q, p), + n = lws_ptr_diff(q, p); + if (n == -1) /* coverity */ + goto bail; + *amount = (unsigned int)lws_b64_decode_string_len((char *)p, n, (char *)pem, (int)(long long)len); *buf = (uint8_t *)pem; diff --git a/3rdparty/libwebsockets/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt new file mode 100644 index 00000000..4ff5c55c --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt @@ -0,0 +1,23 @@ +project(lws-minimal-raw-client C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-raw-client) +set(SRCS main.c) + +set(requirements 1) +require_lws_config(LWS_WITH_CLIENT 1 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 --git a/3rdparty/libwebsockets/minimal-examples-lowlevel/raw/minimal-raw-client/main.c b/3rdparty/libwebsockets/minimal-examples-lowlevel/raw/minimal-raw-client/main.c new file mode 100644 index 00000000..db18a99e --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples-lowlevel/raw/minimal-raw-client/main.c @@ -0,0 +1,214 @@ +/* + * lws-minimal-raw-client + * + * Written in 2010-2022 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates connecting a "raw" client connection + */ + +#include +#include +#include +#if !defined(WIN32) +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#if !defined(WIN32) +#include +#endif +#include + +#include + +static struct lws *raw_wsi, *stdin_wsi; +static uint8_t buf[LWS_PRE + 4096]; +static int waiting, interrupted; +static struct lws_context *context; +static int us_wait_after_input_close = LWS_USEC_PER_SEC / 10; + +static const char *server = "libwebsockets.org", *port = "443"; + +static int +callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + const char *cp = (const char *)in; + + switch (reason) { + + /* callbacks related to file descriptor */ + + case LWS_CALLBACK_RAW_ADOPT_FILE: + lwsl_user("LWS_CALLBACK_RAW_ADOPT_FILE\n"); + break; + + case LWS_CALLBACK_RAW_CLOSE_FILE: + lwsl_user("LWS_CALLBACK_RAW_CLOSE_FILE\n"); + /* stdin close, wait 1s then close the raw skt */ + stdin_wsi = NULL; /* invalid now we close */ + if (raw_wsi) + lws_set_timer_usecs(raw_wsi, us_wait_after_input_close); + else { + interrupted = 1; + lws_cancel_service(context); + } + break; + + case LWS_CALLBACK_RAW_RX_FILE: + lwsl_user("LWS_CALLBACK_RAW_RX_FILE\n"); + waiting = (int)read(0, buf, sizeof(buf)); + lwsl_notice("raw file read %d\n", waiting); + if (waiting < 0) + return -1; + + if (raw_wsi) + lws_callback_on_writable(raw_wsi); + lws_rx_flow_control(wsi, 0); + break; + + + /* callbacks related to raw socket descriptor */ + + case LWS_CALLBACK_RAW_ADOPT: + lwsl_user("LWS_CALLBACK_RAW_ADOPT\n"); + lws_callback_on_writable(wsi); + break; + + case LWS_CALLBACK_RAW_CONNECTED: + lwsl_user("LWS_CALLBACK_RAW_CONNECTED\n"); + break; + + case LWS_CALLBACK_RAW_CLOSE: + lwsl_user("LWS_CALLBACK_RAW_CLOSE\n"); + /* + * If the socket to the remote server closed, we must close + * and drop any remaining stdin + */ + interrupted = 1; + lws_cancel_service(context); + /* our pointer to this wsi is invalid now we close */ + raw_wsi = NULL; + break; + + case LWS_CALLBACK_RAW_RX: + lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); + while (len--) + putchar(*cp++); + fflush(stdout); + break; + + case LWS_CALLBACK_RAW_WRITEABLE: + lwsl_user("LWS_CALLBACK_RAW_WRITEABLE\n"); + // lwsl_hexdump_info(buf, waiting); + if (!waiting) + break; + if (stdin_wsi) + lws_rx_flow_control(stdin_wsi, 1); + if (lws_write(wsi, buf, (unsigned int)waiting, LWS_WRITE_RAW) != waiting) { + lwsl_notice("%s: raw skt write failed\n", __func__); + + return -1; + } + break; + + case LWS_CALLBACK_TIMER: + lwsl_user("LWS_CALLBACK_TIMER\n"); + interrupted = 1; + lws_cancel_service(context); + return -1; + + default: + break; + } + + return 0; +} + +static struct lws_protocols protocols[] = { + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM +}; + +static int +system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_client_connect_info i; + + if (current != LWS_SYSTATE_OPERATIONAL || + target != LWS_SYSTATE_OPERATIONAL) + return 0; + + memset(&i, 0, sizeof i); + i.context = context; + i.method = "RAW"; + i.ssl_connection = LCCSCF_USE_SSL; + i.alpn = "http/1.1"; + i.address = server; + i.host = server; + i.port = atoi(port); + i.local_protocol_name = "raw-test"; + + waiting = lws_snprintf((char *)buf, sizeof(buf), "GET / HTTP/1.1\xaHost: libwebsockets.org\xa\xa"); + + if (!lws_client_connect_via_info(&i)) { + lwsl_err("Client creation failed\n"); + interrupted = 1; + } + + return 0; +} + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + const char *p; + int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + + 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 raw client\n"); + + memset(&info, 0, sizeof info); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN_SERVER; + info.protocols = protocols; + info.register_notifier_list = na; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lwsl_user("%s: destroying context\n", __func__); + + lws_context_destroy(context); + + return 0; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt index 256726ca..f2954d0f 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt @@ -1,14 +1,10 @@ project(lws-api-test-async-dns C) cmake_minimum_required(VERSION 2.8.12) 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) -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_ASYNC_DNS 1 requirements) diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/CMakeLists.txt new file mode 100644 index 00000000..bd6b1428 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/CMakeLists.txt @@ -0,0 +1,29 @@ +project(lws-api-test-cose C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-api-test-cose) +set(SRCS main.c keys.c sign.c) + +set(requirements 1) +require_lws_config(LWS_WITH_COSE 1 requirements) +require_lws_config(LWS_WITH_CBOR 1 requirements) + +if (requirements) + + add_executable(${SAMP} ${SRCS}) + + if (NOT (LWS_WITH_MBEDTLS AND NOT LWS_HAVE_mbedtls_internal_aes_encrypt)) + add_test(NAME api-test-cose COMMAND lws-api-test-cose) + 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() +endif() diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/README.md b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/README.md new file mode 100644 index 00000000..74034c79 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/README.md @@ -0,0 +1,22 @@ +# lws api test lwsac + +Demonstrates how to use and performs selftests for lwsac + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` + $ ./lws-api-test-lwsac +[2018/10/09 09:14:17:4834] USER: LWS API selftest: lwsac +[2018/10/09 09:14:17:4835] USER: Completed: PASS +``` + diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/keys.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/keys.c new file mode 100644 index 00000000..134784d1 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/keys.c @@ -0,0 +1,931 @@ +/* + * lws-api-test-jose - RFC8152 cose_key tests + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Raw key CBOR created from descriptions at + * + * https://github.com/cose-wg/Examples/blob/master/KeySet.txt + */ + +#include +#include +#include + +static int +key_import_cb(struct lws_cose_key *s, void *user) +{ + lwsl_notice("%s: key type %lld\n", __func__, (long long)s->kty); + + return 0; +} + +static const uint8_t + cose_key1[] = { + 0xa6, 0x01, 0x02, 0x02, 0x62, + 0x31, 0x31, 0x20, 0x01, 0x21, + 0x58, 0x20, 0xba, 0xc5, 0xb1, + 0x1c, 0xad, 0x8f, 0x99, 0xf9, + 0xc7, 0x2b, 0x05, 0xcf, 0x4b, + 0x9e, 0x26, 0xd2, 0x44, 0xdc, + 0x18, 0x9f, 0x74, 0x52, 0x28, + 0x25, 0x5a, 0x21, 0x9a, 0x86, + 0xd6, 0xa0, 0x9e, 0xff, 0x22, + 0x58, 0x20, 0x20, 0x13, 0x8b, + 0xf8, 0x2d, 0xc1, 0xb6, 0xd5, + 0x62, 0xbe, 0x0f, 0xa5, 0x4a, + 0xb7, 0x80, 0x4a, 0x3a, 0x64, + 0xb6, 0xd7, 0x2c, 0xcf, 0xed, + 0x6b, 0x6f, 0xb6, 0xed, 0x28, + 0xbb, 0xfc, 0x11, 0x7e, 0x23, + 0x58, 0x20, 0x57, 0xc9, 0x20, + 0x77, 0x66, 0x41, 0x46, 0xe8, + 0x76, 0x76, 0x0c, 0x95, 0x20, + 0xd0, 0x54, 0xaa, 0x93, 0xc3, + 0xaf, 0xb0, 0x4e, 0x30, 0x67, + 0x05, 0xdb, 0x60, 0x90, 0x30, + 0x85, 0x07, 0xb4, 0xd3 }, + cose_key2[] = { + 0xa6, 0x01, 0x02, 0x02, 0x78, + 0x24, 0x6d, 0x65, 0x72, 0x69, + 0x61, 0x64, 0x6f, 0x63, 0x2e, + 0x62, 0x72, 0x61, 0x6e, 0x64, + 0x79, 0x62, 0x75, 0x63, 0x6b, + 0x40, 0x62, 0x75, 0x63, 0x6b, + 0x6c, 0x61, 0x6e, 0x64, 0x2e, + 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x20, 0x01, 0x21, + 0x58, 0x20, 0x65, 0xed, 0xa5, + 0xa1, 0x25, 0x77, 0xc2, 0xba, + 0xe8, 0x29, 0x43, 0x7f, 0xe3, + 0x38, 0x70, 0x1a, 0x10, 0xaa, + 0xa3, 0x75, 0xe1, 0xbb, 0x5b, + 0x5d, 0xe1, 0x08, 0xde, 0x43, + 0x9c, 0x08, 0x55, 0x1d, 0x22, + 0x58, 0x20, 0x1e, 0x52, 0xed, + 0x75, 0x70, 0x11, 0x63, 0xf7, + 0xf9, 0xe4, 0x0d, 0xdf, 0x9f, + 0x34, 0x1b, 0x3d, 0xc9, 0xba, + 0x86, 0x0a, 0xf7, 0xe0, 0xca, + 0x7c, 0xa7, 0xe9, 0xee, 0xcd, + 0x00, 0x84, 0xd1, 0x9c, 0x23, + 0x58, 0x20, 0xaf, 0xf9, 0x07, + 0xc9, 0x9f, 0x9a, 0xd3, 0xaa, + 0xe6, 0xc4, 0xcd, 0xf2, 0x11, + 0x22, 0xbc, 0xe2, 0xbd, 0x68, + 0xb5, 0x28, 0x3e, 0x69, 0x07, + 0x15, 0x4a, 0xd9, 0x11, 0x84, + 0x0f, 0xa2, 0x08, 0xcf }, + + cose_key3[] = { 0xa3, 0x01, 0x04, 0x02, 0x6a, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x20, 0x58, 0x20, 0x84, 0x9b, + 0x57, 0x21, 0x9d, 0xae, 0x48, + 0xde, 0x64, 0x6d, 0x07, 0xdb, + 0xb5, 0x33, 0x56, 0x6e, 0x97, + 0x66, 0x86, 0x45, 0x7c, 0x14, + 0x91, 0xbe, 0x3a, 0x76, 0xdc, + 0xea, 0x6c, 0x42, 0x71, 0x88 }, + + cose_key4[] = { 0xa6, 0x01, 0x02, 0x02, 0x78, + 0x1e, 0x62, 0x69, 0x6c, 0x62, + 0x6f, 0x2e, 0x62, 0x61, 0x67, + 0x67, 0x69, 0x6e, 0x73, 0x40, + 0x68, 0x6f, 0x62, 0x62, 0x69, + 0x74, 0x6f, 0x6e, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x03, 0x21, 0x58, + 0x42, 0x00, 0x72, 0x99, 0x2c, + 0xb3, 0xac, 0x08, 0xec, 0xf3, + 0xe5, 0xc6, 0x3d, 0xed, 0xec, + 0x0d, 0x51, 0xa8, 0xc1, 0xf7, + 0x9e, 0xf2, 0xf8, 0x2f, 0x94, + 0xf3, 0xc7, 0x37, 0xbf, 0x5d, + 0xe7, 0x98, 0x66, 0x71, 0xea, + 0xc6, 0x25, 0xfe, 0x82, 0x57, + 0xbb, 0xd0, 0x39, 0x46, 0x44, + 0xca, 0xaa, 0x3a, 0xaf, 0x8f, + 0x27, 0xa4, 0x58, 0x5f, 0xbb, + 0xca, 0xd0, 0xf2, 0x45, 0x76, + 0x20, 0x08, 0x5e, 0x5c, 0x8f, + 0x42, 0xad, 0x22, 0x58, 0x42, + 0x01, 0xdc, 0xa6, 0x94, 0x7b, + 0xce, 0x88, 0xbc, 0x57, 0x90, + 0x48, 0x5a, 0xc9, 0x74, 0x27, + 0x34, 0x2b, 0xc3, 0x5f, 0x88, + 0x7d, 0x86, 0xd6, 0x5a, 0x08, + 0x93, 0x77, 0xe2, 0x47, 0xe6, + 0x0b, 0xaa, 0x55, 0xe4, 0xe8, + 0x50, 0x1e, 0x2a, 0xda, 0x57, + 0x24, 0xac, 0x51, 0xd6, 0x90, + 0x90, 0x08, 0x03, 0x3e, 0xbc, + 0x10, 0xac, 0x99, 0x9b, 0x9d, + 0x7f, 0x5c, 0xc2, 0x51, 0x9f, + 0x3f, 0xe1, 0xea, 0x1d, 0x94, + 0x75, 0x23, 0x58, 0x42, 0x00, + 0x08, 0x51, 0x38, 0xdd, 0xab, + 0xf5, 0xca, 0x97, 0x5f, 0x58, + 0x60, 0xf9, 0x1a, 0x08, 0xe9, + 0x1d, 0x6d, 0x5f, 0x9a, 0x76, + 0xad, 0x40, 0x18, 0x76, 0x6a, + 0x47, 0x66, 0x80, 0xb5, 0x5c, + 0xd3, 0x39, 0xe8, 0xab, 0x6c, + 0x72, 0xb5, 0xfa, 0xcd, 0xb2, + 0xa2, 0xa5, 0x0a, 0xc2, 0x5b, + 0xd0, 0x86, 0x64, 0x7d, 0xd3, + 0xe2, 0xe6, 0xe9, 0x9e, 0x84, + 0xca, 0x2c, 0x36, 0x09, 0xfd, + 0xf1, 0x77, 0xfe, 0xb2, 0x6d }, + cose_key5[] = { 0xa3, 0x01, 0x04, 0x02, 0x6b, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x32, 0x20, 0x50, 0x84, 0x9b, + 0x57, 0x86, 0x45, 0x7c, 0x14, + 0x91, 0xbe, 0x3a, 0x76, 0xdc, + 0xea, 0x6c, 0x42, 0x71 }, + + cose_key6[] = { 0xa6, 0x01, 0x02, 0x02, 0x78, + 0x21, 0x70, 0x65, 0x72, 0x65, + 0x67, 0x72, 0x69, 0x6e, 0x2e, + 0x74, 0x6f, 0x6f, 0x6b, 0x40, + 0x74, 0x75, 0x63, 0x6b, 0x62, + 0x6f, 0x72, 0x6f, 0x75, 0x67, + 0x68, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, + 0x01, 0x21, 0x58, 0x20, 0x98, + 0xf5, 0x0a, 0x4f, 0xf6, 0xc0, + 0x58, 0x61, 0xc8, 0x86, 0x0d, + 0x13, 0xa6, 0x38, 0xea, 0x56, + 0xc3, 0xf5, 0xad, 0x75, 0x90, + 0xbb, 0xfb, 0xf0, 0x54, 0xe1, + 0xc7, 0xb4, 0xd9, 0x1d, 0x62, + 0x80, 0x22, 0x58, 0x20, 0xf0, + 0x14, 0x00, 0xb0, 0x89, 0x86, + 0x78, 0x04, 0xb8, 0xe9, 0xfc, + 0x96, 0xc3, 0x93, 0x21, 0x61, + 0xf1, 0x93, 0x4f, 0x42, 0x23, + 0x06, 0x91, 0x70, 0xd9, 0x24, + 0xb7, 0xe0, 0x3b, 0xf8, 0x22, + 0xbb, 0x23, 0x58, 0x20, 0x02, + 0xd1, 0xf7, 0xe6, 0xf2, 0x6c, + 0x43, 0xd4, 0x86, 0x8d, 0x87, + 0xce, 0xb2, 0x35, 0x31, 0x61, + 0x74, 0x0a, 0xac, 0xf1, 0xf7, + 0x16, 0x36, 0x47, 0x98, 0x4b, + 0x52, 0x2a, 0x84, 0x8d, 0xf1, + 0xc3 }, + cose_key7[] = { 0xa3, 0x01, 0x04, 0x02, 0x58, + 0x24, 0x30, 0x31, 0x38, 0x63, + 0x30, 0x61, 0x65, 0x35, 0x2d, + 0x34, 0x64, 0x39, 0x62, 0x2d, + 0x34, 0x37, 0x31, 0x62, 0x2d, + 0x62, 0x66, 0x64, 0x36, 0x2d, + 0x65, 0x65, 0x66, 0x33, 0x31, + 0x34, 0x62, 0x63, 0x37, 0x30, + 0x33, 0x37, 0x20, 0x58, 0x20, + 0x84, 0x9b, 0x57, 0x21, 0x9d, + 0xae, 0x48, 0xde, 0x64, 0x6d, + 0x07, 0xdb, 0xb5, 0x33, 0x56, + 0x6e, 0x97, 0x66, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71, 0x88 }, + + cose_key8[] = { + /* kid "sec-48" for hmac 384 */ + + 0xa3, 0x01, 0x04, 0x02, 0x66, + 0x73, 0x65, 0x63, 0x2d, 0x34, + 0x38, 0x20, 0x58, 0x30, 0x84, + 0x9b, 0x57, 0x21, 0x9d, 0xae, + 0x48, 0xde, 0x64, 0x6d, 0x07, + 0xdb, 0xb5, 0x33, 0x56, 0x6e, + 0x97, 0x66, 0x86, 0x45, 0x7c, + 0x14, 0x91, 0xbe, 0x3a, 0x76, + 0xdc, 0xea, 0x6c, 0x42, 0x71, + 0x88, 0x00, 0x11, 0x22, 0x33, + 0x77, 0x88, 0x99, 0xaa, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28 + }, + + cose_key9[] = { + /* kid "sec-64" for hmac 512 */ + + 0xa3, 0x01, 0x04, 0x02, 0x46, + 0x73, 0x65, 0x63, 0x2d, 0x36, + 0x34, 0x20, 0x58, 0x40, 0x84, + 0x9b, 0x57, 0x21, 0x9d, 0xae, + 0x48, 0xde, 0x64, 0x6d, 0x07, + 0xdb, 0xb5, 0x33, 0x56, 0x6e, + 0x97, 0x66, 0x86, 0x45, 0x7c, + 0x14, 0x91, 0xbe, 0x3a, 0x76, + 0xdc, 0xea, 0x6c, 0x42, 0x71, + 0x88, 0x00, 0x11, 0x22, 0x33, + 0x77, 0x88, 0x99, 0xaa, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0xaa, 0xbb, 0xcc, + 0xdd, 0xee, 0xff, 0xa5, 0xa6, + 0xa7, 0xa8, 0xa9, 0xa0, 0xb1, + 0xb2, 0xb3, 0xb4, + }, + + cose_key10[] = { /* kid "11" (again) ed22519 OKP key */ + 0xa5, 0x01, 0x01, 0x02, 0x42, + 0x31, 0x31, 0x20, 0x06, 0x21, + 0x58, 0x20, 0xd7, 0x5a, 0x98, + 0x01, 0x82, 0xb1, 0x0a, 0xb7, + 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, + 0x64, 0x07, 0x3a, 0x0e, 0xe1, + 0x72, 0xf3, 0xda, 0xa6, 0x23, + 0x25, 0xaf, 0x02, 0x1a, 0x68, + 0xf7, 0x07, 0x51, 0x1a, 0x23, + 0x58, 0x20, 0x9d, 0x61, 0xb1, + 0x9d, 0xef, 0xfd, 0x5a, 0x60, + 0xba, 0x84, 0x4a, 0xf4, 0x92, + 0xec, 0x2c, 0xc4, 0x44, 0x49, + 0xc5, 0x69, 0x7b, 0x32, 0x69, + 0x19, 0x70, 0x3b, 0xac, 0x03, + 0x1c, 0xae, 0x7f, 0x60 + }, + + cose_key_set1[] = { + + 0x89, + + 0xa6, 0x01, 0x02, 0x02, 0x42, + 0x31, 0x31, 0x20, 0x01, 0x21, + 0x58, 0x20, 0xba, 0xc5, 0xb1, + 0x1c, 0xad, 0x8f, 0x99, 0xf9, + 0xc7, 0x2b, 0x05, 0xcf, 0x4b, + 0x9e, 0x26, 0xd2, 0x44, 0xdc, + 0x18, 0x9f, 0x74, 0x52, 0x28, + 0x25, 0x5a, 0x21, 0x9a, 0x86, + 0xd6, 0xa0, 0x9e, 0xff, 0x22, + 0x58, 0x20, 0x20, 0x13, 0x8b, + 0xf8, 0x2d, 0xc1, 0xb6, 0xd5, + 0x62, 0xbe, 0x0f, 0xa5, 0x4a, + 0xb7, 0x80, 0x4a, 0x3a, 0x64, + 0xb6, 0xd7, 0x2c, 0xcf, 0xed, + 0x6b, 0x6f, 0xb6, 0xed, 0x28, + 0xbb, 0xfc, 0x11, 0x7e, 0x23, + 0x58, 0x20, 0x57, 0xc9, 0x20, + 0x77, 0x66, 0x41, 0x46, 0xe8, + 0x76, 0x76, 0x0c, 0x95, 0x20, + 0xd0, 0x54, 0xaa, 0x93, 0xc3, + 0xaf, 0xb0, 0x4e, 0x30, 0x67, + 0x05, 0xdb, 0x60, 0x90, 0x30, + 0x85, 0x07, 0xb4, 0xd3, + + 0xa6, 0x01, 0x02, 0x02, 0x58, + 0x24, 0x6d, 0x65, 0x72, 0x69, + 0x61, 0x64, 0x6f, 0x63, 0x2e, + 0x62, 0x72, 0x61, 0x6e, 0x64, + 0x79, 0x62, 0x75, 0x63, 0x6b, + 0x40, 0x62, 0x75, 0x63, 0x6b, + 0x6c, 0x61, 0x6e, 0x64, 0x2e, + 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x20, 0x01, 0x21, + 0x58, 0x20, 0x65, 0xed, 0xa5, + 0xa1, 0x25, 0x77, 0xc2, 0xba, + 0xe8, 0x29, 0x43, 0x7f, 0xe3, + 0x38, 0x70, 0x1a, 0x10, 0xaa, + 0xa3, 0x75, 0xe1, 0xbb, 0x5b, + 0x5d, 0xe1, 0x08, 0xde, 0x43, + 0x9c, 0x08, 0x55, 0x1d, 0x22, + 0x58, 0x20, 0x1e, 0x52, 0xed, + 0x75, 0x70, 0x11, 0x63, 0xf7, + 0xf9, 0xe4, 0x0d, 0xdf, 0x9f, + 0x34, 0x1b, 0x3d, 0xc9, 0xba, + 0x86, 0x0a, 0xf7, 0xe0, 0xca, + 0x7c, 0xa7, 0xe9, 0xee, 0xcd, + 0x00, 0x84, 0xd1, 0x9c, 0x23, + 0x58, 0x20, 0xaf, 0xf9, 0x07, + 0xc9, 0x9f, 0x9a, 0xd3, 0xaa, + 0xe6, 0xc4, 0xcd, 0xf2, 0x11, + 0x22, 0xbc, 0xe2, 0xbd, 0x68, + 0xb5, 0x28, 0x3e, 0x69, 0x07, + 0x15, 0x4a, 0xd9, 0x11, 0x84, + 0x0f, 0xa2, 0x08, 0xcf, + + 0xa3, 0x01, 0x04, 0x02, 0x4a, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x20, 0x58, 0x20, 0x84, 0x9b, + 0x57, 0x21, 0x9d, 0xae, 0x48, + 0xde, 0x64, 0x6d, 0x07, 0xdb, + 0xb5, 0x33, 0x56, 0x6e, 0x97, + 0x66, 0x86, 0x45, 0x7c, 0x14, + 0x91, 0xbe, 0x3a, 0x76, 0xdc, + 0xea, 0x6c, 0x42, 0x71, 0x88, + + 0xa6, 0x01, 0x02, 0x02, 0x58, + 0x1e, 0x62, 0x69, 0x6c, 0x62, + 0x6f, 0x2e, 0x62, 0x61, 0x67, + 0x67, 0x69, 0x6e, 0x73, 0x40, + 0x68, 0x6f, 0x62, 0x62, 0x69, + 0x74, 0x6f, 0x6e, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x03, 0x21, 0x58, + 0x42, 0x00, 0x72, 0x99, 0x2c, + 0xb3, 0xac, 0x08, 0xec, 0xf3, + 0xe5, 0xc6, 0x3d, 0xed, 0xec, + 0x0d, 0x51, 0xa8, 0xc1, 0xf7, + 0x9e, 0xf2, 0xf8, 0x2f, 0x94, + 0xf3, 0xc7, 0x37, 0xbf, 0x5d, + 0xe7, 0x98, 0x66, 0x71, 0xea, + 0xc6, 0x25, 0xfe, 0x82, 0x57, + 0xbb, 0xd0, 0x39, 0x46, 0x44, + 0xca, 0xaa, 0x3a, 0xaf, 0x8f, + 0x27, 0xa4, 0x58, 0x5f, 0xbb, + 0xca, 0xd0, 0xf2, 0x45, 0x76, + 0x20, 0x08, 0x5e, 0x5c, 0x8f, + 0x42, 0xad, 0x22, 0x58, 0x42, + 0x01, 0xdc, 0xa6, 0x94, 0x7b, + 0xce, 0x88, 0xbc, 0x57, 0x90, + 0x48, 0x5a, 0xc9, 0x74, 0x27, + 0x34, 0x2b, 0xc3, 0x5f, 0x88, + 0x7d, 0x86, 0xd6, 0x5a, 0x08, + 0x93, 0x77, 0xe2, 0x47, 0xe6, + 0x0b, 0xaa, 0x55, 0xe4, 0xe8, + 0x50, 0x1e, 0x2a, 0xda, 0x57, + 0x24, 0xac, 0x51, 0xd6, 0x90, + 0x90, 0x08, 0x03, 0x3e, 0xbc, + 0x10, 0xac, 0x99, 0x9b, 0x9d, + 0x7f, 0x5c, 0xc2, 0x51, 0x9f, + 0x3f, 0xe1, 0xea, 0x1d, 0x94, + 0x75, 0x23, 0x58, 0x42, 0x00, + 0x08, 0x51, 0x38, 0xdd, 0xab, + 0xf5, 0xca, 0x97, 0x5f, 0x58, + 0x60, 0xf9, 0x1a, 0x08, 0xe9, + 0x1d, 0x6d, 0x5f, 0x9a, 0x76, + 0xad, 0x40, 0x18, 0x76, 0x6a, + 0x47, 0x66, 0x80, 0xb5, 0x5c, + 0xd3, 0x39, 0xe8, 0xab, 0x6c, + 0x72, 0xb5, 0xfa, 0xcd, 0xb2, + 0xa2, 0xa5, 0x0a, 0xc2, 0x5b, + 0xd0, 0x86, 0x64, 0x7d, 0xd3, + 0xe2, 0xe6, 0xe9, 0x9e, 0x84, + 0xca, 0x2c, 0x36, 0x09, 0xfd, + 0xf1, 0x77, 0xfe, 0xb2, 0x6d, + + 0xa3, 0x01, 0x04, 0x02, 0x4b, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x32, 0x20, 0x50, 0x84, 0x9b, + 0x57, 0x86, 0x45, 0x7c, 0x14, + 0x91, 0xbe, 0x3a, 0x76, 0xdc, + 0xea, 0x6c, 0x42, 0x71, + + 0xa6, 0x01, 0x02, 0x02, 0x58, + 0x21, 0x70, 0x65, 0x72, 0x65, + 0x67, 0x72, 0x69, 0x6e, 0x2e, + 0x74, 0x6f, 0x6f, 0x6b, 0x40, + 0x74, 0x75, 0x63, 0x6b, 0x62, + 0x6f, 0x72, 0x6f, 0x75, 0x67, + 0x68, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x20, + 0x01, 0x21, 0x58, 0x20, 0x98, + 0xf5, 0x0a, 0x4f, 0xf6, 0xc0, + 0x58, 0x61, 0xc8, 0x86, 0x0d, + 0x13, 0xa6, 0x38, 0xea, 0x56, + 0xc3, 0xf5, 0xad, 0x75, 0x90, + 0xbb, 0xfb, 0xf0, 0x54, 0xe1, + 0xc7, 0xb4, 0xd9, 0x1d, 0x62, + 0x80, 0x22, 0x58, 0x20, 0xf0, + 0x14, 0x00, 0xb0, 0x89, 0x86, + 0x78, 0x04, 0xb8, 0xe9, 0xfc, + 0x96, 0xc3, 0x93, 0x21, 0x61, + 0xf1, 0x93, 0x4f, 0x42, 0x23, + 0x06, 0x91, 0x70, 0xd9, 0x24, + 0xb7, 0xe0, 0x3b, 0xf8, 0x22, + 0xbb, 0x23, 0x58, 0x20, 0x02, + 0xd1, 0xf7, 0xe6, 0xf2, 0x6c, + 0x43, 0xd4, 0x86, 0x8d, 0x87, + 0xce, 0xb2, 0x35, 0x31, 0x61, + 0x74, 0x0a, 0xac, 0xf1, 0xf7, + 0x16, 0x36, 0x47, 0x98, 0x4b, + 0x52, 0x2a, 0x84, 0x8d, 0xf1, + 0xc3, + + 0xa3, 0x01, 0x04, 0x02, 0x58, + 0x24, 0x30, 0x31, 0x38, 0x63, + 0x30, 0x61, 0x65, 0x35, 0x2d, + 0x34, 0x64, 0x39, 0x62, 0x2d, + 0x34, 0x37, 0x31, 0x62, 0x2d, + 0x62, 0x66, 0x64, 0x36, 0x2d, + 0x65, 0x65, 0x66, 0x33, 0x31, + 0x34, 0x62, 0x63, 0x37, 0x30, + 0x33, 0x37, 0x04, 0x58, 0x20, + 0x84, 0x9b, 0x57, 0x21, 0x9d, + 0xae, 0x48, 0xde, 0x64, 0x6d, + 0x07, 0xdb, 0xb5, 0x33, 0x56, + 0x6e, 0x97, 0x66, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71, 0x88, + + /* kid "sec-48" for hmac 384 */ + + 0xa3, 0x01, 0x04, 0x02, 0x46, + 0x73, 0x65, 0x63, 0x2d, 0x34, + 0x38, 0x20, 0x58, 0x30, 0x84, + 0x9b, 0x57, 0x21, 0x9d, 0xae, + 0x48, 0xde, 0x64, 0x6d, 0x07, + 0xdb, 0xb5, 0x33, 0x56, 0x6e, + 0x97, 0x66, 0x86, 0x45, 0x7c, + 0x14, 0x91, 0xbe, 0x3a, 0x76, + 0xdc, 0xea, 0x6c, 0x42, 0x71, + 0x88, 0x00, 0x11, 0x22, 0x33, + 0x77, 0x88, 0x99, 0xaa, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, + + /* kid "sec-64" for hmac 512 */ + + 0xa3, 0x01, 0x04, 0x02, 0x46, + 0x73, 0x65, 0x63, 0x2d, 0x36, + 0x34, 0x20, 0x58, 0x40, 0x84, + 0x9b, 0x57, 0x21, 0x9d, 0xae, + 0x48, 0xde, 0x64, 0x6d, 0x07, + 0xdb, 0xb5, 0x33, 0x56, 0x6e, + 0x97, 0x66, 0x86, 0x45, 0x7c, + 0x14, 0x91, 0xbe, 0x3a, 0x76, + 0xdc, 0xea, 0x6c, 0x42, 0x71, + 0x88, 0x00, 0x11, 0x22, 0x33, + 0x77, 0x88, 0x99, 0xaa, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0xaa, 0xbb, 0xcc, + 0xdd, 0xee, 0xff, 0xa5, 0xa6, + 0xa7, 0xa8, 0xa9, 0xa0, 0xb1, + 0xb2, 0xb3, 0xb4, +} +; + +struct keyinfo { + const uint8_t *set; + size_t len; +}; + +struct keyinfo keyset1 = { cose_key_set1, sizeof(cose_key_set1) }, + key3 = { cose_key3, sizeof(cose_key3) }, + key8 = { cose_key8, sizeof(cose_key8) }, + key9 = { cose_key9, sizeof(cose_key9) }, + key10 = { cose_key10, sizeof(cose_key10) } +; + +/* key pieces */ + +static const uint8_t + key1_x[] = { 0xba, 0xc5, 0xb1, 0x1c, 0xad, + 0x8f, 0x99, 0xf9, 0xc7, 0x2b, + 0x05, 0xcf, 0x4b, 0x9e, 0x26, + 0xd2, 0x44, 0xdc, 0x18, 0x9f, + 0x74, 0x52, 0x28, 0x25, 0x5a, + 0x21, 0x9a, 0x86, 0xd6, 0xa0, + 0x9e, 0xff }, + key1_y[] = { 0x20, 0x13, 0x8b, 0xf8, 0x2d, + 0xc1, 0xb6, 0xd5, 0x62, 0xbe, + 0x0f, 0xa5, 0x4a, 0xb7, 0x80, + 0x4a, 0x3a, 0x64, 0xb6, 0xd7, + 0x2c, 0xcf, 0xed, 0x6b, 0x6f, + 0xb6, 0xed, 0x28, 0xbb, 0xfc, + 0x11, 0x7e }, + key1_d[] = { 0x57, 0xc9, 0x20, 0x77, 0x66, + 0x41, 0x46, 0xe8, 0x76, 0x76, + 0x0c, 0x95, 0x20, 0xd0, 0x54, + 0xaa, 0x93, 0xc3, 0xaf, 0xb0, + 0x4e, 0x30, 0x67, 0x05, 0xdb, + 0x60, 0x90, 0x30, 0x85, 0x07, + 0xb4, 0xd3 }, + + key2_x[] = { 0x65, 0xed, 0xa5, 0xa1, 0x25, + 0x77, 0xc2, 0xba, 0xe8, 0x29, + 0x43, 0x7f, 0xe3, 0x38, 0x70, + 0x1a, 0x10, 0xaa, 0xa3, 0x75, + 0xe1, 0xbb, 0x5b, 0x5d, 0xe1, + 0x08, 0xde, 0x43, 0x9c, 0x08, + 0x55, 0x1d }, + key2_y[] = { 0x1e, 0x52, 0xed, 0x75, 0x70, + 0x11, 0x63, 0xf7, 0xf9, 0xe4, + 0x0d, 0xdf, 0x9f, 0x34, 0x1b, + 0x3d, 0xc9, 0xba, 0x86, 0x0a, + 0xf7, 0xe0, 0xca, 0x7c, 0xa7, + 0xe9, 0xee, 0xcd, 0x00, 0x84, + 0xd1, 0x9c }, + key2_d[] = { 0xaf, 0xf9, 0x07, 0xc9, 0x9f, + 0x9a, 0xd3, 0xaa, 0xe6, 0xc4, + 0xcd, 0xf2, 0x11, 0x22, 0xbc, + 0xe2, 0xbd, 0x68, 0xb5, 0x28, + 0x3e, 0x69, 0x07, 0x15, 0x4a, + 0xd9, 0x11, 0x84, 0x0f, 0xa2, + 0x08, 0xcf }, + + key3_k[] = { 0x84, 0x9b, 0x57, 0x21, 0x9d, + 0xae, 0x48, 0xde, 0x64, 0x6d, + 0x07, 0xdb, 0xb5, 0x33, 0x56, + 0x6e, 0x97, 0x66, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71, 0x88 }, + + key4_x[] = { 0x00, 0x72, 0x99, 0x2c, 0xb3, + 0xac, 0x08, 0xec, 0xf3, 0xe5, + 0xc6, 0x3d, 0xed, 0xec, 0x0d, + 0x51, 0xa8, 0xc1, 0xf7, 0x9e, + 0xf2, 0xf8, 0x2f, 0x94, 0xf3, + 0xc7, 0x37, 0xbf, 0x5d, 0xe7, + 0x98, 0x66, 0x71, 0xea, 0xc6, + 0x25, 0xfe, 0x82, 0x57, 0xbb, + 0xd0, 0x39, 0x46, 0x44, 0xca, + 0xaa, 0x3a, 0xaf, 0x8f, 0x27, + 0xa4, 0x58, 0x5f, 0xbb, 0xca, + 0xd0, 0xf2, 0x45, 0x76, 0x20, + 0x08, 0x5e, 0x5c, 0x8f, 0x42, + 0xad }, + key4_y[] = { 0x01, 0xdc, 0xa6, 0x94, 0x7b, + 0xce, 0x88, 0xbc, 0x57, 0x90, + 0x48, 0x5a, 0xc9, 0x74, 0x27, + 0x34, 0x2b, 0xc3, 0x5f, 0x88, + 0x7d, 0x86, 0xd6, 0x5a, 0x08, + 0x93, 0x77, 0xe2, 0x47, 0xe6, + 0x0b, 0xaa, 0x55, 0xe4, 0xe8, + 0x50, 0x1e, 0x2a, 0xda, 0x57, + 0x24, 0xac, 0x51, 0xd6, 0x90, + 0x90, 0x08, 0x03, 0x3e, 0xbc, + 0x10, 0xac, 0x99, 0x9b, 0x9d, + 0x7f, 0x5c, 0xc2, 0x51, 0x9f, + 0x3f, 0xe1, 0xea, 0x1d, 0x94, + 0x75 }, + key4_d[] = { 0x00, 0x08, 0x51, 0x38, 0xdd, + 0xab, 0xf5, 0xca, 0x97, 0x5f, + 0x58, 0x60, 0xf9, 0x1a, 0x08, + 0xe9, 0x1d, 0x6d, 0x5f, 0x9a, + 0x76, 0xad, 0x40, 0x18, 0x76, + 0x6a, 0x47, 0x66, 0x80, 0xb5, + 0x5c, 0xd3, 0x39, 0xe8, 0xab, + 0x6c, 0x72, 0xb5, 0xfa, 0xcd, + 0xb2, 0xa2, 0xa5, 0x0a, 0xc2, + 0x5b, 0xd0, 0x86, 0x64, 0x7d, + 0xd3, 0xe2, 0xe6, 0xe9, 0x9e, + 0x84, 0xca, 0x2c, 0x36, 0x09, + 0xfd, 0xf1, 0x77, 0xfe, 0xb2, + 0x6d }, + key5_k[] = { 0x84, 0x9b, 0x57, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71 }, + + key6_x[] = { 0x98, 0xf5, 0x0a, 0x4f, 0xf6, + 0xc0, 0x58, 0x61, 0xc8, 0x86, + 0x0d, 0x13, 0xa6, 0x38, 0xea, + 0x56, 0xc3, 0xf5, 0xad, 0x75, + 0x90, 0xbb, 0xfb, 0xf0, 0x54, + 0xe1, 0xc7, 0xb4, 0xd9, 0x1d, + 0x62, 0x80 }, + key6_y[] = { 0xf0, 0x14, 0x00, 0xb0, 0x89, + 0x86, 0x78, 0x04, 0xb8, 0xe9, + 0xfc, 0x96, 0xc3, 0x93, 0x21, + 0x61, 0xf1, 0x93, 0x4f, 0x42, + 0x23, 0x06, 0x91, 0x70, 0xd9, + 0x24, 0xb7, 0xe0, 0x3b, 0xf8, + 0x22, 0xbb }, + key6_d[] = { 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce, 0xb2, 0x35, 0x31, + 0x61, 0x74, 0x0a, 0xac, 0xf1, + 0xf7, 0x16, 0x36, 0x47, 0x98, + 0x4b, 0x52, 0x2a, 0x84, 0x8d, + 0xf1, 0xc3 }, + + key7_k[] = { 0x84, 0x9b, 0x57, 0x21, 0x9d, + 0xae, 0x48, 0xde, 0x64, 0x6d, + 0x07, 0xdb, 0xb5, 0x33, 0x56, + 0x6e, 0x97, 0x66, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71, 0x88 }, + + key8_k[] = { 0x84, 0x9b, 0x57, 0x21, 0x9d, + 0xae, 0x48, 0xde, 0x64, 0x6d, + 0x07, 0xdb, 0xb5, 0x33, 0x56, + 0x6e, 0x97, 0x66, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71, 0x88, 0x00, 0x11, 0x22, + 0x33, 0x77, 0x88, 0x99, 0xaa, + 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28 }, + + key9_k[] = { 0x84, 0x9b, 0x57, 0x21, 0x9d, + 0xae, 0x48, 0xde, 0x64, 0x6d, + 0x07, 0xdb, 0xb5, 0x33, 0x56, + 0x6e, 0x97, 0x66, 0x86, 0x45, + 0x7c, 0x14, 0x91, 0xbe, 0x3a, + 0x76, 0xdc, 0xea, 0x6c, 0x42, + 0x71, 0x88, 0x00, 0x11, 0x22, + 0x33, 0x77, 0x88, 0x99, 0xaa, + 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xa0, + 0xb1, 0xb2, 0xb3, 0xb4 } +#if 0 + , + key10_x[] = { + 0xd7, 0x5a, 0x98, 0x01, 0x82, + 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, + 0xfe, 0xd3, 0xc9, 0x64, 0x07, + 0x3a, 0x0e, 0xe1, 0x72, 0xf3, + 0xda, 0xa6, 0x23, 0x25, 0xaf, + 0x02, 0x1a, 0x68, 0xf7, 0x07, + 0x51, 0x1a + }, key10_d[] = { + 0x9d, 0x61, 0xb1, 0x9d, 0xef, + 0xfd, 0x5a, 0x60, 0xba, 0x84, + 0x4a, 0xf4, 0x92, 0xec, 0x2c, + 0xc4, 0x44, 0x49, 0xc5, 0x69, + 0x7b, 0x32, 0x69, 0x19, 0x70, + 0x3b, 0xac, 0x03, 0x1c, 0xae, + 0x7f, 0x60 + } +#endif +; + +int +test_cose_keys(struct lws_context *context) +{ + struct lws_cose_key *ck; + lws_dll2_owner_t set; + lws_lec_pctx_t wc; + uint8_t buf[4096]; + int n; + +#if 0 + { + int fd = open("set1.cks", + LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600); + + if (fd >= 0) { + write(fd, cose_key_set1, sizeof(cose_key_set1)); + close(fd); + } + } +#endif + +#if 0 + lws_lec_pctx_t wx; + uint8_t dump[8192]; + + lws_lec_init(&wx, buf, sizeof(buf)); + + if (lws_lec_printf(&wx, + "{%d:%d, %d:%.*b, %d:%d, %d:%.*b, %d:%.*b}", + LWSCOSE_WKK_KTY, LWSCOSE_WKKTV_OKP, + LWSCOSE_WKK_KID, 2, "11", + LWSCOSE_WKOKP_CRV, LWSCOSE_WKEC_ED25519, + LWSCOSE_WKECKP_X, (int)sizeof(key10_x), key10_x, +// LWSCOSE_WKECKP_Y, (int)sizeof(key6_y), key6_y, + LWSCOSE_WKECKP_D, (int)sizeof(key10_d), key10_d) != + LWS_LECPCTX_RET_FINISHED) + return 1; + + lws_hex_from_byte_array(buf, wx.used, (char *)dump, sizeof(dump)); + puts((const char *)dump); +#endif +#if 0 + lws_lec_pctx_t wx; + uint8_t dump[8192]; + + lws_lec_init(&wx, buf, sizeof(buf)); + + if (lws_lec_printf(&wx, + "{%d:%d, %d:%.*b, %d:%.*b}", + LWSCOSE_WKK_KTY, LWSCOSE_WKKTV_SYMMETRIC, + LWSCOSE_WKK_KID, 6, "sec-64", + -1, (int)sizeof(key9_k), key9_k) != + LWS_LECPCTX_RET_FINISHED) + return 1; + + lws_hex_from_byte_array(buf, wx.used, (char *)dump, sizeof(dump)); + puts((const char *)dump); +#endif + + /* key1 import */ + + lwsl_user("%s: key 1 import\n", __func__); + + ck = lws_cose_key_import(NULL, key_import_cb, NULL, cose_key1, sizeof(cose_key1)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_EC2 || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_EC || + ck->e[LWS_GENCRYPTO_EC_KEYEL_X].len != sizeof(key1_x) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != sizeof(key1_y) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_D].len != sizeof(key1_d) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_X].buf, key1_x, sizeof(key1_x)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].buf, key1_y, sizeof(key1_y)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_D].buf, key1_d, sizeof(key1_d))) + goto bail; + + // lws_cose_key_dump(ck); + + /* key 1 export */ + + lwsl_user("%s: key 1 export\n", __func__); + + lws_lec_init(&wc, buf, sizeof(buf)); + n = (int)lws_cose_key_export(ck, &wc, LWSJWKF_EXPORT_PRIVATE); + lws_cose_key_destroy(&ck); + if (n != LWS_LECPCTX_RET_FINISHED) + goto bail; + + // lwsl_hexdump_notice(buf, wc.used); + + /* key2 import */ + + lwsl_user("%s: key 2 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key2, sizeof(cose_key2)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_EC2 || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_EC || + ck->e[LWS_GENCRYPTO_EC_KEYEL_X].len != sizeof(key2_x) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != sizeof(key2_y) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_D].len != sizeof(key2_d) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_X].buf, key2_x, sizeof(key2_x)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].buf, key2_y, sizeof(key2_y)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_D].buf, key2_d, sizeof(key2_d))) + goto bail; + + lws_cose_key_destroy(&ck); + + /* key3 import */ + + lwsl_user("%s: key 3 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key3, sizeof(cose_key3)); + if (!ck) { + lwsl_err("%s: key 3 import failed\n", __func__); + goto bail; + } + + if (ck->kty != LWSCOSE_WKKTV_SYMMETRIC || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_OCT || + ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].len != sizeof(key3_k) || + memcmp(ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, key3_k, sizeof(key3_k))) { + lwsl_err("%s: key 3 checks failed %d %d %d\n", __func__, + (int)ck->kty, (int)ck->gencrypto_kty, + (int)ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].len); + goto bail; + } + + lws_cose_key_destroy(&ck); + + /* key4 import */ + + lwsl_user("%s: key 4 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key4, sizeof(cose_key4)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_EC2 || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_EC || + ck->e[LWS_GENCRYPTO_EC_KEYEL_X].len != sizeof(key4_x) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != sizeof(key4_y) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_D].len != sizeof(key4_d) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_X].buf, key4_x, sizeof(key4_x)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].buf, key4_y, sizeof(key4_y)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_D].buf, key4_d, sizeof(key4_d))) + goto bail; + + lws_cose_key_destroy(&ck); + + /* key5 import */ + + lwsl_user("%s: key 5 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key5, sizeof(cose_key5)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_SYMMETRIC || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_OCT || + ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].len != sizeof(key5_k) || + memcmp(ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, key5_k, sizeof(key5_k))) + goto bail; + + lws_cose_key_destroy(&ck); + + /* key6 import */ + + lwsl_user("%s: key 6 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key6, sizeof(cose_key6)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_EC2 || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_EC || + ck->e[LWS_GENCRYPTO_EC_KEYEL_X].len != sizeof(key6_x) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != sizeof(key6_y) || + ck->e[LWS_GENCRYPTO_EC_KEYEL_D].len != sizeof(key6_d) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_X].buf, key6_x, sizeof(key6_x)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_Y].buf, key6_y, sizeof(key6_y)) || + memcmp(ck->e[LWS_GENCRYPTO_EC_KEYEL_D].buf, key6_d, sizeof(key6_d))) + goto bail; + + lws_cose_key_destroy(&ck); + + /* key7 import */ + + lwsl_user("%s: key 7 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key7, sizeof(cose_key7)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_SYMMETRIC || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_OCT || + ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].len != sizeof(key7_k) || + memcmp(ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, key7_k, sizeof(key7_k))) + goto bail; + + lws_cose_key_destroy(&ck); + + /* key8 import */ + + lwsl_user("%s: key 8 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key8, sizeof(cose_key8)); + if (!ck) + return 1; + + if (ck->kty != LWSCOSE_WKKTV_SYMMETRIC || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_OCT || + ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].len != sizeof(key8_k) || + memcmp(ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, key8_k, sizeof(key8_k))) + goto bail; + + lws_cose_key_destroy(&ck); + + /* key9 import */ + + lwsl_user("%s: key 9 import\n", __func__); + + ck = lws_cose_key_import(NULL, NULL, NULL, cose_key9, sizeof(cose_key9)); + if (!ck) { + lwsl_err("%s: cose9 import fail\n", __func__); + goto bail; + } + + if (ck->kty != LWSCOSE_WKKTV_SYMMETRIC || + ck->gencrypto_kty != LWS_GENCRYPTO_KTY_OCT || + ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].len != sizeof(key9_k) || + memcmp(ck->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, key9_k, sizeof(key9_k))) { + lwsl_notice("%s: key9 check fails\n", __func__); + goto bail; + } + + lws_cose_key_destroy(&ck); + + /* key set 1 */ + + lwsl_user("%s: key_set1\n", __func__); + lws_dll2_owner_clear(&set); + ck = lws_cose_key_import(&set, NULL, NULL, cose_key_set1, sizeof(cose_key_set1)); + if (!ck) + return 1; + + lws_cose_key_set_destroy(&set); + + /* generate */ + + ck = lws_cose_key_generate(context, LWSCOSE_WKKTV_EC2, + (1 << LWSCOSE_WKKO_SIGN) | + (1 << LWSCOSE_WKKO_VERIFY) | + (1 << LWSCOSE_WKKO_ENCRYPT) | + (1 << LWSCOSE_WKKO_DECRYPT), + 0, "P-256", (const uint8_t *)"the-keyid", 9); + if (!ck) + return 1; + + // lws_cose_key_dump(ck); + + lws_cose_key_destroy(&ck); + + return 0; + +bail: + lwsl_err("%s: selftest failed ++++++++++++++++++++\n", __func__); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/main.c new file mode 100644 index 00000000..19de29c5 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/main.c @@ -0,0 +1,50 @@ +/* + * lws-api-test-cose + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include + +int +test_cose_keys(struct lws_context *context); +int +test_cose_sign(struct lws_context *context); + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + const char *p; + int result = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS COSE api tests\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ +#if defined(LWS_WITH_NETWORK) + info.port = CONTEXT_PORT_NO_LISTEN; +#endif + info.options = 0; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + result |= test_cose_keys(context); + result |= test_cose_sign(context); + + lwsl_user("Completed: %s\n", result ? "FAIL" : "PASS"); + + lws_context_destroy(context); + + return result; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/sign.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/sign.c new file mode 100644 index 00000000..6c8c50b6 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-cose/sign.c @@ -0,0 +1,1862 @@ +/* + * lws-api-test-jose - RFC8152 cose_sign tests + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Raw key CBOR created from descriptions at + * + * https://github.com/cose-wg/Examples/blob/master/KeySet.txt + */ + +#include +#include +#include + +static const uint8_t + sign1_pass_01[] = { + /* + * https://github.com/cose-wg/Examples/blob/master/ + * sign1-tests/sign-pass-01.json + */ + 0xd2, 0x84, 0x41, 0xa0, 0xa2, + 0x01, 0x26, 0x04, 0x42, 0x31, + 0x31, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x58, 0x40, 0x87, + 0xdb, 0x0d, 0x2e, 0x55, 0x71, + 0x84, 0x3b, 0x78, 0xac, 0x33, + 0xec, 0xb2, 0x83, 0x0d, 0xf7, + 0xb6, 0xe0, 0xa4, 0xd5, 0xb7, + 0x37, 0x6d, 0xe3, 0x36, 0xb2, + 0x3c, 0x59, 0x1c, 0x90, 0xc4, + 0x25, 0x31, 0x7e, 0x56, 0x12, + 0x7f, 0xbe, 0x04, 0x37, 0x00, + 0x97, 0xce, 0x34, 0x70, 0x87, + 0xb2, 0x33, 0xbf, 0x72, 0x2b, + 0x64, 0x07, 0x2b, 0xeb, 0x44, + 0x86, 0xbd, 0xa4, 0x03, 0x1d, + 0x27, 0x24, 0x4f }, + sign1_pass_02[] = { + 0xd2, 0x84, 0x43, 0xa1, 0x01, + 0x26, 0xa1, 0x04, 0x42, 0x31, + 0x31, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x58, 0x40, 0x10, + 0x72, 0x9c, 0xd7, 0x11, 0xcb, + 0x38, 0x13, 0xd8, 0xd8, 0xe9, + 0x44, 0xa8, 0xda, 0x71, 0x11, + 0xe7, 0xb2, 0x58, 0xc9, 0xbd, + 0xca, 0x61, 0x35, 0xf7, 0xae, + 0x1a, 0xdb, 0xee, 0x95, 0x09, + 0x89, 0x12, 0x67, 0x83, 0x7e, + 0x1e, 0x33, 0xbd, 0x36, 0xc1, + 0x50, 0x32, 0x6a, 0xe6, 0x27, + 0x55, 0xc6, 0xbd, 0x8e, 0x54, + 0x0c, 0x3e, 0x8f, 0x92, 0xd7, + 0xd2, 0x25, 0xe8, 0xdb, 0x72, + 0xb8, 0x82, 0x0b }, + + sign1_pass_02_ext[] = { + 0x11, 0xaa, 0x22, 0xbb, 0x33, + 0xcc, 0x44, 0xdd, 0x55, 0x00, + 0x66, 0x99 }, + + sign1_pass_03[] = { + 0x84, 0x43, 0xa1, 0x01, 0x26, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x58, 0x40, 0x8e, 0xb3, + 0x3e, 0x4c, 0xa3, 0x1d, 0x1c, + 0x46, 0x5a, 0xb0, 0x5a, 0xac, + 0x34, 0xcc, 0x6b, 0x23, 0xd5, + 0x8f, 0xef, 0x5c, 0x08, 0x31, + 0x06, 0xc4, 0xd2, 0x5a, 0x91, + 0xae, 0xf0, 0xb0, 0x11, 0x7e, + 0x2a, 0xf9, 0xa2, 0x91, 0xaa, + 0x32, 0xe1, 0x4a, 0xb8, 0x34, + 0xdc, 0x56, 0xed, 0x2a, 0x22, + 0x34, 0x44, 0x54, 0x7e, 0x01, + 0xf1, 0x1d, 0x3b, 0x09, 0x16, + 0xe5, 0xa4, 0xc3, 0x45, 0xca, + 0xcb, 0x36 }, + sign1_fail_01[] = { + 0xd9, 0x03, 0xe6, 0x84, 0x43, + 0xa1, 0x01, 0x26, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x40, 0x8e, 0xb3, 0x3e, 0x4c, + 0xa3, 0x1d, 0x1c, 0x46, 0x5a, + 0xb0, 0x5a, 0xac, 0x34, 0xcc, + 0x6b, 0x23, 0xd5, 0x8f, 0xef, + 0x5c, 0x08, 0x31, 0x06, 0xc4, + 0xd2, 0x5a, 0x91, 0xae, 0xf0, + 0xb0, 0x11, 0x7e, 0x2a, 0xf9, + 0xa2, 0x91, 0xaa, 0x32, 0xe1, + 0x4a, 0xb8, 0x34, 0xdc, 0x56, + 0xed, 0x2a, 0x22, 0x34, 0x44, + 0x54, 0x7e, 0x01, 0xf1, 0x1d, + 0x3b, 0x09, 0x16, 0xe5, 0xa4, + 0xc3, 0x45, 0xca, 0xcb, 0x36 }, + sign1_fail_02[] = { + 0xd2, 0x84, 0x43, 0xa1, 0x01, + 0x26, 0xa1, 0x04, 0x42, 0x31, + 0x31, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2f, 0x58, 0x40, 0x8e, + 0xb3, 0x3e, 0x4c, 0xa3, 0x1d, + 0x1c, 0x46, 0x5a, 0xb0, 0x5a, + 0xac, 0x34, 0xcc, 0x6b, 0x23, + 0xd5, 0x8f, 0xef, 0x5c, 0x08, + 0x31, 0x06, 0xc4, 0xd2, 0x5a, + 0x91, 0xae, 0xf0, 0xb0, 0x11, + 0x7e, 0x2a, 0xf9, 0xa2, 0x91, + 0xaa, 0x32, 0xe1, 0x4a, 0xb8, + 0x34, 0xdc, 0x56, 0xed, 0x2a, + 0x22, 0x34, 0x44, 0x54, 0x7e, + 0x01, 0xf1, 0x1d, 0x3b, 0x09, + 0x16, 0xe5, 0xa4, 0xc3, 0x45, + 0xca, 0xcb, 0x36 }, + sign1_fail_03[] = { + 0xd2, 0x84, 0x45, 0xa1, 0x01, + 0x39, 0x03, 0xe6, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x40, 0x8e, 0xb3, 0x3e, 0x4c, + 0xa3, 0x1d, 0x1c, 0x46, 0x5a, + 0xb0, 0x5a, 0xac, 0x34, 0xcc, + 0x6b, 0x23, 0xd5, 0x8f, 0xef, + 0x5c, 0x08, 0x31, 0x06, 0xc4, + 0xd2, 0x5a, 0x91, 0xae, 0xf0, + 0xb0, 0x11, 0x7e, 0x2a, 0xf9, + 0xa2, 0x91, 0xaa, 0x32, 0xe1, + 0x4a, 0xb8, 0x34, 0xdc, 0x56, + 0xed, 0x2a, 0x22, 0x34, 0x44, + 0x54, 0x7e, 0x01, 0xf1, 0x1d, + 0x3b, 0x09, 0x16, 0xe5, 0xa4, + 0xc3, 0x45, 0xca, 0xcb, 0x36 }, + sign1_fail_04[] = { + 0xd2, 0x84, 0x4a, 0xa1, 0x01, + 0x67, 0x75, 0x6e, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x40, 0x8e, 0xb3, 0x3e, 0x4c, + 0xa3, 0x1d, 0x1c, 0x46, 0x5a, + 0xb0, 0x5a, 0xac, 0x34, 0xcc, + 0x6b, 0x23, 0xd5, 0x8f, 0xef, + 0x5c, 0x08, 0x31, 0x06, 0xc4, + 0xd2, 0x5a, 0x91, 0xae, 0xf0, + 0xb0, 0x11, 0x7e, 0x2a, 0xf9, + 0xa2, 0x91, 0xaa, 0x32, 0xe1, + 0x4a, 0xb8, 0x34, 0xdc, 0x56, + 0xed, 0x2a, 0x22, 0x34, 0x44, + 0x54, 0x7e, 0x01, 0xf1, 0x1d, + 0x3b, 0x09, 0x16, 0xe5, 0xa4, + 0xc3, 0x45, 0xca, 0xcb, 0x36 }, + + /* sign1/fail05 is missing upstream */ + + sign1_fail_06[] = { + 0xd2, 0x84, 0x45, 0xa2, 0x01, + 0x26, 0x03, 0x00, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x40, 0x8e, 0xb3, 0x3e, 0x4c, + 0xa3, 0x1d, 0x1c, 0x46, 0x5a, + 0xb0, 0x5a, 0xac, 0x34, 0xcc, + 0x6b, 0x23, 0xd5, 0x8f, 0xef, + 0x5c, 0x08, 0x31, 0x06, 0xc4, + 0xd2, 0x5a, 0x91, 0xae, 0xf0, + 0xb0, 0x11, 0x7e, 0x2a, 0xf9, + 0xa2, 0x91, 0xaa, 0x32, 0xe1, + 0x4a, 0xb8, 0x34, 0xdc, 0x56, + 0xed, 0x2a, 0x22, 0x34, 0x44, + 0x54, 0x7e, 0x01, 0xf1, 0x1d, + 0x3b, 0x09, 0x16, 0xe5, 0xa4, + 0xc3, 0x45, 0xca, 0xcb, 0x36 }, + + sign1_fail_07[] = { + 0xd2, 0x84, 0x43, 0xa1, 0x01, + 0x26, 0xa1, 0x04, 0x42, 0x31, + 0x31, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x58, 0x40, 0x65, + 0x20, 0xbb, 0xaf, 0x20, 0x81, + 0xd7, 0xe0, 0xed, 0x0f, 0x95, + 0xf7, 0x6e, 0xb0, 0x73, 0x3d, + 0x66, 0x70, 0x05, 0xf7, 0x46, + 0x7c, 0xec, 0x4b, 0x87, 0xb9, + 0x38, 0x1a, 0x6b, 0xa1, 0xed, + 0xe8, 0xe0, 0x0d, 0xf2, 0x9f, + 0x32, 0xa3, 0x72, 0x30, 0xf3, + 0x9a, 0x84, 0x2a, 0x54, 0x82, + 0x1f, 0xdd, 0x22, 0x30, 0x92, + 0x81, 0x9d, 0x77, 0x28, 0xef, + 0xb9, 0xd3, 0xa0, 0x08, 0x0b, + 0x75, 0x38, 0x0b }, + + sign_pass_01[] = { + 0xd8, 0x62, 0x84, 0x41, 0xa0, + 0xa0, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x81, 0x83, 0x43, + 0xa1, 0x01, 0x26, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0xe2, 0xae, 0xaf, 0xd4, 0x0d, + 0x69, 0xd1, 0x9d, 0xfe, 0x6e, + 0x52, 0x07, 0x7c, 0x5d, 0x7f, + 0xf4, 0xe4, 0x08, 0x28, 0x2c, + 0xbe, 0xfb, 0x5d, 0x06, 0xcb, + 0xf4, 0x14, 0xaf, 0x2e, 0x19, + 0xd9, 0x82, 0xac, 0x45, 0xac, + 0x98, 0xb8, 0x54, 0x4c, 0x90, + 0x8b, 0x45, 0x07, 0xde, 0x1e, + 0x90, 0xb7, 0x17, 0xc3, 0xd3, + 0x48, 0x16, 0xfe, 0x92, 0x6a, + 0x2b, 0x98, 0xf5, 0x3a, 0xfd, + 0x2f, 0xa0, 0xf3, 0x0a }, + + sign_pass_02[] = { + 0xd8, 0x62, 0x84, 0x40, 0xa0, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x81, 0x83, 0x43, 0xa1, + 0x01, 0x26, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0xcb, + 0xb8, 0xda, 0xd9, 0xbe, 0xaf, + 0xb8, 0x90, 0xe1, 0xa4, 0x14, + 0x12, 0x4d, 0x8b, 0xfb, 0xc2, + 0x6b, 0xed, 0xf2, 0xa9, 0x4f, + 0xcb, 0x5a, 0x88, 0x24, 0x32, + 0xbf, 0xf6, 0xd6, 0x3e, 0x15, + 0xf5, 0x74, 0xee, 0xb2, 0xab, + 0x51, 0xd8, 0x3f, 0xa2, 0xcb, + 0xf6, 0x26, 0x72, 0xeb, 0xf4, + 0xc7, 0xd9, 0x93, 0xb0, 0xf4, + 0xc2, 0x44, 0x76, 0x47, 0xd8, + 0x31, 0xba, 0x57, 0xcc, 0xa8, + 0x6b, 0x93, 0x0a }, + + sign_pass_03[] = { + 0x84, 0x40, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x81, + 0x83, 0x43, 0xa1, 0x01, 0x26, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0xe2, 0xae, 0xaf, + 0xd4, 0x0d, 0x69, 0xd1, 0x9d, + 0xfe, 0x6e, 0x52, 0x07, 0x7c, + 0x5d, 0x7f, 0xf4, 0xe4, 0x08, + 0x28, 0x2c, 0xbe, 0xfb, 0x5d, + 0x06, 0xcb, 0xf4, 0x14, 0xaf, + 0x2e, 0x19, 0xd9, 0x82, 0xac, + 0x45, 0xac, 0x98, 0xb8, 0x54, + 0x4c, 0x90, 0x8b, 0x45, 0x07, + 0xde, 0x1e, 0x90, 0xb7, 0x17, + 0xc3, 0xd3, 0x48, 0x16, 0xfe, + 0x92, 0x6a, 0x2b, 0x98, 0xf5, + 0x3a, 0xfd, 0x2f, 0xa0, 0xf3, + 0x0a }, + + sign_fail_01[] = { + 0xd9, 0x03, 0xe6, 0x84, 0x40, + 0xa0, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x81, 0x83, 0x43, + 0xa1, 0x01, 0x26, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0xe2, 0xae, 0xaf, 0xd4, 0x0d, + 0x69, 0xd1, 0x9d, 0xfe, 0x6e, + 0x52, 0x07, 0x7c, 0x5d, 0x7f, + 0xf4, 0xe4, 0x08, 0x28, 0x2c, + 0xbe, 0xfb, 0x5d, 0x06, 0xcb, + 0xf4, 0x14, 0xaf, 0x2e, 0x19, + 0xd9, 0x82, 0xac, 0x45, 0xac, + 0x98, 0xb8, 0x54, 0x4c, 0x90, + 0x8b, 0x45, 0x07, 0xde, 0x1e, + 0x90, 0xb7, 0x17, 0xc3, 0xd3, + 0x48, 0x16, 0xfe, 0x92, 0x6a, + 0x2b, 0x98, 0xf5, 0x3a, 0xfd, + 0x2f, 0xa0, 0xf3, 0x0a }, + + sign_fail_02[] = { + 0xd8, 0x62, 0x84, 0x40, 0xa0, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x81, 0x83, 0x43, 0xa1, + 0x01, 0x26, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0xe2, + 0xae, 0xaf, 0xd4, 0x0d, 0x69, + 0xd1, 0x9d, 0xfe, 0x6e, 0x52, + 0x07, 0x7c, 0x5d, 0x7f, 0xf4, + 0xe4, 0x08, 0x28, 0x2c, 0xbe, + 0xfb, 0x5d, 0x06, 0xcb, 0xf4, + 0x14, 0xaf, 0x2e, 0x19, 0xd9, + 0x82, 0xac, 0x45, 0xac, 0x98, + 0xb8, 0x54, 0x4c, 0x90, 0x8b, + 0x45, 0x07, 0xde, 0x1e, 0x90, + 0xb7, 0x17, 0xc3, 0xd3, 0x48, + 0x16, 0xfe, 0x92, 0x6a, 0x2b, + 0x98, 0xf5, 0x3a, 0xfd, 0x2f, + 0xa0, 0xf3, 0x0b }, + + sign_fail_03[] = { + 0xd8, 0x62, 0x84, 0x40, 0xa0, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x81, 0x83, 0x45, 0xa1, + 0x01, 0x39, 0x03, 0xe6, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xe2, 0xae, 0xaf, 0xd4, + 0x0d, 0x69, 0xd1, 0x9d, 0xfe, + 0x6e, 0x52, 0x07, 0x7c, 0x5d, + 0x7f, 0xf4, 0xe4, 0x08, 0x28, + 0x2c, 0xbe, 0xfb, 0x5d, 0x06, + 0xcb, 0xf4, 0x14, 0xaf, 0x2e, + 0x19, 0xd9, 0x82, 0xac, 0x45, + 0xac, 0x98, 0xb8, 0x54, 0x4c, + 0x90, 0x8b, 0x45, 0x07, 0xde, + 0x1e, 0x90, 0xb7, 0x17, 0xc3, + 0xd3, 0x48, 0x16, 0xfe, 0x92, + 0x6a, 0x2b, 0x98, 0xf5, 0x3a, + 0xfd, 0x2f, 0xa0, 0xf3, 0x0a }, + + sign_fail_04[] = { + 0xd8, 0x62, 0x84, 0x40, 0xa0, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x81, 0x83, 0x4a, 0xa1, + 0x01, 0x67, 0x75, 0x6e, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xe2, 0xae, 0xaf, 0xd4, + 0x0d, 0x69, 0xd1, 0x9d, 0xfe, + 0x6e, 0x52, 0x07, 0x7c, 0x5d, + 0x7f, 0xf4, 0xe4, 0x08, 0x28, + 0x2c, 0xbe, 0xfb, 0x5d, 0x06, + 0xcb, 0xf4, 0x14, 0xaf, 0x2e, + 0x19, 0xd9, 0x82, 0xac, 0x45, + 0xac, 0x98, 0xb8, 0x54, 0x4c, + 0x90, 0x8b, 0x45, 0x07, 0xde, + 0x1e, 0x90, 0xb7, 0x17, 0xc3, + 0xd3, 0x48, 0x16, 0xfe, 0x92, + 0x6a, 0x2b, 0x98, 0xf5, 0x3a, + 0xfd, 0x2f, 0xa0, 0xf3, 0x0a }, + + /* fail 5 missing upstream */ + + sign_fail_06[] = { + 0xd8, 0x62, 0x84, 0x43, 0xa1, + 0x03, 0x00, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x81, + 0x83, 0x43, 0xa1, 0x01, 0x26, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0xe2, 0xae, 0xaf, + 0xd4, 0x0d, 0x69, 0xd1, 0x9d, + 0xfe, 0x6e, 0x52, 0x07, 0x7c, + 0x5d, 0x7f, 0xf4, 0xe4, 0x08, + 0x28, 0x2c, 0xbe, 0xfb, 0x5d, + 0x06, 0xcb, 0xf4, 0x14, 0xaf, + 0x2e, 0x19, 0xd9, 0x82, 0xac, + 0x45, 0xac, 0x98, 0xb8, 0x54, + 0x4c, 0x90, 0x8b, 0x45, 0x07, + 0xde, 0x1e, 0x90, 0xb7, 0x17, + 0xc3, 0xd3, 0x48, 0x16, 0xfe, + 0x92, 0x6a, 0x2b, 0x98, 0xf5, + 0x3a, 0xfd, 0x2f, 0xa0, 0xf3, + 0x0a }, + + sign_fail_07[] = { + 0xd8, 0x62, 0x84, 0x41, 0xa0, + 0xa0, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x81, 0x83, 0x43, + 0xa1, 0x01, 0x26, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0xd7, 0x1c, 0x05, 0xdb, 0x52, + 0xc9, 0xce, 0x7f, 0x1b, 0xf5, + 0xaa, 0xc0, 0x13, 0x34, 0xbb, + 0xea, 0xca, 0xc1, 0xd8, 0x6a, + 0x23, 0x03, 0xe6, 0xee, 0xaa, + 0x89, 0x26, 0x6f, 0x45, 0xc0, + 0x1e, 0xd6, 0x02, 0xca, 0x64, + 0x9e, 0xaf, 0x79, 0x0d, 0x8b, + 0xc9, 0x9d, 0x24, 0x58, 0x45, + 0x7c, 0xa6, 0xa8, 0x72, 0x06, + 0x19, 0x40, 0xe7, 0xaf, 0xbe, + 0x48, 0xe2, 0x89, 0xdf, 0xac, + 0x14, 0x6a, 0xe2, 0x58 }, + + sign_hmac_01[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x05, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x20, 0x2b, 0xdc, 0xc8, 0x9f, + 0x05, 0x82, 0x16, 0xb8, 0xa2, + 0x08, 0xdd, 0xc6, 0xd8, 0xb5, + 0x4a, 0xa9, 0x1f, 0x48, 0xbd, + 0x63, 0x48, 0x49, 0x86, 0x56, + 0x51, 0x05, 0xc9, 0xad, 0x5a, + 0x66, 0x82, 0xf6, 0x81, 0x83, + 0x40, 0xa2, 0x01, 0x25, 0x04, + 0x4a, 0x6f, 0x75, 0x72, 0x2d, + 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x40 }, + + sign_hmac_02[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x06, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x30, 0xb3, 0x09, 0x7f, 0x70, + 0x00, 0x9a, 0x11, 0x50, 0x74, + 0x09, 0x59, 0x8a, 0x83, 0xe1, + 0x5b, 0xbb, 0xbf, 0x19, 0x82, + 0xdc, 0xe2, 0x8e, 0x5a, 0xb6, + 0xd5, 0xa6, 0xaf, 0xf6, 0x89, + 0x7b, 0xd2, 0x4b, 0xb8, 0xb7, + 0x47, 0x96, 0x22, 0xc9, 0x40, + 0x1b, 0x24, 0x09, 0x0d, 0x45, + 0x82, 0x06, 0xd5, 0x87, 0x81, + 0x83, 0x40, 0xa2, 0x01, 0x25, + 0x04, 0x46, 0x73, 0x65, 0x63, + 0x2d, 0x34, 0x38, 0x40 }, + + sign_hmac_03[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x07, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x40, 0xcd, 0x28, 0xa6, 0xb3, + 0xcf, 0xbb, 0xbf, 0x21, 0x48, + 0x51, 0xb9, 0x06, 0xe0, 0x50, + 0x05, 0x6c, 0xb4, 0x38, 0xa8, + 0xb8, 0x89, 0x05, 0xb8, 0xb7, + 0x46, 0x19, 0x77, 0x02, 0x27, + 0x11, 0xa9, 0xd8, 0xac, 0x5d, + 0xbc, 0x54, 0xe2, 0x9a, 0x56, + 0xd9, 0x26, 0x04, 0x6b, 0x40, + 0xfc, 0x26, 0x07, 0xc2, 0x5b, + 0x34, 0x44, 0x54, 0xaa, 0x5f, + 0x68, 0xde, 0x09, 0xa3, 0xe5, + 0x25, 0xd3, 0x86, 0x5a, 0x05, + 0x81, 0x83, 0x40, 0xa2, 0x01, + 0x25, 0x04, 0x46, 0x73, 0x65, + 0x63, 0x2d, 0x36, 0x34, 0x40 }, + + sign_hmac_04[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x05, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x58, + 0x20, 0x2b, 0xdc, 0xc8, 0x9f, + 0x05, 0x82, 0x16, 0xb8, 0xa2, + 0x08, 0xdd, 0xc6, 0xd8, 0xb5, + 0x4a, 0xa9, 0x1f, 0x48, 0xbd, + 0x63, 0x48, 0x49, 0x86, 0x56, + 0x51, 0x05, 0xc9, 0xad, 0x5a, + 0x66, 0x82, 0xf7, 0x81, 0x83, + 0x40, 0xa2, 0x01, 0x25, 0x04, + 0x4a, 0x6f, 0x75, 0x72, 0x2d, + 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x40 }, + + sign_hmac_05[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x04, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x48, + 0x6f, 0x35, 0xca, 0xb7, 0x79, + 0xf7, 0x78, 0x33, 0x81, 0x83, + 0x40, 0xa2, 0x01, 0x25, 0x04, + 0x4a, 0x6f, 0x75, 0x72, 0x2d, + 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x40 }, + + enc_hmac_01[] = { + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x05, 0xa0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x20, + 0xa1, 0xa8, 0x48, 0xd3, 0x47, + 0x1f, 0x9d, 0x61, 0xee, 0x49, + 0x01, 0x8d, 0x24, 0x4c, 0x82, + 0x47, 0x72, 0xf2, 0x23, 0xad, + 0x4f, 0x93, 0x52, 0x93, 0xf1, + 0x78, 0x9f, 0xc3, 0xa0, 0x8d, + 0x8c, 0x58 }, + + enc_hmac_02[] = { + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x06, 0xa0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x30, + 0x99, 0x8d, 0x26, 0xc6, 0x45, + 0x9a, 0xae, 0xec, 0xf4, 0x4e, + 0xd2, 0x0c, 0xe0, 0x0c, 0x8c, + 0xce, 0xdf, 0x0a, 0x1f, 0x3d, + 0x22, 0xa9, 0x2f, 0xc0, 0x5d, + 0xb0, 0x8c, 0x5a, 0xeb, 0x1c, + 0xb5, 0x94, 0xca, 0xaf, 0x5a, + 0x5c, 0x5e, 0x2e, 0x9d, 0x01, + 0xcc, 0xe7, 0xe7, 0x7a, 0x93, + 0xaa, 0x8c, 0x62 }, + + enc_hmac_03[] = { + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x07, 0xa0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x40, + 0x4a, 0x55, 0x5b, 0xf9, 0x71, + 0xf7, 0xc1, 0x89, 0x1d, 0x9d, + 0xdf, 0x30, 0x4a, 0x1a, 0x13, + 0x2e, 0x2d, 0x6f, 0x81, 0x74, + 0x49, 0x47, 0x4d, 0x81, 0x3e, + 0x6d, 0x04, 0xd6, 0x59, 0x62, + 0xbe, 0xd8, 0xbb, 0xa7, 0x0c, + 0x17, 0xe1, 0xf5, 0x30, 0x8f, + 0xa3, 0x99, 0x62, 0x95, 0x9a, + 0x4b, 0x9b, 0x8d, 0x7d, 0xa8, + 0xe6, 0xd8, 0x49, 0xb2, 0x09, + 0xdc, 0xd3, 0xe9, 0x8c, 0xc0, + 0xf1, 0x1e, 0xdd, 0xf2 }, + + enc_hmac_04[] = { + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x05, 0xa0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x20, + 0xa1, 0xa8, 0x48, 0xd3, 0x47, + 0x1f, 0x9d, 0x61, 0xee, 0x49, + 0x01, 0x8d, 0x24, 0x4c, 0x82, + 0x47, 0x72, 0xf2, 0x23, 0xad, + 0x4f, 0x93, 0x52, 0x93, 0xf1, + 0x78, 0x9f, 0xc3, 0xa0, 0x8d, + 0x8c, 0x59 }, + + enc_hmac_05[] = { + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x04, 0xa0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x48, 0x11, + 0xf9, 0xe3, 0x57, 0x97, 0x5f, + 0xb8, 0x49 } +#if 0 +, + + countersign_sign_01[] = { + 0xd8, 0x62, 0x84, 0x43, 0xa1, + 0x03, 0x00, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x81, + 0x83, 0x43, 0xa1, 0x01, 0x27, + 0xa2, 0x07, 0x83, 0x43, 0xa1, + 0x01, 0x27, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x8e, + 0x1b, 0xe2, 0xf9, 0x45, 0x3d, + 0x26, 0x48, 0x12, 0xe5, 0x90, + 0x49, 0x91, 0x32, 0xbe, 0xf3, + 0xfb, 0xf9, 0xee, 0x9d, 0xb2, + 0x7c, 0x2c, 0x16, 0x87, 0x88, + 0xe3, 0xb7, 0xeb, 0xe5, 0x06, + 0xc0, 0x4f, 0xd3, 0xd1, 0x9f, + 0xaa, 0x9f, 0x51, 0x23, 0x2a, + 0xf5, 0xc9, 0x59, 0xe4, 0xef, + 0x47, 0x92, 0x88, 0x34, 0x64, + 0x7f, 0x56, 0xdf, 0xbe, 0x93, + 0x91, 0x12, 0x88, 0x4d, 0x08, + 0xef, 0x25, 0x05, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x77, + 0xf3, 0xea, 0xcd, 0x11, 0x85, + 0x2c, 0x4b, 0xf9, 0xcb, 0x1d, + 0x72, 0xfa, 0xbe, 0x6b, 0x26, + 0xfb, 0xa1, 0xd7, 0x60, 0x92, + 0xb2, 0xb5, 0xb7, 0xec, 0x83, + 0xb8, 0x35, 0x57, 0x65, 0x22, + 0x64, 0xe6, 0x96, 0x90, 0xdb, + 0xc1, 0x17, 0x2d, 0xdc, 0x0b, + 0xf8, 0x84, 0x11, 0xc0, 0xd2, + 0x5a, 0x50, 0x7f, 0xdb, 0x24, + 0x7a, 0x20, 0xc4, 0x0d, 0x5e, + 0x24, 0x5f, 0xab, 0xd3, 0xfc, + 0x9e, 0xc1, 0x06 } +#endif +; + +extern const struct { + const uint8_t *set; + size_t len; +} keyset1, key3, key8, key9, key10; + +static int +xcb(lws_cose_sig_ext_pay_t *x) +{ + x->ext = sign1_pass_02_ext; + x->xl = sizeof(sign1_pass_02_ext); + + return LCOSESIGEXTCB_RET_FINISHED; +} + + + +int +test_cose_sign(struct lws_context *context) +{ + struct lws_cose_validate_context *cps; + lws_cose_validate_create_info_t info; + lws_cose_validate_res_t *res; + lws_dll2_owner_t set; + lws_dll2_owner_t *o; + int n; + + memset(&info, 0, sizeof(info)); + info.cx = context; + info.keyset = &set; + +#if 1 + { + int fd = open("sign_hmac01.sig", + LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600); + + if (fd >= 0) { + write(fd, sign_hmac_01, sizeof(sign_hmac_01)); + close(fd); + } + } +#endif + + /* + * valid sign1 we have key for + */ + + lwsl_user("%s: sign1/sign-pass-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_pass_01, sizeof(sign1_pass_01), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid sign1 but empty key set, so can't judge it + */ + + lwsl_user("%s: sign1/sign-pass-01 - no key\n", __func__); + + lws_dll2_owner_clear(&set); + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_pass_01, sizeof(sign1_pass_01), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid sign1 + */ + + lwsl_user("%s: sign1/sign-pass-02\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + info.ext_cb = xcb; + info.ext_len = sizeof(sign1_pass_02_ext); + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_pass_02, sizeof(sign1_pass_02), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid sign1 without enclosing tag + */ + + lwsl_user("%s: sign1/sign-pass-03\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + info.ext_cb = NULL; + info.ext_len = 0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_pass_03, sizeof(sign1_pass_03), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * sign1 with wrong tag + */ + + lwsl_user("%s: sign1/sign-fail-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_fail_01, sizeof(sign1_fail_01), + NULL); + if (!n) { + lwsl_notice("%s: sign_val_chunk should have failed\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid sign1, signature tampered + */ + + lwsl_user("%s: sign1/sign-fail-02\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_fail_02, sizeof(sign1_fail_02), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + /* validation result must be fail */ + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid sign1, alg tampered + */ + + lwsl_user("%s: sign1/sign-fail-03\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_fail_03, sizeof(sign1_fail_03), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + /* validation result must be fail */ + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid sign1, alg sign tampered + */ + + lwsl_user("%s: sign1/sign-fail-04\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_fail_04, sizeof(sign1_fail_04), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + /* validation result must be fail */ + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid sign1, protected attributes tampered + */ + + lwsl_user("%s: sign1/sign-fail-06\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_fail_06, sizeof(sign1_fail_06), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + /* validation result must be fail */ + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid sign1, protected attribute removed + */ + + lwsl_user("%s: sign1/sign-fail-07\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_SINGLE; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign1_fail_07, sizeof(sign1_fail_07), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) + goto bail1; + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + /* validation result must be fail */ + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid sign we have key for + */ + + lwsl_user("%s: sign/sign-pass-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_pass_01, sizeof(sign_pass_01), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid sign we have key for + */ + + lwsl_user("%s: sign/sign-pass-02\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + info.ext_cb = xcb; + info.ext_len = sizeof(sign1_pass_02_ext); + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_pass_02, sizeof(sign_pass_02), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid sign we have key for + */ + + lwsl_user("%s: sign/sign-pass-03\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + info.ext_cb = NULL; + info.ext_len = 0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_pass_03, sizeof(sign_pass_03), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * wrong cbor tag + */ + + lwsl_user("%s: sign/sign-fail-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_fail_01, sizeof(sign_fail_01), + NULL); + if (!n) { + lwsl_notice("%s: sign_val_chunk should fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * tampered signature + */ + + lwsl_user("%s: sign/sign-fail-02\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_fail_02, sizeof(sign_fail_02), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * tampered sign alg -999 + */ + + lwsl_user("%s: sign/sign-fail-03\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_fail_03, sizeof(sign_fail_03), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * tampered sign alg 0 + */ + + lwsl_user("%s: sign/sign-fail-04\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_fail_04, sizeof(sign_fail_04), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * add protected attribute + */ + + lwsl_user("%s: sign/sign-fail-06\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_fail_06, sizeof(sign_fail_06), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * remove protected attribute + */ + + lwsl_user("%s: sign/sign-fail-07\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MULTI; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_fail_07, sizeof(sign_fail_07), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_notice("%s: results: %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) + goto bail1; + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + + /* + * valid HMAC sign we have key for + */ + + lwsl_user("%s: hmac-examples/hmac-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_hmac_01, sizeof(sign_hmac_01), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid HMAC sign we have key for + */ + + lwsl_user("%s: hmac-examples/hmac-02\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_hmac_02, sizeof(sign_hmac_02), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + + /* + * valid HMAC sign we have key for + */ + + lwsl_user("%s: hmac-examples/hmac-03\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_hmac_03, sizeof(sign_hmac_03), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid HMAC sign we have key for + */ + + lwsl_user("%s: hmac-examples/hmac-04 fail mac tag\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_hmac_04, sizeof(sign_hmac_04), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) { + lwsl_err("%s: result is wrongly succeeding\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid HMAC sign we have key for HS256/64 + */ + + lwsl_user("%s: hmac-examples/hmac-05\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, keyset1.set, keyset1.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, sign_hmac_05, sizeof(sign_hmac_05), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid HMAC sign with implicit HS256 key + */ + + lwsl_user("%s: hmac-examples/enc-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, key3.set, key3.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, enc_hmac_01, sizeof(enc_hmac_01), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid HMAC sign with implicit HS384 key + */ + + lwsl_user("%s: hmac-examples/enc-02\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, key8.set, key8.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, enc_hmac_02, sizeof(enc_hmac_02), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid HMAC sign with implicit HS512 key + */ + + lwsl_user("%s: hmac-examples/enc-03\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, key9.set, key9.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, enc_hmac_03, sizeof(enc_hmac_03), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * invalid HMAC sign with implicit HS256 key, tampered hmac tag + */ + + lwsl_user("%s: hmac-examples/enc-04\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, key3.set, key3.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, enc_hmac_04, sizeof(enc_hmac_04), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (!res->result) { + lwsl_err("%s: result wrongly succeeds\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); + + /* + * valid HMAC sign with implicit HS256 key, HS256/64 + */ + + lwsl_user("%s: hmac-examples/enc-05\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, key3.set, key3.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_MAC0; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, enc_hmac_05, sizeof(enc_hmac_05), + NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); +#if 0 + /* + * valid Ed25519 signature with countersignature from same key + alg + */ + + lwsl_user("%s: countersign/sign-01\n", __func__); + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, key10.set, key10.len)) { + lwsl_notice("%s: key import fail\n", __func__); + return 1; + } + + info.sigtype = SIGTYPE_COUNTERSIGNED; + cps = lws_cose_validate_create(&info); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + n = lws_cose_validate_chunk(cps, countersign_sign_01, + sizeof(countersign_sign_01), NULL); + if (n) { + lwsl_notice("%s: sign_val_chunk failed\n", __func__); + goto bail1; + } + + o = lws_cose_validate_results(cps); + if (o->count != 1) { + lwsl_err("%s: result count %d\n", __func__, o->count); + goto bail1; + } + + res = lws_container_of(o->head, lws_cose_validate_res_t, list); + if (res->result) { + lwsl_err("%s: result is fail\n", __func__); + goto bail1; + } + + lws_cose_validate_destroy(&cps); + lws_cose_key_set_destroy(&set); +#endif + + return 0; + +bail1: + lws_cose_validate_destroy(&cps); +bail: + lws_cose_key_set_destroy(&set); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-dhcpc/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-dhcpc/main.c index 3914f439..b0dccbb3 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-dhcpc/main.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-dhcpc/main.c @@ -52,7 +52,9 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; +#if !defined(__COVERITY__) const char *p; +#endif int n = 1; signal(SIGINT, sigint_handler); @@ -64,8 +66,10 @@ main(int argc, const char **argv) info.port = CONTEXT_PORT_NO_LISTEN; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#if !defined(__COVERITY__) if ((p = lws_cmdline_option(argc, argv, "-i"))) nif = p; +#endif context = lws_create_context(&info); if (!context) { diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt index 6bfe7f21..a3678d56 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt @@ -11,7 +11,7 @@ set(SRCS main.c lws-genaes.c lws-genec.c) set(requirements 1) require_lws_config(LWS_WITH_GENCRYPTO 1 requirements) require_lws_config(LWS_WITH_JOSE 1 requirements) - +require_lws_config(USE_WOLFSSL 0 requirements) if (requirements) diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c index 90636472..e7f2aa2f 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c @@ -9,6 +9,10 @@ #include + +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CBC))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_cbc)) + static const uint8_t /* * produced with (plaintext.txt contains "test plaintext\0\0") @@ -101,7 +105,10 @@ test_genaes_cbc(void) return -1; } +#endif +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CFB))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_cfb128)) static const uint8_t /* * produced with (plaintext.txt contains "test plaintext\0\0") @@ -188,6 +195,10 @@ test_genaes_cfb128(void) return -1; } +#endif + +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CFB))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_cfb8)) static const uint8_t /* @@ -272,7 +283,10 @@ test_genaes_cfb8(void) return -1; } +#endif +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CTR))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_ctr)) static const uint8_t /* * produced with (plaintext.txt contains "test plaintext\0\0") @@ -365,7 +379,10 @@ test_genaes_ctr(void) return -1; } +#endif +#if (defined(LWS_WITH_MBEDTLS)) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_ecb)) static const uint8_t /* * produced with (plaintext.txt contains "test plaintext\0\0") @@ -449,10 +466,10 @@ test_genaes_ecb(void) return -1; } +#endif -#if defined(MBEDTLS_CONFIG_H) && !defined(MBEDTLS_CIPHER_MODE_OFB) -#else - +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_OFB))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_ofb)) static const uint8_t /* * produced with (plaintext.txt contains "test plaintext\0\0") @@ -481,7 +498,6 @@ static const uint8_t 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, } ; - static int test_genaes_ofb(void) { @@ -549,8 +565,8 @@ test_genaes_ofb(void) #endif -#if defined(MBEDTLS_CONFIG_H) && !defined(MBEDTLS_CIPHER_MODE_XTS) -#else +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_XTS))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_xts)) static const uint8_t /* @@ -575,10 +591,10 @@ static const uint8_t 0x5f, 0x31, 0x9e, 0xcd, 0x33, 0x08, 0xa0, 0x44 } ; - static int test_genaes_xts(void) { + struct lws_genaes_ctx ctx; struct lws_gencrypto_keyelem e; uint8_t res[32], res1[32], data_unit[16]; @@ -757,30 +773,38 @@ test_genaes_gcm(void) int test_genaes(struct lws_context *context) { - +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CBC))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_cbc)) if (test_genaes_cbc()) goto bail; - +#endif +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CFB))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_cfb128)) if (test_genaes_cfb128()) goto bail; - +#endif +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CFB))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_cfb8)) if (test_genaes_cfb8()) goto bail; - +#endif +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_CTR))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_ctr)) if (test_genaes_ctr()) goto bail; - +#endif +#if (defined(LWS_WITH_MBEDTLS)) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_ecb)) if (test_genaes_ecb()) goto bail; - -#if defined(MBEDTLS_CONFIG_H) && !defined(MBEDTLS_CIPHER_MODE_OFB) -#else +#endif +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_OFB))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_ofb)) if (test_genaes_ofb()) goto bail; #endif - -#if defined(MBEDTLS_CONFIG_H) && !defined(MBEDTLS_CIPHER_MODE_XTS) -#else +#if (defined(LWS_WITH_MBEDTLS) && (!defined(MBEDTLS_CONFIG_H) || defined(MBEDTLS_CIPHER_MODE_XTS))) || \ + (!defined(LWS_WITH_MBEDTLS) && defined(LWS_HAVE_EVP_aes_128_xts)) if (test_genaes_xts()) goto bail; #endif diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-jose/jws.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-jose/jws.c index 7626e1ca..b6f8e699 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-jose/jws.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-jose/jws.c @@ -853,14 +853,14 @@ test_jwt_RS256(struct lws_context *context) goto bail; } - if (lws_x509_jwk_privkey_pem(&jwk, (char *)rsa_key, + if (lws_x509_jwk_privkey_pem(context, &jwk, (char *)rsa_key, LWS_ARRAY_SIZE(rsa_key), NULL)) { lwsl_err("%s: failed to copy private key to jwk\n", __func__); goto bail; } if (lws_x509_info(pub, LWS_TLS_CERT_INFO_DER_RAW, der_info, - LWS_ARRAY_SIZE(der_buf) - sizeof(der_info) + + LWS_ARRAY_SIZE(der_buf) - sizeof(*der_info) + sizeof(der_info->ns.name)) || der_info->ns.len <= 0) { lwsl_err("%s: failed to parse x509 public key\n", __func__); diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/CMakeLists.txt new file mode 100644 index 00000000..b09ee02e --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/CMakeLists.txt @@ -0,0 +1,22 @@ +project(lws-api-test-lecp C) +cmake_minimum_required(VERSION 2.8.12) +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_CBOR 1 requirements) + +if (requirements) + + add_executable(${PROJECT_NAME} main.c) + add_test(NAME api-test-lecp COMMAND lws-api-test-lecp) + + 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 --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/README.md b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/README.md new file mode 100644 index 00000000..ebe930d2 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/README.md @@ -0,0 +1,56 @@ +# lws api test lws_struct JSON + +Demonstrates how to use and performs selftests for lws_struct +JSON serialization and deserialization + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-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 +``` + diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/main.c new file mode 100644 index 00000000..89133d70 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lecp/main.c @@ -0,0 +1,5020 @@ +/* + * lws-api-test-lecp + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * unit tests for lecp + */ + +#include + +#if defined(LWS_WITH_CBOR_FLOAT) +#include +#endif + +#define VERBOSE + +#if defined(VERBOSE) +static const char * const reason_names[] = { + "LECPCB_CONSTRUCTED", + "LECPCB_DESTRUCTED", + "LECPCB_START", + "LECPCB_COMPLETE", + "LECPCB_FAILED", + "LECPCB_PAIR_NAME", + "LECPCB_VAL_TRUE", + "LECPCB_VAL_FALSE", + "LECPCB_VAL_NULL", + "LECPCB_VAL_NUM_INT", + "LECPCB_VAL_RESERVED", /* float in lejp */ + "LECPCB_VAL_STR_START", + "LECPCB_VAL_STR_CHUNK", + "LECPCB_VAL_STR_END", + "LECPCB_ARRAY_START", + "LECPCB_ARRAY_END", + "LECPCB_OBJECT_START", + "LECPCB_OBJECT_END", + "LECPCB_TAG_START", + "LECPCB_TAG_END", + "LECPCB_VAL_NUM_UINT", + "LECPCB_VAL_UNDEFINED", + "LECPCB_VAL_FLOAT16", + "LECPCB_VAL_FLOAT32", + "LECPCB_VAL_FLOAT64", + "LECPCB_VAL_SIMPLE", + "LECPCB_VAL_BLOB_START", + "LECPCB_VAL_BLOB_CHUNK", + "LECPCB_VAL_BLOB_END", + "LECPCB_ARRAY_ITEM_START", + "LECPCB_ARRAY_ITEM_END", + "LECPCB_LITERAL_CBOR" +}; +#endif + +/* + * Based on the official CBOR test vectors from here + * + * https://github.com/cbor/test-vectors/blob/master/appendix_a.json + */ + +static const uint8_t + test1[] = { 0x00 }, + test2[] = { 0x01 }, + test3[] = { 0x0a }, + test4[] = { 0x17 }, + test5[] = { 0x18, 0x18 }, + test6[] = { 0x18, 0x19 }, + test7[] = { 0x18, 0x64 }, + test8[] = { 0x19, 0x03, 0xe8 }, + test9[] = { 0x1a, 0x00, 0x0f, 0x42, 0x40 }, + test10[] = { 0x1b, 0x00, 0x00, 0x00, + 0xe8, 0xd4, 0xa5, 0x10, 0x00 }, + test11[] = { 0x1b, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff }, + test12[] = { 0xc2, 0x49, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 }, + test13[] = { 0x3b, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff }, + test14[] = { 0xc3, 0x49, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 }, + test15[] = { 0x20 }, + test16[] = { 0x29 }, + test17[] = { 0x38, 0x63 }, + test18[] = { 0x39, 0x03, 0xe7 }, + test19[] = { 0xf9, 0x00, 0x00 }, + test20[] = { 0xf9, 0x80, 0x00 }, + test21[] = { 0xf9, 0x3c, 0x00 }, + test22[] = { 0xfb, 0x3f, 0xf1, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x9a }, + test23[] = { 0xf9, 0x3e, 0x00 }, + test24[] = { 0xf9, 0x7b, 0xff }, + test25[] = { 0xfa, 0x47, 0xc3, 0x50, 0x00 }, + test26[] = { 0xfa, 0x7f, 0x7f, 0xff, 0xff }, + test27[] = { 0xfb, 0x7e, 0x37, 0xe4, 0x3c, + 0x88, 0x00, 0x75, 0x9c }, + test28[] = { 0xf9, 0x00, 0x01 }, + test29[] = { 0xf9, 0x04, 0x00 }, + test30[] = { 0xf9, 0xc4, 0x00 }, + test31[] = { 0xfb, 0xc0, 0x10, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66 }, + test32[] = { 0xf9, 0x7c, 0x00 }, + test33[] = { 0xf9, 0x7e, 0x00 }, + test34[] = { 0xf9, 0xfc, 0x00 }, + test35[] = { 0xfa, 0x7f, 0x80, 0x00, 0x00 }, + test36[] = { 0xfa, 0x7f, 0xc0, 0x00, 0x00 }, + test37[] = { 0xfa, 0xff, 0x80, 0x00, 0x00 }, + test38[] = { 0xfb, 0x7f, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + test39[] = { 0xfb, 0x7f, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + test40[] = { 0xfb, 0xff, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + test41[] = { 0xf4 }, + test42[] = { 0xf5 }, + test43[] = { 0xf6 }, + test44[] = { 0xf7 }, + test45[] = { 0xf0 }, + test46[] = { 0xf8, 0x18 }, + test47[] = { 0xf8, 0xff }, + test48[] = { 0xc0, 0x74, 0x32, 0x30, 0x31, + 0x33, 0x2d, 0x30, 0x33, 0x2d, + 0x32, 0x31, 0x54, 0x32, 0x30, + 0x3a, 0x30, 0x34, 0x3a, 0x30, + 0x30, 0x5a }, + test49[] = { 0xc1, 0x1a, 0x51, 0x4b, 0x67, + 0xb0 }, + test50[] = { 0xc1, 0xfb, 0x41, 0xd4, 0x52, + 0xd9, 0xec, 0x20, 0x00, 0x00 }, + test51[] = { 0xd7, 0x44, 0x01, 0x02, 0x03, + 0x04 }, + test52[] = { 0xd8, 0x18, 0x45, 0x64, 0x49, + 0x45, 0x54, 0x46 }, + test53[] = { 0xd8, 0x20, 0x76, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x77, 0x77, 0x77, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d }, + test54[] = { 0x40 }, + test55[] = { 0x44, 0x01, 0x02, 0x03, 0x04 }, + test56[] = { 0x60 }, + test57[] = { 0x61, 0x61 }, + test58[] = { 0x64, 0x49, 0x45, 0x54, 0x46 }, + test59[] = { 0x62, 0x22, 0x5c }, + test60[] = { 0x62, 0xc3, 0xbc }, + test61[] = { 0x63, 0xe6, 0xb0, 0xb4 }, + test62[] = { 0x64, 0xf0, 0x90, 0x85, 0x91 }, + test63[] = { 0x80 }, + test64[] = { 0x83, 0x01, 0x02, 0x03 }, + test65[] = { 0x83, 0x01, 0x82, 0x02, 0x03, + 0x82, 0x04, 0x05 }, + test66[] = { 0x98, 0x19, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x18, 0x18, 0x19 }, + test67[] = { 0xa0 }, + test68[] = { 0xa2, 0x01, 0x02, 0x03, 0x04 }, + test69[] = { 0xa2, 0x61, 0x61, 0x01, 0x61, + 0x62, 0x82, 0x02, 0x03 }, + test70[] = { 0x82, 0x61, 0x61, 0xa1, 0x61, + 0x62, 0x61, 0x63 }, + test71[] = { 0xa5, 0x61, 0x61, 0x61, 0x41, + 0x61, 0x62, 0x61, 0x42, 0x61, + 0x63, 0x61, 0x43, 0x61, 0x64, + 0x61, 0x44, 0x61, 0x65, 0x61, + 0x45 }, + test72[] = { 0x5f, 0x42, 0x01, 0x02, 0x43, + 0x03, 0x04, 0x05, 0xff }, + test73[] = { 0x7f, 0x65, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x67, 0xff }, + test74[] = { 0x9f, 0xff }, + test75[] = { 0x9f, 0x01, 0x82, 0x02, 0x03, + 0x9f, 0x04, 0x05, 0xff, 0xff }, + test76[] = { 0x9f, 0x01, 0x82, 0x02, 0x03, + 0x82, 0x04, 0x05, 0xff }, + test77[] = { 0x83, 0x01, 0x82, 0x02, 0x03, + 0x9f, 0x04, 0x05, 0xff }, + test78[] = { 0x83, 0x01, 0x9f, 0x02, 0x03, + 0xff, 0x82, 0x04, 0x05 }, + test79[] = { 0x9f, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, + 0x18, 0x18, 0x19, 0xff }, + test80[] = { 0xbf, 0x61, 0x61, 0x01, 0x61, + 0x62, 0x9f, 0x02, 0x03, 0xff, + 0xff }, + test81[] = { 0x82, 0x61, 0x61, 0xbf, 0x61, + 0x62, 0x61, 0x63, 0xff }, + test82[] = { 0xbf, 0x63, 0x46, 0x75, 0x6e, + 0xf5, 0x63, 0x41, 0x6d, 0x74, + 0x21, 0xff }, + + /* some random COSE examples + * + * COSE hmac-01 test vector + */ + + test83[] = { 0xD8, 0x61, 0x85, 0x43, 0xA1, + 0x01, 0x05, 0xA0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E, 0x58, + 0x20, 0x2B, 0xDC, 0xC8, 0x9F, + 0x05, 0x82, 0x16, 0xB8, 0xA2, + 0x08, 0xDD, 0xC6, 0xD8, 0xB5, + 0x4A, 0xA9, 0x1F, 0x48, 0xBD, + 0x63, 0x48, 0x49, 0x86, 0x56, + 0x51, 0x05, 0xC9, 0xAD, 0x5A, + 0x66, 0x82, 0xF6, 0x81, 0x83, + 0x40, 0xA2, 0x01, 0x25, 0x04, + 0x4A, 0x6F, 0x75, 0x72, 0x2D, + 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x40 }, + /* + * COSE hmac-02 test vector + */ + test84[] = { 0xD8, 0x61, 0x85, 0x43, 0xA1, + 0x01, 0x06, 0xA0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E, 0x58, + 0x30, 0xB3, 0x09, 0x7F, 0x70, + 0x00, 0x9A, 0x11, 0x50, 0x74, + 0x09, 0x59, 0x8A, 0x83, 0xE1, + 0x5B, 0xBB, 0xBF, 0x19, 0x82, + 0xDC, 0xE2, 0x8E, 0x5A, 0xB6, + 0xD5, 0xA6, 0xAF, 0xF6, 0x89, + 0x7B, 0xD2, 0x4B, 0xB8, 0xB7, + 0x47, 0x96, 0x22, 0xC9, 0x40, + 0x1B, 0x24, 0x09, 0x0D, 0x45, + 0x82, 0x06, 0xD5, 0x87, 0x81, + 0x83, 0x40, 0xA2, 0x01, 0x25, + 0x04, 0x46, 0x73, 0x65, 0x63, + 0x2D, 0x34, 0x38, 0x40 }, + test85[] = { 0xD8, 0x61, 0x85, 0x43, 0xA1, + 0x01, 0x07, 0xA0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E, 0x58, + 0x40, 0xCD, 0x28, 0xA6, 0xB3, + 0xCF, 0xBB, 0xBF, 0x21, 0x48, + 0x51, 0xB9, 0x06, 0xE0, 0x50, + 0x05, 0x6C, 0xB4, 0x38, 0xA8, + 0xB8, 0x89, 0x05, 0xB8, 0xB7, + 0x46, 0x19, 0x77, 0x02, 0x27, + 0x11, 0xA9, 0xD8, 0xAC, 0x5D, + 0xBC, 0x54, 0xE2, 0x9A, 0x56, + 0xD9, 0x26, 0x04, 0x6B, 0x40, + 0xFC, 0x26, 0x07, 0xC2, 0x5B, + 0x34, 0x44, 0x54, 0xAA, 0x5F, + 0x68, 0xDE, 0x09, 0xA3, 0xE5, + 0x25, 0xD3, 0x86, 0x5A, 0x05, + 0x81, 0x83, 0x40, 0xA2, 0x01, + 0x25, 0x04, 0x46, 0x73, 0x65, + 0x63, 0x2D, 0x36, 0x34, 0x40 }, + test86[] = { 0xD8, 0x61, 0x85, 0x43, 0xA1, + 0x01, 0x05, 0xA0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E, 0x58, + 0x20, 0x2B, 0xDC, 0xC8, 0x9F, + 0x05, 0x82, 0x16, 0xB8, 0xA2, + 0x08, 0xDD, 0xC6, 0xD8, 0xB5, + 0x4A, 0xA9, 0x1F, 0x48, 0xBD, + 0x63, 0x48, 0x49, 0x86, 0x56, + 0x51, 0x05, 0xC9, 0xAD, 0x5A, + 0x66, 0x82, 0xF7, 0x81, 0x83, + 0x40, 0xA2, 0x01, 0x25, 0x04, + 0x4A, 0x6F, 0x75, 0x72, 0x2D, + 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x40 }, + test87[] = { 0xD8, 0x61, 0x85, 0x43, 0xA1, + 0x01, 0x04, 0xA0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E, 0x48, + 0x6F, 0x35, 0xCA, 0xB7, 0x79, + 0xF7, 0x78, 0x33, 0x81, 0x83, + 0x40, 0xA2, 0x01, 0x25, 0x04, + 0x4A, 0x6F, 0x75, 0x72, 0x2D, + 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x40 + + /* COSE HMAX Enc 01 vector */ + + }, test88[] = { 0xD1, 0x84, 0x43, 0xA1, 0x01, + 0x05, 0xA0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x2E, 0x58, 0x20, + 0xA1, 0xA8, 0x48, 0xD3, 0x47, + 0x1F, 0x9D, 0x61, 0xEE, 0x49, + 0x01, 0x8D, 0x24, 0x4C, 0x82, + 0x47, 0x72, 0xF2, 0x23, 0xAD, + 0x4F, 0x93, 0x52, 0x93, 0xF1, + 0x78, 0x9F, 0xC3, 0xA0, 0x8D, + 0x8C, 0x58 + }, test89[] = { 0xD1, 0x84, 0x43, 0xA1, 0x01, + 0x06, 0xA0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x2E, 0x58, 0x30, + 0x99, 0x8D, 0x26, 0xC6, 0x45, + 0x9A, 0xAE, 0xEC, 0xF4, 0x4E, + 0xD2, 0x0C, 0xE0, 0x0C, 0x8C, + 0xCE, 0xDF, 0x0A, 0x1F, 0x3D, + 0x22, 0xA9, 0x2F, 0xC0, 0x5D, + 0xB0, 0x8C, 0x5A, 0xEB, 0x1C, + 0xB5, 0x94, 0xCA, 0xAF, 0x5A, + 0x5C, 0x5E, 0x2E, 0x9D, 0x01, + 0xCC, 0xE7, 0xE7, 0x7A, 0x93, + 0xAA, 0x8C, 0x62 + }, test90[] = { 0xD1, 0x84, 0x43, 0xA1, 0x01, + 0x07, 0xA0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x2E, 0x58, 0x40, + 0x4A, 0x55, 0x5B, 0xF9, 0x71, + 0xF7, 0xC1, 0x89, 0x1D, 0x9D, + 0xDF, 0x30, 0x4A, 0x1A, 0x13, + 0x2E, 0x2D, 0x6F, 0x81, 0x74, + 0x49, 0x47, 0x4D, 0x81, 0x3E, + 0x6D, 0x04, 0xD6, 0x59, 0x62, + 0xBE, 0xD8, 0xBB, 0xA7, 0x0C, + 0x17, 0xE1, 0xF5, 0x30, 0x8F, + 0xA3, 0x99, 0x62, 0x95, 0x9A, + 0x4B, 0x9B, 0x8D, 0x7D, 0xA8, + 0xE6, 0xD8, 0x49, 0xB2, 0x09, + 0xDC, 0xD3, 0xE9, 0x8C, 0xC0, + 0xF1, 0x1E, 0xDD, 0xF2 + + }, test91[] = { 0xD1, 0x84, 0x43, 0xA1, 0x01, + 0x05, 0xA0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x2E, 0x58, 0x20, + 0xA1, 0xA8, 0x48, 0xD3, 0x47, + 0x1F, 0x9D, 0x61, 0xEE, 0x49, + 0x01, 0x8D, 0x24, 0x4C, 0x82, + 0x47, 0x72, 0xF2, 0x23, 0xAD, + 0x4F, 0x93, 0x52, 0x93, 0xF1, + 0x78, 0x9F, 0xC3, 0xA0, 0x8D, + 0x8C, 0x59 + + }, test92[] = { 0xD1, 0x84, 0x43, 0xA1, 0x01, + 0x04, 0xA0, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x6E, 0x74, 0x2E, 0x48, 0x11, + 0xF9, 0xE3, 0x57, 0x97, 0x5F, + 0xB8, 0x49 + + /* + * COSE countersign encrypt-01 + */ + + }, test93[] = { + 0xd0, 0x83, 0x43, 0xa1, 0x01, + 0x01, 0xa2, 0x05, 0x4c, 0x02, + 0xd1, 0xf7, 0xe6, 0xf2, 0x6c, + 0x43, 0xd4, 0x86, 0x8d, 0x87, + 0xce, 0x07, 0x83, 0x43, 0xa1, + 0x01, 0x27, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0xe1, + 0x04, 0x39, 0x15, 0x4c, 0xc7, + 0x5c, 0x7a, 0x3a, 0x53, 0x91, + 0x49, 0x1f, 0x88, 0x65, 0x1e, + 0x02, 0x92, 0xfd, 0x0f, 0xe0, + 0xe0, 0x2c, 0xf7, 0x40, 0x54, + 0x7e, 0xaf, 0x66, 0x77, 0xb4, + 0xa4, 0x04, 0x0b, 0x8e, 0xca, + 0x16, 0xdb, 0x59, 0x28, 0x81, + 0x26, 0x2f, 0x77, 0xb1, 0x4c, + 0x1a, 0x08, 0x6c, 0x02, 0x26, + 0x8b, 0x17, 0x17, 0x1c, 0xa1, + 0x6b, 0xe4, 0xb8, 0x59, 0x5f, + 0x8c, 0x0a, 0x08, 0x58, 0x24, + 0x60, 0x97, 0x3a, 0x94, 0xbb, + 0x28, 0x98, 0x00, 0x9e, 0xe5, + 0x2e, 0xcf, 0xd9, 0xab, 0x1d, + 0xd2, 0x58, 0x67, 0x37, 0x4b, + 0x16, 0x2e, 0x2c, 0x03, 0x56, + 0x8b, 0x41, 0xf5, 0x7c, 0x3c, + 0xc1, 0x6f, 0x91, 0x66, 0x25, + 0x0a + /* + * COSE countersign encrypt-02 + */ + }, test94[] = { + 0xd0, 0x83, 0x43, 0xa1, 0x01, + 0x01, 0xa2, 0x05, 0x4c, 0x02, + 0xd1, 0xf7, 0xe6, 0xf2, 0x6c, + 0x43, 0xd4, 0x86, 0x8d, 0x87, + 0xce, 0x07, 0x82, 0x83, 0x43, + 0xa1, 0x01, 0x27, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0xe1, 0x04, 0x39, 0x15, 0x4c, + 0xc7, 0x5c, 0x7a, 0x3a, 0x53, + 0x91, 0x49, 0x1f, 0x88, 0x65, + 0x1e, 0x02, 0x92, 0xfd, 0x0f, + 0xe0, 0xe0, 0x2c, 0xf7, 0x40, + 0x54, 0x7e, 0xaf, 0x66, 0x77, + 0xb4, 0xa4, 0x04, 0x0b, 0x8e, + 0xca, 0x16, 0xdb, 0x59, 0x28, + 0x81, 0x26, 0x2f, 0x77, 0xb1, + 0x4c, 0x1a, 0x08, 0x6c, 0x02, + 0x26, 0x8b, 0x17, 0x17, 0x1c, + 0xa1, 0x6b, 0xe4, 0xb8, 0x59, + 0x5f, 0x8c, 0x0a, 0x08, 0x83, + 0x43, 0xa1, 0x01, 0x26, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xfc, 0xa9, 0x8e, 0xca, + 0xc8, 0x0b, 0x5f, 0xeb, 0x3a, + 0xc7, 0xc1, 0x08, 0xb2, 0xb7, + 0x91, 0x10, 0xde, 0x88, 0x86, + 0x7b, 0xc0, 0x42, 0x6f, 0xc8, + 0x3c, 0x53, 0xcc, 0xd6, 0x78, + 0x96, 0x94, 0xed, 0xc5, 0xfe, + 0xe3, 0xc4, 0x0d, 0xe8, 0xe7, + 0xb4, 0x4f, 0xe8, 0xaa, 0xd3, + 0x67, 0xe0, 0x95, 0xc8, 0xfc, + 0x31, 0xb7, 0x9e, 0xe6, 0x66, + 0xdf, 0x9c, 0xf9, 0x09, 0x06, + 0xeb, 0x43, 0x75, 0x6c, 0x73, + 0x58, 0x24, 0x60, 0x97, 0x3a, + 0x94, 0xbb, 0x28, 0x98, 0x00, + 0x9e, 0xe5, 0x2e, 0xcf, 0xd9, + 0xab, 0x1d, 0xd2, 0x58, 0x67, + 0x37, 0x4b, 0x16, 0x2e, 0x2c, + 0x03, 0x56, 0x8b, 0x41, 0xf5, + 0x7c, 0x3c, 0xc1, 0x6f, 0x91, + 0x66, 0x25, 0x0a + + /* + * COSE countersign enveloped-01 + */ + }, test95[] = { + 0xd8, 0x60, 0x84, 0x43, 0xa1, + 0x01, 0x01, 0xa2, 0x05, 0x4c, + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce, 0x07, 0x83, 0x43, + 0xa1, 0x01, 0x27, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0x9a, 0x8e, 0xed, 0xe3, 0xb3, + 0xcb, 0x83, 0x7b, 0xa0, 0x0d, + 0xf0, 0x8f, 0xa2, 0x1b, 0x12, + 0x8b, 0x2d, 0x6d, 0x91, 0x62, + 0xa4, 0x29, 0x0a, 0x58, 0x2d, + 0x9f, 0x19, 0xbd, 0x0f, 0xb5, + 0x02, 0xf0, 0xf9, 0x2b, 0x9b, + 0xf4, 0x53, 0xa4, 0x05, 0x40, + 0x1f, 0x8b, 0x70, 0x55, 0xef, + 0x4e, 0x95, 0x8d, 0xf7, 0xf4, + 0xfb, 0xd7, 0xcf, 0xb4, 0xa0, + 0xc9, 0x71, 0x60, 0xf9, 0x47, + 0x2b, 0x0a, 0xa1, 0x04, 0x58, + 0x24, 0x60, 0x97, 0x3a, 0x94, + 0xbb, 0x28, 0x98, 0x00, 0x9e, + 0xe5, 0x2e, 0xcf, 0xd9, 0xab, + 0x1d, 0xd2, 0x58, 0x67, 0x37, + 0x4b, 0x35, 0x81, 0xf2, 0xc8, + 0x00, 0x39, 0x82, 0x63, 0x50, + 0xb9, 0x7a, 0xe2, 0x30, 0x0e, + 0x42, 0xfc, 0x81, 0x83, 0x40, + 0xa2, 0x01, 0x25, 0x04, 0x4a, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x40 + }, test96[] = { + 0xd8, 0x60, 0x84, 0x43, 0xa1, + 0x01, 0x01, 0xa2, 0x05, 0x4c, + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce, 0x07, 0x82, 0x83, + 0x43, 0xa1, 0x01, 0x27, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0x9a, 0x8e, 0xed, 0xe3, + 0xb3, 0xcb, 0x83, 0x7b, 0xa0, + 0x0d, 0xf0, 0x8f, 0xa2, 0x1b, + 0x12, 0x8b, 0x2d, 0x6d, 0x91, + 0x62, 0xa4, 0x29, 0x0a, 0x58, + 0x2d, 0x9f, 0x19, 0xbd, 0x0f, + 0xb5, 0x02, 0xf0, 0xf9, 0x2b, + 0x9b, 0xf4, 0x53, 0xa4, 0x05, + 0x40, 0x1f, 0x8b, 0x70, 0x55, + 0xef, 0x4e, 0x95, 0x8d, 0xf7, + 0xf4, 0xfb, 0xd7, 0xcf, 0xb4, + 0xa0, 0xc9, 0x71, 0x60, 0xf9, + 0x47, 0x2b, 0x0a, 0xa1, 0x04, + 0x83, 0x43, 0xa1, 0x01, 0x26, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0x24, 0x27, 0xcb, + 0x37, 0x56, 0x85, 0x0f, 0xbb, + 0x79, 0x05, 0x18, 0x07, 0xc8, + 0xb2, 0x3d, 0x2e, 0x6d, 0x16, + 0xa3, 0x22, 0x4f, 0x99, 0x01, + 0xb4, 0x73, 0x99, 0xcf, 0xc7, + 0xe3, 0xfa, 0xc4, 0xcc, 0x62, + 0x1d, 0xbb, 0xeb, 0x02, 0x02, + 0xa6, 0xd8, 0xbb, 0x25, 0x69, + 0x5c, 0x9d, 0xcc, 0x9c, 0x47, + 0x49, 0x20, 0xff, 0x57, 0x60, + 0x6d, 0x76, 0x4d, 0xea, 0x19, + 0x2f, 0xc8, 0x67, 0x41, 0x16, + 0xf2, 0x58, 0x24, 0x60, 0x97, + 0x3a, 0x94, 0xbb, 0x28, 0x98, + 0x00, 0x9e, 0xe5, 0x2e, 0xcf, + 0xd9, 0xab, 0x1d, 0xd2, 0x58, + 0x67, 0x37, 0x4b, 0x35, 0x81, + 0xf2, 0xc8, 0x00, 0x39, 0x82, + 0x63, 0x50, 0xb9, 0x7a, 0xe2, + 0x30, 0x0e, 0x42, 0xfc, 0x81, + 0x83, 0x40, 0xa2, 0x01, 0x25, + 0x04, 0x4a, 0x6f, 0x75, 0x72, + 0x2d, 0x73, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x40 + + }, test97[] = { + 0xd8, 0x60, 0x84, 0x43, 0xa1, + 0x01, 0x01, 0xa1, 0x05, 0x4c, + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce, 0x58, 0x24, 0x60, + 0x97, 0x3a, 0x94, 0xbb, 0x28, + 0x98, 0x00, 0x9e, 0xe5, 0x2e, + 0xcf, 0xd9, 0xab, 0x1d, 0xd2, + 0x58, 0x67, 0x37, 0x4b, 0x35, + 0x81, 0xf2, 0xc8, 0x00, 0x39, + 0x82, 0x63, 0x50, 0xb9, 0x7a, + 0xe2, 0x30, 0x0e, 0x42, 0xfc, + 0x81, 0x83, 0x40, 0xa3, 0x01, + 0x25, 0x04, 0x4a, 0x6f, 0x75, + 0x72, 0x2d, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x07, 0x83, + 0x43, 0xa1, 0x01, 0x27, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xcc, 0xb1, 0xf3, 0xfe, + 0xdf, 0xce, 0xa7, 0x2b, 0x9c, + 0x86, 0x79, 0x63, 0xe2, 0x52, + 0xb6, 0x65, 0x8a, 0xd0, 0x7f, + 0x3f, 0x5f, 0x15, 0xa3, 0x26, + 0xa3, 0xf5, 0x72, 0x54, 0xcc, + 0xb8, 0xd4, 0x8d, 0x60, 0x02, + 0x1d, 0x2f, 0x1f, 0x8a, 0x80, + 0x3b, 0x84, 0x4b, 0x78, 0x72, + 0x16, 0x6c, 0x6d, 0x45, 0x90, + 0x25, 0xd2, 0x1c, 0x8c, 0x84, + 0x62, 0xa2, 0x44, 0xba, 0x19, + 0x60, 0x4e, 0xc4, 0xd5, 0x0b, + 0x40 + }, test98[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x05, 0xa1, 0x07, 0x83, + 0x43, 0xa1, 0x01, 0x27, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xb4, 0x92, 0x4b, 0x18, + 0xeb, 0x4e, 0x04, 0x73, 0x13, + 0xc7, 0x07, 0xb0, 0xed, 0xa4, + 0xab, 0x84, 0x43, 0x45, 0xf2, + 0xc4, 0x49, 0x87, 0xd6, 0xf9, + 0xeb, 0xcc, 0x77, 0x7e, 0xfd, + 0x40, 0x78, 0xcc, 0x0f, 0x4c, + 0x10, 0x8d, 0xef, 0x95, 0x9f, + 0x78, 0xf1, 0xed, 0xb2, 0x76, + 0x54, 0x25, 0x78, 0x5f, 0xcd, + 0x17, 0xd5, 0x12, 0xbe, 0x31, + 0xee, 0xb6, 0x6b, 0xef, 0xf1, + 0xe8, 0xfc, 0x27, 0x47, 0x07, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x58, 0x20, 0x2b, 0xdc, + 0xc8, 0x9f, 0x05, 0x82, 0x16, + 0xb8, 0xa2, 0x08, 0xdd, 0xc6, + 0xd8, 0xb5, 0x4a, 0xa9, 0x1f, + 0x48, 0xbd, 0x63, 0x48, 0x49, + 0x86, 0x56, 0x51, 0x05, 0xc9, + 0xad, 0x5a, 0x66, 0x82, 0xf6, + 0x81, 0x83, 0x40, 0xa2, 0x01, + 0x25, 0x04, 0x4a, 0x6f, 0x75, + 0x72, 0x2d, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x40 + }, test99[] = { + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x05, 0xa1, 0x07, 0x82, + 0x83, 0x43, 0xa1, 0x01, 0x27, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0xb4, 0x92, 0x4b, + 0x18, 0xeb, 0x4e, 0x04, 0x73, + 0x13, 0xc7, 0x07, 0xb0, 0xed, + 0xa4, 0xab, 0x84, 0x43, 0x45, + 0xf2, 0xc4, 0x49, 0x87, 0xd6, + 0xf9, 0xeb, 0xcc, 0x77, 0x7e, + 0xfd, 0x40, 0x78, 0xcc, 0x0f, + 0x4c, 0x10, 0x8d, 0xef, 0x95, + 0x9f, 0x78, 0xf1, 0xed, 0xb2, + 0x76, 0x54, 0x25, 0x78, 0x5f, + 0xcd, 0x17, 0xd5, 0x12, 0xbe, + 0x31, 0xee, 0xb6, 0x6b, 0xef, + 0xf1, 0xe8, 0xfc, 0x27, 0x47, + 0x07, 0x83, 0x43, 0xa1, 0x01, + 0x26, 0xa1, 0x04, 0x42, 0x31, + 0x31, 0x58, 0x40, 0x6a, 0xcd, + 0x94, 0xd3, 0xcc, 0xf7, 0x1d, + 0x19, 0x2e, 0x85, 0x28, 0x36, + 0x0b, 0xa7, 0xe3, 0x46, 0xda, + 0xc4, 0x64, 0xe9, 0xed, 0xca, + 0x4c, 0xfe, 0xb6, 0xce, 0xb6, + 0xbd, 0xe7, 0xba, 0xec, 0x9f, + 0xf2, 0x6c, 0xa6, 0xbd, 0xf7, + 0x3d, 0x0b, 0xe4, 0x1e, 0x36, + 0x12, 0x9d, 0xcf, 0xf7, 0x51, + 0xdd, 0x2b, 0x5a, 0xd5, 0xce, + 0x11, 0x6e, 0x8a, 0x96, 0x3a, + 0x27, 0x38, 0xa2, 0x99, 0x47, + 0x7a, 0x68, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x20, + 0x2b, 0xdc, 0xc8, 0x9f, 0x05, + 0x82, 0x16, 0xb8, 0xa2, 0x08, + 0xdd, 0xc6, 0xd8, 0xb5, 0x4a, + 0xa9, 0x1f, 0x48, 0xbd, 0x63, + 0x48, 0x49, 0x86, 0x56, 0x51, + 0x05, 0xc9, 0xad, 0x5a, 0x66, + 0x82, 0xf6, 0x81, 0x83, 0x40, + 0xa2, 0x01, 0x25, 0x04, 0x4a, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x40 + }, test100[] = { + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x05, 0xa1, 0x07, 0x83, 0x43, + 0xa1, 0x01, 0x27, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07, 0x54, + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e, + 0x58, 0x20, 0xa1, 0xa8, 0x48, + 0xd3, 0x47, 0x1f, 0x9d, 0x61, + 0xee, 0x49, 0x01, 0x8d, 0x24, + 0x4c, 0x82, 0x47, 0x72, 0xf2, + 0x23, 0xad, 0x4f, 0x93, 0x52, + 0x93, 0xf1, 0x78, 0x9f, 0xc3, + 0xa0, 0x8d, 0x8c, 0x58 + }, test101[] = { /* mac-02 */ + 0xd8, 0x61, 0x85, 0x43, 0xa1, + 0x01, 0x05, 0xa1, 0x07, 0x82, + 0x83, 0x43, 0xa1, 0x01, 0x27, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0xb4, 0x92, 0x4b, + 0x18, 0xeb, 0x4e, 0x04, 0x73, + 0x13, 0xc7, 0x07, 0xb0, 0xed, + 0xa4, 0xab, 0x84, 0x43, 0x45, + 0xf2, 0xc4, 0x49, 0x87, 0xd6, + 0xf9, 0xeb, 0xcc, 0x77, 0x7e, + 0xfd, 0x40, 0x78, 0xcc, 0x0f, + 0x4c, 0x10, 0x8d, 0xef, 0x95, + 0x9f, 0x78, 0xf1, 0xed, 0xb2, + 0x76, 0x54, 0x25, 0x78, 0x5f, + 0xcd, 0x17, 0xd5, 0x12, 0xbe, + 0x31, 0xee, 0xb6, 0x6b, 0xef, + 0xf1, 0xe8, 0xfc, 0x27, 0x47, + 0x07, 0x83, 0x43, 0xa1, 0x01, + 0x26, 0xa1, 0x04, 0x42, 0x31, + 0x31, 0x58, 0x40, 0x6a, 0xcd, + 0x94, 0xd3, 0xcc, 0xf7, 0x1d, + 0x19, 0x2e, 0x85, 0x28, 0x36, + 0x0b, 0xa7, 0xe3, 0x46, 0xda, + 0xc4, 0x64, 0xe9, 0xed, 0xca, + 0x4c, 0xfe, 0xb6, 0xce, 0xb6, + 0xbd, 0xe7, 0xba, 0xec, 0x9f, + 0xf2, 0x6c, 0xa6, 0xbd, 0xf7, + 0x3d, 0x0b, 0xe4, 0x1e, 0x36, + 0x12, 0x9d, 0xcf, 0xf7, 0x51, + 0xdd, 0x2b, 0x5a, 0xd5, 0xce, + 0x11, 0x6e, 0x8a, 0x96, 0x3a, + 0x27, 0x38, 0xa2, 0x99, 0x47, + 0x7a, 0x68, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x20, + 0x2b, 0xdc, 0xc8, 0x9f, 0x05, + 0x82, 0x16, 0xb8, 0xa2, 0x08, + 0xdd, 0xc6, 0xd8, 0xb5, 0x4a, + 0xa9, 0x1f, 0x48, 0xbd, 0x63, + 0x48, 0x49, 0x86, 0x56, 0x51, + 0x05, 0xc9, 0xad, 0x5a, 0x66, + 0x82, 0xf6, 0x81, 0x83, 0x40, + 0xa2, 0x01, 0x25, 0x04, 0x4a, + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, + 0x40 + }, test102[] = { /* mac0-01 */ + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x05, 0xa1, 0x07, 0x83, 0x43, + 0xa1, 0x01, 0x27, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07, 0x54, + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e, + 0x58, 0x20, 0xa1, 0xa8, 0x48, + 0xd3, 0x47, 0x1f, 0x9d, 0x61, + 0xee, 0x49, 0x01, 0x8d, 0x24, + 0x4c, 0x82, 0x47, 0x72, 0xf2, + 0x23, 0xad, 0x4f, 0x93, 0x52, + 0x93, 0xf1, 0x78, 0x9f, 0xc3, + 0xa0, 0x8d, 0x8c, 0x58 + }, test103[] = { /* mac0-02 */ + 0xd1, 0x84, 0x43, 0xa1, 0x01, + 0x05, 0xa1, 0x07, 0x82, 0x83, + 0x43, 0xa1, 0x01, 0x27, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xb4, 0x92, 0x4b, 0x18, + 0xeb, 0x4e, 0x04, 0x73, 0x13, + 0xc7, 0x07, 0xb0, 0xed, 0xa4, + 0xab, 0x84, 0x43, 0x45, 0xf2, + 0xc4, 0x49, 0x87, 0xd6, 0xf9, + 0xeb, 0xcc, 0x77, 0x7e, 0xfd, + 0x40, 0x78, 0xcc, 0x0f, 0x4c, + 0x10, 0x8d, 0xef, 0x95, 0x9f, + 0x78, 0xf1, 0xed, 0xb2, 0x76, + 0x54, 0x25, 0x78, 0x5f, 0xcd, + 0x17, 0xd5, 0x12, 0xbe, 0x31, + 0xee, 0xb6, 0x6b, 0xef, 0xf1, + 0xe8, 0xfc, 0x27, 0x47, 0x07, + 0x83, 0x43, 0xa1, 0x01, 0x26, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0x6a, 0xcd, 0x94, + 0xd3, 0xcc, 0xf7, 0x1d, 0x19, + 0x2e, 0x85, 0x28, 0x36, 0x0b, + 0xa7, 0xe3, 0x46, 0xda, 0xc4, + 0x64, 0xe9, 0xed, 0xca, 0x4c, + 0xfe, 0xb6, 0xce, 0xb6, 0xbd, + 0xe7, 0xba, 0xec, 0x9f, 0xf2, + 0x6c, 0xa6, 0xbd, 0xf7, 0x3d, + 0x0b, 0xe4, 0x1e, 0x36, 0x12, + 0x9d, 0xcf, 0xf7, 0x51, 0xdd, + 0x2b, 0x5a, 0xd5, 0xce, 0x11, + 0x6e, 0x8a, 0x96, 0x3a, 0x27, + 0x38, 0xa2, 0x99, 0x47, 0x7a, + 0x68, 0x54, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x58, 0x20, 0xa1, + 0xa8, 0x48, 0xd3, 0x47, 0x1f, + 0x9d, 0x61, 0xee, 0x49, 0x01, + 0x8d, 0x24, 0x4c, 0x82, 0x47, + 0x72, 0xf2, 0x23, 0xad, 0x4f, + 0x93, 0x52, 0x93, 0xf1, 0x78, + 0x9f, 0xc3, 0xa0, 0x8d, 0x8c, + 0x58 + }, test104[] = { /* signed-01 */ + 0xd8, 0x62, 0x84, 0x43, 0xa1, + 0x03, 0x00, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x81, + 0x83, 0x43, 0xa1, 0x01, 0x27, + 0xa2, 0x07, 0x83, 0x43, 0xa1, + 0x01, 0x27, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x8e, + 0x1b, 0xe2, 0xf9, 0x45, 0x3d, + 0x26, 0x48, 0x12, 0xe5, 0x90, + 0x49, 0x91, 0x32, 0xbe, 0xf3, + 0xfb, 0xf9, 0xee, 0x9d, 0xb2, + 0x7c, 0x2c, 0x16, 0x87, 0x88, + 0xe3, 0xb7, 0xeb, 0xe5, 0x06, + 0xc0, 0x4f, 0xd3, 0xd1, 0x9f, + 0xaa, 0x9f, 0x51, 0x23, 0x2a, + 0xf5, 0xc9, 0x59, 0xe4, 0xef, + 0x47, 0x92, 0x88, 0x34, 0x64, + 0x7f, 0x56, 0xdf, 0xbe, 0x93, + 0x91, 0x12, 0x88, 0x4d, 0x08, + 0xef, 0x25, 0x05, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x77, + 0xf3, 0xea, 0xcd, 0x11, 0x85, + 0x2c, 0x4b, 0xf9, 0xcb, 0x1d, + 0x72, 0xfa, 0xbe, 0x6b, 0x26, + 0xfb, 0xa1, 0xd7, 0x60, 0x92, + 0xb2, 0xb5, 0xb7, 0xec, 0x83, + 0xb8, 0x35, 0x57, 0x65, 0x22, + 0x64, 0xe6, 0x96, 0x90, 0xdb, + 0xc1, 0x17, 0x2d, 0xdc, 0x0b, + 0xf8, 0x84, 0x11, 0xc0, 0xd2, + 0x5a, 0x50, 0x7f, 0xdb, 0x24, + 0x7a, 0x20, 0xc4, 0x0d, 0x5e, + 0x24, 0x5f, 0xab, 0xd3, 0xfc, + 0x9e, 0xc1, 0x06 + }, test105[] = { /* signed-02 */ + 0xd8, 0x62, 0x84, 0x43, 0xa1, + 0x03, 0x00, 0xa0, 0x54, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2e, 0x81, + 0x83, 0x43, 0xa1, 0x01, 0x27, + 0xa2, 0x07, 0x82, 0x83, 0x43, + 0xa1, 0x01, 0x27, 0xa1, 0x04, + 0x42, 0x31, 0x31, 0x58, 0x40, + 0x8e, 0x1b, 0xe2, 0xf9, 0x45, + 0x3d, 0x26, 0x48, 0x12, 0xe5, + 0x90, 0x49, 0x91, 0x32, 0xbe, + 0xf3, 0xfb, 0xf9, 0xee, 0x9d, + 0xb2, 0x7c, 0x2c, 0x16, 0x87, + 0x88, 0xe3, 0xb7, 0xeb, 0xe5, + 0x06, 0xc0, 0x4f, 0xd3, 0xd1, + 0x9f, 0xaa, 0x9f, 0x51, 0x23, + 0x2a, 0xf5, 0xc9, 0x59, 0xe4, + 0xef, 0x47, 0x92, 0x88, 0x34, + 0x64, 0x7f, 0x56, 0xdf, 0xbe, + 0x93, 0x91, 0x12, 0x88, 0x4d, + 0x08, 0xef, 0x25, 0x05, 0x83, + 0x43, 0xa1, 0x01, 0x26, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xaf, 0x04, 0x9b, 0x80, + 0xd5, 0x2c, 0x36, 0x69, 0xb2, + 0x99, 0x70, 0xc1, 0x33, 0x54, + 0x37, 0x54, 0xf9, 0xcc, 0x60, + 0x8c, 0xe4, 0x11, 0x23, 0xae, + 0x1c, 0x82, 0x7e, 0x36, 0xb3, + 0x8c, 0xb8, 0x25, 0x98, 0x7f, + 0x01, 0xf2, 0x2b, 0xb8, 0xab, + 0x13, 0xe9, 0xc6, 0x62, 0x26, + 0xee, 0x23, 0x17, 0x8f, 0xfa, + 0x00, 0xa4, 0xfc, 0x22, 0x05, + 0x93, 0xb6, 0xe5, 0xac, 0x38, + 0x96, 0x00, 0x71, 0xc9, 0xc8, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0x77, 0xf3, 0xea, 0xcd, + 0x11, 0x85, 0x2c, 0x4b, 0xf9, + 0xcb, 0x1d, 0x72, 0xfa, 0xbe, + 0x6b, 0x26, 0xfb, 0xa1, 0xd7, + 0x60, 0x92, 0xb2, 0xb5, 0xb7, + 0xec, 0x83, 0xb8, 0x35, 0x57, + 0x65, 0x22, 0x64, 0xe6, 0x96, + 0x90, 0xdb, 0xc1, 0x17, 0x2d, + 0xdc, 0x0b, 0xf8, 0x84, 0x11, + 0xc0, 0xd2, 0x5a, 0x50, 0x7f, + 0xdb, 0x24, 0x7a, 0x20, 0xc4, + 0x0d, 0x5e, 0x24, 0x5f, 0xab, + 0xd3, 0xfc, 0x9e, 0xc1, 0x06 + }, test106[] = { /* signed-03 */ + 0xd8, 0x62, 0x84, 0x43, 0xa1, + 0x03, 0x00, 0xa1, 0x07, 0x83, + 0x43, 0xa1, 0x01, 0x27, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xb7, 0xca, 0xcb, 0xa2, + 0x85, 0xc4, 0xcd, 0x3e, 0xd2, + 0xf0, 0x14, 0x6f, 0x41, 0x98, + 0x86, 0x14, 0x4c, 0xa6, 0x38, + 0xd0, 0x87, 0xde, 0x12, 0x3d, + 0x40, 0x01, 0x67, 0x30, 0x8a, + 0xce, 0xab, 0xc4, 0xb5, 0xe5, + 0xc6, 0xa4, 0x0c, 0x0d, 0xe0, + 0xb7, 0x11, 0x67, 0xa3, 0x91, + 0x75, 0xea, 0x56, 0xc1, 0xfe, + 0x96, 0xc8, 0x9e, 0x5e, 0x7d, + 0x30, 0xda, 0xf2, 0x43, 0x8a, + 0x45, 0x61, 0x59, 0xa2, 0x0a, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x81, 0x83, 0x43, 0xa1, + 0x01, 0x27, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x77, + 0xf3, 0xea, 0xcd, 0x11, 0x85, + 0x2c, 0x4b, 0xf9, 0xcb, 0x1d, + 0x72, 0xfa, 0xbe, 0x6b, 0x26, + 0xfb, 0xa1, 0xd7, 0x60, 0x92, + 0xb2, 0xb5, 0xb7, 0xec, 0x83, + 0xb8, 0x35, 0x57, 0x65, 0x22, + 0x64, 0xe6, 0x96, 0x90, 0xdb, + 0xc1, 0x17, 0x2d, 0xdc, 0x0b, + 0xf8, 0x84, 0x11, 0xc0, 0xd2, + 0x5a, 0x50, 0x7f, 0xdb, 0x24, + 0x7a, 0x20, 0xc4, 0x0d, 0x5e, + 0x24, 0x5f, 0xab, 0xd3, 0xfc, + 0x9e, 0xc1, 0x06 + }, test107[] = { /* signed1-01 */ + 0xd2, 0x84, 0x45, 0xa2, 0x01, + 0x27, 0x03, 0x00, 0xa2, 0x07, + 0x83, 0x43, 0xa1, 0x01, 0x27, + 0xa1, 0x04, 0x42, 0x31, 0x31, + 0x58, 0x40, 0x6d, 0xae, 0xd1, + 0x58, 0xaf, 0xe4, 0x03, 0x2e, + 0x8d, 0xd4, 0x77, 0xd3, 0xd2, + 0xb7, 0xf6, 0x67, 0xe7, 0x95, + 0x7a, 0xa8, 0x30, 0x2b, 0xb5, + 0xe5, 0x68, 0xb4, 0xdc, 0xbc, + 0xce, 0x3c, 0xf0, 0xed, 0x5a, + 0x90, 0xf8, 0x31, 0x35, 0x1c, + 0x85, 0xd6, 0x15, 0x5a, 0x42, + 0xa1, 0x7c, 0xa1, 0xf2, 0x5f, + 0x50, 0x1c, 0xc1, 0x3f, 0x67, + 0x10, 0x8a, 0xe5, 0x3b, 0xda, + 0x92, 0xdb, 0x88, 0x27, 0x2e, + 0x00, 0x04, 0x42, 0x31, 0x31, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x58, 0x40, 0x71, 0x42, + 0xfd, 0x2f, 0xf9, 0x6d, 0x56, + 0xdb, 0x85, 0xbe, 0xe9, 0x05, + 0xa7, 0x6b, 0xa1, 0xd0, 0xb7, + 0x32, 0x1a, 0x95, 0xc8, 0xc4, + 0xd3, 0x60, 0x7c, 0x57, 0x81, + 0x93, 0x2b, 0x7a, 0xfb, 0x87, + 0x11, 0x49, 0x7d, 0xfa, 0x75, + 0x1b, 0xf4, 0x0b, 0x58, 0xb3, + 0xbc, 0xc3, 0x23, 0x00, 0xb1, + 0x48, 0x7f, 0x3d, 0xb3, 0x40, + 0x85, 0xee, 0xf0, 0x13, 0xbf, + 0x08, 0xf4, 0xa4, 0x4d, 0x6f, + 0xef, 0x0d + }, test108[] = { /* signed1-02 */ + 0xd2, 0x84, 0x45, 0xa2, 0x01, + 0x27, 0x03, 0x00, 0xa2, 0x07, + 0x82, 0x83, 0x43, 0xa1, 0x01, + 0x27, 0xa1, 0x04, 0x42, 0x31, + 0x31, 0x58, 0x40, 0x6d, 0xae, + 0xd1, 0x58, 0xaf, 0xe4, 0x03, + 0x2e, 0x8d, 0xd4, 0x77, 0xd3, + 0xd2, 0xb7, 0xf6, 0x67, 0xe7, + 0x95, 0x7a, 0xa8, 0x30, 0x2b, + 0xb5, 0xe5, 0x68, 0xb4, 0xdc, + 0xbc, 0xce, 0x3c, 0xf0, 0xed, + 0x5a, 0x90, 0xf8, 0x31, 0x35, + 0x1c, 0x85, 0xd6, 0x15, 0x5a, + 0x42, 0xa1, 0x7c, 0xa1, 0xf2, + 0x5f, 0x50, 0x1c, 0xc1, 0x3f, + 0x67, 0x10, 0x8a, 0xe5, 0x3b, + 0xda, 0x92, 0xdb, 0x88, 0x27, + 0x2e, 0x00, 0x83, 0x43, 0xa1, + 0x01, 0x26, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x93, + 0x48, 0x7d, 0x09, 0x25, 0x6a, + 0x3e, 0xf4, 0x96, 0x37, 0x19, + 0xba, 0x5c, 0xf1, 0x01, 0xac, + 0xe2, 0xfc, 0x13, 0xd6, 0x31, + 0x4b, 0x49, 0x58, 0x21, 0x71, + 0xff, 0xa4, 0xa1, 0x31, 0x4d, + 0xc9, 0x3e, 0x4a, 0x4a, 0xdf, + 0xa4, 0x2a, 0x79, 0xe3, 0x1b, + 0x35, 0xd7, 0x30, 0x43, 0x58, + 0x58, 0x5b, 0x41, 0x79, 0x96, + 0x78, 0xce, 0x00, 0xca, 0x47, + 0xc3, 0xe0, 0x23, 0x86, 0x39, + 0x23, 0xf8, 0xc8, 0x04, 0x42, + 0x31, 0x31, 0x54, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2e, 0x58, 0x40, + 0x71, 0x42, 0xfd, 0x2f, 0xf9, + 0x6d, 0x56, 0xdb, 0x85, 0xbe, + 0xe9, 0x05, 0xa7, 0x6b, 0xa1, + 0xd0, 0xb7, 0x32, 0x1a, 0x95, + 0xc8, 0xc4, 0xd3, 0x60, 0x7c, + 0x57, 0x81, 0x93, 0x2b, 0x7a, + 0xfb, 0x87, 0x11, 0x49, 0x7d, + 0xfa, 0x75, 0x1b, 0xf4, 0x0b, + 0x58, 0xb3, 0xbc, 0xc3, 0x23, + 0x00, 0xb1, 0x48, 0x7f, 0x3d, + 0xb3, 0x40, 0x85, 0xee, 0xf0, + 0x13, 0xbf, 0x08, 0xf4, 0xa4, + 0x4d, 0x6f, 0xef, 0x0d + }; +; + +struct seq { + char reason; + struct lecp_item item; + const uint8_t *buf; + size_t buf_len; +}; + +static const uint8_t bm12[] = { + 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00 +}, bm48[] = { + 0x32, 0x30, 0x31, 0x33, + 0x2D, 0x30, 0x33, 0x2D, + 0x32, 0x31, 0x54, 0x32, + 0x30, 0x3A, 0x30, 0x34, + 0x3A, 0x30, 0x30, 0x5A +}, bm51[] = { + 0x01, 0x02, 0x03, 0x04 +}, bm52[] = { + 0x64, 0x49, 0x45, 0x54, + 0x46 +}, bm53[] = { + 0x68, 0x74, 0x74, 0x70, + 0x3A, 0x2F, 0x2F, 0x77, + 0x77, 0x77, 0x2E, 0x65, + 0x78, 0x61, 0x6D, 0x70, + 0x6C, 0x65, 0x2E, 0x63, + 0x6F, 0x6D +}, bm57[] = { + 0x61 +}, bm58[] = { + 0x49, 0x45, 0x54, 0x46 +}, bm59[] = { + 0x22, 0x5C +}, bm60[] = { + 0xc3, 0xbc +}, bm61[] = { + 0xe6, 0xb0, 0xb4 +}, bm62[] = { + 0xF0, 0x90, 0x85, 0x91 +}, bm72a[] = { + 0x01, 0x02 +}, bm72b[] = { + 0x03, 0x04, 0x05 +}, bm83a[] = { + 0xa1, 0x01, 0x05 +}, bm83b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm83c[] = { + 0x2B, 0xDC, 0xC8, 0x9F, + 0x05, 0x82, 0x16, 0xB8, + 0xA2, 0x08, 0xDD, 0xC6, + 0xD8, 0xB5, 0x4A, 0xA9, + 0x1F, 0x48, 0xBD, 0x63, + 0x48, 0x49, 0x86, 0x56, + 0x51, 0x05, 0xC9, 0xAD, + 0x5A, 0x66, 0x82, 0xF6 +}, bm83d[] = { + 0x6F, 0x75, 0x72, 0x2D, + 0x73, 0x65, 0x63, 0x72, + 0x65, 0x74 +}, bm84a[] = { + 0xa1, 0x01, 0x06 +}, bm84b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm84c[] = { + 0xB3, 0x09, 0x7F, 0x70, + 0x00, 0x9A, 0x11, 0x50, + 0x74, 0x09, 0x59, 0x8A, + 0x83, 0xE1, 0x5B, 0xBB, + 0xBF, 0x19, 0x82, 0xDC, + 0xE2, 0x8E, 0x5A, 0xB6, + 0xD5, 0xA6, 0xAF, 0xF6, + 0x89, 0x7B, 0xD2, 0x4B, + 0xB8, 0xB7, 0x47, 0x96, + 0x22, 0xC9, 0x40, 0x1B, + 0x24, 0x09, 0x0D, 0x45, + 0x82, 0x06, 0xD5, 0x87 +}, bm84d[] = { + 0x73, 0x65, 0x63, 0x2D, + 0x34, 0x38 +}, bm85a[] = { + 0xa1, 0x01, 0x07 +}, bm85b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm85c[] = { + 0xCD, 0x28, 0xA6, 0xB3, + 0xCF, 0xBB, 0xBF, 0x21, + 0x48, 0x51, 0xB9, 0x06, + 0xE0, 0x50, 0x05, 0x6C, + 0xB4, 0x38, 0xA8, 0xB8, + 0x89, 0x05, 0xB8, 0xB7, + 0x46, 0x19, 0x77, 0x02, + 0x27, 0x11, 0xA9, 0xD8, + 0xAC, 0x5D, 0xBC, 0x54, + 0xE2, 0x9A, 0x56, 0xD9, + 0x26, 0x04, 0x6B, 0x40, + 0xFC, 0x26, 0x07, 0xC2, + 0x5B, 0x34, 0x44, 0x54, + 0xAA, 0x5F, 0x68, 0xDE, + 0x09, 0xA3, 0xE5, 0x25, + 0xD3, 0x86, 0x5A, 0x05 +}, bm85d[] = { + 0x73, 0x65, 0x63, 0x2D, + 0x36, 0x34 +}, bm86a[] = { + 0xa1, 0x01, 0x05 +}, bm86b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm86c[] = { + 0x2B, 0xDC, 0xC8, 0x9F, + 0x05, 0x82, 0x16, 0xB8, + 0xA2, 0x08, 0xDD, 0xC6, + 0xD8, 0xB5, 0x4A, 0xA9, + 0x1F, 0x48, 0xBD, 0x63, + 0x48, 0x49, 0x86, 0x56, + 0x51, 0x05, 0xC9, 0xAD, + 0x5A, 0x66, 0x82, 0xF7 +}, bm86d[] = { + 0x6F, 0x75, 0x72, 0x2D, + 0x73, 0x65, 0x63, 0x72, + 0x65, 0x74 +}, bm87a[] = { + 0xa1, 0x01, 0x04 +}, bm87b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm87c[] = { + 0x6F, 0x35, 0xCA, 0xB7, + 0x79, 0xF7, 0x78, 0x33 +}, bm87d[] = { + 0x6F, 0x75, 0x72, 0x2D, + 0x73, 0x65, 0x63, 0x72, + 0x65, 0x74 +}, bm88a[] = { + 0xa1, 0x01, 0x05 +}, bm88b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm88c[] = { + 0xA1, 0xA8, 0x48, 0xD3, + 0x47, 0x1F, 0x9D, 0x61, + 0xEE, 0x49, 0x01, 0x8D, + 0x24, 0x4C, 0x82, 0x47, + 0x72, 0xF2, 0x23, 0xAD, + 0x4F, 0x93, 0x52, 0x93, + 0xF1, 0x78, 0x9F, 0xC3, + 0xA0, 0x8D, 0x8C, 0x58 +}, bm89a[] = { + 0xa1, 0x01, 0x06 +}, bm89b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm89c[] = { + 0x99, 0x8D, 0x26, 0xC6, + 0x45, 0x9A, 0xAE, 0xEC, + 0xF4, 0x4E, 0xD2, 0x0C, + 0xE0, 0x0C, 0x8C, 0xCE, + 0xDF, 0x0A, 0x1F, 0x3D, + 0x22, 0xA9, 0x2F, 0xC0, + 0x5D, 0xB0, 0x8C, 0x5A, + 0xEB, 0x1C, 0xB5, 0x94, + 0xCA, 0xAF, 0x5A, 0x5C, + 0x5E, 0x2E, 0x9D, 0x01, + 0xCC, 0xE7, 0xE7, 0x7A, + 0x93, 0xAA, 0x8C, 0x62 +}, bm90a[] = { + 0xa1, 0x01, 0x07 +}, bm90b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm90c[] = { + 0x4A, 0x55, 0x5B, 0xF9, + 0x71, 0xF7, 0xC1, 0x89, + 0x1D, 0x9D, 0xDF, 0x30, + 0x4A, 0x1A, 0x13, 0x2E, + 0x2D, 0x6F, 0x81, 0x74, + 0x49, 0x47, 0x4D, 0x81, + 0x3E, 0x6D, 0x04, 0xD6, + 0x59, 0x62, 0xBE, 0xD8, + 0xBB, 0xA7, 0x0C, 0x17, + 0xE1, 0xF5, 0x30, 0x8F, + 0xA3, 0x99, 0x62, 0x95, + 0x9A, 0x4B, 0x9B, 0x8D, + 0x7D, 0xA8, 0xE6, 0xD8, + 0x49, 0xB2, 0x09, 0xDC, + 0xD3, 0xE9, 0x8C, 0xC0, + 0xF1, 0x1E, 0xDD, 0xF2 +}, bm91a[] = { + 0xa1, 0x01, 0x05 +}, bm91b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm91c[] = { + 0xA1, 0xA8, 0x48, 0xD3, + 0x47, 0x1F, 0x9D, 0x61, + 0xEE, 0x49, 0x01, 0x8D, + 0x24, 0x4C, 0x82, 0x47, + 0x72, 0xF2, 0x23, 0xAD, + 0x4F, 0x93, 0x52, 0x93, + 0xF1, 0x78, 0x9F, 0xC3, + 0xA0, 0x8D, 0x8C, 0x59 +}, bm92a[] = { + 0xa1, 0x01, 0x04 +}, bm92b[] = { + 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6F, 0x6E, 0x74, + 0x65, 0x6E, 0x74, 0x2E +}, bm92c[] = { + 0x11, 0xF9, 0xE3, 0x57, + 0x97, 0x5F, 0xB8, 0x49 +}, bm93a[] = { + 0xa1, 0x01, 0x01 +}, bm93b[] = { + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce +}, bm93c[] = { + 0xa1, 0x01, 0x27 +}, bm93d[] = { + 0x31, 0x31 +}, bm93e[] = { + 0xe1, 0x04, 0x39, 0x15, 0x4c, + 0xc7, 0x5c, 0x7a, 0x3a, 0x53, + 0x91, 0x49, 0x1f, 0x88, 0x65, + 0x1e, 0x02, 0x92, 0xfd, 0x0f, + 0xe0, 0xe0, 0x2c, 0xf7, 0x40, + 0x54, 0x7e, 0xaf, 0x66, 0x77, + 0xb4, 0xa4, 0x04, 0x0b, 0x8e, + 0xca, 0x16, 0xdb, 0x59, 0x28, + 0x81, 0x26, 0x2f, 0x77, 0xb1, + 0x4c, 0x1a, 0x08, 0x6c, 0x02, + 0x26, 0x8b, 0x17, 0x17, 0x1c, + 0xa1, 0x6b, 0xe4, 0xb8, 0x59, + 0x5f, 0x8c, 0x0a, 0x08 +}, bm93f[] = { + 0x60, 0x97, 0x3a, 0x94, 0xbb, + 0x28, 0x98, 0x00, 0x9e, 0xe5, + 0x2e, 0xcf, 0xd9, 0xab, 0x1d, + 0xd2, 0x58, 0x67, 0x37, 0x4b, + 0x16, 0x2e, 0x2c, 0x03, 0x56, + 0x8b, 0x41, 0xf5, 0x7c, 0x3c, + 0xc1, 0x6f, 0x91, 0x66, 0x25, + 0x0a + +}, bm94a[] = { + 0xa1, 0x01, 0x01 +}, bm94b[] = { + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce +}, bm94c[] = { + 0xa1, 0x01, 0x27 +}, bm94d[] = { + 0x31, 0x31 +}, bm94e[] = { + 0xe1, 0x04, 0x39, 0x15, 0x4c, + 0xc7, 0x5c, 0x7a, 0x3a, 0x53, + 0x91, 0x49, 0x1f, 0x88, 0x65, + 0x1e, 0x02, 0x92, 0xfd, 0x0f, + 0xe0, 0xe0, 0x2c, 0xf7, 0x40, + 0x54, 0x7e, 0xaf, 0x66, 0x77, + 0xb4, 0xa4, 0x04, 0x0b, 0x8e, + 0xca, 0x16, 0xdb, 0x59, 0x28, + 0x81, 0x26, 0x2f, 0x77, 0xb1, + 0x4c, 0x1a, 0x08, 0x6c, 0x02, + 0x26, 0x8b, 0x17, 0x17, 0x1c, + 0xa1, 0x6b, 0xe4, 0xb8, 0x59, + 0x5f, 0x8c, 0x0a, 0x08 +}, bm94f[] = { + 0xa1, 0x01, 0x26 +}, bm94g[] = { + 0x31, 0x31 +}, bm94h[] = { + 0xfc, 0xa9, 0x8e, 0xca, 0xc8, + 0x0b, 0x5f, 0xeb, 0x3a, 0xc7, + 0xc1, 0x08, 0xb2, 0xb7, 0x91, + 0x10, 0xde, 0x88, 0x86, 0x7b, + 0xc0, 0x42, 0x6f, 0xc8, 0x3c, + 0x53, 0xcc, 0xd6, 0x78, 0x96, + 0x94, 0xed, 0xc5, 0xfe, 0xe3, + 0xc4, 0x0d, 0xe8, 0xe7, 0xb4, + 0x4f, 0xe8, 0xaa, 0xd3, 0x67, + 0xe0, 0x95, 0xc8, 0xfc, 0x31, + 0xb7, 0x9e, 0xe6, 0x66, 0xdf, + 0x9c, 0xf9, 0x09, 0x06, 0xeb, + 0x43, 0x75, 0x6c, 0x73 +}, bm94i[] = { + 0x60, 0x97, 0x3a, 0x94, 0xbb, + 0x28, 0x98, 0x00, 0x9e, 0xe5, + 0x2e, 0xcf, 0xd9, 0xab, 0x1d, + 0xd2, 0x58, 0x67, 0x37, 0x4b, + 0x16, 0x2e, 0x2c, 0x03, 0x56, + 0x8b, 0x41, 0xf5, 0x7c, 0x3c, + 0xc1, 0x6f, 0x91, 0x66, 0x25, + 0x0a + +}, bm95a[] = { + 0xa1, 0x01, 0x01 +}, bm95b[] = { + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce +}, bm95c[] = { + 0xa1, 0x01, 0x27 +}, bm95d[] = { + 0x31, 0x31 +}, bm95e[] = { + 0x9a, 0x8e, 0xed, 0xe3, 0xb3, + 0xcb, 0x83, 0x7b, 0xa0, 0x0d, + 0xf0, 0x8f, 0xa2, 0x1b, 0x12, + 0x8b, 0x2d, 0x6d, 0x91, 0x62, + 0xa4, 0x29, 0x0a, 0x58, 0x2d, + 0x9f, 0x19, 0xbd, 0x0f, 0xb5, + 0x02, 0xf0, 0xf9, 0x2b, 0x9b, + 0xf4, 0x53, 0xa4, 0x05, 0x40, + 0x1f, 0x8b, 0x70, 0x55, 0xef, + 0x4e, 0x95, 0x8d, 0xf7, 0xf4, + 0xfb, 0xd7, 0xcf, 0xb4, 0xa0, + 0xc9, 0x71, 0x60, 0xf9, 0x47, + 0x2b, 0x0a, 0xa1, 0x04 +}, bm95f[] = { + 0x60, 0x97, 0x3a, 0x94, 0xbb, + 0x28, 0x98, 0x00, 0x9e, 0xe5, + 0x2e, 0xcf, 0xd9, 0xab, 0x1d, + 0xd2, 0x58, 0x67, 0x37, 0x4b, + 0x35, 0x81, 0xf2, 0xc8, 0x00, + 0x39, 0x82, 0x63, 0x50, 0xb9, + 0x7a, 0xe2, 0x30, 0x0E, 0x42, + 0xFC +}, bm95g[] = { + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74 + +}, bm96a[] = { + 0xa1, 0x01, 0x01 +}, bm96b[] = { + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce +}, bm96c[] = { + 0xa1, 0x01, 0x27 +}, bm96d[] = { + 0x31, 0x31 +}, bm96e[] = { + 0x9a, 0x8e, 0xed, 0xe3, 0xb3, + 0xcb, 0x83, 0x7b, 0xa0, 0x0d, + 0xf0, 0x8f, 0xa2, 0x1b, 0x12, + 0x8b, 0x2d, 0x6d, 0x91, 0x62, + 0xa4, 0x29, 0x0a, 0x58, 0x2d, + 0x9f, 0x19, 0xbd, 0x0f, 0xb5, + 0x02, 0xf0, 0xf9, 0x2b, 0x9b, + 0xf4, 0x53, 0xa4, 0x05, 0x40, + 0x1f, 0x8b, 0x70, 0x55, 0xef, + 0x4e, 0x95, 0x8d, 0xf7, 0xf4, + 0xfb, 0xd7, 0xcf, 0xb4, 0xa0, + 0xc9, 0x71, 0x60, 0xf9, 0x47, + 0x2b, 0x0a, 0xa1, 0x04 +}, bm96f[] = { + 0xa1, 0x01, 0x26 +}, bm96g[] = { + 0x31, 0x31 +}, bm96h[] = { + 0x24, 0x27, 0xcb, 0x37, 0x56, + 0x85, 0x0f, 0xbb, 0x79, 0x05, + 0x18, 0x07, 0xc8, 0xb2, 0x3d, + 0x2e, 0x6d, 0x16, 0xa3, 0x22, + 0x4f, 0x99, 0x01, 0xb4, 0x73, + 0x99, 0xcf, 0xc7, 0xe3, 0xfa, + 0xc4, 0xcc, 0x62, 0x1d, 0xbb, + 0xeb, 0x02, 0x02, 0xa6, 0xd8, + 0xbb, 0x25, 0x69, 0x5c, 0x9d, + 0xcc, 0x9c, 0x47, 0x49, 0x20, + 0xff, 0x57, 0x60, 0x6d, 0x76, + 0x4d, 0xea, 0x19, 0x2f, 0xc8, + 0x67, 0x41, 0x16, 0xf2 +}, bm96i[] = { + 0x60, 0x97, 0x3a, 0x94, 0xbb, + 0x28, 0x98, 0x00, 0x9e, 0xe5, + 0x2e, 0xcf, 0xd9, 0xab, 0x1d, + 0xd2, 0x58, 0x67, 0x37, 0x4b, + 0x35, 0x81, 0xf2, 0xc8, 0x00, + 0x39, 0x82, 0x63, 0x50, 0xb9, + 0x7a, 0xe2, 0x30, 0x0e, 0x42, + 0xfc +}, bm96j[] = { + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74 + +}, bm97a[] = { + 0xa1, 0x01, 0x01 +}, bm97b[] = { + 0x02, 0xd1, 0xf7, 0xe6, 0xf2, + 0x6c, 0x43, 0xd4, 0x86, 0x8d, + 0x87, 0xce +}, bm97c[] = { + 0x60, 0x97, 0x3a, 0x94, 0xbb, + 0x28, 0x98, 0x00, 0x9e, 0xe5, + 0x2e, 0xcf, 0xd9, 0xab, 0x1d, + 0xd2, 0x58, 0x67, 0x37, 0x4b, + 0x35, 0x81, 0xf2, 0xc8, 0x00, + 0x39, 0x82, 0x63, 0x50, 0xb9, + 0x7a, 0xe2, 0x30, 0x0e, 0x42, + 0xfc +}, bm97d[] = { + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74 +}, bm97e[] = { + 0xa1, 0x01, 0x27 +}, bm97f[] = { + 0x31, 0x31 +}, bm97g[] = { + 0xcc, 0xb1, 0xf3, 0xfe, 0xdf, + 0xce, 0xa7, 0x2b, 0x9c, 0x86, + 0x79, 0x63, 0xe2, 0x52, 0xb6, + 0x65, 0x8a, 0xd0, 0x7f, 0x3f, + 0x5f, 0x15, 0xa3, 0x26, 0xa3, + 0xf5, 0x72, 0x54, 0xcc, 0xb8, + 0xd4, 0x8d, 0x60, 0x02, 0x1d, + 0x2f, 0x1f, 0x8a, 0x80, 0x3b, + 0x84, 0x4b, 0x78, 0x72, 0x16, + 0x6c, 0x6d, 0x45, 0x90, 0x25, + 0xd2, 0x1c, 0x8c, 0x84, 0x62, + 0xa2, 0x44, 0xba, 0x19, 0x60, + 0x4e, 0xc4, 0xd5, 0x0b + +}, bm98a[] = { + 0xa1, 0x01, 0x05 +}, bm98b[] = { + 0xa1, 0x01, 0x27 +}, bm98c[] = { + 0x31, 0x31 +}, bm98d[] = { + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07 +}, bm98e[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm98f[] = { + 0x2b, 0xdc, 0xc8, 0x9f, 0x05, + 0x82, 0x16, 0xb8, 0xa2, 0x08, + 0xdd, 0xc6, 0xd8, 0xb5, 0x4a, + 0xa9, 0x1f, 0x48, 0xbd, 0x63, + 0x48, 0x49, 0x86, 0x56, 0x51, + 0x05, 0xc9, 0xad, 0x5a, 0x66, + 0x82, 0xf6 +}, bm98g[] = { + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74 + +}, bm99a[] = { + 0xa1, 0x01, 0x05 +}, bm99b[] = { + 0xa1, 0x01, 0x27 +}, bm99c[] = { + 0x31, 0x31 +}, bm99d[] = { + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07 +}, bm99e[] = { + 0xa1, 0x01, 0x26 +}, bm99f[] = { + 0x31, 0x31 +}, bm99g[] = { + 0x6a, 0xcd, 0x94, 0xd3, 0xcc, + 0xf7, 0x1d, 0x19, 0x2e, 0x85, + 0x28, 0x36, 0x0b, 0xa7, 0xe3, + 0x46, 0xda, 0xc4, 0x64, 0xe9, + 0xed, 0xca, 0x4c, 0xfe, 0xb6, + 0xce, 0xb6, 0xbd, 0xe7, 0xba, + 0xec, 0x9f, 0xf2, 0x6c, 0xa6, + 0xbd, 0xf7, 0x3d, 0x0b, 0xe4, + 0x1e, 0x36, 0x12, 0x9d, 0xcf, + 0xf7, 0x51, 0xdd, 0x2b, 0x5a, + 0xd5, 0xce, 0x11, 0x6e, 0x8a, + 0x96, 0x3a, 0x27, 0x38, 0xa2, + 0x99, 0x47, 0x7a, 0x68 +}, bm99h[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm99i[] = { + 0x2b, 0xdc, 0xc8, 0x9f, 0x05, + 0x82, 0x16, 0xb8, 0xa2, 0x08, + 0xdd, 0xc6, 0xd8, 0xb5, 0x4a, + 0xa9, 0x1f, 0x48, 0xbd, 0x63, + 0x48, 0x49, 0x86, 0x56, 0x51, + 0x05, 0xc9, 0xad, 0x5a, 0x66, + 0x82, 0xf6 +}, bm99j[] = { + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74 + +}, bm100a[] = { + 0xa1, 0x01, 0x05 +}, bm100b[] = { + 0xa1, 0x01, 0x27 +}, bm100c[] = { + 0x31, 0x31 +}, bm100d[] = { + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07 +}, bm100e[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm100f[] = { + 0xa1, 0xa8, 0x48, 0xd3, 0x47, + 0x1f, 0x9d, 0x61, 0xee, 0x49, + 0x01, 0x8d, 0x24, 0x4c, 0x82, + 0x47, 0x72, 0xf2, 0x23, 0xad, + 0x4f, 0x93, 0x52, 0x93, 0xf1, + 0x78, 0x9f, 0xc3, 0xa0, 0x8d, + 0x8c, 0x58 + + +}, bm101a[] = { + 0xa1, 0x01, 0x05 +}, bm101b[] = { + 0xa1, 0x01, 0x27 +}, bm101c[] = { + 0x31, 0x31 +}, bm101d[] = { + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07 +}, bm101e[] = { + 0xa1, 0x01, 0x26 +}, bm101f[] = { + 0x31, 0x31 +}, bm101g[] = { + 0x6a, 0xcd, 0x94, 0xd3, 0xcc, + 0xf7, 0x1d, 0x19, 0x2e, 0x85, + 0x28, 0x36, 0x0b, 0xa7, 0xe3, + 0x46, 0xda, 0xc4, 0x64, 0xe9, + 0xed, 0xca, 0x4c, 0xfe, 0xb6, + 0xce, 0xb6, 0xbd, 0xe7, 0xba, + 0xec, 0x9f, 0xf2, 0x6c, 0xa6, + 0xbd, 0xf7, 0x3d, 0x0b, 0xe4, + 0x1e, 0x36, 0x12, 0x9d, 0xcf, + 0xf7, 0x51, 0xdd, 0x2b, 0x5a, + 0xd5, 0xce, 0x11, 0x6e, 0x8a, + 0x96, 0x3a, 0x27, 0x38, 0xa2, + 0x99, 0x47, 0x7a, 0x68 +}, bm101h[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm101i[] = { + 0x2b, 0xdc, 0xc8, 0x9f, 0x05, + 0x82, 0x16, 0xb8, 0xa2, 0x08, + 0xdd, 0xc6, 0xd8, 0xb5, 0x4a, + 0xa9, 0x1f, 0x48, 0xbd, 0x63, + 0x48, 0x49, 0x86, 0x56, 0x51, + 0x05, 0xc9, 0xad, 0x5a, 0x66, + 0x82, 0xf6 +}, bm101j[] = { + 0x6f, 0x75, 0x72, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74 + +}, bm102a[] = { /* mac0-01 */ + 0xa1, 0x01, 0x05 +}, bm102b[] = { + 0xa1, 0x01, 0x27 +}, bm102c[] = { + 0x31, 0x31 +}, bm102d[] = { + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07 +}, bm102e[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm102f[] = { + 0xa1, 0xa8, 0x48, 0xd3, 0x47, + 0x1f, 0x9d, 0x61, 0xee, 0x49, + 0x01, 0x8d, 0x24, 0x4c, 0x82, + 0x47, 0x72, 0xf2, 0x23, 0xad, + 0x4f, 0x93, 0x52, 0x93, 0xf1, + 0x78, 0x9f, 0xc3, 0xa0, 0x8d, + 0x8c, 0x58 + +}, bm103a[] = { + 0xa1, 0x01, 0x05 +}, bm103b[] = { + 0xa1, 0x01, 0x27 +}, bm103c[] = { + 0x31, 0x31 +}, bm103d[] = { + 0xb4, 0x92, 0x4b, 0x18, 0xeb, + 0x4e, 0x04, 0x73, 0x13, 0xc7, + 0x07, 0xb0, 0xed, 0xa4, 0xab, + 0x84, 0x43, 0x45, 0xf2, 0xc4, + 0x49, 0x87, 0xd6, 0xf9, 0xeb, + 0xcc, 0x77, 0x7e, 0xfd, 0x40, + 0x78, 0xcc, 0x0f, 0x4c, 0x10, + 0x8d, 0xef, 0x95, 0x9f, 0x78, + 0xf1, 0xed, 0xb2, 0x76, 0x54, + 0x25, 0x78, 0x5f, 0xcd, 0x17, + 0xd5, 0x12, 0xbe, 0x31, 0xee, + 0xb6, 0x6b, 0xef, 0xf1, 0xe8, + 0xfc, 0x27, 0x47, 0x07 +}, bm103e[] = { + 0xa1, 0x01, 0x26 +}, bm103f[] = { + 0x31, 0x31 +}, bm103g[] = { + 0x6a, 0xcd, 0x94, 0xd3, 0xcc, + 0xf7, 0x1d, 0x19, 0x2e, 0x85, + 0x28, 0x36, 0x0b, 0xa7, 0xe3, + 0x46, 0xda, 0xc4, 0x64, 0xe9, + 0xed, 0xca, 0x4c, 0xfe, 0xb6, + 0xce, 0xb6, 0xbd, 0xe7, 0xba, + 0xec, 0x9f, 0xf2, 0x6c, 0xa6, + 0xbd, 0xf7, 0x3d, 0x0b, 0xe4, + 0x1e, 0x36, 0x12, 0x9d, 0xcf, + 0xf7, 0x51, 0xdd, 0x2b, 0x5a, + 0xd5, 0xce, 0x11, 0x6e, 0x8a, + 0x96, 0x3a, 0x27, 0x38, 0xa2, + 0x99, 0x47, 0x7a, 0x68 +}, bm103h[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm103i[] = { + 0xa1, 0xa8, 0x48, 0xd3, 0x47, + 0x1f, 0x9d, 0x61, 0xee, 0x49, + 0x01, 0x8d, 0x24, 0x4c, 0x82, + 0x47, 0x72, 0xf2, 0x23, 0xad, + 0x4f, 0x93, 0x52, 0x93, 0xf1, + 0x78, 0x9f, 0xc3, 0xa0, 0x8d, + 0x8c, 0x58 + +}, bm104a[] = { + 0xa1, 0x03, 0x00 +}, bm104b[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm104c[] = { + 0xa1, 0x01, 0x27 +}, bm104d[] = { + 0xa1, 0x01, 0x27 +}, bm104e[] = { + 0x31, 0x31 +}, bm104f[] = { + 0x8e, 0x1b, 0xe2, 0xf9, 0x45, + 0x3d, 0x26, 0x48, 0x12, 0xe5, + 0x90, 0x49, 0x91, 0x32, 0xbe, + 0xf3, 0xfb, 0xf9, 0xee, 0x9d, + 0xb2, 0x7c, 0x2c, 0x16, 0x87, + 0x88, 0xe3, 0xb7, 0xeb, 0xe5, + 0x06, 0xc0, 0x4f, 0xd3, 0xd1, + 0x9f, 0xaa, 0x9f, 0x51, 0x23, + 0x2a, 0xf5, 0xc9, 0x59, 0xe4, + 0xef, 0x47, 0x92, 0x88, 0x34, + 0x64, 0x7f, 0x56, 0xdf, 0xbe, + 0x93, 0x91, 0x12, 0x88, 0x4d, + 0x08, 0xef, 0x25, 0x05 +}, bm104g[] = { + 0x31, 0x31 +}, bm104h[] = { + 0x77, 0xf3, 0xea, 0xcd, 0x11, + 0x85, 0x2c, 0x4b, 0xf9, 0xcb, + 0x1d, 0x72, 0xfa, 0xbe, 0x6b, + 0x26, 0xfb, 0xa1, 0xd7, 0x60, + 0x92, 0xb2, 0xb5, 0xb7, 0xec, + 0x83, 0xb8, 0x35, 0x57, 0x65, + 0x22, 0x64, 0xe6, 0x96, 0x90, + 0xdb, 0xc1, 0x17, 0x2d, 0xdc, + 0x0b, 0xf8, 0x84, 0x11, 0xc0, + 0xd2, 0x5a, 0x50, 0x7f, 0xdb, + 0x24, 0x7a, 0x20, 0xc4, 0x0d, + 0x5e, 0x24, 0x5f, 0xab, 0xd3, + 0xfc, 0x9e, 0xc1, 0x06 + +}, bm105a[] = { + 0xa1, 0x03, 0x00 +}, bm105b[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm105c[] = { + 0xa1, 0x01, 0x27 +}, bm105d[] = { + 0xa1, 0x01, 0x27 +}, bm105e[] = { + 0x31, 0x31 +}, bm105f[] = { + 0x8e, 0x1b, 0xe2, 0xf9, 0x45, + 0x3d, 0x26, 0x48, 0x12, 0xe5, + 0x90, 0x49, 0x91, 0x32, 0xbe, + 0xf3, 0xfb, 0xf9, 0xee, 0x9d, + 0xb2, 0x7c, 0x2c, 0x16, 0x87, + 0x88, 0xe3, 0xb7, 0xeb, 0xe5, + 0x06, 0xc0, 0x4f, 0xd3, 0xd1, + 0x9f, 0xaa, 0x9f, 0x51, 0x23, + 0x2a, 0xf5, 0xc9, 0x59, 0xe4, + 0xef, 0x47, 0x92, 0x88, 0x34, + 0x64, 0x7f, 0x56, 0xdf, 0xbe, + 0x93, 0x91, 0x12, 0x88, 0x4d, + 0x08, 0xef, 0x25, 0x05 +}, bm105g[] = { + 0xa1, 0x01, 0x26 +}, bm105h[] = { + 0x31, 0x31 +}, bm105i[] = { + 0xaf, 0x04, 0x9b, 0x80, 0xd5, + 0x2c, 0x36, 0x69, 0xb2, 0x99, + 0x70, 0xc1, 0x33, 0x54, 0x37, + 0x54, 0xf9, 0xcc, 0x60, 0x8c, + 0xe4, 0x11, 0x23, 0xae, 0x1c, + 0x82, 0x7e, 0x36, 0xb3, 0x8c, + 0xb8, 0x25, 0x98, 0x7f, 0x01, + 0xf2, 0x2b, 0xb8, 0xab, 0x13, + 0xe9, 0xc6, 0x62, 0x26, 0xee, + 0x23, 0x17, 0x8f, 0xfa, 0x00, + 0xa4, 0xfc, 0x22, 0x05, 0x93, + 0xb6, 0xe5, 0xac, 0x38, 0x96, + 0x00, 0x71, 0xc9, 0xc8 +}, bm105j[] = { + 0x31, 0x31 +}, bm105k[] = { + 0x77, 0xf3, 0xea, 0xcd, 0x11, + 0x85, 0x2c, 0x4b, 0xf9, 0xcb, + 0x1d, 0x72, 0xfa, 0xbe, 0x6b, + 0x26, 0xfb, 0xa1, 0xd7, 0x60, + 0x92, 0xb2, 0xb5, 0xb7, 0xec, + 0x83, 0xb8, 0x35, 0x57, 0x65, + 0x22, 0x64, 0xe6, 0x96, 0x90, + 0xdb, 0xc1, 0x17, 0x2d, 0xdc, + 0x0b, 0xf8, 0x84, 0x11, 0xc0, + 0xd2, 0x5a, 0x50, 0x7f, 0xdb, + 0x24, 0x7a, 0x20, 0xc4, 0x0d, + 0x5e, 0x24, 0x5f, 0xab, 0xd3, + 0xfc, 0x9e, 0xc1, 0x06 + +}, bm106a[] = { + 0xa1, 0x03, 0x00 +}, bm106b[] = { + 0xa1, 0x01, 0x27 +}, bm106c[] = { + 0x31, 0x31 +}, bm106d[] = { + 0xb7, 0xca, 0xcb, 0xa2, 0x85, + 0xc4, 0xcd, 0x3e, 0xd2, 0xf0, + 0x14, 0x6f, 0x41, 0x98, 0x86, + 0x14, 0x4c, 0xa6, 0x38, 0xd0, + 0x87, 0xde, 0x12, 0x3d, 0x40, + 0x01, 0x67, 0x30, 0x8a, 0xce, + 0xab, 0xc4, 0xb5, 0xe5, 0xc6, + 0xa4, 0x0c, 0x0d, 0xe0, 0xb7, + 0x11, 0x67, 0xa3, 0x91, 0x75, + 0xea, 0x56, 0xc1, 0xfe, 0x96, + 0xc8, 0x9e, 0x5e, 0x7d, 0x30, + 0xda, 0xf2, 0x43, 0x8a, 0x45, + 0x61, 0x59, 0xa2, 0x0a +}, bm106e[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm106f[] = { + 0xa1, 0x01, 0x27 +}, bm106g[] = { + 0x31, 0x31 +}, bm106h[] = { + 0x77, 0xf3, 0xea, 0xcd, 0x11, + 0x85, 0x2c, 0x4b, 0xf9, 0xcb, + 0x1d, 0x72, 0xfa, 0xbe, 0x6b, + 0x26, 0xfb, 0xa1, 0xd7, 0x60, + 0x92, 0xb2, 0xb5, 0xb7, 0xec, + 0x83, 0xb8, 0x35, 0x57, 0x65, + 0x22, 0x64, 0xe6, 0x96, 0x90, + 0xdb, 0xc1, 0x17, 0x2d, 0xdc, + 0x0b, 0xf8, 0x84, 0x11, 0xc0, + 0xd2, 0x5a, 0x50, 0x7f, 0xdb, + 0x24, 0x7a, 0x20, 0xc4, 0x0d, + 0x5e, 0x24, 0x5f, 0xab, 0xd3, + 0xfc, 0x9e, 0xc1, 0x06 + +}, bm107a[] = { + 0xa2, 0x01, 0x27, 0x03, 0x00 +}, bm107b[] = { + 0xa1, 0x01, 0x27, +}, bm107c[] = { + 0x31, 0x31 +}, bm107d[] = { + 0x6d, 0xae, 0xd1, 0x58, 0xaf, + 0xe4, 0x03, 0x2e, 0x8d, 0xd4, + 0x77, 0xd3, 0xd2, 0xb7, 0xf6, + 0x67, 0xe7, 0x95, 0x7a, 0xa8, + 0x30, 0x2b, 0xb5, 0xe5, 0x68, + 0xb4, 0xdc, 0xbc, 0xce, 0x3c, + 0xf0, 0xed, 0x5a, 0x90, 0xf8, + 0x31, 0x35, 0x1c, 0x85, 0xd6, + 0x15, 0x5a, 0x42, 0xa1, 0x7c, + 0xa1, 0xf2, 0x5f, 0x50, 0x1c, + 0xc1, 0x3f, 0x67, 0x10, 0x8a, + 0xe5, 0x3b, 0xda, 0x92, 0xdb, + 0x88, 0x27, 0x2e, 0x00 +}, bm107e[] = { + 0x31, 0x31 +}, bm107f[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm107g[] = { + 0x71, 0x42, 0xfd, 0x2f, 0xf9, + 0x6d, 0x56, 0xdb, 0x85, 0xbe, + 0xe9, 0x05, 0xa7, 0x6b, 0xa1, + 0xd0, 0xb7, 0x32, 0x1a, 0x95, + 0xc8, 0xc4, 0xd3, 0x60, 0x7c, + 0x57, 0x81, 0x93, 0x2b, 0x7a, + 0xfb, 0x87, 0x11, 0x49, 0x7d, + 0xfa, 0x75, 0x1b, 0xf4, 0x0b, + 0x58, 0xb3, 0xbc, 0xc3, 0x23, + 0x00, 0xb1, 0x48, 0x7f, 0x3d, + 0xb3, 0x40, 0x85, 0xee, 0xf0, + 0x13, 0xbf, 0x08, 0xf4, 0xa4, + 0x4d, 0x6f, 0xef, 0x0d + +}, bm108a[] = { + 0xa2, 0x01, 0x27, 0x03, 0x00 +}, bm108b[] = { + 0xa1, 0x01, 0x27 +}, bm108c[] = { + 0x31, 0x31 +}, bm108d[] = { + 0x6d, 0xae, 0xd1, 0x58, 0xaf, + 0xe4, 0x03, 0x2e, 0x8d, 0xd4, + 0x77, 0xd3, 0xd2, 0xb7, 0xf6, + 0x67, 0xe7, 0x95, 0x7a, 0xa8, + 0x30, 0x2b, 0xb5, 0xe5, 0x68, + 0xb4, 0xdc, 0xbc, 0xce, 0x3c, + 0xf0, 0xed, 0x5a, 0x90, 0xf8, + 0x31, 0x35, 0x1c, 0x85, 0xd6, + 0x15, 0x5a, 0x42, 0xa1, 0x7c, + 0xa1, 0xf2, 0x5f, 0x50, 0x1c, + 0xc1, 0x3f, 0x67, 0x10, 0x8a, + 0xe5, 0x3b, 0xda, 0x92, 0xdb, + 0x88, 0x27, 0x2e, 0x00 +}, bm108e[] = { + 0xa1, 0x01, 0x26 +}, bm108f[] = { + 0x31, 0x31 +}, bm108g[] = { + 0x93, 0x48, 0x7d, 0x09, 0x25, + 0x6a, 0x3e, 0xf4, 0x96, 0x37, + 0x19, 0xba, 0x5c, 0xf1, 0x01, + 0xac, 0xe2, 0xfc, 0x13, 0xd6, + 0x31, 0x4b, 0x49, 0x58, 0x21, + 0x71, 0xff, 0xa4, 0xa1, 0x31, + 0x4d, 0xc9, 0x3e, 0x4a, 0x4a, + 0xdf, 0xa4, 0x2a, 0x79, 0xe3, + 0x1b, 0x35, 0xd7, 0x30, 0x43, + 0x58, 0x58, 0x5b, 0x41, 0x79, + 0x96, 0x78, 0xce, 0x00, 0xca, + 0x47, 0xc3, 0xe0, 0x23, 0x86, + 0x39, 0x23, 0xf8, 0xc8 +}, bm108h[] = { + 0x31, 0x31 +}, bm108i[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2e +}, bm108j[] = { + 0x71, 0x42, 0xfd, 0x2f, 0xf9, + 0x6d, 0x56, 0xdb, 0x85, 0xbe, + 0xe9, 0x05, 0xa7, 0x6b, 0xa1, + 0xd0, 0xb7, 0x32, 0x1a, 0x95, + 0xc8, 0xc4, 0xd3, 0x60, 0x7c, + 0x57, 0x81, 0x93, 0x2b, 0x7a, + 0xfb, 0x87, 0x11, 0x49, 0x7d, + 0xfa, 0x75, 0x1b, 0xf4, 0x0b, + 0x58, 0xb3, 0xbc, 0xc3, 0x23, + 0x00, 0xb1, 0x48, 0x7f, 0x3d, + 0xb3, 0x40, 0x85, 0xee, 0xf0, + 0x13, 0xbf, 0x08, 0xf4, 0xa4, + 0x4d, 0x6f, 0xef, 0x0d +}; + +static const struct seq +seq1[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 0 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq2[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq3[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 10 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq4[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 23 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq5[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 24 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq6[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 25 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq7[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 100 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq8[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1000 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq9[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1000000 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq10[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1000000000000 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq11[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 18446744073709551615ull } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq12[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 0 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm12, .buf_len = sizeof(bm12)}, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq13[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = 0ull } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq14[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm12, .buf_len = sizeof(bm12)}, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq15[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -1ll } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq16[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -10ll } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq17[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -100ll } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq18[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -1000ll } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq19[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq20[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x8000 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq21[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x3c00 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq22[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.d = 1.1 } }, +#else + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x3ff199999999999aull } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq23[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x3e00 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq24[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x7bff } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq25[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 100000.0 } }, +#else + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 0x47c35000 } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq26[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 3.4028234663852886e+38 } }, +#else + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 0x7f7fffff } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq27[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x7e37e43c8800759cull } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq28[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x0001 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq29[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x0400 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq30[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0xc400 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq31[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0xc010666666666666ull } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq32[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x7c00 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq33[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0x7e00 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq34[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FLOAT16, .item = { .u.hf = 0xfc00 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq35[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.u32 = 0x7f800000 } }, +#else + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 0x7f800000 } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq36[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = NAN } }, +#else + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 0x7fc00000 } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq37[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.u32 = 0xff800000 } }, +#else + { .reason = LECPCB_VAL_FLOAT32, .item = { .u.f = 0xff800000 } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq38[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x7ff0000000000000ull } }, +#else + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x7ff0000000000000ull } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq39[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x7ff8000000000000ull } }, +#else + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x7ff8000000000000ull } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq40[] = { + { .reason = LECPCB_CONSTRUCTED }, +#if defined(LWS_WITH_CBOR_FLOAT) + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0xfff0000000000000ull } }, +#else + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0xfff0000000000000ull } }, +#endif + { .reason = LECPCB_DESTRUCTED }, +}, seq41[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_FALSE }, + { .reason = LECPCB_DESTRUCTED }, +}, seq42[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_TRUE }, + { .reason = LECPCB_DESTRUCTED }, +}, seq43[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_NULL }, + { .reason = LECPCB_DESTRUCTED }, +}, seq44[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_UNDEFINED }, + { .reason = LECPCB_DESTRUCTED }, +}, seq45[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_SIMPLE, .item = { .u.u64 = 16 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq46[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_FAILED }, /* example disallowed by RFC! */ + { .reason = LECPCB_DESTRUCTED }, +}, seq47[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_SIMPLE, .item = { .u.u64 = 255 } }, + { .reason = LECPCB_DESTRUCTED }, +}, seq48[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 0 } }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm48, .buf_len = sizeof(bm48)}, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq49[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1363896240 } }, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq50[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_FLOAT64, .item = { .u.u64 = 0x41d452d9ec200000ull } }, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq51[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 23 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm51, .buf_len = sizeof(bm51)}, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq52[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 24 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm52, .buf_len = sizeof(bm52)}, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq53[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 32 } }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm53, .buf_len = sizeof(bm53)}, + { .reason = LECPCB_TAG_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq54[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm53, .buf_len = 0}, + { .reason = LECPCB_DESTRUCTED }, +}, seq55[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm51, .buf_len = sizeof(bm51)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq56[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm53, .buf_len = 0}, + { .reason = LECPCB_DESTRUCTED }, +}, seq57[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm57, .buf_len = sizeof(bm57)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq58[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm58, .buf_len = sizeof(bm58)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq59[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm59, .buf_len = sizeof(bm59)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq60[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm60, .buf_len = sizeof(bm60)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq61[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm61, .buf_len = sizeof(bm61)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq62[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = bm62, .buf_len = sizeof(bm62)}, + { .reason = LECPCB_DESTRUCTED }, +}, seq63[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq64[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq65[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq66[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 6 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 8 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 9 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 10 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 11 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 12 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 13 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 14 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 15 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 16 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 18 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 19 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 20 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 21 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 22 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 23 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 24 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 25 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq67[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq68[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq69[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"a", .buf_len = 1}, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"b", .buf_len = 1}, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq70[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"a", .buf_len = 1}, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"b", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"c", .buf_len = 1}, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq71[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"a", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"A", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"b", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"B", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"c", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"C", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"d", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"D", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"e", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"E", .buf_len = 1}, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq72[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_CHUNK, .buf = bm72a, .buf_len = sizeof(bm72a)}, + { .reason = LECPCB_VAL_BLOB_CHUNK, .buf = bm72b, .buf_len = sizeof(bm72b)}, + { .reason = LECPCB_VAL_BLOB_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq73[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_CHUNK, .buf = (const uint8_t *)"stream", .buf_len = 5}, + { .reason = LECPCB_VAL_STR_CHUNK, .buf = (const uint8_t *)"ming", .buf_len = 4}, + { .reason = LECPCB_VAL_STR_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq74[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq75[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq76[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq77[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq78[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq79[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 6 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 8 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 9 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 10 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 11 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 12 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 13 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 14 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 15 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 16 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 18 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 19 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 20 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 21 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 22 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 23 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 24 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 25 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq80[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"a", .buf_len = 1}, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"b", .buf_len = 1}, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 2 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 3 } }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq81[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"a", .buf_len = 1}, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"b", .buf_len = 1}, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"c", .buf_len = 1}, + { .reason = LECPCB_OBJECT_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END }, + { .reason = LECPCB_DESTRUCTED }, +}, seq82[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"Fun", .buf_len = 3}, + { .reason = LECPCB_VAL_TRUE }, + { .reason = LECPCB_VAL_STR_START, }, + { .reason = LECPCB_VAL_STR_END, .buf = (const uint8_t *)"Amt", .buf_len = 3}, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = (int64_t)-2ll } }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq83[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm83a, .buf_len = sizeof(bm83a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm83b, .buf_len = sizeof(bm83b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm83c, .buf_len = sizeof(bm83c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm83a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm83d, .buf_len = sizeof(bm83d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm83a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq84[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm84a, .buf_len = sizeof(bm84a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm84b, .buf_len = sizeof(bm84b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm84c, .buf_len = sizeof(bm84c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm84a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm84d, .buf_len = sizeof(bm84d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm84a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq85[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm85a, .buf_len = sizeof(bm85a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm85b, .buf_len = sizeof(bm85b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm85c, .buf_len = sizeof(bm85c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm85a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm85d, .buf_len = sizeof(bm85d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm85a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq86[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm86a, .buf_len = sizeof(bm86a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm86b, .buf_len = sizeof(bm86b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm86c, .buf_len = sizeof(bm86c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm86a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm86d, .buf_len = sizeof(bm86d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm86a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq87[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm87a, .buf_len = sizeof(bm87a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm87b, .buf_len = sizeof(bm87b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm87c, .buf_len = sizeof(bm87c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm87a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm87d, .buf_len = sizeof(bm87d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm87a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq88[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm88a, .buf_len = sizeof(bm88a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm88b, .buf_len = sizeof(bm88b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm88c, .buf_len = sizeof(bm88c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq89[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm89a, .buf_len = sizeof(bm89a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm89b, .buf_len = sizeof(bm89b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm89c, .buf_len = sizeof(bm89c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq90[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm90a, .buf_len = sizeof(bm90a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm90b, .buf_len = sizeof(bm90b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm90c, .buf_len = sizeof(bm90c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq91[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm91a, .buf_len = sizeof(bm91a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm91b, .buf_len = sizeof(bm91b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm91c, .buf_len = sizeof(bm91c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq92[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm92a, .buf_len = sizeof(bm92a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm92b, .buf_len = sizeof(bm92b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm92c, .buf_len = sizeof(bm92c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq93[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 16 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm93a, .buf_len = sizeof(bm93a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm93b, .buf_len = sizeof(bm93b) }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm93c, .buf_len = sizeof(bm93c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm93d, .buf_len = sizeof(bm93d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm93e, .buf_len = sizeof(bm93e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm93f, .buf_len = sizeof(bm93f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq94[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 16 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94a, .buf_len = sizeof(bm94a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94b, .buf_len = sizeof(bm94b) }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94c, .buf_len = sizeof(bm94c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94d, .buf_len = sizeof(bm94d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94e, .buf_len = sizeof(bm94e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94f, .buf_len = sizeof(bm94f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94g, .buf_len = sizeof(bm94g) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94h, .buf_len = sizeof(bm94h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm94i, .buf_len = sizeof(bm94i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq95[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 96 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95a, .buf_len = sizeof(bm95a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95b, .buf_len = sizeof(bm95b) }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95c, .buf_len = sizeof(bm95c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95d, .buf_len = sizeof(bm95d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95e, .buf_len = sizeof(bm95e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95f, .buf_len = sizeof(bm95f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95f, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95g, .buf_len = sizeof(bm95g) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm95f, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq96[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 96 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96a, .buf_len = sizeof(bm96a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96b, .buf_len = sizeof(bm96b) }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96c, .buf_len = sizeof(bm96c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96d, .buf_len = sizeof(bm96d) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96e, .buf_len = sizeof(bm96e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96f, .buf_len = sizeof(bm96f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96g, .buf_len = sizeof(bm96g) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96h, .buf_len = sizeof(bm96h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96i, .buf_len = sizeof(bm96i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96f, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96j, .buf_len = sizeof(bm96j) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm96f, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq97[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 96 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97a, .buf_len = sizeof(bm97a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 5 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97b, .buf_len = sizeof(bm97b) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97c, .buf_len = sizeof(bm97c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97f, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97d, .buf_len = sizeof(bm97d) }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97e, .buf_len = sizeof(bm97e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97f, .buf_len = sizeof(bm97f) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97g, .buf_len = sizeof(bm97g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm97e, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq98[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98a, .buf_len = sizeof(bm98a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98b, .buf_len = sizeof(bm98b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98c, .buf_len = sizeof(bm98c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98d, .buf_len = sizeof(bm98d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98e, .buf_len = sizeof(bm98e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98f, .buf_len = sizeof(bm98f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98e, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98g, .buf_len = sizeof(bm98g) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98e, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq99[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 97 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99a, .buf_len = sizeof(bm99a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99b, .buf_len = sizeof(bm99b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99c, .buf_len = sizeof(bm99c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99d, .buf_len = sizeof(bm99d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99e, .buf_len = sizeof(bm99e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99f, .buf_len = sizeof(bm99f) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99g, .buf_len = sizeof(bm99g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99h, .buf_len = sizeof(bm99h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99i, .buf_len = sizeof(bm99i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99a, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm99j, .buf_len = sizeof(bm99j) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm98e, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq100[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm100a, .buf_len = sizeof(bm100a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm100b, .buf_len = sizeof(bm100b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm100c, .buf_len = sizeof(bm100c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm100d, .buf_len = sizeof(bm100d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm100e, .buf_len = sizeof(bm100e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm100f, .buf_len = sizeof(bm100f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq101[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101a, .buf_len = sizeof(bm101a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101b, .buf_len = sizeof(bm101b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101c, .buf_len = sizeof(bm101c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101d, .buf_len = sizeof(bm101d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101e, .buf_len = sizeof(bm101e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101f, .buf_len = sizeof(bm101f) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101g, .buf_len = sizeof(bm101g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101h, .buf_len = sizeof(bm101h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101i, .buf_len = sizeof(bm101i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101j, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 1 } }, + { .reason = LECPCB_VAL_NUM_INT, .item = { .u.i64 = -6 } }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101j, .buf_len = sizeof(bm101j) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm101j, .buf_len = 0 }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq102[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm102a, .buf_len = sizeof(bm102a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm102b, .buf_len = sizeof(bm102b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm102c, .buf_len = sizeof(bm102c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm102d, .buf_len = sizeof(bm102d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm102e, .buf_len = sizeof(bm102e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm102f, .buf_len = sizeof(bm102f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq103[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103a, .buf_len = sizeof(bm103a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103b, .buf_len = sizeof(bm103b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103c, .buf_len = sizeof(bm103c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103d, .buf_len = sizeof(bm103d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103e, .buf_len = sizeof(bm103e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103f, .buf_len = sizeof(bm103f) }, + + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103g, .buf_len = sizeof(bm103g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103h, .buf_len = sizeof(bm103h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm103i, .buf_len = sizeof(bm103i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, + +}, seq104[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 98 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104a, .buf_len = sizeof(bm104a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104b, .buf_len = sizeof(bm104b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104c, .buf_len = sizeof(bm104c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104d, .buf_len = sizeof(bm104d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104e, .buf_len = sizeof(bm104e) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104f, .buf_len = sizeof(bm104f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104g, .buf_len = sizeof(bm104g) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm104h, .buf_len = sizeof(bm104h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq105[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 98 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105a, .buf_len = sizeof(bm105a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_OBJECT_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105b, .buf_len = sizeof(bm105b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105c, .buf_len = sizeof(bm105c) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105d, .buf_len = sizeof(bm105d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105e, .buf_len = sizeof(bm105e) }, + { .reason = LECPCB_OBJECT_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105f, .buf_len = sizeof(bm105f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105g, .buf_len = sizeof(bm105g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105h, .buf_len = sizeof(bm105h) }, + { .reason = LECPCB_OBJECT_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105i, .buf_len = sizeof(bm105i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105j, .buf_len = sizeof(bm105j) }, + { .reason = LECPCB_OBJECT_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm105k, .buf_len = sizeof(bm105k) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq106[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 98 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106a, .buf_len = sizeof(bm106a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106b, .buf_len = sizeof(bm106b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106c, .buf_len = sizeof(bm106c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106d, .buf_len = sizeof(bm106d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106e, .buf_len = sizeof(bm106e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106f, .buf_len = sizeof(bm106f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106g, .buf_len = sizeof(bm106g) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm106h, .buf_len = sizeof(bm106h) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq107[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 17 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107a, .buf_len = sizeof(bm107a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107b, .buf_len = sizeof(bm107b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107c, .buf_len = sizeof(bm107c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107d, .buf_len = sizeof(bm107d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107e, .buf_len = sizeof(bm107e) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107f, .buf_len = sizeof(bm107f) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm107g, .buf_len = sizeof(bm107g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}, seq108[] = { + { .reason = LECPCB_CONSTRUCTED }, + { .reason = LECPCB_TAG_START, .item = { .u.u64 = 18 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108a, .buf_len = sizeof(bm108a) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 7 } }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108b, .buf_len = sizeof(bm108b) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108c, .buf_len = sizeof(bm108c) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108d, .buf_len = sizeof(bm108d) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_ARRAY_START, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108e, .buf_len = sizeof(bm108e) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_OBJECT_START, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108f, .buf_len = sizeof(bm108f) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108g, .buf_len = sizeof(bm108g) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_VAL_NUM_UINT, .item = { .u.u64 = 4 } }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108h, .buf_len = sizeof(bm108h) }, + { .reason = LECPCB_OBJECT_END }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108i, .buf_len = sizeof(bm108i) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_ITEM_START, }, + { .reason = LECPCB_VAL_BLOB_START, }, + { .reason = LECPCB_VAL_BLOB_END, .buf = bm108j, .buf_len = sizeof(bm108j) }, + { .reason = LECPCB_ARRAY_ITEM_END, }, + { .reason = LECPCB_ARRAY_END, }, + { .reason = LECPCB_TAG_END, }, + { .reason = LECPCB_DESTRUCTED }, +}; + + +struct cbort { + const uint8_t *b; + size_t blen; + const struct seq *seq; + size_t seq_size; +}; + +static const struct cbort cbor_tests[] = { + { .b = test1, .blen = sizeof(test1), + .seq = seq1, .seq_size = LWS_ARRAY_SIZE(seq1) }, + { .b = test2, .blen = sizeof(test2), + .seq = seq2, .seq_size = LWS_ARRAY_SIZE(seq2) }, + { .b = test3, .blen = sizeof(test3), + .seq = seq3, .seq_size = LWS_ARRAY_SIZE(seq3) }, + { .b = test4, .blen = sizeof(test4), + .seq = seq4, .seq_size = LWS_ARRAY_SIZE(seq4) }, + { .b = test5, .blen = sizeof(test5), + .seq = seq5, .seq_size = LWS_ARRAY_SIZE(seq5) }, + { .b = test6, .blen = sizeof(test6), + .seq = seq6, .seq_size = LWS_ARRAY_SIZE(seq6) }, + { .b = test7, .blen = sizeof(test7), + .seq = seq7, .seq_size = LWS_ARRAY_SIZE(seq7) }, + { .b = test8, .blen = sizeof(test8), + .seq = seq8, .seq_size = LWS_ARRAY_SIZE(seq8) }, + { .b = test9, .blen = sizeof(test9), + .seq = seq9, .seq_size = LWS_ARRAY_SIZE(seq9) }, + { .b = test10, .blen = sizeof(test10), + .seq = seq10, .seq_size = LWS_ARRAY_SIZE(seq10) }, + { .b = test11, .blen = sizeof(test11), + .seq = seq11, .seq_size = LWS_ARRAY_SIZE(seq11) }, + { .b = test12, .blen = sizeof(test12), + .seq = seq12, .seq_size = LWS_ARRAY_SIZE(seq12) }, + { .b = test13, .blen = sizeof(test13), + .seq = seq13, .seq_size = LWS_ARRAY_SIZE(seq13) }, + { .b = test14, .blen = sizeof(test14), + .seq = seq14, .seq_size = LWS_ARRAY_SIZE(seq14) }, + { .b = test15, .blen = sizeof(test15), + .seq = seq15, .seq_size = LWS_ARRAY_SIZE(seq15) }, + { .b = test16, .blen = sizeof(test16), + .seq = seq16, .seq_size = LWS_ARRAY_SIZE(seq16) }, + { .b = test17, .blen = sizeof(test17), + .seq = seq17, .seq_size = LWS_ARRAY_SIZE(seq17) }, + { .b = test18, .blen = sizeof(test18), + .seq = seq18, .seq_size = LWS_ARRAY_SIZE(seq18) }, + { .b = test19, .blen = sizeof(test19), + .seq = seq19, .seq_size = LWS_ARRAY_SIZE(seq19) }, + { .b = test20, .blen = sizeof(test20), + .seq = seq20, .seq_size = LWS_ARRAY_SIZE(seq20) }, + { .b = test21, .blen = sizeof(test21), + .seq = seq21, .seq_size = LWS_ARRAY_SIZE(seq21) }, + { .b = test22, .blen = sizeof(test22), + .seq = seq22, .seq_size = LWS_ARRAY_SIZE(seq22) }, + { .b = test23, .blen = sizeof(test23), + .seq = seq23, .seq_size = LWS_ARRAY_SIZE(seq23) }, + { .b = test24, .blen = sizeof(test24), + .seq = seq24, .seq_size = LWS_ARRAY_SIZE(seq24) }, + { .b = test25, .blen = sizeof(test25), + .seq = seq25, .seq_size = LWS_ARRAY_SIZE(seq25) }, + { .b = test26, .blen = sizeof(test26), + .seq = seq26, .seq_size = LWS_ARRAY_SIZE(seq26) }, + { .b = test27, .blen = sizeof(test27), + .seq = seq27, .seq_size = LWS_ARRAY_SIZE(seq27) }, + { .b = test28, .blen = sizeof(test28), + .seq = seq28, .seq_size = LWS_ARRAY_SIZE(seq28) }, + { .b = test29, .blen = sizeof(test29), + .seq = seq29, .seq_size = LWS_ARRAY_SIZE(seq29) }, + { .b = test30, .blen = sizeof(test30), + .seq = seq30, .seq_size = LWS_ARRAY_SIZE(seq30) }, + { .b = test31, .blen = sizeof(test31), + .seq = seq31, .seq_size = LWS_ARRAY_SIZE(seq31) }, + { .b = test32, .blen = sizeof(test32), + .seq = seq32, .seq_size = LWS_ARRAY_SIZE(seq32) }, + { .b = test33, .blen = sizeof(test33), + .seq = seq33, .seq_size = LWS_ARRAY_SIZE(seq33) }, + { .b = test34, .blen = sizeof(test34), + .seq = seq34, .seq_size = LWS_ARRAY_SIZE(seq34) }, + { .b = test35, .blen = sizeof(test35), + .seq = seq35, .seq_size = LWS_ARRAY_SIZE(seq35) }, + { .b = test36, .blen = sizeof(test36), + .seq = seq36, .seq_size = LWS_ARRAY_SIZE(seq36) }, + { .b = test37, .blen = sizeof(test37), + .seq = seq37, .seq_size = LWS_ARRAY_SIZE(seq37) }, + { .b = test38, .blen = sizeof(test38), + .seq = seq38, .seq_size = LWS_ARRAY_SIZE(seq38) }, + { .b = test39, .blen = sizeof(test39), + .seq = seq39, .seq_size = LWS_ARRAY_SIZE(seq39) }, + { .b = test40, .blen = sizeof(test40), + .seq = seq40, .seq_size = LWS_ARRAY_SIZE(seq40) }, + { .b = test41, .blen = sizeof(test41), + .seq = seq41, .seq_size = LWS_ARRAY_SIZE(seq41) }, + { .b = test42, .blen = sizeof(test42), + .seq = seq42, .seq_size = LWS_ARRAY_SIZE(seq42) }, + { .b = test43, .blen = sizeof(test43), + .seq = seq43, .seq_size = LWS_ARRAY_SIZE(seq43) }, + { .b = test44, .blen = sizeof(test44), + .seq = seq44, .seq_size = LWS_ARRAY_SIZE(seq44) }, + { .b = test45, .blen = sizeof(test45), + .seq = seq45, .seq_size = LWS_ARRAY_SIZE(seq45) }, + { .b = test46, .blen = sizeof(test46), + .seq = seq46, .seq_size = LWS_ARRAY_SIZE(seq46) }, + { .b = test47, .blen = sizeof(test47), + .seq = seq47, .seq_size = LWS_ARRAY_SIZE(seq47) }, + { .b = test48, .blen = sizeof(test48), + .seq = seq48, .seq_size = LWS_ARRAY_SIZE(seq48) }, + { .b = test49, .blen = sizeof(test49), + .seq = seq49, .seq_size = LWS_ARRAY_SIZE(seq49) }, + { .b = test50, .blen = sizeof(test50), + .seq = seq50, .seq_size = LWS_ARRAY_SIZE(seq50) }, + { .b = test51, .blen = sizeof(test51), + .seq = seq51, .seq_size = LWS_ARRAY_SIZE(seq51) }, + { .b = test52, .blen = sizeof(test52), + .seq = seq52, .seq_size = LWS_ARRAY_SIZE(seq52) }, + { .b = test53, .blen = sizeof(test53), + .seq = seq53, .seq_size = LWS_ARRAY_SIZE(seq53) }, + { .b = test54, .blen = sizeof(test54), + .seq = seq54, .seq_size = LWS_ARRAY_SIZE(seq54) }, + { .b = test55, .blen = sizeof(test55), + .seq = seq55, .seq_size = LWS_ARRAY_SIZE(seq55) }, + { .b = test56, .blen = sizeof(test56), + .seq = seq56, .seq_size = LWS_ARRAY_SIZE(seq56) }, + { .b = test57, .blen = sizeof(test57), + .seq = seq57, .seq_size = LWS_ARRAY_SIZE(seq57) }, + { .b = test58, .blen = sizeof(test58), + .seq = seq58, .seq_size = LWS_ARRAY_SIZE(seq58) }, + { .b = test59, .blen = sizeof(test59), + .seq = seq59, .seq_size = LWS_ARRAY_SIZE(seq59) }, + { .b = test60, .blen = sizeof(test60), + .seq = seq60, .seq_size = LWS_ARRAY_SIZE(seq60) }, + { .b = test61, .blen = sizeof(test61), + .seq = seq61, .seq_size = LWS_ARRAY_SIZE(seq61) }, + { .b = test62, .blen = sizeof(test62), + .seq = seq62, .seq_size = LWS_ARRAY_SIZE(seq62) }, + { .b = test63, .blen = sizeof(test63), + .seq = seq63, .seq_size = LWS_ARRAY_SIZE(seq63) }, + { .b = test64, .blen = sizeof(test64), + .seq = seq64, .seq_size = LWS_ARRAY_SIZE(seq64) }, + { .b = test65, .blen = sizeof(test65), + .seq = seq65, .seq_size = LWS_ARRAY_SIZE(seq65) }, + { .b = test66, .blen = sizeof(test66), + .seq = seq66, .seq_size = LWS_ARRAY_SIZE(seq66) }, + { .b = test67, .blen = sizeof(test67), + .seq = seq67, .seq_size = LWS_ARRAY_SIZE(seq67) }, + { .b = test68, .blen = sizeof(test68), + .seq = seq68, .seq_size = LWS_ARRAY_SIZE(seq68) }, + { .b = test69, .blen = sizeof(test69), + .seq = seq69, .seq_size = LWS_ARRAY_SIZE(seq69) }, + { .b = test70, .blen = sizeof(test70), + .seq = seq70, .seq_size = LWS_ARRAY_SIZE(seq70) }, + { .b = test71, .blen = sizeof(test71), + .seq = seq71, .seq_size = LWS_ARRAY_SIZE(seq71) }, + { .b = test72, .blen = sizeof(test72), + .seq = seq72, .seq_size = LWS_ARRAY_SIZE(seq72) }, + { .b = test73, .blen = sizeof(test73), + .seq = seq73, .seq_size = LWS_ARRAY_SIZE(seq73) }, + { .b = test74, .blen = sizeof(test74), + .seq = seq74, .seq_size = LWS_ARRAY_SIZE(seq74) }, + { .b = test75, .blen = sizeof(test75), + .seq = seq75, .seq_size = LWS_ARRAY_SIZE(seq75) }, + { .b = test76, .blen = sizeof(test76), + .seq = seq76, .seq_size = LWS_ARRAY_SIZE(seq76) }, + { .b = test77, .blen = sizeof(test77), + .seq = seq77, .seq_size = LWS_ARRAY_SIZE(seq77) }, + { .b = test78, .blen = sizeof(test78), + .seq = seq78, .seq_size = LWS_ARRAY_SIZE(seq78) }, + { .b = test79, .blen = sizeof(test79), + .seq = seq79, .seq_size = LWS_ARRAY_SIZE(seq79) }, + { .b = test80, .blen = sizeof(test80), + .seq = seq80, .seq_size = LWS_ARRAY_SIZE(seq80) }, + { .b = test81, .blen = sizeof(test81), + .seq = seq81, .seq_size = LWS_ARRAY_SIZE(seq81) }, + { .b = test82, .blen = sizeof(test82), + .seq = seq82, .seq_size = LWS_ARRAY_SIZE(seq82) }, + + /* COSE-dervied test vectors */ + + { .b = test83, .blen = sizeof(test83), + .seq = seq83, .seq_size = LWS_ARRAY_SIZE(seq83) }, + { .b = test84, .blen = sizeof(test84), + .seq = seq84, .seq_size = LWS_ARRAY_SIZE(seq84) }, + { .b = test85, .blen = sizeof(test85), + .seq = seq85, .seq_size = LWS_ARRAY_SIZE(seq85) }, + { .b = test86, .blen = sizeof(test86), + .seq = seq86, .seq_size = LWS_ARRAY_SIZE(seq86) }, + { .b = test87, .blen = sizeof(test87), + .seq = seq87, .seq_size = LWS_ARRAY_SIZE(seq87) }, + { .b = test88, .blen = sizeof(test88), + .seq = seq88, .seq_size = LWS_ARRAY_SIZE(seq88) }, + { .b = test89, .blen = sizeof(test89), + .seq = seq89, .seq_size = LWS_ARRAY_SIZE(seq89) }, + { .b = test90, .blen = sizeof(test90), + .seq = seq90, .seq_size = LWS_ARRAY_SIZE(seq90) }, + { .b = test91, .blen = sizeof(test91), + .seq = seq91, .seq_size = LWS_ARRAY_SIZE(seq91) }, + { .b = test92, .blen = sizeof(test92), + .seq = seq92, .seq_size = LWS_ARRAY_SIZE(seq92) }, + { .b = test93, .blen = sizeof(test93), + .seq = seq93, .seq_size = LWS_ARRAY_SIZE(seq93) }, + { .b = test94, .blen = sizeof(test94), + .seq = seq94, .seq_size = LWS_ARRAY_SIZE(seq94) }, + { .b = test95, .blen = sizeof(test95), + .seq = seq95, .seq_size = LWS_ARRAY_SIZE(seq95) }, + { .b = test96, .blen = sizeof(test96), + .seq = seq96, .seq_size = LWS_ARRAY_SIZE(seq96) }, + { .b = test97, .blen = sizeof(test97), + .seq = seq97, .seq_size = LWS_ARRAY_SIZE(seq97) }, + { .b = test98, .blen = sizeof(test98), + .seq = seq98, .seq_size = LWS_ARRAY_SIZE(seq98) }, + { .b = test99, .blen = sizeof(test99), + .seq = seq99, .seq_size = LWS_ARRAY_SIZE(seq99) }, + { .b = test100, .blen = sizeof(test100), + .seq = seq100, .seq_size = LWS_ARRAY_SIZE(seq100) }, + { .b = test101, .blen = sizeof(test101), + .seq = seq101, .seq_size = LWS_ARRAY_SIZE(seq101) }, + { .b = test102, .blen = sizeof(test102), + .seq = seq102, .seq_size = LWS_ARRAY_SIZE(seq102) }, + { .b = test103, .blen = sizeof(test103), + .seq = seq103, .seq_size = LWS_ARRAY_SIZE(seq103) }, + { .b = test104, .blen = sizeof(test104), + .seq = seq104, .seq_size = LWS_ARRAY_SIZE(seq104) }, + { .b = test105, .blen = sizeof(test105), + .seq = seq105, .seq_size = LWS_ARRAY_SIZE(seq105) }, + { .b = test106, .blen = sizeof(test106), + .seq = seq106, .seq_size = LWS_ARRAY_SIZE(seq106) }, + { .b = test107, .blen = sizeof(test107), + .seq = seq107, .seq_size = LWS_ARRAY_SIZE(seq107) }, + { .b = test108, .blen = sizeof(test108), + .seq = seq108, .seq_size = LWS_ARRAY_SIZE(seq108) }, +}; + +static const uint8_t + w1[] = { 0x65, 0x68, 0x65, 0x6C, + 0x6C, 0x6F }, + w2[] = { 0xc2 }, + w3[] = { 0x82, 0x63, 0x61, 0x62, + 0x63, 0x63, 0x64, 0x65, + 0x66 }, + w4[] = { 0xA2, 0x63, 0x67, 0x68, + 0x69, 0x01, 0x63, 0x6A, + 0x6B, 0x6C, 0x02 }, + w5[] = { 0xD8, 0x7B, 0xA2, 0x63, + 0x67, 0x68, 0x69, 0x01, + 0x63, 0x6A, 0x6B, 0x6C, + 0x02 }, + w6[] = { 0xCC, 0xA2, 0x63, 0x67, + 0x68, 0x69, 0x01, 0x63, + 0x6A, 0x6B, 0x6C, 0x82, + 0x61, 0x61, 0x61, 0x62 }, + w7[] = { 0x20, }, + w8[] = { 0x0c, }, + w13[] = { 0x18, 0x34 }, + w14[] = { 0x19, 0x12, 0x34 }, + w15[] = { 0x1a, 0x12, 0x34, 0x56, 0x78 }, + w16[] = { 0x1b, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }, + w17[] = { 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F }, + w18[] = { 0x25 }, + w19[] = { + 0xd8, 0x7b, 0x58, 0xb7, + 0xd8, 0x62, 0x84, 0x43, 0xa1, + 0x03, 0x00, 0xa1, 0x07, 0x83, + 0x43, 0xa1, 0x01, 0x27, 0xa1, + 0x04, 0x42, 0x31, 0x31, 0x58, + 0x40, 0xb7, 0xca, 0xcb, 0xa2, + 0x85, 0xc4, 0xcd, 0x3e, 0xd2, + 0xf0, 0x14, 0x6f, 0x41, 0x98, + 0x86, 0x14, 0x4c, 0xa6, 0x38, + 0xd0, 0x87, 0xde, 0x12, 0x3d, + 0x40, 0x01, 0x67, 0x30, 0x8a, + 0xce, 0xab, 0xc4, 0xb5, 0xe5, + 0xc6, 0xa4, 0x0c, 0x0d, 0xe0, + }, + w19a[] = { + 0xb7, 0x11, 0x67, 0xa3, 0x91, + 0x75, 0xea, 0x56, 0xc1, 0xfe, + 0x96, 0xc8, 0x9e, 0x5e, 0x7d, + 0x30, 0xda, 0xf2, 0x43, 0x8a, + 0x45, 0x61, 0x59, 0xa2, 0x0a, + 0x54, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x81, 0x83, 0x43, 0xa1, + 0x01, 0x27, 0xa1, 0x04, 0x42, + 0x31, 0x31, 0x58, 0x40, 0x77, + 0xf3, 0xea, 0xcd, 0x11,}, + w19b[] = { + 0x85, 0x2c, 0x4b, 0xf9, 0xcb, 0x1d, + 0x72, 0xfa, 0xbe, 0x6b, 0x26, + 0xfb, 0xa1, 0xd7, 0x60, 0x92, + 0xb2, 0xb5, 0xb7, 0xec, 0x83, + 0xb8, 0x35, 0x57, 0x65, 0x22, + 0x64, 0xe6, 0x96, 0x90, 0xdb, + 0xc1, 0x17, 0x2d, 0xdc, 0x0b, + 0xf8, 0x84, 0x11, 0xc0, 0xd2, + 0x5a, 0x50, 0x7f, 0xdb, 0x24, + 0x7a, 0x20, 0xc4, 0x0d, 0x5e, + 0x24, 0x5f, 0xab, 0xd3, 0xfc, + 0x9e, 0xc1, 0x06 }, + w22[] = { 0xD8, 0x7B, 0x19, 0x01, 0xC8 }, + w24[] = { 0xDB, 0x12, 0x34, 0x56, 0x78, 0x9A, + 0xBC, 0xED, 0xF0, 0x19, 0x01, 0xC8}, + w25[] = { 0xF9, 0x3C, 0x00 }, + w26[] = { 0xF9, 0x3E, 0x00 }, + w27[] = { 0xFB, 0x3F, 0xF1, 0xF7, 0xCE, 0xD9, 0x16, 0x87, 0x2B }, + w28[] = { 0xA2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03 }, + w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF +} +; + +static const char * const tok[] = { + "something", +}; + +struct priv { + const struct cbort *cbt; + size_t idx; +}; + +static int pass; + +static signed char +test_cb(struct lecp_ctx *ctx, char reason) +{ + struct priv *priv = (struct priv *)ctx->user; + size_t i = priv->idx++; + +#if defined(VERBOSE) + lwsl_notice("%s: %s, ctx->path %s\n", __func__, + reason_names[(int)reason & 0x1f], ctx->path); +#endif + + // if (ctx->npos) + // lwsl_hexdump_notice(ctx->buf, ctx->npos); + + if (!priv->cbt->seq) + return 0; + + if (i >= priv->cbt->seq_size) { + lwsl_warn("%s: unexpected parse states\n", __func__); + return 1; + } + + if (priv->cbt->seq[i].reason != reason) { + lwsl_warn("%s: reason mismatch\n", __func__); + return 1; + } + + if (priv->cbt->seq[i].buf && + (priv->cbt->seq[i].buf_len != ctx->npos || + memcmp(priv->cbt->seq[i].buf, ctx->buf, ctx->npos))) { + lwsl_warn("%s: buf mismatch\n", __func__); + lwsl_hexdump_notice(ctx->buf, (size_t)ctx->npos); + return 1; + } + + switch (reason) { + case LECPCB_VAL_SIMPLE: + case LECPCB_VAL_NUM_UINT: + case LECPCB_VAL_NUM_INT: + if (ctx->item.u.u64 != priv->cbt->seq[i].item.u.u64) { + lwsl_warn("%s: number mismatch %llu %llu\n", __func__, + (unsigned long long)ctx->item.u.u64, + (unsigned long long)priv->cbt->seq[i].item.u.u64); + return 1; + } + break; + + case LECPCB_VAL_FLOAT16: + if (ctx->item.u.hf != priv->cbt->seq[i].item.u.hf) { + lwsl_warn("%s: number mismatch %llu %llu\n", __func__, + (unsigned long long)ctx->item.u.hf, + (unsigned long long)priv->cbt->seq[i].item.u.hf); + return 1; + } + break; + case LECPCB_VAL_FLOAT32: +#if defined(LWS_WITH_CBOR_FLOAT) + if (!isfinite(ctx->item.u.f) && + !isfinite(priv->cbt->seq[i].item.u.f)) + break; + if (isnan(ctx->item.u.f) && + isnan(priv->cbt->seq[i].item.u.f)) + break; +#endif + if (ctx->item.u.f != priv->cbt->seq[i].item.u.f) { +#if defined(LWS_WITH_CBOR_FLOAT) + lwsl_warn("%s: number mismatch %f %f\n", __func__, + ctx->item.u.f, + priv->cbt->seq[i].item.u.f); +#else + lwsl_warn("%s: f32 number mismatch %llu %llu\n", __func__, + (unsigned long long)ctx->item.u.f, + (unsigned long long)priv->cbt->seq[i].item.u.f); +#endif + return 1; + } + break; + case LECPCB_VAL_FLOAT64: +#if defined(LWS_WITH_CBOR_FLOAT) + if (!isfinite(ctx->item.u.d) && + !isfinite(priv->cbt->seq[i].item.u.d)) + break; + if (isnan(ctx->item.u.d) && + isnan(priv->cbt->seq[i].item.u.d)) + break; +#endif + if (ctx->item.u.d != priv->cbt->seq[i].item.u.d) { +#if defined(LWS_WITH_CBOR_FLOAT) + lwsl_warn("%s: f64 number mismatch %f %f\n", __func__, + ctx->item.u.d, + priv->cbt->seq[i].item.u.d); +#else + lwsl_warn("%s: number mismatch %llu %llu\n", __func__, + (unsigned long long)ctx->item.u.d, + (unsigned long long)priv->cbt->seq[i].item.u.d); +#endif + return 1; + } + break; + + case LECPCB_DESTRUCTED: + pass++; + break; + } + + return 0; +} + +int main(int argc, const char **argv) +{ + int n, m, e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, + expected = (int)LWS_ARRAY_SIZE(cbor_tests) + + 29 /* <-- how many write tests */; + struct lecp_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: LECP CBOR parser\n"); + + for (m = 0; m < (int)LWS_ARRAY_SIZE(cbor_tests); m++) { + + struct priv priv; + + priv.cbt = &cbor_tests[m]; + priv.idx = 0; + + lwsl_notice("%s: ++++++++++++++++ test %d\n", __func__, m + 1); + + lecp_construct(&ctx, test_cb, &priv, tok, LWS_ARRAY_SIZE(tok)); + + lwsl_hexdump_info(cbor_tests[m].b, cbor_tests[m].blen); + +#if 0 + { + char fn[128]; + int fd; + + lws_snprintf(fn, sizeof(fn), "/tmp/cbor-%d", m + 1); + fd = open(fn, LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600); + if (fd != -1) { + write(fd, cbor_tests[m].b, + cbor_tests[m].blen); + close(fd); + } + } +#endif + + n = lecp_parse(&ctx, cbor_tests[m].b, + cbor_tests[m].blen); + + lecp_destruct(&ctx); + + if (n < 0 && m + 1 != 46 /* expected to fail */) { + lwsl_err("%s: test %d: CBOR decode failed %d '%s'\n", + __func__, m + 1, n, + lecp_error_to_string(n)); + e++; + } + } + + { + lws_lec_pctx_t ctx; + uint8_t buf[64]; + + lws_lec_init(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "'hello'") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w1) || memcmp(w1, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "2()") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w2) || memcmp(w2, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "['abc','def']") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w3) || memcmp(w3, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test4\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "{'ghi':1,'jkl':2}") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w4) || memcmp(w4, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test5\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "123({'ghi':1,'jkl':2})") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w5) || memcmp(w5, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test6\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "12({'ghi':1,'jkl':['a', 'b']})") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w6) || memcmp(w6, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test7\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%d", -1) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w7) || memcmp(w7, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test8\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%ld", -1l) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w7) || memcmp(w7, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test9\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%lld", -1ll) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w7) || memcmp(w7, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test10\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%u", 12) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w8) || memcmp(w8, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test11\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%ld", 12l) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w8) || memcmp(w8, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test12\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%lld", 12ll) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w8) || memcmp(w8, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test13\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%u", 0x34u) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w13) || memcmp(w13, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test14\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%ld", 0x1234ul) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w14) || memcmp(w14, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test15\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%lld", 0x12345678ull) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w15) || memcmp(w15, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test16\n", __func__); + + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%lld", 0x123456789abcdef0ull) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w16) || memcmp(w16, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test17\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%s", "hello") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w17) || memcmp(w17, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test18\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "-6") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w18) || memcmp(w18, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + /* + * A big binary blob is going to get emitted in 3 output + * buffers, by calling it two more times while still handling + * the same format object, format objects before that which + * were completed are skipped on the subsequent calls + */ + + lwsl_user("%s: test19\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "123(%.*b)", (int)sizeof(test106), test106) != + LWS_LECPCTX_RET_AGAIN || + ctx.used != sizeof(w19) || memcmp(w19, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test20\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "123(%.*b)", (int)sizeof(test106), test106) != + LWS_LECPCTX_RET_AGAIN || + ctx.used != sizeof(w19a) || memcmp(w19a, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test21\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "123(%.*b)", (int)sizeof(test106), test106) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w19b) || memcmp(w19b, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test22\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%t(456)", 123) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w22) || memcmp(w22, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test23\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%lt(456)", 123ul) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w22) || memcmp(w22, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test24\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%llt(456)", 0x123456789abcedf0ull) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w24) || memcmp(w24, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test25\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%f", 1.0) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w25) || memcmp(w25, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test26\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%f", 1.5) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w26) || memcmp(w26, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test27\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "%f", 1.123) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w27) || memcmp(w27, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + { + int args[3] = { 1, 2, 3 }; + + lwsl_user("%s: test28\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "{'a':%d,'b':[%d,%d]}", + args[0], args[1], args[2]) != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w28) || + memcmp(w28, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + } + + lwsl_user("%s: test29\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w29) || memcmp(w29, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + } + + if (e) + goto bail; + + if (pass != expected) + goto bail; + + lwsl_user("Completed: PASS %d / %d\n", pass, expected); + + return 0; + +bail: + lwsl_user("Completed: FAIL, passed %d / %d (e %d)\n", pass, + expected, e); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/CMakeLists.txt new file mode 100644 index 00000000..72ae86a5 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/CMakeLists.txt @@ -0,0 +1,19 @@ +project(lws-api-test-lws_cache C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-api-test-lws_cache) +set(SRCS main.c) + +add_executable(${SAMP} ${SRCS}) +add_test(NAME api-test-lws_cache COMMAND lws-api-test-lws_cache) + +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 --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/README.md b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/README.md new file mode 100644 index 00000000..74034c79 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/README.md @@ -0,0 +1,22 @@ +# lws api test lwsac + +Demonstrates how to use and performs selftests for lwsac + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` + $ ./lws-api-test-lwsac +[2018/10/09 09:14:17:4834] USER: LWS API selftest: lwsac +[2018/10/09 09:14:17:4835] USER: Completed: PASS +``` + diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/main.c new file mode 100644 index 00000000..64835fff --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/main.c @@ -0,0 +1,512 @@ +/* + * lws-api-test-lws_cache + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include + +static struct lws_context *cx; +static int tests, fail; + +static int +test_just_l1(void) +{ + struct lws_cache_creation_info ci; + struct lws_cache_ttl_lru *l1; + int ret = 1; + size_t size; + char *po; + + lwsl_user("%s\n", __func__); + + tests++; + + /* just create a heap cache "L1" */ + + memset(&ci, 0, sizeof(ci)); + ci.cx = cx; + ci.ops = &lws_cache_ops_heap; + ci.name = "L1"; + + l1 = lws_cache_create(&ci); + if (!l1) + goto cdone; + + /* add two items, a has 1s expiry and b has 2s */ + + if (lws_cache_write_through(l1, "a", (const uint8_t *)"is_a", 5, + lws_now_usecs() + LWS_US_PER_SEC, NULL)) + goto cdone; + + if (lws_cache_write_through(l1, "b", (const uint8_t *)"is_b", 5, + lws_now_usecs() + LWS_US_PER_SEC * 2, NULL)) + goto cdone; + + /* check they exist as intended */ + + if (lws_cache_item_get(l1, "a", (const void **)&po, &size) || + size != 5 || strcmp(po, "is_a")) + goto cdone; + + if (lws_cache_item_get(l1, "b", (const void **)&po, &size) || + size != 5 || strcmp(po, "is_b")) + goto cdone; + + /* wait for 1.2s to pass, working the event loop by hand */ + + lws_cancel_service(cx); + if (lws_service(cx, 0) < 0) + goto cdone; +#if defined(WIN32) + Sleep(1200); +#else + /* netbsd cares about < 1M */ + usleep(999999); + usleep(200001); +#endif + lws_cancel_service(cx); + if (lws_service(cx, 0) < 0) + goto cdone; + + lws_cancel_service(cx); + if (lws_service(cx, 0) < 0) + goto cdone; + + /* a only had 1s lifetime, he should be gone */ + + if (!lws_cache_item_get(l1, "a", (const void **)&po, &size)) { + lwsl_err("%s: cache: a still exists after expiry\n", __func__); + fail++; + goto cdone; + } + + /* that's ok then */ + + ret = 0; + +cdone: + lws_cache_destroy(&l1); + + if (ret) + lwsl_warn("%s: fail\n", __func__); + + return ret; +} + +static int +test_just_l1_limits(void) +{ + struct lws_cache_creation_info ci; + struct lws_cache_ttl_lru *l1; + int ret = 1; + size_t size; + char *po; + + lwsl_user("%s\n", __func__); + tests++; + + /* just create a heap cache "L1" */ + + memset(&ci, 0, sizeof(ci)); + ci.cx = cx; + ci.ops = &lws_cache_ops_heap; + ci.name = "L1_lim"; + ci.max_items = 1; /* ie, adding a second item destroys the first */ + + l1 = lws_cache_create(&ci); + if (!l1) + goto cdone; + + /* add two items, a has 1s expiry and b has 2s */ + + if (lws_cache_write_through(l1, "a", (const uint8_t *)"is_a", 5, + lws_now_usecs() + LWS_US_PER_SEC, NULL)) + goto cdone; + + if (lws_cache_write_through(l1, "b", (const uint8_t *)"is_b", 5, + lws_now_usecs() + LWS_US_PER_SEC * 2, NULL)) + goto cdone; + + /* only b should exit, since we limit to cache to just one entry */ + + if (!lws_cache_item_get(l1, "a", (const void **)&po, &size)) + goto cdone; + + if (lws_cache_item_get(l1, "b", (const void **)&po, &size) || + size != 5 || strcmp(po, "is_b")) + goto cdone; + + /* that's ok then */ + + ret = 0; + +cdone: + lws_cache_destroy(&l1); + + if (ret) + lwsl_warn("%s: fail\n", __func__); + + return ret; +} + +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) + +static const char + *cookie1 = "host.com\tFALSE\t/\tTRUE\t4000000000\tmycookie\tmycookievalue", + *tag_cookie1 = "host.com|/|mycookie", + *cookie2 = "host.com\tFALSE\t/xxx\tTRUE\t4000000000\tmycookie\tmyxxxcookievalue", + *tag_cookie2 = "host.com|/xxx|mycookie", + *cookie3 = "host.com\tFALSE\t/\tTRUE\t4000000000\textra\tcookie3value", + *tag_cookie3 = "host.com|/|extra", + *cookie4 = "host.com\tFALSE\t/yyy\tTRUE\t4000000000\tnewcookie\tnewcookievalue", + *tag_cookie4 = "host.com|/yyy|newcookie" +; + +static int +test_nsc1(void) +{ + struct lws_cache_creation_info ci; + struct lws_cache_ttl_lru *l1 = NULL, *nsc; + lws_cache_results_t cr; + int n, ret = 1; + size_t size; + char *po; + + lwsl_user("%s\n", __func__); + tests++; + + /* First create a netscape cookie cache object */ + + memset(&ci, 0, sizeof(ci)); + ci.cx = cx; + ci.ops = &lws_cache_ops_nscookiejar; + ci.name = "NSC"; + ci.u.nscookiejar.filepath = "./cookies.txt"; + + nsc = lws_cache_create(&ci); + if (!nsc) + goto cdone; + + /* Then a heap cache "L1" as a child of nsc */ + + ci.ops = &lws_cache_ops_heap; + ci.name = "L1"; + ci.parent = nsc; + + l1 = lws_cache_create(&ci); + if (!l1) + goto cdone; + + lws_cache_debug_dump(nsc); + lws_cache_debug_dump(l1); + + lwsl_user("%s: add cookies to L1\n", __func__); + + /* add three cookies */ + + if (lws_cache_write_through(l1, tag_cookie1, + (const uint8_t *)cookie1, strlen(cookie1), + lws_now_usecs() + LWS_US_PER_SEC, NULL)) { + lwsl_err("%s: write1 failed\n", __func__); + goto cdone; + } + + lws_cache_debug_dump(nsc); + lws_cache_debug_dump(l1); + + if (lws_cache_write_through(l1, tag_cookie2, + (const uint8_t *)cookie2, strlen(cookie2), + lws_now_usecs() + LWS_US_PER_SEC * 2, NULL)) { + lwsl_err("%s: write2 failed\n", __func__); + goto cdone; + } + + lws_cache_debug_dump(nsc); + lws_cache_debug_dump(l1); + + if (lws_cache_write_through(l1, tag_cookie3, + (const uint8_t *)cookie3, strlen(cookie3), + lws_now_usecs() + LWS_US_PER_SEC * 2, NULL)) { + lwsl_err("%s: write3 failed\n", __func__); + goto cdone; + } + + lws_cache_debug_dump(nsc); + lws_cache_debug_dump(l1); + + lwsl_user("%s: check cookies in L1\n", __func__); + + /* confirm that the cookies are individually in L1 */ + + if (lws_cache_item_get(l1, tag_cookie1, (const void **)&po, &size) || + size != strlen(cookie1) || memcmp(po, cookie1, size)) { + lwsl_err("%s: L1 '%s' missing, size %llu, po %s\n", __func__, + tag_cookie1, (unsigned long long)size, po); + goto cdone; + } + + if (lws_cache_item_get(l1, tag_cookie2, (const void **)&po, &size) || + size != strlen(cookie2) || memcmp(po, cookie2, size)) { + lwsl_err("%s: L1 '%s' missing\n", __func__, tag_cookie2); + goto cdone; + } + + if (lws_cache_item_get(l1, tag_cookie3, (const void **)&po, &size) || + size != strlen(cookie3) || memcmp(po, cookie3, size)) { + lwsl_err("%s: L1 '%s' missing\n", __func__, tag_cookie3); + goto cdone; + } + + /* confirm that the cookies are individually in L2 / NSC... normally + * we don't do this but check via L1 so we can get it from there if + * present. But as a unit test, we want to make sure it's in L2 / NSC + */ + + lwsl_user("%s: check cookies written thru to NSC\n", __func__); + + if (lws_cache_item_get(nsc, tag_cookie1, (const void **)&po, &size) || + size != strlen(cookie1) || memcmp(po, cookie1, size)) { + lwsl_err("%s: NSC '%s' missing, size %llu, po %s\n", __func__, + tag_cookie1, (unsigned long long)size, po); + goto cdone; + } + + if (lws_cache_item_get(nsc, tag_cookie2, (const void **)&po, &size) || + size != strlen(cookie2) || memcmp(po, cookie2, size)) { + lwsl_err("%s: NSC '%s' missing\n", __func__, tag_cookie2); + goto cdone; + } + + if (lws_cache_item_get(nsc, tag_cookie3, (const void **)&po, &size) || + size != strlen(cookie3) || memcmp(po, cookie3, size)) { + lwsl_err("%s: NSC '%s' missing\n", __func__, tag_cookie3); + goto cdone; + } + + /* let's do a lookup with no results */ + + lwsl_user("%s: nonexistant get must not pass\n", __func__); + + if (!lws_cache_item_get(l1, "x.com|y|z", (const void **)&po, &size)) { + lwsl_err("%s: nonexistant found size %llu, po %s\n", __func__, + (unsigned long long)size, po); + goto cdone; + } + + /* + * let's try some url paths and check we get the right results set... + * for / and any cookie, we expect only c1 and c3 to be listed + */ + + lwsl_user("%s: wildcard lookup 1\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + lwsl_hexdump_notice(cr.ptr, size); + + if (cr.size != 53) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* + * for /xxx and any cookie, we expect all 3 listed + */ + + lwsl_user("%s: wildcard lookup 2\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/xxx|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + + if (cr.size != 84) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* + * for /yyyy and any cookie, we expect only c1 and c3 + */ + + lwsl_user("%s: wildcard lookup 3\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/yyyy|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + + if (cr.size != 53) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* + * repeat the above test, results should come from cache + */ + + lwsl_user("%s: wildcard lookup 4\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/yyyy|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + + if (cr.size != 53) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* now let's try deleting cookie 1 */ + + if (lws_cache_item_remove(l1, tag_cookie1)) + goto cdone; + + lws_cache_debug_dump(nsc); + lws_cache_debug_dump(l1); + + /* with c1 gone, we should only get c3 */ + + lwsl_user("%s: wildcard lookup 5\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + + if (cr.size != 25) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* + * let's add a fourth cookie (third in cache now we deleted one) + */ + + if (lws_cache_write_through(l1, tag_cookie4, + (const uint8_t *)cookie4, strlen(cookie4), + lws_now_usecs() + LWS_US_PER_SEC * 2, NULL)) { + lwsl_err("%s: write4 failed\n", __func__); + goto cdone; + } + + /* + * for /yy and any cookie, we expect only c3 + */ + + lwsl_user("%s: wildcard lookup 6\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/yy|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + + if (cr.size != 25) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* + * for /yyy and any cookie, we expect c3 and c4 + */ + + lwsl_user("%s: wildcard lookup 7\n", __func__); + + n = lws_cache_lookup(l1, "host.com|/yyy|*", + (const void **)&cr.ptr, &cr.size); + if (n) { + lwsl_err("%s: lookup failed %d\n", __func__, n); + goto cdone; + } + + if (cr.size != 57) + goto cdone; + + while (!lws_cache_results_walk(&cr)) + lwsl_notice(" %s (%d)\n", (const char *)cr.tag, + (int)cr.payload_len); + + /* that's ok then */ + + lwsl_user("%s: done\n", __func__); + + ret = 0; + +cdone: + lws_cache_destroy(&nsc); + lws_cache_destroy(&l1); + + if (ret) + lwsl_warn("%s: fail\n", __func__); + + return ret; +} +#endif + + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; + + lwsl_user("LWS API selftest: lws_cache\n"); + + cx = lws_create_context(&info); + if (!cx) { + lwsl_err("lws init failed\n"); + return 1; + } + + if (test_just_l1()) + fail++; + if (test_just_l1_limits()) + fail++; + +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) + if (test_nsc1()) + fail++; +#endif + + lws_context_destroy(cx); + + if (tests && !fail) + lwsl_user("Completed: PASS\n"); + else + lwsl_err("Completed: FAIL %d / %d\n", fail, tests); + + return 0; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/text1.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/text1.txt new file mode 100644 index 00000000..c4079a20 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_cache/text1.txt @@ -0,0 +1,3 @@ +# Netscape HTTP Cookie File +host.com FALSE / FALSE 1234 mycookie value +host.com FALSE /xxx FALSE 1234 mycookie valuexxx diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_dsh/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_dsh/main.c index 98639dfa..befd490e 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_dsh/main.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_dsh/main.c @@ -91,85 +91,6 @@ test1(void) return 1; } -int -test2(void) -{ - struct lws_dsh *dsh, *dsh2; - lws_dll2_owner_t owner; - uint8_t blob[4096]; - - memset(blob, 0, sizeof(blob)); - - /* - * test 2: multiple dsh, overflow allocation and dynamic destroy - */ - - lws_dll2_owner_clear(&owner); - - dsh = lws_dsh_create(&owner, 4096, 2); - if (!dsh) { - lwsl_err("%s: Failed to create dsh1\n", __func__); - - return 1; - } - - dsh2 = lws_dsh_create(&owner, 4096, 2); - if (!dsh2) { - lwsl_err("%s: Failed to create dsh2\n", __func__); - - goto bail; - } - - if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) { - lwsl_err("%s: Failed to alloc 1\n", __func__); - - goto bail2; - } - - if (lws_dsh_alloc_tail(dsh2, 0, "hello", 5, NULL, 0)) { - lwsl_err("%s: Failed to alloc 2\n", __func__); - - goto bail2; - } - - /* - * We create this logically on dsh. But there's no room for the body. - * It should figure out it can use space on dsh2. - */ - - if (lws_dsh_alloc_tail(dsh, 0, blob, 2000, NULL, 0)) { - lwsl_err("%s: Failed to alloc 3\n", __func__); - - goto bail2; - } - - if (lws_dsh_alloc_tail(dsh2, 0, "hello again", 11, NULL, 0)) { - lwsl_err("%s: Failed to alloc 4\n", __func__); - - goto bail2; - } - - /* - * When we destroy dsh2 it will try to migrate out the 2000 allocation - * from there but find there is no space in dsh1. It should handle it - * by logicalling dropping the object. - */ - - lws_dsh_destroy(&dsh2); - lws_dsh_destroy(&dsh); - - return 0; - -bail2: - lws_dsh_destroy(&dsh2); - -bail: - lws_dsh_destroy(&dsh); - - return 1; - -} - int test3(void) { @@ -431,10 +352,6 @@ int main(int argc, const char **argv) lwsl_user("%s: test1: %d\n", __func__, n); ret |= n; - n = test2(); - lwsl_user("%s: test2: %d\n", __func__, n); - ret |= n; - n = test3(); lwsl_user("%s: test3: %d\n", __func__, n); ret |= n; diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_map/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_map/CMakeLists.txt new file mode 100644 index 00000000..897042c7 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_map/CMakeLists.txt @@ -0,0 +1,17 @@ +project(lws-api-test-lws_map C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) + + + add_executable(${PROJECT_NAME} main.c) + add_test(NAME api-test-lws_map COMMAND lws-api-test-lws_map) + + 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() + diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_map/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_map/main.c new file mode 100644 index 00000000..c17be818 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_map/main.c @@ -0,0 +1,266 @@ +/* + * lws-api-test-lws_map + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * unit tests for lws_map + */ + +#include + +typedef struct lws_map_item lws_map_item_t; + +/* custom key and comparator for test 3 */ + +typedef struct mykey { + int key; +} mykey_t; + +static int +compare_mykey_t(const lws_map_key_t key1, size_t kl1, + const lws_map_value_t key2, size_t kl2) +{ + const mykey_t *m1 = (mykey_t *)key1, *m2 = (mykey_t *)key2; + + return m1->key != m2->key; +} + +int main(int argc, const char **argv) +{ + int e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, + expected = 4, pass = 0; + mykey_t k1 = { .key = 123 }, k2 = { .key = 234 }, k3 = { .key = 999 }; + struct lwsac *ac = NULL; + lws_map_item_t *item; + lws_map_info_t info; + lws_map_t *map; + 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_map\n"); + + /* Test 1: string keys */ + + lwsl_user("%s: test1\n", __func__); + memset(&info, 0, sizeof(info)); + map = lws_map_create(&info); + if (!map) { + e++; + goto end_t1; + } + if (!lws_map_item_create_ks(map, "abc", (lws_map_value_t)"def", 3)) { + e++; + goto end_t1; + } + if (!lws_map_item_create_ks(map, "123", (lws_map_value_t)"4567", 4)) { + e++; + goto end_t1; + } + item = lws_map_item_lookup_ks(map, "abc"); + if (!item) { + e++; + goto end_t1; + } + + if (lws_map_item_value_len(item) != 3 || + memcmp(lws_map_item_value(item), "def", 3)) { + e++; + goto end_t1; + } + + item = lws_map_item_lookup_ks(map, "123"); + if (!item) { + e++; + goto end_t1; + } + + if (lws_map_item_value_len(item) != 4 || + memcmp(lws_map_item_value(item), "4567", 4)) { + e++; + goto end_t1; + } + + item = lws_map_item_lookup_ks(map, "nope"); + if (item) { + e++; + goto end_t1; + } + + pass++; + +end_t1: + lws_map_destroy(&map); + + /* Test 2: Use lwsac item allocators */ + + lwsl_user("%s: test2\n", __func__); + memset(&info, 0, sizeof(info)); + info._alloc = lws_map_alloc_lwsac; + info._free = lws_map_free_lwsac; + info.opaque = (void *)∾ + + map = lws_map_create(&info); + if (!map) { + e++; + goto end_t2; + } + if (!lws_map_item_create_ks(map, "abc", "def", 3)) { + e++; + goto end_t2; + } + if (!lws_map_item_create_ks(map, "123", "4567", 4)) { + e++; + goto end_t2; + } + item = lws_map_item_lookup_ks(map, "abc"); + if (!item) { + e++; + goto end_t2; + } + + if (lws_map_item_value_len(item) != 3 || + memcmp(lws_map_item_value(item), "def", 3)) { + e++; + goto end_t2; + } + + item = lws_map_item_lookup_ks(map, "123"); + if (!item) { + e++; + goto end_t2; + } + + if (lws_map_item_value_len(item) != 4 || + memcmp(lws_map_item_value(item), "4567", 4)) { + e++; + goto end_t2; + } + + item = lws_map_item_lookup_ks(map, "nope"); + if (item) { + e++; + goto end_t2; + } + + pass++; + +end_t2: + lws_map_destroy(&map); + lwsac_free(&ac); + + /* Test 3: custom key object and comparator */ + + lwsl_user("%s: test3\n", __func__); + memset(&info, 0, sizeof(info)); + info._compare = compare_mykey_t; + + map = lws_map_create(&info); + if (!map) { + e++; + goto end_t3; + } + if (!lws_map_item_create(map, (lws_map_key_t)&k1, sizeof(k1), + (lws_map_value_t)"def", 3)) { + lwsl_err("%s: t3; a\n", __func__); + e++; + goto end_t3; + } + if (!lws_map_item_create(map, (lws_map_key_t)&k2, sizeof(k2), + (lws_map_value_t)"4567", 4)) { + lwsl_err("%s: t3; b\n", __func__); + e++; + goto end_t3; + } + item = lws_map_item_lookup(map, (lws_map_key_t)&k1, sizeof(k1)); + if (!item) { + lwsl_err("%s: t3; c\n", __func__); + e++; + goto end_t3; + } + + if (lws_map_item_value_len(item) != 3 || + memcmp(lws_map_item_value(item), "def", 3)) { + lwsl_err("%s: t3; d\n", __func__); + e++; + goto end_t3; + } + + item = lws_map_item_lookup(map, (lws_map_key_t)&k2, sizeof(k2)); + if (!item) { + lwsl_err("%s: t3; e\n", __func__); + e++; + goto end_t3; + } + + if (lws_map_item_value_len(item) != 4 || + memcmp(lws_map_item_value(item), "4567", 4)) { + lwsl_err("%s: t3; f\n", __func__); + e++; + goto end_t3; + } + + item = lws_map_item_lookup(map, (lws_map_key_t)&k3, sizeof(k3)); + if (item) { + lwsl_err("%s: t3; g\n", __func__); + e++; + goto end_t3; + } + + pass++; + +end_t3: + lws_map_destroy(&map); + + /* Test 4: same key items */ + + lwsl_user("%s: test4\n", __func__); + memset(&info, 0, sizeof(info)); + map = lws_map_create(&info); + if (!map) { + e++; + goto end_t4; + } + if (!lws_map_item_create_ks(map, "abc", (lws_map_value_t)"def", 3)) { + e++; + goto end_t4; + } + if (!lws_map_item_create_ks(map, "abc", (lws_map_value_t)"4567", 4)) { + e++; + goto end_t4; + } + item = lws_map_item_lookup_ks(map, "abc"); + if (!item) { + e++; + goto end_t4; + } + + if (lws_map_item_value_len(item) != 4 || + memcmp(lws_map_item_value(item), "4567", 4)) { + e++; + goto end_t4; + } + + pass++; + +end_t4: + lws_map_destroy(&map); + + if (e) + goto bail; + + lwsl_user("Completed: PASS %d / %d\n", pass, expected); + + return 0; + +bail: + lwsl_user("Completed: FAIL, passed %d / %d (e %d)\n", pass, + expected, e); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/main.c index 5bedb283..0db7f400 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/main.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_sequencer/main.c @@ -169,8 +169,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static const struct lws_protocols protocols[] = { - { "seq-test-http", callback_http, 0, 0, }, - { NULL, NULL, 0, 0 } + { "seq-test-http", callback_http, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; @@ -218,7 +218,7 @@ sequencer_start_client(struct myseq *s) /* we couldn't even get started with the client connection */ lws_seq_queue_event(lws_seq_from_user(s), - SEQ_MSG_CLIENT_FAILED, NULL, NULL); + (lws_seq_events_t)SEQ_MSG_CLIENT_FAILED, NULL, NULL); return 1; } diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt index b4d157d3..e2827064 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt @@ -8,6 +8,7 @@ include(LwsCheckRequirements) set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_WITH_SYS_SMD 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${PROJECT_NAME} main.c) diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/main.c index 9e2510fa..b3f8bd5e 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/main.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_smd/main.c @@ -181,7 +181,8 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, int main(int argc, const char **argv) { - lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + 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; diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_tokenize/main.c index 073bdb0b..b9bbcea9 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -322,6 +322,8 @@ static const char *exp_inp1 = "this-is-a-${test}-for-strexp"; int main(int argc, const char **argv) { + struct lws_context_creation_info info; + struct lws_context *cx; struct lws_tokenize ts; lws_tokenize_elem e; const char *p; @@ -344,6 +346,41 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "-f"))) flags = atoi(p); + + memset(&info, 0, sizeof info); + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | + LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW; + + /* + * 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 + * have to use the default allocations for fd tables up to ulimit -n. + * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we + * will use. + */ + info.fd_limit_per_thread = 1 + 1 + 1; + +#if 0 +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) + /* + * OpenSSL uses the system trust store. mbedTLS has to be told which + * CA to trust explicitly. + */ + info.client_ssl_ca_filepath = "./warmcat.com.cer"; +#endif +#endif +#if 0 + n = open("./warmcat.com.cer", O_RDONLY); + if (n >= 0) { + info.client_ssl_ca_mem_len = read(n, memcert, sizeof(memcert)); + info.client_ssl_ca_mem = memcert; + close(n); + n = 0; + memcert[info.client_ssl_ca_mem_len++] = '\0'; + } +#endif + cx = lws_create_context(&info); + /* lws_strexp */ { @@ -668,72 +705,75 @@ int main(int argc, const char **argv) } } - if (lws_strcmp_wildcard("allied", 6, "allied")) { + if (lws_strcmp_wildcard("allied", 6, "allied", 6)) { lwsl_user("%s: wc 1 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("a*", 2, "allied")) { + if (lws_strcmp_wildcard("a*", 2, "allied", 6)) { lwsl_user("%s: wc 2 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("all*", 4, "allied")) { + if (lws_strcmp_wildcard("all*", 4, "allied", 6)) { lwsl_user("%s: wc 3 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("all*d", 5, "allied")) { + if (lws_strcmp_wildcard("all*d", 5, "allied", 6)) { lwsl_user("%s: wc 4 fail\n", __func__); fail++; } - if (!lws_strcmp_wildcard("b*", 2, "allied")) { + if (!lws_strcmp_wildcard("b*", 2, "allied", 6)) { lwsl_user("%s: wc 5 fail\n", __func__); fail++; } - if (!lws_strcmp_wildcard("b*ed", 4, "allied")) { + if (!lws_strcmp_wildcard("b*ed", 4, "allied", 6)) { lwsl_user("%s: wc 6 fail\n", __func__); fail++; } - if (!lws_strcmp_wildcard("allie", 5, "allied")) { + if (!lws_strcmp_wildcard("allie", 5, "allied", 6)) { lwsl_user("%s: wc 7 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("allie*", 6, "allied")) { + if (lws_strcmp_wildcard("allie*", 6, "allied", 6)) { lwsl_user("%s: wc 8 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("*llie*", 6, "allied")) { + if (lws_strcmp_wildcard("*llie*", 6, "allied", 6)) { lwsl_user("%s: wc 9 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("*llied", 6, "allied")) { + if (lws_strcmp_wildcard("*llied", 6, "allied", 6)) { lwsl_user("%s: wc 10 fail\n", __func__); fail++; } - if (!lws_strcmp_wildcard("*llie", 5, "allied")) { + if (!lws_strcmp_wildcard("*llie", 5, "allied", 6)) { lwsl_user("%s: wc 11 fail\n", __func__); fail++; } - if (!lws_strcmp_wildcard("*nope", 5, "allied")) { + if (!lws_strcmp_wildcard("*nope", 5, "allied", 6)) { lwsl_user("%s: wc 12 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("*li*", 4, "allied")) { + if (lws_strcmp_wildcard("*li*", 4, "allied", 6)) { lwsl_user("%s: wc 13 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("*", 1, "allied")) { + if (lws_strcmp_wildcard("*", 1, "allied", 6)) { lwsl_user("%s: wc 14 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("*abc*d", 6, "xxabyyabcdd")) { + if (lws_strcmp_wildcard("*abc*d", 6, "xxabyyabcdd", 11)) { lwsl_user("%s: wc 15 fail\n", __func__); fail++; } - if (lws_strcmp_wildcard("ssproxy.n.cn.*", 14, "ssproxy.n.cn.failures")) { + if (lws_strcmp_wildcard("ssproxy.n.cn.*", 14, + "ssproxy.n.cn.failures", 21)) { lwsl_user("%s: wc 16 fail\n", __func__); fail++; } lwsl_user("Completed: PASS: %d, FAIL: %d\n", ok, fail); + lws_context_destroy(cx); + return !(ok && !fail); } diff --git a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-secure-streams/main.c b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-secure-streams/main.c index 8becb676..841cd1a9 100644 --- a/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-secure-streams/main.c +++ b/3rdparty/libwebsockets/minimal-examples/api-tests/api-test-secure-streams/main.c @@ -183,11 +183,11 @@ myss_tx_post(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, *len = budget; m->sent += budget; if (m->sent != next_test->send) - lws_ss_request_tx(m->ss); - else - *flags |= LWSSS_FLAG_EOM; + return lws_ss_request_tx(m->ss); - return 0; + *flags |= LWSSS_FLAG_EOM; + + return LWSSSSRET_OK; } static lws_ss_state_return_t @@ -195,15 +195,18 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { myss_t *m = (myss_t *)userobj; + lws_ss_state_return_t r; lwsl_notice("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name((int)state), (unsigned int)ack); switch (state) { case LWSSSCS_CREATING: - lws_ss_client_connect(m->ss); + r = lws_ss_client_connect(m->ss); + if (r) + return r; if (next_test->send) - lws_ss_request_tx_len(m->ss, (unsigned long)next_test->send); + return lws_ss_request_tx_len(m->ss, (unsigned long)next_test->send); break; case LWSSSCS_ALL_RETRIES_FAILED: lwsl_notice("%s: Connection failed\n", __func__); @@ -258,7 +261,7 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, break; } - return 0; + return LWSSSSRET_OK; } static const lws_ss_info_t ssi_get = { diff --git a/3rdparty/libwebsockets/minimal-examples/client-server/minimal-ws-proxy/minimal-ws-proxy.c b/3rdparty/libwebsockets/minimal-examples/client-server/minimal-ws-proxy/minimal-ws-proxy.c index 4bb5a3e5..e304c618 100644 --- a/3rdparty/libwebsockets/minimal-examples/client-server/minimal-ws-proxy/minimal-ws-proxy.c +++ b/3rdparty/libwebsockets/minimal-examples/client-server/minimal-ws-proxy/minimal-ws-proxy.c @@ -24,9 +24,10 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0}, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/CMakeLists.txt new file mode 100644 index 00000000..6ee78ae9 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/CMakeLists.txt @@ -0,0 +1,55 @@ +project(lws-crypto-cose-key C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-crypto-cose-key) +set(SRCS main.c) + +set(requirements 1) +require_lws_config(LWS_WITH_COSE 1 requirements) + +if (requirements) + + add_executable(${SAMP} ${SRCS}) + + add_test(NAME crypto-cose-key-1 + COMMAND lws-crypto-cose-key --stdin set1.cks ) + add_test(NAME crypto-cose-key-2 + COMMAND lws-crypto-cose-key --kty EC2 --curve P-256 --kid ctest-256 --stdout ctest-ec-256.key) + add_test(NAME crypto-cose-key-3 + COMMAND lws-crypto-cose-key --kty EC2 --curve P-384 --kid ctest-384 --stdout ctest-ec-384.key) + add_test(NAME crypto-cose-key-4 + COMMAND lws-crypto-cose-key --kty EC2 --curve P-521 --kid ctest-512 --stdout ctest-ec-512.key) + add_test(NAME crypto-cose-key-5 + COMMAND lws-crypto-cose-key --kty SYMMETRIC --bits 256 --stdout ctest-sym-256.key) + add_test(NAME crypto-cose-key-6 + COMMAND lws-crypto-cose-key --kty RSA --bits 2048 --stdout ctest-rsa-2048.key) + add_test(NAME crypto-cose-key-7 + COMMAND lws-crypto-cose-key --stdin ctest-rsa-2048.key) + + set_tests_properties(crypto-cose-key-1 + crypto-cose-key-2 + crypto-cose-key-3 + crypto-cose-key-4 + crypto-cose-key-5 + crypto-cose-key-6 + crypto-cose-key-7 + PROPERTIES + WORKING_DIRECTORY + ${CMAKE_SOURCE_DIR}/minimal-examples/crypto/minimal-crypto-cose-key + TIMEOUT 5) + + set_tests_properties(crypto-cose-key-7 + PROPERTIES + DEPENDS crypto-cose-key-6) + + 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 --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/README.md b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/README.md new file mode 100644 index 00000000..f6be13db --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/README.md @@ -0,0 +1,132 @@ +# lws minimal example for cose_key + +Demonstrates how to create and dump cose_keys. + +## Dump key or key_set + +Pipe a cose_key or cose_key_set into stdin to get a textual dump of all the keys +inside. You can optionally use --kid kid or --kid-hex HEXSTRING to dump one key +from a set. + +``` +$ cat set1.cks | ./bin/lws-crypto-cose-key +$ cat set1.cks | ./bin/lws-crypto-cose-key --kid 11 +``` + +## Create keys + +Stdin is not used, give parameters for the kty and kid etc to create a +new key on stdout (which can be redirected to a file). + +``` +$ ./bin/lws-crypto-cose-key --kty EC2 --curve P-521 --kid sec512 >ec512.key +``` + +## build + +``` + $ cmake . && make +``` + +## usage + +|Option|Meaning| +|---|---| +|--kty type|Key type, one of OKP, EC2, RSA or SYMMETRIC| +|-k \|One or a set of cose_keys| +|--kid string|Specifies the key ID to use as a string| +|--kid-hex HEXSTRING|Specifies the key ID to use as a hex blob| +|--curve curve|For EC type key creation, specify the curve| +|--stdin filepath|Makes tool fetch from filepath instead of stdin (useful for CI)| +|--stdout filepath|Makes tool write to filepath instead of stdout (useful for CI)| + + +HEXSTRING above means a string like `1a2b3c` + +## Examples + +### cose_key dumping + +``` +$ cat set1.cks | ./bin/lws-crypto-cose-key +[2021/07/30 10:14:31:0420] U: LWS cose-key example tool -k keyset [-s alg-name kid ] +[2021/07/30 10:14:31:0780] N: lws_create_context: LWS: 4.2.99-v4.2.0-134-g8433c8b459, NET CLI SRV H1 H2 WS ConMon IPV6-on +[2021/07/30 10:14:31:0892] N: ++ [wsi|0|pipe] (1) +[2021/07/30 10:14:31:0926] N: ++ [vh|0|netlink] (1) +[2021/07/30 10:14:31:0977] N: ++ [vh|1|default||-1] (2) +[2021/07/30 10:14:31:1057] N: main: importing +Cose key #1 + kty: EC2 + kid: 11 + kty: P-256 + x: bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff + d: 57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3 + y: 20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e +Cose key #2 + kty: EC2 + kid: meriadoc.brandybuck@buckland.example + kty: P-256 + x: 65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d + d: aff907c99f9ad3aae6c4cdf21122bce2bd68b5283e6907154ad911840fa208cf + y: 1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c +Cose key #3 + kty: SYMMETRIC + kid: our-secret + k: 849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188 +Cose key #4 + kty: EC2 + kid: bilbo.baggins@hobbiton.example + kty: P-521 + x: 0072992cb3ac08ecf3e5c63dedec0d51a8c1f79ef2f82f94f3c737bf5de7986671eac625fe8257bbd0394644caaa3aaf8f27a4585fbbcad0f2457620085e5c8f42ad + d: 00085138ddabf5ca975f5860f91a08e91d6d5f9a76ad4018766a476680b55cd339e8ab6c72b5facdb2a2a50ac25bd086647dd3e2e6e99e84ca2c3609fdf177feb26d + y: 01dca6947bce88bc5790485ac97427342bc35f887d86d65a089377e247e60baa55e4e8501e2ada5724ac51d6909008033ebc10ac999b9d7f5cc2519f3fe1ea1d9475 +Cose key #5 + kty: SYMMETRIC + kid: our-secret2 + k: 849b5786457c1491be3a76dcea6c4271 +Cose key #6 + kty: EC2 + kid: peregrin.took@tuckborough.example + kty: P-256 + x: 98f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91d6280 + d: 02d1f7e6f26c43d4868d87ceb2353161740aacf1f7163647984b522a848df1c3 + y: f01400b089867804b8e9fc96c3932161f1934f4223069170d924b7e03bf822bb +Cose key #7 + kty: SYMMETRIC + kid: 018c0ae5-4d9b-471b-bfd6-eef314bc7037 + use: 849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188 +Cose key #8 + kty: SYMMETRIC + kid: sec-48 + k: 849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c42718800112233778899aa2122232425262728 +Cose key #9 + kty: SYMMETRIC + kid: sec-64 + k: 849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c42718800112233778899aa2122232425262728aabbccddeeffa5a6a7a8a9a0b1b2b3b4 +Cose key #10 + kty: EC2 + kid: sec384 + kty: P-384 + x: ea2866349fe3a2f9ad4d6bfe7c30c527436e901c5fb22210b67b2150574ffcd0b1dd8c43d5d1e3d5cb849ecec202117c + d: 4d46a58480d43d5454307edcf501e098ef7c0186cc6b56b41dfd13fe4b9b1ab1425851cf5b23e6636ed18f5bbdde1896 + y: 4c3d245515a688ef25ff68034089ca4f10a01bef51cc57309f12919c3d484142368795c6f2a5d30af650b4e12d0133e4 +Cose key #11 + kty: EC2 + kid: sec512 + kty: P-521 + x: 003b81ed66d8a2194b42f29ecb2c9ae48199be695924804a8407194ed0e172f39693f870f32463e2d36950034a21901487c5a0c43a1713a818fb89fa8a5b3b2dc181 + d: 013e0f06ce394ac14a3df3953fc560679ad0dee14779ef0d475787451fca71e3b4b827b6f7cedcf00e23c716fb829b5419234ba5c92c33e0bc94351fe97be21f2b82 + y: 004b9b6b0adf41913b5d700cf43bfe0ee8b79eb58fc308509e574fcb910b3fd5a2ad585affc6776f7fc9d4ff48f5923fe900660ecc6e3720f89c1363eecfffb38b5b +[2021/07/30 10:14:31:1430] N: -- [wsi|0|pipe] (0) 52.763ms +[2021/07/30 10:14:31:1441] N: -- [vh|0|netlink] (1) 51.437ms +[2021/07/30 10:14:31:1491] N: -- [vh|1|default||-1] (0) 51.591ms +[2021/07/30 10:14:31:1536] N: main: PASS + +``` + +### cose_key creation + +``` +$ ./bin/lws-crypto-cose-key --kty EC2 --curve P-521 --kid sec512 >ec512.key +``` + diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/main.c b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/main.c new file mode 100644 index 00000000..5a19e2c8 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/main.c @@ -0,0 +1,313 @@ +/* + * lws-minimal-crypto-cose-key + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include +#include +#include +#include +#include + +static int fdin = 0, fdout = 1; + +static const char *meta_names[] = { + "kty", "kid", "use", "key_ops", "base_iv", "alg" +}; + +static const char *oct_names[] = { + "k" +}; + +static const char *rsa_names[] = { + "e", "n", "d", "p", "q", "dp", "dq", "qi", "other", "ri", "di", "ti" +}; + +static const char *ec_names[] = { + "crv", "x", "d", "y", +}; + +static void +cose_key_dump(const struct lws_cose_key *ck) +{ + const char **enames; + char hex[2048], dump[3072]; + int elems; + size_t l; + int n; + + (void)enames; + (void)meta_names; + + switch (ck->gencrypto_kty) { + + case LWS_GENCRYPTO_KTY_OCT: + elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT; + enames = oct_names; + break; + case LWS_GENCRYPTO_KTY_RSA: + elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT; + enames = rsa_names; + break; + case LWS_GENCRYPTO_KTY_EC: + elems = LWS_GENCRYPTO_EC_KEYEL_COUNT; + enames = ec_names; + break; + + default: + lwsl_err("%s: jwk %p: unknown type\n", __func__, ck); + + return; + } + + for (n = 0; n < LWS_COUNT_COSE_KEY_ELEMENTS; n++) { + if (ck->meta[n].buf) { + if (n < 2) { + l = (size_t)lws_snprintf(dump, sizeof(dump), + " %s: %.*s\n", meta_names[n], + (int)ck->meta[n].len, + ck->meta[n].buf); + write(fdout, dump, l); + } else { + l = (size_t)lws_snprintf(dump, sizeof(dump), + " %s: ", meta_names[n]); + write(fdout, dump, l); + lws_hex_from_byte_array(ck->meta[n].buf, + ck->meta[n].len, + hex, sizeof(hex)); + write(fdout, hex, strlen(hex)); + write(fdout, "\n", 1); + } + } + } + + for (n = 0; n < elems; n++) { + if (ck->e[n].buf) { + if (!n && ck->gencrypto_kty == LWS_GENCRYPTO_KTY_EC) { + l = (size_t)lws_snprintf(dump, sizeof(dump), + " %s: %.*s\n", enames[n], + (int)ck->e[n].len, + ck->e[n].buf); + write(fdout, dump, l); + } else { + l = (size_t)lws_snprintf(dump, sizeof(dump), + " %s: ", enames[n]); + write(fdout, dump, l); + lws_hex_from_byte_array(ck->e[n].buf, + ck->e[n].len, + hex, sizeof(hex)); + write(fdout, hex, strlen(hex)); + write(fdout, "\n", 1); + } + } + } +} + +int main(int argc, const char **argv) +{ + uint8_t *kid = NULL, ktmp[4096], set_temp[32 * 1024], temp[256]; + int result = 1, bits = 0, + logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lws_context_creation_info info; + size_t kid_len = 0, stp = 0; + struct lws_context *context; + lws_cose_key_t *ck = NULL; + cose_param_t cose_kty = 0; + lws_dll2_owner_t set; + const char *p, *crv; + lws_lec_pctx_t lec; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + + lwsl_user("LWS cose-key example tool -k keyset [-s alg-name kid ]\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ +#if defined(LWS_WITH_NETWORK) + info.port = CONTEXT_PORT_NO_LISTEN; +#endif + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + if ((p = lws_cmdline_option(argc, argv, "--stdin"))) { + fdin = open(p, LWS_O_RDONLY, 0); + if (fdin < 0) { + lwsl_err("%s: unable to open stdin file\n", __func__); + return 1; + } + } + + if ((p = lws_cmdline_option(argc, argv, "--stdout"))) { + fdout = open(p, LWS_O_WRONLY | LWS_O_CREAT | LWS_O_TRUNC, 0600); + if (fdout < 0) { + lwsl_err("%s: unable to open stdout file\n", __func__); + goto bail_early; + } + } + + if ((p = lws_cmdline_option(argc, argv, "--kid"))) { + kid = (uint8_t *)p; + kid_len = strlen(p); + //lwsl_hexdump_notice(kid, kid_len); + } + + if ((p = lws_cmdline_option(argc, argv, "--kid-hex"))) { + kid_len = (size_t)lws_hex_to_byte_array(p, ktmp, sizeof(ktmp)); + kid = (uint8_t *)ktmp; + } + + /* + * If we have some stdin queued up, we understand we are dumping + * an existing cose_key or key_set from stdin + */ + + if (!fdin) { + struct timeval timeout; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(0, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 1000; + + if (select(fdin + 1, &fds, NULL, NULL, &timeout) < 0) + goto no_stdin; + + if (!FD_ISSET(0, &fds)) + goto no_stdin; + } + + do { + int n = (int)read(fdin, temp, sizeof(temp)); + + if (n < 0) + goto bail; + if (!n) { + int kc = 0; + + if (!stp) + /* there was no stdin */ + break; + + lwsl_notice("%s: importing\n", __func__); + + lws_dll2_owner_clear(&set); + ck = lws_cose_key_import(&set, NULL, NULL, set_temp, stp); + if (!ck) { + lwsl_err("%s: import failed\n", __func__); + goto bail; + } + + lws_start_foreach_dll(struct lws_dll2 *, p, + lws_dll2_get_head(&set)) { + lws_cose_key_t *ck = lws_container_of(p, + lws_cose_key_t, list); + struct lws_gencrypto_keyelem *ke = + &ck->meta[COSEKEY_META_KID]; + + kc++; + + if (!kid_len || (ke->len && + ke->len == (uint32_t)kid_len && + !memcmp(ke->buf, kid, kid_len))) { + printf("Cose key #%d\n", kc); + cose_key_dump(ck); + } + + } lws_end_foreach_dll(p); + + lws_cose_key_set_destroy(&set); + result = 0; + goto bail; + + } + + if (stp + (size_t)n > sizeof(set_temp)) { + lwsl_err("%s: stdin bigger than our buffer\n", __func__); + goto bail; + } + memcpy(set_temp + stp, temp, (size_t)n); + stp += (size_t)n; + } while (1); + +no_stdin: + + /* + * + */ + + p = lws_cmdline_option(argc, argv, "--kty"); + if (!p) { + lwsl_err("%s: use --kty OKP|EC2|RSA|SYMMETRIC\n", + __func__); + goto bail; + } + + if (!strcmp(p, "OKP")) + cose_kty = LWSCOSE_WKKTV_OKP; + if (!strcmp(p, "EC2")) + cose_kty = LWSCOSE_WKKTV_EC2; + if (!strcmp(p, "RSA")) + cose_kty = LWSCOSE_WKKTV_RSA; + if (!strcmp(p, "SYMMETRIC") || !strcmp(p, "SYM")) + cose_kty = LWSCOSE_WKKTV_SYMMETRIC; + + if (!cose_kty) { + lwsl_err("%s: use --kty OKP|EC2|RSA|SYMMETRIC\n", + __func__); + goto bail; + } + + crv = NULL; + if (cose_kty == LWSCOSE_WKKTV_OKP || + cose_kty == LWSCOSE_WKKTV_EC2) { + crv = lws_cmdline_option(argc, argv, "--curve"); + if (!crv) { + lwsl_err("%s: use --curve P-256 etc\n", __func__); + goto bail; + } + } + + p = lws_cmdline_option(argc, argv, "--bits"); + if (p) + bits = atoi(p); + + ck = lws_cose_key_generate(context, cose_kty, 0, bits, crv, + kid, kid_len); + if (!ck) + goto bail; + + lws_lec_init(&lec, ktmp, sizeof(ktmp)); + lws_cose_key_export(ck, &lec, LWSJWKF_EXPORT_PRIVATE); + write(fdout, ktmp, lec.used); + + lws_cose_key_destroy(&ck); + result = 0; + +bail: + lws_context_destroy(context); + + if (result) + lwsl_err("%s: FAIL: %d\n", __func__, result); + else + lwsl_notice("%s: PASS\n", __func__); + +bail_early: + if (fdin > 0) + close(fdin); + if (fdout != 1 && fdout >= 0) + close(fdout); + + return result; +} diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/set1.cks b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/set1.cks new file mode 100644 index 00000000..e5eca18e Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/set1.cks differ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass01.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass01.sig new file mode 100644 index 00000000..d78767e6 Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass01.sig differ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass02.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass02.sig new file mode 100644 index 00000000..2b53930d --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass02.sig @@ -0,0 +1 @@ +Ò„C¡&¡B11TThis is the content.X@rœ×Ë8ØØéD¨Úqç²XɽÊa5÷®Ûî• ‰gƒ~3½6ÁP2jæ'UƽŽT >’×Ò%èÛr¸‚ \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass03.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass03.sig new file mode 100644 index 00000000..a10fc966 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign1_pass03.sig @@ -0,0 +1 @@ +„C¡&¡B11TThis is the content.X@޳>L£FZ°Z¬4Ìk#Õï\1ÄÒZ‘®ð°~*ù¢‘ª2áJ¸4ÜVí*"4DT~ñ; å¤ÃEÊË6 \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass01.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass01.sig new file mode 100644 index 00000000..268b0861 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass01.sig @@ -0,0 +1 @@ +Øb„A  TThis is the content.ƒC¡&¡B11X@â®¯Ô iÑþnR|]ôä(,¾û]Ëô¯.Ù‚¬E¬˜¸TL‹EÞ·ÃÓHþ’j+˜õ:ý/ ó diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass02.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass02.sig new file mode 100644 index 00000000..b80f7a26 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass02.sig @@ -0,0 +1 @@ +Øb„@ TThis is the content.ƒC¡&¡B11X@˸ÚÙ¾¯¸á¤M‹ûÂkíò©OËZˆ$2¿öÖ>õtQØ?¢Ëö&rëôÇÙ“°ôÂDvGØ1ºW̨k“ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass03.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass03.sig new file mode 100644 index 00000000..60d8f039 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/sign_pass03.sig @@ -0,0 +1 @@ +„@ TThis is the content.ƒC¡&¡B11X@â®¯Ô iÑþnR|]ôä(,¾û]Ëô¯.Ù‚¬E¬˜¸TL‹EÞ·ÃÓHþ’j+˜õ:ý/ ó diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/CMakeLists.txt new file mode 100644 index 00000000..b49b4173 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/CMakeLists.txt @@ -0,0 +1,219 @@ +project(lws-crypto-cose-sign C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-crypto-cose-sign) +set(SRCS main.c) + +set(requirements 1) +require_lws_config(LWS_WITH_COSE 1 requirements) + +if (requirements) + + add_executable(${SAMP} ${SRCS}) + + # EC signing + + add_test(NAME crypto-cose-sign-1 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid 11 + --alg ES256 --cose-sign + --stdin payload.txt + --stdout ctest-sig-es256.sig) + add_test(NAME crypto-cose-sign-2 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid sec384 + --alg ES384 --cose-sign + --stdin payload.txt + --stdout ctest-sig-es384.sig) + add_test(NAME crypto-cose-sign-3 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid sec512 + --alg ES512 --cose-sign + --stdin payload.txt + --stdout ctest-sig-es512.sig) + + # EC validation + + add_test(NAME crypto-cose-sign-4 + COMMAND lws-crypto-cose-sign -k set1.cks + --stdout r1.txt + --stdin ctest-sig-es256.sig) + set_tests_properties(crypto-cose-sign-4 PROPERTIES + DEPENDS crypto-cose-sign-1) + + add_test(NAME crypto-cose-sign-5 + COMMAND lws-crypto-cose-sign -k set1.cks + --stdout r2.txt + --stdin ctest-sig-es384.sig) + set_tests_properties(crypto-cose-sign-5 PROPERTIES + DEPENDS crypto-cose-sign-2) + + add_test(NAME crypto-cose-sign-6 + COMMAND lws-crypto-cose-sign -k set1.cks --cose-sign + --stdout r3.txt + --stdin ctest-sig-es512.sig) + set_tests_properties(crypto-cose-sign-6 PROPERTIES + DEPENDS crypto-cose-sign-3) + + # RSA 4096 signing + + add_test(NAME crypto-cose-sign-7 + COMMAND lws-crypto-cose-sign -s -k rsa-4096.ck + --alg RS512 --cose-sign + --stdin payload.txt + --stdout ctest-sig-rs512.sig) + + # RSA 4096 validation + + add_test(NAME crypto-cose-sign-8 + COMMAND lws-crypto-cose-sign -k rsa-4096.ck --cose-sign + --stdout r8.txt + --stdin ctest-sig-rs512.sig) + set_tests_properties(crypto-cose-sign-8 PROPERTIES + DEPENDS crypto-cose-sign-7) + + # HMAC signing, cose-mac + +# add_test(NAME crypto-cose-sign-9 +# COMMAND lws-crypto-cose-sign -s -k set1.cks --kid our-secret +# --alg HS256 --cose-mac +# --stdin payload.txt +# --stdout ctest-sig-hmac256.sig) +# add_test(NAME crypto-cose-sign-10 +# COMMAND lws-crypto-cose-sign -s -k set1.cks --kid sec-48 +# --alg HS384 --cose-mac +# --stdin payload.txt +# --stdout ctest-sig-hmac384.sig) +# add_test(NAME crypto-cose-sign-11 +# COMMAND lws-crypto-cose-sign -s -k set1.cks --kid sec-64 +# --alg HS512 --cose-mac +# --stdin payload.txt +# --stdout ctest-sig-hmac512.sig) +# add_test(NAME crypto-cose-sign-12 +# COMMAND lws-crypto-cose-sign -s -k set1.cks --kid our-secret +# --alg HS256_64 --cose-mac +# --stdin payload.txt +# --stdout ctest-sig-hmac256_64.sig) + + # HMAC validation, cose-mac + +# add_test(NAME crypto-cose-sign-13 +# COMMAND lws-crypto-cose-sign -k set1.cks +# --stdout r1.txt +# --stdin ctest-sig-hmac256.sig) +# set_tests_properties(crypto-cose-sign-13 +# PROPERTIES DEPENDS crypto-cose-sign-9) +# +# add_test(NAME crypto-cose-sign-14 +# COMMAND lws-crypto-cose-sign -k set1.cks +# --stdout r2.txt +# --stdin ctest-sig-hmac384.sig) +# set_tests_properties(crypto-cose-sign-14 +# PROPERTIES DEPENDS crypto-cose-sign-10) +# +# add_test(NAME crypto-cose-sign-15 +# COMMAND lws-crypto-cose-sign -k set1.cks +# --stdout r3.txt +# --stdin ctest-sig-hmac512.sig) +# set_tests_properties(crypto-cose-sign-15 +# PROPERTIES DEPENDS crypto-cose-sign-11) +# +# add_test(NAME crypto-cose-sign-16 +# COMMAND lws-crypto-cose-sign -k set1.cks +# --stdout r4.txt +# --stdin ctest-sig-hmac256_64.sig) +# set_tests_properties(crypto-cose-sign-16 +# PROPERTIES DEPENDS crypto-cose-sign-12) + + # HMAC signing, cose-mac0 + + add_test(NAME crypto-cose-sign-17 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid our-secret + --alg HS256 --cose-mac0 + --stdin payload.txt + --stdout ctest-sig-hmac0256.sig) + add_test(NAME crypto-cose-sign-18 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid sec-48 + --alg HS384 --cose-mac0 + --stdin payload.txt + --stdout ctest-sig-hmac0384.sig) + add_test(NAME crypto-cose-sign-19 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid sec-64 + --alg HS512 --cose-mac0 + --stdin payload.txt + --stdout ctest-sig-hmac0512.sig) + add_test(NAME crypto-cose-sign-20 + COMMAND lws-crypto-cose-sign -s -k set1.cks --kid our-secret + --alg HS256_64 --cose-mac0 + --stdin payload.txt + --stdout ctest-sig-hmac0256_64.sig) + + # HMAC validation, cose-mac0 + + add_test(NAME crypto-cose-sign-21 + COMMAND lws-crypto-cose-sign -k set1.cks + --stdout r1.txt + --stdin ctest-sig-hmac0256.sig) + set_tests_properties(crypto-cose-sign-21 + PROPERTIES DEPENDS crypto-cose-sign-17) + + add_test(NAME crypto-cose-sign-22 + COMMAND lws-crypto-cose-sign -k set1.cks + --stdout r2.txt + --stdin ctest-sig-hmac0384.sig) + set_tests_properties(crypto-cose-sign-22 + PROPERTIES DEPENDS crypto-cose-sign-18) + + add_test(NAME crypto-cose-sign-23 + COMMAND lws-crypto-cose-sign -k set1.cks + --stdout r3.txt + --stdin ctest-sig-hmac0512.sig) + set_tests_properties(crypto-cose-sign-23 + PROPERTIES DEPENDS crypto-cose-sign-19) + + add_test(NAME crypto-cose-sign-24 + COMMAND lws-crypto-cose-sign -k set1.cks + --stdout r4.txt + --stdin ctest-sig-hmac0256_64.sig) + set_tests_properties(crypto-cose-sign-24 + PROPERTIES DEPENDS crypto-cose-sign-20) + + + set_tests_properties(crypto-cose-sign-1 + crypto-cose-sign-2 + crypto-cose-sign-3 + crypto-cose-sign-4 + crypto-cose-sign-5 + crypto-cose-sign-6 + crypto-cose-sign-7 + crypto-cose-sign-8 +# crypto-cose-sign-9 +# crypto-cose-sign-10 +# crypto-cose-sign-11 +# crypto-cose-sign-12 +# crypto-cose-sign-13 +# crypto-cose-sign-14 +# crypto-cose-sign-15 +# crypto-cose-sign-16 + crypto-cose-sign-17 + crypto-cose-sign-18 + crypto-cose-sign-19 + crypto-cose-sign-20 + crypto-cose-sign-21 + crypto-cose-sign-22 + crypto-cose-sign-23 + crypto-cose-sign-24 + + PROPERTIES + WORKING_DIRECTORY + ${CMAKE_SOURCE_DIR}/minimal-examples/crypto/minimal-crypto-cose-sign + TIMEOUT 5) + + 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 --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/README.md b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/README.md new file mode 100644 index 00000000..f241d75e --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/README.md @@ -0,0 +1,105 @@ +# lws minimal example for cose_sign + +Demonstrates how to sign and verify using cose_sign and cose_key, providing a +commandline tool for signing and verifying stdin. + +## build + +``` + $ cmake . && make +``` + +## usage + +|Option|Sig|Val|Meaning| +|---|---|---|---| +|-s|o|||Select signing mode (stdin is payload)| +|-k |o|o|One or a set of cose_keys| +|--kid string|o|mac0|Specifies the key ID to use as a string| +|--kid-hex HEXSTRING|o|mac0|Specifies the key ID to use as a hex blob| +|--cose-sign|o|if no tag|Sets cose-sign mode| +|--cose-sign1|o|if no tag|Sets cose-sign1 mode| +|--cose-mac|o|if no tag|Sets cose-sign1 mode| +|--cose-mac0|o|if no tag|Sets cose-sign1 mode| +|--extra HEXSTRING|o|o|Optional extra payload data| + +HEXSTRING above means a string like `1a2b3c` + +Stdin is either the plaintext (if signing) or cose_sign (if verifying). + +For convenience, a keyset from the COSE RFC is provided in +`minimal-examples/crypto/minimal-crypto-cose-sign/set1.cks`. Six example +cose_sign1 and cose_sign are also provided in that directory signed with keys +from the provided keyset. + +## Examples + +### Validation + +The RFC8152 sign1_pass01.sig is a cose_sign1 that contains the ES256 alg +parameter along with a kid hint that it was signed with the key with kid "11" +from the RFC8152 key set. So we just need to provide the signature and the key +set and lws can sort it out. + +``` +$ cat sign1_pass01.sig | ./lws-crypto-cose-sign -k set1.cks +[2021/07/26 05:41:29:1663] N: lws_create_context: LWS: 4.2.99-v4.2.0-133-g300f3f3250, NET CLI SRV H1 H2 WS ConMon IPV6-on +[2021/07/26 05:41:29:3892] N: results count 1 +[2021/07/26 05:41:29:3901] N: result: 0 (alg ES256, kid 3131) +[2021/07/26 05:41:29:4168] N: main: PASS +``` + +Notice how the validation just delivers a results list and leaves it to the user +code to iterate it, and confirm that it's happy with the result, the alg used, +and the kid that was used. + +RFC8152 sign1_pass02.sig is similar but contains extra application data in the +signature, that must be given at validation too. + +``` +$cat sign1_pass02.sig | ./lws-crypto-cose-sign -k set1.cks --extra 11aa22bb33cc44dd55006699 +[2021/07/26 05:55:50:9103] N: lws_create_context: LWS: 4.2.99-v4.2.0-133-g300f3f3250, NET CLI SRV H1 H2 WS ConMon IPV6-on +[2021/07/26 05:55:50:9381] N: 12 +[2021/07/26 05:55:51:0924] N: +[2021/07/26 05:55:51:0939] N: 0000: 11 AA 22 BB 33 CC 44 DD 55 00 66 99 ..".3.D.U.f. +[2021/07/26 05:55:51:0943] N: +[2021/07/26 05:55:51:1368] N: results count 1 +[2021/07/26 05:55:51:1377] N: result: 0 (alg ES256, kid 3131) +[2021/07/26 05:55:51:1657] N: main: PASS +``` + +### Signing + +Generate a cose-sign1 using ES256 and the key set key with id "11" for the +payload given on stdin + +``` +$ echo -n "This is the content." |\ + ./bin/lws-crypto-cose-sign -s -k set1.cks \ + --kid 11 --alg ES256 > ./test.sig + +00000000 d2 84 43 a1 01 26 a1 04 42 31 31 54 54 68 69 73 |..C..&..B11TThis| +00000010 20 69 73 20 74 68 65 20 63 6f 6e 74 65 6e 74 2e | is the content.| +00000020 58 40 b9 a8 85 09 17 7f 01 f6 78 5d 39 62 d0 44 |X@........x]9b.D| +00000030 08 0b fa b4 b4 5b 17 80 c2 e3 ba a3 af 33 6f e6 |.....[.......3o.| +00000040 44 09 13 1f cf 4f 17 5c 62 9f 8d 29 29 1c ab 28 |D....O.\b..))..(| +00000050 b2 f4 e6 af f9 62 ea 69 52 90 07 0e 2c 40 72 d3 |.....b.iR...,@r.| +00000060 12 cf |..| + +``` + +Same as above, but force it to use cose-sign layout + +``` +$ echo -n "This is the content." |\ + ./bin/lws-crypto-cose-sign -s -k set1.cks \ + --kid 11 --alg ES256 --cose-sign > ./test.sig + +00000000 d8 62 84 40 40 54 54 68 69 73 20 69 73 20 74 68 |.b.@@TThis is th| +00000010 65 20 63 6f 6e 74 65 6e 74 2e 81 83 a1 01 26 a1 |e content.....&.| +00000020 04 42 31 31 58 40 37 5d 93 48 20 b0 d0 75 16 41 |.B11X@7].H ..u.A| +00000030 db 95 95 5b 39 7d 6d 92 6e 52 c9 78 96 d8 a2 9b |...[9}m.nR.x....| +00000040 62 62 89 9e e5 26 31 63 4b 90 d1 37 86 ca 82 a2 |bb...&1cK..7....| +00000050 28 9a d2 82 a7 6d 24 23 cd de 58 91 47 98 bb 11 |(....m$#..X.G...| +00000060 e4 b9 08 18 48 65 |....He| +``` diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/main.c b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/main.c new file mode 100644 index 00000000..c1e8e588 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/main.c @@ -0,0 +1,406 @@ +/* + * lws-minimal-crypto-cose-sign + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include +#include +#include + +static int fdin = 0, fdout = 1; +static uint8_t extra[4096]; +static size_t ext_len; + +int +_alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, + size_t *amount) +{ + FILE *f; + size_t s; + ssize_t m; + int n = 0; + + f = fopen(filename, "rb"); + if (f == NULL) { + n = 1; + goto bail; + } + + if (fseek(f, 0, SEEK_END) != 0) { + n = 1; + goto bail; + } + + m = ftell(f); + if (m == -1l) { + n = 1; + goto bail; + } + s = (size_t)m; + + if (fseek(f, 0, SEEK_SET) != 0) { + n = 1; + goto bail; + } + + *buf = malloc(s + 1); + if (!*buf) { + n = 2; + goto bail; + } + + if (fread(*buf, s, 1, f) != 1) { + free(*buf); + n = 1; + goto bail; + } + + *amount = s; + +bail: + if (f) + fclose(f); + + return n; + +} + +static int +extra_cb(lws_cose_sig_ext_pay_t *x) +{ + x->ext = extra; + x->xl = ext_len; + + // lwsl_hexdump_notice(extra, ext_len); + + return 0; +} + +int +pay_cb(struct lws_cose_validate_context *cps, void *opaque, + const uint8_t *paychunk, size_t paychunk_len) +{ + write(fdout, paychunk, paychunk_len); + + return 0; +} + +int main(int argc, const char **argv) +{ + uint8_t *ks, temp[256], *kid = NULL, ktmp[4096], sbuf[512]; + int n, m, sign = 0, result = 1, + logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + enum lws_cose_sig_types sigtype = SIGTYPE_UNKNOWN; + struct lws_cose_validate_context *cps = NULL; + struct lws_cose_sign_context *csc = NULL; + const struct lws_gencrypto_keyelem *ke; + struct lws_context_creation_info info; + lws_cose_validate_create_info_t vi; + struct lws_buflist *paybuf = NULL; + lws_cose_sign_create_info_t i; + struct lws_context *context; + size_t ks_len, kid_len = 0; + lws_cose_key_t *ck = NULL; + lws_dll2_owner_t *o, set; + lws_lec_pctx_t lec; + cose_param_t alg; + const char *p; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + + lwsl_user("LWS cose-sign example tool -k keyset [-s alg-name kid ]\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ +#if defined(LWS_WITH_NETWORK) + info.port = CONTEXT_PORT_NO_LISTEN; +#endif + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + if ((p = lws_cmdline_option(argc, argv, "--stdin"))) { + fdin = open(p, LWS_O_RDONLY, 0); + if (fdin < 0) { + lwsl_err("%s: unable to open stdin file\n", __func__); + return 1; + } + } + + if ((p = lws_cmdline_option(argc, argv, "--stdout"))) { + fdout = open(p, LWS_O_WRONLY | LWS_O_CREAT | LWS_O_TRUNC, 0600); + if (fdout < 0) { + lwsl_err("%s: unable to open stdout file\n", __func__); + goto bail_early; + } + } + + /* + * If no tag, you can tell it the signature type, otherwise it will + * use the tag to select the right type without these + */ + + if (lws_cmdline_option(argc, argv, "--cose-sign")) + sigtype = SIGTYPE_MULTI; + + if (lws_cmdline_option(argc, argv, "--cose-sign1")) + sigtype = SIGTYPE_SINGLE; + + if (lws_cmdline_option(argc, argv, "--cose-mac")) + sigtype = SIGTYPE_MAC; + + if (lws_cmdline_option(argc, argv, "--cose-mac0")) + sigtype = SIGTYPE_MAC0; + + /* if signing, set the ciphers */ + + if (lws_cmdline_option(argc, argv, "-s")) + sign = 1; + + if ((p = lws_cmdline_option(argc, argv, "--kid"))) { + kid = (uint8_t *)p; + kid_len = strlen(p); + //lwsl_hexdump_notice(kid, kid_len); + } + + if ((p = lws_cmdline_option(argc, argv, "--kid-hex"))) { + kid_len = (size_t)lws_hex_to_byte_array(p, ktmp, sizeof(ktmp)); + kid = (uint8_t *)ktmp; + } + + if ((p = lws_cmdline_option(argc, argv, "--extra"))) { + ext_len = (size_t)lws_hex_to_byte_array(p, extra, sizeof(extra)); + lwsl_notice("%llu\n", (unsigned long long)ext_len); + if (ext_len == (size_t)-1ll) + ext_len = 0; + } + + /* grab the key */ + + if (!(p = lws_cmdline_option(argc, argv, "-k"))) { + lwsl_err("-k is required\n"); + goto bail; + } + + if (_alloc_file(context, p, &ks, &ks_len)) { + lwsl_err("%s: unable to load %s\n", __func__, p); + goto bail; + } + + lws_dll2_owner_clear(&set); + if (!lws_cose_key_import(&set, NULL, NULL, ks, ks_len)) { + lwsl_notice("%s: key import fail\n", __func__); + free(ks); + goto bail2; + } + + free(ks); + + if (!fdin) { + struct timeval timeout; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(0, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 1000; + + if (select(fdin + 1, &fds, NULL, NULL, &timeout) < 0 || + !FD_ISSET(0, &fds)) { + lwsl_err("%s: pass cose_sign or plaintext " + "on stdin or --stdin\n", __func__); + goto bail2; + } + } + + if (sign) { + uint8_t *ppay; + size_t s; + + p = lws_cmdline_option(argc, argv, "--alg"); + if (!p) { + lwsl_err("%s: need to specify alg (eg, ES256) " + "when signing\n", __func__); + goto bail2; + } + alg = lws_cose_name_to_alg(p); + + lws_lec_init(&lec, sbuf, sizeof(sbuf)); + memset(&i, 0, sizeof(i)); + i.cx = context; + i.keyset = &set; + i.lec = &lec; + i.flags = LCSC_FL_ADD_CBOR_TAG | + LCSC_FL_ADD_CBOR_PREFER_MAC0; + i.sigtype = sigtype; + + /* + * Unfortunately, with COSE we must know the payload length + * before we have seen the payload. It's illegal to use + * indeterminite lengths inside COSE objects. + */ + + do { + n = (int)read(fdin, temp, sizeof(temp)); + if (n < 0) + goto bail3; + if (!n) + break; + + s = (size_t)n; + + if (lws_buflist_append_segment(&paybuf, temp, s) < 0) + goto bail3; + i.inline_payload_len += s; + + } while (1); + + // lwsl_notice("%s: inline_payload_len %llu\n", __func__, + // (unsigned long long)i.inline_payload_len); + + csc = lws_cose_sign_create(&i); + if (!csc) + goto bail2; + ck = lws_cose_key_from_set(&set, kid, kid_len); + if (!ck) + goto bail2; + + if (lws_cose_sign_add(csc, alg, ck)) + goto bail2; + + do { + s = lws_buflist_next_segment_len(&paybuf, &ppay); + if (!s) + break; + + do { + m = (int)lws_cose_sign_payload_chunk(csc, + ppay, s); + if (lec.used) { + // lwsl_hexdump_err(sbuf, lec.used); + write(fdout, sbuf, lec.used); + lws_lec_setbuf(&lec, sbuf, sizeof(sbuf)); + } + } while (m == LCOSESIGEXTCB_RET_AGAIN); + + if (m == LWS_LECPCTX_RET_FAIL) + goto bail2; + + if (lec.used) { + write(fdout, sbuf, lec.used); + lws_lec_setbuf(&lec, sbuf, sizeof(sbuf)); + } + + lws_buflist_use_segment(&paybuf, s); + } while(1); + + } else { + memset(&vi, 0, sizeof(vi)); + + vi.cx = context; + vi.keyset = &set; + vi.sigtype = sigtype; + vi.ext_cb = extra_cb; + vi.ext_opaque = extra; + vi.ext_len = ext_len; + vi.pay_cb = pay_cb; + + cps = lws_cose_validate_create(&vi); + if (!cps) { + lwsl_notice("%s: sign_val_create fail\n", __func__); + goto bail; + } + + do { + n = (int)read(fdin, temp, sizeof(temp)); + if (n < 0) + goto bail3; + if (!n) + break; + + n = lws_cose_validate_chunk(cps, temp, (size_t)n, NULL); + if (n && n != LECP_CONTINUE) { + lwsl_err("%s: chunk validation failed: %d\n", + __func__, n); + goto bail2; + } + } while (1); + } + +bail3: + + result = 0; + + if (!sign) { + char buf[2048]; + int os; + + o = lws_cose_validate_results(cps); + if (!o) + result = 1; + else { + os = lws_snprintf(buf, sizeof(buf), + "\nresults count %d\n", o->count); + write(fdout, buf, (size_t)os); + + if (!o->count) + result = 1; + } + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(o)) { + lws_cose_validate_res_t *res = lws_container_of(p, + lws_cose_validate_res_t, list); + char khr[256]; + + khr[0] = '\0'; + if (res->cose_key) { + ke = &res->cose_key->meta[COSEKEY_META_KID]; + if (ke && ke->buf) + lws_hex_from_byte_array(ke->buf, ke->len, + khr, sizeof(khr)); + } + os = lws_snprintf(buf, sizeof(buf), + " result: %d (alg %s, kid %s)\n", + res->result, + lws_cose_alg_to_name(res->cose_alg), khr); + write(fdout, buf, (size_t)os); + result |= res->result; + } lws_end_foreach_dll_safe(p, tp); + } + +bail2: + if (!sign) + lws_cose_validate_destroy(&cps); + else { + lws_buflist_destroy_all_segments(&paybuf); + lws_cose_sign_destroy(&csc); + } +//bail1: + lws_cose_key_set_destroy(&set); +bail: + lws_context_destroy(context); + + if (result) + lwsl_err("%s: FAIL: %d\n", __func__, result); + else + lwsl_notice("%s: PASS\n", __func__); + +bail_early: + if (fdin > 0) + close(fdin); + if (fdout != 1 && fdout >= 0) + close(fdout); + + return result; +} diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/payload.txt b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/payload.txt new file mode 100644 index 00000000..402bd7c4 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/payload.txt @@ -0,0 +1 @@ +The Test Payload \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/rsa-4096.ck b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/rsa-4096.ck new file mode 100644 index 00000000..8b3fddb9 Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/rsa-4096.ck differ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/set1.cks b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/set1.cks new file mode 100644 index 00000000..e5eca18e Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/set1.cks differ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign-rsa4096.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign-rsa4096.sig new file mode 100644 index 00000000..a233d68c Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign-rsa4096.sig differ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass01.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass01.sig new file mode 100644 index 00000000..d78767e6 Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass01.sig differ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass02.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass02.sig new file mode 100644 index 00000000..2b53930d --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass02.sig @@ -0,0 +1 @@ +Ò„C¡&¡B11TThis is the content.X@rœ×Ë8ØØéD¨Úqç²XɽÊa5÷®Ûî• ‰gƒ~3½6ÁP2jæ'UƽŽT >’×Ò%èÛr¸‚ \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass03.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass03.sig new file mode 100644 index 00000000..a10fc966 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign1_pass03.sig @@ -0,0 +1 @@ +„C¡&¡B11TThis is the content.X@޳>L£FZ°Z¬4Ìk#Õï\1ÄÒZ‘®ð°~*ù¢‘ª2áJ¸4ÜVí*"4DT~ñ; å¤ÃEÊË6 \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass01.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass01.sig new file mode 100644 index 00000000..268b0861 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass01.sig @@ -0,0 +1 @@ +Øb„A  TThis is the content.ƒC¡&¡B11X@â®¯Ô iÑþnR|]ôä(,¾û]Ëô¯.Ù‚¬E¬˜¸TL‹EÞ·ÃÓHþ’j+˜õ:ý/ ó diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass02.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass02.sig new file mode 100644 index 00000000..b80f7a26 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass02.sig @@ -0,0 +1 @@ +Øb„@ TThis is the content.ƒC¡&¡B11X@˸ÚÙ¾¯¸á¤M‹ûÂkíò©OËZˆ$2¿öÖ>õtQØ?¢Ëö&rëôÇÙ“°ôÂDvGØ1ºW̨k“ diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass03.sig b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass03.sig new file mode 100644 index 00000000..60d8f039 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-sign/sign_pass03.sig @@ -0,0 +1 @@ +„@ TThis is the content.ƒC¡&¡B11X@â®¯Ô iÑþnR|]ôä(,¾û]Ëô¯.Ù‚¬E¬˜¸TL‹EÞ·ÃÓHþ’j+˜õ:ý/ ó diff --git a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-x509/main.c b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-x509/main.c index e6f210bc..7a3bc3bc 100644 --- a/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-x509/main.c +++ b/3rdparty/libwebsockets/minimal-examples/crypto/minimal-crypto-x509/main.c @@ -166,7 +166,8 @@ int main(int argc, const char **argv) goto bail3; } - if (lws_x509_jwk_privkey_pem(&jwk, pembuf, (unsigned int)n, NULL)) { + if (lws_x509_jwk_privkey_pem(context, &jwk, pembuf, + (unsigned int)n, NULL)) { lwsl_err("%s: unable to parse privkey %s\n", __func__, p); diff --git a/3rdparty/libwebsockets/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c b/3rdparty/libwebsockets/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c index 066a20ac..353b159d 100644 --- a/3rdparty/libwebsockets/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c +++ b/3rdparty/libwebsockets/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c @@ -26,7 +26,7 @@ static int interrupted; static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_MINIMAL_DBUS_WSPROXY, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; /* diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/CMakeLists.txt new file mode 100644 index 00000000..57d7bfc3 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.5) + +if (ESP_PLATFORM) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(lws-minimal-esp32) + 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 20) + +endif() diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/lws-button.c b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/lws-button.c new file mode 100644 index 00000000..7f5ed313 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/lws-button.c @@ -0,0 +1,497 @@ +/* + * 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; + 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 try to figure out which events have happened. + */ + +#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); + const lws_button_controller_t *bc = bcs->controller; + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + 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 it 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) + // lwsl_notice("%s: starting mon timer\n", __func__); + 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[n].state == LBCS_IDLE) + 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[n].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[n].state); + + switch (each[n].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[n].mon_timer_comp = bcs->mon_timer_count; + each[n].state = LBCS_UP_SETTLE2; + continue; + } + + 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[n].state = LBCS_ASSESS_DOWN_HOLD; + break; + } + 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[n].state = LBCS_WAIT_UP; + goto classify; + } + + 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[n].mon_timer_comp = bcs->mon_timer_count; + each[n].state = LBCS_UP_SETTLE1; + } + break; + + case LBCS_UP_SETTLE1: + if (comp_age_ms > regime->ms_up_settle) + /* + * Just block anything for the up settle time + */ + each[n].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[n].mon_timer_comp = bcs->mon_timer_count; + each[n].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) { +classify_single: + /* + * 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 + */ + event_name = "click"; + each[n].mon_timer_comp = bcs->mon_timer_count; + each[n].state = LBCS_UP_SETTLE2; + goto classify; + } + + if (comp_age_ms >= regime->ms_min_down) { + /* + * It's a double-click + */ + event_name = "doubleclick"; + each[n].state = LBCS_WAIT_UP; + goto classify; + } + break; + + case LBCS_WAIT_UP: + if (!active) { + each[n].mon_timer_comp = bcs->mon_timer_count; + each[n].state = LBCS_UP_SETTLE2; + } + break; + + case LBCS_UP_SETTLE2: + if (comp_age_ms < regime->ms_up_settle) + break; + + each[n].state = LBCS_IDLE; + if (!(--bcs->mon_refcount)) { +#if defined(LWS_PLAT_TIMER_STOP) + LWS_PLAT_TIMER_STOP(bcs->timer_mon); +#endif + } + break; + } + + continue; + +classify: + lws_smd_msg_printf(bcs->ctx, LWSSMDCL_INTERACTION, + "{\"btn\":\"%s/%s\", \"s\":\"%s\"}", + bc->smd_bc_name, + bc->button_map[n].smd_interaction_name, + event_name); + } +} +#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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/CMakeLists.txt new file mode 100644 index 00000000..77040deb --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/CMakeLists.txt @@ -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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/bb-i2c.c b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/bb-i2c.c new file mode 100644 index 00000000..0c89e902 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/bb-i2c.c @@ -0,0 +1,107 @@ +/* + * lws generic bitbang i2c + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include "bb-i2c.h" + +int +lws_bb_i2c_start(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(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(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(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(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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/bb-i2c.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/bb-i2c.h new file mode 100644 index 00000000..31cc3b58 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/bb-i2c.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#include +#include +#include "i2c.h" +#include "gpio-esp32.h" + +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 \ + { \ + .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_start(lws_i2c_ops_t *octx); + +void +lws_bb_i2c_stop(lws_i2c_ops_t *octx); + +int +lws_bb_i2c_write(lws_i2c_ops_t *octx, uint8_t data); + +int +lws_bb_i2c_read(lws_i2c_ops_t *octx); + +void +lws_bb_i2c_set_ack(lws_i2c_ops_t *octx, int ack); + + diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/component.mk b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/component.mk new file mode 100644 index 00000000..0b9d7585 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c new file mode 100644 index 00000000..2d079d5e --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c @@ -0,0 +1,187 @@ +/* + * devices for ESP32 C3 dev board + * + * Written in 2010-2021 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 + */ + +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_8, .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) +}; + +#if 0 +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 +}; +#endif + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "alert", + .gpio = GPIO_NUM_8, + .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, "xxx", 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); + esp_wifi_set_mode(WIFI_MODE_STA); +lws_netdev_wifi_scan_plat(&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; + } + + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); +// lws_led_transition(lls, "alert", &lws_pwmseq_static_off, +// &lws_pwmseq_static_on); + + lwsl_notice("%s: exiting device init\n", __func__); + return 0; +} diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio-esp32.c b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio-esp32.c new file mode 100644 index 00000000..92fe8632 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio-esp32.c @@ -0,0 +1,36 @@ +#include +#include "gpio-esp32.h" + +static void +lws_gpio_esp32_mode_write(_lws_plat_gpio_t gpio) +{ + gpio_reset_pin(gpio); + gpio_set_pull_mode(gpio, GPIO_PULLUP_ONLY); + gpio_set_direction(gpio, GPIO_MODE_INPUT_OUTPUT); + gpio_set_level(gpio, 1); +} +static void +lws_gpio_esp32_mode_read(_lws_plat_gpio_t gpio) +{ + gpio_set_pull_mode(gpio, GPIO_PULLUP_ONLY); + gpio_set_direction(gpio, GPIO_MODE_INPUT); + gpio_set_level(gpio, 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); +} + +const lws_gpio_ops_t lws_gpio_esp32 = { + .mode_write = lws_gpio_esp32_mode_write, + .mode_read = lws_gpio_esp32_mode_read, + .read = lws_gpio_esp32_read, + .set = lws_gpio_esp32_set, +}; + diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio-esp32.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio-esp32.h new file mode 100644 index 00000000..d2201686 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio-esp32.h @@ -0,0 +1,13 @@ +/* + * lws generic gpio - esp32 platform wrapper + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +typedef int _lws_plat_gpio_t; +#include "gpio.h" + +extern const lws_gpio_ops_t lws_gpio_esp32; diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio.h new file mode 100644 index 00000000..50205189 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/gpio.h @@ -0,0 +1,25 @@ +/* + * lws genric gpio + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * You should typedef _lws_plat_gpio_t to int or whatever before + * including this. It's better to wrap this in a platform-specific + * include that does that and then include the platform-specific + * include in your code. + */ + +#if !defined(__LWS_GPIO_H__) +#define __LWS_GPIO_H__ + +typedef struct lws_gpio_ops { + void (*mode_write)(_lws_plat_gpio_t gpio); + void (*mode_read)(_lws_plat_gpio_t gpio); + int (*read)(_lws_plat_gpio_t gpio); + void (*set)(_lws_plat_gpio_t gpio, int val); +} lws_gpio_ops_t; + +#endif diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/i2c.c b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/i2c.c new file mode 100644 index 00000000..5e0b4cdf --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/i2c.c @@ -0,0 +1,32 @@ +#include "i2c.h" + +int +lws_i2c_command(lws_i2c_ops_t *ctx, uint8_t ads, uint8_t c) +{ + if (ctx->start(ctx)) + return 1; + + if (ctx->write(ctx, ads << 1)) { + ctx->stop(ctx); + + return 1; + } + + ctx->write(ctx, 0); + ctx->write(ctx, c); + ctx->stop(ctx); + + return 0; +} + +int +lws_i2c_command_list(lws_i2c_ops_t *ctx, uint8_t ads, const uint8_t *buf, size_t len) +{ + while (len--) + if (lws_i2c_command(ctx, ads, *buf++)) + return 1; + + return 0; +} + + diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/i2c.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/i2c.h new file mode 100644 index 00000000..fe339800 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/i2c.h @@ -0,0 +1,35 @@ +/* + * Generic i2c ops + * + * These ops always appear first in an implementation-specific + * object, so the generic ops can be cast to the implementation- + * specific object in the handlers. + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#if !defined(__LWS_I2C_H__) +#define __LWS_I2C_H__ + +#include +#include + +typedef struct lws_i2c_ops { + int (*start)(struct lws_i2c_ops *ctx); + void (*stop)(struct lws_i2c_ops *ctx); + int (*write)(struct lws_i2c_ops *ctx, uint8_t data); + int (*read)(struct lws_i2c_ops *ctx); + void (*set_ack)(struct lws_i2c_ops *octx, int ack); +} lws_i2c_ops_t; + +int +lws_i2c_command(lws_i2c_ops_t *ctx, uint8_t ads, uint8_t c); + +int +lws_i2c_command_list(lws_i2c_ops_t *ctx, uint8_t ads, const uint8_t *buf, size_t len); + +#endif + diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/policy.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/policy.h new file mode 100644 index 00000000..03c44b68 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/main/policy.h @@ -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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/partitions.csv b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/partitions.csv new file mode 100644 index 00000000..e261b7cb --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/partitions.csv @@ -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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/private-lib-plat-freertos.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/private-lib-plat-freertos.h new file mode 100644 index 00000000..a81bbc05 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/private-lib-plat-freertos.h @@ -0,0 +1,131 @@ + /* + * 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. + * + * 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 + open(const char *path, int oflag, ...); +#else + #include +#endif + + #include + #include + #include + #include + #include + #include + + #ifndef __cplusplus + #include + #endif + #include +#if defined(LWS_AMAZON_RTOS) +const char * +gai_strerror(int); +#else + #include +#endif + +#if defined(LWS_AMAZON_RTOS) + #include "FreeRTOS.h" +#if defined(LWS_WITH_SYS_ASYNC_DNS) + #include "FreeRTOS_IP.h" +#endif + #include "timers.h" + #include +#else + #include "freertos/timers.h" + #include + #include + #include +#endif + +#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) + #include "./misc/getifaddrs.h" + #endif + + #define LWS_ERRNO errno + #define LWS_EAGAIN EAGAIN + #define LWS_EALREADY EALREADY + #define LWS_EINPROGRESS EINPROGRESS + #define LWS_EINTR EINTR + #define LWS_EISCONN EISCONN + #define LWS_ENOTCONN ENOTCONN + #define LWS_EWOULDBLOCK EWOULDBLOCK + #define LWS_EADDRINUSE EADDRINUSE + + #define lws_set_blocking_send(wsi) + + #ifndef LWS_NO_FORK + #ifdef LWS_HAVE_SYS_PRCTL_H + #include + #endif + #endif + +#if !defined(MSG_NOSIGNAL) +#define MSG_NOSIGNAL 0 +#endif + +#define compatible_close(x) close(x) +#define lws_plat_socket_offset() LWIP_SOCKET_OFFSET +#define wsi_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] + +struct lws_context; +struct lws; + +int +insert_wsi(const struct lws_context *context, struct lws *wsi); + +#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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/sdkconfig b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/sdkconfig new file mode 100644 index 00000000..a406123c --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/sdkconfig @@ -0,0 +1,1301 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_RISCV=y +CONFIG_IDF_TARGET="esp32c3" +CONFIG_IDF_TARGET_ESP32C3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0005 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="riscv32-esp-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_OFFSET_IN_FLASH=0x0 +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_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_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_SUPPORTS_RSA=y +CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y +# 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 + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_NO_STUB is not set +# 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=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +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_CONSOLE is not set +# 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_SINGLE_APP_LARGE=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp_large.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_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# 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 +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 +CONFIG_BTDM_CTRL_PCM_POLAR_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_CTRL_MODE_EFF=1 +CONFIG_BT_CTRL_BLE_MAX_ACT=10 +CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=10 +CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 +CONFIG_BT_CTRL_PINNED_TO_CORE=0 +CONFIG_BT_CTRL_HCI_TL=1 +CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 +CONFIG_BT_CTRL_HW_CCA_EFF=0 +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=0 +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BT_CTRL_BLE_SCAN_DUPL=y +CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 +CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 +CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 +CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 +CONFIG_BT_CTRL_HCI_TL_EFF=1 +CONFIG_BT_RESERVE_DRAM=0 +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=y +CONFIG_BT_NIMBLE_USE_ESP_TIMER=y +# 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 + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ESP32C3-Specific +# +# CONFIG_ESP32C3_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32C3_DEFAULT_CPU_FREQ_160=y +CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_ESP32C3_REV_MIN_0 is not set +# CONFIG_ESP32C3_REV_MIN_1 is not set +# CONFIG_ESP32C3_REV_MIN_2 is not set +CONFIG_ESP32C3_REV_MIN_3=y +CONFIG_ESP32C3_REV_MIN=3 +CONFIG_ESP32C3_DEBUG_OCDAWARE=y +# CONFIG_ESP32C3_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32C3_BROWNOUT_DET=y +CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_2 is not set +CONFIG_ESP32C3_BROWNOUT_DET_LVL=7 +CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +# CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32C3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32C3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32C3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32C3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32C3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32C3_RTC_CLK_CAL_CYCLES=1024 +# CONFIG_ESP32C3_NO_BLOBS is not set +CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y +# end of ESP32C3-Specific + +# +# ADC-Calibration +# +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL 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 +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# 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 + +# +# Hardware Settings +# + +# +# MAC Config +# +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 +# CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y +# end of Sleep Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PERIPH_CLK_SRC_PLL160M=y +# CONFIG_LCD_PERIPH_CLK_SRC_XTAL is not set +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# 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 + +# +# 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 + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# 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 +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE=y +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y +# CONFIG_ESP_SYSTEM_USE_EH_FRAME is not set + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=7584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=3048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +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_PANIC_HANDLER_IRAM is not set +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +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_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_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 +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +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_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +CONFIG_FMB_PORT_TASK_AFFINITY=0x7FFFFFFF +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +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 is not set +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +CONFIG_FMB_MASTER_TIMER_GROUP=0 +CONFIG_FMB_MASTER_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +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=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +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_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# 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_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_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_NETIF_API is not set +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_LINGER 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_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_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_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +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=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=0 +# CONFIG_LWIP_NETIF_STATUS_CALLBACK 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_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +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 +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +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=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# 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 + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# 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_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=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_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=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 +# CONFIG_MBEDTLS_NIST_KW_C is not set +# 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_LARGE_KEY_SOFTWARE_MPI=y +# 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=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +# 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_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# 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_ERROR_STACK=y +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +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_ROM_IMPL is not set +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 +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# 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 +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# 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 + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# 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_WAPI_PSK is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT 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="riscv32-esp-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_OPTIMIZATION_ASSERTION_LEVEL=2 +# 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_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_ESP_SYSTEM_PD_FLASH=y +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=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_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_ESP32H2_MEMPROT_FEATURE=y +CONFIG_ESP32H2_MEMPROT_FEATURE_LOCK=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=3304 +CONFIG_MAIN_TASK_STACK_SIZE=7584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +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_TIMER_TASK_STACK_SIZE=3584 +# 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 +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=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +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 is not set +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +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=12 +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=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_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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/sdkconfig.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/sdkconfig.h new file mode 100644 index 00000000..43d3c995 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-c3dev/sdkconfig.h @@ -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 --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c index a4dab2a0..da7cbe9c 100644 --- a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c @@ -31,7 +31,10 @@ lws_netdev_instance_wifi_t *wnd; static void esp32_i2c_delay(void) { - ets_delay_us(1); + volatile int n = 0; + + while (n < 20) + n++; } static const lws_bb_i2c_t li2c = { diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h index a359be28..79e21fd0 100644 --- a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h @@ -26,32 +26,43 @@ static const char * const ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" - "\"}" + "{\"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=" + "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -66,7 +77,7 @@ static const char * const ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}},{" /* * "captive_portal_detect" describes diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h index 00f71f37..55243329 100644 --- a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h @@ -23,32 +23,43 @@ static const char * const ss_policy = /* * Let's Encrypt certs for warmcat.com / libwebsockets.org */ - "{\"dst_root_x3\": \"" - "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" - "\"}" + "{\"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=" + "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -63,7 +74,7 @@ static const char * const ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}},{" /* * "captive_portal_detect" describes diff --git a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h index b8655f7a..cb89fb6b 100644 --- a/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h +++ b/3rdparty/libwebsockets/minimal-examples/embedded/esp32/esp-wrover-kit/main/static-policy.h @@ -3,63 +3,9 @@ */ #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": [ - {"dst_root_x3": "MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ" - }], - "trust_stores": [ - { - "name": "le_via_dst", - "stack": [ - "dst_root_x3" - ] - } - ], - "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_dst" - }},{ - "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: 2211 + Original JSON size: 13 #endif static const uint32_t _rbo_bo_0[] = { @@ -73,123 +19,192 @@ static const lws_retry_bo_t _rbo_0 = { .secs_since_valid_hangup = 35, .jitter_percent = 20, }; -static const uint8_t _ss_der_dst_root_x3[] = { - /* 0x 0 */ 0x30, 0x82, 0x03, 0x4A, 0x30, 0x82, 0x02, 0x32, - /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x44, - /* 0x 10 */ 0xAF, 0xB0, 0x80, 0xD6, 0xA3, 0x27, 0xBA, 0x89, - /* 0x 18 */ 0x30, 0x39, 0x86, 0x2E, 0xF8, 0x40, 0x6B, 0x30, - /* 0x 20 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - /* 0x 28 */ 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3F, - /* 0x 30 */ 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, - /* 0x 38 */ 0x0A, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x74, - /* 0x 40 */ 0x61, 0x6C, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x61, - /* 0x 48 */ 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, - /* 0x 50 */ 0x73, 0x74, 0x20, 0x43, 0x6F, 0x2E, 0x31, 0x17, - /* 0x 58 */ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - /* 0x 60 */ 0x0E, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, - /* 0x 68 */ 0x74, 0x20, 0x43, 0x41, 0x20, 0x58, 0x33, 0x30, - /* 0x 70 */ 0x1E, 0x17, 0x0D, 0x30, 0x30, 0x30, 0x39, 0x33, - /* 0x 78 */ 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5A, - /* 0x 80 */ 0x17, 0x0D, 0x32, 0x31, 0x30, 0x39, 0x33, 0x30, - /* 0x 88 */ 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5A, 0x30, - /* 0x 90 */ 0x3F, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, - /* 0x 98 */ 0x04, 0x0A, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, - /* 0x a0 */ 0x74, 0x61, 0x6C, 0x20, 0x53, 0x69, 0x67, 0x6E, - /* 0x a8 */ 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, - /* 0x b0 */ 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x2E, 0x31, - /* 0x b8 */ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, - /* 0x c0 */ 0x13, 0x0E, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6F, - /* 0x c8 */ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x58, 0x33, - /* 0x d0 */ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, - /* 0x d8 */ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - /* 0x e0 */ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, - /* 0x e8 */ 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, - /* 0x f0 */ 0x00, 0xDF, 0xAF, 0xE9, 0x97, 0x50, 0x08, 0x83, - /* 0x f8 */ 0x57, 0xB4, 0xCC, 0x62, 0x65, 0xF6, 0x90, 0x82, - /* 0x100 */ 0xEC, 0xC7, 0xD3, 0x2C, 0x6B, 0x30, 0xCA, 0x5B, - /* 0x108 */ 0xEC, 0xD9, 0xC3, 0x7D, 0xC7, 0x40, 0xC1, 0x18, - /* 0x110 */ 0x14, 0x8B, 0xE0, 0xE8, 0x33, 0x76, 0x49, 0x2A, - /* 0x118 */ 0xE3, 0x3F, 0x21, 0x49, 0x93, 0xAC, 0x4E, 0x0E, - /* 0x120 */ 0xAF, 0x3E, 0x48, 0xCB, 0x65, 0xEE, 0xFC, 0xD3, - /* 0x128 */ 0x21, 0x0F, 0x65, 0xD2, 0x2A, 0xD9, 0x32, 0x8F, - /* 0x130 */ 0x8C, 0xE5, 0xF7, 0x77, 0xB0, 0x12, 0x7B, 0xB5, - /* 0x138 */ 0x95, 0xC0, 0x89, 0xA3, 0xA9, 0xBA, 0xED, 0x73, - /* 0x140 */ 0x2E, 0x7A, 0x0C, 0x06, 0x32, 0x83, 0xA2, 0x7E, - /* 0x148 */ 0x8A, 0x14, 0x30, 0xCD, 0x11, 0xA0, 0xE1, 0x2A, - /* 0x150 */ 0x38, 0xB9, 0x79, 0x0A, 0x31, 0xFD, 0x50, 0xBD, - /* 0x158 */ 0x80, 0x65, 0xDF, 0xB7, 0x51, 0x63, 0x83, 0xC8, - /* 0x160 */ 0xE2, 0x88, 0x61, 0xEA, 0x4B, 0x61, 0x81, 0xEC, - /* 0x168 */ 0x52, 0x6B, 0xB9, 0xA2, 0xE2, 0x4B, 0x1A, 0x28, - /* 0x170 */ 0x9F, 0x48, 0xA3, 0x9E, 0x0C, 0xDA, 0x09, 0x8E, - /* 0x178 */ 0x3E, 0x17, 0x2E, 0x1E, 0xDD, 0x20, 0xDF, 0x5B, - /* 0x180 */ 0xC6, 0x2A, 0x8A, 0xAB, 0x2E, 0xBD, 0x70, 0xAD, - /* 0x188 */ 0xC5, 0x0B, 0x1A, 0x25, 0x90, 0x74, 0x72, 0xC5, - /* 0x190 */ 0x7B, 0x6A, 0xAB, 0x34, 0xD6, 0x30, 0x89, 0xFF, - /* 0x198 */ 0xE5, 0x68, 0x13, 0x7B, 0x54, 0x0B, 0xC8, 0xD6, - /* 0x1a0 */ 0xAE, 0xEC, 0x5A, 0x9C, 0x92, 0x1E, 0x3D, 0x64, - /* 0x1a8 */ 0xB3, 0x8C, 0xC6, 0xDF, 0xBF, 0xC9, 0x41, 0x70, - /* 0x1b0 */ 0xEC, 0x16, 0x72, 0xD5, 0x26, 0xEC, 0x38, 0x55, - /* 0x1b8 */ 0x39, 0x43, 0xD0, 0xFC, 0xFD, 0x18, 0x5C, 0x40, - /* 0x1c0 */ 0xF1, 0x97, 0xEB, 0xD5, 0x9A, 0x9B, 0x8D, 0x1D, - /* 0x1c8 */ 0xBA, 0xDA, 0x25, 0xB9, 0xC6, 0xD8, 0xDF, 0xC1, - /* 0x1d0 */ 0x15, 0x02, 0x3A, 0xAB, 0xDA, 0x6E, 0xF1, 0x3E, - /* 0x1d8 */ 0x2E, 0xF5, 0x5C, 0x08, 0x9C, 0x3C, 0xD6, 0x83, - /* 0x1e0 */ 0x69, 0xE4, 0x10, 0x9B, 0x19, 0x2A, 0xB6, 0x29, - /* 0x1e8 */ 0x57, 0xE3, 0xE5, 0x3D, 0x9B, 0x9F, 0xF0, 0x02, - /* 0x1f0 */ 0x5D, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x42, - /* 0x1f8 */ 0x30, 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, - /* 0x200 */ 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, - /* 0x208 */ 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, - /* 0x210 */ 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, - /* 0x218 */ 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, - /* 0x220 */ 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC4, 0xA7, - /* 0x228 */ 0xB1, 0xA4, 0x7B, 0x2C, 0x71, 0xFA, 0xDB, 0xE1, - /* 0x230 */ 0x4B, 0x90, 0x75, 0xFF, 0xC4, 0x15, 0x60, 0x85, - /* 0x238 */ 0x89, 0x10, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - /* 0x240 */ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, - /* 0x248 */ 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xA3, 0x1A, - /* 0x250 */ 0x2C, 0x9B, 0x17, 0x00, 0x5C, 0xA9, 0x1E, 0xEE, - /* 0x258 */ 0x28, 0x66, 0x37, 0x3A, 0xBF, 0x83, 0xC7, 0x3F, - /* 0x260 */ 0x4B, 0xC3, 0x09, 0xA0, 0x95, 0x20, 0x5D, 0xE3, - /* 0x268 */ 0xD9, 0x59, 0x44, 0xD2, 0x3E, 0x0D, 0x3E, 0xBD, - /* 0x270 */ 0x8A, 0x4B, 0xA0, 0x74, 0x1F, 0xCE, 0x10, 0x82, - /* 0x278 */ 0x9C, 0x74, 0x1A, 0x1D, 0x7E, 0x98, 0x1A, 0xDD, - /* 0x280 */ 0xCB, 0x13, 0x4B, 0xB3, 0x20, 0x44, 0xE4, 0x91, - /* 0x288 */ 0xE9, 0xCC, 0xFC, 0x7D, 0xA5, 0xDB, 0x6A, 0xE5, - /* 0x290 */ 0xFE, 0xE6, 0xFD, 0xE0, 0x4E, 0xDD, 0xB7, 0x00, - /* 0x298 */ 0x3A, 0xB5, 0x70, 0x49, 0xAF, 0xF2, 0xE5, 0xEB, - /* 0x2a0 */ 0x02, 0xF1, 0xD1, 0x02, 0x8B, 0x19, 0xCB, 0x94, - /* 0x2a8 */ 0x3A, 0x5E, 0x48, 0xC4, 0x18, 0x1E, 0x58, 0x19, - /* 0x2b0 */ 0x5F, 0x1E, 0x02, 0x5A, 0xF0, 0x0C, 0xF1, 0xB1, - /* 0x2b8 */ 0xAD, 0xA9, 0xDC, 0x59, 0x86, 0x8B, 0x6E, 0xE9, - /* 0x2c0 */ 0x91, 0xF5, 0x86, 0xCA, 0xFA, 0xB9, 0x66, 0x33, - /* 0x2c8 */ 0xAA, 0x59, 0x5B, 0xCE, 0xE2, 0xA7, 0x16, 0x73, - /* 0x2d0 */ 0x47, 0xCB, 0x2B, 0xCC, 0x99, 0xB0, 0x37, 0x48, - /* 0x2d8 */ 0xCF, 0xE3, 0x56, 0x4B, 0xF5, 0xCF, 0x0F, 0x0C, - /* 0x2e0 */ 0x72, 0x32, 0x87, 0xC6, 0xF0, 0x44, 0xBB, 0x53, - /* 0x2e8 */ 0x72, 0x6D, 0x43, 0xF5, 0x26, 0x48, 0x9A, 0x52, - /* 0x2f0 */ 0x67, 0xB7, 0x58, 0xAB, 0xFE, 0x67, 0x76, 0x71, - /* 0x2f8 */ 0x78, 0xDB, 0x0D, 0xA2, 0x56, 0x14, 0x13, 0x39, - /* 0x300 */ 0x24, 0x31, 0x85, 0xA2, 0xA8, 0x02, 0x5A, 0x30, - /* 0x308 */ 0x47, 0xE1, 0xDD, 0x50, 0x07, 0xBC, 0x02, 0x09, - /* 0x310 */ 0x90, 0x00, 0xEB, 0x64, 0x63, 0x60, 0x9B, 0x16, - /* 0x318 */ 0xBC, 0x88, 0xC9, 0x12, 0xE6, 0xD2, 0x7D, 0x91, - /* 0x320 */ 0x8B, 0xF9, 0x3D, 0x32, 0x8D, 0x65, 0xB4, 0xE9, - /* 0x328 */ 0x7C, 0xB1, 0x57, 0x76, 0xEA, 0xC5, 0xB6, 0x28, - /* 0x330 */ 0x39, 0xBF, 0x15, 0x65, 0x1C, 0xC8, 0xF6, 0x77, - /* 0x338 */ 0x96, 0x6A, 0x0A, 0x8D, 0x77, 0x0B, 0xD8, 0x91, - /* 0x340 */ 0x0B, 0x04, 0x8E, 0x07, 0xDB, 0x29, 0xB6, 0x0A, - /* 0x348 */ 0xEE, 0x9D, 0x82, 0x35, 0x35, 0x10, +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_dst_root_x3 = { - .vhost_name = "dst_root_x3", - .ca_der = _ss_der_dst_root_x3, - .ca_der_len = 846, +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 lws_ss_trust_store_t _ss_ts_le_via_dst = { - .name = "le_via_dst", +static const lws_ss_trust_store_t _ss_ts_le_via_isrg = { + .name = "le_via_isrg", + .count = 1, .ssx509 = { - &_ss_x509_dst_root_x3, + &_ss_x509_isrg_root_x1, } }; @@ -205,6 +220,7 @@ static const lws_ss_policy_t _ssp_captive_portal_detect = { } }, .flags = 0x1, + .priority = 0x0, .port = 80, .protocol = 0, }, @@ -220,9 +236,10 @@ _ssp_test_stream = { }, .retry_bo = &_rbo_0, .flags = 0x11, + .priority = 0x0, .port = 443, .protocol = 1, - .trust = {.store = &_ss_ts_le_via_dst}, + .trust = {.store = &_ss_ts_le_via_isrg}, }; #define _ss_static_policy_entry _ssp_test_stream -/* estimated footprint 1482 (when sizeof void * = 8) */ +/* estimated footprint 2043 (when sizeof void * = 8) */ diff --git a/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/main.c b/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/main.c index fdb19399..56f234cd 100644 --- a/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/main.c +++ b/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/main.c @@ -130,7 +130,8 @@ static const struct lws_protocols protocols[] = { static gpointer t1_main (gpointer user_data) { - lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; lws_state_notify_link_t *na[] = { ¬ifier, NULL }; GMainContext *t1_mc = (GMainContext *)user_data; struct lws_context_creation_info info; diff --git a/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/gtk/minimal-gtk/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c index 046a005b..460f9466 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c @@ -106,10 +106,9 @@ static const struct lws_protocols protocols[] = { { "http", callback_http, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; void sigint_handler(int sig) diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt index e7be79a9..f332dc5b 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -10,6 +10,7 @@ set(SAMP lws-minimal-http-client-captive-portal) set(SRCS minimal-http-client-captive-portal.c) set(requirements 1) +require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_TLS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -19,9 +20,9 @@ if (NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread ${LIBWEBSOCKETS_DEP_LIBS}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread ${LIBWEBSOCKETS_DEP_LIBS}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c index ffa1390d..d9a00bc9 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c @@ -158,13 +158,13 @@ static const struct lws_protocols protocols[] = { { "http", callback_http, - 0, - 0, + 0, 0, 0, NULL, 0 }, { "lws-cpd-http", - callback_cpd_http + callback_cpd_http, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; void sigint_handler(int sig) diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c index ec9a9ebb..9f3bf04a 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c @@ -78,6 +78,28 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, lwsl_notice(" Peer Cert public key:\n"); lwsl_hexdump_notice(ci->ns.name, (unsigned int)ci->ns.len); } + + if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID, + ci, 0)) { + lwsl_notice(" AUTHORITY_KEY_ID\n"); + lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len); + } + if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER, + ci, 0)) { + lwsl_notice(" AUTHORITY_KEY_ID ISSUER\n"); + lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len); + } + if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL, + ci, 0)) { + lwsl_notice(" AUTHORITY_KEY_ID SERIAL\n"); + lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len); + } + if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_SUBJECT_KEY_ID, + ci, 0)) { + lwsl_notice(" AUTHORITY_KEY_ID SUBJECT_KEY_ID\n"); + lwsl_hexdump_notice(ci->ns.name, (size_t)ci->ns.len); + } + break; /* chunks of chunked content, with header removed */ @@ -132,10 +154,9 @@ static const struct lws_protocols protocols[] = { { "http", callback_http, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void @@ -207,6 +228,10 @@ int main(int argc, const char **argv) i.port = 443; i.address = "warmcat.com"; } + + if ((p = lws_cmdline_option(argc, argv, "-s"))) + i.address = p; + i.path = "/"; i.host = i.address; i.origin = i.address; diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c index 92f5326d..68683717 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/minimal-http-client-custom-headers.c @@ -128,10 +128,9 @@ static const struct lws_protocols protocols[] = { { "http", callback_http, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-custom-headers/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c index 61baa601..dbd04b84 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c @@ -131,9 +131,9 @@ static const struct lws_protocols protocols[] = { "http", callback_http, sizeof(struct pss), - 0, + 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void @@ -235,7 +235,8 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, int main(int argc, const char **argv) { - lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; lws_state_notify_link_t *na[] = { ¬ifier, NULL }; struct lws_context_creation_info info; struct lws_context *context; diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-h2-rxflow/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c index 7b58f3e4..a3cda5d1 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c @@ -132,10 +132,9 @@ static const struct lws_protocols protocols[] = { { "http", callback_http, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/CMakeLists.txt new file mode 100644 index 00000000..eef5cd8d --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/CMakeLists.txt @@ -0,0 +1,157 @@ +project(lws-minimal-http-client-jit-trust C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-http-client-jit-trust) +set(SRCS minimal-http-client.c) + +set(has_fault_injection 1) +set(has_h2 1) +set(has_plugins 1) +set(has_ss_policy_parse 1) +set(has_no_system_vhost 1) +set(has_async_dns 1) + +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) +require_lws_config(LWS_WITH_TLS_JIT_TRUST 1 requirements) + +require_lws_config(LWS_ROLE_H2 1 has_h2) +require_lws_config(LWS_WITH_SYS_FAULT_INJECTION 1 has_fault_injection) +require_lws_config(LWS_WITH_EVLIB_PLUGINS 1 has_plugins) +require_lws_config(LWS_WITH_EVENT_LIBS 1 has_plugins) + +require_lws_config(LWS_WITH_SECURE_STREAMS 1 has_ss_policy_parse) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 has_ss_policy_parse) + +require_lws_config(LWS_WITH_SYS_ASYNC_DNS 0 has_no_system_vhost) +require_lws_config(LWS_WITH_SYS_NTPCLIENT 0 has_no_system_vhost) +require_lws_config(LWS_WITH_SYS_DHCP_CLIENT 0 has_no_system_vhost) + +require_lws_config(LWS_WITH_SYS_ASYNC_DNS 1 has_async_dns) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + find_program(VALGRIND "valgrind") + + sai_resource(warmcat_conns 1 40 http_client_warmcat) + + if (LWS_CTEST_INTERNET_AVAILABLE) + set(mytests http-client-warmcat-h1) + if (has_h2) + add_test(NAME http-client-warmcat COMMAND lws-minimal-http-client ) + list(APPEND mytests http-client-warmcat) + endif() + + + add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --h1) + + if (has_fault_injection) + + # creation related faults + + list(APPEND mytests http-client-fi-ctx1) + add_test(NAME http-client-fi-ctx1 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail1") + + # if (has_plugins) + # !!! need to actually select an available evlib plugin to trigger this + # list(APPEND mytests http-client-fi-pi) + # add_test(NAME http-client-fi-pi COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_plugin_init") + # endif() + + list(APPEND mytests http-client-fi-ctx2) + add_test(NAME http-client-fi-ctx2 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_evlib_sel") + + list(APPEND mytests http-client-fi-ctx3) + add_test(NAME http-client-fi-ctx3 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_oom_ctx") + + list(APPEND mytests http-client-fi-ctx4) + add_test(NAME http-client-fi-ctx4 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_privdrop") + + list(APPEND mytests http-client-fi-ctx5) + add_test(NAME http-client-fi-ctx5 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_maxfds") + + list(APPEND mytests http-client-fi-ctx6) + add_test(NAME http-client-fi-ctx6 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_oom_fds") + + list(APPEND mytests http-client-fi-ctx7) + add_test(NAME http-client-fi-ctx7 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_plat_init") + + list(APPEND mytests http-client-fi-ctx8) + add_test(NAME http-client-fi-ctx8 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_evlib_init") + + list(APPEND mytests http-client-fi-ctx9) + add_test(NAME http-client-fi-ctx9 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_evlib_pt") + + if (NOT has_no_system_vhost) + + list(APPEND mytests http-client-fi-ctx10) + add_test(NAME http-client-fi-ctx10 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_sys_vh") + + list(APPEND mytests http-client-fi-ctx11) + add_test(NAME http-client-fi-ctx11 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_sys_vh_init") + + endif() + + list(APPEND mytests http-client-fi-ctx12) + add_test(NAME http-client-fi-ctx12 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "ctx_createfail_def_vh") + + + list(APPEND mytests http-client-fi-vh1) + add_test(NAME http-client-fi-vh1 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_oom") + + list(APPEND mytests http-client-fi-vh2) + add_test(NAME http-client-fi-vh2 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_pcols_oom") + + list(APPEND mytests http-client-fi-vh3) + add_test(NAME http-client-fi-vh3 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_ssl_srv") + + list(APPEND mytests http-client-fi-vh4) + add_test(NAME http-client-fi-vh4 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_ssl_cli") + + list(APPEND mytests http-client-fi-vh5) + add_test(NAME http-client-fi-vh5 COMMAND lws-minimal-http-client --expected-exit 5 --fault-injection "vh/vh_create_srv_init") + + + list(APPEND mytests http-client-fi-dnsfail) + add_test(NAME http-client-fi-dnsfail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi=user/dnsfail") + + if (has_async_dns) + list(APPEND mytests http-client-fi-connfail) + add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi=user/connfail") + else() + list(APPEND mytests http-client-fi-connfail) + add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 2 --fault-injection "wsi=user/connfail") + endif() + + list(APPEND mytests http-client-fi-user-est-fail) + add_test(NAME http-client-fi-user-est-fail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi/user_reject_at_est") + + + endif() + + set_tests_properties(${mytests} PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client + TIMEOUT 20) + + if (DEFINED ENV{SAI_OVN}) + set_tests_properties(${mytests} PROPERTIES + FIXTURES_REQUIRED "res_http_client_warmcat") + endif() + + 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() +endif() diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/README.md b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/README.md new file mode 100644 index 00000000..024f7397 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/README.md @@ -0,0 +1,96 @@ +# lws minimal http client JIT Trust + +This example turns off any existing trusted CAs and then tries to connect to a server, by default, warmcat.com. + +It validates the remote certificates using trusted CAs from a JIT Trust blob compiled into the code. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 +-l| Connect to https://localhost:7681 and accept selfsigned cert +--h1|Specify http/1.1 only using ALPN, rejects h2 even if server supports it +--server |set server name to connect to +-k|Apply tls option LCCSCF_ALLOW_INSECURE +-j|Apply tls option LCCSCF_ALLOW_SELFSIGNED +-m|Apply tls option LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK +-e|Apply tls option LCCSCF_ALLOW_EXPIRED +-v|Connection validity use 3s / 10s instead of default 5m / 5m10s +--nossl| disable ssl connection +--user | Set Basic Auth username +--password | Set Basic Auth password + +``` + $ ./bin/lws-minimal-http-client-jit-trust --h1 --server ebay.com --path / +==1302866== +[2021/06/17 14:33:54:7500] U: LWS minimal http client JIT Trust [-d] [-l] [--h1] +[2021/06/17 14:33:54:7956] N: LWS: 4.2.99-v4.2.0-70-g80e7e39bae, loglevel 1031 +[2021/06/17 14:33:54:7960] N: NET CLI SRV H1 H2 WS MbedTLS ConMon IPv6-absent +[2021/06/17 14:33:54:8165] N: ++ [wsi|0|pipe] (1) +[2021/06/17 14:33:54:8227] N: ++ [vh|0|netlink] (1) +[2021/06/17 14:33:54:8319] N: ++ [vh|1|default||-1] (2) +[2021/06/17 14:33:55:0107] N: ++ [wsicli|0|GET/h1/ebay.com] (1) +[2021/06/17 14:33:56:0291] N: ++ [vh|2|jitt-7F69A044||-1] (3) +[2021/06/17 14:33:56:0355] E: CLIENT_CONNECTION_ERROR: server's cert didn't look good, invalidca (use_ssl 0x20000061) X509_V_ERR = 24: CA is not trusted + +[2021/06/17 14:33:56:0376] N: ++ [wsicli|1|GET/h1/ebay.com] (2) +[2021/06/17 14:33:56:0746] N: -- [wsicli|0|GET/h1/ebay.com] (1) 1.061s +[2021/06/17 14:33:56:7555] N: lws_client_reset: REDIRECT www.ebay.com:443, path='/', ssl = 1, alpn='http/1.1' +[2021/06/17 14:33:57:0205] N: ++ [vh|3|jitt-DFF2B5B4||-1] (4) +[2021/06/17 14:33:57:0208] E: CLIENT_CONNECTION_ERROR: server's cert didn't look good, invalidca (use_ssl 0x1) X509_V_ERR = 24: CA is not trusted + +[2021/06/17 14:33:57:0210] N: ++ [wsicli|2|GET/h1/ebay.com] (2) +[2021/06/17 14:33:57:0288] N: -- [wsicli|1|GET/h1/ebay.com] (1) 991.119ms +[2021/06/17 14:33:57:7528] N: lws_client_reset: REDIRECT www.ebay.com:443, path='/', ssl = 1, alpn='http/1.1' +[2021/06/17 14:33:58:1564] U: Connected to 195.95.193.127, http response: 200 +[2021/06/17 14:33:58:1637] U: RECEIVE_CLIENT_HTTP_READ: read 209 +[2021/06/17 14:33:58:1796] U: RECEIVE_CLIENT_HTTP_READ: read 197 +[2021/06/17 14:33:58:1822] U: RECEIVE_CLIENT_HTTP_READ: read 1014 +[2021/06/17 14:33:58:1847] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:1851] U: RECEIVE_CLIENT_HTTP_READ: read 1022 +[2021/06/17 14:33:58:2748] U: RECEIVE_CLIENT_HTTP_READ: read 242 +[2021/06/17 14:33:58:2782] U: RECEIVE_CLIENT_HTTP_READ: read 1014 +[2021/06/17 14:33:58:2784] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:2785] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +... +[2021/06/17 14:33:58:4661] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4662] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4663] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4664] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4665] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4666] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4667] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4668] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4669] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4670] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4671] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4672] U: RECEIVE_CLIENT_HTTP_READ: read 1024 +[2021/06/17 14:33:58:4673] U: RECEIVE_CLIENT_HTTP_READ: read 286 +[2021/06/17 14:33:58:4690] U: LWS_CALLBACK_COMPLETED_CLIENT_HTTP +[2021/06/17 14:33:58:4712] E: main: destroying context, interrupted = 1 +[2021/06/17 14:33:58:4774] N: -- [wsi|0|pipe] (0) 3.661s +[2021/06/17 14:33:58:4780] N: callback_http: LWS_CALLBACK_CLOSED_CLIENT_HTTP +[2021/06/17 14:33:58:4829] N: -- [vh|3|jitt-DFF2B5B4||-1] (3) 1.462s +[2021/06/17 14:33:58:4833] N: -- [wsicli|2|GET/h1/ebay.com] (0) 1.462s +[2021/06/17 14:33:58:4834] N: -- [vh|0|netlink] (2) 3.660s +[2021/06/17 14:33:58:4858] N: -- [vh|1|default||-1] (1) 3.654s +[2021/06/17 14:33:58:4860] N: -- [vh|2|jitt-7F69A044||-1] (0) 2.456s +[2021/06/17 14:33:58:4974] U: Completed: OK (seen expected 0) +``` + +You can also test the client Basic Auth support against the http-server/minimal-http-server-basicauth +example. In one console window run the server and in the other + +``` +$ lws-minimal-http-client -l --nossl --path /secret/index.html --user user --password password +``` + +The Basic Auth credentials for the test server are literally username "user" and password "password". + diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/minimal-http-client.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/minimal-http-client.c new file mode 100644 index 00000000..92fd04e6 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/minimal-http-client.c @@ -0,0 +1,468 @@ +/* + * lws-minimal-http-client-jit-trust + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates the a minimal http client using lws. + * + * It visits https://warmcat.com/ and receives the html page there. You + * can dump the page data by changing the #if 0 below. + */ + +#include +#include +#include + +static int interrupted, bad = 1, status, conmon; +#if defined(LWS_WITH_HTTP2) +static int long_poll; +#endif +static struct lws *client_wsi; +static const char *ba_user, *ba_password; +static int budget = 6; + +/* + * For this example, we import the C-formatted array version of the trust blob + * directly. This is produced by running scripts/mozilla-trust-gen.sh and can + * be found in ./_trust after that. + */ + +static uint8_t jit_trust_blob[] = { +#include "./trust_blob.h" +}; + +static const lws_retry_bo_t retry = { + .secs_since_valid_ping = 3, + .secs_since_valid_hangup = 10, +}; + +#if defined(LWS_WITH_CONMON) +void +dump_conmon_data(struct lws *wsi) +{ + const struct addrinfo *ai; + struct lws_conmon cm; + char ads[48]; + + lws_conmon_wsi_take(wsi, &cm); + + lws_sa46_write_numeric_address(&cm.peer46, ads, sizeof(ads)); + lwsl_notice("%s: peer %s, dns: %uus, sockconn: %uus, " + "tls: %uus, txn_resp: %uus\n", + __func__, ads, + (unsigned int)cm.ciu_dns, + (unsigned int)cm.ciu_sockconn, + (unsigned int)cm.ciu_tls, + (unsigned int)cm.ciu_txn_resp); + + ai = cm.dns_results_copy; + while (ai) { + lws_sa46_write_numeric_address((lws_sockaddr46 *)ai->ai_addr, + ads, sizeof(ads)); + lwsl_notice("%s: DNS %s\n", __func__, ads); + ai = ai->ai_next; + } + + /* + * This destroys the DNS list in the lws_conmon that we took + * responsibility for when we used lws_conmon_wsi_take() + */ + + lws_conmon_release(&cm); +} +#endif + +struct args { + int argc; + const char **argv; +}; + +static const struct lws_protocols protocols[]; + +static int +try_connect(struct lws_context *cx) +{ + struct lws_client_connect_info i; + struct args *a = lws_context_user(cx); + const char *p; + + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + i.context = cx; + if (!lws_cmdline_option(a->argc, a->argv, "-n")) { + i.ssl_connection = LCCSCF_USE_SSL; +#if defined(LWS_WITH_HTTP2) + /* requires h2 */ + if (lws_cmdline_option(a->argc, a->argv, "--long-poll")) { + lwsl_user("%s: long poll mode\n", __func__); + long_poll = 1; + } +#endif + } + + if (lws_cmdline_option(a->argc, a->argv, "-l")) { + i.port = 7681; + i.address = "localhost"; + i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; + } else { + i.port = 443; + i.address = "warmcat.com"; + } + + if (lws_cmdline_option(a->argc, a->argv, "--nossl")) + i.ssl_connection = 0; + + i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | + LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM | + LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS; + + i.alpn = "h2,http/1.1"; + 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); + + if ((p = lws_cmdline_option(a->argc, a->argv, "--user"))) + ba_user = p; + if ((p = lws_cmdline_option(a->argc, a->argv, "--password"))) + ba_password = p; + + if (lws_cmdline_option(a->argc, a->argv, "-j")) + i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; + + if (lws_cmdline_option(a->argc, a->argv, "-k")) + i.ssl_connection |= LCCSCF_ALLOW_INSECURE; + + if (lws_cmdline_option(a->argc, a->argv, "-m")) + i.ssl_connection |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; + + if (lws_cmdline_option(a->argc, a->argv, "-e")) + i.ssl_connection |= LCCSCF_ALLOW_EXPIRED; + + if ((p = lws_cmdline_option(a->argc, a->argv, "-f"))) { + i.ssl_connection |= LCCSCF_H2_MANUAL_RXFLOW; + i.manual_initial_tx_credit = atoi(p); + lwsl_notice("%s: manual peer tx credit %d\n", __func__, + i.manual_initial_tx_credit); + } + +#if defined(LWS_WITH_CONMON) + if (lws_cmdline_option(a->argc, a->argv, "--conmon")) { + i.ssl_connection |= LCCSCF_CONMON; + conmon = 1; + } +#endif + + /* the default validity check is 5m / 5m10s... -v = 3s / 10s */ + + if (lws_cmdline_option(a->argc, a->argv, "-v")) + i.retry_and_idle_policy = &retry; + + if ((p = lws_cmdline_option(a->argc, a->argv, "--server"))) + i.address = p; + + if ((p = lws_cmdline_option(a->argc, a->argv, "--path"))) + i.path = p; + else + i.path = "/"; + + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + + i.protocol = protocols[0].name; + i.pwsi = &client_wsi; + i.fi_wsi_name = "user"; + + if (!lws_client_connect_via_info(&i)) { + lwsl_err("Client creation failed\n"); + interrupted = 1; + bad = 2; /* could not even start client connection */ + lws_cancel_service(cx); + + return 1; + } + + return 0; +} + +static const char *ua = "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/51.0.2704.103 Safari/537.36", + *acc = "*/*"; + +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)"); + + if (budget--) { + try_connect(lws_get_context(wsi)); + break; + } + + interrupted = 1; + bad = 3; /* connection failed before we could make connection */ + lws_cancel_service(lws_get_context(wsi)); + +#if defined(LWS_WITH_CONMON) + if (conmon) + dump_conmon_data(wsi); +#endif + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + { + char buf[128]; + + lws_get_peer_simple(wsi, buf, sizeof(buf)); + status = (int)lws_http_client_http_response(wsi); + + lwsl_user("Connected to %s, http response: %d\n", + buf, status); + } +#if defined(LWS_WITH_HTTP2) + if (long_poll) { + lwsl_user("%s: Client entering long poll mode\n", __func__); + lws_h2_client_stream_long_poll_rxonly(wsi); + } +#endif + + if (lws_fi_user_wsi_fi(wsi, "user_reject_at_est")) + return -1; + + break; + + + case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: + { + unsigned char **p = (unsigned char **)in, *end = (*p) + len; + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_USER_AGENT, + (unsigned char *)ua, (int)strlen(ua), p, end)) + return -1; + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ACCEPT, + (unsigned char *)acc, (int)strlen(acc), p, end)) + return -1; + +#if defined(LWS_WITH_HTTP_BASIC_AUTH) + { + char b[128]; + + /* you only need this if you need to do Basic Auth */ + + if (!ba_user || !ba_password) + break; + + if (lws_http_basic_auth_gen(ba_user, ba_password, b, sizeof(b))) + break; + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_AUTHORIZATION, + (unsigned char *)b, (int)strlen(b), p, end)) + return -1; + } +#endif + + 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 defined(LWS_WITH_HTTP2) + if (long_poll) { + char dotstar[128]; + lws_strnncpy(dotstar, (const char *)in, len, + sizeof(dotstar)); + lwsl_notice("long poll rx: %d '%s'\n", (int)len, + dotstar); + } +#endif +#if 0 + lwsl_hexdump_notice(in, len); +#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_fi_user_wsi_fi(wsi, "user_reject_at_rx")) + return -1; + + 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 = 0; // we accept 403 or whatever for this test status != 200; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + lwsl_notice("%s: LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", __func__); + interrupted = 1; + bad = 0; // status != 200; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ +#if defined(LWS_WITH_CONMON) + if (conmon) + dump_conmon_data(wsi); +#endif + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, 0, 0, NULL, 0 + }, + LWS_PROTOCOL_LIST_TERM +}; + +static 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 *cx = mgr->parent; + + if (current != LWS_SYSTATE_OPERATIONAL || + target != LWS_SYSTATE_OPERATIONAL) + return 0; + + lwsl_info("%s: operational\n", __func__); + + try_connect(cx); + + return 0; +} + +static int +jit_trust_query(struct lws_context *cx, const uint8_t *skid, + size_t skid_len, void *got_opaque) +{ + const uint8_t *der = NULL; + size_t der_len = 0; + + lwsl_info("%s\n", __func__); + lwsl_hexdump_info(skid, skid_len); + + /* + * For this example, we look up SKIDs using a trust table that's + * compiled in, synchronously. Lws provides the necessary helper. + * + * DER will remain NULL if no match. + */ + + lws_tls_jit_trust_blob_queury_skid(jit_trust_blob, + sizeof(jit_trust_blob), skid, + skid_len, &der, &der_len); + + if (der) + lwsl_info("%s: found len %d\n", __func__, (int)der_len); + else + lwsl_info("%s: not trusted\n", __func__); + + /* Once we have a result, pass it to the completion helper */ + + return lws_tls_jit_trust_got_cert_cb(cx, got_opaque, skid, skid_len, + der, der_len); +} + +static lws_system_ops_t system_ops = { + .jit_trust_query = jit_trust_query +}; + +int main(int argc, const char **argv) +{ + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + struct lws_context_creation_info info; + struct lws_context *context; + int n = 0, expected = 0; + struct args args; + const char *p; + + args.argc = argc; + args.argv = argv; + + 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 client JIT Trust [-d] [-l] [--h1]\n"); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | + /* we start off not trusting anything */ + LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS | + LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.protocols = protocols; + info.user = &args; + info.register_notifier_list = na; + info.connect_timeout_secs = 30; + info.system_ops = &system_ops; + info.fd_limit_per_thread = 1 + 6 + 1; + info.max_http_header_data = 8192; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + bad = 5; + goto bail; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lwsl_err("%s: destroying context, interrupted = %d\n", __func__, + interrupted); + + lws_context_destroy(context); + +bail: + if ((p = lws_cmdline_option(argc, argv, "--expected-exit"))) + expected = atoi(p); + + if (bad == expected) { + lwsl_user("Completed: OK (seen expected %d)\n", expected); + return 0; + } + + lwsl_err("Completed: failed: exit %d, expected %d\n", bad, expected); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/trust_blob.h b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/trust_blob.h new file mode 100644 index 00000000..615d1dfc --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/trust_blob.h @@ -0,0 +1,8931 @@ +0x54, 0x42, 0x4c, 0x42, 0x00, 0x01, 0x00, 0x80, 0x60, 0xc6, 0xf3, 0x12, 0x00, 0x02, 0x22, 0xd8, +0x00, 0x02, 0x23, 0xd8, 0x00, 0x02, 0x24, 0x58, 0x00, 0x02, 0x2e, 0x30, 0x30, 0x82, 0x05, 0x82, +0x30, 0x82, 0x03, 0x6a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0b, 0x5a, 0x4b, 0xbd, 0x5a, 0xfb, +0x4f, 0x8a, 0x5b, 0xfa, 0x65, 0xe5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x4d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1a, 0x65, +0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, +0x72, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x10, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, +0x32, 0x30, 0x32, 0x30, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x32, 0x31, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x30, 0x36, 0x31, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x5a, 0x30, 0x4d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1a, 0x65, 0x2d, +0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, +0x69, 0x6e, 0x67, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x10, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x32, +0x30, 0x32, 0x30, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, +0x82, 0x02, 0x01, 0x00, 0xae, 0x2e, 0x56, 0xad, 0x1b, 0x1c, 0xef, 0xf6, 0x95, 0x8f, 0xa0, 0x77, +0x1b, 0x2b, 0xd3, 0x63, 0x8f, 0x84, 0x4d, 0x45, 0xa2, 0x0f, 0x9f, 0x5b, 0x45, 0xab, 0x59, 0x7b, +0x51, 0x34, 0xf9, 0xec, 0x8b, 0x8a, 0x78, 0xc5, 0xdd, 0x6b, 0xaf, 0xbd, 0xc4, 0xdf, 0x93, 0x45, +0x1e, 0xbf, 0x91, 0x38, 0x0b, 0xae, 0x0e, 0x16, 0xe7, 0x41, 0x73, 0xf8, 0xdb, 0xbb, 0xd1, 0xb8, +0x51, 0xe0, 0xcb, 0x83, 0x3b, 0x73, 0x38, 0x6e, 0x77, 0x8a, 0x0f, 0x59, 0x63, 0x26, 0xcd, 0xa7, +0x2a, 0xce, 0x54, 0xfb, 0xb8, 0xe2, 0xc0, 0x7c, 0x47, 0xce, 0x60, 0x7c, 0x3f, 0xb2, 0x73, 0xf2, +0xc0, 0x19, 0xb6, 0x8a, 0x92, 0x87, 0x35, 0x0d, 0x90, 0x28, 0xa2, 0xe4, 0x15, 0x04, 0x63, 0x3e, +0xba, 0xaf, 0xee, 0x7c, 0x5e, 0xcc, 0xa6, 0x8b, 0x50, 0xb2, 0x38, 0xf7, 0x41, 0x63, 0xca, 0xce, +0xff, 0x69, 0x8f, 0x68, 0x0e, 0x95, 0x36, 0xe5, 0xcc, 0xb9, 0x8c, 0x09, 0xca, 0x4b, 0xdd, 0x31, +0x90, 0x96, 0xc8, 0xcc, 0x1f, 0xfd, 0x56, 0x96, 0x34, 0xdb, 0x8e, 0x1c, 0xea, 0x2c, 0xbe, 0x85, +0x2e, 0x63, 0xdd, 0xaa, 0xa9, 0x95, 0xd3, 0xfd, 0x29, 0x95, 0x13, 0xf0, 0xc8, 0x98, 0x93, 0xd9, +0x2d, 0x16, 0x47, 0x90, 0x11, 0x83, 0xa2, 0x3a, 0x22, 0xa2, 0x28, 0x57, 0xa2, 0xeb, 0xfe, 0xc0, +0x8c, 0x28, 0xa0, 0xa6, 0x7d, 0xe7, 0x2a, 0x42, 0x3b, 0x82, 0x80, 0x63, 0xa5, 0x63, 0x1f, 0x19, +0xcc, 0x7c, 0xb2, 0x66, 0xa8, 0xc2, 0xd3, 0x6d, 0x37, 0x6f, 0xe2, 0x7e, 0x06, 0x51, 0xd9, 0x45, +0x84, 0x1f, 0x12, 0xce, 0x24, 0x52, 0x64, 0x85, 0x0b, 0x48, 0x80, 0x4e, 0x87, 0xb1, 0x22, 0x22, +0x30, 0xaa, 0xeb, 0xae, 0xbe, 0xe0, 0x02, 0xe0, 0x40, 0xe8, 0xb0, 0x42, 0x80, 0x03, 0x51, 0xaa, +0xb4, 0x7e, 0xaa, 0x44, 0xd7, 0x43, 0x61, 0xf3, 0xa2, 0x6b, 0x16, 0x89, 0x49, 0xa4, 0xa3, 0xa4, +0x2b, 0x8a, 0x02, 0xc4, 0x78, 0xf4, 0x68, 0x8a, 0xc1, 0xe4, 0x7a, 0x36, 0xb1, 0x6f, 0x1b, 0x96, +0x1b, 0x77, 0x49, 0x8d, 0xd4, 0xc9, 0x06, 0x72, 0x8f, 0xcf, 0x53, 0xe3, 0xdc, 0x17, 0x85, 0x20, +0x4a, 0xdc, 0x98, 0x27, 0xd3, 0x91, 0x26, 0x2b, 0x47, 0x1e, 0x69, 0x07, 0xaf, 0xde, 0xa2, 0xe4, +0xe4, 0xd4, 0x6b, 0x0b, 0xb3, 0x5e, 0x7c, 0xd4, 0x24, 0x80, 0x47, 0x29, 0x69, 0x3b, 0x6e, 0xe8, +0xac, 0xfd, 0x40, 0xeb, 0xd8, 0xed, 0x71, 0x71, 0x2b, 0xf2, 0xe8, 0x58, 0x1d, 0xeb, 0x41, 0x97, +0x22, 0xc5, 0x1f, 0xd4, 0x39, 0xd0, 0x27, 0x8f, 0x87, 0xe3, 0x18, 0xf4, 0xe0, 0xa9, 0x46, 0x0d, +0xf5, 0x74, 0x3a, 0x82, 0x2e, 0xd0, 0x6e, 0x2c, 0x91, 0xa3, 0x31, 0x5c, 0x3b, 0x46, 0xea, 0x7b, +0x04, 0x10, 0x56, 0x5e, 0x80, 0x1d, 0xf5, 0xa5, 0x65, 0xe8, 0x82, 0xfc, 0xe2, 0x07, 0x8c, 0x62, +0x45, 0xf5, 0x20, 0xde, 0x46, 0x70, 0x86, 0xa1, 0xbc, 0x93, 0xd3, 0x1e, 0x74, 0xa6, 0x6c, 0xb0, +0x2c, 0xf7, 0x03, 0x0c, 0x88, 0x0c, 0xcb, 0xd4, 0x72, 0x53, 0x86, 0xbc, 0x60, 0x46, 0xf3, 0x98, +0x6a, 0xc2, 0xf1, 0xbf, 0x43, 0xf9, 0x70, 0x20, 0x77, 0xca, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63, +0x8d, 0x5b, 0x12, 0x9f, 0xc5, 0x68, 0xc4, 0x88, 0x9d, 0xac, 0xf2, 0x30, 0xab, 0xb7, 0xa3, 0x31, +0x97, 0x67, 0xad, 0x8f, 0x17, 0x0f, 0x6c, 0xc7, 0x73, 0xed, 0x24, 0x94, 0x6b, 0xc8, 0x83, 0x9a, +0xd0, 0x9a, 0x37, 0x49, 0x04, 0xab, 0xb1, 0x16, 0xc8, 0x6c, 0x49, 0x49, 0x2d, 0xab, 0xa1, 0xd0, +0x8c, 0x92, 0xf2, 0x41, 0x4a, 0x79, 0x21, 0x25, 0xdb, 0x63, 0xd7, 0xb6, 0x9c, 0xa7, 0x7e, 0x42, +0x69, 0xfb, 0x3a, 0x63, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdc, 0x2e, 0x1f, 0xd1, 0x61, 0x37, 0x79, +0xe4, 0xab, 0xd5, 0xd5, 0xb3, 0x12, 0x71, 0x68, 0x3d, 0x6a, 0x68, 0x9c, 0x22, 0x30, 0x1f, 0x06, +0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xdc, 0x2e, 0x1f, 0xd1, 0x61, 0x37, +0x79, 0xe4, 0xab, 0xd5, 0xd5, 0xb3, 0x12, 0x71, 0x68, 0x3d, 0x6a, 0x68, 0x9c, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, +0x01, 0x00, 0x91, 0xf0, 0x42, 0x02, 0x68, 0x40, 0xee, 0xc3, 0x68, 0xc0, 0x54, 0x2f, 0xdf, 0xec, +0x62, 0xc3, 0xc3, 0x9e, 0x8a, 0xa0, 0x31, 0x28, 0xaa, 0x83, 0x8e, 0xa4, 0x56, 0x96, 0x12, 0x10, +0x86, 0x56, 0xba, 0x97, 0x72, 0xd2, 0x54, 0x30, 0x7c, 0xad, 0x19, 0xd5, 0x1d, 0x68, 0x6f, 0xfb, +0x14, 0x42, 0xd8, 0x8d, 0x0e, 0xf3, 0xb5, 0xd1, 0xa5, 0xe3, 0x02, 0x42, 0x5e, 0xdc, 0xe8, 0x46, +0x58, 0x07, 0x35, 0x02, 0x30, 0xe0, 0xbc, 0x74, 0x4a, 0xc1, 0x43, 0x2a, 0xff, 0xdb, 0x1a, 0xd0, +0xb0, 0xaf, 0x6c, 0xc3, 0xfd, 0xcb, 0xb3, 0xf5, 0x7f, 0x6d, 0x03, 0x2e, 0x59, 0x56, 0x9d, 0x2d, +0x2d, 0x35, 0x8c, 0xb2, 0xd6, 0x43, 0x17, 0x2c, 0x92, 0x0a, 0xcb, 0x5d, 0xe8, 0x8c, 0x0f, 0x4b, +0x70, 0x43, 0xd0, 0x82, 0xff, 0xa8, 0xcc, 0xbf, 0xa4, 0x94, 0xc0, 0xbe, 0x87, 0xbd, 0x8a, 0xe3, +0x93, 0x7b, 0xc6, 0x8f, 0x9b, 0x16, 0x9d, 0x27, 0x65, 0xbc, 0x7a, 0xc5, 0x42, 0x82, 0x6c, 0x5c, +0x07, 0xd0, 0xa9, 0xc1, 0x88, 0x60, 0x44, 0xe9, 0x98, 0x85, 0x16, 0x5f, 0xf8, 0x8f, 0xca, 0x01, +0x10, 0xce, 0x25, 0xc3, 0xf9, 0x60, 0x1b, 0xa0, 0xc5, 0x97, 0xc3, 0xd3, 0x2c, 0x88, 0x31, 0xa2, +0xbd, 0x30, 0xec, 0xd0, 0xd0, 0xc0, 0x12, 0xf1, 0xc1, 0x39, 0xe3, 0xe5, 0xf5, 0xf8, 0xd6, 0x4a, +0xdd, 0x34, 0xcd, 0xfb, 0x6f, 0xc1, 0x4f, 0xe3, 0x00, 0x8b, 0x56, 0xe2, 0x92, 0xf7, 0x28, 0xb2, +0x42, 0x77, 0x72, 0x23, 0x67, 0xc7, 0x3f, 0x11, 0x15, 0xb2, 0xc4, 0x03, 0x05, 0xbe, 0xbb, 0x11, +0x7b, 0x0a, 0xbf, 0xa8, 0x6e, 0xe7, 0xff, 0x58, 0x43, 0xcf, 0x9b, 0x67, 0xa0, 0x80, 0x07, 0xb6, +0x1d, 0xca, 0xad, 0x6d, 0xea, 0x41, 0x11, 0x7e, 0x2d, 0x74, 0x93, 0xfb, 0xc2, 0xbc, 0xbe, 0x51, +0x44, 0xc5, 0xef, 0x68, 0x25, 0x27, 0x80, 0xe3, 0xc8, 0xa0, 0xd4, 0x12, 0xec, 0xd9, 0xa5, 0x37, +0x1d, 0x37, 0x7c, 0xb4, 0x91, 0xca, 0xda, 0xd4, 0xb1, 0x96, 0x81, 0xef, 0x68, 0x5c, 0x76, 0x10, +0x49, 0xaf, 0x7e, 0xa5, 0x37, 0x80, 0xb1, 0x1c, 0x52, 0xbd, 0x33, 0x81, 0x4c, 0x8f, 0xf9, 0xdd, +0x65, 0xd9, 0x14, 0xcd, 0x8a, 0x25, 0x58, 0xf4, 0xe2, 0xc5, 0x83, 0xa5, 0x09, 0x90, 0xd4, 0x6c, +0x14, 0x63, 0xb5, 0x40, 0xdf, 0xeb, 0xc0, 0xfc, 0xc4, 0x58, 0x7e, 0x0d, 0x14, 0x16, 0x87, 0x54, +0x27, 0x6e, 0x56, 0xe4, 0x70, 0x84, 0xb8, 0x6c, 0x32, 0x12, 0x7e, 0x82, 0x31, 0x43, 0xbe, 0xd7, +0xdd, 0x7c, 0xa1, 0xad, 0xae, 0xd6, 0xab, 0x20, 0x12, 0xef, 0x0a, 0xc3, 0x10, 0x8c, 0x49, 0x96, +0x35, 0xdc, 0x0b, 0x75, 0x5e, 0xb1, 0x4f, 0xd5, 0x4f, 0x34, 0x0e, 0x11, 0x20, 0x07, 0x75, 0x43, +0x45, 0xe9, 0xa3, 0x11, 0xda, 0xac, 0xa3, 0x99, 0xc2, 0xb6, 0x79, 0x27, 0xe2, 0xb9, 0xef, 0xc8, +0xe2, 0xf6, 0x35, 0x29, 0x7a, 0x74, 0xfa, 0xc5, 0x7f, 0x82, 0x05, 0x62, 0xa6, 0x0a, 0xea, 0x68, +0xb2, 0x79, 0x47, 0x06, 0x6e, 0xf2, 0x57, 0xa8, 0x15, 0x33, 0xc6, 0xf7, 0x78, 0x4a, 0x3d, 0x42, +0x7b, 0x6b, 0x7e, 0xfe, 0xf7, 0x46, 0xea, 0xd1, 0xeb, 0x8e, 0xef, 0x88, 0x68, 0x5b, 0xe8, 0xc1, +0xd9, 0x71, 0x7e, 0xfd, 0x64, 0xef, 0xff, 0x67, 0x47, 0x88, 0x58, 0x25, 0x2f, 0x3e, 0x86, 0x07, +0xbd, 0xfb, 0xa8, 0xe5, 0x82, 0xa8, 0xac, 0xa5, 0xd3, 0x69, 0x43, 0xcd, 0x31, 0x88, 0x49, 0x84, +0x53, 0x92, 0xc0, 0xb1, 0x39, 0x1b, 0x39, 0x83, 0x01, 0x30, 0xc4, 0xf2, 0xa9, 0xfa, 0xd0, 0x03, +0xbd, 0x72, 0x37, 0x60, 0x56, 0x1f, 0x36, 0x7c, 0xbd, 0x39, 0x91, 0xf5, 0x6d, 0x0d, 0xbf, 0x7b, +0xd7, 0x92, 0x30, 0x82, 0x02, 0x59, 0x30, 0x82, 0x01, 0xdf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x10, 0x66, 0xf2, 0x3d, 0xaf, 0x87, 0xde, 0x8b, 0xb1, 0x4a, 0xea, 0x0c, 0x57, 0x31, 0x01, 0xc2, +0xec, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x65, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, +0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36, 0x30, 0x34, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, +0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, +0x32, 0x30, 0x31, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x31, 0x38, 0x32, 0x33, +0x30, 0x36, 0x34, 0x35, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x37, 0x31, 0x38, 0x32, 0x33, 0x31, +0x36, 0x30, 0x34, 0x5a, 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, +0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4d, 0x69, +0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, +0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x76, 0x30, 0x10, 0x06, +0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, +0x62, 0x00, 0x04, 0xd4, 0xbc, 0x3d, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xcd, 0x80, 0x04, 0x86, +0x02, 0x51, 0x2f, 0x6a, 0xa8, 0x81, 0x62, 0x0b, 0x65, 0xcc, 0xf6, 0xca, 0x9d, 0x1e, 0x6f, 0x4a, +0x66, 0x51, 0xa2, 0x03, 0xd9, 0x9d, 0x91, 0xfa, 0xb6, 0x16, 0xb1, 0x8c, 0x6e, 0xde, 0x7c, 0xcd, +0xdb, 0x79, 0xa6, 0x2f, 0xce, 0xbb, 0xce, 0x71, 0x2f, 0xe5, 0xa5, 0xab, 0x28, 0xec, 0x63, 0x04, +0x66, 0x99, 0xf8, 0xfa, 0xf2, 0x93, 0x10, 0x05, 0xe1, 0x81, 0x28, 0x42, 0xe3, 0xc6, 0x68, 0xf4, +0xe6, 0x1b, 0x84, 0x60, 0x4a, 0x89, 0xaf, 0xed, 0x79, 0x0f, 0x3b, 0xce, 0xf1, 0xf6, 0x44, 0xf5, +0x01, 0x78, 0xc0, 0xa3, 0x54, 0x30, 0x52, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, +0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0xc8, 0xcb, 0x99, 0x72, 0x70, 0x52, 0x0c, 0xf8, 0xe6, 0xbe, 0xb2, 0x04, 0x57, +0x29, 0x2a, 0xcf, 0x42, 0x10, 0xed, 0x35, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, +0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x58, 0xf2, 0x4d, 0xea, +0x0c, 0xf9, 0x5f, 0x5e, 0xee, 0x60, 0x29, 0xcb, 0x3a, 0xf2, 0xdb, 0xd6, 0x32, 0x84, 0x19, 0x3f, +0x7c, 0xd5, 0x2f, 0xc2, 0xb1, 0xcc, 0x93, 0xae, 0x50, 0xbb, 0x09, 0x32, 0xc6, 0xc6, 0xed, 0x7e, +0xc9, 0x36, 0x94, 0x12, 0xe4, 0x68, 0x85, 0x06, 0xa2, 0x1b, 0xd0, 0x2f, 0x02, 0x31, 0x00, 0x99, +0xe9, 0x16, 0xb4, 0x0e, 0xfa, 0x56, 0x48, 0xd4, 0xa4, 0x30, 0x16, 0x91, 0x78, 0xdb, 0x54, 0x8c, +0x65, 0x01, 0x8a, 0xe7, 0x50, 0x66, 0xc2, 0x31, 0xb7, 0x39, 0xba, 0xb8, 0x1a, 0x22, 0x07, 0x4e, +0xfc, 0x6b, 0x54, 0x16, 0x20, 0xff, 0x2b, 0xb5, 0xe7, 0x4c, 0x0c, 0x4d, 0xa6, 0x4f, 0x73, 0x30, +0x82, 0x05, 0xa8, 0x30, 0x82, 0x03, 0x90, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x1e, 0xd3, +0x97, 0x09, 0x5f, 0xd8, 0xb4, 0xb3, 0x47, 0x70, 0x1e, 0xaa, 0xbe, 0x7f, 0x45, 0xb3, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x65, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, +0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36, 0x30, 0x34, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, +0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, +0x32, 0x30, 0x31, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x31, 0x38, 0x32, 0x32, +0x35, 0x31, 0x32, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x37, 0x31, 0x38, 0x32, 0x33, 0x30, +0x30, 0x32, 0x33, 0x5a, 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, +0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4d, 0x69, +0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, +0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x82, 0x02, 0x22, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, +0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xca, 0x5b, 0xbe, 0x94, +0x33, 0x8c, 0x29, 0x95, 0x91, 0x16, 0x0a, 0x95, 0xbd, 0x47, 0x62, 0xc1, 0x89, 0xf3, 0x99, 0x36, +0xdf, 0x46, 0x90, 0xc9, 0xa5, 0xed, 0x78, 0x6a, 0x6f, 0x47, 0x91, 0x68, 0xf8, 0x27, 0x67, 0x50, +0x33, 0x1d, 0xa1, 0xa6, 0xfb, 0xe0, 0xe5, 0x43, 0xa3, 0x84, 0x02, 0x57, 0x01, 0x5d, 0x9c, 0x48, +0x40, 0x82, 0x53, 0x10, 0xbc, 0xbf, 0xc7, 0x3b, 0x68, 0x90, 0xb6, 0x82, 0x2d, 0xe5, 0xf4, 0x65, +0xd0, 0xcc, 0x6d, 0x19, 0xcc, 0x95, 0xf9, 0x7b, 0xac, 0x4a, 0x94, 0xad, 0x0e, 0xde, 0x4b, 0x43, +0x1d, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, 0xfc, 0xe5, 0xe9, 0x6c, +0xb3, 0xb6, 0x1f, 0x50, 0x94, 0x38, 0x65, 0x50, 0x5c, 0x17, 0x46, 0xb9, 0xb6, 0x85, 0xb5, 0x1c, +0xb5, 0x17, 0xe8, 0xd6, 0x45, 0x9d, 0xd8, 0xb2, 0x26, 0xb0, 0xca, 0xc4, 0x70, 0x4a, 0xae, 0x60, +0xa4, 0xdd, 0xb3, 0xd9, 0xec, 0xfc, 0x3b, 0xd5, 0x57, 0x72, 0xbc, 0x3f, 0xc8, 0xc9, 0xb2, 0xde, +0x4b, 0x6b, 0xf8, 0x23, 0x6c, 0x03, 0xc0, 0x05, 0xbd, 0x95, 0xc7, 0xcd, 0x73, 0x3b, 0x66, 0x80, +0x64, 0xe3, 0x1a, 0xac, 0x2e, 0xf9, 0x47, 0x05, 0xf2, 0x06, 0xb6, 0x9b, 0x73, 0xf5, 0x78, 0x33, +0x5b, 0xc7, 0xa1, 0xfb, 0x27, 0x2a, 0xa1, 0xb4, 0x9a, 0x91, 0x8c, 0x91, 0xd3, 0x3a, 0x82, 0x3e, +0x76, 0x40, 0xb4, 0xcd, 0x52, 0x61, 0x51, 0x70, 0x28, 0x3f, 0xc5, 0xc5, 0x5a, 0xf2, 0xc9, 0x8c, +0x49, 0xbb, 0x14, 0x5b, 0x4d, 0xc8, 0xff, 0x67, 0x4d, 0x4c, 0x12, 0x96, 0xad, 0xf5, 0xfe, 0x78, +0xa8, 0x97, 0x87, 0xd7, 0xfd, 0x5e, 0x20, 0x80, 0xdc, 0xa1, 0x4b, 0x22, 0xfb, 0xd4, 0x89, 0xad, +0xba, 0xce, 0x47, 0x97, 0x47, 0x55, 0x7b, 0x8f, 0x45, 0xc8, 0x67, 0x28, 0x84, 0x95, 0x1c, 0x68, +0x30, 0xef, 0xef, 0x49, 0xe0, 0x35, 0x7b, 0x64, 0xe7, 0x98, 0xb0, 0x94, 0xda, 0x4d, 0x85, 0x3b, +0x3e, 0x55, 0xc4, 0x28, 0xaf, 0x57, 0xf3, 0x9e, 0x13, 0xdb, 0x46, 0x27, 0x9f, 0x1e, 0xa2, 0x5e, +0x44, 0x83, 0xa4, 0xa5, 0xca, 0xd5, 0x13, 0xb3, 0x4b, 0x3f, 0xc4, 0xe3, 0xc2, 0xe6, 0x86, 0x61, +0xa4, 0x52, 0x30, 0xb9, 0x7a, 0x20, 0x4f, 0x6f, 0x0f, 0x38, 0x53, 0xcb, 0x33, 0x0c, 0x13, 0x2b, +0x8f, 0xd6, 0x9a, 0xbd, 0x2a, 0xc8, 0x2d, 0xb1, 0x1c, 0x7d, 0x4b, 0x51, 0xca, 0x47, 0xd1, 0x48, +0x27, 0x72, 0x5d, 0x87, 0xeb, 0xd5, 0x45, 0xe6, 0x48, 0x65, 0x9d, 0xaf, 0x52, 0x90, 0xba, 0x5b, +0xa2, 0x18, 0x65, 0x57, 0x12, 0x9f, 0x68, 0xb9, 0xd4, 0x15, 0x6b, 0x94, 0xc4, 0x69, 0x22, 0x98, +0xf4, 0x33, 0xe0, 0xed, 0xf9, 0x51, 0x8e, 0x41, 0x50, 0xc9, 0x34, 0x4f, 0x76, 0x90, 0xac, 0xfc, +0x38, 0xc1, 0xd8, 0xe1, 0x7b, 0xb9, 0xe3, 0xe3, 0x94, 0xe1, 0x46, 0x69, 0xcb, 0x0e, 0x0a, 0x50, +0x6b, 0x13, 0xba, 0xac, 0x0f, 0x37, 0x5a, 0xb7, 0x12, 0xb5, 0x90, 0x81, 0x1e, 0x56, 0xae, 0x57, +0x22, 0x86, 0xd9, 0xc9, 0xd2, 0xd1, 0xd7, 0x51, 0xe3, 0xab, 0x3b, 0xc6, 0x55, 0xfd, 0x1e, 0x0e, +0xd3, 0x74, 0x0a, 0xd1, 0xda, 0xaa, 0xea, 0x69, 0xb8, 0x97, 0x28, 0x8f, 0x48, 0xc4, 0x07, 0xf8, +0x52, 0x43, 0x3a, 0xf4, 0xca, 0x55, 0x35, 0x2c, 0xb0, 0xa6, 0x6a, 0xc0, 0x9c, 0xf9, 0xf2, 0x81, +0xe1, 0x12, 0x6a, 0xc0, 0x45, 0xd9, 0x67, 0xb3, 0xce, 0xff, 0x23, 0xa2, 0x89, 0x0a, 0x54, 0xd4, +0x14, 0xb9, 0x2a, 0xa8, 0xd7, 0xec, 0xf9, 0xab, 0xcd, 0x25, 0x58, 0x32, 0x79, 0x8f, 0x90, 0x5b, +0x98, 0x39, 0xc4, 0x08, 0x06, 0xc1, 0xac, 0x7f, 0x0e, 0x3d, 0x00, 0xa5, 0x02, 0x03, 0x01, 0x00, +0x01, 0xa3, 0x54, 0x30, 0x52, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0x09, 0xcb, 0x59, 0x7f, 0x86, 0xb2, 0x70, 0x8f, 0x1a, 0xc3, 0x39, 0xe3, 0xc0, 0xd9, 0xe9, +0xbf, 0xbb, 0x4d, 0xb2, 0x23, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, +0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xac, 0xaf, 0x3e, 0x5d, 0xc2, +0x11, 0x96, 0x89, 0x8e, 0xa3, 0xe7, 0x92, 0xd6, 0x97, 0x15, 0xb8, 0x13, 0xa2, 0xa6, 0x42, 0x2e, +0x02, 0xcd, 0x16, 0x05, 0x59, 0x27, 0xca, 0x20, 0xe8, 0xba, 0xb8, 0xe8, 0x1a, 0xec, 0x4d, 0xa8, +0x97, 0x56, 0xae, 0x65, 0x43, 0xb1, 0x8f, 0x00, 0x9b, 0x52, 0xcd, 0x55, 0xcd, 0x53, 0x39, 0x6d, +0x62, 0x4c, 0x8b, 0x0d, 0x5b, 0x7c, 0x2e, 0x44, 0xbf, 0x83, 0x10, 0x8f, 0xf3, 0x53, 0x82, 0x80, +0xc3, 0x4f, 0x3a, 0xc7, 0x6e, 0x11, 0x3f, 0xe6, 0xe3, 0x16, 0x91, 0x84, 0xfb, 0x6d, 0x84, 0x7f, +0x34, 0x74, 0xad, 0x89, 0xa7, 0xce, 0xb9, 0xd7, 0xd7, 0x9f, 0x84, 0x64, 0x92, 0xbe, 0x95, 0xa1, +0xad, 0x09, 0x53, 0x33, 0xdd, 0xee, 0x0a, 0xea, 0x4a, 0x51, 0x8e, 0x6f, 0x55, 0xab, 0xba, 0xb5, +0x94, 0x46, 0xae, 0x8c, 0x7f, 0xd8, 0xa2, 0x50, 0x25, 0x65, 0x60, 0x80, 0x46, 0xdb, 0x33, 0x04, +0xae, 0x6c, 0xb5, 0x98, 0x74, 0x54, 0x25, 0xdc, 0x93, 0xe4, 0xf8, 0xe3, 0x55, 0x15, 0x3d, 0xb8, +0x6d, 0xc3, 0x0a, 0xa4, 0x12, 0xc1, 0x69, 0x85, 0x6e, 0xdf, 0x64, 0xf1, 0x53, 0x99, 0xe1, 0x4a, +0x75, 0x20, 0x9d, 0x95, 0x0f, 0xe4, 0xd6, 0xdc, 0x03, 0xf1, 0x59, 0x18, 0xe8, 0x47, 0x89, 0xb2, +0x57, 0x5a, 0x94, 0xb6, 0xa9, 0xd8, 0x17, 0x2b, 0x17, 0x49, 0xe5, 0x76, 0xcb, 0xc1, 0x56, 0x99, +0x3a, 0x37, 0xb1, 0xff, 0x69, 0x2c, 0x91, 0x91, 0x93, 0xe1, 0xdf, 0x4c, 0xa3, 0x37, 0x76, 0x4d, +0xa1, 0x9f, 0xf8, 0x6d, 0x1e, 0x1d, 0xd3, 0xfa, 0xec, 0xfb, 0xf4, 0x45, 0x1d, 0x13, 0x6d, 0xcf, +0xf7, 0x59, 0xe5, 0x22, 0x27, 0x72, 0x2b, 0x86, 0xf3, 0x57, 0xbb, 0x30, 0xed, 0x24, 0x4d, 0xdc, +0x7d, 0x56, 0xbb, 0xa3, 0xb3, 0xf8, 0x34, 0x79, 0x89, 0xc1, 0xe0, 0xf2, 0x02, 0x61, 0xf7, 0xa6, +0xfc, 0x0f, 0xbb, 0x1c, 0x17, 0x0b, 0xae, 0x41, 0xd9, 0x7c, 0xbd, 0x27, 0xa3, 0xfd, 0x2e, 0x3a, +0xd1, 0x93, 0x94, 0xb1, 0x73, 0x1d, 0x24, 0x8b, 0xaf, 0x5b, 0x20, 0x89, 0xad, 0xb7, 0x67, 0x66, +0x79, 0xf5, 0x3a, 0xc6, 0xa6, 0x96, 0x33, 0xfe, 0x53, 0x92, 0xc8, 0x46, 0xb1, 0x11, 0x91, 0xc6, +0x99, 0x7f, 0x8f, 0xc9, 0xd6, 0x66, 0x31, 0x20, 0x41, 0x10, 0x87, 0x2d, 0x0c, 0xd6, 0xc1, 0xaf, +0x34, 0x98, 0xca, 0x64, 0x83, 0xfb, 0x13, 0x57, 0xd1, 0xc1, 0xf0, 0x3c, 0x7a, 0x8c, 0xa5, 0xc1, +0xfd, 0x95, 0x21, 0xa0, 0x71, 0xc1, 0x93, 0x67, 0x71, 0x12, 0xea, 0x8f, 0x88, 0x0a, 0x69, 0x19, +0x64, 0x99, 0x23, 0x56, 0xfb, 0xac, 0x2a, 0x2e, 0x70, 0xbe, 0x66, 0xc4, 0x0c, 0x84, 0xef, 0xe5, +0x8b, 0xf3, 0x93, 0x01, 0xf8, 0x6a, 0x90, 0x93, 0x67, 0x4b, 0xb2, 0x68, 0xa3, 0xb5, 0x62, 0x8f, +0xe9, 0x3f, 0x8c, 0x7a, 0x3b, 0x5e, 0x0f, 0xe7, 0x8c, 0xb8, 0xc6, 0x7c, 0xef, 0x37, 0xfd, 0x74, +0xe2, 0xc8, 0x4f, 0x33, 0x72, 0xe1, 0x94, 0x39, 0x6d, 0xbd, 0x12, 0xaf, 0xbe, 0x0c, 0x4e, 0x70, +0x7c, 0x1b, 0x6f, 0x8d, 0xb3, 0x32, 0x93, 0x73, 0x44, 0x16, 0x6d, 0xe8, 0xf4, 0xf7, 0xe0, 0x95, +0x80, 0x8f, 0x96, 0x5d, 0x38, 0xa4, 0xf4, 0xab, 0xde, 0x0a, 0x30, 0x87, 0x93, 0xd8, 0x4d, 0x00, +0x71, 0x62, 0x45, 0x27, 0x4b, 0x3a, 0x42, 0x84, 0x5b, 0x7f, 0x65, 0xb7, 0x67, 0x34, 0x52, 0x2d, +0x9c, 0x16, 0x6b, 0xaa, 0xa8, 0xd8, 0x7b, 0xa3, 0x42, 0x4c, 0x71, 0xc7, 0x0c, 0xca, 0x3e, 0x83, +0xe4, 0xa6, 0xef, 0xb7, 0x01, 0x30, 0x5e, 0x51, 0xa3, 0x79, 0xf5, 0x70, 0x69, 0xa6, 0x41, 0x44, +0x0f, 0x86, 0xb0, 0x2c, 0x91, 0xc6, 0x3d, 0xea, 0xae, 0x0f, 0x84, 0x30, 0x82, 0x05, 0xef, 0x30, +0x82, 0x03, 0xd7, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x0d, 0xd3, 0xe3, 0xbc, 0x6c, 0xf9, +0x6b, 0xb1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x09, 0x47, +0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, +0x41, 0x4e, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, 0x64, 0x65, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6f, 0x6e, 0x31, 0x14, +0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 0x41, 0x4e, 0x46, 0x20, 0x43, 0x41, 0x20, +0x52, 0x61, 0x69, 0x7a, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x41, +0x4e, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x39, +0x30, 0x34, 0x31, 0x30, 0x30, 0x30, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, 0x38, 0x33, +0x30, 0x31, 0x30, 0x30, 0x30, 0x33, 0x38, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, +0x03, 0x55, 0x04, 0x05, 0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x27, 0x30, 0x25, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x41, 0x4e, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x72, +0x69, 0x64, 0x61, 0x64, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, +0x61, 0x63, 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, +0x41, 0x4e, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52, 0x61, 0x69, 0x7a, 0x31, 0x22, 0x30, 0x20, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x41, 0x4e, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, +0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, +0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, +0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, +0xdb, 0xeb, 0x6b, 0x2b, 0xe6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xa3, 0x72, 0xa4, 0x19, 0x01, 0x9d, +0x9c, 0x0b, 0x81, 0x5f, 0x73, 0x49, 0xba, 0xa7, 0xac, 0xf3, 0x04, 0x4e, 0x7b, 0x96, 0x0b, 0xec, +0x11, 0xe0, 0x5b, 0xa6, 0x1c, 0xce, 0x1b, 0xd2, 0x0d, 0x83, 0x1c, 0x2b, 0xb8, 0x9e, 0x1d, 0x7e, +0x45, 0x32, 0x60, 0x0f, 0x07, 0xe9, 0x77, 0x58, 0x7e, 0x9f, 0x6a, 0xc8, 0x61, 0x4e, 0xb6, 0x26, +0xc1, 0x4c, 0x8d, 0xff, 0x4c, 0xef, 0x34, 0xb2, 0x1f, 0x65, 0xd8, 0xb9, 0x78, 0xf5, 0xad, 0xa9, +0x71, 0xb9, 0xef, 0x4f, 0x58, 0x1d, 0xa5, 0xde, 0x74, 0x20, 0x97, 0xa1, 0xed, 0x68, 0x4c, 0xde, +0x92, 0x17, 0x4b, 0xbc, 0xab, 0xff, 0x65, 0x9a, 0x9e, 0xfb, 0x47, 0xd9, 0x57, 0x72, 0xf3, 0x09, +0xa1, 0xae, 0x76, 0x44, 0x13, 0x6e, 0x9c, 0x2d, 0x44, 0x39, 0xbc, 0xf9, 0xc7, 0x3b, 0xa4, 0x58, +0x3d, 0x41, 0xbd, 0xb4, 0xc2, 0x49, 0xa3, 0xc8, 0x0d, 0xd2, 0x97, 0x2f, 0x07, 0x65, 0x52, 0x00, +0xa7, 0x6e, 0xc8, 0xaf, 0x68, 0xec, 0xf4, 0x14, 0x96, 0xb6, 0x57, 0x1f, 0x56, 0xc3, 0x39, 0x9f, +0x2b, 0x6d, 0xe4, 0xf3, 0x3e, 0xf6, 0x35, 0x64, 0xda, 0x0c, 0x1c, 0xa1, 0x84, 0x4b, 0x2f, 0x4b, +0x4b, 0xe2, 0x2c, 0x24, 0x9d, 0x6d, 0x93, 0x40, 0xeb, 0xb5, 0x23, 0x8e, 0x32, 0xca, 0x6f, 0x45, +0xd3, 0xa8, 0x89, 0x7b, 0x1e, 0xcf, 0x1e, 0xfa, 0x5b, 0x43, 0x8b, 0xcd, 0xcd, 0xa8, 0x0f, 0x6a, +0xca, 0x0c, 0x5e, 0xb9, 0x9e, 0x47, 0x8f, 0xf0, 0xd9, 0xb6, 0x0a, 0x0b, 0x58, 0x65, 0x17, 0x33, +0xb9, 0x23, 0xe4, 0x77, 0x19, 0x7d, 0xcb, 0x4a, 0x2e, 0x92, 0x7b, 0x4f, 0x2f, 0x10, 0x77, 0xb1, +0x8d, 0x2f, 0x68, 0x9c, 0x62, 0xcc, 0xe0, 0x50, 0xf8, 0xec, 0x91, 0xa7, 0x54, 0x4c, 0x57, 0x09, +0xd5, 0x76, 0x63, 0xc5, 0xe8, 0x65, 0x1e, 0xee, 0x6d, 0x6a, 0xcf, 0x09, 0x9d, 0xfa, 0x7c, 0x4f, +0xad, 0x60, 0x08, 0xfd, 0x56, 0x99, 0x0f, 0x15, 0x2c, 0x7b, 0xa9, 0x80, 0xab, 0x8c, 0x61, 0x8f, +0x4a, 0x07, 0x76, 0x42, 0xde, 0x3d, 0xf4, 0xdd, 0xb2, 0x24, 0x33, 0x5b, 0xb8, 0xb5, 0xa3, 0x44, +0xc9, 0xac, 0x7f, 0x77, 0x3c, 0x1d, 0x23, 0xec, 0x82, 0xa9, 0xa6, 0xe2, 0xc8, 0x06, 0x4c, 0x02, +0xfe, 0xac, 0x5c, 0x99, 0x99, 0x0b, 0x2f, 0x10, 0x8a, 0xa6, 0xf4, 0x7f, 0xd5, 0x87, 0x74, 0x0d, +0x59, 0x49, 0x45, 0xf6, 0xf0, 0x71, 0x5c, 0x39, 0x29, 0xd6, 0xbf, 0x4a, 0x23, 0x8b, 0xf5, 0x5f, +0x01, 0x63, 0xd2, 0x87, 0x73, 0x28, 0xb5, 0x4b, 0x0a, 0xf5, 0xf8, 0xab, 0x82, 0x2c, 0x7e, 0x73, +0x25, 0x32, 0x1d, 0x0b, 0x63, 0x0a, 0x17, 0x81, 0x00, 0xff, 0xb6, 0x76, 0x5e, 0xe7, 0xb4, 0xb1, +0x40, 0xca, 0x21, 0xbb, 0xd5, 0x80, 0x51, 0xe5, 0x48, 0x52, 0x67, 0x2c, 0xd2, 0x61, 0x89, 0x07, +0x0d, 0x0f, 0xce, 0x42, 0x77, 0xc0, 0x44, 0x73, 0x9c, 0x44, 0x50, 0xa0, 0xdb, 0x10, 0x0a, 0x2d, +0x95, 0x1c, 0x81, 0xaf, 0xe4, 0x1c, 0xe5, 0x14, 0x1e, 0xf1, 0x36, 0x41, 0x01, 0x02, 0x2f, 0x7d, +0x73, 0xa7, 0xde, 0x42, 0xcc, 0x4c, 0xe9, 0x89, 0x0d, 0x56, 0xf7, 0x9f, 0x91, 0xd4, 0x03, 0xc6, +0x6c, 0xc9, 0x8f, 0xdb, 0xd8, 0x1c, 0xe0, 0x40, 0x98, 0x5d, 0x66, 0x99, 0x98, 0x80, 0x6e, 0x2d, +0xff, 0x01, 0xc5, 0xce, 0xcb, 0x46, 0x1f, 0xac, 0x02, 0xc6, 0x43, 0xe6, 0xae, 0xa2, 0x84, 0x3c, +0xc5, 0x4e, 0x1e, 0x3d, 0x6d, 0xc9, 0x14, 0x4c, 0xe3, 0x2e, 0x41, 0xbb, 0xca, 0x39, 0xbf, 0x36, +0x3c, 0x2a, 0x19, 0xaa, 0x41, 0x87, 0x4e, 0xa5, 0xce, 0x4b, 0x32, 0x79, 0xdd, 0x90, 0x49, 0x7f, +0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, +0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9c, 0x5f, 0xd0, 0x6c, 0x63, 0xa3, 0x5f, 0x93, 0xca, 0x93, +0x98, 0x08, 0xad, 0x8c, 0x87, 0xa5, 0x2c, 0x5c, 0xc1, 0x37, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0x9c, 0x5f, 0xd0, 0x6c, 0x63, 0xa3, 0x5f, 0x93, 0xca, 0x93, 0x98, +0x08, 0xad, 0x8c, 0x87, 0xa5, 0x2c, 0x5c, 0xc1, 0x37, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, +0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, +0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x4e, 0x1e, +0xb9, 0x8a, 0xc6, 0xa0, 0x98, 0x3f, 0x6e, 0xc3, 0x69, 0xc0, 0x6a, 0x5c, 0x49, 0x52, 0xac, 0xcb, +0x2b, 0x5d, 0x78, 0x38, 0xc1, 0xd5, 0x54, 0x84, 0x9f, 0x93, 0xf0, 0x87, 0x19, 0x3d, 0x2c, 0x66, +0x89, 0xeb, 0x0d, 0x42, 0xfc, 0xcc, 0xf0, 0x75, 0x85, 0x3f, 0x8b, 0xf4, 0x80, 0x5d, 0x79, 0xe5, +0x17, 0x67, 0xbd, 0x35, 0x82, 0xe2, 0xf2, 0x3c, 0x8e, 0x7d, 0x5b, 0x36, 0xcb, 0x5a, 0x80, 0x00, +0x29, 0xf2, 0xce, 0x2b, 0x2c, 0xf1, 0x8f, 0xaa, 0x6d, 0x05, 0x93, 0x6c, 0x72, 0xc7, 0x56, 0xeb, +0xdf, 0x50, 0x23, 0x28, 0xe5, 0x45, 0x10, 0x3d, 0xe8, 0x67, 0xa3, 0xaf, 0x0e, 0x55, 0x0f, 0x90, +0x09, 0x62, 0xef, 0x4b, 0x59, 0xa2, 0xf6, 0x53, 0xf1, 0xc0, 0x35, 0xe4, 0x2f, 0xc1, 0x24, 0xbd, +0x79, 0x2f, 0x4e, 0x20, 0x22, 0x3b, 0xfd, 0x1a, 0x20, 0xb0, 0xa4, 0x0e, 0x2c, 0x70, 0xed, 0x74, +0x3f, 0xb8, 0x13, 0x95, 0x06, 0x51, 0xc8, 0xe8, 0x87, 0x26, 0xca, 0xa4, 0x5b, 0x6a, 0x16, 0x21, +0x92, 0xdd, 0x73, 0x60, 0x9e, 0x10, 0x18, 0xde, 0x3c, 0x81, 0xea, 0xe8, 0x18, 0xc3, 0x7c, 0x89, +0xf2, 0x8b, 0x50, 0x3e, 0xbd, 0x11, 0xe2, 0x15, 0x03, 0xa8, 0x36, 0x7d, 0x33, 0x01, 0x6c, 0x48, +0x15, 0xd7, 0x88, 0x90, 0x99, 0x04, 0xc5, 0xcc, 0xe6, 0x07, 0xf4, 0xbc, 0xf4, 0x90, 0xed, 0x13, +0xe2, 0xea, 0x8b, 0xc3, 0x8f, 0xa3, 0x33, 0x0f, 0xc1, 0x29, 0x4c, 0x13, 0x4e, 0xda, 0x15, 0x56, +0x71, 0x73, 0x72, 0x82, 0x50, 0xf6, 0x9a, 0x33, 0x7c, 0xa2, 0xb1, 0xa8, 0x1a, 0x34, 0x74, 0x65, +0x5c, 0xce, 0xd1, 0xeb, 0xab, 0x53, 0xe0, 0x1a, 0x80, 0xd8, 0xea, 0x3a, 0x49, 0xe4, 0x26, 0x30, +0x9b, 0xe5, 0x1c, 0x8a, 0xa8, 0xa9, 0x15, 0x32, 0x86, 0x99, 0x92, 0x0a, 0x10, 0x23, 0x56, 0x12, +0xe0, 0xf6, 0xce, 0x4c, 0xe2, 0xbb, 0xbe, 0xdb, 0x8d, 0x92, 0x73, 0x01, 0x66, 0x2f, 0x62, 0x3e, +0xb2, 0x72, 0x27, 0x45, 0x36, 0xed, 0x4d, 0x56, 0xe3, 0x97, 0x99, 0xff, 0x3a, 0x35, 0x3e, 0xa5, +0x54, 0x4a, 0x52, 0x59, 0x4b, 0x60, 0xdb, 0xee, 0xfe, 0x78, 0x11, 0x7f, 0x4a, 0xdc, 0x14, 0x79, +0x60, 0xb6, 0x6b, 0x64, 0x03, 0xdb, 0x15, 0x83, 0xe1, 0xa2, 0xbe, 0xf6, 0x23, 0x97, 0x50, 0xf0, +0x09, 0x33, 0x36, 0xa7, 0x71, 0x96, 0x25, 0xf3, 0xb9, 0x42, 0x7d, 0xdb, 0x38, 0x3f, 0x2c, 0x58, +0xac, 0xe8, 0x42, 0xe1, 0x0e, 0xd8, 0xd3, 0x3b, 0x4c, 0x2e, 0x82, 0xe9, 0x83, 0x2e, 0x6b, 0x31, +0xd9, 0xdd, 0x47, 0x86, 0x4f, 0x6d, 0x97, 0x91, 0x2e, 0x4f, 0xe2, 0x28, 0x71, 0x35, 0x16, 0xd1, +0xf2, 0x73, 0xfe, 0x25, 0x2b, 0x07, 0x47, 0x24, 0x63, 0x27, 0xc8, 0xf8, 0xf6, 0xd9, 0x6b, 0xfc, +0x12, 0x31, 0x56, 0x08, 0xc0, 0x53, 0x42, 0xaf, 0x9c, 0xd0, 0x33, 0x7e, 0xfc, 0x06, 0xf0, 0x31, +0x44, 0x03, 0x14, 0xf1, 0x58, 0xea, 0xf2, 0x6a, 0x0d, 0xa9, 0x11, 0xb2, 0x83, 0xbe, 0xc5, 0x1a, +0xbf, 0x07, 0xea, 0x59, 0xdc, 0xa3, 0x88, 0x35, 0xef, 0x9c, 0x76, 0x32, 0x3c, 0x4d, 0x06, 0x22, +0xce, 0x15, 0xe5, 0xdd, 0x9e, 0xd8, 0x8f, 0xda, 0xde, 0xd2, 0xc4, 0x39, 0xe5, 0x17, 0x81, 0xcf, +0x38, 0x47, 0xeb, 0x7f, 0x88, 0x6d, 0x59, 0x1b, 0xdf, 0x9f, 0x42, 0x14, 0xae, 0x7e, 0xcf, 0xa8, +0xb0, 0x66, 0x65, 0xda, 0x37, 0xaf, 0x9f, 0xaa, 0x3d, 0xea, 0x28, 0xb6, 0xde, 0xd5, 0x31, 0x58, +0x16, 0x82, 0x5b, 0xea, 0xbb, 0x19, 0x75, 0x02, 0x73, 0x1a, 0xca, 0x48, 0x1a, 0x21, 0x93, 0x90, +0x0a, 0x8e, 0x93, 0x84, 0xa7, 0x7d, 0x3b, 0x23, 0x18, 0x92, 0x89, 0xa0, 0x8d, 0xac, 0x30, 0x82, +0x02, 0x65, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x78, 0x8f, 0x27, +0x5c, 0x81, 0x12, 0x52, 0x20, 0xa5, 0x04, 0xd0, 0x2d, 0xdd, 0xba, 0x73, 0xf4, 0x30, 0x0a, 0x06, +0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6f, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x53, +0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, +0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, +0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x45, 0x43, 0x2d, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41, 0x30, +0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x32, 0x36, 0x30, 0x37, 0x32, 0x34, 0x35, 0x34, 0x5a, +0x17, 0x0d, 0x34, 0x33, 0x30, 0x33, 0x32, 0x36, 0x30, 0x37, 0x32, 0x34, 0x35, 0x34, 0x5a, 0x30, +0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, 0x31, 0x21, +0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6f, 0x20, +0x44, 0x61, 0x74, 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, 0x41, +0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x43, 0x65, 0x72, 0x74, +0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, +0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x45, 0x43, 0x2d, 0x33, +0x38, 0x34, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc4, 0x28, 0x8e, +0xab, 0x18, 0x5b, 0x6a, 0xbe, 0x6e, 0x64, 0x37, 0x63, 0xe4, 0xcd, 0xec, 0xab, 0x3a, 0xf7, 0xcc, +0xa1, 0xb8, 0x0e, 0x82, 0x49, 0xd7, 0x86, 0x29, 0x9f, 0xa1, 0x94, 0xf2, 0xe3, 0x60, 0x78, 0x98, +0x81, 0x78, 0x06, 0x4d, 0xf2, 0xec, 0x9a, 0x0e, 0x57, 0x60, 0x83, 0x9f, 0xb4, 0xe6, 0x17, 0x2f, +0x1a, 0xb3, 0x5d, 0x02, 0x5b, 0x89, 0x23, 0x3c, 0xc2, 0x11, 0x05, 0x2a, 0xa7, 0x88, 0x13, 0x18, +0xf3, 0x50, 0x84, 0xd7, 0xbd, 0x34, 0x2c, 0x27, 0x89, 0x55, 0xff, 0xce, 0x4c, 0xe7, 0xdf, 0xa6, +0x1f, 0x28, 0xc4, 0xf0, 0x54, 0xc3, 0xb9, 0x7c, 0xb7, 0x53, 0xad, 0xeb, 0xc2, 0xa3, 0x42, 0x30, +0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x8d, 0x06, 0x66, +0x74, 0x24, 0x76, 0x3a, 0xf3, 0x89, 0xf7, 0xbc, 0xd6, 0xbd, 0x47, 0x7d, 0x2f, 0xbc, 0x10, 0x5f, +0x4b, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, +0x06, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, +0x30, 0x65, 0x02, 0x30, 0x03, 0x55, 0x2d, 0xa6, 0xe6, 0x18, 0xc4, 0x7c, 0xef, 0xc9, 0x50, 0x6e, +0xc1, 0x27, 0x0f, 0x9c, 0x87, 0xaf, 0x6e, 0xd5, 0x1b, 0x08, 0x18, 0xbd, 0x92, 0x29, 0xc1, 0xef, +0x94, 0x91, 0x78, 0xd2, 0x3a, 0x1c, 0x55, 0x89, 0x62, 0xe5, 0x1b, 0x09, 0x1e, 0xba, 0x64, 0x6b, +0xf1, 0x76, 0xb4, 0xd4, 0x02, 0x31, 0x00, 0xb4, 0x42, 0x84, 0x99, 0xff, 0xab, 0xe7, 0x9e, 0xfb, +0x91, 0x97, 0x27, 0x5d, 0xdc, 0xb0, 0x5b, 0x30, 0x71, 0xce, 0x5e, 0x38, 0x1a, 0x6a, 0xd9, 0x25, +0xe7, 0xea, 0xf7, 0x61, 0x92, 0x56, 0xf8, 0xea, 0xda, 0x36, 0xc2, 0x87, 0x65, 0x96, 0x2e, 0x72, +0x25, 0x2f, 0x7f, 0xdf, 0xc3, 0x13, 0xc9, 0x30, 0x82, 0x05, 0xc0, 0x30, 0x82, 0x03, 0xa8, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x1e, 0xbf, 0x59, 0x50, 0xb8, 0xc9, 0x80, 0x37, 0x4c, 0x06, +0xf7, 0xeb, 0x55, 0x4f, 0xb5, 0xed, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x7a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x50, 0x4c, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x41, +0x73, 0x73, 0x65, 0x63, 0x6f, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, +0x6d, 0x73, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x1e, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, +0x6d, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, +0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x31, 0x36, 0x31, 0x32, 0x31, 0x30, 0x31, +0x33, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x33, 0x31, 0x36, 0x31, 0x32, 0x31, 0x30, 0x31, 0x33, +0x5a, 0x30, 0x7a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, +0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, +0x6f, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, +0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x43, 0x65, +0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x54, 0x72, +0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x02, +0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, +0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xd1, 0x2d, +0x8e, 0xbb, 0xb7, 0x36, 0xea, 0x6d, 0x37, 0x91, 0x9f, 0x4e, 0x93, 0xa7, 0x05, 0xe4, 0x29, 0x03, +0x25, 0xce, 0x1c, 0x82, 0xf7, 0x7c, 0x99, 0x9f, 0x41, 0x06, 0xcd, 0xed, 0xa3, 0xba, 0xc0, 0xdb, +0x09, 0x2c, 0xc1, 0x7c, 0xdf, 0x29, 0x7e, 0x4b, 0x65, 0x2f, 0x93, 0xa7, 0xd4, 0x01, 0x6b, 0x03, +0x28, 0x18, 0xa3, 0xd8, 0x9d, 0x05, 0xc1, 0x2a, 0xd8, 0x45, 0xf1, 0x91, 0xde, 0xdf, 0x3b, 0xd0, +0x80, 0x02, 0x8c, 0xcf, 0x38, 0x0f, 0xea, 0xa7, 0x5c, 0x78, 0x11, 0xa4, 0xc1, 0xc8, 0x85, 0x5c, +0x25, 0xd3, 0xd3, 0xb2, 0xe7, 0x25, 0xcf, 0x11, 0x54, 0x97, 0xab, 0x35, 0xc0, 0x1e, 0x76, 0x1c, +0xef, 0x00, 0x53, 0x9f, 0x39, 0xdc, 0x14, 0xa5, 0x2c, 0x22, 0x25, 0xb3, 0x72, 0x72, 0xfc, 0x8d, +0xb3, 0xe5, 0x3e, 0x08, 0x1e, 0x14, 0x2a, 0x37, 0x0b, 0x88, 0x3c, 0xca, 0xb0, 0xf4, 0xc8, 0xc2, +0xa1, 0xae, 0xbc, 0xc1, 0xbe, 0x29, 0x67, 0x55, 0xe2, 0xfc, 0xad, 0x59, 0x5c, 0xfe, 0xbd, 0x57, +0x2c, 0xb0, 0x90, 0x8d, 0xc2, 0xed, 0x37, 0xb6, 0x7c, 0x99, 0x88, 0xb5, 0xd5, 0x03, 0x9a, 0x3d, +0x15, 0x0d, 0x3d, 0x3a, 0xa8, 0xa8, 0x45, 0xf0, 0x95, 0x4e, 0x25, 0x59, 0x1d, 0xcd, 0x98, 0x69, +0xbb, 0xd3, 0xcc, 0x32, 0xc9, 0x8d, 0xef, 0x81, 0xfe, 0xad, 0x7d, 0x89, 0xbb, 0xba, 0x60, 0x13, +0xca, 0x65, 0x95, 0x67, 0xa0, 0xf3, 0x19, 0xf6, 0x03, 0x56, 0xd4, 0x6a, 0xd3, 0x27, 0xe2, 0xa1, +0xad, 0x83, 0xf0, 0x4a, 0x12, 0x22, 0x77, 0x1c, 0x05, 0x73, 0xe2, 0x19, 0x71, 0x42, 0xc0, 0xec, +0x75, 0x46, 0x9a, 0x90, 0x58, 0xe0, 0x6a, 0x8e, 0x2b, 0xa5, 0x46, 0x30, 0x04, 0x8e, 0x19, 0xb2, +0x17, 0xe3, 0xbe, 0xa9, 0xba, 0x7f, 0x56, 0xf1, 0x24, 0x03, 0xd7, 0xb2, 0x21, 0x28, 0x76, 0x0e, +0x36, 0x30, 0x4c, 0x79, 0xd5, 0x41, 0x9a, 0x9a, 0xa8, 0xb8, 0x35, 0xba, 0x0c, 0x3a, 0xf2, 0x44, +0x1b, 0x20, 0x88, 0xf7, 0xc5, 0x25, 0xd7, 0x3d, 0xc6, 0xe3, 0x3e, 0x43, 0xdd, 0x87, 0xfe, 0xc4, +0xea, 0xf5, 0x53, 0x3e, 0x4c, 0x65, 0xff, 0x3b, 0x4a, 0xcb, 0x78, 0x5a, 0x6b, 0x17, 0x5f, 0x0d, +0xc7, 0xc3, 0x4f, 0x4e, 0x9a, 0x2a, 0xa2, 0xed, 0x57, 0x4d, 0x22, 0xe2, 0x46, 0x9a, 0x3f, 0x0f, +0x91, 0x34, 0x24, 0x7d, 0x55, 0xe3, 0x8c, 0x95, 0x37, 0xd3, 0x1a, 0xf0, 0x09, 0x2b, 0x2c, 0xd2, +0xc9, 0x8d, 0xb4, 0x0d, 0x00, 0xab, 0x67, 0x29, 0x28, 0xd8, 0x01, 0xf5, 0x19, 0x04, 0xb6, 0x1d, +0xbe, 0x76, 0xfe, 0x72, 0x5c, 0xc4, 0x85, 0xca, 0xd2, 0x80, 0x41, 0xdf, 0x05, 0xa8, 0xa3, 0xd5, +0x84, 0x90, 0x4f, 0x0b, 0xf3, 0xe0, 0x3f, 0x9b, 0x19, 0xd2, 0x37, 0x89, 0x3f, 0xf2, 0x7b, 0x52, +0x1c, 0x8c, 0xf6, 0xe1, 0xf7, 0x3c, 0x07, 0x97, 0x8c, 0x0e, 0xa2, 0x59, 0x81, 0x0c, 0xb2, 0x90, +0x3d, 0xd3, 0xe3, 0x59, 0x46, 0xed, 0x0f, 0xa9, 0xa7, 0xde, 0x80, 0x6b, 0x5a, 0xaa, 0x07, 0xb6, +0x19, 0xcb, 0xbc, 0x57, 0xf3, 0x97, 0x21, 0x7a, 0x0c, 0xb1, 0x2b, 0x74, 0x3e, 0xeb, 0xda, 0xa7, +0x67, 0x2d, 0x4c, 0xc4, 0x98, 0x9e, 0x36, 0x09, 0x76, 0x66, 0x66, 0xfc, 0x1a, 0x3f, 0xea, 0x48, +0x54, 0x1c, 0xbe, 0x30, 0xbd, 0x80, 0x50, 0xbf, 0x7c, 0xb5, 0xce, 0x00, 0xf6, 0x0c, 0x61, 0xd9, +0xe7, 0x24, 0x03, 0xe0, 0xe3, 0x01, 0x81, 0x0e, 0xbd, 0xd8, 0x85, 0x34, 0x88, 0xbd, 0xb2, 0x36, +0xa8, 0x7b, 0x5c, 0x08, 0xe5, 0x44, 0x80, 0x8c, 0x6f, 0xf8, 0x2f, 0xd5, 0x21, 0xca, 0x1d, 0x1c, +0xd0, 0xfb, 0xc4, 0xb5, 0x87, 0xd1, 0x3a, 0x4e, 0xc7, 0x76, 0xb5, 0x35, 0x48, 0xb5, 0x02, 0x03, +0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0x8c, 0xfb, 0x1c, 0x75, 0xbc, 0x02, 0xd3, 0x9f, 0x4e, 0x2e, 0x48, 0xd9, 0xf9, +0x60, 0x54, 0xaa, 0xc4, 0xb3, 0x4f, 0xfa, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, +0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x48, 0xa2, 0xd5, 0x00, 0x0b, +0x2e, 0xd0, 0x3f, 0xbc, 0x1c, 0xd5, 0xb5, 0x54, 0x49, 0x1e, 0x5a, 0x6b, 0xf4, 0xe4, 0xf2, 0xe0, +0x40, 0x37, 0xe0, 0xcc, 0x14, 0x7b, 0xb9, 0xc9, 0xfa, 0x35, 0xb5, 0x75, 0x17, 0x93, 0x6a, 0x05, +0x69, 0x85, 0x9c, 0xcd, 0x4f, 0x19, 0x78, 0x5b, 0x19, 0x81, 0xf3, 0x63, 0x3e, 0xc3, 0xce, 0x5b, +0x8f, 0xf5, 0x2f, 0x5e, 0x01, 0x76, 0x13, 0x3f, 0x2c, 0x00, 0xb9, 0xcd, 0x96, 0x52, 0x39, 0x49, +0x6d, 0x04, 0x4e, 0xc5, 0xe9, 0x0f, 0x86, 0x0d, 0xe1, 0xfa, 0xb3, 0x5f, 0x82, 0x12, 0xf1, 0x3a, +0xce, 0x66, 0x06, 0x24, 0x34, 0x2b, 0xe8, 0xcc, 0xca, 0xe7, 0x69, 0xdc, 0x87, 0x9d, 0xc2, 0x34, +0xd7, 0x79, 0xd1, 0xd3, 0x77, 0xb8, 0xaa, 0x59, 0x58, 0xfe, 0x9d, 0x26, 0xfa, 0x38, 0x86, 0x3e, +0x9d, 0x8a, 0x87, 0x64, 0x57, 0xe5, 0x17, 0x3a, 0xe2, 0xf9, 0x8d, 0xb9, 0xe3, 0x33, 0x78, 0xc1, +0x90, 0xd8, 0xb8, 0xdd, 0xb7, 0x83, 0x51, 0xe4, 0xc4, 0xcc, 0x23, 0xd5, 0x06, 0x7c, 0xe6, 0x51, +0xd3, 0xcd, 0x34, 0x31, 0xc0, 0xf6, 0x46, 0xbb, 0x0b, 0xad, 0xfc, 0x3d, 0x10, 0x05, 0x2a, 0x3b, +0x4a, 0x91, 0x25, 0xee, 0x8c, 0xd4, 0x84, 0x87, 0x80, 0x2a, 0xbc, 0x09, 0x8c, 0xaa, 0x3a, 0x13, +0x5f, 0xe8, 0x34, 0x79, 0x50, 0xc1, 0x10, 0x19, 0xf9, 0xd3, 0x28, 0x1e, 0xd4, 0xd1, 0x51, 0x30, +0x29, 0xb3, 0xae, 0x90, 0x67, 0xd6, 0x1f, 0x0a, 0x63, 0xb1, 0xc5, 0xa9, 0xc6, 0x42, 0x31, 0x63, +0x17, 0x94, 0xef, 0x69, 0xcb, 0x2f, 0xfa, 0x8c, 0x14, 0x7d, 0xc4, 0x43, 0x18, 0x89, 0xd9, 0xf0, +0x32, 0x40, 0xe6, 0x80, 0xe2, 0x46, 0x5f, 0xe5, 0xe3, 0xc1, 0x00, 0x59, 0xa8, 0xf9, 0xe8, 0x20, +0xbc, 0x89, 0x2c, 0x0e, 0x47, 0x34, 0x0b, 0xea, 0x57, 0xc2, 0x53, 0x36, 0xfc, 0xa7, 0xd4, 0xaf, +0x31, 0xcd, 0xfe, 0x02, 0xe5, 0x75, 0xfa, 0xb9, 0x27, 0x09, 0xf9, 0xf3, 0xf5, 0x3b, 0xca, 0x7d, +0x9f, 0xa9, 0x22, 0xcb, 0x88, 0xc9, 0xaa, 0xd1, 0x47, 0x3d, 0x36, 0x77, 0xa8, 0x59, 0x64, 0x6b, +0x27, 0xcf, 0xef, 0x27, 0xc1, 0xe3, 0x24, 0xb5, 0x86, 0xf7, 0xae, 0x7e, 0x32, 0x4d, 0xb0, 0x79, +0x68, 0xd1, 0x39, 0xe8, 0x90, 0x58, 0xc3, 0x83, 0xbc, 0x0f, 0x2c, 0xd6, 0x97, 0xeb, 0xce, 0x0c, +0xe1, 0x20, 0xc7, 0xda, 0xb7, 0x3e, 0xc3, 0x3f, 0xbf, 0x2f, 0xdc, 0x34, 0xa4, 0xfb, 0x2b, 0x21, +0xcd, 0x67, 0x8f, 0x4b, 0xf4, 0xe3, 0xea, 0xd4, 0x3f, 0xe7, 0x4f, 0xba, 0xb9, 0xa5, 0x93, 0x45, +0x1c, 0x66, 0x1f, 0x21, 0xfa, 0x64, 0x5e, 0x6f, 0xe0, 0x76, 0x94, 0x32, 0xcb, 0x75, 0xf5, 0x6e, +0xe5, 0xf6, 0x8f, 0xc7, 0xb8, 0xa4, 0xcc, 0xa8, 0x96, 0x7d, 0x64, 0xfb, 0x24, 0x5a, 0x4a, 0x03, +0x6c, 0x6b, 0x38, 0xc6, 0xe8, 0x03, 0x43, 0x9a, 0xf7, 0x57, 0xb9, 0xb3, 0x29, 0x69, 0x93, 0x38, +0xf4, 0x03, 0xf2, 0xbb, 0xfb, 0x82, 0x6b, 0x07, 0x20, 0xd1, 0x52, 0x1f, 0x9a, 0x64, 0x02, 0x7b, +0x98, 0x66, 0xdb, 0x5c, 0x4d, 0x5a, 0x0f, 0xd0, 0x84, 0x95, 0xa0, 0x3c, 0x14, 0x43, 0x06, 0xca, +0xca, 0xdb, 0xb8, 0x41, 0x36, 0xda, 0x6a, 0x44, 0x67, 0x87, 0xaf, 0xaf, 0xe3, 0x45, 0x11, 0x15, +0x69, 0x08, 0xb2, 0xbe, 0x16, 0x39, 0x97, 0x24, 0x6f, 0x12, 0x45, 0xd1, 0x67, 0x5d, 0x09, 0xa8, +0xc9, 0x15, 0xda, 0xfa, 0xd2, 0xa6, 0x5f, 0x13, 0x61, 0x1f, 0xbf, 0x85, 0xac, 0xb4, 0xad, 0xad, +0x05, 0x94, 0x08, 0x83, 0x1e, 0x75, 0x17, 0xd3, 0x71, 0x3b, 0x93, 0x50, 0x23, 0x59, 0xa0, 0xed, +0x3c, 0x91, 0x54, 0x9d, 0x76, 0x00, 0xc5, 0xc3, 0xb8, 0x38, 0xdb, 0x30, 0x82, 0x05, 0xcf, 0x30, +0x82, 0x03, 0xb7, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x08, 0x16, 0x5f, 0x8a, 0x4c, 0xa5, +0xec, 0x00, 0xc9, 0x93, 0x40, 0xdf, 0xc4, 0xc6, 0xae, 0x23, 0xb8, 0x1c, 0x5a, 0xa4, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x6f, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x4b, 0x31, 0x12, 0x30, 0x10, +0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x09, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, +0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6f, 0x6e, 0x67, 0x20, +0x4b, 0x6f, 0x6e, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x48, +0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1e, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x20, +0x50, 0x6f, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x30, 0x1e, +0x17, 0x0d, 0x31, 0x37, 0x30, 0x36, 0x30, 0x33, 0x30, 0x32, 0x32, 0x39, 0x34, 0x36, 0x5a, 0x17, +0x0d, 0x34, 0x32, 0x30, 0x36, 0x30, 0x33, 0x30, 0x32, 0x32, 0x39, 0x34, 0x36, 0x5a, 0x30, 0x6f, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x4b, 0x31, 0x12, 0x30, +0x10, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x09, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, +0x67, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6f, 0x6e, 0x67, +0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, +0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x31, 0x20, 0x30, +0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, +0x20, 0x50, 0x6f, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x30, +0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, +0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, +0xb3, 0x88, 0xd7, 0xea, 0xce, 0x0f, 0x20, 0x4e, 0xbe, 0xe6, 0xd6, 0x03, 0x6d, 0xee, 0x59, 0xfc, +0xc2, 0x57, 0xdf, 0x29, 0x68, 0xa1, 0x83, 0x0e, 0x3e, 0x68, 0xc7, 0x68, 0x58, 0x9c, 0x1c, 0x60, +0x4b, 0x89, 0x43, 0x0c, 0xb9, 0xd4, 0x15, 0xb2, 0xee, 0xc1, 0x4e, 0x75, 0xe9, 0xb5, 0xa7, 0xef, +0xe5, 0xe9, 0x35, 0x99, 0xe4, 0xcc, 0x1c, 0xe7, 0x4b, 0x5f, 0x8d, 0x33, 0x30, 0x20, 0x33, 0x53, +0xd9, 0xa6, 0xbb, 0xd5, 0x3e, 0x13, 0x8e, 0xe9, 0x1f, 0x87, 0x49, 0xad, 0x50, 0x2d, 0x50, 0xca, +0x18, 0xbe, 0x01, 0x58, 0xa2, 0x13, 0x70, 0x96, 0xbb, 0x89, 0x88, 0x56, 0x80, 0x5c, 0xf8, 0xbd, +0x2c, 0x3c, 0xe1, 0x4c, 0x57, 0x88, 0xbb, 0xd3, 0xb9, 0x95, 0xef, 0xcb, 0xc7, 0xf6, 0xda, 0x31, +0x74, 0x28, 0xa6, 0xe6, 0x54, 0x89, 0xf5, 0x41, 0x31, 0xca, 0xe5, 0x26, 0x1a, 0xcd, 0x82, 0xe0, +0x70, 0xda, 0x3b, 0x29, 0xbb, 0xd5, 0x03, 0xf5, 0x99, 0xba, 0x55, 0xf5, 0x64, 0xd1, 0x60, 0x0e, +0xb3, 0x89, 0x49, 0xb8, 0x8a, 0x2f, 0x05, 0xd2, 0x84, 0x45, 0x28, 0x7c, 0x8f, 0x68, 0x50, 0x12, +0x78, 0xfc, 0x0b, 0xb5, 0x53, 0xcb, 0xc2, 0x98, 0x1c, 0x84, 0xa3, 0x9e, 0xb0, 0xbe, 0x23, 0xa4, +0xda, 0xdc, 0xc8, 0x2b, 0x1e, 0xda, 0x6e, 0x45, 0x1e, 0x89, 0x98, 0xda, 0xf9, 0x00, 0x2e, 0x06, +0xe9, 0x0c, 0x3b, 0x70, 0xd5, 0x50, 0x25, 0x88, 0x99, 0xcb, 0xcd, 0x73, 0x60, 0xf7, 0xd5, 0xff, +0x35, 0x67, 0xc5, 0xa1, 0xbc, 0x5e, 0xab, 0xcd, 0x4a, 0xb8, 0x45, 0xeb, 0xc8, 0x68, 0x1e, 0x0d, +0x0d, 0x14, 0x46, 0x12, 0xe3, 0xd2, 0x64, 0x62, 0x8a, 0x42, 0x98, 0xbc, 0xb4, 0xc6, 0x08, 0x08, +0xf8, 0xfd, 0xa8, 0x4c, 0x64, 0x9c, 0x76, 0x01, 0xbd, 0x2f, 0xa9, 0x6c, 0x33, 0x0f, 0xd8, 0x3f, +0x28, 0xb8, 0x3c, 0x69, 0x01, 0x42, 0x86, 0x7e, 0x69, 0xc1, 0xc9, 0x06, 0xca, 0xe5, 0x7a, 0x46, +0x65, 0xe9, 0xc2, 0xd6, 0x50, 0x41, 0x2e, 0x3f, 0xb7, 0xe4, 0xed, 0x6c, 0xd7, 0xbf, 0x26, 0x01, +0x11, 0xa2, 0x16, 0x29, 0x4a, 0x6b, 0x34, 0x06, 0x90, 0xec, 0x13, 0xd2, 0xb6, 0xfb, 0x6a, 0x76, +0xd2, 0x3c, 0xed, 0xf0, 0xd6, 0x2d, 0xdd, 0xe1, 0x15, 0xec, 0xa3, 0x9b, 0x2f, 0x2c, 0xc9, 0x3e, +0x2b, 0xe4, 0x69, 0x3b, 0xff, 0x72, 0x25, 0xb1, 0x36, 0x86, 0x5b, 0xc7, 0x7f, 0x6b, 0x8b, 0x55, +0x1b, 0x4a, 0xc5, 0x20, 0x61, 0x3d, 0xae, 0xcb, 0x50, 0xe1, 0x08, 0x3a, 0xbe, 0xb0, 0x8f, 0x63, +0x41, 0x53, 0x30, 0x08, 0x59, 0x3c, 0x98, 0x1d, 0x77, 0xba, 0x63, 0x91, 0x7a, 0xca, 0x10, 0x50, +0x60, 0xbf, 0xf0, 0xd7, 0xbc, 0x95, 0x87, 0x8f, 0x97, 0xc5, 0xfe, 0x97, 0x6a, 0x01, 0x94, 0xa3, +0x7c, 0x5b, 0x85, 0x1d, 0x2a, 0x39, 0x3a, 0xd0, 0x54, 0xa1, 0xd1, 0x39, 0x71, 0x9d, 0xfd, 0x21, +0xf9, 0xb5, 0x7b, 0xf0, 0xe2, 0xe0, 0x02, 0x8f, 0x6e, 0x96, 0x24, 0x25, 0x2c, 0xa0, 0x1e, 0x2c, +0xa8, 0xc4, 0x89, 0xa7, 0xef, 0xed, 0x99, 0x06, 0x2f, 0xb6, 0x0a, 0x4c, 0x4f, 0xdb, 0xa2, 0xcc, +0x37, 0x1a, 0xaf, 0x47, 0x85, 0x2d, 0x8a, 0x5f, 0xc4, 0x34, 0x34, 0x4c, 0x00, 0xfd, 0x18, 0x93, +0x67, 0x13, 0xd1, 0x37, 0xe6, 0x48, 0xb4, 0x8b, 0x06, 0xc5, 0x57, 0x7b, 0x19, 0x86, 0x0a, 0x79, +0xcb, 0x00, 0xc9, 0x52, 0xaf, 0x42, 0xff, 0x37, 0x8f, 0xe1, 0xa3, 0x1e, 0x7a, 0x3d, 0x50, 0xab, +0x63, 0x06, 0xe7, 0x15, 0xb5, 0x3f, 0xb6, 0x45, 0x37, 0x94, 0x37, 0xb1, 0x7e, 0xf2, 0x48, 0xc3, +0x7f, 0xc5, 0x75, 0xfe, 0x97, 0x8d, 0x45, 0x8f, 0x1a, 0xa7, 0x1a, 0x72, 0x28, 0x1a, 0x40, 0x0f, +0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, +0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, +0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x17, 0x9d, 0xcd, 0x1e, 0x8b, 0xd6, 0x39, 0x2b, 0x70, +0xd3, 0x5c, 0xd4, 0xa0, 0xb8, 0x1f, 0xb0, 0x00, 0xfc, 0xc5, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x17, 0x9d, 0xcd, 0x1e, 0x8b, 0xd6, 0x39, 0x2b, 0x70, 0xd3, +0x5c, 0xd4, 0xa0, 0xb8, 0x1f, 0xb0, 0x00, 0xfc, 0xc5, 0x61, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x56, 0xd5, +0x7b, 0x6e, 0xe6, 0x22, 0x01, 0xd2, 0x42, 0x9b, 0x18, 0xd5, 0x0e, 0xd7, 0x66, 0x23, 0x5c, 0xe3, +0xfe, 0xa0, 0xc7, 0x92, 0xd2, 0xe9, 0x94, 0xad, 0x4b, 0xa2, 0xc6, 0xec, 0x12, 0x7c, 0x74, 0xd5, +0x48, 0xd2, 0x59, 0x14, 0x99, 0xc0, 0xeb, 0xb9, 0xd1, 0xeb, 0xf4, 0x48, 0x30, 0x5b, 0xad, 0xa7, +0x57, 0x73, 0x99, 0xa9, 0xd3, 0xe5, 0xb7, 0xd1, 0x2e, 0x59, 0x24, 0x58, 0xdc, 0x68, 0x2e, 0x2e, +0x62, 0xd8, 0x6a, 0xe4, 0x70, 0x0b, 0x2d, 0x20, 0x50, 0x20, 0xa4, 0x32, 0x95, 0xd1, 0x00, 0x98, +0xbb, 0xd3, 0xfd, 0xf7, 0x32, 0xf2, 0x49, 0xae, 0xc6, 0x7a, 0xe0, 0x47, 0xbe, 0x6e, 0xce, 0xcb, +0xa3, 0x72, 0x3a, 0x2d, 0x69, 0x5d, 0xcb, 0xc8, 0xe8, 0x45, 0x39, 0xd4, 0xfa, 0x42, 0xc1, 0x11, +0x4c, 0x77, 0x5d, 0x92, 0xfb, 0x6a, 0xff, 0x58, 0x44, 0xe5, 0xeb, 0x81, 0x9e, 0xaf, 0xa0, 0x99, +0xad, 0xbe, 0xa9, 0x01, 0x66, 0xcb, 0x38, 0x1d, 0x3c, 0xdf, 0x43, 0x1f, 0xf4, 0x4d, 0x6e, 0xb4, +0xba, 0x17, 0x46, 0xfc, 0x7d, 0xfd, 0x87, 0x81, 0x79, 0x6a, 0x0d, 0x33, 0x0f, 0xfa, 0x2f, 0xf8, +0x14, 0xb9, 0x80, 0xb3, 0x5d, 0x4d, 0xaa, 0x97, 0xe1, 0xf9, 0xe4, 0x18, 0xc5, 0xf8, 0xd5, 0x38, +0x8c, 0x26, 0x3c, 0xfd, 0xf2, 0x28, 0xe2, 0xee, 0x5a, 0x49, 0x88, 0x2c, 0xdf, 0x79, 0x3d, 0x8e, +0x9e, 0x90, 0x3c, 0xbd, 0x41, 0x4a, 0x3a, 0xdd, 0x5b, 0xf6, 0x9a, 0xb4, 0xce, 0x3f, 0x25, 0x30, +0x7f, 0x32, 0x7d, 0xa2, 0x03, 0x94, 0xd0, 0xdc, 0x7a, 0xa1, 0x52, 0xde, 0x6e, 0x93, 0x8d, 0x18, +0x26, 0xfd, 0x55, 0xac, 0xbd, 0x8f, 0x9b, 0xd2, 0xcf, 0xaf, 0xe7, 0x86, 0x2c, 0xcb, 0x1f, 0x09, +0x6f, 0xa3, 0x6f, 0xa9, 0x84, 0xd4, 0x73, 0xbf, 0x4d, 0xa1, 0x74, 0x1b, 0x4e, 0x23, 0x60, 0xf2, +0xcc, 0x0e, 0xaa, 0x7f, 0xa4, 0x9c, 0x4c, 0x25, 0xa8, 0xb2, 0x66, 0x3b, 0x38, 0xff, 0xd9, 0x94, +0x30, 0xf6, 0x72, 0x84, 0xbe, 0x68, 0x55, 0x10, 0x0f, 0xc6, 0x73, 0x2c, 0x16, 0x69, 0x93, 0x07, +0xfe, 0xb1, 0x45, 0xed, 0xbb, 0xa2, 0x55, 0x6a, 0xb0, 0xda, 0xb5, 0x4a, 0x02, 0x25, 0x27, 0x85, +0xd7, 0xb7, 0xb7, 0x86, 0x44, 0x16, 0x89, 0x6c, 0x80, 0x2b, 0x3e, 0x97, 0xa9, 0x9c, 0xd5, 0x7e, +0x55, 0x4c, 0xc6, 0xde, 0x45, 0x10, 0x1c, 0xea, 0xe9, 0x3b, 0x9f, 0x03, 0x53, 0xee, 0xee, 0x7a, +0x01, 0x02, 0x16, 0x78, 0xd4, 0xe8, 0xc2, 0xbe, 0x46, 0x76, 0x88, 0x13, 0x3f, 0x22, 0xbb, 0x48, +0x12, 0x1d, 0x52, 0x00, 0xb4, 0x02, 0x7e, 0x21, 0x1a, 0x1e, 0x9c, 0x25, 0xf4, 0xf3, 0x3d, 0x5e, +0x1e, 0xd2, 0x1c, 0xf9, 0xb3, 0x2d, 0xb6, 0xf7, 0x37, 0x5c, 0xc6, 0xcb, 0x21, 0x4e, 0xb0, 0xf7, +0x99, 0x47, 0x18, 0x85, 0xc1, 0x2b, 0xba, 0x55, 0xae, 0x06, 0xea, 0xd0, 0x07, 0xb2, 0xdc, 0xab, +0xd0, 0x82, 0x96, 0x75, 0xce, 0xd2, 0x50, 0xfe, 0x99, 0xe7, 0xcf, 0x2f, 0x9f, 0xe7, 0x76, 0xd1, +0x61, 0x2a, 0xfb, 0x21, 0xbb, 0x31, 0xd0, 0xaa, 0x9f, 0x47, 0xa4, 0xb2, 0x22, 0xca, 0x16, 0x3a, +0x50, 0x57, 0xc4, 0x5b, 0x43, 0x67, 0xc5, 0x65, 0x62, 0x03, 0x49, 0x01, 0xeb, 0x43, 0xd9, 0xd8, +0xf8, 0x9e, 0xad, 0xcf, 0xb1, 0x63, 0x0e, 0x45, 0xf4, 0xa0, 0x5a, 0x2c, 0x9b, 0x2d, 0xc5, 0xa6, +0xc0, 0xad, 0xa8, 0x47, 0xf4, 0x27, 0x4c, 0x38, 0x0d, 0x2e, 0x1b, 0x49, 0x3b, 0x52, 0xf4, 0xe8, +0x88, 0x83, 0x2b, 0x54, 0x28, 0xd4, 0xf2, 0x35, 0x52, 0xb4, 0x32, 0x83, 0x62, 0x69, 0x64, 0x0c, +0x91, 0x9c, 0x9f, 0x97, 0xea, 0x74, 0x16, 0xfd, 0x1f, 0x11, 0x06, 0x9a, 0x9b, 0xf4, 0x30, 0x82, +0x05, 0xeb, 0x30, 0x82, 0x03, 0xd3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x56, 0xb6, 0x29, +0xcd, 0x34, 0xbc, 0x78, 0xf6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x05, 0x54, +0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x48, +0x6f, 0x75, 0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, +0x0f, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, 0x53, 0x53, 0x4c, 0x2e, 0x63, +0x6f, 0x6d, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, +0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, +0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, +0x35, 0x33, 0x31, 0x31, 0x38, 0x31, 0x34, 0x33, 0x37, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x35, +0x33, 0x30, 0x31, 0x38, 0x31, 0x34, 0x33, 0x37, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, +0x04, 0x08, 0x0c, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x04, 0x07, 0x0c, 0x07, 0x48, 0x6f, 0x75, 0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2e, +0x53, 0x53, 0x4c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, +0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x32, 0x30, 0x82, +0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x8f, +0x36, 0x65, 0x40, 0xe1, 0xd6, 0x4d, 0xc0, 0xd7, 0xb4, 0xe9, 0x46, 0xda, 0x6b, 0xea, 0x33, 0x47, +0xcd, 0x4c, 0xf9, 0x7d, 0x7d, 0xbe, 0xbd, 0x2d, 0x3d, 0xf0, 0xdb, 0x78, 0xe1, 0x86, 0xa5, 0xd9, +0xba, 0x09, 0x57, 0x68, 0xed, 0x57, 0x3e, 0xa0, 0xd0, 0x08, 0x41, 0x83, 0xe7, 0x28, 0x41, 0x24, +0x1f, 0xe3, 0x72, 0x15, 0xd0, 0x01, 0x1a, 0xfb, 0x5e, 0x70, 0x23, 0xb2, 0xcb, 0x9f, 0x39, 0xe3, +0xcf, 0xc5, 0x4e, 0xc6, 0x92, 0x6d, 0x26, 0xc6, 0x7b, 0xbb, 0xb3, 0xda, 0x27, 0x9d, 0x0a, 0x86, +0xe9, 0x81, 0x37, 0x05, 0xfe, 0xf0, 0x71, 0x71, 0xec, 0xc3, 0x1c, 0xe9, 0x63, 0xa2, 0x17, 0x14, +0x9d, 0xef, 0x1b, 0x67, 0xd3, 0x85, 0x55, 0x02, 0x02, 0xd6, 0x49, 0xc9, 0xcc, 0x5a, 0xe1, 0xb1, +0xf7, 0x6f, 0x32, 0x9f, 0xc9, 0xd4, 0x3b, 0x88, 0x41, 0xa8, 0x9c, 0xbd, 0xcb, 0xab, 0xdb, 0x6d, +0x7b, 0x09, 0x1f, 0xa2, 0x4c, 0x72, 0x90, 0xda, 0x2b, 0x08, 0xfc, 0xcf, 0x3c, 0x54, 0xce, 0x67, +0x0f, 0xa8, 0xcf, 0x5d, 0x96, 0x19, 0x0b, 0xc4, 0xe3, 0x72, 0xeb, 0xad, 0xd1, 0x7d, 0x1d, 0x27, +0xef, 0x92, 0xeb, 0x10, 0xbf, 0x5b, 0xeb, 0x3b, 0xaf, 0xcf, 0x80, 0xdd, 0xc1, 0xd2, 0x96, 0x04, +0x5b, 0x7a, 0x7e, 0xa4, 0xa9, 0x3c, 0x38, 0x76, 0xa4, 0x62, 0x8e, 0xa0, 0x39, 0x5e, 0xea, 0x77, +0xcf, 0x5d, 0x00, 0x59, 0x8f, 0x66, 0x2c, 0x3e, 0x07, 0xa2, 0xa3, 0x05, 0x26, 0x11, 0x69, 0x97, +0xea, 0x85, 0xb7, 0x0f, 0x96, 0x0b, 0x4b, 0xc8, 0x40, 0xe1, 0x50, 0xba, 0x2e, 0x8a, 0xcb, 0xf7, +0x0f, 0x9a, 0x22, 0xe7, 0x7f, 0x9a, 0x37, 0x13, 0xcd, 0xf2, 0x4d, 0x13, 0x6b, 0x21, 0xd1, 0xc0, +0xcc, 0x22, 0xf2, 0xa1, 0x46, 0xf6, 0x44, 0x69, 0x9c, 0xca, 0x61, 0x35, 0x07, 0x00, 0x6f, 0xd6, +0x61, 0x08, 0x11, 0xea, 0xba, 0xb8, 0xf6, 0xe9, 0xb3, 0x60, 0xe5, 0x4d, 0xb9, 0xec, 0x9f, 0x14, +0x66, 0xc9, 0x57, 0x58, 0xdb, 0xcd, 0x87, 0x69, 0xf8, 0x8a, 0x86, 0x12, 0x03, 0x47, 0xbf, 0x66, +0x13, 0x76, 0xac, 0x77, 0x7d, 0x34, 0x24, 0x85, 0x83, 0xcd, 0xd7, 0xaa, 0x9c, 0x90, 0x1a, 0x9f, +0x21, 0x2c, 0x7f, 0x78, 0xb7, 0x64, 0xb8, 0xd8, 0xe8, 0xa6, 0xf4, 0x78, 0xb3, 0x55, 0xcb, 0x84, +0xd2, 0x32, 0xc4, 0x78, 0xae, 0xa3, 0x8f, 0x61, 0xdd, 0xce, 0x08, 0x53, 0xad, 0xec, 0x88, 0xfc, +0x15, 0xe4, 0x9a, 0x0d, 0xe6, 0x9f, 0x1a, 0x77, 0xce, 0x4c, 0x8f, 0xb8, 0x14, 0x15, 0x3d, 0x62, +0x9c, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12, 0xe4, 0x59, 0x76, 0x5a, 0x53, 0xc0, 0x02, 0x98, 0xa2, +0x10, 0x2b, 0x68, 0x44, 0x7b, 0x8e, 0x79, 0xce, 0x33, 0x4a, 0x76, 0xaa, 0x5b, 0x81, 0x16, 0x1b, +0xb5, 0x8a, 0xd8, 0xd0, 0x00, 0x7b, 0x5e, 0x62, 0xb4, 0x09, 0xd6, 0x86, 0x63, 0x0e, 0xa6, 0x05, +0x95, 0x49, 0xba, 0x28, 0x8b, 0x88, 0x93, 0xb2, 0x34, 0x1c, 0xd8, 0xa4, 0x55, 0x6e, 0xb7, 0x1c, +0xd0, 0xde, 0x99, 0x55, 0x3b, 0x23, 0xf4, 0x22, 0xe0, 0xf9, 0x29, 0x66, 0x26, 0xec, 0x20, 0x50, +0x77, 0xdb, 0x4a, 0x0b, 0x8f, 0xbe, 0xe5, 0x02, 0x60, 0x70, 0x41, 0x5e, 0xd4, 0xae, 0x50, 0x39, +0x22, 0x14, 0x26, 0xcb, 0xb2, 0x3b, 0x73, 0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xa8, 0x30, +0x13, 0x44, 0xe5, 0x04, 0x8a, 0xae, 0x96, 0x13, 0x25, 0x42, 0x0f, 0xb9, 0x53, 0xc4, 0x9b, 0xfc, +0xcd, 0xe4, 0x1c, 0xde, 0x3c, 0xfa, 0xab, 0xd6, 0x06, 0x4a, 0x1f, 0x67, 0xa6, 0x98, 0x30, 0x1c, +0xdd, 0x2c, 0xdb, 0xdc, 0x18, 0x95, 0x57, 0x66, 0xc6, 0xff, 0x5c, 0x8b, 0x56, 0xf5, 0x77, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, +0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, +0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xf9, 0x60, 0xbb, 0xd4, 0xe3, 0xd5, 0x34, 0xf6, 0xb8, 0xf5, +0x06, 0x80, 0x25, 0xa7, 0x73, 0xdb, 0x46, 0x69, 0xa8, 0x9e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0xf9, 0x60, 0xbb, 0xd4, 0xe3, 0xd5, 0x34, 0xf6, 0xb8, 0xf5, 0x06, +0x80, 0x25, 0xa7, 0x73, 0xdb, 0x46, 0x69, 0xa8, 0x9e, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, +0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x56, 0xb3, 0x8e, +0xcb, 0x0a, 0x9d, 0x49, 0x8e, 0xbf, 0xa4, 0xc4, 0x91, 0xbb, 0x66, 0x17, 0x05, 0x51, 0x98, 0x75, +0xfb, 0xe5, 0x50, 0x2c, 0x7a, 0x9e, 0xf1, 0x14, 0xfa, 0xab, 0xd3, 0x8a, 0x3e, 0xff, 0x91, 0x29, +0x8f, 0x63, 0x8b, 0xd8, 0xb4, 0xa9, 0x54, 0x01, 0x0d, 0xbe, 0x93, 0x86, 0x2f, 0xf9, 0x4a, 0x6d, +0xc7, 0x5e, 0xf5, 0x57, 0xf9, 0xca, 0x55, 0x1c, 0x12, 0xbe, 0x47, 0x0f, 0x36, 0xc5, 0xdf, 0x6a, +0xb7, 0xdb, 0x75, 0xc2, 0x47, 0x25, 0x7f, 0xb9, 0xf1, 0x63, 0xf8, 0x68, 0x2d, 0x55, 0x04, 0xd1, +0xf2, 0x8d, 0xb0, 0xa4, 0xcf, 0xbc, 0x3c, 0x5e, 0x1f, 0x78, 0xe7, 0xa5, 0xa0, 0x20, 0x70, 0xb0, +0x04, 0xc5, 0xb7, 0xf7, 0x72, 0xa7, 0xde, 0x22, 0x0d, 0xbd, 0x33, 0x25, 0x46, 0x8c, 0x64, 0x92, +0x26, 0xe3, 0x3e, 0x2e, 0x63, 0x96, 0xda, 0x9b, 0x8c, 0x3d, 0xf8, 0x18, 0x09, 0xd7, 0x03, 0xcc, +0x7d, 0x86, 0x82, 0xe0, 0xca, 0x04, 0x07, 0x51, 0x50, 0xd7, 0xff, 0x92, 0xd5, 0x0c, 0xef, 0xda, +0x86, 0x9f, 0x99, 0xd7, 0xeb, 0xb7, 0xaf, 0x68, 0xe2, 0x39, 0x26, 0x94, 0xba, 0x68, 0xb7, 0xbf, +0x83, 0xd3, 0xea, 0x7a, 0x67, 0x3d, 0x62, 0x67, 0xae, 0x25, 0xe5, 0x72, 0xe8, 0xe2, 0xe4, 0xec, +0xae, 0x12, 0xf6, 0x4b, 0x2b, 0x3c, 0x9f, 0xe9, 0xb0, 0x40, 0xf3, 0x38, 0x54, 0xb3, 0xfd, 0xb7, +0x68, 0xc8, 0xda, 0xc6, 0x8f, 0x51, 0x3c, 0xb2, 0xfb, 0x91, 0xdc, 0x1c, 0xe7, 0x9b, 0x9d, 0xe1, +0xb7, 0x0d, 0x72, 0x8f, 0xe2, 0xa4, 0xc4, 0xa9, 0x78, 0xf9, 0xeb, 0x14, 0xac, 0xc6, 0x43, 0x05, +0xc2, 0x65, 0x39, 0x28, 0x18, 0x02, 0xc3, 0x82, 0xb2, 0x9d, 0x05, 0xbe, 0x65, 0xed, 0x96, 0x5f, +0x65, 0x74, 0x3c, 0xfb, 0x09, 0x35, 0x2e, 0x7b, 0x9c, 0x13, 0xfd, 0x1b, 0x0f, 0x5d, 0xc7, 0x6d, +0x81, 0x3a, 0x56, 0x0f, 0xcc, 0x3b, 0xe1, 0xaf, 0x02, 0x2f, 0x22, 0xac, 0x46, 0xca, 0x46, 0x3c, +0xa0, 0x1c, 0x4c, 0xd6, 0x44, 0xb4, 0x5e, 0x2e, 0x5c, 0x15, 0x66, 0x09, 0xe1, 0x26, 0x29, 0xfe, +0xc6, 0x52, 0x61, 0xba, 0xb1, 0x73, 0xff, 0xc3, 0x0c, 0x9c, 0xe5, 0x6c, 0x6a, 0x94, 0x3f, 0x14, +0xca, 0x40, 0x16, 0x95, 0x84, 0xf3, 0x59, 0xa9, 0xac, 0x5f, 0x4c, 0x61, 0x93, 0x6d, 0xd1, 0x3b, +0xcc, 0xa2, 0x95, 0x0c, 0x22, 0xa6, 0x67, 0x67, 0x44, 0x2e, 0xb9, 0xd9, 0xd2, 0x8a, 0x41, 0xb3, +0x66, 0x0b, 0x5a, 0xfb, 0x7d, 0x23, 0xa5, 0xf2, 0x1a, 0xb0, 0xff, 0xde, 0x9b, 0x83, 0x94, 0x2e, +0xd1, 0x3f, 0xdf, 0x92, 0xb7, 0x91, 0xaf, 0x05, 0x3b, 0x65, 0xc7, 0xa0, 0x6c, 0xb1, 0xcd, 0x62, +0x12, 0xc3, 0x90, 0x1b, 0xe3, 0x25, 0xce, 0x34, 0xbc, 0x6f, 0x77, 0x76, 0xb1, 0x10, 0xc3, 0xf7, +0x05, 0x1a, 0xc0, 0xd6, 0xaf, 0x74, 0x62, 0x48, 0x17, 0x77, 0x92, 0x69, 0x90, 0x61, 0x1c, 0xde, +0x95, 0x80, 0x74, 0x54, 0x8f, 0x18, 0x1c, 0xc3, 0xf3, 0x03, 0xd0, 0xbf, 0xa4, 0x43, 0x75, 0x86, +0x53, 0x18, 0x7a, 0x0a, 0x2e, 0x09, 0x1c, 0x36, 0x9f, 0x91, 0xfd, 0x82, 0x8a, 0x22, 0x4b, 0xd1, +0x0e, 0x50, 0x25, 0xdd, 0xcb, 0x03, 0x0c, 0x17, 0xc9, 0x83, 0x00, 0x08, 0x4e, 0x35, 0x4d, 0x8a, +0x8b, 0xed, 0xf0, 0x02, 0x94, 0x66, 0x2c, 0x44, 0x7f, 0xcb, 0x95, 0x27, 0x96, 0x17, 0xad, 0x09, +0x30, 0xac, 0xb6, 0x71, 0x17, 0x6e, 0x8b, 0x17, 0xf6, 0x1c, 0x09, 0xd4, 0x2d, 0x3b, 0x98, 0xa5, +0x71, 0xd3, 0x54, 0x13, 0xd9, 0x60, 0xf3, 0xf5, 0x4b, 0x66, 0x4f, 0xfa, 0xf1, 0xee, 0x20, 0x12, +0x8d, 0xb4, 0xac, 0x57, 0xb1, 0x45, 0x63, 0xa1, 0xac, 0x76, 0xa9, 0xc2, 0xfb, 0x30, 0x82, 0x05, +0x47, 0x30, 0x82, 0x03, 0x2f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x11, 0x00, 0x34, 0xb6, +0x4e, 0xc6, 0x36, 0x2d, 0x36, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x52, 0x4f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x43, 0x45, +0x52, 0x54, 0x53, 0x49, 0x47, 0x4e, 0x20, 0x53, 0x41, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x13, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4e, 0x20, 0x52, 0x4f, 0x4f, +0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x32, 0x30, +0x36, 0x30, 0x39, 0x32, 0x37, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x32, 0x30, 0x36, +0x30, 0x39, 0x32, 0x37, 0x33, 0x35, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x52, 0x4f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x0b, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4e, 0x20, 0x53, 0x41, 0x31, 0x1c, 0x30, 0x1a, +0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x13, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4e, 0x20, +0x52, 0x4f, 0x4f, 0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, +0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc0, 0xc5, 0x75, 0x19, 0x91, +0x7d, 0x44, 0x74, 0x74, 0x87, 0xfe, 0x0e, 0x3b, 0x96, 0xdc, 0xd8, 0x01, 0x16, 0xcc, 0xee, 0x63, +0x91, 0xe7, 0x0b, 0x6f, 0xce, 0x3b, 0x0a, 0x69, 0x1a, 0x7c, 0xc2, 0xe3, 0xaf, 0x82, 0x8e, 0x86, +0xd7, 0x5e, 0x8f, 0x57, 0xeb, 0xd3, 0x21, 0x59, 0xfd, 0x39, 0x37, 0x42, 0x30, 0xbe, 0x50, 0xea, +0xb6, 0x0f, 0xa9, 0x88, 0xd8, 0x2e, 0x2d, 0x69, 0x21, 0xe7, 0xd1, 0x37, 0x18, 0x4e, 0x7d, 0x91, +0xd5, 0x16, 0x5f, 0x6b, 0x5b, 0x00, 0xc2, 0x39, 0x43, 0x0d, 0x36, 0x85, 0x52, 0xb9, 0x53, 0x65, +0x0f, 0x1d, 0x42, 0xe5, 0x8f, 0xcf, 0x05, 0xd3, 0xee, 0xdc, 0x0c, 0x1a, 0xd9, 0xb8, 0x8b, 0x78, +0x22, 0x67, 0xe4, 0x69, 0xb0, 0x68, 0xc5, 0x3c, 0xe4, 0x6c, 0x5a, 0x46, 0xe7, 0xcd, 0xc7, 0xfa, +0xef, 0xc4, 0xec, 0x4b, 0xbd, 0x6a, 0xa4, 0xac, 0xfd, 0xcc, 0x28, 0x51, 0xef, 0x92, 0xb4, 0x29, +0xab, 0xab, 0x35, 0x9a, 0x4c, 0xe4, 0xc4, 0x08, 0xc6, 0x26, 0xcc, 0xf8, 0x69, 0x9f, 0xe4, 0x9c, +0xf0, 0x29, 0xd3, 0x5c, 0xf9, 0xc6, 0x16, 0x25, 0x9e, 0x23, 0xc3, 0x20, 0xc1, 0x3d, 0x0f, 0x3f, +0x38, 0x40, 0xb0, 0xfe, 0x82, 0x44, 0x38, 0xaa, 0x5a, 0x1a, 0x8a, 0x6b, 0x63, 0x58, 0x38, 0xb4, +0x15, 0xd3, 0xb6, 0x11, 0x69, 0x7b, 0x1e, 0x54, 0xee, 0x8c, 0x1a, 0x22, 0xac, 0x72, 0x97, 0x3f, +0x23, 0x59, 0x9b, 0xc9, 0x22, 0x84, 0xc1, 0x07, 0x4f, 0xcc, 0x7f, 0xe2, 0x57, 0xca, 0x12, 0x70, +0xbb, 0xa6, 0x65, 0xf3, 0x69, 0x75, 0x63, 0xbd, 0x95, 0xfb, 0x1b, 0x97, 0xcd, 0xe4, 0xa8, 0xaf, +0xf6, 0xd1, 0x4e, 0xa8, 0xd9, 0x8a, 0x71, 0x24, 0xcd, 0x36, 0x3d, 0xbc, 0x96, 0xc4, 0xf1, 0x6c, +0xa9, 0xae, 0xe5, 0xcf, 0x0d, 0x6e, 0x28, 0x0d, 0xb0, 0x0e, 0xb5, 0xca, 0x51, 0x7b, 0x78, 0x14, +0xc3, 0x20, 0x2f, 0x7f, 0xfb, 0x14, 0x55, 0xe1, 0x11, 0x99, 0xfd, 0xd5, 0x0a, 0xa1, 0x9e, 0x02, +0xe3, 0x62, 0x5f, 0xeb, 0x35, 0x4b, 0x2c, 0xb8, 0x72, 0xe8, 0x3e, 0x3d, 0x4f, 0xac, 0x2c, 0xbb, +0x2e, 0x86, 0xe2, 0xa3, 0x76, 0x8f, 0xe5, 0x93, 0x2a, 0xcf, 0xa5, 0xab, 0xc8, 0x5c, 0x8d, 0x4b, +0x06, 0xff, 0x12, 0x46, 0xac, 0x78, 0xcb, 0x14, 0x07, 0x35, 0xe0, 0xa9, 0xdf, 0x8b, 0xe9, 0xaf, +0x15, 0x4f, 0x16, 0x89, 0x5b, 0xbd, 0xf6, 0x8d, 0xc6, 0x59, 0xae, 0x88, 0x85, 0x0e, 0xc1, 0x89, +0xeb, 0x1f, 0x67, 0xc5, 0x45, 0x8e, 0xff, 0x6d, 0x37, 0x36, 0x2b, 0x78, 0x66, 0x83, 0x91, 0x51, +0x2b, 0x3d, 0xff, 0x51, 0x77, 0x76, 0x62, 0xa1, 0xec, 0x67, 0x3e, 0x3e, 0x81, 0x83, 0xe0, 0x56, +0xa9, 0x50, 0x1f, 0x1f, 0x7a, 0x99, 0xab, 0x63, 0xbf, 0x84, 0x17, 0x77, 0xf1, 0x0d, 0x3b, 0xdf, +0xf7, 0x9c, 0x61, 0xb3, 0x35, 0x98, 0x8a, 0x3a, 0xb2, 0xec, 0x3c, 0x1a, 0x37, 0x3f, 0x7e, 0x8f, +0x92, 0xcf, 0xd9, 0x12, 0x14, 0x64, 0xda, 0x10, 0x02, 0x15, 0x41, 0xff, 0x4f, 0xc4, 0xeb, 0x1c, +0xa3, 0xc9, 0xfa, 0x99, 0xf7, 0x46, 0xe9, 0xe1, 0x18, 0xd9, 0xb1, 0xb8, 0x32, 0x2d, 0xcb, 0x14, +0x0c, 0x50, 0xd8, 0x83, 0x65, 0x83, 0xee, 0xb9, 0x5c, 0xcf, 0xcb, 0x05, 0x5a, 0x4c, 0xfa, 0x19, +0x97, 0x6b, 0xd6, 0x5d, 0x13, 0xd3, 0xc2, 0x5c, 0x54, 0xbc, 0x32, 0x73, 0xa0, 0x78, 0xf5, 0xf1, +0x6d, 0x1e, 0xcb, 0x9f, 0xa5, 0xa6, 0x9f, 0x22, 0xdc, 0xd1, 0x51, 0x9e, 0x82, 0x79, 0x64, 0x60, +0x29, 0x13, 0x3e, 0xa3, 0xfd, 0x4f, 0x72, 0x6a, 0xab, 0xe2, 0xd4, 0xe5, 0xb8, 0x24, 0x55, 0x2c, +0x44, 0x4b, 0x8a, 0x88, 0x44, 0x9c, 0xca, 0x84, 0xd3, 0x2a, 0x3b, 0x02, 0x03, 0x01, 0x00, 0x01, +0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0x82, 0x21, 0x2d, 0x66, 0xc6, 0xd7, 0xa0, 0xe0, 0x15, 0xeb, 0xce, 0x4c, 0x09, 0x77, 0xc4, 0x60, +0x9e, 0x54, 0x6e, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x60, 0xde, 0x1a, 0xb8, 0xe7, 0xf2, 0x60, 0x82, +0xd5, 0x03, 0x33, 0x81, 0xcb, 0x06, 0x8a, 0xf1, 0x22, 0x49, 0xe9, 0xe8, 0xea, 0x91, 0x7f, 0xc6, +0x33, 0x5e, 0x68, 0x19, 0x03, 0x86, 0x3b, 0x43, 0x01, 0xcf, 0x07, 0x70, 0xe4, 0x08, 0x1e, 0x65, +0x85, 0x91, 0xe6, 0x11, 0x22, 0xb7, 0xf5, 0x02, 0x23, 0x8e, 0xae, 0xb9, 0x1e, 0x7d, 0x1f, 0x7e, +0x6c, 0xe6, 0xbd, 0x25, 0xd5, 0x95, 0x1a, 0xf2, 0x05, 0xa6, 0xaf, 0x85, 0x02, 0x6f, 0xae, 0xf8, +0xd6, 0x31, 0xff, 0x25, 0xc9, 0x4a, 0xc8, 0xc7, 0x8a, 0xa9, 0xd9, 0x9f, 0x4b, 0x49, 0x9b, 0x11, +0x57, 0x99, 0x92, 0x43, 0x11, 0xde, 0xb6, 0x33, 0xa4, 0xcc, 0xd7, 0x8d, 0x64, 0x7d, 0xd4, 0xcd, +0x3c, 0x28, 0x2c, 0xb4, 0x9a, 0x96, 0xea, 0x4d, 0xf5, 0xc4, 0x44, 0xc4, 0x25, 0xaa, 0x20, 0x80, +0xd8, 0x29, 0x55, 0xf7, 0xe0, 0x41, 0xfc, 0x06, 0x26, 0xff, 0xb9, 0x36, 0xf5, 0x43, 0x14, 0x03, +0x66, 0x78, 0xe1, 0x11, 0xb1, 0xda, 0x20, 0x5f, 0x46, 0x00, 0x78, 0x00, 0x21, 0xa5, 0x1e, 0x00, +0x28, 0x61, 0x78, 0x6f, 0xa8, 0x01, 0x01, 0x8f, 0x9d, 0x34, 0x9a, 0xff, 0xf4, 0x38, 0x90, 0xfb, +0xb8, 0xd1, 0xb3, 0x72, 0x06, 0xc9, 0x71, 0xe6, 0x81, 0xc5, 0x79, 0xed, 0x0b, 0xa6, 0x79, 0xf2, +0x13, 0x0b, 0x9c, 0xf7, 0x5d, 0x0e, 0x7b, 0x24, 0x93, 0xb4, 0x48, 0xdb, 0x86, 0x5f, 0xde, 0x50, +0x86, 0x78, 0xe7, 0x40, 0xe6, 0x31, 0xa8, 0x90, 0x76, 0x70, 0x61, 0xaf, 0x9c, 0x37, 0x2c, 0x11, +0xb5, 0x82, 0xb7, 0xaa, 0xae, 0x24, 0x34, 0x5b, 0x72, 0x0c, 0x69, 0x0d, 0xcd, 0x59, 0x9f, 0xf6, +0x71, 0xaf, 0x9c, 0x0b, 0xd1, 0x0a, 0x38, 0xf9, 0x06, 0x22, 0x83, 0x53, 0x25, 0x0c, 0xfc, 0x51, +0xc4, 0xe6, 0xbe, 0xe2, 0x39, 0x95, 0x0b, 0x24, 0xad, 0xaf, 0xd1, 0x95, 0xe4, 0x96, 0xd7, 0x74, +0x64, 0x6b, 0x71, 0x4e, 0x02, 0x3c, 0xaa, 0x85, 0xf3, 0x20, 0xa3, 0x43, 0x39, 0x76, 0x5b, 0x6c, +0x50, 0xfe, 0x9a, 0x9c, 0x14, 0x1e, 0x65, 0x14, 0x8a, 0x15, 0xbd, 0xa3, 0x82, 0x45, 0x5a, 0x49, +0x56, 0x6a, 0xd2, 0x9c, 0xb1, 0x63, 0x32, 0xe5, 0x61, 0xe0, 0x53, 0x22, 0x0e, 0xa7, 0x0a, 0x49, +0xea, 0xcb, 0x7e, 0x1f, 0xa8, 0xe2, 0x62, 0x80, 0xf6, 0x10, 0x45, 0x52, 0x98, 0x06, 0x18, 0xde, +0xa5, 0xcd, 0x2f, 0x7f, 0xaa, 0xd4, 0xe9, 0x3e, 0x08, 0x72, 0xec, 0x23, 0x03, 0x02, 0x3c, 0xa6, +0xaa, 0xd8, 0xbc, 0x67, 0x74, 0x3d, 0x14, 0x17, 0xfb, 0x54, 0x4b, 0x17, 0xe3, 0xd3, 0x79, 0x3d, +0x6d, 0x6b, 0x49, 0xc9, 0x28, 0x0e, 0x2e, 0x74, 0x50, 0xbf, 0x0c, 0xd9, 0x46, 0x3a, 0x10, 0x86, +0xc9, 0xa7, 0x3f, 0xe9, 0xa0, 0xec, 0x7f, 0xeb, 0xa5, 0x77, 0x58, 0x69, 0x71, 0xe6, 0x83, 0x0a, +0x37, 0xf2, 0x86, 0x49, 0x6a, 0xbe, 0x79, 0x08, 0x90, 0xf6, 0x02, 0x16, 0x64, 0x3e, 0xe5, 0xda, +0x4c, 0x7e, 0x0c, 0x34, 0xc9, 0xf9, 0x5f, 0xb6, 0xb3, 0x28, 0x51, 0xa7, 0xa7, 0x2b, 0xaa, 0x49, +0xfa, 0x8d, 0x65, 0x29, 0x4e, 0xe3, 0x6b, 0x13, 0xa7, 0x94, 0xa3, 0x2d, 0x51, 0x6d, 0x78, 0x0c, +0x44, 0xcb, 0xdf, 0xde, 0x08, 0x6f, 0xce, 0xa3, 0x64, 0xab, 0xd3, 0x95, 0x84, 0xd4, 0xb9, 0x52, +0x54, 0x72, 0x7b, 0x96, 0x25, 0xcc, 0xbc, 0x69, 0xe3, 0x48, 0x6e, 0x0d, 0xd0, 0xc7, 0x9d, 0x27, +0x9a, 0xaa, 0xf8, 0x13, 0x92, 0xdd, 0x1e, 0xdf, 0x63, 0x9f, 0x35, 0xa9, 0x16, 0x36, 0xec, 0x8c, +0xb8, 0x83, 0xf4, 0x3d, 0x89, 0x8f, 0xcd, 0xb4, 0x17, 0x5e, 0xd7, 0xb3, 0x17, 0x41, 0x10, 0x5d, +0x27, 0x73, 0x60, 0x85, 0x57, 0x49, 0x22, 0x07, 0x30, 0x82, 0x02, 0x69, 0x30, 0x82, 0x01, 0xef, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x21, 0x2a, 0x56, 0x0c, 0xae, 0xda, 0x0c, 0xab, 0x40, +0x45, 0xbf, 0x2b, 0xa2, 0x2d, 0x3a, 0xea, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x04, 0x03, 0x03, 0x30, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x43, 0x48, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x57, 0x49, 0x53, +0x65, 0x4b, 0x65, 0x79, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x19, 0x4f, +0x49, 0x53, 0x54, 0x45, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, +0x45, 0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x1f, 0x4f, 0x49, 0x53, 0x54, 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4b, 0x65, 0x79, +0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x43, 0x20, +0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x35, 0x30, 0x39, 0x30, 0x39, 0x34, 0x38, +0x33, 0x34, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x35, 0x30, 0x39, 0x30, 0x39, 0x35, 0x38, 0x33, +0x33, 0x5a, 0x30, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, +0x48, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, +0x4b, 0x65, 0x79, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x19, 0x4f, 0x49, +0x53, 0x54, 0x45, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x45, +0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x1f, 0x4f, 0x49, 0x53, 0x54, 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4b, 0x65, 0x79, 0x20, +0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x43, 0x20, 0x43, +0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, +0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x4c, 0xe9, 0x50, 0xc0, 0xc6, 0x0f, 0x72, +0x18, 0xbc, 0xd8, 0xf1, 0xba, 0xb3, 0x89, 0xe2, 0x79, 0x4a, 0xa3, 0x16, 0xa7, 0x6b, 0x54, 0x24, +0xdb, 0x51, 0xff, 0xea, 0xf4, 0x09, 0x24, 0xc3, 0x0b, 0x22, 0x9f, 0xcb, 0x6a, 0x27, 0x82, 0x81, +0x0d, 0xd2, 0xc0, 0xaf, 0x31, 0xe4, 0x74, 0x82, 0x6e, 0xca, 0x25, 0xd9, 0x8c, 0x75, 0x9d, 0xf1, +0xdb, 0xd0, 0x9a, 0xa2, 0x4b, 0x21, 0x7e, 0x16, 0xa7, 0x63, 0x90, 0xd2, 0x39, 0xd4, 0xb1, 0x87, +0x78, 0x5f, 0x18, 0x96, 0x0f, 0x50, 0x1b, 0x35, 0x37, 0x0f, 0x6a, 0xc6, 0xdc, 0xd9, 0x13, 0x4d, +0xa4, 0x8e, 0x90, 0x37, 0xe6, 0xbd, 0x5b, 0x31, 0x91, 0xa3, 0x54, 0x30, 0x52, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48, 0x87, 0x14, 0xac, 0xe3, 0xc3, 0x9e, +0x90, 0x60, 0x3a, 0xd7, 0xca, 0x89, 0xee, 0xd3, 0xad, 0x8c, 0xb4, 0x50, 0x66, 0x30, 0x10, 0x06, +0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, +0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, +0x02, 0x30, 0x26, 0xc7, 0x69, 0x5b, 0xdc, 0xd5, 0xe7, 0xb2, 0xe7, 0xc8, 0x0c, 0x8c, 0x8c, 0xc3, +0xdd, 0x79, 0x8c, 0x1b, 0x63, 0xd5, 0xc9, 0x52, 0x94, 0x4e, 0x4d, 0x82, 0x4a, 0x73, 0x1e, 0xb2, +0x80, 0x84, 0xa9, 0x25, 0xc0, 0x4c, 0x5a, 0x6d, 0x49, 0x29, 0x60, 0x78, 0x13, 0xe2, 0x7e, 0x48, +0xeb, 0x64, 0x02, 0x31, 0x00, 0xdb, 0x34, 0x20, 0x32, 0x08, 0xff, 0x9a, 0x49, 0x02, 0xb6, 0x88, +0xde, 0x14, 0xaf, 0x5d, 0x6c, 0x99, 0x71, 0x8d, 0x1a, 0x3f, 0x8b, 0xd7, 0xe0, 0xa2, 0x36, 0x86, +0x1c, 0x07, 0x82, 0x3a, 0x76, 0x53, 0xfd, 0xc2, 0xa2, 0xed, 0xef, 0x7b, 0xb0, 0x80, 0x4f, 0x58, +0x0f, 0x4b, 0x53, 0x39, 0xbd, 0x30, 0x82, 0x03, 0xb5, 0x30, 0x82, 0x02, 0x9d, 0xa0, 0x03, 0x02, +0x01, 0x02, 0x02, 0x10, 0x76, 0xb1, 0x20, 0x52, 0x74, 0xf0, 0x85, 0x87, 0x46, 0xb3, 0xf8, 0x23, +0x1a, 0xf6, 0xc2, 0xc0, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x30, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x43, 0x48, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x57, 0x49, 0x53, +0x65, 0x4b, 0x65, 0x79, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x19, 0x4f, +0x49, 0x53, 0x54, 0x45, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, +0x45, 0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x1f, 0x4f, 0x49, 0x53, 0x54, 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4b, 0x65, 0x79, +0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x42, 0x20, +0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x30, 0x31, 0x31, 0x35, 0x30, 0x30, +0x33, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x31, 0x32, 0x30, 0x31, 0x31, 0x35, 0x31, 0x30, 0x33, +0x31, 0x5a, 0x30, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, +0x48, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x57, 0x49, 0x53, 0x65, +0x4b, 0x65, 0x79, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x19, 0x4f, 0x49, +0x53, 0x54, 0x45, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x45, +0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x1f, 0x4f, 0x49, 0x53, 0x54, 0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4b, 0x65, 0x79, 0x20, +0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x42, 0x20, 0x43, +0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, +0x01, 0x00, 0xd8, 0x17, 0xb7, 0x1c, 0x4a, 0x24, 0x2a, 0xd6, 0x97, 0xb1, 0xca, 0xe2, 0x1e, 0xfb, +0x7d, 0x38, 0xef, 0x98, 0xf5, 0xb2, 0x39, 0x98, 0x4e, 0x27, 0xb8, 0x11, 0x5d, 0x7b, 0xd2, 0x25, +0x94, 0x88, 0x82, 0x15, 0x26, 0x6a, 0x1b, 0x31, 0xbb, 0xa8, 0x5b, 0x21, 0x21, 0x2b, 0xd8, 0x0f, +0x4e, 0x9f, 0x5a, 0xf1, 0xb1, 0x5a, 0xe4, 0x79, 0xd6, 0x32, 0x23, 0x2b, 0xe1, 0x53, 0xcc, 0x99, +0x45, 0x5c, 0x7b, 0x4f, 0xad, 0xbc, 0xbf, 0x87, 0x4a, 0x0b, 0x4b, 0x97, 0x5a, 0xa8, 0xf6, 0x48, +0xec, 0x7d, 0x7b, 0x0d, 0xcd, 0x21, 0x06, 0xdf, 0x9e, 0x15, 0xfd, 0x41, 0x8a, 0x48, 0xb7, 0x20, +0xf4, 0xa1, 0x7a, 0x1b, 0x57, 0xd4, 0x5d, 0x50, 0xff, 0xba, 0x67, 0xd8, 0x23, 0x99, 0x1f, 0xc8, +0x3f, 0xe3, 0xde, 0xff, 0x6f, 0x5b, 0x77, 0xb1, 0x6b, 0x6e, 0xb8, 0xc9, 0x64, 0xf7, 0xe1, 0xca, +0x41, 0x46, 0x0e, 0x29, 0x71, 0xd0, 0xb9, 0x23, 0xfc, 0xc9, 0x81, 0x5f, 0x4e, 0xf7, 0x6f, 0xdf, +0xbf, 0x84, 0xad, 0x73, 0x64, 0xbb, 0xb7, 0x42, 0x8e, 0x69, 0xf6, 0xd4, 0x76, 0x1d, 0x7e, 0x9d, +0xa7, 0xb8, 0x57, 0x8a, 0x51, 0x67, 0x72, 0xd7, 0xd4, 0xa8, 0xb8, 0x95, 0x54, 0x40, 0x73, 0x03, +0xf6, 0xea, 0xf4, 0xeb, 0xfe, 0x28, 0x42, 0x77, 0x3f, 0x9d, 0x23, 0x1b, 0xb2, 0xb6, 0x3d, 0x80, +0x14, 0x07, 0x4c, 0x2e, 0x4f, 0xf7, 0xd5, 0x0a, 0x16, 0x0d, 0xbd, 0x66, 0x43, 0x37, 0x7e, 0x23, +0x43, 0x79, 0xc3, 0x40, 0x86, 0xf5, 0x4c, 0x29, 0xda, 0x8e, 0x9a, 0xad, 0x0d, 0xa5, 0x04, 0x87, +0x88, 0x1e, 0x85, 0xe3, 0xe9, 0x53, 0xd5, 0x9b, 0xc8, 0x8b, 0x03, 0x63, 0x78, 0xeb, 0xe0, 0x19, +0x4a, 0x6e, 0xbb, 0x2f, 0x6b, 0x33, 0x64, 0x58, 0x93, 0xad, 0x69, 0xbf, 0x8f, 0x1b, 0xef, 0x82, +0x48, 0xc7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x51, 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x03, 0x55, +0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, +0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, +0x04, 0x16, 0x04, 0x14, 0x35, 0x0f, 0xc8, 0x36, 0x63, 0x5e, 0xe2, 0xa3, 0xec, 0xf9, 0x3b, 0x66, +0x15, 0xce, 0x51, 0x52, 0xe3, 0x91, 0x9a, 0x3d, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, +0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x40, 0x4c, +0xfb, 0x87, 0xb2, 0x99, 0x81, 0x90, 0x7e, 0x9d, 0xc5, 0xb0, 0xb0, 0x26, 0xcd, 0x88, 0x7b, 0x2b, +0x32, 0x8d, 0x6e, 0xb8, 0x21, 0x71, 0x58, 0x97, 0x7d, 0xae, 0x37, 0x14, 0xaf, 0x3e, 0xe7, 0xf7, +0x9a, 0xe2, 0x7d, 0xf6, 0x71, 0x98, 0x99, 0x04, 0xaa, 0x43, 0x74, 0x78, 0xa3, 0xe3, 0x49, 0x61, +0x3e, 0x73, 0x8c, 0x4d, 0x94, 0xe0, 0xf9, 0x71, 0xc4, 0xb6, 0x16, 0x0e, 0x53, 0x78, 0x1f, 0xd6, +0xa2, 0x87, 0x2f, 0x02, 0x39, 0x81, 0x29, 0x3c, 0xaf, 0x15, 0x98, 0x21, 0x30, 0xfe, 0x28, 0x90, +0x00, 0x8c, 0xd1, 0xe1, 0xcb, 0xfa, 0x5e, 0xc8, 0xfd, 0xf8, 0x10, 0x46, 0x3b, 0xa2, 0x78, 0x42, +0x91, 0x17, 0x74, 0x55, 0x0a, 0xde, 0x50, 0x67, 0x4d, 0x66, 0xd1, 0xa7, 0xff, 0xfd, 0xd9, 0xc0, +0xb5, 0xa8, 0xa3, 0x8a, 0xce, 0x66, 0xf5, 0x0f, 0x43, 0xcd, 0xa7, 0x2b, 0x57, 0x7b, 0x63, 0x46, +0x6a, 0xaa, 0x2e, 0x52, 0xd8, 0xf4, 0xed, 0xe1, 0x6d, 0xad, 0x29, 0x90, 0x78, 0x48, 0xba, 0xe1, +0x23, 0xaa, 0xa3, 0x89, 0xec, 0xb5, 0xab, 0x96, 0xc0, 0xb4, 0x4b, 0xa2, 0x1d, 0x97, 0x9e, 0x7a, +0xf2, 0x6e, 0x40, 0x71, 0xdf, 0x68, 0xf1, 0x65, 0x4d, 0xce, 0x7c, 0x05, 0xdf, 0x53, 0x65, 0xa9, +0xa5, 0xf0, 0xb1, 0x97, 0x04, 0x70, 0x15, 0x46, 0x03, 0x98, 0xd4, 0xd2, 0xbf, 0x54, 0xb4, 0xa0, +0x58, 0x7d, 0x52, 0x6f, 0xda, 0x56, 0x26, 0x62, 0xd4, 0xd8, 0xdb, 0x89, 0x31, 0x6f, 0x1c, 0xf0, +0x22, 0xc2, 0xd3, 0x62, 0x1c, 0x35, 0xcd, 0x4c, 0x69, 0x15, 0x54, 0x1a, 0x90, 0x98, 0xde, 0xeb, +0x1e, 0x5f, 0xca, 0x77, 0xc7, 0xcb, 0x8e, 0x3d, 0x43, 0x69, 0x9c, 0x9a, 0x58, 0xd0, 0x24, 0x3b, +0xdf, 0x1b, 0x40, 0x96, 0x7e, 0x35, 0xad, 0x81, 0xc7, 0x4e, 0x71, 0xba, 0x88, 0x13, 0x30, 0x82, +0x03, 0x72, 0x30, 0x82, 0x02, 0x5a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x3e, 0x8a, 0x5d, +0x07, 0xec, 0x55, 0xd2, 0x32, 0xd5, 0xb7, 0xe3, 0xb6, 0x5f, 0x01, 0xeb, 0x2d, 0xdc, 0xe4, 0xd6, +0xe4, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x30, 0x51, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, 0x31, +0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1f, 0x4b, 0x72, 0x61, 0x6a, 0x6f, 0x77, +0x61, 0x20, 0x49, 0x7a, 0x62, 0x61, 0x20, 0x52, 0x6f, 0x7a, 0x6c, 0x69, 0x63, 0x7a, 0x65, 0x6e, +0x69, 0x6f, 0x77, 0x61, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x0f, 0x53, 0x5a, 0x41, 0x46, 0x49, 0x52, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x20, +0x43, 0x41, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, 0x31, 0x39, 0x30, 0x37, 0x34, +0x33, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x31, 0x30, 0x31, 0x39, 0x30, 0x37, 0x34, 0x33, +0x33, 0x30, 0x5a, 0x30, 0x51, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x50, 0x4c, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1f, 0x4b, 0x72, 0x61, +0x6a, 0x6f, 0x77, 0x61, 0x20, 0x49, 0x7a, 0x62, 0x61, 0x20, 0x52, 0x6f, 0x7a, 0x6c, 0x69, 0x63, +0x7a, 0x65, 0x6e, 0x69, 0x6f, 0x77, 0x61, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x18, 0x30, 0x16, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x53, 0x5a, 0x41, 0x46, 0x49, 0x52, 0x20, 0x52, 0x4f, +0x4f, 0x54, 0x20, 0x43, 0x41, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, +0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb7, 0xbc, 0x3e, 0x50, 0xa8, 0x4b, 0xcd, 0x40, 0xb5, +0xce, 0x61, 0xe7, 0x96, 0xca, 0xb4, 0xa1, 0xda, 0x0c, 0x22, 0xb0, 0xfa, 0xb5, 0x7b, 0x76, 0x00, +0x77, 0x8c, 0x0b, 0xcf, 0x7d, 0xa8, 0x86, 0xcc, 0x26, 0x51, 0xe4, 0x20, 0x3d, 0x85, 0x0c, 0xd6, +0x58, 0xe3, 0xe7, 0xf4, 0x2a, 0x18, 0x9d, 0xda, 0xd1, 0xae, 0x26, 0xee, 0xeb, 0x53, 0xdc, 0xf4, +0x90, 0xd6, 0x13, 0x4a, 0x0c, 0x90, 0x3c, 0xc3, 0xf4, 0xda, 0xd2, 0x8e, 0x0d, 0x92, 0x3a, 0xdc, +0xb1, 0xb1, 0xff, 0x38, 0xde, 0xc3, 0xba, 0x2d, 0x5f, 0x80, 0xb9, 0x02, 0xbd, 0x4a, 0x9d, 0x1b, +0x0f, 0xb4, 0xc3, 0xc2, 0xc1, 0x67, 0x03, 0xdd, 0xdc, 0x1b, 0x9c, 0x3d, 0xb3, 0xb0, 0xde, 0x00, +0x1e, 0xa8, 0x34, 0x47, 0xbb, 0x9a, 0xeb, 0xfe, 0x0b, 0x14, 0xbd, 0x36, 0x84, 0xda, 0x0d, 0x20, +0xbf, 0xfa, 0x5b, 0xcb, 0xa9, 0x16, 0x20, 0xad, 0x39, 0x60, 0xee, 0x2f, 0x75, 0xb6, 0xe7, 0x97, +0x9c, 0xf9, 0x3e, 0xfd, 0x7e, 0x4d, 0x6f, 0x4d, 0x2f, 0xef, 0x88, 0x0d, 0x6a, 0xfa, 0xdd, 0xf1, +0x3d, 0x6e, 0x20, 0xa5, 0xa0, 0x12, 0xb4, 0x4d, 0x70, 0xb9, 0xce, 0xd7, 0x72, 0x3b, 0x89, 0x93, +0xa7, 0x80, 0x84, 0x1c, 0x27, 0x49, 0x72, 0x49, 0xb5, 0xff, 0x3b, 0x95, 0x9e, 0xc1, 0xcc, 0xc8, +0x01, 0xec, 0xe8, 0x0e, 0x8a, 0x0a, 0x96, 0xe7, 0xb3, 0xa6, 0x87, 0xe5, 0xd6, 0xf9, 0x05, 0x2b, +0x0d, 0x97, 0x40, 0x70, 0x3c, 0xba, 0xac, 0x75, 0x5a, 0x9c, 0xd5, 0x4d, 0x9d, 0x02, 0x0a, 0xd2, +0x4b, 0x9b, 0x66, 0x4b, 0x46, 0x07, 0x17, 0x65, 0xad, 0x9f, 0x6c, 0x88, 0x00, 0xdc, 0x22, 0x89, +0xe0, 0xe1, 0x64, 0xd4, 0x67, 0xbc, 0x31, 0x79, 0x61, 0x3c, 0xbb, 0xca, 0x41, 0xcd, 0x5c, 0x6a, +0x00, 0xc8, 0x3c, 0x38, 0x8e, 0x58, 0xaf, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, +0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2e, 0x16, 0xa9, 0x4a, +0x18, 0xb5, 0xcb, 0xcc, 0xf5, 0x6f, 0x50, 0xf3, 0x23, 0x5f, 0xf8, 0x5d, 0xe7, 0xac, 0xf0, 0xc8, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, +0x82, 0x01, 0x01, 0x00, 0xb5, 0x73, 0xf8, 0x03, 0xdc, 0x59, 0x5b, 0x1d, 0x76, 0xe9, 0xa3, 0x2a, +0x7b, 0x90, 0x28, 0xb2, 0x4d, 0xc0, 0x33, 0x4f, 0xaa, 0x9a, 0xb1, 0xd4, 0xb8, 0xe4, 0x27, 0xff, +0xa9, 0x96, 0x99, 0xce, 0x46, 0xe0, 0x6d, 0x7c, 0x4c, 0xa2, 0x38, 0xa4, 0x06, 0x70, 0xf0, 0xf4, +0x41, 0x11, 0xec, 0x3f, 0x47, 0x8d, 0x3f, 0x72, 0x87, 0xf9, 0x3b, 0xfd, 0xa4, 0x6f, 0x2b, 0x53, +0x00, 0xe0, 0xff, 0x39, 0xb9, 0x6a, 0x07, 0x0e, 0xeb, 0x1d, 0x1c, 0xf6, 0xa2, 0x72, 0x90, 0xcb, +0x82, 0x3d, 0x11, 0x82, 0x8b, 0xd2, 0xbb, 0x9f, 0x2a, 0xaf, 0x21, 0xe6, 0x63, 0x86, 0x9d, 0x79, +0x19, 0xef, 0xf7, 0xbb, 0x0c, 0x35, 0x90, 0xc3, 0x8a, 0xed, 0x4f, 0x0f, 0xf5, 0xcc, 0x12, 0xd9, +0xa4, 0x3e, 0xbb, 0xa0, 0xfc, 0x20, 0x95, 0x5f, 0x4f, 0x26, 0x2f, 0x11, 0x23, 0x83, 0x4e, 0x75, +0x07, 0x0f, 0xbf, 0x9b, 0xd1, 0xb4, 0x1d, 0xe9, 0x10, 0x04, 0xfe, 0xca, 0x60, 0x8f, 0xa2, 0x4c, +0xb8, 0xad, 0xcf, 0xe1, 0x90, 0x0f, 0xcd, 0xae, 0x0a, 0xc7, 0x5d, 0x7b, 0xb7, 0x50, 0xd2, 0xd4, +0x61, 0xfa, 0xd5, 0x15, 0xdb, 0xd7, 0x9f, 0x87, 0x51, 0x54, 0xeb, 0xa5, 0xe3, 0xeb, 0xc9, 0x85, +0xa0, 0x25, 0x20, 0x37, 0xfb, 0x8e, 0xce, 0x0c, 0x34, 0x84, 0xe1, 0x3c, 0x81, 0xb2, 0x77, 0x4e, +0x43, 0xa5, 0x88, 0x5f, 0x86, 0x67, 0xa1, 0x3d, 0xe6, 0xb4, 0x5c, 0x61, 0xb6, 0x3e, 0xdb, 0xfe, +0xb7, 0x28, 0xc5, 0xa2, 0x07, 0xae, 0xb5, 0xca, 0xca, 0x8d, 0x2a, 0x12, 0xef, 0x97, 0xed, 0xc2, +0x30, 0xa4, 0xc9, 0x2a, 0x7a, 0xfb, 0xf3, 0x4d, 0x23, 0x1b, 0x99, 0x33, 0x34, 0xa0, 0x2e, 0xf5, +0xa9, 0x0b, 0x3f, 0xd4, 0x5d, 0xe1, 0xcf, 0x84, 0x9f, 0xe2, 0x19, 0xc2, 0x5f, 0x8a, 0xd6, 0x20, +0x1e, 0xe3, 0x73, 0xb7, 0x30, 0x82, 0x05, 0xd2, 0x30, 0x82, 0x03, 0xba, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x10, 0x21, 0xd6, 0xd0, 0x4a, 0x4f, 0x25, 0x0f, 0xc9, 0x32, 0x37, 0xfc, 0xaa, 0x5e, +0x12, 0x8d, 0xe9, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, +0x05, 0x00, 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x50, 0x4c, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x55, 0x6e, 0x69, +0x7a, 0x65, 0x74, 0x6f, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, +0x73, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, +0x1e, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, +0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, +0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, +0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x31, 0x31, 0x30, 0x30, +0x36, 0x30, 0x38, 0x33, 0x39, 0x35, 0x36, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x34, 0x36, 0x31, 0x30, +0x30, 0x36, 0x30, 0x38, 0x33, 0x39, 0x35, 0x36, 0x5a, 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x19, 0x55, 0x6e, 0x69, 0x7a, 0x65, 0x74, 0x6f, 0x20, 0x54, 0x65, 0x63, 0x68, +0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, +0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, +0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, +0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x1b, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, +0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x82, 0x02, 0x22, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, +0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xbd, 0xf9, 0x78, +0xf8, 0xe6, 0xd5, 0x80, 0x0c, 0x64, 0x9d, 0x86, 0x1b, 0x96, 0x64, 0x67, 0x3f, 0x22, 0x3a, 0x1e, +0x75, 0x01, 0x7d, 0xef, 0xfb, 0x5c, 0x67, 0x8c, 0xc9, 0xcc, 0x5c, 0x6b, 0xa9, 0x91, 0xe6, 0xb9, +0x42, 0xe5, 0x20, 0x4b, 0x9b, 0xda, 0x9b, 0x7b, 0xb9, 0x99, 0x5d, 0xd9, 0x9b, 0x80, 0x4b, 0xd7, +0x84, 0x40, 0x2b, 0x27, 0xd3, 0xe8, 0xba, 0x30, 0xbb, 0x3e, 0x09, 0x1a, 0xa7, 0x49, 0x95, 0xef, +0x2b, 0x40, 0x24, 0xc2, 0x97, 0xc7, 0xa7, 0xee, 0x9b, 0x25, 0xef, 0xa8, 0x0a, 0x00, 0x97, 0x85, +0x5a, 0xaa, 0x9d, 0xdc, 0x29, 0xc9, 0xe2, 0x35, 0x07, 0xeb, 0x70, 0x4d, 0x4a, 0xd6, 0xc1, 0xb3, +0x56, 0xb8, 0xa1, 0x41, 0x38, 0x9b, 0xd1, 0xfb, 0x31, 0x7f, 0x8f, 0xe0, 0x5f, 0xe1, 0xb1, 0x3f, +0x0f, 0x8e, 0x16, 0x49, 0x60, 0xd7, 0x06, 0x8d, 0x18, 0xf9, 0xaa, 0x26, 0x10, 0xab, 0x2a, 0xd3, +0xd0, 0xd1, 0x67, 0x8d, 0x1b, 0x46, 0xbe, 0x47, 0x30, 0xd5, 0x2e, 0x72, 0xd1, 0xc5, 0x63, 0xda, +0xe7, 0x63, 0x79, 0x44, 0x7e, 0x4b, 0x63, 0x24, 0x89, 0x86, 0x2e, 0x34, 0x3f, 0x29, 0x4c, 0x52, +0x8b, 0x2a, 0xa7, 0xc0, 0xe2, 0x91, 0x28, 0x89, 0xb9, 0xc0, 0x5b, 0xf9, 0x1d, 0xd9, 0xe7, 0x27, +0xad, 0xff, 0x9a, 0x02, 0x97, 0xc1, 0xc6, 0x50, 0x92, 0x9b, 0x02, 0x2c, 0xbd, 0xa9, 0xb9, 0x34, +0x59, 0x0a, 0xbf, 0x84, 0x4a, 0xff, 0xdf, 0xfe, 0xb3, 0x9f, 0xeb, 0xd9, 0x9e, 0xe0, 0x98, 0x23, +0xec, 0xa6, 0x6b, 0x77, 0x16, 0x2a, 0xdb, 0xcc, 0xad, 0x3b, 0x1c, 0xa4, 0x87, 0xdc, 0x46, 0x73, +0x5e, 0x19, 0x62, 0x68, 0x45, 0x57, 0xe4, 0x90, 0x82, 0x42, 0xbb, 0x42, 0xd6, 0xf0, 0x61, 0xe0, +0xc1, 0xa3, 0x3d, 0x66, 0xa3, 0x5d, 0xf4, 0x18, 0xee, 0x88, 0xc9, 0x8d, 0x17, 0x45, 0x29, 0x99, +0x32, 0x75, 0x02, 0x31, 0xee, 0x29, 0x26, 0xc8, 0x6b, 0x02, 0xe6, 0xb5, 0x62, 0x45, 0x7f, 0x37, +0x15, 0x5a, 0x23, 0x68, 0x89, 0xd4, 0x3e, 0xde, 0x4e, 0x27, 0xb0, 0xf0, 0x40, 0x0c, 0xbc, 0x4d, +0x17, 0xcb, 0x4d, 0xa2, 0xb3, 0x1e, 0xd0, 0x06, 0x5a, 0xdd, 0xf6, 0x93, 0xcf, 0x57, 0x75, 0x99, +0xf5, 0xfa, 0x86, 0x1a, 0x67, 0x78, 0xb3, 0xbf, 0x96, 0xfe, 0x34, 0xdc, 0xbd, 0xe7, 0x52, 0x56, +0xe5, 0xb3, 0xe5, 0x75, 0x7b, 0xd7, 0x41, 0x91, 0x05, 0xdc, 0x5d, 0x69, 0xe3, 0x95, 0x0d, 0x43, +0xb9, 0xfc, 0x83, 0x96, 0x39, 0x95, 0x7b, 0x6c, 0x80, 0x5a, 0x4f, 0x13, 0x72, 0xc6, 0xd7, 0x7d, +0x29, 0x7a, 0x44, 0xba, 0x52, 0xa4, 0x2a, 0xd5, 0x41, 0x46, 0x09, 0x20, 0xfe, 0x22, 0xa0, 0xb6, +0x5b, 0x30, 0x8d, 0xbc, 0x89, 0x0c, 0xd5, 0xd7, 0x70, 0xf8, 0x87, 0x52, 0xfd, 0xda, 0xef, 0xac, +0x51, 0x2e, 0x07, 0xb3, 0x4e, 0xfe, 0xd0, 0x09, 0xda, 0x70, 0xef, 0x98, 0xfa, 0x56, 0xe6, 0x6d, +0xdb, 0xb5, 0x57, 0x4b, 0xdc, 0xe5, 0x2c, 0x25, 0x15, 0xc8, 0x9e, 0x2e, 0x78, 0x4e, 0xf8, 0xda, +0x9c, 0x9e, 0x86, 0x2c, 0xca, 0x57, 0xf3, 0x1a, 0xe5, 0xc8, 0x92, 0x8b, 0x1a, 0x82, 0x96, 0x7a, +0xc3, 0xbc, 0x50, 0x12, 0x69, 0xd8, 0x0e, 0x5a, 0x46, 0x8b, 0x3a, 0xeb, 0x26, 0xfa, 0x23, 0xc9, +0xb6, 0xb0, 0x81, 0xbe, 0x42, 0x00, 0xa4, 0xf8, 0xd6, 0xfe, 0x30, 0x2e, 0xc7, 0xd2, 0x46, 0xf6, +0xe5, 0x8e, 0x75, 0xfd, 0xf2, 0xcc, 0xb9, 0xd0, 0x87, 0x5b, 0xcc, 0x06, 0x10, 0x60, 0xbb, 0x83, +0x35, 0xb7, 0x5e, 0x67, 0xde, 0x47, 0xec, 0x99, 0x48, 0xf1, 0xa4, 0xa1, 0x15, 0xfe, 0xad, 0x8c, +0x62, 0x8e, 0x39, 0x55, 0x4f, 0x39, 0x16, 0xb9, 0xb1, 0x63, 0x9d, 0xff, 0xb7, 0x02, 0x03, 0x01, +0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, +0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, +0x04, 0x14, 0xb6, 0xa1, 0x54, 0x39, 0x02, 0xc3, 0xa0, 0x3f, 0x8e, 0x8a, 0xbc, 0xfa, 0xd4, 0xf8, +0x1c, 0xa6, 0xd1, 0x3a, 0x0e, 0xfd, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x71, 0xa5, 0x0e, 0xce, 0xe4, 0xe9, +0xbf, 0x3f, 0x38, 0xd5, 0x89, 0x5a, 0xc4, 0x02, 0x61, 0xfb, 0x4c, 0xc5, 0x14, 0x17, 0x2d, 0x8b, +0x4f, 0x53, 0x6b, 0x10, 0x17, 0xfc, 0x65, 0x84, 0xc7, 0x10, 0x49, 0x90, 0xde, 0xdb, 0xc7, 0x26, +0x93, 0x88, 0x26, 0x6f, 0x70, 0xd6, 0x02, 0x5e, 0x39, 0xa0, 0xf7, 0x8f, 0xab, 0x96, 0xb5, 0xa5, +0x13, 0x5c, 0x81, 0x14, 0x6d, 0x0e, 0x81, 0x82, 0x11, 0x1b, 0x8a, 0x4e, 0xc6, 0x4f, 0xa5, 0xdd, +0x62, 0x1e, 0x44, 0xdf, 0x09, 0x59, 0xf4, 0x5b, 0x77, 0x0b, 0x37, 0xe9, 0x8b, 0x20, 0xc6, 0xf8, +0x0a, 0x4e, 0x2e, 0x58, 0x1c, 0xeb, 0x33, 0xd0, 0xcf, 0x86, 0x60, 0xc9, 0xda, 0xfb, 0x80, 0x2f, +0x9e, 0x4c, 0x60, 0x84, 0x78, 0x3d, 0x21, 0x64, 0xd6, 0xfb, 0x41, 0x1f, 0x18, 0x0f, 0xe7, 0xc9, +0x75, 0x71, 0xbd, 0xbd, 0x5c, 0xde, 0x34, 0x87, 0x3e, 0x41, 0xb0, 0x0e, 0xf6, 0xb9, 0xd6, 0x3f, +0x09, 0x13, 0x96, 0x14, 0x2f, 0xde, 0x9a, 0x1d, 0x5a, 0xb9, 0x56, 0xce, 0x35, 0x3a, 0xb0, 0x5f, +0x70, 0x4d, 0x5e, 0xe3, 0x29, 0xf1, 0x23, 0x28, 0x72, 0x59, 0xb6, 0xab, 0xc2, 0x8c, 0x66, 0x26, +0x1c, 0x77, 0x2c, 0x26, 0x76, 0x35, 0x8b, 0x28, 0xa7, 0x69, 0xa0, 0xf9, 0x3b, 0xf5, 0x23, 0xdd, +0x85, 0x10, 0x74, 0xc9, 0x90, 0x03, 0x56, 0x91, 0xe7, 0xaf, 0xba, 0x47, 0xd4, 0x12, 0x97, 0x11, +0x22, 0xe3, 0xa2, 0x49, 0x94, 0x6c, 0xe7, 0xb7, 0x94, 0x4b, 0xba, 0x2d, 0xa4, 0xda, 0x33, 0x8b, +0x4c, 0xa6, 0x44, 0xff, 0x5a, 0x3c, 0xc6, 0x1d, 0x64, 0xd8, 0xb5, 0x31, 0xe4, 0xa6, 0x3c, 0x7a, +0xa8, 0x57, 0x0b, 0xdb, 0xed, 0x61, 0x1a, 0xcb, 0xf1, 0xce, 0x73, 0x77, 0x63, 0xa4, 0x87, 0x6f, +0x4c, 0x51, 0x38, 0xd6, 0xe4, 0x5f, 0xc7, 0x9f, 0xb6, 0x81, 0x2a, 0xe4, 0x85, 0x48, 0x79, 0x58, +0x5e, 0x3b, 0xf8, 0xdb, 0x02, 0x82, 0x67, 0xc1, 0x39, 0xdb, 0xc3, 0x74, 0x4b, 0x3d, 0x36, 0x1e, +0xf9, 0x29, 0x93, 0x88, 0x68, 0x5b, 0xa8, 0x44, 0x19, 0x21, 0xf0, 0xa7, 0xe8, 0x81, 0x0d, 0x2c, +0xe8, 0x93, 0x36, 0xb4, 0x37, 0xb2, 0xca, 0xb0, 0x1b, 0x26, 0x7a, 0x9a, 0x25, 0x1f, 0x9a, 0x9a, +0x80, 0x9e, 0x4b, 0x2a, 0x3f, 0xfb, 0xa3, 0x9a, 0xfe, 0x73, 0x32, 0x71, 0xc2, 0x9e, 0xc6, 0x72, +0xe1, 0x8a, 0x68, 0x27, 0xf1, 0xe4, 0x0f, 0xb4, 0xc4, 0x4c, 0xa5, 0x61, 0x93, 0xf8, 0x97, 0x10, +0x07, 0x2a, 0x30, 0x25, 0xa9, 0xb9, 0xc8, 0x71, 0xb8, 0xef, 0x68, 0xcc, 0x2d, 0x7e, 0xf5, 0xe0, +0x7e, 0x0f, 0x82, 0xa8, 0x6f, 0xb6, 0xba, 0x6c, 0x83, 0x43, 0x77, 0xcd, 0x8a, 0x92, 0x17, 0xa1, +0x9e, 0x5b, 0x78, 0x16, 0x3d, 0x45, 0xe2, 0x33, 0x72, 0xdd, 0xe1, 0x66, 0xca, 0x99, 0xd3, 0xc9, +0xc5, 0x26, 0xfd, 0x0d, 0x68, 0x04, 0x46, 0xae, 0xb6, 0xd9, 0x9b, 0x8c, 0xbe, 0x19, 0xbe, 0xb1, +0xc6, 0xf2, 0x19, 0xe3, 0x5c, 0x02, 0xca, 0x2c, 0xd8, 0x6f, 0x4a, 0x07, 0xd9, 0xc9, 0x35, 0xda, +0x40, 0x75, 0xf2, 0xc4, 0xa7, 0x19, 0x6f, 0x9e, 0x42, 0x10, 0x98, 0x75, 0xe6, 0x95, 0x8b, 0x60, +0xbc, 0xed, 0xc5, 0x12, 0xd7, 0x8a, 0xce, 0xd5, 0x98, 0x5c, 0x56, 0x96, 0x03, 0xc5, 0xee, 0x77, +0x06, 0x35, 0xff, 0xcf, 0xe4, 0xee, 0x3f, 0x13, 0x61, 0xee, 0xdb, 0xda, 0x2d, 0x85, 0xf0, 0xcd, +0xae, 0x9d, 0xb2, 0x18, 0x09, 0x45, 0xc3, 0x92, 0xa1, 0x72, 0x17, 0xfc, 0x47, 0xb6, 0xa0, 0x0b, +0x2c, 0xf1, 0xc4, 0xde, 0x43, 0x68, 0x08, 0x6a, 0x5f, 0x3b, 0xf0, 0x76, 0x63, 0xfb, 0xcc, 0x06, +0x2c, 0xa6, 0xc6, 0xe2, 0x0e, 0xb5, 0xb9, 0xbe, 0x24, 0x8f, 0x30, 0x82, 0x02, 0x6e, 0x30, 0x82, +0x01, 0xf3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x62, 0xf6, 0x32, 0x6c, 0xe5, 0xc4, 0xe3, +0x68, 0x5c, 0x1b, 0x62, 0xdd, 0x9c, 0x2e, 0x9d, 0x95, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x78, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x46, +0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x0c, 0x05, 0x43, 0x65, 0x72, 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, +0x0c, 0x0f, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2d, 0x51, 0x32, 0x38, 0x32, 0x36, 0x30, 0x30, 0x34, +0x4a, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x23, 0x41, 0x43, 0x20, 0x52, +0x41, 0x49, 0x5a, 0x20, 0x46, 0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x20, 0x53, 0x45, 0x52, +0x56, 0x49, 0x44, 0x4f, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, 0x4f, 0x53, 0x30, +0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x32, 0x32, 0x30, 0x30, 0x39, 0x33, 0x37, 0x33, 0x33, 0x5a, +0x17, 0x0d, 0x34, 0x33, 0x31, 0x32, 0x32, 0x30, 0x30, 0x39, 0x33, 0x37, 0x33, 0x33, 0x5a, 0x30, +0x78, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x11, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x46, 0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, +0x4d, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x05, 0x43, 0x65, 0x72, 0x65, +0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0c, 0x0f, 0x56, 0x41, 0x54, 0x45, +0x53, 0x2d, 0x51, 0x32, 0x38, 0x32, 0x36, 0x30, 0x30, 0x34, 0x4a, 0x31, 0x2c, 0x30, 0x2a, 0x06, +0x03, 0x55, 0x04, 0x03, 0x0c, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5a, 0x20, 0x46, 0x4e, +0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, 0x44, 0x4f, 0x52, 0x45, +0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52, 0x4f, 0x53, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, +0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, +0x04, 0xf6, 0xba, 0x57, 0x53, 0xc8, 0xca, 0xab, 0xdf, 0x36, 0x4a, 0x52, 0x21, 0xe4, 0x97, 0xd2, +0x83, 0x67, 0x9e, 0xf0, 0x65, 0x51, 0xd0, 0x5e, 0x87, 0xc7, 0x47, 0xb1, 0x59, 0xf2, 0x57, 0x47, +0x9b, 0x00, 0x02, 0x93, 0x44, 0x17, 0x69, 0xdb, 0x42, 0xc7, 0xb1, 0xb2, 0x3a, 0x18, 0x0e, 0xb4, +0x5d, 0x8c, 0xb3, 0x66, 0x5d, 0xa1, 0x34, 0xf9, 0x36, 0x2c, 0x49, 0xdb, 0xf3, 0x46, 0xfc, 0xb3, +0x44, 0x69, 0x44, 0x13, 0x66, 0xfd, 0xd7, 0xc5, 0xfd, 0xaf, 0x36, 0x4d, 0xce, 0x03, 0x4d, 0x07, +0x71, 0xcf, 0xaf, 0x6a, 0x05, 0xd2, 0xa2, 0x43, 0x5a, 0x0a, 0x52, 0x6f, 0x01, 0x03, 0x4e, 0x8e, +0x8b, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0x01, 0xb9, 0x2f, 0xef, 0xbf, 0x11, 0x86, 0x60, 0xf2, 0x4f, 0xd0, 0x41, 0x6e, 0xab, 0x73, +0x1f, 0xe7, 0xd2, 0x6e, 0x49, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, +0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xae, 0x4a, 0xe3, 0x2b, 0x40, 0xc3, 0x74, +0x11, 0xf2, 0x95, 0xad, 0x16, 0x23, 0xde, 0x4e, 0x0c, 0x1a, 0xe6, 0x5d, 0xa5, 0x24, 0x5e, 0x6b, +0x44, 0x7b, 0xfc, 0x38, 0xe2, 0x4f, 0xcb, 0x9c, 0x45, 0x17, 0x11, 0x4c, 0x14, 0x27, 0x26, 0x55, +0x39, 0x75, 0x4a, 0x03, 0xcc, 0x13, 0x90, 0x9f, 0x92, 0x02, 0x31, 0x00, 0xfa, 0x4a, 0x6c, 0x60, +0x88, 0x73, 0xf3, 0xee, 0xb8, 0x98, 0x62, 0xa9, 0xce, 0x2b, 0xc2, 0xd9, 0x8a, 0xa6, 0x70, 0x31, +0x1d, 0xaf, 0xb0, 0x94, 0x4c, 0xeb, 0x4f, 0xc6, 0xe3, 0xd1, 0xf3, 0x62, 0xa7, 0x3c, 0xff, 0x93, +0x2e, 0x07, 0x5c, 0x49, 0x01, 0x67, 0x69, 0x12, 0x02, 0x72, 0xbf, 0xe7, 0x30, 0x82, 0x05, 0x6b, +0x30, 0x82, 0x03, 0x53, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0x82, 0x10, 0xcf, 0xb0, +0xd2, 0x40, 0xe3, 0x59, 0x44, 0x63, 0xe0, 0xbb, 0x63, 0x82, 0x8b, 0x00, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x4f, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x53, 0x65, +0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, +0x47, 0x72, 0x6f, 0x75, 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0c, +0x49, 0x53, 0x52, 0x47, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x58, 0x31, 0x30, 0x1e, 0x17, 0x0d, +0x31, 0x35, 0x30, 0x36, 0x30, 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x33, +0x35, 0x30, 0x36, 0x30, 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, 0x5a, 0x30, 0x4f, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x53, +0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, +0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x0c, 0x49, 0x53, 0x52, 0x47, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x58, 0x31, 0x30, 0x82, 0x02, +0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, +0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xad, 0xe8, +0x24, 0x73, 0xf4, 0x14, 0x37, 0xf3, 0x9b, 0x9e, 0x2b, 0x57, 0x28, 0x1c, 0x87, 0xbe, 0xdc, 0xb7, +0xdf, 0x38, 0x90, 0x8c, 0x6e, 0x3c, 0xe6, 0x57, 0xa0, 0x78, 0xf7, 0x75, 0xc2, 0xa2, 0xfe, 0xf5, +0x6a, 0x6e, 0xf6, 0x00, 0x4f, 0x28, 0xdb, 0xde, 0x68, 0x86, 0x6c, 0x44, 0x93, 0xb6, 0xb1, 0x63, +0xfd, 0x14, 0x12, 0x6b, 0xbf, 0x1f, 0xd2, 0xea, 0x31, 0x9b, 0x21, 0x7e, 0xd1, 0x33, 0x3c, 0xba, +0x48, 0xf5, 0xdd, 0x79, 0xdf, 0xb3, 0xb8, 0xff, 0x12, 0xf1, 0x21, 0x9a, 0x4b, 0xc1, 0x8a, 0x86, +0x71, 0x69, 0x4a, 0x66, 0x66, 0x6c, 0x8f, 0x7e, 0x3c, 0x70, 0xbf, 0xad, 0x29, 0x22, 0x06, 0xf3, +0xe4, 0xc0, 0xe6, 0x80, 0xae, 0xe2, 0x4b, 0x8f, 0xb7, 0x99, 0x7e, 0x94, 0x03, 0x9f, 0xd3, 0x47, +0x97, 0x7c, 0x99, 0x48, 0x23, 0x53, 0xe8, 0x38, 0xae, 0x4f, 0x0a, 0x6f, 0x83, 0x2e, 0xd1, 0x49, +0x57, 0x8c, 0x80, 0x74, 0xb6, 0xda, 0x2f, 0xd0, 0x38, 0x8d, 0x7b, 0x03, 0x70, 0x21, 0x1b, 0x75, +0xf2, 0x30, 0x3c, 0xfa, 0x8f, 0xae, 0xdd, 0xda, 0x63, 0xab, 0xeb, 0x16, 0x4f, 0xc2, 0x8e, 0x11, +0x4b, 0x7e, 0xcf, 0x0b, 0xe8, 0xff, 0xb5, 0x77, 0x2e, 0xf4, 0xb2, 0x7b, 0x4a, 0xe0, 0x4c, 0x12, +0x25, 0x0c, 0x70, 0x8d, 0x03, 0x29, 0xa0, 0xe1, 0x53, 0x24, 0xec, 0x13, 0xd9, 0xee, 0x19, 0xbf, +0x10, 0xb3, 0x4a, 0x8c, 0x3f, 0x89, 0xa3, 0x61, 0x51, 0xde, 0xac, 0x87, 0x07, 0x94, 0xf4, 0x63, +0x71, 0xec, 0x2e, 0xe2, 0x6f, 0x5b, 0x98, 0x81, 0xe1, 0x89, 0x5c, 0x34, 0x79, 0x6c, 0x76, 0xef, +0x3b, 0x90, 0x62, 0x79, 0xe6, 0xdb, 0xa4, 0x9a, 0x2f, 0x26, 0xc5, 0xd0, 0x10, 0xe1, 0x0e, 0xde, +0xd9, 0x10, 0x8e, 0x16, 0xfb, 0xb7, 0xf7, 0xa8, 0xf7, 0xc7, 0xe5, 0x02, 0x07, 0x98, 0x8f, 0x36, +0x08, 0x95, 0xe7, 0xe2, 0x37, 0x96, 0x0d, 0x36, 0x75, 0x9e, 0xfb, 0x0e, 0x72, 0xb1, 0x1d, 0x9b, +0xbc, 0x03, 0xf9, 0x49, 0x05, 0xd8, 0x81, 0xdd, 0x05, 0xb4, 0x2a, 0xd6, 0x41, 0xe9, 0xac, 0x01, +0x76, 0x95, 0x0a, 0x0f, 0xd8, 0xdf, 0xd5, 0xbd, 0x12, 0x1f, 0x35, 0x2f, 0x28, 0x17, 0x6c, 0xd2, +0x98, 0xc1, 0xa8, 0x09, 0x64, 0x77, 0x6e, 0x47, 0x37, 0xba, 0xce, 0xac, 0x59, 0x5e, 0x68, 0x9d, +0x7f, 0x72, 0xd6, 0x89, 0xc5, 0x06, 0x41, 0x29, 0x3e, 0x59, 0x3e, 0xdd, 0x26, 0xf5, 0x24, 0xc9, +0x11, 0xa7, 0x5a, 0xa3, 0x4c, 0x40, 0x1f, 0x46, 0xa1, 0x99, 0xb5, 0xa7, 0x3a, 0x51, 0x6e, 0x86, +0x3b, 0x9e, 0x7d, 0x72, 0xa7, 0x12, 0x05, 0x78, 0x59, 0xed, 0x3e, 0x51, 0x78, 0x15, 0x0b, 0x03, +0x8f, 0x8d, 0xd0, 0x2f, 0x05, 0xb2, 0x3e, 0x7b, 0x4a, 0x1c, 0x4b, 0x73, 0x05, 0x12, 0xfc, 0xc6, +0xea, 0xe0, 0x50, 0x13, 0x7c, 0x43, 0x93, 0x74, 0xb3, 0xca, 0x74, 0xe7, 0x8e, 0x1f, 0x01, 0x08, +0xd0, 0x30, 0xd4, 0x5b, 0x71, 0x36, 0xb4, 0x07, 0xba, 0xc1, 0x30, 0x30, 0x5c, 0x48, 0xb7, 0x82, +0x3b, 0x98, 0xa6, 0x7d, 0x60, 0x8a, 0xa2, 0xa3, 0x29, 0x82, 0xcc, 0xba, 0xbd, 0x83, 0x04, 0x1b, +0xa2, 0x83, 0x03, 0x41, 0xa1, 0xd6, 0x05, 0xf1, 0x1b, 0xc2, 0xb6, 0xf0, 0xa8, 0x7c, 0x86, 0x3b, +0x46, 0xa8, 0x48, 0x2a, 0x88, 0xdc, 0x76, 0x9a, 0x76, 0xbf, 0x1f, 0x6a, 0xa5, 0x3d, 0x19, 0x8f, +0xeb, 0x38, 0xf3, 0x64, 0xde, 0xc8, 0x2b, 0x0d, 0x0a, 0x28, 0xff, 0xf7, 0xdb, 0xe2, 0x15, 0x42, +0xd4, 0x22, 0xd0, 0x27, 0x5d, 0xe1, 0x79, 0xfe, 0x18, 0xe7, 0x70, 0x88, 0xad, 0x4e, 0xe6, 0xd9, +0x8b, 0x3a, 0xc6, 0xdd, 0x27, 0x51, 0x6e, 0xff, 0xbc, 0x64, 0xf5, 0x33, 0x43, 0x4f, 0x02, 0x03, +0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, +0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0x79, 0xb4, 0x59, 0xe6, 0x7b, 0xb6, 0xe5, 0xe4, 0x01, 0x73, 0x80, 0x08, 0x88, +0xc8, 0x1a, 0x58, 0xf6, 0xe9, 0x9b, 0x6e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x55, 0x1f, 0x58, 0xa9, 0xbc, +0xb2, 0xa8, 0x50, 0xd0, 0x0c, 0xb1, 0xd8, 0x1a, 0x69, 0x20, 0x27, 0x29, 0x08, 0xac, 0x61, 0x75, +0x5c, 0x8a, 0x6e, 0xf8, 0x82, 0xe5, 0x69, 0x2f, 0xd5, 0xf6, 0x56, 0x4b, 0xb9, 0xb8, 0x73, 0x10, +0x59, 0xd3, 0x21, 0x97, 0x7e, 0xe7, 0x4c, 0x71, 0xfb, 0xb2, 0xd2, 0x60, 0xad, 0x39, 0xa8, 0x0b, +0xea, 0x17, 0x21, 0x56, 0x85, 0xf1, 0x50, 0x0e, 0x59, 0xeb, 0xce, 0xe0, 0x59, 0xe9, 0xba, 0xc9, +0x15, 0xef, 0x86, 0x9d, 0x8f, 0x84, 0x80, 0xf6, 0xe4, 0xe9, 0x91, 0x90, 0xdc, 0x17, 0x9b, 0x62, +0x1b, 0x45, 0xf0, 0x66, 0x95, 0xd2, 0x7c, 0x6f, 0xc2, 0xea, 0x3b, 0xef, 0x1f, 0xcf, 0xcb, 0xd6, +0xae, 0x27, 0xf1, 0xa9, 0xb0, 0xc8, 0xae, 0xfd, 0x7d, 0x7e, 0x9a, 0xfa, 0x22, 0x04, 0xeb, 0xff, +0xd9, 0x7f, 0xea, 0x91, 0x2b, 0x22, 0xb1, 0x17, 0x0e, 0x8f, 0xf2, 0x8a, 0x34, 0x5b, 0x58, 0xd8, +0xfc, 0x01, 0xc9, 0x54, 0xb9, 0xb8, 0x26, 0xcc, 0x8a, 0x88, 0x33, 0x89, 0x4c, 0x2d, 0x84, 0x3c, +0x82, 0xdf, 0xee, 0x96, 0x57, 0x05, 0xba, 0x2c, 0xbb, 0xf7, 0xc4, 0xb7, 0xc7, 0x4e, 0x3b, 0x82, +0xbe, 0x31, 0xc8, 0x22, 0x73, 0x73, 0x92, 0xd1, 0xc2, 0x80, 0xa4, 0x39, 0x39, 0x10, 0x33, 0x23, +0x82, 0x4c, 0x3c, 0x9f, 0x86, 0xb2, 0x55, 0x98, 0x1d, 0xbe, 0x29, 0x86, 0x8c, 0x22, 0x9b, 0x9e, +0xe2, 0x6b, 0x3b, 0x57, 0x3a, 0x82, 0x70, 0x4d, 0xdc, 0x09, 0xc7, 0x89, 0xcb, 0x0a, 0x07, 0x4d, +0x6c, 0xe8, 0x5d, 0x8e, 0xc9, 0xef, 0xce, 0xab, 0xc7, 0xbb, 0xb5, 0x2b, 0x4e, 0x45, 0xd6, 0x4a, +0xd0, 0x26, 0xcc, 0xe5, 0x72, 0xca, 0x08, 0x6a, 0xa5, 0x95, 0xe3, 0x15, 0xa1, 0xf7, 0xa4, 0xed, +0xc9, 0x2c, 0x5f, 0xa5, 0xfb, 0xff, 0xac, 0x28, 0x02, 0x2e, 0xbe, 0xd7, 0x7b, 0xbb, 0xe3, 0x71, +0x7b, 0x90, 0x16, 0xd3, 0x07, 0x5e, 0x46, 0x53, 0x7c, 0x37, 0x07, 0x42, 0x8c, 0xd3, 0xc4, 0x96, +0x9c, 0xd5, 0x99, 0xb5, 0x2a, 0xe0, 0x95, 0x1a, 0x80, 0x48, 0xae, 0x4c, 0x39, 0x07, 0xce, 0xcc, +0x47, 0xa4, 0x52, 0x95, 0x2b, 0xba, 0xb8, 0xfb, 0xad, 0xd2, 0x33, 0x53, 0x7d, 0xe5, 0x1d, 0x4d, +0x6d, 0xd5, 0xa1, 0xb1, 0xc7, 0x42, 0x6f, 0xe6, 0x40, 0x27, 0x35, 0x5c, 0xa3, 0x28, 0xb7, 0x07, +0x8d, 0xe7, 0x8d, 0x33, 0x90, 0xe7, 0x23, 0x9f, 0xfb, 0x50, 0x9c, 0x79, 0x6c, 0x46, 0xd5, 0xb4, +0x15, 0xb3, 0x96, 0x6e, 0x7e, 0x9b, 0x0c, 0x96, 0x3a, 0xb8, 0x52, 0x2d, 0x3f, 0xd6, 0x5b, 0xe1, +0xfb, 0x08, 0xc2, 0x84, 0xfe, 0x24, 0xa8, 0xa3, 0x89, 0xda, 0xac, 0x6a, 0xe1, 0x18, 0x2a, 0xb1, +0xa8, 0x43, 0x61, 0x5b, 0xd3, 0x1f, 0xdc, 0x3b, 0x8d, 0x76, 0xf2, 0x2d, 0xe8, 0x8d, 0x75, 0xdf, +0x17, 0x33, 0x6c, 0x3d, 0x53, 0xfb, 0x7b, 0xcb, 0x41, 0x5f, 0xff, 0xdc, 0xa2, 0xd0, 0x61, 0x38, +0xe1, 0x96, 0xb8, 0xac, 0x5d, 0x8b, 0x37, 0xd7, 0x75, 0xd5, 0x33, 0xc0, 0x99, 0x11, 0xae, 0x9d, +0x41, 0xc1, 0x72, 0x75, 0x84, 0xbe, 0x02, 0x41, 0x42, 0x5f, 0x67, 0x24, 0x48, 0x94, 0xd1, 0x9b, +0x27, 0xbe, 0x07, 0x3f, 0xb9, 0xb8, 0x4f, 0x81, 0x74, 0x51, 0xe1, 0x7a, 0xb7, 0xed, 0x9d, 0x23, +0xe2, 0xbe, 0xe0, 0xd5, 0x28, 0x04, 0x13, 0x3c, 0x31, 0x03, 0x9e, 0xdd, 0x7a, 0x6c, 0x8f, 0xc6, +0x07, 0x18, 0xc6, 0x7f, 0xde, 0x47, 0x8e, 0x3f, 0x28, 0x9e, 0x04, 0x06, 0xcf, 0xa5, 0x54, 0x34, +0x77, 0xbd, 0xec, 0x89, 0x9b, 0xe9, 0x17, 0x43, 0xdf, 0x5b, 0xdb, 0x5f, 0xfe, 0x8e, 0x1e, 0x57, +0xa2, 0xcd, 0x40, 0x9d, 0x7e, 0x62, 0x22, 0xda, 0xde, 0x18, 0x27, 0x30, 0x82, 0x04, 0x63, 0x30, +0x82, 0x03, 0x4b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xd2, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, +0x55, 0x04, 0x07, 0x13, 0x0f, 0x47, 0x65, 0x62, 0x7a, 0x65, 0x20, 0x2d, 0x20, 0x4b, 0x6f, 0x63, +0x61, 0x65, 0x6c, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x39, 0x54, +0x75, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x20, 0x42, 0x69, 0x6c, 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x20, +0x76, 0x65, 0x20, 0x54, 0x65, 0x6b, 0x6e, 0x6f, 0x6c, 0x6f, 0x6a, 0x69, 0x6b, 0x20, 0x41, 0x72, +0x61, 0x73, 0x74, 0x69, 0x72, 0x6d, 0x61, 0x20, 0x4b, 0x75, 0x72, 0x75, 0x6d, 0x75, 0x20, 0x2d, +0x20, 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4b, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x13, 0x24, 0x4b, 0x61, 0x6d, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6b, +0x61, 0x73, 0x79, 0x6f, 0x6e, 0x20, 0x4d, 0x65, 0x72, 0x6b, 0x65, 0x7a, 0x69, 0x20, 0x2d, 0x20, +0x4b, 0x61, 0x6d, 0x75, 0x20, 0x53, 0x4d, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x2d, 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4b, 0x20, 0x4b, 0x61, 0x6d, 0x75, 0x20, 0x53, +0x4d, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x4b, 0x6f, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x6b, 0x61, 0x73, 0x69, 0x20, 0x2d, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6d, 0x20, 0x31, 0x30, +0x1e, 0x17, 0x0d, 0x31, 0x33, 0x31, 0x31, 0x32, 0x35, 0x30, 0x38, 0x32, 0x35, 0x35, 0x35, 0x5a, +0x17, 0x0d, 0x34, 0x33, 0x31, 0x30, 0x32, 0x35, 0x30, 0x38, 0x32, 0x35, 0x35, 0x35, 0x5a, 0x30, +0x81, 0xd2, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x52, 0x31, +0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0f, 0x47, 0x65, 0x62, 0x7a, 0x65, 0x20, +0x2d, 0x20, 0x4b, 0x6f, 0x63, 0x61, 0x65, 0x6c, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x20, 0x42, 0x69, 0x6c, 0x69, +0x6d, 0x73, 0x65, 0x6c, 0x20, 0x76, 0x65, 0x20, 0x54, 0x65, 0x6b, 0x6e, 0x6f, 0x6c, 0x6f, 0x6a, +0x69, 0x6b, 0x20, 0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6d, 0x61, 0x20, 0x4b, 0x75, 0x72, +0x75, 0x6d, 0x75, 0x20, 0x2d, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4b, 0x31, 0x2d, 0x30, +0x2b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x4b, 0x61, 0x6d, 0x75, 0x20, 0x53, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x6b, 0x61, 0x73, 0x79, 0x6f, 0x6e, 0x20, 0x4d, 0x65, 0x72, 0x6b, 0x65, +0x7a, 0x69, 0x20, 0x2d, 0x20, 0x4b, 0x61, 0x6d, 0x75, 0x20, 0x53, 0x4d, 0x31, 0x36, 0x30, 0x34, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4b, 0x20, 0x4b, +0x61, 0x6d, 0x75, 0x20, 0x53, 0x4d, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x4b, 0x6f, 0x6b, 0x20, 0x53, +0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6b, 0x61, 0x73, 0x69, 0x20, 0x2d, 0x20, 0x53, 0x75, 0x72, +0x75, 0x6d, 0x20, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, +0x02, 0x82, 0x01, 0x01, 0x00, 0xaf, 0x75, 0x30, 0x33, 0xaa, 0xbb, 0x6b, 0xd3, 0x99, 0x2c, 0x12, +0x37, 0x84, 0xd9, 0x8d, 0x7b, 0x97, 0x80, 0xd3, 0x6e, 0xe7, 0xff, 0x9b, 0x50, 0x95, 0x3e, 0x90, +0x95, 0x56, 0x42, 0xd7, 0x19, 0x7c, 0x26, 0x84, 0x8d, 0x92, 0xfa, 0x01, 0x1d, 0x3a, 0x0f, 0xe2, +0x64, 0x38, 0xb7, 0x8c, 0xbc, 0xe8, 0x88, 0xf9, 0x8b, 0x24, 0xab, 0x2e, 0xa3, 0xf5, 0x37, 0xe4, +0x40, 0x8e, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1f, 0x3b, 0xff, 0x6c, 0xa8, 0xc5, 0xc6, 0x56, 0xf8, +0xb4, 0xed, 0x8a, 0x44, 0xa3, 0xab, 0x6c, 0x4c, 0xfc, 0x1d, 0xd0, 0xdc, 0xef, 0x68, 0xbd, 0xcf, +0xe4, 0xaa, 0xce, 0xf0, 0x55, 0xf7, 0xa2, 0x34, 0xd4, 0x83, 0x6b, 0x37, 0x7c, 0x1c, 0xc2, 0xfe, +0xb5, 0x03, 0xec, 0x57, 0xce, 0xbc, 0xb4, 0xb5, 0xc5, 0xed, 0x00, 0x0f, 0x53, 0x37, 0x2a, 0x4d, +0xf4, 0x4f, 0x0c, 0x83, 0xfb, 0x86, 0xcf, 0xcb, 0xfe, 0x8c, 0x4e, 0xbd, 0x87, 0xf9, 0xa7, 0x8b, +0x21, 0x57, 0x9c, 0x7a, 0xdf, 0x03, 0x67, 0x89, 0x2c, 0x9d, 0x97, 0x61, 0xa7, 0x10, 0xb8, 0x55, +0x90, 0x7f, 0x0e, 0x2d, 0x27, 0x38, 0x74, 0xdf, 0xe7, 0xfd, 0xda, 0x4e, 0x12, 0xe3, 0x4d, 0x15, +0x22, 0x02, 0xc8, 0xe0, 0xe0, 0xfc, 0x0f, 0xad, 0x8a, 0xd7, 0xc9, 0x54, 0x50, 0xcc, 0x3b, 0x0f, +0xca, 0x16, 0x80, 0x84, 0xd0, 0x51, 0x56, 0xc3, 0x8e, 0x56, 0x7f, 0x89, 0x22, 0x33, 0x2f, 0xe6, +0x85, 0x0a, 0xbd, 0xa5, 0xa8, 0x1b, 0x36, 0xde, 0xd3, 0xdc, 0x2c, 0x6d, 0x3b, 0xc7, 0x13, 0xbd, +0x59, 0x23, 0x2c, 0xe6, 0xe5, 0xa4, 0xf7, 0xd8, 0x0b, 0xed, 0xea, 0x90, 0x40, 0x44, 0xa8, 0x95, +0xbb, 0x93, 0xd5, 0xd0, 0x80, 0x34, 0xb6, 0x46, 0x78, 0x0e, 0x1f, 0x00, 0x93, 0x46, 0xe1, 0xee, +0xe9, 0xf9, 0xec, 0x4f, 0x17, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x65, 0x3f, 0xc7, 0x8a, 0x86, 0xc6, 0x3c, +0xdd, 0x3c, 0x54, 0x5c, 0x35, 0xf8, 0x3a, 0xed, 0x52, 0x0c, 0x47, 0x57, 0xc8, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, +0x01, 0x00, 0x2a, 0x3f, 0xe1, 0xf1, 0x32, 0x8e, 0xae, 0xe1, 0x98, 0x5c, 0x4b, 0x5e, 0xcf, 0x6b, +0x1e, 0x6a, 0x09, 0xd2, 0x22, 0xa9, 0x12, 0xc7, 0x5e, 0x57, 0x7d, 0x73, 0x56, 0x64, 0x80, 0x84, +0x7a, 0x93, 0xe4, 0x09, 0xb9, 0x10, 0xcd, 0x9f, 0x2a, 0x27, 0xe1, 0x00, 0x77, 0xbe, 0x48, 0xc8, +0x35, 0xa8, 0x81, 0x9f, 0xe4, 0xb8, 0x2c, 0xc9, 0x7f, 0x0e, 0xb0, 0xd2, 0x4b, 0x37, 0x5d, 0xea, +0xb9, 0xd5, 0x0b, 0x5e, 0x34, 0xbd, 0xf4, 0x73, 0x29, 0xc3, 0xed, 0x26, 0x15, 0x9c, 0x7e, 0x08, +0x53, 0x8a, 0x58, 0x8d, 0xd0, 0x4b, 0x28, 0xdf, 0xc1, 0xb3, 0xdf, 0x20, 0xf3, 0xf9, 0xe3, 0xe3, +0x3a, 0xdf, 0xcc, 0x9c, 0x94, 0xd8, 0x4e, 0x4f, 0xc3, 0x6b, 0x17, 0xb7, 0xf7, 0x72, 0xe8, 0xad, +0x66, 0x33, 0xb5, 0x25, 0x53, 0xab, 0xe0, 0xf8, 0x4c, 0xa9, 0x9d, 0xfd, 0xf2, 0x0d, 0xba, 0xae, +0xb9, 0xd9, 0xaa, 0xc6, 0x6b, 0xf9, 0x93, 0xbb, 0xae, 0xab, 0xb8, 0x97, 0x3c, 0x03, 0x1a, 0xba, +0x43, 0xc6, 0x96, 0xb9, 0x45, 0x72, 0x38, 0xb3, 0xa7, 0xa1, 0x96, 0x3d, 0x91, 0x7b, 0x7e, 0xc0, +0x21, 0x53, 0x4c, 0x87, 0xed, 0xf2, 0x0b, 0x54, 0x95, 0x51, 0x93, 0xd5, 0x22, 0xa5, 0x0d, 0x8a, +0xf1, 0x93, 0x0e, 0x3e, 0x54, 0x0e, 0xb0, 0xd8, 0xc9, 0x4e, 0xdc, 0xf2, 0x31, 0x32, 0x56, 0xea, +0x64, 0xf9, 0xea, 0xb5, 0x9d, 0x16, 0x66, 0x42, 0x72, 0xf3, 0x7f, 0xd3, 0xb1, 0x31, 0x43, 0xfc, +0xa4, 0x8e, 0x17, 0xf1, 0x6d, 0x23, 0xab, 0x94, 0x66, 0xf8, 0xad, 0xfb, 0x0f, 0x08, 0x6e, 0x26, +0x2d, 0x7f, 0x17, 0x07, 0x09, 0xb2, 0x8c, 0xfb, 0x50, 0xc0, 0x9f, 0x96, 0x8d, 0xcf, 0xb6, 0xfd, +0x00, 0x9d, 0x5a, 0x14, 0x9a, 0xbf, 0x02, 0x44, 0xf5, 0xc1, 0xc2, 0x9f, 0x22, 0x5e, 0xa2, 0x0f, +0xa1, 0xe3, 0x30, 0x82, 0x01, 0xb6, 0x30, 0x82, 0x01, 0x5b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x13, 0x06, 0x6c, 0x9f, 0xd5, 0x74, 0x97, 0x36, 0x66, 0x3f, 0x3b, 0x0b, 0x9a, 0xd9, 0xe8, 0x9e, +0x76, 0x03, 0xf2, 0x4a, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, +0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, +0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, +0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x30, +0x30, 0x35, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x39, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, +0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, +0x04, 0x29, 0x97, 0xa7, 0xc6, 0x41, 0x7f, 0xc0, 0x0d, 0x9b, 0xe8, 0x01, 0x1b, 0x56, 0xc6, 0xf2, +0x52, 0xa5, 0xba, 0x2d, 0xb2, 0x12, 0xe8, 0xd2, 0x2e, 0xd7, 0xfa, 0xc9, 0xc5, 0xd8, 0xaa, 0x6d, +0x1f, 0x73, 0x81, 0x3b, 0x3b, 0x98, 0x6b, 0x39, 0x7c, 0x33, 0xa5, 0xc5, 0x4e, 0x86, 0x8e, 0x80, +0x17, 0x68, 0x62, 0x45, 0x57, 0x7d, 0x44, 0x58, 0x1d, 0xb3, 0x37, 0xe5, 0x67, 0x08, 0xeb, 0x66, +0xde, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0xab, 0xb6, 0xdb, 0xd7, 0x06, 0x9e, 0x37, 0xac, 0x30, 0x86, 0x07, 0x91, 0x70, 0xc7, 0x9c, +0xc4, 0x19, 0xb1, 0x78, 0xc0, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, +0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xe0, 0x85, 0x92, 0xa3, 0x17, 0xb7, 0x8d, +0xf9, 0x2b, 0x06, 0xa5, 0x93, 0xac, 0x1a, 0x98, 0x68, 0x61, 0x72, 0xfa, 0xe1, 0xa1, 0xd0, 0xfb, +0x1c, 0x78, 0x60, 0xa6, 0x43, 0x99, 0xc5, 0xb8, 0xc4, 0x02, 0x21, 0x00, 0x9c, 0x02, 0xef, 0xf1, +0x94, 0x9c, 0xb3, 0x96, 0xf9, 0xeb, 0xc6, 0x2a, 0xf8, 0xb6, 0x2c, 0xfe, 0x3a, 0x90, 0x14, 0x16, +0xd7, 0x8c, 0x63, 0x24, 0x48, 0x1c, 0xdf, 0x30, 0x7d, 0xd5, 0x68, 0x3b, 0x30, 0x82, 0x05, 0x88, +0x30, 0x82, 0x03, 0x70, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x7d, 0x09, 0x97, 0xfe, 0xf0, +0x47, 0xea, 0x7a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, +0x05, 0x00, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, +0x4e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x29, 0x47, 0x55, 0x41, 0x4e, +0x47, 0x20, 0x44, 0x4f, 0x4e, 0x47, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, +0x54, 0x45, 0x20, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43, 0x4f, 0x2e, +0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, +0x47, 0x44, 0x43, 0x41, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, +0x35, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x31, 0x32, 0x36, +0x30, 0x35, 0x31, 0x33, 0x31, 0x35, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, +0x35, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x43, 0x4e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x29, +0x47, 0x55, 0x41, 0x4e, 0x47, 0x20, 0x44, 0x4f, 0x4e, 0x47, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, +0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, +0x20, 0x43, 0x4f, 0x2e, 0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x55, +0x54, 0x48, 0x20, 0x52, 0x35, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, +0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xd9, 0xa3, 0x16, 0xf0, 0xc8, +0x74, 0x74, 0x77, 0x9b, 0xef, 0x33, 0x0d, 0x3b, 0x06, 0x7e, 0x55, 0xfc, 0xb5, 0x60, 0x8f, 0x76, +0x86, 0x12, 0x42, 0x7d, 0x56, 0x66, 0x3e, 0x88, 0x82, 0xed, 0x72, 0x63, 0x0e, 0x9e, 0x8b, 0xdd, +0x34, 0x2c, 0x02, 0x51, 0x51, 0xc3, 0x19, 0xfd, 0x59, 0x54, 0x84, 0xc9, 0xf1, 0x6b, 0xb3, 0x4c, +0xb0, 0xe9, 0xe8, 0x46, 0x5d, 0x38, 0xc6, 0xa2, 0xa7, 0x2e, 0x11, 0x57, 0xba, 0x82, 0x15, 0xa2, +0x9c, 0x8f, 0x6d, 0xb0, 0x99, 0x4a, 0x0a, 0xf2, 0xeb, 0x89, 0x70, 0x63, 0x4e, 0x79, 0xc4, 0xb7, +0x5b, 0xbd, 0xa2, 0x5d, 0xb1, 0xf2, 0x41, 0x02, 0x2b, 0xad, 0xa9, 0x3a, 0xa3, 0xec, 0x79, 0x0a, +0xec, 0x5f, 0x3a, 0xe3, 0xfd, 0xef, 0x80, 0x3c, 0xad, 0x34, 0x9b, 0x1a, 0xab, 0x88, 0x26, 0x7b, +0x56, 0xa2, 0x82, 0x86, 0x1f, 0xeb, 0x35, 0x89, 0x83, 0x7f, 0x5f, 0xae, 0x29, 0x4e, 0x3d, 0xb6, +0x6e, 0xec, 0xae, 0xc1, 0xf0, 0x27, 0x9b, 0xae, 0xe3, 0xf4, 0xec, 0xef, 0xae, 0x7f, 0xf7, 0x86, +0x3d, 0x72, 0x7a, 0xeb, 0xa5, 0xfb, 0x59, 0x4e, 0xa7, 0xeb, 0x95, 0x8c, 0x22, 0x39, 0x79, 0xe1, +0x2d, 0x08, 0x8f, 0xcc, 0xbc, 0x91, 0xb8, 0x41, 0xf7, 0x14, 0xc1, 0x23, 0xa9, 0xc3, 0xad, 0x9a, +0x45, 0x44, 0xb3, 0xb2, 0xd7, 0x2c, 0xcd, 0xc6, 0x29, 0xe2, 0x50, 0x10, 0xae, 0x5c, 0xcb, 0x82, +0x8e, 0x17, 0x18, 0x36, 0x7d, 0x97, 0xe6, 0x88, 0x9a, 0xb0, 0x4d, 0x34, 0x09, 0xf4, 0x2c, 0xb9, +0x5a, 0x66, 0x2a, 0xb0, 0x17, 0x9b, 0x9e, 0x1e, 0x76, 0x9d, 0x4a, 0x66, 0x31, 0x41, 0xdf, 0x3f, +0xfb, 0xc5, 0x06, 0xef, 0x1b, 0xb6, 0x7e, 0x1a, 0x46, 0x36, 0xf7, 0x64, 0x63, 0x3b, 0xe3, 0x39, +0x18, 0x23, 0xe7, 0x67, 0x75, 0x14, 0xd5, 0x75, 0x57, 0x92, 0x37, 0xbd, 0xbe, 0x6a, 0x1b, 0x26, +0x50, 0xf2, 0x36, 0x26, 0x06, 0x90, 0xc5, 0x70, 0x01, 0x64, 0x6d, 0x76, 0x66, 0xe1, 0x91, 0xdb, +0x6e, 0x07, 0xc0, 0x61, 0x80, 0x2e, 0xb2, 0x2e, 0x2f, 0x8c, 0x70, 0xa7, 0xd1, 0x3b, 0x3c, 0xb3, +0x91, 0xe4, 0x6e, 0xb6, 0xc4, 0x3b, 0x70, 0xf2, 0x6c, 0x92, 0x97, 0x09, 0xcd, 0x47, 0x7d, 0x18, +0xc0, 0xf3, 0xbb, 0x9e, 0x0f, 0xd6, 0x8b, 0xae, 0x07, 0xb6, 0x5a, 0x0f, 0xce, 0x0b, 0x0c, 0x47, +0xa7, 0xe5, 0x3e, 0xb8, 0xbd, 0x7d, 0xc7, 0x9b, 0x35, 0xa0, 0x61, 0x97, 0x3a, 0x41, 0x75, 0x17, +0xcc, 0x2b, 0x96, 0x77, 0x2a, 0x92, 0x21, 0x1e, 0xd9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xcf, 0x0d, +0xbd, 0xdf, 0xd6, 0x1f, 0x09, 0x6a, 0x9a, 0xe2, 0xcc, 0x73, 0x71, 0xa4, 0x2f, 0x7d, 0x12, 0x80, +0xb7, 0x53, 0x30, 0x46, 0x5e, 0x4b, 0x54, 0x99, 0x0f, 0x67, 0xc9, 0xa5, 0xc8, 0xf2, 0x20, 0xc1, +0x82, 0xec, 0x9d, 0x11, 0xdf, 0xc2, 0x02, 0xfb, 0x1a, 0x3b, 0xd1, 0xed, 0x20, 0x9a, 0xef, 0x65, +0x64, 0x92, 0x10, 0x0d, 0x2a, 0xe2, 0xde, 0x70, 0xf1, 0x18, 0x67, 0x82, 0x8c, 0x61, 0xde, 0xb8, +0xbc, 0xd1, 0x2f, 0x9c, 0xfb, 0x0f, 0xd0, 0x2b, 0xed, 0x1b, 0x76, 0xb9, 0xe4, 0x39, 0x55, 0xf8, +0xf8, 0xa1, 0x1d, 0xb8, 0xaa, 0x80, 0x00, 0x4c, 0x82, 0xe7, 0xb2, 0x7f, 0x09, 0xb8, 0xbc, 0x30, +0xa0, 0x2f, 0x0d, 0xf5, 0x52, 0x9e, 0x8e, 0xf7, 0x92, 0xb3, 0x0a, 0x00, 0x1d, 0x00, 0x54, 0x97, +0x06, 0xe0, 0xb1, 0x07, 0xd9, 0xc7, 0x0f, 0x5c, 0x65, 0x7d, 0x3c, 0x6d, 0x59, 0x57, 0xe4, 0xed, +0xa5, 0x8d, 0xe9, 0x40, 0x53, 0x9f, 0x15, 0x4b, 0xa0, 0x71, 0xf6, 0x1a, 0x21, 0xe3, 0xda, 0x70, +0x06, 0x21, 0x58, 0x14, 0x87, 0x85, 0x77, 0x79, 0xaa, 0x82, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, +0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe2, +0xc9, 0x40, 0x9f, 0x4d, 0xce, 0xe8, 0x9a, 0xa1, 0x7c, 0xcf, 0x0e, 0x3f, 0x65, 0xc5, 0x29, 0x88, +0x6a, 0x19, 0x51, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x86, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xd1, 0x49, 0x57, 0xe0, 0xa7, 0xcc, 0x68, 0x58, +0xba, 0x01, 0x0f, 0x2b, 0x19, 0xcd, 0x8d, 0xb0, 0x61, 0x45, 0xac, 0x11, 0xed, 0x63, 0x50, 0x69, +0xf8, 0x1f, 0x7f, 0xbe, 0x16, 0x8f, 0xfd, 0x9d, 0xeb, 0x0b, 0xaa, 0x32, 0x47, 0x76, 0xd2, 0x67, +0x24, 0xed, 0xbd, 0x7c, 0x33, 0x32, 0x97, 0x2a, 0xc7, 0x05, 0x86, 0x66, 0x0d, 0x17, 0x7d, 0x14, +0x15, 0x1b, 0xd4, 0xeb, 0xfd, 0x1f, 0x9a, 0xf6, 0x5e, 0x97, 0x69, 0xb7, 0x1a, 0x25, 0xa4, 0x0a, +0xb3, 0x91, 0x3f, 0x5f, 0x36, 0xac, 0x8b, 0xec, 0x57, 0xa8, 0x3e, 0xe7, 0x81, 0x8a, 0x18, 0x57, +0x39, 0x85, 0x74, 0x1a, 0x42, 0xc7, 0xe9, 0x5b, 0x13, 0x5f, 0x8f, 0xf9, 0x08, 0xe9, 0x92, 0x74, +0x8d, 0xf5, 0x47, 0xd2, 0xab, 0x3b, 0xd6, 0xfb, 0x78, 0x66, 0x4e, 0x36, 0x7d, 0xf9, 0xe9, 0x92, +0xe9, 0x04, 0xde, 0xfd, 0x49, 0x63, 0xfc, 0x6d, 0xfb, 0x14, 0x71, 0x93, 0x67, 0x2f, 0x47, 0x4a, +0xb7, 0xb9, 0xff, 0x1e, 0x2a, 0x73, 0x70, 0x46, 0x30, 0xbf, 0x5a, 0xf2, 0x2f, 0x79, 0xa5, 0xe1, +0x8d, 0x0c, 0xd9, 0xf9, 0xb2, 0x63, 0x37, 0x8c, 0x37, 0x65, 0x85, 0x70, 0x6a, 0x5c, 0x5b, 0x09, +0x72, 0xb9, 0xad, 0x63, 0x3c, 0xb1, 0xdd, 0xf8, 0xfc, 0x32, 0xbf, 0x37, 0x86, 0xe4, 0xbb, 0x8e, +0x98, 0x27, 0x7e, 0xba, 0x1f, 0x16, 0xe1, 0x70, 0x11, 0xf2, 0x03, 0xdf, 0x25, 0x62, 0x32, 0x27, +0x26, 0x18, 0x32, 0x84, 0x9f, 0xff, 0x00, 0x3a, 0x13, 0xba, 0x9a, 0x4d, 0xf4, 0x4f, 0xb8, 0x14, +0x70, 0x22, 0xb1, 0xca, 0x2b, 0x90, 0xce, 0x29, 0xc1, 0x70, 0xf4, 0x2f, 0x9d, 0x7f, 0xf2, 0x90, +0x1e, 0xd6, 0x5a, 0xdf, 0xb7, 0x46, 0xfc, 0xe6, 0x86, 0xfa, 0xcb, 0xe0, 0x20, 0x76, 0x7a, 0xba, +0xa6, 0xcb, 0xf5, 0x7c, 0xde, 0x62, 0xa5, 0xb1, 0x8b, 0xee, 0xde, 0x82, 0x66, 0x8a, 0x4e, 0x3a, +0x30, 0x1f, 0x3f, 0x80, 0xcb, 0xad, 0x27, 0xba, 0x0c, 0x5e, 0xd7, 0xd0, 0xb1, 0x56, 0xca, 0x77, +0x71, 0xb2, 0xb5, 0x75, 0xa1, 0x50, 0xa9, 0x40, 0x43, 0x17, 0xc2, 0x28, 0xd9, 0xcf, 0x52, 0x8b, +0x5b, 0xc8, 0x63, 0xd4, 0x42, 0x3e, 0xa0, 0x33, 0x7a, 0x46, 0x2e, 0xf7, 0x0a, 0x20, 0x46, 0x54, +0x7e, 0x6a, 0x4f, 0x31, 0xf1, 0x81, 0x7e, 0x42, 0x74, 0x38, 0x65, 0x73, 0x27, 0xee, 0xc6, 0x7c, +0xb8, 0x8e, 0xd7, 0xa5, 0x3a, 0xd7, 0x98, 0xa1, 0x9c, 0x8c, 0x10, 0x55, 0xd3, 0xdb, 0x4b, 0xec, +0x40, 0x90, 0xf2, 0xcd, 0x6e, 0x57, 0xd2, 0x62, 0x0e, 0x7c, 0x57, 0x93, 0xb1, 0xa7, 0x6d, 0xcd, +0x9d, 0x83, 0xbb, 0x2a, 0xe7, 0xe5, 0xb6, 0x3b, 0x71, 0x58, 0xad, 0xfd, 0xd1, 0x45, 0xbc, 0x5a, +0x91, 0xee, 0x53, 0x15, 0x6f, 0xd3, 0x45, 0x09, 0x75, 0x6e, 0xba, 0x90, 0x5d, 0x1e, 0x04, 0xcf, +0x37, 0xdf, 0x1e, 0xa8, 0x66, 0xb1, 0x8c, 0xe6, 0x20, 0x6a, 0xef, 0xfc, 0x48, 0x4e, 0x74, 0x98, +0x42, 0xaf, 0x29, 0x6f, 0x2e, 0x6a, 0xc7, 0xfb, 0x7d, 0xd1, 0x66, 0x31, 0x22, 0xcc, 0x86, 0x00, +0x7e, 0x66, 0x83, 0x0c, 0x42, 0xf4, 0xbd, 0x34, 0x92, 0xc3, 0x1a, 0xea, 0x4f, 0xca, 0x7e, 0x72, +0x4d, 0x0b, 0x70, 0x8c, 0xa6, 0x48, 0xbb, 0xa6, 0xa1, 0x14, 0xf6, 0xfb, 0x58, 0x44, 0x99, 0x14, +0xae, 0xaa, 0x0b, 0x93, 0x69, 0xa0, 0x29, 0x25, 0x4a, 0xa5, 0xcb, 0x2b, 0xdd, 0x8a, 0x66, 0x07, +0x16, 0x78, 0x15, 0x57, 0x71, 0x1b, 0xec, 0xf5, 0x47, 0x84, 0xf3, 0x9e, 0x31, 0x37, 0x7a, 0xd5, +0x7f, 0x24, 0xad, 0xe4, 0xbc, 0xfd, 0xfd, 0xcc, 0x6e, 0x83, 0xe8, 0x0c, 0xa8, 0xb7, 0x41, 0x6c, +0x07, 0xdd, 0xbd, 0x3c, 0x86, 0x97, 0x2f, 0xd2, 0x30, 0x82, 0x05, 0x41, 0x30, 0x82, 0x03, 0x29, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x06, 0x6c, 0x9f, 0xd2, 0x96, 0x35, 0x86, 0x9f, 0x0a, +0x0f, 0xe5, 0x86, 0x78, 0xf8, 0x5b, 0x26, 0xbb, 0x8a, 0x37, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x41, 0x20, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, +0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x5a, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, +0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, +0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, +0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, +0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, +0xad, 0x96, 0x9f, 0x2d, 0x9c, 0x4a, 0x4c, 0x4a, 0x81, 0x79, 0x51, 0x99, 0xec, 0x8a, 0xcb, 0x6b, +0x60, 0x51, 0x13, 0xbc, 0x4d, 0x6d, 0x06, 0xfc, 0xb0, 0x08, 0x8d, 0xdd, 0x19, 0x10, 0x6a, 0xc7, +0x26, 0x0c, 0x35, 0xd8, 0xc0, 0x6f, 0x20, 0x84, 0xe9, 0x94, 0xb1, 0x9b, 0x85, 0x03, 0xc3, 0x5b, +0xdb, 0x4a, 0xe8, 0xc8, 0xf8, 0x90, 0x76, 0xd9, 0x5b, 0x4f, 0xe3, 0x4c, 0xe8, 0x06, 0x36, 0x4d, +0xcc, 0x9a, 0xac, 0x3d, 0x0c, 0x90, 0x2b, 0x92, 0xd4, 0x06, 0x19, 0x60, 0xac, 0x37, 0x44, 0x79, +0x85, 0x81, 0x82, 0xad, 0x5a, 0x37, 0xe0, 0x0d, 0xcc, 0x9d, 0xa6, 0x4c, 0x52, 0x76, 0xea, 0x43, +0x9d, 0xb7, 0x04, 0xd1, 0x50, 0xf6, 0x55, 0xe0, 0xd5, 0xd2, 0xa6, 0x49, 0x85, 0xe9, 0x37, 0xe9, +0xca, 0x7e, 0xae, 0x5c, 0x95, 0x4d, 0x48, 0x9a, 0x3f, 0xae, 0x20, 0x5a, 0x6d, 0x88, 0x95, 0xd9, +0x34, 0xb8, 0x52, 0x1a, 0x43, 0x90, 0xb0, 0xbf, 0x6c, 0x05, 0xb9, 0xb6, 0x78, 0xb7, 0xea, 0xd0, +0xe4, 0x3a, 0x3c, 0x12, 0x53, 0x62, 0xff, 0x4a, 0xf2, 0x7b, 0xbe, 0x35, 0x05, 0xa9, 0x12, 0x34, +0xe3, 0xf3, 0x64, 0x74, 0x62, 0x2c, 0x3d, 0x00, 0x49, 0x5a, 0x28, 0xfe, 0x32, 0x44, 0xbb, 0x87, +0xdd, 0x65, 0x27, 0x02, 0x71, 0x3b, 0xda, 0x4a, 0xf7, 0x1f, 0xda, 0xcd, 0xf7, 0x21, 0x55, 0x90, +0x4f, 0x0f, 0xec, 0xae, 0x82, 0xe1, 0x9f, 0x6b, 0xd9, 0x45, 0xd3, 0xbb, 0xf0, 0x5f, 0x87, 0xed, +0x3c, 0x2c, 0x39, 0x86, 0xda, 0x3f, 0xde, 0xec, 0x72, 0x55, 0xeb, 0x79, 0xa3, 0xad, 0xdb, 0xdd, +0x7c, 0xb0, 0xba, 0x1c, 0xce, 0xfc, 0xde, 0x4f, 0x35, 0x76, 0xcf, 0x0f, 0xf8, 0x78, 0x1f, 0x6a, +0x36, 0x51, 0x46, 0x27, 0x61, 0x5b, 0xe9, 0x9e, 0xcf, 0xf0, 0xa2, 0x55, 0x7d, 0x7c, 0x25, 0x8a, +0x6f, 0x2f, 0xb4, 0xc5, 0xcf, 0x84, 0x2e, 0x2b, 0xfd, 0x0d, 0x51, 0x10, 0x6c, 0xfb, 0x5f, 0x1b, +0xbc, 0x1b, 0x7e, 0xc5, 0xae, 0x3b, 0x98, 0x01, 0x31, 0x92, 0xff, 0x0b, 0x57, 0xf4, 0x9a, 0xb2, +0xb9, 0x57, 0xe9, 0xab, 0xef, 0x0d, 0x76, 0xd1, 0xf0, 0xee, 0xf4, 0xce, 0x86, 0xa7, 0xe0, 0x6e, +0xe9, 0xb4, 0x69, 0xa1, 0xdf, 0x69, 0xf6, 0x33, 0xc6, 0x69, 0x2e, 0x97, 0x13, 0x9e, 0xa5, 0x87, +0xb0, 0x57, 0x10, 0x81, 0x37, 0xc9, 0x53, 0xb3, 0xbb, 0x7f, 0xf6, 0x92, 0xd1, 0x9c, 0xd0, 0x18, +0xf4, 0x92, 0x6e, 0xda, 0x83, 0x4f, 0xa6, 0x63, 0x99, 0x4c, 0xa5, 0xfb, 0x5e, 0xef, 0x21, 0x64, +0x7a, 0x20, 0x5f, 0x6c, 0x64, 0x85, 0x15, 0xcb, 0x37, 0xe9, 0x62, 0x0c, 0x0b, 0x2a, 0x16, 0xdc, +0x01, 0x2e, 0x32, 0xda, 0x3e, 0x4b, 0xf5, 0x9e, 0x3a, 0xf6, 0x17, 0x40, 0x94, 0xef, 0x9e, 0x91, +0x08, 0x86, 0xfa, 0xbe, 0x63, 0xa8, 0x5a, 0x33, 0xec, 0xcb, 0x74, 0x43, 0x95, 0xf9, 0x6c, 0x69, +0x52, 0x36, 0xc7, 0x29, 0x6f, 0xfc, 0x55, 0x03, 0x5c, 0x1f, 0xfb, 0x9f, 0xbd, 0x47, 0xeb, 0xe7, +0x49, 0x47, 0x95, 0x0b, 0x4e, 0x89, 0x22, 0x09, 0x49, 0xe0, 0xf5, 0x61, 0x1e, 0xf1, 0xbf, 0x2e, +0x8a, 0x72, 0x6e, 0x80, 0x59, 0xff, 0x57, 0x3a, 0xf9, 0x75, 0x32, 0xa3, 0x4e, 0x5f, 0xec, 0xed, +0x28, 0x62, 0xd9, 0x4d, 0x73, 0xf2, 0xcc, 0x81, 0x17, 0x60, 0xed, 0xcd, 0xeb, 0xdc, 0xdb, 0xa7, +0xca, 0xc5, 0x7e, 0x02, 0xbd, 0xf2, 0x54, 0x08, 0x54, 0xfd, 0xb4, 0x2d, 0x09, 0x2c, 0x17, 0x54, +0x4a, 0x98, 0xd1, 0x54, 0xe1, 0x51, 0x67, 0x08, 0xd2, 0xed, 0x6e, 0x7e, 0x6f, 0x3f, 0xd2, 0x2d, +0x81, 0x59, 0x29, 0x66, 0xcb, 0x90, 0x39, 0x95, 0x11, 0x1e, 0x74, 0x27, 0xfe, 0xdd, 0xeb, 0xaf, +0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, +0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0xb0, 0x0c, 0xf0, 0x4c, 0x30, 0xf4, 0x05, 0x58, 0x02, 0x48, 0xfd, +0x33, 0xe5, 0x52, 0xaf, 0x4b, 0x84, 0xe3, 0x66, 0x52, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xaa, 0xa8, 0x80, +0x8f, 0x0e, 0x78, 0xa3, 0xe0, 0xa2, 0xd4, 0xcd, 0xe6, 0xf5, 0x98, 0x7a, 0x3b, 0xea, 0x00, 0x03, +0xb0, 0x97, 0x0e, 0x93, 0xbc, 0x5a, 0xa8, 0xf6, 0x2c, 0x8c, 0x72, 0x87, 0xa9, 0xb1, 0xfc, 0x7f, +0x73, 0xfd, 0x63, 0x71, 0x78, 0xa5, 0x87, 0x59, 0xcf, 0x30, 0xe1, 0x0d, 0x10, 0xb2, 0x13, 0x5a, +0x6d, 0x82, 0xf5, 0x6a, 0xe6, 0x80, 0x9f, 0xa0, 0x05, 0x0b, 0x68, 0xe4, 0x47, 0x6b, 0xc7, 0x6a, +0xdf, 0xb6, 0xfd, 0x77, 0x32, 0x72, 0xe5, 0x18, 0xfa, 0x09, 0xf4, 0xa0, 0x93, 0x2c, 0x5d, 0xd2, +0x8c, 0x75, 0x85, 0x76, 0x65, 0x90, 0x0c, 0x03, 0x79, 0xb7, 0x31, 0x23, 0x63, 0xad, 0x78, 0x83, +0x09, 0x86, 0x68, 0x84, 0xca, 0xff, 0xf9, 0xcf, 0x26, 0x9a, 0x92, 0x79, 0xe7, 0xcd, 0x4b, 0xc5, +0xe7, 0x61, 0xa7, 0x17, 0xcb, 0xf3, 0xa9, 0x12, 0x93, 0x93, 0x6b, 0xa7, 0xe8, 0x2f, 0x53, 0x92, +0xc4, 0x60, 0x58, 0xb0, 0xcc, 0x02, 0x51, 0x18, 0x5b, 0x85, 0x8d, 0x62, 0x59, 0x63, 0xb6, 0xad, +0xb4, 0xde, 0x9a, 0xfb, 0x26, 0xf7, 0x00, 0x27, 0xc0, 0x5d, 0x55, 0x37, 0x74, 0x99, 0xc9, 0x50, +0x7f, 0xe3, 0x59, 0x2e, 0x44, 0xe3, 0x2c, 0x25, 0xee, 0xec, 0x4c, 0x32, 0x77, 0xb4, 0x9f, 0x1a, +0xe9, 0x4b, 0x5d, 0x20, 0xc5, 0xda, 0xfd, 0x1c, 0x87, 0x16, 0xc6, 0x43, 0xe8, 0xd4, 0xbb, 0x26, +0x9a, 0x45, 0x70, 0x5e, 0xa9, 0x0b, 0x37, 0x53, 0xe2, 0x46, 0x7b, 0x27, 0xfd, 0xe0, 0x46, 0xf2, +0x89, 0xb7, 0xcc, 0x42, 0xb6, 0xcb, 0x28, 0x26, 0x6e, 0xd9, 0xa5, 0xc9, 0x3a, 0xc8, 0x41, 0x13, +0x60, 0xf7, 0x50, 0x8c, 0x15, 0xae, 0xb2, 0x6d, 0x1a, 0x15, 0x1a, 0x57, 0x78, 0xe6, 0x92, 0x2a, +0xd9, 0x65, 0x90, 0x82, 0x3f, 0x6c, 0x02, 0xaf, 0xae, 0x12, 0x3a, 0x27, 0x96, 0x36, 0x04, 0xd7, +0x1d, 0xa2, 0x80, 0x63, 0xa9, 0x9b, 0xf1, 0xe5, 0xba, 0xb4, 0x7c, 0x14, 0xb0, 0x4e, 0xc9, 0xb1, +0x1f, 0x74, 0x5f, 0x38, 0xf6, 0x51, 0xea, 0x9b, 0xfa, 0x2c, 0xa2, 0x11, 0xd4, 0xa9, 0x2d, 0x27, +0x1a, 0x45, 0xb1, 0xaf, 0xb2, 0x4e, 0x71, 0x0d, 0xc0, 0x58, 0x46, 0xd6, 0x69, 0x06, 0xcb, 0x53, +0xcb, 0xb3, 0xfe, 0x6b, 0x41, 0xcd, 0x41, 0x7e, 0x7d, 0x4c, 0x0f, 0x7c, 0x72, 0x79, 0x7a, 0x59, +0xcd, 0x5e, 0x4a, 0x0e, 0xac, 0x9b, 0xa9, 0x98, 0x73, 0x79, 0x7c, 0xb4, 0xf4, 0xcc, 0xb9, 0xb8, +0x07, 0x0c, 0xb2, 0x74, 0x5c, 0xb8, 0xc7, 0x6f, 0x88, 0xa1, 0x90, 0xa7, 0xf4, 0xaa, 0xf9, 0xbf, +0x67, 0x3a, 0xf4, 0x1a, 0x15, 0x62, 0x1e, 0xb7, 0x9f, 0xbe, 0x3d, 0xb1, 0x29, 0xaf, 0x67, 0xa1, +0x12, 0xf2, 0x58, 0x10, 0x19, 0x53, 0x03, 0x30, 0x1b, 0xb8, 0x1a, 0x89, 0xf6, 0x9c, 0xbd, 0x97, +0x03, 0x8e, 0xa3, 0x09, 0xf3, 0x1d, 0x8b, 0x21, 0xf1, 0xb4, 0xdf, 0xe4, 0x1c, 0xd1, 0x9f, 0x65, +0x02, 0x06, 0xea, 0x5c, 0xd6, 0x13, 0xb3, 0x84, 0xef, 0xa2, 0xa5, 0x5c, 0x8c, 0x77, 0x29, 0xa7, +0x68, 0xc0, 0x6b, 0xae, 0x40, 0xd2, 0xa8, 0xb4, 0xea, 0xcd, 0xf0, 0x8d, 0x4b, 0x38, 0x9c, 0x19, +0x9a, 0x1b, 0x28, 0x54, 0xb8, 0x89, 0x90, 0xef, 0xca, 0x75, 0x81, 0x3e, 0x1e, 0xf2, 0x64, 0x24, +0xc7, 0x18, 0xaf, 0x4e, 0xff, 0x47, 0x9e, 0x07, 0xf6, 0x35, 0x65, 0xa4, 0xd3, 0x0a, 0x56, 0xff, +0xf5, 0x17, 0x64, 0x6c, 0xef, 0xa8, 0x22, 0x25, 0x49, 0x93, 0xb6, 0xdf, 0x00, 0x17, 0xda, 0x58, +0x7e, 0x5d, 0xee, 0xc5, 0x1b, 0xb0, 0xd1, 0xd1, 0x5f, 0x21, 0x10, 0xc7, 0xf9, 0xf3, 0xba, 0x02, +0x0a, 0x27, 0x07, 0xc5, 0xf1, 0xd6, 0xc7, 0xd3, 0xe0, 0xfb, 0x09, 0x60, 0x6c, 0x30, 0x82, 0x03, +0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x06, 0x6c, 0x9f, 0xcf, +0x99, 0xbf, 0x8c, 0x0a, 0x39, 0xe2, 0xf0, 0x78, 0x8a, 0x43, 0xe6, 0x96, 0x36, 0x5b, 0xca, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x39, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, +0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, +0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, +0x35, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, +0x31, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x41, 0x20, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, +0x02, 0x82, 0x01, 0x01, 0x00, 0xb2, 0x78, 0x80, 0x71, 0xca, 0x78, 0xd5, 0xe3, 0x71, 0xaf, 0x47, +0x80, 0x50, 0x74, 0x7d, 0x6e, 0xd8, 0xd7, 0x88, 0x76, 0xf4, 0x99, 0x68, 0xf7, 0x58, 0x21, 0x60, +0xf9, 0x74, 0x84, 0x01, 0x2f, 0xac, 0x02, 0x2d, 0x86, 0xd3, 0xa0, 0x43, 0x7a, 0x4e, 0xb2, 0xa4, +0xd0, 0x36, 0xba, 0x01, 0xbe, 0x8d, 0xdb, 0x48, 0xc8, 0x07, 0x17, 0x36, 0x4c, 0xf4, 0xee, 0x88, +0x23, 0xc7, 0x3e, 0xeb, 0x37, 0xf5, 0xb5, 0x19, 0xf8, 0x49, 0x68, 0xb0, 0xde, 0xd7, 0xb9, 0x76, +0x38, 0x1d, 0x61, 0x9e, 0xa4, 0xfe, 0x82, 0x36, 0xa5, 0xe5, 0x4a, 0x56, 0xe4, 0x45, 0xe1, 0xf9, +0xfd, 0xb4, 0x16, 0xfa, 0x74, 0xda, 0x9c, 0x9b, 0x35, 0x39, 0x2f, 0xfa, 0xb0, 0x20, 0x50, 0x06, +0x6c, 0x7a, 0xd0, 0x80, 0xb2, 0xa6, 0xf9, 0xaf, 0xec, 0x47, 0x19, 0x8f, 0x50, 0x38, 0x07, 0xdc, +0xa2, 0x87, 0x39, 0x58, 0xf8, 0xba, 0xd5, 0xa9, 0xf9, 0x48, 0x67, 0x30, 0x96, 0xee, 0x94, 0x78, +0x5e, 0x6f, 0x89, 0xa3, 0x51, 0xc0, 0x30, 0x86, 0x66, 0xa1, 0x45, 0x66, 0xba, 0x54, 0xeb, 0xa3, +0xc3, 0x91, 0xf9, 0x48, 0xdc, 0xff, 0xd1, 0xe8, 0x30, 0x2d, 0x7d, 0x2d, 0x74, 0x70, 0x35, 0xd7, +0x88, 0x24, 0xf7, 0x9e, 0xc4, 0x59, 0x6e, 0xbb, 0x73, 0x87, 0x17, 0xf2, 0x32, 0x46, 0x28, 0xb8, +0x43, 0xfa, 0xb7, 0x1d, 0xaa, 0xca, 0xb4, 0xf2, 0x9f, 0x24, 0x0e, 0x2d, 0x4b, 0xf7, 0x71, 0x5c, +0x5e, 0x69, 0xff, 0xea, 0x95, 0x02, 0xcb, 0x38, 0x8a, 0xae, 0x50, 0x38, 0x6f, 0xdb, 0xfb, 0x2d, +0x62, 0x1b, 0xc5, 0xc7, 0x1e, 0x54, 0xe1, 0x77, 0xe0, 0x67, 0xc8, 0x0f, 0x9c, 0x87, 0x23, 0xd6, +0x3f, 0x40, 0x20, 0x7f, 0x20, 0x80, 0xc4, 0x80, 0x4c, 0x3e, 0x3b, 0x24, 0x26, 0x8e, 0x04, 0xae, +0x6c, 0x9a, 0xc8, 0xaa, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x84, 0x18, 0xcc, 0x85, 0x34, 0xec, +0xbc, 0x0c, 0x94, 0x94, 0x2e, 0x08, 0x59, 0x9c, 0xc7, 0xb2, 0x10, 0x4e, 0x0a, 0x08, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, +0x01, 0x00, 0x98, 0xf2, 0x37, 0x5a, 0x41, 0x90, 0xa1, 0x1a, 0xc5, 0x76, 0x51, 0x28, 0x20, 0x36, +0x23, 0x0e, 0xae, 0xe6, 0x28, 0xbb, 0xaa, 0xf8, 0x94, 0xae, 0x48, 0xa4, 0x30, 0x7f, 0x1b, 0xfc, +0x24, 0x8d, 0x4b, 0xb4, 0xc8, 0xa1, 0x97, 0xf6, 0xb6, 0xf1, 0x7a, 0x70, 0xc8, 0x53, 0x93, 0xcc, +0x08, 0x28, 0xe3, 0x98, 0x25, 0xcf, 0x23, 0xa4, 0xf9, 0xde, 0x21, 0xd3, 0x7c, 0x85, 0x09, 0xad, +0x4e, 0x9a, 0x75, 0x3a, 0xc2, 0x0b, 0x6a, 0x89, 0x78, 0x76, 0x44, 0x47, 0x18, 0x65, 0x6c, 0x8d, +0x41, 0x8e, 0x3b, 0x7f, 0x9a, 0xcb, 0xf4, 0xb5, 0xa7, 0x50, 0xd7, 0x05, 0x2c, 0x37, 0xe8, 0x03, +0x4b, 0xad, 0xe9, 0x61, 0xa0, 0x02, 0x6e, 0xf5, 0xf2, 0xf0, 0xc5, 0xb2, 0xed, 0x5b, 0xb7, 0xdc, +0xfa, 0x94, 0x5c, 0x77, 0x9e, 0x13, 0xa5, 0x7f, 0x52, 0xad, 0x95, 0xf2, 0xf8, 0x93, 0x3b, 0xde, +0x8b, 0x5c, 0x5b, 0xca, 0x5a, 0x52, 0x5b, 0x60, 0xaf, 0x14, 0xf7, 0x4b, 0xef, 0xa3, 0xfb, 0x9f, +0x40, 0x95, 0x6d, 0x31, 0x54, 0xfc, 0x42, 0xd3, 0xc7, 0x46, 0x1f, 0x23, 0xad, 0xd9, 0x0f, 0x48, +0x70, 0x9a, 0xd9, 0x75, 0x78, 0x71, 0xd1, 0x72, 0x43, 0x34, 0x75, 0x6e, 0x57, 0x59, 0xc2, 0x02, +0x5c, 0x26, 0x60, 0x29, 0xcf, 0x23, 0x19, 0x16, 0x8e, 0x88, 0x43, 0xa5, 0xd4, 0xe4, 0xcb, 0x08, +0xfb, 0x23, 0x11, 0x43, 0xe8, 0x43, 0x29, 0x72, 0x62, 0xa1, 0xa9, 0x5d, 0x5e, 0x08, 0xd4, 0x90, +0xae, 0xb8, 0xd8, 0xce, 0x14, 0xc2, 0xd0, 0x55, 0xf2, 0x86, 0xf6, 0xc4, 0x93, 0x43, 0x77, 0x66, +0x61, 0xc0, 0xb9, 0xe8, 0x41, 0xd7, 0x97, 0x78, 0x60, 0x03, 0x6e, 0x4a, 0x72, 0xae, 0xa5, 0xd1, +0x7d, 0xba, 0x10, 0x9e, 0x86, 0x6c, 0x1b, 0x8a, 0xb9, 0x59, 0x33, 0xf8, 0xeb, 0xc4, 0x90, 0xbe, +0xf1, 0xb9, 0x30, 0x82, 0x01, 0xf2, 0x30, 0x82, 0x01, 0x78, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x13, 0x06, 0x6c, 0x9f, 0xd7, 0xc1, 0xbb, 0x10, 0x4c, 0x29, 0x43, 0xe5, 0x71, 0x7b, 0x7b, 0x2c, +0xc8, 0x1a, 0xc1, 0x0e, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, +0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, +0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, +0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x30, +0x30, 0x35, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x39, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x41, 0x20, 0x34, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, +0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xd2, 0xab, +0x8a, 0x37, 0x4f, 0xa3, 0x53, 0x0d, 0xfe, 0xc1, 0x8a, 0x7b, 0x4b, 0xa8, 0x7b, 0x46, 0x4b, 0x63, +0xb0, 0x62, 0xf6, 0x2d, 0x1b, 0xdb, 0x08, 0x71, 0x21, 0xd2, 0x00, 0xe8, 0x63, 0xbd, 0x9a, 0x27, +0xfb, 0xf0, 0x39, 0x6e, 0x5d, 0xea, 0x3d, 0xa5, 0xc9, 0x81, 0xaa, 0xa3, 0x5b, 0x20, 0x98, 0x45, +0x5d, 0x16, 0xdb, 0xfd, 0xe8, 0x10, 0x6d, 0xe3, 0x9c, 0xe0, 0xe3, 0xbd, 0x5f, 0x84, 0x62, 0xf3, +0x70, 0x64, 0x33, 0xa0, 0xcb, 0x24, 0x2f, 0x70, 0xba, 0x88, 0xa1, 0x2a, 0xa0, 0x75, 0xf8, 0x81, +0xae, 0x62, 0x06, 0xc4, 0x81, 0xdb, 0x39, 0x6e, 0x29, 0xb0, 0x1e, 0xfa, 0x2e, 0x5c, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, +0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd3, 0xec, +0xc7, 0x3a, 0x65, 0x6e, 0xcc, 0xe1, 0xda, 0x76, 0x9a, 0x56, 0xfb, 0x9c, 0xf3, 0x86, 0x6d, 0x57, +0xe5, 0x81, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, +0x00, 0x30, 0x65, 0x02, 0x30, 0x3a, 0x8b, 0x21, 0xf1, 0xbd, 0x7e, 0x11, 0xad, 0xd0, 0xef, 0x58, +0x96, 0x2f, 0xd6, 0xeb, 0x9d, 0x7e, 0x90, 0x8d, 0x2b, 0xcf, 0x66, 0x55, 0xc3, 0x2c, 0xe3, 0x28, +0xa9, 0x70, 0x0a, 0x47, 0x0e, 0xf0, 0x37, 0x59, 0x12, 0xff, 0x2d, 0x99, 0x94, 0x28, 0x4e, 0x2a, +0x4f, 0x35, 0x4d, 0x33, 0x5a, 0x02, 0x31, 0x00, 0xea, 0x75, 0x00, 0x4e, 0x3b, 0xc4, 0x3a, 0x94, +0x12, 0x91, 0xc9, 0x58, 0x46, 0x9d, 0x21, 0x13, 0x72, 0xa7, 0x88, 0x9c, 0x8a, 0xe4, 0x4c, 0x4a, +0xdb, 0x96, 0xd4, 0xac, 0x8b, 0x6b, 0x6b, 0x49, 0x12, 0x53, 0x33, 0xad, 0xd7, 0xe4, 0xbe, 0x24, +0xfc, 0xb5, 0x0a, 0x76, 0xd4, 0xa5, 0xbc, 0x10, 0x30, 0x82, 0x06, 0x0b, 0x30, 0x82, 0x03, 0xf3, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xa6, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, +0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x3b, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, +0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, +0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, +0x65, 0x72, 0x74, 0x2e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, +0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, +0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, +0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, +0x69, 0x6f, 0x6e, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x35, +0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x30, 0x37, 0x31, 0x30, 0x31, 0x31, 0x32, 0x31, +0x5a, 0x17, 0x0d, 0x34, 0x30, 0x30, 0x36, 0x33, 0x30, 0x31, 0x30, 0x31, 0x31, 0x32, 0x31, 0x5a, +0x30, 0x81, 0xa6, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x52, +0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6e, +0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x3b, 0x48, 0x65, 0x6c, 0x6c, +0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, +0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, +0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2e, 0x20, 0x41, 0x75, +0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x37, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, +0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, +0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x35, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, +0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc2, 0xf8, 0xa9, 0x3f, 0x1b, 0x89, +0xfc, 0x3c, 0x3c, 0x04, 0x5d, 0x3d, 0x90, 0x36, 0xb0, 0x91, 0x3a, 0x79, 0x3c, 0x66, 0x5a, 0xef, +0x6d, 0x39, 0x01, 0x49, 0x1a, 0xb4, 0xb7, 0xcf, 0x7f, 0x4d, 0x23, 0x53, 0xb7, 0x90, 0x00, 0xe3, +0x13, 0x2a, 0x28, 0xa6, 0x31, 0xf1, 0x91, 0x00, 0xe3, 0x28, 0xec, 0xae, 0x21, 0x41, 0xce, 0x1f, +0xda, 0xfd, 0x7d, 0x12, 0x5b, 0x01, 0x83, 0x0f, 0xb9, 0xb0, 0x5f, 0x99, 0xe1, 0xf2, 0x12, 0x83, +0x80, 0x4d, 0x06, 0x3e, 0xdf, 0xac, 0xaf, 0xe7, 0xa1, 0x88, 0x6b, 0x31, 0xaf, 0xf0, 0x8b, 0xd0, +0x18, 0x33, 0xb8, 0xdb, 0x45, 0x6a, 0x34, 0xf4, 0x02, 0x80, 0x24, 0x28, 0x0a, 0x02, 0x15, 0x95, +0x5e, 0x76, 0x2a, 0x0d, 0x99, 0x3a, 0x14, 0x5b, 0xf6, 0xcb, 0xcb, 0x53, 0xbc, 0x13, 0x4d, 0x01, +0x88, 0x37, 0x94, 0x25, 0x1b, 0x42, 0xbc, 0x22, 0xd8, 0x8e, 0xa3, 0x96, 0x5e, 0x3a, 0xd9, 0x32, +0xdb, 0x3e, 0xe8, 0xf0, 0x10, 0x65, 0xed, 0x74, 0xe1, 0x2f, 0xa7, 0x7c, 0xaf, 0x27, 0x34, 0xbb, +0x29, 0x7d, 0x9b, 0xb6, 0xcf, 0x09, 0xc8, 0xe5, 0xd3, 0x0a, 0xfc, 0x88, 0x65, 0x65, 0x74, 0x0a, +0xdc, 0x73, 0x1c, 0x5c, 0xcd, 0x40, 0xb1, 0x1c, 0xd4, 0xb6, 0x84, 0x8c, 0x4c, 0x50, 0xcf, 0x68, +0x8e, 0xa8, 0x59, 0xae, 0xc2, 0x27, 0x4e, 0x82, 0xa2, 0x35, 0xdd, 0x14, 0xf4, 0x1f, 0xff, 0xb2, +0x77, 0xd5, 0x87, 0x2f, 0xaa, 0x6e, 0x7d, 0x24, 0x27, 0xe7, 0xc6, 0xcb, 0x26, 0xe6, 0xe5, 0xfe, +0x67, 0x07, 0x63, 0xd8, 0x45, 0x0d, 0xdd, 0x3a, 0x59, 0x65, 0x39, 0x58, 0x7a, 0x92, 0x99, 0x72, +0x3d, 0x9c, 0x84, 0x5e, 0x88, 0x21, 0xb8, 0xd5, 0xf4, 0x2c, 0xfc, 0xd9, 0x70, 0x52, 0x4f, 0x78, +0xb8, 0xbd, 0x3c, 0x2b, 0x8b, 0x95, 0x98, 0xf5, 0xb3, 0xd1, 0x68, 0xcf, 0x20, 0x14, 0x7e, 0x4c, +0x5c, 0x5f, 0xe7, 0x8b, 0xe5, 0xf5, 0x35, 0x81, 0x19, 0x37, 0xd7, 0x11, 0x08, 0xb7, 0x66, 0xbe, +0xd3, 0x4a, 0xce, 0x83, 0x57, 0x00, 0x3a, 0xc3, 0x81, 0xf8, 0x17, 0xcb, 0x92, 0x36, 0x5d, 0xd1, +0xa3, 0xd8, 0x75, 0x1b, 0xe1, 0x8b, 0x27, 0xea, 0x7a, 0x48, 0x41, 0xfd, 0x45, 0x19, 0x06, 0xad, +0x27, 0x99, 0x4e, 0xc1, 0x70, 0x47, 0xdd, 0xb5, 0x9f, 0x81, 0x53, 0x12, 0xe5, 0xb1, 0x8c, 0x48, +0x5d, 0x31, 0x43, 0x17, 0xe3, 0x8c, 0xc6, 0x7a, 0x63, 0x96, 0x4b, 0x29, 0x30, 0x4e, 0x84, 0x4e, +0x62, 0x19, 0x5e, 0x3c, 0xce, 0x97, 0x90, 0xa5, 0x7f, 0x01, 0xeb, 0x9d, 0xe0, 0xf8, 0x8b, 0x89, +0xdd, 0x25, 0x98, 0x3d, 0x92, 0xb6, 0x7e, 0xef, 0xd9, 0xf1, 0x51, 0x51, 0x7d, 0x2d, 0x26, 0xc8, +0x69, 0x59, 0x61, 0xe0, 0xac, 0x6a, 0xb8, 0x2a, 0x36, 0x11, 0x04, 0x7a, 0x50, 0xbd, 0x32, 0x84, +0xbe, 0x2f, 0xdc, 0x72, 0xd5, 0xd7, 0x1d, 0x16, 0x47, 0xe4, 0x47, 0x66, 0x20, 0x3f, 0xf4, 0x96, +0xc5, 0xaf, 0x8e, 0x01, 0x7a, 0xa5, 0x0f, 0x7a, 0x64, 0xf5, 0x0d, 0x18, 0x87, 0xd9, 0xae, 0x88, +0xd5, 0xfa, 0x84, 0xc1, 0x3a, 0xc0, 0x69, 0x28, 0x2d, 0xf2, 0x0d, 0x68, 0x51, 0xaa, 0xe3, 0xa5, +0x77, 0xc6, 0xa4, 0x90, 0x0e, 0xa1, 0x37, 0x8b, 0x31, 0x23, 0x47, 0xc1, 0x09, 0x08, 0xeb, 0x6e, +0xf7, 0x78, 0x9b, 0xd7, 0x82, 0xfc, 0x84, 0x20, 0x99, 0x49, 0x19, 0xb6, 0x12, 0x46, 0xb1, 0xfb, +0x45, 0x55, 0x16, 0xa9, 0xa3, 0x65, 0xac, 0x9c, 0x07, 0x0f, 0xea, 0x6b, 0xdc, 0x1f, 0x2e, 0x06, +0x72, 0xec, 0x86, 0x88, 0x12, 0xe4, 0x2d, 0xdb, 0x5f, 0x05, 0x2f, 0xe4, 0xf0, 0x03, 0xd3, 0x26, +0x33, 0xe7, 0x80, 0xc2, 0xcd, 0x42, 0xa1, 0x17, 0x34, 0x0b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x71, +0x15, 0x67, 0xc8, 0xc8, 0xc9, 0xbd, 0x75, 0x5d, 0x72, 0xd0, 0x38, 0x18, 0x6a, 0x9d, 0xf3, 0x71, +0x24, 0x54, 0x0b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, +0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x75, 0xbb, 0x6d, 0x54, 0x4b, 0xaa, 0x10, 0x58, 0x46, +0x34, 0xf2, 0x62, 0xd7, 0x16, 0x36, 0x5d, 0x08, 0x5e, 0xd5, 0x6c, 0xc8, 0x87, 0xbd, 0xb4, 0x2e, +0x46, 0xf2, 0x31, 0xf8, 0x7c, 0xea, 0x42, 0xb5, 0x93, 0x16, 0x55, 0xdc, 0xa1, 0x0c, 0x12, 0xa0, +0xda, 0x61, 0x7e, 0x0f, 0x58, 0x58, 0x73, 0x64, 0x72, 0xc7, 0xe8, 0x45, 0x8e, 0xdc, 0xa9, 0xf2, +0x26, 0x3f, 0xc6, 0x79, 0x8c, 0xb1, 0x53, 0x08, 0x33, 0x81, 0xb0, 0x56, 0x13, 0xbe, 0xe6, 0x51, +0x5c, 0xd8, 0x9b, 0x0a, 0x4f, 0x4b, 0x9c, 0x56, 0x53, 0x02, 0xe9, 0x4f, 0xf6, 0x0d, 0x60, 0xea, +0x4d, 0x42, 0x55, 0xe8, 0x7c, 0x1b, 0x21, 0x21, 0xd3, 0x1b, 0x3a, 0xcc, 0x77, 0xf2, 0xb8, 0x90, +0xf1, 0x68, 0xc7, 0xf9, 0x5a, 0xfe, 0xfa, 0x2d, 0xf4, 0xbf, 0xc9, 0xf5, 0x45, 0x1b, 0xce, 0x38, +0x10, 0x2a, 0x37, 0x8a, 0x79, 0xa3, 0xb4, 0xe3, 0x09, 0x6c, 0x85, 0x86, 0x93, 0xff, 0x89, 0x96, +0x27, 0x78, 0x81, 0x8f, 0x67, 0xe3, 0x46, 0x74, 0x54, 0x8e, 0xd9, 0x0d, 0x69, 0xe2, 0x4a, 0xf4, +0x4d, 0x74, 0x03, 0xff, 0xb2, 0x77, 0xed, 0x95, 0x67, 0x97, 0xe4, 0xb1, 0xc5, 0xab, 0xbf, 0x6a, +0x23, 0xe8, 0xd4, 0x94, 0xe2, 0x44, 0x28, 0x62, 0xc4, 0x4b, 0xe2, 0xf0, 0xd8, 0xe2, 0x29, 0x6b, +0x1a, 0x70, 0x7e, 0x24, 0x61, 0x93, 0x7b, 0x4f, 0x03, 0x32, 0x25, 0x0d, 0x45, 0x24, 0x2b, 0x96, +0xb4, 0x46, 0x6a, 0xbf, 0x4a, 0x0b, 0xf7, 0x9a, 0x8f, 0xc1, 0xac, 0x1a, 0xc5, 0x67, 0xf3, 0x6f, +0x34, 0xd2, 0xfa, 0x73, 0x63, 0x8c, 0xef, 0x16, 0xb0, 0xa8, 0xa4, 0x46, 0x2a, 0xf8, 0xeb, 0x12, +0xec, 0x72, 0xb4, 0xef, 0xf8, 0x2b, 0x7e, 0x8c, 0x52, 0xc0, 0x8b, 0x84, 0x54, 0xf9, 0x2f, 0x3e, +0xe3, 0x55, 0xa8, 0xdc, 0x66, 0xb1, 0xd9, 0xe1, 0x5f, 0xd8, 0xb3, 0x8c, 0x59, 0x34, 0x59, 0xa4, +0xab, 0x4f, 0x6c, 0xbb, 0x1f, 0x18, 0xdb, 0x75, 0xab, 0xd8, 0xcb, 0x92, 0xcd, 0x94, 0x38, 0x61, +0x0e, 0x07, 0x06, 0x1f, 0x4b, 0x46, 0x10, 0xf1, 0x15, 0xbe, 0x8d, 0x85, 0x5c, 0x3b, 0x4a, 0x2b, +0x81, 0x79, 0x0f, 0xb4, 0x69, 0x9f, 0x49, 0x50, 0x97, 0x4d, 0xf7, 0x0e, 0x56, 0x5d, 0xc0, 0x95, +0x6a, 0xc2, 0x36, 0xc3, 0x1b, 0x68, 0xc9, 0xf5, 0x2a, 0xdc, 0x47, 0x9a, 0xbe, 0xb2, 0xce, 0xc5, +0x25, 0xe8, 0xfa, 0x03, 0xb9, 0xda, 0xf9, 0x16, 0x6e, 0x91, 0x84, 0xf5, 0x1c, 0x28, 0xc8, 0xfc, +0x26, 0xcc, 0xd7, 0x1c, 0x90, 0x56, 0xa7, 0x5f, 0x6f, 0x3a, 0x04, 0xbc, 0xcd, 0x78, 0x89, 0x0b, +0x8e, 0x0f, 0x2f, 0xa3, 0xaa, 0x4f, 0xa2, 0x1b, 0x12, 0x3d, 0x16, 0x08, 0x40, 0x0f, 0xf1, 0x46, +0x4c, 0xd7, 0xaa, 0x7b, 0x08, 0xc1, 0x0a, 0xf5, 0x6d, 0x27, 0xde, 0x02, 0x8f, 0xca, 0xc3, 0xb5, +0x2b, 0xca, 0xe9, 0xeb, 0xc8, 0x21, 0x53, 0x38, 0xa5, 0xcc, 0x3b, 0xd8, 0x77, 0x37, 0x30, 0xa2, +0x4f, 0xd9, 0x6f, 0xd1, 0xf2, 0x40, 0xad, 0x41, 0x7a, 0x17, 0xc5, 0xd6, 0x4a, 0x35, 0x89, 0xb7, +0x41, 0xd5, 0x7c, 0x86, 0x7f, 0x55, 0x4d, 0x83, 0x4a, 0xa5, 0x73, 0x20, 0xc0, 0x3a, 0xaf, 0x90, +0xf1, 0x9a, 0x24, 0x8e, 0xd9, 0x8e, 0x71, 0xca, 0x7b, 0xb8, 0x86, 0xda, 0xb2, 0x8f, 0x99, 0x3e, +0x1d, 0x13, 0x0d, 0x12, 0x11, 0xee, 0xd4, 0xab, 0xf0, 0xe9, 0x15, 0x76, 0x02, 0xe4, 0xe0, 0xdf, +0xaa, 0x20, 0x1e, 0x5b, 0x61, 0x85, 0x64, 0x40, 0xa9, 0x90, 0x97, 0x0d, 0xad, 0x53, 0xd2, 0x5a, +0x1d, 0x87, 0x6a, 0x00, 0x97, 0x65, 0x62, 0xb4, 0xbe, 0x6f, 0x6a, 0xa7, 0xf5, 0x2c, 0x42, 0xed, +0x32, 0xad, 0xb6, 0x21, 0x9e, 0xbe, 0xbc, 0x30, 0x82, 0x02, 0xc3, 0x30, 0x82, 0x02, 0x4a, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x04, 0x03, 0x02, 0x30, 0x81, 0xaa, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x47, 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x41, 0x74, +0x68, 0x65, 0x6e, 0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x3b, 0x48, +0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, +0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, +0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2e, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, +0x55, 0x04, 0x03, 0x13, 0x3b, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, +0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, +0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, +0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x35, +0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x30, 0x37, 0x31, 0x30, 0x33, 0x37, 0x31, 0x32, +0x5a, 0x17, 0x0d, 0x34, 0x30, 0x30, 0x36, 0x33, 0x30, 0x31, 0x30, 0x33, 0x37, 0x31, 0x32, 0x5a, +0x30, 0x81, 0xaa, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x52, +0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6e, +0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x3b, 0x48, 0x65, 0x6c, 0x6c, +0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, +0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, +0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2e, 0x20, 0x41, 0x75, +0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x3b, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, +0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, +0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x45, 0x43, +0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x35, 0x30, 0x76, 0x30, +0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, +0x22, 0x03, 0x62, 0x00, 0x04, 0x92, 0xa0, 0x41, 0xe8, 0x4b, 0x82, 0x84, 0x5c, 0xe2, 0xf8, 0x31, +0x11, 0x99, 0x86, 0x64, 0x4e, 0x09, 0x25, 0x2f, 0x9d, 0x41, 0x2f, 0x0a, 0xae, 0x35, 0x4f, 0x74, +0x95, 0xb2, 0x51, 0x64, 0x6b, 0x8d, 0x6b, 0xe6, 0x3f, 0x70, 0x95, 0xf0, 0x05, 0x44, 0x47, 0xa6, +0x72, 0x38, 0x50, 0x76, 0x95, 0x02, 0x5a, 0x8e, 0xae, 0x28, 0x9e, 0xf9, 0x2d, 0x4e, 0x99, 0xef, +0x2c, 0x48, 0x6f, 0x4c, 0x25, 0x29, 0xe8, 0xd1, 0x71, 0x5b, 0xdf, 0x1d, 0xc1, 0x75, 0x37, 0xb4, +0xd7, 0xfa, 0x7b, 0x7a, 0x42, 0x9c, 0x6a, 0x0a, 0x56, 0x5a, 0x7c, 0x69, 0x0b, 0xaa, 0x80, 0x09, +0x24, 0x6c, 0x7e, 0xc1, 0x46, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, +0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0xb4, 0x22, 0x0b, 0x82, 0x99, 0x24, 0x01, 0x0e, 0x9c, 0xbb, 0xe4, +0x0e, 0xfd, 0xbf, 0xfb, 0x97, 0x20, 0x93, 0x99, 0x2a, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x67, 0x00, 0x30, 0x64, 0x02, 0x30, 0x67, 0xce, 0x16, 0x62, +0x38, 0xa2, 0xac, 0x62, 0x45, 0xa7, 0xa9, 0x95, 0x24, 0xc0, 0x1a, 0x27, 0x9c, 0x32, 0x3b, 0xc0, +0xc0, 0xd5, 0xba, 0xa9, 0xe7, 0xf8, 0x04, 0x43, 0x53, 0x85, 0xee, 0x52, 0x21, 0xde, 0x9d, 0xf5, +0x25, 0x83, 0x3e, 0x9e, 0x58, 0x4b, 0x2f, 0xd7, 0x67, 0x13, 0x0e, 0x21, 0x02, 0x30, 0x05, 0xe1, +0x75, 0x01, 0xde, 0x68, 0xed, 0x2a, 0x1f, 0x4d, 0x4c, 0x09, 0x08, 0x0d, 0xec, 0x4b, 0xad, 0x64, +0x17, 0x28, 0xe7, 0x75, 0xce, 0x45, 0x65, 0x72, 0x21, 0x17, 0xcb, 0x22, 0x41, 0x0e, 0x8c, 0x13, +0x98, 0x38, 0x9a, 0x54, 0x6d, 0x9b, 0xca, 0xe2, 0x7c, 0xea, 0x02, 0x58, 0x22, 0x91, 0x30, 0x82, +0x06, 0x5b, 0x30, 0x82, 0x04, 0x43, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xca, 0xe9, +0x1b, 0x89, 0xf1, 0x55, 0x03, 0x0d, 0xa3, 0xe6, 0x41, 0x6d, 0xc4, 0xe3, 0xa6, 0xe1, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x5a, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x44, 0x68, 0x69, 0x6d, 0x79, 0x6f, 0x74, 0x69, 0x73, +0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x13, 0x30, 0x30, 0x30, 0x32, 0x20, +0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31, 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, +0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, +0x61, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x31, +0x30, 0x30, 0x31, 0x30, 0x38, 0x33, 0x32, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x33, 0x33, 0x31, 0x30, +0x30, 0x31, 0x30, 0x38, 0x33, 0x32, 0x32, 0x37, 0x5a, 0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x0c, 0x09, 0x44, 0x68, 0x69, 0x6d, 0x79, 0x6f, 0x74, 0x69, 0x73, 0x31, 0x1c, 0x30, 0x1a, +0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x13, 0x30, 0x30, 0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, +0x36, 0x33, 0x30, 0x38, 0x31, 0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, +0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xcd, 0x18, 0x39, 0x65, 0x1a, 0x59, 0xb1, 0xea, 0x64, 0x16, +0x0e, 0x8c, 0x94, 0x24, 0x95, 0x7c, 0x83, 0xd3, 0xc5, 0x39, 0x26, 0xdc, 0x0c, 0xef, 0x16, 0x57, +0x8d, 0xd7, 0xd8, 0xac, 0xa3, 0x42, 0x7f, 0x82, 0xca, 0xed, 0xcd, 0x5b, 0xdb, 0x0e, 0xb7, 0x2d, +0xed, 0x45, 0x08, 0x17, 0xb2, 0xd9, 0xb3, 0xcb, 0xd6, 0x17, 0x52, 0x72, 0x28, 0xdb, 0x8e, 0x4e, +0x9e, 0x8a, 0xb6, 0x0b, 0xf9, 0x9e, 0x84, 0x9a, 0x4d, 0x76, 0xde, 0x22, 0x29, 0x5c, 0xd2, 0xb3, +0xd2, 0x06, 0x3e, 0x30, 0x39, 0xa9, 0x74, 0xa3, 0x92, 0x56, 0x1c, 0xa1, 0x6f, 0x4c, 0x0a, 0x20, +0x6d, 0x9f, 0x23, 0x7a, 0xb4, 0xc6, 0xda, 0x2c, 0xe4, 0x1d, 0x2c, 0xdc, 0xb3, 0x28, 0xd0, 0x13, +0xf2, 0x4c, 0x4e, 0x02, 0x49, 0xa1, 0x54, 0x40, 0x9e, 0xe6, 0xe5, 0x05, 0xa0, 0x2d, 0x84, 0xc8, +0xff, 0x98, 0x6c, 0xd0, 0xeb, 0x8a, 0x1a, 0x84, 0x08, 0x1e, 0xb7, 0x68, 0x23, 0xee, 0x23, 0xd5, +0x70, 0xce, 0x6d, 0x51, 0x69, 0x10, 0xee, 0xa1, 0x7a, 0xc2, 0xd1, 0x22, 0x31, 0xc2, 0x82, 0x85, +0xd2, 0xf2, 0x55, 0x76, 0x50, 0x7c, 0x25, 0x7a, 0xc9, 0x84, 0x5c, 0x0b, 0xac, 0xdd, 0x42, 0x4e, +0x2b, 0xe7, 0x82, 0xa2, 0x24, 0x89, 0xcb, 0x90, 0xb2, 0xd0, 0xee, 0x23, 0xba, 0x66, 0x4c, 0xbb, +0x62, 0xa4, 0xf9, 0x53, 0x5a, 0x64, 0x7b, 0x7c, 0x98, 0xfa, 0xa3, 0x48, 0x9e, 0x0f, 0x95, 0xae, +0xa7, 0x18, 0xf4, 0x6a, 0xec, 0x2e, 0x03, 0x45, 0xaf, 0xf0, 0x74, 0xf8, 0x2a, 0xcd, 0x7a, 0x5d, +0xd1, 0xbe, 0x44, 0x26, 0x32, 0x29, 0xf1, 0xf1, 0xf5, 0x6c, 0xcc, 0x7e, 0x02, 0x21, 0x0b, 0x9f, +0x6f, 0xa4, 0x3f, 0xbe, 0x9d, 0x53, 0xe2, 0xcf, 0x7d, 0xa9, 0x2c, 0x7c, 0x58, 0x1a, 0x97, 0xe1, +0x3d, 0x37, 0x37, 0x18, 0x66, 0x28, 0xd2, 0x40, 0xc5, 0x51, 0x8a, 0x8c, 0xc3, 0x2d, 0xce, 0x53, +0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xc5, 0xaa, 0xe0, 0xd6, 0x0a, 0xa6, 0x40, 0xdf, 0x78, 0xf6, +0xf5, 0x04, 0x7c, 0x69, 0x13, 0x84, 0xbc, 0xd1, 0xd1, 0xa7, 0x06, 0xcf, 0x01, 0xf7, 0x68, 0xc0, +0xa8, 0x57, 0xbb, 0x3a, 0x61, 0xad, 0x04, 0x8c, 0x93, 0xe3, 0xad, 0xfc, 0xf0, 0xdb, 0x44, 0x6d, +0x59, 0xdc, 0x49, 0x59, 0xae, 0xac, 0x9a, 0x99, 0x36, 0x30, 0x41, 0x7b, 0x76, 0x33, 0x22, 0x87, +0xa3, 0xc2, 0x92, 0x86, 0x6e, 0xf9, 0x70, 0xee, 0xae, 0x87, 0x87, 0x95, 0x1b, 0xc4, 0x7a, 0xbd, +0x31, 0xf3, 0xd4, 0xd2, 0xe5, 0x99, 0xff, 0xbe, 0x48, 0xec, 0x75, 0xf5, 0x78, 0x16, 0x1d, 0xa6, +0x70, 0xc1, 0x7f, 0x3c, 0x1b, 0xa1, 0x92, 0xfb, 0xcf, 0xc8, 0x3c, 0xd6, 0xc5, 0x93, 0x0a, 0x8f, +0xf5, 0x55, 0x3a, 0x76, 0x95, 0xce, 0x59, 0x98, 0x8a, 0x09, 0x95, 0x77, 0x32, 0x9a, 0x83, 0xba, +0x2c, 0x04, 0x3a, 0x97, 0xbd, 0xd4, 0x2f, 0xbe, 0xd7, 0x6c, 0x9b, 0xa2, 0xca, 0x7d, 0x6d, 0x26, +0xc9, 0x55, 0xd5, 0xcf, 0xc3, 0x79, 0x52, 0x08, 0x09, 0x99, 0x07, 0x24, 0x2d, 0x64, 0x25, 0x6b, +0xa6, 0x21, 0x69, 0x9b, 0x6a, 0xdd, 0x74, 0x4d, 0x6b, 0x97, 0x7a, 0x41, 0xbd, 0xab, 0x17, 0xf9, +0x90, 0x17, 0x48, 0x8f, 0x36, 0xf9, 0x2d, 0xd5, 0xc5, 0xdb, 0xee, 0xaa, 0x85, 0x45, 0x41, 0xfa, +0xcd, 0x3a, 0x45, 0xb1, 0x68, 0xe6, 0x36, 0x4c, 0x9b, 0x90, 0x57, 0xec, 0x23, 0xb9, 0x87, 0x08, +0xc2, 0xc4, 0x09, 0xf1, 0x97, 0x86, 0x2a, 0x28, 0x4d, 0xe2, 0x74, 0xc0, 0xda, 0xc4, 0x8c, 0xdb, +0xdf, 0xe2, 0xa1, 0x17, 0x59, 0xce, 0x24, 0x59, 0x74, 0x31, 0xda, 0x7f, 0xfd, 0x30, 0x6d, 0xd9, +0xdc, 0xe1, 0x6a, 0xe1, 0xfc, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x1a, 0x30, +0x82, 0x01, 0x16, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x18, +0x87, 0x56, 0xe0, 0x6e, 0x77, 0xee, 0x24, 0x35, 0x3c, 0x4e, 0x73, 0x9a, 0x1f, 0xd6, 0xe1, 0xe2, +0x79, 0x7e, 0x2b, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, +0x18, 0x87, 0x56, 0xe0, 0x6e, 0x77, 0xee, 0x24, 0x35, 0x3c, 0x4e, 0x73, 0x9a, 0x1f, 0xd6, 0xe1, +0xe2, 0x79, 0x7e, 0x2b, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, 0x30, 0x3b, 0x30, +0x39, 0x06, 0x04, 0x55, 0x1d, 0x20, 0x00, 0x30, 0x31, 0x30, 0x2f, 0x06, 0x08, 0x2b, 0x06, 0x01, +0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x23, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, +0x77, 0x77, 0x77, 0x2e, 0x63, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, 0x2e, 0x66, 0x72, 0x2f, +0x61, 0x75, 0x74, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x2f, 0x30, 0x6d, 0x06, 0x03, 0x55, 0x1d, +0x1f, 0x04, 0x66, 0x30, 0x64, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b, 0x86, 0x29, 0x68, 0x74, 0x74, +0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, +0x2e, 0x66, 0x72, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, 0x72, 0x6f, 0x6f, 0x74, +0x63, 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x31, 0xa0, 0x2f, 0xa0, 0x2d, 0x86, 0x2b, 0x68, 0x74, +0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x64, 0x68, 0x69, 0x6d, 0x79, 0x6f, 0x74, +0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, 0x72, +0x6f, 0x6f, 0x74, 0x63, 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x94, 0xb8, 0x9e, +0x4f, 0xf0, 0xe3, 0x95, 0x08, 0x22, 0xe7, 0xcd, 0x68, 0x41, 0xf7, 0x1c, 0x55, 0xd5, 0x7c, 0x00, +0xe2, 0x2d, 0x3a, 0x89, 0x5d, 0x68, 0x38, 0x2f, 0x51, 0x22, 0x0b, 0x4a, 0x8d, 0xcb, 0xe9, 0xbb, +0x5d, 0x3e, 0xbb, 0x5c, 0x3d, 0xb1, 0x28, 0xfe, 0xe4, 0x53, 0x55, 0x13, 0xcf, 0xa1, 0x90, 0x1b, +0x02, 0x1d, 0x5f, 0x66, 0x46, 0x09, 0x33, 0x28, 0xe1, 0x0d, 0x24, 0x97, 0x70, 0xd3, 0x10, 0x1f, +0xea, 0x64, 0x57, 0x96, 0xbb, 0x5d, 0xda, 0xe7, 0xc4, 0x8c, 0x4f, 0x4c, 0x64, 0x46, 0x1d, 0x5c, +0x87, 0xe3, 0x59, 0xde, 0x42, 0xd1, 0x9b, 0xa8, 0x7e, 0xa6, 0x89, 0xdd, 0x8f, 0x1c, 0xc9, 0x30, +0x82, 0xed, 0x3b, 0x9c, 0xcd, 0xc0, 0xe9, 0x19, 0xe0, 0x6a, 0xd8, 0x02, 0x75, 0x37, 0xab, 0xf7, +0x34, 0x28, 0x28, 0x91, 0xf2, 0x04, 0x0a, 0x4f, 0x35, 0xe3, 0x60, 0x26, 0x01, 0xfa, 0xd0, 0x11, +0x8c, 0xf9, 0x11, 0x6a, 0xee, 0xaf, 0x3d, 0xc3, 0x50, 0xd3, 0x8f, 0x5f, 0x33, 0x79, 0x3c, 0x86, +0xa8, 0x73, 0x45, 0x90, 0x8c, 0x20, 0xb6, 0x72, 0x73, 0x17, 0x23, 0xbe, 0x07, 0x65, 0xe5, 0x78, +0x92, 0x0d, 0xba, 0x01, 0xc0, 0xeb, 0x8c, 0x1c, 0x66, 0xbf, 0xac, 0x86, 0x77, 0x01, 0x94, 0x0d, +0x9c, 0xe6, 0xe9, 0x39, 0x8d, 0x1f, 0xa6, 0x51, 0x8c, 0x99, 0x0c, 0x39, 0x77, 0xe1, 0xb4, 0x9b, +0xfa, 0x1c, 0x67, 0x57, 0x6f, 0x6a, 0x6a, 0x8e, 0xa9, 0x2b, 0x4c, 0x57, 0x79, 0x7a, 0x57, 0x22, +0xcf, 0xcd, 0x5f, 0x63, 0x46, 0x8d, 0x5c, 0x59, 0x3a, 0x86, 0xf8, 0x32, 0x47, 0x62, 0xa3, 0x67, +0x0d, 0x18, 0x91, 0xdc, 0xfb, 0xa6, 0x6b, 0xf5, 0x48, 0x61, 0x73, 0x23, 0x59, 0x8e, 0x02, 0xa7, +0xbc, 0x44, 0xea, 0xf4, 0x49, 0x9d, 0xf1, 0x54, 0x58, 0xf9, 0x60, 0xaf, 0xda, 0x18, 0xa4, 0x2f, +0x28, 0x45, 0xdc, 0x7a, 0xa0, 0x88, 0x86, 0x5d, 0xf3, 0x3b, 0xe7, 0xff, 0x29, 0x35, 0x80, 0xfc, +0x64, 0x43, 0x94, 0xe6, 0xe3, 0x1c, 0x6f, 0xbe, 0xad, 0x0e, 0x2a, 0x63, 0x99, 0x2b, 0xc9, 0x7e, +0x85, 0xf6, 0x71, 0xe8, 0x06, 0x03, 0x95, 0xfe, 0xde, 0x8f, 0x48, 0x1c, 0x5a, 0xd4, 0x92, 0xe8, +0x2b, 0xee, 0xe7, 0x31, 0xdb, 0xba, 0x04, 0x6a, 0x87, 0x98, 0xe7, 0xc5, 0x5f, 0xef, 0x7d, 0xa7, +0x22, 0xf7, 0x01, 0xd8, 0x4d, 0xf9, 0x89, 0xd0, 0x0e, 0x9a, 0x05, 0x59, 0xa4, 0x9e, 0x98, 0xd9, +0x6f, 0x2b, 0xca, 0x70, 0xbe, 0x64, 0xc2, 0x55, 0xa3, 0xf4, 0xe9, 0xaf, 0xc3, 0x92, 0x29, 0xdc, +0x88, 0x16, 0x24, 0x99, 0x3c, 0x8d, 0x26, 0x98, 0xb6, 0x5b, 0xb7, 0xcc, 0xce, 0xb7, 0x37, 0x07, +0xfd, 0x26, 0xd9, 0x98, 0x85, 0x24, 0xff, 0x59, 0x23, 0x03, 0x9a, 0xed, 0x9d, 0x9d, 0xa8, 0xe4, +0x5e, 0x38, 0xce, 0xd7, 0x52, 0x0d, 0x6f, 0xd2, 0x3f, 0x6d, 0xb1, 0x05, 0x6b, 0x49, 0xce, 0x8a, +0x91, 0x46, 0x73, 0xf4, 0xf6, 0x2f, 0xf0, 0xa8, 0x73, 0x77, 0x0e, 0x65, 0xac, 0xa1, 0x8d, 0x66, +0x52, 0x69, 0x7e, 0x4b, 0x68, 0x0c, 0xc7, 0x1e, 0x37, 0x27, 0x83, 0xa5, 0x8c, 0xc7, 0x02, 0xe4, +0x14, 0xcd, 0x49, 0x01, 0xb0, 0x73, 0xb3, 0xfd, 0xc6, 0x90, 0x3a, 0x6f, 0xd2, 0x6c, 0xed, 0x3b, +0xee, 0xec, 0x91, 0xbe, 0xa2, 0x43, 0x5d, 0x8b, 0x00, 0x4a, 0x66, 0x25, 0x44, 0x70, 0xde, 0x40, +0x0f, 0xf8, 0x7c, 0x15, 0xf7, 0xa2, 0xce, 0x3c, 0xd7, 0x5e, 0x13, 0x8c, 0x81, 0x17, 0x18, 0x17, +0xd1, 0xbd, 0xf1, 0x77, 0x10, 0x3a, 0xd4, 0x65, 0x39, 0xc1, 0x27, 0xac, 0x57, 0x2c, 0x25, 0x54, +0xff, 0xa2, 0xda, 0x4f, 0x8a, 0x61, 0x39, 0x5e, 0xae, 0x3d, 0x4a, 0x8c, 0xbd, 0x30, 0x82, 0x04, +0x20, 0x30, 0x82, 0x03, 0x08, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x84, 0x82, 0x2c, +0x5f, 0x1c, 0x62, 0xd0, 0x40, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x9c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x50, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x06, 0x50, +0x61, 0x6e, 0x61, 0x6d, 0x61, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, +0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x53, +0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, 0x20, 0x64, 0x65, 0x20, 0x52, 0x2e, 0x4c, +0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1e, 0x54, 0x72, 0x75, 0x73, +0x74, 0x43, 0x6f, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x0e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x45, 0x43, +0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x32, 0x30, 0x34, 0x31, 0x32, 0x33, +0x32, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x37, 0x32, 0x38, +0x30, 0x37, 0x5a, 0x30, 0x81, 0x9c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x50, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x06, 0x50, 0x61, +0x6e, 0x61, 0x6d, 0x61, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, 0x50, +0x61, 0x6e, 0x61, 0x6d, 0x61, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x0c, 0x1b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x53, 0x79, +0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, 0x20, 0x64, 0x65, 0x20, 0x52, 0x2e, 0x4c, 0x2e, +0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1e, 0x54, 0x72, 0x75, 0x73, 0x74, +0x43, 0x6f, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, +0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x0e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x45, 0x43, 0x41, +0x2d, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, +0x01, 0x01, 0x00, 0xcf, 0x8f, 0xe0, 0x11, 0xb5, 0x9f, 0xa8, 0x76, 0x76, 0xdb, 0xdf, 0x0f, 0x54, +0xef, 0x73, 0x63, 0x29, 0x82, 0xad, 0x47, 0xc6, 0xa3, 0x6b, 0xed, 0xfe, 0x5f, 0x33, 0xf8, 0x43, +0x51, 0xe9, 0x1a, 0x33, 0x91, 0x31, 0x17, 0xa0, 0x74, 0xc4, 0xd4, 0xa7, 0x01, 0xe6, 0xb2, 0x92, +0x3e, 0x6a, 0x9d, 0xed, 0x0e, 0xf9, 0x74, 0x98, 0x40, 0xd3, 0x3f, 0x03, 0x80, 0x06, 0x82, 0x40, +0xe8, 0xb1, 0xe2, 0xa7, 0x51, 0xa7, 0x1d, 0x83, 0x26, 0x6b, 0xab, 0xde, 0xfa, 0x17, 0x91, 0x2b, +0xd8, 0xc6, 0xac, 0x1e, 0xb1, 0x9e, 0x19, 0x01, 0xd5, 0x97, 0xa6, 0xea, 0x0d, 0xb7, 0xc4, 0x55, +0x1f, 0x27, 0x7c, 0xd2, 0x08, 0xd5, 0x76, 0x1f, 0x29, 0x15, 0x87, 0x40, 0x39, 0xdd, 0x38, 0x45, +0x11, 0x75, 0xd0, 0x9a, 0xa7, 0x34, 0xe0, 0xbf, 0xcd, 0xc8, 0x52, 0x1d, 0xb9, 0x47, 0x7e, 0x0d, +0xb8, 0xbb, 0xc6, 0x0c, 0xf6, 0x73, 0x57, 0x16, 0x5a, 0x7e, 0x43, 0x91, 0x1f, 0x55, 0x3a, 0xc6, +0x6d, 0x44, 0x04, 0xaa, 0x9c, 0xa9, 0x9c, 0xa7, 0x4c, 0x89, 0x17, 0x83, 0xae, 0xa3, 0x04, 0x5e, +0x52, 0x80, 0x8b, 0x1e, 0x12, 0x25, 0x11, 0x19, 0xd7, 0x0c, 0x7d, 0x7d, 0x31, 0x44, 0x41, 0xea, +0xdb, 0xaf, 0xb0, 0x1c, 0xef, 0x81, 0xd0, 0x2c, 0xc5, 0x9a, 0x21, 0x9b, 0x3d, 0xed, 0x42, 0x3b, +0x50, 0x26, 0xf2, 0xec, 0xce, 0x71, 0x61, 0x06, 0x62, 0x21, 0x54, 0x4e, 0x7f, 0xc1, 0x9d, 0x3e, +0x7f, 0x20, 0x8c, 0x80, 0xcb, 0x2a, 0xd8, 0x97, 0x62, 0xc8, 0x83, 0x33, 0x91, 0x7d, 0xb0, 0xa2, +0x5a, 0x0f, 0x57, 0xe8, 0x3b, 0xcc, 0xf2, 0x25, 0xb2, 0xd4, 0x7c, 0x2f, 0xec, 0x4d, 0xc6, 0xa1, +0x3a, 0x15, 0x7a, 0xe7, 0xb6, 0x5d, 0x35, 0xf5, 0xf6, 0x48, 0x4a, 0x36, 0x45, 0x66, 0xd4, 0xba, +0x98, 0x58, 0xc1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x44, 0x9e, 0x48, 0xf5, 0xcc, 0x6d, 0x48, 0xd4, 0xa0, +0x4b, 0x7f, 0xfe, 0x59, 0x24, 0x2f, 0x83, 0x97, 0x99, 0x9a, 0x86, 0x30, 0x1f, 0x06, 0x03, 0x55, +0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0x9e, 0x48, 0xf5, 0xcc, 0x6d, 0x48, 0xd4, +0xa0, 0x4b, 0x7f, 0xfe, 0x59, 0x24, 0x2f, 0x83, 0x97, 0x99, 0x9a, 0x86, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, +0x00, 0x05, 0x3e, 0x35, 0x5c, 0x15, 0x70, 0x9b, 0xc9, 0xc7, 0x73, 0x61, 0x6f, 0x72, 0x2b, 0xd4, +0xc2, 0x8f, 0xf2, 0x43, 0x5d, 0x02, 0xce, 0xc4, 0x94, 0xb9, 0x94, 0x11, 0x83, 0x67, 0x5d, 0xe2, +0x67, 0x6c, 0x75, 0x76, 0xbf, 0xbb, 0x0c, 0xaa, 0x36, 0xc6, 0xad, 0x47, 0x93, 0x63, 0xdc, 0x1e, +0x7e, 0xd6, 0xde, 0x2e, 0xfe, 0xe9, 0x19, 0x32, 0x38, 0x03, 0x7f, 0x14, 0xf6, 0x00, 0x73, 0x2c, +0x59, 0xb1, 0x21, 0x06, 0xe1, 0xfb, 0xac, 0x18, 0x95, 0x0c, 0xa3, 0xff, 0x99, 0x96, 0xf7, 0x2b, +0x27, 0x9b, 0xd5, 0x24, 0xcc, 0x1d, 0xdd, 0xc1, 0x3a, 0xe0, 0x98, 0x44, 0xb0, 0xc4, 0xe4, 0x3e, +0x77, 0xb1, 0x73, 0xa9, 0x64, 0x2c, 0xf6, 0x1c, 0x01, 0x7c, 0x3f, 0x5d, 0x45, 0x85, 0xc0, 0x85, +0xe7, 0x25, 0x8f, 0x95, 0xdc, 0x17, 0xf3, 0x3c, 0x9f, 0x1a, 0x6e, 0xb0, 0xca, 0xe3, 0x1d, 0x2a, +0xe9, 0x4c, 0x63, 0xfa, 0x24, 0x61, 0x62, 0xd6, 0xda, 0x7e, 0xb6, 0x1c, 0x6c, 0xf5, 0x02, 0x1d, +0xd4, 0x2a, 0xdd, 0x55, 0x90, 0xeb, 0x2a, 0x11, 0x47, 0x3c, 0x2e, 0x5e, 0x74, 0xb2, 0x82, 0x22, +0xa5, 0x7d, 0x53, 0x1f, 0x45, 0xec, 0x27, 0x91, 0x7d, 0xe7, 0x22, 0x16, 0xe8, 0xc0, 0x68, 0x36, +0xd8, 0xc6, 0xf1, 0x4f, 0x80, 0x44, 0x32, 0xf9, 0xe1, 0xd1, 0xd1, 0x1d, 0xaa, 0xde, 0xa8, 0xab, +0x9c, 0x04, 0xaf, 0xad, 0x20, 0x0e, 0x64, 0x98, 0x4d, 0xa5, 0x6b, 0xc0, 0x48, 0x58, 0x96, 0x69, +0x4d, 0xdc, 0x07, 0x8c, 0x51, 0x93, 0xa2, 0xdf, 0x9f, 0x0f, 0x3d, 0x8b, 0x60, 0xb4, 0x82, 0x8d, +0xaa, 0x08, 0x4e, 0x62, 0x45, 0xe0, 0xf9, 0x0b, 0xd2, 0xe0, 0xe0, 0x3c, 0x5b, 0xde, 0x5c, 0x71, +0x27, 0x25, 0xc2, 0xe6, 0x03, 0x81, 0x8b, 0x10, 0x53, 0xe3, 0xc7, 0x55, 0xa2, 0xb4, 0x9f, 0xd7, +0xe6, 0x30, 0x82, 0x06, 0x2f, 0x30, 0x82, 0x04, 0x17, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, +0x25, 0xa1, 0xdf, 0xca, 0x33, 0xcb, 0x59, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xa4, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x08, +0x0c, 0x06, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, +0x07, 0x0c, 0x0b, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x24, +0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, +0x72, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, 0x20, 0x64, 0x65, 0x20, +0x52, 0x2e, 0x4c, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1e, 0x54, +0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, +0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x20, 0x43, 0x41, 0x2d, 0x32, 0x30, 0x1e, +0x17, 0x0d, 0x31, 0x36, 0x30, 0x32, 0x30, 0x34, 0x31, 0x32, 0x33, 0x32, 0x32, 0x33, 0x5a, 0x17, +0x0d, 0x33, 0x34, 0x31, 0x32, 0x33, 0x31, 0x31, 0x37, 0x32, 0x36, 0x33, 0x39, 0x5a, 0x30, 0x81, +0xa4, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x41, 0x31, 0x0f, +0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x06, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x31, +0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, +0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1b, +0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, +0x20, 0x53, 0x2e, 0x20, 0x64, 0x65, 0x20, 0x52, 0x2e, 0x4c, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, +0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x43, +0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x54, +0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, +0x20, 0x43, 0x41, 0x2d, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, +0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa7, 0x20, 0x6e, 0xc2, 0x2a, 0xa2, 0x62, 0x24, 0x95, 0x90, +0x76, 0xc8, 0x38, 0x7e, 0x80, 0xd2, 0xab, 0xc1, 0x9b, 0x65, 0x05, 0x94, 0xf4, 0xc1, 0x0a, 0x10, +0xd5, 0x02, 0xac, 0xed, 0x9f, 0x93, 0xc7, 0x87, 0xc8, 0xb0, 0x27, 0x2b, 0x42, 0x0c, 0x3d, 0x0a, +0x3e, 0x41, 0x5a, 0x9e, 0x75, 0xdd, 0x8d, 0xca, 0xe0, 0x9b, 0xec, 0x68, 0x32, 0xa4, 0x69, 0x92, +0x68, 0x8c, 0x0b, 0x81, 0x0e, 0x56, 0xa0, 0x3e, 0x1a, 0xdd, 0x2c, 0x25, 0x14, 0x82, 0x2f, 0x97, +0xd3, 0x64, 0x46, 0xf4, 0x54, 0xa9, 0xdc, 0x3a, 0x54, 0x2d, 0x31, 0x2b, 0x99, 0x82, 0xf2, 0xd9, +0x2a, 0xd7, 0xef, 0x71, 0x00, 0xb8, 0x31, 0xa4, 0xbe, 0x7a, 0x24, 0x07, 0xc3, 0x42, 0x20, 0xf2, +0x8a, 0xd4, 0x92, 0x04, 0x1b, 0x65, 0x56, 0x4c, 0x6c, 0xd4, 0xfb, 0xb6, 0x61, 0x5a, 0x47, 0x23, +0xb4, 0xd8, 0x69, 0xb4, 0xb7, 0x3a, 0xd0, 0x74, 0x3c, 0x0c, 0x75, 0xa1, 0x8c, 0x4e, 0x76, 0xa1, +0xe9, 0xdb, 0x2a, 0xa5, 0x3b, 0xfa, 0xce, 0xb0, 0xff, 0x7e, 0x6a, 0x28, 0xfd, 0x27, 0x1c, 0xc8, +0xb1, 0xe9, 0x29, 0xf1, 0x57, 0x6e, 0x64, 0xb4, 0xd0, 0xc1, 0x15, 0x6d, 0x0e, 0xbe, 0x2e, 0x0e, +0x46, 0xc8, 0x5e, 0xf4, 0x51, 0xfe, 0xef, 0x0e, 0x63, 0x3a, 0x3b, 0x71, 0xba, 0xcf, 0x6f, 0x59, +0xca, 0x0c, 0xe3, 0x9b, 0x5d, 0x49, 0xb8, 0x4c, 0xe2, 0x57, 0xb1, 0x98, 0x8a, 0x42, 0x57, 0x9c, +0x76, 0xef, 0xef, 0xbd, 0xd1, 0x68, 0xa8, 0xd2, 0xf4, 0x09, 0xbb, 0x77, 0x35, 0xbe, 0x25, 0x82, +0x08, 0xc4, 0x16, 0x2c, 0x44, 0x20, 0x56, 0xa9, 0x44, 0x11, 0x77, 0xef, 0x5d, 0xb4, 0x1d, 0xaa, +0x5e, 0x6b, 0x3e, 0x8b, 0x32, 0xf6, 0x07, 0x2f, 0x57, 0x04, 0x92, 0xca, 0xf5, 0xfe, 0x9d, 0xc2, +0xe9, 0xe8, 0xb3, 0x8e, 0x4c, 0x4b, 0x02, 0x31, 0xd9, 0xe4, 0x3c, 0x48, 0x82, 0x27, 0xf7, 0x18, +0x82, 0x76, 0x48, 0x3a, 0x71, 0xb1, 0x13, 0xa1, 0x39, 0xd5, 0x2e, 0xc5, 0x34, 0xc2, 0x1d, 0x62, +0x85, 0xdf, 0x03, 0xfe, 0x4d, 0xf4, 0xaf, 0x3d, 0xdf, 0x5c, 0x5b, 0x8d, 0xfa, 0x70, 0xe1, 0xa5, +0x7e, 0x27, 0xc7, 0x86, 0x2e, 0x6a, 0x8f, 0x12, 0xc6, 0x84, 0x5e, 0x43, 0x51, 0x50, 0x9c, 0x19, +0x9b, 0x78, 0xe6, 0xfc, 0xf6, 0xed, 0x47, 0x7e, 0x7b, 0x3d, 0x66, 0xef, 0x13, 0x13, 0x88, 0x5f, +0x3c, 0xa1, 0x63, 0xfb, 0xf9, 0xac, 0x87, 0x35, 0x9f, 0xf3, 0x82, 0x9e, 0xa4, 0x3f, 0x0a, 0x9c, +0x31, 0x69, 0x8b, 0x99, 0xa4, 0x88, 0x4a, 0x8e, 0x6e, 0x66, 0x4d, 0xef, 0x16, 0xc4, 0x0f, 0x79, +0x28, 0x21, 0x60, 0x0d, 0x85, 0x16, 0x7d, 0xd7, 0x54, 0x38, 0xf1, 0x92, 0x56, 0xfd, 0xb5, 0x33, +0x4c, 0x83, 0xdc, 0xd7, 0x10, 0x9f, 0x4b, 0xfd, 0xc6, 0xf8, 0x42, 0xbd, 0xba, 0x7c, 0x73, 0x02, +0xe0, 0xff, 0x7d, 0xcd, 0x5b, 0xe1, 0xd4, 0xac, 0x61, 0x7b, 0x57, 0xd5, 0x4a, 0x7b, 0x5b, 0xd4, +0x85, 0x58, 0x27, 0x5d, 0xbf, 0xf8, 0x2b, 0x60, 0xac, 0xa0, 0x26, 0xae, 0x14, 0x21, 0x27, 0xc6, +0x77, 0x9a, 0x33, 0x80, 0x3c, 0x5e, 0x46, 0x3f, 0xf7, 0xc3, 0xb1, 0xa3, 0x86, 0x33, 0xc6, 0xe8, +0x5e, 0x0d, 0xb9, 0x35, 0x2c, 0xaa, 0x46, 0xc1, 0x85, 0x02, 0x75, 0x80, 0xa0, 0xeb, 0x24, 0xfb, +0x15, 0xaa, 0xe4, 0x67, 0x7f, 0x6e, 0x77, 0x3f, 0xf4, 0x04, 0x8a, 0x2f, 0x7c, 0x7b, 0xe3, 0x17, +0x61, 0xf0, 0xdd, 0x09, 0xa9, 0x20, 0xc8, 0xbe, 0x09, 0xa4, 0xd0, 0x7e, 0x44, 0xc3, 0xb2, 0x30, +0x4a, 0x38, 0xaa, 0xa9, 0xec, 0x18, 0x9a, 0x07, 0x82, 0x2b, 0xdb, 0xb8, 0x9c, 0x18, 0xad, 0xda, +0xe0, 0x46, 0x17, 0xac, 0xcf, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd9, 0xfe, 0x21, 0x40, 0x6e, 0x94, +0x9e, 0xbc, 0x9b, 0x3d, 0x9c, 0x7d, 0x98, 0x20, 0x19, 0xe5, 0x8c, 0x30, 0x62, 0xb2, 0x30, 0x1f, +0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd9, 0xfe, 0x21, 0x40, 0x6e, +0x94, 0x9e, 0xbc, 0x9b, 0x3d, 0x9c, 0x7d, 0x98, 0x20, 0x19, 0xe5, 0x8c, 0x30, 0x62, 0xb2, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, +0x82, 0x02, 0x01, 0x00, 0x9e, 0x45, 0x9e, 0x0c, 0x3b, 0xb6, 0xef, 0xe1, 0x3a, 0xc8, 0x7c, 0xd1, +0x00, 0x3d, 0xcf, 0xe2, 0xea, 0x06, 0xb5, 0xb2, 0x3a, 0xbb, 0x06, 0x4b, 0x68, 0x7a, 0xd0, 0x23, +0x97, 0x74, 0xa7, 0x2c, 0xf0, 0x08, 0xd8, 0x79, 0x5a, 0xd7, 0x5a, 0x84, 0x8a, 0xd8, 0x12, 0x9a, +0x1b, 0xd9, 0x7d, 0x5c, 0x4d, 0x70, 0xc5, 0xa5, 0xf9, 0xab, 0xe5, 0xa3, 0x89, 0x89, 0xdd, 0x01, +0xfa, 0xec, 0xdd, 0xf9, 0xe9, 0x92, 0x97, 0xdb, 0xb0, 0x46, 0x42, 0xf3, 0xd3, 0x62, 0xaa, 0x95, +0xfe, 0x31, 0x67, 0x14, 0x69, 0x58, 0x90, 0x0a, 0xaa, 0x0b, 0xee, 0x37, 0x23, 0xc7, 0x50, 0x51, +0xb4, 0xf5, 0x7e, 0x9e, 0xe3, 0x7b, 0xf7, 0xe4, 0xcc, 0x42, 0x32, 0x2d, 0x49, 0x0c, 0xcb, 0xff, +0x49, 0x0c, 0x9b, 0x1e, 0x34, 0xfd, 0x6e, 0x6e, 0x96, 0x8a, 0x79, 0x03, 0xb6, 0x6f, 0xdb, 0x09, +0xcb, 0xfd, 0x5f, 0x65, 0x14, 0x37, 0xe1, 0x38, 0xf5, 0xf3, 0x61, 0x16, 0x58, 0xe4, 0xb5, 0x6d, +0x0d, 0x0b, 0x04, 0x1b, 0x3f, 0x50, 0x2d, 0x7f, 0xb3, 0xc7, 0x7a, 0x1a, 0x16, 0x80, 0x60, 0xf8, +0x8a, 0x1f, 0xe9, 0x1b, 0x2a, 0xc6, 0xf9, 0xba, 0x01, 0x1a, 0x69, 0xbf, 0xd2, 0x58, 0xc7, 0x54, +0x57, 0x08, 0x8f, 0xe1, 0x39, 0x60, 0x77, 0x4b, 0xac, 0x59, 0x84, 0x1a, 0x88, 0xf1, 0xdd, 0xcb, +0x4f, 0x78, 0xd7, 0xe7, 0xe1, 0x33, 0x2d, 0xfc, 0xee, 0x41, 0xfa, 0x20, 0xb0, 0xbe, 0xcb, 0xf7, +0x38, 0x94, 0xc0, 0xe1, 0xd0, 0x85, 0x0f, 0xbb, 0xed, 0x2c, 0x73, 0xab, 0xed, 0xfe, 0x92, 0x76, +0x1a, 0x64, 0x7f, 0x5b, 0x0d, 0x33, 0x09, 0x07, 0x33, 0x7b, 0x06, 0x3f, 0x11, 0xa4, 0x5c, 0x70, +0x3c, 0x85, 0xc0, 0xcf, 0xe3, 0x90, 0xa8, 0x83, 0x77, 0xfa, 0xdb, 0xe6, 0xc5, 0x8c, 0x68, 0x67, +0x10, 0x67, 0xa5, 0x52, 0x2d, 0xf0, 0xc4, 0x99, 0x8f, 0x7f, 0xbf, 0xd1, 0x6b, 0xe2, 0xb5, 0x47, +0xd6, 0xd9, 0xd0, 0x85, 0x99, 0x4d, 0x94, 0x9b, 0x0f, 0x4b, 0x8d, 0xee, 0x00, 0x5a, 0x47, 0x1d, +0x11, 0x03, 0xac, 0x41, 0x18, 0xaf, 0x87, 0xb7, 0x6f, 0x0c, 0x3a, 0x8f, 0xca, 0xcf, 0xdc, 0x03, +0xc1, 0xa2, 0x09, 0xc8, 0xe5, 0xfd, 0x80, 0x5e, 0xc8, 0x60, 0x42, 0x01, 0x1b, 0x1a, 0x53, 0x5a, +0xbb, 0x37, 0xa6, 0xb7, 0xbc, 0xba, 0x84, 0xe9, 0x1e, 0x6c, 0x1a, 0xd4, 0x64, 0xda, 0xd4, 0x43, +0xfe, 0x93, 0x8b, 0x4b, 0xf2, 0x2c, 0x79, 0x16, 0x10, 0xd4, 0x93, 0x0b, 0x88, 0x8f, 0xa1, 0xd8, +0x86, 0x14, 0x46, 0x91, 0x47, 0x9b, 0x28, 0x24, 0xef, 0x57, 0x52, 0x4e, 0x5c, 0x42, 0x9c, 0xaa, +0xf7, 0x49, 0xec, 0x27, 0xe8, 0x40, 0x1e, 0xb3, 0xa6, 0x89, 0x22, 0x72, 0x9c, 0xf5, 0x0d, 0x33, +0xb4, 0x58, 0xa3, 0x30, 0x3b, 0xdd, 0xd4, 0x6a, 0x54, 0x93, 0xbe, 0x1a, 0x4d, 0xf3, 0x93, 0x94, +0xf7, 0xfc, 0x84, 0x0b, 0x3f, 0x84, 0x20, 0x5c, 0x34, 0x03, 0x44, 0xc5, 0xda, 0xad, 0xbc, 0x0a, +0xc1, 0x02, 0xcf, 0x1e, 0xe5, 0x94, 0xd9, 0xf3, 0x8e, 0x5b, 0xd8, 0x4c, 0xf0, 0x9d, 0xec, 0x61, +0x17, 0xbb, 0x14, 0x32, 0x54, 0x0c, 0x02, 0x29, 0x93, 0x1e, 0x92, 0x86, 0xf6, 0x7f, 0xef, 0xe7, +0x92, 0x05, 0x0e, 0x59, 0xdd, 0x99, 0x08, 0x2e, 0x2e, 0xfa, 0x9c, 0x00, 0x52, 0xd3, 0xc5, 0x66, +0x29, 0xe4, 0xa7, 0x97, 0x44, 0xa4, 0x0e, 0x28, 0x81, 0x13, 0x35, 0xc5, 0xf6, 0x6f, 0x64, 0xe6, +0x41, 0xc4, 0xd5, 0x2f, 0xcc, 0x34, 0x45, 0x25, 0xcf, 0x41, 0x00, 0x96, 0x3d, 0x4a, 0x2e, 0xc2, +0x96, 0x98, 0x4f, 0x4e, 0x4a, 0x9c, 0x97, 0xb7, 0xdb, 0x1f, 0x92, 0x32, 0xc8, 0xff, 0x0f, 0x51, +0x6e, 0xd6, 0xec, 0x09, 0x30, 0x82, 0x04, 0x30, 0x30, 0x82, 0x03, 0x18, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x09, 0x00, 0xda, 0x9b, 0xec, 0x71, 0xf3, 0x03, 0xb0, 0x19, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xa4, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, +0x03, 0x55, 0x04, 0x08, 0x0c, 0x06, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x31, 0x14, 0x30, 0x12, +0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x20, 0x43, 0x69, +0x74, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1b, 0x54, 0x72, 0x75, +0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, +0x20, 0x64, 0x65, 0x20, 0x52, 0x2e, 0x4c, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x0c, 0x1e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, +0x79, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x54, 0x72, 0x75, 0x73, +0x74, 0x43, 0x6f, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x20, 0x43, 0x41, +0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x32, 0x30, 0x34, 0x31, 0x32, 0x33, 0x32, +0x31, 0x36, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x37, 0x32, 0x33, 0x31, +0x36, 0x5a, 0x30, 0x81, 0xa4, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x50, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x06, 0x50, 0x61, 0x6e, +0x61, 0x6d, 0x61, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, 0x50, 0x61, +0x6e, 0x61, 0x6d, 0x61, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x0c, 0x1b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x53, 0x79, 0x73, +0x74, 0x65, 0x6d, 0x73, 0x20, 0x53, 0x2e, 0x20, 0x64, 0x65, 0x20, 0x52, 0x2e, 0x4c, 0x2e, 0x31, +0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, +0x6f, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, +0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x16, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x43, 0x65, 0x72, 0x74, 0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, +0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbf, 0x8e, 0xb7, 0x95, 0xe2, 0xc2, +0x26, 0x12, 0x6b, 0x33, 0x19, 0xc7, 0x40, 0x58, 0x0a, 0xab, 0x59, 0xaa, 0x8d, 0x00, 0xa3, 0xfc, +0x80, 0xc7, 0x50, 0x7b, 0x8e, 0xd4, 0x20, 0x26, 0xba, 0x32, 0x12, 0xd8, 0x23, 0x54, 0x49, 0x25, +0x10, 0x22, 0x98, 0x9d, 0x46, 0xd2, 0xc1, 0xc9, 0x9e, 0x4e, 0x1b, 0x2e, 0x2c, 0x0e, 0x38, 0xf3, +0x1a, 0x25, 0x68, 0x1c, 0xa6, 0x5a, 0x05, 0xe6, 0x1e, 0x8b, 0x48, 0xbf, 0x98, 0x96, 0x74, 0x3e, +0x69, 0xca, 0xe9, 0xb5, 0x78, 0xa5, 0x06, 0xbc, 0xd5, 0x00, 0x5e, 0x09, 0x0a, 0xf2, 0x27, 0x7a, +0x52, 0xfc, 0x2d, 0xd5, 0xb1, 0xea, 0xb4, 0x89, 0x61, 0x24, 0xf3, 0x1a, 0x13, 0xdb, 0xa9, 0xcf, +0x52, 0xed, 0x0c, 0x24, 0xba, 0xb9, 0x9e, 0xec, 0x7e, 0x00, 0x74, 0xfa, 0x93, 0xad, 0x6c, 0x29, +0x92, 0xae, 0x51, 0xb4, 0xbb, 0xd3, 0x57, 0xbf, 0xb3, 0xf3, 0xa8, 0x8d, 0x9c, 0xf4, 0x24, 0x4b, +0x2a, 0xd6, 0x99, 0x9e, 0xf4, 0x9e, 0xfe, 0xc0, 0x7e, 0x42, 0x3a, 0xe7, 0x0b, 0x95, 0x53, 0xda, +0xb7, 0x68, 0x0e, 0x90, 0x4c, 0xfb, 0x70, 0x3f, 0x8f, 0x4a, 0x2c, 0x94, 0xf3, 0x26, 0xdd, 0x63, +0x69, 0xa9, 0x94, 0xd8, 0x10, 0x4e, 0xc5, 0x47, 0x08, 0x90, 0x99, 0x1b, 0x17, 0x4d, 0xb9, 0x6c, +0x6e, 0xef, 0x60, 0x95, 0x11, 0x8e, 0x21, 0x80, 0xb5, 0xbd, 0xa0, 0x73, 0xd8, 0xd0, 0xb2, 0x77, +0xc4, 0x45, 0xea, 0x5a, 0x26, 0xfb, 0x66, 0x76, 0x76, 0xf8, 0x06, 0x1f, 0x61, 0x6d, 0x0f, 0x55, +0xc5, 0x83, 0xb7, 0x10, 0x56, 0x72, 0x06, 0x07, 0xa5, 0xf3, 0xb1, 0x1a, 0x03, 0x05, 0x64, 0x0e, +0x9d, 0x5a, 0x8a, 0xd6, 0x86, 0x70, 0x1b, 0x24, 0xde, 0xfe, 0x28, 0x8a, 0x2b, 0xd0, 0x6a, 0xb0, +0xfc, 0x7a, 0xa2, 0xdc, 0xb2, 0x79, 0x0e, 0x8b, 0x65, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x6b, +0x49, 0x3c, 0x7a, 0x3f, 0x0d, 0xe3, 0xb1, 0x09, 0xb7, 0x8a, 0xc8, 0xab, 0x19, 0x9f, 0x73, 0x33, +0x50, 0xe7, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xee, +0x6b, 0x49, 0x3c, 0x7a, 0x3f, 0x0d, 0xe3, 0xb1, 0x09, 0xb7, 0x8a, 0xc8, 0xab, 0x19, 0x9f, 0x73, +0x33, 0x50, 0xe7, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x86, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x25, 0x18, 0xd4, 0x91, 0x8f, 0x13, 0xee, 0x8f, +0x1e, 0x1d, 0x11, 0x53, 0xda, 0x2d, 0x44, 0x29, 0x19, 0xa0, 0x1e, 0x6b, 0x31, 0x9e, 0x4d, 0x0e, +0x9e, 0xad, 0x3d, 0x5c, 0x41, 0x6f, 0x95, 0x2b, 0x24, 0xa1, 0x79, 0x98, 0x3a, 0x38, 0x36, 0xfb, +0xbb, 0x66, 0x9e, 0x48, 0xff, 0x90, 0x90, 0xef, 0x3d, 0xd4, 0xb8, 0x9b, 0xb4, 0x87, 0x75, 0x3f, +0x20, 0x9b, 0xce, 0x72, 0xcf, 0xa1, 0x55, 0xc1, 0x4d, 0x64, 0xa2, 0x19, 0x06, 0xa1, 0x07, 0x33, +0x0c, 0x0b, 0x29, 0xe5, 0xf1, 0xea, 0xab, 0xa3, 0xec, 0xb5, 0x0a, 0x74, 0x90, 0xc7, 0x7d, 0x72, +0xf2, 0xd7, 0x5c, 0x9f, 0x91, 0xef, 0x91, 0x8b, 0xb7, 0xdc, 0xed, 0x66, 0xa2, 0xcf, 0x8e, 0x66, +0x3b, 0xbc, 0x9f, 0x3a, 0x02, 0xe0, 0x27, 0xdd, 0x16, 0x98, 0xc0, 0x95, 0xd4, 0x0a, 0xa4, 0xe4, +0x81, 0x9a, 0x75, 0x94, 0x35, 0x9c, 0x90, 0x5f, 0x88, 0x37, 0x06, 0xad, 0x59, 0x95, 0x0a, 0xb0, +0xd1, 0x67, 0xd3, 0x19, 0xca, 0x89, 0xe7, 0x32, 0x5a, 0x36, 0x1c, 0x3e, 0x82, 0xa8, 0x5a, 0x93, +0xbe, 0xc6, 0xd0, 0x64, 0x91, 0xb6, 0xcf, 0xd9, 0xb6, 0x18, 0xcf, 0xdb, 0x7e, 0xd2, 0x65, 0xa3, +0xa6, 0xc4, 0x8e, 0x17, 0x31, 0xc1, 0xfb, 0x7e, 0x76, 0xdb, 0xd3, 0x85, 0xe3, 0x58, 0xb2, 0x77, +0x7a, 0x76, 0x3b, 0x6c, 0x2f, 0x50, 0x1c, 0xe7, 0xdb, 0xf6, 0x67, 0x79, 0x1f, 0xf5, 0x82, 0x95, +0x9a, 0x07, 0xa7, 0x14, 0xaf, 0x8f, 0xdc, 0x28, 0x21, 0x67, 0x09, 0xd2, 0xd6, 0x4d, 0x5a, 0x1c, +0x19, 0x1c, 0x8e, 0x77, 0x5c, 0xc3, 0x94, 0x24, 0x3d, 0x32, 0x6b, 0x4b, 0x7e, 0xd4, 0x78, 0x94, +0x83, 0xbe, 0x37, 0x4d, 0xce, 0x5f, 0xc7, 0x1e, 0x4e, 0x3c, 0xe0, 0x89, 0x33, 0x95, 0x0b, 0x0f, +0xa5, 0x32, 0xd6, 0x3c, 0x5a, 0x79, 0x2c, 0x19, 0x30, 0x82, 0x05, 0x5a, 0x30, 0x82, 0x03, 0x42, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4f, 0xd2, 0x2b, 0x8f, 0xf5, 0x64, 0xc8, 0x33, 0x9e, +0x4f, 0x34, 0x58, 0x66, 0x23, 0x70, 0x60, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x43, 0x4e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, +0x55, 0x6e, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x1c, 0x55, 0x43, 0x41, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, +0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, +0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x33, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, +0x17, 0x0d, 0x33, 0x38, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, +0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4e, 0x31, 0x11, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x55, 0x6e, 0x69, 0x54, 0x72, 0x75, 0x73, +0x74, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x55, 0x43, 0x41, 0x20, +0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, +0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xb0, +0x99, 0xe0, 0x64, 0xaa, 0x1e, 0x43, 0x16, 0x7a, 0x73, 0xb1, 0x91, 0xa0, 0x75, 0x3e, 0xa8, 0xfa, +0xe3, 0x38, 0x00, 0x7a, 0xec, 0x89, 0x6a, 0x20, 0x0f, 0x8b, 0xc5, 0xb0, 0x9b, 0x33, 0x03, 0x5a, +0x86, 0xc6, 0x58, 0x86, 0xd5, 0xc1, 0x85, 0xbb, 0x4f, 0xc6, 0x9c, 0x40, 0x4d, 0xca, 0xbe, 0xee, +0x69, 0x96, 0xb8, 0xad, 0x81, 0x30, 0x9a, 0x7c, 0x92, 0x05, 0xeb, 0x05, 0x2b, 0x9a, 0x48, 0xd0, +0xb8, 0x76, 0x3e, 0x96, 0xc8, 0x20, 0xbb, 0xd2, 0xb0, 0xf1, 0x8f, 0xd8, 0xac, 0x45, 0x46, 0xff, +0xaa, 0x67, 0x60, 0xb4, 0x77, 0x7e, 0x6a, 0x1f, 0x3c, 0x1a, 0x52, 0x7a, 0x04, 0x3d, 0x07, 0x3c, +0x85, 0x0d, 0x84, 0xd0, 0x1f, 0x76, 0x0a, 0xf7, 0x6a, 0x14, 0xdf, 0x72, 0xe3, 0x34, 0x7c, 0x57, +0x4e, 0x56, 0x01, 0x3e, 0x79, 0xf1, 0xaa, 0x29, 0x3b, 0x6c, 0xfa, 0xf8, 0x8f, 0x6d, 0x4d, 0xc8, +0x35, 0xdf, 0xae, 0xeb, 0xdc, 0x24, 0xee, 0x79, 0x45, 0xa7, 0x85, 0xb6, 0x05, 0x88, 0xde, 0x88, +0x5d, 0x25, 0x7c, 0x97, 0x64, 0x67, 0x09, 0xd9, 0xbf, 0x5a, 0x15, 0x05, 0x86, 0xf3, 0x09, 0x1e, +0xec, 0x58, 0x32, 0x33, 0x11, 0xf3, 0x77, 0x64, 0xb0, 0x76, 0x1f, 0xe4, 0x10, 0x35, 0x17, 0x1b, +0xf2, 0x0e, 0xb1, 0x6c, 0xa4, 0x2a, 0xa3, 0x73, 0xfc, 0x09, 0x1f, 0x1e, 0x32, 0x19, 0x53, 0x11, +0xe7, 0xd9, 0xb3, 0x2c, 0x2e, 0x76, 0x2e, 0xa1, 0xa3, 0xde, 0x7e, 0x6a, 0x88, 0x09, 0xe8, 0xf2, +0x07, 0x8a, 0xf8, 0xb2, 0xcd, 0x10, 0xe7, 0xe2, 0x73, 0x40, 0x93, 0xbb, 0x08, 0xd1, 0x3f, 0xe1, +0xfc, 0x0b, 0x94, 0xb3, 0x25, 0xef, 0x7c, 0xa6, 0xd7, 0xd1, 0xaf, 0x9f, 0xff, 0x96, 0x9a, 0xf5, +0x91, 0x7b, 0x98, 0x0b, 0x77, 0xd4, 0x7e, 0xe8, 0x07, 0xd2, 0x62, 0xb5, 0x95, 0x39, 0xe3, 0xf3, +0xf1, 0x6d, 0x0f, 0x0e, 0x65, 0x84, 0x8a, 0x63, 0x54, 0xc5, 0x80, 0xb6, 0xe0, 0x9e, 0x4b, 0x7d, +0x47, 0x26, 0xa7, 0x01, 0x08, 0x5d, 0xd1, 0x88, 0x9e, 0xd7, 0xc3, 0x32, 0x44, 0xfa, 0x82, 0x4a, +0x0a, 0x68, 0x54, 0x7f, 0x38, 0x53, 0x03, 0xcc, 0xa4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0b, 0xa3, +0x82, 0x91, 0x7a, 0x5e, 0xec, 0x16, 0xc2, 0xf3, 0x2a, 0xe6, 0x62, 0xda, 0x2a, 0xdb, 0x59, 0x62, +0x10, 0x25, 0x4a, 0x2a, 0x81, 0x0b, 0x47, 0x07, 0x43, 0x06, 0x70, 0x87, 0xd2, 0xfa, 0x93, 0x11, +0x29, 0x7a, 0x48, 0x4d, 0xeb, 0x94, 0xc7, 0x70, 0x4d, 0xaf, 0x67, 0xd5, 0x51, 0xb1, 0x80, 0x20, +0x01, 0x01, 0xb4, 0x7a, 0x08, 0xa6, 0x90, 0x7f, 0x4e, 0xe0, 0xef, 0x07, 0x41, 0x87, 0xaf, 0x6a, +0xa5, 0x5e, 0x8b, 0xfb, 0xcf, 0x50, 0xb2, 0x9a, 0x54, 0xaf, 0xc3, 0x89, 0xba, 0x58, 0x2d, 0xf5, +0x30, 0x98, 0xb1, 0x36, 0x72, 0x39, 0x7e, 0x49, 0x04, 0xfd, 0x29, 0xa7, 0x4c, 0x79, 0xe4, 0x05, +0x57, 0xdb, 0x94, 0xb9, 0x16, 0x53, 0x8d, 0x46, 0xb3, 0x1d, 0x95, 0x61, 0x57, 0x56, 0x7f, 0xaf, +0xf0, 0x16, 0x5b, 0x61, 0x58, 0x6f, 0x36, 0x50, 0x11, 0x0b, 0xd8, 0xac, 0x2b, 0x95, 0x16, 0x1a, +0x0e, 0x1f, 0x08, 0xcd, 0x36, 0x34, 0x65, 0x10, 0x62, 0x66, 0xd5, 0x80, 0x5f, 0x14, 0x20, 0x5f, +0x2d, 0x0c, 0xa0, 0x78, 0x0a, 0x68, 0xd6, 0x2c, 0xd7, 0xe9, 0x6f, 0x2b, 0xd2, 0x4a, 0x05, 0x93, +0xfc, 0x9e, 0x6f, 0x6b, 0x67, 0xff, 0x88, 0xf1, 0x4e, 0xa5, 0x69, 0x4a, 0x52, 0x37, 0x05, 0xea, +0xc6, 0x16, 0x8d, 0xd2, 0xc4, 0x99, 0xd1, 0x82, 0x2b, 0x3b, 0xba, 0x35, 0x75, 0xf7, 0x51, 0x51, +0x58, 0xf3, 0xc8, 0x07, 0xdd, 0xe4, 0xb4, 0x03, 0x7f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd9, 0x74, 0x3a, +0xe4, 0x30, 0x3d, 0x0d, 0xf7, 0x12, 0xdc, 0x7e, 0x5a, 0x05, 0x9f, 0x1e, 0x34, 0x9a, 0xf7, 0xe1, +0x14, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x86, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x36, 0x8d, 0x97, 0xcc, 0x42, 0x15, 0x64, 0x29, 0x37, 0x9b, +0x26, 0x2c, 0xd6, 0xfb, 0xae, 0x15, 0x69, 0x2c, 0x6b, 0x1a, 0x1a, 0xf7, 0x5f, 0xb6, 0xf9, 0x07, +0x4c, 0x59, 0xea, 0xf3, 0xc9, 0xc8, 0xb9, 0xae, 0xcc, 0xba, 0x2e, 0x7a, 0xdc, 0xc0, 0xf5, 0xb0, +0x2d, 0xc0, 0x3b, 0xaf, 0x9f, 0x70, 0x05, 0x11, 0x6a, 0x9f, 0x25, 0x4f, 0x01, 0x29, 0x70, 0xe3, +0xe5, 0x0c, 0xe1, 0xea, 0x5a, 0x7c, 0xdc, 0x49, 0xbb, 0xc1, 0x1e, 0x2a, 0x81, 0xf5, 0x16, 0x4b, +0x72, 0x91, 0xc8, 0xa2, 0x31, 0xb9, 0xaa, 0xda, 0xfc, 0x9d, 0x1f, 0xf3, 0x5d, 0x40, 0x02, 0x13, +0xfc, 0x4e, 0x1c, 0x06, 0xca, 0xb3, 0x14, 0x90, 0x54, 0x17, 0x19, 0x12, 0x1a, 0xf1, 0x1f, 0xd7, +0x0c, 0x69, 0x5a, 0xf6, 0x71, 0x78, 0xf4, 0x94, 0x7d, 0x91, 0x0b, 0x8e, 0xec, 0x90, 0x54, 0x8e, +0xbc, 0x6f, 0xa1, 0x4c, 0xab, 0xfc, 0x74, 0x64, 0xfd, 0x71, 0x9a, 0xf8, 0x41, 0x07, 0xa1, 0xcd, +0x91, 0xe4, 0x3c, 0x9a, 0xe0, 0x9b, 0x32, 0x39, 0x73, 0xab, 0x2a, 0xd5, 0x69, 0xc8, 0x78, 0x91, +0x26, 0x31, 0x7d, 0xe2, 0xc7, 0x30, 0xf1, 0xfc, 0x14, 0x78, 0x77, 0x12, 0x0e, 0x13, 0xf4, 0xdd, +0x16, 0x94, 0xbf, 0x4b, 0x67, 0x7b, 0x70, 0x53, 0x85, 0xca, 0xb0, 0xbb, 0xf3, 0x38, 0x4d, 0x2c, +0x90, 0x39, 0xc0, 0x0d, 0xc2, 0x5d, 0x6b, 0xe9, 0xe2, 0xe5, 0xd5, 0x88, 0x8d, 0xd6, 0x2c, 0xbf, +0xab, 0x1b, 0xbe, 0xb5, 0x28, 0x87, 0x12, 0x17, 0x74, 0x6e, 0xfc, 0x7d, 0xfc, 0x8f, 0xd0, 0x87, +0x26, 0xb0, 0x1b, 0xfb, 0xb9, 0x6c, 0xab, 0xe2, 0x9e, 0x3d, 0x15, 0xc1, 0x3b, 0x2e, 0x67, 0x02, +0x58, 0x91, 0x9f, 0xef, 0xf8, 0x42, 0x1f, 0x2c, 0xb7, 0x68, 0xf5, 0x75, 0xad, 0xcf, 0xb5, 0xf6, +0xff, 0x11, 0x7d, 0xc2, 0xf0, 0x24, 0xa5, 0xad, 0xd3, 0xfa, 0xa0, 0x3c, 0xa9, 0xfa, 0x5d, 0xdc, +0xa5, 0xa0, 0xef, 0x44, 0xa4, 0xbe, 0xd6, 0xe8, 0xe5, 0xe4, 0x13, 0x96, 0x17, 0x7b, 0x06, 0x3e, +0x32, 0xed, 0xc7, 0xb7, 0x42, 0xbc, 0x76, 0xa3, 0xd8, 0x65, 0x38, 0x2b, 0x38, 0x35, 0x51, 0x21, +0x0e, 0x0e, 0x6f, 0x2e, 0x34, 0x13, 0x40, 0xe1, 0x2b, 0x67, 0x0c, 0x6d, 0x4a, 0x41, 0x30, 0x18, +0x23, 0x5a, 0x32, 0x55, 0x99, 0xc9, 0x17, 0xe0, 0x3c, 0xde, 0xf6, 0xec, 0x79, 0xad, 0x2b, 0x58, +0x19, 0xa2, 0xad, 0x2c, 0x22, 0x1a, 0x95, 0x8e, 0xbe, 0x96, 0x90, 0x5d, 0x42, 0x57, 0xc4, 0xf9, +0x14, 0x03, 0x35, 0x2b, 0x1c, 0x2d, 0x51, 0x57, 0x08, 0xa7, 0x3a, 0xde, 0x3f, 0xe4, 0xc8, 0xb4, +0x03, 0x73, 0xc2, 0xc1, 0x26, 0x80, 0xbb, 0x0b, 0x42, 0x1f, 0xad, 0x0d, 0xaf, 0x26, 0x72, 0xda, +0xcc, 0xbe, 0xb3, 0xa3, 0x83, 0x58, 0x0d, 0x82, 0xc5, 0x1f, 0x46, 0x51, 0xe3, 0x9c, 0x18, 0xcc, +0x8d, 0x9b, 0x8d, 0xec, 0x49, 0xeb, 0x75, 0x50, 0xd5, 0x8c, 0x28, 0x59, 0xca, 0x74, 0x34, 0xda, +0x8c, 0x0b, 0x21, 0xab, 0x1e, 0xea, 0x1b, 0xe5, 0xc7, 0xfd, 0x15, 0x3e, 0xc0, 0x17, 0xaa, 0xfb, +0x23, 0x6e, 0x26, 0x46, 0xcb, 0xfa, 0xf9, 0xb1, 0x72, 0x6b, 0x69, 0xcf, 0x22, 0x84, 0x0b, 0x62, +0x0f, 0xac, 0xd9, 0x19, 0x00, 0x94, 0xa2, 0x76, 0x3c, 0xd4, 0x2d, 0x9a, 0xed, 0x04, 0x9e, 0x2d, +0x06, 0x62, 0x10, 0x37, 0x52, 0x1c, 0x85, 0x72, 0x1b, 0x27, 0xe5, 0xcc, 0xc6, 0x31, 0xec, 0x37, +0xec, 0x63, 0x59, 0x9b, 0x0b, 0x1d, 0x76, 0xcc, 0x7e, 0x32, 0x9a, 0x88, 0x95, 0x08, 0x36, 0x52, +0xbb, 0xde, 0x76, 0x5f, 0x76, 0x49, 0x49, 0xad, 0x7f, 0xbd, 0x65, 0x20, 0xb2, 0xc9, 0xc1, 0x2b, +0x76, 0x18, 0x76, 0x9f, 0x56, 0xb1, 0x30, 0x82, 0x05, 0x46, 0x30, 0x82, 0x03, 0x2e, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x10, 0x5d, 0xdf, 0xb1, 0xda, 0x5a, 0xa3, 0xed, 0x5d, 0xbe, 0x5a, 0x65, +0x20, 0x65, 0x03, 0x90, 0xef, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x30, 0x3d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x43, 0x4e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x55, 0x6e, +0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, +0x12, 0x55, 0x43, 0x41, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x47, 0x32, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x31, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x5a, 0x30, 0x3d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x43, 0x4e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x55, 0x6e, 0x69, +0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x12, +0x55, 0x43, 0x41, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x47, 0x32, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, +0x02, 0x01, 0x00, 0xc5, 0xe6, 0x2b, 0x6f, 0x7c, 0xef, 0x26, 0x05, 0x27, 0xa3, 0x81, 0x24, 0xda, +0x6f, 0xcb, 0x01, 0xf9, 0x99, 0x9a, 0xa9, 0x32, 0xc2, 0x22, 0x87, 0x61, 0x41, 0x91, 0x3b, 0xcb, +0xc3, 0x68, 0x1b, 0x06, 0xc5, 0x4c, 0xa9, 0x2b, 0xc1, 0x67, 0x17, 0x22, 0x1d, 0x2b, 0xed, 0xf9, +0x29, 0x89, 0x93, 0xa2, 0x78, 0xbd, 0x92, 0x6b, 0xa0, 0xa3, 0x0d, 0xa2, 0x7e, 0xca, 0x93, 0xb3, +0xa6, 0xd1, 0x8c, 0x35, 0xd5, 0x75, 0xf9, 0x17, 0xf6, 0xcf, 0x45, 0xc5, 0xe5, 0x7a, 0xec, 0x77, +0x93, 0xa0, 0x8f, 0x23, 0xae, 0x0e, 0x1a, 0x03, 0x7f, 0xbe, 0xd4, 0xd0, 0xed, 0x2e, 0x7b, 0xab, +0x46, 0x23, 0x5b, 0xff, 0x2c, 0xe6, 0x54, 0x7a, 0x94, 0xc0, 0x2a, 0x15, 0xf0, 0xc9, 0x8d, 0xb0, +0x7a, 0x3b, 0x24, 0xe1, 0xd7, 0x68, 0xe2, 0x31, 0x3c, 0x06, 0x33, 0x46, 0xb6, 0x54, 0x11, 0xa6, +0xa5, 0x2f, 0x22, 0x54, 0x2a, 0x58, 0x0d, 0x01, 0x02, 0xf1, 0xfa, 0x15, 0x51, 0x67, 0x6c, 0xc0, +0xfa, 0xd7, 0xb6, 0x1b, 0x7f, 0xd1, 0x56, 0x88, 0x2f, 0x1a, 0x3a, 0x8d, 0x3b, 0xbb, 0x82, 0x11, +0xe0, 0x47, 0x00, 0xd0, 0x52, 0x87, 0xab, 0xfb, 0x86, 0x7e, 0x0f, 0x24, 0x6b, 0x40, 0x9d, 0x34, +0x67, 0xbc, 0x8d, 0xc7, 0x2d, 0x86, 0x6f, 0x79, 0x3e, 0x8e, 0xa9, 0x3c, 0x17, 0x4b, 0x7f, 0xb0, +0x99, 0xe3, 0xb0, 0x71, 0x60, 0xdc, 0x0b, 0xf5, 0x64, 0xc3, 0xce, 0x43, 0xbc, 0x6d, 0x71, 0xb9, +0xd2, 0xde, 0x27, 0x5b, 0x8a, 0xe8, 0xd8, 0xc6, 0xae, 0xe1, 0x59, 0x7d, 0xcf, 0x28, 0x2d, 0x35, +0xb8, 0x95, 0x56, 0x1a, 0xf1, 0xb2, 0x58, 0x4b, 0xb7, 0x12, 0x37, 0xc8, 0x7c, 0xb3, 0xed, 0x4b, +0x80, 0xe1, 0x8d, 0xfa, 0x32, 0x23, 0xb6, 0x6f, 0xb7, 0x48, 0x95, 0x08, 0xb1, 0x44, 0x4e, 0x85, +0x8c, 0x3a, 0x02, 0x54, 0x20, 0x2f, 0xdf, 0xbf, 0x57, 0x4f, 0x3b, 0x3a, 0x90, 0x21, 0xd7, 0xc1, +0x26, 0x35, 0x54, 0x20, 0xec, 0xc7, 0x3f, 0x47, 0xec, 0xef, 0x5a, 0xbf, 0x4b, 0x7a, 0xc1, 0xad, +0x3b, 0x17, 0x50, 0x5c, 0x62, 0xd8, 0x0f, 0x4b, 0x4a, 0xdc, 0x2b, 0xfa, 0x6e, 0xbc, 0x73, 0x92, +0xcd, 0xec, 0xc7, 0x50, 0xe8, 0x41, 0x96, 0xd7, 0xa9, 0x7e, 0x6d, 0xd8, 0xe9, 0x1d, 0x8f, 0x8a, +0xb5, 0xb9, 0x58, 0x92, 0xba, 0x4a, 0x92, 0x2b, 0x0c, 0x56, 0xfd, 0x80, 0xeb, 0x08, 0xf0, 0x5e, +0x29, 0x6e, 0x1b, 0x1c, 0x0c, 0xaf, 0x8f, 0x93, 0x89, 0xad, 0xdb, 0xbd, 0xa3, 0x9e, 0x21, 0xca, +0x89, 0x19, 0xec, 0xdf, 0xb5, 0xc3, 0x1a, 0xeb, 0x16, 0xfe, 0x78, 0x36, 0x4c, 0xd6, 0x6e, 0xd0, +0x3e, 0x17, 0x1c, 0x90, 0x17, 0x6b, 0x26, 0xba, 0xfb, 0x7a, 0x2f, 0xbf, 0x11, 0x1c, 0x18, 0x0e, +0x2d, 0x73, 0x03, 0x8f, 0xa0, 0xe5, 0x35, 0xa0, 0x5a, 0xe2, 0x4c, 0x75, 0x1d, 0x71, 0xe1, 0x39, +0x38, 0x53, 0x78, 0x40, 0xcc, 0x83, 0x93, 0xd7, 0x0a, 0x9e, 0x9d, 0x5b, 0x8f, 0x8a, 0xe4, 0xe5, +0xe0, 0x48, 0xe4, 0x48, 0xb2, 0x47, 0xcd, 0x4e, 0x2a, 0x75, 0x2a, 0x7b, 0xf2, 0x22, 0xf6, 0xc9, +0xbe, 0x09, 0x91, 0x96, 0x57, 0x7a, 0x88, 0x88, 0xac, 0xee, 0x70, 0xac, 0xf9, 0xdc, 0x29, 0xe3, +0x0c, 0x1c, 0x3b, 0x12, 0x4e, 0x44, 0xd6, 0xa7, 0x4e, 0xb0, 0x26, 0xc8, 0xf3, 0xd9, 0x1a, 0x97, +0x91, 0x68, 0xea, 0xef, 0x8d, 0x46, 0x06, 0xd2, 0x56, 0x45, 0x58, 0x9a, 0x3c, 0x0c, 0x0f, 0x83, +0xb8, 0x05, 0x25, 0xc3, 0x39, 0xcf, 0x3b, 0xa4, 0x34, 0x89, 0xb7, 0x79, 0x12, 0x2f, 0x47, 0xc5, +0xe7, 0xa9, 0x97, 0x69, 0xfc, 0xa6, 0x77, 0x67, 0xb5, 0xdf, 0x7b, 0xf1, 0x7a, 0x65, 0x15, 0xe4, +0x61, 0x56, 0x65, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, +0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, +0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x81, 0xc4, 0x8c, 0xcc, 0xf5, 0xe4, 0x30, 0xff, +0xa5, 0x0c, 0x08, 0x5f, 0x8c, 0x15, 0x67, 0x21, 0x74, 0x01, 0xdf, 0xdf, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, +0x13, 0x65, 0x22, 0xf5, 0x8e, 0x2b, 0xad, 0x44, 0xe4, 0xcb, 0xff, 0xb9, 0x68, 0xe6, 0xc3, 0x80, +0x48, 0x3d, 0x04, 0x7b, 0xfa, 0x23, 0x2f, 0x7a, 0xed, 0x36, 0xda, 0xb2, 0xce, 0x6d, 0xf6, 0xe6, +0x9e, 0xe5, 0x5f, 0x58, 0x8f, 0xcb, 0x37, 0x32, 0xa1, 0xc8, 0x65, 0xb6, 0xae, 0x38, 0x3d, 0x35, +0x1b, 0x3e, 0xbc, 0x3b, 0xb6, 0x04, 0xd0, 0xbc, 0xf9, 0x49, 0xf5, 0x9b, 0xf7, 0x85, 0xc5, 0x36, +0xb6, 0xcb, 0xbc, 0xf8, 0xc8, 0x39, 0xd5, 0xe4, 0x5f, 0x07, 0xbd, 0x15, 0x54, 0x97, 0x74, 0xca, +0xca, 0xed, 0x4f, 0xba, 0xba, 0x64, 0x76, 0x9f, 0x81, 0xb8, 0x84, 0x45, 0x49, 0x4c, 0x8d, 0x6f, +0xa2, 0xeb, 0xb1, 0xcc, 0xd1, 0xc3, 0x94, 0xda, 0x44, 0xc2, 0xe6, 0xe2, 0xea, 0x18, 0xe8, 0xa2, +0x1f, 0x27, 0x05, 0xba, 0xd7, 0xe5, 0xd6, 0xa9, 0xcd, 0xdd, 0xef, 0x76, 0x98, 0x8d, 0x00, 0x0e, +0xcd, 0x1b, 0xfa, 0x03, 0xb7, 0x8e, 0x80, 0x58, 0x0e, 0x27, 0x3f, 0x52, 0xfb, 0x94, 0xa2, 0xca, +0x5e, 0x65, 0xc9, 0xd6, 0x84, 0xda, 0xb9, 0x35, 0x71, 0xf3, 0x26, 0xc0, 0x4f, 0x77, 0xe6, 0x81, +0x27, 0xd2, 0x77, 0x3b, 0x9a, 0x14, 0x6f, 0x79, 0xf4, 0xf6, 0xd0, 0xe1, 0xd3, 0x94, 0xba, 0xd0, +0x57, 0x51, 0xbd, 0x27, 0x05, 0x0d, 0xc1, 0xfd, 0xc8, 0x12, 0x30, 0xee, 0x6f, 0x8d, 0x11, 0x2b, +0x08, 0x9d, 0xd4, 0xd4, 0xbf, 0x80, 0x45, 0x14, 0x9a, 0x88, 0x44, 0xda, 0x30, 0xea, 0xb4, 0xa7, +0xe3, 0xee, 0xef, 0x5b, 0x82, 0xd5, 0x3e, 0xd6, 0xad, 0x78, 0x92, 0xdb, 0x5c, 0x3c, 0xf3, 0xd8, +0xad, 0xfa, 0xb8, 0x6b, 0x7f, 0xc4, 0x36, 0x28, 0xb6, 0x02, 0x15, 0x8a, 0x54, 0x2c, 0x9c, 0xb0, +0x17, 0x73, 0x8e, 0xd0, 0x37, 0xa3, 0x14, 0x3c, 0x98, 0x95, 0x00, 0x0c, 0x29, 0x05, 0x5b, 0x9e, +0x49, 0x49, 0xb1, 0x5f, 0xc7, 0xe3, 0xcb, 0xcf, 0x27, 0x65, 0x8e, 0x35, 0x17, 0xb7, 0x57, 0xc8, +0x30, 0xd9, 0x41, 0x5b, 0xb9, 0x14, 0xb6, 0xe8, 0xc2, 0x0f, 0x94, 0x31, 0xa7, 0x94, 0x98, 0xcc, +0x6a, 0xeb, 0xb5, 0xe1, 0x27, 0xf5, 0x10, 0xa8, 0x01, 0xe8, 0x8e, 0x12, 0x62, 0xe8, 0x88, 0xcc, +0xb5, 0x7f, 0x46, 0x97, 0xc0, 0x9b, 0x10, 0x66, 0x38, 0x1a, 0x36, 0x46, 0x5f, 0x22, 0x68, 0x3d, +0xdf, 0xc9, 0xc6, 0x13, 0x27, 0xab, 0x53, 0x06, 0xac, 0xa2, 0x3c, 0x86, 0x06, 0x65, 0x6f, 0xb1, +0x7e, 0xb1, 0x29, 0x44, 0x9a, 0xa3, 0xba, 0x49, 0x69, 0x28, 0x69, 0x8f, 0xd7, 0xe5, 0x5f, 0xad, +0x04, 0x86, 0x64, 0x6f, 0x1a, 0xa0, 0x0c, 0xc5, 0x08, 0x62, 0xce, 0x80, 0xa3, 0xd0, 0xf3, 0xec, +0x68, 0xde, 0xbe, 0x33, 0xc7, 0x17, 0x5b, 0x7f, 0x80, 0xc4, 0x4c, 0x4c, 0xb1, 0xa6, 0x84, 0x8a, +0xc3, 0x3b, 0xb8, 0x09, 0xcd, 0x14, 0x81, 0xba, 0x18, 0xe3, 0x54, 0x57, 0x36, 0xfe, 0xdb, 0x2f, +0x7c, 0x47, 0xa1, 0x3a, 0x33, 0xc8, 0xf9, 0x58, 0x3b, 0x44, 0x4f, 0xb1, 0xca, 0x02, 0x89, 0x04, +0x96, 0x28, 0x68, 0xc5, 0x4b, 0xb8, 0x26, 0x89, 0xbb, 0xd6, 0x33, 0x2f, 0x50, 0xd5, 0xfe, 0x9a, +0x89, 0xba, 0x18, 0x32, 0x92, 0x54, 0xc6, 0x5b, 0xe0, 0x9d, 0xf9, 0x5e, 0xe5, 0x0d, 0x22, 0x9b, +0xf6, 0xda, 0xe2, 0xc8, 0x21, 0xb2, 0x62, 0x21, 0xaa, 0x86, 0x40, 0xb2, 0x2e, 0x64, 0xd3, 0x5f, +0xc8, 0xe3, 0x7e, 0x11, 0x67, 0x45, 0x1f, 0x05, 0xfe, 0xe3, 0xa2, 0xef, 0xb3, 0xa8, 0xb3, 0xf3, +0x7d, 0x8f, 0xf8, 0x0c, 0x1f, 0x22, 0x1f, 0x2d, 0x70, 0xb4, 0xb8, 0x01, 0x34, 0x76, 0x30, 0x00, +0xe5, 0x23, 0x78, 0xa7, 0x56, 0xd7, 0x50, 0x1f, 0x8a, 0xfb, 0x06, 0xf5, 0xc2, 0x19, 0xf0, 0xd0, +0x30, 0x82, 0x02, 0x94, 0x30, 0x82, 0x02, 0x1a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x2c, +0x29, 0x9c, 0x5b, 0x16, 0xed, 0x05, 0x95, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x04, 0x03, 0x02, 0x30, 0x7f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x05, 0x54, 0x65, 0x78, +0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x48, 0x6f, 0x75, +0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x53, +0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x34, +0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2b, 0x53, 0x53, 0x4c, 0x2e, 0x63, 0x6f, 0x6d, +0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x20, 0x45, 0x43, 0x43, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x32, 0x31, 0x32, 0x31, 0x38, +0x31, 0x35, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x38, 0x31, +0x35, 0x32, 0x33, 0x5a, 0x30, 0x7f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x05, 0x54, 0x65, +0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x48, 0x6f, +0x75, 0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, +0x53, 0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, +0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2b, 0x53, 0x53, 0x4c, 0x2e, 0x63, 0x6f, +0x6d, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, +0x79, 0x20, 0x45, 0x43, 0x43, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xaa, 0x12, 0x47, +0x90, 0x98, 0x1b, 0xfb, 0xef, 0xc3, 0x40, 0x07, 0x83, 0x20, 0x4e, 0xf1, 0x30, 0x82, 0xa2, 0x06, +0xd1, 0xf2, 0x92, 0x86, 0x61, 0xf2, 0xf6, 0x21, 0x68, 0xca, 0x00, 0xc4, 0xc7, 0xea, 0x43, 0x00, +0x54, 0x86, 0xdc, 0xfd, 0x1f, 0xdf, 0x00, 0xb8, 0x41, 0x62, 0x5c, 0xdc, 0x70, 0x16, 0x32, 0xde, +0x1f, 0x99, 0xd4, 0xcc, 0xc5, 0x07, 0xc8, 0x08, 0x1f, 0x61, 0x16, 0x07, 0x51, 0x3d, 0x7d, 0x5c, +0x07, 0x53, 0xe3, 0x35, 0x38, 0x8c, 0xdf, 0xcd, 0x9f, 0xd9, 0x2e, 0x0d, 0x4a, 0xb6, 0x19, 0x2e, +0x5a, 0x70, 0x5a, 0x06, 0xed, 0xbe, 0xf0, 0xa1, 0xb0, 0xca, 0xd0, 0x09, 0x29, 0xa3, 0x63, 0x30, +0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x5b, 0xca, 0x5e, 0xe5, +0xde, 0xd2, 0x81, 0xaa, 0xcd, 0xa8, 0x2d, 0x64, 0x51, 0xb6, 0xd9, 0x72, 0x9b, 0x97, 0xe6, 0x4f, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x5b, 0xca, +0x5e, 0xe5, 0xde, 0xd2, 0x81, 0xaa, 0xcd, 0xa8, 0x2d, 0x64, 0x51, 0xb6, 0xd9, 0x72, 0x9b, 0x97, +0xe6, 0x4f, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x86, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, +0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0x8a, 0xe6, 0x40, 0x89, 0x37, 0xeb, 0xe9, 0xd5, 0x13, 0xd9, +0xca, 0xd4, 0x6b, 0x24, 0xf3, 0xb0, 0x3d, 0x87, 0x46, 0x58, 0x1a, 0xec, 0xb1, 0xdf, 0x6f, 0xfb, +0x56, 0xba, 0x70, 0x6b, 0xc7, 0x38, 0xcc, 0xe8, 0xb1, 0x8c, 0x4f, 0x0f, 0xf7, 0xf1, 0x67, 0x76, +0x0e, 0x83, 0xd0, 0x1e, 0x51, 0x8f, 0x02, 0x30, 0x3d, 0xf6, 0x23, 0x28, 0x26, 0x4c, 0xc6, 0x60, +0x87, 0x93, 0x26, 0x9b, 0xb2, 0x35, 0x1e, 0xba, 0xd6, 0xf7, 0x3c, 0xd1, 0x1c, 0xce, 0xfa, 0x25, +0x3c, 0xa6, 0x1a, 0x81, 0x15, 0x5b, 0xf3, 0x12, 0x0f, 0x6c, 0xee, 0x65, 0x8a, 0xc9, 0x87, 0xa8, +0xf9, 0x07, 0xe0, 0x62, 0x9a, 0x8c, 0x5c, 0x4a, 0x30, 0x82, 0x02, 0x8d, 0x30, 0x82, 0x02, 0x14, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x75, 0xe6, 0xdf, 0xcb, 0xc1, 0x68, 0x5b, 0xa8, 0x30, +0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x7c, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, +0x55, 0x04, 0x08, 0x0c, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, +0x55, 0x04, 0x07, 0x0c, 0x07, 0x48, 0x6f, 0x75, 0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, +0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, +0x28, 0x53, 0x53, 0x4c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, +0x32, 0x31, 0x32, 0x31, 0x38, 0x31, 0x34, 0x30, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x31, 0x30, 0x32, +0x31, 0x32, 0x31, 0x38, 0x31, 0x34, 0x30, 0x33, 0x5a, 0x30, 0x7c, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, +0x08, 0x0c, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, +0x07, 0x0c, 0x07, 0x48, 0x6f, 0x75, 0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x28, 0x53, +0x53, 0x4c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, +0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x45, +0x6e, 0xa9, 0x50, 0xc4, 0xa6, 0x23, 0x36, 0x9e, 0x5f, 0x28, 0x8d, 0x17, 0xcb, 0x96, 0x22, 0x64, +0x3f, 0xdc, 0x7a, 0x8e, 0x1d, 0xcc, 0x08, 0xb3, 0xa2, 0x71, 0x24, 0xba, 0x8e, 0x49, 0xb9, 0x04, +0x1b, 0x47, 0x96, 0x58, 0xab, 0x2d, 0x95, 0xc8, 0xed, 0x9e, 0x08, 0x35, 0xc8, 0x27, 0xeb, 0x89, +0x8c, 0x53, 0x58, 0xeb, 0x62, 0x8a, 0xfe, 0xf0, 0x5b, 0x0f, 0x6b, 0x31, 0x52, 0x63, 0x41, 0x3b, +0x89, 0xcd, 0xec, 0xec, 0xb6, 0x8d, 0x19, 0xd3, 0x34, 0x07, 0xdc, 0xbb, 0xc6, 0x06, 0x7f, 0xc2, +0x45, 0x95, 0xec, 0xcb, 0x7f, 0xa8, 0x23, 0xe0, 0x09, 0xe9, 0x81, 0xfa, 0xf3, 0x47, 0xd3, 0xa3, +0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x82, 0xd1, +0x85, 0x73, 0x30, 0xe7, 0x35, 0x04, 0xd3, 0x8e, 0x02, 0x92, 0xfb, 0xe5, 0xa4, 0xd1, 0xc4, 0x21, +0xe8, 0xcd, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, +0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, +0x82, 0xd1, 0x85, 0x73, 0x30, 0xe7, 0x35, 0x04, 0xd3, 0x8e, 0x02, 0x92, 0xfb, 0xe5, 0xa4, 0xd1, +0xc4, 0x21, 0xe8, 0xcd, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x86, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, +0x03, 0x67, 0x00, 0x30, 0x64, 0x02, 0x30, 0x6f, 0xe7, 0xeb, 0x59, 0x11, 0xa4, 0x60, 0xcf, 0x61, +0xb0, 0x96, 0x7b, 0xed, 0x05, 0xf9, 0x2f, 0x13, 0x91, 0xdc, 0xed, 0xe5, 0xfc, 0x50, 0x6b, 0x11, +0x46, 0x46, 0xb3, 0x1c, 0x21, 0x00, 0x62, 0xbb, 0xbe, 0xc3, 0xe7, 0xe8, 0xcd, 0x07, 0x99, 0xf9, +0x0d, 0x0b, 0x5d, 0x72, 0x3e, 0xc4, 0xaa, 0x02, 0x30, 0x1f, 0xbc, 0xba, 0x0b, 0xe2, 0x30, 0x24, +0xfb, 0x7c, 0x6d, 0x80, 0x55, 0x0a, 0x99, 0x3e, 0x80, 0x0d, 0x33, 0xe5, 0x66, 0xa3, 0xb3, 0xa3, +0xbb, 0xa5, 0xd5, 0x8b, 0x8f, 0x09, 0x2c, 0xa6, 0x5d, 0x7e, 0xe2, 0xf0, 0x07, 0x08, 0x68, 0x6d, +0xd2, 0x7c, 0x69, 0x6e, 0x5f, 0xdf, 0xe5, 0x6a, 0x65, 0x30, 0x82, 0x05, 0xdd, 0x30, 0x82, 0x03, +0xc5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x7b, 0x2c, 0x9b, 0xd3, 0x16, 0x80, 0x32, 0x99, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, +0x7c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, +0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x48, 0x6f, 0x75, 0x73, 0x74, 0x6f, 0x6e, +0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x53, 0x53, 0x4c, 0x20, 0x43, +0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x28, 0x53, 0x53, 0x4c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, +0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x30, 0x1e, 0x17, +0x0d, 0x31, 0x36, 0x30, 0x32, 0x31, 0x32, 0x31, 0x37, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x17, 0x0d, +0x34, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x37, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x30, 0x7c, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, +0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x48, 0x6f, 0x75, 0x73, 0x74, 0x6f, 0x6e, 0x31, 0x18, +0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6f, 0x72, +0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x28, 0x53, 0x53, 0x4c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, +0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x30, 0x82, 0x02, 0x22, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, +0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xf9, 0x0f, 0xdd, 0xa3, +0x2b, 0x7d, 0xcb, 0xd0, 0x2a, 0xfe, 0xec, 0x67, 0x85, 0xa6, 0xe7, 0x2e, 0x1b, 0xba, 0x77, 0xe1, +0xe3, 0xf5, 0xaf, 0xa4, 0xec, 0xfa, 0x4a, 0x5d, 0x91, 0xc4, 0x57, 0x47, 0x6b, 0x18, 0x77, 0x6b, +0x76, 0xf2, 0xfd, 0x93, 0xe4, 0x3d, 0x0f, 0xc2, 0x16, 0x9e, 0x0b, 0x66, 0xc3, 0x56, 0x94, 0x9e, +0x17, 0x83, 0x85, 0xce, 0x56, 0xef, 0xf2, 0x16, 0xfd, 0x00, 0x62, 0xf5, 0x22, 0x09, 0x54, 0xe8, +0x65, 0x17, 0x4e, 0x41, 0xb9, 0xe0, 0x4f, 0x46, 0x97, 0xaa, 0x1b, 0xc8, 0xb8, 0x6e, 0x62, 0x5e, +0x69, 0xb1, 0x5f, 0xdb, 0x2a, 0x02, 0x7e, 0xfc, 0x6c, 0xca, 0xf3, 0x41, 0xd8, 0xed, 0xd0, 0xe8, +0xfc, 0x3f, 0x61, 0x48, 0xed, 0xb0, 0x03, 0x14, 0x1d, 0x10, 0x0e, 0x4b, 0x19, 0xe0, 0xbb, 0x4e, +0xec, 0x86, 0x65, 0xff, 0x36, 0xf3, 0x5e, 0x67, 0x02, 0x0b, 0x9d, 0x86, 0x55, 0x61, 0xfd, 0x7a, +0x38, 0xed, 0xfe, 0xe2, 0x19, 0x00, 0xb7, 0x6f, 0xa1, 0x50, 0x62, 0x75, 0x74, 0x3c, 0xa0, 0xfa, +0xc8, 0x25, 0x92, 0xb4, 0x6e, 0x7a, 0x22, 0xc7, 0xf8, 0x1e, 0xa1, 0xe3, 0xb2, 0xdd, 0x91, 0x31, +0xab, 0x2b, 0x1d, 0x04, 0xff, 0xa5, 0x4a, 0x04, 0x37, 0xe9, 0x85, 0xa4, 0x33, 0x2b, 0xfd, 0xe2, +0xd6, 0x55, 0x34, 0x7c, 0x19, 0xa4, 0x4a, 0x68, 0xc7, 0xb2, 0xa8, 0xd3, 0xb7, 0xca, 0xa1, 0x93, +0x88, 0xeb, 0xc1, 0x97, 0xbc, 0x8c, 0xf9, 0x1d, 0xd9, 0x22, 0x84, 0x24, 0x74, 0xc7, 0x04, 0x3d, +0x6a, 0xa9, 0x29, 0x93, 0xcc, 0xeb, 0xb8, 0x5b, 0xe1, 0xfe, 0x5f, 0x25, 0xaa, 0x34, 0x58, 0xc8, +0xc1, 0x23, 0x54, 0x9d, 0x1b, 0x98, 0x11, 0xc3, 0x38, 0x9c, 0x7e, 0x3d, 0x86, 0x6c, 0xa5, 0x0f, +0x40, 0x86, 0x7c, 0x02, 0xf4, 0x5c, 0x02, 0x4f, 0x28, 0xcb, 0xae, 0x71, 0x9f, 0x0f, 0x3a, 0xc8, +0x33, 0xfe, 0x11, 0x25, 0x35, 0xea, 0xfc, 0xba, 0xc5, 0x60, 0x3d, 0xd9, 0x7c, 0x18, 0xd5, 0xb2, +0xa9, 0xd3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xca, 0x3a, 0xc3, 0x1f, 0xef, 0x2c, 0xe5, 0x2e, 0xa9, +0xfa, 0x9e, 0x2c, 0xb6, 0x51, 0x46, 0xfd, 0xaf, 0x03, 0xd6, 0xea, 0x60, 0x68, 0xea, 0x85, 0x16, +0x36, 0x6b, 0x85, 0xe9, 0x1e, 0xc0, 0xb3, 0xdd, 0xc4, 0x24, 0xdc, 0x80, 0x2a, 0x81, 0x41, 0x6d, +0x94, 0x3e, 0xc8, 0xe0, 0xc9, 0x81, 0x41, 0x00, 0x9e, 0x5e, 0xbf, 0x7f, 0xc5, 0x08, 0x98, 0xa2, +0x18, 0x2c, 0x42, 0x40, 0xb3, 0xf9, 0x6f, 0x38, 0x27, 0x4b, 0x4e, 0x80, 0xf4, 0x3d, 0x81, 0x47, +0xe0, 0x88, 0x7c, 0xea, 0x1c, 0xce, 0xb5, 0x75, 0x5c, 0x51, 0x2e, 0x1c, 0x2b, 0x7f, 0x1a, 0x72, +0x28, 0xe7, 0x00, 0xb5, 0xd1, 0x74, 0xc6, 0xd7, 0xe4, 0x9f, 0xad, 0x07, 0x93, 0xb6, 0x53, 0x35, +0x35, 0xfc, 0x37, 0xe4, 0xc3, 0xf6, 0x5d, 0x16, 0xbe, 0x21, 0x73, 0xde, 0x92, 0x0a, 0xf8, 0xa0, +0x63, 0x6a, 0xbc, 0x96, 0x92, 0x6a, 0x3e, 0xf8, 0xbc, 0x65, 0x55, 0x9b, 0xde, 0xf5, 0x0d, 0x89, +0x26, 0x04, 0xfc, 0x25, 0x1a, 0xa6, 0x25, 0x69, 0xcb, 0xc2, 0x6d, 0xca, 0x7c, 0xe2, 0x59, 0x5f, +0x97, 0xac, 0xeb, 0xef, 0x2e, 0xc8, 0xbc, 0xd7, 0x1b, 0x59, 0x3c, 0x2b, 0xcc, 0xf2, 0x19, 0xc8, +0x93, 0x6b, 0x27, 0x63, 0x19, 0xcf, 0xfc, 0xe9, 0x26, 0xf8, 0xca, 0x71, 0x9b, 0x7f, 0x93, 0xfe, +0x34, 0x67, 0x84, 0x4e, 0x99, 0xeb, 0xfc, 0xb3, 0x78, 0x09, 0x33, 0x70, 0xba, 0x66, 0xa6, 0x76, +0xed, 0x1b, 0x73, 0xeb, 0x1a, 0xa5, 0x0d, 0xc4, 0x22, 0x13, 0x20, 0x94, 0x56, 0x0a, 0x4e, 0x2c, +0x6c, 0x4e, 0xb1, 0xfd, 0xcf, 0x9c, 0x09, 0xba, 0xa2, 0x33, 0xed, 0x87, 0x02, 0x03, 0x01, 0x00, +0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0xdd, 0x04, 0x09, 0x07, 0xa2, 0xf5, 0x7a, 0x7d, 0x52, 0x53, 0x12, 0x92, 0x95, 0xee, 0x38, 0x80, +0x25, 0x0d, 0xa6, 0x59, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, +0x80, 0x14, 0xdd, 0x04, 0x09, 0x07, 0xa2, 0xf5, 0x7a, 0x7d, 0x52, 0x53, 0x12, 0x92, 0x95, 0xee, +0x38, 0x80, 0x25, 0x0d, 0xa6, 0x59, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x20, 0x18, 0x11, 0x94, 0x29, 0xfb, +0x26, 0x9d, 0x1c, 0x1e, 0x1e, 0x70, 0x61, 0xf1, 0x95, 0x72, 0x93, 0x71, 0x24, 0xad, 0x68, 0x93, +0x58, 0x8e, 0x32, 0xaf, 0x1b, 0xb3, 0x70, 0x03, 0xfc, 0x25, 0x2b, 0x74, 0x85, 0x90, 0x3d, 0x78, +0x6a, 0xf4, 0xb9, 0x8b, 0xa5, 0x97, 0x3b, 0xb5, 0x18, 0x91, 0xbb, 0x1e, 0xa7, 0xf9, 0x40, 0x5b, +0x91, 0xf9, 0x55, 0x99, 0xaf, 0x1e, 0x11, 0xd0, 0x5c, 0x1d, 0xa7, 0x66, 0xe3, 0xb1, 0x94, 0x07, +0x0c, 0x32, 0x39, 0xa6, 0xea, 0x1b, 0xb0, 0x79, 0xd8, 0x1d, 0x9c, 0x70, 0x44, 0xe3, 0x8a, 0xdd, +0xc4, 0xf9, 0x95, 0x1f, 0x8a, 0x38, 0x43, 0x3f, 0x01, 0x85, 0xa5, 0x47, 0xa7, 0x3d, 0x46, 0xb2, +0xbc, 0xe5, 0x22, 0x68, 0xf7, 0x7b, 0x9c, 0xd8, 0x2c, 0x3e, 0x0a, 0x21, 0xc8, 0x2d, 0x33, 0xac, +0xbf, 0xc5, 0x81, 0x99, 0x31, 0x74, 0xc1, 0x75, 0x71, 0xc5, 0xbe, 0xb1, 0xf0, 0x23, 0x45, 0xf4, +0x9d, 0x6b, 0xfc, 0x19, 0x63, 0x9d, 0xa3, 0xbc, 0x04, 0xc6, 0x18, 0x0b, 0x25, 0xbb, 0x53, 0x89, +0x0f, 0xb3, 0x80, 0x50, 0xde, 0x45, 0xee, 0x44, 0x7f, 0xab, 0x94, 0x78, 0x64, 0x98, 0xd3, 0xf6, +0x28, 0xdd, 0x87, 0xd8, 0x70, 0x65, 0x74, 0xfb, 0x0e, 0xb9, 0x13, 0xeb, 0xa7, 0x0f, 0x61, 0xa9, +0x32, 0x96, 0xcc, 0xde, 0xbb, 0xed, 0x63, 0x4c, 0x18, 0xbb, 0xa9, 0x40, 0xf7, 0xa0, 0x54, 0x6e, +0x20, 0x88, 0x71, 0x75, 0x18, 0xea, 0x7a, 0xb4, 0x34, 0x72, 0xe0, 0x23, 0x27, 0x77, 0x5c, 0xb6, +0x90, 0xea, 0x86, 0x25, 0x40, 0xab, 0xef, 0x33, 0x0f, 0xcb, 0x9f, 0x82, 0xbe, 0xa2, 0x20, 0xfb, +0xf6, 0xb5, 0x2d, 0x1a, 0xe6, 0xc2, 0x85, 0xb1, 0x74, 0x0f, 0xfb, 0xc8, 0x65, 0x02, 0xa4, 0x52, +0x01, 0x47, 0xdd, 0x49, 0x22, 0xc1, 0xbf, 0xd8, 0xeb, 0x6b, 0xac, 0x7e, 0xde, 0xec, 0x63, 0x33, +0x15, 0xb7, 0x23, 0x08, 0x8f, 0xc6, 0x0f, 0x8d, 0x41, 0x5a, 0xdd, 0x8e, 0xc5, 0xb9, 0x8f, 0xe5, +0x45, 0x3f, 0x78, 0xdb, 0xba, 0xd2, 0x1b, 0x40, 0xb1, 0xfe, 0x71, 0x4d, 0x3f, 0xe0, 0x81, 0xa2, +0xba, 0x5e, 0xb4, 0xec, 0x15, 0xe0, 0x93, 0xdd, 0x08, 0x1f, 0x7e, 0xe1, 0x55, 0x99, 0x0b, 0x21, +0xde, 0x93, 0x9e, 0x0a, 0xfb, 0xe6, 0xa3, 0x49, 0xbd, 0x36, 0x30, 0xfe, 0xe7, 0x77, 0xb2, 0xa0, +0x75, 0x97, 0xb5, 0x2d, 0x81, 0x88, 0x17, 0x65, 0x20, 0xf7, 0xda, 0x90, 0x00, 0x9f, 0xc9, 0x52, +0xcc, 0x32, 0xca, 0x35, 0x7c, 0xf5, 0x3d, 0x0f, 0xd8, 0x2b, 0xd7, 0xf5, 0x26, 0x6c, 0xc9, 0x06, +0x34, 0x96, 0x16, 0xea, 0x70, 0x59, 0x1a, 0x32, 0x79, 0x79, 0x0b, 0xb6, 0x88, 0x7f, 0x0f, 0x52, +0x48, 0x3d, 0xbf, 0x6c, 0xd8, 0xa2, 0x44, 0x2e, 0xd1, 0x4e, 0xb7, 0x72, 0x58, 0xd3, 0x89, 0x13, +0x95, 0xfe, 0x44, 0xab, 0xf8, 0xd7, 0x8b, 0x1b, 0x6e, 0x9c, 0xbc, 0x2c, 0xa0, 0x5b, 0xd5, 0x6a, +0x00, 0xaf, 0x5f, 0x37, 0xe1, 0xd5, 0xfa, 0x10, 0x0b, 0x98, 0x9c, 0x86, 0xe7, 0x26, 0x8f, 0xce, +0xf0, 0xec, 0x6e, 0x8a, 0x57, 0x0b, 0x80, 0xe3, 0x4e, 0xb2, 0xc0, 0xa0, 0x63, 0x61, 0x90, 0xba, +0x55, 0x68, 0x37, 0x74, 0x6a, 0xb6, 0x92, 0xdb, 0x9f, 0xa1, 0x86, 0x22, 0xb6, 0x65, 0x27, 0x0e, +0xec, 0xb6, 0x9f, 0x42, 0x60, 0xe4, 0x67, 0xc2, 0xb5, 0xda, 0x41, 0x0b, 0xc4, 0xd3, 0x8b, 0x61, +0x1b, 0xbc, 0xfa, 0x1f, 0x91, 0x2b, 0xd7, 0x44, 0x07, 0x5e, 0xba, 0x29, 0xac, 0xd9, 0xc5, 0xe9, +0xef, 0x53, 0x48, 0x5a, 0xeb, 0x80, 0xf1, 0x28, 0x58, 0x21, 0xcd, 0xb0, 0x06, 0x55, 0xfb, 0x27, +0x3f, 0x53, 0x90, 0x70, 0xa9, 0x04, 0x1e, 0x57, 0x27, 0xb9, 0x30, 0x82, 0x05, 0x83, 0x30, 0x82, +0x03, 0x6b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0f, 0x5d, 0x93, 0x8d, 0x30, 0x67, 0x36, 0xc8, +0x06, 0x1d, 0x1a, 0xc7, 0x54, 0x84, 0x69, 0x07, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, +0x08, 0x46, 0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x0c, 0x10, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5a, 0x20, 0x46, 0x4e, 0x4d, 0x54, +0x2d, 0x52, 0x43, 0x4d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x31, 0x30, 0x32, 0x39, 0x31, 0x35, +0x35, 0x39, 0x35, 0x36, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x46, 0x4e, +0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, +0x10, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5a, 0x20, 0x46, 0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, +0x4d, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, +0x01, 0x00, 0xba, 0x71, 0x80, 0x7a, 0x4c, 0x86, 0x6e, 0x7f, 0xc8, 0x13, 0x6d, 0xc0, 0xc6, 0x7d, +0x1c, 0x00, 0x97, 0x8f, 0x2c, 0x0c, 0x23, 0xbb, 0x10, 0x9a, 0x40, 0xa9, 0x1a, 0xb7, 0x87, 0x88, +0xf8, 0x9b, 0x56, 0x6a, 0xfb, 0xe6, 0x7b, 0x8e, 0x8b, 0x92, 0x8e, 0xa7, 0x25, 0x5d, 0x59, 0x11, +0xdb, 0x36, 0x2e, 0xb7, 0x51, 0x17, 0x1f, 0xa9, 0x08, 0x1f, 0x04, 0x17, 0x24, 0x58, 0xaa, 0x37, +0x4a, 0x18, 0xdf, 0xe5, 0x39, 0xd4, 0x57, 0xfd, 0xd7, 0xc1, 0x2c, 0x91, 0x01, 0x91, 0xe2, 0x22, +0xd4, 0x03, 0xc0, 0x58, 0xfc, 0x77, 0x47, 0xec, 0x8f, 0x3e, 0x74, 0x43, 0xba, 0xac, 0x34, 0x8d, +0x4d, 0x38, 0x76, 0x67, 0x8e, 0xb0, 0xc8, 0x6f, 0x30, 0x33, 0x58, 0x71, 0x5c, 0xb4, 0xf5, 0x6b, +0x6e, 0xd4, 0x01, 0x50, 0xb8, 0x13, 0x7e, 0x6c, 0x4a, 0xa3, 0x49, 0xd1, 0x20, 0x19, 0xee, 0xbc, +0xc0, 0x29, 0x18, 0x65, 0xa7, 0xde, 0xfe, 0xef, 0xdd, 0x0a, 0x90, 0x21, 0xe7, 0x1a, 0x67, 0x92, +0x42, 0x10, 0x98, 0x5f, 0x4f, 0x30, 0xbc, 0x3e, 0x1c, 0x45, 0xb4, 0x10, 0xd7, 0x68, 0x40, 0x14, +0xc0, 0x40, 0xfa, 0xe7, 0x77, 0x17, 0x7a, 0xe6, 0x0b, 0x8f, 0x65, 0x5b, 0x3c, 0xd9, 0x9a, 0x52, +0xdb, 0xb5, 0xbd, 0x9e, 0x46, 0xcf, 0x3d, 0xeb, 0x91, 0x05, 0x02, 0xc0, 0x96, 0xb2, 0x76, 0x4c, +0x4d, 0x10, 0x96, 0x3b, 0x92, 0xfa, 0x9c, 0x7f, 0x0f, 0x99, 0xdf, 0xbe, 0x23, 0x35, 0x45, 0x1e, +0x02, 0x5c, 0xfe, 0xb5, 0xa8, 0x9b, 0x99, 0x25, 0xda, 0x5e, 0xf3, 0x22, 0xc3, 0x39, 0xf5, 0xe4, +0x2a, 0x2e, 0xd3, 0xc6, 0x1f, 0xc4, 0x6c, 0xaa, 0xc5, 0x1c, 0x6a, 0x01, 0x05, 0x4a, 0x2f, 0xd2, +0xc5, 0xc1, 0xa8, 0x34, 0x26, 0x5d, 0x66, 0xa5, 0xd2, 0x02, 0x21, 0xf9, 0x18, 0xb7, 0x06, 0xf5, +0x4e, 0x99, 0x6f, 0xa8, 0xab, 0x4c, 0x51, 0xe8, 0xcf, 0x50, 0x18, 0xc5, 0x77, 0xc8, 0x39, 0x09, +0x2c, 0x49, 0x92, 0x32, 0x99, 0xa8, 0xbb, 0x17, 0x17, 0x79, 0xb0, 0x5a, 0xc5, 0xe6, 0xa3, 0xc4, +0x59, 0x65, 0x47, 0x35, 0x83, 0x5e, 0xa9, 0xe8, 0x35, 0x0b, 0x99, 0xbb, 0xe4, 0xcd, 0x20, 0xc6, +0x9b, 0x4a, 0x06, 0x39, 0xb5, 0x68, 0xfc, 0x22, 0xba, 0xee, 0x55, 0x8c, 0x2b, 0x4e, 0xea, 0xf3, +0xb1, 0xe3, 0xfc, 0xb6, 0x99, 0x9a, 0xd5, 0x42, 0xfa, 0x71, 0x4d, 0x08, 0xcf, 0x87, 0x1e, 0x6a, +0x71, 0x7d, 0xf9, 0xd3, 0xb4, 0xe9, 0xa5, 0x71, 0x81, 0x7b, 0xc2, 0x4e, 0x47, 0x96, 0xa5, 0xf6, +0x76, 0x85, 0xa3, 0x28, 0x8f, 0xe9, 0x80, 0x6e, 0x81, 0x53, 0xa5, 0x6d, 0x5f, 0xb8, 0x48, 0xf9, +0xc2, 0xf9, 0x36, 0xa6, 0x2e, 0x49, 0xff, 0xb8, 0x96, 0xc2, 0x8c, 0x07, 0xb3, 0x9b, 0x88, 0x58, +0xfc, 0xeb, 0x1b, 0x1c, 0xde, 0x2d, 0x70, 0xe2, 0x97, 0x92, 0x30, 0xa1, 0x89, 0xe3, 0xbc, 0x55, +0xa8, 0x27, 0xd6, 0x4b, 0xed, 0x90, 0xad, 0x8b, 0xfa, 0x63, 0x25, 0x59, 0x2d, 0xa8, 0x35, 0xdd, +0xca, 0x97, 0x33, 0xbc, 0xe5, 0xcd, 0xc7, 0x9d, 0xd1, 0xec, 0xef, 0x5e, 0x0e, 0x4a, 0x90, 0x06, +0x26, 0x63, 0xad, 0xb9, 0xd9, 0x35, 0x2d, 0x07, 0xba, 0x76, 0x65, 0x2c, 0xac, 0x57, 0x8f, 0x7d, +0xf4, 0x07, 0x94, 0xd7, 0x81, 0x02, 0x96, 0x5d, 0xa3, 0x07, 0x49, 0xd5, 0x7a, 0xd0, 0x57, 0xf9, +0x1b, 0xe7, 0x53, 0x46, 0x75, 0xaa, 0xb0, 0x79, 0x42, 0xcb, 0x68, 0x71, 0x08, 0xe9, 0x60, 0xbd, +0x39, 0x69, 0xce, 0xf4, 0xaf, 0xc3, 0x56, 0x40, 0xc7, 0xad, 0x52, 0xa2, 0x09, 0xe4, 0x6f, 0x86, +0x47, 0x8a, 0x1f, 0xeb, 0x28, 0x27, 0x5d, 0x83, 0x20, 0xaf, 0x04, 0xc9, 0x6c, 0x56, 0x9a, 0x8b, +0x46, 0xf5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x83, 0x30, 0x81, 0x80, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf7, 0x7d, 0xc5, 0xfd, 0xc4, 0xe8, 0x9a, +0x1b, 0x77, 0x64, 0xa7, 0xf5, 0x1d, 0xa0, 0xcc, 0xbf, 0x87, 0x60, 0x9a, 0x6d, 0x30, 0x3e, 0x06, +0x03, 0x55, 0x1d, 0x20, 0x04, 0x37, 0x30, 0x35, 0x30, 0x33, 0x06, 0x04, 0x55, 0x1d, 0x20, 0x00, +0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1d, +0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x65, 0x72, 0x74, 0x2e, +0x66, 0x6e, 0x6d, 0x74, 0x2e, 0x65, 0x73, 0x2f, 0x64, 0x70, 0x63, 0x73, 0x2f, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, +0x00, 0x07, 0x90, 0x4a, 0xdf, 0xf3, 0x23, 0x4e, 0xf0, 0xc3, 0x9c, 0x51, 0x65, 0x9b, 0x9c, 0x22, +0xa2, 0x8a, 0x0c, 0x85, 0xf3, 0x73, 0x29, 0x6b, 0x4d, 0xfe, 0x01, 0xe2, 0xa9, 0x0c, 0x63, 0x01, +0xbf, 0x04, 0x67, 0xa5, 0x9d, 0x98, 0x5f, 0xfd, 0x01, 0x13, 0xfa, 0xec, 0x9a, 0x62, 0xe9, 0x86, +0xfe, 0xb6, 0x62, 0xd2, 0x6e, 0x4c, 0x94, 0xfb, 0xc0, 0x75, 0x45, 0x7c, 0x65, 0x0c, 0xf8, 0xb2, +0x37, 0xcf, 0xac, 0x0f, 0xcf, 0x8d, 0x6f, 0xf9, 0x19, 0xf7, 0x8f, 0xec, 0x1e, 0xf2, 0x70, 0x9e, +0xf0, 0xca, 0xb8, 0xef, 0xb7, 0xff, 0x76, 0x37, 0x76, 0x5b, 0xf6, 0x6e, 0x88, 0xf3, 0xaf, 0x62, +0x32, 0x22, 0x93, 0x0d, 0x3a, 0x6a, 0x8e, 0x14, 0x66, 0x0c, 0x2d, 0x53, 0x74, 0x57, 0x65, 0x1e, +0xd5, 0xb2, 0xdd, 0x23, 0x81, 0x3b, 0xa5, 0x66, 0x23, 0x27, 0x67, 0x09, 0x8f, 0xe1, 0x77, 0xaa, +0x43, 0xcd, 0x65, 0x51, 0x08, 0xed, 0x51, 0x58, 0xfe, 0xe6, 0x39, 0xf9, 0xcb, 0x47, 0x84, 0xa4, +0x15, 0xf1, 0x76, 0xbb, 0xa4, 0xee, 0xa4, 0x3b, 0xc4, 0x5f, 0xef, 0xb2, 0x33, 0x96, 0x11, 0x18, +0xb7, 0xc9, 0x65, 0xbe, 0x18, 0xe1, 0xa3, 0xa4, 0xdc, 0xfa, 0x18, 0xf9, 0xd3, 0xbc, 0x13, 0x9b, +0x39, 0x7a, 0x34, 0xba, 0xd3, 0x41, 0xfb, 0xfa, 0x32, 0x8a, 0x2a, 0xb7, 0x2b, 0x86, 0x0b, 0x69, +0x83, 0x38, 0xbe, 0xcd, 0x8a, 0x2e, 0x0b, 0x70, 0xad, 0x8d, 0x26, 0x92, 0xee, 0x1e, 0xf5, 0x01, +0x2b, 0x0a, 0xd9, 0xd6, 0x97, 0x9b, 0x6e, 0xe0, 0xa8, 0x19, 0x1c, 0x3a, 0x21, 0x8b, 0x0c, 0x1e, +0x40, 0xad, 0x03, 0xe7, 0xdd, 0x66, 0x7e, 0xf5, 0xb9, 0x20, 0x0d, 0x03, 0xe8, 0x96, 0xf9, 0x82, +0x45, 0xd4, 0x39, 0xe0, 0xa0, 0x00, 0x5d, 0xd7, 0x98, 0xe6, 0x7d, 0x9e, 0x67, 0x73, 0xc3, 0x9a, +0x2a, 0xf7, 0xab, 0x8b, 0xa1, 0x3a, 0x14, 0xef, 0x34, 0xbc, 0x52, 0x0e, 0x89, 0x98, 0x9a, 0x04, +0x40, 0x84, 0x1d, 0x7e, 0x45, 0x69, 0x93, 0x57, 0xce, 0xeb, 0xce, 0xf8, 0x50, 0x7c, 0x4f, 0x1c, +0x6e, 0x04, 0x43, 0x9b, 0xf9, 0xd6, 0x3b, 0x23, 0x18, 0xe9, 0xea, 0x8e, 0xd1, 0x4d, 0x46, 0x8d, +0xf1, 0x3b, 0xe4, 0x6a, 0xca, 0xba, 0xfb, 0x23, 0xb7, 0x9b, 0xfa, 0x99, 0x01, 0x29, 0x5a, 0x58, +0x5a, 0x2d, 0xe3, 0xf9, 0xd4, 0x6d, 0x0e, 0x26, 0xad, 0xc1, 0x6e, 0x34, 0xbc, 0x32, 0xf8, 0x0c, +0x05, 0xfa, 0x65, 0xa3, 0xdb, 0x3b, 0x37, 0x83, 0x22, 0xe9, 0xd6, 0xdc, 0x72, 0x33, 0xfd, 0x5d, +0xf2, 0x20, 0xbd, 0x76, 0x3c, 0x23, 0xda, 0x28, 0xf7, 0xf9, 0x1b, 0xeb, 0x59, 0x64, 0xd5, 0xdc, +0x5f, 0x72, 0x7e, 0x20, 0xfc, 0xcd, 0x89, 0xb5, 0x90, 0x67, 0x4d, 0x62, 0x7a, 0x3f, 0x4e, 0xad, +0x1d, 0xc3, 0x39, 0xfe, 0x7a, 0xf4, 0x28, 0x16, 0xdf, 0x41, 0xf6, 0x48, 0x80, 0x05, 0xd7, 0x0f, +0x51, 0x79, 0xac, 0x10, 0xab, 0xd4, 0xec, 0x03, 0x66, 0xe6, 0x6a, 0xb0, 0xba, 0x31, 0x92, 0x42, +0x40, 0x6a, 0xbe, 0x3a, 0xd3, 0x72, 0xe1, 0x6a, 0x37, 0x55, 0xbc, 0xac, 0x1d, 0x95, 0xb7, 0x69, +0x61, 0xf2, 0x43, 0x91, 0x74, 0xe6, 0xa0, 0xd3, 0x0a, 0x24, 0x46, 0xa1, 0x08, 0xaf, 0xd6, 0xda, +0x45, 0x19, 0x96, 0xd4, 0x53, 0x1d, 0x5b, 0x84, 0x79, 0xf0, 0xc0, 0xf7, 0x47, 0xef, 0x8b, 0x8f, +0xc5, 0x06, 0xae, 0x9d, 0x4c, 0x62, 0x9d, 0xff, 0x46, 0x04, 0xf8, 0xd3, 0xc9, 0xb6, 0x10, 0x25, +0x40, 0x75, 0xfe, 0x16, 0xaa, 0xc9, 0x4a, 0x60, 0x86, 0x2f, 0xba, 0xef, 0x30, 0x77, 0xe4, 0x54, +0xe2, 0xb8, 0x84, 0x99, 0x58, 0x80, 0xaa, 0x13, 0x8b, 0x51, 0x3a, 0x4f, 0x48, 0xf6, 0x8b, 0xb6, +0xb3, 0x30, 0x82, 0x05, 0x8d, 0x30, 0x82, 0x03, 0x75, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, +0x18, 0x4a, 0xcc, 0xd6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x30, 0x56, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x43, 0x4e, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x27, 0x43, 0x68, 0x69, +0x6e, 0x61, 0x20, 0x46, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x69, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x43, +0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x32, 0x30, 0x38, 0x30, 0x38, 0x30, 0x33, 0x30, 0x37, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x39, +0x31, 0x32, 0x33, 0x31, 0x30, 0x33, 0x30, 0x37, 0x30, 0x31, 0x5a, 0x30, 0x56, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4e, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x0c, 0x27, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x46, 0x69, 0x6e, 0x61, 0x6e, +0x63, 0x69, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20, 0x52, +0x4f, 0x4f, 0x54, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, +0x82, 0x02, 0x01, 0x00, 0xd7, 0x5d, 0x6b, 0xcd, 0x10, 0x3f, 0x1f, 0x05, 0x59, 0xd5, 0x05, 0x4d, +0x37, 0xb1, 0x0e, 0xec, 0x98, 0x2b, 0x8e, 0x15, 0x1d, 0xfa, 0x93, 0x4b, 0x17, 0x82, 0x21, 0x71, +0x10, 0x52, 0xd7, 0x51, 0x64, 0x70, 0x16, 0xc2, 0x55, 0x69, 0x4d, 0x8e, 0x15, 0x6d, 0x9f, 0xbf, +0x0c, 0x1b, 0xc2, 0xe0, 0xa3, 0x67, 0xd6, 0x0c, 0xac, 0xcf, 0x22, 0xae, 0xaf, 0x77, 0x54, 0x2a, +0x4b, 0x4c, 0x8a, 0x53, 0x52, 0x7a, 0xc3, 0xee, 0x2e, 0xde, 0xb3, 0x71, 0x25, 0xc1, 0xe9, 0x5d, +0x3d, 0xee, 0xa1, 0x2f, 0xa3, 0xf7, 0x2a, 0x3c, 0xc9, 0x23, 0x1d, 0x6a, 0xab, 0x1d, 0xa1, 0xa7, +0xf1, 0xf3, 0xec, 0xa0, 0xd5, 0x44, 0xcf, 0x15, 0xcf, 0x72, 0x2f, 0x1d, 0x63, 0x97, 0xe8, 0x99, +0xf9, 0xfd, 0x93, 0xa4, 0x54, 0x80, 0x4c, 0x52, 0xd4, 0x52, 0xab, 0x2e, 0x49, 0xdf, 0x90, 0xcd, +0xb8, 0x5f, 0xbe, 0x3f, 0xde, 0xa1, 0xca, 0x4d, 0x20, 0xd4, 0x25, 0xe8, 0x84, 0x29, 0x53, 0xb7, +0xb1, 0x88, 0x1f, 0xff, 0xfa, 0xda, 0x90, 0x9f, 0x0a, 0xa9, 0x2d, 0x41, 0x3f, 0xb1, 0xf1, 0x18, +0x29, 0xee, 0x16, 0x59, 0x2c, 0x34, 0x49, 0x1a, 0xa8, 0x06, 0xd7, 0xa8, 0x88, 0xd2, 0x03, 0x72, +0x7a, 0x32, 0xe2, 0xea, 0x68, 0x4d, 0x6e, 0x2c, 0x96, 0x65, 0x7b, 0xca, 0x59, 0xfa, 0xf2, 0xe2, +0xdd, 0xee, 0x30, 0x2c, 0xfb, 0xcc, 0x46, 0xac, 0xc4, 0x63, 0xeb, 0x6f, 0x7f, 0x36, 0x2b, 0x34, +0x73, 0x12, 0x94, 0x7f, 0xdf, 0xcc, 0x26, 0x9e, 0xf1, 0x72, 0x5d, 0x50, 0x65, 0x59, 0x8f, 0x69, +0xb3, 0x87, 0x5e, 0x32, 0x6f, 0xc3, 0x18, 0x8a, 0xb5, 0x95, 0x8f, 0xb0, 0x7a, 0x37, 0xde, 0x5a, +0x45, 0x3b, 0xc7, 0x36, 0xe1, 0xef, 0x67, 0xd1, 0x39, 0xd3, 0x97, 0x5b, 0x73, 0x62, 0x19, 0x48, +0x2d, 0x87, 0x1c, 0x06, 0xfb, 0x74, 0x98, 0x20, 0x49, 0x73, 0xf0, 0x05, 0xd2, 0x1b, 0xb1, 0xa0, +0xa3, 0xb7, 0x1b, 0x70, 0xd3, 0x88, 0x69, 0xb9, 0x5a, 0xd6, 0x38, 0xf4, 0x62, 0xdc, 0x25, 0x8b, +0x78, 0xbf, 0xf8, 0xe8, 0x7e, 0xb8, 0x5c, 0xc9, 0x95, 0x4f, 0x5f, 0xa7, 0x2d, 0xb9, 0x20, 0x6b, +0xcf, 0x6b, 0xdd, 0xf5, 0x0d, 0xf4, 0x82, 0xb7, 0xf4, 0xb2, 0x66, 0x2e, 0x10, 0x28, 0xf6, 0x97, +0x5a, 0x7b, 0x96, 0x16, 0x8f, 0x01, 0x19, 0x2d, 0x6c, 0x6e, 0x7f, 0x39, 0x58, 0x06, 0x64, 0x83, +0x01, 0x83, 0x83, 0xc3, 0x4d, 0x92, 0xdd, 0x32, 0xc6, 0x87, 0xa4, 0x37, 0xe9, 0x16, 0xce, 0xaa, +0x2d, 0x68, 0xaf, 0x0a, 0x81, 0x65, 0x3a, 0x70, 0xc1, 0x9b, 0xad, 0x4d, 0x6d, 0x54, 0xca, 0x2a, +0x2d, 0x4b, 0x85, 0x1b, 0xb3, 0x80, 0xe6, 0x70, 0x45, 0x0d, 0x6b, 0x5e, 0x35, 0xf0, 0x7f, 0x3b, +0xb8, 0x9c, 0xe4, 0x04, 0x70, 0x89, 0x12, 0x25, 0x93, 0xda, 0x0a, 0x99, 0x22, 0x60, 0x6a, 0x63, +0x60, 0x4e, 0x76, 0x06, 0x98, 0x4e, 0xbd, 0x83, 0xad, 0x1d, 0x58, 0x8a, 0x25, 0x85, 0xd2, 0xc7, +0x65, 0x1e, 0x2d, 0x8e, 0xc6, 0xdf, 0xb6, 0xc6, 0xe1, 0x7f, 0x8a, 0x04, 0x21, 0x15, 0x29, 0x74, +0xf0, 0x3e, 0x9c, 0x90, 0x9d, 0x0c, 0x2e, 0xf1, 0x8a, 0x3e, 0x5a, 0xaa, 0x0c, 0x09, 0x1e, 0xc7, +0xd5, 0x3c, 0xa3, 0xed, 0x97, 0xc3, 0x1e, 0x34, 0xfa, 0x38, 0xf9, 0x08, 0x0e, 0xe3, 0xc0, 0x5d, +0x2b, 0x83, 0xd1, 0x56, 0x6a, 0xc9, 0xb6, 0xa8, 0x54, 0x53, 0x2e, 0x78, 0x32, 0x67, 0x3d, 0x82, +0x7f, 0x74, 0xd0, 0xfb, 0xe1, 0xb6, 0x05, 0x60, 0xb9, 0x70, 0xdb, 0x8e, 0x0b, 0xf9, 0x13, 0x58, +0x6f, 0x71, 0x60, 0x10, 0x52, 0x10, 0xb9, 0xc1, 0x41, 0x09, 0xef, 0x72, 0x1f, 0x67, 0x31, 0x78, +0xff, 0x96, 0x05, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1f, 0x06, +0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe3, 0xfe, 0x2d, 0xfd, 0x28, 0xd0, +0x0b, 0xb5, 0xba, 0xb6, 0xa2, 0xc4, 0xbf, 0x06, 0xaa, 0x05, 0x8c, 0x93, 0xfb, 0x2f, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe3, 0xfe, 0x2d, 0xfd, 0x28, 0xd0, +0x0b, 0xb5, 0xba, 0xb6, 0xa2, 0xc4, 0xbf, 0x06, 0xaa, 0x05, 0x8c, 0x93, 0xfb, 0x2f, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, +0x01, 0x00, 0x25, 0xc6, 0xba, 0x6b, 0xeb, 0x87, 0xcb, 0xde, 0x82, 0x39, 0x96, 0x3d, 0xf0, 0x44, +0xa7, 0x6b, 0x84, 0x73, 0x03, 0xde, 0x9d, 0x2b, 0x4f, 0xba, 0x20, 0x7f, 0xbc, 0x78, 0xb2, 0xcf, +0x97, 0xb0, 0x1b, 0x9c, 0xf3, 0xd7, 0x79, 0x2e, 0xf5, 0x48, 0xb6, 0xd2, 0xfb, 0x17, 0x88, 0xe6, +0xd3, 0x7a, 0x3f, 0xed, 0x53, 0x13, 0xd0, 0xe2, 0x2f, 0x6a, 0x79, 0xcb, 0x00, 0x23, 0x28, 0xe6, +0x1e, 0x37, 0x57, 0x35, 0x89, 0x84, 0xc2, 0x76, 0x4f, 0x34, 0x36, 0xad, 0x67, 0xc3, 0xce, 0x41, +0x06, 0x88, 0xc5, 0xf7, 0xee, 0xd8, 0x1a, 0xb8, 0xd6, 0x0b, 0x7f, 0x50, 0xff, 0x93, 0xaa, 0x17, +0x4b, 0x8c, 0xec, 0xed, 0x52, 0x60, 0xb2, 0xa4, 0x06, 0xea, 0x4e, 0xeb, 0xf4, 0x6b, 0x19, 0xfd, +0xeb, 0xf5, 0x1a, 0xe0, 0x25, 0x2a, 0x9a, 0xdc, 0xc7, 0x41, 0x36, 0xf7, 0xc8, 0x74, 0x05, 0x84, +0x39, 0x95, 0x39, 0xd6, 0x0b, 0x3b, 0xa4, 0x27, 0xfa, 0x08, 0xd8, 0x5c, 0x1e, 0xf8, 0x04, 0x60, +0x52, 0x11, 0x28, 0x28, 0x03, 0xff, 0xef, 0x53, 0x66, 0x00, 0xa5, 0x4a, 0x34, 0x16, 0x66, 0x7c, +0xfd, 0x09, 0xa4, 0xae, 0x9e, 0x67, 0x1a, 0x6f, 0x41, 0x0b, 0x6b, 0x06, 0x13, 0x9b, 0x8f, 0x86, +0x71, 0x05, 0xb4, 0x2f, 0x8d, 0x89, 0x66, 0x33, 0x29, 0x76, 0x54, 0x9a, 0x11, 0xf8, 0x27, 0xfa, +0xb2, 0x3f, 0x91, 0xe0, 0xce, 0x0d, 0x1b, 0xf3, 0x30, 0x1a, 0xad, 0xbf, 0x22, 0x5d, 0x1b, 0xd3, +0xbf, 0x25, 0x05, 0x4d, 0xe1, 0x92, 0x1a, 0x7f, 0x99, 0x9f, 0x3c, 0x44, 0x93, 0xca, 0xd4, 0x40, +0x49, 0x6c, 0x80, 0x87, 0xd7, 0x04, 0x3a, 0xc3, 0x32, 0x52, 0x35, 0x0e, 0x56, 0xf8, 0xa5, 0xdd, +0x7d, 0xc4, 0x8b, 0x0d, 0x11, 0x1f, 0x53, 0xcb, 0x1e, 0xb2, 0x17, 0xb6, 0x68, 0x77, 0x5a, 0xe0, +0xd4, 0xcb, 0xc8, 0x07, 0xae, 0xf5, 0x3a, 0x2e, 0x8e, 0x37, 0xb7, 0xd0, 0x01, 0x4b, 0x43, 0x29, +0x77, 0x8c, 0x39, 0x97, 0x8f, 0x82, 0x5a, 0xf8, 0x51, 0xe5, 0x89, 0xa0, 0x18, 0xe7, 0x68, 0x7f, +0x5d, 0x0a, 0x2e, 0xfb, 0xa3, 0x47, 0x0e, 0x3d, 0xa6, 0x23, 0x7a, 0xc6, 0x01, 0xc7, 0x8f, 0xc8, +0x5e, 0xbf, 0x6d, 0x80, 0x56, 0xbe, 0x8a, 0x24, 0xba, 0x33, 0xea, 0x9f, 0xe1, 0x32, 0x11, 0x9e, +0xf1, 0xd2, 0x4f, 0x80, 0xf6, 0x1b, 0x40, 0xaf, 0x38, 0x9e, 0x11, 0x50, 0x79, 0x73, 0x12, 0x12, +0xcd, 0xe6, 0x6c, 0x9d, 0x2c, 0x88, 0x72, 0x3c, 0x30, 0x81, 0x06, 0x91, 0x22, 0xea, 0x59, 0xad, +0xda, 0x19, 0x2e, 0x22, 0xc2, 0x8d, 0xb9, 0x8c, 0x87, 0xe0, 0x66, 0xbc, 0x73, 0x23, 0x5f, 0x21, +0x64, 0x63, 0x80, 0x48, 0xf5, 0xa0, 0x3c, 0x18, 0x3d, 0x94, 0xc8, 0x48, 0x41, 0x1d, 0x40, 0xba, +0x5e, 0xfe, 0xfe, 0x56, 0x39, 0xa1, 0xc8, 0xcf, 0x5e, 0x9e, 0x19, 0x64, 0x46, 0x10, 0xda, 0x17, +0x91, 0xb7, 0x05, 0x80, 0xac, 0x8b, 0x99, 0x92, 0x7d, 0xe7, 0xa2, 0xd8, 0x07, 0x0b, 0x36, 0x27, +0xe7, 0x48, 0x79, 0x60, 0x8a, 0xc3, 0xd7, 0x13, 0x5c, 0xf8, 0x72, 0x40, 0xdf, 0x4a, 0xcb, 0xcf, +0x99, 0x00, 0x0a, 0x00, 0x0b, 0x11, 0x95, 0xda, 0x56, 0x45, 0x03, 0x88, 0x0a, 0x9f, 0x67, 0xd0, +0xd5, 0x79, 0xb1, 0xa8, 0x8d, 0x40, 0x6d, 0x0d, 0xc2, 0x7a, 0x40, 0xfa, 0xf3, 0x5f, 0x64, 0x47, +0x92, 0xcb, 0x53, 0xb9, 0xbb, 0x59, 0xce, 0x4f, 0xfd, 0xd0, 0x15, 0x53, 0x01, 0xd8, 0xdf, 0xeb, +0xd9, 0xe6, 0x76, 0xef, 0xd0, 0x23, 0xbb, 0x3b, 0xa9, 0x79, 0xb3, 0xd5, 0x02, 0x29, 0xcd, 0x89, +0xa3, 0x96, 0x0f, 0x4a, 0x35, 0xe7, 0x4e, 0x42, 0xc0, 0x75, 0xcd, 0x07, 0xcf, 0xe6, 0x2c, 0xeb, +0x7b, 0x2e, 0x30, 0x82, 0x04, 0x15, 0x30, 0x82, 0x02, 0xfd, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x06, 0x49, 0x41, 0x2c, 0xe4, 0x00, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xa7, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, +0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x0c, 0x0c, 0x4e, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x4b, 0x66, 0x74, 0x2e, +0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x2e, 0x54, 0x61, 0x6e, 0xc3, 0xba, +0x73, 0xc3, 0xad, 0x74, 0x76, 0xc3, 0xa1, 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, 0xc3, 0xb3, 0x6b, +0x20, 0x28, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, +0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x2c, 0x4e, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x41, 0x72, 0x61, 0x6e, +0x79, 0x20, 0x28, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x47, 0x6f, 0x6c, 0x64, 0x29, 0x20, 0x46, +0xc5, 0x91, 0x74, 0x61, 0x6e, 0xc3, 0xba, 0x73, 0xc3, 0xad, 0x74, 0x76, 0xc3, 0xa1, 0x6e, 0x79, +0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x31, 0x32, 0x31, 0x31, 0x31, 0x35, 0x30, 0x38, 0x32, 0x31, +0x5a, 0x17, 0x0d, 0x32, 0x38, 0x31, 0x32, 0x30, 0x36, 0x31, 0x35, 0x30, 0x38, 0x32, 0x31, 0x5a, +0x30, 0x81, 0xa7, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, +0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, +0x65, 0x73, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x4e, 0x65, +0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x0c, 0x2e, 0x54, 0x61, 0x6e, 0xc3, 0xba, 0x73, 0xc3, 0xad, 0x74, 0x76, 0xc3, +0xa1, 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, 0xc3, 0xb3, 0x6b, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, +0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x4e, 0x65, +0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x41, 0x72, 0x61, 0x6e, 0x79, 0x20, 0x28, 0x43, 0x6c, 0x61, +0x73, 0x73, 0x20, 0x47, 0x6f, 0x6c, 0x64, 0x29, 0x20, 0x46, 0xc5, 0x91, 0x74, 0x61, 0x6e, 0xc3, +0xba, 0x73, 0xc3, 0xad, 0x74, 0x76, 0xc3, 0xa1, 0x6e, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, +0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x24, 0x5e, 0x73, 0xbe, +0x4b, 0x6d, 0x14, 0xc3, 0xa1, 0xf4, 0xe3, 0x97, 0x90, 0x6e, 0xd2, 0x30, 0x45, 0x1e, 0x3c, 0xee, +0x67, 0xd9, 0x64, 0xe0, 0x1a, 0x8a, 0x7f, 0xca, 0x30, 0xca, 0x83, 0xe3, 0x20, 0xc1, 0xe3, 0xf4, +0x3a, 0xd3, 0x94, 0x5f, 0x1a, 0x7c, 0x5b, 0x6d, 0xbf, 0x30, 0x4f, 0x84, 0x27, 0xf6, 0x9f, 0x1f, +0x49, 0xbc, 0xc6, 0x99, 0x0a, 0x90, 0xf2, 0x0f, 0xf5, 0x7f, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8b, +0x7a, 0xa5, 0x70, 0xfc, 0x7a, 0x58, 0xcd, 0x8e, 0x9b, 0xed, 0xc3, 0x46, 0x6c, 0x84, 0x70, 0x5d, +0xda, 0xf3, 0x01, 0x90, 0x23, 0xfc, 0x4e, 0x30, 0xa9, 0x7e, 0xe1, 0x27, 0x63, 0xe7, 0xed, 0x64, +0x3c, 0xa0, 0xb8, 0xc9, 0x33, 0x63, 0xfe, 0x16, 0x90, 0xff, 0xb0, 0xb8, 0xfd, 0xd7, 0xa8, 0xc0, +0xc0, 0x94, 0x43, 0x0b, 0xb6, 0xd5, 0x59, 0xa6, 0x9e, 0x56, 0xd0, 0x24, 0x1f, 0x70, 0x79, 0xaf, +0xdb, 0x39, 0x54, 0x0d, 0x65, 0x75, 0xd9, 0x15, 0x41, 0x94, 0x01, 0xaf, 0x5e, 0xec, 0xf6, 0x8d, +0xf1, 0xff, 0xad, 0x64, 0xfe, 0x20, 0x9a, 0xd7, 0x5c, 0xeb, 0xfe, 0xa6, 0x1f, 0x08, 0x64, 0xa3, +0x8b, 0x76, 0x55, 0xad, 0x1e, 0x3b, 0x28, 0x60, 0x2e, 0x87, 0x25, 0xe8, 0xaa, 0xaf, 0x1f, 0xc6, +0x64, 0x46, 0x20, 0xb7, 0x70, 0x7f, 0x3c, 0xde, 0x48, 0xdb, 0x96, 0x53, 0xb7, 0x39, 0x77, 0xe4, +0x1a, 0xe2, 0xc7, 0x16, 0x84, 0x76, 0x97, 0x5b, 0x2f, 0xbb, 0x19, 0x15, 0x85, 0xf8, 0x69, 0x85, +0xf5, 0x99, 0xa7, 0xa9, 0xf2, 0x34, 0xa7, 0xa9, 0xb6, 0xa6, 0x03, 0xfc, 0x6f, 0x86, 0x3d, 0x54, +0x7c, 0x76, 0x04, 0x9b, 0x6b, 0xf9, 0x40, 0x5d, 0x00, 0x34, 0xc7, 0x2e, 0x99, 0x75, 0x9d, 0xe5, +0x88, 0x03, 0xaa, 0x4d, 0xf8, 0x03, 0xd2, 0x42, 0x76, 0xc0, 0x1b, 0x02, 0x03, 0x00, 0xa8, 0x8b, +0xa3, 0x45, 0x30, 0x43, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, +0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x04, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0xcc, 0xfa, 0x67, 0x93, 0xf0, 0xb6, 0xb8, 0xd0, 0xa5, 0xc0, 0x1e, 0xf3, 0x53, +0xfd, 0x8c, 0x53, 0xdf, 0x83, 0xd7, 0x96, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xab, 0x7f, 0xee, 0x1c, 0x16, +0xa9, 0x9c, 0x3c, 0x51, 0x00, 0xa0, 0xc0, 0x11, 0x08, 0x05, 0xa7, 0x99, 0xe6, 0x6f, 0x01, 0x88, +0x54, 0x61, 0x6e, 0xf1, 0xb9, 0x18, 0xad, 0x4a, 0xad, 0xfe, 0x81, 0x40, 0x23, 0x94, 0x2f, 0xfb, +0x75, 0x7c, 0x2f, 0x28, 0x4b, 0x62, 0x24, 0x81, 0x82, 0x0b, 0xf5, 0x61, 0xf1, 0x1c, 0x6e, 0xb8, +0x61, 0x38, 0xeb, 0x81, 0xfa, 0x62, 0xa1, 0x3b, 0x5a, 0x62, 0xd3, 0x94, 0x65, 0xc4, 0xe1, 0xe6, +0x6d, 0x82, 0xf8, 0x2f, 0x25, 0x70, 0xb2, 0x21, 0x26, 0xc1, 0x72, 0x51, 0x1f, 0x8c, 0x2c, 0xc3, +0x84, 0x90, 0xc3, 0x5a, 0x8f, 0xba, 0xcf, 0xf4, 0xa7, 0x65, 0xa5, 0xeb, 0x98, 0xd1, 0xfb, 0x05, +0xb2, 0x46, 0x75, 0x15, 0x23, 0x6a, 0x6f, 0x85, 0x63, 0x30, 0x80, 0xf0, 0xd5, 0x9e, 0x1f, 0x29, +0x1c, 0xc2, 0x6c, 0xb0, 0x50, 0x59, 0x5d, 0x90, 0x5b, 0x3b, 0xa8, 0x0d, 0x30, 0xcf, 0xbf, 0x7d, +0x7f, 0xce, 0xf1, 0x9d, 0x83, 0xbd, 0xc9, 0x46, 0x6e, 0x20, 0xa6, 0xf9, 0x61, 0x51, 0xba, 0x21, +0x2f, 0x7b, 0xbe, 0xa5, 0x15, 0x63, 0xa1, 0xd4, 0x95, 0x87, 0xf1, 0x9e, 0xb9, 0xf3, 0x89, 0xf3, +0x3d, 0x85, 0xb8, 0xb8, 0xdb, 0xbe, 0xb5, 0xb9, 0x29, 0xf9, 0xda, 0x37, 0x05, 0x00, 0x49, 0x94, +0x03, 0x84, 0x44, 0xe7, 0xbf, 0x43, 0x31, 0xcf, 0x75, 0x8b, 0x25, 0xd1, 0xf4, 0xa6, 0x64, 0xf5, +0x92, 0xf6, 0xab, 0x05, 0xeb, 0x3d, 0xe9, 0xa5, 0x0b, 0x36, 0x62, 0xda, 0xcc, 0x06, 0x5f, 0x36, +0x8b, 0xb6, 0x5e, 0x31, 0xb8, 0x2a, 0xfb, 0x5e, 0xf6, 0x71, 0xdf, 0x44, 0x26, 0x9e, 0xc4, 0xe6, +0x0d, 0x91, 0xb4, 0x2e, 0x75, 0x95, 0x80, 0x51, 0x6a, 0x4b, 0x30, 0xa6, 0xb0, 0x62, 0xa1, 0x93, +0xf1, 0x9b, 0xd8, 0xce, 0xc4, 0x63, 0x75, 0x3f, 0x59, 0x47, 0xb1, 0x30, 0x82, 0x03, 0x4a, 0x30, +0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, +0x27, 0xba, 0x89, 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, +0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, +0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, +0x30, 0x39, 0x33, 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, +0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, 0x3f, 0x31, 0x24, 0x30, 0x22, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, +0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, +0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x44, 0x53, 0x54, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, +0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xdf, 0xaf, 0xe9, 0x97, +0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, +0x30, 0xca, 0x5b, 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, 0x33, +0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, 0xaf, 0x3e, 0x48, 0xcb, 0x65, +0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, +0x12, 0x7b, 0xb5, 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, 0x32, +0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, 0x38, 0xb9, 0x79, 0x0a, 0x31, +0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, +0x61, 0x81, 0xec, 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, 0x0c, +0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, 0xc6, 0x2a, 0x8a, 0xab, 0x2e, +0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, +0x30, 0x89, 0xff, 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, 0x92, +0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, 0xec, 0x16, 0x72, 0xd5, 0x26, +0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, +0x9b, 0x8d, 0x1d, 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, 0xda, +0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, 0x69, 0xe4, 0x10, 0x9b, 0x19, +0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, +0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0xc4, 0xa7, 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, 0xc4, +0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, +0xa9, 0x1e, 0xee, 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, 0x95, +0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, 0x8a, 0x4b, 0xa0, 0x74, 0x1f, +0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, +0x44, 0xe4, 0x91, 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, 0x4e, +0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, 0x02, 0xf1, 0xd1, 0x02, 0x8b, +0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, +0x0c, 0xf1, 0xb1, 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, 0xfa, +0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, 0x47, 0xcb, 0x2b, 0xcc, 0x99, +0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, +0x44, 0xbb, 0x53, 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, 0xfe, +0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, 0x24, 0x31, 0x85, 0xa2, 0xa8, +0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, +0x60, 0x9b, 0x16, 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, 0x8d, +0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, 0x39, 0xbf, 0x15, 0x65, 0x1c, +0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, +0x29, 0xb6, 0x0a, 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10, 0x30, 0x82, 0x03, 0xe6, 0x30, 0x82, 0x02, +0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x57, 0xcb, 0x33, 0x6f, 0xc2, 0x5c, 0x16, 0xe6, +0x47, 0x16, 0x17, 0xe3, 0x90, 0x31, 0x68, 0xe0, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x18, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x53, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, +0x6e, 0x73, 0x20, 0x4c, 0x2e, 0x4c, 0x2e, 0x43, 0x2e, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x27, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x53, 0x6f, 0x6c, 0x75, +0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, +0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, +0x36, 0x31, 0x32, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, +0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x62, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x18, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x53, 0x6f, 0x6c, +0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x4c, 0x2e, 0x4c, 0x2e, 0x43, 0x2e, 0x31, 0x30, 0x30, +0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, +0x53, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, +0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, +0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, +0xe4, 0xbc, 0x7e, 0x92, 0x30, 0x6d, 0xc6, 0xd8, 0x8e, 0x2b, 0x0b, 0xbc, 0x46, 0xce, 0xe0, 0x27, +0x96, 0xde, 0xde, 0xf9, 0xfa, 0x12, 0xd3, 0x3c, 0x33, 0x73, 0xb3, 0x04, 0x2f, 0xbc, 0x71, 0x8c, +0xe5, 0x9f, 0xb6, 0x22, 0x60, 0x3e, 0x5f, 0x5d, 0xce, 0x09, 0xff, 0x82, 0x0c, 0x1b, 0x9a, 0x51, +0x50, 0x1a, 0x26, 0x89, 0xdd, 0xd5, 0x61, 0x5d, 0x19, 0xdc, 0x12, 0x0f, 0x2d, 0x0a, 0xa2, 0x43, +0x5d, 0x17, 0xd0, 0x34, 0x92, 0x20, 0xea, 0x73, 0xcf, 0x38, 0x2c, 0x06, 0x26, 0x09, 0x7a, 0x72, +0xf7, 0xfa, 0x50, 0x32, 0xf8, 0xc2, 0x93, 0xd3, 0x69, 0xa2, 0x23, 0xce, 0x41, 0xb1, 0xcc, 0xe4, +0xd5, 0x1f, 0x36, 0xd1, 0x8a, 0x3a, 0xf8, 0x8c, 0x63, 0xe2, 0x14, 0x59, 0x69, 0xed, 0x0d, 0xd3, +0x7f, 0x6b, 0xe8, 0xb8, 0x03, 0xe5, 0x4f, 0x6a, 0xe5, 0x98, 0x63, 0x69, 0x48, 0x05, 0xbe, 0x2e, +0xff, 0x33, 0xb6, 0xe9, 0x97, 0x59, 0x69, 0xf8, 0x67, 0x19, 0xae, 0x93, 0x61, 0x96, 0x44, 0x15, +0xd3, 0x72, 0xb0, 0x3f, 0xbc, 0x6a, 0x7d, 0xec, 0x48, 0x7f, 0x8d, 0xc3, 0xab, 0xaa, 0x71, 0x2b, +0x53, 0x69, 0x41, 0x53, 0x34, 0xb5, 0xb0, 0xb9, 0xc5, 0x06, 0x0a, 0xc4, 0xb0, 0x45, 0xf5, 0x41, +0x5d, 0x6e, 0x89, 0x45, 0x7b, 0x3d, 0x3b, 0x26, 0x8c, 0x74, 0xc2, 0xe5, 0xd2, 0xd1, 0x7d, 0xb2, +0x11, 0xd4, 0xfb, 0x58, 0x32, 0x22, 0x9a, 0x80, 0xc9, 0xdc, 0xfd, 0x0c, 0xe9, 0x7f, 0x5e, 0x03, +0x97, 0xce, 0x3b, 0x00, 0x14, 0x87, 0x27, 0x70, 0x38, 0xa9, 0x8e, 0x6e, 0xb3, 0x27, 0x76, 0x98, +0x51, 0xe0, 0x05, 0xe3, 0x21, 0xab, 0x1a, 0xd5, 0x85, 0x22, 0x3c, 0x29, 0xb5, 0x9a, 0x16, 0xc5, +0x80, 0xa8, 0xf4, 0xbb, 0x6b, 0x30, 0x8f, 0x2f, 0x46, 0x02, 0xa2, 0xb1, 0x0c, 0x22, 0xe0, 0xd3, +0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x97, 0x30, 0x81, 0x94, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x21, 0x30, 0xc9, 0xfb, 0x00, 0xd7, 0x4e, 0x98, 0xda, 0x87, +0xaa, 0x2a, 0xd0, 0xa7, 0x2e, 0xb1, 0x40, 0x31, 0xa7, 0x4c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, +0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x52, 0x06, 0x03, 0x55, +0x1d, 0x1f, 0x04, 0x4b, 0x30, 0x49, 0x30, 0x47, 0xa0, 0x45, 0xa0, 0x43, 0x86, 0x41, 0x68, 0x74, +0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6e, 0x65, 0x74, 0x73, 0x6f, 0x6c, 0x73, +0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x53, 0x6f, +0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, +0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x63, 0x72, 0x6c, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, +0x01, 0x01, 0x00, 0xbb, 0xae, 0x4b, 0xe7, 0xb7, 0x57, 0xeb, 0x7f, 0xaa, 0x2d, 0xb7, 0x73, 0x47, +0x85, 0x6a, 0xc1, 0xe4, 0xa5, 0x1d, 0xe4, 0xe7, 0x3c, 0xe9, 0xf4, 0x59, 0x65, 0x77, 0xb5, 0x7a, +0x5b, 0x5a, 0x8d, 0x25, 0x36, 0xe0, 0x7a, 0x97, 0x2e, 0x38, 0xc0, 0x57, 0x60, 0x83, 0x98, 0x06, +0x83, 0x9f, 0xb9, 0x76, 0x7a, 0x6e, 0x50, 0xe0, 0xba, 0x88, 0x2c, 0xfc, 0x45, 0xcc, 0x18, 0xb0, +0x99, 0x95, 0x51, 0x0e, 0xec, 0x1d, 0xb8, 0x88, 0xff, 0x87, 0x50, 0x1c, 0x82, 0xc2, 0xe3, 0xe0, +0x32, 0x80, 0xbf, 0xa0, 0x0b, 0x47, 0xc8, 0xc3, 0x31, 0xef, 0x99, 0x67, 0x32, 0x80, 0x4f, 0x17, +0x21, 0x79, 0x0c, 0x69, 0x5c, 0xde, 0x5e, 0x34, 0xae, 0x02, 0xb5, 0x26, 0xea, 0x50, 0xdf, 0x7f, +0x18, 0x65, 0x2c, 0xc9, 0xf2, 0x63, 0xe1, 0xa9, 0x07, 0xfe, 0x7c, 0x71, 0x1f, 0x6b, 0x33, 0x24, +0x6a, 0x1e, 0x05, 0xf7, 0x05, 0x68, 0xc0, 0x6a, 0x12, 0xcb, 0x2e, 0x5e, 0x61, 0xcb, 0xae, 0x28, +0xd3, 0x7e, 0xc2, 0xb4, 0x66, 0x91, 0x26, 0x5f, 0x3c, 0x2e, 0x24, 0x5f, 0xcb, 0x58, 0x0f, 0xeb, +0x28, 0xec, 0xaf, 0x11, 0x96, 0xf3, 0xdc, 0x7b, 0x6f, 0xc0, 0xa7, 0x88, 0xf2, 0x53, 0x77, 0xb3, +0x60, 0x5e, 0xae, 0xae, 0x28, 0xda, 0x35, 0x2c, 0x6f, 0x34, 0x45, 0xd3, 0x26, 0xe1, 0xde, 0xec, +0x5b, 0x4f, 0x27, 0x6b, 0x16, 0x7c, 0xbd, 0x44, 0x04, 0x18, 0x82, 0xb3, 0x89, 0x79, 0x17, 0x10, +0x71, 0x3d, 0x7a, 0xa2, 0x16, 0x4e, 0xf5, 0x01, 0xcd, 0xa4, 0x6c, 0x65, 0x68, 0xa1, 0x49, 0x76, +0x5c, 0x43, 0xc9, 0xd8, 0xbc, 0x36, 0x67, 0x6c, 0xa5, 0x94, 0xb5, 0xd4, 0xcc, 0xb9, 0xbd, 0x6a, +0x35, 0x56, 0x21, 0xde, 0xd8, 0xc3, 0xeb, 0xfb, 0xcb, 0xa4, 0x60, 0x4c, 0xb0, 0x55, 0xa0, 0xa0, +0x7b, 0x57, 0xb2, 0x30, 0x82, 0x05, 0x60, 0x30, 0x82, 0x03, 0x48, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x14, 0x78, 0x58, 0x5f, 0x2e, 0xad, 0x2c, 0x19, 0x4b, 0xe3, 0x37, 0x07, 0x35, 0x34, 0x13, +0x28, 0xb5, 0x96, 0xd4, 0x65, 0x93, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, +0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, +0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, +0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x47, 0x33, 0x30, +0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x31, 0x31, 0x32, 0x31, 0x37, 0x32, 0x37, 0x34, 0x34, 0x5a, +0x17, 0x0d, 0x34, 0x32, 0x30, 0x31, 0x31, 0x32, 0x31, 0x37, 0x32, 0x37, 0x34, 0x34, 0x5a, 0x30, +0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, +0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, +0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x47, 0x33, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, +0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa0, 0xbe, 0x50, 0x10, 0x8e, 0xe9, +0xf2, 0x6c, 0x40, 0xb4, 0x04, 0x9c, 0x85, 0xb9, 0x31, 0xca, 0xdc, 0x2d, 0xe4, 0x11, 0xa9, 0x04, +0x3c, 0x1b, 0x55, 0xc1, 0xe7, 0x58, 0x30, 0x1d, 0x24, 0xb4, 0xc3, 0xef, 0x85, 0xde, 0x8c, 0x2c, +0xe1, 0xc1, 0x3d, 0xdf, 0x82, 0xe6, 0x4f, 0xad, 0x47, 0x87, 0x6c, 0xec, 0x5b, 0x49, 0xc1, 0x4a, +0xd5, 0xbb, 0x8f, 0xec, 0x87, 0xac, 0x7f, 0x82, 0x9a, 0x86, 0xec, 0x3d, 0x03, 0x99, 0x52, 0x01, +0xd2, 0x35, 0x9e, 0xac, 0xda, 0xf0, 0x53, 0xc9, 0x66, 0x3c, 0xd4, 0xac, 0x02, 0x01, 0xda, 0x24, +0xd3, 0x3b, 0xa8, 0x02, 0x46, 0xaf, 0xa4, 0x1c, 0xe3, 0xf8, 0x73, 0x58, 0x76, 0xb7, 0xf6, 0x0e, +0x90, 0x0d, 0xb5, 0xf0, 0xcf, 0xcc, 0xfa, 0xf9, 0xc6, 0x4c, 0xe5, 0xc3, 0x86, 0x30, 0x0a, 0x8d, +0x17, 0x7e, 0x35, 0xeb, 0xc5, 0xdf, 0xbb, 0x0e, 0x9c, 0xc0, 0x8d, 0x87, 0xe3, 0x88, 0x38, 0x85, +0x67, 0xfa, 0x3e, 0xc7, 0xab, 0xe0, 0x13, 0x9c, 0x05, 0x18, 0x98, 0xcf, 0x93, 0xf5, 0xb1, 0x92, +0xb4, 0xfc, 0x23, 0xd3, 0xcf, 0xd5, 0xc4, 0x27, 0x49, 0xe0, 0x9e, 0x3c, 0x9b, 0x08, 0xa3, 0x8b, +0x5d, 0x2a, 0x21, 0xe0, 0xfc, 0x39, 0xaa, 0x53, 0xda, 0x7d, 0x7e, 0xcf, 0x1a, 0x09, 0x53, 0xbc, +0x5d, 0x05, 0x04, 0xcf, 0xa1, 0x4a, 0x8f, 0x8b, 0x76, 0x82, 0x0d, 0xa1, 0xf8, 0xd2, 0xc7, 0x14, +0x77, 0x5b, 0x90, 0x36, 0x07, 0x81, 0x9b, 0x3e, 0x06, 0xfa, 0x52, 0x5e, 0x63, 0xc5, 0xa6, 0x00, +0xfe, 0xa5, 0xe9, 0x52, 0x1b, 0x52, 0xb5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xbd, 0xb0, 0x60, +0x16, 0x6e, 0xa6, 0xdd, 0x25, 0xc2, 0x03, 0x66, 0xdd, 0xf3, 0x04, 0xd1, 0x40, 0xe2, 0x4e, 0x8b, +0x86, 0xf4, 0x6f, 0xe5, 0x83, 0xa0, 0x27, 0x84, 0x5e, 0x04, 0xc1, 0xf5, 0x90, 0xbd, 0x30, 0x3d, +0xc4, 0xef, 0xa8, 0x69, 0xbc, 0x38, 0x9b, 0xa4, 0xa4, 0x96, 0xd1, 0x62, 0xda, 0x69, 0xc0, 0x01, +0x96, 0xae, 0xcb, 0xc4, 0x51, 0x34, 0xea, 0x0c, 0xaa, 0xff, 0x21, 0x8e, 0x59, 0x8f, 0x4a, 0x5c, +0xe4, 0x61, 0x9a, 0xa7, 0xd2, 0xe9, 0x2a, 0x78, 0x8d, 0x51, 0x3d, 0x3a, 0x15, 0xee, 0xa2, 0x59, +0x8e, 0xa9, 0x5c, 0xde, 0xc5, 0xf9, 0x90, 0x22, 0xe5, 0x88, 0x45, 0x71, 0xdd, 0x91, 0x99, 0x6c, +0x7a, 0x9f, 0x3d, 0x3d, 0x98, 0x7c, 0x5e, 0xf6, 0xbe, 0x16, 0x68, 0xa0, 0x5e, 0xae, 0x0b, 0x23, +0xfc, 0x5a, 0x0f, 0xaa, 0x22, 0x76, 0x2d, 0xc9, 0xa1, 0x10, 0x1d, 0xe4, 0xd3, 0x44, 0x23, 0x90, +0x88, 0x9f, 0xc6, 0x2a, 0xe6, 0xd7, 0xf5, 0x9a, 0xb3, 0x58, 0x1e, 0x2f, 0x30, 0x89, 0x08, 0x1b, +0x54, 0xa2, 0xb5, 0x98, 0x23, 0xec, 0x08, 0x77, 0x1c, 0x95, 0x5d, 0x61, 0xd1, 0xcb, 0x89, 0x9c, +0x5f, 0xa2, 0x4a, 0x91, 0x9a, 0xef, 0x21, 0xaa, 0x49, 0x16, 0x08, 0xa8, 0xbd, 0x61, 0x28, 0x31, +0xc9, 0x74, 0xad, 0x85, 0xf6, 0xd9, 0xc5, 0xb1, 0x8b, 0xd1, 0xe5, 0x10, 0x32, 0x4d, 0x5f, 0x8b, +0x20, 0x3a, 0x3c, 0x49, 0x1f, 0x33, 0x85, 0x59, 0x0d, 0xdb, 0xcb, 0x09, 0x75, 0x43, 0x69, 0x73, +0xfb, 0x6b, 0x71, 0x7d, 0xf0, 0xdf, 0xc4, 0x4c, 0x7d, 0xc6, 0xa3, 0x2e, 0xc8, 0x95, 0x79, 0xcb, +0x73, 0xa2, 0x8e, 0x4e, 0x4d, 0x24, 0xfb, 0x5e, 0xe4, 0x04, 0xbe, 0x72, 0x1b, 0xa6, 0x27, 0x2d, +0x49, 0x5a, 0x99, 0x7a, 0xd7, 0x5c, 0x09, 0x20, 0xb7, 0x7f, 0x94, 0xb9, 0x4f, 0xf1, 0x0d, 0x1c, +0x5e, 0x88, 0x42, 0x1b, 0x11, 0xb7, 0xe7, 0x91, 0xdb, 0x9e, 0x6c, 0xf4, 0x6a, 0xdf, 0x8c, 0x06, +0x98, 0x03, 0xad, 0xcc, 0x28, 0xef, 0xa5, 0x47, 0xf3, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa3, +0x97, 0xd6, 0xf3, 0x5e, 0xa2, 0x10, 0xe1, 0xab, 0x45, 0x9f, 0x3c, 0x17, 0x64, 0x3c, 0xee, 0x01, +0x70, 0x9c, 0xcc, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, +0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x18, 0xfa, 0x5b, 0x75, 0xfc, 0x3e, 0x7a, 0xc7, 0x5f, +0x77, 0xc7, 0xca, 0xdf, 0xcf, 0x5f, 0xc3, 0x12, 0xc4, 0x40, 0x5d, 0xd4, 0x32, 0xaa, 0xb8, 0x6a, +0xd7, 0xd5, 0x15, 0x15, 0x46, 0x98, 0x23, 0xa5, 0xe6, 0x90, 0x5b, 0x18, 0x99, 0x4c, 0xe3, 0xad, +0x42, 0xa3, 0x82, 0x31, 0x36, 0x88, 0xcd, 0xe9, 0xfb, 0xc4, 0x04, 0x96, 0x48, 0x8b, 0x01, 0xc7, +0x8d, 0x01, 0xcf, 0x5b, 0x33, 0x06, 0x96, 0x46, 0x66, 0x74, 0x1d, 0x4f, 0xed, 0xc1, 0xb6, 0xb9, +0xb4, 0x0d, 0x61, 0xcc, 0x63, 0x7e, 0xd7, 0x2e, 0x77, 0x8c, 0x96, 0x1c, 0x2a, 0x23, 0x68, 0x6b, +0x85, 0x57, 0x76, 0x70, 0x33, 0x13, 0xfe, 0xe1, 0x4f, 0xa6, 0x23, 0x77, 0x18, 0xfa, 0x1a, 0x8c, +0xe8, 0xbd, 0x65, 0xc9, 0xcf, 0x3f, 0xf4, 0xc9, 0x17, 0xdc, 0xeb, 0xc7, 0xbc, 0xc0, 0x04, 0x2e, +0x2d, 0x46, 0x2f, 0x69, 0x66, 0xc3, 0x1b, 0x8f, 0xfe, 0xec, 0x3e, 0xd3, 0xca, 0x94, 0xbf, 0x76, +0x0a, 0x25, 0x0d, 0xa9, 0x7b, 0x02, 0x1c, 0xa9, 0xd0, 0x3b, 0x5f, 0x0b, 0xc0, 0x81, 0x3a, 0x3d, +0x64, 0xe1, 0xbf, 0xa7, 0x2d, 0x4e, 0xbd, 0x4d, 0xc4, 0xd8, 0x29, 0xc6, 0x22, 0x18, 0xd0, 0xc5, +0xac, 0x72, 0x02, 0x82, 0x3f, 0xaa, 0x3a, 0xa2, 0x3a, 0x22, 0x97, 0x31, 0xdd, 0x08, 0x63, 0xc3, +0x75, 0x14, 0xb9, 0x60, 0x28, 0x2d, 0x5b, 0x68, 0xe0, 0x16, 0xa9, 0x66, 0x82, 0x23, 0x51, 0xf5, +0xeb, 0x53, 0xd8, 0x31, 0x9b, 0x7b, 0xe9, 0xb7, 0x9d, 0x4b, 0xeb, 0x88, 0x16, 0xcf, 0xf9, 0x5d, +0x38, 0x8a, 0x49, 0x30, 0x8f, 0xed, 0xf1, 0xeb, 0x19, 0xf4, 0x77, 0x1a, 0x31, 0x18, 0x4d, 0x67, +0x54, 0x6c, 0x2f, 0x6f, 0x65, 0xf9, 0xdb, 0x3d, 0xec, 0x21, 0xec, 0x5e, 0xf4, 0xf4, 0x8b, 0xca, +0x60, 0x65, 0x54, 0xd1, 0x71, 0x64, 0xf4, 0xf9, 0xa6, 0xa3, 0x81, 0x33, 0x36, 0x33, 0x71, 0xf0, +0xa4, 0x78, 0x5f, 0x4e, 0xad, 0x83, 0x21, 0xde, 0x34, 0x49, 0x8d, 0xe8, 0x59, 0xac, 0x9d, 0xf2, +0x76, 0x5a, 0x36, 0xf2, 0x13, 0xf4, 0xaf, 0xe0, 0x09, 0xc7, 0x61, 0x2a, 0x6c, 0xf7, 0xe0, 0x9d, +0xae, 0xbb, 0x86, 0x4a, 0x28, 0x6f, 0x2e, 0xee, 0xb4, 0x79, 0xcd, 0x90, 0x33, 0xc3, 0xb3, 0x76, +0xfa, 0xf5, 0xf0, 0x6c, 0x9d, 0x01, 0x90, 0xfa, 0x9e, 0x90, 0xf6, 0x9c, 0x72, 0xcf, 0x47, 0xda, +0xc3, 0x1f, 0xe4, 0x35, 0x20, 0x53, 0xf2, 0x54, 0xd1, 0xdf, 0x61, 0x83, 0xa6, 0x02, 0xe2, 0x25, +0x38, 0xde, 0x85, 0x32, 0x2d, 0x5e, 0x73, 0x90, 0x52, 0x5d, 0x42, 0xc4, 0xce, 0x3d, 0x4b, 0xe1, +0xf9, 0x19, 0x84, 0x1d, 0xd5, 0xa2, 0x50, 0xcc, 0x41, 0xfb, 0x41, 0x14, 0xc3, 0xbd, 0xd6, 0xc9, +0x5a, 0xa3, 0x63, 0x66, 0x02, 0x80, 0xbd, 0x05, 0x3a, 0x3b, 0x47, 0x9c, 0xec, 0x00, 0x26, 0x4c, +0xf5, 0x88, 0x51, 0xbf, 0xa8, 0x23, 0x7f, 0x18, 0x07, 0xb0, 0x0b, 0xed, 0x8b, 0x26, 0xa1, 0x64, +0xd3, 0x61, 0x4a, 0xeb, 0x5c, 0x9f, 0xde, 0xb3, 0xaf, 0x67, 0x03, 0xb3, 0x1f, 0xdd, 0x6d, 0x5d, +0x69, 0x68, 0x69, 0xab, 0x5e, 0x3a, 0xec, 0x7c, 0x69, 0xbc, 0xc7, 0x3b, 0x85, 0x4e, 0x9e, 0x15, +0xb9, 0xb4, 0x15, 0x4f, 0xc3, 0x95, 0x7a, 0x58, 0xd7, 0xc9, 0x6c, 0xe9, 0x6c, 0xb9, 0xf3, 0x29, +0x63, 0x5e, 0xb4, 0x2c, 0xf0, 0x2d, 0x3d, 0xed, 0x5a, 0x65, 0xe0, 0xa9, 0x5b, 0x40, 0xc2, 0x48, +0x99, 0x81, 0x6d, 0x9e, 0x1f, 0x06, 0x2a, 0x3c, 0x12, 0xb4, 0x8b, 0x0f, 0x9b, 0xa2, 0x24, 0xf0, +0xa6, 0x8d, 0xd6, 0x7a, 0xe0, 0x4b, 0xb6, 0x64, 0x96, 0x63, 0x95, 0x84, 0xc2, 0x4a, 0xcd, 0x1c, +0x2e, 0x24, 0x87, 0x33, 0x60, 0xe5, 0xc3, 0x30, 0x82, 0x05, 0xb7, 0x30, 0x82, 0x03, 0x9f, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x05, 0x09, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, +0x64, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6f, 0x56, +0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x1e, +0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, 0x32, 0x34, 0x31, 0x38, 0x32, 0x37, 0x30, 0x30, 0x5a, 0x17, +0x0d, 0x33, 0x31, 0x31, 0x31, 0x32, 0x34, 0x31, 0x38, 0x32, 0x33, 0x33, 0x33, 0x5a, 0x30, 0x45, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, +0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, +0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x12, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, +0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x9a, 0x18, 0xca, 0x4b, 0x94, 0x0d, 0x00, 0x2d, 0xaf, 0x03, +0x29, 0x8a, 0xf0, 0x0f, 0x81, 0xc8, 0xae, 0x4c, 0x19, 0x85, 0x1d, 0x08, 0x9f, 0xab, 0x29, 0x44, +0x85, 0xf3, 0x2f, 0x81, 0xad, 0x32, 0x1e, 0x90, 0x46, 0xbf, 0xa3, 0x86, 0x26, 0x1a, 0x1e, 0xfe, +0x7e, 0x1c, 0x18, 0x3a, 0x5c, 0x9c, 0x60, 0x17, 0x2a, 0x3a, 0x74, 0x83, 0x33, 0x30, 0x7d, 0x61, +0x54, 0x11, 0xcb, 0xed, 0xab, 0xe0, 0xe6, 0xd2, 0xa2, 0x7e, 0xf5, 0x6b, 0x6f, 0x18, 0xb7, 0x0a, +0x0b, 0x2d, 0xfd, 0xe9, 0x3e, 0xef, 0x0a, 0xc6, 0xb3, 0x10, 0xe9, 0xdc, 0xc2, 0x46, 0x17, 0xf8, +0x5d, 0xfd, 0xa4, 0xda, 0xff, 0x9e, 0x49, 0x5a, 0x9c, 0xe6, 0x33, 0xe6, 0x24, 0x96, 0xf7, 0x3f, +0xba, 0x5b, 0x2b, 0x1c, 0x7a, 0x35, 0xc2, 0xd6, 0x67, 0xfe, 0xab, 0x66, 0x50, 0x8b, 0x6d, 0x28, +0x60, 0x2b, 0xef, 0xd7, 0x60, 0xc3, 0xc7, 0x93, 0xbc, 0x8d, 0x36, 0x91, 0xf3, 0x7f, 0xf8, 0xdb, +0x11, 0x13, 0xc4, 0x9c, 0x77, 0x76, 0xc1, 0xae, 0xb7, 0x02, 0x6a, 0x81, 0x7a, 0xa9, 0x45, 0x83, +0xe2, 0x05, 0xe6, 0xb9, 0x56, 0xc1, 0x94, 0x37, 0x8f, 0x48, 0x71, 0x63, 0x22, 0xec, 0x17, 0x65, +0x07, 0x95, 0x8a, 0x4b, 0xdf, 0x8f, 0xc6, 0x5a, 0x0a, 0xe5, 0xb0, 0xe3, 0x5f, 0x5e, 0x6b, 0x11, +0xab, 0x0c, 0xf9, 0x85, 0xeb, 0x44, 0xe9, 0xf8, 0x04, 0x73, 0xf2, 0xe9, 0xfe, 0x5c, 0x98, 0x8c, +0xf5, 0x73, 0xaf, 0x6b, 0xb4, 0x7e, 0xcd, 0xd4, 0x5c, 0x02, 0x2b, 0x4c, 0x39, 0xe1, 0xb2, 0x95, +0x95, 0x2d, 0x42, 0x87, 0xd7, 0xd5, 0xb3, 0x90, 0x43, 0xb7, 0x6c, 0x13, 0xf1, 0xde, 0xdd, 0xf6, +0xc4, 0xf8, 0x89, 0x3f, 0xd1, 0x75, 0xf5, 0x92, 0xc3, 0x91, 0xd5, 0x8a, 0x88, 0xd0, 0x90, 0xec, +0xdc, 0x6d, 0xde, 0x89, 0xc2, 0x65, 0x71, 0x96, 0x8b, 0x0d, 0x03, 0xfd, 0x9c, 0xbf, 0x5b, 0x16, +0xac, 0x92, 0xdb, 0xea, 0xfe, 0x79, 0x7c, 0xad, 0xeb, 0xaf, 0xf7, 0x16, 0xcb, 0xdb, 0xcd, 0x25, +0x2b, 0xe5, 0x1f, 0xfb, 0x9a, 0x9f, 0xe2, 0x51, 0xcc, 0x3a, 0x53, 0x0c, 0x48, 0xe6, 0x0e, 0xbd, +0xc9, 0xb4, 0x76, 0x06, 0x52, 0xe6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xe0, 0x04, 0x36, +0x2b, 0x20, 0x19, 0x02, 0xe8, 0x74, 0xa7, 0x1f, 0xb6, 0xc9, 0x56, 0x66, 0xf0, 0x75, 0x25, 0xdc, +0x67, 0xc1, 0x0e, 0x61, 0x60, 0x88, 0xb3, 0x3e, 0xd1, 0xa8, 0xfc, 0xa3, 0xda, 0x1d, 0xb0, 0xd1, +0xb1, 0x23, 0x54, 0xdf, 0x44, 0x76, 0x6d, 0xed, 0x41, 0xd8, 0xc1, 0xb2, 0x22, 0xb6, 0x53, 0x1c, +0xdf, 0x35, 0x1d, 0xdc, 0xa1, 0x77, 0x2a, 0x31, 0xe4, 0x2d, 0xf5, 0xe5, 0xe5, 0xdb, 0xc8, 0xe0, +0xff, 0xe5, 0x80, 0xd7, 0x0b, 0x63, 0xa0, 0xff, 0x33, 0xa1, 0x0f, 0xba, 0x2c, 0x15, 0x15, 0xea, +0x97, 0xb3, 0xd2, 0xa2, 0xb5, 0xbe, 0xf2, 0x8c, 0x96, 0x1e, 0x1a, 0x8f, 0x1d, 0x6c, 0xa4, 0x61, +0x37, 0xb9, 0x86, 0x73, 0x33, 0xd7, 0x97, 0x96, 0x9e, 0x23, 0x7d, 0x82, 0xa4, 0x4c, 0x81, 0xe2, +0xa1, 0xd1, 0xba, 0x67, 0x5f, 0x95, 0x07, 0xa3, 0x27, 0x11, 0xee, 0x16, 0x10, 0x7b, 0xbc, 0x45, +0x4a, 0x4c, 0xb2, 0x04, 0xd2, 0xab, 0xef, 0xd5, 0xfd, 0x0c, 0x51, 0xce, 0x50, 0x6a, 0x08, 0x31, +0xf9, 0x91, 0xda, 0x0c, 0x8f, 0x64, 0x5c, 0x03, 0xc3, 0x3a, 0x8b, 0x20, 0x3f, 0x6e, 0x8d, 0x67, +0x3d, 0x3a, 0xd6, 0xfe, 0x7d, 0x5b, 0x88, 0xc9, 0x5e, 0xfb, 0xcc, 0x61, 0xdc, 0x8b, 0x33, 0x77, +0xd3, 0x44, 0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xd8, 0x9e, 0x27, 0x47, 0xfb, 0x3b, +0x21, 0xe3, 0xf8, 0xeb, 0x1d, 0x5b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xb0, 0x30, 0x81, +0xad, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1a, 0x84, 0x62, 0xbc, 0x48, 0x4c, +0x33, 0x25, 0x04, 0xd4, 0xee, 0xd0, 0xf6, 0x03, 0xc4, 0x19, 0x46, 0xd1, 0x94, 0x6b, 0x30, 0x6e, +0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x1a, 0x84, 0x62, 0xbc, 0x48, +0x4c, 0x33, 0x25, 0x04, 0xd4, 0xee, 0xd0, 0xf6, 0x03, 0xc4, 0x19, 0x46, 0xd1, 0x94, 0x6b, 0xa1, +0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, +0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1b, 0x30, +0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x82, 0x02, 0x05, 0x09, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, +0x01, 0x00, 0x3e, 0x0a, 0x16, 0x4d, 0x9f, 0x06, 0x5b, 0xa8, 0xae, 0x71, 0x5d, 0x2f, 0x05, 0x2f, +0x67, 0xe6, 0x13, 0x45, 0x83, 0xc4, 0x36, 0xf6, 0xf3, 0xc0, 0x26, 0x0c, 0x0d, 0xb5, 0x47, 0x64, +0x5d, 0xf8, 0xb4, 0x72, 0xc9, 0x46, 0xa5, 0x03, 0x18, 0x27, 0x55, 0x89, 0x78, 0x7d, 0x76, 0xea, +0x96, 0x34, 0x80, 0x17, 0x20, 0xdc, 0xe7, 0x83, 0xf8, 0x8d, 0xfc, 0x07, 0xb8, 0xda, 0x5f, 0x4d, +0x2e, 0x67, 0xb2, 0x84, 0xfd, 0xd9, 0x44, 0xfc, 0x77, 0x50, 0x81, 0xe6, 0x7c, 0xb4, 0xc9, 0x0d, +0x0b, 0x72, 0x53, 0xf8, 0x76, 0x07, 0x07, 0x41, 0x47, 0x96, 0x0c, 0xfb, 0xe0, 0x82, 0x26, 0x93, +0x55, 0x8c, 0xfe, 0x22, 0x1f, 0x60, 0x65, 0x7c, 0x5f, 0xe7, 0x26, 0xb3, 0xf7, 0x32, 0x90, 0x98, +0x50, 0xd4, 0x37, 0x71, 0x55, 0xf6, 0x92, 0x21, 0x78, 0xf7, 0x95, 0x79, 0xfa, 0xf8, 0x2d, 0x26, +0x87, 0x66, 0x56, 0x30, 0x77, 0xa6, 0x37, 0x78, 0x33, 0x52, 0x10, 0x58, 0xae, 0x3f, 0x61, 0x8e, +0xf2, 0x6a, 0xb1, 0xef, 0x18, 0x7e, 0x4a, 0x59, 0x63, 0xca, 0x8d, 0xa2, 0x56, 0xd5, 0xa7, 0x2f, +0xbc, 0x56, 0x1f, 0xcf, 0x39, 0xc1, 0xe2, 0xfb, 0x0a, 0xa8, 0x15, 0x2c, 0x7d, 0x4d, 0x7a, 0x63, +0xc6, 0x6c, 0x97, 0x44, 0x3c, 0xd2, 0x6f, 0xc3, 0x4a, 0x17, 0x0a, 0xf8, 0x90, 0xd2, 0x57, 0xa2, +0x19, 0x51, 0xa5, 0x2d, 0x97, 0x41, 0xda, 0x07, 0x4f, 0xa9, 0x50, 0xda, 0x90, 0x8d, 0x94, 0x46, +0xe1, 0x3e, 0xf0, 0x94, 0xfd, 0x10, 0x00, 0x38, 0xf5, 0x3b, 0xe8, 0x40, 0xe1, 0xb4, 0x6e, 0x56, +0x1a, 0x20, 0xcc, 0x6f, 0x58, 0x8d, 0xed, 0x2e, 0x45, 0x8f, 0xd6, 0xe9, 0x93, 0x3f, 0xe7, 0xb1, +0x2c, 0xdf, 0x3a, 0xd6, 0x22, 0x8c, 0xdc, 0x84, 0xbb, 0x22, 0x6f, 0xd0, 0xf8, 0xe4, 0xc6, 0x39, +0xe9, 0x04, 0x88, 0x3c, 0xc3, 0xba, 0xeb, 0x55, 0x7a, 0x6d, 0x80, 0x99, 0x24, 0xf5, 0x6c, 0x01, +0xfb, 0xf8, 0x97, 0xb0, 0x94, 0x5b, 0xeb, 0xfd, 0xd2, 0x6f, 0xf1, 0x77, 0x68, 0x0d, 0x35, 0x64, +0x23, 0xac, 0xb8, 0x55, 0xa1, 0x03, 0xd1, 0x4d, 0x42, 0x19, 0xdc, 0xf8, 0x75, 0x59, 0x56, 0xa3, +0xf9, 0xa8, 0x49, 0x79, 0xf8, 0xaf, 0x0e, 0xb9, 0x11, 0xa0, 0x7c, 0xb7, 0x6a, 0xed, 0x34, 0xd0, +0xb6, 0x26, 0x62, 0x38, 0x1a, 0x87, 0x0c, 0xf8, 0xe8, 0xfd, 0x2e, 0xd3, 0x90, 0x7f, 0x07, 0x91, +0x2a, 0x1d, 0xd6, 0x7e, 0x5c, 0x85, 0x83, 0x99, 0xb0, 0x38, 0x08, 0x3f, 0xe9, 0x5e, 0xf9, 0x35, +0x07, 0xe4, 0xc9, 0x62, 0x6e, 0x57, 0x7f, 0xa7, 0x50, 0x95, 0xf7, 0xba, 0xc8, 0x9b, 0xe6, 0x8e, +0xa2, 0x01, 0xc5, 0xd6, 0x66, 0xbf, 0x79, 0x61, 0xf3, 0x3c, 0x1c, 0xe1, 0xb9, 0x82, 0x5c, 0x5d, +0xa0, 0xc3, 0xe9, 0xd8, 0x48, 0xbd, 0x19, 0xa2, 0x11, 0x14, 0x19, 0x6e, 0xb2, 0x86, 0x1b, 0x68, +0x3e, 0x48, 0x37, 0x1a, 0x88, 0xb7, 0x5d, 0x96, 0x5e, 0x9c, 0xc7, 0xef, 0x27, 0x62, 0x08, 0xe2, +0x91, 0x19, 0x5c, 0xd2, 0xf1, 0x21, 0xdd, 0xba, 0x17, 0x42, 0x82, 0x97, 0x71, 0x81, 0x53, 0x31, +0xa9, 0x9f, 0xf6, 0x7d, 0x62, 0xbf, 0x72, 0xe1, 0xa3, 0x93, 0x1d, 0xcc, 0x8a, 0x26, 0x5a, 0x09, +0x38, 0xd0, 0xce, 0xd7, 0x0d, 0x80, 0x16, 0xb4, 0x78, 0xa5, 0x3a, 0x87, 0x4c, 0x8d, 0x8a, 0xa5, +0xd5, 0x46, 0x97, 0xf2, 0x2c, 0x10, 0xb9, 0xbc, 0x54, 0x22, 0xc0, 0x01, 0x50, 0x69, 0x43, 0x9e, +0xf4, 0xb2, 0xef, 0x6d, 0xf8, 0xec, 0xda, 0xf1, 0xe3, 0xb1, 0xef, 0xdf, 0x91, 0x8f, 0x54, 0x2a, +0x0b, 0x25, 0xc1, 0x26, 0x19, 0xc4, 0x52, 0x10, 0x05, 0x65, 0xd5, 0x82, 0x10, 0xea, 0xc2, 0x31, +0xcd, 0x2e, 0x30, 0x82, 0x05, 0x60, 0x30, 0x82, 0x03, 0x48, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x14, 0x44, 0x57, 0x34, 0x24, 0x5b, 0x81, 0x89, 0x9b, 0x35, 0xf2, 0xce, 0xb8, 0x2b, 0x3b, 0x5b, +0xa7, 0x26, 0xf0, 0x75, 0x28, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x30, 0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, +0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1e, +0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, +0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x47, 0x33, 0x30, 0x1e, +0x17, 0x0d, 0x31, 0x32, 0x30, 0x31, 0x31, 0x32, 0x31, 0x38, 0x35, 0x39, 0x33, 0x32, 0x5a, 0x17, +0x0d, 0x34, 0x32, 0x30, 0x31, 0x31, 0x32, 0x31, 0x38, 0x35, 0x39, 0x33, 0x32, 0x5a, 0x30, 0x48, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, +0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, +0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x15, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x47, 0x33, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, +0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa1, 0xae, 0x25, 0xb2, 0x01, 0x18, 0xdc, +0x57, 0x88, 0x3f, 0x46, 0xeb, 0xf9, 0xaf, 0xe2, 0xeb, 0x23, 0x71, 0xe2, 0x9a, 0xd1, 0x61, 0x66, +0x21, 0x5f, 0xaa, 0xaf, 0x27, 0x51, 0xe5, 0x6e, 0x1b, 0x16, 0xd4, 0x2d, 0x7d, 0x50, 0xb0, 0x53, +0x77, 0xbd, 0x78, 0x3a, 0x60, 0xe2, 0x64, 0x02, 0x9b, 0x7c, 0x86, 0x9b, 0xd6, 0x1a, 0x8e, 0xad, +0xff, 0x1f, 0x15, 0x7f, 0xd5, 0x95, 0x1e, 0x12, 0xcb, 0xe6, 0x14, 0x84, 0x04, 0xc1, 0xdf, 0x36, +0xb3, 0x16, 0x9f, 0x8a, 0xe3, 0xc9, 0xdb, 0x98, 0x34, 0xce, 0xd8, 0x33, 0x17, 0x28, 0x46, 0xfc, +0xa7, 0xc9, 0xf0, 0xd2, 0xb4, 0xd5, 0x4d, 0x09, 0x72, 0x49, 0xf9, 0xf2, 0x87, 0xe3, 0xa9, 0xda, +0x7d, 0xa1, 0x7d, 0x6b, 0xb2, 0x3a, 0x25, 0xa9, 0x6d, 0x52, 0x44, 0xac, 0xf8, 0xbe, 0x6e, 0xfb, +0xdc, 0xa6, 0x73, 0x91, 0x90, 0x61, 0xa6, 0x03, 0x14, 0x20, 0xf2, 0xe7, 0x87, 0xa3, 0x88, 0xad, +0xad, 0xa0, 0x8c, 0xff, 0xa6, 0x0b, 0x25, 0x52, 0x25, 0xe7, 0x16, 0x01, 0xd5, 0xcb, 0xb8, 0x35, +0x81, 0x0c, 0xa3, 0x3b, 0xf0, 0xe1, 0xe1, 0xfc, 0x5a, 0x5d, 0xce, 0x80, 0x71, 0x6d, 0xf8, 0x49, +0xab, 0x3e, 0x3b, 0xba, 0xb8, 0xd7, 0x80, 0x01, 0xfb, 0xa5, 0xeb, 0x5b, 0xb3, 0xc5, 0x5e, 0x60, +0x2a, 0x31, 0xa0, 0xaf, 0x37, 0xe8, 0x20, 0x3a, 0x9f, 0xa8, 0x32, 0x2c, 0x0c, 0xcc, 0x09, 0x1d, +0xd3, 0x9e, 0x8e, 0x5d, 0xbc, 0x4c, 0x98, 0xee, 0xc5, 0x1a, 0x68, 0x7b, 0xec, 0x53, 0xa6, 0xe9, +0x14, 0x35, 0xa3, 0xdf, 0xcd, 0x80, 0x9f, 0x0c, 0x48, 0xfb, 0x1c, 0xf4, 0xf1, 0xbf, 0x4a, 0xb8, +0xfa, 0xd5, 0x8c, 0x71, 0x4a, 0xc7, 0x1f, 0xad, 0xfe, 0x41, 0x9a, 0xb3, 0x83, 0x5d, 0xf2, 0x84, +0x56, 0xef, 0xa5, 0x57, 0x43, 0xce, 0x29, 0xad, 0x8c, 0xab, 0x55, 0xbf, 0xc4, 0xfb, 0x5b, 0x01, +0xdd, 0x23, 0x21, 0xa1, 0x58, 0x00, 0x8e, 0xc3, 0xd0, 0x6a, 0x13, 0xed, 0x13, 0xe3, 0x12, 0x2b, +0x80, 0xdc, 0x67, 0xe6, 0x95, 0xb2, 0xcd, 0x1e, 0x22, 0x6e, 0x2a, 0xf8, 0x41, 0xd4, 0xf2, 0xca, +0x14, 0x07, 0x8d, 0x8a, 0x55, 0x12, 0xc6, 0x69, 0xf5, 0xb8, 0x86, 0x68, 0x2f, 0x53, 0x5e, 0xb0, +0xd2, 0xaa, 0x21, 0xc1, 0x98, 0xe6, 0x30, 0xe3, 0x67, 0x55, 0xc7, 0x9b, 0x6e, 0xac, 0x19, 0xa8, +0x55, 0xa6, 0x45, 0x06, 0xd0, 0x23, 0x3a, 0xdb, 0xeb, 0x65, 0x5d, 0x2a, 0x11, 0x11, 0xf0, 0x3b, +0x4f, 0xca, 0x6d, 0xf4, 0x34, 0xc4, 0x71, 0xe4, 0xff, 0x00, 0x5a, 0xf6, 0x5c, 0xae, 0x23, 0x60, +0x85, 0x73, 0xf1, 0xe4, 0x10, 0xb1, 0x25, 0xae, 0xd5, 0x92, 0xbb, 0x13, 0xc1, 0x0c, 0xe0, 0x39, +0xda, 0xb4, 0x39, 0x57, 0xb5, 0xab, 0x35, 0xaa, 0x72, 0x21, 0x3b, 0x83, 0x35, 0xe7, 0x31, 0xdf, +0x7a, 0x21, 0x6e, 0xb8, 0x32, 0x08, 0x7d, 0x1d, 0x32, 0x91, 0x15, 0x4a, 0x62, 0x72, 0xcf, 0xe3, +0x77, 0xa1, 0xbc, 0xd5, 0x11, 0x1b, 0x76, 0x01, 0x67, 0x08, 0xe0, 0x41, 0x0b, 0xc3, 0xeb, 0x15, +0x6e, 0xf8, 0xa4, 0x19, 0xd9, 0xa2, 0xab, 0xaf, 0xe2, 0x27, 0x52, 0x56, 0x2b, 0x02, 0x8a, 0x2c, +0x14, 0x24, 0xf9, 0xbf, 0x42, 0x02, 0xbf, 0x26, 0xc8, 0xc6, 0x8f, 0xe0, 0x6e, 0x38, 0x7d, 0x53, +0x2d, 0xe5, 0xed, 0x98, 0xb3, 0x95, 0x63, 0x68, 0x7f, 0xf9, 0x35, 0xf4, 0xdf, 0x88, 0xc5, 0x60, +0x35, 0x92, 0xc0, 0x7c, 0x69, 0x1c, 0x61, 0x95, 0x16, 0xd0, 0xeb, 0xde, 0x0b, 0xaf, 0x3e, 0x04, +0x10, 0x45, 0x65, 0x58, 0x50, 0x38, 0xaf, 0x48, 0xf2, 0x59, 0xb6, 0x16, 0xf2, 0x3c, 0x0d, 0x90, +0x02, 0xc6, 0x70, 0x2e, 0x01, 0xad, 0x3c, 0x15, 0xd7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, +0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xed, 0xe7, +0x6f, 0x76, 0x5a, 0xbf, 0x60, 0xec, 0x49, 0x5b, 0xc6, 0xa5, 0x77, 0xbb, 0x72, 0x16, 0x71, 0x9b, +0xc4, 0x3d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x91, 0xdf, 0x80, 0x3f, 0x43, 0x09, 0x7e, 0x71, 0xc2, 0xf7, +0xeb, 0xb3, 0x88, 0x8f, 0xe1, 0x51, 0xb2, 0xbc, 0x3d, 0x75, 0xf9, 0x28, 0x5d, 0xc8, 0xbc, 0x99, +0x9b, 0x7b, 0x5d, 0xaa, 0xe5, 0xca, 0xe1, 0x0a, 0xf7, 0xe8, 0xb2, 0xd3, 0x9f, 0xdd, 0x67, 0x31, +0x7e, 0xba, 0x01, 0xaa, 0xc7, 0x6a, 0x41, 0x3b, 0x90, 0xd4, 0x08, 0x5c, 0xb2, 0x60, 0x6a, 0x90, +0xf0, 0xc8, 0xce, 0x03, 0x62, 0xf9, 0x8b, 0xed, 0xfb, 0x6e, 0x2a, 0xdc, 0x06, 0x4d, 0x3c, 0x29, +0x0f, 0x89, 0x16, 0x8a, 0x58, 0x4c, 0x48, 0x0f, 0xe8, 0x84, 0x61, 0xea, 0x3c, 0x72, 0xa6, 0x77, +0xe4, 0x42, 0xae, 0x88, 0xa3, 0x43, 0x58, 0x79, 0x7e, 0xae, 0xca, 0xa5, 0x53, 0x0d, 0xa9, 0x3d, +0x70, 0xbd, 0x20, 0x19, 0x61, 0xa4, 0x6c, 0x38, 0xfc, 0x43, 0x32, 0xe1, 0xc1, 0x47, 0xff, 0xf8, +0xec, 0xf1, 0x11, 0x22, 0x32, 0x96, 0x9c, 0xc2, 0xf6, 0x5b, 0x69, 0x96, 0x7b, 0x20, 0x0c, 0x43, +0x41, 0x9a, 0x5b, 0xf6, 0x59, 0x19, 0x88, 0xde, 0x55, 0x88, 0x37, 0x51, 0x0b, 0x78, 0x5c, 0x0a, +0x1e, 0xa3, 0x42, 0xfd, 0xc7, 0x9d, 0x88, 0x0f, 0xc0, 0xf2, 0x78, 0x02, 0x24, 0x54, 0x93, 0xaf, +0x89, 0x87, 0x88, 0xc9, 0x4a, 0x80, 0x1d, 0xea, 0xd0, 0x6e, 0x3e, 0x61, 0x2e, 0x36, 0xbb, 0x35, +0x0e, 0x27, 0x96, 0xfd, 0x66, 0x34, 0x3b, 0x61, 0x72, 0x73, 0xf1, 0x16, 0x5c, 0x47, 0x06, 0x54, +0x49, 0x00, 0x7a, 0x58, 0x12, 0xb0, 0x0a, 0xef, 0x85, 0xfd, 0xb1, 0xb8, 0x33, 0x75, 0x6a, 0x93, +0x1c, 0x12, 0xe6, 0x60, 0x5e, 0x6f, 0x1d, 0x7f, 0xc9, 0x1f, 0x23, 0xcb, 0x84, 0x61, 0x9f, 0x1e, +0x82, 0x44, 0xf9, 0x5f, 0xad, 0x62, 0x55, 0x24, 0x9a, 0x52, 0x98, 0xed, 0x51, 0xe7, 0xa1, 0x7e, +0x97, 0x3a, 0xe6, 0x2f, 0x1f, 0x11, 0xda, 0x53, 0x80, 0x2c, 0x85, 0x9e, 0xab, 0x35, 0x10, 0xdb, +0x22, 0x5f, 0x6a, 0xc5, 0x5e, 0x97, 0x53, 0xf2, 0x32, 0x02, 0x09, 0x30, 0xa3, 0x58, 0xf0, 0x0d, +0x01, 0xd5, 0x72, 0xc6, 0xb1, 0x7c, 0x69, 0x7b, 0xc3, 0xf5, 0x36, 0x45, 0xcc, 0x61, 0x6e, 0x5e, +0x4c, 0x94, 0xc5, 0x5e, 0xae, 0xe8, 0x0e, 0x5e, 0x8b, 0xbf, 0xf7, 0xcd, 0xe0, 0xed, 0xa1, 0x0e, +0x1b, 0x33, 0xee, 0x54, 0x18, 0xfe, 0x0f, 0xbe, 0xef, 0x7e, 0x84, 0x6b, 0x43, 0xe3, 0x70, 0x98, +0xdb, 0x5d, 0x75, 0xb2, 0x0d, 0x59, 0x07, 0x85, 0x15, 0x23, 0x39, 0xd6, 0xf1, 0xdf, 0xa9, 0x26, +0x0f, 0xd6, 0x48, 0xc7, 0xb3, 0xa6, 0x22, 0xf5, 0x33, 0x37, 0x5a, 0x95, 0x47, 0x9f, 0x7b, 0xba, +0x18, 0x15, 0x6f, 0xff, 0xd6, 0x14, 0x64, 0x83, 0x49, 0xd2, 0x0a, 0x67, 0x21, 0xdb, 0x0f, 0x35, +0x63, 0x60, 0x28, 0x22, 0xe3, 0xb1, 0x95, 0x83, 0xcd, 0x85, 0xa6, 0xdd, 0x2f, 0x0f, 0xe7, 0x67, +0x52, 0x6e, 0xbb, 0x2f, 0x85, 0x7c, 0xf5, 0x4a, 0x73, 0xe7, 0xc5, 0x3e, 0xc0, 0xbd, 0x21, 0x12, +0x05, 0x3f, 0xfc, 0xb7, 0x03, 0x49, 0x02, 0x5b, 0xc8, 0x25, 0xe6, 0xe2, 0x54, 0x38, 0xf5, 0x79, +0x87, 0x8c, 0x1d, 0x53, 0xb2, 0x4e, 0x85, 0x7b, 0x06, 0x38, 0xc7, 0x2c, 0xf8, 0xf8, 0xb0, 0x72, +0x8d, 0x25, 0xe5, 0x77, 0x52, 0xf4, 0x03, 0x1c, 0x48, 0xa6, 0x50, 0x5f, 0x88, 0x20, 0x30, 0x6e, +0xf2, 0x82, 0x43, 0xab, 0x3d, 0x97, 0x84, 0xe7, 0x53, 0xfb, 0x21, 0xc1, 0x4f, 0x0f, 0x22, 0x9a, +0x86, 0xb8, 0x59, 0x2a, 0xf6, 0x47, 0x3d, 0x19, 0x88, 0x2d, 0xe8, 0x85, 0xe1, 0x9e, 0xec, 0x85, +0x08, 0x6a, 0xb1, 0x6c, 0x34, 0xc9, 0x1d, 0xec, 0x48, 0x2b, 0x3b, 0x78, 0xed, 0x66, 0xc4, 0x8e, +0x79, 0x69, 0x83, 0xde, 0x7f, 0x8c, 0x30, 0x82, 0x06, 0x9d, 0x30, 0x82, 0x04, 0x85, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x02, 0x05, 0xc6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, +0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, +0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6f, 0x56, 0x61, +0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x30, 0x1e, 0x17, +0x0d, 0x30, 0x36, 0x31, 0x31, 0x32, 0x34, 0x31, 0x39, 0x31, 0x31, 0x32, 0x33, 0x5a, 0x17, 0x0d, +0x33, 0x31, 0x31, 0x31, 0x32, 0x34, 0x31, 0x39, 0x30, 0x36, 0x34, 0x34, 0x5a, 0x30, 0x45, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, +0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x12, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x41, 0x20, 0x33, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, +0x02, 0x82, 0x02, 0x01, 0x00, 0xcc, 0x57, 0x42, 0x16, 0x54, 0x9c, 0xe6, 0x98, 0xd3, 0xd3, 0x4d, +0xee, 0xfe, 0xed, 0xc7, 0x9f, 0x43, 0x39, 0x4a, 0x65, 0xb3, 0xe8, 0x16, 0x88, 0x34, 0xdb, 0x0d, +0x59, 0x91, 0x74, 0xcf, 0x92, 0xb8, 0x04, 0x40, 0xad, 0x02, 0x4b, 0x31, 0xab, 0xbc, 0x8d, 0x91, +0x68, 0xd8, 0x20, 0x0e, 0x1a, 0x01, 0xe2, 0x1a, 0x7b, 0x4e, 0x17, 0x5d, 0xe2, 0x8a, 0xb7, 0x3f, +0x99, 0x1a, 0xcd, 0xeb, 0x61, 0xab, 0xc2, 0x65, 0xa6, 0x1f, 0xb7, 0xb7, 0xbd, 0xb7, 0x8f, 0xfc, +0xfd, 0x70, 0x8f, 0x0b, 0xa0, 0x67, 0xbe, 0x01, 0xa2, 0x59, 0xcf, 0x71, 0xe6, 0x0f, 0x29, 0x76, +0xff, 0xb1, 0x56, 0x79, 0x45, 0x2b, 0x1f, 0x9e, 0x7a, 0x54, 0xe8, 0xa3, 0x29, 0x35, 0x68, 0xa4, +0x01, 0x4f, 0x0f, 0xa4, 0x2e, 0x37, 0xef, 0x1b, 0xbf, 0xe3, 0x8f, 0x10, 0xa8, 0x72, 0xab, 0x58, +0x57, 0xe7, 0x54, 0x86, 0xc8, 0xc9, 0xf3, 0x5b, 0xda, 0x2c, 0xda, 0x5d, 0x8e, 0x6e, 0x3c, 0xa3, +0x3e, 0xda, 0xfb, 0x82, 0xe5, 0xdd, 0xf2, 0x5c, 0xb2, 0x05, 0x33, 0x6f, 0x8a, 0x36, 0xce, 0xd0, +0x13, 0x4e, 0xff, 0xbf, 0x4a, 0x0c, 0x34, 0x4c, 0xa6, 0xc3, 0x21, 0xbd, 0x50, 0x04, 0x55, 0xeb, +0xb1, 0xbb, 0x9d, 0xfb, 0x45, 0x1e, 0x64, 0x15, 0xde, 0x55, 0x01, 0x8c, 0x02, 0x76, 0xb5, 0xcb, +0xa1, 0x3f, 0x42, 0x69, 0xbc, 0x2f, 0xbd, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2a, 0x37, 0x61, 0x91, +0xfd, 0xa6, 0xae, 0x4e, 0xc0, 0xcb, 0x14, 0x65, 0x94, 0x37, 0x4b, 0x92, 0x06, 0xef, 0x04, 0xd0, +0xc8, 0x9c, 0x88, 0xdb, 0x0b, 0x7b, 0x81, 0xaf, 0xb1, 0x3d, 0x2a, 0xc4, 0x65, 0x3a, 0x78, 0xb6, +0xee, 0xdc, 0x80, 0xb1, 0xd2, 0xd3, 0x99, 0x9c, 0x3a, 0xee, 0x6b, 0x5a, 0x6b, 0xb3, 0x8d, 0xb7, +0xd5, 0xce, 0x9c, 0xc2, 0xbe, 0xa5, 0x4b, 0x2f, 0x16, 0xb1, 0x9e, 0x68, 0x3b, 0x06, 0x6f, 0xae, +0x7d, 0x9f, 0xf8, 0xde, 0xec, 0xcc, 0x29, 0xa7, 0x98, 0xa3, 0x25, 0x43, 0x2f, 0xef, 0xf1, 0x5f, +0x26, 0xe1, 0x88, 0x4d, 0xf8, 0x5e, 0x6e, 0xd7, 0xd9, 0x14, 0x6e, 0x19, 0x33, 0x69, 0xa7, 0x3b, +0x84, 0x89, 0x93, 0xc4, 0x53, 0x55, 0x13, 0xa1, 0x51, 0x78, 0x40, 0xf8, 0xb8, 0xc9, 0xa2, 0xee, +0x7b, 0xba, 0x52, 0x42, 0x83, 0x9e, 0x14, 0xed, 0x05, 0x52, 0x5a, 0x59, 0x56, 0xa7, 0x97, 0xfc, +0x9d, 0x3f, 0x0a, 0x29, 0xd8, 0xdc, 0x4f, 0x91, 0x0e, 0x13, 0xbc, 0xde, 0x95, 0xa4, 0xdf, 0x8b, +0x99, 0xbe, 0xac, 0x9b, 0x33, 0x88, 0xef, 0xb5, 0x81, 0xaf, 0x1b, 0xc6, 0x22, 0x53, 0xc8, 0xf6, +0xc7, 0xee, 0x97, 0x14, 0xb0, 0xc5, 0x7c, 0x78, 0x52, 0xc8, 0xf0, 0xce, 0x6e, 0x77, 0x60, 0x84, +0xa6, 0xe9, 0x2a, 0x76, 0x20, 0xed, 0x58, 0x01, 0x17, 0x30, 0x93, 0xe9, 0x1a, 0x8b, 0xe0, 0x73, +0x63, 0xd9, 0x6a, 0x92, 0x94, 0x49, 0x4e, 0xb4, 0xad, 0x4a, 0x85, 0xc4, 0xa3, 0x22, 0x30, 0xfc, +0x09, 0xed, 0x68, 0x22, 0x73, 0xa6, 0x88, 0x0c, 0x55, 0x21, 0x58, 0xc5, 0xe1, 0x3a, 0x9f, 0x2a, +0xdd, 0xca, 0xe1, 0x90, 0xe0, 0xd9, 0x73, 0xab, 0x6c, 0x80, 0xb8, 0xe8, 0x0b, 0x64, 0x93, 0xa0, +0x9c, 0x8c, 0x19, 0xff, 0xb3, 0xd2, 0x0c, 0xec, 0x91, 0x26, 0x87, 0x8a, 0xb3, 0xa2, 0xe1, 0x70, +0x8f, 0x2c, 0x0a, 0xe5, 0xcd, 0x6d, 0x68, 0x51, 0xeb, 0xda, 0x3f, 0x05, 0x7f, 0x8b, 0x32, 0xe6, +0x13, 0x5c, 0x6b, 0xfe, 0x5f, 0x40, 0xe2, 0x22, 0xc8, 0xb4, 0xb4, 0x64, 0x4f, 0xd6, 0xba, 0x7d, +0x48, 0x3e, 0xa8, 0x69, 0x0c, 0xd7, 0xbb, 0x86, 0x71, 0xc9, 0x73, 0xb8, 0x3f, 0x3b, 0x9d, 0x25, +0x4b, 0xda, 0xff, 0x40, 0xeb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x95, 0x30, 0x82, +0x01, 0x91, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, +0x01, 0x01, 0xff, 0x30, 0x81, 0xe1, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x81, 0xd9, 0x30, 0x81, +0xd6, 0x30, 0x81, 0xd3, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xbe, 0x58, 0x00, 0x03, 0x30, +0x81, 0xc5, 0x30, 0x81, 0x93, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, +0x81, 0x86, 0x1a, 0x81, 0x83, 0x41, 0x6e, 0x79, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, +0x74, 0x68, 0x69, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, +0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x73, 0x20, 0x61, 0x63, 0x63, +0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x51, +0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, +0x33, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x50, 0x6f, +0x6c, 0x69, 0x63, 0x79, 0x20, 0x2f, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x65, 0x20, 0x53, 0x74, +0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, +0x05, 0x07, 0x02, 0x01, 0x16, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, +0x2e, 0x71, 0x75, 0x6f, 0x76, 0x61, 0x64, 0x69, 0x73, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2e, +0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x70, 0x73, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, +0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf2, +0xc0, 0x13, 0xe0, 0x82, 0x43, 0x3e, 0xfb, 0xee, 0x2f, 0x67, 0x32, 0x96, 0x35, 0x5c, 0xdb, 0xb8, +0xcb, 0x02, 0xd0, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, +0xf2, 0xc0, 0x13, 0xe0, 0x82, 0x43, 0x3e, 0xfb, 0xee, 0x2f, 0x67, 0x32, 0x96, 0x35, 0x5c, 0xdb, +0xb8, 0xcb, 0x02, 0xd0, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, +0x65, 0x64, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6f, +0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x82, +0x02, 0x05, 0xc6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, +0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x4f, 0xad, 0xa0, 0x2c, 0x4c, 0xfa, 0xc0, 0xf2, 0x6f, +0xf7, 0x66, 0x55, 0xab, 0x23, 0x34, 0xee, 0xe7, 0x29, 0xda, 0xc3, 0x5b, 0xb6, 0xb0, 0x83, 0xd9, +0xd0, 0xd0, 0xe2, 0x21, 0xfb, 0xf3, 0x60, 0xa7, 0x3b, 0x5d, 0x60, 0x53, 0x27, 0xa2, 0x9b, 0xf6, +0x08, 0x22, 0x2a, 0xe7, 0xbf, 0xa0, 0x72, 0xe5, 0x9c, 0x24, 0x6a, 0x31, 0xb1, 0x90, 0x7a, 0x27, +0xdb, 0x84, 0x11, 0x89, 0x27, 0xa6, 0x77, 0x5a, 0x38, 0xd7, 0xbf, 0xac, 0x86, 0xfc, 0xee, 0x5d, +0x83, 0xbc, 0x06, 0xc6, 0xd1, 0x77, 0x6b, 0x0f, 0x6d, 0x24, 0x2f, 0x4b, 0x7a, 0x6c, 0xa7, 0x07, +0x96, 0xca, 0xe3, 0x84, 0x9f, 0xad, 0x88, 0x8b, 0x1d, 0xab, 0x16, 0x8d, 0x5b, 0x66, 0x17, 0xd9, +0x16, 0xf4, 0x8b, 0x80, 0xd2, 0xdd, 0xf8, 0xb2, 0x76, 0xc3, 0xfc, 0x38, 0x13, 0xaa, 0x0c, 0xde, +0x42, 0x69, 0x2b, 0x6e, 0xf3, 0x3c, 0xeb, 0x80, 0x27, 0xdb, 0xf5, 0xa6, 0x44, 0x0d, 0x9f, 0x5a, +0x55, 0x59, 0x0b, 0xd5, 0x0d, 0x52, 0x48, 0xc5, 0xae, 0x9f, 0xf2, 0x2f, 0x80, 0xc5, 0xea, 0x32, +0x50, 0x35, 0x12, 0x97, 0x2e, 0xc1, 0xe1, 0xff, 0xf1, 0x23, 0x88, 0x51, 0x38, 0x9f, 0xf2, 0x66, +0x56, 0x76, 0xe7, 0x0f, 0x51, 0x97, 0xa5, 0x52, 0x0c, 0x4d, 0x49, 0x51, 0x95, 0x36, 0x3d, 0xbf, +0xa2, 0x4b, 0x0c, 0x10, 0x1d, 0x86, 0x99, 0x4c, 0xaa, 0xf3, 0x72, 0x11, 0x93, 0xe4, 0xea, 0xf6, +0x9b, 0xda, 0xa8, 0x5d, 0xa7, 0x4d, 0xb7, 0x9e, 0x02, 0xae, 0x73, 0x00, 0xc8, 0xda, 0x23, 0x03, +0xe8, 0xf9, 0xea, 0x19, 0x74, 0x62, 0x00, 0x94, 0xcb, 0x22, 0x20, 0xbe, 0x94, 0xa7, 0x59, 0xb5, +0x82, 0x6a, 0xbe, 0x99, 0x79, 0x7a, 0xa9, 0xf2, 0x4a, 0x24, 0x52, 0xf7, 0x74, 0xfd, 0xba, 0x4e, +0xe6, 0xa8, 0x1d, 0x02, 0x6e, 0xb1, 0x0d, 0x80, 0x44, 0xc1, 0xae, 0xd3, 0x23, 0x37, 0x5f, 0xbb, +0x85, 0x7c, 0x2b, 0x92, 0x2e, 0xe8, 0x7e, 0xa5, 0x8b, 0xdd, 0x99, 0xe1, 0xbf, 0x27, 0x6f, 0x2d, +0x5d, 0xaa, 0x7b, 0x87, 0xfe, 0x0a, 0xdd, 0x4b, 0xfc, 0x8e, 0xf5, 0x26, 0xe4, 0x6e, 0x70, 0x42, +0x6e, 0x33, 0xec, 0x31, 0x9e, 0x7b, 0x93, 0xc1, 0xe4, 0xc9, 0x69, 0x1a, 0x3d, 0xc0, 0x6b, 0x4e, +0x22, 0x6d, 0xee, 0xab, 0x58, 0x4d, 0xc6, 0xd0, 0x41, 0xc1, 0x2b, 0xea, 0x4f, 0x12, 0x87, 0x5e, +0xeb, 0x45, 0xd8, 0x6c, 0xf5, 0x98, 0x02, 0xd3, 0xa0, 0xd8, 0x55, 0x8a, 0x06, 0x99, 0x19, 0xa2, +0xa0, 0x77, 0xd1, 0x30, 0x9e, 0xac, 0xcc, 0x75, 0xee, 0x83, 0xf5, 0xb0, 0x62, 0x39, 0xcf, 0x6c, +0x57, 0xe2, 0x4c, 0xd2, 0x91, 0x0b, 0x0e, 0x75, 0x28, 0x1b, 0x9a, 0xbf, 0xfd, 0x1a, 0x43, 0xf1, +0xca, 0x77, 0xfb, 0x3b, 0x8f, 0x61, 0xb8, 0x69, 0x28, 0x16, 0x42, 0x04, 0x5e, 0x70, 0x2a, 0x1c, +0x21, 0xd8, 0x8f, 0xe1, 0xbd, 0x23, 0x5b, 0x2d, 0x74, 0x40, 0x92, 0xd9, 0x63, 0x19, 0x0d, 0x73, +0xdd, 0x69, 0xbc, 0x62, 0x47, 0xbc, 0xe0, 0x74, 0x2b, 0xb2, 0xeb, 0x7d, 0xbe, 0x41, 0x1b, 0xb5, +0xc0, 0x46, 0xc5, 0xa1, 0x22, 0xcb, 0x5f, 0x4e, 0xc1, 0x28, 0x92, 0xde, 0x18, 0xba, 0xd5, 0x2a, +0x28, 0xbb, 0x11, 0x8b, 0x17, 0x93, 0x98, 0x99, 0x60, 0x94, 0x5c, 0x23, 0xcf, 0x5a, 0x27, 0x97, +0x5e, 0x0b, 0x05, 0x06, 0x93, 0x37, 0x1e, 0x3b, 0x69, 0x36, 0xeb, 0xa9, 0x9e, 0x61, 0x1d, 0x8f, +0x32, 0xda, 0x8e, 0x0c, 0xd6, 0x74, 0x3e, 0x7b, 0x09, 0x24, 0xda, 0x01, 0x77, 0x47, 0xc4, 0x3b, +0xcd, 0x34, 0x8c, 0x99, 0xf5, 0xca, 0xe1, 0x25, 0x61, 0x33, 0xb2, 0x59, 0x1b, 0xe2, 0x6e, 0xd7, +0x37, 0x57, 0xb6, 0x0d, 0xa9, 0x12, 0xda, 0x30, 0x82, 0x05, 0x60, 0x30, 0x82, 0x03, 0x48, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x2e, 0xf5, 0x9b, 0x02, 0x28, 0xa7, 0xdb, 0x7a, 0xff, 0xd5, +0xa3, 0xa9, 0xee, 0xbd, 0x03, 0xa0, 0xcf, 0x12, 0x6a, 0x1d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, +0x74, 0x65, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, +0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, +0x20, 0x47, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x31, 0x31, 0x32, 0x32, 0x30, 0x32, +0x36, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x31, 0x31, 0x32, 0x32, 0x30, 0x32, 0x36, +0x33, 0x32, 0x5a, 0x30, 0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x42, 0x4d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x51, 0x75, 0x6f, +0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1e, 0x30, +0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6f, 0x56, 0x61, 0x64, 0x69, 0x73, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20, 0x47, 0x33, 0x30, 0x82, 0x02, +0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, +0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb3, 0xcb, +0x0e, 0x10, 0x67, 0x8e, 0xea, 0x14, 0x97, 0xa7, 0x32, 0x2a, 0x0a, 0x56, 0x36, 0x7f, 0x68, 0x4c, +0xc7, 0xb3, 0x6f, 0x3a, 0x23, 0x14, 0x91, 0xff, 0x19, 0x7f, 0xa5, 0xca, 0xac, 0xee, 0xb3, 0x76, +0x9d, 0x7a, 0xe9, 0x8b, 0x1b, 0xab, 0x6b, 0x31, 0xdb, 0xfa, 0x0b, 0x53, 0x4c, 0xaf, 0xc5, 0xa5, +0x1a, 0x79, 0x3c, 0x8a, 0x4c, 0xff, 0xac, 0xdf, 0x25, 0xde, 0x4e, 0xd9, 0x82, 0x32, 0x0b, 0x44, +0xde, 0xca, 0xdb, 0x8c, 0xac, 0xa3, 0x6e, 0x16, 0x83, 0x3b, 0xa6, 0x64, 0x4b, 0x32, 0x89, 0xfb, +0x16, 0x16, 0x38, 0x7e, 0xeb, 0x43, 0xe2, 0xd3, 0x74, 0x4a, 0xc2, 0x62, 0x0a, 0x73, 0x0a, 0xdd, +0x49, 0xb3, 0x57, 0xd2, 0xb0, 0x0a, 0x85, 0x9d, 0x71, 0x3c, 0xde, 0xa3, 0xcb, 0xc0, 0x32, 0xf3, +0x01, 0x39, 0x20, 0x43, 0x1b, 0x35, 0xd1, 0x53, 0xb3, 0xb1, 0xee, 0xc5, 0x93, 0x69, 0x82, 0x3e, +0x16, 0xb5, 0x28, 0x46, 0xa1, 0xde, 0xea, 0x89, 0x09, 0xed, 0x43, 0xb8, 0x05, 0x46, 0x8a, 0x86, +0xf5, 0x59, 0x47, 0xbe, 0x1b, 0x6f, 0x01, 0x21, 0x10, 0xb9, 0xfd, 0xa9, 0xd2, 0x28, 0xca, 0x10, +0x39, 0x09, 0xca, 0x13, 0x36, 0xcf, 0x9c, 0xad, 0xad, 0x40, 0x74, 0x79, 0x2b, 0x02, 0x3f, 0x34, +0xff, 0xfa, 0x20, 0x69, 0x7d, 0xd3, 0xee, 0x61, 0xf5, 0xba, 0xb3, 0xe7, 0x30, 0xd0, 0x37, 0x23, +0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6f, 0x77, 0xa6, 0x2e, 0x81, 0xbe, 0x07, 0x4d, +0x6f, 0xaf, 0xce, 0xc4, 0x45, 0x13, 0x91, 0x14, 0x70, 0x06, 0x8f, 0x1f, 0x9f, 0xf8, 0x87, 0x69, +0xb1, 0x0e, 0xef, 0xc3, 0x89, 0x19, 0xeb, 0xea, 0x1c, 0x61, 0xfc, 0x7a, 0x6c, 0x8a, 0xdc, 0xd6, +0x03, 0x0b, 0x9e, 0x26, 0xba, 0x12, 0xdd, 0xd4, 0x54, 0x39, 0xab, 0x26, 0xa3, 0x33, 0xea, 0x75, +0x81, 0xda, 0x2d, 0xcd, 0x0f, 0x4f, 0xe4, 0x03, 0xd1, 0xef, 0x15, 0x97, 0x1b, 0x6b, 0x90, 0xc5, +0x02, 0x90, 0x93, 0x66, 0x02, 0x21, 0xb1, 0x47, 0xde, 0x8b, 0x9a, 0x4a, 0x80, 0xb9, 0x55, 0x8f, +0xb5, 0xa2, 0x2f, 0xc0, 0xd6, 0x33, 0x67, 0xda, 0x7e, 0xc4, 0xa7, 0xb4, 0x04, 0x44, 0xeb, 0x47, +0xfb, 0xe6, 0x58, 0xb9, 0xf7, 0x0c, 0xf0, 0x7b, 0x2b, 0xb1, 0xc0, 0x70, 0x29, 0xc3, 0x40, 0x62, +0x2d, 0x3b, 0x48, 0x69, 0xdc, 0x23, 0x3c, 0x48, 0xeb, 0x7b, 0x09, 0x79, 0xa9, 0x6d, 0xda, 0xa8, +0x30, 0x98, 0xcf, 0x80, 0x72, 0x03, 0x88, 0xa6, 0x5b, 0x46, 0xae, 0x72, 0x79, 0x7c, 0x08, 0x03, +0x21, 0x65, 0xae, 0xb7, 0xe1, 0x1c, 0xa5, 0xb1, 0x2a, 0xa2, 0x31, 0xde, 0x66, 0x04, 0xf7, 0xc0, +0x74, 0xe8, 0x71, 0xde, 0xff, 0x3d, 0x59, 0xcc, 0x96, 0x26, 0x12, 0x8b, 0x85, 0x95, 0x57, 0x1a, +0xab, 0x6b, 0x75, 0x0b, 0x44, 0x3d, 0x11, 0x28, 0x3c, 0x7b, 0x61, 0xb7, 0xe2, 0x8f, 0x67, 0x4f, +0xe5, 0xec, 0x3c, 0x4c, 0x60, 0x80, 0x69, 0x57, 0x38, 0x1e, 0x01, 0x5b, 0x8d, 0x55, 0xe8, 0xc7, +0xdf, 0xc0, 0xcc, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7c, 0xf6, 0x98, 0x11, 0xeb, 0x2d, 0xde, 0xed, +0x41, 0x2e, 0x14, 0x05, 0x02, 0x7f, 0xe0, 0xfe, 0x20, 0xeb, 0x35, 0xe7, 0x11, 0xac, 0x22, 0xce, +0x57, 0x3d, 0xde, 0xc9, 0x30, 0x6d, 0x10, 0x03, 0x85, 0xcd, 0xf1, 0xff, 0x8c, 0x16, 0xb5, 0xc1, +0xb2, 0x3e, 0x88, 0x6c, 0x60, 0x7f, 0x90, 0x4f, 0x95, 0xf7, 0xf6, 0x2d, 0xad, 0x01, 0x39, 0x07, +0x04, 0xfa, 0x75, 0x80, 0x7d, 0xbf, 0x49, 0x50, 0xed, 0xef, 0xc9, 0xc4, 0x7c, 0x1c, 0xeb, 0x80, +0x7e, 0xdb, 0xb6, 0xd0, 0xdd, 0x13, 0xfe, 0xc9, 0xd3, 0x9c, 0xd7, 0xb2, 0x97, 0xa9, 0x02, 0x03, +0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0xc6, 0x17, 0xd0, 0xbc, 0xa8, 0xea, 0x02, 0x43, 0xf2, 0x1b, 0x06, 0x99, 0x5d, +0x2b, 0x90, 0x20, 0xb9, 0xd7, 0x9c, 0xe4, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x34, 0x61, 0xd9, 0x56, 0xb5, +0x12, 0x87, 0x55, 0x4d, 0xdd, 0xa3, 0x35, 0x31, 0x46, 0xbb, 0xa4, 0x07, 0x72, 0xbc, 0x5f, 0x61, +0x62, 0xe8, 0xa5, 0xfb, 0x0b, 0x37, 0xb1, 0x3c, 0xb6, 0xb3, 0xfa, 0x29, 0x9d, 0x7f, 0x02, 0xf5, +0xa4, 0xc9, 0xa8, 0x93, 0xb7, 0x7a, 0x71, 0x28, 0x69, 0x8f, 0x73, 0xe1, 0x52, 0x90, 0xda, 0xd5, +0xbe, 0x3a, 0xe5, 0xb7, 0x76, 0x6a, 0x56, 0x80, 0x21, 0xdf, 0x5d, 0xe6, 0xe9, 0x3a, 0x9e, 0xe5, +0x3e, 0xf6, 0xa2, 0x69, 0xc7, 0x2a, 0x0a, 0xb0, 0x18, 0x47, 0xdc, 0x20, 0x70, 0x7d, 0x52, 0xa3, +0x3e, 0x59, 0x7c, 0xc1, 0xba, 0xc9, 0xc8, 0x15, 0x40, 0x61, 0xca, 0x72, 0xd6, 0x70, 0xac, 0xd2, +0xb7, 0xf0, 0x1c, 0xe4, 0x86, 0x29, 0xf0, 0xce, 0xef, 0x68, 0x63, 0xd0, 0xb5, 0x20, 0x8a, 0x15, +0x61, 0x9a, 0x7e, 0x86, 0x98, 0xb4, 0xc9, 0xc2, 0x76, 0xfb, 0xcc, 0xba, 0x30, 0x16, 0xcc, 0xa3, +0x61, 0xc6, 0x74, 0x13, 0xe5, 0x6b, 0xef, 0xa3, 0x15, 0xea, 0x03, 0xfe, 0x13, 0x8b, 0x64, 0xe4, +0xd3, 0xc1, 0xd2, 0xe8, 0x84, 0xfb, 0x49, 0xd1, 0x10, 0x4d, 0x79, 0x66, 0xeb, 0xaa, 0xfd, 0xf4, +0x8d, 0x31, 0x1e, 0x70, 0x14, 0xad, 0xdc, 0xde, 0x67, 0x13, 0x4c, 0x81, 0x15, 0x61, 0xbc, 0xb7, +0xd9, 0x91, 0x77, 0x71, 0x19, 0x81, 0x60, 0xbb, 0xf0, 0x58, 0xa5, 0xb5, 0x9c, 0x0b, 0xf7, 0x8f, +0x22, 0x55, 0x27, 0xc0, 0x4b, 0x01, 0x6d, 0x3b, 0x99, 0x0d, 0xd4, 0x1d, 0x9b, 0x63, 0x67, 0x2f, +0xd0, 0xee, 0x0d, 0xca, 0x66, 0xbc, 0x94, 0x4f, 0xa6, 0xad, 0xed, 0xfc, 0xee, 0x63, 0xac, 0x57, +0x3f, 0x65, 0x25, 0xcf, 0xb2, 0x86, 0x8f, 0xd0, 0x08, 0xff, 0xb8, 0x76, 0x14, 0x6e, 0xde, 0xe5, +0x27, 0xec, 0xab, 0x78, 0xb5, 0x53, 0xb9, 0xb6, 0x3f, 0xe8, 0x20, 0xf9, 0xd2, 0xa8, 0xbe, 0x61, +0x46, 0xca, 0x87, 0x8c, 0x84, 0xf3, 0xf9, 0xf1, 0xa0, 0x68, 0x9b, 0x22, 0x1e, 0x81, 0x26, 0x9b, +0x10, 0x04, 0x91, 0x71, 0xc0, 0x06, 0x1f, 0xdc, 0xa0, 0xd3, 0xb9, 0x56, 0xa7, 0xe3, 0x98, 0x2d, +0x7f, 0x83, 0x9d, 0xdf, 0x8c, 0x2b, 0x9c, 0x32, 0x8e, 0x32, 0x94, 0xf0, 0x01, 0x3c, 0x22, 0x2a, +0x9f, 0x43, 0xc2, 0x2e, 0xc3, 0x98, 0x39, 0x07, 0x38, 0x7b, 0xfc, 0x5e, 0x00, 0x42, 0x1f, 0xf3, +0x32, 0x26, 0x79, 0x83, 0x84, 0xf6, 0xe5, 0xf0, 0xc1, 0x51, 0x12, 0xc0, 0x0b, 0x1e, 0x04, 0x23, +0x0c, 0x54, 0xa5, 0x4c, 0x2f, 0x49, 0xc5, 0x4a, 0xd1, 0xb6, 0x6e, 0x60, 0x0d, 0x6b, 0xfc, 0x6b, +0x8b, 0x85, 0x24, 0x64, 0xb7, 0x89, 0x0e, 0xab, 0x25, 0x47, 0x5b, 0x3c, 0xcf, 0x7e, 0x49, 0xbd, +0xc7, 0xe9, 0x0a, 0xc6, 0xda, 0xf7, 0x7e, 0x0e, 0x17, 0x08, 0xd3, 0x48, 0x97, 0xd0, 0x71, 0x92, +0xf0, 0x0f, 0x39, 0x3e, 0x34, 0x6a, 0x1c, 0x7d, 0xd8, 0xf2, 0x22, 0xae, 0xbb, 0x69, 0xf4, 0x33, +0xb4, 0xa6, 0x48, 0x55, 0xd1, 0x0f, 0x0e, 0x26, 0xe8, 0xec, 0xb6, 0x0b, 0x2d, 0xa7, 0x85, 0x35, +0xcd, 0xfd, 0x59, 0xc8, 0x9f, 0xd1, 0xcd, 0x3e, 0x5a, 0x29, 0x34, 0xb9, 0x3d, 0x84, 0xce, 0xb1, +0x65, 0xd4, 0x59, 0x91, 0x91, 0x56, 0x75, 0x21, 0xc1, 0x77, 0x9e, 0xf9, 0x7a, 0xe1, 0x60, 0x9d, +0xd3, 0xad, 0x04, 0x18, 0xf4, 0x7c, 0xeb, 0x5e, 0x93, 0x8f, 0x53, 0x4a, 0x22, 0x29, 0xf8, 0x48, +0x2b, 0x3e, 0x4d, 0x86, 0xac, 0x5b, 0x7f, 0xcb, 0x06, 0x99, 0x59, 0x60, 0xd8, 0x58, 0x65, 0x95, +0x8d, 0x44, 0xd1, 0xf7, 0x7f, 0x7e, 0x27, 0x7f, 0x7d, 0xae, 0x80, 0xf5, 0x07, 0x4c, 0xb6, 0x3e, +0x9c, 0x71, 0x54, 0x99, 0x04, 0x4b, 0xfd, 0x58, 0xf9, 0x98, 0xf4, 0x30, 0x82, 0x03, 0x6d, 0x30, +0x82, 0x02, 0x55, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x58, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x22, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, +0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x13, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x43, 0x41, 0x31, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x34, 0x30, 0x38, 0x30, 0x34, +0x35, 0x36, 0x34, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x34, 0x30, 0x38, 0x30, 0x34, 0x35, +0x36, 0x34, 0x37, 0x5a, 0x30, 0x58, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x4a, 0x50, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x22, 0x4a, 0x61, +0x70, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, +0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x53, 0x65, 0x63, 0x75, 0x72, +0x65, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x31, 0x31, 0x30, 0x82, +0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xfd, +0x77, 0xaa, 0xa5, 0x1c, 0x90, 0x05, 0x3b, 0xcb, 0x4c, 0x9b, 0x33, 0x8b, 0x5a, 0x14, 0x45, 0xa4, +0xe7, 0x90, 0x16, 0xd1, 0xdf, 0x57, 0xd2, 0x21, 0x10, 0xa4, 0x17, 0xfd, 0xdf, 0xac, 0xd6, 0x1f, +0xa7, 0xe4, 0xdb, 0x7c, 0xf7, 0xec, 0xdf, 0xb8, 0x03, 0xda, 0x94, 0x58, 0xfd, 0x5d, 0x72, 0x7c, +0x8c, 0x3f, 0x5f, 0x01, 0x67, 0x74, 0x15, 0x96, 0xe3, 0x02, 0x3c, 0x87, 0xdb, 0xae, 0xcb, 0x01, +0x8e, 0xc2, 0xf3, 0x66, 0xc6, 0x85, 0x45, 0xf4, 0x02, 0xc6, 0x3a, 0xb5, 0x62, 0xb2, 0xaf, 0xfa, +0x9c, 0xbf, 0xa4, 0xe6, 0xd4, 0x80, 0x30, 0x98, 0xf3, 0x0d, 0xb6, 0x93, 0x8f, 0xa9, 0xd4, 0xd8, +0x36, 0xf2, 0xb0, 0xfc, 0x8a, 0xca, 0x2c, 0xa1, 0x15, 0x33, 0x95, 0x31, 0xda, 0xc0, 0x1b, 0xf2, +0xee, 0x62, 0x99, 0x86, 0x63, 0x3f, 0xbf, 0xdd, 0x93, 0x2a, 0x83, 0xa8, 0x76, 0xb9, 0x13, 0x1f, +0xb7, 0xce, 0x4e, 0x42, 0x85, 0x8f, 0x22, 0xe7, 0x2e, 0x1a, 0xf2, 0x95, 0x09, 0xb2, 0x05, 0xb5, +0x44, 0x4e, 0x77, 0xa1, 0x20, 0xbd, 0xa9, 0xf2, 0x4e, 0x0a, 0x7d, 0x50, 0xad, 0xf5, 0x05, 0x0d, +0x45, 0x4f, 0x46, 0x71, 0xfd, 0x28, 0x3e, 0x53, 0xfb, 0x04, 0xd8, 0x2d, 0xd7, 0x65, 0x1d, 0x4a, +0x1b, 0xfa, 0xcf, 0x3b, 0xb0, 0x31, 0x9a, 0x35, 0x6e, 0xc8, 0x8b, 0x06, 0xd3, 0x00, 0x91, 0xf2, +0x94, 0x08, 0x65, 0x4c, 0xb1, 0x34, 0x06, 0x00, 0x7a, 0x89, 0xe2, 0xf0, 0xc7, 0x03, 0x59, 0xcf, +0xd5, 0xd6, 0xe8, 0xa7, 0x32, 0xb3, 0xe6, 0x98, 0x40, 0x86, 0xc5, 0xcd, 0x27, 0x12, 0x8b, 0xcc, +0x7b, 0xce, 0xb7, 0x11, 0x3c, 0x62, 0x60, 0x07, 0x23, 0x3e, 0x2b, 0x40, 0x6e, 0x94, 0x80, 0x09, +0x6d, 0xb6, 0xb3, 0x6f, 0x77, 0x6f, 0x35, 0x08, 0x50, 0xfb, 0x02, 0x87, 0xc5, 0x3e, 0x89, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0x5b, 0xf8, 0x4d, 0x4f, 0xb2, 0xa5, 0x86, 0xd4, 0x3a, 0xd2, 0xf1, 0x63, 0x9a, +0xa0, 0xbe, 0x09, 0xf6, 0x57, 0xb7, 0xde, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, +0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa0, 0xa1, 0x38, 0x16, +0x66, 0x2e, 0xa7, 0x56, 0x1f, 0x21, 0x9c, 0x06, 0xfa, 0x1d, 0xed, 0xb9, 0x22, 0xc5, 0x38, 0x26, +0xd8, 0x4e, 0x4f, 0xec, 0xa3, 0x7f, 0x79, 0xde, 0x46, 0x21, 0xa1, 0x87, 0x77, 0x8f, 0x07, 0x08, +0x9a, 0xb2, 0xa4, 0xc5, 0xaf, 0x0f, 0x32, 0x98, 0x0b, 0x7c, 0x66, 0x29, 0xb6, 0x9b, 0x7d, 0x25, +0x52, 0x49, 0x43, 0xab, 0x4c, 0x2e, 0x2b, 0x6e, 0x7a, 0x70, 0xaf, 0x16, 0x0e, 0xe3, 0x02, 0x6c, +0xfb, 0x42, 0xe6, 0x18, 0x9d, 0x45, 0xd8, 0x55, 0xc8, 0xe8, 0x3b, 0xdd, 0xe7, 0xe1, 0xf4, 0x2e, +0x0b, 0x1c, 0x34, 0x5c, 0x6c, 0x58, 0x4a, 0xfb, 0x8c, 0x88, 0x50, 0x5f, 0x95, 0x1c, 0xbf, 0xed, +0xab, 0x22, 0xb5, 0x65, 0xb3, 0x85, 0xba, 0x9e, 0x0f, 0xb8, 0xad, 0xe5, 0x7a, 0x1b, 0x8a, 0x50, +0x3a, 0x1d, 0xbd, 0x0d, 0xbc, 0x7b, 0x54, 0x50, 0x0b, 0xb9, 0x42, 0xaf, 0x55, 0xa0, 0x18, 0x81, +0xad, 0x65, 0x99, 0xef, 0xbe, 0xe4, 0x9c, 0xbf, 0xc4, 0x85, 0xab, 0x41, 0xb2, 0x54, 0x6f, 0xdc, +0x25, 0xcd, 0xed, 0x78, 0xe2, 0x8e, 0x0c, 0x8d, 0x09, 0x49, 0xdd, 0x63, 0x7b, 0x5a, 0x69, 0x96, +0x02, 0x21, 0xa8, 0xbd, 0x52, 0x59, 0xe9, 0x7d, 0x35, 0xcb, 0xc8, 0x52, 0xca, 0x7f, 0x81, 0xfe, +0xd9, 0x6b, 0xd3, 0xf7, 0x11, 0xed, 0x25, 0xdf, 0xf8, 0xe7, 0xf9, 0xa4, 0xfa, 0x72, 0x97, 0x84, +0x53, 0x0d, 0xa5, 0xd0, 0x32, 0x18, 0x51, 0x76, 0x59, 0x14, 0x6c, 0x0f, 0xeb, 0xec, 0x5f, 0x80, +0x8c, 0x75, 0x43, 0x83, 0xc3, 0x85, 0x98, 0xff, 0x4c, 0x9e, 0x2d, 0x0d, 0xe4, 0x77, 0x83, 0x93, +0x4e, 0xb5, 0x96, 0x07, 0x8b, 0x28, 0x13, 0x9b, 0x8c, 0x19, 0x8d, 0x41, 0x27, 0x49, 0x40, 0xee, +0xde, 0xe6, 0x23, 0x44, 0x39, 0xdc, 0xa1, 0x22, 0xd6, 0xba, 0x03, 0xf2, 0x30, 0x82, 0x03, 0x5a, +0x30, 0x82, 0x02, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x50, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0f, 0x53, 0x45, 0x43, 0x4f, 0x4d, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, +0x2e, 0x6e, 0x65, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x53, +0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x31, 0x30, 0x1e, 0x17, +0x0d, 0x30, 0x33, 0x30, 0x39, 0x33, 0x30, 0x30, 0x34, 0x32, 0x30, 0x34, 0x39, 0x5a, 0x17, 0x0d, +0x32, 0x33, 0x30, 0x39, 0x33, 0x30, 0x30, 0x34, 0x32, 0x30, 0x34, 0x39, 0x5a, 0x30, 0x50, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x18, 0x30, 0x16, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0f, 0x53, 0x45, 0x43, 0x4f, 0x4d, 0x20, 0x54, 0x72, 0x75, +0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, +0x1e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, +0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x31, 0x30, +0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, +0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, +0xb3, 0xb3, 0xfe, 0x7f, 0xd3, 0x6d, 0xb1, 0xef, 0x16, 0x7c, 0x57, 0xa5, 0x0c, 0x6d, 0x76, 0x8a, +0x2f, 0x4b, 0xbf, 0x64, 0xfb, 0x4c, 0xee, 0x8a, 0xf0, 0xf3, 0x29, 0x7c, 0xf5, 0xff, 0xee, 0x2a, +0xe0, 0xe9, 0xe9, 0xba, 0x5b, 0x64, 0x22, 0x9a, 0x9a, 0x6f, 0x2c, 0x3a, 0x26, 0x69, 0x51, 0x05, +0x99, 0x26, 0xdc, 0xd5, 0x1c, 0x6a, 0x71, 0xc6, 0x9a, 0x7d, 0x1e, 0x9d, 0xdd, 0x7c, 0x6c, 0xc6, +0x8c, 0x67, 0x67, 0x4a, 0x3e, 0xf8, 0x71, 0xb0, 0x19, 0x27, 0xa9, 0x09, 0x0c, 0xa6, 0x95, 0xbf, +0x4b, 0x8c, 0x0c, 0xfa, 0x55, 0x98, 0x3b, 0xd8, 0xe8, 0x22, 0xa1, 0x4b, 0x71, 0x38, 0x79, 0xac, +0x97, 0x92, 0x69, 0xb3, 0x89, 0x7e, 0xea, 0x21, 0x68, 0x06, 0x98, 0x14, 0x96, 0x87, 0xd2, 0x61, +0x36, 0xbc, 0x6d, 0x27, 0x56, 0x9e, 0x57, 0xee, 0xc0, 0xc0, 0x56, 0xfd, 0x32, 0xcf, 0xa4, 0xd9, +0x8e, 0xc2, 0x23, 0xd7, 0x8d, 0xa8, 0xf3, 0xd8, 0x25, 0xac, 0x97, 0xe4, 0x70, 0x38, 0xf4, 0xb6, +0x3a, 0xb4, 0x9d, 0x3b, 0x97, 0x26, 0x43, 0xa3, 0xa1, 0xbc, 0x49, 0x59, 0x72, 0x4c, 0x23, 0x30, +0x87, 0x01, 0x58, 0xf6, 0x4e, 0xbe, 0x1c, 0x68, 0x56, 0x66, 0xaf, 0xcd, 0x41, 0x5d, 0xc8, 0xb3, +0x4d, 0x2a, 0x55, 0x46, 0xab, 0x1f, 0xda, 0x1e, 0xe2, 0x40, 0x3d, 0xdb, 0xcd, 0x7d, 0xb9, 0x92, +0x80, 0x9c, 0x37, 0xdd, 0x0c, 0x96, 0x64, 0x9d, 0xdc, 0x22, 0xf7, 0x64, 0x8b, 0xdf, 0x61, 0xde, +0x15, 0x94, 0x52, 0x15, 0xa0, 0x7d, 0x52, 0xc9, 0x4b, 0xa8, 0x21, 0xc9, 0xc6, 0xb1, 0xed, 0xcb, +0xc3, 0x95, 0x60, 0xd1, 0x0f, 0xf0, 0xab, 0x70, 0xf8, 0xdf, 0xcb, 0x4d, 0x7e, 0xec, 0xd6, 0xfa, +0xab, 0xd9, 0xbd, 0x7f, 0x54, 0xf2, 0xa5, 0xe9, 0x79, 0xfa, 0xd9, 0xd6, 0x76, 0x24, 0x28, 0x73, +0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x3f, 0x30, 0x3d, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, +0x04, 0x16, 0x04, 0x14, 0xa0, 0x73, 0x49, 0x99, 0x68, 0xdc, 0x85, 0x5b, 0x65, 0xe3, 0x9b, 0x28, +0x2f, 0x57, 0x9f, 0xbd, 0x33, 0xbc, 0x07, 0x48, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x68, 0x40, 0xa9, 0xa8, 0xbb, 0xe4, +0x4f, 0x5d, 0x79, 0xb3, 0x05, 0xb5, 0x17, 0xb3, 0x60, 0x13, 0xeb, 0xc6, 0x92, 0x5d, 0xe0, 0xd1, +0xd3, 0x6a, 0xfe, 0xfb, 0xbe, 0x9b, 0x6d, 0xbf, 0xc7, 0x05, 0x6d, 0x59, 0x20, 0xc4, 0x1c, 0xf0, +0xb7, 0xda, 0x84, 0x58, 0x02, 0x63, 0xfa, 0x48, 0x16, 0xef, 0x4f, 0xa5, 0x0b, 0xf7, 0x4a, 0x98, +0xf2, 0x3f, 0x9e, 0x1b, 0xad, 0x47, 0x6b, 0x63, 0xce, 0x08, 0x47, 0xeb, 0x52, 0x3f, 0x78, 0x9c, +0xaf, 0x4d, 0xae, 0xf8, 0xd5, 0x4f, 0xcf, 0x9a, 0x98, 0x2a, 0x10, 0x41, 0x39, 0x52, 0xc4, 0xdd, +0xd9, 0x9b, 0x0e, 0xef, 0x93, 0x01, 0xae, 0xb2, 0x2e, 0xca, 0x68, 0x42, 0x24, 0x42, 0x6c, 0xb0, +0xb3, 0x3a, 0x3e, 0xcd, 0xe9, 0xda, 0x48, 0xc4, 0x15, 0xcb, 0xe9, 0xf9, 0x07, 0x0f, 0x92, 0x50, +0x49, 0x8a, 0xdd, 0x31, 0x97, 0x5f, 0xc9, 0xe9, 0x37, 0xaa, 0x3b, 0x59, 0x65, 0x97, 0x94, 0x32, +0xc9, 0xb3, 0x9f, 0x3e, 0x3a, 0x62, 0x58, 0xc5, 0x49, 0xad, 0x62, 0x0e, 0x71, 0xa5, 0x32, 0xaa, +0x2f, 0xc6, 0x89, 0x76, 0x43, 0x40, 0x13, 0x13, 0x67, 0x3d, 0xa2, 0x54, 0x25, 0x10, 0xcb, 0xf1, +0x3a, 0xf2, 0xd9, 0xfa, 0xdb, 0x49, 0x56, 0xbb, 0xa6, 0xfe, 0xa7, 0x41, 0x35, 0xc3, 0xe0, 0x88, +0x61, 0xc9, 0x88, 0xc7, 0xdf, 0x36, 0x10, 0x22, 0x98, 0x59, 0xea, 0xb0, 0x4a, 0xfb, 0x56, 0x16, +0x73, 0x6e, 0xac, 0x4d, 0xf7, 0x22, 0xa1, 0x4f, 0xad, 0x1d, 0x7a, 0x2d, 0x45, 0x27, 0xe5, 0x30, +0xc1, 0x5e, 0xf2, 0xda, 0x13, 0xcb, 0x25, 0x42, 0x51, 0x95, 0x47, 0x03, 0x8c, 0x6c, 0x21, 0xcc, +0x74, 0x42, 0xed, 0x53, 0xff, 0x33, 0x8b, 0x8f, 0x0f, 0x57, 0x01, 0x16, 0x2f, 0xcf, 0xa6, 0xee, +0xc9, 0x70, 0x22, 0x14, 0xbd, 0xfd, 0xbe, 0x6c, 0x0b, 0x03, 0x30, 0x82, 0x03, 0x77, 0x30, 0x82, +0x02, 0x5f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x5d, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x1c, 0x53, 0x45, 0x43, 0x4f, 0x4d, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, +0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x43, 0x4f, 0x2e, 0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x31, +0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, +0x74, 0x79, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x35, +0x32, 0x39, 0x30, 0x35, 0x30, 0x30, 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x35, 0x32, +0x39, 0x30, 0x35, 0x30, 0x30, 0x33, 0x39, 0x5a, 0x30, 0x5d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x1c, 0x53, 0x45, 0x43, 0x4f, 0x4d, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, 0x79, +0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x43, 0x4f, 0x2e, 0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x31, 0x27, +0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, +0x79, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, +0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd0, 0x15, 0x39, 0x52, 0xb1, 0x52, 0xb3, 0xba, +0xc5, 0x59, 0x82, 0xc4, 0x5d, 0x52, 0xae, 0x3a, 0x43, 0x65, 0x80, 0x4b, 0xc7, 0xf2, 0x96, 0xbc, +0xdb, 0x36, 0x97, 0xd6, 0xa6, 0x64, 0x8c, 0xa8, 0x5e, 0xf0, 0xe3, 0x0a, 0x1c, 0xf7, 0xdf, 0x97, +0x3d, 0x4b, 0xae, 0xf6, 0x5d, 0xec, 0x21, 0xb5, 0x41, 0xab, 0xcd, 0xb9, 0x7e, 0x76, 0x9f, 0xbe, +0xf9, 0x3e, 0x36, 0x34, 0xa0, 0x3b, 0xc1, 0xf6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3d, 0x57, 0x80, +0xc5, 0xf9, 0x89, 0x99, 0xca, 0xe5, 0xab, 0x6a, 0xd4, 0xb5, 0xda, 0x41, 0x90, 0x10, 0xc1, 0xd6, +0xd6, 0x42, 0x89, 0xc2, 0xbf, 0xf4, 0x38, 0x12, 0x95, 0x4c, 0x54, 0x05, 0xf7, 0x36, 0xe4, 0x45, +0x83, 0x7b, 0x14, 0x65, 0xd6, 0xdc, 0x0c, 0x4d, 0xd1, 0xde, 0x7e, 0x0c, 0xab, 0x3b, 0xc4, 0x15, +0xbe, 0x3a, 0x56, 0xa6, 0x5a, 0x6f, 0x76, 0x69, 0x52, 0xa9, 0x7a, 0xb9, 0xc8, 0xeb, 0x6a, 0x9a, +0x5d, 0x52, 0xd0, 0x2d, 0x0a, 0x6b, 0x35, 0x16, 0x09, 0x10, 0x84, 0xd0, 0x6a, 0xca, 0x3a, 0x06, +0x00, 0x37, 0x47, 0xe4, 0x7e, 0x57, 0x4f, 0x3f, 0x8b, 0xeb, 0x67, 0xb8, 0x88, 0xaa, 0xc5, 0xbe, +0x53, 0x55, 0xb2, 0x91, 0xc4, 0x7d, 0xb9, 0xb0, 0x85, 0x19, 0x06, 0x78, 0x2e, 0xdb, 0x61, 0x1a, +0xfa, 0x85, 0xf5, 0x4a, 0x91, 0xa1, 0xe7, 0x16, 0xd5, 0x8e, 0xa2, 0x39, 0xdf, 0x94, 0xb8, 0x70, +0x1f, 0x28, 0x3f, 0x8b, 0xfc, 0x40, 0x5e, 0x63, 0x83, 0x3c, 0x83, 0x2a, 0x1a, 0x99, 0x6b, 0xcf, +0xde, 0x59, 0x6a, 0x3b, 0xfc, 0x6f, 0x16, 0xd7, 0x1f, 0xfd, 0x4a, 0x10, 0xeb, 0x4e, 0x82, 0x16, +0x3a, 0xac, 0x27, 0x0c, 0x53, 0xf1, 0xad, 0xd5, 0x24, 0xb0, 0x6b, 0x03, 0x50, 0xc1, 0x2d, 0x3c, +0x16, 0xdd, 0x44, 0x34, 0x27, 0x1a, 0x75, 0xfb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, +0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x0a, 0x85, 0xa9, 0x77, +0x65, 0x05, 0x98, 0x7c, 0x40, 0x81, 0xf8, 0x0f, 0x97, 0x2c, 0x38, 0xf1, 0x0a, 0xec, 0x3c, 0xcf, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0x3a, 0xa3, 0x44, 0xac, 0xb9, 0x45, 0xb1, 0xc7, 0x93, 0x7e, +0xc8, 0x0b, 0x0a, 0x42, 0xdf, 0x64, 0xea, 0x1c, 0xee, 0x59, 0x6c, 0x08, 0xba, 0x89, 0x5f, 0x6a, +0xca, 0x4a, 0x95, 0x9e, 0x7a, 0x8f, 0x07, 0xc5, 0xda, 0x45, 0x72, 0x82, 0x71, 0x0e, 0x3a, 0xd2, +0xcc, 0x6f, 0xa7, 0xb4, 0xa1, 0x23, 0xbb, 0xf6, 0x24, 0x9f, 0xcb, 0x17, 0xfe, 0x8c, 0xa6, 0xce, +0xc2, 0xd2, 0xdb, 0xcc, 0x8d, 0xfc, 0x71, 0xfc, 0x03, 0x29, 0xc1, 0x6c, 0x5d, 0x33, 0x5f, 0x64, +0xb6, 0x65, 0x3b, 0x89, 0x6f, 0x18, 0x76, 0x78, 0xf5, 0xdc, 0xa2, 0x48, 0x1f, 0x19, 0x3f, 0x8e, +0x93, 0xeb, 0xf1, 0xfa, 0x17, 0xee, 0xcd, 0x4e, 0xe3, 0x04, 0x12, 0x55, 0xd6, 0xe5, 0xe4, 0xdd, +0xfb, 0x3e, 0x05, 0x7c, 0xe2, 0x1d, 0x5e, 0xc6, 0xa7, 0xbc, 0x97, 0x4f, 0x68, 0x3a, 0xf5, 0xe9, +0x2e, 0x0a, 0x43, 0xb6, 0xaf, 0x57, 0x5c, 0x62, 0x68, 0x7c, 0xb7, 0xfd, 0xa3, 0x8a, 0x84, 0xa0, +0xac, 0x62, 0xbe, 0x2b, 0x09, 0x87, 0x34, 0xf0, 0x6a, 0x01, 0xbb, 0x9b, 0x29, 0x56, 0x3c, 0xfe, +0x00, 0x37, 0xcf, 0x23, 0x6c, 0xf1, 0x4e, 0xaa, 0xb6, 0x74, 0x46, 0x12, 0x6c, 0x91, 0xee, 0x34, +0xd5, 0xec, 0x9a, 0x91, 0xe7, 0x44, 0xbe, 0x90, 0x31, 0x72, 0xd5, 0x49, 0x02, 0xf6, 0x02, 0xe5, +0xf4, 0x1f, 0xeb, 0x7c, 0xd9, 0x96, 0x55, 0xa9, 0xff, 0xec, 0x8a, 0xf9, 0x99, 0x47, 0xff, 0x35, +0x5a, 0x02, 0xaa, 0x04, 0xcb, 0x8a, 0x5b, 0x87, 0x71, 0x29, 0x91, 0xbd, 0xa4, 0xb4, 0x7a, 0x0d, +0xbd, 0x9a, 0xf5, 0x57, 0x23, 0x00, 0x07, 0x21, 0x17, 0x3f, 0x4a, 0x39, 0xd1, 0x05, 0x49, 0x0b, +0xa7, 0xb6, 0x37, 0x81, 0xa5, 0x5d, 0x8c, 0xaa, 0x33, 0x5e, 0x81, 0x28, 0x7c, 0xa7, 0x7d, 0x27, +0xeb, 0x00, 0xae, 0x8d, 0x37, 0x30, 0x82, 0x05, 0xd8, 0x30, 0x82, 0x03, 0xc0, 0xa0, 0x03, 0x02, +0x01, 0x02, 0x02, 0x10, 0x4c, 0xaa, 0xf9, 0xca, 0xdb, 0x63, 0x6f, 0xe0, 0x1f, 0xf7, 0x4e, 0xd8, +0x5b, 0x03, 0x86, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0c, 0x05, 0x00, 0x30, 0x81, 0x85, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, +0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, +0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, +0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, +0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2b, +0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, +0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x30, 0x30, 0x31, 0x31, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, +0x30, 0x31, 0x31, 0x38, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x85, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, +0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, +0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, +0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, +0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x22, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, +0x69, 0x74, 0x79, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, +0x82, 0x02, 0x01, 0x00, 0x91, 0xe8, 0x54, 0x92, 0xd2, 0x0a, 0x56, 0xb1, 0xac, 0x0d, 0x24, 0xdd, +0xc5, 0xcf, 0x44, 0x67, 0x74, 0x99, 0x2b, 0x37, 0xa3, 0x7d, 0x23, 0x70, 0x00, 0x71, 0xbc, 0x53, +0xdf, 0xc4, 0xfa, 0x2a, 0x12, 0x8f, 0x4b, 0x7f, 0x10, 0x56, 0xbd, 0x9f, 0x70, 0x72, 0xb7, 0x61, +0x7f, 0xc9, 0x4b, 0x0f, 0x17, 0xa7, 0x3d, 0xe3, 0xb0, 0x04, 0x61, 0xee, 0xff, 0x11, 0x97, 0xc7, +0xf4, 0x86, 0x3e, 0x0a, 0xfa, 0x3e, 0x5c, 0xf9, 0x93, 0xe6, 0x34, 0x7a, 0xd9, 0x14, 0x6b, 0xe7, +0x9c, 0xb3, 0x85, 0xa0, 0x82, 0x7a, 0x76, 0xaf, 0x71, 0x90, 0xd7, 0xec, 0xfd, 0x0d, 0xfa, 0x9c, +0x6c, 0xfa, 0xdf, 0xb0, 0x82, 0xf4, 0x14, 0x7e, 0xf9, 0xbe, 0xc4, 0xa6, 0x2f, 0x4f, 0x7f, 0x99, +0x7f, 0xb5, 0xfc, 0x67, 0x43, 0x72, 0xbd, 0x0c, 0x00, 0xd6, 0x89, 0xeb, 0x6b, 0x2c, 0xd3, 0xed, +0x8f, 0x98, 0x1c, 0x14, 0xab, 0x7e, 0xe5, 0xe3, 0x6e, 0xfc, 0xd8, 0xa8, 0xe4, 0x92, 0x24, 0xda, +0x43, 0x6b, 0x62, 0xb8, 0x55, 0xfd, 0xea, 0xc1, 0xbc, 0x6c, 0xb6, 0x8b, 0xf3, 0x0e, 0x8d, 0x9a, +0xe4, 0x9b, 0x6c, 0x69, 0x99, 0xf8, 0x78, 0x48, 0x30, 0x45, 0xd5, 0xad, 0xe1, 0x0d, 0x3c, 0x45, +0x60, 0xfc, 0x32, 0x96, 0x51, 0x27, 0xbc, 0x67, 0xc3, 0xca, 0x2e, 0xb6, 0x6b, 0xea, 0x46, 0xc7, +0xc7, 0x20, 0xa0, 0xb1, 0x1f, 0x65, 0xde, 0x48, 0x08, 0xba, 0xa4, 0x4e, 0xa9, 0xf2, 0x83, 0x46, +0x37, 0x84, 0xeb, 0xe8, 0xcc, 0x81, 0x48, 0x43, 0x67, 0x4e, 0x72, 0x2a, 0x9b, 0x5c, 0xbd, 0x4c, +0x1b, 0x28, 0x8a, 0x5c, 0x22, 0x7b, 0xb4, 0xab, 0x98, 0xd9, 0xee, 0xe0, 0x51, 0x83, 0xc3, 0x09, +0x46, 0x4e, 0x6d, 0x3e, 0x99, 0xfa, 0x95, 0x17, 0xda, 0x7c, 0x33, 0x57, 0x41, 0x3c, 0x8d, 0x51, +0xed, 0x0b, 0xb6, 0x5c, 0xaf, 0x2c, 0x63, 0x1a, 0xdf, 0x57, 0xc8, 0x3f, 0xbc, 0xe9, 0x5d, 0xc4, +0x9b, 0xaf, 0x45, 0x99, 0xe2, 0xa3, 0x5a, 0x24, 0xb4, 0xba, 0xa9, 0x56, 0x3d, 0xcf, 0x6f, 0xaa, +0xff, 0x49, 0x58, 0xbe, 0xf0, 0xa8, 0xff, 0xf4, 0xb8, 0xad, 0xe9, 0x37, 0xfb, 0xba, 0xb8, 0xf4, +0x0b, 0x3a, 0xf9, 0xe8, 0x43, 0x42, 0x1e, 0x89, 0xd8, 0x84, 0xcb, 0x13, 0xf1, 0xd9, 0xbb, 0xe1, +0x89, 0x60, 0xb8, 0x8c, 0x28, 0x56, 0xac, 0x14, 0x1d, 0x9c, 0x0a, 0xe7, 0x71, 0xeb, 0xcf, 0x0e, +0xdd, 0x3d, 0xa9, 0x96, 0xa1, 0x48, 0xbd, 0x3c, 0xf7, 0xaf, 0xb5, 0x0d, 0x22, 0x4c, 0xc0, 0x11, +0x81, 0xec, 0x56, 0x3b, 0xf6, 0xd3, 0xa2, 0xe2, 0x5b, 0xb7, 0xb2, 0x04, 0x22, 0x52, 0x95, 0x80, +0x93, 0x69, 0xe8, 0x8e, 0x4c, 0x65, 0xf1, 0x91, 0x03, 0x2d, 0x70, 0x74, 0x02, 0xea, 0x8b, 0x67, +0x15, 0x29, 0x69, 0x52, 0x02, 0xbb, 0xd7, 0xdf, 0x50, 0x6a, 0x55, 0x46, 0xbf, 0xa0, 0xa3, 0x28, +0x61, 0x7f, 0x70, 0xd0, 0xc3, 0xa2, 0xaa, 0x2c, 0x21, 0xaa, 0x47, 0xce, 0x28, 0x9c, 0x06, 0x45, +0x76, 0xbf, 0x82, 0x18, 0x27, 0xb4, 0xd5, 0xae, 0xb4, 0xcb, 0x50, 0xe6, 0x6b, 0xf4, 0x4c, 0x86, +0x71, 0x30, 0xe9, 0xa6, 0xdf, 0x16, 0x86, 0xe0, 0xd8, 0xff, 0x40, 0xdd, 0xfb, 0xd0, 0x42, 0x88, +0x7f, 0xa3, 0x33, 0x3a, 0x2e, 0x5c, 0x1e, 0x41, 0x11, 0x81, 0x63, 0xce, 0x18, 0x71, 0x6b, 0x2b, +0xec, 0xa6, 0x8a, 0xb7, 0x31, 0x5c, 0x3a, 0x6a, 0x47, 0xe0, 0xc3, 0x79, 0x59, 0xd6, 0x20, 0x1a, +0xaf, 0xf2, 0x6a, 0x98, 0xaa, 0x72, 0xbc, 0x57, 0x4a, 0xd2, 0x4b, 0x9d, 0xbb, 0x10, 0xfc, 0xb0, +0x4c, 0x41, 0xe5, 0xed, 0x1d, 0x3d, 0x5e, 0x28, 0x9d, 0x9c, 0xcc, 0xbf, 0xb3, 0x51, 0xda, 0xa7, +0x47, 0xe5, 0x84, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, +0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xbb, 0xaf, 0x7e, 0x02, 0x3d, 0xfa, 0xa6, 0xf1, +0x3c, 0x84, 0x8e, 0xad, 0xee, 0x38, 0x98, 0xec, 0xd9, 0x32, 0x32, 0xd4, 0x30, 0x0e, 0x06, 0x03, +0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, +0x00, 0x0a, 0xf1, 0xd5, 0x46, 0x84, 0xb7, 0xae, 0x51, 0xbb, 0x6c, 0xb2, 0x4d, 0x41, 0x14, 0x00, +0x93, 0x4c, 0x9c, 0xcb, 0xe5, 0xc0, 0x54, 0xcf, 0xa0, 0x25, 0x8e, 0x02, 0xf9, 0xfd, 0xb0, 0xa2, +0x0d, 0xf5, 0x20, 0x98, 0x3c, 0x13, 0x2d, 0xac, 0x56, 0xa2, 0xb0, 0xd6, 0x7e, 0x11, 0x92, 0xe9, +0x2e, 0xba, 0x9e, 0x2e, 0x9a, 0x72, 0xb1, 0xbd, 0x19, 0x44, 0x6c, 0x61, 0x35, 0xa2, 0x9a, 0xb4, +0x16, 0x12, 0x69, 0x5a, 0x8c, 0xe1, 0xd7, 0x3e, 0xa4, 0x1a, 0xe8, 0x2f, 0x03, 0xf4, 0xae, 0x61, +0x1d, 0x10, 0x1b, 0x2a, 0xa4, 0x8b, 0x7a, 0xc5, 0xfe, 0x05, 0xa6, 0xe1, 0xc0, 0xd6, 0xc8, 0xfe, +0x9e, 0xae, 0x8f, 0x2b, 0xba, 0x3d, 0x99, 0xf8, 0xd8, 0x73, 0x09, 0x58, 0x46, 0x6e, 0xa6, 0x9c, +0xf4, 0xd7, 0x27, 0xd3, 0x95, 0xda, 0x37, 0x83, 0x72, 0x1c, 0xd3, 0x73, 0xe0, 0xa2, 0x47, 0x99, +0x03, 0x38, 0x5d, 0xd5, 0x49, 0x79, 0x00, 0x29, 0x1c, 0xc7, 0xec, 0x9b, 0x20, 0x1c, 0x07, 0x24, +0x69, 0x57, 0x78, 0xb2, 0x39, 0xfc, 0x3a, 0x84, 0xa0, 0xb5, 0x9c, 0x7c, 0x8d, 0xbf, 0x2e, 0x93, +0x62, 0x27, 0xb7, 0x39, 0xda, 0x17, 0x18, 0xae, 0xbd, 0x3c, 0x09, 0x68, 0xff, 0x84, 0x9b, 0x3c, +0xd5, 0xd6, 0x0b, 0x03, 0xe3, 0x57, 0x9e, 0x14, 0xf7, 0xd1, 0xeb, 0x4f, 0xc8, 0xbd, 0x87, 0x23, +0xb7, 0xb6, 0x49, 0x43, 0x79, 0x85, 0x5c, 0xba, 0xeb, 0x92, 0x0b, 0xa1, 0xc6, 0xe8, 0x68, 0xa8, +0x4c, 0x16, 0xb1, 0x1a, 0x99, 0x0a, 0xe8, 0x53, 0x2c, 0x92, 0xbb, 0xa1, 0x09, 0x18, 0x75, 0x0c, +0x65, 0xa8, 0x7b, 0xcb, 0x23, 0xb7, 0x1a, 0xc2, 0x28, 0x85, 0xc3, 0x1b, 0xff, 0xd0, 0x2b, 0x62, +0xef, 0xa4, 0x7b, 0x09, 0x91, 0x98, 0x67, 0x8c, 0x14, 0x01, 0xcd, 0x68, 0x06, 0x6a, 0x63, 0x21, +0x75, 0x03, 0x80, 0x88, 0x8a, 0x6e, 0x81, 0xc6, 0x85, 0xf2, 0xa9, 0xa4, 0x2d, 0xe7, 0xf4, 0xa5, +0x24, 0x10, 0x47, 0x83, 0xca, 0xcd, 0xf4, 0x8d, 0x79, 0x58, 0xb1, 0x06, 0x9b, 0xe7, 0x1a, 0x2a, +0xd9, 0x9d, 0x01, 0xd7, 0x94, 0x7d, 0xed, 0x03, 0x4a, 0xca, 0xf0, 0xdb, 0xe8, 0xa9, 0x01, 0x3e, +0xf5, 0x56, 0x99, 0xc9, 0x1e, 0x8e, 0x49, 0x3d, 0xbb, 0xe5, 0x09, 0xb9, 0xe0, 0x4f, 0x49, 0x92, +0x3d, 0x16, 0x82, 0x40, 0xcc, 0xcc, 0x59, 0xc6, 0xe6, 0x3a, 0xed, 0x12, 0x2e, 0x69, 0x3c, 0x6c, +0x95, 0xb1, 0xfd, 0xaa, 0x1d, 0x7b, 0x7f, 0x86, 0xbe, 0x1e, 0x0e, 0x32, 0x46, 0xfb, 0xfb, 0x13, +0x8f, 0x75, 0x7f, 0x4c, 0x8b, 0x4b, 0x46, 0x63, 0xfe, 0x00, 0x34, 0x40, 0x70, 0xc1, 0xc3, 0xb9, +0xa1, 0xdd, 0xa6, 0x70, 0xe2, 0x04, 0xb3, 0x41, 0xbc, 0xe9, 0x80, 0x91, 0xea, 0x64, 0x9c, 0x7a, +0xe1, 0x22, 0x03, 0xa9, 0x9c, 0x6e, 0x6f, 0x0e, 0x65, 0x4f, 0x6c, 0x87, 0x87, 0x5e, 0xf3, 0x6e, +0xa0, 0xf9, 0x75, 0xa5, 0x9b, 0x40, 0xe8, 0x53, 0xb2, 0x27, 0x9d, 0x4a, 0xb9, 0xc0, 0x77, 0x21, +0x8d, 0xff, 0x87, 0xf2, 0xde, 0xbc, 0x8c, 0xef, 0x17, 0xdf, 0xb7, 0x49, 0x0b, 0xd1, 0xf2, 0x6e, +0x30, 0x0b, 0x1a, 0x0e, 0x4e, 0x76, 0xed, 0x11, 0xfc, 0xf5, 0xe9, 0x56, 0xb2, 0x7d, 0xbf, 0xc7, +0x6d, 0x0a, 0x93, 0x8c, 0xa5, 0xd0, 0xc0, 0xb6, 0x1d, 0xbe, 0x3a, 0x4e, 0x94, 0xa2, 0xd7, 0x6e, +0x6c, 0x0b, 0xc2, 0x8a, 0x7c, 0xfa, 0x20, 0xf3, 0xc4, 0xe4, 0xe5, 0xcd, 0x0d, 0xa8, 0xcb, 0x91, +0x92, 0xb1, 0x7c, 0x85, 0xec, 0xb5, 0x14, 0x69, 0x66, 0x0e, 0x82, 0xe7, 0xcd, 0xce, 0xc8, 0x2d, +0xa6, 0x51, 0x7f, 0x21, 0xc1, 0x35, 0x53, 0x85, 0x06, 0x4a, 0x5d, 0x9f, 0xad, 0xbb, 0x1b, 0x5f, +0x74, 0x30, 0x82, 0x04, 0x0f, 0x30, 0x82, 0x02, 0xf7, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, +0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, +0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, +0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, +0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, +0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, +0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, +0x30, 0x36, 0x32, 0x39, 0x31, 0x37, 0x33, 0x39, 0x31, 0x36, 0x5a, 0x17, 0x0d, 0x33, 0x34, 0x30, +0x36, 0x32, 0x39, 0x31, 0x37, 0x33, 0x39, 0x31, 0x36, 0x5a, 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, +0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, +0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, +0x69, 0x65, 0x6c, 0x64, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0d, 0x00, 0x30, 0x82, 0x01, 0x08, +0x02, 0x82, 0x01, 0x01, 0x00, 0xb7, 0x32, 0xc8, 0xfe, 0xe9, 0x71, 0xa6, 0x04, 0x85, 0xad, 0x0c, +0x11, 0x64, 0xdf, 0xce, 0x4d, 0xef, 0xc8, 0x03, 0x18, 0x87, 0x3f, 0xa1, 0xab, 0xfb, 0x3c, 0xa6, +0x9f, 0xf0, 0xc3, 0xa1, 0xda, 0xd4, 0xd8, 0x6e, 0x2b, 0x53, 0x90, 0xfb, 0x24, 0xa4, 0x3e, 0x84, +0xf0, 0x9e, 0xe8, 0x5f, 0xec, 0xe5, 0x27, 0x44, 0xf5, 0x28, 0xa6, 0x3f, 0x7b, 0xde, 0xe0, 0x2a, +0xf0, 0xc8, 0xaf, 0x53, 0x2f, 0x9e, 0xca, 0x05, 0x01, 0x93, 0x1e, 0x8f, 0x66, 0x1c, 0x39, 0xa7, +0x4d, 0xfa, 0x5a, 0xb6, 0x73, 0x04, 0x25, 0x66, 0xeb, 0x77, 0x7f, 0xe7, 0x59, 0xc6, 0x4a, 0x99, +0x25, 0x14, 0x54, 0xeb, 0x26, 0xc7, 0xf3, 0x7f, 0x19, 0xd5, 0x30, 0x70, 0x8f, 0xaf, 0xb0, 0x46, +0x2a, 0xff, 0xad, 0xeb, 0x29, 0xed, 0xd7, 0x9f, 0xaa, 0x04, 0x87, 0xa3, 0xd4, 0xf9, 0x89, 0xa5, +0x34, 0x5f, 0xdb, 0x43, 0x91, 0x82, 0x36, 0xd9, 0x66, 0x3c, 0xb1, 0xb8, 0xb9, 0x82, 0xfd, 0x9c, +0x3a, 0x3e, 0x10, 0xc8, 0x3b, 0xef, 0x06, 0x65, 0x66, 0x7a, 0x9b, 0x19, 0x18, 0x3d, 0xff, 0x71, +0x51, 0x3c, 0x30, 0x2e, 0x5f, 0xbe, 0x3d, 0x77, 0x73, 0xb2, 0x5d, 0x06, 0x6c, 0xc3, 0x23, 0x56, +0x9a, 0x2b, 0x85, 0x26, 0x92, 0x1c, 0xa7, 0x02, 0xb3, 0xe4, 0x3f, 0x0d, 0xaf, 0x08, 0x79, 0x82, +0xb8, 0x36, 0x3d, 0xea, 0x9c, 0xd3, 0x35, 0xb3, 0xbc, 0x69, 0xca, 0xf5, 0xcc, 0x9d, 0xe8, 0xfd, +0x64, 0x8d, 0x17, 0x80, 0x33, 0x6e, 0x5e, 0x4a, 0x5d, 0x99, 0xc9, 0x1e, 0x87, 0xb4, 0x9d, 0x1a, +0xc0, 0xd5, 0x6e, 0x13, 0x35, 0x23, 0x5e, 0xdf, 0x9b, 0x5f, 0x3d, 0xef, 0xd6, 0xf7, 0x76, 0xc2, +0xea, 0x3e, 0xbb, 0x78, 0x0d, 0x1c, 0x42, 0x67, 0x6b, 0x04, 0xd8, 0xf8, 0xd6, 0xda, 0x6f, 0x8b, +0xf2, 0x44, 0xa0, 0x01, 0xab, 0x02, 0x01, 0x03, 0xa3, 0x81, 0xc5, 0x30, 0x81, 0xc2, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xbf, 0x5f, 0xb7, 0xd1, 0xce, 0xdd, 0x1f, +0x86, 0xf4, 0x5b, 0x55, 0xac, 0xdc, 0xd7, 0x10, 0xc2, 0x0e, 0xa9, 0x88, 0xe7, 0x30, 0x81, 0x92, +0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0x8a, 0x30, 0x81, 0x87, 0x80, 0x14, 0xbf, 0x5f, 0xb7, +0xd1, 0xce, 0xdd, 0x1f, 0x86, 0xf4, 0x5b, 0x55, 0xac, 0xdc, 0xd7, 0x10, 0xc2, 0x0e, 0xa9, 0x88, +0xe7, 0xa1, 0x6c, 0xa4, 0x6a, 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, +0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, +0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x32, 0x30, 0x30, 0x06, +0x03, 0x55, 0x04, 0x0b, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, +0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x82, +0x01, 0x00, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, +0x82, 0x01, 0x01, 0x00, 0x05, 0x9d, 0x3f, 0x88, 0x9d, 0xd1, 0xc9, 0x1a, 0x55, 0xa1, 0xac, 0x69, +0xf3, 0xf3, 0x59, 0xda, 0x9b, 0x01, 0x87, 0x1a, 0x4f, 0x57, 0xa9, 0xa1, 0x79, 0x09, 0x2a, 0xdb, +0xf7, 0x2f, 0xb2, 0x1e, 0xcc, 0xc7, 0x5e, 0x6a, 0xd8, 0x83, 0x87, 0xa1, 0x97, 0xef, 0x49, 0x35, +0x3e, 0x77, 0x06, 0x41, 0x58, 0x62, 0xbf, 0x8e, 0x58, 0xb8, 0x0a, 0x67, 0x3f, 0xec, 0xb3, 0xdd, +0x21, 0x66, 0x1f, 0xc9, 0x54, 0xfa, 0x72, 0xcc, 0x3d, 0x4c, 0x40, 0xd8, 0x81, 0xaf, 0x77, 0x9e, +0x83, 0x7a, 0xbb, 0xa2, 0xc7, 0xf5, 0x34, 0x17, 0x8e, 0xd9, 0x11, 0x40, 0xf4, 0xfc, 0x2c, 0x2a, +0x4d, 0x15, 0x7f, 0xa7, 0x62, 0x5d, 0x2e, 0x25, 0xd3, 0x00, 0x0b, 0x20, 0x1a, 0x1d, 0x68, 0xf9, +0x17, 0xb8, 0xf4, 0xbd, 0x8b, 0xed, 0x28, 0x59, 0xdd, 0x4d, 0x16, 0x8b, 0x17, 0x83, 0xc8, 0xb2, +0x65, 0xc7, 0x2d, 0x7a, 0xa5, 0xaa, 0xbc, 0x53, 0x86, 0x6d, 0xdd, 0x57, 0xa4, 0xca, 0xf8, 0x20, +0x41, 0x0b, 0x68, 0xf0, 0xf4, 0xfb, 0x74, 0xbe, 0x56, 0x5d, 0x7a, 0x79, 0xf5, 0xf9, 0x1d, 0x85, +0xe3, 0x2d, 0x95, 0xbe, 0xf5, 0x71, 0x90, 0x43, 0xcc, 0x8d, 0x1f, 0x9a, 0x00, 0x0a, 0x87, 0x29, +0xe9, 0x55, 0x22, 0x58, 0x00, 0x23, 0xea, 0xe3, 0x12, 0x43, 0x29, 0x5b, 0x47, 0x08, 0xdd, 0x8c, +0x41, 0x6a, 0x65, 0x06, 0xa8, 0xe5, 0x21, 0xaa, 0x41, 0xb4, 0x95, 0x21, 0x95, 0xb9, 0x7d, 0xd1, +0x34, 0xab, 0x13, 0xd6, 0xad, 0xbc, 0xdc, 0xe2, 0x3d, 0x39, 0xcd, 0xbd, 0x3e, 0x75, 0x70, 0xa1, +0x18, 0x59, 0x03, 0xc9, 0x22, 0xb4, 0x8f, 0x9c, 0xd5, 0x5e, 0x2a, 0xd7, 0xa5, 0xb6, 0xd4, 0x0a, +0x6d, 0xf8, 0xb7, 0x40, 0x11, 0x46, 0x9a, 0x1f, 0x79, 0x0e, 0x62, 0xbf, 0x0f, 0x97, 0xec, 0xe0, +0x2f, 0x1f, 0x17, 0x94, 0x30, 0x82, 0x03, 0xdd, 0x30, 0x82, 0x02, 0xc5, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x30, 0x81, 0x8f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, +0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, +0x53, 0x63, 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, +0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, +0x2e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, +0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, +0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x39, 0x30, 0x31, 0x30, +0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, +0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x8f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, +0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, +0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, +0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, +0x6e, 0x63, 0x2e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, +0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, +0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, +0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbd, 0xed, 0xc1, 0x03, 0xfc, 0xf6, 0x8f, 0xfc, +0x02, 0xb1, 0x6f, 0x5b, 0x9f, 0x48, 0xd9, 0x9d, 0x79, 0xe2, 0xa2, 0xb7, 0x03, 0x61, 0x56, 0x18, +0xc3, 0x47, 0xb6, 0xd7, 0xca, 0x3d, 0x35, 0x2e, 0x89, 0x43, 0xf7, 0xa1, 0x69, 0x9b, 0xde, 0x8a, +0x1a, 0xfd, 0x13, 0x20, 0x9c, 0xb4, 0x49, 0x77, 0x32, 0x29, 0x56, 0xfd, 0xb9, 0xec, 0x8c, 0xdd, +0x22, 0xfa, 0x72, 0xdc, 0x27, 0x61, 0x97, 0xee, 0xf6, 0x5a, 0x84, 0xec, 0x6e, 0x19, 0xb9, 0x89, +0x2c, 0xdc, 0x84, 0x5b, 0xd5, 0x74, 0xfb, 0x6b, 0x5f, 0xc5, 0x89, 0xa5, 0x10, 0x52, 0x89, 0x46, +0x55, 0xf4, 0xb8, 0x75, 0x1c, 0xe6, 0x7f, 0xe4, 0x54, 0xae, 0x4b, 0xf8, 0x55, 0x72, 0x57, 0x02, +0x19, 0xf8, 0x17, 0x71, 0x59, 0xeb, 0x1e, 0x28, 0x07, 0x74, 0xc5, 0x9d, 0x48, 0xbe, 0x6c, 0xb4, +0xf4, 0xa4, 0xb0, 0xf3, 0x64, 0x37, 0x79, 0x92, 0xc0, 0xec, 0x46, 0x5e, 0x7f, 0xe1, 0x6d, 0x53, +0x4c, 0x62, 0xaf, 0xcd, 0x1f, 0x0b, 0x63, 0xbb, 0x3a, 0x9d, 0xfb, 0xfc, 0x79, 0x00, 0x98, 0x61, +0x74, 0xcf, 0x26, 0x82, 0x40, 0x63, 0xf3, 0xb2, 0x72, 0x6a, 0x19, 0x0d, 0x99, 0xca, 0xd4, 0x0e, +0x75, 0xcc, 0x37, 0xfb, 0x8b, 0x89, 0xc1, 0x59, 0xf1, 0x62, 0x7f, 0x5f, 0xb3, 0x5f, 0x65, 0x30, +0xf8, 0xa7, 0xb7, 0x4d, 0x76, 0x5a, 0x1e, 0x76, 0x5e, 0x34, 0xc0, 0xe8, 0x96, 0x56, 0x99, 0x8a, +0xb3, 0xf0, 0x7f, 0xa4, 0xcd, 0xbd, 0xdc, 0x32, 0x31, 0x7c, 0x91, 0xcf, 0xe0, 0x5f, 0x11, 0xf8, +0x6b, 0xaa, 0x49, 0x5c, 0xd1, 0x99, 0x94, 0xd1, 0xa2, 0xe3, 0x63, 0x5b, 0x09, 0x76, 0xb5, 0x56, +0x62, 0xe1, 0x4b, 0x74, 0x1d, 0x96, 0xd4, 0x26, 0xd4, 0x08, 0x04, 0x59, 0xd0, 0x98, 0x0e, 0x0e, +0xe6, 0xde, 0xfc, 0xc3, 0xec, 0x1f, 0x90, 0xf1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, +0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7c, 0x0c, 0x32, +0x1f, 0xa7, 0xd9, 0x30, 0x7f, 0xc4, 0x7d, 0x68, 0xa3, 0x62, 0xa8, 0xa1, 0xce, 0xab, 0x07, 0x5b, +0x27, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x03, 0x82, 0x01, 0x01, 0x00, 0x11, 0x59, 0xfa, 0x25, 0x4f, 0x03, 0x6f, 0x94, 0x99, 0x3b, 0x9a, +0x1f, 0x82, 0x85, 0x39, 0xd4, 0x76, 0x05, 0x94, 0x5e, 0xe1, 0x28, 0x93, 0x6d, 0x62, 0x5d, 0x09, +0xc2, 0xa0, 0xa8, 0xd4, 0xb0, 0x75, 0x38, 0xf1, 0x34, 0x6a, 0x9d, 0xe4, 0x9f, 0x8a, 0x86, 0x26, +0x51, 0xe6, 0x2c, 0xd1, 0xc6, 0x2d, 0x6e, 0x95, 0x20, 0x4a, 0x92, 0x01, 0xec, 0xb8, 0x8a, 0x67, +0x7b, 0x31, 0xe2, 0x67, 0x2e, 0x8c, 0x95, 0x03, 0x26, 0x2e, 0x43, 0x9d, 0x4a, 0x31, 0xf6, 0x0e, +0xb5, 0x0c, 0xbb, 0xb7, 0xe2, 0x37, 0x7f, 0x22, 0xba, 0x00, 0xa3, 0x0e, 0x7b, 0x52, 0xfb, 0x6b, +0xbb, 0x3b, 0xc4, 0xd3, 0x79, 0x51, 0x4e, 0xcd, 0x90, 0xf4, 0x67, 0x07, 0x19, 0xc8, 0x3c, 0x46, +0x7a, 0x0d, 0x01, 0x7d, 0xc5, 0x58, 0xe7, 0x6d, 0xe6, 0x85, 0x30, 0x17, 0x9a, 0x24, 0xc4, 0x10, +0xe0, 0x04, 0xf7, 0xe0, 0xf2, 0x7f, 0xd4, 0xaa, 0x0a, 0xff, 0x42, 0x1d, 0x37, 0xed, 0x94, 0xe5, +0x64, 0x59, 0x12, 0x20, 0x77, 0x38, 0xd3, 0x32, 0x3e, 0x38, 0x81, 0x75, 0x96, 0x73, 0xfa, 0x68, +0x8f, 0xb1, 0xcb, 0xce, 0x1f, 0xc5, 0xec, 0xfa, 0x9c, 0x7e, 0xcf, 0x7e, 0xb1, 0xf1, 0x07, 0x2d, +0xb6, 0xfc, 0xbf, 0xca, 0xa4, 0xbf, 0xd0, 0x97, 0x05, 0x4a, 0xbc, 0xea, 0x18, 0x28, 0x02, 0x90, +0xbd, 0x54, 0x78, 0x09, 0x21, 0x71, 0xd3, 0xd1, 0x7d, 0x1d, 0xd9, 0x16, 0xb0, 0xa9, 0x61, 0x3d, +0xd0, 0x0a, 0x00, 0x22, 0xfc, 0xc7, 0x7b, 0xcb, 0x09, 0x64, 0x45, 0x0b, 0x3b, 0x40, 0x81, 0xf7, +0x7d, 0x7c, 0x32, 0xf5, 0x98, 0xca, 0x58, 0x8e, 0x7d, 0x2a, 0xee, 0x90, 0x59, 0x73, 0x64, 0xf9, +0x36, 0x74, 0x5e, 0x25, 0xa1, 0xf5, 0x66, 0x05, 0x2e, 0x7f, 0x39, 0x15, 0xa9, 0x2a, 0xfb, 0x50, +0x8b, 0x8e, 0x85, 0x69, 0xf4, 0x30, 0x82, 0x03, 0xef, 0x30, 0x82, 0x02, 0xd7, 0xa0, 0x03, 0x02, +0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x41, +0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, +0x0a, 0x53, 0x63, 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, +0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, +0x63, 0x2e, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, +0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, +0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x39, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, +0x17, 0x0d, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, +0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, +0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, +0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, +0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3b, 0x30, +0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, +0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, +0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd5, 0x0c, 0x3a, 0xc4, 0x2a, +0xf9, 0x4e, 0xe2, 0xf5, 0xbe, 0x19, 0x97, 0x5f, 0x8e, 0x88, 0x53, 0xb1, 0x1f, 0x3f, 0xcb, 0xcf, +0x9f, 0x20, 0x13, 0x6d, 0x29, 0x3a, 0xc8, 0x0f, 0x7d, 0x3c, 0xf7, 0x6b, 0x76, 0x38, 0x63, 0xd9, +0x36, 0x60, 0xa8, 0x9b, 0x5e, 0x5c, 0x00, 0x80, 0xb2, 0x2f, 0x59, 0x7f, 0xf6, 0x87, 0xf9, 0x25, +0x43, 0x86, 0xe7, 0x69, 0x1b, 0x52, 0x9a, 0x90, 0xe1, 0x71, 0xe3, 0xd8, 0x2d, 0x0d, 0x4e, 0x6f, +0xf6, 0xc8, 0x49, 0xd9, 0xb6, 0xf3, 0x1a, 0x56, 0xae, 0x2b, 0xb6, 0x74, 0x14, 0xeb, 0xcf, 0xfb, +0x26, 0xe3, 0x1a, 0xba, 0x1d, 0x96, 0x2e, 0x6a, 0x3b, 0x58, 0x94, 0x89, 0x47, 0x56, 0xff, 0x25, +0xa0, 0x93, 0x70, 0x53, 0x83, 0xda, 0x84, 0x74, 0x14, 0xc3, 0x67, 0x9e, 0x04, 0x68, 0x3a, 0xdf, +0x8e, 0x40, 0x5a, 0x1d, 0x4a, 0x4e, 0xcf, 0x43, 0x91, 0x3b, 0xe7, 0x56, 0xd6, 0x00, 0x70, 0xcb, +0x52, 0xee, 0x7b, 0x7d, 0xae, 0x3a, 0xe7, 0xbc, 0x31, 0xf9, 0x45, 0xf6, 0xc2, 0x60, 0xcf, 0x13, +0x59, 0x02, 0x2b, 0x80, 0xcc, 0x34, 0x47, 0xdf, 0xb9, 0xde, 0x90, 0x65, 0x6d, 0x02, 0xcf, 0x2c, +0x91, 0xa6, 0xa6, 0xe7, 0xde, 0x85, 0x18, 0x49, 0x7c, 0x66, 0x4e, 0xa3, 0x3a, 0x6d, 0xa9, 0xb5, +0xee, 0x34, 0x2e, 0xba, 0x0d, 0x03, 0xb8, 0x33, 0xdf, 0x47, 0xeb, 0xb1, 0x6b, 0x8d, 0x25, 0xd9, +0x9b, 0xce, 0x81, 0xd1, 0x45, 0x46, 0x32, 0x96, 0x70, 0x87, 0xde, 0x02, 0x0e, 0x49, 0x43, 0x85, +0xb6, 0x6c, 0x73, 0xbb, 0x64, 0xea, 0x61, 0x41, 0xac, 0xc9, 0xd4, 0x54, 0xdf, 0x87, 0x2f, 0xc7, +0x22, 0xb2, 0x26, 0xcc, 0x9f, 0x59, 0x54, 0x68, 0x9f, 0xfc, 0xbe, 0x2a, 0x2f, 0xc4, 0x55, 0x1c, +0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, 0x39, 0x8b, 0x7f, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, +0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0x9c, 0x5f, 0x00, 0xdf, 0xaa, 0x01, 0xd7, 0x30, 0x2b, 0x38, 0x88, 0xa2, 0xb8, 0x6d, 0x4a, 0x9c, +0xf2, 0x11, 0x91, 0x83, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4b, 0x36, 0xa6, 0x84, 0x77, 0x69, 0xdd, 0x3b, +0x19, 0x9f, 0x67, 0x23, 0x08, 0x6f, 0x0e, 0x61, 0xc9, 0xfd, 0x84, 0xdc, 0x5f, 0xd8, 0x36, 0x81, +0xcd, 0xd8, 0x1b, 0x41, 0x2d, 0x9f, 0x60, 0xdd, 0xc7, 0x1a, 0x68, 0xd9, 0xd1, 0x6e, 0x86, 0xe1, +0x88, 0x23, 0xcf, 0x13, 0xde, 0x43, 0xcf, 0xe2, 0x34, 0xb3, 0x04, 0x9d, 0x1f, 0x29, 0xd5, 0xbf, +0xf8, 0x5e, 0xc8, 0xd5, 0xc1, 0xbd, 0xee, 0x92, 0x6f, 0x32, 0x74, 0xf2, 0x91, 0x82, 0x2f, 0xbd, +0x82, 0x42, 0x7a, 0xad, 0x2a, 0xb7, 0x20, 0x7d, 0x4d, 0xbc, 0x7a, 0x55, 0x12, 0xc2, 0x15, 0xea, +0xbd, 0xf7, 0x6a, 0x95, 0x2e, 0x6c, 0x74, 0x9f, 0xcf, 0x1c, 0xb4, 0xf2, 0xc5, 0x01, 0xa3, 0x85, +0xd0, 0x72, 0x3e, 0xad, 0x73, 0xab, 0x0b, 0x9b, 0x75, 0x0c, 0x6d, 0x45, 0xb7, 0x8e, 0x94, 0xac, +0x96, 0x37, 0xb5, 0xa0, 0xd0, 0x8f, 0x15, 0x47, 0x0e, 0xe3, 0xe8, 0x83, 0xdd, 0x8f, 0xfd, 0xef, +0x41, 0x01, 0x77, 0xcc, 0x27, 0xa9, 0x62, 0x85, 0x33, 0xf2, 0x37, 0x08, 0xef, 0x71, 0xcf, 0x77, +0x06, 0xde, 0xc8, 0x19, 0x1d, 0x88, 0x40, 0xcf, 0x7d, 0x46, 0x1d, 0xff, 0x1e, 0xc7, 0xe1, 0xce, +0xff, 0x23, 0xdb, 0xc6, 0xfa, 0x8d, 0x55, 0x4e, 0xa9, 0x02, 0xe7, 0x47, 0x11, 0x46, 0x3e, 0xf4, +0xfd, 0xbd, 0x7b, 0x29, 0x26, 0xbb, 0xa9, 0x61, 0x62, 0x37, 0x28, 0xb6, 0x2d, 0x2a, 0xf6, 0x10, +0x86, 0x64, 0xc9, 0x70, 0xa7, 0xd2, 0xad, 0xb7, 0x29, 0x70, 0x79, 0xea, 0x3c, 0xda, 0x63, 0x25, +0x9f, 0xfd, 0x68, 0xb7, 0x30, 0xec, 0x70, 0xfb, 0x75, 0x8a, 0xb7, 0x6d, 0x60, 0x67, 0xb2, 0x1e, +0xc8, 0xb9, 0xe9, 0xd8, 0xa8, 0x6f, 0x02, 0x8b, 0x67, 0x0d, 0x4d, 0x26, 0x57, 0x71, 0xda, 0x20, +0xfc, 0xc1, 0x4a, 0x50, 0x8d, 0xb1, 0x28, 0xba, 0x30, 0x82, 0x05, 0xde, 0x30, 0x82, 0x03, 0xc6, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 0xfd, 0x6d, 0x30, 0xfc, 0xa3, 0xca, 0x51, 0xa8, +0x1b, 0xbc, 0x64, 0x0e, 0x35, 0x03, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, +0x0a, 0x4e, 0x65, 0x77, 0x20, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, +0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, +0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, +0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, +0x6b, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, +0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, +0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x32, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x38, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, +0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4e, 0x65, 0x77, 0x20, +0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, +0x0b, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, +0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x2e, 0x30, 0x2c, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, 0x75, 0x73, 0x74, +0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x02, 0x22, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, +0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x80, 0x12, 0x65, +0x17, 0x36, 0x0e, 0xc3, 0xdb, 0x08, 0xb3, 0xd0, 0xac, 0x57, 0x0d, 0x76, 0xed, 0xcd, 0x27, 0xd3, +0x4c, 0xad, 0x50, 0x83, 0x61, 0xe2, 0xaa, 0x20, 0x4d, 0x09, 0x2d, 0x64, 0x09, 0xdc, 0xce, 0x89, +0x9f, 0xcc, 0x3d, 0xa9, 0xec, 0xf6, 0xcf, 0xc1, 0xdc, 0xf1, 0xd3, 0xb1, 0xd6, 0x7b, 0x37, 0x28, +0x11, 0x2b, 0x47, 0xda, 0x39, 0xc6, 0xbc, 0x3a, 0x19, 0xb4, 0x5f, 0xa6, 0xbd, 0x7d, 0x9d, 0xa3, +0x63, 0x42, 0xb6, 0x76, 0xf2, 0xa9, 0x3b, 0x2b, 0x91, 0xf8, 0xe2, 0x6f, 0xd0, 0xec, 0x16, 0x20, +0x90, 0x09, 0x3e, 0xe2, 0xe8, 0x74, 0xc9, 0x18, 0xb4, 0x91, 0xd4, 0x62, 0x64, 0xdb, 0x7f, 0xa3, +0x06, 0xf1, 0x88, 0x18, 0x6a, 0x90, 0x22, 0x3c, 0xbc, 0xfe, 0x13, 0xf0, 0x87, 0x14, 0x7b, 0xf6, +0xe4, 0x1f, 0x8e, 0xd4, 0xe4, 0x51, 0xc6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xcb, 0x86, 0x14, 0x54, +0x3f, 0xbc, 0x33, 0xfe, 0x7e, 0x6c, 0x9c, 0xff, 0x16, 0x9d, 0x18, 0xbd, 0x51, 0x8e, 0x35, 0xa6, +0xa7, 0x66, 0xc8, 0x72, 0x67, 0xdb, 0x21, 0x66, 0xb1, 0xd4, 0x9b, 0x78, 0x03, 0xc0, 0x50, 0x3a, +0xe8, 0xcc, 0xf0, 0xdc, 0xbc, 0x9e, 0x4c, 0xfe, 0xaf, 0x05, 0x96, 0x35, 0x1f, 0x57, 0x5a, 0xb7, +0xff, 0xce, 0xf9, 0x3d, 0xb7, 0x2c, 0xb6, 0xf6, 0x54, 0xdd, 0xc8, 0xe7, 0x12, 0x3a, 0x4d, 0xae, +0x4c, 0x8a, 0xb7, 0x5c, 0x9a, 0xb4, 0xb7, 0x20, 0x3d, 0xca, 0x7f, 0x22, 0x34, 0xae, 0x7e, 0x3b, +0x68, 0x66, 0x01, 0x44, 0xe7, 0x01, 0x4e, 0x46, 0x53, 0x9b, 0x33, 0x60, 0xf7, 0x94, 0xbe, 0x53, +0x37, 0x90, 0x73, 0x43, 0xf3, 0x32, 0xc3, 0x53, 0xef, 0xdb, 0xaa, 0xfe, 0x74, 0x4e, 0x69, 0xc7, +0x6b, 0x8c, 0x60, 0x93, 0xde, 0xc4, 0xc7, 0x0c, 0xdf, 0xe1, 0x32, 0xae, 0xcc, 0x93, 0x3b, 0x51, +0x78, 0x95, 0x67, 0x8b, 0xee, 0x3d, 0x56, 0xfe, 0x0c, 0xd0, 0x69, 0x0f, 0x1b, 0x0f, 0xf3, 0x25, +0x26, 0x6b, 0x33, 0x6d, 0xf7, 0x6e, 0x47, 0xfa, 0x73, 0x43, 0xe5, 0x7e, 0x0e, 0xa5, 0x66, 0xb1, +0x29, 0x7c, 0x32, 0x84, 0x63, 0x55, 0x89, 0xc4, 0x0d, 0xc1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xac, +0xd3, 0x7d, 0x37, 0xa7, 0xeb, 0x5d, 0x3a, 0x6c, 0x35, 0x5c, 0xdb, 0x41, 0xd7, 0x12, 0xda, 0xa9, +0x49, 0x0b, 0xdf, 0xd8, 0x80, 0x8a, 0x09, 0x93, 0x62, 0x8e, 0xb5, 0x66, 0xcf, 0x25, 0x88, 0xcd, +0x84, 0xb8, 0xb1, 0x3f, 0xa4, 0x39, 0x0f, 0xd9, 0x02, 0x9e, 0xeb, 0x12, 0x4c, 0x95, 0x7c, 0xf3, +0x6b, 0x05, 0xa9, 0x5e, 0x16, 0x83, 0xcc, 0xb8, 0x67, 0xe2, 0xe8, 0x13, 0x9d, 0xcc, 0x5b, 0x82, +0xd3, 0x4c, 0xb3, 0xed, 0x5b, 0xff, 0xde, 0xe5, 0x73, 0xac, 0x23, 0x3b, 0x2d, 0x00, 0xbf, 0x35, +0x55, 0x74, 0x09, 0x49, 0xd8, 0x49, 0x58, 0x1a, 0x7f, 0x92, 0x36, 0xe6, 0x51, 0x92, 0x0e, 0xf3, +0x26, 0x7d, 0x1c, 0x4d, 0x17, 0xbc, 0xc9, 0xec, 0x43, 0x26, 0xd0, 0xbf, 0x41, 0x5f, 0x40, 0xa9, +0x44, 0x44, 0xf4, 0x99, 0xe7, 0x57, 0x87, 0x9e, 0x50, 0x1f, 0x57, 0x54, 0xa8, 0x3e, 0xfd, 0x74, +0x63, 0x2f, 0xb1, 0x50, 0x65, 0x09, 0xe6, 0x58, 0x42, 0x2e, 0x43, 0x1a, 0x4c, 0xb4, 0xf0, 0x25, +0x47, 0x59, 0xfa, 0x04, 0x1e, 0x93, 0xd4, 0x26, 0x46, 0x4a, 0x50, 0x81, 0xb2, 0xde, 0xbe, 0x78, +0xb7, 0xfc, 0x67, 0x15, 0xe1, 0xc9, 0x57, 0x84, 0x1e, 0x0f, 0x63, 0xd6, 0xe9, 0x62, 0xba, 0xd6, +0x5f, 0x55, 0x2e, 0xea, 0x5c, 0xc6, 0x28, 0x08, 0x04, 0x25, 0x39, 0xb8, 0x0e, 0x2b, 0xa9, 0xf2, +0x4c, 0x97, 0x1c, 0x07, 0x3f, 0x0d, 0x52, 0xf5, 0xed, 0xef, 0x2f, 0x82, 0x0f, 0x02, 0x03, 0x01, +0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0x53, 0x79, 0xbf, 0x5a, 0xaa, 0x2b, 0x4a, 0xcf, 0x54, 0x80, 0xe1, 0xd8, 0x9b, 0xc0, 0x9d, +0xf2, 0xb2, 0x03, 0x66, 0xcb, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x5c, 0xd4, 0x7c, 0x0d, 0xcf, 0xf7, +0x01, 0x7d, 0x41, 0x99, 0x65, 0x0c, 0x73, 0xc5, 0x52, 0x9f, 0xcb, 0xf8, 0xcf, 0x99, 0x06, 0x7f, +0x1b, 0xda, 0x43, 0x15, 0x9f, 0x9e, 0x02, 0x55, 0x57, 0x96, 0x14, 0xf1, 0x52, 0x3c, 0x27, 0x87, +0x94, 0x28, 0xed, 0x1f, 0x3a, 0x01, 0x37, 0xa2, 0x76, 0xfc, 0x53, 0x50, 0xc0, 0x84, 0x9b, 0xc6, +0x6b, 0x4e, 0xba, 0x8c, 0x21, 0x4f, 0xa2, 0x8e, 0x55, 0x62, 0x91, 0xf3, 0x69, 0x15, 0xd8, 0xbc, +0x88, 0xe3, 0xc4, 0xaa, 0x0b, 0xfd, 0xef, 0xa8, 0xe9, 0x4b, 0x55, 0x2a, 0x06, 0x20, 0x6d, 0x55, +0x78, 0x29, 0x19, 0xee, 0x5f, 0x30, 0x5c, 0x4b, 0x24, 0x11, 0x55, 0xff, 0x24, 0x9a, 0x6e, 0x5e, +0x2a, 0x2b, 0xee, 0x0b, 0x4d, 0x9f, 0x7f, 0xf7, 0x01, 0x38, 0x94, 0x14, 0x95, 0x43, 0x07, 0x09, +0xfb, 0x60, 0xa9, 0xee, 0x1c, 0xab, 0x12, 0x8c, 0xa0, 0x9a, 0x5e, 0xa7, 0x98, 0x6a, 0x59, 0x6d, +0x8b, 0x3f, 0x08, 0xfb, 0xc8, 0xd1, 0x45, 0xaf, 0x18, 0x15, 0x64, 0x90, 0x12, 0x0f, 0x73, 0x28, +0x2e, 0xc5, 0xe2, 0x24, 0x4e, 0xfc, 0x58, 0xec, 0xf0, 0xf4, 0x45, 0xfe, 0x22, 0xb3, 0xeb, 0x2f, +0x8e, 0xd2, 0xd9, 0x45, 0x61, 0x05, 0xc1, 0x97, 0x6f, 0xa8, 0x76, 0x72, 0x8f, 0x8b, 0x8c, 0x36, +0xaf, 0xbf, 0x0d, 0x05, 0xce, 0x71, 0x8d, 0xe6, 0xa6, 0x6f, 0x1f, 0x6c, 0xa6, 0x71, 0x62, 0xc5, +0xd8, 0xd0, 0x83, 0x72, 0x0c, 0xf1, 0x67, 0x11, 0x89, 0x0c, 0x9c, 0x13, 0x4c, 0x72, 0x34, 0xdf, +0xbc, 0xd5, 0x71, 0xdf, 0xaa, 0x71, 0xdd, 0xe1, 0xb9, 0x6c, 0x8c, 0x3c, 0x12, 0x5d, 0x65, 0xda, +0xbd, 0x57, 0x12, 0xb6, 0x43, 0x6b, 0xff, 0xe5, 0xde, 0x4d, 0x66, 0x11, 0x51, 0xcf, 0x99, 0xae, +0xec, 0x17, 0xb6, 0xe8, 0x71, 0x91, 0x8c, 0xde, 0x49, 0xfe, 0xdd, 0x35, 0x71, 0xa2, 0x15, 0x27, +0x94, 0x1c, 0xcf, 0x61, 0xe3, 0x26, 0xbb, 0x6f, 0xa3, 0x67, 0x25, 0x21, 0x5d, 0xe6, 0xdd, 0x1d, +0x0b, 0x2e, 0x68, 0x1b, 0x3b, 0x82, 0xaf, 0xec, 0x83, 0x67, 0x85, 0xd4, 0x98, 0x51, 0x74, 0xb1, +0xb9, 0x99, 0x80, 0x89, 0xff, 0x7f, 0x78, 0x19, 0x5c, 0x79, 0x4a, 0x60, 0x2e, 0x92, 0x40, 0xae, +0x4c, 0x37, 0x2a, 0x2c, 0xc9, 0xc7, 0x62, 0xc8, 0x0e, 0x5d, 0xf7, 0x36, 0x5b, 0xca, 0xe0, 0x25, +0x25, 0x01, 0xb4, 0xdd, 0x1a, 0x07, 0x9c, 0x77, 0x00, 0x3f, 0xd0, 0xdc, 0xd5, 0xec, 0x3d, 0xd4, +0xfa, 0xbb, 0x3f, 0xcc, 0x85, 0xd6, 0x6f, 0x7f, 0xa9, 0x2d, 0xdf, 0xb9, 0x02, 0xf7, 0xf5, 0x97, +0x9a, 0xb5, 0x35, 0xda, 0xc3, 0x67, 0xb0, 0x87, 0x4a, 0xa9, 0x28, 0x9e, 0x23, 0x8e, 0xff, 0x5c, +0x27, 0x6b, 0xe1, 0xb0, 0x4f, 0xf3, 0x07, 0xee, 0x00, 0x2e, 0xd4, 0x59, 0x87, 0xcb, 0x52, 0x41, +0x95, 0xea, 0xf4, 0x47, 0xd7, 0xee, 0x64, 0x41, 0x55, 0x7c, 0x8d, 0x59, 0x02, 0x95, 0xdd, 0x62, +0x9d, 0xc2, 0xb9, 0xee, 0x5a, 0x28, 0x74, 0x84, 0xa5, 0x9b, 0xb7, 0x90, 0xc7, 0x0c, 0x07, 0xdf, +0xf5, 0x89, 0x36, 0x74, 0x32, 0xd6, 0x28, 0xc1, 0xb0, 0xb0, 0x0b, 0xe0, 0x9c, 0x4c, 0xc3, 0x1c, +0xd6, 0xfc, 0xe3, 0x69, 0xb5, 0x47, 0x46, 0x81, 0x2f, 0xa2, 0x82, 0xab, 0xd3, 0x63, 0x44, 0x70, +0xc4, 0x8d, 0xff, 0x2d, 0x33, 0xba, 0xad, 0x8f, 0x7b, 0xb5, 0x70, 0x88, 0xae, 0x3e, 0x19, 0xcf, +0x40, 0x28, 0xd8, 0xfc, 0xc8, 0x90, 0xbb, 0x5d, 0x99, 0x22, 0xf5, 0x52, 0xe6, 0x58, 0xc5, 0x1f, +0x88, 0x31, 0x43, 0xee, 0x88, 0x1d, 0xd7, 0xc6, 0x8e, 0x3c, 0x43, 0x6a, 0x1d, 0xa7, 0x18, 0xde, +0x7d, 0x3d, 0x16, 0xf1, 0x62, 0xf9, 0xca, 0x90, 0xa8, 0xfd, 0x30, 0x82, 0x02, 0x8f, 0x30, 0x82, +0x02, 0x15, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x5c, 0x8b, 0x99, 0xc5, 0x5a, 0x94, 0xc5, +0xd2, 0x71, 0x56, 0xde, 0xcd, 0x89, 0x80, 0xcc, 0x26, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, +0x4e, 0x65, 0x77, 0x20, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, +0x55, 0x04, 0x07, 0x13, 0x0b, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, +0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, +0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, +0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, +0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x32, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, +0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x38, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, +0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, +0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4e, 0x65, 0x77, 0x20, 0x4a, +0x65, 0x72, 0x73, 0x65, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, +0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, +0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x2e, 0x30, 0x2c, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, +0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x76, 0x30, 0x10, 0x06, +0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, +0x62, 0x00, 0x04, 0x1a, 0xac, 0x54, 0x5a, 0xa9, 0xf9, 0x68, 0x23, 0xe7, 0x7a, 0xd5, 0x24, 0x6f, +0x53, 0xc6, 0x5a, 0xd8, 0x4b, 0xab, 0xc6, 0xd5, 0xb6, 0xd1, 0xe6, 0x73, 0x71, 0xae, 0xdd, 0x9c, +0xd6, 0x0c, 0x61, 0xfd, 0xdb, 0xa0, 0x89, 0x03, 0xb8, 0x05, 0x14, 0xec, 0x57, 0xce, 0xee, 0x5d, +0x3f, 0xe2, 0x21, 0xb3, 0xce, 0xf7, 0xd4, 0x8a, 0x79, 0xe0, 0xa3, 0x83, 0x7e, 0x2d, 0x97, 0xd0, +0x61, 0xc4, 0xf1, 0x99, 0xdc, 0x25, 0x91, 0x63, 0xab, 0x7f, 0x30, 0xa3, 0xb4, 0x70, 0xe2, 0xc7, +0xa1, 0x33, 0x9c, 0xf3, 0xbf, 0x2e, 0x5c, 0x53, 0xb1, 0x5f, 0xb3, 0x7d, 0x32, 0x7f, 0x8a, 0x34, +0xe3, 0x79, 0x79, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, +0x04, 0x14, 0x3a, 0xe1, 0x09, 0x86, 0xd4, 0xcf, 0x19, 0xc2, 0x96, 0x76, 0x74, 0x49, 0x76, 0xdc, +0xe0, 0x35, 0xc6, 0x63, 0x63, 0x9a, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, +0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x36, 0x67, 0xa1, 0x16, 0x08, 0xdc, +0xe4, 0x97, 0x00, 0x41, 0x1d, 0x4e, 0xbe, 0xe1, 0x63, 0x01, 0xcf, 0x3b, 0xaa, 0x42, 0x11, 0x64, +0xa0, 0x9d, 0x94, 0x39, 0x02, 0x11, 0x79, 0x5c, 0x7b, 0x1d, 0xfa, 0x64, 0xb9, 0xee, 0x16, 0x42, +0xb3, 0xbf, 0x8a, 0xc2, 0x09, 0xc4, 0xec, 0xe4, 0xb1, 0x4d, 0x02, 0x31, 0x00, 0xe9, 0x2a, 0x61, +0x47, 0x8c, 0x52, 0x4a, 0x4b, 0x4e, 0x18, 0x70, 0xf6, 0xd6, 0x44, 0xd6, 0x6e, 0xf5, 0x83, 0xba, +0x6d, 0x58, 0xbd, 0x24, 0xd9, 0x56, 0x48, 0xea, 0xef, 0xc4, 0xa2, 0x46, 0x81, 0x88, 0x6a, 0x3a, +0x46, 0xd1, 0xa9, 0x9b, 0x4d, 0xc9, 0x61, 0xda, 0xd1, 0x5d, 0x57, 0x6a, 0x18, 0x30, 0x82, 0x04, +0x91, 0x30, 0x82, 0x03, 0x79, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x45, 0x6b, 0x50, 0x54, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, +0x81, 0xb0, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, +0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x30, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, +0x74, 0x2f, 0x43, 0x50, 0x53, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, +0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, +0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x28, 0x63, 0x29, +0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, +0x6e, 0x63, 0x2e, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45, 0x6e, +0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, +0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, +0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, 0x32, 0x37, 0x32, 0x30, 0x32, 0x33, +0x34, 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x31, 0x31, 0x32, 0x37, 0x32, 0x30, 0x35, 0x33, 0x34, +0x32, 0x5a, 0x30, 0x81, 0xb0, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, +0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, +0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x43, 0x50, 0x53, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f, +0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, +0x72, 0x65, 0x6e, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, +0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, +0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x24, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, +0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb6, 0x95, 0xb6, 0x43, 0x42, 0xfa, 0xc6, 0x6d, 0x2a, 0x6f, +0x48, 0xdf, 0x94, 0x4c, 0x39, 0x57, 0x05, 0xee, 0xc3, 0x79, 0x11, 0x41, 0x68, 0x36, 0xed, 0xec, +0xfe, 0x9a, 0x01, 0x8f, 0xa1, 0x38, 0x28, 0xfc, 0xf7, 0x10, 0x46, 0x66, 0x2e, 0x4d, 0x1e, 0x1a, +0xb1, 0x1a, 0x4e, 0xc6, 0xd1, 0xc0, 0x95, 0x88, 0xb0, 0xc9, 0xff, 0x31, 0x8b, 0x33, 0x03, 0xdb, +0xb7, 0x83, 0x7b, 0x3e, 0x20, 0x84, 0x5e, 0xed, 0xb2, 0x56, 0x28, 0xa7, 0xf8, 0xe0, 0xb9, 0x40, +0x71, 0x37, 0xc5, 0xcb, 0x47, 0x0e, 0x97, 0x2a, 0x68, 0xc0, 0x22, 0x95, 0x62, 0x15, 0xdb, 0x47, +0xd9, 0xf5, 0xd0, 0x2b, 0xff, 0x82, 0x4b, 0xc9, 0xad, 0x3e, 0xde, 0x4c, 0xdb, 0x90, 0x80, 0x50, +0x3f, 0x09, 0x8a, 0x84, 0x00, 0xec, 0x30, 0x0a, 0x3d, 0x18, 0xcd, 0xfb, 0xfd, 0x2a, 0x59, 0x9a, +0x23, 0x95, 0x17, 0x2c, 0x45, 0x9e, 0x1f, 0x6e, 0x43, 0x79, 0x6d, 0x0c, 0x5c, 0x98, 0xfe, 0x48, +0xa7, 0xc5, 0x23, 0x47, 0x5c, 0x5e, 0xfd, 0x6e, 0xe7, 0x1e, 0xb4, 0xf6, 0x68, 0x45, 0xd1, 0x86, +0x83, 0x5b, 0xa2, 0x8a, 0x8d, 0xb1, 0xe3, 0x29, 0x80, 0xfe, 0x25, 0x71, 0x88, 0xad, 0xbe, 0xbc, +0x8f, 0xac, 0x52, 0x96, 0x4b, 0xaa, 0x51, 0x8d, 0xe4, 0x13, 0x31, 0x19, 0xe8, 0x4e, 0x4d, 0x9f, +0xdb, 0xac, 0xb3, 0x6a, 0xd5, 0xbc, 0x39, 0x54, 0x71, 0xca, 0x7a, 0x7a, 0x7f, 0x90, 0xdd, 0x7d, +0x1d, 0x80, 0xd9, 0x81, 0xbb, 0x59, 0x26, 0xc2, 0x11, 0xfe, 0xe6, 0x93, 0xe2, 0xf7, 0x80, 0xe4, +0x65, 0xfb, 0x34, 0x37, 0x0e, 0x29, 0x80, 0x70, 0x4d, 0xaf, 0x38, 0x86, 0x2e, 0x9e, 0x7f, 0x57, +0xaf, 0x9e, 0x17, 0xae, 0xeb, 0x1c, 0xcb, 0x28, 0x21, 0x5f, 0xb6, 0x1c, 0xd8, 0xe7, 0xa2, 0x04, +0x22, 0xf9, 0xd3, 0xda, 0xd8, 0xcb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xb0, 0x30, 0x81, +0xad, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, +0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d, 0x10, 0x04, 0x24, 0x30, 0x22, 0x80, 0x0f, 0x32, +0x30, 0x30, 0x36, 0x31, 0x31, 0x32, 0x37, 0x32, 0x30, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x81, 0x0f, +0x32, 0x30, 0x32, 0x36, 0x31, 0x31, 0x32, 0x37, 0x32, 0x30, 0x35, 0x33, 0x34, 0x32, 0x5a, 0x30, +0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x68, 0x90, 0xe4, 0x67, +0xa4, 0xa6, 0x53, 0x80, 0xc7, 0x86, 0x66, 0xa4, 0xf1, 0xf7, 0x4b, 0x43, 0xfb, 0x84, 0xbd, 0x6d, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x68, 0x90, 0xe4, 0x67, 0xa4, +0xa6, 0x53, 0x80, 0xc7, 0x86, 0x66, 0xa4, 0xf1, 0xf7, 0x4b, 0x43, 0xfb, 0x84, 0xbd, 0x6d, 0x30, +0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf6, 0x7d, 0x07, 0x41, 0x00, 0x04, 0x10, 0x30, 0x0e, +0x1b, 0x08, 0x56, 0x37, 0x2e, 0x31, 0x3a, 0x34, 0x2e, 0x30, 0x03, 0x02, 0x04, 0x90, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, +0x01, 0x00, 0x93, 0xd4, 0x30, 0xb0, 0xd7, 0x03, 0x20, 0x2a, 0xd0, 0xf9, 0x63, 0xe8, 0x91, 0x0c, +0x05, 0x20, 0xa9, 0x5f, 0x19, 0xca, 0x7b, 0x72, 0x4e, 0xd4, 0xb1, 0xdb, 0xd0, 0x96, 0xfb, 0x54, +0x5a, 0x19, 0x2c, 0x0c, 0x08, 0xf7, 0xb2, 0xbc, 0x85, 0xa8, 0x9d, 0x7f, 0x6d, 0x3b, 0x52, 0xb3, +0x2a, 0xdb, 0xe7, 0xd4, 0x84, 0x8c, 0x63, 0xf6, 0x0f, 0xcb, 0x26, 0x01, 0x91, 0x50, 0x6c, 0xf4, +0x5f, 0x14, 0xe2, 0x93, 0x74, 0xc0, 0x13, 0x9e, 0x30, 0x3a, 0x50, 0xe3, 0xb4, 0x60, 0xc5, 0x1c, +0xf0, 0x22, 0x44, 0x8d, 0x71, 0x47, 0xac, 0xc8, 0x1a, 0xc9, 0xe9, 0x9b, 0x9a, 0x00, 0x60, 0x13, +0xff, 0x70, 0x7e, 0x5f, 0x11, 0x4d, 0x49, 0x1b, 0xb3, 0x15, 0x52, 0x7b, 0xc9, 0x54, 0xda, 0xbf, +0x9d, 0x95, 0xaf, 0x6b, 0x9a, 0xd8, 0x9e, 0xe9, 0xf1, 0xe4, 0x43, 0x8d, 0xe2, 0x11, 0x44, 0x3a, +0xbf, 0xaf, 0xbd, 0x83, 0x42, 0x73, 0x52, 0x8b, 0xaa, 0xbb, 0xa7, 0x29, 0xcf, 0xf5, 0x64, 0x1c, +0x0a, 0x4d, 0xd1, 0xbc, 0xaa, 0xac, 0x9f, 0x2a, 0xd0, 0xff, 0x7f, 0x7f, 0xda, 0x7d, 0xea, 0xb1, +0xed, 0x30, 0x25, 0xc1, 0x84, 0xda, 0x34, 0xd2, 0x5b, 0x78, 0x83, 0x56, 0xec, 0x9c, 0x36, 0xc3, +0x26, 0xe2, 0x11, 0xf6, 0x67, 0x49, 0x1d, 0x92, 0xab, 0x8c, 0xfb, 0xeb, 0xff, 0x7a, 0xee, 0x85, +0x4a, 0xa7, 0x50, 0x80, 0xf0, 0xa7, 0x5c, 0x4a, 0x94, 0x2e, 0x5f, 0x05, 0x99, 0x3c, 0x52, 0x41, +0xe0, 0xcd, 0xb4, 0x63, 0xcf, 0x01, 0x43, 0xba, 0x9c, 0x83, 0xdc, 0x8f, 0x60, 0x3b, 0xf3, 0x5a, +0xb4, 0xb4, 0x7b, 0xae, 0xda, 0x0b, 0x90, 0x38, 0x75, 0xef, 0x81, 0x1d, 0x66, 0xd2, 0xf7, 0x57, +0x70, 0x36, 0xb3, 0xbf, 0xfc, 0x28, 0xaf, 0x71, 0x25, 0x85, 0x5b, 0x13, 0xfe, 0x1e, 0x7f, 0x5a, +0xb4, 0x3c, 0x30, 0x82, 0x05, 0x56, 0x30, 0x82, 0x04, 0x3e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x10, 0xee, 0x2b, 0x3d, 0xeb, 0xd4, 0x21, 0xde, 0x14, 0xa8, 0x62, 0xac, 0x04, 0xf3, 0xdd, 0xc4, +0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, +0x30, 0x81, 0xf3, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, +0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x32, 0x41, 0x67, 0x65, 0x6e, 0x63, +0x69, 0x61, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x61, 0x6e, 0x61, 0x20, 0x64, 0x65, 0x20, 0x43, +0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6f, 0x20, 0x28, 0x4e, 0x49, 0x46, +0x20, 0x51, 0x2d, 0x30, 0x38, 0x30, 0x31, 0x31, 0x37, 0x36, 0x2d, 0x49, 0x29, 0x31, 0x28, 0x30, +0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x69, 0x73, 0x20, +0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x73, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, +0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6f, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x2c, 0x56, 0x65, 0x67, 0x65, 0x75, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, +0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, +0x76, 0x65, 0x72, 0x61, 0x72, 0x72, 0x65, 0x6c, 0x20, 0x28, 0x63, 0x29, 0x30, 0x33, 0x31, 0x35, +0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2c, 0x4a, 0x65, 0x72, 0x61, 0x72, 0x71, 0x75, +0x69, 0x61, 0x20, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x61, 0x74, 0x73, 0x20, 0x64, 0x65, 0x20, 0x43, +0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6f, 0x20, 0x43, 0x61, 0x74, 0x61, +0x6c, 0x61, 0x6e, 0x65, 0x73, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x06, +0x45, 0x43, 0x2d, 0x41, 0x43, 0x43, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x33, 0x30, 0x31, 0x30, 0x37, +0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x30, 0x31, 0x30, 0x37, 0x32, +0x32, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xf3, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x32, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x61, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x61, 0x6e, +0x61, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, +0x6f, 0x20, 0x28, 0x4e, 0x49, 0x46, 0x20, 0x51, 0x2d, 0x30, 0x38, 0x30, 0x31, 0x31, 0x37, 0x36, +0x2d, 0x49, 0x29, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, +0x72, 0x76, 0x65, 0x69, 0x73, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x73, 0x20, 0x64, 0x65, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6f, 0x31, 0x35, 0x30, +0x33, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2c, 0x56, 0x65, 0x67, 0x65, 0x75, 0x20, 0x68, 0x74, +0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x65, 0x72, +0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x76, 0x65, 0x72, 0x61, 0x72, 0x72, 0x65, 0x6c, 0x20, 0x28, +0x63, 0x29, 0x30, 0x33, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2c, 0x4a, +0x65, 0x72, 0x61, 0x72, 0x71, 0x75, 0x69, 0x61, 0x20, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x61, 0x74, +0x73, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, +0x6f, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x31, 0x0f, 0x30, 0x0d, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x06, 0x45, 0x43, 0x2d, 0x41, 0x43, 0x43, 0x30, 0x82, 0x01, 0x22, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, +0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb3, 0x22, 0xc7, +0x4f, 0xe2, 0x97, 0x42, 0x95, 0x88, 0x47, 0x83, 0x40, 0xf6, 0x1d, 0x17, 0xf3, 0x83, 0x73, 0x24, +0x1e, 0x51, 0xf3, 0x98, 0x8a, 0xc3, 0x92, 0xb8, 0xff, 0x40, 0x90, 0x05, 0x70, 0x87, 0x60, 0xc9, +0x00, 0xa9, 0xb5, 0x94, 0x65, 0x19, 0x22, 0x15, 0x17, 0xc2, 0x43, 0x6c, 0x66, 0x44, 0x9a, 0x0d, +0x04, 0x3e, 0x39, 0x6f, 0xa5, 0x4b, 0x7a, 0xaa, 0x63, 0xb7, 0x8a, 0x44, 0x9d, 0xd9, 0x63, 0x91, +0x84, 0x66, 0xe0, 0x28, 0x0f, 0xba, 0x42, 0xe3, 0x6e, 0x8e, 0xf7, 0x14, 0x27, 0x93, 0x69, 0xee, +0x91, 0x0e, 0xa3, 0x5f, 0x0e, 0xb1, 0xeb, 0x66, 0xa2, 0x72, 0x4f, 0x12, 0x13, 0x86, 0x65, 0x7a, +0x3e, 0xdb, 0x4f, 0x07, 0xf4, 0xa7, 0x09, 0x60, 0xda, 0x3a, 0x42, 0x99, 0xc7, 0xb2, 0x7f, 0xb3, +0x16, 0x95, 0x1c, 0xc7, 0xf9, 0x34, 0xb5, 0x94, 0x85, 0xd5, 0x99, 0x5e, 0xa0, 0x48, 0xa0, 0x7e, +0xe7, 0x17, 0x65, 0xb8, 0xa2, 0x75, 0xb8, 0x1e, 0xf3, 0xe5, 0x42, 0x7d, 0xaf, 0xed, 0xf3, 0x8a, +0x48, 0x64, 0x5d, 0x82, 0x14, 0x93, 0xd8, 0xc0, 0xe4, 0xff, 0xb3, 0x50, 0x72, 0xf2, 0x76, 0xf6, +0xb3, 0x5d, 0x42, 0x50, 0x79, 0xd0, 0x94, 0x3e, 0x6b, 0x0c, 0x00, 0xbe, 0xd8, 0x6b, 0x0e, 0x4e, +0x2a, 0xec, 0x3e, 0xd2, 0xcc, 0x82, 0xa2, 0x18, 0x65, 0x33, 0x13, 0x77, 0x9e, 0x9a, 0x5d, 0x1a, +0x13, 0xd8, 0xc3, 0xdb, 0x3d, 0xc8, 0x97, 0x7a, 0xee, 0x70, 0xed, 0xa7, 0xe6, 0x7c, 0xdb, 0x71, +0xcf, 0x2d, 0x94, 0x62, 0xdf, 0x6d, 0xd6, 0xf5, 0x38, 0xbe, 0x3f, 0xa5, 0x85, 0x0a, 0x19, 0xb8, +0xa8, 0xd8, 0x09, 0x75, 0x42, 0x70, 0xc4, 0xea, 0xef, 0xcb, 0x0e, 0xc8, 0x34, 0xa8, 0x12, 0x22, +0x98, 0x0c, 0xb8, 0x13, 0x94, 0xb6, 0x4b, 0xec, 0xf0, 0xd0, 0x90, 0xe7, 0x27, 0x02, 0x03, 0x01, +0x00, 0x01, 0xa3, 0x81, 0xe3, 0x30, 0x81, 0xe0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, +0x16, 0x30, 0x14, 0x81, 0x12, 0x65, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x40, 0x63, 0x61, 0x74, 0x63, +0x65, 0x72, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0xa0, 0xc3, 0x8b, 0x44, 0xaa, 0x37, 0xa5, 0x45, 0xbf, 0x97, 0x80, 0x5a, 0xd1, +0xf1, 0x78, 0xa2, 0x9b, 0xe9, 0x5d, 0x8d, 0x30, 0x7f, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x78, +0x30, 0x76, 0x30, 0x74, 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xf5, 0x78, 0x01, 0x03, 0x01, +0x0a, 0x30, 0x65, 0x30, 0x2c, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, +0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x74, +0x63, 0x65, 0x72, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x76, 0x65, 0x72, 0x61, 0x72, 0x72, 0x65, +0x6c, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x29, 0x1a, +0x27, 0x56, 0x65, 0x67, 0x65, 0x75, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, +0x77, 0x77, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x76, +0x65, 0x72, 0x61, 0x72, 0x72, 0x65, 0x6c, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa0, 0x48, 0x5b, 0x82, +0x01, 0xf6, 0x4d, 0x48, 0xb8, 0x39, 0x55, 0x35, 0x9c, 0x80, 0x7a, 0x53, 0x99, 0xd5, 0x5a, 0xff, +0xb1, 0x71, 0x3b, 0xcc, 0x39, 0x09, 0x94, 0x5e, 0xd6, 0xda, 0xef, 0xbe, 0x01, 0x5b, 0x5d, 0xd3, +0x1e, 0xd8, 0xfd, 0x7d, 0x4f, 0xcd, 0xa0, 0x41, 0xe0, 0x34, 0x93, 0xbf, 0xcb, 0xe2, 0x86, 0x9c, +0x37, 0x92, 0x90, 0x56, 0x1c, 0xdc, 0xeb, 0x29, 0x05, 0xe5, 0xc4, 0x9e, 0xc7, 0x35, 0xdf, 0x8a, +0x0c, 0xcd, 0xc5, 0x21, 0x43, 0xe9, 0xaa, 0x88, 0xe5, 0x35, 0xc0, 0x19, 0x42, 0x63, 0x5a, 0x02, +0x5e, 0xa4, 0x48, 0x18, 0x3a, 0x85, 0x6f, 0xdc, 0x9d, 0xbc, 0x3f, 0x9d, 0x9c, 0xc1, 0x87, 0xb8, +0x7a, 0x61, 0x08, 0xe9, 0x77, 0x0b, 0x7f, 0x70, 0xab, 0x7a, 0xdd, 0xd9, 0x97, 0x2c, 0x64, 0x1e, +0x85, 0xbf, 0xbc, 0x74, 0x96, 0xa1, 0xc3, 0x7a, 0x12, 0xec, 0x0c, 0x1a, 0x6e, 0x83, 0x0c, 0x3c, +0xe8, 0x72, 0x46, 0x9f, 0xfb, 0x48, 0xd5, 0x5e, 0x97, 0xe6, 0xb1, 0xa1, 0xf8, 0xe4, 0xef, 0x46, +0x25, 0x94, 0x9c, 0x89, 0xdb, 0x69, 0x38, 0xbe, 0xec, 0x5c, 0x0e, 0x56, 0xc7, 0x65, 0x51, 0xe5, +0x50, 0x88, 0x88, 0xbf, 0x42, 0xd5, 0x2b, 0x3d, 0xe5, 0xf9, 0xba, 0x9e, 0x2e, 0xb3, 0xca, 0xf4, +0x73, 0x92, 0x02, 0x0b, 0xbe, 0x4c, 0x66, 0xeb, 0x20, 0xfe, 0xb9, 0xcb, 0xb5, 0x99, 0x7f, 0xe6, +0xb6, 0x13, 0xfa, 0xca, 0x4b, 0x4d, 0xd9, 0xee, 0x53, 0x46, 0x06, 0x3b, 0xc6, 0x4e, 0xad, 0x93, +0x5a, 0x81, 0x7e, 0x6c, 0x2a, 0x4b, 0x6a, 0x05, 0x45, 0x8c, 0xf2, 0x21, 0xa4, 0x31, 0x90, 0x87, +0x6c, 0x65, 0x9c, 0x9d, 0xa5, 0x60, 0x95, 0x3a, 0x52, 0x7f, 0xf5, 0xd1, 0xab, 0x08, 0x6e, 0xf3, +0xee, 0x5b, 0xf9, 0x88, 0x3d, 0x7e, 0xb8, 0x6f, 0x6e, 0x03, 0xe4, 0x42, 0x30, 0x82, 0x04, 0x2a, +0x30, 0x82, 0x03, 0x12, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x38, 0x63, 0xde, 0xf8, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, +0xb4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x45, 0x6e, 0x74, 0x72, +0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x31, 0x40, 0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x14, 0x37, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, +0x74, 0x2f, 0x43, 0x50, 0x53, 0x5f, 0x32, 0x30, 0x34, 0x38, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, +0x70, 0x2e, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x2e, 0x20, 0x28, 0x6c, 0x69, 0x6d, 0x69, +0x74, 0x73, 0x20, 0x6c, 0x69, 0x61, 0x62, 0x2e, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x1c, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x45, 0x6e, 0x74, +0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, +0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2a, 0x45, 0x6e, 0x74, 0x72, 0x75, +0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, +0x32, 0x30, 0x34, 0x38, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x31, 0x32, 0x32, 0x34, 0x31, +0x37, 0x35, 0x30, 0x35, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x37, 0x32, 0x34, 0x31, 0x34, +0x31, 0x35, 0x31, 0x32, 0x5a, 0x30, 0x81, 0xb4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x0b, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x31, 0x40, +0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x14, 0x37, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, +0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x43, 0x50, 0x53, 0x5f, 0x32, 0x30, 0x34, +0x38, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, +0x2e, 0x20, 0x28, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x20, 0x6c, 0x69, 0x61, 0x62, 0x2e, 0x29, +0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1c, 0x28, 0x63, 0x29, 0x20, 0x31, +0x39, 0x39, 0x39, 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x20, +0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x2a, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, 0x34, 0x38, 0x29, 0x30, 0x82, 0x01, 0x22, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, +0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xad, 0x4d, 0x4b, +0xa9, 0x12, 0x86, 0xb2, 0xea, 0xa3, 0x20, 0x07, 0x15, 0x16, 0x64, 0x2a, 0x2b, 0x4b, 0xd1, 0xbf, +0x0b, 0x4a, 0x4d, 0x8e, 0xed, 0x80, 0x76, 0xa5, 0x67, 0xb7, 0x78, 0x40, 0xc0, 0x73, 0x42, 0xc8, +0x68, 0xc0, 0xdb, 0x53, 0x2b, 0xdd, 0x5e, 0xb8, 0x76, 0x98, 0x35, 0x93, 0x8b, 0x1a, 0x9d, 0x7c, +0x13, 0x3a, 0x0e, 0x1f, 0x5b, 0xb7, 0x1e, 0xcf, 0xe5, 0x24, 0x14, 0x1e, 0xb1, 0x81, 0xa9, 0x8d, +0x7d, 0xb8, 0xcc, 0x6b, 0x4b, 0x03, 0xf1, 0x02, 0x0c, 0xdc, 0xab, 0xa5, 0x40, 0x24, 0x00, 0x7f, +0x74, 0x94, 0xa1, 0x9d, 0x08, 0x29, 0xb3, 0x88, 0x0b, 0xf5, 0x87, 0x77, 0x9d, 0x55, 0xcd, 0xe4, +0xc3, 0x7e, 0xd7, 0x6a, 0x64, 0xab, 0x85, 0x14, 0x86, 0x95, 0x5b, 0x97, 0x32, 0x50, 0x6f, 0x3d, +0xc8, 0xba, 0x66, 0x0c, 0xe3, 0xfc, 0xbd, 0xb8, 0x49, 0xc1, 0x76, 0x89, 0x49, 0x19, 0xfd, 0xc0, +0xa8, 0xbd, 0x89, 0xa3, 0x67, 0x2f, 0xc6, 0x9f, 0xbc, 0x71, 0x19, 0x60, 0xb8, 0x2d, 0xe9, 0x2c, +0xc9, 0x90, 0x76, 0x66, 0x7b, 0x94, 0xe2, 0xaf, 0x78, 0xd6, 0x65, 0x53, 0x5d, 0x3c, 0xd6, 0x9c, +0xb2, 0xcf, 0x29, 0x03, 0xf9, 0x2f, 0xa4, 0x50, 0xb2, 0xd4, 0x48, 0xce, 0x05, 0x32, 0x55, 0x8a, +0xfd, 0xb2, 0x64, 0x4c, 0x0e, 0xe4, 0x98, 0x07, 0x75, 0xdb, 0x7f, 0xdf, 0xb9, 0x08, 0x55, 0x60, +0x85, 0x30, 0x29, 0xf9, 0x7b, 0x48, 0xa4, 0x69, 0x86, 0xe3, 0x35, 0x3f, 0x1e, 0x86, 0x5d, 0x7a, +0x7a, 0x15, 0xbd, 0xef, 0x00, 0x8e, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xbc, 0x0e, +0x49, 0x68, 0x91, 0xbf, 0xf8, 0x47, 0xd3, 0x9d, 0x95, 0x42, 0xc1, 0x0e, 0x4d, 0xdf, 0x6f, 0x26, +0xcf, 0xc3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xd6, 0xd5, 0xc0, 0x07, 0xe1, 0x02, 0x03, 0x01, +0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, +0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, +0x04, 0x14, 0x55, 0xe4, 0x81, 0xd1, 0x11, 0x80, 0xbe, 0xd8, 0x89, 0xb9, 0x08, 0xa3, 0x31, 0xf9, +0xa1, 0x24, 0x09, 0x16, 0xb9, 0x70, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3b, 0x9b, 0x8f, 0x56, 0x9b, 0x30, +0xe7, 0x53, 0x99, 0x7c, 0x7a, 0x79, 0xa7, 0x4d, 0x97, 0xd7, 0x19, 0x95, 0x90, 0xfb, 0x06, 0x1f, +0xca, 0x33, 0x7c, 0x46, 0x63, 0x8f, 0x96, 0x66, 0x24, 0xfa, 0x40, 0x1b, 0x21, 0x27, 0xca, 0xe6, +0x72, 0x73, 0xf2, 0x4f, 0xfe, 0x31, 0x99, 0xfd, 0xc8, 0x0c, 0x4c, 0x68, 0x53, 0xc6, 0x80, 0x82, +0x13, 0x98, 0xfa, 0xb6, 0xad, 0xda, 0x5d, 0x3d, 0xf1, 0xce, 0x6e, 0xf6, 0x15, 0x11, 0x94, 0x82, +0x0c, 0xee, 0x3f, 0x95, 0xaf, 0x11, 0xab, 0x0f, 0xd7, 0x2f, 0xde, 0x1f, 0x03, 0x8f, 0x57, 0x2c, +0x1e, 0xc9, 0xbb, 0x9a, 0x1a, 0x44, 0x95, 0xeb, 0x18, 0x4f, 0xa6, 0x1f, 0xcd, 0x7d, 0x57, 0x10, +0x2f, 0x9b, 0x04, 0x09, 0x5a, 0x84, 0xb5, 0x6e, 0xd8, 0x1d, 0x3a, 0xe1, 0xd6, 0x9e, 0xd1, 0x6c, +0x79, 0x5e, 0x79, 0x1c, 0x14, 0xc5, 0xe3, 0xd0, 0x4c, 0x93, 0x3b, 0x65, 0x3c, 0xed, 0xdf, 0x3d, +0xbe, 0xa6, 0xe5, 0x95, 0x1a, 0xc3, 0xb5, 0x19, 0xc3, 0xbd, 0x5e, 0x5b, 0xbb, 0xff, 0x23, 0xef, +0x68, 0x19, 0xcb, 0x12, 0x93, 0x27, 0x5c, 0x03, 0x2d, 0x6f, 0x30, 0xd0, 0x1e, 0xb6, 0x1a, 0xac, +0xde, 0x5a, 0xf7, 0xd1, 0xaa, 0xa8, 0x27, 0xa6, 0xfe, 0x79, 0x81, 0xc4, 0x79, 0x99, 0x33, 0x57, +0xba, 0x12, 0xb0, 0xa9, 0xe0, 0x42, 0x6c, 0x93, 0xca, 0x56, 0xde, 0xfe, 0x6d, 0x84, 0x0b, 0x08, +0x8b, 0x7e, 0x8d, 0xea, 0xd7, 0x98, 0x21, 0xc6, 0xf3, 0xe7, 0x3c, 0x79, 0x2f, 0x5e, 0x9c, 0xd1, +0x4c, 0x15, 0x8d, 0xe1, 0xec, 0x22, 0x37, 0xcc, 0x9a, 0x43, 0x0b, 0x97, 0xdc, 0x80, 0x90, 0x8d, +0xb3, 0x67, 0x9b, 0x6f, 0x48, 0x08, 0x15, 0x56, 0xcf, 0xbf, 0xf1, 0x2b, 0x7c, 0x5e, 0x9a, 0x76, +0xe9, 0x59, 0x90, 0xc5, 0x7c, 0x83, 0x35, 0x11, 0x65, 0x51, 0x30, 0x82, 0x04, 0x32, 0x30, 0x82, +0x03, 0x1a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7b, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, +0x08, 0x0c, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, +0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, +0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x11, 0x43, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, +0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18, 0x41, 0x41, +0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, +0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x31, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x31, 0x32, 0x33, 0x31, 0x32, +0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x7b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x12, +0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, +0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x61, 0x6c, +0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x43, +0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, +0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, +0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, +0x63, 0x65, 0x73, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, +0x82, 0x01, 0x01, 0x00, 0xbe, 0x40, 0x9d, 0xf4, 0x6e, 0xe1, 0xea, 0x76, 0x87, 0x1c, 0x4d, 0x45, +0x44, 0x8e, 0xbe, 0x46, 0xc8, 0x83, 0x06, 0x9d, 0xc1, 0x2a, 0xfe, 0x18, 0x1f, 0x8e, 0xe4, 0x02, +0xfa, 0xf3, 0xab, 0x5d, 0x50, 0x8a, 0x16, 0x31, 0x0b, 0x9a, 0x06, 0xd0, 0xc5, 0x70, 0x22, 0xcd, +0x49, 0x2d, 0x54, 0x63, 0xcc, 0xb6, 0x6e, 0x68, 0x46, 0x0b, 0x53, 0xea, 0xcb, 0x4c, 0x24, 0xc0, +0xbc, 0x72, 0x4e, 0xea, 0xf1, 0x15, 0xae, 0xf4, 0x54, 0x9a, 0x12, 0x0a, 0xc3, 0x7a, 0xb2, 0x33, +0x60, 0xe2, 0xda, 0x89, 0x55, 0xf3, 0x22, 0x58, 0xf3, 0xde, 0xdc, 0xcf, 0xef, 0x83, 0x86, 0xa2, +0x8c, 0x94, 0x4f, 0x9f, 0x68, 0xf2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xc7, 0x76, 0xbf, 0xe3, 0xcc, +0x35, 0x2c, 0x8b, 0x5e, 0x07, 0x64, 0x65, 0x82, 0xc0, 0x48, 0xb0, 0xa8, 0x91, 0xf9, 0x61, 0x9f, +0x76, 0x20, 0x50, 0xa8, 0x91, 0xc7, 0x66, 0xb5, 0xeb, 0x78, 0x62, 0x03, 0x56, 0xf0, 0x8a, 0x1a, +0x13, 0xea, 0x31, 0xa3, 0x1e, 0xa0, 0x99, 0xfd, 0x38, 0xf6, 0xf6, 0x27, 0x32, 0x58, 0x6f, 0x07, +0xf5, 0x6b, 0xb8, 0xfb, 0x14, 0x2b, 0xaf, 0xb7, 0xaa, 0xcc, 0xd6, 0x63, 0x5f, 0x73, 0x8c, 0xda, +0x05, 0x99, 0xa8, 0x38, 0xa8, 0xcb, 0x17, 0x78, 0x36, 0x51, 0xac, 0xe9, 0x9e, 0xf4, 0x78, 0x3a, +0x8d, 0xcf, 0x0f, 0xd9, 0x42, 0xe2, 0x98, 0x0c, 0xab, 0x2f, 0x9f, 0x0e, 0x01, 0xde, 0xef, 0x9f, +0x99, 0x49, 0xf1, 0x2d, 0xdf, 0xac, 0x74, 0x4d, 0x1b, 0x98, 0xb5, 0x47, 0xc5, 0xe5, 0x29, 0xd1, +0xf9, 0x90, 0x18, 0xc7, 0x62, 0x9c, 0xbe, 0x83, 0xc7, 0x26, 0x7b, 0x3e, 0x8a, 0x25, 0xc7, 0xc0, +0xdd, 0x9d, 0xe6, 0x35, 0x68, 0x10, 0x20, 0x9d, 0x8f, 0xd8, 0xde, 0xd2, 0xc3, 0x84, 0x9c, 0x0d, +0x5e, 0xe8, 0x2f, 0xc9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xc0, 0x30, 0x81, 0xbd, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa0, 0x11, 0x0a, 0x23, 0x3e, 0x96, +0xf1, 0x07, 0xec, 0xe2, 0xaf, 0x29, 0xef, 0x82, 0xa5, 0x7f, 0xd0, 0x30, 0xa4, 0xb4, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, +0x7b, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, 0xa0, 0x34, +0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, +0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x41, 0x41, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, +0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, +0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, +0x74, 0x2f, 0x41, 0x41, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, +0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, +0x08, 0x56, 0xfc, 0x02, 0xf0, 0x9b, 0xe8, 0xff, 0xa4, 0xfa, 0xd6, 0x7b, 0xc6, 0x44, 0x80, 0xce, +0x4f, 0xc4, 0xc5, 0xf6, 0x00, 0x58, 0xcc, 0xa6, 0xb6, 0xbc, 0x14, 0x49, 0x68, 0x04, 0x76, 0xe8, +0xe6, 0xee, 0x5d, 0xec, 0x02, 0x0f, 0x60, 0xd6, 0x8d, 0x50, 0x18, 0x4f, 0x26, 0x4e, 0x01, 0xe3, +0xe6, 0xb0, 0xa5, 0xee, 0xbf, 0xbc, 0x74, 0x54, 0x41, 0xbf, 0xfd, 0xfc, 0x12, 0xb8, 0xc7, 0x4f, +0x5a, 0xf4, 0x89, 0x60, 0x05, 0x7f, 0x60, 0xb7, 0x05, 0x4a, 0xf3, 0xf6, 0xf1, 0xc2, 0xbf, 0xc4, +0xb9, 0x74, 0x86, 0xb6, 0x2d, 0x7d, 0x6b, 0xcc, 0xd2, 0xf3, 0x46, 0xdd, 0x2f, 0xc6, 0xe0, 0x6a, +0xc3, 0xc3, 0x34, 0x03, 0x2c, 0x7d, 0x96, 0xdd, 0x5a, 0xc2, 0x0e, 0xa7, 0x0a, 0x99, 0xc1, 0x05, +0x8b, 0xab, 0x0c, 0x2f, 0xf3, 0x5c, 0x3a, 0xcf, 0x6c, 0x37, 0x55, 0x09, 0x87, 0xde, 0x53, 0x40, +0x6c, 0x58, 0xef, 0xfc, 0xb6, 0xab, 0x65, 0x6e, 0x04, 0xf6, 0x1b, 0xdc, 0x3c, 0xe0, 0x5a, 0x15, +0xc6, 0x9e, 0xd9, 0xf1, 0x59, 0x48, 0x30, 0x21, 0x65, 0x03, 0x6c, 0xec, 0xe9, 0x21, 0x73, 0xec, +0x9b, 0x03, 0xa1, 0xe0, 0x37, 0xad, 0xa0, 0x15, 0x18, 0x8f, 0xfa, 0xba, 0x02, 0xce, 0xa7, 0x2c, +0xa9, 0x10, 0x13, 0x2c, 0xd4, 0xe5, 0x08, 0x26, 0xab, 0x22, 0x97, 0x60, 0xf8, 0x90, 0x5e, 0x74, +0xd4, 0xa2, 0x9a, 0x53, 0xbd, 0xf2, 0xa9, 0x68, 0xe0, 0xa2, 0x6e, 0xc2, 0xd7, 0x6c, 0xb1, 0xa3, +0x0f, 0x9e, 0xbf, 0xeb, 0x68, 0xe7, 0x56, 0xf2, 0xae, 0xf2, 0xe3, 0x2b, 0x38, 0x3a, 0x09, 0x81, +0xb5, 0x6b, 0x85, 0xd7, 0xbe, 0x2d, 0xed, 0x3f, 0x1a, 0xb7, 0xb2, 0x63, 0xe2, 0xf5, 0x62, 0x2c, +0x82, 0xd4, 0x6a, 0x00, 0x41, 0x50, 0xf1, 0x39, 0x83, 0x9f, 0x95, 0xe9, 0x36, 0x96, 0x98, 0x6e, +0x30, 0x82, 0x07, 0xd3, 0x30, 0x82, 0x05, 0xbb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5e, +0xc3, 0xb7, 0xa6, 0x43, 0x7f, 0xa4, 0xe0, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5a, 0x31, 0x31, 0x10, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x50, 0x4b, 0x49, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0d, +0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, +0x30, 0x35, 0x30, 0x35, 0x30, 0x39, 0x33, 0x37, 0x33, 0x37, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, +0x32, 0x33, 0x31, 0x30, 0x39, 0x33, 0x37, 0x33, 0x37, 0x5a, 0x30, 0x42, 0x31, 0x12, 0x30, 0x10, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5a, 0x31, +0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x50, 0x4b, 0x49, 0x41, 0x43, +0x43, 0x56, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x04, 0x41, 0x43, 0x43, +0x56, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x30, 0x82, +0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x9b, +0xa9, 0xab, 0xbf, 0x61, 0x4a, 0x97, 0xaf, 0x2f, 0x97, 0x66, 0x9a, 0x74, 0x5f, 0xd0, 0xd9, 0x96, +0xfd, 0xcf, 0xe2, 0xe4, 0x66, 0xef, 0x1f, 0x1f, 0x47, 0x33, 0xc2, 0x44, 0xa3, 0xdf, 0x9a, 0xde, +0x1f, 0xb5, 0x54, 0xdd, 0x15, 0x7c, 0x69, 0x35, 0x11, 0x6f, 0xbb, 0xc8, 0x0c, 0x8e, 0x6a, 0x18, +0x1e, 0xd8, 0x8f, 0xd9, 0x16, 0xbc, 0x10, 0x48, 0x36, 0x5c, 0xf0, 0x63, 0xb3, 0x90, 0x5a, 0x5c, +0x24, 0x37, 0xd7, 0xa3, 0xd6, 0xcb, 0x09, 0x71, 0xb9, 0xf1, 0x01, 0x72, 0x84, 0xb0, 0x7d, 0xdb, +0x4d, 0x80, 0xcd, 0xfc, 0xd3, 0x6f, 0xc9, 0xf8, 0xda, 0xb6, 0x0e, 0x82, 0xd2, 0x45, 0x85, 0xa8, +0x1b, 0x68, 0xa8, 0x3d, 0xe8, 0xf4, 0x44, 0x6c, 0xbd, 0xa1, 0xc2, 0xcb, 0x03, 0xbe, 0x8c, 0x3e, +0x13, 0x00, 0x84, 0xdf, 0x4a, 0x48, 0xc0, 0xe3, 0x22, 0x0a, 0xe8, 0xe9, 0x37, 0xa7, 0x18, 0x4c, +0xb1, 0x09, 0x0d, 0x23, 0x56, 0x7f, 0x04, 0x4d, 0xd9, 0x17, 0x84, 0x18, 0xa5, 0xc8, 0xda, 0x40, +0x94, 0x73, 0xeb, 0xce, 0x0e, 0x57, 0x3c, 0x03, 0x81, 0x3a, 0x9d, 0x0a, 0xa1, 0x57, 0x43, 0x69, +0xac, 0x57, 0x6d, 0x79, 0x90, 0x78, 0xe5, 0xb5, 0xb4, 0x3b, 0xd8, 0xbc, 0x4c, 0x8d, 0x28, 0xa1, +0xa7, 0xa3, 0xa7, 0xba, 0x02, 0x4e, 0x25, 0xd1, 0x2a, 0xae, 0xed, 0xae, 0x03, 0x22, 0xb8, 0x6b, +0x20, 0x0f, 0x30, 0x28, 0x54, 0x95, 0x7f, 0xe0, 0xee, 0xce, 0x0a, 0x66, 0x9d, 0xd1, 0x40, 0x2d, +0x6e, 0x22, 0xaf, 0x9d, 0x1a, 0xc1, 0x05, 0x19, 0xd2, 0x6f, 0xc0, 0xf2, 0x9f, 0xf8, 0x7b, 0xb3, +0x02, 0x42, 0xfb, 0x50, 0xa9, 0x1d, 0x2d, 0x93, 0x0f, 0x23, 0xab, 0xc6, 0xc1, 0x0f, 0x92, 0xff, +0xd0, 0xa2, 0x15, 0xf5, 0x53, 0x09, 0x71, 0x1c, 0xff, 0x45, 0x13, 0x84, 0xe6, 0x26, 0x5e, 0xf8, +0xe0, 0x88, 0x1c, 0x0a, 0xfc, 0x16, 0xb6, 0xa8, 0x73, 0x06, 0xb8, 0xf0, 0x63, 0x84, 0x02, 0xa0, +0xc6, 0x5a, 0xec, 0xe7, 0x74, 0xdf, 0x70, 0xae, 0xa3, 0x83, 0x25, 0xea, 0xd6, 0xc7, 0x97, 0x87, +0x93, 0xa7, 0xc6, 0x8a, 0x8a, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3e, 0x97, 0x3e, 0x6e, 0x29, 0x15, +0xd6, 0xa1, 0x0f, 0xd1, 0x88, 0x2c, 0x12, 0x9f, 0x6f, 0xaa, 0xa4, 0xc6, 0x42, 0xeb, 0x41, 0xa2, +0xe3, 0x95, 0x43, 0xd3, 0x01, 0x85, 0x6d, 0x8e, 0xbb, 0x3b, 0xf3, 0x23, 0x36, 0xc7, 0xfe, 0x3b, +0xe0, 0xa1, 0x25, 0x07, 0x48, 0xab, 0xc9, 0x89, 0x74, 0xff, 0x08, 0x8f, 0x80, 0xbf, 0xc0, 0x96, +0x65, 0xf3, 0xee, 0xec, 0x4b, 0x68, 0xbd, 0x9d, 0x88, 0xc3, 0x31, 0xb3, 0x40, 0xf1, 0xe8, 0xcf, +0xf6, 0x38, 0xbb, 0x9c, 0xe4, 0xd1, 0x7f, 0xd4, 0xe5, 0x58, 0x9b, 0x7c, 0xfa, 0xd4, 0xf3, 0x0e, +0x9b, 0x75, 0x91, 0xe4, 0xba, 0x52, 0x2e, 0x19, 0x7e, 0xd1, 0xf5, 0xcd, 0x5a, 0x19, 0xfc, 0xba, +0x06, 0xf6, 0xfb, 0x52, 0xa8, 0x4b, 0x99, 0x04, 0xdd, 0xf8, 0xf9, 0xb4, 0x8b, 0x50, 0xa3, 0x4e, +0x62, 0x89, 0xf0, 0x87, 0x24, 0xfa, 0x83, 0x42, 0xc1, 0x87, 0xfa, 0xd5, 0x2d, 0x29, 0x2a, 0x5a, +0x71, 0x7a, 0x64, 0x6a, 0xd7, 0x27, 0x60, 0x63, 0x0d, 0xdb, 0xce, 0x49, 0xf5, 0x8d, 0x1f, 0x90, +0x89, 0x32, 0x17, 0xf8, 0x73, 0x43, 0xb8, 0xd2, 0x5a, 0x93, 0x86, 0x61, 0xd6, 0xe1, 0x75, 0x0a, +0xea, 0x79, 0x66, 0x76, 0x88, 0x4f, 0x71, 0xeb, 0x04, 0x25, 0xd6, 0x0a, 0x5a, 0x7a, 0x93, 0xe5, +0xb9, 0x4b, 0x17, 0x40, 0x0f, 0xb1, 0xb6, 0xb9, 0xf5, 0xde, 0x4f, 0xdc, 0xe0, 0xb3, 0xac, 0x3b, +0x11, 0x70, 0x60, 0x84, 0x4a, 0x43, 0x6e, 0x99, 0x20, 0xc0, 0x29, 0x71, 0x0a, 0xc0, 0x65, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0xcb, 0x30, 0x82, 0x02, 0xc7, 0x30, 0x7d, 0x06, 0x08, +0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x71, 0x30, 0x6f, 0x30, 0x4c, 0x06, 0x08, +0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x40, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x63, 0x63, 0x76, 0x2e, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x6c, +0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2f, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x6f, 0x73, 0x2f, +0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x64, 0x6f, 0x73, 0x2f, 0x72, 0x61, 0x69, +0x7a, 0x61, 0x63, 0x63, 0x76, 0x31, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, +0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x13, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, +0x63, 0x73, 0x70, 0x2e, 0x61, 0x63, 0x63, 0x76, 0x2e, 0x65, 0x73, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd2, 0x87, 0xb4, 0xe3, 0xdf, 0x37, 0x27, 0x93, 0x55, 0xf6, +0x56, 0xea, 0x81, 0xe5, 0x36, 0xcc, 0x8c, 0x1e, 0x3f, 0xbd, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, +0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, +0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd2, 0x87, 0xb4, 0xe3, 0xdf, 0x37, 0x27, 0x93, +0x55, 0xf6, 0x56, 0xea, 0x81, 0xe5, 0x36, 0xcc, 0x8c, 0x1e, 0x3f, 0xbd, 0x30, 0x82, 0x01, 0x73, +0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0x6a, 0x30, 0x82, 0x01, 0x66, 0x30, 0x82, 0x01, +0x62, 0x06, 0x04, 0x55, 0x1d, 0x20, 0x00, 0x30, 0x82, 0x01, 0x58, 0x30, 0x82, 0x01, 0x22, 0x06, +0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x14, 0x1e, 0x82, 0x01, +0x10, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x69, 0x00, 0x64, 0x00, +0x61, 0x00, 0x64, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x43, 0x00, 0x65, 0x00, +0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x63, 0x00, +0x69, 0x00, 0xf3, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x52, 0x00, 0x61, 0x00, 0xed, 0x00, 0x7a, 0x00, +0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x20, 0x00, 0x41, 0x00, +0x43, 0x00, 0x43, 0x00, 0x56, 0x00, 0x20, 0x00, 0x28, 0x00, 0x41, 0x00, 0x67, 0x00, 0x65, 0x00, +0x6e, 0x00, 0x63, 0x00, 0x69, 0x00, 0x61, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, +0x54, 0x00, 0x65, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x67, 0x00, +0xed, 0x00, 0x61, 0x00, 0x20, 0x00, 0x79, 0x00, 0x20, 0x00, 0x43, 0x00, 0x65, 0x00, 0x72, 0x00, +0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, +0xf3, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, +0x72, 0x00, 0xf3, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x2c, 0x00, 0x20, 0x00, +0x43, 0x00, 0x49, 0x00, 0x46, 0x00, 0x20, 0x00, 0x51, 0x00, 0x34, 0x00, 0x36, 0x00, 0x30, 0x00, +0x31, 0x00, 0x31, 0x00, 0x35, 0x00, 0x36, 0x00, 0x45, 0x00, 0x29, 0x00, 0x2e, 0x00, 0x20, 0x00, +0x43, 0x00, 0x50, 0x00, 0x53, 0x00, 0x20, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x68, 0x00, +0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x77, 0x00, 0x77, 0x00, +0x77, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x76, 0x00, 0x2e, 0x00, 0x65, 0x00, +0x73, 0x30, 0x30, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x24, 0x68, +0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x63, 0x63, 0x76, 0x2e, 0x65, +0x73, 0x2f, 0x6c, 0x65, 0x67, 0x69, 0x73, 0x6c, 0x61, 0x63, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x2e, +0x68, 0x74, 0x6d, 0x30, 0x55, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x4e, 0x30, 0x4c, 0x30, 0x4a, +0xa0, 0x48, 0xa0, 0x46, 0x86, 0x44, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, +0x2e, 0x61, 0x63, 0x63, 0x76, 0x2e, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x61, 0x64, 0x6d, +0x69, 0x6e, 0x2f, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x6f, 0x73, 0x2f, 0x63, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x64, 0x6f, 0x73, 0x2f, 0x72, 0x61, 0x69, 0x7a, 0x61, 0x63, 0x63, +0x76, 0x31, 0x5f, 0x64, 0x65, 0x72, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, +0x11, 0x04, 0x10, 0x30, 0x0e, 0x81, 0x0c, 0x61, 0x63, 0x63, 0x76, 0x40, 0x61, 0x63, 0x63, 0x76, +0x2e, 0x65, 0x73, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, +0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x97, 0x31, 0x02, 0x9f, 0xe7, 0xfd, 0x43, 0x67, 0x48, +0x44, 0x14, 0xe4, 0x29, 0x87, 0xed, 0x4c, 0x28, 0x66, 0xd0, 0x8f, 0x35, 0xda, 0x4d, 0x61, 0xb7, +0x4a, 0x97, 0x4d, 0xb5, 0xdb, 0x90, 0xe0, 0x05, 0x2e, 0x0e, 0xc6, 0x79, 0xd0, 0xf2, 0x97, 0x69, +0x0f, 0xbd, 0x04, 0x47, 0xd9, 0xbe, 0xdb, 0xb5, 0x29, 0xda, 0x9b, 0xd9, 0xae, 0xa9, 0x99, 0xd5, +0xd3, 0x3c, 0x30, 0x93, 0xf5, 0x8d, 0xa1, 0xa8, 0xfc, 0x06, 0x8d, 0x44, 0xf4, 0xca, 0x16, 0x95, +0x7c, 0x33, 0xdc, 0x62, 0x8b, 0xa8, 0x37, 0xf8, 0x27, 0xd8, 0x09, 0x2d, 0x1b, 0xef, 0xc8, 0x14, +0x27, 0x20, 0xa9, 0x64, 0x44, 0xff, 0x2e, 0xd6, 0x75, 0xaa, 0x6c, 0x4d, 0x60, 0x40, 0x19, 0x49, +0x43, 0x54, 0x63, 0xda, 0xe2, 0xcc, 0xba, 0x66, 0xe5, 0x4f, 0x44, 0x7a, 0x5b, 0xd9, 0x6a, 0x81, +0x2b, 0x40, 0xd5, 0x7f, 0xf9, 0x01, 0x27, 0x58, 0x2c, 0xc8, 0xed, 0x48, 0x91, 0x7c, 0x3f, 0xa6, +0x00, 0xcf, 0xc4, 0x29, 0x73, 0x11, 0x36, 0xde, 0x86, 0x19, 0x3e, 0x9d, 0xee, 0x19, 0x8a, 0x1b, +0xd5, 0xb0, 0xed, 0x8e, 0x3d, 0x9c, 0x2a, 0xc0, 0x0d, 0xd8, 0x3d, 0x66, 0xe3, 0x3c, 0x0d, 0xbd, +0xd5, 0x94, 0x5c, 0xe2, 0xe2, 0xa7, 0x35, 0x1b, 0x04, 0x00, 0xf6, 0x3f, 0x5a, 0x8d, 0xea, 0x43, +0xbd, 0x5f, 0x89, 0x1d, 0xa9, 0xc1, 0xb0, 0xcc, 0x99, 0xe2, 0x4d, 0x00, 0x0a, 0xda, 0xc9, 0x27, +0x5b, 0xe7, 0x13, 0x90, 0x5c, 0xe4, 0xf5, 0x33, 0xa2, 0x55, 0x6d, 0xdc, 0xe0, 0x09, 0x4d, 0x2f, +0xb1, 0x26, 0x5b, 0x27, 0x75, 0x00, 0x09, 0xc4, 0x62, 0x77, 0x29, 0x08, 0x5f, 0x9e, 0x59, 0xac, +0xb6, 0x7e, 0xad, 0x9f, 0x54, 0x30, 0x22, 0x03, 0xc1, 0x1e, 0x71, 0x64, 0xfe, 0xf9, 0x38, 0x0a, +0x96, 0x18, 0xdd, 0x02, 0x14, 0xac, 0x23, 0xcb, 0x06, 0x1c, 0x1e, 0xa4, 0x7d, 0x8d, 0x0d, 0xde, +0x27, 0x41, 0xe8, 0xad, 0xda, 0x15, 0xb7, 0xb0, 0x23, 0xdd, 0x2b, 0xa8, 0xd3, 0xda, 0x25, 0x87, +0xed, 0xe8, 0x55, 0x44, 0x4d, 0x88, 0xf4, 0x36, 0x7e, 0x84, 0x9a, 0x78, 0xac, 0xf7, 0x0e, 0x56, +0x49, 0x0e, 0xd6, 0x33, 0x25, 0xd6, 0x84, 0x50, 0x42, 0x6c, 0x20, 0x12, 0x1d, 0x2a, 0xd5, 0xbe, +0xbc, 0xf2, 0x70, 0x81, 0xa4, 0x70, 0x60, 0xbe, 0x05, 0xb5, 0x9b, 0x9e, 0x04, 0x44, 0xbe, 0x61, +0x23, 0xac, 0xe9, 0xa5, 0x24, 0x8c, 0x11, 0x80, 0x94, 0x5a, 0xa2, 0xa2, 0xb9, 0x49, 0xd2, 0xc1, +0xdc, 0xd1, 0xa7, 0xed, 0x31, 0x11, 0x2c, 0x9e, 0x19, 0xa6, 0xee, 0xe1, 0x55, 0xe1, 0xc0, 0xea, +0xcf, 0x0d, 0x84, 0xe4, 0x17, 0xb7, 0xa2, 0x7c, 0xa5, 0xde, 0x55, 0x25, 0x06, 0xee, 0xcc, 0xc0, +0x87, 0x5c, 0x40, 0xda, 0xcc, 0x95, 0x3f, 0x55, 0xe0, 0x35, 0xc7, 0xb8, 0x84, 0xbe, 0xb4, 0x5d, +0xcd, 0x7a, 0x83, 0x01, 0x72, 0xee, 0x87, 0xe6, 0x5f, 0x1d, 0xae, 0xb5, 0x85, 0xc6, 0x26, 0xdf, +0xe6, 0xc1, 0x9a, 0xe9, 0x1e, 0x02, 0x47, 0x9f, 0x2a, 0xa8, 0x6d, 0xa9, 0x5b, 0xcf, 0xec, 0x45, +0x77, 0x7f, 0x98, 0x27, 0x9a, 0x32, 0x5d, 0x2a, 0xe3, 0x84, 0xee, 0xc5, 0x98, 0x66, 0x2f, 0x96, +0x20, 0x1d, 0xdd, 0xd8, 0xc3, 0x27, 0xd7, 0xb0, 0xf9, 0xfe, 0xd9, 0x7d, 0xcd, 0xd0, 0x9f, 0x8f, +0x0b, 0x14, 0x58, 0x51, 0x9f, 0x2f, 0x8b, 0xc3, 0x38, 0x2d, 0xde, 0xe8, 0x8f, 0xd6, 0x8d, 0x87, +0xa4, 0xf5, 0x56, 0x43, 0x16, 0x99, 0x2c, 0xf4, 0xa4, 0x56, 0xb4, 0x34, 0xb8, 0x61, 0x37, 0xc9, +0xc2, 0x58, 0x80, 0x1b, 0xa0, 0x97, 0xa1, 0xfc, 0x59, 0x8d, 0xe9, 0x11, 0xf6, 0xd1, 0x0f, 0x4b, +0x55, 0x34, 0x46, 0x2a, 0x8b, 0x86, 0x3b, 0x30, 0x82, 0x05, 0xbb, 0x30, 0x82, 0x03, 0xa3, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x57, 0x0a, 0x11, 0x97, 0x42, 0xc4, 0xe3, 0xcc, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x6b, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x54, 0x31, 0x0e, 0x30, 0x0c, +0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x05, 0x4d, 0x69, 0x6c, 0x61, 0x6e, 0x31, 0x23, 0x30, 0x21, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1a, 0x41, 0x63, 0x74, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x53, +0x2e, 0x70, 0x2e, 0x41, 0x2e, 0x2f, 0x30, 0x33, 0x33, 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, +0x37, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x41, 0x63, 0x74, 0x61, +0x6c, 0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, +0x30, 0x39, 0x32, 0x32, 0x31, 0x31, 0x32, 0x32, 0x30, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x30, +0x39, 0x32, 0x32, 0x31, 0x31, 0x32, 0x32, 0x30, 0x32, 0x5a, 0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x54, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, +0x04, 0x07, 0x0c, 0x05, 0x4d, 0x69, 0x6c, 0x61, 0x6e, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x0c, 0x1a, 0x41, 0x63, 0x74, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x53, 0x2e, 0x70, 0x2e, +0x41, 0x2e, 0x2f, 0x30, 0x33, 0x33, 0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, +0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x41, 0x63, 0x74, 0x61, 0x6c, 0x69, 0x73, +0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, +0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa7, 0xc6, 0xc4, 0xa5, 0x29, 0xa4, 0x2c, 0xef, +0xe5, 0x18, 0xc5, 0xb0, 0x50, 0xa3, 0x6f, 0x51, 0x3b, 0x9f, 0x0a, 0x5a, 0xc9, 0xc2, 0x48, 0x38, +0x0a, 0xc2, 0x1c, 0xa0, 0x18, 0x7f, 0x91, 0xb5, 0x87, 0xb9, 0x40, 0x3f, 0xdd, 0x1d, 0x68, 0x1f, +0x08, 0x83, 0xd5, 0x2d, 0x1e, 0x88, 0xa0, 0xf8, 0x8f, 0x56, 0x8f, 0x6d, 0x99, 0x02, 0x92, 0x90, +0x16, 0xd5, 0x5f, 0x08, 0x6c, 0x89, 0xd7, 0xe1, 0xac, 0xbc, 0x20, 0xc2, 0xb1, 0xe0, 0x83, 0x51, +0x8a, 0x69, 0x4d, 0x00, 0x96, 0x5a, 0x6f, 0x2f, 0xc0, 0x44, 0x7e, 0xa3, 0x0e, 0xe4, 0x91, 0xcd, +0x58, 0xee, 0xdc, 0xfb, 0xc7, 0x1e, 0x45, 0x47, 0xdd, 0x27, 0xb9, 0x08, 0x01, 0x9f, 0xa6, 0x21, +0x1d, 0xf5, 0x41, 0x2d, 0x2f, 0x4c, 0xfd, 0x28, 0xad, 0xe0, 0x8a, 0xad, 0x22, 0xb4, 0x56, 0x65, +0x8e, 0x86, 0x54, 0x8f, 0x93, 0x43, 0x29, 0xde, 0x39, 0x46, 0x78, 0xa3, 0x30, 0x23, 0xba, 0xcd, +0xf0, 0x7d, 0x13, 0x57, 0xc0, 0x5d, 0xd2, 0x83, 0x6b, 0x48, 0x4c, 0xc4, 0xab, 0x9f, 0x80, 0x5a, +0x5b, 0x3a, 0xbd, 0xc9, 0xa7, 0x22, 0x3f, 0x80, 0x27, 0x33, 0x5b, 0x0e, 0xb7, 0x8a, 0x0c, 0x5d, +0x07, 0x37, 0x08, 0xcb, 0x6c, 0xd2, 0x7a, 0x47, 0x22, 0x44, 0x35, 0xc5, 0xcc, 0xcc, 0x2e, 0x8e, +0xdd, 0x2a, 0xed, 0xb7, 0x7d, 0x66, 0x0d, 0x5f, 0x61, 0x51, 0x22, 0x55, 0x1b, 0xe3, 0x46, 0xe3, +0xe3, 0x3d, 0xd0, 0x35, 0x62, 0x9a, 0xdb, 0xaf, 0x14, 0xc8, 0x5b, 0xa1, 0xcc, 0x89, 0x1b, 0xe1, +0x30, 0x26, 0xfc, 0xa0, 0x9b, 0x1f, 0x81, 0xa7, 0x47, 0x1f, 0x04, 0xeb, 0xa3, 0x39, 0x92, 0x06, +0x9f, 0x99, 0xd3, 0xbf, 0xd3, 0xea, 0x4f, 0x50, 0x9c, 0x19, 0xfe, 0x96, 0x87, 0x1e, 0x3c, 0x65, +0xf6, 0xa3, 0x18, 0x24, 0x83, 0x86, 0x10, 0xe7, 0x54, 0x3e, 0xa8, 0x3a, 0x76, 0x24, 0x4f, 0x81, +0x21, 0xc5, 0xe3, 0x0f, 0x02, 0xf8, 0x93, 0x94, 0x47, 0x20, 0xbb, 0xfe, 0xd4, 0x0e, 0xd3, 0x68, +0xb9, 0xdd, 0xc4, 0x7a, 0x84, 0x82, 0xe3, 0x53, 0x54, 0x79, 0xdd, 0xdb, 0x9c, 0xd2, 0xf2, 0x07, +0x9b, 0x2e, 0xb6, 0xbc, 0x3e, 0xed, 0x85, 0x6d, 0xef, 0x25, 0x11, 0xf2, 0x97, 0x1a, 0x42, 0x61, +0xf7, 0x4a, 0x97, 0xe8, 0x8b, 0xb1, 0x10, 0x07, 0xfa, 0x65, 0x81, 0xb2, 0xa2, 0x39, 0xcf, 0xf7, +0x3c, 0xff, 0x18, 0xfb, 0xc6, 0xf1, 0x5a, 0x8b, 0x59, 0xe2, 0x02, 0xac, 0x7b, 0x92, 0xd0, 0x4e, +0x14, 0x4f, 0x59, 0x45, 0xf6, 0x0c, 0x5e, 0x28, 0x5f, 0xb0, 0xe8, 0x3f, 0x45, 0xcf, 0xcf, 0xaf, +0x9b, 0x6f, 0xfb, 0x84, 0xd3, 0x77, 0x5a, 0x95, 0x6f, 0xac, 0x94, 0x84, 0x9e, 0xee, 0xbc, 0xc0, +0x4a, 0x8f, 0x4a, 0x93, 0xf8, 0x44, 0x21, 0xe2, 0x31, 0x45, 0x61, 0x50, 0x4e, 0x10, 0xd8, 0xe3, +0x35, 0x7c, 0x4c, 0x19, 0xb4, 0xde, 0x05, 0xbf, 0xa3, 0x06, 0x9f, 0xc8, 0xb5, 0xcd, 0xe4, 0x1f, +0xd7, 0x17, 0x06, 0x0d, 0x7a, 0x95, 0x74, 0x55, 0x0d, 0x68, 0x1a, 0xfc, 0x10, 0x1b, 0x62, 0x64, +0x9d, 0x6d, 0xe0, 0x95, 0xa0, 0xc3, 0x94, 0x07, 0x57, 0x0d, 0x14, 0xe6, 0xbd, 0x05, 0xfb, 0xb8, +0x9f, 0xe6, 0xdf, 0x8b, 0xe2, 0xc6, 0xe7, 0x7e, 0x96, 0xf6, 0x53, 0xc5, 0x80, 0x34, 0x50, 0x28, +0x58, 0xf0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xba, 0xe6, 0x78, 0x63, 0xbc, 0xf4, 0xb2, 0xad, 0x9b, +0x2b, 0xb2, 0xfe, 0xe1, 0x39, 0x8c, 0x5e, 0xba, 0x0b, 0x20, 0x94, 0xde, 0x7b, 0x83, 0xb8, 0xff, +0xe3, 0x56, 0x8d, 0xb7, 0x11, 0xe9, 0x3b, 0x8c, 0xf2, 0xb1, 0xc1, 0x5d, 0x9d, 0xa4, 0x0b, 0x4c, +0x2b, 0xd9, 0xb2, 0x18, 0xf5, 0xb5, 0x9f, 0x4b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, +0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x52, 0xd8, 0x88, 0x3a, +0xc8, 0x9f, 0x78, 0x66, 0xed, 0x89, 0xf3, 0x7b, 0x38, 0x70, 0x94, 0xc9, 0x02, 0x02, 0x36, 0xd0, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x52, 0xd8, +0x88, 0x3a, 0xc8, 0x9f, 0x78, 0x66, 0xed, 0x89, 0xf3, 0x7b, 0x38, 0x70, 0x94, 0xc9, 0x02, 0x02, +0x36, 0xd0, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0b, 0x7b, 0x72, 0x87, 0xc0, 0x60, 0xa6, 0x49, 0x4c, 0x88, +0x58, 0xe6, 0x1d, 0x88, 0xf7, 0x14, 0x64, 0x48, 0xa6, 0xd8, 0x58, 0x0a, 0x0e, 0x4f, 0x13, 0x35, +0xdf, 0x35, 0x1d, 0xd4, 0xed, 0x06, 0x31, 0xc8, 0x81, 0x3e, 0x6a, 0xd5, 0xdd, 0x3b, 0x1a, 0x32, +0xee, 0x90, 0x3d, 0x11, 0xd2, 0x2e, 0xf4, 0x8e, 0xc3, 0x63, 0x2e, 0x23, 0x66, 0xb0, 0x67, 0xbe, +0x6f, 0xb6, 0xc0, 0x13, 0x39, 0x60, 0xaa, 0xa2, 0x34, 0x25, 0x93, 0x75, 0x52, 0xde, 0xa7, 0x9d, +0xad, 0x0e, 0x87, 0x89, 0x52, 0x71, 0x6a, 0x16, 0x3c, 0x19, 0x1d, 0x83, 0xf8, 0x9a, 0x29, 0x65, +0xbe, 0xf4, 0x3f, 0x9a, 0xd9, 0xf0, 0xf3, 0x5a, 0x87, 0x21, 0x71, 0x80, 0x4d, 0xcb, 0xe0, 0x38, +0x9b, 0x3f, 0xbb, 0xfa, 0xe0, 0x30, 0x4d, 0xcf, 0x86, 0xd3, 0x65, 0x10, 0x19, 0x18, 0xd1, 0x97, +0x02, 0xb1, 0x2b, 0x72, 0x42, 0x68, 0xac, 0xa0, 0xbd, 0x4e, 0x5a, 0xda, 0x18, 0xbf, 0x6b, 0x98, +0x81, 0xd0, 0xfd, 0x9a, 0xbe, 0x5e, 0x15, 0x48, 0xcd, 0x11, 0x15, 0xb9, 0xc0, 0x29, 0x5c, 0xb4, +0xe8, 0x88, 0xf7, 0x3e, 0x36, 0xae, 0xb7, 0x62, 0xfd, 0x1e, 0x62, 0xde, 0x70, 0x78, 0x10, 0x1c, +0x48, 0x5b, 0xda, 0xbc, 0xa4, 0x38, 0xba, 0x67, 0xed, 0x55, 0x3e, 0x5e, 0x57, 0xdf, 0xd4, 0x03, +0x40, 0x4c, 0x81, 0xa4, 0xd2, 0x4f, 0x63, 0xa7, 0x09, 0x42, 0x09, 0x14, 0xfc, 0x00, 0xa9, 0xc2, +0x80, 0x73, 0x4f, 0x2e, 0xc0, 0x40, 0xd9, 0x11, 0x7b, 0x48, 0xea, 0x7a, 0x02, 0xc0, 0xd3, 0xeb, +0x28, 0x01, 0x26, 0x58, 0x74, 0xc1, 0xc0, 0x73, 0x22, 0x6d, 0x93, 0x95, 0xfd, 0x39, 0x7d, 0xbb, +0x2a, 0xe3, 0xf6, 0x82, 0xe3, 0x2c, 0x97, 0x5f, 0x4e, 0x1f, 0x91, 0x94, 0xfa, 0xfe, 0x2c, 0xa3, +0xd8, 0x76, 0x1a, 0xb8, 0x4d, 0xb2, 0x38, 0x4f, 0x9b, 0xfa, 0x1d, 0x48, 0x60, 0x79, 0x26, 0xe2, +0xf3, 0xfd, 0xa9, 0xd0, 0x9a, 0xe8, 0x70, 0x8f, 0x49, 0x7a, 0xd6, 0xe5, 0xbd, 0x0a, 0x0e, 0xdb, +0x2d, 0xf3, 0x8d, 0xbf, 0xeb, 0xe3, 0xa4, 0x7d, 0xcb, 0xc7, 0x95, 0x71, 0xe8, 0xda, 0xa3, 0x7c, +0xc5, 0xc2, 0xf8, 0x74, 0x92, 0x04, 0x1b, 0x86, 0xac, 0xa4, 0x22, 0x53, 0x40, 0xb6, 0xac, 0xfe, +0x4c, 0x76, 0xcf, 0xfb, 0x94, 0x32, 0xc0, 0x35, 0x9f, 0x76, 0x3f, 0x6e, 0xe5, 0x90, 0x6e, 0xa0, +0xa6, 0x26, 0xa2, 0xb8, 0x2c, 0xbe, 0xd1, 0x2b, 0x85, 0xfd, 0xa7, 0x68, 0xc8, 0xba, 0x01, 0x2b, +0xb1, 0x6c, 0x74, 0x1d, 0xb8, 0x73, 0x95, 0xe7, 0xee, 0xb7, 0xc7, 0x25, 0xf0, 0x00, 0x4c, 0x00, +0xb2, 0x7e, 0xb6, 0x0b, 0x8b, 0x1c, 0xf3, 0xc0, 0x50, 0x9e, 0x25, 0xb9, 0xe0, 0x08, 0xde, 0x36, +0x66, 0xff, 0x37, 0xa5, 0xd1, 0xbb, 0x54, 0x64, 0x2c, 0xc9, 0x27, 0xb5, 0x4b, 0x92, 0x7e, 0x65, +0xff, 0xd3, 0x2d, 0xe1, 0xb9, 0x4e, 0xbc, 0x7f, 0xa4, 0x41, 0x21, 0x90, 0x41, 0x77, 0xa6, 0x39, +0x1f, 0xea, 0x9e, 0xe3, 0x9f, 0xd0, 0x66, 0x6f, 0x05, 0xec, 0xaa, 0x76, 0x7e, 0xbf, 0x6b, 0x16, +0xa0, 0xeb, 0xb5, 0xc7, 0xfc, 0x92, 0x54, 0x2f, 0x2b, 0x11, 0x27, 0x25, 0x37, 0x78, 0x4c, 0x51, +0x6a, 0xb0, 0xf3, 0xcc, 0x58, 0x5d, 0x14, 0xf1, 0x6a, 0x48, 0x15, 0xff, 0xc2, 0x07, 0xb6, 0xb1, +0x8d, 0x0f, 0x8e, 0x5c, 0x50, 0x46, 0xb3, 0x3d, 0xbf, 0x01, 0x98, 0x4f, 0xb2, 0x59, 0x54, 0x47, +0x3e, 0x34, 0x7b, 0x78, 0x6d, 0x56, 0x93, 0x2e, 0x73, 0xea, 0x66, 0x28, 0x78, 0xcd, 0x1d, 0x14, +0xbf, 0xa0, 0x8f, 0x2f, 0x2e, 0xb8, 0x2e, 0x8e, 0xf2, 0x14, 0x8a, 0xcc, 0xe9, 0xb5, 0x7c, 0xfb, +0x6c, 0x9d, 0x0c, 0xa5, 0xe1, 0x96, 0x30, 0x82, 0x03, 0x4c, 0x30, 0x82, 0x02, 0x34, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x08, 0x77, 0x77, 0x06, 0x27, 0x26, 0xa9, 0xb1, 0x7c, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x44, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, +0x74, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x41, 0x66, 0x66, 0x69, +0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, +0x61, 0x6c, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x32, 0x39, 0x31, 0x34, 0x30, 0x36, +0x30, 0x36, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x30, 0x36, 0x30, +0x36, 0x5a, 0x30, 0x44, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, 0x69, +0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, +0x0c, 0x16, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, +0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6c, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, +0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf6, 0x1b, 0x4f, 0x67, 0x07, 0x2b, 0xa1, +0x15, 0xf5, 0x06, 0x22, 0xcb, 0x1f, 0x01, 0xb2, 0xe3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2c, 0xbb, +0x49, 0x25, 0x14, 0xd6, 0xce, 0xc3, 0xb7, 0xab, 0x2c, 0x4f, 0xc6, 0x41, 0x32, 0x94, 0x57, 0xfa, +0x12, 0xa7, 0x5b, 0x0e, 0xe2, 0x8f, 0x1f, 0x1e, 0x86, 0x19, 0xa7, 0xaa, 0xb5, 0x2d, 0xb9, 0x5f, +0x0d, 0x8a, 0xc2, 0xaf, 0x85, 0x35, 0x79, 0x32, 0x2d, 0xbb, 0x1c, 0x62, 0x37, 0xf2, 0xb1, 0x5b, +0x4a, 0x3d, 0xca, 0xcd, 0x71, 0x5f, 0xe9, 0x42, 0xbe, 0x94, 0xe8, 0xc8, 0xde, 0xf9, 0x22, 0x48, +0x64, 0xc6, 0xe5, 0xab, 0xc6, 0x2b, 0x6d, 0xad, 0x05, 0xf0, 0xfa, 0xd5, 0x0b, 0xcf, 0x9a, 0xe5, +0xf0, 0x50, 0xa4, 0x8b, 0x3b, 0x47, 0xa5, 0x23, 0x5b, 0x7a, 0x7a, 0xf8, 0x33, 0x3f, 0xb8, 0xef, +0x99, 0x97, 0xe3, 0x20, 0xc1, 0xd6, 0x28, 0x89, 0xcf, 0x94, 0xfb, 0xb9, 0x45, 0xed, 0xe3, 0x40, +0x17, 0x11, 0xd4, 0x74, 0xf0, 0x0b, 0x31, 0xe2, 0x2b, 0x26, 0x6a, 0x9b, 0x4c, 0x57, 0xae, 0xac, +0x20, 0x3e, 0xba, 0x45, 0x7a, 0x05, 0xf3, 0xbd, 0x9b, 0x69, 0x15, 0xae, 0x7d, 0x4e, 0x20, 0x63, +0xc4, 0x35, 0x76, 0x3a, 0x07, 0x02, 0xc9, 0x37, 0xfd, 0xc7, 0x47, 0xee, 0xe8, 0xf1, 0x76, 0x1d, +0x73, 0x15, 0xf2, 0x97, 0xa4, 0xb5, 0xc8, 0x7a, 0x79, 0xd9, 0x42, 0xaa, 0x2b, 0x7f, 0x5c, 0xfe, +0xce, 0x26, 0x4f, 0xa3, 0x66, 0x81, 0x35, 0xaf, 0x44, 0xba, 0x54, 0x1e, 0x1c, 0x30, 0x32, 0x65, +0x9d, 0xe6, 0x3c, 0x93, 0x5e, 0x50, 0x4e, 0x7a, 0xe3, 0x3a, 0xd4, 0x6e, 0xcc, 0x1a, 0xfb, 0xf9, +0xd2, 0x37, 0xae, 0x24, 0x2a, 0xab, 0x57, 0x03, 0x22, 0x28, 0x0d, 0x49, 0x75, 0x7f, 0xb7, 0x28, +0xda, 0x75, 0xbf, 0x8e, 0xe3, 0xdc, 0x0e, 0x79, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, 0x93, 0xc6, +0x53, 0x8b, 0x5e, 0xca, 0xaf, 0x3f, 0x9f, 0x1e, 0x0f, 0xe5, 0x99, 0x95, 0xbc, 0x24, 0xf6, 0x94, +0x8f, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x58, 0xac, 0xf4, 0x04, 0x0e, 0xcd, 0xc0, 0x0d, 0xff, 0x0a, +0xfd, 0xd4, 0xba, 0x16, 0x5f, 0x29, 0xbd, 0x7b, 0x68, 0x99, 0x58, 0x49, 0xd2, 0xb4, 0x1d, 0x37, +0x4d, 0x7f, 0x27, 0x7d, 0x46, 0x06, 0x5d, 0x43, 0xc6, 0x86, 0x2e, 0x3e, 0x73, 0xb2, 0x26, 0x7d, +0x4f, 0x93, 0xa9, 0xb6, 0xc4, 0x2a, 0x9a, 0xab, 0x21, 0x97, 0x14, 0xb1, 0xde, 0x8c, 0xd3, 0xab, +0x89, 0x15, 0xd8, 0x6b, 0x24, 0xd4, 0xf1, 0x16, 0xae, 0xd8, 0xa4, 0x5c, 0xd4, 0x7f, 0x51, 0x8e, +0xed, 0x18, 0x01, 0xb1, 0x93, 0x63, 0xbd, 0xbc, 0xf8, 0x61, 0x80, 0x9a, 0x9e, 0xb1, 0xce, 0x42, +0x70, 0xe2, 0xa9, 0x7d, 0x06, 0x25, 0x7d, 0x27, 0xa1, 0xfe, 0x6f, 0xec, 0xb3, 0x1e, 0x24, 0xda, +0xe3, 0x4b, 0x55, 0x1a, 0x00, 0x3b, 0x35, 0xb4, 0x3b, 0xd9, 0xd7, 0x5d, 0x30, 0xfd, 0x81, 0x13, +0x89, 0xf2, 0xc2, 0x06, 0x2b, 0xed, 0x67, 0xc4, 0x8e, 0xc9, 0x43, 0xb2, 0x5c, 0x6b, 0x15, 0x89, +0x02, 0xbc, 0x62, 0xfc, 0x4e, 0xf2, 0xb5, 0x33, 0xaa, 0xb2, 0x6f, 0xd3, 0x0a, 0xa2, 0x50, 0xe3, +0xf6, 0x3b, 0xe8, 0x2e, 0x44, 0xc2, 0xdb, 0x66, 0x38, 0xa9, 0x33, 0x56, 0x48, 0xf1, 0x6d, 0x1b, +0x33, 0x8d, 0x0d, 0x8c, 0x3f, 0x60, 0x37, 0x9d, 0xd3, 0xca, 0x6d, 0x7e, 0x34, 0x7e, 0x0d, 0x9f, +0x72, 0x76, 0x8b, 0x1b, 0x9f, 0x72, 0xfd, 0x52, 0x35, 0x41, 0x45, 0x02, 0x96, 0x2f, 0x1c, 0xb2, +0x9a, 0x73, 0x49, 0x21, 0xb1, 0x49, 0x47, 0x45, 0x47, 0xb4, 0xef, 0x6a, 0x34, 0x11, 0xc9, 0x4d, +0x9a, 0xcc, 0x59, 0xb7, 0xd6, 0x02, 0x9e, 0x5a, 0x4e, 0x65, 0xb5, 0x94, 0xae, 0x1b, 0xdf, 0x29, +0xb0, 0x16, 0xf1, 0xbf, 0x00, 0x9e, 0x07, 0x3a, 0x17, 0x64, 0xb5, 0x04, 0xb5, 0x23, 0x21, 0x99, +0x0a, 0x95, 0x3b, 0x97, 0x7c, 0xef, 0x30, 0x82, 0x05, 0xb0, 0x30, 0x82, 0x03, 0x98, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x10, 0x15, 0xc8, 0xbd, 0x65, 0x47, 0x5c, 0xaf, 0xb8, 0x97, 0x00, 0x5e, +0xe4, 0x06, 0xd2, 0xbc, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x05, 0x05, 0x00, 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1a, 0x43, 0x68, +0x75, 0x6e, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, 0x65, 0x6c, 0x65, 0x63, 0x6f, 0x6d, 0x20, 0x43, +0x6f, 0x2e, 0x2c, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x0c, 0x21, 0x65, 0x50, 0x4b, 0x49, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, 0x31, 0x32, 0x32, 0x30, 0x30, 0x32, +0x33, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x33, 0x34, 0x31, 0x32, 0x32, 0x30, 0x30, 0x32, 0x33, +0x31, 0x32, 0x37, 0x5a, 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1a, 0x43, 0x68, +0x75, 0x6e, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54, 0x65, 0x6c, 0x65, 0x63, 0x6f, 0x6d, 0x20, 0x43, +0x6f, 0x2e, 0x2c, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x0c, 0x21, 0x65, 0x50, 0x4b, 0x49, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, +0x02, 0x82, 0x02, 0x01, 0x00, 0xe1, 0x25, 0x0f, 0xee, 0x8d, 0xdb, 0x88, 0x33, 0x75, 0x67, 0xcd, +0xad, 0x1f, 0x7d, 0x3a, 0x4e, 0x6d, 0x9d, 0xd3, 0x2f, 0x14, 0xf3, 0x63, 0x74, 0xcb, 0x01, 0x21, +0x6a, 0x37, 0xea, 0x84, 0x50, 0x07, 0x4b, 0x26, 0x5b, 0x09, 0x43, 0x6c, 0x21, 0x9e, 0x6a, 0xc8, +0xd5, 0x03, 0xf5, 0x60, 0x69, 0x8f, 0xcc, 0xf0, 0x22, 0xe4, 0x1f, 0xe7, 0xf7, 0x6a, 0x22, 0x31, +0xb7, 0x2c, 0x15, 0xf2, 0xe0, 0xfe, 0x00, 0x6a, 0x43, 0xff, 0x87, 0x65, 0xc6, 0xb5, 0x1a, 0xc1, +0xa7, 0x4c, 0x6d, 0x22, 0x70, 0x21, 0x8a, 0x31, 0xf2, 0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1c, +0x9e, 0xca, 0xd9, 0x12, 0xa2, 0x95, 0x3c, 0xda, 0xe9, 0x67, 0xbf, 0x08, 0xa0, 0x64, 0xe3, 0xd6, +0x42, 0xb7, 0x45, 0xef, 0x97, 0xf4, 0xf6, 0xf5, 0xd7, 0xb5, 0x4a, 0x15, 0x02, 0x58, 0x7d, 0x98, +0x58, 0x4b, 0x60, 0xbc, 0xcd, 0xd7, 0x0d, 0x9a, 0x13, 0x33, 0x53, 0xd1, 0x61, 0xf9, 0x7a, 0xd5, +0xd7, 0x78, 0xb3, 0x9a, 0x33, 0xf7, 0x00, 0x86, 0xce, 0x1d, 0x4d, 0x94, 0x38, 0xaf, 0xa8, 0xec, +0x78, 0x51, 0x70, 0x8a, 0x5c, 0x10, 0x83, 0x51, 0x21, 0xf7, 0x11, 0x3d, 0x34, 0x86, 0x5e, 0xe5, +0x48, 0xcd, 0x97, 0x81, 0x82, 0x35, 0x4c, 0x19, 0xec, 0x65, 0xf6, 0x6b, 0xc5, 0x05, 0xa1, 0xee, +0x47, 0x13, 0xd6, 0xb3, 0x21, 0x27, 0x94, 0x10, 0x0a, 0xd9, 0x24, 0x3b, 0xba, 0xbe, 0x44, 0x13, +0x46, 0x30, 0x3f, 0x97, 0x3c, 0xd8, 0xd7, 0xd7, 0x6a, 0xee, 0x3b, 0x38, 0xe3, 0x2b, 0xd4, 0x97, +0x0e, 0xb9, 0x1b, 0xe7, 0x07, 0x49, 0x7f, 0x37, 0x2a, 0xf9, 0x77, 0x78, 0xcf, 0x54, 0xed, 0x5b, +0x46, 0x9d, 0xa3, 0x80, 0x0e, 0x91, 0x43, 0xc1, 0xd6, 0x5b, 0x5f, 0x14, 0xba, 0x9f, 0xa6, 0x8d, +0x24, 0x47, 0x40, 0x59, 0xbf, 0x72, 0x38, 0xb2, 0x36, 0x6c, 0x37, 0xff, 0x99, 0xd1, 0x5d, 0x0e, +0x59, 0x0a, 0xab, 0x69, 0xf7, 0xc0, 0xb2, 0x04, 0x45, 0x7a, 0x54, 0x00, 0xae, 0xbe, 0x53, 0xf6, +0xb5, 0xe7, 0xe1, 0xf8, 0x3c, 0xa3, 0x31, 0xd2, 0xa9, 0xfe, 0x21, 0x52, 0x64, 0xc5, 0xa6, 0x67, +0xf0, 0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xc6, 0x27, 0xe4, 0x01, 0x8f, 0x17, 0xc1, 0x6a, +0x71, 0xd7, 0xbe, 0x4b, 0xfb, 0x94, 0x58, 0x7d, 0x7e, 0x11, 0x33, 0xb1, 0x42, 0xf7, 0x62, 0x6c, +0x18, 0xd6, 0xcf, 0x09, 0x68, 0x3e, 0x7f, 0x6c, 0xf6, 0x1e, 0x8f, 0x62, 0xad, 0xa5, 0x63, 0xdb, +0x09, 0xa7, 0x1f, 0x22, 0x42, 0x41, 0x1e, 0x6f, 0x99, 0x8a, 0x3e, 0xd7, 0xf9, 0x3f, 0x40, 0x7a, +0x79, 0xb0, 0xa5, 0x01, 0x92, 0xd2, 0x9d, 0x3d, 0x08, 0x15, 0xa5, 0x10, 0x01, 0x2d, 0xb3, 0x32, +0x76, 0xa8, 0x95, 0x0d, 0xb3, 0x7a, 0x9a, 0xfb, 0x07, 0x10, 0x78, 0x11, 0x6f, 0xe1, 0x8f, 0xc7, +0xba, 0x0f, 0x25, 0x1a, 0x74, 0x2a, 0xe5, 0x1c, 0x98, 0x41, 0x99, 0xdf, 0x21, 0x87, 0xe8, 0x95, +0x06, 0x6a, 0x0a, 0xb3, 0x6a, 0x47, 0x76, 0x65, 0xf6, 0x3a, 0xcf, 0x8f, 0x62, 0x17, 0x19, 0x7b, +0x0a, 0x28, 0xcd, 0x1a, 0xd2, 0x83, 0x1e, 0x21, 0xc7, 0x2c, 0xbf, 0xbe, 0xff, 0x61, 0x68, 0xb7, +0x67, 0x1b, 0xbb, 0x78, 0x4d, 0x8d, 0xce, 0x67, 0xe5, 0xe4, 0xc1, 0x8e, 0xb7, 0x23, 0x66, 0xe2, +0x9d, 0x90, 0x75, 0x34, 0x98, 0xa9, 0x36, 0x2b, 0x8a, 0x9a, 0x94, 0xb9, 0x9d, 0xec, 0xcc, 0x8a, +0xb1, 0xf8, 0x25, 0x89, 0x5c, 0x5a, 0xb6, 0x2f, 0x8c, 0x1f, 0x6d, 0x79, 0x24, 0xa7, 0x52, 0x68, +0xc3, 0x84, 0x35, 0xe2, 0x66, 0x8d, 0x63, 0x0e, 0x25, 0x4d, 0xd5, 0x19, 0xb2, 0xe6, 0x79, 0x37, +0xa7, 0x22, 0x9d, 0x54, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x6a, 0x30, 0x68, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1e, 0x0c, 0xf7, 0xb6, 0x67, 0xf2, 0xe1, +0x92, 0x26, 0x09, 0x45, 0xc0, 0x55, 0x39, 0x2e, 0x77, 0x3f, 0x42, 0x4a, 0xa2, 0x30, 0x0c, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x39, 0x06, 0x04, 0x67, +0x2a, 0x07, 0x00, 0x04, 0x31, 0x30, 0x2f, 0x30, 0x2d, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, +0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x07, 0x06, 0x05, 0x67, 0x2a, 0x03, 0x00, 0x00, +0x04, 0x14, 0x45, 0xb0, 0xc2, 0xc7, 0x0a, 0x56, 0x7c, 0xee, 0x5b, 0x78, 0x0c, 0x95, 0xf9, 0x18, +0x53, 0xc1, 0xa6, 0x1c, 0xd8, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x09, 0xb3, 0x83, 0x53, 0x59, 0x01, +0x3e, 0x95, 0x49, 0xb9, 0xf1, 0x81, 0xba, 0xf9, 0x76, 0x20, 0x23, 0xb5, 0x27, 0x60, 0x74, 0xd4, +0x6a, 0x99, 0x34, 0x5e, 0x6c, 0x00, 0x53, 0xd9, 0x9f, 0xf2, 0xa6, 0xb1, 0x24, 0x07, 0x44, 0x6a, +0x2a, 0xc6, 0xa5, 0x8e, 0x78, 0x12, 0xe8, 0x47, 0xd9, 0x58, 0x1b, 0x13, 0x2a, 0x5e, 0x79, 0x9b, +0x9f, 0x0a, 0x2a, 0x67, 0xa6, 0x25, 0x3f, 0x06, 0x69, 0x56, 0x73, 0xc3, 0x8a, 0x66, 0x48, 0xfb, +0x29, 0x81, 0x57, 0x74, 0x06, 0xca, 0x9c, 0xea, 0x28, 0xe8, 0x38, 0x67, 0x26, 0x2b, 0xf1, 0xd5, +0xb5, 0x3f, 0x65, 0x93, 0xf8, 0x36, 0x5d, 0x8e, 0x8d, 0x8d, 0x40, 0x20, 0x87, 0x19, 0xea, 0xef, +0x27, 0xc0, 0x3d, 0xb4, 0x39, 0x0f, 0x25, 0x7b, 0x68, 0x50, 0x74, 0x55, 0x9c, 0x0c, 0x59, 0x7d, +0x5a, 0x3d, 0x41, 0x94, 0x25, 0x52, 0x08, 0xe0, 0x47, 0x2c, 0x15, 0x31, 0x19, 0xd5, 0xbf, 0x07, +0x55, 0xc6, 0xbb, 0x12, 0xb5, 0x97, 0xf4, 0x5f, 0x83, 0x85, 0xba, 0x71, 0xc1, 0xd9, 0x6c, 0x81, +0x11, 0x76, 0x0a, 0x0a, 0xb0, 0xbf, 0x82, 0x97, 0xf7, 0xea, 0x3d, 0xfa, 0xfa, 0xec, 0x2d, 0xa9, +0x28, 0x94, 0x3b, 0x56, 0xdd, 0xd2, 0x51, 0x2e, 0xae, 0xc0, 0xbd, 0x08, 0x15, 0x8c, 0x77, 0x52, +0x34, 0x96, 0xd6, 0x9b, 0xac, 0xd3, 0x1d, 0x8e, 0x61, 0x0f, 0x35, 0x7b, 0x9b, 0xae, 0x39, 0x69, +0x0b, 0x62, 0x60, 0x40, 0x20, 0x36, 0x8f, 0xaf, 0xfb, 0x36, 0xee, 0x2d, 0x08, 0x4a, 0x1d, 0xb8, +0xbf, 0x9b, 0x5c, 0xf8, 0xea, 0xa5, 0x1b, 0xa0, 0x73, 0xa6, 0xd8, 0xf8, 0x6e, 0xe0, 0x33, 0x04, +0x5f, 0x68, 0xaa, 0x27, 0x87, 0xed, 0xd9, 0xc1, 0x90, 0x9c, 0xed, 0xbd, 0xe3, 0x6a, 0x35, 0xaf, +0x63, 0xdf, 0xab, 0x18, 0xd9, 0xba, 0xe6, 0xe9, 0x4a, 0xea, 0x50, 0x8a, 0x0f, 0x61, 0x93, 0x1e, +0xe2, 0x2d, 0x19, 0xe2, 0x30, 0x94, 0x35, 0x92, 0x5d, 0x0e, 0xb6, 0x07, 0xaf, 0x19, 0x80, 0x8f, +0x47, 0x90, 0x51, 0x4b, 0x2e, 0x4d, 0xdd, 0x85, 0xe2, 0xd2, 0x0a, 0x52, 0x0a, 0x17, 0x9a, 0xfc, +0x1a, 0xb0, 0x50, 0x02, 0xe5, 0x01, 0xa3, 0x63, 0x37, 0x21, 0x4c, 0x44, 0xc4, 0x9b, 0x51, 0x99, +0x11, 0x0e, 0x73, 0x9c, 0x06, 0x8f, 0x54, 0x2e, 0xa7, 0x28, 0x5e, 0x44, 0x39, 0x87, 0x56, 0x2d, +0x37, 0xbd, 0x85, 0x44, 0x94, 0xe1, 0x0c, 0x4b, 0x2c, 0x9c, 0xc3, 0x92, 0x85, 0x34, 0x61, 0xcb, +0x0f, 0xb8, 0x9b, 0x4a, 0x43, 0x52, 0xfe, 0x34, 0x3a, 0x7d, 0xb8, 0xe9, 0x29, 0xdc, 0x76, 0xa9, +0xc8, 0x30, 0xf8, 0x14, 0x71, 0x80, 0xc6, 0x1e, 0x36, 0x48, 0x74, 0x22, 0x41, 0x5c, 0x87, 0x82, +0xe8, 0x18, 0x71, 0x8b, 0x41, 0x89, 0x44, 0xe7, 0x7e, 0x58, 0x5b, 0xa8, 0xb8, 0x8d, 0x13, 0xe9, +0xa7, 0x6c, 0xc3, 0x47, 0xed, 0xb3, 0x1a, 0x9d, 0x62, 0xae, 0x8d, 0x82, 0xea, 0x94, 0x9e, 0xdd, +0x59, 0x10, 0xc3, 0xad, 0xdd, 0xe2, 0x4d, 0xe3, 0x31, 0xd5, 0xc7, 0xec, 0xe8, 0xf2, 0xb0, 0xfe, +0x92, 0x1e, 0x16, 0x0a, 0x1a, 0xfc, 0xd9, 0xf3, 0xf8, 0x27, 0xb6, 0xc9, 0xbe, 0x1d, 0xb4, 0x6c, +0x64, 0x90, 0x7f, 0xf4, 0xe4, 0xc4, 0x5b, 0xd7, 0x37, 0xae, 0x42, 0x0e, 0xdd, 0xa4, 0x1a, 0x6f, +0x7c, 0x88, 0x54, 0xc5, 0x16, 0x6e, 0xe1, 0x7a, 0x68, 0x2e, 0xf8, 0x3a, 0xbf, 0x0d, 0xa4, 0x3c, +0x89, 0x3b, 0x78, 0xa7, 0x4e, 0x63, 0x83, 0x04, 0x21, 0x08, 0x67, 0x8d, 0xf2, 0x82, 0x49, 0xd0, +0x5b, 0xfd, 0xb1, 0xcd, 0x0f, 0x83, 0x84, 0xd4, 0x3e, 0x20, 0x85, 0xf7, 0x4a, 0x3d, 0x2b, 0x9c, +0xfd, 0x2a, 0x0a, 0x09, 0x4d, 0xea, 0x81, 0xf8, 0x11, 0x9c, 0x30, 0x82, 0x05, 0x46, 0x30, 0x82, +0x03, 0x2e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x6d, 0x8c, 0x14, 0x46, 0xb1, 0xa6, 0x0a, +0xee, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, +0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, +0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, +0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x72, 0x65, 0x6d, +0x69, 0x75, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x32, 0x39, 0x31, 0x34, 0x31, +0x30, 0x33, 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x31, 0x30, +0x33, 0x36, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, +0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x13, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, +0x72, 0x65, 0x6d, 0x69, 0x75, 0x6d, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, +0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc4, 0x12, 0xdf, 0xa9, 0x5f, 0xfe, 0x41, 0xdd, 0xdd, +0xf5, 0x9f, 0x8a, 0xe3, 0xf6, 0xac, 0xe1, 0x3c, 0x78, 0x9a, 0xbc, 0xd8, 0xf0, 0x7f, 0x7a, 0xa0, +0x33, 0x2a, 0xdc, 0x8d, 0x20, 0x5b, 0xae, 0x2d, 0x6f, 0xe7, 0x93, 0xd9, 0x36, 0x70, 0x6a, 0x68, +0xcf, 0x8e, 0x51, 0xa3, 0x85, 0x5b, 0x67, 0x04, 0xa0, 0x10, 0x24, 0x6f, 0x5d, 0x28, 0x82, 0xc1, +0x97, 0x57, 0xd8, 0x48, 0x29, 0x13, 0xb6, 0xe1, 0xbe, 0x91, 0x4d, 0xdf, 0x85, 0x0c, 0x53, 0x18, +0x9a, 0x1e, 0x24, 0xa2, 0x4f, 0x8f, 0xf0, 0xa2, 0x85, 0x0b, 0xcb, 0xf4, 0x29, 0x7f, 0xd2, 0xa4, +0x58, 0xee, 0x26, 0x4d, 0xc9, 0xaa, 0xa8, 0x7b, 0x9a, 0xd9, 0xfa, 0x38, 0xde, 0x44, 0x57, 0x15, +0xe5, 0xf8, 0x8c, 0xc8, 0xd9, 0x48, 0xe2, 0x0d, 0x16, 0x27, 0x1d, 0x1e, 0xc8, 0x83, 0x85, 0x25, +0xb7, 0xba, 0xaa, 0x55, 0x41, 0xcc, 0x03, 0x22, 0x4b, 0x2d, 0x91, 0x8d, 0x8b, 0xe6, 0x89, 0xaf, +0x66, 0xc7, 0xe9, 0xff, 0x2b, 0xe9, 0x3c, 0xac, 0xda, 0xd2, 0xb3, 0xc3, 0xe1, 0x68, 0x9c, 0x89, +0xf8, 0x7a, 0x00, 0x56, 0xde, 0xf4, 0x55, 0x95, 0x6c, 0xfb, 0xba, 0x64, 0xdd, 0x62, 0x8b, 0xdf, +0x0b, 0x77, 0x32, 0xeb, 0x62, 0xcc, 0x26, 0x9a, 0x9b, 0xbb, 0xaa, 0x62, 0x83, 0x4c, 0xb4, 0x06, +0x7a, 0x30, 0xc8, 0x29, 0xbf, 0xed, 0x06, 0x4d, 0x97, 0xb9, 0x1c, 0xc4, 0x31, 0x2b, 0xd5, 0x5f, +0xbc, 0x53, 0x12, 0x17, 0x9c, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2e, 0x25, +0x49, 0x9d, 0x18, 0xf2, 0xee, 0xf3, 0x2b, 0x71, 0x8c, 0xb5, 0xba, 0x39, 0x07, 0x49, 0x77, 0xfc, +0xef, 0x2e, 0x92, 0x90, 0x05, 0x8d, 0x2d, 0x2f, 0x77, 0x7b, 0xef, 0x43, 0xbf, 0x35, 0xbb, 0x9a, +0xd8, 0xf9, 0x73, 0xa7, 0x2c, 0xf2, 0xd0, 0x57, 0xee, 0x28, 0x4e, 0x26, 0x5f, 0x8f, 0x90, 0x68, +0x09, 0x2f, 0xb8, 0xf8, 0xdc, 0x06, 0xe9, 0x2e, 0x9a, 0x3e, 0x51, 0xa7, 0xd1, 0x22, 0xc4, 0x0a, +0xa7, 0x38, 0x48, 0x6c, 0xb3, 0xf9, 0xff, 0x7d, 0xab, 0x86, 0x57, 0xe3, 0xba, 0xd6, 0x85, 0x78, +0x77, 0xba, 0x43, 0xea, 0x48, 0x7f, 0xf6, 0xd8, 0xbe, 0x23, 0x6d, 0x1e, 0xbf, 0xd1, 0x36, 0x6c, +0x58, 0x5c, 0xf1, 0xee, 0xa4, 0x19, 0x54, 0x1a, 0xf5, 0x03, 0xd2, 0x76, 0xe6, 0xe1, 0x8c, 0xbd, +0x3c, 0xb3, 0xd3, 0x48, 0x4b, 0xe2, 0xc8, 0xf8, 0x7f, 0x92, 0xa8, 0x76, 0x46, 0x9c, 0x42, 0x65, +0x3e, 0xa4, 0x1e, 0xc1, 0x07, 0x03, 0x5a, 0x46, 0x2d, 0xb8, 0x97, 0xf3, 0xb7, 0xd5, 0xb2, 0x55, +0x21, 0xef, 0xba, 0xdc, 0x4c, 0x00, 0x97, 0xfb, 0x14, 0x95, 0x27, 0x33, 0xbf, 0xe8, 0x43, 0x47, +0x46, 0xd2, 0x08, 0x99, 0x16, 0x60, 0x3b, 0x9a, 0x7e, 0xd2, 0xe6, 0xed, 0x38, 0xea, 0xec, 0x01, +0x1e, 0x3c, 0x48, 0x56, 0x49, 0x09, 0xc7, 0x4c, 0x37, 0x00, 0x9e, 0x88, 0x0e, 0xc0, 0x73, 0xe1, +0x6f, 0x66, 0xe9, 0x72, 0x47, 0x30, 0x3e, 0x10, 0xe5, 0x0b, 0x03, 0xc9, 0x9a, 0x42, 0x00, 0x6c, +0xc5, 0x94, 0x7e, 0x61, 0xc4, 0x8a, 0xdf, 0x7f, 0x82, 0x1a, 0x0b, 0x59, 0xc4, 0x59, 0x32, 0x77, +0xb3, 0xbc, 0x60, 0x69, 0x56, 0x39, 0xfd, 0xb4, 0x06, 0x7b, 0x2c, 0xd6, 0x64, 0x36, 0xd9, 0xbd, +0x48, 0xed, 0x84, 0x1f, 0x7e, 0xa5, 0x22, 0x8f, 0x2a, 0xb8, 0x42, 0xf4, 0x82, 0xb7, 0xd4, 0x53, +0x90, 0x78, 0x4e, 0x2d, 0x1a, 0xfd, 0x81, 0x6f, 0x44, 0xd7, 0x3b, 0x01, 0x74, 0x96, 0x42, 0xe0, +0x00, 0xe2, 0x2e, 0x6b, 0xea, 0xc5, 0xee, 0x72, 0xac, 0xbb, 0xbf, 0xfe, 0xea, 0xaa, 0xa8, 0xf8, +0xdc, 0xf6, 0xb2, 0x79, 0x8a, 0xb6, 0x67, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, 0xc0, 0x67, 0xa6, 0x0c, +0x22, 0xd9, 0x26, 0xf5, 0x45, 0xab, 0xa6, 0x65, 0x52, 0x11, 0x27, 0xd8, 0x45, 0xac, 0x63, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, +0x82, 0x02, 0x01, 0x00, 0xb3, 0x57, 0x4d, 0x10, 0x62, 0x4e, 0x3a, 0xe4, 0xac, 0xea, 0xb8, 0x1c, +0xaf, 0x32, 0x23, 0xc8, 0xb3, 0x49, 0x5a, 0x51, 0x9c, 0x76, 0x28, 0x8d, 0x79, 0xaa, 0x57, 0x46, +0x17, 0xd5, 0xf5, 0x52, 0xf6, 0xb7, 0x44, 0xe8, 0x08, 0x44, 0xbf, 0x18, 0x84, 0xd2, 0x0b, 0x80, +0xcd, 0xc5, 0x12, 0xfd, 0x00, 0x55, 0x05, 0x61, 0x87, 0x41, 0xdc, 0xb5, 0x24, 0x9e, 0x3c, 0xc4, +0xd8, 0xc8, 0xfb, 0x70, 0x9e, 0x2f, 0x78, 0x96, 0x83, 0x20, 0x36, 0xde, 0x7c, 0x0f, 0x69, 0x13, +0x88, 0xa5, 0x75, 0x36, 0x98, 0x08, 0xa6, 0xc6, 0xdf, 0xac, 0xce, 0xe3, 0x58, 0xd6, 0xb7, 0x3e, +0xde, 0xba, 0xf3, 0xeb, 0x34, 0x40, 0xd8, 0xa2, 0x81, 0xf5, 0x78, 0x3f, 0x2f, 0xd5, 0xa5, 0xfc, +0xd9, 0xa2, 0xd4, 0x5e, 0x04, 0x0e, 0x17, 0xad, 0xfe, 0x41, 0xf0, 0xe5, 0xb2, 0x72, 0xfa, 0x44, +0x82, 0x33, 0x42, 0xe8, 0x2d, 0x58, 0xf7, 0x56, 0x8c, 0x62, 0x3f, 0xba, 0x42, 0xb0, 0x9c, 0x0c, +0x5c, 0x7e, 0x2e, 0x65, 0x26, 0x5c, 0x53, 0x4f, 0x00, 0xb2, 0x78, 0x7e, 0xa1, 0x0d, 0x99, 0x2d, +0x8d, 0xb8, 0x1d, 0x8e, 0xa2, 0xc4, 0xb0, 0xfd, 0x60, 0xd0, 0x30, 0xa4, 0x8e, 0xc8, 0x04, 0x62, +0xa9, 0xc4, 0xed, 0x35, 0xde, 0x7a, 0x97, 0xed, 0x0e, 0x38, 0x5e, 0x92, 0x2f, 0x93, 0x70, 0xa5, +0xa9, 0x9c, 0x6f, 0xa7, 0x7d, 0x13, 0x1d, 0x7e, 0xc6, 0x08, 0x48, 0xb1, 0x5e, 0x67, 0xeb, 0x51, +0x08, 0x25, 0xe9, 0xe6, 0x25, 0x6b, 0x52, 0x29, 0x91, 0x9c, 0xd2, 0x39, 0x73, 0x08, 0x57, 0xde, +0x99, 0x06, 0xb4, 0x5b, 0x9d, 0x10, 0x06, 0xe1, 0xc2, 0x00, 0xa8, 0xb8, 0x1c, 0x4a, 0x02, 0x0a, +0x14, 0xd0, 0xc1, 0x41, 0xca, 0xfb, 0x8c, 0x35, 0x21, 0x7d, 0x82, 0x38, 0xf2, 0xa9, 0x54, 0x91, +0x19, 0x35, 0x93, 0x94, 0x6d, 0x6a, 0x3a, 0xc5, 0xb2, 0xd0, 0xbb, 0x89, 0x86, 0x93, 0xe8, 0x9b, +0xc9, 0x0f, 0x3a, 0xa7, 0x7a, 0xb8, 0xa1, 0xf0, 0x78, 0x46, 0xfa, 0xfc, 0x37, 0x2f, 0xe5, 0x8a, +0x84, 0xf3, 0xdf, 0xfe, 0x04, 0xd9, 0xa1, 0x68, 0xa0, 0x2f, 0x24, 0xe2, 0x09, 0x95, 0x06, 0xd5, +0x95, 0xca, 0xe1, 0x24, 0x96, 0xeb, 0x7c, 0xf6, 0x93, 0x05, 0xbb, 0xed, 0x73, 0xe9, 0x2d, 0xd1, +0x75, 0x39, 0xd7, 0xe7, 0x24, 0xdb, 0xd8, 0x4e, 0x5f, 0x43, 0x8f, 0x9e, 0xd0, 0x14, 0x39, 0xbf, +0x55, 0x70, 0x48, 0x99, 0x57, 0x31, 0xb4, 0x9c, 0xee, 0x4a, 0x98, 0x03, 0x96, 0x30, 0x1f, 0x60, +0x06, 0xee, 0x1b, 0x23, 0xfe, 0x81, 0x60, 0x23, 0x1a, 0x47, 0x62, 0x85, 0xa5, 0xcc, 0x19, 0x34, +0x80, 0x6f, 0xb3, 0xac, 0x1a, 0xe3, 0x9f, 0xf0, 0x7b, 0x48, 0xad, 0xd5, 0x01, 0xd9, 0x67, 0xb6, +0xa9, 0x72, 0x93, 0xea, 0x2d, 0x66, 0xb5, 0xb2, 0xb8, 0xe4, 0x3d, 0x3c, 0xb2, 0xef, 0x4c, 0x8c, +0xea, 0xeb, 0x07, 0xbf, 0xab, 0x35, 0x9a, 0x55, 0x86, 0xbc, 0x18, 0xa6, 0xb5, 0xa8, 0x5e, 0xb4, +0x83, 0x6c, 0x6b, 0x69, 0x40, 0xd3, 0x9f, 0xdc, 0xf1, 0xc3, 0x69, 0x6b, 0xb9, 0xe1, 0x6d, 0x09, +0xf4, 0xf1, 0xaa, 0x50, 0x76, 0x0a, 0x7a, 0x7d, 0x7a, 0x17, 0xa1, 0x55, 0x96, 0x42, 0x99, 0x31, +0x09, 0xdd, 0x60, 0x11, 0x8d, 0x05, 0x30, 0x7e, 0xe6, 0x8e, 0x46, 0xd1, 0x9d, 0x14, 0xda, 0xc7, +0x17, 0xe4, 0x05, 0x96, 0x8c, 0xc4, 0x24, 0xb5, 0x1b, 0xcf, 0x14, 0x07, 0xb2, 0x40, 0xf8, 0xa3, +0x9e, 0x41, 0x86, 0xbc, 0x04, 0xd0, 0x6b, 0x96, 0xc8, 0x2a, 0x80, 0x34, 0xfd, 0xbf, 0xef, 0x06, +0xa3, 0xdd, 0x58, 0xc5, 0x85, 0x3d, 0x3e, 0x8f, 0xfe, 0x9e, 0x29, 0xe0, 0xb6, 0xb8, 0x09, 0x68, +0x19, 0x1c, 0x18, 0x43, 0x30, 0x82, 0x01, 0xfe, 0x30, 0x82, 0x01, 0x85, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x08, 0x74, 0x97, 0x25, 0x8a, 0xc7, 0x3f, 0x7a, 0x54, 0x30, 0x0a, 0x06, 0x08, 0x2a, +0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, +0x0b, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1e, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, +0x73, 0x74, 0x20, 0x50, 0x72, 0x65, 0x6d, 0x69, 0x75, 0x6d, 0x20, 0x45, 0x43, 0x43, 0x30, 0x1e, +0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x32, 0x39, 0x31, 0x34, 0x32, 0x30, 0x32, 0x34, 0x5a, 0x17, +0x0d, 0x34, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x32, 0x30, 0x32, 0x34, 0x5a, 0x30, 0x45, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, +0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, +0x75, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x41, 0x66, +0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x72, 0x65, 0x6d, 0x69, 0x75, +0x6d, 0x20, 0x45, 0x43, 0x43, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x0d, 0x30, 0x5e, +0x1b, 0x15, 0x9d, 0x03, 0xd0, 0xa1, 0x79, 0x35, 0xb7, 0x3a, 0x3c, 0x92, 0x7a, 0xca, 0x15, 0x1c, +0xcd, 0x62, 0xf3, 0x9c, 0x26, 0x5c, 0x07, 0x3d, 0xe5, 0x54, 0xfa, 0xa3, 0xd6, 0xcc, 0x12, 0xea, +0xf4, 0x14, 0x5f, 0xe8, 0x8e, 0x19, 0xab, 0x2f, 0x2e, 0x48, 0xe6, 0xac, 0x18, 0x43, 0x78, 0xac, +0xd0, 0x37, 0xc3, 0xbd, 0xb2, 0xcd, 0x2c, 0xe6, 0x47, 0xe2, 0x1a, 0xe6, 0x63, 0xb8, 0x3d, 0x2e, +0x2f, 0x78, 0xc4, 0x4f, 0xdb, 0xf4, 0x0f, 0xa4, 0x68, 0x4c, 0x55, 0x72, 0x6b, 0x95, 0x1d, 0x4e, +0x18, 0x42, 0x95, 0x78, 0xcc, 0x37, 0x3c, 0x91, 0xe2, 0x9b, 0x65, 0x2b, 0x29, 0xa3, 0x42, 0x30, +0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9a, 0xaf, 0x29, 0x7a, +0xc0, 0x11, 0x35, 0x35, 0x26, 0x51, 0x30, 0x00, 0xc3, 0x6a, 0xfe, 0x40, 0xd5, 0xae, 0xd6, 0x3c, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, +0x06, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, +0x30, 0x64, 0x02, 0x30, 0x17, 0x09, 0xf3, 0x87, 0x88, 0x50, 0x5a, 0xaf, 0xc8, 0xc0, 0x42, 0xbf, +0x47, 0x5f, 0xf5, 0x6c, 0x6a, 0x86, 0xe0, 0xc4, 0x27, 0x74, 0xe4, 0x38, 0x53, 0xd7, 0x05, 0x7f, +0x1b, 0x34, 0xe3, 0xc6, 0x2f, 0xb3, 0xca, 0x09, 0x3c, 0x37, 0x9d, 0xd7, 0xe7, 0xb8, 0x46, 0xf1, +0xfd, 0xa1, 0xe2, 0x71, 0x02, 0x30, 0x42, 0x59, 0x87, 0x43, 0xd4, 0x51, 0xdf, 0xba, 0xd3, 0x09, +0x32, 0x5a, 0xce, 0x88, 0x7e, 0x57, 0x3d, 0x9c, 0x5f, 0x42, 0x6b, 0xf5, 0x07, 0x2d, 0xb5, 0xf0, +0x82, 0x93, 0xf9, 0x59, 0x6f, 0xae, 0x64, 0xfa, 0x58, 0xe5, 0x8b, 0x1e, 0xe3, 0x63, 0xbe, 0xb5, +0x81, 0xcd, 0x6f, 0x02, 0x8c, 0x79, 0x30, 0x82, 0x03, 0x4c, 0x30, 0x82, 0x02, 0x34, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x08, 0x7c, 0x4f, 0x04, 0x39, 0x1c, 0xd4, 0x99, 0x2d, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x44, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, +0x74, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x41, 0x66, 0x66, 0x69, +0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, +0x6e, 0x67, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x32, 0x39, 0x31, 0x34, 0x30, 0x38, +0x32, 0x34, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x30, 0x38, 0x32, +0x34, 0x5a, 0x30, 0x44, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x66, 0x66, 0x69, +0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, +0x0c, 0x16, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, +0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, +0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb4, 0x84, 0xcc, 0x33, 0x17, 0x2e, 0x6b, +0x94, 0x6c, 0x6b, 0x61, 0x52, 0xa0, 0xeb, 0xa3, 0xcf, 0x79, 0x94, 0x4c, 0xe5, 0x94, 0x80, 0x99, +0xcb, 0x55, 0x64, 0x44, 0x65, 0x8f, 0x67, 0x64, 0xe2, 0x06, 0xe3, 0x5c, 0x37, 0x49, 0xf6, 0x2f, +0x9b, 0x84, 0x84, 0x1e, 0x2d, 0xf2, 0x60, 0x9d, 0x30, 0x4e, 0xcc, 0x84, 0x85, 0xe2, 0x2c, 0xcf, +0x1e, 0x9e, 0xfe, 0x36, 0xab, 0x33, 0x77, 0x35, 0x44, 0xd8, 0x35, 0x96, 0x1a, 0x3d, 0x36, 0xe8, +0x7a, 0x0e, 0xd8, 0xd5, 0x47, 0xa1, 0x6a, 0x69, 0x8b, 0xd9, 0xfc, 0xbb, 0x3a, 0xae, 0x79, 0x5a, +0xd5, 0xf4, 0xd6, 0x71, 0xbb, 0x9a, 0x90, 0x23, 0x6b, 0x9a, 0xb7, 0x88, 0x74, 0x87, 0x0c, 0x1e, +0x5f, 0xb9, 0x9e, 0x2d, 0xfa, 0xab, 0x53, 0x2b, 0xdc, 0xbb, 0x76, 0x3e, 0x93, 0x4c, 0x08, 0x08, +0x8c, 0x1e, 0xa2, 0x23, 0x1c, 0xd4, 0x6a, 0xad, 0x22, 0xba, 0x99, 0x01, 0x2e, 0x6d, 0x65, 0xcb, +0xbe, 0x24, 0x66, 0x55, 0x24, 0x4b, 0x40, 0x44, 0xb1, 0x1b, 0xd7, 0xe1, 0xc2, 0x85, 0xc0, 0xde, +0x10, 0x3f, 0x3d, 0xed, 0xb8, 0xfc, 0xf1, 0xf1, 0x23, 0x53, 0xdc, 0xbf, 0x65, 0x97, 0x6f, 0xd9, +0xf9, 0x40, 0x71, 0x8d, 0x7d, 0xbd, 0x95, 0xd4, 0xce, 0xbe, 0xa0, 0x5e, 0x27, 0x23, 0xde, 0xfd, +0xa6, 0xd0, 0x26, 0x0e, 0x00, 0x29, 0xeb, 0x3c, 0x46, 0xf0, 0x3d, 0x60, 0xbf, 0x3f, 0x50, 0xd2, +0xdc, 0x26, 0x41, 0x51, 0x9e, 0x14, 0x37, 0x42, 0x04, 0xa3, 0x70, 0x57, 0xa8, 0x1b, 0x87, 0xed, +0x2d, 0xfa, 0x7b, 0xee, 0x8c, 0x0a, 0xe3, 0xa9, 0x66, 0x89, 0x19, 0xcb, 0x41, 0xf9, 0xdd, 0x44, +0x36, 0x61, 0xcf, 0xe2, 0x77, 0x46, 0xc8, 0x7d, 0xf6, 0xf4, 0x92, 0x81, 0x36, 0xfd, 0xdb, 0x34, +0xf1, 0x72, 0x7e, 0xf3, 0x0c, 0x16, 0xbd, 0xb4, 0x15, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x07, 0x1f, 0xd2, +0xe7, 0x9c, 0xda, 0xc2, 0x6e, 0xa2, 0x40, 0xb4, 0xb0, 0x7a, 0x50, 0x10, 0x50, 0x74, 0xc4, 0xc8, +0xbd, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, +0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x89, 0x57, 0xb2, 0x16, 0x7a, 0xa8, 0xc2, 0xfd, 0xd6, 0xd9, +0x9b, 0x9b, 0x34, 0xc2, 0x9c, 0xb4, 0x32, 0x14, 0x4d, 0xa7, 0xa4, 0xdf, 0xec, 0xbe, 0xa7, 0xbe, +0xf8, 0x43, 0xdb, 0x91, 0x37, 0xce, 0xb4, 0x32, 0x2e, 0x50, 0x55, 0x1a, 0x35, 0x4e, 0x76, 0x43, +0x71, 0x20, 0xef, 0x93, 0x77, 0x4e, 0x15, 0x70, 0x2e, 0x87, 0xc3, 0xc1, 0x1d, 0x6d, 0xdc, 0xcb, +0xb5, 0x27, 0xd4, 0x2c, 0x56, 0xd1, 0x52, 0x53, 0x3a, 0x44, 0xd2, 0x73, 0xc8, 0xc4, 0x1b, 0x05, +0x65, 0x5a, 0x62, 0x92, 0x9c, 0xee, 0x41, 0x8d, 0x31, 0xdb, 0xe7, 0x34, 0xea, 0x59, 0x21, 0xd5, +0x01, 0x7a, 0xd7, 0x64, 0xb8, 0x64, 0x39, 0xcd, 0xc9, 0xed, 0xaf, 0xed, 0x4b, 0x03, 0x48, 0xa7, +0xa0, 0x99, 0x01, 0x80, 0xdc, 0x65, 0xa3, 0x36, 0xae, 0x65, 0x59, 0x48, 0x4f, 0x82, 0x4b, 0xc8, +0x65, 0xf1, 0x57, 0x1d, 0xe5, 0x59, 0x2e, 0x0a, 0x3f, 0x6c, 0xd8, 0xd1, 0xf5, 0xe5, 0x09, 0xb4, +0x6c, 0x54, 0x00, 0x0a, 0xe0, 0x15, 0x4d, 0x87, 0x75, 0x6d, 0xb7, 0x58, 0x96, 0x5a, 0xdd, 0x6d, +0xd2, 0x00, 0xa0, 0xf4, 0x9b, 0x48, 0xbe, 0xc3, 0x37, 0xa4, 0xba, 0x36, 0xe0, 0x7c, 0x87, 0x85, +0x97, 0x1a, 0x15, 0xa2, 0xde, 0x2e, 0xa2, 0x5b, 0xbd, 0xaf, 0x18, 0xf9, 0x90, 0x50, 0xcd, 0x70, +0x59, 0xf8, 0x27, 0x67, 0x47, 0xcb, 0xc7, 0xa0, 0x07, 0x3a, 0x7d, 0xd1, 0x2c, 0x5d, 0x6c, 0x19, +0x3a, 0x66, 0xb5, 0x7d, 0xfd, 0x91, 0x6f, 0x82, 0xb1, 0xbe, 0x08, 0x93, 0xdb, 0x14, 0x47, 0xf1, +0xa2, 0x37, 0xc7, 0x45, 0x9e, 0x3c, 0xc7, 0x77, 0xaf, 0x64, 0xa8, 0x93, 0xdf, 0xf6, 0x69, 0x83, +0x82, 0x60, 0xf2, 0x49, 0x42, 0x34, 0xed, 0x5a, 0x00, 0x54, 0x85, 0x1c, 0x16, 0x36, 0x92, 0x0c, +0x5c, 0xfa, 0xa6, 0xad, 0xbf, 0xdb, 0x30, 0x82, 0x06, 0x14, 0x30, 0x82, 0x03, 0xfc, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x08, 0x53, 0xec, 0x3b, 0xee, 0xfb, 0xb2, 0x48, 0x5f, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x51, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, +0x03, 0x55, 0x04, 0x03, 0x0c, 0x39, 0x41, 0x75, 0x74, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20, +0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, 0x69, 0x6f, 0x6e, +0x20, 0x46, 0x69, 0x72, 0x6d, 0x61, 0x70, 0x72, 0x6f, 0x66, 0x65, 0x73, 0x69, 0x6f, 0x6e, 0x61, +0x6c, 0x20, 0x43, 0x49, 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x30, +0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x35, 0x32, 0x30, 0x30, 0x38, 0x33, 0x38, 0x31, 0x35, 0x5a, +0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x31, 0x30, 0x38, 0x33, 0x38, 0x31, 0x35, 0x5a, 0x30, +0x51, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x42, +0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x39, 0x41, 0x75, 0x74, 0x6f, 0x72, 0x69, 0x64, +0x61, 0x64, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x63, +0x69, 0x6f, 0x6e, 0x20, 0x46, 0x69, 0x72, 0x6d, 0x61, 0x70, 0x72, 0x6f, 0x66, 0x65, 0x73, 0x69, +0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x43, 0x49, 0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, +0x36, 0x38, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, +0x02, 0x01, 0x00, 0xca, 0x96, 0x6b, 0x8e, 0xea, 0xf8, 0xfb, 0xf1, 0xa2, 0x35, 0xe0, 0x7f, 0x4c, +0xda, 0xe0, 0xc3, 0x52, 0xd7, 0x7d, 0xb6, 0x10, 0xc8, 0x02, 0x5e, 0xb3, 0x43, 0x2a, 0xc4, 0x4f, +0x6a, 0xb2, 0xca, 0x1c, 0x5d, 0x28, 0x9a, 0x78, 0x11, 0x1a, 0x69, 0x59, 0x57, 0xaf, 0xb5, 0x20, +0x42, 0xe4, 0x8b, 0x0f, 0xe6, 0xdf, 0x5b, 0xa6, 0x03, 0x92, 0x2f, 0xf5, 0x11, 0xe4, 0x62, 0xd7, +0x32, 0x71, 0x38, 0xd9, 0x04, 0x0c, 0x71, 0xab, 0x3d, 0x51, 0x7e, 0x0f, 0x07, 0xdf, 0x63, 0x05, +0x5c, 0xe9, 0xbf, 0x94, 0x6f, 0xc1, 0x29, 0x82, 0xc0, 0xb4, 0xda, 0x51, 0xb0, 0xc1, 0x3c, 0xbb, +0xad, 0x37, 0x4a, 0x5c, 0xca, 0xf1, 0x4b, 0x36, 0x0e, 0x24, 0xab, 0xbf, 0xc3, 0x84, 0x77, 0xfd, +0xa8, 0x50, 0xf4, 0xb1, 0xe7, 0xc6, 0x2f, 0xd2, 0x2d, 0x59, 0x8d, 0x7a, 0x0a, 0x4e, 0x96, 0x69, +0x52, 0x02, 0xaa, 0x36, 0x98, 0xec, 0xfc, 0xfa, 0x14, 0x83, 0x0c, 0x37, 0x1f, 0xc9, 0x92, 0x37, +0x7f, 0xd7, 0x81, 0x2d, 0xe5, 0xc4, 0xb9, 0xe0, 0x3e, 0x34, 0xfe, 0x67, 0xf4, 0x3e, 0x66, 0xd1, +0xd3, 0xf4, 0x40, 0xcf, 0x5e, 0x62, 0x34, 0x0f, 0x70, 0x06, 0x3e, 0x20, 0x18, 0x5a, 0xce, 0xf7, +0x72, 0x1b, 0x25, 0x6c, 0x93, 0x74, 0x14, 0x93, 0xa3, 0x73, 0xb1, 0x0e, 0xaa, 0x87, 0x10, 0x23, +0x59, 0x5f, 0x20, 0x05, 0x19, 0x47, 0xed, 0x68, 0x8e, 0x92, 0x12, 0xca, 0x5d, 0xfc, 0xd6, 0x2b, +0xb2, 0x92, 0x3c, 0x20, 0xcf, 0xe1, 0x5f, 0xaf, 0x20, 0xbe, 0xa0, 0x76, 0x7f, 0x76, 0xe5, 0xec, +0x1a, 0x86, 0x61, 0x33, 0x3e, 0xe7, 0x7b, 0xb4, 0x3f, 0xa0, 0x0f, 0x8e, 0xa2, 0xb9, 0x6a, 0x6f, +0xb9, 0x87, 0x26, 0x6f, 0x41, 0x6c, 0x88, 0xa6, 0x50, 0xfd, 0x6a, 0x63, 0x0b, 0xf5, 0x93, 0x16, +0x1b, 0x19, 0x8f, 0xb2, 0xed, 0x9b, 0x9b, 0xc9, 0x90, 0xf5, 0x01, 0x0c, 0xdf, 0x19, 0x3d, 0x0f, +0x3e, 0x38, 0x23, 0xc9, 0x2f, 0x8f, 0x0c, 0xd1, 0x02, 0xfe, 0x1b, 0x55, 0xd6, 0x4e, 0xd0, 0x8d, +0x3c, 0xaf, 0x4f, 0xa4, 0xf3, 0xfe, 0xaf, 0x2a, 0xd3, 0x05, 0x9d, 0x79, 0x08, 0xa1, 0xcb, 0x57, +0x31, 0xb4, 0x9c, 0xc8, 0x90, 0xb2, 0x67, 0xf4, 0x18, 0x16, 0x93, 0x3a, 0xfc, 0x47, 0xd8, 0xd1, +0x78, 0x96, 0x31, 0x1f, 0xba, 0x2b, 0x0c, 0x5f, 0x5d, 0x99, 0xad, 0x63, 0x89, 0x5a, 0x24, 0x20, +0x76, 0xd8, 0xdf, 0xfd, 0xab, 0x4e, 0xa6, 0x22, 0xaa, 0x9d, 0x5e, 0xe6, 0x27, 0x8a, 0x7d, 0x68, +0x29, 0xa3, 0xe7, 0x8a, 0xb8, 0xda, 0x11, 0xbb, 0x17, 0x2d, 0x99, 0x9d, 0x13, 0x24, 0x46, 0xf7, +0xc5, 0xe2, 0xd8, 0x9f, 0x8e, 0x7f, 0xc7, 0x8f, 0x74, 0x6d, 0x5a, 0xb2, 0xe8, 0x72, 0xf5, 0xac, +0xee, 0x24, 0x10, 0xad, 0x2f, 0x14, 0xda, 0xff, 0x2d, 0x9a, 0x46, 0x71, 0x47, 0xbe, 0x42, 0xdf, +0xbb, 0x01, 0xdb, 0xf4, 0x7f, 0xd3, 0x28, 0x8f, 0x31, 0x59, 0x5b, 0xd3, 0xc9, 0x02, 0xa6, 0xb4, +0x52, 0xca, 0x6e, 0x97, 0xfb, 0x43, 0xc5, 0x08, 0x26, 0x6f, 0x8a, 0xf4, 0xbb, 0xfd, 0x9f, 0x28, +0xaa, 0x0d, 0xd5, 0x45, 0xf3, 0x13, 0x3a, 0x1d, 0xd8, 0xc0, 0x78, 0x8f, 0x41, 0x67, 0x3c, 0x1e, +0x94, 0x64, 0xae, 0x7b, 0x0b, 0xc5, 0xe8, 0xd9, 0x01, 0x88, 0x39, 0x1a, 0x97, 0x86, 0x64, 0x41, +0xd5, 0x3b, 0x87, 0x0c, 0x6e, 0xfa, 0x0f, 0xc6, 0xbd, 0x48, 0x14, 0xbf, 0x39, 0x4d, 0xd4, 0x9e, +0x41, 0xb6, 0x8f, 0x96, 0x1d, 0x63, 0x96, 0x93, 0xd9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9e, 0x37, +0x06, 0x3b, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xc7, 0x1b, 0x44, 0xa3, 0x15, 0xe5, 0x1c, 0xf8, +0x92, 0x30, 0xbb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xef, 0x30, 0x81, 0xec, 0x30, 0x12, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, +0x01, 0x01, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x65, 0xcd, 0xeb, +0xab, 0x35, 0x1e, 0x00, 0x3e, 0x7e, 0xd5, 0x74, 0xc0, 0x1c, 0xb4, 0x73, 0x47, 0x0e, 0x1a, 0x64, +0x2f, 0x30, 0x81, 0xa6, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x81, 0x9e, 0x30, 0x81, 0x9b, 0x30, +0x81, 0x98, 0x06, 0x04, 0x55, 0x1d, 0x20, 0x00, 0x30, 0x81, 0x8f, 0x30, 0x2f, 0x06, 0x08, 0x2b, +0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, +0x77, 0x77, 0x77, 0x2e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x70, 0x72, 0x6f, 0x66, 0x65, 0x73, 0x69, +0x6f, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x70, 0x73, 0x30, 0x5c, 0x06, 0x08, +0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x50, 0x1e, 0x4e, 0x00, 0x50, 0x00, 0x61, +0x00, 0x73, 0x00, 0x65, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6c, +0x00, 0x61, 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x6f, +0x00, 0x76, 0x00, 0x61, 0x00, 0x20, 0x00, 0x34, 0x00, 0x37, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, +0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x20, +0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x31, 0x00, 0x37, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x17, 0x7d, +0xa0, 0xf9, 0xb4, 0xdd, 0xc5, 0xc5, 0xeb, 0xad, 0x4b, 0x24, 0xb5, 0xa1, 0x02, 0xab, 0xdd, 0xa5, +0x88, 0x4a, 0xb2, 0x0f, 0x55, 0x4b, 0x2b, 0x57, 0x8c, 0x3b, 0xe5, 0x31, 0xdd, 0xfe, 0xc4, 0x32, +0xf1, 0xe7, 0x5b, 0x64, 0x96, 0x36, 0x32, 0x18, 0xec, 0xa5, 0x32, 0x77, 0xd7, 0xe3, 0x44, 0xb6, +0xc0, 0x11, 0x2a, 0x80, 0xb9, 0x3d, 0x6a, 0x6e, 0x7c, 0x9b, 0xd3, 0xad, 0xfc, 0xc3, 0xd6, 0xa3, +0xe6, 0x64, 0x29, 0x7c, 0xd1, 0xe1, 0x38, 0x1e, 0x82, 0x2b, 0xff, 0x27, 0x65, 0xaf, 0xfb, 0x16, +0x15, 0xc4, 0x2e, 0x71, 0x84, 0xe5, 0xb5, 0xff, 0xfa, 0xa4, 0x47, 0xbd, 0x64, 0x32, 0xbb, 0xf6, +0x25, 0x84, 0xa2, 0x27, 0x42, 0xf5, 0x20, 0xb0, 0xc2, 0x13, 0x10, 0x11, 0xcd, 0x10, 0x15, 0xba, +0x42, 0x90, 0x2a, 0xd2, 0x44, 0xe1, 0x96, 0x26, 0xeb, 0x31, 0x48, 0x12, 0xfd, 0x2a, 0xda, 0xc9, +0x06, 0xcf, 0x74, 0x1e, 0xa9, 0x4b, 0xd5, 0x87, 0x28, 0xf9, 0x79, 0x34, 0x92, 0x3e, 0x2e, 0x44, +0xe8, 0xf6, 0x8f, 0x4f, 0x8f, 0x35, 0x3f, 0x25, 0xb3, 0x39, 0xdc, 0x63, 0x2a, 0x90, 0x6b, 0x20, +0x5f, 0xc4, 0x52, 0x12, 0x4e, 0x97, 0x2c, 0x2a, 0xac, 0x9d, 0x97, 0xde, 0x48, 0xf2, 0xa3, 0x66, +0xdb, 0xc2, 0xd2, 0x83, 0x95, 0xa6, 0x66, 0xa7, 0x9e, 0x25, 0x0f, 0xe9, 0x0b, 0x33, 0x91, 0x65, +0x0a, 0x5a, 0xc3, 0xd9, 0x54, 0x12, 0xdd, 0xaf, 0xc3, 0x4e, 0x0e, 0x1f, 0x26, 0x5e, 0x0d, 0xdc, +0xb3, 0x8d, 0xec, 0xd5, 0x81, 0x70, 0xde, 0xd2, 0x4f, 0x24, 0x05, 0xf3, 0x6c, 0x4e, 0xf5, 0x4c, +0x49, 0x66, 0x8d, 0xd1, 0xff, 0xd2, 0x0b, 0x25, 0x41, 0x48, 0xfe, 0x51, 0x84, 0xc6, 0x42, 0xaf, +0x80, 0x04, 0xcf, 0xd0, 0x7e, 0x64, 0x49, 0xe4, 0xf2, 0xdf, 0xa2, 0xec, 0xb1, 0x4c, 0xc0, 0x2a, +0x1d, 0xe7, 0xb4, 0xb1, 0x65, 0xa2, 0xc4, 0xbc, 0xf1, 0x98, 0xf4, 0xaa, 0x70, 0x07, 0x63, 0xb4, +0xb8, 0xda, 0x3b, 0x4c, 0xfa, 0x40, 0x22, 0x30, 0x5b, 0x11, 0xa6, 0xf0, 0x05, 0x0e, 0xc6, 0x02, +0x03, 0x48, 0xab, 0x86, 0x9b, 0x85, 0xdd, 0xdb, 0xdd, 0xea, 0xa2, 0x76, 0x80, 0x73, 0x7d, 0xf5, +0x9c, 0x04, 0xc4, 0x45, 0x8d, 0xe7, 0xb9, 0x1c, 0x8b, 0x9e, 0xea, 0xd7, 0x75, 0xd1, 0x72, 0xb1, +0xde, 0x75, 0x44, 0xe7, 0x42, 0x7d, 0xe2, 0x57, 0x6b, 0x7d, 0xdc, 0x99, 0xbc, 0x3d, 0x83, 0x28, +0xea, 0x80, 0x93, 0x8d, 0xc5, 0x4c, 0x65, 0xc1, 0x70, 0x81, 0xb8, 0x38, 0xfc, 0x43, 0x31, 0xb2, +0xf6, 0x03, 0x34, 0x47, 0xb2, 0xac, 0xfb, 0x22, 0x06, 0xcb, 0x1e, 0xdd, 0x17, 0x47, 0x1c, 0x5f, +0x66, 0xb9, 0xd3, 0x1a, 0xa2, 0xda, 0x11, 0xb1, 0xa4, 0xbc, 0x23, 0xc9, 0xe4, 0xbe, 0x87, 0xff, +0xb9, 0x94, 0xb6, 0xf8, 0x5d, 0x20, 0x4a, 0xd4, 0x5f, 0xe7, 0xbd, 0x68, 0x7b, 0x65, 0xf2, 0x15, +0x1e, 0xd2, 0x3a, 0xa9, 0x2d, 0xe9, 0xd8, 0x6b, 0x24, 0xac, 0x97, 0x58, 0x44, 0x47, 0xad, 0x59, +0x18, 0xf1, 0x21, 0x65, 0x70, 0xde, 0xce, 0x34, 0x60, 0xa8, 0x40, 0xf1, 0xf3, 0x3c, 0xa4, 0xc3, +0x28, 0x23, 0x8c, 0xfe, 0x27, 0x33, 0x43, 0x40, 0xa0, 0x17, 0x3c, 0xeb, 0xea, 0x3b, 0xb0, 0x72, +0xa6, 0xa3, 0xb9, 0x4a, 0x4b, 0x5e, 0x16, 0x48, 0xf4, 0xb2, 0xbc, 0xc8, 0x8c, 0x92, 0xc5, 0x9d, +0x9f, 0xac, 0x72, 0x36, 0xbc, 0x34, 0x80, 0x34, 0x6b, 0xa9, 0x8b, 0x92, 0xc0, 0xb8, 0x17, 0xed, +0xec, 0x76, 0x53, 0xf5, 0x24, 0x01, 0x8c, 0xb3, 0x22, 0xe8, 0x4b, 0x7c, 0x55, 0xc6, 0x9d, 0xfa, +0xa3, 0x14, 0xbb, 0x65, 0x85, 0x6e, 0x6e, 0x4f, 0x12, 0x7e, 0x0a, 0x3c, 0x9d, 0x95, 0x30, 0x82, +0x03, 0x77, 0x30, 0x82, 0x02, 0x5f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x02, 0x00, 0x00, +0xb9, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, +0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x45, 0x31, +0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, +0x6f, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x43, 0x79, +0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x19, 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, +0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, +0x30, 0x30, 0x30, 0x35, 0x31, 0x32, 0x31, 0x38, 0x34, 0x36, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, +0x35, 0x30, 0x35, 0x31, 0x32, 0x32, 0x33, 0x35, 0x39, 0x30, 0x30, 0x5a, 0x30, 0x5a, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x72, 0x65, 0x31, +0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, +0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, +0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, +0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, +0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa3, 0x04, 0xbb, 0x22, 0xab, 0x98, 0x3d, +0x57, 0xe8, 0x26, 0x72, 0x9a, 0xb5, 0x79, 0xd4, 0x29, 0xe2, 0xe1, 0xe8, 0x95, 0x80, 0xb1, 0xb0, +0xe3, 0x5b, 0x8e, 0x2b, 0x29, 0x9a, 0x64, 0xdf, 0xa1, 0x5d, 0xed, 0xb0, 0x09, 0x05, 0x6d, 0xdb, +0x28, 0x2e, 0xce, 0x62, 0xa2, 0x62, 0xfe, 0xb4, 0x88, 0xda, 0x12, 0xeb, 0x38, 0xeb, 0x21, 0x9d, +0xc0, 0x41, 0x2b, 0x01, 0x52, 0x7b, 0x88, 0x77, 0xd3, 0x1c, 0x8f, 0xc7, 0xba, 0xb9, 0x88, 0xb5, +0x6a, 0x09, 0xe7, 0x73, 0xe8, 0x11, 0x40, 0xa7, 0xd1, 0xcc, 0xca, 0x62, 0x8d, 0x2d, 0xe5, 0x8f, +0x0b, 0xa6, 0x50, 0xd2, 0xa8, 0x50, 0xc3, 0x28, 0xea, 0xf5, 0xab, 0x25, 0x87, 0x8a, 0x9a, 0x96, +0x1c, 0xa9, 0x67, 0xb8, 0x3f, 0x0c, 0xd5, 0xf7, 0xf9, 0x52, 0x13, 0x2f, 0xc2, 0x1b, 0xd5, 0x70, +0x70, 0xf0, 0x8f, 0xc0, 0x12, 0xca, 0x06, 0xcb, 0x9a, 0xe1, 0xd9, 0xca, 0x33, 0x7a, 0x77, 0xd6, +0xf8, 0xec, 0xb9, 0xf1, 0x68, 0x44, 0x42, 0x48, 0x13, 0xd2, 0xc0, 0xc2, 0xa4, 0xae, 0x5e, 0x60, +0xfe, 0xb6, 0xa6, 0x05, 0xfc, 0xb4, 0xdd, 0x07, 0x59, 0x02, 0xd4, 0x59, 0x18, 0x98, 0x63, 0xf5, +0xa5, 0x63, 0xe0, 0x90, 0x0c, 0x7d, 0x5d, 0xb2, 0x06, 0x7a, 0xf3, 0x85, 0xea, 0xeb, 0xd4, 0x03, +0xae, 0x5e, 0x84, 0x3e, 0x5f, 0xff, 0x15, 0xed, 0x69, 0xbc, 0xf9, 0x39, 0x36, 0x72, 0x75, 0xcf, +0x77, 0x52, 0x4d, 0xf3, 0xc9, 0x90, 0x2c, 0xb9, 0x3d, 0xe5, 0xc9, 0x23, 0x53, 0x3f, 0x1f, 0x24, +0x98, 0x21, 0x5c, 0x07, 0x99, 0x29, 0xbd, 0xc6, 0x3a, 0xec, 0xe7, 0x6e, 0x86, 0x3a, 0x6b, 0x97, +0x74, 0x63, 0x33, 0xbd, 0x68, 0x18, 0x31, 0xf0, 0x78, 0x8d, 0x76, 0xbf, 0xfc, 0x9e, 0x8e, 0x5d, +0x2a, 0x86, 0xa7, 0x4d, 0x90, 0xdc, 0x27, 0x1a, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x45, +0x30, 0x43, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe5, 0x9d, 0x59, +0x30, 0x82, 0x47, 0x58, 0xcc, 0xac, 0xfa, 0x08, 0x54, 0x36, 0x86, 0x7b, 0x3a, 0xb5, 0x04, 0x4d, +0xf0, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, +0x01, 0xff, 0x02, 0x01, 0x03, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x85, 0x0c, 0x5d, 0x8e, 0xe4, 0x6f, 0x51, +0x68, 0x42, 0x05, 0xa0, 0xdd, 0xbb, 0x4f, 0x27, 0x25, 0x84, 0x03, 0xbd, 0xf7, 0x64, 0xfd, 0x2d, +0xd7, 0x30, 0xe3, 0xa4, 0x10, 0x17, 0xeb, 0xda, 0x29, 0x29, 0xb6, 0x79, 0x3f, 0x76, 0xf6, 0x19, +0x13, 0x23, 0xb8, 0x10, 0x0a, 0xf9, 0x58, 0xa4, 0xd4, 0x61, 0x70, 0xbd, 0x04, 0x61, 0x6a, 0x12, +0x8a, 0x17, 0xd5, 0x0a, 0xbd, 0xc5, 0xbc, 0x30, 0x7c, 0xd6, 0xe9, 0x0c, 0x25, 0x8d, 0x86, 0x40, +0x4f, 0xec, 0xcc, 0xa3, 0x7e, 0x38, 0xc6, 0x37, 0x11, 0x4f, 0xed, 0xdd, 0x68, 0x31, 0x8e, 0x4c, +0xd2, 0xb3, 0x01, 0x74, 0xee, 0xbe, 0x75, 0x5e, 0x07, 0x48, 0x1a, 0x7f, 0x70, 0xff, 0x16, 0x5c, +0x84, 0xc0, 0x79, 0x85, 0xb8, 0x05, 0xfd, 0x7f, 0xbe, 0x65, 0x11, 0xa3, 0x0f, 0xc0, 0x02, 0xb4, +0xf8, 0x52, 0x37, 0x39, 0x04, 0xd5, 0xa9, 0x31, 0x7a, 0x18, 0xbf, 0xa0, 0x2a, 0xf4, 0x12, 0x99, +0xf7, 0xa3, 0x45, 0x82, 0xe3, 0x3c, 0x5e, 0xf5, 0x9d, 0x9e, 0xb5, 0xc8, 0x9e, 0x7c, 0x2e, 0xc8, +0xa4, 0x9e, 0x4e, 0x08, 0x14, 0x4b, 0x6d, 0xfd, 0x70, 0x6d, 0x6b, 0x1a, 0x63, 0xbd, 0x64, 0xe6, +0x1f, 0xb7, 0xce, 0xf0, 0xf2, 0x9f, 0x2e, 0xbb, 0x1b, 0xb7, 0xf2, 0x50, 0x88, 0x73, 0x92, 0xc2, +0xe2, 0xe3, 0x16, 0x8d, 0x9a, 0x32, 0x02, 0xab, 0x8e, 0x18, 0xdd, 0xe9, 0x10, 0x11, 0xee, 0x7e, +0x35, 0xab, 0x90, 0xaf, 0x3e, 0x30, 0x94, 0x7a, 0xd0, 0x33, 0x3d, 0xa7, 0x65, 0x0f, 0xf5, 0xfc, +0x8e, 0x9e, 0x62, 0xcf, 0x47, 0x44, 0x2c, 0x01, 0x5d, 0xbb, 0x1d, 0xb5, 0x32, 0xd2, 0x47, 0xd2, +0x38, 0x2e, 0xd0, 0xfe, 0x81, 0xdc, 0x32, 0x6a, 0x1e, 0xb5, 0xee, 0x3c, 0xd5, 0xfc, 0xe7, 0x81, +0x1d, 0x19, 0xc3, 0x24, 0x42, 0xea, 0x63, 0x39, 0xa9, 0x30, 0x82, 0x05, 0x59, 0x30, 0x82, 0x03, +0x41, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4f, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, 0x2d, 0x39, 0x38, 0x33, +0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, +0x17, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, +0x32, 0x36, 0x30, 0x38, 0x33, 0x38, 0x30, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x32, +0x36, 0x30, 0x38, 0x33, 0x38, 0x30, 0x33, 0x5a, 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4f, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53, 0x2d, 0x39, 0x38, 0x33, +0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, +0x17, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, +0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xd7, 0xc7, 0x5e, 0xf7, 0xc1, 0x07, 0xd4, +0x77, 0xfb, 0x43, 0x21, 0xf4, 0xf4, 0xf5, 0x69, 0xe4, 0xee, 0x32, 0x01, 0xdb, 0xa3, 0x86, 0x1f, +0xe4, 0x59, 0x0d, 0xba, 0xe7, 0x75, 0x83, 0x52, 0xeb, 0xea, 0x1c, 0x61, 0x15, 0x48, 0xbb, 0x1d, +0x07, 0xca, 0x8c, 0xae, 0xb0, 0xdc, 0x96, 0x9d, 0xea, 0xc3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, +0x9c, 0x56, 0x06, 0xff, 0x4b, 0x64, 0xf0, 0x0c, 0x2a, 0x37, 0x49, 0xb5, 0xe5, 0xcf, 0x0c, 0x7c, +0xee, 0xf1, 0x4a, 0xbb, 0x73, 0x30, 0x65, 0xf3, 0xd5, 0x2f, 0x83, 0xb6, 0x7e, 0xe3, 0xe7, 0xf5, +0x9e, 0xab, 0x60, 0xf9, 0xd3, 0xf1, 0x9d, 0x92, 0x74, 0x8a, 0xe4, 0x1c, 0x96, 0xac, 0x5b, 0x80, +0xe9, 0xb5, 0xf4, 0x31, 0x87, 0xa3, 0x51, 0xfc, 0xc7, 0x7e, 0xa1, 0x6f, 0x8e, 0x53, 0x77, 0xd4, +0x97, 0xc1, 0x55, 0x33, 0x92, 0x3e, 0x18, 0x2f, 0x75, 0xd4, 0xad, 0x86, 0x49, 0xcb, 0x95, 0xaf, +0x54, 0x06, 0x6c, 0xd8, 0x06, 0x13, 0x8d, 0x5b, 0xff, 0xe1, 0x26, 0x19, 0x59, 0xc0, 0x24, 0xba, +0x81, 0x71, 0x79, 0x90, 0x44, 0x50, 0x68, 0x24, 0x94, 0x5f, 0xb8, 0xb3, 0x11, 0xf1, 0x29, 0x41, +0x61, 0xa3, 0x41, 0xcb, 0x23, 0x36, 0xd5, 0xc1, 0xf1, 0x32, 0x50, 0x10, 0x4e, 0x7f, 0xf4, 0x86, +0x93, 0xec, 0x84, 0xd3, 0x8e, 0xbc, 0x4b, 0xbf, 0x5c, 0x01, 0x4e, 0x07, 0x3d, 0xdc, 0x14, 0x8a, +0x94, 0x0a, 0xa4, 0xea, 0x73, 0xfb, 0x0b, 0x51, 0xe8, 0x13, 0x07, 0x18, 0xfa, 0x0e, 0xf1, 0x2b, +0xd1, 0x54, 0x15, 0x7d, 0x3c, 0xe1, 0xf7, 0xb4, 0x19, 0x42, 0x67, 0x62, 0x5e, 0x77, 0xe0, 0xa2, +0x55, 0xec, 0xb6, 0xd9, 0x69, 0x17, 0xd5, 0x3a, 0xaf, 0x44, 0xed, 0x4a, 0xc5, 0x9e, 0xe4, 0x7a, +0x27, 0x7c, 0xe5, 0x75, 0xd7, 0xaa, 0xcb, 0x25, 0xe7, 0xdf, 0x6b, 0x0a, 0xdb, 0x0f, 0x4d, 0x93, +0x4e, 0xa8, 0xa0, 0xcd, 0x7b, 0x2e, 0xf2, 0x59, 0x01, 0x6a, 0xb7, 0x0d, 0xb8, 0x07, 0x81, 0x7e, +0x8b, 0x38, 0x1b, 0x38, 0xe6, 0x0a, 0x57, 0x99, 0x3d, 0xee, 0x21, 0xe8, 0xa3, 0xf5, 0x0c, 0x16, +0xdd, 0x8b, 0xec, 0x34, 0x8e, 0x9c, 0x2a, 0x1c, 0x00, 0x15, 0x17, 0x8d, 0x68, 0x83, 0xd2, 0x70, +0x9f, 0x18, 0x08, 0xcd, 0x11, 0x68, 0xd5, 0xc9, 0x6b, 0x52, 0xcd, 0xc4, 0x46, 0x8f, 0xdc, 0xb5, +0xf3, 0xd8, 0x57, 0x73, 0x1e, 0xe9, 0x94, 0x39, 0x04, 0xbf, 0xd3, 0xde, 0x38, 0xde, 0xb4, 0x53, +0xec, 0x69, 0x1c, 0xa2, 0x7e, 0xc4, 0x8f, 0xe4, 0x1b, 0x70, 0xad, 0xf2, 0xa2, 0xf9, 0xfb, 0xf7, +0x16, 0x64, 0x66, 0x69, 0x9f, 0x49, 0x51, 0xa2, 0xe2, 0x15, 0x18, 0x67, 0x06, 0x4a, 0x7f, 0xd5, +0x6c, 0xb5, 0x4d, 0xb3, 0x33, 0xe0, 0x61, 0xeb, 0x5d, 0xbe, 0xe9, 0x98, 0x0f, 0x32, 0xd7, 0x1d, +0x4b, 0x3c, 0x2e, 0x5a, 0x01, 0x52, 0x91, 0x09, 0xf2, 0xdf, 0xea, 0x8d, 0xd8, 0x06, 0x40, 0x63, +0xaa, 0x11, 0xe4, 0xfe, 0xc3, 0x37, 0x9e, 0x14, 0x52, 0x3f, 0xf4, 0xe2, 0xcc, 0xf2, 0x61, 0x93, +0xd1, 0xfd, 0x67, 0x6b, 0xd7, 0x52, 0xae, 0xbf, 0x68, 0xab, 0x40, 0x43, 0xa0, 0x57, 0x35, 0x53, +0x78, 0xf0, 0x53, 0xf8, 0x61, 0x42, 0x07, 0x64, 0xc6, 0xd7, 0x6f, 0x9b, 0x4c, 0x38, 0x0d, 0x63, +0xac, 0x62, 0xaf, 0x36, 0x8b, 0xa2, 0x73, 0x0a, 0x0d, 0xf5, 0x21, 0xbd, 0x74, 0xaa, 0x4d, 0xea, +0x72, 0x03, 0x49, 0xdb, 0xc7, 0x5f, 0x1d, 0x62, 0x63, 0xc7, 0xfd, 0xdd, 0x91, 0xec, 0x33, 0xee, +0xf5, 0x6d, 0xb4, 0x6e, 0x30, 0x68, 0xde, 0xc8, 0xd6, 0x26, 0xb0, 0x75, 0x5e, 0x7b, 0xb4, 0x07, +0x20, 0x98, 0xa1, 0x76, 0x32, 0xb8, 0x4d, 0x6c, 0x4f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, +0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc9, 0x80, +0x77, 0xe0, 0x62, 0x92, 0x82, 0xf5, 0x46, 0x9c, 0xf3, 0xba, 0xf7, 0x4c, 0xc3, 0xde, 0xb8, 0xa3, +0xad, 0x39, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x53, 0x5f, 0x21, 0xf5, 0xba, 0xb0, 0x3a, 0x52, 0x39, 0x2c, +0x92, 0xb0, 0x6c, 0x00, 0xc9, 0xef, 0xce, 0x20, 0xef, 0x06, 0xf2, 0x96, 0x9e, 0xe9, 0xa4, 0x74, +0x7f, 0x7a, 0x16, 0xfc, 0xb7, 0xf5, 0xb6, 0xfb, 0x15, 0x1b, 0x3f, 0xab, 0xa6, 0xc0, 0x72, 0x5d, +0x10, 0xb1, 0x71, 0xee, 0xbc, 0x4f, 0xe3, 0xad, 0xac, 0x03, 0x6d, 0x2e, 0x71, 0x2e, 0xaf, 0xc4, +0xe3, 0xad, 0xa3, 0xbd, 0x0c, 0x11, 0xa7, 0xb4, 0xff, 0x4a, 0xb2, 0x7b, 0x10, 0x10, 0x1f, 0xa7, +0x57, 0x41, 0xb2, 0xc0, 0xae, 0xf4, 0x2c, 0x59, 0xd6, 0x47, 0x10, 0x88, 0xf3, 0x21, 0x51, 0x29, +0x30, 0xca, 0x60, 0x86, 0xaf, 0x46, 0xab, 0x1d, 0xed, 0x3a, 0x5b, 0xb0, 0x94, 0xde, 0x44, 0xe3, +0x41, 0x08, 0xa2, 0xc1, 0xec, 0x1d, 0xd6, 0xfd, 0x4f, 0xb6, 0xd6, 0x47, 0xd0, 0x14, 0x0b, 0xca, +0xe6, 0xca, 0xb5, 0x7b, 0x77, 0x7e, 0x41, 0x1f, 0x5e, 0x83, 0xc7, 0xb6, 0x8c, 0x39, 0x96, 0xb0, +0x3f, 0x96, 0x81, 0x41, 0x6f, 0x60, 0x90, 0xe2, 0xe8, 0xf9, 0xfb, 0x22, 0x71, 0xd9, 0x7d, 0xb3, +0x3d, 0x46, 0xbf, 0xb4, 0x84, 0xaf, 0x90, 0x1c, 0x0f, 0x8f, 0x12, 0x6a, 0xaf, 0xef, 0xee, 0x1e, +0x7a, 0xae, 0x02, 0x4a, 0x8a, 0x17, 0x2b, 0x76, 0xfe, 0xac, 0x54, 0x89, 0x24, 0x2c, 0x4f, 0x3f, +0xb6, 0xb2, 0xa7, 0x4e, 0x8c, 0xa8, 0x91, 0x97, 0xfb, 0x29, 0xc6, 0x7b, 0x5c, 0x2d, 0xb9, 0xcb, +0x66, 0xb6, 0xb7, 0xa8, 0x5b, 0x12, 0x51, 0x85, 0xb5, 0x09, 0x7e, 0x62, 0x78, 0x70, 0xfe, 0xa9, +0x6a, 0x60, 0xb6, 0x1d, 0x0e, 0x79, 0x0c, 0xfd, 0xca, 0xea, 0x24, 0x80, 0x72, 0xc3, 0x97, 0x3f, +0xf2, 0x77, 0xab, 0x43, 0x22, 0x0a, 0xc7, 0xeb, 0xb6, 0x0c, 0x84, 0x82, 0x2c, 0x80, 0x6b, 0x41, +0x8a, 0x08, 0xc0, 0xeb, 0xa5, 0x6b, 0xdf, 0x99, 0x12, 0xcb, 0x8a, 0xd5, 0x5e, 0x80, 0x0c, 0x91, +0xe0, 0x26, 0x08, 0x36, 0x48, 0xc5, 0xfa, 0x38, 0x11, 0x35, 0xff, 0x25, 0x83, 0x2d, 0xf2, 0x7a, +0xbf, 0xda, 0xfd, 0x8e, 0xfe, 0xa5, 0xcb, 0x45, 0x2c, 0x1f, 0xc4, 0x88, 0x53, 0xae, 0x77, 0x0e, +0xd9, 0x9a, 0x76, 0xc5, 0x8e, 0x2c, 0x1d, 0xa3, 0xba, 0xd5, 0xec, 0x32, 0xae, 0xc0, 0xaa, 0xac, +0xf7, 0xd1, 0x7a, 0x4d, 0xeb, 0xd4, 0x07, 0xe2, 0x48, 0xf7, 0x22, 0x8e, 0xb0, 0xa4, 0x9f, 0x6a, +0xce, 0x8e, 0xb2, 0xb2, 0x60, 0xf4, 0xa3, 0x22, 0xd0, 0x23, 0xeb, 0x94, 0x5a, 0x7a, 0x69, 0xdd, +0x0f, 0xbf, 0x40, 0x57, 0xac, 0x6b, 0x59, 0x50, 0xd9, 0xa3, 0x99, 0xe1, 0x6e, 0xfe, 0x8d, 0x01, +0x79, 0x27, 0x23, 0x15, 0xde, 0x92, 0x9d, 0x7b, 0x09, 0x4d, 0x5a, 0xe7, 0x4b, 0x48, 0x30, 0x5a, +0x18, 0xe6, 0x0a, 0x6d, 0xe6, 0x8f, 0xe0, 0xd2, 0xbb, 0xe6, 0xdf, 0x7c, 0x6e, 0x21, 0x82, 0xc1, +0x68, 0x39, 0x4d, 0xb4, 0x98, 0x58, 0x66, 0x62, 0xcc, 0x4a, 0x90, 0x5e, 0xc3, 0xfa, 0x27, 0x04, +0xb1, 0x79, 0x15, 0x74, 0x99, 0xcc, 0xbe, 0xad, 0x20, 0xde, 0x26, 0x60, 0x1c, 0xeb, 0x56, 0x51, +0xa6, 0xa3, 0xea, 0xe4, 0xa3, 0x3f, 0xa7, 0xff, 0x61, 0xdc, 0xf1, 0x5a, 0x4d, 0x6c, 0x32, 0x23, +0x43, 0xee, 0xac, 0xa8, 0xee, 0xee, 0x4a, 0x12, 0x09, 0x3c, 0x5d, 0x71, 0xc2, 0xbe, 0x79, 0xfa, +0xc2, 0x87, 0x68, 0x1d, 0x0b, 0xfd, 0x5c, 0x69, 0xcc, 0x06, 0xd0, 0x9a, 0x7d, 0x54, 0x99, 0x2a, +0xc9, 0x39, 0x1a, 0x19, 0xaf, 0x4b, 0x2a, 0x43, 0xf3, 0x63, 0x5d, 0x5a, 0x58, 0xe2, 0x2f, 0xe3, +0x1d, 0xe4, 0xa9, 0xd6, 0xd0, 0x0a, 0xd0, 0x9e, 0xbf, 0xd7, 0x81, 0x09, 0xf1, 0xc9, 0xc7, 0x26, +0x0d, 0xac, 0x98, 0x16, 0x56, 0xa0, 0x30, 0x82, 0x03, 0x77, 0x30, 0x82, 0x02, 0x5f, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x33, 0xcb, 0x62, 0x2c, 0x5f, 0xb3, 0x32, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3c, 0x31, 0x1e, +0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x41, 0x74, 0x6f, 0x73, 0x20, 0x54, 0x72, +0x75, 0x73, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0d, +0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x04, 0x41, 0x74, 0x6f, 0x73, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, +0x30, 0x37, 0x30, 0x37, 0x31, 0x34, 0x35, 0x38, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, +0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x3c, 0x31, 0x1e, 0x30, 0x1c, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x41, 0x74, 0x6f, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, +0x74, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0d, 0x30, 0x0b, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x04, 0x41, 0x74, 0x6f, 0x73, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, +0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x95, 0x85, 0x3b, 0x97, 0x6f, 0x2a, 0x3b, +0x2e, 0x3b, 0xcf, 0xa6, 0xf3, 0x29, 0x35, 0xbe, 0xcf, 0x18, 0xac, 0x3e, 0xaa, 0xd9, 0xf8, 0x4d, +0xa0, 0x3e, 0x1a, 0x47, 0xb9, 0xbc, 0x9a, 0xdf, 0xf2, 0xfe, 0xcc, 0x3e, 0x47, 0xe8, 0x7a, 0x96, +0xc2, 0x24, 0x8e, 0x35, 0xf4, 0xa9, 0x0c, 0xfc, 0x82, 0xfd, 0x6d, 0xc1, 0x72, 0x62, 0x27, 0xbd, +0xea, 0x6b, 0xeb, 0xe7, 0x8a, 0xcc, 0x54, 0x3e, 0x90, 0x50, 0xcf, 0x80, 0xd4, 0x95, 0xfb, 0xe8, +0xb5, 0x82, 0xd4, 0x14, 0xc5, 0xb6, 0xa9, 0x55, 0x25, 0x57, 0xdb, 0xb1, 0x50, 0xf6, 0xb0, 0x60, +0x64, 0x59, 0x7a, 0x69, 0xcf, 0x03, 0xb7, 0x6f, 0x0d, 0xbe, 0xca, 0x3e, 0x6f, 0x74, 0x72, 0xea, +0xaa, 0x30, 0x2a, 0x73, 0x62, 0xbe, 0x49, 0x91, 0x61, 0xc8, 0x11, 0xfe, 0x0e, 0x03, 0x2a, 0xf7, +0x6a, 0x20, 0xdc, 0x02, 0x15, 0x0d, 0x5e, 0x15, 0x6a, 0xfc, 0xe3, 0x82, 0xc1, 0xb5, 0xc5, 0x9d, +0x64, 0x09, 0x6c, 0xa3, 0x59, 0x98, 0x07, 0x27, 0xc7, 0x1b, 0x96, 0x2b, 0x61, 0x74, 0x71, 0x6c, +0x43, 0xf1, 0xf7, 0x35, 0x89, 0x10, 0xe0, 0x9e, 0xec, 0x55, 0xa1, 0x37, 0x22, 0xa2, 0x87, 0x04, +0x05, 0x2c, 0x47, 0x7d, 0xb4, 0x1c, 0xb9, 0x62, 0x29, 0x66, 0x28, 0xca, 0xb7, 0xe1, 0x93, 0xf5, +0xa4, 0x94, 0x03, 0x99, 0xb9, 0x70, 0x85, 0xb5, 0xe6, 0x48, 0xea, 0x8d, 0x50, 0xfc, 0xd9, 0xde, +0xcc, 0x6f, 0x07, 0x0e, 0xdd, 0x0b, 0x72, 0x9d, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3f, 0x28, 0x0e, +0xfd, 0xc5, 0x75, 0x4f, 0x53, 0xd6, 0x74, 0x9a, 0xb4, 0x24, 0x2e, 0x8e, 0x02, 0x91, 0xcf, 0x76, +0xc5, 0x9b, 0x1e, 0x55, 0x74, 0x9c, 0x78, 0x21, 0xb1, 0xf0, 0x2d, 0xf1, 0x0b, 0x9f, 0xc2, 0xd5, +0x96, 0x18, 0x1f, 0xf0, 0x54, 0x22, 0x7a, 0x8c, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x7d, +0x30, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa7, 0xa5, 0x06, +0xb1, 0x2c, 0xa6, 0x09, 0x60, 0xee, 0xd1, 0x97, 0xe9, 0x70, 0xae, 0xbc, 0x3b, 0x19, 0x6c, 0xdb, +0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa7, +0xa5, 0x06, 0xb1, 0x2c, 0xa6, 0x09, 0x60, 0xee, 0xd1, 0x97, 0xe9, 0x70, 0xae, 0xbc, 0x3b, 0x19, +0x6c, 0xdb, 0x21, 0x30, 0x18, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x11, 0x30, 0x0f, 0x30, 0x0d, +0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb0, 0x2d, 0x03, 0x04, 0x01, 0x01, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, +0x00, 0x26, 0x77, 0x34, 0xdb, 0x94, 0x48, 0x86, 0x2a, 0x41, 0x9d, 0x2c, 0x3e, 0x06, 0x90, 0x60, +0xc4, 0x8c, 0xac, 0x0b, 0x54, 0xb8, 0x1f, 0xb9, 0x7b, 0xd3, 0x07, 0x39, 0xe4, 0xfa, 0x3e, 0x7b, +0xb2, 0x3d, 0x4e, 0xed, 0x9f, 0x23, 0xbd, 0x97, 0xf3, 0x6b, 0x5c, 0xef, 0xee, 0xfd, 0x40, 0xa6, +0xdf, 0xa1, 0x93, 0xa1, 0x0a, 0x86, 0xac, 0xef, 0x20, 0xd0, 0x79, 0x01, 0xbd, 0x78, 0xf7, 0x19, +0xd8, 0x24, 0x31, 0x34, 0x04, 0x01, 0xa6, 0xba, 0x15, 0x9a, 0xc3, 0x27, 0xdc, 0xd8, 0x4f, 0x0f, +0xcc, 0x18, 0x63, 0xff, 0x99, 0x0f, 0x0e, 0x91, 0x6b, 0x75, 0x16, 0xe1, 0x21, 0xfc, 0xd8, 0x26, +0xc7, 0x47, 0xb7, 0xa6, 0xcf, 0x58, 0x72, 0x71, 0x7e, 0xba, 0xe1, 0x4d, 0x95, 0x47, 0x3b, 0xc9, +0xaf, 0x6d, 0xa1, 0xb4, 0xc1, 0xec, 0x89, 0xf6, 0xb4, 0x0f, 0x38, 0xb5, 0xe2, 0x64, 0xdc, 0x25, +0xcf, 0xa6, 0xdb, 0xeb, 0x9a, 0x5c, 0x99, 0xa1, 0xc5, 0x08, 0xde, 0xfd, 0xe6, 0xda, 0xd5, 0xd6, +0x5a, 0x45, 0x0c, 0xc4, 0xb7, 0xc2, 0xb5, 0x14, 0xef, 0xb4, 0x11, 0xff, 0x0e, 0x15, 0xb5, 0xf5, +0xf5, 0xdb, 0xc6, 0xbd, 0xeb, 0x5a, 0xa7, 0xf0, 0x56, 0x22, 0xa9, 0x3c, 0x65, 0x54, 0xc6, 0x15, +0xa8, 0xbd, 0x86, 0x9e, 0xcd, 0x83, 0x96, 0x68, 0x7a, 0x71, 0x81, 0x89, 0xe1, 0x0b, 0xe1, 0xea, +0x11, 0x1b, 0x68, 0x08, 0xcc, 0x69, 0x9e, 0xec, 0x9e, 0x41, 0x9e, 0x44, 0x32, 0x26, 0x7a, 0xe2, +0x87, 0x0a, 0x71, 0x3d, 0xeb, 0xe4, 0x5a, 0xa4, 0xd2, 0xdb, 0xc5, 0xcd, 0xc6, 0xde, 0x60, 0x7f, +0xb9, 0xf3, 0x4f, 0x44, 0x92, 0xef, 0x2a, 0xb7, 0x18, 0x3e, 0xa7, 0x19, 0xd9, 0x0b, 0x7d, 0xb1, +0x37, 0x41, 0x42, 0xb0, 0xba, 0x60, 0x1d, 0xf2, 0xfe, 0x09, 0x11, 0xb0, 0xf0, 0x87, 0x7b, 0xa7, +0x9d, 0x30, 0x82, 0x05, 0x59, 0x30, 0x82, 0x03, 0x41, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, +0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4f, 0x31, +0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, +0x73, 0x20, 0x41, 0x53, 0x2d, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, +0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, +0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, +0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x32, 0x36, 0x30, 0x38, 0x32, 0x38, 0x35, 0x38, +0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x30, 0x32, 0x36, 0x30, 0x38, 0x32, 0x38, 0x35, 0x38, 0x5a, +0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4f, 0x31, +0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, +0x73, 0x20, 0x41, 0x53, 0x2d, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20, +0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, +0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, +0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, +0x00, 0xa5, 0xda, 0x0a, 0x95, 0x16, 0x50, 0xe3, 0x95, 0xf2, 0x5e, 0x9d, 0x76, 0x31, 0x06, 0x32, +0x7a, 0x9b, 0xf1, 0x10, 0x76, 0xb8, 0x00, 0x9a, 0xb5, 0x52, 0x36, 0xcd, 0x24, 0x47, 0xb0, 0x9f, +0x18, 0x64, 0xbc, 0x9a, 0xf6, 0xfa, 0xd5, 0x79, 0xd8, 0x90, 0x62, 0x4c, 0x22, 0x2f, 0xde, 0x38, +0x3d, 0xd6, 0xe0, 0xa8, 0xe9, 0x1c, 0x2c, 0xdb, 0x78, 0x11, 0xe9, 0x8e, 0x68, 0x51, 0x15, 0x72, +0xc7, 0xf3, 0x33, 0x87, 0xe4, 0xa0, 0x5d, 0x0b, 0x5c, 0xe0, 0x57, 0x07, 0x2a, 0x30, 0xf5, 0xcd, +0xc4, 0x37, 0x77, 0x28, 0x4d, 0x18, 0x91, 0xe6, 0xbf, 0xd5, 0x52, 0xfd, 0x71, 0x2d, 0x70, 0x3e, +0xe7, 0xc6, 0xc4, 0x8a, 0xe3, 0xf0, 0x28, 0x0b, 0xf4, 0x76, 0x98, 0xa1, 0x8b, 0x87, 0x55, 0xb2, +0x3a, 0x13, 0xfc, 0xb7, 0x3e, 0x27, 0x37, 0x8e, 0x22, 0xe3, 0xa8, 0x4f, 0x2a, 0xef, 0x60, 0xbb, +0x3d, 0xb7, 0x39, 0xc3, 0x0e, 0x01, 0x47, 0x99, 0x5d, 0x12, 0x4f, 0xdb, 0x43, 0xfa, 0x57, 0xa1, +0xed, 0xf9, 0x9d, 0xbe, 0x11, 0x47, 0x26, 0x5b, 0x13, 0x98, 0xab, 0x5d, 0x16, 0x8a, 0xb0, 0x37, +0x1c, 0x57, 0x9d, 0x45, 0xff, 0x88, 0x96, 0x36, 0xbf, 0xbb, 0xca, 0x07, 0x7b, 0x6f, 0x87, 0x63, +0xd7, 0xd0, 0x32, 0x6a, 0xd6, 0x5d, 0x6c, 0x0c, 0xf1, 0xb3, 0x6e, 0x39, 0xe2, 0x6b, 0x31, 0x2e, +0x39, 0x00, 0x27, 0x14, 0xde, 0x38, 0xc0, 0xec, 0x19, 0x66, 0x86, 0x12, 0xe8, 0x9d, 0x72, 0x16, +0x13, 0x64, 0x52, 0xc7, 0xa9, 0x37, 0x1c, 0xfd, 0x82, 0x30, 0xed, 0x84, 0x18, 0x1d, 0xf4, 0xae, +0x5c, 0xff, 0x70, 0x13, 0x00, 0xeb, 0xb1, 0xf5, 0x33, 0x7a, 0x4b, 0xd6, 0x55, 0xf8, 0x05, 0x8d, +0x4b, 0x69, 0xb0, 0xf5, 0xb3, 0x28, 0x36, 0x5c, 0x14, 0xc4, 0x51, 0x73, 0x4d, 0x6b, 0x0b, 0xf1, +0x34, 0x07, 0xdb, 0x17, 0x39, 0xd7, 0xdc, 0x28, 0x7b, 0x6b, 0xf5, 0x9f, 0xf3, 0x2e, 0xc1, 0x4f, +0x17, 0x2a, 0x10, 0xf3, 0xcc, 0xca, 0xe8, 0xeb, 0xfd, 0x6b, 0xab, 0x2e, 0x9a, 0x9f, 0x2d, 0x82, +0x6e, 0x04, 0xd4, 0x52, 0x01, 0x93, 0x2d, 0x3d, 0x86, 0xfc, 0x7e, 0xfc, 0xdf, 0xef, 0x42, 0x1d, +0xa6, 0x6b, 0xef, 0xb9, 0x20, 0xc6, 0xf7, 0xbd, 0xa0, 0xa7, 0x95, 0xfd, 0xa7, 0xe6, 0x89, 0x24, +0xd8, 0xcc, 0x8c, 0x34, 0x6c, 0xe2, 0x23, 0x2f, 0xd9, 0x12, 0x1a, 0x21, 0xb9, 0x55, 0x91, 0x6f, +0x0b, 0x91, 0x79, 0x19, 0x0c, 0xad, 0x40, 0x88, 0x0b, 0x70, 0xe2, 0x7a, 0xd2, 0x0e, 0xd8, 0x68, +0x48, 0xbb, 0x82, 0x13, 0x39, 0x10, 0x58, 0xe9, 0xd8, 0x2a, 0x07, 0xc6, 0x12, 0xdb, 0x58, 0xdb, +0xd2, 0x3b, 0x55, 0x10, 0x47, 0x05, 0x15, 0x67, 0x62, 0x7e, 0x18, 0x63, 0xa6, 0x46, 0x3f, 0x09, +0x0e, 0x54, 0x32, 0x5e, 0xbf, 0x0d, 0x62, 0x7a, 0x27, 0xef, 0x80, 0xe8, 0xdb, 0xd9, 0x4b, 0x06, +0x5a, 0x37, 0x5a, 0x25, 0xd0, 0x08, 0x12, 0x77, 0xd4, 0x6f, 0x09, 0x50, 0x97, 0x3d, 0xc8, 0x1d, +0xc3, 0xdf, 0x8c, 0x45, 0x30, 0x56, 0xc6, 0xd3, 0x64, 0xab, 0x66, 0xf3, 0xc0, 0x5e, 0x96, 0x9c, +0xc3, 0xc4, 0xef, 0xc3, 0x7c, 0x6b, 0x8b, 0x3a, 0x79, 0x7f, 0xb3, 0x49, 0xcf, 0x3d, 0xe2, 0x89, +0x9f, 0xa0, 0x30, 0x4b, 0x85, 0xb9, 0x9c, 0x94, 0x24, 0x79, 0x8f, 0x7d, 0x6b, 0xa9, 0x45, 0x68, +0x0f, 0x2b, 0xd0, 0xf1, 0xda, 0x1c, 0xcb, 0x69, 0xb8, 0xca, 0x49, 0x62, 0x6d, 0xc8, 0xd0, 0x63, +0x62, 0xdd, 0x60, 0x0f, 0x58, 0xaa, 0x8f, 0xa1, 0xbc, 0x05, 0xa5, 0x66, 0xa2, 0xcf, 0x1b, 0x76, +0xb2, 0x84, 0x64, 0xb1, 0x4c, 0x39, 0x52, 0xc0, 0x30, 0xba, 0xf0, 0x8c, 0x4b, 0x02, 0xb0, 0xb6, +0xb7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, +0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x47, 0xb8, 0xcd, 0xff, 0xe5, 0x6f, 0xee, 0xf8, 0xb2, 0xec, +0x2f, 0x4e, 0x0e, 0xf9, 0x25, 0xb0, 0x8e, 0x3c, 0x6b, 0xc3, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x00, 0x20, +0x23, 0x41, 0x35, 0x04, 0x90, 0xc2, 0x40, 0x62, 0x60, 0xef, 0xe2, 0x35, 0x4c, 0xd7, 0x3f, 0xac, +0xe2, 0x34, 0x90, 0xb8, 0xa1, 0x6f, 0x76, 0xfa, 0x16, 0x16, 0xa4, 0x48, 0x37, 0x2c, 0xe9, 0x90, +0xc2, 0xf2, 0x3c, 0xf8, 0x0a, 0x9f, 0xd8, 0x81, 0xe5, 0xbb, 0x5b, 0xda, 0x25, 0x2c, 0xa4, 0xa7, +0x55, 0x71, 0x24, 0x32, 0xf6, 0xc8, 0x0b, 0xf2, 0xbc, 0x6a, 0xf8, 0x93, 0xac, 0xb2, 0x07, 0xc2, +0x5f, 0x9f, 0xdb, 0xcc, 0xc8, 0x8a, 0xaa, 0xbe, 0x6a, 0x6f, 0xe1, 0x49, 0x10, 0xcc, 0x31, 0xd7, +0x80, 0xbb, 0xbb, 0xc8, 0xd8, 0xa2, 0x0e, 0x64, 0x57, 0xea, 0xa2, 0xf5, 0xc2, 0xa9, 0x31, 0x15, +0xd2, 0x20, 0x6a, 0xec, 0xfc, 0x22, 0x01, 0x28, 0xcf, 0x86, 0xb8, 0x80, 0x1e, 0xa9, 0xcc, 0x11, +0xa5, 0x3c, 0xf2, 0x16, 0xb3, 0x47, 0x9d, 0xfc, 0xd2, 0x80, 0x21, 0xc4, 0xcb, 0xd0, 0x47, 0x70, +0x41, 0xa1, 0xca, 0x83, 0x19, 0x08, 0x2c, 0x6d, 0xf2, 0x5d, 0x77, 0x9c, 0x8a, 0x14, 0x13, 0xd4, +0x36, 0x1c, 0x92, 0xf0, 0xe5, 0x06, 0x37, 0xdc, 0xa6, 0xe6, 0x90, 0x9b, 0x38, 0x8f, 0x5c, 0x6b, +0x1b, 0x46, 0x86, 0x43, 0x42, 0x5f, 0x3e, 0x01, 0x07, 0x53, 0x54, 0x5d, 0x65, 0x7d, 0xf7, 0x8a, +0x73, 0xa1, 0x9a, 0x54, 0x5a, 0x1f, 0x29, 0x43, 0x14, 0x27, 0xc2, 0x85, 0x0f, 0xb5, 0x88, 0x7b, +0x1a, 0x3b, 0x94, 0xb7, 0x1d, 0x60, 0xa7, 0xb5, 0x9c, 0xe7, 0x29, 0x69, 0x57, 0x5a, 0x9b, 0x93, +0x7a, 0x43, 0x30, 0x1b, 0x03, 0xd7, 0x62, 0xc8, 0x40, 0xa6, 0xaa, 0xfc, 0x64, 0xe4, 0x4a, 0xd7, +0x91, 0x53, 0x01, 0xa8, 0x20, 0x88, 0x6e, 0x9c, 0x5f, 0x44, 0xb9, 0xcb, 0x60, 0x81, 0x34, 0xec, +0x6f, 0xd3, 0x7d, 0xda, 0x48, 0x5f, 0xeb, 0xb4, 0x90, 0xbc, 0x2d, 0xa9, 0x1c, 0x0b, 0xac, 0x1c, +0xd5, 0xa2, 0x68, 0x20, 0x80, 0x04, 0xd6, 0xfc, 0xb1, 0x8f, 0x2f, 0xbb, 0x4a, 0x31, 0x0d, 0x4a, +0x86, 0x1c, 0xeb, 0xe2, 0x36, 0x29, 0x26, 0xf5, 0xda, 0xd8, 0xc4, 0xf2, 0x75, 0x61, 0xcf, 0x7e, +0xae, 0x76, 0x63, 0x4a, 0x7a, 0x40, 0x65, 0x93, 0x87, 0xf8, 0x1e, 0x80, 0x8c, 0x86, 0xe5, 0x86, +0xd6, 0x8f, 0x0e, 0xfc, 0x53, 0x2c, 0x60, 0xe8, 0x16, 0x61, 0x1a, 0xa2, 0x3e, 0x43, 0x7b, 0xcd, +0x39, 0x60, 0x54, 0x6a, 0xf5, 0xf2, 0x89, 0x26, 0x01, 0x68, 0x83, 0x48, 0xa2, 0x33, 0xe8, 0xc9, +0x04, 0x91, 0xb2, 0x11, 0x34, 0x11, 0x3e, 0xea, 0xd0, 0x43, 0x19, 0x1f, 0x03, 0x93, 0x90, 0x0c, +0xff, 0x51, 0x3d, 0x57, 0xf4, 0x41, 0x6e, 0xe1, 0xcb, 0xa0, 0xbe, 0xeb, 0xc9, 0x63, 0xcd, 0x6d, +0xcc, 0xe4, 0xf8, 0x36, 0xaa, 0x68, 0x9d, 0xed, 0xbd, 0x5d, 0x97, 0x70, 0x44, 0x0d, 0xb6, 0x0e, +0x35, 0xdc, 0xe1, 0x0c, 0x5d, 0xbb, 0xa0, 0x51, 0x94, 0xcb, 0x7e, 0x16, 0xeb, 0x11, 0x2f, 0xa3, +0x92, 0x45, 0xc8, 0x4c, 0x71, 0xd9, 0xbc, 0xc9, 0x99, 0x52, 0x57, 0x46, 0x2f, 0x50, 0xcf, 0xbd, +0x35, 0x69, 0xf4, 0x3d, 0x15, 0xce, 0x06, 0xa5, 0x2c, 0x0f, 0x3e, 0xf6, 0x81, 0xba, 0x94, 0xbb, +0xc3, 0xbb, 0xbf, 0x65, 0x78, 0xd2, 0x86, 0x79, 0xff, 0x49, 0x3b, 0x1a, 0x83, 0x0c, 0xf0, 0xde, +0x78, 0xec, 0xc8, 0xf2, 0x4d, 0x4c, 0x1a, 0xde, 0x82, 0x29, 0xf8, 0xc1, 0x5a, 0xda, 0xed, 0xee, +0xe6, 0x27, 0x5e, 0xe8, 0x45, 0xd0, 0x9d, 0x1c, 0x51, 0xa8, 0x68, 0xab, 0x44, 0xe3, 0xd0, 0x8b, +0x6a, 0xe3, 0xf8, 0x3b, 0xbb, 0xdc, 0x4d, 0xd7, 0x64, 0xf2, 0x51, 0xbe, 0xe6, 0xaa, 0xab, 0x5a, +0xe9, 0x31, 0xee, 0x06, 0xbc, 0x73, 0xbf, 0x13, 0x62, 0x0a, 0x9f, 0xc7, 0xb9, 0x97, 0x30, 0x82, +0x05, 0x69, 0x30, 0x82, 0x03, 0x51, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x92, 0xb8, +0x88, 0xdb, 0xb0, 0x8a, 0xc1, 0x63, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x52, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x53, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x42, +0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x0a, 0x44, 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2e, 0x73, 0x2e, 0x31, 0x19, +0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44, 0x69, 0x73, 0x69, +0x67, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, +0x37, 0x31, 0x39, 0x30, 0x39, 0x31, 0x35, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x37, +0x31, 0x39, 0x30, 0x39, 0x31, 0x35, 0x33, 0x30, 0x5a, 0x30, 0x52, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x53, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, +0x07, 0x13, 0x0a, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x31, 0x13, 0x30, +0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x44, 0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2e, +0x73, 0x2e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, +0x44, 0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x32, 0x30, 0x82, 0x02, +0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, +0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa2, 0xa3, +0xc4, 0x00, 0x09, 0xd6, 0x85, 0x5d, 0x2d, 0x6d, 0x14, 0xf6, 0xc2, 0xc3, 0x73, 0x9e, 0x35, 0xc2, +0x71, 0x55, 0x7e, 0x81, 0xfb, 0xab, 0x46, 0x50, 0xe0, 0xc1, 0x7c, 0x49, 0x78, 0xe6, 0xab, 0x79, +0x58, 0x3c, 0xda, 0xff, 0x7c, 0x1c, 0x9f, 0xd8, 0x97, 0x02, 0x78, 0x3e, 0x6b, 0x41, 0x04, 0xe9, +0x41, 0xbd, 0xbe, 0x03, 0x2c, 0x45, 0xf6, 0x2f, 0x64, 0xd4, 0xab, 0x5d, 0xa3, 0x47, 0x3d, 0x64, +0x9b, 0xe9, 0x68, 0x9a, 0xc6, 0xcc, 0x1b, 0x3f, 0xba, 0xbe, 0xb2, 0x8b, 0x34, 0x02, 0x2e, 0x98, +0x55, 0x19, 0xfc, 0x8c, 0x6f, 0xaa, 0x5f, 0xda, 0x4c, 0xce, 0x4d, 0x03, 0x21, 0xa3, 0xd8, 0xd2, +0x34, 0x93, 0x56, 0x96, 0xcb, 0x4c, 0x0c, 0x00, 0x16, 0x3c, 0x5f, 0x1a, 0xcd, 0xc8, 0xc7, 0x6c, +0xa6, 0xad, 0xd3, 0x31, 0xa7, 0xbc, 0xe8, 0xe5, 0xe1, 0x66, 0xd6, 0xd2, 0xfb, 0x03, 0xb4, 0x41, +0x65, 0xc9, 0x10, 0xae, 0x0e, 0x05, 0x63, 0xc6, 0x80, 0x6a, 0x69, 0x30, 0xfd, 0xd2, 0xee, 0x90, +0xef, 0x0d, 0x27, 0xdf, 0x9f, 0x95, 0x73, 0xf4, 0xe1, 0x25, 0xda, 0x6c, 0x16, 0xde, 0x41, 0x38, +0x34, 0xea, 0x8b, 0xfc, 0xd1, 0xe8, 0x04, 0x14, 0x61, 0x2d, 0x41, 0x7e, 0xac, 0xc7, 0x77, 0x4e, +0xcb, 0x51, 0x54, 0xfb, 0x5e, 0x92, 0x18, 0x1b, 0x04, 0x5a, 0x68, 0xc6, 0xc9, 0xc4, 0xfa, 0xb7, +0x13, 0xa0, 0x98, 0xb7, 0x11, 0x2b, 0xb7, 0xd6, 0x57, 0xcc, 0x7c, 0x9e, 0x17, 0xd1, 0xcb, 0x25, +0xfe, 0x86, 0x4e, 0x24, 0x2e, 0x56, 0x0c, 0x78, 0x4d, 0x9e, 0x01, 0x12, 0xa6, 0x2b, 0xa7, 0x01, +0x65, 0x6e, 0x7c, 0x62, 0x1d, 0x84, 0x84, 0xdf, 0xea, 0xc0, 0x6b, 0xb5, 0xa5, 0x2a, 0x95, 0x83, +0xc3, 0x53, 0x11, 0x0c, 0x73, 0x1d, 0x0b, 0xb2, 0x46, 0x90, 0xd1, 0x42, 0x3a, 0xce, 0x40, 0x6e, +0x95, 0xad, 0xff, 0xc6, 0x94, 0xad, 0x6e, 0x97, 0x84, 0x8e, 0x7d, 0x6f, 0x9e, 0x8a, 0x80, 0x0d, +0x49, 0x6d, 0x73, 0xe2, 0x7b, 0x92, 0x1e, 0xc3, 0xf3, 0xc1, 0xf3, 0xeb, 0x2e, 0x05, 0x6f, 0xd9, +0x1b, 0xcf, 0x37, 0x76, 0x04, 0xc8, 0xb4, 0x5a, 0xe4, 0x17, 0xa7, 0xcb, 0xdd, 0x76, 0x1f, 0xd0, +0x19, 0x76, 0xe8, 0x2c, 0x05, 0xb3, 0xd6, 0x9c, 0x34, 0xd8, 0x96, 0xdc, 0x61, 0x87, 0x91, 0x05, +0xe4, 0x44, 0x08, 0x33, 0xc1, 0xda, 0xb9, 0x08, 0x65, 0xd4, 0xae, 0xb2, 0x36, 0x0d, 0xeb, 0xba, +0x38, 0xba, 0x0c, 0xe5, 0x9b, 0x9e, 0xeb, 0x8d, 0x66, 0xdd, 0x99, 0xcf, 0xd6, 0x89, 0x41, 0xf6, +0x04, 0x92, 0x8a, 0x29, 0x29, 0x6d, 0x6b, 0x3a, 0x1c, 0xe7, 0x75, 0x7d, 0x02, 0x71, 0x0e, 0xf3, +0xc0, 0xe7, 0xbd, 0xcb, 0x19, 0xdd, 0x9d, 0x60, 0xb2, 0xc2, 0x66, 0x60, 0xb6, 0xb1, 0x04, 0xee, +0xc9, 0xe6, 0x86, 0xb9, 0x9a, 0x66, 0x40, 0xa8, 0xe7, 0x11, 0xed, 0x81, 0x45, 0x03, 0x8b, 0xf6, +0x67, 0x59, 0xe8, 0xc1, 0x06, 0x11, 0xbd, 0xdd, 0xcf, 0x80, 0x02, 0x4f, 0x65, 0x40, 0x78, 0x5c, +0x47, 0x50, 0xc8, 0x9b, 0xe6, 0x1f, 0x81, 0x7b, 0xe4, 0x44, 0xa8, 0x5b, 0x85, 0x9a, 0xe2, 0xde, +0x5a, 0xd5, 0xc7, 0xf9, 0x3a, 0x44, 0x66, 0x4b, 0xe4, 0x32, 0x54, 0x7c, 0xe4, 0x6c, 0x9c, 0xb3, +0x0e, 0x3d, 0x17, 0xa2, 0xb2, 0x34, 0x12, 0xd6, 0x7e, 0xb2, 0xa8, 0x49, 0xbb, 0xd1, 0x7a, 0x28, +0x40, 0xbe, 0xa2, 0x16, 0x1f, 0xdf, 0xe4, 0x37, 0x1f, 0x11, 0x73, 0xfb, 0x90, 0x0a, 0x65, 0x43, +0xa2, 0x0d, 0x7c, 0xf8, 0x06, 0x01, 0x55, 0x33, 0x7d, 0xb0, 0x0d, 0xb8, 0xf4, 0xf5, 0xae, 0xa5, +0x42, 0x57, 0x7c, 0x36, 0x11, 0x8c, 0x7b, 0x5e, 0xc4, 0x03, 0x9d, 0x8c, 0x79, 0x9d, 0x02, 0x03, +0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0xb5, 0x99, 0xf8, 0xaf, 0xb0, 0x94, 0xf5, 0xe3, 0x20, 0xd6, 0x0a, 0xad, 0xce, +0x4e, 0x56, 0xa4, 0x2e, 0x6e, 0x42, 0xed, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x26, 0x06, 0x5e, 0x70, 0xe7, +0x65, 0x33, 0xc8, 0x82, 0x6e, 0xd9, 0x9c, 0x17, 0x3a, 0x1b, 0x7a, 0x66, 0xb2, 0x01, 0xf6, 0x78, +0x3b, 0x69, 0x5e, 0x2f, 0xea, 0xff, 0x4e, 0xf9, 0x28, 0xc3, 0x98, 0x2a, 0x61, 0x4c, 0xb4, 0x24, +0x12, 0x8a, 0x7d, 0x6d, 0x11, 0x14, 0xf7, 0x9c, 0xb5, 0xca, 0xe6, 0xbc, 0x9e, 0x27, 0x8e, 0x4c, +0x19, 0xc8, 0xa9, 0xbd, 0x7a, 0xc0, 0xd7, 0x36, 0x0e, 0x6d, 0x85, 0x72, 0x6e, 0xa8, 0xc6, 0xa2, +0x6d, 0xf6, 0xfa, 0x73, 0x63, 0x7f, 0xbc, 0x6e, 0x79, 0x08, 0x1c, 0x9d, 0x8a, 0x9f, 0x1a, 0x8a, +0x53, 0xa6, 0xd8, 0xbb, 0xd9, 0x35, 0x55, 0xb1, 0x11, 0xc5, 0xa9, 0x03, 0xb3, 0x56, 0x3b, 0xb9, +0x84, 0x93, 0x22, 0x5e, 0x7e, 0xc1, 0xf6, 0x12, 0x52, 0x8b, 0xea, 0x2c, 0x67, 0xbc, 0xfe, 0x36, +0x4c, 0xf5, 0xb8, 0xcf, 0xd1, 0xb3, 0x49, 0x92, 0x3b, 0xd3, 0x29, 0x0e, 0x99, 0x1b, 0x96, 0xf7, +0x61, 0xb8, 0x3b, 0xc4, 0x2b, 0xb6, 0x78, 0x6c, 0xb4, 0x23, 0x6f, 0xf0, 0xfd, 0xd3, 0xb2, 0x5e, +0x75, 0x1f, 0x99, 0x95, 0xa8, 0xac, 0xf6, 0xda, 0xe1, 0xc5, 0x31, 0x7b, 0xfb, 0xd1, 0x46, 0xb3, +0xd2, 0xbc, 0x67, 0xb4, 0x62, 0x54, 0xba, 0x09, 0xf7, 0x63, 0xb0, 0x93, 0xa2, 0x9a, 0xf9, 0xe9, +0x52, 0x2e, 0x8b, 0x60, 0x12, 0xab, 0xfc, 0xf5, 0x60, 0x56, 0xef, 0x10, 0x5c, 0x8b, 0xc4, 0x1a, +0x42, 0xdc, 0x83, 0x5b, 0x64, 0x0e, 0xcb, 0xb5, 0xbc, 0xd6, 0x4f, 0xc1, 0x7c, 0x3c, 0x6e, 0x8d, +0x13, 0x6d, 0xfb, 0x7b, 0xeb, 0x30, 0xd0, 0xdc, 0x4d, 0xaf, 0xc5, 0xd5, 0xb6, 0xa5, 0x4c, 0x5b, +0x71, 0xc9, 0xe8, 0x31, 0xbe, 0xe8, 0x38, 0x06, 0x48, 0xa1, 0x1a, 0xe2, 0xea, 0xd2, 0xde, 0x12, +0x39, 0x58, 0x1a, 0xff, 0x80, 0x0e, 0x82, 0x75, 0xe6, 0xb7, 0xc9, 0x07, 0x6c, 0x0e, 0xef, 0xff, +0x38, 0xf1, 0x98, 0x71, 0xc4, 0xb7, 0x7f, 0x0e, 0x15, 0xd0, 0x25, 0x69, 0xbd, 0x22, 0x9d, 0x2b, +0xed, 0x05, 0xf6, 0x46, 0x47, 0xac, 0xed, 0xc0, 0xf0, 0xd4, 0x3b, 0xe2, 0xec, 0xee, 0x96, 0x5b, +0x90, 0x13, 0x4e, 0x1e, 0x56, 0x3a, 0xeb, 0xb0, 0xef, 0x96, 0xbb, 0x96, 0x23, 0x11, 0xba, 0xf2, +0x43, 0x86, 0x74, 0x64, 0x95, 0xc8, 0x28, 0x75, 0xdf, 0x1d, 0x35, 0xba, 0xd2, 0x37, 0x83, 0x38, +0x53, 0x38, 0x36, 0x3b, 0xcf, 0x6c, 0xe9, 0xf9, 0x6b, 0x0e, 0xd0, 0xfb, 0x04, 0xe8, 0x4f, 0x77, +0xd7, 0x65, 0x01, 0x78, 0x86, 0x0c, 0x7a, 0x3e, 0x21, 0x62, 0xf1, 0x7f, 0x63, 0x71, 0x0c, 0xc9, +0x9f, 0x44, 0xdb, 0xa8, 0x27, 0xa2, 0x75, 0xbe, 0x6e, 0x81, 0x3e, 0xd7, 0xc0, 0xeb, 0x1b, 0x98, +0x0f, 0x70, 0x5c, 0x34, 0xb2, 0x8a, 0xcc, 0xc0, 0x85, 0x18, 0xeb, 0x6e, 0x7a, 0xb3, 0xf7, 0x5a, +0xa1, 0x07, 0xbf, 0xa9, 0x42, 0x92, 0xf3, 0x60, 0x22, 0x97, 0xe4, 0x14, 0xa1, 0x07, 0x9b, 0x4e, +0x76, 0xc0, 0x8e, 0x7d, 0xfd, 0xa4, 0x25, 0xc7, 0x47, 0xed, 0xff, 0x1f, 0x73, 0xac, 0xcc, 0xc3, +0xa5, 0xe9, 0x6f, 0x0a, 0x8e, 0x9b, 0x65, 0xc2, 0x50, 0x85, 0xb5, 0xa3, 0xa0, 0x53, 0x12, 0xcc, +0x55, 0x87, 0x61, 0xf3, 0x81, 0xae, 0x10, 0x46, 0x61, 0xbd, 0x44, 0x21, 0xb8, 0xc2, 0x3d, 0x74, +0xcf, 0x7e, 0x24, 0x35, 0xfa, 0x1c, 0x07, 0x0e, 0x9b, 0x3d, 0x22, 0xca, 0xef, 0x31, 0x2f, 0x8c, +0xac, 0x12, 0xbd, 0xef, 0x40, 0x28, 0xfc, 0x29, 0x67, 0x9f, 0xb2, 0x13, 0x4f, 0x66, 0x24, 0xc4, +0x53, 0x19, 0xe9, 0x1e, 0x29, 0x15, 0xef, 0xe6, 0x6d, 0xb0, 0x7f, 0x2d, 0x67, 0xfd, 0xf3, 0x6c, +0x1b, 0x75, 0x46, 0xa3, 0xe5, 0x4a, 0x17, 0xe9, 0xa4, 0xd7, 0x0b, 0x30, 0x82, 0x03, 0xa8, 0x30, +0x82, 0x02, 0x90, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xfe, 0xdc, 0xe3, 0x01, 0x0f, +0xc9, 0x48, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, +0x05, 0x00, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, +0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x44, 0x68, 0x69, 0x6d, +0x79, 0x6f, 0x74, 0x69, 0x73, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, +0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, +0x32, 0x39, 0x31, 0x35, 0x31, 0x33, 0x30, 0x35, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x36, 0x32, +0x39, 0x31, 0x35, 0x31, 0x33, 0x30, 0x35, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x09, 0x44, 0x68, 0x69, 0x6d, 0x79, 0x6f, 0x74, 0x69, 0x73, 0x31, 0x11, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6e, 0x61, 0x30, 0x82, +0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc8, +0x68, 0xf1, 0xc9, 0xd6, 0xd6, 0xb3, 0x34, 0x75, 0x26, 0x82, 0x1e, 0xec, 0xb4, 0xbe, 0xea, 0x5c, +0xe1, 0x26, 0xed, 0x11, 0x47, 0x61, 0xe1, 0xa2, 0x7c, 0x16, 0x78, 0x40, 0x21, 0xe4, 0x60, 0x9e, +0x5a, 0xc8, 0x63, 0xe1, 0xc4, 0xb1, 0x96, 0x92, 0xff, 0x18, 0x6d, 0x69, 0x23, 0xe1, 0x2b, 0x62, +0xf7, 0xdd, 0xe2, 0x36, 0x2f, 0x91, 0x07, 0xb9, 0x48, 0xcf, 0x0e, 0xec, 0x79, 0xb6, 0x2c, 0xe7, +0x34, 0x4b, 0x70, 0x08, 0x25, 0xa3, 0x3c, 0x87, 0x1b, 0x19, 0xf2, 0x81, 0x07, 0x0f, 0x38, 0x90, +0x19, 0xd3, 0x11, 0xfe, 0x86, 0xb4, 0xf2, 0xd1, 0x5e, 0x1e, 0x1e, 0x96, 0xcd, 0x80, 0x6c, 0xce, +0x3b, 0x31, 0x93, 0xb6, 0xf2, 0xa0, 0xd0, 0xa9, 0x95, 0x12, 0x7d, 0xa5, 0x9a, 0xcc, 0x6b, 0xc8, +0x84, 0x56, 0x8a, 0x33, 0xa9, 0xe7, 0x22, 0x15, 0x53, 0x16, 0xf0, 0xcc, 0x17, 0xec, 0x57, 0x5f, +0xe9, 0xa2, 0x0a, 0x98, 0x09, 0xde, 0xe3, 0x5f, 0x9c, 0x6f, 0xdc, 0x48, 0xe3, 0x85, 0x0b, 0x15, +0x5a, 0xa6, 0xba, 0x9f, 0xac, 0x48, 0xe3, 0x09, 0xb2, 0xf7, 0xf4, 0x32, 0xde, 0x5e, 0x34, 0xbe, +0x1c, 0x78, 0x5d, 0x42, 0x5b, 0xce, 0x0e, 0x22, 0x8f, 0x4d, 0x90, 0xd7, 0x7d, 0x32, 0x18, 0xb3, +0x0b, 0x2c, 0x6a, 0xbf, 0x8e, 0x3f, 0x14, 0x11, 0x89, 0x20, 0x0e, 0x77, 0x14, 0xb5, 0x3d, 0x94, +0x08, 0x87, 0xf7, 0x25, 0x1e, 0xd5, 0xb2, 0x60, 0x00, 0xec, 0x6f, 0x2a, 0x28, 0x25, 0x6e, 0x2a, +0x3e, 0x18, 0x63, 0x17, 0x25, 0x3f, 0x3e, 0x44, 0x20, 0x16, 0xf6, 0x26, 0xc8, 0x25, 0xae, 0x05, +0x4a, 0xb4, 0xe7, 0x63, 0x2c, 0xf3, 0x8c, 0x16, 0x53, 0x7e, 0x5c, 0xfb, 0x11, 0x1a, 0x08, 0xc1, +0x46, 0x62, 0x9f, 0x22, 0xb8, 0xf1, 0xc2, 0x8d, 0x69, 0xdc, 0xfa, 0x3a, 0x58, 0x06, 0xdf, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xbc, 0x30, 0x81, 0xb9, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, +0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1a, 0xed, 0xfe, 0x41, 0x39, 0x90, 0xb4, 0x24, 0x59, 0xbe, +0x01, 0xf2, 0x52, 0xd5, 0x45, 0xf6, 0x5a, 0x39, 0xdc, 0x11, 0x30, 0x64, 0x06, 0x03, 0x55, 0x1d, +0x23, 0x04, 0x5d, 0x30, 0x5b, 0x80, 0x14, 0x1a, 0xed, 0xfe, 0x41, 0x39, 0x90, 0xb4, 0x24, 0x59, +0xbe, 0x01, 0xf2, 0x52, 0xd5, 0x45, 0xf6, 0x5a, 0x39, 0xdc, 0x11, 0xa1, 0x38, 0xa4, 0x36, 0x30, +0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52, 0x31, 0x12, +0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x44, 0x68, 0x69, 0x6d, 0x79, 0x6f, 0x74, +0x69, 0x73, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x43, 0x65, 0x72, +0x74, 0x69, 0x67, 0x6e, 0x61, 0x82, 0x09, 0x00, 0xfe, 0xdc, 0xe3, 0x01, 0x0f, 0xc9, 0x48, 0xff, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, +0x02, 0x00, 0x07, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, +0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x85, 0x03, 0x1e, 0x92, 0x71, 0xf6, 0x42, 0xaf, 0xe1, +0xa3, 0x61, 0x9e, 0xeb, 0xf3, 0xc0, 0x0f, 0xf2, 0xa5, 0xd4, 0xda, 0x95, 0xe6, 0xd6, 0xbe, 0x68, +0x36, 0x3d, 0x7e, 0x6e, 0x1f, 0x4c, 0x8a, 0xef, 0xd1, 0x0f, 0x21, 0x6d, 0x5e, 0xa5, 0x52, 0x63, +0xce, 0x12, 0xf8, 0xef, 0x2a, 0xda, 0x6f, 0xeb, 0x37, 0xfe, 0x13, 0x02, 0xc7, 0xcb, 0x3b, 0x3e, +0x22, 0x6b, 0xda, 0x61, 0x2e, 0x7f, 0xd4, 0x72, 0x3d, 0xdd, 0x30, 0xe1, 0x1e, 0x4c, 0x40, 0x19, +0x8c, 0x0f, 0xd7, 0x9c, 0xd1, 0x83, 0x30, 0x7b, 0x98, 0x59, 0xdc, 0x7d, 0xc6, 0xb9, 0x0c, 0x29, +0x4c, 0xa1, 0x33, 0xa2, 0xeb, 0x67, 0x3a, 0x65, 0x84, 0xd3, 0x96, 0xe2, 0xed, 0x76, 0x45, 0x70, +0x8f, 0xb5, 0x2b, 0xde, 0xf9, 0x23, 0xd6, 0x49, 0x6e, 0x3c, 0x14, 0xb5, 0xc6, 0x9f, 0x35, 0x1e, +0x50, 0xd0, 0xc1, 0x8f, 0x6a, 0x70, 0x44, 0x02, 0x62, 0xcb, 0xae, 0x1d, 0x68, 0x41, 0xa7, 0xaa, +0x57, 0xe8, 0x53, 0xaa, 0x07, 0xd2, 0x06, 0xf6, 0xd5, 0x14, 0x06, 0x0b, 0x91, 0x03, 0x75, 0x2c, +0x6c, 0x72, 0xb5, 0x61, 0x95, 0x9a, 0x0d, 0x8b, 0xb9, 0x0d, 0xe7, 0xf5, 0xdf, 0x54, 0xcd, 0xde, +0xe6, 0xd8, 0xd6, 0x09, 0x08, 0x97, 0x63, 0xe5, 0xc1, 0x2e, 0xb0, 0xb7, 0x44, 0x26, 0xc0, 0x26, +0xc0, 0xaf, 0x55, 0x30, 0x9e, 0x3b, 0xd5, 0x36, 0x2a, 0x19, 0x04, 0xf4, 0x5c, 0x1e, 0xff, 0xcf, +0x2c, 0xb7, 0xff, 0xd0, 0xfd, 0x87, 0x40, 0x11, 0xd5, 0x11, 0x23, 0xbb, 0x48, 0xc0, 0x21, 0xa9, +0xa4, 0x28, 0x2d, 0xfd, 0x15, 0xf8, 0xb0, 0x4e, 0x2b, 0xf4, 0x30, 0x5b, 0x21, 0xfc, 0x11, 0x91, +0x34, 0xbe, 0x41, 0xef, 0x7b, 0x9d, 0x97, 0x75, 0xff, 0x97, 0x95, 0xc0, 0x96, 0x58, 0x2f, 0xea, +0xbb, 0x46, 0xd7, 0xbb, 0xe4, 0xd9, 0x2e, 0x30, 0x82, 0x05, 0x38, 0x30, 0x82, 0x03, 0x20, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0x95, 0xbe, 0x16, 0xa0, 0xf7, 0x2e, 0x46, 0xf1, 0x7b, +0x39, 0x82, 0x72, 0xfa, 0x8b, 0xcd, 0x96, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x0c, 0x0b, 0x54, 0x65, 0x6c, 0x69, 0x61, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x31, 0x1f, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x54, 0x65, 0x6c, 0x69, 0x61, 0x53, 0x6f, +0x6e, 0x65, 0x72, 0x61, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31, 0x30, +0x1e, 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x31, 0x38, 0x31, 0x32, 0x30, 0x30, 0x35, 0x30, 0x5a, +0x17, 0x0d, 0x33, 0x32, 0x31, 0x30, 0x31, 0x38, 0x31, 0x32, 0x30, 0x30, 0x35, 0x30, 0x5a, 0x30, +0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x54, 0x65, 0x6c, 0x69, +0x61, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, +0x0c, 0x16, 0x54, 0x65, 0x6c, 0x69, 0x61, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, +0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc2, 0xbe, 0xeb, 0x27, 0xf0, 0x21, 0xa3, +0xf3, 0x69, 0x26, 0x55, 0x7e, 0x9d, 0xc5, 0x55, 0x16, 0x91, 0x5c, 0xfd, 0xef, 0x21, 0xbf, 0x53, +0x80, 0x7a, 0x2d, 0xd2, 0x91, 0x8c, 0x63, 0x31, 0xf0, 0xec, 0x24, 0xf0, 0xc3, 0xa5, 0xd2, 0x72, +0x7c, 0x10, 0x6d, 0xf4, 0x37, 0xb7, 0xe5, 0xe6, 0x7c, 0x79, 0xea, 0x8c, 0xb5, 0x82, 0x8b, 0xae, +0x48, 0xb6, 0xac, 0x00, 0xdc, 0x65, 0x75, 0xec, 0x2a, 0x4d, 0x5f, 0xc1, 0x87, 0xf5, 0x20, 0x65, +0x2b, 0x81, 0xa8, 0x47, 0x3e, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7f, 0xe8, 0x57, 0x07, 0x48, +0xe7, 0x19, 0xae, 0xbf, 0x45, 0x67, 0xb1, 0x37, 0x1b, 0x06, 0x2a, 0xfe, 0xde, 0xf9, 0xac, 0x7d, +0x83, 0xfb, 0x5e, 0xba, 0xe4, 0x8f, 0x97, 0x67, 0xbe, 0x4b, 0x8e, 0x8d, 0x64, 0x07, 0x57, 0x38, +0x55, 0x69, 0x34, 0x36, 0x3d, 0x13, 0x48, 0xef, 0x4f, 0xe2, 0xd3, 0x66, 0x1e, 0xa4, 0xcf, 0x1a, +0xb7, 0x5e, 0x36, 0x33, 0xd4, 0xb4, 0x06, 0xbd, 0x18, 0x01, 0xfd, 0x77, 0x84, 0x50, 0x00, 0x45, +0xf5, 0x8c, 0x5d, 0xe8, 0x23, 0xbc, 0x7e, 0xfe, 0x35, 0xe1, 0xed, 0x50, 0x7b, 0xa9, 0x30, 0x8d, +0x19, 0xd3, 0x09, 0x8e, 0x68, 0x67, 0x5d, 0xbf, 0x3c, 0x97, 0x18, 0x53, 0xbb, 0x29, 0x62, 0xc5, +0xca, 0x5e, 0x72, 0xc1, 0xc7, 0x96, 0xd4, 0xdb, 0x2d, 0xa0, 0xb4, 0x1f, 0x69, 0x03, 0xec, 0xea, +0xe2, 0x50, 0xf1, 0x0c, 0x3c, 0xf0, 0xac, 0xf3, 0x53, 0x2d, 0xf0, 0x1c, 0xf5, 0xed, 0x6c, 0x39, +0x39, 0x73, 0x80, 0x16, 0xc8, 0x52, 0xb0, 0x23, 0xcd, 0xe0, 0x3e, 0xdc, 0xdd, 0x3c, 0x47, 0xa0, +0xbb, 0x35, 0x8a, 0xe2, 0x98, 0x68, 0x8b, 0xbe, 0xe5, 0xbf, 0x72, 0xee, 0xd2, 0xfa, 0xa5, 0xed, +0x12, 0xed, 0xfc, 0x98, 0x18, 0xa9, 0x26, 0x76, 0xdc, 0x28, 0x4b, 0x10, 0x20, 0x1c, 0xd3, 0x7f, +0x16, 0x77, 0x2d, 0xed, 0x6f, 0x80, 0xf7, 0x49, 0xbb, 0x53, 0x05, 0xbb, 0x5d, 0x68, 0xc7, 0xd4, +0xc8, 0x75, 0x16, 0x3f, 0x89, 0x5a, 0x8b, 0xf7, 0x17, 0x47, 0xd4, 0x4c, 0xf1, 0xd2, 0x89, 0x79, +0x3e, 0x4d, 0x3d, 0x98, 0xa8, 0x61, 0xde, 0x3a, 0x1e, 0xd2, 0xf8, 0x5e, 0x03, 0xe0, 0xc1, 0xc9, +0x1c, 0x8c, 0xd3, 0x8d, 0x4d, 0xd3, 0x95, 0x36, 0xb3, 0x37, 0x5f, 0x63, 0x63, 0x9b, 0x33, 0x14, +0xf0, 0x2d, 0x26, 0x6b, 0x53, 0x7c, 0x89, 0x8c, 0x32, 0xc2, 0x6e, 0xec, 0x3d, 0x21, 0x00, 0x39, +0xc9, 0xa1, 0x68, 0xe2, 0x50, 0x83, 0x2e, 0xb0, 0x3a, 0x2b, 0xf3, 0x36, 0xa0, 0xac, 0x2f, 0xe4, +0x6f, 0x61, 0xc2, 0x51, 0x09, 0x39, 0x3e, 0x8b, 0x53, 0xb9, 0xbb, 0x67, 0xda, 0xdc, 0x53, 0xb9, +0x76, 0x59, 0x36, 0x9d, 0x43, 0xe5, 0x20, 0xe0, 0x3d, 0x32, 0x60, 0x85, 0x22, 0x51, 0xb7, 0xc7, +0x33, 0xbb, 0xdd, 0x15, 0x2f, 0xa4, 0x78, 0xa6, 0x07, 0x7b, 0x81, 0x46, 0x36, 0x04, 0x86, 0xdd, +0x79, 0x35, 0xc7, 0x95, 0x2c, 0x3b, 0xb0, 0xa3, 0x17, 0x35, 0xe5, 0x73, 0x1f, 0xb4, 0x5c, 0x59, +0xef, 0xda, 0xea, 0x10, 0x65, 0x7b, 0x7a, 0xd0, 0x7f, 0x9f, 0xb3, 0xb4, 0x2a, 0x37, 0x3b, 0x70, +0x8b, 0x9b, 0x5b, 0xb9, 0x2b, 0xb7, 0xec, 0xb2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5a, 0xd4, 0xf0, +0x12, 0x10, 0xdc, 0x4f, 0x02, 0xbb, 0x12, 0x92, 0x2f, 0x62, 0xd4, 0x3f, 0x69, 0x43, 0x7c, 0x0d, +0xd6, 0xfc, 0x58, 0x75, 0x01, 0x88, 0x9d, 0x58, 0x16, 0x4b, 0xde, 0xba, 0x90, 0xff, 0x47, 0x01, +0x89, 0x06, 0x6a, 0xf6, 0x5f, 0xb2, 0x90, 0x6a, 0xb3, 0x02, 0xa6, 0x02, 0x88, 0xbf, 0xb3, 0x47, +0x7e, 0x2a, 0xd9, 0xd5, 0xfa, 0x68, 0x78, 0x35, 0x4d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x3f, +0x30, 0x3d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, +0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf0, 0x8f, 0x59, 0x38, 0x00, +0xb3, 0xf5, 0x8f, 0x9a, 0x96, 0x0c, 0xd5, 0xeb, 0xfa, 0x7b, 0xaa, 0x17, 0xe8, 0x13, 0x12, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, +0x02, 0x01, 0x00, 0xbe, 0xe4, 0x5c, 0x62, 0x4e, 0x24, 0xf4, 0x0c, 0x08, 0xff, 0xf0, 0xd3, 0x0c, +0x68, 0xe4, 0x93, 0x49, 0x22, 0x3f, 0x44, 0x27, 0x6f, 0xbb, 0x6d, 0xde, 0x83, 0x66, 0xce, 0xa8, +0xcc, 0x0d, 0xfc, 0xf5, 0x9a, 0x06, 0xe5, 0x77, 0x14, 0x91, 0xeb, 0x9d, 0x41, 0x7b, 0x99, 0x2a, +0x84, 0xe5, 0xff, 0xfc, 0x21, 0xc1, 0x5d, 0xf0, 0xe4, 0x1f, 0x57, 0xb7, 0x75, 0xa9, 0xa1, 0x5f, +0x02, 0x26, 0xff, 0xd7, 0xc7, 0xf7, 0x4e, 0xde, 0x4f, 0xf8, 0xf7, 0x1c, 0x46, 0xc0, 0x7a, 0x4f, +0x40, 0x2c, 0x22, 0x35, 0xf0, 0x19, 0xb1, 0xd0, 0x6b, 0x67, 0x2c, 0xb0, 0xa8, 0xe0, 0xc0, 0x40, +0x37, 0x35, 0xf6, 0x84, 0x5c, 0x5c, 0xe3, 0xaf, 0x42, 0x78, 0xfe, 0xa7, 0xc9, 0x0d, 0x50, 0xea, +0x0d, 0x84, 0x76, 0xf6, 0x51, 0xef, 0x83, 0x53, 0xc6, 0x7a, 0xff, 0x0e, 0x56, 0x49, 0x2e, 0x8f, +0x7a, 0xd6, 0x0c, 0xe6, 0x27, 0x54, 0xe3, 0x4d, 0x0a, 0x60, 0x72, 0x62, 0xcd, 0x91, 0x07, 0xd6, +0xa5, 0xbf, 0xc8, 0x99, 0x6b, 0xed, 0xc4, 0x19, 0xe6, 0xab, 0x4c, 0x11, 0x38, 0xc5, 0x6f, 0x31, +0xe2, 0x6e, 0x49, 0xc8, 0x3f, 0x76, 0x80, 0x26, 0x03, 0x26, 0x29, 0xe0, 0x36, 0xf6, 0xf6, 0x20, +0x53, 0xe3, 0x17, 0x70, 0x34, 0x17, 0x9d, 0x63, 0x68, 0x1e, 0x6b, 0xec, 0xc3, 0x4d, 0x86, 0xb8, +0x13, 0x30, 0x2f, 0x5d, 0x46, 0x0d, 0x47, 0x43, 0xd5, 0x1b, 0xaa, 0x59, 0x0e, 0xb9, 0x5c, 0x8d, +0x06, 0x48, 0xad, 0x74, 0x87, 0x5f, 0xc7, 0xfc, 0x31, 0x54, 0x41, 0x13, 0xe2, 0xc7, 0x21, 0x0e, +0x9e, 0xe0, 0x1e, 0x0d, 0xe1, 0xc0, 0x7b, 0x43, 0x85, 0x90, 0xc5, 0x8a, 0x58, 0xc6, 0x65, 0x0a, +0x78, 0x57, 0xf2, 0xc6, 0x23, 0x0f, 0x01, 0xd9, 0x20, 0x4b, 0xde, 0x0f, 0xfb, 0x92, 0x85, 0x75, +0x2a, 0x5c, 0x73, 0x8d, 0x6d, 0x7b, 0x25, 0x91, 0xca, 0xee, 0x45, 0xae, 0x06, 0x4b, 0x00, 0xcc, +0xd3, 0xb1, 0x59, 0x50, 0xda, 0x3a, 0x88, 0x3b, 0x29, 0x43, 0x46, 0x5e, 0x97, 0x2b, 0x54, 0xce, +0x53, 0x6f, 0x8d, 0x4a, 0xe7, 0x96, 0xfa, 0xbf, 0x71, 0x0e, 0x42, 0x8b, 0x7c, 0xfd, 0x28, 0xa0, +0xd0, 0x48, 0xca, 0xda, 0xc4, 0x81, 0x4c, 0xbb, 0xa2, 0x73, 0x93, 0x26, 0xc8, 0xeb, 0x0c, 0xd6, +0x26, 0x88, 0xb6, 0xc0, 0x24, 0xcf, 0xbb, 0xbd, 0x5b, 0xeb, 0x75, 0x7d, 0xe9, 0x08, 0x8e, 0x86, +0x33, 0x2c, 0x79, 0x77, 0x09, 0x69, 0xa5, 0x89, 0xfc, 0xb3, 0x70, 0x90, 0x87, 0x76, 0x8f, 0xd3, +0x22, 0xbb, 0x42, 0xce, 0xbd, 0x73, 0x0b, 0x20, 0x26, 0x2a, 0xd0, 0x9b, 0x3d, 0x70, 0x1e, 0x24, +0x6c, 0xcd, 0x87, 0x76, 0xa9, 0x17, 0x96, 0xb7, 0xcf, 0x0d, 0x92, 0xfb, 0x8e, 0x18, 0xa9, 0x98, +0x49, 0xd1, 0x9e, 0xfe, 0x60, 0x44, 0x72, 0x21, 0xb9, 0x19, 0xed, 0xc2, 0xf5, 0x31, 0xf1, 0x39, +0x48, 0x88, 0x90, 0x24, 0x75, 0x54, 0x16, 0xad, 0xce, 0xf4, 0xf8, 0x69, 0x14, 0x64, 0x39, 0xfb, +0xa3, 0xb8, 0xba, 0x70, 0x40, 0xc7, 0x27, 0x1c, 0xbf, 0xc4, 0x56, 0x53, 0xfa, 0x63, 0x65, 0xd0, +0xf3, 0x1c, 0x0e, 0x16, 0xf5, 0x6b, 0x86, 0x58, 0x4d, 0x18, 0xd4, 0xe4, 0x0d, 0x8e, 0xa5, 0x9d, +0x5b, 0x91, 0xdc, 0x76, 0x24, 0x50, 0x3f, 0xc6, 0x2a, 0xfb, 0xd9, 0xb7, 0x9c, 0xb5, 0xd6, 0xe6, +0xd0, 0xd9, 0xe8, 0x19, 0x8b, 0x15, 0x71, 0x48, 0xad, 0xb7, 0xea, 0xd8, 0x59, 0x88, 0xd4, 0x90, +0xbf, 0x16, 0xb3, 0xd9, 0xe9, 0xac, 0x59, 0x61, 0x54, 0xc8, 0x1c, 0xba, 0xca, 0xc1, 0xca, 0xe1, +0xb9, 0x20, 0x4c, 0x8f, 0x3a, 0x93, 0x89, 0xa5, 0xa0, 0xcc, 0xbf, 0xd3, 0xf6, 0x75, 0xa4, 0x75, +0x96, 0x6d, 0x56, 0x30, 0x82, 0x05, 0x60, 0x30, 0x82, 0x03, 0x48, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x10, 0x0a, 0x01, 0x42, 0x80, 0x00, 0x00, 0x01, 0x45, 0x23, 0xc8, 0x44, 0xb5, 0x00, 0x00, +0x00, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, +0x00, 0x30, 0x4a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, +0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x49, 0x64, 0x65, 0x6e, 0x54, +0x72, 0x75, 0x73, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1e, 0x49, +0x64, 0x65, 0x6e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, +0x69, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x1e, 0x17, +0x0d, 0x31, 0x34, 0x30, 0x31, 0x31, 0x36, 0x31, 0x38, 0x31, 0x32, 0x32, 0x33, 0x5a, 0x17, 0x0d, +0x33, 0x34, 0x30, 0x31, 0x31, 0x36, 0x31, 0x38, 0x31, 0x32, 0x32, 0x33, 0x5a, 0x30, 0x4a, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x49, 0x64, 0x65, 0x6e, 0x54, 0x72, 0x75, 0x73, 0x74, +0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1e, 0x49, 0x64, 0x65, 0x6e, 0x54, +0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6c, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, +0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xa7, 0x50, 0x19, 0xde, 0x3f, 0x99, +0x3d, 0xd4, 0x33, 0x46, 0xf1, 0x6f, 0x51, 0x61, 0x82, 0xb2, 0xa9, 0x4f, 0x8f, 0x67, 0x89, 0x5d, +0x84, 0xd9, 0x53, 0xdd, 0x0c, 0x28, 0xd9, 0xd7, 0xf0, 0xff, 0xae, 0x95, 0x43, 0x72, 0x99, 0xf9, +0xb5, 0x5d, 0x7c, 0x8a, 0xc1, 0x42, 0xe1, 0x31, 0x50, 0x74, 0xd1, 0x81, 0x0d, 0x7c, 0xcd, 0x9b, +0x21, 0xab, 0x43, 0xe2, 0xac, 0xad, 0x5e, 0x86, 0x6e, 0xf3, 0x09, 0x8a, 0x1f, 0x5a, 0x32, 0xbd, +0xa2, 0xeb, 0x94, 0xf9, 0xe8, 0x5c, 0x0a, 0xec, 0xff, 0x98, 0xd2, 0xaf, 0x71, 0xb3, 0xb4, 0x53, +0x9f, 0x4e, 0x87, 0xef, 0x92, 0xbc, 0xbd, 0xec, 0x4f, 0x32, 0x30, 0x88, 0x4b, 0x17, 0x5e, 0x57, +0xc4, 0x53, 0xc2, 0xf6, 0x02, 0x97, 0x8d, 0xd9, 0x62, 0x2b, 0xbf, 0x24, 0x1f, 0x62, 0x8d, 0xdf, +0xc3, 0xb8, 0x29, 0x4b, 0x49, 0x78, 0x3c, 0x93, 0x60, 0x88, 0x22, 0xfc, 0x99, 0xda, 0x36, 0xc8, +0xc2, 0xa2, 0xd4, 0x2c, 0x54, 0x00, 0x67, 0x35, 0x6e, 0x73, 0xbf, 0x02, 0x58, 0xf0, 0xa4, 0xdd, +0xe5, 0xb0, 0xa2, 0x26, 0x7a, 0xca, 0xe0, 0x36, 0xa5, 0x19, 0x16, 0xf5, 0xfd, 0xb7, 0xef, 0xae, +0x3f, 0x40, 0xf5, 0x6d, 0x5a, 0x04, 0xfd, 0xce, 0x34, 0xca, 0x24, 0xdc, 0x74, 0x23, 0x1b, 0x5d, +0x33, 0x13, 0x12, 0x5d, 0xc4, 0x01, 0x25, 0xf6, 0x30, 0xdd, 0x02, 0x5d, 0x9f, 0xe0, 0xd5, 0x47, +0xbd, 0xb4, 0xeb, 0x1b, 0xa1, 0xbb, 0x49, 0x49, 0xd8, 0x9f, 0x5b, 0x02, 0xf3, 0x8a, 0xe4, 0x24, +0x90, 0xe4, 0x62, 0x4f, 0x4f, 0xc1, 0xaf, 0x8b, 0x0e, 0x74, 0x17, 0xa8, 0xd1, 0x72, 0x88, 0x6a, +0x7a, 0x01, 0x49, 0xcc, 0xb4, 0x46, 0x79, 0xc6, 0x17, 0xb1, 0xda, 0x98, 0x1e, 0x07, 0x59, 0xfa, +0x75, 0x21, 0x85, 0x65, 0xdd, 0x90, 0x56, 0xce, 0xfb, 0xab, 0xa5, 0x60, 0x9d, 0xc4, 0x9d, 0xf9, +0x52, 0xb0, 0x8b, 0xbd, 0x87, 0xf9, 0x8f, 0x2b, 0x23, 0x0a, 0x23, 0x76, 0x3b, 0xf7, 0x33, 0xe1, +0xc9, 0x00, 0xf3, 0x69, 0xf9, 0x4b, 0xa2, 0xe0, 0x4e, 0xbc, 0x7e, 0x93, 0x39, 0x84, 0x07, 0xf7, +0x44, 0x70, 0x7e, 0xfe, 0x07, 0x5a, 0xe5, 0xb1, 0xac, 0xd1, 0x18, 0xcc, 0xf2, 0x35, 0xe5, 0x49, +0x49, 0x08, 0xca, 0x56, 0xc9, 0x3d, 0xfb, 0x0f, 0x18, 0x7d, 0x8b, 0x3b, 0xc1, 0x13, 0xc2, 0x4d, +0x8f, 0xc9, 0x4f, 0x0e, 0x37, 0xe9, 0x1f, 0xa1, 0x0e, 0x6a, 0xdf, 0x62, 0x2e, 0xcb, 0x35, 0x06, +0x51, 0x79, 0x2c, 0xc8, 0x25, 0x38, 0xf4, 0xfa, 0x4b, 0xa7, 0x89, 0x5c, 0x9c, 0xd2, 0xe3, 0x0d, +0x39, 0x86, 0x4a, 0x74, 0x7c, 0xd5, 0x59, 0x87, 0xc2, 0x3f, 0x4e, 0x0c, 0x5c, 0x52, 0xf4, 0x3d, +0xf7, 0x52, 0x82, 0xf1, 0xea, 0xa3, 0xac, 0xfd, 0x49, 0x34, 0x1a, 0x28, 0xf3, 0x41, 0x88, 0x3a, +0x13, 0xee, 0xe8, 0xde, 0xff, 0x99, 0x1d, 0x5f, 0xba, 0xcb, 0xe8, 0x1e, 0xf2, 0xb9, 0x50, 0x60, +0xc0, 0x31, 0xd3, 0x73, 0xe5, 0xef, 0xbe, 0xa0, 0xed, 0x33, 0x0b, 0x74, 0xbe, 0x20, 0x20, 0xc4, +0x67, 0x6c, 0xf0, 0x08, 0x03, 0x7a, 0x55, 0x80, 0x7f, 0x46, 0x4e, 0x96, 0xa7, 0xf4, 0x1e, 0x3e, +0xe1, 0xf6, 0xd8, 0x09, 0xe1, 0x33, 0x64, 0x2b, 0x63, 0xd7, 0x32, 0x5e, 0x9f, 0xf9, 0xc0, 0x7b, +0x0f, 0x78, 0x6f, 0x97, 0xbc, 0x93, 0x9a, 0xf9, 0x9c, 0x12, 0x90, 0x78, 0x7a, 0x80, 0x87, 0x15, +0xd7, 0x72, 0x74, 0x9c, 0x55, 0x74, 0x78, 0xb1, 0xba, 0xe1, 0x6e, 0x70, 0x04, 0xba, 0x4f, 0xa0, +0xba, 0x68, 0xc3, 0x7b, 0xff, 0x31, 0xf0, 0x73, 0x3d, 0x3d, 0x94, 0x2a, 0xb1, 0x0b, 0x41, 0x0e, +0xa0, 0xfe, 0x4d, 0x88, 0x65, 0x6b, 0x79, 0x33, 0xb4, 0xd7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xed, +0x44, 0x19, 0xc0, 0xd3, 0xf0, 0x06, 0x8b, 0xee, 0xa4, 0x7b, 0xbe, 0x42, 0xe7, 0x26, 0x54, 0xc8, +0x8e, 0x36, 0x76, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, +0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0d, 0xae, 0x90, 0x32, 0xf6, 0xa6, 0x4b, 0x7c, 0x44, +0x76, 0x19, 0x61, 0x1e, 0x27, 0x28, 0xcd, 0x5e, 0x54, 0xef, 0x25, 0xbc, 0xe3, 0x08, 0x90, 0xf9, +0x29, 0xd7, 0xae, 0x68, 0x08, 0xe1, 0x94, 0x00, 0x58, 0xef, 0x2e, 0x2e, 0x7e, 0x53, 0x52, 0x8c, +0xb6, 0x5c, 0x07, 0xea, 0x88, 0xba, 0x99, 0x8b, 0x50, 0x94, 0xd7, 0x82, 0x80, 0xdf, 0x61, 0x09, +0x00, 0x93, 0xad, 0x0d, 0x14, 0xe6, 0xce, 0xc1, 0xf2, 0x37, 0x94, 0x78, 0xb0, 0x5f, 0x9c, 0xb3, +0xa2, 0x73, 0xb8, 0x8f, 0x05, 0x93, 0x38, 0xcd, 0x8d, 0x3e, 0xb0, 0xb8, 0xfb, 0xc0, 0xcf, 0xb1, +0xf2, 0xec, 0x2d, 0x2d, 0x1b, 0xcc, 0xec, 0xaa, 0x9a, 0xb3, 0xaa, 0x60, 0x82, 0x1b, 0x2d, 0x3b, +0xc3, 0x84, 0x3d, 0x57, 0x8a, 0x96, 0x1e, 0x9c, 0x75, 0xb8, 0xd3, 0x30, 0xcd, 0x60, 0x08, 0x83, +0x90, 0xd3, 0x8e, 0x54, 0xf1, 0x4d, 0x66, 0xc0, 0x5d, 0x74, 0x03, 0x40, 0xa3, 0xee, 0x85, 0x7e, +0xc2, 0x1f, 0x77, 0x9c, 0x06, 0xe8, 0xc1, 0xa7, 0x18, 0x5d, 0x52, 0x95, 0xed, 0xc9, 0xdd, 0x25, +0x9e, 0x6d, 0xfa, 0xa9, 0xed, 0xa3, 0x3a, 0x34, 0xd0, 0x59, 0x7b, 0xda, 0xed, 0x50, 0xf3, 0x35, +0xbf, 0xed, 0xeb, 0x14, 0x4d, 0x31, 0xc7, 0x60, 0xf4, 0xda, 0xf1, 0x87, 0x9c, 0xe2, 0x48, 0xe2, +0xc6, 0xc5, 0x37, 0xfb, 0x06, 0x10, 0xfa, 0x75, 0x59, 0x66, 0x31, 0x47, 0x29, 0xda, 0x76, 0x9a, +0x1c, 0xe9, 0x82, 0xae, 0xef, 0x9a, 0xb9, 0x51, 0xf7, 0x88, 0x23, 0x9a, 0x69, 0x95, 0x62, 0x3c, +0xe5, 0x55, 0x80, 0x36, 0xd7, 0x54, 0x02, 0xff, 0xf1, 0xb9, 0x5d, 0xce, 0xd4, 0x23, 0x6f, 0xd8, +0x45, 0x84, 0x4a, 0x5b, 0x65, 0xef, 0x89, 0x0c, 0xdd, 0x14, 0xa7, 0x20, 0xcb, 0x18, 0xa5, 0x25, +0xb4, 0x0d, 0xf9, 0x01, 0xf0, 0xa2, 0xd2, 0xf4, 0x00, 0xc8, 0x74, 0x8e, 0xa1, 0x2a, 0x48, 0x8e, +0x65, 0xdb, 0x13, 0xc4, 0xe2, 0x25, 0x17, 0x7d, 0xeb, 0xbe, 0x87, 0x5b, 0x17, 0x20, 0x54, 0x51, +0x93, 0x4a, 0x53, 0x03, 0x0b, 0xec, 0x5d, 0xca, 0x33, 0xed, 0x62, 0xfd, 0x45, 0xc7, 0x2f, 0x5b, +0xdc, 0x58, 0xa0, 0x80, 0x39, 0xe6, 0xfa, 0xd7, 0xfe, 0x13, 0x14, 0xa6, 0xed, 0x3d, 0x94, 0x4a, +0x42, 0x74, 0xd4, 0xc3, 0x77, 0x59, 0x73, 0xcd, 0x8f, 0x46, 0xbe, 0x55, 0x38, 0xef, 0xfa, 0xe8, +0x91, 0x32, 0xea, 0x97, 0x58, 0x04, 0x22, 0xde, 0x38, 0xc3, 0xcc, 0xbc, 0x6d, 0xc9, 0x33, 0x3a, +0x6a, 0x0a, 0x69, 0x3f, 0xa0, 0xc8, 0xea, 0x72, 0x8f, 0x8c, 0x63, 0x86, 0x23, 0xbd, 0x6d, 0x3c, +0x96, 0x9e, 0x95, 0xe0, 0x49, 0x4c, 0xaa, 0xa2, 0xb9, 0x2a, 0x1b, 0x9c, 0x36, 0x81, 0x78, 0xed, +0xc3, 0xe8, 0x46, 0xe2, 0x26, 0x59, 0x44, 0x75, 0x1e, 0xd9, 0x75, 0x89, 0x51, 0xcd, 0x10, 0x84, +0x9d, 0x61, 0x60, 0xcb, 0x5d, 0xf9, 0x97, 0x22, 0x4d, 0x8e, 0x98, 0xe6, 0xe3, 0x7f, 0xf6, 0x5b, +0xbb, 0xae, 0xcd, 0xca, 0x4a, 0x81, 0x6b, 0x5e, 0x0b, 0xf3, 0x51, 0xe1, 0x74, 0x2b, 0xe9, 0x7e, +0x27, 0xa7, 0xd9, 0x99, 0x49, 0x4e, 0xf8, 0xa5, 0x80, 0xdb, 0x25, 0x0f, 0x1c, 0x63, 0x62, 0x8a, +0xc9, 0x33, 0x67, 0x6b, 0x3c, 0x10, 0x83, 0xc6, 0xad, 0xde, 0xa8, 0xcd, 0x16, 0x8e, 0x8d, 0xf0, +0x07, 0x37, 0x71, 0x9f, 0xf2, 0xab, 0xfc, 0x41, 0xf5, 0xc1, 0x8b, 0xec, 0x00, 0x37, 0x5d, 0x09, +0xe5, 0x4e, 0x80, 0xef, 0xfa, 0xb1, 0x5c, 0x38, 0x06, 0xa5, 0x1b, 0x4a, 0xe1, 0xdc, 0x38, 0x2d, +0x3c, 0xdc, 0xab, 0x1f, 0x90, 0x1a, 0xd5, 0x4a, 0x9c, 0xee, 0xd1, 0x70, 0x6c, 0xcc, 0xee, 0xf4, +0x57, 0xf8, 0x18, 0xba, 0x84, 0x6e, 0x87, 0x30, 0x82, 0x05, 0x66, 0x30, 0x82, 0x03, 0x4e, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x0a, 0x01, 0x42, 0x80, 0x00, 0x00, 0x01, 0x45, 0x23, 0xcf, +0x46, 0x7c, 0x00, 0x00, 0x00, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x4d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x49, +0x64, 0x65, 0x6e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x21, 0x49, 0x64, 0x65, 0x6e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, +0x6c, 0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x41, 0x20, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x31, 0x31, 0x36, 0x31, 0x37, +0x35, 0x33, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x34, 0x30, 0x31, 0x31, 0x36, 0x31, 0x37, 0x35, +0x33, 0x33, 0x32, 0x5a, 0x30, 0x4d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x49, 0x64, +0x65, 0x6e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x21, 0x49, 0x64, 0x65, 0x6e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6c, +0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, +0x41, 0x20, 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, +0x82, 0x02, 0x01, 0x00, 0xb6, 0x22, 0x94, 0xfc, 0xa4, 0x48, 0xaf, 0xe8, 0x47, 0x6b, 0x0a, 0xfb, +0x27, 0x76, 0xe4, 0xf2, 0x3f, 0x8a, 0x3b, 0x7a, 0x4a, 0x2c, 0x31, 0x2a, 0x8c, 0x8d, 0xb0, 0xa9, +0xc3, 0x31, 0x6b, 0xa8, 0x77, 0x76, 0x84, 0x26, 0xb6, 0xac, 0x81, 0x42, 0x0d, 0x08, 0xeb, 0x55, +0x58, 0xbb, 0x7a, 0xf8, 0xbc, 0x65, 0x7d, 0xf2, 0xa0, 0x6d, 0x8b, 0xa8, 0x47, 0xe9, 0x62, 0x76, +0x1e, 0x11, 0xee, 0x08, 0x14, 0xd1, 0xb2, 0x44, 0x16, 0xf4, 0xea, 0xd0, 0xfa, 0x1e, 0x2f, 0x5e, +0xdb, 0xcb, 0x73, 0x41, 0xae, 0xbc, 0x00, 0xb0, 0x4a, 0x2b, 0x40, 0xb2, 0xac, 0xe1, 0x3b, 0x4b, +0xc2, 0x2d, 0x9d, 0xe4, 0xa1, 0x9b, 0xec, 0x1a, 0x3a, 0x1e, 0xf0, 0x08, 0xb3, 0xd0, 0xe4, 0x24, +0x35, 0x07, 0x9f, 0x9c, 0xb4, 0xc9, 0x52, 0x6d, 0xdb, 0x07, 0xca, 0x8f, 0xb5, 0x5b, 0xf0, 0x83, +0xf3, 0x4f, 0xc7, 0x2d, 0xa5, 0xc8, 0xad, 0xcb, 0x95, 0x20, 0xa4, 0x31, 0x28, 0x57, 0x58, 0x5a, +0xe4, 0x8d, 0x1b, 0x9a, 0xab, 0x9e, 0x0d, 0x0c, 0xf2, 0x0a, 0x33, 0x39, 0x22, 0x39, 0x0a, 0x97, +0x2e, 0xf3, 0x53, 0x77, 0xb9, 0x44, 0x45, 0xfd, 0x84, 0xcb, 0x36, 0x20, 0x81, 0x59, 0x2d, 0x9a, +0x6f, 0x6d, 0x48, 0x48, 0x61, 0xca, 0x4c, 0xdf, 0x53, 0xd1, 0xaf, 0x52, 0xbc, 0x44, 0x9f, 0xab, +0x2f, 0x6b, 0x83, 0x72, 0xef, 0x75, 0x80, 0xda, 0x06, 0x33, 0x1b, 0x5d, 0xc8, 0xda, 0x63, 0xc6, +0x4d, 0xcd, 0xac, 0x66, 0x31, 0xcd, 0xd1, 0xde, 0x3e, 0x87, 0x10, 0x36, 0xe1, 0xb9, 0xa4, 0x7a, +0xef, 0x60, 0x50, 0xb2, 0xcb, 0xca, 0xa6, 0x56, 0xe0, 0x37, 0xaf, 0xab, 0x34, 0x13, 0x39, 0x25, +0xe8, 0x39, 0x66, 0xe4, 0x98, 0x7a, 0xaa, 0x12, 0x98, 0x9c, 0x59, 0x66, 0x86, 0x3e, 0xad, 0xf1, +0xb0, 0xca, 0x3e, 0x06, 0x0f, 0x7b, 0xf0, 0x11, 0x4b, 0x37, 0xa0, 0x44, 0x6d, 0x7b, 0xcb, 0xa8, +0x8c, 0x71, 0xf4, 0xd5, 0xb5, 0x91, 0x36, 0xcc, 0xf0, 0x15, 0xc6, 0x2b, 0xde, 0x51, 0x17, 0xb1, +0x97, 0x4c, 0x50, 0x3d, 0xb1, 0x95, 0x59, 0x7c, 0x05, 0x7d, 0x2d, 0x21, 0xd5, 0x00, 0xbf, 0x01, +0x67, 0xa2, 0x5e, 0x7b, 0xa6, 0x5c, 0xf2, 0xf7, 0x22, 0xf1, 0x90, 0x0d, 0x93, 0xdb, 0xaa, 0x44, +0x51, 0x66, 0xcc, 0x7d, 0x76, 0x03, 0xeb, 0x6a, 0xa8, 0x2a, 0x38, 0x19, 0x97, 0x76, 0x0d, 0x6b, +0x8a, 0x61, 0xf9, 0xbc, 0xf6, 0xee, 0x76, 0xfd, 0x70, 0x2b, 0xdd, 0x29, 0x3c, 0xf8, 0x0a, 0x1e, +0x5b, 0x42, 0x1c, 0x8b, 0x56, 0x2f, 0x55, 0x1b, 0x1c, 0xa1, 0x2e, 0xb5, 0xc7, 0x16, 0xe6, 0xf8, +0xaa, 0x3c, 0x92, 0x8e, 0x69, 0xb6, 0x01, 0xc1, 0xb5, 0x86, 0x9d, 0x89, 0x0f, 0x0b, 0x38, 0x94, +0x54, 0xe8, 0xea, 0xdc, 0x9e, 0x3d, 0x25, 0xbc, 0x53, 0x26, 0xed, 0xd5, 0xab, 0x39, 0xaa, 0xc5, +0x40, 0x4c, 0x54, 0xab, 0xb2, 0xb4, 0xd9, 0xd9, 0xf8, 0xd7, 0x72, 0xdb, 0x1c, 0xbc, 0x6d, 0xbd, +0x65, 0x5f, 0xef, 0x88, 0x35, 0x2a, 0x66, 0x2f, 0xee, 0xf6, 0xb3, 0x65, 0xf0, 0x33, 0x8d, 0x7c, +0x98, 0x41, 0x69, 0x46, 0x0f, 0x43, 0x1c, 0x69, 0xfa, 0x9b, 0xb5, 0xd0, 0x61, 0x6a, 0xcd, 0xca, +0x4b, 0xd9, 0x4c, 0x90, 0x46, 0xab, 0x15, 0x59, 0xa1, 0x47, 0x54, 0x29, 0x2e, 0x83, 0x28, 0x5f, +0x1c, 0xc2, 0xa2, 0xab, 0x72, 0x17, 0x00, 0x06, 0x8e, 0x45, 0xec, 0x8b, 0xe2, 0x33, 0x3d, 0x7f, +0xda, 0x19, 0x44, 0xe4, 0x62, 0x72, 0xc3, 0xdf, 0x22, 0xc6, 0xf2, 0x56, 0xd4, 0xdd, 0x5f, 0x95, +0x72, 0xed, 0x6d, 0x5f, 0xf7, 0x48, 0x03, 0x5b, 0xfd, 0xc5, 0x2a, 0xa0, 0xf6, 0x73, 0x23, 0x84, +0x10, 0x1b, 0x01, 0xe7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe3, 0x71, 0xe0, 0x9e, 0xd8, 0xa7, 0x42, +0xd9, 0xdb, 0x71, 0x91, 0x6b, 0x94, 0x93, 0xeb, 0xc3, 0xa3, 0xd1, 0x14, 0xa3, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, +0x00, 0x47, 0xfa, 0xdd, 0x0a, 0xb0, 0x11, 0x91, 0x38, 0xad, 0x4d, 0x5d, 0xf7, 0xe5, 0x0e, 0x97, +0x54, 0x19, 0x82, 0x48, 0x87, 0x54, 0x8c, 0xaa, 0x64, 0x99, 0xd8, 0x5a, 0xfe, 0x88, 0x01, 0xc5, +0x58, 0xa5, 0x99, 0xb1, 0x23, 0x54, 0x23, 0xb7, 0x6a, 0x1d, 0x20, 0x57, 0xe5, 0x01, 0x62, 0x41, +0x17, 0xd3, 0x09, 0xdb, 0x75, 0xcb, 0x6e, 0x54, 0x90, 0x75, 0xfe, 0x1a, 0x9f, 0x81, 0x0a, 0xc2, +0xdd, 0xd7, 0xf7, 0x09, 0xd0, 0x5b, 0x72, 0x15, 0xe4, 0x1e, 0x09, 0x6a, 0x3d, 0x33, 0xf3, 0x21, +0x9a, 0xe6, 0x15, 0x7e, 0xad, 0x51, 0xd5, 0x0d, 0x10, 0xed, 0x7d, 0x42, 0xc0, 0x8f, 0xee, 0xc0, +0x9a, 0x08, 0xd5, 0x41, 0xd6, 0x5c, 0x0e, 0x21, 0x69, 0x6e, 0x80, 0x61, 0x0e, 0x15, 0xc0, 0xb8, +0xcf, 0xc5, 0x49, 0x12, 0x52, 0xcc, 0xbe, 0x3a, 0xcc, 0xd4, 0x2e, 0x38, 0x05, 0xde, 0x35, 0xfd, +0x1f, 0x6f, 0xb8, 0x80, 0x68, 0x98, 0x3d, 0x4d, 0xa0, 0xca, 0x40, 0x65, 0xd2, 0x73, 0x7c, 0xf5, +0x8b, 0xd9, 0x0a, 0x95, 0x3f, 0xd8, 0x3f, 0x23, 0x6d, 0x1a, 0xd1, 0x2a, 0x24, 0x19, 0xd9, 0x85, +0xb3, 0x17, 0xef, 0x78, 0x6e, 0xa9, 0x58, 0xd1, 0x23, 0xd3, 0xc7, 0x13, 0xed, 0x72, 0x25, 0x7f, +0x5d, 0xb1, 0x73, 0x70, 0xd0, 0x7f, 0x06, 0x97, 0x09, 0x84, 0x29, 0x80, 0x61, 0x1d, 0xfa, 0x5e, +0xff, 0x73, 0xac, 0xa0, 0xe3, 0x89, 0xb8, 0x1c, 0x71, 0x15, 0xc6, 0xde, 0x31, 0x7f, 0x12, 0xdc, +0xe1, 0x6d, 0x9b, 0xaf, 0xe7, 0xe8, 0x9f, 0x75, 0x78, 0x4c, 0xab, 0x46, 0x3b, 0x9a, 0xce, 0xbf, +0x05, 0x18, 0x5d, 0x4d, 0x15, 0x3c, 0x16, 0x9a, 0x19, 0x50, 0x04, 0x9a, 0xb2, 0x9a, 0x6f, 0x65, +0x8b, 0x52, 0x5f, 0x3c, 0x58, 0x04, 0x28, 0x25, 0xc0, 0x66, 0x61, 0x31, 0x7e, 0xb9, 0xe0, 0x75, +0xb9, 0x1a, 0xa8, 0x81, 0xd6, 0x72, 0x17, 0xb3, 0xc5, 0x03, 0x31, 0x35, 0x11, 0x78, 0x78, 0xa2, +0xe0, 0xe9, 0x30, 0x8c, 0x7f, 0x80, 0xdf, 0x58, 0xdf, 0x3c, 0xba, 0x27, 0x96, 0xe2, 0x80, 0x34, +0x6d, 0xe3, 0x98, 0xd3, 0x64, 0x27, 0xac, 0x48, 0x7e, 0x28, 0x77, 0x5c, 0xc6, 0x25, 0x61, 0x25, +0xf8, 0x85, 0x0c, 0x65, 0xfa, 0xc4, 0x32, 0x2f, 0xa5, 0x98, 0x05, 0xe4, 0xf8, 0x0b, 0x67, 0x16, +0x16, 0xc6, 0x82, 0xb8, 0x32, 0x19, 0xf9, 0xf9, 0xb9, 0x79, 0xdc, 0x1f, 0xcd, 0xeb, 0xaf, 0xab, +0x0e, 0xdd, 0x1b, 0xdb, 0x45, 0xe4, 0x7a, 0xe7, 0x02, 0xe2, 0x95, 0x5d, 0xfc, 0x69, 0xf0, 0x53, +0x69, 0x61, 0x95, 0x75, 0x79, 0x0b, 0x5e, 0x55, 0xe6, 0x38, 0x1c, 0x94, 0xa9, 0x59, 0x33, 0x9e, +0xc8, 0x71, 0x74, 0x79, 0x7f, 0x51, 0x89, 0xb6, 0xc8, 0x6a, 0xb8, 0x30, 0xc8, 0x6a, 0x38, 0xc3, +0x6e, 0x9e, 0xe1, 0x37, 0x16, 0xea, 0x05, 0x62, 0x4c, 0x5b, 0x12, 0x47, 0xed, 0xa7, 0xb4, 0xb3, +0x58, 0x56, 0xc7, 0x49, 0xf3, 0x7f, 0x12, 0x68, 0x09, 0x31, 0x71, 0xf0, 0x6d, 0xf8, 0x4e, 0x47, +0xfb, 0xd6, 0x85, 0xee, 0xc5, 0x58, 0x40, 0x19, 0xa4, 0x1d, 0xa7, 0xf9, 0x4b, 0x43, 0x37, 0xdc, +0x68, 0x5a, 0x4f, 0xcf, 0xeb, 0xc2, 0x64, 0x74, 0xde, 0xb4, 0x15, 0xd9, 0xf4, 0x54, 0x54, 0x1a, +0x2f, 0x1c, 0xd7, 0x97, 0x71, 0x54, 0x90, 0x8e, 0xd9, 0x20, 0x9d, 0x53, 0x2b, 0x7f, 0xab, 0x8f, +0xe2, 0xea, 0x30, 0xbc, 0x50, 0x37, 0xef, 0xf1, 0x47, 0xb5, 0x7d, 0x7c, 0x2c, 0x04, 0xec, 0x68, +0x9d, 0xb4, 0x49, 0x44, 0x10, 0xf4, 0x72, 0x4b, 0x1c, 0x64, 0xe7, 0xfc, 0xe6, 0x6b, 0x90, 0xdd, +0x69, 0x7d, 0x69, 0xfd, 0x00, 0x56, 0xa5, 0xb7, 0xac, 0xb6, 0xad, 0xb7, 0xca, 0x3e, 0x01, 0xef, +0x9c, 0x30, 0x82, 0x05, 0x70, 0x30, 0x82, 0x03, 0x58, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, +0x00, 0x98, 0x96, 0x8d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x30, 0x58, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x4e, 0x4c, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x15, 0x53, 0x74, 0x61, +0x61, 0x74, 0x20, 0x64, 0x65, 0x72, 0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, +0x65, 0x6e, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x53, 0x74, 0x61, +0x61, 0x74, 0x20, 0x64, 0x65, 0x72, 0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, +0x65, 0x6e, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, +0x0d, 0x31, 0x30, 0x31, 0x32, 0x30, 0x38, 0x31, 0x31, 0x31, 0x39, 0x32, 0x39, 0x5a, 0x17, 0x0d, +0x32, 0x32, 0x31, 0x32, 0x30, 0x38, 0x31, 0x31, 0x31, 0x30, 0x32, 0x38, 0x5a, 0x30, 0x58, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x1e, 0x30, 0x1c, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x15, 0x53, 0x74, 0x61, 0x61, 0x74, 0x20, 0x64, 0x65, 0x72, +0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x65, 0x6e, 0x31, 0x29, 0x30, 0x27, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x53, 0x74, 0x61, 0x61, 0x74, 0x20, 0x64, 0x65, 0x72, +0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x65, 0x6e, 0x20, 0x45, 0x56, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, +0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xe3, 0xc7, 0x7e, 0x89, 0xf9, 0x24, 0x4b, 0x3a, +0xd2, 0x33, 0x83, 0x35, 0x2c, 0x69, 0xec, 0xdc, 0x09, 0xa4, 0xe3, 0x51, 0xa8, 0x25, 0x2b, 0x79, +0xb8, 0x08, 0x3d, 0xe0, 0x91, 0xba, 0x84, 0x85, 0xc6, 0x85, 0xa4, 0xca, 0xe6, 0xc9, 0x2e, 0x53, +0xa4, 0xc9, 0x24, 0x1e, 0xfd, 0x55, 0x66, 0x71, 0x5d, 0x2c, 0xc5, 0x60, 0x68, 0x04, 0xb7, 0xd9, +0xc2, 0x52, 0x26, 0x38, 0x88, 0xa4, 0xd6, 0x3b, 0x40, 0xa6, 0xc2, 0xcd, 0x3f, 0xcd, 0x98, 0x93, +0xb3, 0x54, 0x14, 0x58, 0x96, 0x55, 0xd5, 0x50, 0xfe, 0x86, 0xad, 0xa4, 0x63, 0x7f, 0x5c, 0x87, +0xf6, 0x8e, 0xe6, 0x27, 0x92, 0x67, 0x17, 0x92, 0x02, 0x03, 0x2c, 0xdc, 0xd6, 0x66, 0x74, 0xed, +0xdd, 0x67, 0xff, 0xc1, 0x61, 0x8d, 0x63, 0x4f, 0x0f, 0x9b, 0x6d, 0x17, 0x30, 0x26, 0xef, 0xab, +0xd2, 0x1f, 0x10, 0xa0, 0xf9, 0xc5, 0x7f, 0x16, 0x69, 0x81, 0x03, 0x47, 0xed, 0x1e, 0x68, 0x8d, +0x72, 0xa1, 0x4d, 0xb2, 0x26, 0xc6, 0xba, 0x6c, 0x5f, 0x6d, 0xd6, 0xaf, 0xd1, 0xb1, 0x13, 0x8e, +0xa9, 0xad, 0xf3, 0x5e, 0x69, 0x75, 0x26, 0x18, 0x3e, 0x41, 0x2b, 0x21, 0x7f, 0xee, 0x8b, 0x5d, +0x07, 0x06, 0x9d, 0x43, 0xc4, 0x29, 0x0a, 0x2b, 0xfc, 0x2a, 0x3e, 0x86, 0xcb, 0x3c, 0x83, 0x3a, +0xf9, 0xc9, 0x0d, 0xda, 0xc5, 0x99, 0xe2, 0xbc, 0x78, 0x41, 0x33, 0x76, 0xe1, 0xbf, 0x2f, 0x5d, +0xe5, 0xa4, 0x98, 0x50, 0x0c, 0x15, 0xdd, 0xe0, 0xfa, 0x9c, 0x7f, 0x38, 0x68, 0xd0, 0xb2, 0xa6, +0x7a, 0xa7, 0xd1, 0x31, 0xbd, 0x7e, 0x8a, 0x58, 0x27, 0x43, 0xb3, 0xba, 0x33, 0x91, 0xd3, 0xa7, +0x98, 0x15, 0x5c, 0x9a, 0xe6, 0xd3, 0x0f, 0x75, 0xd9, 0xfc, 0x41, 0x98, 0x97, 0x3e, 0xaa, 0x25, +0xdb, 0x8f, 0x92, 0x2e, 0xb0, 0x7b, 0x0c, 0x5f, 0xf1, 0x63, 0xa9, 0x37, 0xf9, 0x9b, 0x75, 0x69, +0x4c, 0x28, 0x26, 0x25, 0xda, 0xd5, 0xf2, 0x12, 0x70, 0x45, 0x55, 0xe3, 0xdf, 0x73, 0x5e, 0x37, +0xf5, 0x21, 0x6c, 0x90, 0x8e, 0x35, 0x5a, 0xc9, 0xd3, 0x23, 0xeb, 0xd3, 0xc0, 0xbe, 0x78, 0xac, +0x42, 0x28, 0x58, 0x66, 0xa5, 0x46, 0x6d, 0x70, 0x02, 0xd7, 0x10, 0xf9, 0x4b, 0x54, 0xfc, 0x5d, +0x86, 0x4a, 0x87, 0xcf, 0x7f, 0xca, 0x45, 0xac, 0x11, 0x5a, 0xb5, 0x20, 0x51, 0x8d, 0x2f, 0x88, +0x47, 0x97, 0x39, 0xc0, 0xcf, 0xba, 0xc0, 0x42, 0x01, 0x40, 0x99, 0x48, 0x21, 0x0b, 0x6b, 0xa7, +0xd2, 0xfd, 0x96, 0xd5, 0xd1, 0xbe, 0x46, 0x9d, 0x49, 0xe0, 0x0b, 0xa6, 0xa0, 0x22, 0x4e, 0x38, +0xd0, 0xc1, 0x3c, 0x30, 0xbc, 0x70, 0x8f, 0x2c, 0x75, 0xcc, 0xd0, 0xc5, 0x8c, 0x51, 0x3b, 0x3d, +0x94, 0x08, 0x64, 0x26, 0x61, 0x7d, 0xb9, 0xc3, 0x65, 0x8f, 0x14, 0x9c, 0x21, 0xd0, 0xaa, 0xfd, +0x17, 0x72, 0x03, 0x8f, 0xbd, 0x9b, 0x8c, 0xe6, 0x5e, 0x53, 0x9e, 0xb9, 0x9d, 0xef, 0x82, 0xbb, +0xe1, 0xbc, 0xe2, 0x72, 0x41, 0x5b, 0x21, 0x94, 0xd3, 0x45, 0x37, 0x94, 0xd1, 0xdf, 0x09, 0x39, +0x5d, 0xe7, 0x23, 0xaa, 0x9a, 0x1d, 0xca, 0x6d, 0xa8, 0x0a, 0x86, 0x85, 0x8a, 0x82, 0xbe, 0x42, +0x07, 0xd6, 0xf2, 0x38, 0x82, 0x73, 0xda, 0x87, 0x5b, 0xe5, 0x3c, 0xd3, 0x9e, 0x3e, 0xa7, 0x3b, +0x9e, 0xf4, 0x03, 0xb3, 0xf9, 0xf1, 0x7d, 0x13, 0x74, 0x02, 0xff, 0xbb, 0xa1, 0xe5, 0xfa, 0x00, +0x79, 0x1c, 0xa6, 0x66, 0x41, 0x88, 0x5c, 0x60, 0x57, 0xa6, 0x2e, 0x09, 0xc4, 0xba, 0xfd, 0x9a, +0xcf, 0xa7, 0x1f, 0x40, 0xc3, 0xbb, 0xcc, 0x5a, 0x0a, 0x55, 0x4b, 0x3b, 0x38, 0x76, 0x51, 0xb8, +0x63, 0x8b, 0x84, 0x94, 0x16, 0xe6, 0x56, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, +0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfe, 0xab, 0x00, +0x90, 0x98, 0x9e, 0x24, 0xfc, 0xa9, 0xcc, 0x1a, 0x8a, 0xfb, 0x27, 0xb8, 0xbf, 0x30, 0x6e, 0xa8, +0x3b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x03, 0x82, 0x02, 0x01, 0x00, 0xcf, 0x77, 0x2c, 0x6e, 0x56, 0xbe, 0x4e, 0xb3, 0xb6, 0x84, 0x00, +0x94, 0xab, 0x47, 0xc9, 0x0d, 0xd2, 0x76, 0xc7, 0x86, 0x9f, 0x1d, 0x07, 0xd3, 0xb6, 0xb4, 0xbb, +0x08, 0x78, 0xaf, 0x69, 0xd2, 0x0b, 0x49, 0xde, 0x33, 0xc5, 0xac, 0xad, 0xc2, 0x88, 0x02, 0x7d, +0x06, 0xb7, 0x35, 0x02, 0xc1, 0x60, 0xc9, 0xbf, 0xc4, 0xe8, 0x94, 0xde, 0xd4, 0xd3, 0xa9, 0x13, +0x25, 0x5a, 0xfe, 0x6e, 0xa2, 0xae, 0x7d, 0x05, 0xdc, 0x7d, 0xf3, 0x6c, 0xf0, 0x7e, 0xa6, 0x8d, +0xee, 0xd9, 0xd7, 0xce, 0x58, 0x17, 0xe8, 0xa9, 0x29, 0xae, 0x73, 0x48, 0x87, 0xe7, 0x9b, 0xca, +0x6e, 0x29, 0xa1, 0x64, 0x5f, 0x19, 0x13, 0xf7, 0xae, 0x06, 0x10, 0xff, 0x51, 0xc6, 0x9b, 0x4d, +0x55, 0x25, 0x4f, 0x93, 0x99, 0x10, 0x01, 0x53, 0x75, 0xf1, 0x13, 0xce, 0xc7, 0xa6, 0x41, 0x41, +0xd2, 0xbf, 0x88, 0xa5, 0x7f, 0x45, 0xfc, 0xac, 0xb8, 0xa5, 0xb5, 0x33, 0x0c, 0x82, 0xc4, 0xfb, +0x07, 0xf6, 0x6a, 0xe5, 0x25, 0x84, 0x5f, 0x06, 0xca, 0xc1, 0x86, 0x39, 0x11, 0xdb, 0x58, 0xcd, +0x77, 0x3b, 0x2c, 0xc2, 0x4c, 0x0f, 0x5e, 0x9a, 0xe3, 0xf0, 0xab, 0x3e, 0x61, 0x1b, 0x50, 0x24, +0xc2, 0xc0, 0xf4, 0xf1, 0x19, 0xf0, 0x11, 0x29, 0xb6, 0xa5, 0x18, 0x02, 0x9b, 0xd7, 0x63, 0x4c, +0x70, 0x8c, 0x47, 0xa3, 0x03, 0x43, 0x5c, 0xb9, 0x5d, 0x46, 0xa0, 0x0d, 0x6f, 0xff, 0x59, 0x8e, +0xbe, 0xdd, 0x9f, 0x72, 0xc3, 0x5b, 0x2b, 0xdf, 0x8c, 0x5b, 0xce, 0xe5, 0x0c, 0x46, 0x6c, 0x92, +0xb2, 0x0a, 0xa3, 0x4c, 0x54, 0x42, 0x18, 0x15, 0x12, 0x18, 0xbd, 0xda, 0xfc, 0xba, 0x74, 0x6e, +0xff, 0xc1, 0xb6, 0xa0, 0x64, 0xd8, 0xa9, 0x5f, 0x55, 0xae, 0x9f, 0x5c, 0x6a, 0x76, 0x96, 0xd8, +0x73, 0x67, 0x87, 0xfb, 0x4d, 0x7f, 0x5c, 0xee, 0x69, 0xca, 0x73, 0x10, 0xfb, 0x8a, 0xa9, 0xfd, +0x9e, 0xbd, 0x36, 0x38, 0x49, 0x49, 0x87, 0xf4, 0x0e, 0x14, 0xf0, 0xe9, 0x87, 0xb8, 0x3f, 0xa7, +0x4f, 0x7a, 0x5a, 0x8e, 0x79, 0xd4, 0x93, 0xe4, 0xbb, 0x68, 0x52, 0x84, 0xac, 0x6c, 0xe9, 0xf3, +0x98, 0x70, 0x55, 0x72, 0x32, 0xf9, 0x34, 0xab, 0x2b, 0x49, 0xb5, 0xcd, 0x20, 0x62, 0xe4, 0x3a, +0x7a, 0x67, 0x63, 0xab, 0x96, 0xdc, 0x6d, 0xae, 0x97, 0xec, 0xfc, 0x9f, 0x76, 0x56, 0x88, 0x2e, +0x66, 0xcf, 0x5b, 0xb6, 0xc9, 0xa4, 0xb0, 0xd7, 0x05, 0xba, 0xe1, 0x27, 0x2f, 0x93, 0xbb, 0x26, +0x2a, 0xa2, 0x93, 0xb0, 0x1b, 0xf3, 0x8e, 0xbe, 0x1d, 0x40, 0xa3, 0xb9, 0x36, 0x8f, 0x3e, 0x82, +0x1a, 0x1a, 0x5e, 0x88, 0xea, 0x50, 0xf8, 0x59, 0xe2, 0x83, 0x46, 0x29, 0x0b, 0xe3, 0x44, 0x5c, +0xe1, 0x95, 0xb6, 0x69, 0x90, 0x9a, 0x14, 0x6f, 0x97, 0xae, 0x81, 0xcf, 0x68, 0xef, 0x99, 0x9a, +0xbe, 0xb5, 0xe7, 0xe1, 0x7f, 0xf8, 0xfa, 0x13, 0x47, 0x16, 0x4c, 0xcc, 0x6d, 0x08, 0x40, 0xe7, +0x8b, 0x78, 0x6f, 0x50, 0x82, 0x44, 0x50, 0x3f, 0x66, 0x06, 0x8a, 0xab, 0x43, 0x84, 0x56, 0x4a, +0x0f, 0x20, 0x2d, 0x86, 0x0e, 0xf5, 0xd2, 0xdb, 0xd2, 0x7a, 0x8a, 0x4b, 0xcd, 0xa5, 0xe8, 0x4e, +0xf1, 0x5e, 0x26, 0x25, 0x01, 0x59, 0x23, 0xa0, 0x7e, 0xd2, 0xf6, 0x7e, 0x21, 0x57, 0xd7, 0x27, +0xbc, 0x15, 0x57, 0x4c, 0xa4, 0x46, 0xc1, 0xe0, 0x83, 0x1e, 0x0c, 0x4c, 0x4d, 0x1f, 0x4f, 0x06, +0x19, 0xe2, 0xf9, 0xa8, 0xf4, 0x3a, 0x82, 0xa1, 0xb2, 0x79, 0x43, 0x79, 0xd6, 0xad, 0x6f, 0x7a, +0x27, 0x90, 0x03, 0xa4, 0xea, 0x24, 0x87, 0x3f, 0xd9, 0xbd, 0xd9, 0xe9, 0xf2, 0x5f, 0x50, 0x49, +0x1c, 0xee, 0xec, 0xd7, 0x2e, 0x30, 0x82, 0x04, 0x3e, 0x30, 0x82, 0x03, 0x26, 0xa0, 0x03, 0x02, +0x01, 0x02, 0x02, 0x04, 0x4a, 0x53, 0x8c, 0x28, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xbe, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, +0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, +0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, 0x65, +0x67, 0x61, 0x6c, 0x2d, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x30, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6e, 0x74, +0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x66, 0x6f, 0x72, +0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, +0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, +0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, +0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x37, +0x30, 0x37, 0x31, 0x37, 0x32, 0x35, 0x35, 0x34, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x30, +0x37, 0x31, 0x37, 0x35, 0x35, 0x35, 0x34, 0x5a, 0x30, 0x81, 0xbe, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, +0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, 0x65, 0x20, 0x77, +0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, +0x65, 0x67, 0x61, 0x6c, 0x2d, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x30, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6e, +0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x66, 0x6f, +0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, +0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, +0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, +0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xba, 0x84, 0xb6, 0x72, 0xdb, 0x9e, +0x0c, 0x6b, 0xe2, 0x99, 0xe9, 0x30, 0x01, 0xa7, 0x76, 0xea, 0x32, 0xb8, 0x95, 0x41, 0x1a, 0xc9, +0xda, 0x61, 0x4e, 0x58, 0x72, 0xcf, 0xfe, 0xf6, 0x82, 0x79, 0xbf, 0x73, 0x61, 0x06, 0x0a, 0xa5, +0x27, 0xd8, 0xb3, 0x5f, 0xd3, 0x45, 0x4e, 0x1c, 0x72, 0xd6, 0x4e, 0x32, 0xf2, 0x72, 0x8a, 0x0f, +0xf7, 0x83, 0x19, 0xd0, 0x6a, 0x80, 0x80, 0x00, 0x45, 0x1e, 0xb0, 0xc7, 0xe7, 0x9a, 0xbf, 0x12, +0x57, 0x27, 0x1c, 0xa3, 0x68, 0x2f, 0x0a, 0x87, 0xbd, 0x6a, 0x6b, 0x0e, 0x5e, 0x65, 0xf3, 0x1c, +0x77, 0xd5, 0xd4, 0x85, 0x8d, 0x70, 0x21, 0xb4, 0xb3, 0x32, 0xe7, 0x8b, 0xa2, 0xd5, 0x86, 0x39, +0x02, 0xb1, 0xb8, 0xd2, 0x47, 0xce, 0xe4, 0xc9, 0x49, 0xc4, 0x3b, 0xa7, 0xde, 0xfb, 0x54, 0x7d, +0x57, 0xbe, 0xf0, 0xe8, 0x6e, 0xc2, 0x79, 0xb2, 0x3a, 0x0b, 0x55, 0xe2, 0x50, 0x98, 0x16, 0x32, +0x13, 0x5c, 0x2f, 0x78, 0x56, 0xc1, 0xc2, 0x94, 0xb3, 0xf2, 0x5a, 0xe4, 0x27, 0x9a, 0x9f, 0x24, +0xd7, 0xc6, 0xec, 0xd0, 0x9b, 0x25, 0x82, 0xe3, 0xcc, 0xc2, 0xc4, 0x45, 0xc5, 0x8c, 0x97, 0x7a, +0x06, 0x6b, 0x2a, 0x11, 0x9f, 0xa9, 0x0a, 0x6e, 0x48, 0x3b, 0x6f, 0xdb, 0xd4, 0x11, 0x19, 0x42, +0xf7, 0x8f, 0x07, 0xbf, 0xf5, 0x53, 0x5f, 0x9c, 0x3e, 0xf4, 0x17, 0x2c, 0xe6, 0x69, 0xac, 0x4e, +0x32, 0x4c, 0x62, 0x77, 0xea, 0xb7, 0xe8, 0xe5, 0xbb, 0x34, 0xbc, 0x19, 0x8b, 0xae, 0x9c, 0x51, +0xe7, 0xb7, 0x7e, 0xb5, 0x53, 0xb1, 0x33, 0x22, 0xe5, 0x6d, 0xcf, 0x70, 0x3c, 0x1a, 0xfa, 0xe2, +0x9b, 0x67, 0xb6, 0x83, 0xf4, 0x8d, 0xa5, 0xaf, 0x62, 0x4c, 0x4d, 0xe0, 0x58, 0xac, 0x64, 0x34, +0x12, 0x03, 0xf8, 0xb6, 0x8d, 0x94, 0x63, 0x24, 0xa4, 0x71, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6a, +0x72, 0x26, 0x7a, 0xd0, 0x1e, 0xef, 0x7d, 0xe7, 0x3b, 0x69, 0x51, 0xd4, 0x6c, 0x8d, 0x9f, 0x90, +0x12, 0x66, 0xab, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, +0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x79, 0x9f, 0x1d, 0x96, 0xc6, 0xb6, 0x79, 0x3f, 0x22, +0x8d, 0x87, 0xd3, 0x87, 0x03, 0x04, 0x60, 0x6a, 0x6b, 0x9a, 0x2e, 0x59, 0x89, 0x73, 0x11, 0xac, +0x43, 0xd1, 0xf5, 0x13, 0xff, 0x8d, 0x39, 0x2b, 0xc0, 0xf2, 0xbd, 0x4f, 0x70, 0x8c, 0xa9, 0x2f, +0xea, 0x17, 0xc4, 0x0b, 0x54, 0x9e, 0xd4, 0x1b, 0x96, 0x98, 0x33, 0x3c, 0xa8, 0xad, 0x62, 0xa2, +0x00, 0x76, 0xab, 0x59, 0x69, 0x6e, 0x06, 0x1d, 0x7e, 0xc4, 0xb9, 0x44, 0x8d, 0x98, 0xaf, 0x12, +0xd4, 0x61, 0xdb, 0x0a, 0x19, 0x46, 0x47, 0xf3, 0xeb, 0xf7, 0x63, 0xc1, 0x40, 0x05, 0x40, 0xa5, +0xd2, 0xb7, 0xf4, 0xb5, 0x9a, 0x36, 0xbf, 0xa9, 0x88, 0x76, 0x88, 0x04, 0x55, 0x04, 0x2b, 0x9c, +0x87, 0x7f, 0x1a, 0x37, 0x3c, 0x7e, 0x2d, 0xa5, 0x1a, 0xd8, 0xd4, 0x89, 0x5e, 0xca, 0xbd, 0xac, +0x3d, 0x6c, 0xd8, 0x6d, 0xaf, 0xd5, 0xf3, 0x76, 0x0f, 0xcd, 0x3b, 0x88, 0x38, 0x22, 0x9d, 0x6c, +0x93, 0x9a, 0xc4, 0x3d, 0xbf, 0x82, 0x1b, 0x65, 0x3f, 0xa6, 0x0f, 0x5d, 0xaa, 0xfc, 0xe5, 0xb2, +0x15, 0xca, 0xb5, 0xad, 0xc6, 0xbc, 0x3d, 0xd0, 0x84, 0xe8, 0xea, 0x06, 0x72, 0xb0, 0x4d, 0x39, +0x32, 0x78, 0xbf, 0x3e, 0x11, 0x9c, 0x0b, 0xa4, 0x9d, 0x9a, 0x21, 0xf3, 0xf0, 0x9b, 0x0b, 0x30, +0x78, 0xdb, 0xc1, 0xdc, 0x87, 0x43, 0xfe, 0xbc, 0x63, 0x9a, 0xca, 0xc5, 0xc2, 0x1c, 0xc9, 0xc7, +0x8d, 0xff, 0x3b, 0x12, 0x58, 0x08, 0xe6, 0xb6, 0x3d, 0xec, 0x7a, 0x2c, 0x4e, 0xfb, 0x83, 0x96, +0xce, 0x0c, 0x3c, 0x69, 0x87, 0x54, 0x73, 0xa4, 0x73, 0xc2, 0x93, 0xff, 0x51, 0x10, 0xac, 0x15, +0x54, 0x01, 0xd8, 0xfc, 0x05, 0xb1, 0x89, 0xa1, 0x7f, 0x74, 0x83, 0x9a, 0x49, 0xd7, 0xdc, 0x4e, +0x7b, 0x8a, 0x48, 0x6f, 0x8b, 0x45, 0xf6, 0x30, 0x82, 0x02, 0xf9, 0x30, 0x82, 0x02, 0x80, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x0d, 0x00, 0xa6, 0x8b, 0x79, 0x29, 0x00, 0x00, 0x00, 0x00, 0x50, +0xd0, 0x91, 0xf9, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, +0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, +0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x1f, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, +0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x2d, 0x74, 0x65, 0x72, 0x6d, +0x73, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x30, 0x28, 0x63, 0x29, 0x20, +0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, +0x63, 0x2e, 0x20, 0x2d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, +0x7a, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x31, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2a, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x45, 0x43, +0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x32, 0x31, 0x38, 0x31, 0x35, 0x32, 0x35, 0x33, +0x36, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x32, 0x31, 0x38, 0x31, 0x35, 0x35, 0x35, 0x33, 0x36, +0x5a, 0x30, 0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, +0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, +0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x2d, 0x74, 0x65, +0x72, 0x6d, 0x73, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x30, 0x28, 0x63, +0x29, 0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, +0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x33, +0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2a, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, +0x45, 0x43, 0x31, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, +0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x84, 0x13, 0xc9, 0xd0, 0xba, +0x6d, 0x41, 0x7b, 0xe2, 0x6c, 0xd0, 0xeb, 0x55, 0x5f, 0x66, 0x02, 0x1a, 0x24, 0xf4, 0x5b, 0x89, +0x69, 0x47, 0xe3, 0xb8, 0xc2, 0x7d, 0xf1, 0xf2, 0x02, 0xc5, 0x9f, 0xa0, 0xf6, 0x5b, 0xd5, 0x8b, +0x06, 0x19, 0x86, 0x4f, 0x53, 0x10, 0x6d, 0x07, 0x24, 0x27, 0xa1, 0xa0, 0xf8, 0xd5, 0x47, 0x19, +0x61, 0x4c, 0x7d, 0xca, 0x93, 0x27, 0xea, 0x74, 0x0c, 0xef, 0x6f, 0x96, 0x09, 0xfe, 0x63, 0xec, +0x70, 0x5d, 0x36, 0xad, 0x67, 0x77, 0xae, 0xc9, 0x9d, 0x7c, 0x55, 0x44, 0x3a, 0xa2, 0x63, 0x51, +0x1f, 0xf5, 0xe3, 0x62, 0xd4, 0xa9, 0x47, 0x07, 0x3e, 0xcc, 0x20, 0xa3, 0x42, 0x30, 0x40, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, 0x63, 0xe7, 0x1a, 0xdd, +0x8d, 0xe9, 0x08, 0xa6, 0x55, 0x83, 0xa4, 0xe0, 0x6a, 0x50, 0x41, 0x65, 0x11, 0x42, 0x49, 0x30, +0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, 0x30, 0x64, +0x02, 0x30, 0x61, 0x79, 0xd8, 0xe5, 0x42, 0x47, 0xdf, 0x1c, 0xae, 0x53, 0x99, 0x17, 0xb6, 0x6f, +0x1c, 0x7d, 0xe1, 0xbf, 0x11, 0x94, 0xd1, 0x03, 0x88, 0x75, 0xe4, 0x8d, 0x89, 0xa4, 0x8a, 0x77, +0x46, 0xde, 0x6d, 0x61, 0xef, 0x02, 0xf5, 0xfb, 0xb5, 0xdf, 0xcc, 0xfe, 0x4e, 0xff, 0xfe, 0xa9, +0xe6, 0xa7, 0x02, 0x30, 0x5b, 0x99, 0xd7, 0x85, 0x37, 0x06, 0xb5, 0x7b, 0x08, 0xfd, 0xeb, 0x27, +0x8b, 0x4a, 0x94, 0xf9, 0xe1, 0xfa, 0xa7, 0x8e, 0x26, 0x08, 0xe8, 0x7c, 0x92, 0x68, 0x6d, 0x73, +0xd8, 0x6f, 0x26, 0xac, 0x21, 0x02, 0xb8, 0x99, 0xb7, 0x26, 0x41, 0x5b, 0x25, 0x60, 0xae, 0xd0, +0x48, 0x1a, 0xee, 0x06, 0x30, 0x82, 0x03, 0x38, 0x30, 0x82, 0x02, 0x20, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x06, 0x20, 0x06, 0x05, 0x16, 0x70, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x52, 0x4f, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x10, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4e, 0x20, 0x52, 0x4f, +0x4f, 0x54, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x37, 0x30, 0x34, 0x31, +0x37, 0x32, 0x30, 0x30, 0x34, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x30, 0x37, 0x30, 0x34, 0x31, 0x37, +0x32, 0x30, 0x30, 0x34, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x52, 0x4f, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x63, +0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x10, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4e, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x20, +0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, +0x01, 0x01, 0x00, 0xb7, 0x33, 0xb9, 0x7e, 0xc8, 0x25, 0x4a, 0x8e, 0xb5, 0xdb, 0xb4, 0x28, 0x1b, +0xaa, 0x57, 0x90, 0xe8, 0xd1, 0x22, 0xd3, 0x64, 0xba, 0xd3, 0x93, 0xe8, 0xd4, 0xac, 0x86, 0x61, +0x40, 0x6a, 0x60, 0x57, 0x68, 0x54, 0x84, 0x4d, 0xbc, 0x6a, 0x54, 0x02, 0x05, 0xff, 0xdf, 0x9b, +0x9a, 0x2a, 0xae, 0x5d, 0x07, 0x8f, 0x4a, 0xc3, 0x28, 0x7f, 0xef, 0xfb, 0x2b, 0xfa, 0x79, 0xf1, +0xc7, 0xad, 0xf0, 0x10, 0x53, 0x24, 0x90, 0x8b, 0x66, 0xc9, 0xa8, 0x88, 0xab, 0xaf, 0x5a, 0xa3, +0x00, 0xe9, 0xbe, 0xba, 0x46, 0xee, 0x5b, 0x73, 0x7b, 0x2c, 0x17, 0x82, 0x81, 0x5e, 0x62, 0x2c, +0xa1, 0x02, 0x65, 0xb3, 0xbd, 0xc5, 0x2b, 0x00, 0x7e, 0xc4, 0xfc, 0x03, 0x33, 0x57, 0x0d, 0xed, +0xe2, 0xfa, 0xce, 0x5d, 0x45, 0xd6, 0x38, 0xcd, 0x35, 0xb6, 0xb2, 0xc1, 0xd0, 0x9c, 0x81, 0x4a, +0xaa, 0xe4, 0xb2, 0x01, 0x5c, 0x1d, 0x8f, 0x5f, 0x99, 0xc4, 0xb1, 0xad, 0xdb, 0x88, 0x21, 0xeb, +0x90, 0x08, 0x82, 0x80, 0xf3, 0x30, 0xa3, 0x43, 0xe6, 0x90, 0x82, 0xae, 0x55, 0x28, 0x49, 0xed, +0x5b, 0xd7, 0xa9, 0x10, 0x38, 0x0e, 0xfe, 0x8f, 0x4c, 0x5b, 0x9b, 0x46, 0xea, 0x41, 0xf5, 0xb0, +0x08, 0x74, 0xc3, 0xd0, 0x88, 0x33, 0xb6, 0x7c, 0xd7, 0x74, 0xdf, 0xdc, 0x84, 0xd1, 0x43, 0x0e, +0x75, 0x39, 0xa1, 0x25, 0x40, 0x28, 0xea, 0x78, 0xcb, 0x0e, 0x2c, 0x2e, 0x39, 0x9d, 0x8c, 0x8b, +0x6e, 0x16, 0x1c, 0x2f, 0x26, 0x82, 0x10, 0xe2, 0xe3, 0x65, 0x94, 0x0a, 0x04, 0xc0, 0x5e, 0xf7, +0x5d, 0x5b, 0xf8, 0x10, 0xe2, 0xd0, 0xba, 0x7a, 0x4b, 0xfb, 0xde, 0x37, 0x00, 0x00, 0x1a, 0x5b, +0x28, 0xe3, 0xd2, 0x9c, 0x73, 0x3e, 0x32, 0x87, 0x98, 0xa1, 0xc9, 0x51, 0x2f, 0xd7, 0xde, 0xac, +0x33, 0xb3, 0x4f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0xc6, 0x30, 0x1d, 0x06, +0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe0, 0x8c, 0x9b, 0xdb, 0x25, 0x49, 0xb3, 0xf1, +0x7c, 0x86, 0xd6, 0xb2, 0x42, 0x87, 0x0b, 0xd0, 0x6b, 0xa0, 0xd9, 0xe4, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, +0x3e, 0xd2, 0x1c, 0x89, 0x2e, 0x35, 0xfc, 0xf8, 0x75, 0xdd, 0xe6, 0x7f, 0x65, 0x88, 0xf4, 0x72, +0x4c, 0xc9, 0x2c, 0xd7, 0x32, 0x4e, 0xf3, 0xdd, 0x19, 0x79, 0x47, 0xbd, 0x8e, 0x3b, 0x5b, 0x93, +0x0f, 0x50, 0x49, 0x24, 0x13, 0x6b, 0x14, 0x06, 0x72, 0xef, 0x09, 0xd3, 0xa1, 0xa1, 0xe3, 0x40, +0x84, 0xc9, 0xe7, 0x18, 0x32, 0x74, 0x3c, 0x48, 0x6e, 0x0f, 0x9f, 0x4b, 0xd4, 0xf7, 0x1e, 0xd3, +0x93, 0x86, 0x64, 0x54, 0x97, 0x63, 0x72, 0x50, 0xd5, 0x55, 0xcf, 0xfa, 0x20, 0x93, 0x02, 0xa2, +0x9b, 0xc3, 0x23, 0x93, 0x4e, 0x16, 0x55, 0x76, 0xa0, 0x70, 0x79, 0x6d, 0xcd, 0x21, 0x1f, 0xcf, +0x2f, 0x2d, 0xbc, 0x19, 0xe3, 0x88, 0x31, 0xf8, 0x59, 0x1a, 0x81, 0x09, 0xc8, 0x97, 0xa6, 0x74, +0xc7, 0x60, 0xc4, 0x5b, 0xcc, 0x57, 0x8e, 0xb2, 0x75, 0xfd, 0x1b, 0x02, 0x09, 0xdb, 0x59, 0x6f, +0x72, 0x93, 0x69, 0xf7, 0x31, 0x41, 0xd6, 0x88, 0x38, 0xbf, 0x87, 0xb2, 0xbd, 0x16, 0x79, 0xf9, +0xaa, 0xe4, 0xbe, 0x88, 0x25, 0xdd, 0x61, 0x27, 0x23, 0x1c, 0xb5, 0x31, 0x07, 0x04, 0x36, 0xb4, +0x1a, 0x90, 0xbd, 0xa0, 0x74, 0x71, 0x50, 0x89, 0x6d, 0xbc, 0x14, 0xe3, 0x0f, 0x86, 0xae, 0xf1, +0xab, 0x3e, 0xc7, 0xa0, 0x09, 0xcc, 0xa3, 0x48, 0xd1, 0xe0, 0xdb, 0x64, 0xe7, 0x92, 0xb5, 0xcf, +0xaf, 0x72, 0x43, 0x70, 0x8b, 0xf9, 0xc3, 0x84, 0x3c, 0x13, 0xaa, 0x7e, 0x92, 0x9b, 0x57, 0x53, +0x93, 0xfa, 0x70, 0xc2, 0x91, 0x0e, 0x31, 0xf9, 0x9b, 0x67, 0x5d, 0xe9, 0x96, 0x38, 0x5e, 0x5f, +0xb3, 0x73, 0x4e, 0x88, 0x15, 0x67, 0xde, 0x9e, 0x76, 0x10, 0x62, 0x20, 0xbe, 0x55, 0x69, 0x95, +0x43, 0x00, 0x39, 0x4d, 0xf6, 0xee, 0xb0, 0x5a, 0x4e, 0x49, 0x44, 0x54, 0x58, 0x5f, 0x42, 0x83, +0x30, 0x82, 0x03, 0xbb, 0x30, 0x82, 0x02, 0xa3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x04, +0x44, 0xc0, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, +0x00, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, +0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x55, 0x6e, 0x69, 0x7a, 0x65, +0x74, 0x6f, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x20, +0x53, 0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x43, +0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, +0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x54, +0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x43, +0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x31, 0x30, 0x32, 0x32, 0x31, 0x32, 0x30, 0x37, 0x33, +0x37, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x32, 0x30, 0x37, 0x33, 0x37, +0x5a, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50, 0x4c, +0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x55, 0x6e, 0x69, 0x7a, 0x65, +0x74, 0x6f, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x20, +0x53, 0x2e, 0x41, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1e, 0x43, +0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, +0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6d, 0x20, 0x54, +0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x43, +0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, +0x01, 0x00, 0xe3, 0xfb, 0x7d, 0xa3, 0x72, 0xba, 0xc2, 0xf0, 0xc9, 0x14, 0x87, 0xf5, 0x6b, 0x01, +0x4e, 0xe1, 0x6e, 0x40, 0x07, 0xba, 0x6d, 0x27, 0x5d, 0x7f, 0xf7, 0x5b, 0x2d, 0xb3, 0x5a, 0xc7, +0x51, 0x5f, 0xab, 0xa4, 0x32, 0xa6, 0x61, 0x87, 0xb6, 0x6e, 0x0f, 0x86, 0xd2, 0x30, 0x02, 0x97, +0xf8, 0xd7, 0x69, 0x57, 0xa1, 0x18, 0x39, 0x5d, 0x6a, 0x64, 0x79, 0xc6, 0x01, 0x59, 0xac, 0x3c, +0x31, 0x4a, 0x38, 0x7c, 0xd2, 0x04, 0xd2, 0x4b, 0x28, 0xe8, 0x20, 0x5f, 0x3b, 0x07, 0xa2, 0xcc, +0x4d, 0x73, 0xdb, 0xf3, 0xae, 0x4f, 0xc7, 0x56, 0xd5, 0x5a, 0xa7, 0x96, 0x89, 0xfa, 0xf3, 0xab, +0x68, 0xd4, 0x23, 0x86, 0x59, 0x27, 0xcf, 0x09, 0x27, 0xbc, 0xac, 0x6e, 0x72, 0x83, 0x1c, 0x30, +0x72, 0xdf, 0xe0, 0xa2, 0xe9, 0xd2, 0xe1, 0x74, 0x75, 0x19, 0xbd, 0x2a, 0x9e, 0x7b, 0x15, 0x54, +0x04, 0x1b, 0xd7, 0x43, 0x39, 0xad, 0x55, 0x28, 0xc5, 0xe2, 0x1a, 0xbb, 0xf4, 0xc0, 0xe4, 0xae, +0x38, 0x49, 0x33, 0xcc, 0x76, 0x85, 0x9f, 0x39, 0x45, 0xd2, 0xa4, 0x9e, 0xf2, 0x12, 0x8c, 0x51, +0xf8, 0x7c, 0xe4, 0x2d, 0x7f, 0xf5, 0xac, 0x5f, 0xeb, 0x16, 0x9f, 0xb1, 0x2d, 0xd1, 0xba, 0xcc, +0x91, 0x42, 0x77, 0x4c, 0x25, 0xc9, 0x90, 0x38, 0x6f, 0xdb, 0xf0, 0xcc, 0xfb, 0x8e, 0x1e, 0x97, +0x59, 0x3e, 0xd5, 0x60, 0x4e, 0xe6, 0x05, 0x28, 0xed, 0x49, 0x79, 0x13, 0x4b, 0xba, 0x48, 0xdb, +0x2f, 0xf9, 0x72, 0xd3, 0x39, 0xca, 0xfe, 0x1f, 0xd8, 0x34, 0x72, 0xf5, 0xb4, 0x40, 0xcf, 0x31, +0x01, 0xc3, 0xec, 0xde, 0x11, 0x2d, 0x17, 0x5d, 0x1f, 0xb8, 0x50, 0xd1, 0x5e, 0x19, 0xa7, 0x69, +0xde, 0x07, 0x33, 0x28, 0xca, 0x50, 0x95, 0xf9, 0xa7, 0x54, 0xcb, 0x54, 0x86, 0x50, 0x45, 0xa9, +0xf9, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, +0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x08, 0x76, 0xcd, 0xcb, 0x07, 0xff, 0x24, 0xf6, 0xc5, +0xcd, 0xed, 0xbb, 0x90, 0xbc, 0xe2, 0x84, 0x37, 0x46, 0x75, 0xf7, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa6, +0xa8, 0xad, 0x22, 0xce, 0x01, 0x3d, 0xa6, 0xa3, 0xff, 0x62, 0xd0, 0x48, 0x9d, 0x8b, 0x5e, 0x72, +0xb0, 0x78, 0x44, 0xe3, 0xdc, 0x1c, 0xaf, 0x09, 0xfd, 0x23, 0x48, 0xfa, 0xbd, 0x2a, 0xc4, 0xb9, +0x55, 0x04, 0xb5, 0x10, 0xa3, 0x8d, 0x27, 0xde, 0x0b, 0x82, 0x63, 0xd0, 0xee, 0xde, 0x0c, 0x37, +0x79, 0x41, 0x5b, 0x22, 0xb2, 0xb0, 0x9a, 0x41, 0x5c, 0xa6, 0x70, 0xe0, 0xd4, 0xd0, 0x77, 0xcb, +0x23, 0xd3, 0x00, 0xe0, 0x6c, 0x56, 0x2f, 0xe1, 0x69, 0x0d, 0x0d, 0xd9, 0xaa, 0xbf, 0x21, 0x81, +0x50, 0xd9, 0x06, 0xa5, 0xa8, 0xff, 0x95, 0x37, 0xd0, 0xaa, 0xfe, 0xe2, 0xb3, 0xf5, 0x99, 0x2d, +0x45, 0x84, 0x8a, 0xe5, 0x42, 0x09, 0xd7, 0x74, 0x02, 0x2f, 0xf7, 0x89, 0xd8, 0x99, 0xe9, 0xbc, +0x27, 0xd4, 0x47, 0x8d, 0xba, 0x0d, 0x46, 0x1c, 0x77, 0xcf, 0x14, 0xa4, 0x1c, 0xb9, 0xa4, 0x31, +0xc4, 0x9c, 0x28, 0x74, 0x03, 0x34, 0xff, 0x33, 0x19, 0x26, 0xa5, 0xe9, 0x0d, 0x74, 0xb7, 0x3e, +0x97, 0xc6, 0x76, 0xe8, 0x27, 0x96, 0xa3, 0x66, 0xdd, 0xe1, 0xae, 0xf2, 0x41, 0x5b, 0xca, 0x98, +0x56, 0x83, 0x73, 0x70, 0xe4, 0x86, 0x1a, 0xd2, 0x31, 0x41, 0xba, 0x2f, 0xbe, 0x2d, 0x13, 0x5a, +0x76, 0x6f, 0x4e, 0xe8, 0x4e, 0x81, 0x0e, 0x3f, 0x5b, 0x03, 0x22, 0xa0, 0x12, 0xbe, 0x66, 0x58, +0x11, 0x4a, 0xcb, 0x03, 0xc4, 0xb4, 0x2a, 0x2a, 0x2d, 0x96, 0x17, 0xe0, 0x39, 0x54, 0xbc, 0x48, +0xd3, 0x76, 0x27, 0x9d, 0x9a, 0x2d, 0x06, 0xa6, 0xc9, 0xec, 0x39, 0xd2, 0xab, 0xdb, 0x9f, 0x9a, +0x0b, 0x27, 0x02, 0x35, 0x29, 0xb1, 0x40, 0x95, 0xe7, 0xf9, 0xe8, 0x9c, 0x55, 0x88, 0x19, 0x46, +0xd6, 0xb7, 0x34, 0xf5, 0x7e, 0xce, 0x39, 0x9a, 0xd9, 0x38, 0xf1, 0x51, 0xf7, 0x4f, 0x2c, 0x30, +0x82, 0x04, 0x1d, 0x30, 0x82, 0x03, 0x05, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4e, 0x81, +0x2d, 0x8a, 0x82, 0x65, 0xe0, 0x0b, 0x02, 0xee, 0x3e, 0x35, 0x02, 0x46, 0xe5, 0x3d, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x81, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, +0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, +0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, +0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, +0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x1e, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, +0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, +0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x32, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, +0x5a, 0x30, 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, +0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, +0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, +0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, +0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1e, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, +0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd0, 0x40, 0x8b, 0x8b, 0x72, 0xe3, 0x91, 0x1b, 0xf7, 0x51, +0xc1, 0x1b, 0x54, 0x04, 0x98, 0xd3, 0xa9, 0xbf, 0xc1, 0xe6, 0x8a, 0x5d, 0x3b, 0x87, 0xfb, 0xbb, +0x88, 0xce, 0x0d, 0xe3, 0x2f, 0x3f, 0x06, 0x96, 0xf0, 0xa2, 0x29, 0x50, 0x99, 0xae, 0xdb, 0x3b, +0xa1, 0x57, 0xb0, 0x74, 0x51, 0x71, 0xcd, 0xed, 0x42, 0x91, 0x4d, 0x41, 0xfe, 0xa9, 0xc8, 0xd8, +0x6a, 0x86, 0x77, 0x44, 0xbb, 0x59, 0x66, 0x97, 0x50, 0x5e, 0xb4, 0xd4, 0x2c, 0x70, 0x44, 0xcf, +0xda, 0x37, 0x95, 0x42, 0x69, 0x3c, 0x30, 0xc4, 0x71, 0xb3, 0x52, 0xf0, 0x21, 0x4d, 0xa1, 0xd8, +0xba, 0x39, 0x7c, 0x1c, 0x9e, 0xa3, 0x24, 0x9d, 0xf2, 0x83, 0x16, 0x98, 0xaa, 0x16, 0x7c, 0x43, +0x9b, 0x15, 0x5b, 0xb7, 0xae, 0x34, 0x91, 0xfe, 0xd4, 0x62, 0x26, 0x18, 0x46, 0x9a, 0x3f, 0xeb, +0xc1, 0xf9, 0xf1, 0x90, 0x57, 0xeb, 0xac, 0x7a, 0x0d, 0x8b, 0xdb, 0x72, 0x30, 0x6a, 0x66, 0xd5, +0xe0, 0x46, 0xa3, 0x70, 0xdc, 0x68, 0xd9, 0xff, 0x04, 0x48, 0x89, 0x77, 0xde, 0xb5, 0xe9, 0xfb, +0x67, 0x6d, 0x41, 0xe9, 0xbc, 0x39, 0xbd, 0x32, 0xd9, 0x62, 0x02, 0xf1, 0xb1, 0xa8, 0x3d, 0x6e, +0x37, 0x9c, 0xe2, 0x2f, 0xe2, 0xd3, 0xa2, 0x26, 0x8b, 0xc6, 0xb8, 0x55, 0x43, 0x88, 0xe1, 0x23, +0x3e, 0xa5, 0xd2, 0x24, 0x39, 0x6a, 0x47, 0xab, 0x00, 0xd4, 0xa1, 0xb3, 0xa9, 0x25, 0xfe, 0x0d, +0x3f, 0xa7, 0x1d, 0xba, 0xd3, 0x51, 0xc1, 0x0b, 0xa4, 0xda, 0xac, 0x38, 0xef, 0x55, 0x50, 0x24, +0x05, 0x65, 0x46, 0x93, 0x34, 0x4f, 0x2d, 0x8d, 0xad, 0xc6, 0xd4, 0x21, 0x19, 0xd2, 0x8e, 0xca, +0x05, 0x61, 0x71, 0x07, 0x73, 0x47, 0xe5, 0x8a, 0x19, 0x12, 0xbd, 0x04, 0x4d, 0xce, 0x4e, 0x9c, +0xa5, 0x48, 0xac, 0xbb, 0x26, 0xf7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x8e, 0x30, 0x81, +0x8b, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x0b, 0x58, 0xe5, 0x8b, +0xc6, 0x4c, 0x15, 0x37, 0xa4, 0x40, 0xa9, 0x30, 0xa9, 0x21, 0xbe, 0x47, 0x36, 0x5a, 0x56, 0xff, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x49, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x42, 0x30, 0x40, 0x30, 0x3e, 0xa0, 0x3c, +0xa0, 0x3a, 0x86, 0x38, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, +0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f, +0x44, 0x4f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, +0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, +0x3e, 0x98, 0x9e, 0x9b, 0xf6, 0x1b, 0xe9, 0xd7, 0x39, 0xb7, 0x78, 0xae, 0x1d, 0x72, 0x18, 0x49, +0xd3, 0x87, 0xe4, 0x43, 0x82, 0xeb, 0x3f, 0xc9, 0xaa, 0xf5, 0xa8, 0xb5, 0xef, 0x55, 0x7c, 0x21, +0x52, 0x65, 0xf9, 0xd5, 0x0d, 0xe1, 0x6c, 0xf4, 0x3e, 0x8c, 0x93, 0x73, 0x91, 0x2e, 0x02, 0xc4, +0x4e, 0x07, 0x71, 0x6f, 0xc0, 0x8f, 0x38, 0x61, 0x08, 0xa8, 0x1e, 0x81, 0x0a, 0xc0, 0x2f, 0x20, +0x2f, 0x41, 0x8b, 0x91, 0xdc, 0x48, 0x45, 0xbc, 0xf1, 0xc6, 0xde, 0xba, 0x76, 0x6b, 0x33, 0xc8, +0x00, 0x2d, 0x31, 0x46, 0x4c, 0xed, 0xe7, 0x9d, 0xcf, 0x88, 0x94, 0xff, 0x33, 0xc0, 0x56, 0xe8, +0x24, 0x86, 0x26, 0xb8, 0xd8, 0x38, 0x38, 0xdf, 0x2a, 0x6b, 0xdd, 0x12, 0xcc, 0xc7, 0x3f, 0x47, +0x17, 0x4c, 0xa2, 0xc2, 0x06, 0x96, 0x09, 0xd6, 0xdb, 0xfe, 0x3f, 0x3c, 0x46, 0x41, 0xdf, 0x58, +0xe2, 0x56, 0x0f, 0x3c, 0x3b, 0xc1, 0x1c, 0x93, 0x35, 0xd9, 0x38, 0x52, 0xac, 0xee, 0xc8, 0xec, +0x2e, 0x30, 0x4e, 0x94, 0x35, 0xb4, 0x24, 0x1f, 0x4b, 0x78, 0x69, 0xda, 0xf2, 0x02, 0x38, 0xcc, +0x95, 0x52, 0x93, 0xf0, 0x70, 0x25, 0x59, 0x9c, 0x20, 0x67, 0xc4, 0xee, 0xf9, 0x8b, 0x57, 0x61, +0xf4, 0x92, 0x76, 0x7d, 0x3f, 0x84, 0x8d, 0x55, 0xb7, 0xe8, 0xe5, 0xac, 0xd5, 0xf1, 0xf5, 0x19, +0x56, 0xa6, 0x5a, 0xfb, 0x90, 0x1c, 0xaf, 0x93, 0xeb, 0xe5, 0x1c, 0xd4, 0x67, 0x97, 0x5d, 0x04, +0x0e, 0xbe, 0x0b, 0x83, 0xa6, 0x17, 0x83, 0xb9, 0x30, 0x12, 0xa0, 0xc5, 0x33, 0x15, 0x05, 0xb9, +0x0d, 0xfb, 0xc7, 0x05, 0x76, 0xe3, 0xd8, 0x4a, 0x8d, 0xfc, 0x34, 0x17, 0xa3, 0xc6, 0x21, 0x28, +0xbe, 0x30, 0x45, 0x31, 0x1e, 0xc7, 0x78, 0xbe, 0x58, 0x61, 0x38, 0xac, 0x3b, 0xe2, 0x01, 0x65, +0x30, 0x82, 0x03, 0xa1, 0x30, 0x82, 0x02, 0x89, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0b, 0x04, +0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x85, 0xaa, 0x2d, 0x48, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x18, 0x30, 0x16, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x0f, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, +0x2c, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, +0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, +0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x32, 0x31, 0x35, +0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x35, 0x30, +0x38, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x0f, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, +0x6e, 0x63, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x79, 0x62, +0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, +0x82, 0x01, 0x01, 0x00, 0xf8, 0xc8, 0xbc, 0xbd, 0x14, 0x50, 0x66, 0x13, 0xff, 0xf0, 0xd3, 0x79, +0xec, 0x23, 0xf2, 0xb7, 0x1a, 0xc7, 0x8e, 0x85, 0xf1, 0x12, 0x73, 0xa6, 0x19, 0xaa, 0x10, 0xdb, +0x9c, 0xa2, 0x65, 0x74, 0x5a, 0x77, 0x3e, 0x51, 0x7d, 0x56, 0xf6, 0xdc, 0x23, 0xb6, 0xd4, 0xed, +0x5f, 0x58, 0xb1, 0x37, 0x4d, 0xd5, 0x49, 0x0e, 0x6e, 0xf5, 0x6a, 0x87, 0xd6, 0xd2, 0x8c, 0xd2, +0x27, 0xc6, 0xe2, 0xff, 0x36, 0x9f, 0x98, 0x65, 0xa0, 0x13, 0x4e, 0xc6, 0x2a, 0x64, 0x9b, 0xd5, +0x90, 0x12, 0xcf, 0x14, 0x06, 0xf4, 0x3b, 0xe3, 0xd4, 0x28, 0xbe, 0xe8, 0x0e, 0xf8, 0xab, 0x4e, +0x48, 0x94, 0x6d, 0x8e, 0x95, 0x31, 0x10, 0x5c, 0xed, 0xa2, 0x2d, 0xbd, 0xd5, 0x3a, 0x6d, 0xb2, +0x1c, 0xbb, 0x60, 0xc0, 0x46, 0x4b, 0x01, 0xf5, 0x49, 0xae, 0x7e, 0x46, 0x8a, 0xd0, 0x74, 0x8d, +0xa1, 0x0c, 0x02, 0xce, 0xee, 0xfc, 0xe7, 0x8f, 0xb8, 0x6b, 0x66, 0xf3, 0x7f, 0x44, 0x00, 0xbf, +0x66, 0x25, 0x14, 0x2b, 0xdd, 0x10, 0x30, 0x1d, 0x07, 0x96, 0x3f, 0x4d, 0xf6, 0x6b, 0xb8, 0x8f, +0xb7, 0x7b, 0x0c, 0xa5, 0x38, 0xeb, 0xde, 0x47, 0xdb, 0xd5, 0x5d, 0x39, 0xfc, 0x88, 0xa7, 0xf3, +0xd7, 0x2a, 0x74, 0xf1, 0xe8, 0x5a, 0xa2, 0x3b, 0x9f, 0x50, 0xba, 0xa6, 0x8c, 0x45, 0x35, 0xc2, +0x50, 0x65, 0x95, 0xdc, 0x63, 0x82, 0xef, 0xdd, 0xbf, 0x77, 0x4d, 0x9c, 0x62, 0xc9, 0x63, 0x73, +0x16, 0xd0, 0x29, 0x0f, 0x49, 0xa9, 0x48, 0xf0, 0xb3, 0xaa, 0xb7, 0x6c, 0xc5, 0xa7, 0x30, 0x39, +0x40, 0x5d, 0xae, 0xc4, 0xe2, 0x5d, 0x26, 0x53, 0xf0, 0xce, 0x1c, 0x23, 0x08, 0x61, 0xa8, 0x94, +0x19, 0xba, 0x04, 0x62, 0x40, 0xec, 0x1f, 0x38, 0x70, 0x77, 0x12, 0x06, 0x71, 0xa7, 0x30, 0x18, +0x5d, 0x25, 0x27, 0xa5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa5, 0x30, 0x81, 0xa2, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb6, 0x08, 0x7b, 0x0d, 0x7a, +0xcc, 0xac, 0x20, 0x4c, 0x86, 0x56, 0x32, 0x5e, 0xcf, 0xab, 0x6e, 0x85, 0x2d, 0x70, 0x57, 0x30, +0x3f, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x38, 0x30, 0x36, 0x30, 0x34, 0xa0, 0x32, 0xa0, 0x30, +0x86, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x32, 0x2e, 0x70, 0x75, +0x62, 0x6c, 0x69, 0x63, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, +0x72, 0x6c, 0x2f, 0x63, 0x74, 0x2f, 0x63, 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x72, 0x6c, +0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb6, 0x08, 0x7b, +0x0d, 0x7a, 0xcc, 0xac, 0x20, 0x4c, 0x86, 0x56, 0x32, 0x5e, 0xcf, 0xab, 0x6e, 0x85, 0x2d, 0x70, +0x57, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, +0x03, 0x82, 0x01, 0x01, 0x00, 0x56, 0xef, 0x0a, 0x23, 0xa0, 0x54, 0x4e, 0x95, 0x97, 0xc9, 0xf8, +0x89, 0xda, 0x45, 0xc1, 0xd4, 0xa3, 0x00, 0x25, 0xf4, 0x1f, 0x13, 0xab, 0xb7, 0xa3, 0x85, 0x58, +0x69, 0xc2, 0x30, 0xad, 0xd8, 0x15, 0x8a, 0x2d, 0xe3, 0xc9, 0xcd, 0x81, 0x5a, 0xf8, 0x73, 0x23, +0x5a, 0xa7, 0x7c, 0x05, 0xf3, 0xfd, 0x22, 0x3b, 0x0e, 0xd1, 0x06, 0xc4, 0xdb, 0x36, 0x4c, 0x73, +0x04, 0x8e, 0xe5, 0xb0, 0x22, 0xe4, 0xc5, 0xf3, 0x2e, 0xa5, 0xd9, 0x23, 0xe3, 0xb8, 0x4e, 0x4a, +0x20, 0xa7, 0x6e, 0x02, 0x24, 0x9f, 0x22, 0x60, 0x67, 0x7b, 0x8b, 0x1d, 0x72, 0x09, 0xc5, 0x31, +0x5c, 0xe9, 0x79, 0x9f, 0x80, 0x47, 0x3d, 0xad, 0xa1, 0x0b, 0x07, 0x14, 0x3d, 0x47, 0xff, 0x03, +0x69, 0x1a, 0x0c, 0x0b, 0x44, 0xe7, 0x63, 0x25, 0xa7, 0x7f, 0xb2, 0xc9, 0xb8, 0x76, 0x84, 0xed, +0x23, 0xf6, 0x7d, 0x07, 0xab, 0x45, 0x7e, 0xd3, 0xdf, 0xb3, 0xbf, 0xe9, 0x8a, 0xb6, 0xcd, 0xa8, +0xa2, 0x67, 0x2b, 0x52, 0xd5, 0xb7, 0x65, 0xf0, 0x39, 0x4c, 0x63, 0xa0, 0x91, 0x79, 0x93, 0x52, +0x0f, 0x54, 0xdd, 0x83, 0xbb, 0x9f, 0xd1, 0x8f, 0xa7, 0x53, 0x73, 0xc3, 0xcb, 0xff, 0x30, 0xec, +0x7c, 0x04, 0xb8, 0xd8, 0x44, 0x1f, 0x93, 0x5f, 0x71, 0x09, 0x22, 0xb7, 0x6e, 0x3e, 0xea, 0x1c, +0x03, 0x4e, 0x9d, 0x1a, 0x20, 0x61, 0xfb, 0x81, 0x37, 0xec, 0x5e, 0xfc, 0x0a, 0x45, 0xab, 0xd7, +0xe7, 0x17, 0x55, 0xd0, 0xa0, 0xea, 0x60, 0x9b, 0xa6, 0xf6, 0xe3, 0x8c, 0x5b, 0x29, 0xc2, 0x06, +0x60, 0x14, 0x9d, 0x2d, 0x97, 0x4c, 0xa9, 0x93, 0x15, 0x9d, 0x61, 0xc4, 0x01, 0x5f, 0x48, 0xd6, +0x58, 0xbd, 0x56, 0x31, 0x12, 0x4e, 0x11, 0xc8, 0x21, 0xe0, 0xb3, 0x11, 0x91, 0x65, 0xdb, 0xb4, +0xa6, 0x88, 0x38, 0xce, 0x55, 0x30, 0x82, 0x02, 0x89, 0x30, 0x82, 0x02, 0x0f, 0xa0, 0x03, 0x02, +0x01, 0x02, 0x02, 0x10, 0x1f, 0x47, 0xaf, 0xaa, 0x62, 0x00, 0x70, 0x50, 0x54, 0x4c, 0x01, 0x9e, +0x9b, 0x63, 0x99, 0x2a, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, +0x30, 0x81, 0x85, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, +0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, +0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, +0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, +0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2b, 0x30, 0x29, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x45, 0x43, 0x43, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, +0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, +0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, +0x38, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x85, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, +0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, +0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, +0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, +0x74, 0x65, 0x64, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4f, +0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, +0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x03, 0x47, 0x7b, 0x2f, 0x75, 0xc9, 0x82, 0x15, +0x85, 0xfb, 0x75, 0xe4, 0x91, 0x16, 0xd4, 0xab, 0x62, 0x99, 0xf5, 0x3e, 0x52, 0x0b, 0x06, 0xce, +0x41, 0x00, 0x7f, 0x97, 0xe1, 0x0a, 0x24, 0x3c, 0x1d, 0x01, 0x04, 0xee, 0x3d, 0xd2, 0x8d, 0x09, +0x97, 0x0c, 0xe0, 0x75, 0xe4, 0xfa, 0xfb, 0x77, 0x8a, 0x2a, 0xf5, 0x03, 0x60, 0x4b, 0x36, 0x8b, +0x16, 0x23, 0x16, 0xad, 0x09, 0x71, 0xf4, 0x4a, 0xf4, 0x28, 0x50, 0xb4, 0xfe, 0x88, 0x1c, 0x6e, +0x3f, 0x6c, 0x2f, 0x2f, 0x09, 0x59, 0x5b, 0xa5, 0x5b, 0x0b, 0x33, 0x99, 0xe2, 0xc3, 0x3d, 0x89, +0xf9, 0x6a, 0x2c, 0xef, 0xb2, 0xd3, 0x06, 0xe9, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0x71, 0xa7, 0x19, 0x48, 0x19, 0xbc, 0x9d, 0x9d, +0xea, 0x41, 0x47, 0xdf, 0x94, 0xc4, 0x48, 0x77, 0x99, 0xd3, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, +0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, +0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, +0xef, 0x03, 0x5b, 0x7a, 0xac, 0xb7, 0x78, 0x0a, 0x72, 0xb7, 0x88, 0xdf, 0xff, 0xb5, 0x46, 0x14, +0x09, 0x0a, 0xfa, 0xa0, 0xe6, 0x7d, 0x08, 0xc6, 0x1a, 0x87, 0xbd, 0x18, 0xa8, 0x73, 0xbd, 0x26, +0xca, 0x60, 0x0c, 0x9d, 0xce, 0x99, 0x9f, 0xcf, 0x5c, 0x0f, 0x30, 0xe1, 0xbe, 0x14, 0x31, 0xea, +0x02, 0x30, 0x14, 0xf4, 0x93, 0x3c, 0x49, 0xa7, 0x33, 0x7a, 0x90, 0x46, 0x47, 0xb3, 0x63, 0x7d, +0x13, 0x9b, 0x4e, 0xb7, 0x6f, 0x18, 0x37, 0x80, 0x53, 0xfe, 0xdd, 0x20, 0xe0, 0x35, 0x9a, 0x36, +0xd1, 0xc7, 0x01, 0xb9, 0xe6, 0xdc, 0xdd, 0xf3, 0xff, 0x1d, 0x2c, 0x3a, 0x16, 0x57, 0xd9, 0x92, +0x39, 0xd6, 0x30, 0x82, 0x03, 0xb7, 0x30, 0x82, 0x02, 0x9f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x10, 0x0c, 0xe7, 0xe0, 0xe5, 0x17, 0xd8, 0x46, 0xfe, 0x8f, 0xe5, 0x60, 0xfc, 0x1b, 0xf0, 0x30, +0x39, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, +0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, +0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, +0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, +0x6d, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, +0x43, 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, 0x31, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x31, 0x31, 0x31, 0x30, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, +0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, +0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, +0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, +0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xad, +0x0e, 0x15, 0xce, 0xe4, 0x43, 0x80, 0x5c, 0xb1, 0x87, 0xf3, 0xb7, 0x60, 0xf9, 0x71, 0x12, 0xa5, +0xae, 0xdc, 0x26, 0x94, 0x88, 0xaa, 0xf4, 0xce, 0xf5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0c, 0xf8, +0x80, 0xda, 0xa9, 0x15, 0x95, 0x32, 0x61, 0x3c, 0xb5, 0xb1, 0x28, 0x84, 0x8a, 0x8a, 0xdc, 0x9f, +0x0a, 0x0c, 0x83, 0x17, 0x7a, 0x8f, 0x90, 0xac, 0x8a, 0xe7, 0x79, 0x53, 0x5c, 0x31, 0x84, 0x2a, +0xf6, 0x0f, 0x98, 0x32, 0x36, 0x76, 0xcc, 0xde, 0xdd, 0x3c, 0xa8, 0xa2, 0xef, 0x6a, 0xfb, 0x21, +0xf2, 0x52, 0x61, 0xdf, 0x9f, 0x20, 0xd7, 0x1f, 0xe2, 0xb1, 0xd9, 0xfe, 0x18, 0x64, 0xd2, 0x12, +0x5b, 0x5f, 0xf9, 0x58, 0x18, 0x35, 0xbc, 0x47, 0xcd, 0xa1, 0x36, 0xf9, 0x6b, 0x7f, 0xd4, 0xb0, +0x38, 0x3e, 0xc1, 0x1b, 0xc3, 0x8c, 0x33, 0xd9, 0xd8, 0x2f, 0x18, 0xfe, 0x28, 0x0f, 0xb3, 0xa7, +0x83, 0xd6, 0xc3, 0x6e, 0x44, 0xc0, 0x61, 0x35, 0x96, 0x16, 0xfe, 0x59, 0x9c, 0x8b, 0x76, 0x6d, +0xd7, 0xf1, 0xa2, 0x4b, 0x0d, 0x2b, 0xff, 0x0b, 0x72, 0xda, 0x9e, 0x60, 0xd0, 0x8e, 0x90, 0x35, +0xc6, 0x78, 0x55, 0x87, 0x20, 0xa1, 0xcf, 0xe5, 0x6d, 0x0a, 0xc8, 0x49, 0x7c, 0x31, 0x98, 0x33, +0x6c, 0x22, 0xe9, 0x87, 0xd0, 0x32, 0x5a, 0xa2, 0xba, 0x13, 0x82, 0x11, 0xed, 0x39, 0x17, 0x9d, +0x99, 0x3a, 0x72, 0xa1, 0xe6, 0xfa, 0xa4, 0xd9, 0xd5, 0x17, 0x31, 0x75, 0xae, 0x85, 0x7d, 0x22, +0xae, 0x3f, 0x01, 0x46, 0x86, 0xf6, 0x28, 0x79, 0xc8, 0xb1, 0xda, 0xe4, 0x57, 0x17, 0xc4, 0x7e, +0x1c, 0x0e, 0xb0, 0xb4, 0x92, 0xa6, 0x56, 0xb3, 0xbd, 0xb2, 0x97, 0xed, 0xaa, 0xa7, 0xf0, 0xb7, +0xc5, 0xa8, 0x3f, 0x95, 0x16, 0xd0, 0xff, 0xa1, 0x96, 0xeb, 0x08, 0x5f, 0x18, 0x77, 0x4f, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, +0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, +0x04, 0x16, 0x04, 0x14, 0x45, 0xeb, 0xa2, 0xaf, 0xf4, 0x92, 0xcb, 0x82, 0x31, 0x2d, 0x51, 0x8b, +0xa7, 0xa7, 0x21, 0x9d, 0xf3, 0x6d, 0xc8, 0x0f, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, +0x18, 0x30, 0x16, 0x80, 0x14, 0x45, 0xeb, 0xa2, 0xaf, 0xf4, 0x92, 0xcb, 0x82, 0x31, 0x2d, 0x51, +0x8b, 0xa7, 0xa7, 0x21, 0x9d, 0xf3, 0x6d, 0xc8, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa2, 0x0e, 0xbc, +0xdf, 0xe2, 0xed, 0xf0, 0xe3, 0x72, 0x73, 0x7a, 0x64, 0x94, 0xbf, 0xf7, 0x72, 0x66, 0xd8, 0x32, +0xe4, 0x42, 0x75, 0x62, 0xae, 0x87, 0xeb, 0xf2, 0xd5, 0xd9, 0xde, 0x56, 0xb3, 0x9f, 0xcc, 0xce, +0x14, 0x28, 0xb9, 0x0d, 0x97, 0x60, 0x5c, 0x12, 0x4c, 0x58, 0xe4, 0xd3, 0x3d, 0x83, 0x49, 0x45, +0x58, 0x97, 0x35, 0x69, 0x1a, 0xa8, 0x47, 0xea, 0x56, 0xc6, 0x79, 0xab, 0x12, 0xd8, 0x67, 0x81, +0x84, 0xdf, 0x7f, 0x09, 0x3c, 0x94, 0xe6, 0xb8, 0x26, 0x2c, 0x20, 0xbd, 0x3d, 0xb3, 0x28, 0x89, +0xf7, 0x5f, 0xff, 0x22, 0xe2, 0x97, 0x84, 0x1f, 0xe9, 0x65, 0xef, 0x87, 0xe0, 0xdf, 0xc1, 0x67, +0x49, 0xb3, 0x5d, 0xeb, 0xb2, 0x09, 0x2a, 0xeb, 0x26, 0xed, 0x78, 0xbe, 0x7d, 0x3f, 0x2b, 0xf3, +0xb7, 0x26, 0x35, 0x6d, 0x5f, 0x89, 0x01, 0xb6, 0x49, 0x5b, 0x9f, 0x01, 0x05, 0x9b, 0xab, 0x3d, +0x25, 0xc1, 0xcc, 0xb6, 0x7f, 0xc2, 0xf1, 0x6f, 0x86, 0xc6, 0xfa, 0x64, 0x68, 0xeb, 0x81, 0x2d, +0x94, 0xeb, 0x42, 0xb7, 0xfa, 0x8c, 0x1e, 0xdd, 0x62, 0xf1, 0xbe, 0x50, 0x67, 0xb7, 0x6c, 0xbd, +0xf3, 0xf1, 0x1f, 0x6b, 0x0c, 0x36, 0x07, 0x16, 0x7f, 0x37, 0x7c, 0xa9, 0x5b, 0x6d, 0x7a, 0xf1, +0x12, 0x46, 0x60, 0x83, 0xd7, 0x27, 0x04, 0xbe, 0x4b, 0xce, 0x97, 0xbe, 0xc3, 0x67, 0x2a, 0x68, +0x11, 0xdf, 0x80, 0xe7, 0x0c, 0x33, 0x66, 0xbf, 0x13, 0x0d, 0x14, 0x6e, 0xf3, 0x7f, 0x1f, 0x63, +0x10, 0x1e, 0xfa, 0x8d, 0x1b, 0x25, 0x6d, 0x6c, 0x8f, 0xa5, 0xb7, 0x61, 0x01, 0xb1, 0xd2, 0xa3, +0x26, 0xa1, 0x10, 0x71, 0x9d, 0xad, 0xe2, 0xc3, 0xf9, 0xc3, 0x99, 0x51, 0xb7, 0x2b, 0x07, 0x08, +0xce, 0x2e, 0xe6, 0x50, 0xb2, 0xa7, 0xfa, 0x0a, 0x45, 0x2f, 0xa2, 0xf0, 0xf2, 0x30, 0x82, 0x03, +0x96, 0x30, 0x82, 0x02, 0x7e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x0b, 0x93, 0x1c, 0x3a, +0xd6, 0x39, 0x67, 0xea, 0x67, 0x23, 0xbf, 0xc3, 0xaf, 0x9a, 0xf4, 0x4b, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x65, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, +0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, +0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x24, 0x30, 0x22, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, +0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, +0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, +0x30, 0x5a, 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, +0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, +0x63, 0x6f, 0x6d, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x44, 0x69, +0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, +0x44, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, +0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd9, 0xe7, 0x28, 0x2f, 0x52, 0x3f, +0x36, 0x72, 0x49, 0x88, 0x93, 0x34, 0xf3, 0xf8, 0x6a, 0x1e, 0x31, 0x54, 0x80, 0x9f, 0xad, 0x54, +0x41, 0xb5, 0x47, 0xdf, 0x96, 0xa8, 0xd4, 0xaf, 0x80, 0x2d, 0xb9, 0x0a, 0xcf, 0x75, 0xfd, 0x89, +0xa5, 0x7d, 0x24, 0xfa, 0xe3, 0x22, 0x0c, 0x2b, 0xbc, 0x95, 0x17, 0x0b, 0x33, 0xbf, 0x19, 0x4d, +0x41, 0x06, 0x90, 0x00, 0xbd, 0x0c, 0x4d, 0x10, 0xfe, 0x07, 0xb5, 0xe7, 0x1c, 0x6e, 0x22, 0x55, +0x31, 0x65, 0x97, 0xbd, 0xd3, 0x17, 0xd2, 0x1e, 0x62, 0xf3, 0xdb, 0xea, 0x6c, 0x50, 0x8c, 0x3f, +0x84, 0x0c, 0x96, 0xcf, 0xb7, 0xcb, 0x03, 0xe0, 0xca, 0x6d, 0xa1, 0x14, 0x4c, 0x1b, 0x89, 0xdd, +0xed, 0x00, 0xb0, 0x52, 0x7c, 0xaf, 0x91, 0x6c, 0xb1, 0x38, 0x13, 0xd1, 0xe9, 0x12, 0x08, 0xc0, +0x00, 0xb0, 0x1c, 0x2b, 0x11, 0xda, 0x77, 0x70, 0x36, 0x9b, 0xae, 0xce, 0x79, 0x87, 0xdc, 0x82, +0x70, 0xe6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xaf, 0xa3, 0x68, 0x9f, 0xbf, 0xdd, 0xb6, 0x79, 0xb3, +0xf2, 0x9d, 0x70, 0x29, 0x55, 0xf4, 0xab, 0xff, 0x95, 0x61, 0xf3, 0xc9, 0x40, 0x6f, 0x1d, 0xd1, +0xbe, 0x93, 0xbb, 0xd3, 0x88, 0x2a, 0xbb, 0x9d, 0xbf, 0x72, 0x5a, 0x56, 0x71, 0x3b, 0x3f, 0xd4, +0xf3, 0xd1, 0x0a, 0xfe, 0x28, 0xef, 0xa3, 0xee, 0xd9, 0x99, 0xaf, 0x03, 0xd3, 0x8f, 0x60, 0xb7, +0xf2, 0x92, 0xa1, 0xb1, 0xbd, 0x89, 0x89, 0x1f, 0x30, 0xcd, 0xc3, 0xa6, 0x2e, 0x62, 0x33, 0xae, +0x16, 0x02, 0x77, 0x44, 0x5a, 0xe7, 0x81, 0x0a, 0x3c, 0xa7, 0x44, 0x2e, 0x79, 0xb8, 0x3f, 0x04, +0xbc, 0x5c, 0xa0, 0x87, 0xe1, 0x1b, 0xaf, 0x51, 0x8e, 0xcd, 0xec, 0x2c, 0xfa, 0xf8, 0xfe, 0x6d, +0xf0, 0x3a, 0x7c, 0xaa, 0x8b, 0xe4, 0x67, 0x95, 0x31, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xce, +0xc3, 0x4a, 0xb9, 0x99, 0x55, 0xf2, 0xb8, 0xdb, 0x60, 0xbf, 0xa9, 0x7e, 0xbd, 0x56, 0xb5, 0x97, +0x36, 0xa7, 0xd6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, +0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xca, 0xa5, 0x55, 0x8c, 0xe3, 0xc8, 0x41, 0x6e, 0x69, +0x27, 0xa7, 0x75, 0x11, 0xef, 0x3c, 0x86, 0x36, 0x6f, 0xd2, 0x9d, 0xc6, 0x78, 0x38, 0x1d, 0x69, +0x96, 0xa2, 0x92, 0x69, 0x2e, 0x38, 0x6c, 0x9b, 0x7d, 0x04, 0xd4, 0x89, 0xa5, 0xb1, 0x31, 0x37, +0x8a, 0xc9, 0x21, 0xcc, 0xab, 0x6c, 0xcd, 0x8b, 0x1c, 0x9a, 0xd6, 0xbf, 0x48, 0xd2, 0x32, 0x66, +0xc1, 0x8a, 0xc0, 0xf3, 0x2f, 0x3a, 0xef, 0xc0, 0xe3, 0xd4, 0x91, 0x86, 0xd1, 0x50, 0xe3, 0x03, +0xdb, 0x73, 0x77, 0x6f, 0x4a, 0x39, 0x53, 0xed, 0xde, 0x26, 0xc7, 0xb5, 0x7d, 0xaf, 0x2b, 0x42, +0xd1, 0x75, 0x62, 0xe3, 0x4a, 0x2b, 0x02, 0xc7, 0x50, 0x4b, 0xe0, 0x69, 0xe2, 0x96, 0x6c, 0x0e, +0x44, 0x66, 0x10, 0x44, 0x8f, 0xad, 0x05, 0xeb, 0xf8, 0x79, 0xac, 0xa6, 0x1b, 0xe8, 0x37, 0x34, +0x9d, 0x53, 0xc9, 0x61, 0xaa, 0xa2, 0x52, 0xaf, 0x4a, 0x70, 0x16, 0x86, 0xc2, 0x3a, 0xc8, 0xb1, +0x13, 0x70, 0x36, 0xd8, 0xcf, 0xee, 0xf4, 0x0a, 0x34, 0xd5, 0x5b, 0x4c, 0xfd, 0x07, 0x9c, 0xa2, +0xba, 0xd9, 0x01, 0x72, 0x5c, 0xf3, 0x4d, 0xc1, 0xdd, 0x0e, 0xb1, 0x1c, 0x0d, 0xc4, 0x63, 0xbe, +0xad, 0xf4, 0x14, 0xfb, 0x89, 0xec, 0xa2, 0x41, 0x0e, 0x4c, 0xcc, 0xc8, 0x57, 0x40, 0xd0, 0x6e, +0x03, 0xaa, 0xcd, 0x0c, 0x8e, 0x89, 0x99, 0x99, 0x6c, 0xf0, 0x3c, 0x30, 0xaf, 0x38, 0xdf, 0x6f, +0xbc, 0xa3, 0xbe, 0x29, 0x20, 0x27, 0xab, 0x74, 0xff, 0x13, 0x22, 0x78, 0xde, 0x97, 0x52, 0x55, +0x1e, 0x83, 0xb5, 0x54, 0x20, 0x03, 0xee, 0xae, 0xc0, 0x4f, 0x56, 0xde, 0x37, 0xcc, 0xc3, 0x7f, +0xaa, 0x04, 0x27, 0xbb, 0xd3, 0x77, 0xb8, 0x62, 0xdb, 0x17, 0x7c, 0x9c, 0x28, 0x22, 0x13, 0x73, +0x6c, 0xcf, 0x26, 0xf5, 0x8a, 0x29, 0xe7, 0x30, 0x82, 0x03, 0xaf, 0x30, 0x82, 0x02, 0x97, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x08, 0x3b, 0xe0, 0x56, 0x90, 0x42, 0x46, 0xb1, 0xa1, 0x75, +0x6a, 0xc9, 0x59, 0x91, 0xc7, 0x4a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, +0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, +0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, +0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, +0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x31, 0x31, 0x31, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, +0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, +0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, +0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x3b, 0xe1, 0x11, +0x72, 0xde, 0xa8, 0xa4, 0xd3, 0xa3, 0x57, 0xaa, 0x50, 0xa2, 0x8f, 0x0b, 0x77, 0x90, 0xc9, 0xa2, +0xa5, 0xee, 0x12, 0xce, 0x96, 0x5b, 0x01, 0x09, 0x20, 0xcc, 0x01, 0x93, 0xa7, 0x4e, 0x30, 0xb7, +0x53, 0xf7, 0x43, 0xc4, 0x69, 0x00, 0x57, 0x9d, 0xe2, 0x8d, 0x22, 0xdd, 0x87, 0x06, 0x40, 0x00, +0x81, 0x09, 0xce, 0xce, 0x1b, 0x83, 0xbf, 0xdf, 0xcd, 0x3b, 0x71, 0x46, 0xe2, 0xd6, 0x66, 0xc7, +0x05, 0xb3, 0x76, 0x27, 0x16, 0x8f, 0x7b, 0x9e, 0x1e, 0x95, 0x7d, 0xee, 0xb7, 0x48, 0xa3, 0x08, +0xda, 0xd6, 0xaf, 0x7a, 0x0c, 0x39, 0x06, 0x65, 0x7f, 0x4a, 0x5d, 0x1f, 0xbc, 0x17, 0xf8, 0xab, +0xbe, 0xee, 0x28, 0xd7, 0x74, 0x7f, 0x7a, 0x78, 0x99, 0x59, 0x85, 0x68, 0x6e, 0x5c, 0x23, 0x32, +0x4b, 0xbf, 0x4e, 0xc0, 0xe8, 0x5a, 0x6d, 0xe3, 0x70, 0xbf, 0x77, 0x10, 0xbf, 0xfc, 0x01, 0xf6, +0x85, 0xd9, 0xa8, 0x44, 0x10, 0x58, 0x32, 0xa9, 0x75, 0x18, 0xd5, 0xd1, 0xa2, 0xbe, 0x47, 0xe2, +0x27, 0x6a, 0xf4, 0x9a, 0x33, 0xf8, 0x49, 0x08, 0x60, 0x8b, 0xd4, 0x5f, 0xb4, 0x3a, 0x84, 0xbf, +0xa1, 0xaa, 0x4a, 0x4c, 0x7d, 0x3e, 0xcf, 0x4f, 0x5f, 0x6c, 0x76, 0x5e, 0xa0, 0x4b, 0x37, 0x91, +0x9e, 0xdc, 0x22, 0xe6, 0x6d, 0xce, 0x14, 0x1a, 0x8e, 0x6a, 0xcb, 0xfe, 0xcd, 0xb3, 0x14, 0x64, +0x17, 0xc7, 0x5b, 0x29, 0x9e, 0x32, 0xbf, 0xf2, 0xee, 0xfa, 0xd3, 0x0b, 0x42, 0xd4, 0xab, 0xb7, +0x41, 0x32, 0xda, 0x0c, 0xd4, 0xef, 0xf8, 0x81, 0xd5, 0xbb, 0x8d, 0x58, 0x3f, 0xb5, 0x1b, 0xe8, +0x49, 0x28, 0xa2, 0x70, 0xda, 0x31, 0x04, 0xdd, 0xf7, 0xb2, 0x16, 0xf2, 0x4c, 0x0a, 0x4e, 0x07, +0xa8, 0xed, 0x4a, 0x3d, 0x5e, 0xb5, 0x7f, 0xa3, 0x90, 0xc3, 0xaf, 0x27, 0x02, 0x03, 0x01, 0x00, +0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0x03, 0xde, 0x50, 0x35, 0x56, 0xd1, 0x4c, 0xbb, 0x66, 0xf0, 0xa3, 0xe2, 0x1b, 0x1b, 0xc3, +0x97, 0xb2, 0x3d, 0xd1, 0x55, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, +0x80, 0x14, 0x03, 0xde, 0x50, 0x35, 0x56, 0xd1, 0x4c, 0xbb, 0x66, 0xf0, 0xa3, 0xe2, 0x1b, 0x1b, +0xc3, 0x97, 0xb2, 0x3d, 0xd1, 0x55, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xcb, 0x9c, 0x37, 0xaa, 0x48, 0x13, +0x12, 0x0a, 0xfa, 0xdd, 0x44, 0x9c, 0x4f, 0x52, 0xb0, 0xf4, 0xdf, 0xae, 0x04, 0xf5, 0x79, 0x79, +0x08, 0xa3, 0x24, 0x18, 0xfc, 0x4b, 0x2b, 0x84, 0xc0, 0x2d, 0xb9, 0xd5, 0xc7, 0xfe, 0xf4, 0xc1, +0x1f, 0x58, 0xcb, 0xb8, 0x6d, 0x9c, 0x7a, 0x74, 0xe7, 0x98, 0x29, 0xab, 0x11, 0xb5, 0xe3, 0x70, +0xa0, 0xa1, 0xcd, 0x4c, 0x88, 0x99, 0x93, 0x8c, 0x91, 0x70, 0xe2, 0xab, 0x0f, 0x1c, 0xbe, 0x93, +0xa9, 0xff, 0x63, 0xd5, 0xe4, 0x07, 0x60, 0xd3, 0xa3, 0xbf, 0x9d, 0x5b, 0x09, 0xf1, 0xd5, 0x8e, +0xe3, 0x53, 0xf4, 0x8e, 0x63, 0xfa, 0x3f, 0xa7, 0xdb, 0xb4, 0x66, 0xdf, 0x62, 0x66, 0xd6, 0xd1, +0x6e, 0x41, 0x8d, 0xf2, 0x2d, 0xb5, 0xea, 0x77, 0x4a, 0x9f, 0x9d, 0x58, 0xe2, 0x2b, 0x59, 0xc0, +0x40, 0x23, 0xed, 0x2d, 0x28, 0x82, 0x45, 0x3e, 0x79, 0x54, 0x92, 0x26, 0x98, 0xe0, 0x80, 0x48, +0xa8, 0x37, 0xef, 0xf0, 0xd6, 0x79, 0x60, 0x16, 0xde, 0xac, 0xe8, 0x0e, 0xcd, 0x6e, 0xac, 0x44, +0x17, 0x38, 0x2f, 0x49, 0xda, 0xe1, 0x45, 0x3e, 0x2a, 0xb9, 0x36, 0x53, 0xcf, 0x3a, 0x50, 0x06, +0xf7, 0x2e, 0xe8, 0xc4, 0x57, 0x49, 0x6c, 0x61, 0x21, 0x18, 0xd5, 0x04, 0xad, 0x78, 0x3c, 0x2c, +0x3a, 0x80, 0x6b, 0xa7, 0xeb, 0xaf, 0x15, 0x14, 0xe9, 0xd8, 0x89, 0xc1, 0xb9, 0x38, 0x6c, 0xe2, +0x91, 0x6c, 0x8a, 0xff, 0x64, 0xb9, 0x77, 0x25, 0x57, 0x30, 0xc0, 0x1b, 0x24, 0xa3, 0xe1, 0xdc, +0xe9, 0xdf, 0x47, 0x7c, 0xb5, 0xb4, 0x24, 0x08, 0x05, 0x30, 0xec, 0x2d, 0xbd, 0x0b, 0xbf, 0x45, +0xbf, 0x50, 0xb9, 0xa9, 0xf3, 0xeb, 0x98, 0x01, 0x12, 0xad, 0xc8, 0x88, 0xc6, 0x98, 0x34, 0x5f, +0x8d, 0x0a, 0x3c, 0xc6, 0xe9, 0xd5, 0x95, 0x95, 0x6d, 0xde, 0x30, 0x82, 0x03, 0x8e, 0x30, 0x82, +0x02, 0x76, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x03, 0x3a, 0xf1, 0xe6, 0xa7, 0x11, 0xa9, +0xa0, 0xbb, 0x28, 0x64, 0xb1, 0x1d, 0x09, 0xfa, 0xe5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, +0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, +0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x33, 0x30, 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, +0x30, 0x31, 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x61, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, +0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, +0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, +0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x32, 0x30, 0x82, +0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, +0x37, 0xcd, 0x34, 0xdc, 0x7b, 0x6b, 0xc9, 0xb2, 0x68, 0x90, 0xad, 0x4a, 0x75, 0xff, 0x46, 0xba, +0x21, 0x0a, 0x08, 0x8d, 0xf5, 0x19, 0x54, 0xc9, 0xfb, 0x88, 0xdb, 0xf3, 0xae, 0xf2, 0x3a, 0x89, +0x91, 0x3c, 0x7a, 0xe6, 0xab, 0x06, 0x1a, 0x6b, 0xcf, 0xac, 0x2d, 0xe8, 0x5e, 0x09, 0x24, 0x44, +0xba, 0x62, 0x9a, 0x7e, 0xd6, 0xa3, 0xa8, 0x7e, 0xe0, 0x54, 0x75, 0x20, 0x05, 0xac, 0x50, 0xb7, +0x9c, 0x63, 0x1a, 0x6c, 0x30, 0xdc, 0xda, 0x1f, 0x19, 0xb1, 0xd7, 0x1e, 0xde, 0xfd, 0xd7, 0xe0, +0xcb, 0x94, 0x83, 0x37, 0xae, 0xec, 0x1f, 0x43, 0x4e, 0xdd, 0x7b, 0x2c, 0xd2, 0xbd, 0x2e, 0xa5, +0x2f, 0xe4, 0xa9, 0xb8, 0xad, 0x3a, 0xd4, 0x99, 0xa4, 0xb6, 0x25, 0xe9, 0x9b, 0x6b, 0x00, 0x60, +0x92, 0x60, 0xff, 0x4f, 0x21, 0x49, 0x18, 0xf7, 0x67, 0x90, 0xab, 0x61, 0x06, 0x9c, 0x8f, 0xf2, +0xba, 0xe9, 0xb4, 0xe9, 0x92, 0x32, 0x6b, 0xb5, 0xf3, 0x57, 0xe8, 0x5d, 0x1b, 0xcd, 0x8c, 0x1d, +0xab, 0x95, 0x04, 0x95, 0x49, 0xf3, 0x35, 0x2d, 0x96, 0xe3, 0x49, 0x6d, 0xdd, 0x77, 0xe3, 0xfb, +0x49, 0x4b, 0xb4, 0xac, 0x55, 0x07, 0xa9, 0x8f, 0x95, 0xb3, 0xb4, 0x23, 0xbb, 0x4c, 0x6d, 0x45, +0xf0, 0xf6, 0xa9, 0xb2, 0x95, 0x30, 0xb4, 0xfd, 0x4c, 0x55, 0x8c, 0x27, 0x4a, 0x57, 0x14, 0x7c, +0x82, 0x9d, 0xcd, 0x73, 0x92, 0xd3, 0x16, 0x4a, 0x06, 0x0c, 0x8c, 0x50, 0xd1, 0x8f, 0x1e, 0x09, +0xbe, 0x17, 0xa1, 0xe6, 0x21, 0xca, 0xfd, 0x83, 0xe5, 0x10, 0xbc, 0x83, 0xa5, 0x0a, 0xc4, 0x67, +0x28, 0xf6, 0x73, 0x14, 0x14, 0x3d, 0x46, 0x76, 0xc3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4d, 0xaf, +0x0f, 0x45, 0x0c, 0xa6, 0x49, 0xa1, 0xba, 0xbb, 0x9c, 0xc5, 0xb1, 0x33, 0x83, 0x29, 0x85, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, +0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, +0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, +0x04, 0x16, 0x04, 0x14, 0x4e, 0x22, 0x54, 0x20, 0x18, 0x95, 0xe6, 0xe3, 0x6e, 0xe6, 0x0f, 0xfa, +0xfa, 0xb9, 0x12, 0xed, 0x06, 0x17, 0x8f, 0x39, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x60, 0x67, 0x28, 0x94, +0x6f, 0x0e, 0x48, 0x63, 0xeb, 0x31, 0xdd, 0xea, 0x67, 0x18, 0xd5, 0x89, 0x7d, 0x3c, 0xc5, 0x8b, +0x4a, 0x7f, 0xe9, 0xbe, 0xdb, 0x2b, 0x17, 0xdf, 0xb0, 0x5f, 0x73, 0x77, 0x2a, 0x32, 0x13, 0x39, +0x81, 0x67, 0x42, 0x84, 0x23, 0xf2, 0x45, 0x67, 0x35, 0xec, 0x88, 0xbf, 0xf8, 0x8f, 0xb0, 0x61, +0x0c, 0x34, 0xa4, 0xae, 0x20, 0x4c, 0x84, 0xc6, 0xdb, 0xf8, 0x35, 0xe1, 0x76, 0xd9, 0xdf, 0xa6, +0x42, 0xbb, 0xc7, 0x44, 0x08, 0x86, 0x7f, 0x36, 0x74, 0x24, 0x5a, 0xda, 0x6c, 0x0d, 0x14, 0x59, +0x35, 0xbd, 0xf2, 0x49, 0xdd, 0xb6, 0x1f, 0xc9, 0xb3, 0x0d, 0x47, 0x2a, 0x3d, 0x99, 0x2f, 0xbb, +0x5c, 0xbb, 0xb5, 0xd4, 0x20, 0xe1, 0x99, 0x5f, 0x53, 0x46, 0x15, 0xdb, 0x68, 0x9b, 0xf0, 0xf3, +0x30, 0xd5, 0x3e, 0x31, 0xe2, 0x8d, 0x84, 0x9e, 0xe3, 0x8a, 0xda, 0xda, 0x96, 0x3e, 0x35, 0x13, +0xa5, 0x5f, 0xf0, 0xf9, 0x70, 0x50, 0x70, 0x47, 0x41, 0x11, 0x57, 0x19, 0x4e, 0xc0, 0x8f, 0xae, +0x06, 0xc4, 0x95, 0x13, 0x17, 0x2f, 0x1b, 0x25, 0x9f, 0x75, 0xf2, 0xb1, 0x8e, 0x99, 0xa1, 0x6f, +0x13, 0xb1, 0x41, 0x71, 0xfe, 0x88, 0x2a, 0xc8, 0x4f, 0x10, 0x20, 0x55, 0xd7, 0xf3, 0x14, 0x45, +0xe5, 0xe0, 0x44, 0xf4, 0xea, 0x87, 0x95, 0x32, 0x93, 0x0e, 0xfe, 0x53, 0x46, 0xfa, 0x2c, 0x9d, +0xff, 0x8b, 0x22, 0xb9, 0x4b, 0xd9, 0x09, 0x45, 0xa4, 0xde, 0xa4, 0xb8, 0x9a, 0x58, 0xdd, 0x1b, +0x7d, 0x52, 0x9f, 0x8e, 0x59, 0x43, 0x88, 0x81, 0xa4, 0x9e, 0x26, 0xd5, 0x6f, 0xad, 0xdd, 0x0d, +0xc6, 0x37, 0x7d, 0xed, 0x03, 0x92, 0x1b, 0xe5, 0x77, 0x5f, 0x76, 0xee, 0x3c, 0x8d, 0xc4, 0x5d, +0x56, 0x5b, 0xa2, 0xd9, 0x66, 0x6e, 0xb3, 0x35, 0x37, 0xe5, 0x32, 0xb6, 0x30, 0x82, 0x02, 0x3f, +0x30, 0x82, 0x01, 0xc5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x05, 0x55, 0x56, 0xbc, 0xf2, +0x5e, 0xa4, 0x35, 0x35, 0xc3, 0xa4, 0x0f, 0xd5, 0xab, 0x45, 0x72, 0x30, 0x0a, 0x06, 0x08, 0x2a, +0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, +0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, +0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, +0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, +0x30, 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, +0x31, 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, +0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, +0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, +0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x33, 0x30, 0x76, 0x30, +0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, +0x22, 0x03, 0x62, 0x00, 0x04, 0xdd, 0xa7, 0xd9, 0xbb, 0x8a, 0xb8, 0x0b, 0xfb, 0x0b, 0x7f, 0x21, +0xd2, 0xf0, 0xbe, 0xbe, 0x73, 0xf3, 0x33, 0x5d, 0x1a, 0xbc, 0x34, 0xea, 0xde, 0xc6, 0x9b, 0xbc, +0xd0, 0x95, 0xf6, 0xf0, 0xcc, 0xd0, 0x0b, 0xba, 0x61, 0x5b, 0x51, 0x46, 0x7e, 0x9e, 0x2d, 0x9f, +0xee, 0x8e, 0x63, 0x0c, 0x17, 0xec, 0x07, 0x70, 0xf5, 0xcf, 0x84, 0x2e, 0x40, 0x83, 0x9c, 0xe8, +0x3f, 0x41, 0x6d, 0x3b, 0xad, 0xd3, 0xa4, 0x14, 0x59, 0x36, 0x78, 0x9d, 0x03, 0x43, 0xee, 0x10, +0x13, 0x6c, 0x72, 0xde, 0xae, 0x88, 0xa7, 0xa1, 0x6b, 0xb5, 0x43, 0xce, 0x67, 0xdc, 0x23, 0xff, +0x03, 0x1c, 0xa3, 0xe2, 0x3e, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, +0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0xb3, 0xdb, 0x48, 0xa4, 0xf9, 0xa1, 0xc5, 0xd8, 0xae, 0x36, 0x41, +0xcc, 0x11, 0x63, 0x69, 0x62, 0x29, 0xbc, 0x4b, 0xc6, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xad, 0xbc, 0xf2, +0x6c, 0x3f, 0x12, 0x4a, 0xd1, 0x2d, 0x39, 0xc3, 0x0a, 0x09, 0x97, 0x73, 0xf4, 0x88, 0x36, 0x8c, +0x88, 0x27, 0xbb, 0xe6, 0x88, 0x8d, 0x50, 0x85, 0xa7, 0x63, 0xf9, 0x9e, 0x32, 0xde, 0x66, 0x93, +0x0f, 0xf1, 0xcc, 0xb1, 0x09, 0x8f, 0xdd, 0x6c, 0xab, 0xfa, 0x6b, 0x7f, 0xa0, 0x02, 0x30, 0x39, +0x66, 0x5b, 0xc2, 0x64, 0x8d, 0xb8, 0x9e, 0x50, 0xdc, 0xa8, 0xd5, 0x49, 0xa2, 0xed, 0xc7, 0xdc, +0xd1, 0x49, 0x7f, 0x17, 0x01, 0xb8, 0xc8, 0x86, 0x8f, 0x4e, 0x8c, 0x88, 0x2b, 0xa8, 0x9a, 0xa9, +0x8a, 0xc5, 0xd1, 0x00, 0xbd, 0xf8, 0x54, 0xe2, 0x9a, 0xe5, 0x5b, 0x7c, 0xb3, 0x27, 0x17, 0x30, +0x82, 0x03, 0xc5, 0x30, 0x82, 0x02, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x02, 0xac, +0x5c, 0x26, 0x6a, 0x0b, 0x40, 0x9b, 0x8f, 0x0b, 0x79, 0xf2, 0xae, 0x46, 0x25, 0x77, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x6c, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, +0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, +0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x2b, +0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, +0x74, 0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6e, 0x63, 0x65, +0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, +0x36, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, +0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6c, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, +0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, +0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x2b, 0x30, 0x29, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, +0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x45, +0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, +0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc6, 0xcc, 0xe5, 0x73, 0xe6, 0xfb, +0xd4, 0xbb, 0xe5, 0x2d, 0x2d, 0x32, 0xa6, 0xdf, 0xe5, 0x81, 0x3f, 0xc9, 0xcd, 0x25, 0x49, 0xb6, +0x71, 0x2a, 0xc3, 0xd5, 0x94, 0x34, 0x67, 0xa2, 0x0a, 0x1c, 0xb0, 0x5f, 0x69, 0xa6, 0x40, 0xb1, +0xc4, 0xb7, 0xb2, 0x8f, 0xd0, 0x98, 0xa4, 0xa9, 0x41, 0x59, 0x3a, 0xd3, 0xdc, 0x94, 0xd6, 0x3c, +0xdb, 0x74, 0x38, 0xa4, 0x4a, 0xcc, 0x4d, 0x25, 0x82, 0xf7, 0x4a, 0xa5, 0x53, 0x12, 0x38, 0xee, +0xf3, 0x49, 0x6d, 0x71, 0x91, 0x7e, 0x63, 0xb6, 0xab, 0xa6, 0x5f, 0xc3, 0xa4, 0x84, 0xf8, 0x4f, +0x62, 0x51, 0xbe, 0xf8, 0xc5, 0xec, 0xdb, 0x38, 0x92, 0xe3, 0x06, 0xe5, 0x08, 0x91, 0x0c, 0xc4, +0x28, 0x41, 0x55, 0xfb, 0xcb, 0x5a, 0x89, 0x15, 0x7e, 0x71, 0xe8, 0x35, 0xbf, 0x4d, 0x72, 0x09, +0x3d, 0xbe, 0x3a, 0x38, 0x50, 0x5b, 0x77, 0x31, 0x1b, 0x8d, 0xb3, 0xc7, 0x24, 0x45, 0x9a, 0xa7, +0xac, 0x6d, 0x00, 0x14, 0x5a, 0x04, 0xb7, 0xba, 0x13, 0xeb, 0x51, 0x0a, 0x98, 0x41, 0x41, 0x22, +0x4e, 0x65, 0x61, 0x87, 0x81, 0x41, 0x50, 0xa6, 0x79, 0x5c, 0x89, 0xde, 0x19, 0x4a, 0x57, 0xd5, +0x2e, 0xe6, 0x5d, 0x1c, 0x53, 0x2c, 0x7e, 0x98, 0xcd, 0x1a, 0x06, 0x16, 0xa4, 0x68, 0x73, 0xd0, +0x34, 0x04, 0x13, 0x5c, 0xa1, 0x71, 0xd3, 0x5a, 0x7c, 0x55, 0xdb, 0x5e, 0x64, 0xe1, 0x37, 0x87, +0x30, 0x56, 0x04, 0xe5, 0x11, 0xb4, 0x29, 0x80, 0x12, 0xf1, 0x79, 0x39, 0x88, 0xa2, 0x02, 0x11, +0x7c, 0x27, 0x66, 0xb7, 0x88, 0xb7, 0x78, 0xf2, 0xca, 0x0a, 0xa8, 0x38, 0xab, 0x0a, 0x64, 0xc2, +0xbf, 0x66, 0x5d, 0x95, 0x84, 0xc1, 0xa1, 0x25, 0x1e, 0x87, 0x5d, 0x1a, 0x50, 0x0b, 0x20, 0x12, +0xcc, 0x41, 0xbb, 0x6e, 0x0b, 0x51, 0x38, 0xb8, 0x4b, 0xcb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x63, 0x30, 0x61, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, +0x3e, 0xc3, 0x69, 0x03, 0xf8, 0xbf, 0x47, 0x01, 0xd4, 0x98, 0x26, 0x1a, 0x08, 0x02, 0xef, 0x63, +0x64, 0x2b, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, +0xb1, 0x3e, 0xc3, 0x69, 0x03, 0xf8, 0xbf, 0x47, 0x01, 0xd4, 0x98, 0x26, 0x1a, 0x08, 0x02, 0xef, +0x63, 0x64, 0x2b, 0xc3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x1c, 0x1a, 0x06, 0x97, 0xdc, 0xd7, 0x9c, 0x9f, +0x3c, 0x88, 0x66, 0x06, 0x08, 0x57, 0x21, 0xdb, 0x21, 0x47, 0xf8, 0x2a, 0x67, 0xaa, 0xbf, 0x18, +0x32, 0x76, 0x40, 0x10, 0x57, 0xc1, 0x8a, 0xf3, 0x7a, 0xd9, 0x11, 0x65, 0x8e, 0x35, 0xfa, 0x9e, +0xfc, 0x45, 0xb5, 0x9e, 0xd9, 0x4c, 0x31, 0x4b, 0xb8, 0x91, 0xe8, 0x43, 0x2c, 0x8e, 0xb3, 0x78, +0xce, 0xdb, 0xe3, 0x53, 0x79, 0x71, 0xd6, 0xe5, 0x21, 0x94, 0x01, 0xda, 0x55, 0x87, 0x9a, 0x24, +0x64, 0xf6, 0x8a, 0x66, 0xcc, 0xde, 0x9c, 0x37, 0xcd, 0xa8, 0x34, 0xb1, 0x69, 0x9b, 0x23, 0xc8, +0x9e, 0x78, 0x22, 0x2b, 0x70, 0x43, 0xe3, 0x55, 0x47, 0x31, 0x61, 0x19, 0xef, 0x58, 0xc5, 0x85, +0x2f, 0x4e, 0x30, 0xf6, 0xa0, 0x31, 0x16, 0x23, 0xc8, 0xe7, 0xe2, 0x65, 0x16, 0x33, 0xcb, 0xbf, +0x1a, 0x1b, 0xa0, 0x3d, 0xf8, 0xca, 0x5e, 0x8b, 0x31, 0x8b, 0x60, 0x08, 0x89, 0x2d, 0x0c, 0x06, +0x5c, 0x52, 0xb7, 0xc4, 0xf9, 0x0a, 0x98, 0xd1, 0x15, 0x5f, 0x9f, 0x12, 0xbe, 0x7c, 0x36, 0x63, +0x38, 0xbd, 0x44, 0xa4, 0x7f, 0xe4, 0x26, 0x2b, 0x0a, 0xc4, 0x97, 0x69, 0x0d, 0xe9, 0x8c, 0xe2, +0xc0, 0x10, 0x57, 0xb8, 0xc8, 0x76, 0x12, 0x91, 0x55, 0xf2, 0x48, 0x69, 0xd8, 0xbc, 0x2a, 0x02, +0x5b, 0x0f, 0x44, 0xd4, 0x20, 0x31, 0xdb, 0xf4, 0xba, 0x70, 0x26, 0x5d, 0x90, 0x60, 0x9e, 0xbc, +0x4b, 0x17, 0x09, 0x2f, 0xb4, 0xcb, 0x1e, 0x43, 0x68, 0xc9, 0x07, 0x27, 0xc1, 0xd2, 0x5c, 0xf7, +0xea, 0x21, 0xb9, 0x68, 0x12, 0x9c, 0x3c, 0x9c, 0xbf, 0x9e, 0xfc, 0x80, 0x5c, 0x9b, 0x63, 0xcd, +0xec, 0x47, 0xaa, 0x25, 0x27, 0x67, 0xa0, 0x37, 0xf3, 0x00, 0x82, 0x7d, 0x54, 0xd7, 0xa9, 0xf8, +0xe9, 0x2e, 0x13, 0xa3, 0x77, 0xe8, 0x1f, 0x4a, 0x30, 0x82, 0x05, 0x90, 0x30, 0x82, 0x03, 0x78, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x05, 0x9b, 0x1b, 0x57, 0x9e, 0x8e, 0x21, 0x32, 0xe2, +0x39, 0x07, 0xbd, 0xa7, 0x77, 0x75, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, +0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, +0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, +0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, +0x65, 0x64, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x34, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, +0x30, 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, +0x31, 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, +0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, +0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x54, +0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x34, 0x30, 0x82, +0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xbf, +0xe6, 0x90, 0x73, 0x68, 0xde, 0xbb, 0xe4, 0x5d, 0x4a, 0x3c, 0x30, 0x22, 0x30, 0x69, 0x33, 0xec, +0xc2, 0xa7, 0x25, 0x2e, 0xc9, 0x21, 0x3d, 0xf2, 0x8a, 0xd8, 0x59, 0xc2, 0xe1, 0x29, 0xa7, 0x3d, +0x58, 0xab, 0x76, 0x9a, 0xcd, 0xae, 0x7b, 0x1b, 0x84, 0x0d, 0xc4, 0x30, 0x1f, 0xf3, 0x1b, 0xa4, +0x38, 0x16, 0xeb, 0x56, 0xc6, 0x97, 0x6d, 0x1d, 0xab, 0xb2, 0x79, 0xf2, 0xca, 0x11, 0xd2, 0xe4, +0x5f, 0xd6, 0x05, 0x3c, 0x52, 0x0f, 0x52, 0x1f, 0xc6, 0x9e, 0x15, 0xa5, 0x7e, 0xbe, 0x9f, 0xa9, +0x57, 0x16, 0x59, 0x55, 0x72, 0xaf, 0x68, 0x93, 0x70, 0xc2, 0xb2, 0xba, 0x75, 0x99, 0x6a, 0x73, +0x32, 0x94, 0xd1, 0x10, 0x44, 0x10, 0x2e, 0xdf, 0x82, 0xf3, 0x07, 0x84, 0xe6, 0x74, 0x3b, 0x6d, +0x71, 0xe2, 0x2d, 0x0c, 0x1b, 0xee, 0x20, 0xd5, 0xc9, 0x20, 0x1d, 0x63, 0x29, 0x2d, 0xce, 0xec, +0x5e, 0x4e, 0xc8, 0x93, 0xf8, 0x21, 0x61, 0x9b, 0x34, 0xeb, 0x05, 0xc6, 0x5e, 0xec, 0x5b, 0x1a, +0xbc, 0xeb, 0xc9, 0xcf, 0xcd, 0xac, 0x34, 0x40, 0x5f, 0xb1, 0x7a, 0x66, 0xee, 0x77, 0xc8, 0x48, +0xa8, 0x66, 0x57, 0x57, 0x9f, 0x54, 0x58, 0x8e, 0x0c, 0x2b, 0xb7, 0x4f, 0xa7, 0x30, 0xd9, 0x56, +0xee, 0xca, 0x7b, 0x5d, 0xe3, 0xad, 0xc9, 0x4f, 0x5e, 0xe5, 0x35, 0xe7, 0x31, 0xcb, 0xda, 0x93, +0x5e, 0xdc, 0x8e, 0x8f, 0x80, 0xda, 0xb6, 0x91, 0x98, 0x40, 0x90, 0x79, 0xc3, 0x78, 0xc7, 0xb6, +0xb1, 0xc4, 0xb5, 0x6a, 0x18, 0x38, 0x03, 0x10, 0x8d, 0xd8, 0xd4, 0x37, 0xa4, 0x2e, 0x05, 0x7d, +0x88, 0xf5, 0x82, 0x3e, 0x10, 0x91, 0x70, 0xab, 0x55, 0x82, 0x41, 0x32, 0xd7, 0xdb, 0x04, 0x73, +0x2a, 0x6e, 0x91, 0x01, 0x7c, 0x21, 0x4c, 0xd4, 0xbc, 0xae, 0x1b, 0x03, 0x75, 0x5d, 0x78, 0x66, +0xd9, 0x3a, 0x31, 0x44, 0x9a, 0x33, 0x40, 0xbf, 0x08, 0xd7, 0x5a, 0x49, 0xa4, 0xc2, 0xe6, 0xa9, +0xa0, 0x67, 0xdd, 0xa4, 0x27, 0xbc, 0xa1, 0x4f, 0x39, 0xb5, 0x11, 0x58, 0x17, 0xf7, 0x24, 0x5c, +0x46, 0x8f, 0x64, 0xf7, 0xc1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3d, 0x59, 0x5d, 0x42, 0x76, 0x87, +0x89, 0x97, 0x69, 0x7a, 0x48, 0xf0, 0xe0, 0xa2, 0x12, 0x1b, 0x66, 0x9a, 0x74, 0xca, 0xde, 0x4b, +0x1e, 0xe7, 0x0e, 0x63, 0xae, 0xe6, 0xd4, 0xef, 0x92, 0x92, 0x3a, 0x9e, 0x3d, 0xdc, 0x00, 0xe4, +0x45, 0x25, 0x89, 0xb6, 0x9a, 0x44, 0x19, 0x2b, 0x7e, 0xc0, 0x94, 0xb4, 0xd2, 0x61, 0x6d, 0xeb, +0x33, 0xd9, 0xc5, 0xdf, 0x4b, 0x04, 0x00, 0xcc, 0x7d, 0x1c, 0x95, 0xc3, 0x8f, 0xf7, 0x21, 0xb2, +0xb2, 0x11, 0xb7, 0xbb, 0x7f, 0xf2, 0xd5, 0x8c, 0x70, 0x2c, 0x41, 0x60, 0xaa, 0xb1, 0x63, 0x18, +0x44, 0x95, 0x1a, 0x76, 0x62, 0x7e, 0xf6, 0x80, 0xb0, 0xfb, 0xe8, 0x64, 0xa6, 0x33, 0xd1, 0x89, +0x07, 0xe1, 0xbd, 0xb7, 0xe6, 0x43, 0xa4, 0x18, 0xb8, 0xa6, 0x77, 0x01, 0xe1, 0x0f, 0x94, 0x0c, +0x21, 0x1d, 0xb2, 0x54, 0x29, 0x25, 0x89, 0x6c, 0xe5, 0x0e, 0x52, 0x51, 0x47, 0x74, 0xbe, 0x26, +0xac, 0xb6, 0x41, 0x75, 0xde, 0x7a, 0xac, 0x5f, 0x8d, 0x3f, 0xc9, 0xbc, 0xd3, 0x41, 0x11, 0x12, +0x5b, 0xe5, 0x10, 0x50, 0xeb, 0x31, 0xc5, 0xca, 0x72, 0x16, 0x22, 0x09, 0xdf, 0x7c, 0x4c, 0x75, +0x3f, 0x63, 0xec, 0x21, 0x5f, 0xc4, 0x20, 0x51, 0x6b, 0x6f, 0xb1, 0xab, 0x86, 0x8b, 0x4f, 0xc2, +0xd6, 0x45, 0x5f, 0x9d, 0x20, 0xfc, 0xa1, 0x1e, 0xc5, 0xc0, 0x8f, 0xa2, 0xb1, 0x7e, 0x0a, 0x26, +0x99, 0xf5, 0xe4, 0x69, 0x2f, 0x98, 0x1d, 0x2d, 0xf5, 0xd9, 0xa9, 0xb2, 0x1d, 0xe5, 0x1b, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, +0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, +0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, +0x04, 0x16, 0x04, 0x14, 0xec, 0xd7, 0xe3, 0x82, 0xd2, 0x71, 0x5d, 0x64, 0x4c, 0xdf, 0x2e, 0x67, +0x3f, 0xe7, 0xba, 0x98, 0xae, 0x1c, 0x0f, 0x4f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xbb, 0x61, 0xd9, 0x7d, +0xa9, 0x6c, 0xbe, 0x17, 0xc4, 0x91, 0x1b, 0xc3, 0xa1, 0xa2, 0x00, 0x8d, 0xe3, 0x64, 0x68, 0x0f, +0x56, 0xcf, 0x77, 0xae, 0x70, 0xf9, 0xfd, 0x9a, 0x4a, 0x99, 0xb9, 0xc9, 0x78, 0x5c, 0x0c, 0x0c, +0x5f, 0xe4, 0xe6, 0x14, 0x29, 0x56, 0x0b, 0x36, 0x49, 0x5d, 0x44, 0x63, 0xe0, 0xad, 0x9c, 0x96, +0x18, 0x66, 0x1b, 0x23, 0x0d, 0x3d, 0x79, 0xe9, 0x6d, 0x6b, 0xd6, 0x54, 0xf8, 0xd2, 0x3c, 0xc1, +0x43, 0x40, 0xae, 0x1d, 0x50, 0xf5, 0x52, 0xfc, 0x90, 0x3b, 0xbb, 0x98, 0x99, 0x69, 0x6b, 0xc7, +0xc1, 0xa7, 0xa8, 0x68, 0xa4, 0x27, 0xdc, 0x9d, 0xf9, 0x27, 0xae, 0x30, 0x85, 0xb9, 0xf6, 0x67, +0x4d, 0x3a, 0x3e, 0x8f, 0x59, 0x39, 0x22, 0x53, 0x44, 0xeb, 0xc8, 0x5d, 0x03, 0xca, 0xed, 0x50, +0x7a, 0x7d, 0x62, 0x21, 0x0a, 0x80, 0xc8, 0x73, 0x66, 0xd1, 0xa0, 0x05, 0x60, 0x5f, 0xe8, 0xa5, +0xb4, 0xa7, 0xaf, 0xa8, 0xf7, 0x6d, 0x35, 0x9c, 0x7c, 0x5a, 0x8a, 0xd6, 0xa2, 0x38, 0x99, 0xf3, +0x78, 0x8b, 0xf4, 0x4d, 0xd2, 0x20, 0x0b, 0xde, 0x04, 0xee, 0x8c, 0x9b, 0x47, 0x81, 0x72, 0x0d, +0xc0, 0x14, 0x32, 0xef, 0x30, 0x59, 0x2e, 0xae, 0xe0, 0x71, 0xf2, 0x56, 0xe4, 0x6a, 0x97, 0x6f, +0x92, 0x50, 0x6d, 0x96, 0x8d, 0x68, 0x7a, 0x9a, 0xb2, 0x36, 0x14, 0x7a, 0x06, 0xf2, 0x24, 0xb9, +0x09, 0x11, 0x50, 0xd7, 0x08, 0xb1, 0xb8, 0x89, 0x7a, 0x84, 0x23, 0x61, 0x42, 0x29, 0xe5, 0xa3, +0xcd, 0xa2, 0x20, 0x41, 0xd7, 0xd1, 0x9c, 0x64, 0xd9, 0xea, 0x26, 0xa1, 0x8b, 0x14, 0xd7, 0x4c, +0x19, 0xb2, 0x50, 0x41, 0x71, 0x3d, 0x3f, 0x4d, 0x70, 0x23, 0x86, 0x0c, 0x4a, 0xdc, 0x81, 0xd2, +0xcc, 0x32, 0x94, 0x84, 0x0d, 0x08, 0x09, 0x97, 0x1c, 0x4f, 0xc0, 0xee, 0x6b, 0x20, 0x74, 0x30, +0xd2, 0xe0, 0x39, 0x34, 0x10, 0x85, 0x21, 0x15, 0x01, 0x08, 0xe8, 0x55, 0x32, 0xde, 0x71, 0x49, +0xd9, 0x28, 0x17, 0x50, 0x4d, 0xe6, 0xbe, 0x4d, 0xd1, 0x75, 0xac, 0xd0, 0xca, 0xfb, 0x41, 0xb8, +0x43, 0xa5, 0xaa, 0xd3, 0xc3, 0x05, 0x44, 0x4f, 0x2c, 0x36, 0x9b, 0xe2, 0xfa, 0xe2, 0x45, 0xb8, +0x23, 0x53, 0x6c, 0x06, 0x6f, 0x67, 0x55, 0x7f, 0x46, 0xb5, 0x4c, 0x3f, 0x6e, 0x28, 0x5a, 0x79, +0x26, 0xd2, 0xa4, 0xa8, 0x62, 0x97, 0xd2, 0x1e, 0xe2, 0xed, 0x4a, 0x8b, 0xbc, 0x1b, 0xfd, 0x47, +0x4a, 0x0d, 0xdf, 0x67, 0x66, 0x7e, 0xb2, 0x5b, 0x41, 0xd0, 0x3b, 0xe4, 0xf4, 0x3b, 0xf4, 0x04, +0x63, 0xe9, 0xef, 0xc2, 0x54, 0x00, 0x51, 0xa0, 0x8a, 0x2a, 0xc9, 0xce, 0x78, 0xcc, 0xd5, 0xea, +0x87, 0x04, 0x18, 0xb3, 0xce, 0xaf, 0x49, 0x88, 0xaf, 0xf3, 0x92, 0x99, 0xb6, 0xb3, 0xe6, 0x61, +0x0f, 0xd2, 0x85, 0x00, 0xe7, 0x50, 0x1a, 0xe4, 0x1b, 0x95, 0x9d, 0x19, 0xa1, 0xb9, 0x9c, 0xb1, +0x9b, 0xb1, 0x00, 0x1e, 0xef, 0xd0, 0x0f, 0x4f, 0x42, 0x6c, 0xc9, 0x0a, 0xbc, 0xee, 0x43, 0xfa, +0x3a, 0x71, 0xa5, 0xc8, 0x4d, 0x26, 0xa5, 0x35, 0xfd, 0x89, 0x5d, 0xbc, 0x85, 0x62, 0x1d, 0x32, +0xd2, 0xa0, 0x2b, 0x54, 0xed, 0x9a, 0x57, 0xc1, 0xdb, 0xfa, 0x10, 0xcf, 0x19, 0xb7, 0x8b, 0x4a, +0x1b, 0x8f, 0x01, 0xb6, 0x27, 0x95, 0x53, 0xe8, 0xb6, 0x89, 0x6d, 0x5b, 0xbc, 0x68, 0xd4, 0x23, +0xe8, 0x8b, 0x51, 0xa2, 0x56, 0xf9, 0xf0, 0xa6, 0x80, 0xa0, 0xd6, 0x1e, 0xb3, 0xbc, 0x0f, 0x0f, +0x53, 0x75, 0x29, 0xaa, 0xea, 0x13, 0x77, 0xe4, 0xde, 0x8c, 0x81, 0x21, 0xad, 0x07, 0x10, 0x47, +0x11, 0xad, 0x87, 0x3d, 0x07, 0xd1, 0x75, 0xbc, 0xcf, 0xf3, 0x66, 0x7e, 0x30, 0x82, 0x02, 0x46, +0x30, 0x82, 0x01, 0xcd, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x0b, 0xa1, 0x5a, 0xfa, 0x1d, +0xdf, 0xa0, 0xb5, 0x49, 0x44, 0xaf, 0xcd, 0x24, 0xa0, 0x6c, 0xec, 0x30, 0x0a, 0x06, 0x08, 0x2a, +0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, +0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, +0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, +0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, 0x33, 0x30, 0x1e, +0x17, 0x0d, 0x31, 0x33, 0x30, 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, +0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x65, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, +0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, +0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, +0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, +0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, +0x72, 0x74, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x47, 0x33, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, +0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x19, 0xe7, 0xbc, +0xac, 0x44, 0x65, 0xed, 0xcd, 0xb8, 0x3f, 0x58, 0xfb, 0x8d, 0xb1, 0x57, 0xa9, 0x44, 0x2d, 0x05, +0x15, 0xf2, 0xef, 0x0b, 0xff, 0x10, 0x74, 0x9f, 0xb5, 0x62, 0x52, 0x5f, 0x66, 0x7e, 0x1f, 0xe5, +0xdc, 0x1b, 0x45, 0x79, 0x0b, 0xcc, 0xc6, 0x53, 0x0a, 0x9d, 0x8d, 0x5d, 0x02, 0xd9, 0xa9, 0x59, +0xde, 0x02, 0x5a, 0xf6, 0x95, 0x2a, 0x0e, 0x8d, 0x38, 0x4a, 0x8a, 0x49, 0xc6, 0xbc, 0xc6, 0x03, +0x38, 0x07, 0x5f, 0x55, 0xda, 0x7e, 0x09, 0x6e, 0xe2, 0x7f, 0x5e, 0xd0, 0x45, 0x20, 0x0f, 0x59, +0x76, 0x10, 0xd6, 0xa0, 0x24, 0xf0, 0x2d, 0xde, 0x36, 0xf2, 0x6c, 0x29, 0x39, 0xa3, 0x42, 0x30, +0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, +0x01, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcb, 0xd0, 0xbd, +0xa9, 0xe1, 0x98, 0x05, 0x51, 0xa1, 0x4d, 0x37, 0xa2, 0x83, 0x79, 0xce, 0x8d, 0x1d, 0x2a, 0xe4, +0x84, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, +0x30, 0x64, 0x02, 0x30, 0x25, 0xa4, 0x81, 0x45, 0x02, 0x6b, 0x12, 0x4b, 0x75, 0x74, 0x4f, 0xc8, +0x23, 0xe3, 0x70, 0xf2, 0x75, 0x72, 0xde, 0x7c, 0x89, 0xf0, 0xcf, 0x91, 0x72, 0x61, 0x9e, 0x5e, +0x10, 0x92, 0x59, 0x56, 0xb9, 0x83, 0xc7, 0x10, 0xe7, 0x38, 0xe9, 0x58, 0x26, 0x36, 0x7d, 0xd5, +0xe4, 0x34, 0x86, 0x39, 0x02, 0x30, 0x7c, 0x36, 0x53, 0xf0, 0x30, 0xe5, 0x62, 0x63, 0x3a, 0x99, +0xe2, 0xb6, 0xa3, 0x3b, 0x9b, 0x34, 0xfa, 0x1e, 0xda, 0x10, 0x92, 0x71, 0x5e, 0x91, 0x13, 0xa7, +0xdd, 0xa4, 0x6e, 0x92, 0xcc, 0x32, 0xd6, 0xf5, 0x21, 0x66, 0xc7, 0x2f, 0xea, 0x96, 0x63, 0x6a, +0x65, 0x45, 0x92, 0x95, 0x01, 0xb4, 0x30, 0x82, 0x04, 0x00, 0x30, 0x82, 0x02, 0xe8, 0xa0, 0x03, +0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x63, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x54, +0x68, 0x65, 0x20, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x47, 0x72, 0x6f, 0x75, +0x70, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x28, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, +0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, +0x30, 0x36, 0x32, 0x39, 0x31, 0x37, 0x30, 0x36, 0x32, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x34, 0x30, +0x36, 0x32, 0x39, 0x31, 0x37, 0x30, 0x36, 0x32, 0x30, 0x5a, 0x30, 0x63, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, +0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x31, 0x30, 0x2f, +0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, +0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, +0x82, 0x01, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, +0x05, 0x00, 0x03, 0x82, 0x01, 0x0d, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, +0xde, 0x9d, 0xd7, 0xea, 0x57, 0x18, 0x49, 0xa1, 0x5b, 0xeb, 0xd7, 0x5f, 0x48, 0x86, 0xea, 0xbe, +0xdd, 0xff, 0xe4, 0xef, 0x67, 0x1c, 0xf4, 0x65, 0x68, 0xb3, 0x57, 0x71, 0xa0, 0x5e, 0x77, 0xbb, +0xed, 0x9b, 0x49, 0xe9, 0x70, 0x80, 0x3d, 0x56, 0x18, 0x63, 0x08, 0x6f, 0xda, 0xf2, 0xcc, 0xd0, +0x3f, 0x7f, 0x02, 0x54, 0x22, 0x54, 0x10, 0xd8, 0xb2, 0x81, 0xd4, 0xc0, 0x75, 0x3d, 0x4b, 0x7f, +0xc7, 0x77, 0xc3, 0x3e, 0x78, 0xab, 0x1a, 0x03, 0xb5, 0x20, 0x6b, 0x2f, 0x6a, 0x2b, 0xb1, 0xc5, +0x88, 0x7e, 0xc4, 0xbb, 0x1e, 0xb0, 0xc1, 0xd8, 0x45, 0x27, 0x6f, 0xaa, 0x37, 0x58, 0xf7, 0x87, +0x26, 0xd7, 0xd8, 0x2d, 0xf6, 0xa9, 0x17, 0xb7, 0x1f, 0x72, 0x36, 0x4e, 0xa6, 0x17, 0x3f, 0x65, +0x98, 0x92, 0xdb, 0x2a, 0x6e, 0x5d, 0xa2, 0xfe, 0x88, 0xe0, 0x0b, 0xde, 0x7f, 0xe5, 0x8d, 0x15, +0xe1, 0xeb, 0xcb, 0x3a, 0xd5, 0xe2, 0x12, 0xa2, 0x13, 0x2d, 0xd8, 0x8e, 0xaf, 0x5f, 0x12, 0x3d, +0xa0, 0x08, 0x05, 0x08, 0xb6, 0x5c, 0xa5, 0x65, 0x38, 0x04, 0x45, 0x99, 0x1e, 0xa3, 0x60, 0x60, +0x74, 0xc5, 0x41, 0xa5, 0x72, 0x62, 0x1b, 0x62, 0xc5, 0x1f, 0x6f, 0x5f, 0x1a, 0x42, 0xbe, 0x02, +0x51, 0x65, 0xa8, 0xae, 0x23, 0x18, 0x6a, 0xfc, 0x78, 0x03, 0xa9, 0x4d, 0x7f, 0x80, 0xc3, 0xfa, +0xab, 0x5a, 0xfc, 0xa1, 0x40, 0xa4, 0xca, 0x19, 0x16, 0xfe, 0xb2, 0xc8, 0xef, 0x5e, 0x73, 0x0d, +0xee, 0x77, 0xbd, 0x9a, 0xf6, 0x79, 0x98, 0xbc, 0xb1, 0x07, 0x67, 0xa2, 0x15, 0x0d, 0xdd, 0xa0, +0x58, 0xc6, 0x44, 0x7b, 0x0a, 0x3e, 0x62, 0x28, 0x5f, 0xba, 0x41, 0x07, 0x53, 0x58, 0xcf, 0x11, +0x7e, 0x38, 0x74, 0xc5, 0xf8, 0xff, 0xb5, 0x69, 0x90, 0x8f, 0x84, 0x74, 0xea, 0x97, 0x1b, 0xaf, +0x02, 0x01, 0x03, 0xa3, 0x81, 0xc0, 0x30, 0x81, 0xbd, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, +0x04, 0x16, 0x04, 0x14, 0xd2, 0xc4, 0xb0, 0xd2, 0x91, 0xd4, 0x4c, 0x11, 0x71, 0xb3, 0x61, 0xcb, +0x3d, 0xa1, 0xfe, 0xdd, 0xa8, 0x6a, 0xd4, 0xe3, 0x30, 0x81, 0x8d, 0x06, 0x03, 0x55, 0x1d, 0x23, +0x04, 0x81, 0x85, 0x30, 0x81, 0x82, 0x80, 0x14, 0xd2, 0xc4, 0xb0, 0xd2, 0x91, 0xd4, 0x4c, 0x11, +0x71, 0xb3, 0x61, 0xcb, 0x3d, 0xa1, 0xfe, 0xdd, 0xa8, 0x6a, 0xd4, 0xe3, 0xa1, 0x67, 0xa4, 0x65, +0x30, 0x63, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6f, +0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x49, 0x6e, +0x63, 0x2e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x47, 0x6f, 0x20, +0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x82, 0x01, 0x00, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x32, 0x4b, 0xf3, 0xb2, 0xca, 0x3e, +0x91, 0xfc, 0x12, 0xc6, 0xa1, 0x07, 0x8c, 0x8e, 0x77, 0xa0, 0x33, 0x06, 0x14, 0x5c, 0x90, 0x1e, +0x18, 0xf7, 0x08, 0xa6, 0x3d, 0x0a, 0x19, 0xf9, 0x87, 0x80, 0x11, 0x6e, 0x69, 0xe4, 0x96, 0x17, +0x30, 0xff, 0x34, 0x91, 0x63, 0x72, 0x38, 0xee, 0xcc, 0x1c, 0x01, 0xa3, 0x1d, 0x94, 0x28, 0xa4, +0x31, 0xf6, 0x7a, 0xc4, 0x54, 0xd7, 0xf6, 0xe5, 0x31, 0x58, 0x03, 0xa2, 0xcc, 0xce, 0x62, 0xdb, +0x94, 0x45, 0x73, 0xb5, 0xbf, 0x45, 0xc9, 0x24, 0xb5, 0xd5, 0x82, 0x02, 0xad, 0x23, 0x79, 0x69, +0x8d, 0xb8, 0xb6, 0x4d, 0xce, 0xcf, 0x4c, 0xca, 0x33, 0x23, 0xe8, 0x1c, 0x88, 0xaa, 0x9d, 0x8b, +0x41, 0x6e, 0x16, 0xc9, 0x20, 0xe5, 0x89, 0x9e, 0xcd, 0x3b, 0xda, 0x70, 0xf7, 0x7e, 0x99, 0x26, +0x20, 0x14, 0x54, 0x25, 0xab, 0x6e, 0x73, 0x85, 0xe6, 0x9b, 0x21, 0x9d, 0x0a, 0x6c, 0x82, 0x0e, +0xa8, 0xf8, 0xc2, 0x0c, 0xfa, 0x10, 0x1e, 0x6c, 0x96, 0xef, 0x87, 0x0d, 0xc4, 0x0f, 0x61, 0x8b, +0xad, 0xee, 0x83, 0x2b, 0x95, 0xf8, 0x8e, 0x92, 0x84, 0x72, 0x39, 0xeb, 0x20, 0xea, 0x83, 0xed, +0x83, 0xcd, 0x97, 0x6e, 0x08, 0xbc, 0xeb, 0x4e, 0x26, 0xb6, 0x73, 0x2b, 0xe4, 0xd3, 0xf6, 0x4c, +0xfe, 0x26, 0x71, 0xe2, 0x61, 0x11, 0x74, 0x4a, 0xff, 0x57, 0x1a, 0x87, 0x0f, 0x75, 0x48, 0x2e, +0xcf, 0x51, 0x69, 0x17, 0xa0, 0x02, 0x12, 0x61, 0x95, 0xd5, 0xd1, 0x40, 0xb2, 0x10, 0x4c, 0xee, +0xc4, 0xac, 0x10, 0x43, 0xa6, 0xa5, 0x9e, 0x0a, 0xd5, 0x95, 0x62, 0x9a, 0x0d, 0xcf, 0x88, 0x82, +0xc5, 0x32, 0x0c, 0xe4, 0x2b, 0x9f, 0x45, 0xe6, 0x0d, 0x9f, 0x28, 0x9c, 0xb1, 0xb9, 0x2a, 0x5a, +0x57, 0xad, 0x37, 0x0f, 0xaf, 0x1d, 0x7f, 0xdb, 0xbd, 0x9f, 0x30, 0x82, 0x03, 0xc5, 0x30, 0x82, +0x02, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x83, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, +0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, +0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, +0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x31, 0x30, 0x2f, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, +0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x39, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, +0x17, 0x0d, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, +0x81, 0x83, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, +0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, +0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, +0x63, 0x2e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6f, 0x20, +0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, +0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, +0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbf, 0x71, 0x62, 0x08, 0xf1, 0xfa, 0x59, 0x34, 0xf7, 0x1b, +0xc9, 0x18, 0xa3, 0xf7, 0x80, 0x49, 0x58, 0xe9, 0x22, 0x83, 0x13, 0xa6, 0xc5, 0x20, 0x43, 0x01, +0x3b, 0x84, 0xf1, 0xe6, 0x85, 0x49, 0x9f, 0x27, 0xea, 0xf6, 0x84, 0x1b, 0x4e, 0xa0, 0xb4, 0xdb, +0x70, 0x98, 0xc7, 0x32, 0x01, 0xb1, 0x05, 0x3e, 0x07, 0x4e, 0xee, 0xf4, 0xfa, 0x4f, 0x2f, 0x59, +0x30, 0x22, 0xe7, 0xab, 0x19, 0x56, 0x6b, 0xe2, 0x80, 0x07, 0xfc, 0xf3, 0x16, 0x75, 0x80, 0x39, +0x51, 0x7b, 0xe5, 0xf9, 0x35, 0xb6, 0x74, 0x4e, 0xa9, 0x8d, 0x82, 0x13, 0xe4, 0xb6, 0x3f, 0xa9, +0x03, 0x83, 0xfa, 0xa2, 0xbe, 0x8a, 0x15, 0x6a, 0x7f, 0xde, 0x0b, 0xc3, 0xb6, 0x19, 0x14, 0x05, +0xca, 0xea, 0xc3, 0xa8, 0x04, 0x94, 0x3b, 0x46, 0x7c, 0x32, 0x0d, 0xf3, 0x00, 0x66, 0x22, 0xc8, +0x8d, 0x69, 0x6d, 0x36, 0x8c, 0x11, 0x18, 0xb7, 0xd3, 0xb2, 0x1c, 0x60, 0xb4, 0x38, 0xfa, 0x02, +0x8c, 0xce, 0xd3, 0xdd, 0x46, 0x07, 0xde, 0x0a, 0x3e, 0xeb, 0x5d, 0x7c, 0xc8, 0x7c, 0xfb, 0xb0, +0x2b, 0x53, 0xa4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1a, 0x44, 0x81, 0x8c, 0x2c, 0xa9, +0x43, 0x96, 0x23, 0xdf, 0xac, 0x3a, 0x81, 0x9a, 0x0e, 0x29, 0xc5, 0x1c, 0xa9, 0xe9, 0x5d, 0x1e, +0xb6, 0x9e, 0x9e, 0x30, 0x0a, 0x39, 0xce, 0xf1, 0x88, 0x80, 0xfb, 0x4b, 0x5d, 0xcc, 0x32, 0xec, +0x85, 0x62, 0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xb4, 0x3b, 0x70, 0x2a, 0x3f, 0x6e, +0xb1, 0xe8, 0x9c, 0x88, 0x01, 0x7d, 0x9f, 0xd4, 0xf9, 0xdb, 0x53, 0x6d, 0x60, 0x9d, 0xbf, 0x2c, +0xe7, 0x58, 0xab, 0xb8, 0x5f, 0x46, 0xfc, 0xce, 0xc4, 0x1b, 0x03, 0x3c, 0x09, 0xeb, 0x49, 0x31, +0x5c, 0x69, 0x46, 0xb3, 0xe0, 0x47, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x3a, 0x9a, 0x85, 0x07, 0x10, +0x67, 0x28, 0xb6, 0xef, 0xf6, 0xbd, 0x05, 0x41, 0x6e, 0x20, 0xc1, 0x94, 0xda, 0x0f, 0xde, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, +0x01, 0x01, 0x00, 0x99, 0xdb, 0x5d, 0x79, 0xd5, 0xf9, 0x97, 0x59, 0x67, 0x03, 0x61, 0xf1, 0x7e, +0x3b, 0x06, 0x31, 0x75, 0x2d, 0xa1, 0x20, 0x8e, 0x4f, 0x65, 0x87, 0xb4, 0xf7, 0xa6, 0x9c, 0xbc, +0xd8, 0xe9, 0x2f, 0xd0, 0xdb, 0x5a, 0xee, 0xcf, 0x74, 0x8c, 0x73, 0xb4, 0x38, 0x42, 0xda, 0x05, +0x7b, 0xf8, 0x02, 0x75, 0xb8, 0xfd, 0xa5, 0xb1, 0xd7, 0xae, 0xf6, 0xd7, 0xde, 0x13, 0xcb, 0x53, +0x10, 0x7e, 0x8a, 0x46, 0xd1, 0x97, 0xfa, 0xb7, 0x2e, 0x2b, 0x11, 0xab, 0x90, 0xb0, 0x27, 0x80, +0xf9, 0xe8, 0x9f, 0x5a, 0xe9, 0x37, 0x9f, 0xab, 0xe4, 0xdf, 0x6c, 0xb3, 0x85, 0x17, 0x9d, 0x3d, +0xd9, 0x24, 0x4f, 0x79, 0x91, 0x35, 0xd6, 0x5f, 0x04, 0xeb, 0x80, 0x83, 0xab, 0x9a, 0x02, 0x2d, +0xb5, 0x10, 0xf4, 0xd8, 0x90, 0xc7, 0x04, 0x73, 0x40, 0xed, 0x72, 0x25, 0xa0, 0xa9, 0x9f, 0xec, +0x9e, 0xab, 0x68, 0x12, 0x99, 0x57, 0xc6, 0x8f, 0x12, 0x3a, 0x09, 0xa4, 0xbd, 0x44, 0xfd, 0x06, +0x15, 0x37, 0xc1, 0x9b, 0xe4, 0x32, 0xa3, 0xed, 0x38, 0xe8, 0xd8, 0x64, 0xf3, 0x2c, 0x7e, 0x14, +0xfc, 0x02, 0xea, 0x9f, 0xcd, 0xff, 0x07, 0x68, 0x17, 0xdb, 0x22, 0x90, 0x38, 0x2d, 0x7a, 0x8d, +0xd1, 0x54, 0xf1, 0x69, 0xe3, 0x5f, 0x33, 0xca, 0x7a, 0x3d, 0x7b, 0x0a, 0xe3, 0xca, 0x7f, 0x5f, +0x39, 0xe5, 0xe2, 0x75, 0xba, 0xc5, 0x76, 0x18, 0x33, 0xce, 0x2c, 0xf0, 0x2f, 0x4c, 0xad, 0xf7, +0xb1, 0xe7, 0xce, 0x4f, 0xa8, 0xc4, 0x9b, 0x4a, 0x54, 0x06, 0xc5, 0x7f, 0x7d, 0xd5, 0x08, 0x0f, +0xe2, 0x1c, 0xfe, 0x7e, 0x17, 0xb8, 0xac, 0x5e, 0xf6, 0xd4, 0x16, 0xb2, 0x43, 0x09, 0x0c, 0x4d, +0xf6, 0xa7, 0x6b, 0xb4, 0x99, 0x84, 0x65, 0xca, 0x7a, 0x88, 0xe2, 0xe2, 0x44, 0xbe, 0x5c, 0xf7, +0xea, 0x1c, 0xf5, 0x30, 0x82, 0x04, 0x31, 0x30, 0x82, 0x03, 0x19, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, +0x05, 0x00, 0x30, 0x81, 0x95, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x47, 0x52, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x3b, 0x48, 0x65, 0x6c, +0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, +0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, +0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2e, 0x20, 0x41, +0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x37, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, +0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, +0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, +0x31, 0x32, 0x30, 0x36, 0x31, 0x33, 0x34, 0x39, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x31, +0x32, 0x30, 0x31, 0x31, 0x33, 0x34, 0x39, 0x35, 0x32, 0x5a, 0x30, 0x81, 0x95, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x52, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x3b, 0x48, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, +0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, +0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, +0x20, 0x43, 0x65, 0x72, 0x74, 0x2e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x31, 0x40, 0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6c, 0x6c, 0x65, +0x6e, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x63, 0x20, 0x61, 0x6e, 0x64, +0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, +0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, +0x31, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, +0x01, 0x01, 0x00, 0xa9, 0x53, 0x00, 0xe3, 0x2e, 0xa6, 0xf6, 0x8e, 0xfa, 0x60, 0xd8, 0x2d, 0x95, +0x3e, 0xf8, 0x2c, 0x2a, 0x54, 0x4e, 0xcd, 0xb9, 0x84, 0x61, 0x94, 0x58, 0x4f, 0x8f, 0x3d, 0x8b, +0xe4, 0x43, 0xf3, 0x75, 0x89, 0x8d, 0x51, 0xe4, 0xc3, 0x37, 0xd2, 0x8a, 0x88, 0x4d, 0x79, 0x1e, +0xb7, 0x12, 0xdd, 0x43, 0x78, 0x4a, 0x8a, 0x92, 0xe6, 0xd7, 0x48, 0xd5, 0x0f, 0xa4, 0x3a, 0x29, +0x44, 0x35, 0xb8, 0x07, 0xf6, 0x68, 0x1d, 0x55, 0xcd, 0x38, 0x51, 0xf0, 0x8c, 0x24, 0x31, 0x85, +0xaf, 0x83, 0xc9, 0x7d, 0xe9, 0x77, 0xaf, 0xed, 0x1a, 0x7b, 0x9d, 0x17, 0xf9, 0xb3, 0x9d, 0x38, +0x50, 0x0f, 0xa6, 0x5a, 0x79, 0x91, 0x80, 0xaf, 0x37, 0xae, 0xa6, 0xd3, 0x31, 0xfb, 0xb5, 0x26, +0x09, 0x9d, 0x3c, 0x5a, 0xef, 0x51, 0xc5, 0x2b, 0xdf, 0x96, 0x5d, 0xeb, 0x32, 0x1e, 0x02, 0xda, +0x70, 0x49, 0xec, 0x6e, 0x0c, 0xc8, 0x9a, 0x37, 0x8d, 0xf7, 0xf1, 0x36, 0x60, 0x4b, 0x26, 0x2c, +0x82, 0x9e, 0xd0, 0x78, 0xf3, 0x0d, 0x0f, 0x63, 0xa4, 0x51, 0x30, 0xe1, 0xf9, 0x2b, 0x27, 0x12, +0x07, 0xd8, 0xea, 0xbd, 0x18, 0x62, 0x98, 0xb0, 0x59, 0x37, 0x7d, 0xbe, 0xee, 0xf3, 0x20, 0x51, +0x42, 0x5a, 0x83, 0xef, 0x93, 0xba, 0x69, 0x15, 0xf1, 0x62, 0x9d, 0x9f, 0x99, 0x39, 0x82, 0xa1, +0xb7, 0x74, 0x2e, 0x8b, 0xd4, 0xc5, 0x0b, 0x7b, 0x2f, 0xf0, 0xc8, 0x0a, 0xda, 0x3d, 0x79, 0x0a, +0x9a, 0x93, 0x1c, 0xa5, 0x28, 0x72, 0x73, 0x91, 0x43, 0x9a, 0xa7, 0xd1, 0x4d, 0x85, 0x84, 0xb9, +0xa9, 0x74, 0x8f, 0x14, 0x40, 0xc7, 0xdc, 0xde, 0xac, 0x41, 0x64, 0x6c, 0xb4, 0x19, 0x9b, 0x02, +0x63, 0x6d, 0x24, 0x64, 0x8f, 0x44, 0xb2, 0x25, 0xea, 0xce, 0x5d, 0x74, 0x0c, 0x63, 0x32, 0x5c, +0x8d, 0x87, 0xe5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x89, 0x30, 0x81, 0x86, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, +0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa6, 0x91, 0x42, 0xfd, 0x13, 0x61, 0x4a, 0x23, 0x9e, +0x08, 0xa4, 0x29, 0xe5, 0xd8, 0x13, 0x04, 0x23, 0xee, 0x41, 0x25, 0x30, 0x47, 0x06, 0x03, 0x55, +0x1d, 0x1e, 0x04, 0x40, 0x30, 0x3e, 0xa0, 0x3c, 0x30, 0x05, 0x82, 0x03, 0x2e, 0x67, 0x72, 0x30, +0x05, 0x82, 0x03, 0x2e, 0x65, 0x75, 0x30, 0x06, 0x82, 0x04, 0x2e, 0x65, 0x64, 0x75, 0x30, 0x06, +0x82, 0x04, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x05, 0x81, 0x03, 0x2e, 0x67, 0x72, 0x30, 0x05, 0x81, +0x03, 0x2e, 0x65, 0x75, 0x30, 0x06, 0x81, 0x04, 0x2e, 0x65, 0x64, 0x75, 0x30, 0x06, 0x81, 0x04, +0x2e, 0x6f, 0x72, 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x1f, 0xef, 0x79, 0x41, 0xe1, 0x7b, 0x6e, 0x3f, +0xb2, 0x8c, 0x86, 0x37, 0x42, 0x4a, 0x4e, 0x1c, 0x37, 0x1e, 0x8d, 0x66, 0xba, 0x24, 0x81, 0xc9, +0x4f, 0x12, 0x0f, 0x21, 0xc0, 0x03, 0x97, 0x86, 0x25, 0x6d, 0x5d, 0xd3, 0x22, 0x29, 0xa8, 0x6c, +0xa2, 0x0d, 0xa9, 0xeb, 0x3d, 0x06, 0x5b, 0x99, 0x3a, 0xc7, 0xcc, 0xc3, 0x9a, 0x34, 0x7f, 0xab, +0x0e, 0xc8, 0x4e, 0x1c, 0xe1, 0xfa, 0xe4, 0xdc, 0xcd, 0x0d, 0xbe, 0xbf, 0x24, 0xfe, 0x6c, 0xe7, +0x6b, 0xc2, 0x0d, 0xc8, 0x06, 0x9e, 0x4e, 0x8d, 0x61, 0x28, 0xa6, 0x6a, 0xfd, 0xe5, 0xf6, 0x62, +0xea, 0x18, 0x3c, 0x4e, 0xa0, 0x53, 0x9d, 0xb2, 0x3a, 0x9c, 0xeb, 0xa5, 0x9c, 0x91, 0x16, 0xb6, +0x4d, 0x82, 0xe0, 0x0c, 0x05, 0x48, 0xa9, 0x6c, 0xf5, 0xcc, 0xf8, 0xcb, 0x9d, 0x49, 0xb4, 0xf0, +0x02, 0xa5, 0xfd, 0x70, 0x03, 0xed, 0x8a, 0x21, 0xa5, 0xae, 0x13, 0x86, 0x49, 0xc3, 0x33, 0x73, +0xbe, 0x87, 0x3b, 0x74, 0x8b, 0x17, 0x45, 0x26, 0x4c, 0x16, 0x91, 0x83, 0xfe, 0x67, 0x7d, 0xcd, +0x4d, 0x63, 0x67, 0xfa, 0xf3, 0x03, 0x12, 0x96, 0x78, 0x06, 0x8d, 0xb1, 0x67, 0xed, 0x8e, 0x3f, +0xbe, 0x9f, 0x4f, 0x02, 0xf5, 0xb3, 0x09, 0x2f, 0xf3, 0x4c, 0x87, 0xdf, 0x2a, 0xcb, 0x95, 0x7c, +0x01, 0xcc, 0xac, 0x36, 0x7a, 0xbf, 0xa2, 0x73, 0x7a, 0xf7, 0x8f, 0xc1, 0xb5, 0x9a, 0xa1, 0x14, +0xb2, 0x8f, 0x33, 0x9f, 0x0d, 0xef, 0x22, 0xdc, 0x66, 0x7b, 0x84, 0xbd, 0x45, 0x17, 0x06, 0x3d, +0x3c, 0xca, 0xb9, 0x77, 0x34, 0x8f, 0xca, 0xea, 0xcf, 0x3f, 0x31, 0x3e, 0xe3, 0x88, 0xe3, 0x80, +0x49, 0x25, 0xc8, 0x97, 0xb5, 0x9d, 0x9a, 0x99, 0x4d, 0xb0, 0x3c, 0xf8, 0x4a, 0x00, 0x9b, 0x64, +0xdd, 0x9f, 0x39, 0x4b, 0xd1, 0x27, 0xd7, 0xb8, 0x30, 0x82, 0x03, 0x30, 0x30, 0x82, 0x02, 0x18, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0xe8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x4b, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x0d, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x31, +0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, +0x6e, 0x67, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, +0x31, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x33, 0x30, 0x35, 0x31, 0x35, 0x30, 0x35, 0x31, 0x33, 0x31, +0x34, 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x35, 0x31, 0x35, 0x30, 0x34, 0x35, 0x32, 0x32, 0x39, +0x5a, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x4b, +0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x48, 0x6f, 0x6e, 0x67, 0x6b, +0x6f, 0x6e, 0x67, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x17, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x20, 0x50, 0x6f, 0x73, 0x74, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, +0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xac, 0xff, 0x38, 0xb6, 0xe9, +0x66, 0x02, 0x49, 0xe3, 0xa2, 0xb4, 0xe1, 0x90, 0xf9, 0x40, 0x8f, 0x79, 0xf9, 0xe2, 0xbd, 0x79, +0xfe, 0x02, 0xbd, 0xee, 0x24, 0x92, 0x1d, 0x22, 0xf6, 0xda, 0x85, 0x72, 0x69, 0xfe, 0xd7, 0x3f, +0x09, 0xd4, 0xdd, 0x91, 0xb5, 0x02, 0x9c, 0xd0, 0x8d, 0x5a, 0xe1, 0x55, 0xc3, 0x50, 0x86, 0xb9, +0x29, 0x26, 0xc2, 0xe3, 0xd9, 0xa0, 0xf1, 0x69, 0x03, 0x28, 0x20, 0x80, 0x45, 0x22, 0x2d, 0x56, +0xa7, 0x3b, 0x54, 0x95, 0x56, 0x22, 0x59, 0x1f, 0x28, 0xdf, 0x1f, 0x20, 0x3d, 0x6d, 0xa2, 0x36, +0xbe, 0x23, 0xa0, 0xb1, 0x6e, 0xb5, 0xb1, 0x27, 0x3f, 0x39, 0x53, 0x09, 0xea, 0xab, 0x6a, 0xe8, +0x74, 0xb2, 0xc2, 0x65, 0x5c, 0x8e, 0xbf, 0x7c, 0xc3, 0x78, 0x84, 0xcd, 0x9e, 0x16, 0xfc, 0xf5, +0x2e, 0x4f, 0x20, 0x2a, 0x08, 0x9f, 0x77, 0xf3, 0xc5, 0x1e, 0xc4, 0x9a, 0x52, 0x66, 0x1e, 0x48, +0x5e, 0xe3, 0x10, 0x06, 0x8f, 0x22, 0x98, 0xe1, 0x65, 0x8e, 0x1b, 0x5d, 0x23, 0x66, 0x3b, 0xb8, +0xa5, 0x32, 0x51, 0xc8, 0x86, 0xaa, 0xa1, 0xa9, 0x9e, 0x7f, 0x76, 0x94, 0xc2, 0xa6, 0x6c, 0xb7, +0x41, 0xf0, 0xd5, 0xc8, 0x06, 0x38, 0xe6, 0xd4, 0x0c, 0xe2, 0xf3, 0x3b, 0x4c, 0x6d, 0x50, 0x8c, +0xc4, 0x83, 0x27, 0xc1, 0x13, 0x84, 0x59, 0x3d, 0x9e, 0x75, 0x74, 0xb6, 0xd8, 0x02, 0x5e, 0x3a, +0x90, 0x7a, 0xc0, 0x42, 0x36, 0x72, 0xec, 0x6a, 0x4d, 0xdc, 0xef, 0xc4, 0x00, 0xdf, 0x13, 0x18, +0x57, 0x5f, 0x26, 0x78, 0xc8, 0xd6, 0x0a, 0x79, 0x77, 0xbf, 0xf7, 0xaf, 0xb7, 0x76, 0xb9, 0xa5, +0x0b, 0x84, 0x17, 0x5d, 0x10, 0xea, 0x6f, 0xe1, 0xab, 0x95, 0x11, 0x5f, 0x6d, 0x3c, 0xa3, 0x5c, +0x4d, 0x83, 0x5b, 0xf2, 0xb3, 0x19, 0x8a, 0x80, 0x8b, 0x0b, 0x87, 0x02, 0x03, 0x01, 0x00, 0x01, +0xa3, 0x26, 0x30, 0x24, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, +0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x03, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0xc6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x0e, 0x46, 0xd5, 0x3c, +0xae, 0xe2, 0x87, 0xd9, 0x5e, 0x81, 0x8b, 0x02, 0x98, 0x41, 0x08, 0x8c, 0x4c, 0xbc, 0xda, 0xdb, +0xee, 0x27, 0x1b, 0x82, 0xe7, 0x6a, 0x45, 0xec, 0x16, 0x8b, 0x4f, 0x85, 0xa0, 0xf3, 0xb2, 0x70, +0xbd, 0x5a, 0x96, 0xba, 0xca, 0x6e, 0x6d, 0xee, 0x46, 0x8b, 0x6e, 0xe7, 0x2a, 0x2e, 0x96, 0xb3, +0x19, 0x33, 0xeb, 0xb4, 0x9f, 0xa8, 0xb2, 0x37, 0xee, 0x98, 0xa8, 0x97, 0xb6, 0x2e, 0xb6, 0x67, +0x27, 0xd4, 0xa6, 0x49, 0xfd, 0x1c, 0x93, 0x65, 0x76, 0x9e, 0x42, 0x2f, 0xdc, 0x22, 0x6c, 0x9a, +0x4f, 0xf2, 0x5a, 0x15, 0x39, 0xb1, 0x71, 0xd7, 0x2b, 0x51, 0xe8, 0x6d, 0x1c, 0x98, 0xc0, 0xd9, +0x2a, 0xf4, 0xa1, 0x82, 0x7b, 0xd5, 0xc9, 0x41, 0xa2, 0x23, 0x01, 0x74, 0x38, 0x55, 0x8b, 0x0f, +0xb9, 0x2e, 0x67, 0xa2, 0x20, 0x04, 0x37, 0xda, 0x9c, 0x0b, 0xd3, 0x17, 0x21, 0xe0, 0x8f, 0x97, +0x79, 0x34, 0x6f, 0x84, 0x48, 0x02, 0x20, 0x33, 0x1b, 0xe6, 0x34, 0x44, 0x9f, 0x91, 0x70, 0xf4, +0x80, 0x5e, 0x84, 0x43, 0xc2, 0x29, 0xd2, 0x6c, 0x12, 0x14, 0xe4, 0x61, 0x8d, 0xac, 0x10, 0x90, +0x9e, 0x84, 0x50, 0xbb, 0xf0, 0x96, 0x6f, 0x45, 0x9f, 0x8a, 0xf3, 0xca, 0x6c, 0x4f, 0xfa, 0x11, +0x3a, 0x15, 0x15, 0x46, 0xc3, 0xcd, 0x1f, 0x83, 0x5b, 0x2d, 0x41, 0x12, 0xed, 0x50, 0x67, 0x41, +0x13, 0x3d, 0x21, 0xab, 0x94, 0x8a, 0xaa, 0x4e, 0x7c, 0xc1, 0xb1, 0xfb, 0xa7, 0xd6, 0xb5, 0x27, +0x2f, 0x97, 0xab, 0x6e, 0xe0, 0x1d, 0xe2, 0xd1, 0x1c, 0x2c, 0x1f, 0x44, 0xe2, 0xfc, 0xbe, 0x91, +0xa1, 0x9c, 0xfb, 0xd6, 0x29, 0x53, 0x73, 0x86, 0x9f, 0x53, 0xd8, 0x43, 0x0e, 0x5d, 0xd6, 0x63, +0x82, 0x71, 0x1d, 0x80, 0x74, 0xca, 0xf6, 0xe2, 0x02, 0x6b, 0xd9, 0x5a, 0x30, 0x82, 0x05, 0xf1, +0x30, 0x82, 0x03, 0xd9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0xb0, 0xb7, 0x5a, 0x16, +0x48, 0x5f, 0xbf, 0xe1, 0xcb, 0xf5, 0x8b, 0xd7, 0x19, 0xe6, 0x7d, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x38, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x0c, 0x0b, 0x49, 0x5a, 0x45, 0x4e, 0x50, 0x45, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, +0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x49, 0x7a, 0x65, 0x6e, 0x70, 0x65, +0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x31, 0x32, 0x31, 0x33, 0x31, 0x33, +0x30, 0x38, 0x32, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x32, 0x31, 0x33, 0x30, 0x38, 0x32, +0x37, 0x32, 0x35, 0x5a, 0x30, 0x38, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x49, 0x5a, +0x45, 0x4e, 0x50, 0x45, 0x20, 0x53, 0x2e, 0x41, 0x2e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x0a, 0x49, 0x7a, 0x65, 0x6e, 0x70, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, +0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc9, +0xd3, 0x7a, 0xca, 0x0f, 0x1e, 0xac, 0xa7, 0x86, 0xe8, 0x16, 0x65, 0x6a, 0xb1, 0xc2, 0x1b, 0x45, +0x32, 0x71, 0x95, 0xd9, 0xfe, 0x10, 0x5b, 0xcc, 0xaf, 0xe7, 0xa5, 0x79, 0x01, 0x8f, 0x89, 0xc3, +0xca, 0xf2, 0x55, 0x71, 0xf7, 0x77, 0xbe, 0x77, 0x94, 0xf3, 0x72, 0xa4, 0x2c, 0x44, 0xd8, 0x9e, +0x92, 0x9b, 0x14, 0x3a, 0xa1, 0xe7, 0x24, 0x90, 0x0a, 0x0a, 0x56, 0x8e, 0xc5, 0xd8, 0x26, 0x94, +0xe1, 0xd9, 0x48, 0xe1, 0x2d, 0x3e, 0xda, 0x0a, 0x72, 0xdd, 0xa3, 0x99, 0x15, 0xda, 0x81, 0xa2, +0x87, 0xf4, 0x7b, 0x6e, 0x26, 0x77, 0x89, 0x58, 0xad, 0xd6, 0xeb, 0x0c, 0xb2, 0x41, 0x7a, 0x73, +0x6e, 0x6d, 0xdb, 0x7a, 0x78, 0x41, 0xe9, 0x08, 0x88, 0x12, 0x7e, 0x87, 0x2e, 0x66, 0x11, 0x63, +0x6c, 0x54, 0xfb, 0x3c, 0x9d, 0x72, 0xc0, 0xbc, 0x2e, 0xff, 0xc2, 0xb7, 0xdd, 0x0d, 0x76, 0xe3, +0x3a, 0xd7, 0xf7, 0xb4, 0x68, 0xbe, 0xa2, 0xf5, 0xe3, 0x81, 0x6e, 0xc1, 0x46, 0x6f, 0x5d, 0x8d, +0xe0, 0x4d, 0xc6, 0x54, 0x55, 0x89, 0x1a, 0x33, 0x31, 0x0a, 0xb1, 0x57, 0xb9, 0xa3, 0x8a, 0x98, +0xc3, 0xec, 0x3b, 0x34, 0xc5, 0x95, 0x41, 0x69, 0x7e, 0x75, 0xc2, 0x3c, 0x20, 0xc5, 0x61, 0xba, +0x51, 0x47, 0xa0, 0x20, 0x90, 0x93, 0xa1, 0x90, 0x4b, 0xf3, 0x4e, 0x7c, 0x85, 0x45, 0x54, 0x9a, +0xd1, 0x05, 0x26, 0x41, 0xb0, 0xb5, 0x4d, 0x1d, 0x33, 0xbe, 0xc4, 0x03, 0xc8, 0x25, 0x7c, 0xc1, +0x70, 0xdb, 0x3b, 0xf4, 0x09, 0x2d, 0x54, 0x27, 0x48, 0xac, 0x2f, 0xe1, 0xc4, 0xac, 0x3e, 0xc8, +0xcb, 0x92, 0x4c, 0x53, 0x39, 0x37, 0x23, 0xec, 0xd3, 0x01, 0xf9, 0xe0, 0x09, 0x44, 0x4d, 0x4d, +0x64, 0xc0, 0xe1, 0x0d, 0x5a, 0x87, 0x22, 0xbc, 0xad, 0x1b, 0xa3, 0xfe, 0x26, 0xb5, 0x15, 0xf3, +0xa7, 0xfc, 0x84, 0x19, 0xe9, 0xec, 0xa1, 0x88, 0xb4, 0x44, 0x69, 0x84, 0x83, 0xf3, 0x89, 0xd1, +0x74, 0x06, 0xa9, 0xcc, 0x0b, 0xd6, 0xc2, 0xde, 0x27, 0x85, 0x50, 0x26, 0xca, 0x17, 0xb8, 0xc9, +0x7a, 0x87, 0x56, 0x2c, 0x1a, 0x01, 0x1e, 0x6c, 0xbe, 0x13, 0xad, 0x10, 0xac, 0xb5, 0x24, 0xf5, +0x38, 0x91, 0xa1, 0xd6, 0x4b, 0xda, 0xf1, 0xbb, 0xd2, 0xde, 0x47, 0xb5, 0xf1, 0xbc, 0x81, 0xf6, +0x59, 0x6b, 0xcf, 0x19, 0x53, 0xe9, 0x8d, 0x15, 0xcb, 0x4a, 0xcb, 0xa9, 0x6f, 0x44, 0xe5, 0x1b, +0x41, 0xcf, 0xe1, 0x86, 0xa7, 0xca, 0xd0, 0x6a, 0x9f, 0xbc, 0x4c, 0x8d, 0x06, 0x33, 0x5a, 0xa2, +0x85, 0xe5, 0x90, 0x35, 0xa0, 0x62, 0x5c, 0x16, 0x4e, 0xf0, 0xe3, 0xa2, 0xfa, 0x03, 0x1a, 0xb4, +0x2c, 0x71, 0xb3, 0x58, 0x2c, 0xde, 0x7b, 0x0b, 0xdb, 0x1a, 0x0f, 0xeb, 0xde, 0x21, 0x1f, 0x06, +0x77, 0x06, 0x03, 0xb0, 0xc9, 0xef, 0x99, 0xfc, 0xc0, 0xb9, 0x4f, 0x0b, 0x86, 0x28, 0xfe, 0xd2, +0xb9, 0xea, 0xe3, 0xda, 0xa5, 0xc3, 0x47, 0x69, 0x12, 0xe0, 0xdb, 0xf0, 0xf6, 0x19, 0x8b, 0xed, +0x7b, 0x70, 0xd7, 0x02, 0xd6, 0xed, 0x87, 0x18, 0x28, 0x2c, 0x04, 0x24, 0x4c, 0x77, 0xe4, 0x48, +0x8a, 0x1a, 0xc6, 0x3b, 0x9a, 0xd4, 0x0f, 0xca, 0xfa, 0x75, 0xd2, 0x01, 0x40, 0x5a, 0x8d, 0x79, +0xbf, 0x8b, 0xcf, 0x4b, 0xcf, 0xaa, 0x16, 0xc1, 0x95, 0xe4, 0xad, 0x4c, 0x8a, 0x3e, 0x17, 0x91, +0xd4, 0xb1, 0x62, 0xe5, 0x82, 0xe5, 0x80, 0x04, 0xa4, 0x03, 0x7e, 0x8d, 0xbf, 0xda, 0x7f, 0xa2, +0x0f, 0x97, 0x4f, 0x0c, 0xd3, 0x0d, 0xfb, 0xd7, 0xd1, 0xe5, 0x72, 0x7e, 0x1c, 0xc8, 0x77, 0xff, +0x5b, 0x9a, 0x0f, 0xb7, 0xae, 0x05, 0x46, 0xe5, 0xf1, 0xa8, 0x16, 0xec, 0x47, 0xa4, 0x17, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xf6, 0x30, 0x81, 0xf3, 0x30, 0x81, 0xb0, 0x06, 0x03, 0x55, +0x1d, 0x11, 0x04, 0x81, 0xa8, 0x30, 0x81, 0xa5, 0x81, 0x0f, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x69, +0x7a, 0x65, 0x6e, 0x70, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0xa4, 0x81, 0x91, 0x30, 0x81, 0x8e, 0x31, +0x47, 0x30, 0x45, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x3e, 0x49, 0x5a, 0x45, 0x4e, 0x50, 0x45, +0x20, 0x53, 0x2e, 0x41, 0x2e, 0x20, 0x2d, 0x20, 0x43, 0x49, 0x46, 0x20, 0x41, 0x30, 0x31, 0x33, +0x33, 0x37, 0x32, 0x36, 0x30, 0x2d, 0x52, 0x4d, 0x65, 0x72, 0x63, 0x2e, 0x56, 0x69, 0x74, 0x6f, +0x72, 0x69, 0x61, 0x2d, 0x47, 0x61, 0x73, 0x74, 0x65, 0x69, 0x7a, 0x20, 0x54, 0x31, 0x30, 0x35, +0x35, 0x20, 0x46, 0x36, 0x32, 0x20, 0x53, 0x38, 0x31, 0x43, 0x30, 0x41, 0x06, 0x03, 0x55, 0x04, +0x09, 0x0c, 0x3a, 0x41, 0x76, 0x64, 0x61, 0x20, 0x64, 0x65, 0x6c, 0x20, 0x4d, 0x65, 0x64, 0x69, +0x74, 0x65, 0x72, 0x72, 0x61, 0x6e, 0x65, 0x6f, 0x20, 0x45, 0x74, 0x6f, 0x72, 0x62, 0x69, 0x64, +0x65, 0x61, 0x20, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x30, 0x31, 0x30, 0x31, 0x30, 0x20, 0x56, 0x69, +0x74, 0x6f, 0x72, 0x69, 0x61, 0x2d, 0x47, 0x61, 0x73, 0x74, 0x65, 0x69, 0x7a, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1d, 0x1c, 0x65, 0x0e, 0xa8, 0xf2, 0x25, +0x7b, 0xb4, 0x91, 0xcf, 0xe4, 0xb1, 0xb1, 0xe6, 0xbd, 0x55, 0x74, 0x6c, 0x05, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, +0x00, 0x78, 0xa6, 0x0c, 0x16, 0x4a, 0x9f, 0x4c, 0x88, 0x3a, 0xc0, 0xcb, 0x0e, 0xa5, 0x16, 0x7d, +0x9f, 0xb9, 0x48, 0x5f, 0x18, 0x8f, 0x0d, 0x62, 0x36, 0xf6, 0xcd, 0x19, 0x6b, 0xac, 0xab, 0xd5, +0xf6, 0x91, 0x7d, 0xae, 0x71, 0xf3, 0x3f, 0xb3, 0x0e, 0x78, 0x85, 0x9b, 0x95, 0xa4, 0x27, 0x21, +0x47, 0x42, 0x4a, 0x7c, 0x48, 0x3a, 0xf5, 0x45, 0x7c, 0xb3, 0x0c, 0x8e, 0x51, 0x78, 0xac, 0x95, +0x13, 0xde, 0xc6, 0xfd, 0x7d, 0xb8, 0x1a, 0x90, 0x4c, 0xab, 0x92, 0x03, 0xc7, 0xed, 0x42, 0x01, +0xce, 0x0f, 0xd8, 0xb1, 0xfa, 0xa2, 0x92, 0xe1, 0x60, 0x6d, 0xae, 0x7a, 0x6b, 0x09, 0xaa, 0xc6, +0x29, 0xee, 0x68, 0x49, 0x67, 0x30, 0x80, 0x24, 0x7a, 0x31, 0x16, 0x39, 0x5b, 0x7e, 0xf1, 0x1c, +0x2e, 0xdd, 0x6c, 0x09, 0xad, 0xf2, 0x31, 0xc1, 0x82, 0x4e, 0xb9, 0xbb, 0xf9, 0xbe, 0xbf, 0x2a, +0x85, 0x3f, 0xc0, 0x40, 0xa3, 0x3a, 0x59, 0xfc, 0x59, 0x4b, 0x3c, 0x28, 0x24, 0xdb, 0xb4, 0x15, +0x75, 0xae, 0x0d, 0x88, 0xba, 0x2e, 0x73, 0xc0, 0xbd, 0x58, 0x87, 0xe5, 0x42, 0xf2, 0xeb, 0x5e, +0xee, 0x1e, 0x30, 0x22, 0x99, 0xcb, 0x37, 0xd1, 0xc4, 0x21, 0x6c, 0x81, 0xec, 0xbe, 0x6d, 0x26, +0xe6, 0x1c, 0xe4, 0x42, 0x20, 0x9e, 0x47, 0xb0, 0xac, 0x83, 0x59, 0x70, 0x2c, 0x35, 0xd6, 0xaf, +0x36, 0x34, 0xb4, 0xcd, 0x3b, 0xf8, 0x32, 0xa8, 0xef, 0xe3, 0x78, 0x89, 0xfb, 0x8d, 0x45, 0x2c, +0xda, 0x9c, 0xb8, 0x7e, 0x40, 0x1c, 0x61, 0xe7, 0x3e, 0xa2, 0x92, 0x2c, 0x4b, 0xf2, 0xcd, 0xfa, +0x98, 0xb6, 0x29, 0xff, 0xf3, 0xf2, 0x7b, 0xa9, 0x1f, 0x2e, 0xa0, 0x93, 0x57, 0x2b, 0xde, 0x85, +0x03, 0xf9, 0x69, 0x37, 0xcb, 0x9e, 0x78, 0x6a, 0x05, 0xb4, 0xc5, 0x31, 0x78, 0x89, 0xec, 0x7a, +0xa7, 0x85, 0xe1, 0xb9, 0x7b, 0x3c, 0xde, 0xbe, 0x1e, 0x79, 0x84, 0xce, 0x9f, 0x70, 0x0e, 0x59, +0xc2, 0x35, 0x2e, 0x90, 0x2a, 0x31, 0xd9, 0xe4, 0x45, 0x7a, 0x41, 0xa4, 0x2e, 0x13, 0x9b, 0x34, +0x0e, 0x66, 0x7b, 0x49, 0xab, 0x64, 0x97, 0xd0, 0x46, 0xc3, 0x79, 0x9d, 0x72, 0x50, 0x63, 0xa6, +0x98, 0x5b, 0x06, 0xbd, 0x48, 0x6d, 0xd8, 0x39, 0x83, 0x70, 0xe8, 0x35, 0xf0, 0x05, 0xd1, 0xaa, +0xbc, 0xe3, 0xdb, 0xc8, 0x02, 0xea, 0x7c, 0xfd, 0x82, 0xda, 0xc2, 0x5b, 0x52, 0x35, 0xae, 0x98, +0x3a, 0xad, 0xba, 0x35, 0x93, 0x23, 0xa7, 0x1f, 0x48, 0xdd, 0x35, 0x46, 0x98, 0xb2, 0x10, 0x68, +0xe4, 0xa5, 0x31, 0xc2, 0x0a, 0x58, 0x2e, 0x19, 0x81, 0x10, 0xc9, 0x50, 0x75, 0xfc, 0xea, 0x5a, +0x16, 0xce, 0x11, 0xd7, 0xee, 0xef, 0x50, 0x88, 0x2d, 0x61, 0xff, 0x3f, 0x42, 0x73, 0x05, 0x94, +0x43, 0xd5, 0x8e, 0x3c, 0x4e, 0x01, 0x3a, 0x19, 0xa5, 0x1f, 0x46, 0x4e, 0x77, 0xd0, 0x5d, 0xe5, +0x81, 0x22, 0x21, 0x87, 0xfe, 0x94, 0x7d, 0x84, 0xd8, 0x93, 0xad, 0xd6, 0x68, 0x43, 0x48, 0xb2, +0xdb, 0xeb, 0x73, 0x24, 0xe7, 0x91, 0x7f, 0x54, 0xa4, 0xb6, 0x80, 0x3e, 0x9d, 0xa3, 0x3c, 0x4c, +0x72, 0xc2, 0x57, 0xc4, 0xa0, 0xd4, 0xcc, 0x38, 0x27, 0xce, 0xd5, 0x06, 0x9e, 0xa2, 0x48, 0xd9, +0xe9, 0x9f, 0xce, 0x82, 0x70, 0x36, 0x93, 0x9a, 0x3b, 0xdf, 0x96, 0x21, 0xe3, 0x59, 0xb7, 0x0c, +0xda, 0x91, 0x37, 0xf0, 0xfd, 0x59, 0x5a, 0xb3, 0x99, 0xc8, 0x69, 0x6c, 0x43, 0x26, 0x01, 0x35, +0x63, 0x60, 0x55, 0x89, 0x03, 0x3a, 0x75, 0xd8, 0xba, 0x4a, 0xd9, 0x54, 0xff, 0xee, 0xde, 0x80, +0xd8, 0x2d, 0xd1, 0x38, 0xd5, 0x5e, 0x2d, 0x0b, 0x98, 0x7d, 0x3e, 0x6c, 0xdb, 0xfc, 0x26, 0x88, +0xc7, 0x30, 0x82, 0x03, 0xc3, 0x30, 0x82, 0x02, 0xab, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, +0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, +0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x22, 0x54, 0x2d, 0x53, 0x79, 0x73, +0x74, 0x65, 0x6d, 0x73, 0x20, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, +0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x31, 0x1f, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x16, 0x54, 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, +0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x31, 0x25, +0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x2d, 0x54, 0x65, 0x6c, 0x65, 0x53, +0x65, 0x63, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x6c, +0x61, 0x73, 0x73, 0x20, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x31, 0x30, 0x30, 0x31, 0x31, +0x30, 0x34, 0x30, 0x31, 0x34, 0x5a, 0x17, 0x0d, 0x33, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x33, +0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x22, +0x54, 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, +0x72, 0x69, 0x73, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6d, +0x62, 0x48, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x16, 0x54, 0x2d, 0x53, +0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6e, +0x74, 0x65, 0x72, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x2d, +0x54, 0x65, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, +0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x5f, 0xda, 0x1b, 0x5f, +0xe8, 0x73, 0x91, 0xe5, 0xda, 0x5c, 0xf4, 0xa2, 0xe6, 0x47, 0xe5, 0xf3, 0x68, 0x55, 0x60, 0x05, +0x1d, 0x02, 0xa4, 0xb3, 0x9b, 0x59, 0xf3, 0x1e, 0x8a, 0xaf, 0x34, 0xad, 0xfc, 0x0d, 0xc2, 0xd9, +0x48, 0x19, 0xee, 0x69, 0x8f, 0xc9, 0x20, 0xfc, 0x21, 0xaa, 0x07, 0x19, 0xed, 0xb0, 0x5c, 0xac, +0x65, 0xc7, 0x5f, 0xed, 0x02, 0x7c, 0x7b, 0x7c, 0x2d, 0x1b, 0xd6, 0xba, 0xb9, 0x80, 0xc2, 0x18, +0x82, 0x16, 0x84, 0xfa, 0x66, 0xb0, 0x08, 0xc6, 0x54, 0x23, 0x81, 0xe4, 0xcd, 0xb9, 0x49, 0x3f, +0xf6, 0x4f, 0x6e, 0x37, 0x48, 0x28, 0x38, 0x0f, 0xc5, 0xbe, 0xe7, 0x68, 0x70, 0xfd, 0x39, 0x97, +0x4d, 0xd2, 0xc7, 0x98, 0x91, 0x50, 0xaa, 0xc4, 0x44, 0xb3, 0x23, 0x7d, 0x39, 0x47, 0xe9, 0x52, +0x62, 0xd6, 0x12, 0x93, 0x5e, 0xb7, 0x31, 0x96, 0x42, 0x05, 0xfb, 0x76, 0xa7, 0x1e, 0xa3, 0xf5, +0xc2, 0xfc, 0xe9, 0x7a, 0xc5, 0x6c, 0xa9, 0x71, 0x4f, 0xea, 0xcb, 0x78, 0xbc, 0x60, 0xaf, 0xc7, +0xde, 0xf4, 0xd9, 0xcb, 0xbe, 0x7e, 0x33, 0xa5, 0x6e, 0x94, 0x83, 0xf0, 0x34, 0xfa, 0x21, 0xab, +0xea, 0x8e, 0x72, 0xa0, 0x3f, 0xa4, 0xde, 0x30, 0x5b, 0xef, 0x86, 0x4d, 0x6a, 0x95, 0x5b, 0x43, +0x44, 0xa8, 0x10, 0x15, 0x1c, 0xe5, 0x01, 0x57, 0xc5, 0x98, 0xf1, 0xe6, 0x06, 0x28, 0x91, 0xaa, +0x20, 0xc5, 0xb7, 0x53, 0x26, 0x51, 0x43, 0xb2, 0x0b, 0x11, 0x95, 0x58, 0xe1, 0xc0, 0x0f, 0x76, +0xd9, 0xc0, 0x8d, 0x7c, 0x81, 0xf3, 0x72, 0x70, 0x9e, 0x6f, 0xfe, 0x1a, 0x8e, 0xd9, 0x5f, 0x35, +0xc6, 0xb2, 0x6f, 0x34, 0x7c, 0xbe, 0x48, 0x4f, 0xe2, 0x5a, 0x39, 0xd7, 0xd8, 0x9d, 0x78, 0x9e, +0x9f, 0x86, 0x3e, 0x03, 0x5e, 0x19, 0x8b, 0x44, 0xa2, 0xd5, 0xc7, 0x02, 0x03, 0x01, 0x00, 0x01, +0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0xbf, 0x59, 0x20, 0x36, 0x00, 0x79, 0xa0, 0xa0, 0x22, 0x6b, 0x8c, 0xd5, 0xf2, 0x61, 0xd2, 0xb8, +0x2c, 0xcb, 0x82, 0x4a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x31, 0x03, 0xa2, 0x61, 0x0b, 0x1f, 0x74, 0xe8, +0x72, 0x36, 0xc6, 0x6d, 0xf9, 0x4d, 0x9e, 0xfa, 0x22, 0xa8, 0xe1, 0x81, 0x56, 0xcf, 0xcd, 0xbb, +0x9f, 0xea, 0xab, 0x91, 0x19, 0x38, 0xaf, 0xaa, 0x7c, 0x15, 0x4d, 0xf3, 0xb6, 0xa3, 0x8d, 0xa5, +0xf4, 0x8e, 0xf6, 0x44, 0xa9, 0xa7, 0xe8, 0x21, 0x95, 0xad, 0x3e, 0x00, 0x62, 0x16, 0x88, 0xf0, +0x02, 0xba, 0xfc, 0x61, 0x23, 0xe6, 0x33, 0x9b, 0x30, 0x7a, 0x6b, 0x36, 0x62, 0x7b, 0xad, 0x04, +0x23, 0x84, 0x58, 0x65, 0xe2, 0xdb, 0x2b, 0x8a, 0xe7, 0x25, 0x53, 0x37, 0x62, 0x53, 0x5f, 0xbc, +0xda, 0x01, 0x62, 0x29, 0xa2, 0xa6, 0x27, 0x71, 0xe6, 0x3a, 0x22, 0x7e, 0xc1, 0x6f, 0x1d, 0x95, +0x70, 0x20, 0x4a, 0x07, 0x34, 0xdf, 0xea, 0xff, 0x15, 0x80, 0xe5, 0xba, 0xd7, 0x7a, 0xd8, 0x5b, +0x75, 0x7c, 0x05, 0x7a, 0x29, 0x47, 0x7e, 0x40, 0xa8, 0x31, 0x13, 0x77, 0xcd, 0x40, 0x3b, 0xb4, +0x51, 0x47, 0x7a, 0x2e, 0x11, 0xe3, 0x47, 0x11, 0xde, 0x9d, 0x66, 0xd0, 0x8b, 0xd5, 0x54, 0x66, +0xfa, 0x83, 0x55, 0xea, 0x7c, 0xc2, 0x29, 0x89, 0x1b, 0xe9, 0x6f, 0xb3, 0xce, 0xe2, 0x05, 0x84, +0xc9, 0x2f, 0x3e, 0x78, 0x85, 0x62, 0x6e, 0xc9, 0x5f, 0xc1, 0x78, 0x63, 0x74, 0x58, 0xc0, 0x48, +0x18, 0x0c, 0x99, 0x39, 0xeb, 0xa4, 0xcc, 0x1a, 0xb5, 0x79, 0x5a, 0x8d, 0x15, 0x9c, 0xd8, 0x14, +0x0d, 0xf6, 0x7a, 0x07, 0x57, 0xc7, 0x22, 0x83, 0x05, 0x2d, 0x3c, 0x9b, 0x25, 0x26, 0x3d, 0x18, +0xb3, 0xa9, 0x43, 0x7c, 0xc8, 0xc8, 0xab, 0x64, 0x8f, 0x0e, 0xa3, 0xbf, 0x9c, 0x1b, 0x9d, 0x30, +0xdb, 0xda, 0xd0, 0x19, 0x2e, 0xaa, 0x3c, 0xf1, 0xfb, 0x33, 0x80, 0x76, 0xe4, 0xcd, 0xad, 0x19, +0x4f, 0x05, 0x27, 0x8e, 0x13, 0xa1, 0x6e, 0xc2, 0x30, 0x82, 0x03, 0xc3, 0x30, 0x82, 0x02, 0xab, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, +0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x22, 0x54, 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x45, 0x6e, 0x74, 0x65, +0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, +0x47, 0x6d, 0x62, 0x48, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x16, 0x54, +0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, +0x65, 0x6e, 0x74, 0x65, 0x72, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, +0x54, 0x2d, 0x54, 0x65, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x30, 0x1e, 0x17, 0x0d, +0x30, 0x38, 0x31, 0x30, 0x30, 0x31, 0x31, 0x30, 0x32, 0x39, 0x35, 0x36, 0x5a, 0x17, 0x0d, 0x33, +0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x82, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x2b, 0x30, 0x29, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x22, 0x54, 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, +0x20, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, +0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x0c, 0x16, 0x54, 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x54, 0x72, +0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x2d, 0x54, 0x65, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, +0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, +0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, +0x01, 0x00, 0xbd, 0x75, 0x93, 0xf0, 0x62, 0x22, 0x6f, 0x24, 0xae, 0xe0, 0x7a, 0x76, 0xac, 0x7d, +0xbd, 0xd9, 0x24, 0xd5, 0xb8, 0xb7, 0xfc, 0xcd, 0xf0, 0x42, 0xe0, 0xeb, 0x78, 0x88, 0x56, 0x5e, +0x9b, 0x9a, 0x54, 0x1d, 0x4d, 0x0c, 0x8a, 0xf6, 0xd3, 0xcf, 0x70, 0xf4, 0x52, 0xb5, 0xd8, 0x93, +0x04, 0xe3, 0x46, 0x86, 0x71, 0x41, 0x4a, 0x2b, 0xf0, 0x2a, 0x2c, 0x55, 0x03, 0xd6, 0x48, 0xc3, +0xe0, 0x39, 0x38, 0xed, 0xf2, 0x5c, 0x3c, 0x3f, 0x44, 0xbc, 0x93, 0x3d, 0x61, 0xab, 0x4e, 0xcd, +0x0d, 0xbe, 0xf0, 0x20, 0x27, 0x58, 0x0e, 0x44, 0x7f, 0x04, 0x1a, 0x87, 0xa5, 0xd7, 0x96, 0x14, +0x36, 0x90, 0xd0, 0x49, 0x7b, 0xa1, 0x75, 0xfb, 0x1a, 0x6b, 0x73, 0xb1, 0xf8, 0xce, 0xa9, 0x09, +0x2c, 0xf2, 0x53, 0xd5, 0xc3, 0x14, 0x44, 0xb8, 0x86, 0xa5, 0xf6, 0x8b, 0x2b, 0x39, 0xda, 0xa3, +0x33, 0x54, 0xd9, 0xfa, 0x72, 0x1a, 0xf7, 0x22, 0x15, 0x1c, 0x88, 0x91, 0x6b, 0x7f, 0x66, 0xe5, +0xc3, 0x6a, 0x80, 0xb0, 0x24, 0xf3, 0xdf, 0x86, 0x45, 0x88, 0xfd, 0x19, 0x7f, 0x75, 0x87, 0x1f, +0x1f, 0xb1, 0x1b, 0x0a, 0x73, 0x24, 0x5b, 0xb9, 0x65, 0xe0, 0x2c, 0x54, 0xc8, 0x60, 0xd3, 0x66, +0x17, 0x3f, 0xe1, 0xcc, 0x54, 0x33, 0x73, 0x91, 0x02, 0x3a, 0xa6, 0x7f, 0x7b, 0x76, 0x39, 0xa2, +0x1f, 0x96, 0xb6, 0x38, 0xae, 0xb5, 0xc8, 0x93, 0x74, 0x1d, 0x9e, 0xb9, 0xb4, 0xe5, 0x60, 0x9d, +0x2f, 0x56, 0xd1, 0xe0, 0xeb, 0x5e, 0x5b, 0x4c, 0x12, 0x70, 0x0c, 0x6c, 0x44, 0x20, 0xab, 0x11, +0xd8, 0xf4, 0x19, 0xf6, 0xd2, 0x9c, 0x52, 0x37, 0xe7, 0xfa, 0xb6, 0xc2, 0x31, 0x3b, 0x4a, 0xd4, +0x14, 0x99, 0xad, 0xc7, 0x1a, 0xf5, 0x5d, 0x5f, 0xfa, 0x07, 0xb8, 0x7c, 0x0d, 0x1f, 0xd6, 0x83, +0x1e, 0xb3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, +0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, +0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb5, 0x03, 0xf7, 0x76, 0x3b, 0x61, 0x82, 0x6a, 0x12, +0xaa, 0x18, 0x53, 0xeb, 0x03, 0x21, 0x94, 0xbf, 0xfe, 0xce, 0xca, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x56, +0x3d, 0xef, 0x94, 0xd5, 0xbd, 0xda, 0x73, 0xb2, 0x58, 0xbe, 0xae, 0x90, 0xad, 0x98, 0x27, 0x97, +0xfe, 0x01, 0xb1, 0xb0, 0x52, 0x00, 0xb8, 0x4d, 0xe4, 0x1b, 0x21, 0x74, 0x1b, 0x7e, 0xc0, 0xee, +0x5e, 0x69, 0x2a, 0x25, 0xaf, 0x5c, 0xd6, 0x1d, 0xda, 0xd2, 0x79, 0xc9, 0xf3, 0x97, 0x29, 0xe0, +0x86, 0x87, 0xde, 0x04, 0x59, 0x0f, 0xf1, 0x59, 0xd4, 0x64, 0x85, 0x4b, 0x99, 0xaf, 0x25, 0x04, +0x1e, 0xc9, 0x46, 0xa9, 0x97, 0xde, 0x82, 0xb2, 0x1b, 0x70, 0x9f, 0x9c, 0xf6, 0xaf, 0x71, 0x31, +0xdd, 0x7b, 0x05, 0xa5, 0x2c, 0xd3, 0xb9, 0xca, 0x47, 0xf6, 0xca, 0xf2, 0xf6, 0xe7, 0xad, 0xb9, +0x48, 0x3f, 0xbc, 0x16, 0xb7, 0xc1, 0x6d, 0xf4, 0xea, 0x09, 0xaf, 0xec, 0xf3, 0xb5, 0xe7, 0x05, +0x9e, 0xa6, 0x1e, 0x8a, 0x53, 0x51, 0xd6, 0x93, 0x81, 0xcc, 0x74, 0x93, 0xf6, 0xb9, 0xda, 0xa6, +0x25, 0x05, 0x74, 0x79, 0x5a, 0x7e, 0x40, 0x3e, 0x82, 0x4b, 0x26, 0x11, 0x30, 0x6e, 0xe1, 0x3f, +0x41, 0xc7, 0x47, 0x00, 0x35, 0xd5, 0xf5, 0xd3, 0xf7, 0x54, 0x3e, 0x81, 0x3d, 0xda, 0x49, 0x6a, +0x9a, 0xb3, 0xef, 0x10, 0x3d, 0xe6, 0xeb, 0x6f, 0xd1, 0xc8, 0x22, 0x47, 0xcb, 0xcc, 0xcf, 0x01, +0x31, 0x92, 0xd9, 0x18, 0xe3, 0x22, 0xbe, 0x09, 0x1e, 0x1a, 0x3e, 0x5a, 0xb2, 0xe4, 0x6b, 0x0c, +0x54, 0x7a, 0x7d, 0x43, 0x4e, 0xb8, 0x89, 0xa5, 0x7b, 0xd7, 0xa2, 0x3d, 0x96, 0x86, 0xcc, 0xf2, +0x26, 0x34, 0x2d, 0x6a, 0x92, 0x9d, 0x9a, 0x1a, 0xd0, 0x30, 0xe2, 0x5d, 0x4e, 0x04, 0xb0, 0x5f, +0x8b, 0x20, 0x7e, 0x77, 0xc1, 0x3d, 0x95, 0x82, 0xd1, 0x46, 0x9a, 0x3b, 0x3c, 0x78, 0xb8, 0x6f, +0xa1, 0xd0, 0x0d, 0x64, 0xa2, 0x78, 0x1e, 0x29, 0x4e, 0x93, 0xc3, 0xa4, 0x54, 0x14, 0x5b, 0x30, +0x82, 0x05, 0x41, 0x30, 0x82, 0x03, 0x29, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x0c, 0xbe, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, +0x51, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x57, 0x31, 0x12, +0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4e, 0x2d, +0x43, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x07, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x41, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x54, +0x57, 0x43, 0x41, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x32, 0x37, 0x30, 0x36, 0x32, 0x38, +0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, 0x35, 0x35, 0x39, 0x35, +0x39, 0x5a, 0x30, 0x51, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, +0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x54, 0x41, 0x49, 0x57, +0x41, 0x4e, 0x2d, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x07, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, +0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, +0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb0, 0x05, 0xdb, 0xc8, 0xeb, 0x8c, 0xc4, 0x6e, 0x8a, 0x21, +0xef, 0x8e, 0x4d, 0x9c, 0x71, 0x0a, 0x1f, 0x52, 0x70, 0xed, 0x6d, 0x82, 0x9c, 0x97, 0xc5, 0xd7, +0x4c, 0x4e, 0x45, 0x49, 0xcb, 0x40, 0x42, 0xb5, 0x12, 0x34, 0x6c, 0x19, 0xc2, 0x74, 0xa4, 0x31, +0x5f, 0x85, 0x02, 0x97, 0xec, 0x43, 0x33, 0x0a, 0x53, 0xd2, 0x9c, 0x8c, 0x8e, 0xb7, 0xb8, 0x79, +0xdb, 0x2b, 0xd5, 0x6a, 0xf2, 0x8e, 0x66, 0xc4, 0xee, 0x2b, 0x01, 0x07, 0x92, 0xd4, 0xb3, 0xd0, +0x02, 0xdf, 0x50, 0xf6, 0x55, 0xaf, 0x66, 0x0e, 0xcb, 0xe0, 0x47, 0x60, 0x2f, 0x2b, 0x32, 0x39, +0x35, 0x52, 0x3a, 0x28, 0x83, 0xf8, 0x7b, 0x16, 0xc6, 0x18, 0xb8, 0x62, 0xd6, 0x47, 0x25, 0x91, +0xce, 0xf0, 0x19, 0x12, 0x4d, 0xad, 0x63, 0xf5, 0xd3, 0x3f, 0x75, 0x5f, 0x29, 0xf0, 0xa1, 0x30, +0x1c, 0x2a, 0xa0, 0x98, 0xa6, 0x15, 0xbd, 0xee, 0xfd, 0x19, 0x36, 0xf0, 0xe2, 0x91, 0x43, 0x8f, +0xfa, 0xca, 0xd6, 0x10, 0x27, 0x49, 0x4c, 0xef, 0xdd, 0xc1, 0xf1, 0x85, 0x70, 0x9b, 0xca, 0xea, +0xa8, 0x5a, 0x43, 0xfc, 0x6d, 0x86, 0x6f, 0x73, 0xe9, 0x37, 0x45, 0xa9, 0xf0, 0x36, 0xc7, 0xcc, +0x88, 0x75, 0x1e, 0xbb, 0x6c, 0x06, 0xff, 0x9b, 0x6b, 0x3e, 0x17, 0xec, 0x61, 0xaa, 0x71, 0x7c, +0xc6, 0x1d, 0xa2, 0xf7, 0x49, 0xe9, 0x15, 0xb5, 0x3c, 0xd6, 0xa1, 0x61, 0xf5, 0x11, 0xf7, 0x05, +0x6f, 0x1d, 0xfd, 0x11, 0xbe, 0xd0, 0x30, 0x07, 0xc2, 0x29, 0xb0, 0x09, 0x4e, 0x26, 0xdc, 0xe3, +0xa2, 0xa8, 0x91, 0x6a, 0x1f, 0xc2, 0x91, 0x45, 0x88, 0x5c, 0xe5, 0x98, 0xb8, 0x71, 0xa5, 0x15, +0x19, 0xc9, 0x7c, 0x75, 0x11, 0xcc, 0x70, 0x74, 0x4f, 0x2d, 0x9b, 0x1d, 0x91, 0x44, 0xfd, 0x56, +0x28, 0xa0, 0xfe, 0xbb, 0x86, 0x6a, 0xc8, 0xfa, 0x5c, 0x0b, 0x58, 0xdc, 0xc6, 0x4b, 0x76, 0xc8, +0xab, 0x22, 0xd9, 0x73, 0x0f, 0xa5, 0xf4, 0x5a, 0x02, 0x89, 0x3f, 0x4f, 0x9e, 0x22, 0x82, 0xee, +0xa2, 0x74, 0x53, 0x2a, 0x3d, 0x53, 0x27, 0x69, 0x1d, 0x6c, 0x8e, 0x32, 0x2c, 0x64, 0x00, 0x26, +0x63, 0x61, 0x36, 0x4e, 0xa3, 0x46, 0xb7, 0x3f, 0x7d, 0xb3, 0x2d, 0xac, 0x6d, 0x90, 0xa2, 0x95, +0xa2, 0xce, 0xcf, 0xda, 0x82, 0xe7, 0x07, 0x34, 0x19, 0x96, 0xe9, 0xb8, 0x21, 0xaa, 0x29, 0x7e, +0xa6, 0x38, 0xbe, 0x8e, 0x29, 0x4a, 0x21, 0x66, 0x79, 0x1f, 0xb3, 0xc3, 0xb5, 0x09, 0x67, 0xde, +0xd6, 0xd4, 0x07, 0x46, 0xf3, 0x2a, 0xda, 0xe6, 0x22, 0x37, 0x60, 0xcb, 0x81, 0xb6, 0x0f, 0xa0, +0x0f, 0xe9, 0xc8, 0x95, 0x7f, 0xbf, 0x55, 0x91, 0x05, 0x7a, 0xcf, 0x3d, 0x15, 0xc0, 0x6f, 0xde, +0x09, 0x94, 0x01, 0x83, 0xd7, 0x34, 0x1b, 0xcc, 0x40, 0xa5, 0xf0, 0xb8, 0x9b, 0x67, 0xd5, 0x98, +0x91, 0x3b, 0xa7, 0x84, 0x78, 0x95, 0x26, 0xa4, 0x5a, 0x08, 0xf8, 0x2b, 0x74, 0xb4, 0x00, 0x04, +0x3c, 0xdf, 0xb8, 0x14, 0x8e, 0xe8, 0xdf, 0xa9, 0x8d, 0x6c, 0x67, 0x92, 0x33, 0x1d, 0xc0, 0xb7, +0xd2, 0xec, 0x92, 0xc8, 0xbe, 0x09, 0xbf, 0x2c, 0x29, 0x05, 0x6f, 0x02, 0x6b, 0x9e, 0xef, 0xbc, +0xbf, 0x2a, 0xbc, 0x5b, 0xc0, 0x50, 0x8f, 0x41, 0x70, 0x71, 0x87, 0xb2, 0x4d, 0xb7, 0x04, 0xa9, +0x84, 0xa3, 0x32, 0xaf, 0xae, 0xee, 0x6b, 0x17, 0x8b, 0xb2, 0xb1, 0xfe, 0x6c, 0xe1, 0x90, 0x8c, +0x88, 0xa8, 0x97, 0x48, 0xce, 0xc8, 0x4d, 0xcb, 0xf3, 0x06, 0xcf, 0x5f, 0x6a, 0x0a, 0x42, 0xb1, +0x1e, 0x1e, 0x77, 0x2f, 0x8e, 0xa0, 0xe6, 0x92, 0x0e, 0x06, 0xfc, 0x05, 0x22, 0xd2, 0x26, 0xe1, +0x31, 0x51, 0x7d, 0x32, 0xdc, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, +0x82, 0x02, 0x01, 0x00, 0x5f, 0x34, 0x81, 0x76, 0xef, 0x96, 0x1d, 0xd5, 0xe5, 0xb5, 0xd9, 0x02, +0x63, 0x84, 0x16, 0xc1, 0xae, 0xa0, 0x70, 0x51, 0xa7, 0xf7, 0x4c, 0x47, 0x35, 0xc8, 0x0b, 0xd7, +0x28, 0x3d, 0x89, 0x71, 0xd9, 0xaa, 0x33, 0x41, 0xea, 0x14, 0x1b, 0x6c, 0x21, 0x00, 0xc0, 0x6c, +0x42, 0x19, 0x7e, 0x9f, 0x69, 0x5b, 0x20, 0x42, 0xdf, 0xa2, 0xd2, 0xda, 0xc4, 0x7c, 0x97, 0x4b, +0x8d, 0xb0, 0xe8, 0xac, 0xc8, 0xee, 0xa5, 0x69, 0x04, 0x99, 0x0a, 0x92, 0xa6, 0xab, 0x27, 0x2e, +0x1a, 0x4d, 0x81, 0xbf, 0x84, 0xd4, 0x70, 0x1e, 0xad, 0x47, 0xfe, 0xfd, 0x4a, 0x9d, 0x33, 0xe0, +0xf2, 0xb9, 0xc4, 0x45, 0x08, 0x21, 0x0a, 0xda, 0x69, 0x69, 0x73, 0x72, 0x0d, 0xbe, 0x34, 0xfe, +0x94, 0x8b, 0xad, 0xc3, 0x1e, 0x35, 0xd7, 0xa2, 0x83, 0xef, 0xe5, 0x38, 0xc7, 0xa5, 0x85, 0x1f, +0xab, 0xcf, 0x34, 0xec, 0x3f, 0x28, 0xfe, 0x0c, 0xf1, 0x57, 0x86, 0x4e, 0xc9, 0x55, 0xf7, 0x1c, +0xd4, 0xd8, 0xa5, 0x7d, 0x06, 0x7a, 0x6f, 0xd5, 0xdf, 0x10, 0xdf, 0x81, 0x4e, 0x21, 0x65, 0xb1, +0xb6, 0xe1, 0x17, 0x79, 0x95, 0x45, 0x06, 0xce, 0x5f, 0xcc, 0xdc, 0x46, 0x89, 0x63, 0x68, 0x44, +0x8d, 0x93, 0xf4, 0x64, 0x70, 0xa0, 0x3d, 0x9d, 0x28, 0x05, 0xc3, 0x39, 0x70, 0xb8, 0x62, 0x7b, +0x20, 0xfd, 0xe4, 0xdb, 0xe9, 0x08, 0xa1, 0xb8, 0x9e, 0x3d, 0x09, 0xc7, 0x4f, 0xfb, 0x2c, 0xf8, +0x93, 0x76, 0x41, 0xde, 0x52, 0xe0, 0xe1, 0x57, 0xd2, 0x9d, 0x03, 0xbc, 0x77, 0x9e, 0xfe, 0x9e, +0x29, 0x5e, 0xf7, 0xc1, 0x51, 0x60, 0x1f, 0xde, 0xda, 0x0b, 0xb2, 0x2d, 0x75, 0xb7, 0x43, 0x48, +0x93, 0xe7, 0xf6, 0x79, 0xc6, 0x84, 0x5d, 0x80, 0x59, 0x60, 0x94, 0xfc, 0x78, 0x98, 0x8f, 0x3c, +0x93, 0x51, 0xed, 0x40, 0x90, 0x07, 0xdf, 0x64, 0x63, 0x24, 0xcb, 0x4e, 0x71, 0x05, 0xa1, 0xd7, +0x94, 0x1a, 0x88, 0x32, 0xf1, 0x22, 0x74, 0x22, 0xae, 0xa5, 0xa6, 0xd8, 0x12, 0x69, 0x4c, 0x60, +0xa3, 0x02, 0xee, 0x2b, 0xec, 0xd4, 0x63, 0x92, 0x0b, 0x5e, 0xbe, 0x2f, 0x76, 0x6b, 0xa3, 0xb6, +0x26, 0xbc, 0x8f, 0x03, 0xd8, 0x0a, 0xf2, 0x4c, 0x64, 0x46, 0xbd, 0x39, 0x62, 0xe5, 0x96, 0xeb, +0x34, 0x63, 0x11, 0x28, 0xcc, 0x95, 0xf1, 0xad, 0xef, 0xef, 0xdc, 0x80, 0x58, 0x48, 0xe9, 0x4b, +0xb8, 0xea, 0x65, 0xac, 0xe9, 0xfc, 0x80, 0xb5, 0xb5, 0xc8, 0x45, 0xf9, 0xac, 0xc1, 0x9f, 0xd9, +0xb9, 0xea, 0x62, 0x88, 0x8e, 0xc4, 0xf1, 0x4b, 0x83, 0x12, 0xad, 0xe6, 0x8b, 0x84, 0xd6, 0x9e, +0xc2, 0xeb, 0x83, 0x18, 0x9f, 0x6a, 0xbb, 0x1b, 0x24, 0x60, 0x33, 0x70, 0xcc, 0xec, 0xf7, 0x32, +0xf3, 0x5c, 0xd9, 0x79, 0x7d, 0xef, 0x9e, 0xa4, 0xfe, 0xc9, 0x23, 0xc3, 0x24, 0xee, 0x15, 0x92, +0xb1, 0x3d, 0x91, 0x4f, 0x26, 0x86, 0xbd, 0x66, 0x73, 0x24, 0x13, 0xea, 0xa4, 0xae, 0x63, 0xc1, +0xad, 0x7d, 0x84, 0x03, 0x3c, 0x10, 0x78, 0x86, 0x1b, 0x79, 0xe3, 0xc4, 0xf3, 0xf2, 0x04, 0x95, +0x20, 0xae, 0x23, 0x82, 0xc4, 0xb3, 0x3a, 0x00, 0x62, 0xbf, 0xe6, 0x36, 0x24, 0xe1, 0x57, 0xba, +0xc7, 0x1e, 0x90, 0x75, 0xd5, 0x5f, 0x3f, 0x95, 0x61, 0x2b, 0xc1, 0x3b, 0xcd, 0xe5, 0xb3, 0x68, +0x61, 0xd0, 0x46, 0x26, 0xa9, 0x21, 0x52, 0x69, 0x2d, 0xeb, 0x2e, 0xc7, 0xeb, 0x77, 0xce, 0xa6, +0x3a, 0xb5, 0x03, 0x33, 0x4f, 0x76, 0xd1, 0xe7, 0x5c, 0x54, 0x01, 0x5d, 0xcb, 0x78, 0xf4, 0xc9, +0x0c, 0xbf, 0xcf, 0x12, 0x8e, 0x17, 0x2d, 0x23, 0x68, 0x94, 0xe7, 0xab, 0xfe, 0xa9, 0xb2, 0x2b, +0x06, 0xd0, 0x04, 0xcd, 0x30, 0x82, 0x03, 0x7b, 0x30, 0x82, 0x02, 0x63, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x54, 0x41, 0x49, +0x57, 0x41, 0x4e, 0x2d, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, +0x07, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x38, 0x32, 0x38, 0x30, 0x37, +0x32, 0x34, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x31, 0x31, 0x35, 0x35, +0x39, 0x35, 0x39, 0x5a, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x54, 0x41, +0x49, 0x57, 0x41, 0x4e, 0x2d, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x0c, 0x07, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, +0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb0, 0x7e, 0x72, 0xb8, 0xa4, 0x03, 0x94, 0xe6, 0xa7, 0xde, +0x09, 0x38, 0x91, 0x4a, 0x11, 0x40, 0x87, 0xa7, 0x7c, 0x59, 0x64, 0x14, 0x7b, 0xb5, 0x11, 0x10, +0xdd, 0xfe, 0xbf, 0xd5, 0xc0, 0xbb, 0x56, 0xe2, 0x85, 0x25, 0xf4, 0x35, 0x72, 0x0f, 0xf8, 0x53, +0xd0, 0x41, 0xe1, 0x44, 0x01, 0xc2, 0xb4, 0x1c, 0xc3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, +0x76, 0xb2, 0x0a, 0x6f, 0x0f, 0xe5, 0x25, 0x50, 0x4f, 0x85, 0x86, 0xbe, 0xbf, 0x98, 0x2e, 0x10, +0x67, 0x1e, 0xbe, 0x11, 0x05, 0x86, 0x05, 0x90, 0xc4, 0x59, 0xd0, 0x7c, 0x78, 0x10, 0xb0, 0x80, +0x5c, 0xb7, 0xe1, 0xc7, 0x2b, 0x75, 0xcb, 0x7c, 0x9f, 0xae, 0xb5, 0xd1, 0x9d, 0x23, 0x37, 0x63, +0xa7, 0xdc, 0x42, 0xa2, 0x2d, 0x92, 0x04, 0x1b, 0x50, 0xc1, 0x7b, 0xb8, 0x3e, 0x1b, 0xc9, 0x56, +0x04, 0x8b, 0x2f, 0x52, 0x9b, 0xad, 0xa9, 0x56, 0xe9, 0xc1, 0xff, 0xad, 0xa9, 0x58, 0x87, 0x30, +0xb6, 0x81, 0xf7, 0x97, 0x45, 0xfc, 0x19, 0x57, 0x3b, 0x2b, 0x6f, 0xe4, 0x47, 0xf4, 0x99, 0x45, +0xfe, 0x1d, 0xf1, 0xf8, 0x97, 0xa3, 0x88, 0x1d, 0x37, 0x1c, 0x5c, 0x8f, 0xe0, 0x76, 0x25, 0x9a, +0x50, 0xf8, 0xa0, 0x54, 0xff, 0x44, 0x90, 0x76, 0x23, 0xd2, 0x32, 0xc6, 0xc3, 0xab, 0x06, 0xbf, +0xfc, 0xfb, 0xbf, 0xf3, 0xad, 0x7d, 0x92, 0x62, 0x02, 0x5b, 0x29, 0xd3, 0x35, 0xa3, 0x93, 0x9a, +0x43, 0x64, 0x60, 0x5d, 0xb2, 0xfa, 0x32, 0xff, 0x3b, 0x04, 0xaf, 0x4d, 0x40, 0x6a, 0xf9, 0xc7, +0xe3, 0xef, 0x23, 0xfd, 0x6b, 0xcb, 0xe5, 0x0f, 0x8b, 0x38, 0x0d, 0xee, 0x0a, 0xfc, 0xfe, 0x0f, +0x98, 0x9f, 0x30, 0x31, 0xdd, 0x6c, 0x52, 0x65, 0xf9, 0x8b, 0x81, 0xbe, 0x22, 0xe1, 0x1c, 0x58, +0x03, 0xba, 0x91, 0x1b, 0x89, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6a, 0x38, 0x5b, 0x26, 0x8d, +0xde, 0x8b, 0x5a, 0xf2, 0x4f, 0x7a, 0x54, 0x83, 0x19, 0x18, 0xe3, 0x08, 0x35, 0xa6, 0xba, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, +0x01, 0x01, 0x00, 0x3c, 0xd5, 0x77, 0x3d, 0xda, 0xdf, 0x89, 0xba, 0x87, 0x0c, 0x08, 0x54, 0x6a, +0x20, 0x50, 0x92, 0xbe, 0xb0, 0x41, 0x3d, 0xb9, 0x26, 0x64, 0x83, 0x0a, 0x2f, 0xe8, 0x40, 0xc0, +0x97, 0x28, 0x27, 0x82, 0x30, 0x4a, 0xc9, 0x93, 0xff, 0x6a, 0xe7, 0xa6, 0x00, 0x7f, 0x89, 0x42, +0x9a, 0xd6, 0x11, 0xe5, 0x53, 0xce, 0x2f, 0xcc, 0xf2, 0xda, 0x05, 0xc4, 0xfe, 0xe2, 0x50, 0xc4, +0x3a, 0x86, 0x7d, 0xcc, 0xda, 0x7e, 0x10, 0x09, 0x3b, 0x92, 0x35, 0x2a, 0x53, 0xb2, 0xfe, 0xeb, +0x2b, 0x05, 0xd9, 0x6c, 0x5d, 0xe6, 0xd0, 0xef, 0xd3, 0x6a, 0x66, 0x9e, 0x15, 0x28, 0x85, 0x7a, +0xe8, 0x82, 0x00, 0xac, 0x1e, 0xa7, 0x09, 0x69, 0x56, 0x42, 0xd3, 0x68, 0x51, 0x18, 0xbe, 0x54, +0x9a, 0xbf, 0x44, 0x41, 0xba, 0x49, 0xbe, 0x20, 0xba, 0x69, 0x5c, 0xee, 0xb8, 0x77, 0xcd, 0xce, +0x6c, 0x1f, 0xad, 0x83, 0x96, 0x18, 0x7d, 0x0e, 0xb5, 0x14, 0x39, 0x84, 0xf1, 0x28, 0xe9, 0x2d, +0xa3, 0x9e, 0x7b, 0x1e, 0x7a, 0x72, 0x5a, 0x83, 0xb3, 0x79, 0x6f, 0xef, 0xb4, 0xfc, 0xd0, 0x0a, +0xa5, 0x58, 0x4f, 0x46, 0xdf, 0xfb, 0x6d, 0x79, 0x59, 0xf2, 0x84, 0x22, 0x52, 0xae, 0x0f, 0xcc, +0xfb, 0x7c, 0x3b, 0xe7, 0x6a, 0xca, 0x47, 0x61, 0xc3, 0x7a, 0xf8, 0xd3, 0x92, 0x04, 0x1f, 0xb8, +0x20, 0x84, 0xe1, 0x36, 0x54, 0x16, 0xc7, 0x40, 0xde, 0x3b, 0x8a, 0x73, 0xdc, 0xdf, 0xc6, 0x09, +0x4c, 0xdf, 0xec, 0xda, 0xff, 0xd4, 0x53, 0x42, 0xa1, 0xc9, 0xf2, 0x62, 0x1d, 0x22, 0x83, 0x3c, +0x97, 0xc5, 0xf9, 0x19, 0x62, 0x27, 0xac, 0x65, 0x22, 0xd7, 0xd3, 0x3c, 0xc6, 0xe5, 0x8e, 0xb2, +0x53, 0xcc, 0x49, 0xce, 0xbc, 0x30, 0xfe, 0x7b, 0x0e, 0x33, 0x90, 0xfb, 0xed, 0xd2, 0x14, 0x91, +0x1f, 0x07, 0xaf, 0x30, 0x82, 0x05, 0xa2, 0x30, 0x82, 0x03, 0x8a, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x14, 0x01, 0x94, 0x30, 0x1e, 0xa2, 0x0b, 0xdd, 0xf5, 0xc5, 0x33, 0x2a, 0xb1, 0x43, 0x44, +0x71, 0xf8, 0xd6, 0x50, 0x4d, 0x0d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x4b, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1d, 0x4e, +0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49, 0x4e, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4c, +0x41, 0x54, 0x46, 0x4f, 0x52, 0x4d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x2e, 0x31, 0x32, 0x30, 0x30, +0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x29, 0x4e, 0x41, 0x56, 0x45, 0x52, 0x20, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x38, 0x31, 0x38, 0x30, 0x38, 0x35, 0x38, 0x34, 0x32, +0x5a, 0x17, 0x0d, 0x33, 0x37, 0x30, 0x38, 0x31, 0x38, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, +0x30, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, 0x52, 0x31, +0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x1d, 0x4e, 0x41, 0x56, 0x45, 0x52, 0x20, +0x42, 0x55, 0x53, 0x49, 0x4e, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52, +0x4d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x2e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, +0x0c, 0x29, 0x4e, 0x41, 0x56, 0x45, 0x52, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x02, 0x22, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, +0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb6, 0xd4, 0xf1, 0x93, +0x5c, 0xb5, 0x40, 0x89, 0x0a, 0xab, 0x0d, 0x90, 0x5b, 0x50, 0x63, 0xae, 0x90, 0x94, 0x74, 0x17, +0x45, 0x72, 0xd6, 0x7b, 0x65, 0x5a, 0x29, 0x4b, 0xa7, 0x56, 0xa0, 0x4b, 0xb8, 0x2f, 0x42, 0x75, +0xe9, 0xd9, 0x7b, 0x24, 0x5a, 0x31, 0x65, 0xab, 0x17, 0x17, 0xd1, 0x33, 0x3a, 0xd9, 0x11, 0xdc, +0x40, 0x36, 0x87, 0xdf, 0xc7, 0x6a, 0xe9, 0x26, 0x5e, 0x59, 0x8a, 0x77, 0xe3, 0xe8, 0x48, 0x9c, +0x31, 0x16, 0xfa, 0x3e, 0x91, 0xb1, 0xca, 0xc9, 0xa3, 0xe2, 0x9f, 0xce, 0x21, 0x53, 0xa3, 0x02, +0x36, 0x30, 0xcb, 0x52, 0x02, 0xe5, 0xda, 0x32, 0x5d, 0xc3, 0xc5, 0xe6, 0xf9, 0xee, 0x11, 0xc7, +0x8b, 0xc9, 0x44, 0x1e, 0x84, 0x93, 0x18, 0x4a, 0xb4, 0x9f, 0xe5, 0x12, 0x64, 0x69, 0xd0, 0x26, +0x85, 0x62, 0x01, 0xb6, 0xc9, 0x02, 0x1d, 0xbe, 0x83, 0x51, 0xbb, 0x5c, 0xda, 0xf8, 0xad, 0x15, +0x6a, 0x99, 0xf7, 0x92, 0x54, 0xf7, 0x34, 0x5b, 0xe9, 0xbf, 0xea, 0x29, 0x81, 0x12, 0xd4, 0x53, +0x91, 0x96, 0xb3, 0x91, 0x5a, 0xdd, 0xfe, 0x90, 0x73, 0x28, 0xfb, 0x30, 0x46, 0xb5, 0xca, 0x08, +0x07, 0xc7, 0x71, 0x72, 0xc9, 0x66, 0xd3, 0x34, 0x97, 0xf6, 0x8c, 0xf4, 0x18, 0x4a, 0xe1, 0xd0, +0x3d, 0x5a, 0x45, 0xb6, 0x69, 0xa7, 0x29, 0xfb, 0x23, 0xce, 0x88, 0xd8, 0x12, 0x9c, 0x00, 0x48, +0xa8, 0xa6, 0x0f, 0xb3, 0x3b, 0x92, 0x8d, 0x71, 0x0e, 0x74, 0xc5, 0x8b, 0xc8, 0x4c, 0xf9, 0xf4, +0x9b, 0x8e, 0xb8, 0x3c, 0x69, 0xed, 0x6f, 0x3b, 0x50, 0x2f, 0x58, 0xed, 0xc4, 0xb0, 0xd0, 0x1c, +0x1b, 0x6a, 0x0c, 0xe2, 0xbc, 0x44, 0xaa, 0xd8, 0xcd, 0x14, 0x5d, 0x94, 0x78, 0x61, 0xbf, 0x0e, +0x6e, 0xda, 0x2a, 0xbc, 0x2f, 0x0c, 0x0b, 0x71, 0xa6, 0xb3, 0x16, 0x3f, 0x9c, 0xe6, 0xf9, 0xcc, +0x9f, 0x53, 0x35, 0xe2, 0x03, 0xa0, 0xa0, 0x18, 0xbf, 0xbb, 0xf1, 0xbe, 0xf4, 0xd6, 0x8c, 0x87, +0x0d, 0x42, 0xf7, 0x06, 0xb9, 0xf1, 0x6d, 0xed, 0x04, 0x94, 0xa8, 0xfe, 0xb6, 0xd3, 0x06, 0xc6, +0x40, 0x61, 0xdf, 0x9d, 0x9d, 0xf3, 0x54, 0x76, 0xce, 0x53, 0x3a, 0x01, 0xa6, 0x92, 0x41, 0xec, +0x04, 0xa3, 0x8f, 0x0d, 0xa2, 0xd5, 0x09, 0xca, 0xd6, 0xcb, 0x9a, 0xf1, 0xef, 0x43, 0x5d, 0xc0, +0xab, 0xa5, 0x41, 0xcf, 0x5c, 0x53, 0x70, 0x70, 0xc9, 0x88, 0xa6, 0x2d, 0xd4, 0x6b, 0x61, 0x73, +0x50, 0x26, 0x86, 0x61, 0x0e, 0x5f, 0x1b, 0xc2, 0x2b, 0xe2, 0x8c, 0xd5, 0xbb, 0x9d, 0xc1, 0x03, +0x42, 0xba, 0x94, 0xda, 0x5f, 0xa9, 0xb0, 0xca, 0xcc, 0x4d, 0x0a, 0xef, 0x47, 0x69, 0x03, 0x2f, +0x22, 0xfb, 0xf1, 0x28, 0xce, 0xbf, 0x5d, 0x50, 0x65, 0xa8, 0x90, 0x6d, 0xb3, 0x74, 0xb0, 0x08, +0xc7, 0xac, 0xa8, 0xd1, 0xeb, 0x3e, 0x9c, 0xfc, 0x5d, 0x1a, 0x83, 0x2e, 0x2b, 0xcb, 0xb5, 0xf3, +0x44, 0x9d, 0x3a, 0xa7, 0x17, 0x61, 0x96, 0xa2, 0x71, 0xd3, 0x70, 0x96, 0x15, 0x4d, 0xb7, 0x4c, +0x73, 0xee, 0x19, 0x5c, 0xc5, 0x5b, 0x3e, 0x41, 0xfe, 0xac, 0x75, 0x60, 0x3b, 0x1b, 0x63, 0xce, +0x00, 0xdd, 0xda, 0x08, 0x90, 0x62, 0xb4, 0xe5, 0x2d, 0xee, 0x48, 0xa7, 0x6b, 0x17, 0x99, 0x54, +0xbe, 0x87, 0x4a, 0xe3, 0xa9, 0x5e, 0x04, 0x4c, 0xeb, 0x10, 0x6d, 0x54, 0xd6, 0xef, 0xf1, 0xe8, +0xf2, 0x62, 0x16, 0xcb, 0x80, 0x6b, 0xed, 0x3d, 0xed, 0xf5, 0x1f, 0x30, 0xa5, 0xae, 0x4b, 0xc9, +0x13, 0xed, 0x8a, 0x01, 0x01, 0xc9, 0xb8, 0x51, 0x58, 0xc0, 0x66, 0x3a, 0xb1, 0x66, 0x4b, 0xc4, +0xd5, 0x31, 0x02, 0x62, 0xe9, 0x74, 0x84, 0x0c, 0xdb, 0x4d, 0x46, 0x2d, 0x02, 0x03, 0x01, 0x00, +0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0xd2, 0x9f, 0x88, 0xdf, 0xa1, 0xcd, 0x2c, 0xbd, 0xec, 0xf5, 0x3b, 0x01, 0x01, 0x93, 0x33, 0x27, +0xb2, 0xeb, 0x60, 0x4b, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x32, 0xca, 0x80, 0xb3, 0x9d, 0x3d, 0x54, +0x06, 0xdd, 0xd2, 0xd2, 0x2e, 0xf0, 0xa4, 0x01, 0x21, 0x0b, 0x67, 0x48, 0xca, 0x6d, 0x8e, 0xe0, +0xc8, 0xaa, 0x0d, 0xaa, 0x8d, 0x21, 0x57, 0x8f, 0xc6, 0x3e, 0x7a, 0xca, 0xdb, 0x51, 0xd4, 0x52, +0xb3, 0xd4, 0x96, 0x84, 0xa5, 0x58, 0x60, 0x7f, 0xe5, 0x0b, 0x8e, 0x1f, 0xf5, 0xdc, 0x0a, 0x15, +0x81, 0xe5, 0x3b, 0xb6, 0xb7, 0x22, 0x2f, 0x09, 0x9c, 0x13, 0x16, 0xb1, 0x6c, 0x0c, 0x35, 0x08, +0x6d, 0xab, 0x63, 0x72, 0xed, 0xdc, 0xbe, 0xec, 0xc7, 0x57, 0xe6, 0x30, 0x20, 0x71, 0xd6, 0xd7, +0x10, 0xc1, 0x13, 0x55, 0x01, 0x8c, 0x2a, 0x43, 0xe4, 0x41, 0xf1, 0xcf, 0x3a, 0x7a, 0x53, 0x92, +0xce, 0xa2, 0x03, 0x05, 0x0d, 0x38, 0xdf, 0x02, 0xbb, 0x10, 0x2e, 0xd9, 0x3b, 0xd2, 0x9b, 0x7a, +0xc0, 0xa1, 0xa6, 0xf8, 0xb5, 0x31, 0xe6, 0xf4, 0x75, 0xc9, 0xb9, 0x53, 0x99, 0x75, 0x47, 0x22, +0x5a, 0x14, 0x15, 0xc7, 0x78, 0x1b, 0xb6, 0x9d, 0xe9, 0x0c, 0xf8, 0x1b, 0x76, 0xf1, 0x85, 0x84, +0xde, 0xa1, 0xda, 0x12, 0xef, 0xa4, 0xe2, 0x10, 0x97, 0x7a, 0x78, 0xde, 0x0c, 0x51, 0x97, 0xa8, +0x21, 0x40, 0x8b, 0x86, 0xbd, 0x0d, 0xf0, 0x5e, 0x4e, 0x4b, 0x36, 0xbb, 0x3b, 0x20, 0x1f, 0x8a, +0x42, 0x56, 0xe1, 0x0b, 0x1a, 0xbf, 0x7b, 0xd0, 0x22, 0x43, 0x2c, 0x44, 0x8c, 0xfb, 0xe5, 0x2a, +0xb4, 0x6c, 0x1c, 0x1c, 0xba, 0x94, 0xe0, 0x13, 0x7e, 0x21, 0xe6, 0x9a, 0xc2, 0xcb, 0xc5, 0x42, +0x64, 0xb4, 0x1e, 0x94, 0x7b, 0x08, 0x25, 0xc8, 0x71, 0xcc, 0x87, 0x45, 0x57, 0x85, 0xd3, 0x9f, +0x29, 0x62, 0x22, 0x83, 0x51, 0x97, 0x00, 0x18, 0x97, 0x77, 0x6a, 0x98, 0x92, 0xc9, 0x7c, 0x60, +0x6c, 0xdf, 0x6c, 0x7d, 0x4a, 0xe4, 0x70, 0x4c, 0xc2, 0x9e, 0xb8, 0x1d, 0xf7, 0xd0, 0x34, 0xc7, +0x0f, 0xcc, 0xfb, 0xa7, 0xff, 0x03, 0xbe, 0xad, 0x70, 0x90, 0xda, 0x0b, 0xdd, 0xc8, 0x6d, 0x97, +0x5f, 0x9a, 0x7f, 0x09, 0x32, 0x41, 0xfd, 0xcd, 0xa2, 0xcc, 0x5a, 0x6d, 0x4c, 0xf2, 0xaa, 0x49, +0xfe, 0x66, 0xf8, 0xe9, 0xd8, 0x35, 0xeb, 0x0e, 0x28, 0x1e, 0xee, 0x48, 0x2f, 0x3a, 0xd0, 0x79, +0x09, 0x38, 0x7c, 0xa6, 0x22, 0x82, 0x93, 0x95, 0xd0, 0x03, 0xbe, 0xbe, 0x02, 0xa0, 0x05, 0xdd, +0x20, 0x22, 0xe3, 0x6f, 0x1d, 0x88, 0x34, 0x60, 0xc6, 0xe6, 0x0a, 0xb9, 0x09, 0x75, 0x0b, 0xf0, +0x07, 0xe8, 0x69, 0x96, 0x35, 0xc7, 0xfb, 0x23, 0x81, 0x8e, 0x38, 0x39, 0xb8, 0x45, 0x2b, 0x43, +0x78, 0xa2, 0xd1, 0x2c, 0x14, 0xff, 0x0d, 0x28, 0x72, 0x72, 0x95, 0x9b, 0x5e, 0x09, 0xdb, 0x89, +0x44, 0x98, 0xaa, 0xa1, 0x49, 0xbb, 0x71, 0x52, 0xf2, 0xbf, 0xf6, 0xff, 0x27, 0xa1, 0x36, 0xaf, +0xb8, 0xb6, 0x77, 0x88, 0xdd, 0x3a, 0xa4, 0x6d, 0x9b, 0x34, 0x90, 0xdc, 0x14, 0x5d, 0x30, 0xbf, +0xb7, 0xeb, 0x17, 0xe4, 0x87, 0xb7, 0x71, 0xd0, 0xa1, 0xd7, 0x77, 0x15, 0xd4, 0x42, 0xd7, 0xf2, +0xf3, 0x31, 0x99, 0x5d, 0x9b, 0xdd, 0x16, 0x6d, 0x3f, 0xea, 0x06, 0x23, 0xf8, 0x46, 0xa2, 0x22, +0xed, 0x93, 0xf6, 0xdd, 0x9a, 0xe6, 0x2a, 0x87, 0xb1, 0x98, 0x54, 0xf1, 0x22, 0xf7, 0x6b, 0x45, +0xe3, 0xe2, 0x8e, 0x76, 0x1d, 0x9a, 0x8d, 0xc4, 0x06, 0x8d, 0x36, 0xb7, 0x14, 0xf3, 0x9d, 0x54, +0x69, 0xb7, 0x8e, 0x3c, 0xd5, 0xa4, 0x6d, 0x93, 0x81, 0xb7, 0xad, 0xf6, 0xbd, 0x64, 0x7b, 0xc2, +0xc9, 0x68, 0x39, 0xa0, 0x92, 0x9c, 0xcd, 0x34, 0x86, 0x91, 0x90, 0xfa, 0x64, 0x51, 0x9d, 0xfe, +0xfe, 0xeb, 0xa5, 0xf5, 0x75, 0xde, 0x89, 0xf7, 0x72, 0x30, 0x82, 0x05, 0x5a, 0x30, 0x82, 0x03, +0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x6e, 0x47, 0xa9, 0xc6, 0x5a, 0xb3, 0xe7, 0x20, +0xc5, 0x30, 0x9a, 0x3f, 0x68, 0x52, 0xf2, 0x6f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, 0x65, +0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, +0x55, 0x04, 0x03, 0x13, 0x0b, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x32, +0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, +0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, +0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, +0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, +0x4c, 0x4c, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x47, 0x54, +0x53, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, +0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0xde, 0xfd, 0xa6, 0xfb, 0xec, +0xec, 0x14, 0x34, 0x3c, 0x07, 0x06, 0x5a, 0x6c, 0x59, 0xf7, 0x19, 0x35, 0xdd, 0xf7, 0xc1, 0x9d, +0x55, 0xaa, 0xd3, 0xcd, 0x3b, 0xa4, 0x93, 0x72, 0xef, 0x0a, 0xfa, 0x6d, 0x9d, 0xf6, 0xf0, 0x85, +0x80, 0x5b, 0xa1, 0x48, 0x52, 0x9f, 0x39, 0xc5, 0xb7, 0xee, 0x28, 0xac, 0xef, 0xcb, 0x76, 0x68, +0x14, 0xb9, 0xdf, 0xad, 0x01, 0x6c, 0x99, 0x1f, 0xc4, 0x22, 0x1d, 0x9f, 0xfe, 0x72, 0x77, 0xe0, +0x2c, 0x5b, 0xaf, 0xe4, 0x04, 0xbf, 0x4f, 0x72, 0xa0, 0x1a, 0x34, 0x98, 0xe8, 0x39, 0x68, 0xec, +0x95, 0x25, 0x7b, 0x76, 0xa1, 0xe6, 0x69, 0xb9, 0x85, 0x19, 0xbd, 0x89, 0x8c, 0xfe, 0xad, 0xed, +0x36, 0xea, 0x73, 0xbc, 0xff, 0x83, 0xe2, 0xcb, 0x7d, 0xc1, 0xd2, 0xce, 0x4a, 0xb3, 0x8d, 0x05, +0x9e, 0x8b, 0x49, 0x93, 0xdf, 0xc1, 0x5b, 0xd0, 0x6e, 0x5e, 0xf0, 0x2e, 0x30, 0x2e, 0x82, 0xfc, +0xfa, 0xbc, 0xb4, 0x17, 0x0a, 0x48, 0xe5, 0x88, 0x9b, 0xc5, 0x9b, 0x6b, 0xde, 0xb0, 0xca, 0xb4, +0x03, 0xf0, 0xda, 0xf4, 0x90, 0xb8, 0x65, 0x64, 0xf7, 0x5c, 0x4c, 0xad, 0xe8, 0x7e, 0x66, 0x5e, +0x99, 0xd7, 0xb8, 0xc2, 0x3e, 0xc8, 0xd0, 0x13, 0x9d, 0xad, 0xee, 0xe4, 0x45, 0x7b, 0x89, 0x55, +0xf7, 0x8a, 0x1f, 0x62, 0x52, 0x84, 0x12, 0xb3, 0xc2, 0x40, 0x97, 0xe3, 0x8a, 0x1f, 0x47, 0x91, +0xa6, 0x74, 0x5a, 0xd2, 0xf8, 0xb1, 0x63, 0x28, 0x10, 0xb8, 0xb3, 0x09, 0xb8, 0x56, 0x77, 0x40, +0xa2, 0x26, 0x98, 0x79, 0xc6, 0xfe, 0xdf, 0x25, 0xee, 0x3e, 0xe5, 0xa0, 0x7f, 0xd4, 0x61, 0x0f, +0x51, 0x4b, 0x3c, 0x3f, 0x8c, 0xda, 0xe1, 0x70, 0x74, 0xd8, 0xc2, 0x68, 0xa1, 0xf9, 0xc1, 0x0c, +0xe9, 0xa1, 0xe2, 0x7f, 0xbb, 0x55, 0x3c, 0x76, 0x06, 0xee, 0x6a, 0x4e, 0xcc, 0x92, 0x88, 0x30, +0x4d, 0x9a, 0xbd, 0x4f, 0x0b, 0x48, 0x9a, 0x84, 0xb5, 0x98, 0xa3, 0xd5, 0xfb, 0x73, 0xc1, 0x57, +0x61, 0xdd, 0x28, 0x56, 0x75, 0x13, 0xae, 0x87, 0x8e, 0xe7, 0x0c, 0x51, 0x09, 0x10, 0x75, 0x88, +0x4c, 0xbc, 0x8d, 0xf9, 0x7b, 0x3c, 0xd4, 0x22, 0x48, 0x1f, 0x2a, 0xdc, 0xeb, 0x6b, 0xbb, 0x44, +0xb1, 0xcb, 0x33, 0x71, 0x32, 0x46, 0xaf, 0xad, 0x4a, 0xf1, 0x8c, 0xe8, 0x74, 0x3a, 0xac, 0xe7, +0x1a, 0x22, 0x73, 0x80, 0xd2, 0x30, 0xf7, 0x25, 0x42, 0xc7, 0x22, 0x3b, 0x3b, 0x12, 0xad, 0x96, +0x2e, 0xc6, 0xc3, 0x76, 0x07, 0xaa, 0x20, 0xb7, 0x35, 0x49, 0x57, 0xe9, 0x92, 0x49, 0xe8, 0x76, +0x16, 0x72, 0x31, 0x67, 0x2b, 0x96, 0x7e, 0x8a, 0xa3, 0xc7, 0x94, 0x56, 0x22, 0xbf, 0x6a, 0x4b, +0x7e, 0x01, 0x21, 0xb2, 0x23, 0x32, 0xdf, 0xe4, 0x9a, 0x44, 0x6d, 0x59, 0x5b, 0x5d, 0xf5, 0x00, +0xa0, 0x1c, 0x9b, 0xc6, 0x78, 0x97, 0x8d, 0x90, 0xff, 0x9b, 0xc8, 0xaa, 0xb4, 0xaf, 0x11, 0x51, +0x39, 0x5e, 0xd9, 0xfb, 0x67, 0xad, 0xd5, 0x5b, 0x11, 0x9d, 0x32, 0x9a, 0x1b, 0xbd, 0xd5, 0xba, +0x5b, 0xa5, 0xc9, 0xcb, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5c, 0xe0, 0xca, 0x36, 0xcb, 0x88, 0x61, +0xfb, 0x1e, 0xb7, 0xd0, 0xcb, 0xee, 0x16, 0xfb, 0xd3, 0xa6, 0x4c, 0xde, 0x92, 0xa5, 0xd4, 0xe2, +0xdf, 0xf5, 0x06, 0x54, 0xde, 0x2e, 0x9d, 0x4b, 0xb4, 0x93, 0x30, 0xaa, 0x81, 0xce, 0xdd, 0x1a, +0xdc, 0x51, 0x73, 0x0d, 0x4f, 0x70, 0xe9, 0xe5, 0xb6, 0x16, 0x21, 0x19, 0x79, 0xb2, 0xe6, 0x89, +0x0b, 0x75, 0x64, 0xca, 0xd5, 0xab, 0xbc, 0x09, 0xc1, 0x18, 0xa1, 0xff, 0xd4, 0x54, 0xa1, 0x85, +0x3c, 0xfd, 0x14, 0x24, 0x03, 0xb2, 0x87, 0xd3, 0xa4, 0xb7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xbb, +0xff, 0xca, 0x8e, 0x23, 0x9f, 0x4f, 0x99, 0xca, 0xdb, 0xe2, 0x68, 0xa6, 0xa5, 0x15, 0x27, 0x17, +0x1e, 0xd9, 0x0e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, +0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xb6, 0x69, 0xf0, 0xa6, 0x77, 0xfe, 0x9e, 0xee, 0x0b, +0x81, 0xad, 0xe1, 0xc0, 0xa9, 0xc7, 0xf9, 0x35, 0x1d, 0x40, 0x82, 0xab, 0xe6, 0x04, 0xb4, 0xdf, +0xcb, 0xf7, 0x1d, 0x0f, 0x83, 0xf0, 0x7e, 0x13, 0x4d, 0x8d, 0x8c, 0xee, 0xe3, 0x33, 0x22, 0xc3, +0x39, 0xfc, 0x40, 0xdf, 0x6e, 0x41, 0x4b, 0x42, 0x53, 0xbe, 0x16, 0x88, 0xf1, 0xd2, 0x38, 0x5e, +0xc4, 0x68, 0x99, 0x1c, 0x98, 0x52, 0x93, 0x8c, 0xe7, 0x68, 0xed, 0x1b, 0x6a, 0x73, 0x7a, 0x05, +0x40, 0x4d, 0x7f, 0x65, 0x3b, 0xd6, 0x58, 0xf1, 0xce, 0x83, 0x47, 0x60, 0xe3, 0xff, 0x97, 0xa9, +0x9c, 0x60, 0x77, 0x18, 0x55, 0xb5, 0x7e, 0x08, 0x93, 0xcf, 0xd0, 0xf6, 0x3c, 0x67, 0x03, 0x15, +0x61, 0x09, 0xf9, 0x81, 0x79, 0xf5, 0xec, 0x53, 0xa4, 0x9f, 0xc9, 0x8f, 0x01, 0x8b, 0x73, 0xc4, +0x77, 0x76, 0xdc, 0x83, 0xa2, 0xf5, 0x0c, 0x49, 0x1a, 0xa8, 0x76, 0xde, 0x92, 0x9b, 0x64, 0xf8, +0xb3, 0x2c, 0xc5, 0x27, 0xd3, 0x07, 0xc0, 0x08, 0x80, 0xa4, 0x98, 0x92, 0xe3, 0x01, 0x96, 0x02, +0xaa, 0x02, 0xee, 0x8f, 0x3b, 0xc5, 0xd1, 0x6d, 0x0a, 0x33, 0x30, 0x73, 0x78, 0xb9, 0x4f, 0x54, +0x16, 0xbf, 0x0b, 0x07, 0xa1, 0xa4, 0x5c, 0xe6, 0xcb, 0xc9, 0x5c, 0x84, 0x8f, 0x0f, 0xe0, 0x15, +0x77, 0x2c, 0x7e, 0x26, 0x7e, 0xda, 0xc4, 0x4b, 0xdb, 0xa7, 0x16, 0x77, 0x07, 0xb0, 0xcd, 0x75, +0xe8, 0x72, 0x42, 0xd6, 0x95, 0x84, 0x9d, 0x86, 0x83, 0xf2, 0xe4, 0x90, 0xcd, 0x09, 0x47, 0xd4, +0x8b, 0x03, 0x70, 0xda, 0x5a, 0xc6, 0x03, 0x42, 0xf4, 0xed, 0x37, 0xa2, 0xf0, 0x1b, 0x50, 0x54, +0x4b, 0x0e, 0xd8, 0x84, 0xde, 0x19, 0x28, 0x99, 0x81, 0x47, 0xae, 0x09, 0x1b, 0x3f, 0x48, 0xd1, +0xc3, 0x6f, 0xe2, 0xb0, 0x60, 0x17, 0xf5, 0xee, 0x23, 0x02, 0xa5, 0xda, 0x00, 0x5b, 0x6d, 0x90, +0xab, 0xee, 0xa2, 0xe9, 0x1b, 0x3b, 0xe9, 0xc7, 0x44, 0x27, 0x45, 0x8e, 0x6b, 0x9f, 0xf5, 0xa4, +0x84, 0xbc, 0x77, 0xf9, 0x6b, 0x97, 0xac, 0x3e, 0x51, 0x45, 0xa2, 0x11, 0xa6, 0xcc, 0x85, 0xee, +0x0a, 0x68, 0xf2, 0x3e, 0x50, 0x38, 0x7a, 0x24, 0x62, 0x1e, 0x17, 0x20, 0x37, 0x6d, 0x6a, 0x4d, +0xb7, 0x09, 0x9b, 0xc9, 0xfc, 0xa4, 0x58, 0xf5, 0xb6, 0xfb, 0x9c, 0x4e, 0x18, 0xbb, 0x95, 0x02, +0xe7, 0xa1, 0xad, 0x9b, 0x07, 0xee, 0x36, 0x6b, 0x24, 0xd2, 0x39, 0x86, 0xc1, 0x93, 0x83, 0x50, +0xd2, 0x81, 0x46, 0xa8, 0x5f, 0x62, 0x57, 0x2c, 0xbb, 0x6c, 0x64, 0x88, 0x08, 0x6e, 0xef, 0x13, +0x54, 0x5f, 0xdd, 0x2d, 0xc4, 0x67, 0x63, 0xd3, 0xcf, 0x89, 0x37, 0xbf, 0x9d, 0x20, 0xf4, 0xfb, +0x7a, 0x83, 0x9b, 0xa0, 0x1e, 0x81, 0x00, 0x50, 0xc2, 0xe4, 0x0c, 0x22, 0x59, 0x52, 0x10, 0xed, +0x43, 0x56, 0x87, 0x00, 0xf8, 0x14, 0x52, 0xa7, 0x1d, 0x8b, 0x93, 0x8c, 0xa2, 0x4d, 0x46, 0x7f, +0x27, 0xc6, 0x71, 0x9b, 0x24, 0xde, 0xe4, 0xda, 0x86, 0x8b, 0x0d, 0x7e, 0x6b, 0x20, 0xc1, 0xc0, +0x9e, 0xe1, 0x65, 0xd8, 0x6a, 0xa3, 0xa6, 0xe8, 0x85, 0x8b, 0x3a, 0x07, 0x08, 0x1c, 0xba, 0xf5, +0x8f, 0x55, 0x9a, 0x18, 0x75, 0x7e, 0xe5, 0xec, 0x81, 0x66, 0xd1, 0x21, 0x73, 0xa1, 0x35, 0x44, +0x0b, 0x80, 0x3d, 0x5b, 0x9c, 0x5e, 0x6f, 0x2a, 0x17, 0x96, 0xd1, 0x83, 0x23, 0x88, 0x66, 0x6d, +0xe6, 0x86, 0xe2, 0x70, 0x32, 0x2f, 0x52, 0x22, 0xe7, 0xc8, 0xe7, 0x7f, 0xc4, 0x2c, 0x60, 0x5d, +0x2f, 0xc3, 0xaf, 0x9e, 0x45, 0x05, 0xc3, 0x84, 0x02, 0xb7, 0xfd, 0x2c, 0x08, 0x52, 0x4f, 0x82, +0xdd, 0xa3, 0xf0, 0xd4, 0x86, 0x09, 0x02, 0x30, 0x82, 0x02, 0x0c, 0x30, 0x82, 0x01, 0x91, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x6e, 0x47, 0xa9, 0xc7, 0x6c, 0xa9, 0x73, 0x24, 0x40, 0x89, +0x0f, 0x03, 0x55, 0xdd, 0x8d, 0x1d, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, +0x03, 0x03, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, 0x67, +0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, +0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, +0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x36, 0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x36, +0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x47, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, +0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, 0x14, +0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x52, 0x33, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, +0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x1f, 0x4f, 0x33, 0x87, +0x33, 0x29, 0x8a, 0xa1, 0x84, 0xde, 0xcb, 0xc7, 0x21, 0x58, 0x41, 0x89, 0xea, 0x56, 0x9d, 0x2b, +0x4b, 0x85, 0xc6, 0x1d, 0x4c, 0x27, 0xbc, 0x7f, 0x26, 0x51, 0x72, 0x6f, 0xe2, 0x9f, 0xd6, 0xa3, +0xca, 0xcc, 0x45, 0x14, 0x46, 0x8b, 0xad, 0xef, 0x7e, 0x86, 0x8c, 0xec, 0xb1, 0x7e, 0x2f, 0xff, +0xa9, 0x71, 0x9d, 0x18, 0x84, 0x45, 0x04, 0x41, 0x55, 0x6e, 0x2b, 0xea, 0x26, 0x7f, 0xbb, 0x90, +0x01, 0xe3, 0x4b, 0x19, 0xba, 0xe4, 0x54, 0x96, 0x45, 0x09, 0xb1, 0xd5, 0x6c, 0x91, 0x44, 0xad, +0x84, 0x13, 0x8e, 0x9a, 0x8c, 0x0d, 0x80, 0x0c, 0x32, 0xf6, 0xe0, 0x27, 0xa3, 0x42, 0x30, 0x40, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc1, 0xf1, 0x26, 0xba, +0xa0, 0x2d, 0xae, 0x85, 0x81, 0xcf, 0xd3, 0xf1, 0x2a, 0x12, 0xbd, 0xb8, 0x0a, 0x67, 0xfd, 0xbc, +0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, +0x66, 0x02, 0x31, 0x00, 0x80, 0x5b, 0xa4, 0x7c, 0x23, 0xc0, 0x95, 0xa5, 0x2c, 0xdc, 0xbe, 0x89, +0x6f, 0x23, 0xb9, 0xa3, 0xdd, 0x65, 0x00, 0x52, 0x5e, 0x91, 0xac, 0xc8, 0x9d, 0x72, 0x74, 0x82, +0x53, 0x0b, 0x7d, 0xa9, 0x40, 0xbd, 0x68, 0x60, 0xc5, 0xe1, 0xb8, 0x54, 0x3b, 0xc1, 0x36, 0x17, +0x25, 0xd8, 0xc1, 0xbd, 0x02, 0x31, 0x00, 0x9e, 0x35, 0x92, 0x74, 0x85, 0x25, 0x51, 0xf5, 0x24, +0xec, 0x64, 0x52, 0x24, 0x50, 0xa5, 0x1f, 0xdb, 0xe8, 0xcb, 0xc9, 0x76, 0xec, 0xec, 0x82, 0x6e, +0xf5, 0x85, 0x18, 0x53, 0xe8, 0xb8, 0xe3, 0x9a, 0x29, 0xaa, 0x96, 0xd3, 0x83, 0x23, 0xc9, 0xa4, +0x7b, 0x61, 0xb3, 0xcc, 0x02, 0xe8, 0x5d, 0x30, 0x82, 0x02, 0x0a, 0x30, 0x82, 0x01, 0x91, 0xa0, +0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x6e, 0x47, 0xa9, 0xc8, 0x8b, 0x94, 0xb6, 0xe8, 0xbb, 0x3b, +0x2a, 0xd8, 0xa2, 0xb2, 0xc1, 0x99, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, +0x03, 0x03, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, +0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, 0x67, +0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, +0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, +0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x34, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x36, 0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x36, +0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x47, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, +0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, 0x14, +0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x52, 0x34, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, +0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xf3, 0x74, 0x73, 0xa7, +0x68, 0x8b, 0x60, 0xae, 0x43, 0xb8, 0x35, 0xc5, 0x81, 0x30, 0x7b, 0x4b, 0x49, 0x9d, 0xfb, 0xc1, +0x61, 0xce, 0xe6, 0xde, 0x46, 0xbd, 0x6b, 0xd5, 0x61, 0x18, 0x35, 0xae, 0x40, 0xdd, 0x73, 0xf7, +0x89, 0x91, 0x30, 0x5a, 0xeb, 0x3c, 0xee, 0x85, 0x7c, 0xa2, 0x40, 0x76, 0x3b, 0xa9, 0xc6, 0xb8, +0x47, 0xd8, 0x2a, 0xe7, 0x92, 0x91, 0x6a, 0x73, 0xe9, 0xb1, 0x72, 0x39, 0x9f, 0x29, 0x9f, 0xa2, +0x98, 0xd3, 0x5f, 0x5e, 0x58, 0x86, 0x65, 0x0f, 0xa1, 0x84, 0x65, 0x06, 0xd1, 0xdc, 0x8b, 0xc9, +0xc7, 0x73, 0xc8, 0x8c, 0x6a, 0x2f, 0xe5, 0xc4, 0xab, 0xd1, 0x1d, 0x8a, 0xa3, 0x42, 0x30, 0x40, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, +0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x80, 0x4c, 0xd6, 0xeb, +0x74, 0xff, 0x49, 0x36, 0xa3, 0xd5, 0xd8, 0xfc, 0xb5, 0x3e, 0xc5, 0x6a, 0xf0, 0x94, 0x1d, 0x8c, +0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, 0x30, +0x64, 0x02, 0x30, 0x6a, 0x50, 0x52, 0x74, 0x08, 0xc4, 0x70, 0xdc, 0x9e, 0x50, 0x74, 0x21, 0xe8, +0x8d, 0x7a, 0x21, 0xc3, 0x4f, 0x96, 0x6e, 0x15, 0xd1, 0x22, 0x35, 0x61, 0x2d, 0xfa, 0x08, 0x37, +0xee, 0x19, 0x6d, 0xad, 0xdb, 0xb2, 0xcc, 0x7d, 0x07, 0x34, 0xf5, 0x60, 0x19, 0x2c, 0xb5, 0x34, +0xd9, 0x6f, 0x20, 0x02, 0x30, 0x03, 0x71, 0xb1, 0xba, 0xa3, 0x60, 0x0b, 0x86, 0xed, 0x9a, 0x08, +0x6a, 0x95, 0x68, 0x9f, 0xe2, 0xb3, 0xe1, 0x93, 0x64, 0x7c, 0x5e, 0x93, 0xa6, 0xdf, 0x79, 0x2d, +0x8d, 0x85, 0xe3, 0x94, 0xcf, 0x23, 0x5d, 0x71, 0xcc, 0xf2, 0xb0, 0x4d, 0xd6, 0xfe, 0x99, 0xc8, +0x94, 0xa9, 0x75, 0xa2, 0xe3, 0x30, 0x82, 0x05, 0x5a, 0x30, 0x82, 0x03, 0x42, 0xa0, 0x03, 0x02, +0x01, 0x02, 0x02, 0x10, 0x6e, 0x47, 0xa9, 0xc5, 0x4b, 0x47, 0x0c, 0x0d, 0xec, 0x33, 0xd0, 0x89, +0xb9, 0x1c, 0xf4, 0xe1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0c, 0x05, 0x00, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, +0x67, 0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, +0x65, 0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x0b, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x31, 0x30, 0x1e, 0x17, 0x0d, +0x31, 0x36, 0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, +0x36, 0x30, 0x36, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x47, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x72, 0x75, +0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x4c, 0x4c, 0x43, 0x31, +0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x52, 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, +0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb6, 0x11, 0x02, 0x8b, 0x1e, 0xe3, 0xa1, 0x77, 0x9b, 0x3b, +0xdc, 0xbf, 0x94, 0x3e, 0xb7, 0x95, 0xa7, 0x40, 0x3c, 0xa1, 0xfd, 0x82, 0xf9, 0x7d, 0x32, 0x06, +0x82, 0x71, 0xf6, 0xf6, 0x8c, 0x7f, 0xfb, 0xe8, 0xdb, 0xbc, 0x6a, 0x2e, 0x97, 0x97, 0xa3, 0x8c, +0x4b, 0xf9, 0x2b, 0xf6, 0xb1, 0xf9, 0xce, 0x84, 0x1d, 0xb1, 0xf9, 0xc5, 0x97, 0xde, 0xef, 0xb9, +0xf2, 0xa3, 0xe9, 0xbc, 0x12, 0x89, 0x5e, 0xa7, 0xaa, 0x52, 0xab, 0xf8, 0x23, 0x27, 0xcb, 0xa4, +0xb1, 0x9c, 0x63, 0xdb, 0xd7, 0x99, 0x7e, 0xf0, 0x0a, 0x5e, 0xeb, 0x68, 0xa6, 0xf4, 0xc6, 0x5a, +0x47, 0x0d, 0x4d, 0x10, 0x33, 0xe3, 0x4e, 0xb1, 0x13, 0xa3, 0xc8, 0x18, 0x6c, 0x4b, 0xec, 0xfc, +0x09, 0x90, 0xdf, 0x9d, 0x64, 0x29, 0x25, 0x23, 0x07, 0xa1, 0xb4, 0xd2, 0x3d, 0x2e, 0x60, 0xe0, +0xcf, 0xd2, 0x09, 0x87, 0xbb, 0xcd, 0x48, 0xf0, 0x4d, 0xc2, 0xc2, 0x7a, 0x88, 0x8a, 0xbb, 0xba, +0xcf, 0x59, 0x19, 0xd6, 0xaf, 0x8f, 0xb0, 0x07, 0xb0, 0x9e, 0x31, 0xf1, 0x82, 0xc1, 0xc0, 0xdf, +0x2e, 0xa6, 0x6d, 0x6c, 0x19, 0x0e, 0xb5, 0xd8, 0x7e, 0x26, 0x1a, 0x45, 0x03, 0x3d, 0xb0, 0x79, +0xa4, 0x94, 0x28, 0xad, 0x0f, 0x7f, 0x26, 0xe5, 0xa8, 0x08, 0xfe, 0x96, 0xe8, 0x3c, 0x68, 0x94, +0x53, 0xee, 0x83, 0x3a, 0x88, 0x2b, 0x15, 0x96, 0x09, 0xb2, 0xe0, 0x7a, 0x8c, 0x2e, 0x75, 0xd6, +0x9c, 0xeb, 0xa7, 0x56, 0x64, 0x8f, 0x96, 0x4f, 0x68, 0xae, 0x3d, 0x97, 0xc2, 0x84, 0x8f, 0xc0, +0xbc, 0x40, 0xc0, 0x0b, 0x5c, 0xbd, 0xf6, 0x87, 0xb3, 0x35, 0x6c, 0xac, 0x18, 0x50, 0x7f, 0x84, +0xe0, 0x4c, 0xcd, 0x92, 0xd3, 0x20, 0xe9, 0x33, 0xbc, 0x52, 0x99, 0xaf, 0x32, 0xb5, 0x29, 0xb3, +0x25, 0x2a, 0xb4, 0x48, 0xf9, 0x72, 0xe1, 0xca, 0x64, 0xf7, 0xe6, 0x82, 0x10, 0x8d, 0xe8, 0x9d, +0xc2, 0x8a, 0x88, 0xfa, 0x38, 0x66, 0x8a, 0xfc, 0x63, 0xf9, 0x01, 0xf9, 0x78, 0xfd, 0x7b, 0x5c, +0x77, 0xfa, 0x76, 0x87, 0xfa, 0xec, 0xdf, 0xb1, 0x0e, 0x79, 0x95, 0x57, 0xb4, 0xbd, 0x26, 0xef, +0xd6, 0x01, 0xd1, 0xeb, 0x16, 0x0a, 0xbb, 0x8e, 0x0b, 0xb5, 0xc5, 0xc5, 0x8a, 0x55, 0xab, 0xd3, +0xac, 0xea, 0x91, 0x4b, 0x29, 0xcc, 0x19, 0xa4, 0x32, 0x25, 0x4e, 0x2a, 0xf1, 0x65, 0x44, 0xd0, +0x02, 0xce, 0xaa, 0xce, 0x49, 0xb4, 0xea, 0x9f, 0x7c, 0x83, 0xb0, 0x40, 0x7b, 0xe7, 0x43, 0xab, +0xa7, 0x6c, 0xa3, 0x8f, 0x7d, 0x89, 0x81, 0xfa, 0x4c, 0xa5, 0xff, 0xd5, 0x8e, 0xc3, 0xce, 0x4b, +0xe0, 0xb5, 0xd8, 0xb3, 0x8e, 0x45, 0xcf, 0x76, 0xc0, 0xed, 0x40, 0x2b, 0xfd, 0x53, 0x0f, 0xb0, +0xa7, 0xd5, 0x3b, 0x0d, 0xb1, 0x8a, 0xa2, 0x03, 0xde, 0x31, 0xad, 0xcc, 0x77, 0xea, 0x6f, 0x7b, +0x3e, 0xd6, 0xdf, 0x91, 0x22, 0x12, 0xe6, 0xbe, 0xfa, 0xd8, 0x32, 0xfc, 0x10, 0x63, 0x14, 0x51, +0x72, 0xde, 0x5d, 0xd6, 0x16, 0x93, 0xbd, 0x29, 0x68, 0x33, 0xef, 0x3a, 0x66, 0xec, 0x07, 0x8a, +0x26, 0xdf, 0x13, 0xd7, 0x57, 0x65, 0x78, 0x27, 0xde, 0x5e, 0x49, 0x14, 0x00, 0xa2, 0x00, 0x7f, +0x9a, 0xa8, 0x21, 0xb6, 0xa9, 0xb1, 0x95, 0xb0, 0xa5, 0xb9, 0x0d, 0x16, 0x11, 0xda, 0xc7, 0x6c, +0x48, 0x3c, 0x40, 0xe0, 0x7e, 0x0d, 0x5a, 0xcd, 0x56, 0x3c, 0xd1, 0x97, 0x05, 0xb9, 0xcb, 0x4b, +0xed, 0x39, 0x4b, 0x9c, 0xc4, 0x3f, 0xd2, 0x55, 0x13, 0x6e, 0x24, 0xb0, 0xd6, 0x71, 0xfa, 0xf4, +0xc1, 0xba, 0xcc, 0xed, 0x1b, 0xf5, 0xfe, 0x81, 0x41, 0xd8, 0x00, 0x98, 0x3d, 0x3a, 0xc8, 0xae, +0x7a, 0x98, 0x37, 0x18, 0x05, 0x95, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe4, 0xaf, 0x2b, 0x26, 0x71, +0x1a, 0x2b, 0x48, 0x27, 0x85, 0x2f, 0x52, 0x66, 0x2c, 0xef, 0xf0, 0x89, 0x13, 0x71, 0x3e, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, +0x02, 0x01, 0x00, 0x38, 0x96, 0x0a, 0xee, 0x3d, 0xb4, 0x96, 0x1e, 0x5f, 0xef, 0x9d, 0x9c, 0x0b, +0x33, 0x9f, 0x2b, 0xe0, 0xca, 0xfd, 0xd2, 0x8e, 0x0a, 0x1f, 0x41, 0x74, 0xa5, 0x7c, 0xaa, 0x84, +0xd4, 0xe5, 0xf2, 0x1e, 0xe6, 0x37, 0x52, 0x32, 0x9c, 0x0b, 0xd1, 0x61, 0x1d, 0xbf, 0x28, 0xc1, +0xb6, 0x44, 0x29, 0x35, 0x75, 0x77, 0x98, 0xb2, 0x7c, 0xd9, 0xbd, 0x74, 0xac, 0x8a, 0x68, 0xe3, +0xa9, 0x31, 0x09, 0x29, 0x01, 0x60, 0x73, 0xe3, 0x47, 0x7c, 0x53, 0xa8, 0x90, 0x4a, 0x27, 0xef, +0x4b, 0xd7, 0x9f, 0x93, 0xe7, 0x82, 0x36, 0xce, 0x9a, 0x68, 0x0c, 0x82, 0xe7, 0xcf, 0xd4, 0x10, +0x16, 0x6f, 0x5f, 0x0e, 0x99, 0x5c, 0xf6, 0x1f, 0x71, 0x7d, 0xef, 0xef, 0x7b, 0x2f, 0x7e, 0xea, +0x36, 0xd6, 0x97, 0x70, 0x0b, 0x15, 0xee, 0xd7, 0x5c, 0x56, 0x6a, 0x33, 0xa5, 0xe3, 0x49, 0x38, +0x0c, 0xb8, 0x7d, 0xfb, 0x8d, 0x85, 0xa4, 0xb1, 0x59, 0x5e, 0xf4, 0x6a, 0xe1, 0xdd, 0xa1, 0xf6, +0x64, 0x44, 0xae, 0xe6, 0x51, 0x83, 0x21, 0x66, 0xc6, 0x11, 0x3e, 0xf3, 0xce, 0x47, 0xee, 0x9c, +0x28, 0x1f, 0x25, 0xda, 0xff, 0xac, 0x66, 0x95, 0xdd, 0x35, 0x0f, 0x5c, 0xef, 0x20, 0x2c, 0x62, +0xfd, 0x91, 0xba, 0xa9, 0xcc, 0xfc, 0x5a, 0x9c, 0x93, 0x81, 0x83, 0x29, 0x97, 0x4a, 0x7c, 0x5a, +0x72, 0xb4, 0x39, 0xd0, 0xb7, 0x77, 0xcb, 0x79, 0xfd, 0x69, 0x3a, 0x92, 0x37, 0xed, 0x6e, 0x38, +0x65, 0x46, 0x7e, 0xe9, 0x60, 0xbd, 0x79, 0x88, 0x97, 0x5f, 0x38, 0x12, 0xf4, 0xee, 0xaf, 0x5b, +0x82, 0xc8, 0x86, 0xd5, 0xe1, 0x99, 0x6d, 0x8c, 0x04, 0xf2, 0x76, 0xba, 0x49, 0xf6, 0x6e, 0xe9, +0x6d, 0x1e, 0x5f, 0xa0, 0xef, 0x27, 0x82, 0x76, 0x40, 0xf8, 0xa6, 0xd3, 0x58, 0x5c, 0x0f, 0x2c, +0x42, 0xda, 0x42, 0xc6, 0x7b, 0x88, 0x34, 0xc7, 0xc1, 0xd8, 0x45, 0x9b, 0xc1, 0x3e, 0xc5, 0x61, +0x1d, 0xd9, 0x63, 0x50, 0x49, 0xf6, 0x34, 0x85, 0x6a, 0xe0, 0x18, 0xc5, 0x6e, 0x47, 0xab, 0x41, +0x42, 0x29, 0x9b, 0xf6, 0x60, 0x0d, 0xd2, 0x31, 0xd3, 0x63, 0x98, 0x23, 0x93, 0x5a, 0x00, 0x81, +0x48, 0xb4, 0xef, 0xcd, 0x8a, 0xcd, 0xc9, 0xcf, 0x99, 0xee, 0xd9, 0x9e, 0xaa, 0x36, 0xe1, 0x68, +0x4b, 0x71, 0x49, 0x14, 0x36, 0x28, 0x3a, 0x3d, 0x1d, 0xce, 0x9a, 0x8f, 0x25, 0xe6, 0x80, 0x71, +0x61, 0x2b, 0xb5, 0x7b, 0xcc, 0xf9, 0x25, 0x16, 0x81, 0xe1, 0x31, 0x5f, 0xa1, 0xa3, 0x7e, 0x16, +0xa4, 0x9c, 0x16, 0x6a, 0x97, 0x18, 0xbd, 0x76, 0x72, 0xa5, 0x0b, 0x9e, 0x1d, 0x36, 0xe6, 0x2f, +0xa1, 0x2f, 0xbe, 0x70, 0x91, 0x0f, 0xa8, 0xe6, 0xda, 0xf8, 0xc4, 0x92, 0x40, 0x6c, 0x25, 0x7e, +0x7b, 0xb3, 0x09, 0xdc, 0xb2, 0x17, 0xad, 0x80, 0x44, 0xf0, 0x68, 0xa5, 0x8f, 0x94, 0x75, 0xff, +0x74, 0x5a, 0xe8, 0xa8, 0x02, 0x7c, 0x0c, 0x09, 0xe2, 0xa9, 0x4b, 0x0b, 0xa0, 0x85, 0x0b, 0x62, +0xb9, 0xef, 0xa1, 0x31, 0x92, 0xfb, 0xef, 0xf6, 0x51, 0x04, 0x89, 0x6c, 0xe8, 0xa9, 0x74, 0xa1, +0xbb, 0x17, 0xb3, 0xb5, 0xfd, 0x49, 0x0f, 0x7c, 0x3c, 0xec, 0x83, 0x18, 0x20, 0x43, 0x4e, 0xd5, +0x93, 0xba, 0xb4, 0x34, 0xb1, 0x1f, 0x16, 0x36, 0x1f, 0x0c, 0xe6, 0x64, 0x39, 0x16, 0x4c, 0xdc, +0xe0, 0xfe, 0x1d, 0xc8, 0xa9, 0x62, 0x3d, 0x40, 0xea, 0xca, 0xc5, 0x34, 0x02, 0xb4, 0xae, 0x89, +0x88, 0x33, 0x35, 0xdc, 0x2c, 0x13, 0x73, 0xd8, 0x27, 0xf1, 0xd0, 0x72, 0xee, 0x75, 0x3b, 0x22, +0xde, 0x98, 0x68, 0x66, 0x5b, 0xf1, 0xc6, 0x63, 0x47, 0x55, 0x1c, 0xba, 0xa5, 0x08, 0x51, 0x75, +0xa6, 0x48, 0x25, 0x30, 0x82, 0x05, 0x5a, 0x30, 0x82, 0x03, 0x42, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x12, 0x11, 0xd2, 0xbb, 0xb9, 0xd7, 0x23, 0x18, 0x9e, 0x40, 0x5f, 0x0a, 0x9d, 0x2d, 0xd0, +0xdf, 0x25, 0x67, 0xd1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0c, 0x05, 0x00, 0x30, 0x46, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, 0x73, 0x61, 0x31, 0x1c, 0x30, +0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, +0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x52, 0x34, 0x36, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x39, 0x30, 0x33, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, +0x30, 0x33, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x46, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, +0x6e, 0x76, 0x2d, 0x73, 0x61, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, +0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x52, 0x34, 0x36, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, +0x82, 0x02, 0x01, 0x00, 0xac, 0xac, 0x74, 0x32, 0xe8, 0xb3, 0x65, 0xe5, 0xba, 0xed, 0x43, 0x26, +0x1d, 0xa6, 0x89, 0x0d, 0x45, 0xba, 0x29, 0x88, 0xb2, 0xa4, 0x1d, 0x63, 0xdd, 0xd3, 0xc1, 0x2c, +0x09, 0x57, 0x89, 0x39, 0xa1, 0x55, 0xe9, 0x67, 0x34, 0x77, 0x0c, 0x6e, 0xe4, 0x55, 0x1d, 0x52, +0x25, 0xd2, 0x13, 0x6b, 0x5e, 0xe1, 0x1d, 0xa9, 0xb7, 0x7d, 0x89, 0x32, 0x5f, 0x0d, 0x9e, 0x9f, +0x2c, 0x7a, 0x63, 0x60, 0x40, 0x1f, 0xa6, 0xb0, 0xb6, 0x78, 0x8f, 0x99, 0x54, 0x96, 0x08, 0x58, +0xae, 0xe4, 0x06, 0xbc, 0x62, 0x05, 0x02, 0x16, 0xbf, 0xaf, 0xa8, 0x23, 0x03, 0xb6, 0x94, 0x0f, +0xbc, 0x6e, 0x6c, 0xc2, 0xcb, 0xd5, 0xa6, 0xbb, 0x0c, 0xe9, 0xf6, 0xc1, 0x02, 0xfb, 0x21, 0xde, +0x66, 0xdd, 0x17, 0xab, 0x74, 0x42, 0xef, 0xf0, 0x74, 0x2f, 0x25, 0xf4, 0xea, 0x6b, 0x55, 0x5b, +0x90, 0xdb, 0x9d, 0xdf, 0x5e, 0x87, 0x0a, 0x40, 0xfb, 0xad, 0x19, 0x6b, 0xfb, 0xf7, 0xca, 0x60, +0x88, 0xde, 0xda, 0xc1, 0x8f, 0xd6, 0xae, 0xd5, 0x7f, 0xd4, 0x3c, 0x83, 0xee, 0xd7, 0x16, 0x4c, +0x83, 0x45, 0x33, 0x6b, 0x27, 0xd0, 0x86, 0xd0, 0x1c, 0x2d, 0x6b, 0xf3, 0xab, 0x7d, 0xf1, 0x85, +0xa9, 0xf5, 0x28, 0xd2, 0xad, 0xef, 0xf3, 0x84, 0x4b, 0x1c, 0x87, 0xfc, 0x13, 0xa3, 0x3a, 0x72, +0xa2, 0x5a, 0x11, 0x2b, 0xd6, 0x27, 0x71, 0x27, 0xed, 0x81, 0x2d, 0x6d, 0x66, 0x81, 0x92, 0x87, +0xb4, 0x1b, 0x58, 0x7a, 0xcc, 0x3f, 0x0a, 0xfa, 0x46, 0x4f, 0x4d, 0x78, 0x5c, 0xf8, 0x2b, 0x48, +0xe3, 0x04, 0x84, 0xcb, 0x5d, 0xf6, 0xb4, 0x6a, 0xb3, 0x65, 0xfc, 0x42, 0x9e, 0x51, 0x26, 0x23, +0x20, 0xcb, 0x3d, 0x14, 0xf9, 0x81, 0xed, 0x65, 0x16, 0x00, 0x4f, 0x1a, 0x64, 0x97, 0x66, 0x08, +0xcf, 0x8c, 0x7b, 0xe3, 0x2b, 0xc0, 0x9d, 0xf9, 0x14, 0xf2, 0x1b, 0xf1, 0x56, 0x6a, 0x16, 0xbf, +0x2c, 0x85, 0x85, 0xcd, 0x78, 0x38, 0x9a, 0xeb, 0x42, 0x6a, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4e, +0x94, 0x56, 0xf8, 0xb6, 0x82, 0xb5, 0xf3, 0x96, 0xdd, 0x3d, 0xf3, 0xbe, 0x7f, 0x20, 0x77, 0x3e, +0x7b, 0x19, 0x23, 0x6b, 0x2c, 0xd4, 0x72, 0x73, 0x43, 0x57, 0x7d, 0xe0, 0xf8, 0xd7, 0x69, 0x4f, +0x17, 0x36, 0x04, 0xf9, 0xc0, 0x90, 0x60, 0x37, 0x45, 0xde, 0xe6, 0x0c, 0xd8, 0x74, 0x8d, 0xae, +0x9c, 0xa2, 0x6d, 0x74, 0x5d, 0x42, 0xbe, 0x06, 0xf5, 0xd9, 0x64, 0x6e, 0x02, 0x10, 0xac, 0x89, +0xb0, 0x4c, 0x3b, 0x07, 0x4d, 0x40, 0x7e, 0x24, 0xc5, 0x8a, 0x98, 0x82, 0x79, 0x8e, 0xa4, 0xa7, +0x82, 0x20, 0x8d, 0x23, 0xfa, 0x27, 0x71, 0xc9, 0xdf, 0xc6, 0x41, 0x74, 0xa0, 0x4d, 0xf6, 0x91, +0x16, 0xdc, 0x46, 0x8c, 0x5f, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0c, 0xd8, 0x6f, 0xc2, 0xb6, 0x32, +0x7d, 0xfb, 0xe6, 0x5d, 0x53, 0xa6, 0x7e, 0x15, 0xfc, 0xbb, 0x75, 0x7c, 0x5d, 0xec, 0xf8, 0xf6, +0x17, 0x1c, 0xec, 0xc7, 0x6b, 0x19, 0xcb, 0xf3, 0x7b, 0xf0, 0x2b, 0x07, 0xa5, 0xd9, 0x6c, 0x79, +0x54, 0x76, 0x6c, 0x9d, 0x1c, 0xa6, 0x6e, 0x0e, 0xe9, 0x79, 0x0c, 0xa8, 0x23, 0x6a, 0xa3, 0xdf, +0x1b, 0x30, 0x31, 0x9f, 0xb1, 0x54, 0x7b, 0xfe, 0x6a, 0xcb, 0x66, 0xaa, 0xdc, 0x65, 0xd0, 0xa2, +0x9e, 0x4a, 0x9a, 0x07, 0x21, 0x6b, 0x81, 0x8f, 0xdb, 0xc4, 0x59, 0xfa, 0xde, 0x22, 0xc0, 0x04, +0x9c, 0xe3, 0xaa, 0x5b, 0x36, 0x93, 0xe8, 0x3d, 0xbd, 0x7a, 0xa1, 0x9d, 0x0b, 0x76, 0xb1, 0x0b, +0xc7, 0x9d, 0xfd, 0xcf, 0x98, 0xa8, 0x06, 0xc2, 0xf8, 0x2a, 0xa3, 0xa1, 0x83, 0xa0, 0xb7, 0x25, +0x72, 0xa5, 0x02, 0xe3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x03, 0x5c, 0xab, 0x73, 0x81, 0x87, 0xa8, +0xcc, 0xb0, 0xa6, 0xd5, 0x94, 0xe2, 0x36, 0x96, 0x49, 0xff, 0x05, 0x99, 0x2c, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, +0x00, 0x7c, 0x78, 0xec, 0xf6, 0x02, 0x2c, 0xbb, 0x5b, 0x7e, 0x92, 0x2b, 0x5d, 0x39, 0xdc, 0xbe, +0xd8, 0x1d, 0xa2, 0x42, 0x33, 0x4d, 0xf9, 0xef, 0xa4, 0x2a, 0x3b, 0x44, 0x69, 0x1e, 0xac, 0xd9, +0x45, 0xa3, 0x4e, 0x3c, 0xa7, 0xd8, 0x24, 0x51, 0xb2, 0x54, 0x1c, 0x93, 0x4e, 0xc4, 0xef, 0x7b, +0x93, 0x85, 0x60, 0x26, 0xea, 0x09, 0x48, 0xe0, 0xf5, 0xbb, 0xc7, 0xe9, 0x68, 0xd2, 0xbb, 0x6a, +0x31, 0x71, 0xcc, 0x79, 0xae, 0x11, 0xa8, 0xf0, 0x99, 0xfd, 0xe5, 0x1f, 0xbc, 0x2f, 0xa8, 0xcc, +0x57, 0xeb, 0x76, 0xc4, 0x21, 0xa6, 0x47, 0x53, 0x55, 0x4d, 0x68, 0xbf, 0x05, 0xa4, 0xee, 0xd7, +0x26, 0xab, 0x62, 0xda, 0x43, 0x37, 0x4b, 0xe2, 0xc6, 0xb5, 0xe5, 0xb2, 0x83, 0x19, 0x3a, 0xc7, +0xd3, 0xdb, 0x4d, 0x9e, 0x08, 0x7a, 0xf3, 0xee, 0xcf, 0x3e, 0x62, 0xfb, 0xac, 0xe8, 0x60, 0xcc, +0xd1, 0xc7, 0xa1, 0x5c, 0x83, 0x45, 0xc4, 0x45, 0xcc, 0xf3, 0x17, 0x6b, 0x14, 0xc9, 0x04, 0x02, +0x3e, 0xd2, 0x24, 0xa6, 0x79, 0xe9, 0x1e, 0xce, 0xa2, 0xe7, 0xc1, 0x59, 0x15, 0x9f, 0x1d, 0xe2, +0x4b, 0x9a, 0x3e, 0x9f, 0x76, 0x08, 0x2d, 0x6b, 0xd8, 0xba, 0x57, 0x14, 0xda, 0x83, 0xea, 0xfe, +0x8c, 0x55, 0xe9, 0xd0, 0x4e, 0xa9, 0xcc, 0x77, 0x31, 0xb1, 0x44, 0x11, 0x7a, 0x5c, 0xb1, 0x3e, +0xd3, 0x14, 0x45, 0x15, 0x18, 0x62, 0x24, 0x13, 0xd2, 0xcb, 0x4d, 0xce, 0x5c, 0x83, 0xc1, 0x36, +0xf2, 0x10, 0xb5, 0x0e, 0x88, 0x6d, 0xb8, 0xe1, 0x56, 0x9f, 0x89, 0xde, 0x96, 0x66, 0x39, 0x47, +0x64, 0x2c, 0x6e, 0x4d, 0xae, 0x62, 0x7b, 0xbf, 0x60, 0x74, 0x19, 0xb8, 0x56, 0xac, 0x92, 0xac, +0x16, 0x32, 0xed, 0xad, 0x68, 0x55, 0xfe, 0x98, 0xba, 0xd3, 0x34, 0xde, 0xf4, 0xc9, 0x61, 0xc3, +0x0e, 0x86, 0xf6, 0x4b, 0x84, 0x60, 0xee, 0x0d, 0x7b, 0xb5, 0x32, 0x58, 0x79, 0x91, 0x55, 0x2c, +0x81, 0x43, 0xb3, 0x74, 0x1f, 0x7a, 0xaa, 0x25, 0x9e, 0x1d, 0xd7, 0xa1, 0x8b, 0xb9, 0xcd, 0x42, +0x2e, 0x04, 0xa4, 0x66, 0x83, 0x4d, 0x89, 0x35, 0xb6, 0x6c, 0xa8, 0x36, 0x4a, 0x79, 0x21, 0x78, +0x22, 0xd0, 0x42, 0xbc, 0xd1, 0x40, 0x31, 0x90, 0xa1, 0xbe, 0x04, 0xcf, 0xca, 0x67, 0xed, 0xf5, +0xf0, 0x80, 0xd3, 0x60, 0xc9, 0x83, 0x2a, 0x22, 0x05, 0xd0, 0x07, 0x3b, 0x52, 0xbf, 0x0c, 0x9e, +0xaa, 0x2b, 0xf9, 0xbb, 0xe6, 0x1f, 0x8f, 0x25, 0xba, 0x85, 0x8d, 0x17, 0x1e, 0x02, 0xfe, 0x5d, +0x50, 0x04, 0x57, 0xcf, 0xfe, 0x2d, 0xbc, 0xef, 0x5c, 0xc0, 0x1a, 0xab, 0xb6, 0x9f, 0x24, 0xc6, +0xdf, 0x73, 0x68, 0x48, 0x90, 0x2c, 0x14, 0xf4, 0x3f, 0x52, 0x1a, 0xe4, 0xd2, 0xcb, 0x14, 0xc3, +0x61, 0x69, 0xcf, 0xe2, 0xf9, 0x18, 0xc5, 0xba, 0x33, 0x9f, 0x14, 0xa3, 0x04, 0x5d, 0xb9, 0x71, +0xf7, 0xb5, 0x94, 0xd8, 0xf6, 0x33, 0xc1, 0x5a, 0xc1, 0x34, 0x8b, 0x7c, 0x9b, 0xdd, 0x93, 0x3a, +0xe7, 0x13, 0xa2, 0x70, 0x61, 0x9f, 0xaf, 0x8f, 0xeb, 0xd8, 0xc5, 0x75, 0xf8, 0x33, 0x66, 0xd4, +0x74, 0x67, 0x3a, 0x37, 0x77, 0x9c, 0xe7, 0xdd, 0xa4, 0x0f, 0x76, 0x43, 0x66, 0x8a, 0x43, 0xf2, +0x9f, 0xfb, 0x0c, 0x42, 0x78, 0x63, 0xd1, 0xe2, 0x0f, 0x6f, 0x7b, 0xd4, 0xa1, 0x3d, 0x74, 0x97, +0x85, 0xb7, 0x48, 0x39, 0x41, 0xd6, 0x20, 0xfc, 0xd0, 0x3a, 0xb3, 0xfa, 0xe8, 0x6f, 0xc4, 0x8a, +0xba, 0x71, 0x37, 0xbe, 0x8b, 0x97, 0xb1, 0x78, 0x31, 0x4f, 0xb3, 0xe7, 0xb6, 0x03, 0x13, 0xce, +0x54, 0x9d, 0xae, 0x25, 0x59, 0xcc, 0x7f, 0x35, 0x5f, 0x08, 0xf7, 0x40, 0x45, 0x31, 0x78, 0x2a, +0x7a, 0x30, 0x82, 0x02, 0x0b, 0x30, 0x82, 0x01, 0x91, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x12, +0x11, 0xd2, 0xbb, 0xba, 0x33, 0x6e, 0xd4, 0xbc, 0xe6, 0x24, 0x68, 0xc5, 0x0d, 0x84, 0x1d, 0x98, +0xe8, 0x43, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x46, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, +0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, +0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, 0x73, 0x61, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x13, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x45, 0x34, 0x36, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x33, 0x32, 0x30, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x33, 0x32, 0x30, 0x30, +0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x46, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, +0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, +0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, 0x73, 0x61, +0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6c, 0x6f, 0x62, 0x61, +0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x45, 0x34, 0x36, 0x30, 0x76, +0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, +0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x9c, 0x0e, 0xb1, 0xcf, 0xb7, 0xe8, 0x9e, 0x52, 0x77, 0x75, +0x34, 0xfa, 0xa5, 0x46, 0xa7, 0xad, 0x32, 0x19, 0x32, 0xb4, 0x07, 0xa9, 0x27, 0xca, 0x94, 0xbb, +0x0c, 0xd2, 0x0a, 0x10, 0xc7, 0xda, 0x89, 0xb0, 0x97, 0x0c, 0x70, 0x13, 0x09, 0x01, 0x8e, 0xd8, +0xea, 0x47, 0xea, 0xbe, 0xb2, 0x80, 0x2b, 0xcd, 0xfc, 0x28, 0x0d, 0xdb, 0xac, 0xbc, 0xa4, 0x86, +0x37, 0xed, 0x70, 0x08, 0x00, 0x75, 0xea, 0x93, 0x0b, 0x7b, 0x2e, 0x52, 0x9c, 0x23, 0x68, 0x23, +0x06, 0x43, 0xec, 0x92, 0x2f, 0x53, 0x84, 0xdb, 0xfb, 0x47, 0x14, 0x07, 0xe8, 0x5f, 0x94, 0x67, +0x5d, 0xc9, 0x7a, 0x81, 0x3c, 0x20, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, +0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x31, 0x0a, 0x90, 0x8f, 0xb6, 0xc6, 0x9d, 0xd2, 0x44, 0x4b, +0x80, 0xb5, 0xa2, 0xe6, 0x1f, 0xb1, 0x12, 0x4f, 0x1b, 0x95, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, +0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xdf, 0x54, +0x90, 0xed, 0x9b, 0xef, 0x8b, 0x94, 0x02, 0x93, 0x17, 0x82, 0x99, 0xbe, 0xb3, 0x9e, 0x2c, 0xf6, +0x0b, 0x91, 0x8c, 0x9f, 0x4a, 0x14, 0xb1, 0xf6, 0x64, 0xbc, 0xbb, 0x68, 0x51, 0x13, 0x0c, 0x03, +0xf7, 0x15, 0x8b, 0x84, 0x60, 0xb9, 0x8b, 0xff, 0x52, 0x8e, 0xe7, 0x8c, 0xbc, 0x1c, 0x02, 0x30, +0x3c, 0xf9, 0x11, 0xd4, 0x8c, 0x4e, 0xc0, 0xc1, 0x61, 0xc2, 0x15, 0x4c, 0xaa, 0xab, 0x1d, 0x0b, +0x31, 0x5f, 0x3b, 0x1c, 0xe2, 0x00, 0x97, 0x44, 0x31, 0xe6, 0xfe, 0x73, 0x96, 0x2f, 0xda, 0x96, +0xd3, 0xfe, 0x08, 0x07, 0xb3, 0x34, 0x89, 0xbc, 0x05, 0x9f, 0xf7, 0x1e, 0x86, 0xee, 0x8b, 0x70, +0x30, 0x82, 0x03, 0xba, 0x30, 0x82, 0x02, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0b, 0x04, +0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x86, 0x26, 0xe6, 0x0d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, +0x03, 0x55, 0x04, 0x0b, 0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, +0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x32, 0x31, 0x13, 0x30, +0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, +0x67, 0x6e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x32, 0x31, +0x35, 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x35, +0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x32, 0x31, 0x13, 0x30, 0x11, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, +0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, +0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, +0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa6, 0xcf, 0x24, 0x0e, 0xbe, 0x2e, 0x6f, 0x28, 0x99, 0x45, +0x42, 0xc4, 0xab, 0x3e, 0x21, 0x54, 0x9b, 0x0b, 0xd3, 0x7f, 0x84, 0x70, 0xfa, 0x12, 0xb3, 0xcb, +0xbf, 0x87, 0x5f, 0xc6, 0x7f, 0x86, 0xd3, 0xb2, 0x30, 0x5c, 0xd6, 0xfd, 0xad, 0xf1, 0x7b, 0xdc, +0xe5, 0xf8, 0x60, 0x96, 0x09, 0x92, 0x10, 0xf5, 0xd0, 0x53, 0xde, 0xfb, 0x7b, 0x7e, 0x73, 0x88, +0xac, 0x52, 0x88, 0x7b, 0x4a, 0xa6, 0xca, 0x49, 0xa6, 0x5e, 0xa8, 0xa7, 0x8c, 0x5a, 0x11, 0xbc, +0x7a, 0x82, 0xeb, 0xbe, 0x8c, 0xe9, 0xb3, 0xac, 0x96, 0x25, 0x07, 0x97, 0x4a, 0x99, 0x2a, 0x07, +0x2f, 0xb4, 0x1e, 0x77, 0xbf, 0x8a, 0x0f, 0xb5, 0x02, 0x7c, 0x1b, 0x96, 0xb8, 0xc5, 0xb9, 0x3a, +0x2c, 0xbc, 0xd6, 0x12, 0xb9, 0xeb, 0x59, 0x7d, 0xe2, 0xd0, 0x06, 0x86, 0x5f, 0x5e, 0x49, 0x6a, +0xb5, 0x39, 0x5e, 0x88, 0x34, 0xec, 0xbc, 0x78, 0x0c, 0x08, 0x98, 0x84, 0x6c, 0xa8, 0xcd, 0x4b, +0xb4, 0xa0, 0x7d, 0x0c, 0x79, 0x4d, 0xf0, 0xb8, 0x2d, 0xcb, 0x21, 0xca, 0xd5, 0x6c, 0x5b, 0x7d, +0xe1, 0xa0, 0x29, 0x84, 0xa1, 0xf9, 0xd3, 0x94, 0x49, 0xcb, 0x24, 0x62, 0x91, 0x20, 0xbc, 0xdd, +0x0b, 0xd5, 0xd9, 0xcc, 0xf9, 0xea, 0x27, 0x0a, 0x2b, 0x73, 0x91, 0xc6, 0x9d, 0x1b, 0xac, 0xc8, +0xcb, 0xe8, 0xe0, 0xa0, 0xf4, 0x2f, 0x90, 0x8b, 0x4d, 0xfb, 0xb0, 0x36, 0x1b, 0xf6, 0x19, 0x7a, +0x85, 0xe0, 0x6d, 0xf2, 0x61, 0x13, 0x88, 0x5c, 0x9f, 0xe0, 0x93, 0x0a, 0x51, 0x97, 0x8a, 0x5a, +0xce, 0xaf, 0xab, 0xd5, 0xf7, 0xaa, 0x09, 0xaa, 0x60, 0xbd, 0xdc, 0xd9, 0x5f, 0xdf, 0x72, 0xa9, +0x60, 0x13, 0x5e, 0x00, 0x01, 0xc9, 0x4a, 0xfa, 0x3f, 0xa4, 0xea, 0x07, 0x03, 0x21, 0x02, 0x8e, +0x82, 0xca, 0x03, 0xc2, 0x9b, 0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x9c, 0x30, 0x81, +0x99, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, +0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9b, 0xe2, 0x07, +0x57, 0x67, 0x1c, 0x1e, 0xc0, 0x6a, 0x06, 0xde, 0x59, 0xb4, 0x9a, 0x2d, 0xdf, 0xdc, 0x19, 0x86, +0x2e, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, +0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, +0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x72, 0x6f, +0x6f, 0x74, 0x2d, 0x72, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, +0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9b, 0xe2, 0x07, 0x57, 0x67, 0x1c, 0x1e, 0xc0, 0x6a, 0x06, +0xde, 0x59, 0xb4, 0x9a, 0x2d, 0xdf, 0xdc, 0x19, 0x86, 0x2e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, +0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x99, 0x81, +0x53, 0x87, 0x1c, 0x68, 0x97, 0x86, 0x91, 0xec, 0xe0, 0x4a, 0xb8, 0x44, 0x0b, 0xab, 0x81, 0xac, +0x27, 0x4f, 0xd6, 0xc1, 0xb8, 0x1c, 0x43, 0x78, 0xb3, 0x0c, 0x9a, 0xfc, 0xea, 0x2c, 0x3c, 0x6e, +0x61, 0x1b, 0x4d, 0x4b, 0x29, 0xf5, 0x9f, 0x05, 0x1d, 0x26, 0xc1, 0xb8, 0xe9, 0x83, 0x00, 0x62, +0x45, 0xb6, 0xa9, 0x08, 0x93, 0xb9, 0xa9, 0x33, 0x4b, 0x18, 0x9a, 0xc2, 0xf8, 0x87, 0x88, 0x4e, +0xdb, 0xdd, 0x71, 0x34, 0x1a, 0xc1, 0x54, 0xda, 0x46, 0x3f, 0xe0, 0xd3, 0x2a, 0xab, 0x6d, 0x54, +0x22, 0xf5, 0x3a, 0x62, 0xcd, 0x20, 0x6f, 0xba, 0x29, 0x89, 0xd7, 0xdd, 0x91, 0xee, 0xd3, 0x5c, +0xa2, 0x3e, 0xa1, 0x5b, 0x41, 0xf5, 0xdf, 0xe5, 0x64, 0x43, 0x2d, 0xe9, 0xd5, 0x39, 0xab, 0xd2, +0xa2, 0xdf, 0xb7, 0x8b, 0xd0, 0xc0, 0x80, 0x19, 0x1c, 0x45, 0xc0, 0x2d, 0x8c, 0xe8, 0xf8, 0x2d, +0xa4, 0x74, 0x56, 0x49, 0xc5, 0x05, 0xb5, 0x4f, 0x15, 0xde, 0x6e, 0x44, 0x78, 0x39, 0x87, 0xa8, +0x7e, 0xbb, 0xf3, 0x79, 0x18, 0x91, 0xbb, 0xf4, 0x6f, 0x9d, 0xc1, 0xf0, 0x8c, 0x35, 0x8c, 0x5d, +0x01, 0xfb, 0xc3, 0x6d, 0xb9, 0xef, 0x44, 0x6d, 0x79, 0x46, 0x31, 0x7e, 0x0a, 0xfe, 0xa9, 0x82, +0xc1, 0xff, 0xef, 0xab, 0x6e, 0x20, 0xc4, 0x50, 0xc9, 0x5f, 0x9d, 0x4d, 0x9b, 0x17, 0x8c, 0x0c, +0xe5, 0x01, 0xc9, 0xa0, 0x41, 0x6a, 0x73, 0x53, 0xfa, 0xa5, 0x50, 0xb4, 0x6e, 0x25, 0x0f, 0xfb, +0x4c, 0x18, 0xf4, 0xfd, 0x52, 0xd9, 0x8e, 0x69, 0xb1, 0xe8, 0x11, 0x0f, 0xde, 0x88, 0xd8, 0xfb, +0x1d, 0x49, 0xf7, 0xaa, 0xde, 0x95, 0xcf, 0x20, 0x78, 0xc2, 0x60, 0x12, 0xdb, 0x25, 0x40, 0x8c, +0x6a, 0xfc, 0x7e, 0x42, 0x38, 0x40, 0x64, 0x12, 0xf7, 0x9e, 0x81, 0xe1, 0x93, 0x2e, 0x30, 0x82, +0x03, 0x5f, 0x30, 0x82, 0x02, 0x47, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0b, 0x04, 0x00, 0x00, +0x00, 0x00, 0x01, 0x21, 0x58, 0x53, 0x08, 0xa2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x33, 0x31, 0x13, 0x30, 0x11, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, +0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, +0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x33, 0x31, 0x38, 0x31, +0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x33, 0x31, 0x38, 0x31, 0x30, +0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0b, +0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x33, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x31, 0x13, +0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, +0x69, 0x67, 0x6e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, +0x82, 0x01, 0x01, 0x00, 0xcc, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xf5, 0xc0, 0x83, +0xb6, 0x84, 0xca, 0x28, 0x9e, 0xfd, 0x05, 0x76, 0x11, 0xc5, 0xad, 0x88, 0x72, 0xfc, 0x46, 0x02, +0x43, 0xc7, 0xb2, 0x8a, 0x9d, 0x04, 0x5f, 0x24, 0xcb, 0x2e, 0x4b, 0xe1, 0x60, 0x82, 0x46, 0xe1, +0x52, 0xab, 0x0c, 0x81, 0x47, 0x70, 0x6c, 0xdd, 0x64, 0xd1, 0xeb, 0xf5, 0x2c, 0xa3, 0x0f, 0x82, +0x3d, 0x0c, 0x2b, 0xae, 0x97, 0xd7, 0xb6, 0x14, 0x86, 0x10, 0x79, 0xbb, 0x3b, 0x13, 0x80, 0x77, +0x8c, 0x08, 0xe1, 0x49, 0xd2, 0x6a, 0x62, 0x2f, 0x1f, 0x5e, 0xfa, 0x96, 0x68, 0xdf, 0x89, 0x27, +0x95, 0x38, 0x9f, 0x06, 0xd7, 0x3e, 0xc9, 0xcb, 0x26, 0x59, 0x0d, 0x73, 0xde, 0xb0, 0xc8, 0xe9, +0x26, 0x0e, 0x83, 0x15, 0xc6, 0xef, 0x5b, 0x8b, 0xd2, 0x04, 0x60, 0xca, 0x49, 0xa6, 0x28, 0xf6, +0x69, 0x3b, 0xf6, 0xcb, 0xc8, 0x28, 0x91, 0xe5, 0x9d, 0x8a, 0x61, 0x57, 0x37, 0xac, 0x74, 0x14, +0xdc, 0x74, 0xe0, 0x3a, 0xee, 0x72, 0x2f, 0x2e, 0x9c, 0xfb, 0xd0, 0xbb, 0xbf, 0xf5, 0x3d, 0x00, +0xe1, 0x06, 0x33, 0xe8, 0x82, 0x2b, 0xae, 0x53, 0xa6, 0x3a, 0x16, 0x73, 0x8c, 0xdd, 0x41, 0x0e, +0x20, 0x3a, 0xc0, 0xb4, 0xa7, 0xa1, 0xe9, 0xb2, 0x4f, 0x90, 0x2e, 0x32, 0x60, 0xe9, 0x57, 0xcb, +0xb9, 0x04, 0x92, 0x68, 0x68, 0xe5, 0x38, 0x26, 0x60, 0x75, 0xb2, 0x9f, 0x77, 0xff, 0x91, 0x14, +0xef, 0xae, 0x20, 0x49, 0xfc, 0xad, 0x40, 0x15, 0x48, 0xd1, 0x02, 0x31, 0x61, 0x19, 0x5e, 0xb8, +0x97, 0xef, 0xad, 0x77, 0xb7, 0x64, 0x9a, 0x7a, 0xbf, 0x5f, 0xc1, 0x13, 0xef, 0x9b, 0x62, 0xfb, +0x0d, 0x6c, 0xe0, 0x54, 0x69, 0x16, 0xa9, 0x03, 0xda, 0x6e, 0xe9, 0x83, 0x93, 0x71, 0x76, 0xc6, +0x69, 0x85, 0x82, 0x17, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x8f, 0xf0, 0x4b, 0x7f, 0xa8, 0x2e, 0x45, +0x24, 0xae, 0x4d, 0x50, 0xfa, 0x63, 0x9a, 0x8b, 0xde, 0xe2, 0xdd, 0x1b, 0xbc, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, +0x00, 0x4b, 0x40, 0xdb, 0xc0, 0x50, 0xaa, 0xfe, 0xc8, 0x0c, 0xef, 0xf7, 0x96, 0x54, 0x45, 0x49, +0xbb, 0x96, 0x00, 0x09, 0x41, 0xac, 0xb3, 0x13, 0x86, 0x86, 0x28, 0x07, 0x33, 0xca, 0x6b, 0xe6, +0x74, 0xb9, 0xba, 0x00, 0x2d, 0xae, 0xa4, 0x0a, 0xd3, 0xf5, 0xf1, 0xf1, 0x0f, 0x8a, 0xbf, 0x73, +0x67, 0x4a, 0x83, 0xc7, 0x44, 0x7b, 0x78, 0xe0, 0xaf, 0x6e, 0x6c, 0x6f, 0x03, 0x29, 0x8e, 0x33, +0x39, 0x45, 0xc3, 0x8e, 0xe4, 0xb9, 0x57, 0x6c, 0xaa, 0xfc, 0x12, 0x96, 0xec, 0x53, 0xc6, 0x2d, +0xe4, 0x24, 0x6c, 0xb9, 0x94, 0x63, 0xfb, 0xdc, 0x53, 0x68, 0x67, 0x56, 0x3e, 0x83, 0xb8, 0xcf, +0x35, 0x21, 0xc3, 0xc9, 0x68, 0xfe, 0xce, 0xda, 0xc2, 0x53, 0xaa, 0xcc, 0x90, 0x8a, 0xe9, 0xf0, +0x5d, 0x46, 0x8c, 0x95, 0xdd, 0x7a, 0x58, 0x28, 0x1a, 0x2f, 0x1d, 0xde, 0xcd, 0x00, 0x37, 0x41, +0x8f, 0xed, 0x44, 0x6d, 0xd7, 0x53, 0x28, 0x97, 0x7e, 0xf3, 0x67, 0x04, 0x1e, 0x15, 0xd7, 0x8a, +0x96, 0xb4, 0xd3, 0xde, 0x4c, 0x27, 0xa4, 0x4c, 0x1b, 0x73, 0x73, 0x76, 0xf4, 0x17, 0x99, 0xc2, +0x1f, 0x7a, 0x0e, 0xe3, 0x2d, 0x08, 0xad, 0x0a, 0x1c, 0x2c, 0xff, 0x3c, 0xab, 0x55, 0x0e, 0x0f, +0x91, 0x7e, 0x36, 0xeb, 0xc3, 0x57, 0x49, 0xbe, 0xe1, 0x2e, 0x2d, 0x7c, 0x60, 0x8b, 0xc3, 0x41, +0x51, 0x13, 0x23, 0x9d, 0xce, 0xf7, 0x32, 0x6b, 0x94, 0x01, 0xa8, 0x99, 0xe7, 0x2c, 0x33, 0x1f, +0x3a, 0x3b, 0x25, 0xd2, 0x86, 0x40, 0xce, 0x3b, 0x2c, 0x86, 0x78, 0xc9, 0x61, 0x2f, 0x14, 0xba, +0xee, 0xdb, 0x55, 0x6f, 0xdf, 0x84, 0xee, 0x05, 0x09, 0x4d, 0xbd, 0x28, 0xd8, 0x72, 0xce, 0xd3, +0x62, 0x50, 0x65, 0x1e, 0xeb, 0x92, 0x97, 0x83, 0x31, 0xd9, 0xb3, 0xb5, 0xca, 0x47, 0x58, 0x3f, +0x5f, 0x30, 0x82, 0x03, 0x75, 0x30, 0x82, 0x02, 0x5d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0b, +0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x4b, 0x5a, 0xc3, 0x94, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, +0x76, 0x2d, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x07, 0x52, +0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x12, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x38, 0x30, 0x39, 0x30, 0x31, 0x31, 0x32, 0x30, +0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x31, 0x32, 0x38, 0x31, 0x32, 0x30, 0x30, +0x30, 0x30, 0x5a, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, 0x73, 0x61, 0x31, 0x10, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x07, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, +0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, +0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xda, 0x0e, 0xe6, +0x99, 0x8d, 0xce, 0xa3, 0xe3, 0x4f, 0x8a, 0x7e, 0xfb, 0xf1, 0x8b, 0x83, 0x25, 0x6b, 0xea, 0x48, +0x1f, 0xf1, 0x2a, 0xb0, 0xb9, 0x95, 0x11, 0x04, 0xbd, 0xf0, 0x63, 0xd1, 0xe2, 0x67, 0x66, 0xcf, +0x1c, 0xdd, 0xcf, 0x1b, 0x48, 0x2b, 0xee, 0x8d, 0x89, 0x8e, 0x9a, 0xaf, 0x29, 0x80, 0x65, 0xab, +0xe9, 0xc7, 0x2d, 0x12, 0xcb, 0xab, 0x1c, 0x4c, 0x70, 0x07, 0xa1, 0x3d, 0x0a, 0x30, 0xcd, 0x15, +0x8d, 0x4f, 0xf8, 0xdd, 0xd4, 0x8c, 0x50, 0x15, 0x1c, 0xef, 0x50, 0xee, 0xc4, 0x2e, 0xf7, 0xfc, +0xe9, 0x52, 0xf2, 0x91, 0x7d, 0xe0, 0x6d, 0xd5, 0x35, 0x30, 0x8e, 0x5e, 0x43, 0x73, 0xf2, 0x41, +0xe9, 0xd5, 0x6a, 0xe3, 0xb2, 0x89, 0x3a, 0x56, 0x39, 0x38, 0x6f, 0x06, 0x3c, 0x88, 0x69, 0x5b, +0x2a, 0x4d, 0xc5, 0xa7, 0x54, 0xb8, 0x6c, 0x89, 0xcc, 0x9b, 0xf9, 0x3c, 0xca, 0xe5, 0xfd, 0x89, +0xf5, 0x12, 0x3c, 0x92, 0x78, 0x96, 0xd6, 0xdc, 0x74, 0x6e, 0x93, 0x44, 0x61, 0xd1, 0x8d, 0xc7, +0x46, 0xb2, 0x75, 0x0e, 0x86, 0xe8, 0x19, 0x8a, 0xd5, 0x6d, 0x6c, 0xd5, 0x78, 0x16, 0x95, 0xa2, +0xe9, 0xc8, 0x0a, 0x38, 0xeb, 0xf2, 0x24, 0x13, 0x4f, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3a, 0x1b, +0xbc, 0x1e, 0x34, 0xb5, 0x8b, 0x05, 0x8c, 0xb9, 0x77, 0x8b, 0xb1, 0xdb, 0x1f, 0x20, 0x91, 0xab, +0x09, 0x53, 0x6e, 0x90, 0xce, 0x7b, 0x37, 0x74, 0xb9, 0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, +0x79, 0xae, 0xb1, 0xae, 0x41, 0x26, 0x08, 0xc8, 0x19, 0x2b, 0xd1, 0x46, 0xaa, 0x48, 0xd6, 0x64, +0x2a, 0xd7, 0x83, 0x34, 0xff, 0x2c, 0x2a, 0xc1, 0x6c, 0x19, 0x43, 0x4a, 0x07, 0x85, 0xe7, 0xd3, +0x7c, 0xf6, 0x21, 0x68, 0xef, 0xea, 0xf2, 0x52, 0x9f, 0x7f, 0x93, 0x90, 0xcf, 0x02, 0x03, 0x01, +0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, +0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, +0x04, 0x14, 0x60, 0x7b, 0x66, 0x1a, 0x45, 0x0d, 0x97, 0xca, 0x89, 0x50, 0x2f, 0x7d, 0x04, 0xcd, +0x34, 0xa8, 0xff, 0xfc, 0xfd, 0x4b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xd6, 0x73, 0xe7, 0x7c, 0x4f, 0x76, +0xd0, 0x8d, 0xbf, 0xec, 0xba, 0xa2, 0xbe, 0x34, 0xc5, 0x28, 0x32, 0xb5, 0x7c, 0xfc, 0x6c, 0x9c, +0x2c, 0x2b, 0xbd, 0x09, 0x9e, 0x53, 0xbf, 0x6b, 0x5e, 0xaa, 0x11, 0x48, 0xb6, 0xe5, 0x08, 0xa3, +0xb3, 0xca, 0x3d, 0x61, 0x4d, 0xd3, 0x46, 0x09, 0xb3, 0x3e, 0xc3, 0xa0, 0xe3, 0x63, 0x55, 0x1b, +0xf2, 0xba, 0xef, 0xad, 0x39, 0xe1, 0x43, 0xb9, 0x38, 0xa3, 0xe6, 0x2f, 0x8a, 0x26, 0x3b, 0xef, +0xa0, 0x50, 0x56, 0xf9, 0xc6, 0x0a, 0xfd, 0x38, 0xcd, 0xc4, 0x0b, 0x70, 0x51, 0x94, 0x97, 0x98, +0x04, 0xdf, 0xc3, 0x5f, 0x94, 0xd5, 0x15, 0xc9, 0x14, 0x41, 0x9c, 0xc4, 0x5d, 0x75, 0x64, 0x15, +0x0d, 0xff, 0x55, 0x30, 0xec, 0x86, 0x8f, 0xff, 0x0d, 0xef, 0x2c, 0xb9, 0x63, 0x46, 0xf6, 0xaa, +0xfc, 0xdf, 0xbc, 0x69, 0xfd, 0x2e, 0x12, 0x48, 0x64, 0x9a, 0xe0, 0x95, 0xf0, 0xa6, 0xef, 0x29, +0x8f, 0x01, 0xb1, 0x15, 0xb5, 0x0c, 0x1d, 0xa5, 0xfe, 0x69, 0x2c, 0x69, 0x24, 0x78, 0x1e, 0xb3, +0xa7, 0x1c, 0x71, 0x62, 0xee, 0xca, 0xc8, 0x97, 0xac, 0x17, 0x5d, 0x8a, 0xc2, 0xf8, 0x47, 0x86, +0x6e, 0x2a, 0xc4, 0x56, 0x31, 0x95, 0xd0, 0x67, 0x89, 0x85, 0x2b, 0xf9, 0x6c, 0xa6, 0x5d, 0x46, +0x9d, 0x0c, 0xaa, 0x82, 0xe4, 0x99, 0x51, 0xdd, 0x70, 0xb7, 0xdb, 0x56, 0x3d, 0x61, 0xe4, 0x6a, +0xe1, 0x5c, 0xd6, 0xf6, 0xfe, 0x3d, 0xde, 0x41, 0xcc, 0x07, 0xae, 0x63, 0x52, 0xbf, 0x53, 0x53, +0xf4, 0x2b, 0xe9, 0xc7, 0xfd, 0xb6, 0xf7, 0x82, 0x5f, 0x85, 0xd2, 0x41, 0x18, 0xdb, 0x81, 0xb3, +0x04, 0x1c, 0xc5, 0x1f, 0xa4, 0x80, 0x6f, 0x15, 0x20, 0xc9, 0xde, 0x0c, 0x88, 0x0a, 0x1d, 0xd6, +0x66, 0x55, 0xe2, 0xfc, 0x48, 0xc9, 0x29, 0x26, 0x69, 0xe0, 0x30, 0x82, 0x02, 0x1e, 0x30, 0x82, +0x01, 0xa4, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x60, 0x59, 0x49, 0xe0, 0x26, 0x2e, 0xbb, +0x55, 0xf9, 0x0a, 0x77, 0x8a, 0x71, 0xf9, 0x4a, 0xd8, 0x6c, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, +0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x13, 0x1b, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x45, 0x43, +0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x35, 0x31, 0x13, +0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, +0x69, 0x67, 0x6e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, +0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x31, +0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, +0x39, 0x30, 0x33, 0x31, 0x34, 0x30, 0x37, 0x5a, 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x1b, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, +0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x35, +0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, +0x6c, 0x53, 0x69, 0x67, 0x6e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, +0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, +0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, +0x00, 0x04, 0x47, 0x45, 0x0e, 0x96, 0xfb, 0x7d, 0x5d, 0xbf, 0xe9, 0x39, 0xd1, 0x21, 0xf8, 0x9f, +0x0b, 0xb6, 0xd5, 0x7b, 0x1e, 0x92, 0x3a, 0x48, 0x59, 0x1c, 0xf0, 0x62, 0x31, 0x2d, 0xc0, 0x7a, +0x28, 0xfe, 0x1a, 0xa7, 0x5c, 0xb3, 0xb6, 0xcc, 0x97, 0xe7, 0x45, 0xd4, 0x58, 0xfa, 0xd1, 0x77, +0x6d, 0x43, 0xa2, 0xc0, 0x87, 0x65, 0x34, 0x0a, 0x1f, 0x7a, 0xdd, 0xeb, 0x3c, 0x33, 0xa1, 0xc5, +0x9d, 0x4d, 0xa4, 0x6f, 0x41, 0x95, 0x38, 0x7f, 0xc9, 0x1e, 0x84, 0xeb, 0xd1, 0x9e, 0x49, 0x92, +0x87, 0x94, 0x87, 0x0c, 0x3a, 0x85, 0x4a, 0x66, 0x9f, 0x9d, 0x59, 0x93, 0x4d, 0x97, 0x61, 0x06, +0x86, 0x4a, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, +0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, +0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, +0x04, 0x14, 0x3d, 0xe6, 0x29, 0x48, 0x9b, 0xea, 0x07, 0xca, 0x21, 0x44, 0x4a, 0x26, 0xde, 0x6e, +0xde, 0xd2, 0x83, 0xd0, 0x9f, 0x59, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, +0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xe5, 0x69, 0x12, 0xc9, 0x6e, 0xdb, +0xc6, 0x31, 0xba, 0x09, 0x41, 0xe1, 0x97, 0xf8, 0xfb, 0xfd, 0x9a, 0xe2, 0x7d, 0x12, 0xc9, 0xed, +0x7c, 0x64, 0xd3, 0xcb, 0x05, 0x25, 0x8b, 0x56, 0xd9, 0xa0, 0xe7, 0x5e, 0x5d, 0x4e, 0x0b, 0x83, +0x9c, 0x5b, 0x76, 0x29, 0xa0, 0x09, 0x26, 0x21, 0x6a, 0x62, 0x02, 0x30, 0x71, 0xd2, 0xb5, 0x8f, +0x5c, 0xea, 0x3b, 0xe1, 0x78, 0x09, 0x85, 0xa8, 0x75, 0x92, 0x3b, 0xc8, 0x5c, 0xfd, 0x48, 0xef, +0x0d, 0x74, 0x22, 0xa8, 0x08, 0xe2, 0x6e, 0xc5, 0x49, 0xce, 0xc7, 0x0c, 0xbc, 0xa7, 0x61, 0x69, +0xf1, 0xf7, 0x3b, 0xe1, 0x2a, 0xcb, 0xf9, 0x2b, 0xf3, 0x66, 0x90, 0x37, 0x30, 0x82, 0x05, 0x83, +0x30, 0x82, 0x03, 0x6b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0e, 0x45, 0xe6, 0xbb, 0x03, 0x83, +0x33, 0xc3, 0x85, 0x65, 0x48, 0xe6, 0xff, 0x45, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, +0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x36, 0x31, 0x13, 0x30, 0x11, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, +0x6e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, +0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x30, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x34, 0x31, 0x32, 0x31, 0x30, 0x30, +0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x13, 0x17, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x36, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x31, +0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x53, 0x69, 0x67, 0x6e, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, +0x02, 0x82, 0x02, 0x01, 0x00, 0x95, 0x07, 0xe8, 0x73, 0xca, 0x66, 0xf9, 0xec, 0x14, 0xca, 0x7b, +0x3c, 0xf7, 0x0d, 0x08, 0xf1, 0xb4, 0x45, 0x0b, 0x2c, 0x82, 0xb4, 0x48, 0xc6, 0xeb, 0x5b, 0x3c, +0xae, 0x83, 0xb8, 0x41, 0x92, 0x33, 0x14, 0xa4, 0x6f, 0x7f, 0xe9, 0x2a, 0xcc, 0xc6, 0xb0, 0x88, +0x6b, 0xc5, 0xb6, 0x89, 0xd1, 0xc6, 0xb2, 0xff, 0x14, 0xce, 0x51, 0x14, 0x21, 0xec, 0x4a, 0xdd, +0x1b, 0x5a, 0xc6, 0xd6, 0x87, 0xee, 0x4d, 0x3a, 0x15, 0x06, 0xed, 0x64, 0x66, 0x0b, 0x92, 0x80, +0xca, 0x44, 0xde, 0x73, 0x94, 0x4e, 0xf3, 0xa7, 0x89, 0x7f, 0x4f, 0x78, 0x63, 0x08, 0xc8, 0x12, +0x50, 0x6d, 0x42, 0x66, 0x2f, 0x4d, 0xb9, 0x79, 0x28, 0x4d, 0x52, 0x1a, 0x8a, 0x1a, 0x80, 0xb7, +0x19, 0x81, 0x0e, 0x7e, 0xc4, 0x8a, 0xbc, 0x64, 0x4c, 0x21, 0x1c, 0x43, 0x68, 0xd7, 0x3d, 0x3c, +0x8a, 0xc5, 0xb2, 0x66, 0xd5, 0x90, 0x9a, 0xb7, 0x31, 0x06, 0xc5, 0xbe, 0xe2, 0x6d, 0x32, 0x06, +0xa6, 0x1e, 0xf9, 0xb9, 0xeb, 0xaa, 0xa3, 0xb8, 0xbf, 0xbe, 0x82, 0x63, 0x50, 0xd0, 0xf0, 0x18, +0x89, 0xdf, 0xe4, 0x0f, 0x79, 0xf5, 0xea, 0xa2, 0x1f, 0x2a, 0xd2, 0x70, 0x2e, 0x7b, 0xe7, 0xbc, +0x93, 0xbb, 0x6d, 0x53, 0xe2, 0x48, 0x7c, 0x8c, 0x10, 0x07, 0x38, 0xff, 0x66, 0xb2, 0x77, 0x61, +0x7e, 0xe0, 0xea, 0x8c, 0x3c, 0xaa, 0xb4, 0xa4, 0xf6, 0xf3, 0x95, 0x4a, 0x12, 0x07, 0x6d, 0xfd, +0x8c, 0xb2, 0x89, 0xcf, 0xd0, 0xa0, 0x61, 0x77, 0xc8, 0x58, 0x74, 0xb0, 0xd4, 0x23, 0x3a, 0xf7, +0x5d, 0x3a, 0xca, 0xa2, 0xdb, 0x9d, 0x09, 0xde, 0x5d, 0x44, 0x2d, 0x90, 0xf1, 0x81, 0xcd, 0x57, +0x92, 0xfa, 0x7e, 0xbc, 0x50, 0x04, 0x63, 0x34, 0xdf, 0x6b, 0x93, 0x18, 0xbe, 0x6b, 0x36, 0xb2, +0x39, 0xe4, 0xac, 0x24, 0x36, 0xb7, 0xf0, 0xef, 0xb6, 0x1c, 0x13, 0x57, 0x93, 0xb6, 0xde, 0xb2, +0xf8, 0xe2, 0x85, 0xb7, 0x73, 0xa2, 0xb8, 0x35, 0xaa, 0x45, 0xf2, 0xe0, 0x9d, 0x36, 0xa1, 0x6f, +0x54, 0x8a, 0xf1, 0x72, 0x56, 0x6e, 0x2e, 0x88, 0xc5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xee, 0xa3, +0xc5, 0x38, 0x96, 0x9b, 0x4e, 0x4e, 0x5a, 0x0b, 0x47, 0xf3, 0x06, 0x36, 0x49, 0x77, 0x30, 0xbc, +0x71, 0x37, 0xe5, 0xa6, 0xec, 0x21, 0x08, 0x75, 0xfc, 0xe6, 0x61, 0x16, 0x3f, 0x77, 0xd5, 0xd9, +0x91, 0x97, 0x84, 0x0a, 0x6c, 0xd4, 0x02, 0x4d, 0x74, 0xc0, 0x14, 0xed, 0xfd, 0x39, 0xfb, 0x83, +0xf2, 0x5e, 0x14, 0xa1, 0x04, 0xb0, 0x0b, 0xe9, 0xfe, 0xee, 0x8f, 0xe1, 0x6e, 0x0b, 0xb2, 0x08, +0xb3, 0x61, 0x66, 0x09, 0x6a, 0xb1, 0x06, 0x3a, 0x65, 0x96, 0x59, 0xc0, 0xf0, 0x35, 0xfd, 0xc9, +0xda, 0x28, 0x8d, 0x1a, 0x11, 0x87, 0x70, 0x81, 0x0a, 0xa8, 0x9a, 0x75, 0x1d, 0x9e, 0x3a, 0x86, +0x05, 0x00, 0x9e, 0xdb, 0x80, 0xd6, 0x25, 0xf9, 0xdc, 0x05, 0x9e, 0x27, 0x59, 0x4c, 0x76, 0x39, +0x5b, 0xea, 0xf9, 0xa5, 0xa1, 0xd8, 0x83, 0x0f, 0xd1, 0xff, 0xdf, 0x30, 0x11, 0xf9, 0x85, 0xcf, +0x33, 0x48, 0xf5, 0xca, 0x6d, 0x64, 0x14, 0x2c, 0x7a, 0x58, 0x4f, 0xd3, 0x4b, 0x08, 0x49, 0xc5, +0x95, 0x64, 0x1a, 0x63, 0x0e, 0x79, 0x3d, 0xf5, 0xb3, 0x8c, 0xca, 0x58, 0xad, 0x9c, 0x42, 0x45, +0x79, 0x6e, 0x0e, 0x87, 0x19, 0x5c, 0x54, 0xb1, 0x65, 0xb6, 0xbf, 0x8c, 0x9b, 0xdc, 0x13, 0xe9, +0x0d, 0x6f, 0xb8, 0x2e, 0xdc, 0x67, 0x6e, 0xc9, 0x8b, 0x11, 0xb5, 0x84, 0x14, 0x8a, 0x00, 0x19, +0x70, 0x83, 0x79, 0x91, 0x97, 0x91, 0xd4, 0x1a, 0x27, 0xbf, 0x37, 0x1e, 0x32, 0x07, 0xd8, 0x14, +0x63, 0x3c, 0x28, 0x4c, 0xaf, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xae, 0x6c, 0x05, 0xa3, 0x93, 0x13, +0xe2, 0xa2, 0xe7, 0xe2, 0xd7, 0x1c, 0xd6, 0xc7, 0xf0, 0x7f, 0xc8, 0x67, 0x53, 0xa0, 0x30, 0x1f, +0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xae, 0x6c, 0x05, 0xa3, 0x93, +0x13, 0xe2, 0xa2, 0xe7, 0xe2, 0xd7, 0x1c, 0xd6, 0xc7, 0xf0, 0x7f, 0xc8, 0x67, 0x53, 0xa0, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, +0x02, 0x01, 0x00, 0x83, 0x25, 0xed, 0xe8, 0xd1, 0xfd, 0x95, 0x52, 0xcd, 0x9e, 0xc0, 0x04, 0xa0, +0x91, 0x69, 0xe6, 0x5c, 0xd0, 0x84, 0xde, 0xdc, 0xad, 0xa2, 0x4f, 0xe8, 0x47, 0x78, 0xd6, 0x65, +0x98, 0xa9, 0x5b, 0xa8, 0x3c, 0x87, 0x7c, 0x02, 0x8a, 0xd1, 0x6e, 0xb7, 0x16, 0x73, 0xe6, 0x5f, +0xc0, 0x54, 0x98, 0xd5, 0x74, 0xbe, 0xc1, 0xcd, 0xe2, 0x11, 0x91, 0xad, 0x23, 0x18, 0x3d, 0xdd, +0xe1, 0x72, 0x44, 0x96, 0xb4, 0x95, 0x5e, 0xc0, 0x7b, 0x8e, 0x99, 0x78, 0x16, 0x43, 0x13, 0x56, +0x57, 0xb3, 0xa2, 0xb3, 0x3b, 0xb5, 0x77, 0xdc, 0x40, 0x72, 0xac, 0xa3, 0xeb, 0x9b, 0x35, 0x3e, +0xb1, 0x08, 0x21, 0xa1, 0xe7, 0xc4, 0x43, 0x37, 0x79, 0x32, 0xbe, 0xb5, 0xe7, 0x9c, 0x2c, 0x4c, +0xbc, 0x43, 0x29, 0x99, 0x8e, 0x30, 0xd3, 0xac, 0x21, 0xe0, 0xe3, 0x1d, 0xfa, 0xd8, 0x07, 0x33, +0x76, 0x54, 0x00, 0x22, 0x2a, 0xb9, 0x4d, 0x20, 0x2e, 0x70, 0x68, 0xda, 0xe5, 0x53, 0xfc, 0x83, +0x5c, 0xd3, 0x9d, 0xf2, 0xff, 0x44, 0x0c, 0x44, 0x66, 0xf2, 0xd2, 0xe3, 0xbd, 0x46, 0x00, 0x1a, +0x6d, 0x02, 0xba, 0x25, 0x5d, 0x8d, 0xa1, 0x31, 0x51, 0xdd, 0x54, 0x46, 0x1c, 0x4d, 0xdb, 0x99, +0x96, 0xef, 0x1a, 0x1c, 0x04, 0x5c, 0xa6, 0x15, 0xef, 0x78, 0xe0, 0x79, 0xfe, 0x5d, 0xdb, 0x3e, +0xaa, 0x4c, 0x55, 0xfd, 0x9a, 0x15, 0xa9, 0x6f, 0xe1, 0xa6, 0xfb, 0xdf, 0x70, 0x30, 0xe9, 0xc3, +0xee, 0x42, 0x46, 0xed, 0xc2, 0x93, 0x05, 0x89, 0xfa, 0x7d, 0x63, 0x7b, 0x3f, 0xd0, 0x71, 0x81, +0x7c, 0x00, 0xe8, 0x98, 0xae, 0x0e, 0x78, 0x34, 0xc3, 0x25, 0xfb, 0xaf, 0x0a, 0x9f, 0x20, 0x6b, +0xdd, 0x3b, 0x13, 0x8f, 0x12, 0x8c, 0xe2, 0x41, 0x1a, 0x48, 0x7a, 0x73, 0xa0, 0x77, 0x69, 0xc7, +0xb6, 0x5c, 0x7f, 0x82, 0xc8, 0x1e, 0xfe, 0x58, 0x1b, 0x28, 0x2b, 0xa8, 0x6c, 0xad, 0x5e, 0x6d, +0xc0, 0x05, 0xd2, 0x7b, 0xb7, 0xeb, 0x80, 0xfe, 0x25, 0x37, 0xfe, 0x02, 0x9b, 0x68, 0xac, 0x42, +0x5d, 0xc3, 0xee, 0xf5, 0xcc, 0xdc, 0xf0, 0x50, 0x75, 0xd2, 0x36, 0x69, 0x9c, 0xe6, 0x7b, 0x04, +0xdf, 0x6e, 0x06, 0x69, 0xb6, 0xde, 0x0a, 0x09, 0x48, 0x59, 0x87, 0xeb, 0x7b, 0x14, 0x60, 0x7a, +0x64, 0xaa, 0x69, 0x43, 0xef, 0x91, 0xc7, 0x4c, 0xec, 0x18, 0xdd, 0x6c, 0xef, 0x53, 0x2d, 0x8c, +0x99, 0xe1, 0x5e, 0xf2, 0x72, 0x3e, 0xcf, 0x54, 0xc8, 0xbd, 0x67, 0xec, 0xa4, 0x0f, 0x4c, 0x45, +0xff, 0xd3, 0xb9, 0x30, 0x23, 0x07, 0x4c, 0x8f, 0x10, 0xbf, 0x86, 0x96, 0xd9, 0x99, 0x5a, 0xb4, +0x99, 0x57, 0x1c, 0xa4, 0xcc, 0xbb, 0x15, 0x89, 0x53, 0xba, 0x2c, 0x05, 0x0f, 0xe4, 0xc4, 0x9e, +0x19, 0xb1, 0x18, 0x34, 0xd5, 0x4c, 0x9d, 0xba, 0xed, 0xf7, 0x1f, 0xaf, 0x24, 0x95, 0x04, 0x78, +0xa8, 0x03, 0xbb, 0xee, 0x81, 0xe5, 0xda, 0x5f, 0x7c, 0x8b, 0x4a, 0xa1, 0x90, 0x74, 0x25, 0xa7, +0xb3, 0x3e, 0x4b, 0xc8, 0x2c, 0x56, 0xbd, 0xc7, 0xc8, 0xef, 0x38, 0xe2, 0x5c, 0x92, 0xf0, 0x79, +0xf7, 0x9c, 0x84, 0xba, 0x74, 0x2d, 0x61, 0x01, 0x20, 0x7e, 0x7e, 0xd1, 0xf2, 0x4f, 0x07, 0x59, +0x5f, 0x8b, 0x2d, 0x43, 0x52, 0xeb, 0x46, 0x0c, 0x94, 0xe1, 0xf5, 0x66, 0x47, 0x79, 0x77, 0xd5, +0x54, 0x5b, 0x1f, 0xad, 0x24, 0x37, 0xcb, 0x45, 0x5a, 0x4e, 0xa0, 0x44, 0x48, 0xc8, 0xd8, 0xb0, +0x99, 0xc5, 0x15, 0x84, 0x09, 0xf6, 0xd6, 0x49, 0x49, 0xc0, 0x65, 0xb8, 0xe6, 0x1a, 0x71, 0x6e, +0xa0, 0xa8, 0xf1, 0x82, 0xe8, 0x45, 0x3e, 0x6c, 0xd6, 0x02, 0xd7, 0x0a, 0x67, 0x83, 0x05, 0x5a, +0xc9, 0xa4, 0x10, 0x30, 0x82, 0x04, 0x0a, 0x30, 0x82, 0x02, 0xf2, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x09, 0x00, 0xc2, 0x7e, 0x43, 0x04, 0x4e, 0x47, 0x3f, 0x19, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, 0x30, +0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, +0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, +0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2d, 0x53, 0x7a, 0x69, 0x67, 0x6e, +0x6f, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x30, 0x39, 0x31, 0x1f, +0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, +0x6e, 0x66, 0x6f, 0x40, 0x65, 0x2d, 0x73, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x2e, 0x68, 0x75, 0x30, +0x1e, 0x17, 0x0d, 0x30, 0x39, 0x30, 0x36, 0x31, 0x36, 0x31, 0x31, 0x33, 0x30, 0x31, 0x38, 0x5a, +0x17, 0x0d, 0x32, 0x39, 0x31, 0x32, 0x33, 0x30, 0x31, 0x31, 0x33, 0x30, 0x31, 0x38, 0x5a, 0x30, +0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, 0x31, +0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, +0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, 0x69, 0x63, +0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x1e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2d, +0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, +0x30, 0x30, 0x39, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x65, 0x2d, 0x73, 0x7a, 0x69, 0x67, 0x6e, +0x6f, 0x2e, 0x68, 0x75, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, +0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, +0x02, 0x82, 0x01, 0x01, 0x00, 0xe9, 0xf8, 0x8f, 0xf3, 0x63, 0xad, 0xda, 0x86, 0xd8, 0xa7, 0xe0, +0x42, 0xfb, 0xcf, 0x91, 0xde, 0xa6, 0x26, 0xf8, 0x99, 0xa5, 0x63, 0x70, 0xad, 0x9b, 0xae, 0xca, +0x33, 0x40, 0x7d, 0x6d, 0x96, 0x6e, 0xa1, 0x0e, 0x44, 0xee, 0xe1, 0x13, 0x9d, 0x94, 0x42, 0x52, +0x9a, 0xbd, 0x75, 0x85, 0x74, 0x2c, 0xa8, 0x0e, 0x1d, 0x93, 0xb6, 0x18, 0xb7, 0x8c, 0x2c, 0xa8, +0xcf, 0xfb, 0x5c, 0x71, 0xb9, 0xda, 0xec, 0xfe, 0xe8, 0x7e, 0x8f, 0xe4, 0x2f, 0x1d, 0xb2, 0xa8, +0x75, 0x87, 0xd8, 0xb7, 0xa1, 0xe5, 0x3b, 0xcf, 0x99, 0x4a, 0x46, 0xd0, 0x83, 0x19, 0x7d, 0xc0, +0xa1, 0x12, 0x1c, 0x95, 0x6d, 0x4a, 0xf4, 0xd8, 0xc7, 0xa5, 0x4d, 0x33, 0x2e, 0x85, 0x39, 0x40, +0x75, 0x7e, 0x14, 0x7c, 0x80, 0x12, 0x98, 0x50, 0xc7, 0x41, 0x67, 0xb8, 0xa0, 0x80, 0x61, 0x54, +0xa6, 0x6c, 0x4e, 0x1f, 0xe0, 0x9d, 0x0e, 0x07, 0xe9, 0xc9, 0xba, 0x33, 0xe7, 0xfe, 0xc0, 0x55, +0x28, 0x2c, 0x02, 0x80, 0xa7, 0x19, 0xf5, 0x9e, 0xdc, 0x55, 0x53, 0x03, 0x97, 0x7b, 0x07, 0x48, +0xff, 0x99, 0xfb, 0x37, 0x8a, 0x24, 0xc4, 0x59, 0xcc, 0x50, 0x10, 0x63, 0x8e, 0xaa, 0xa9, 0x1a, +0xb0, 0x84, 0x1a, 0x86, 0xf9, 0x5f, 0xbb, 0xb1, 0x50, 0x6e, 0xa4, 0xd1, 0x0a, 0xcc, 0xd5, 0x71, +0x7e, 0x1f, 0xa7, 0x1b, 0x7c, 0xf5, 0x53, 0x6e, 0x22, 0x5f, 0xcb, 0x2b, 0xe6, 0xd4, 0x7c, 0x5d, +0xae, 0xd6, 0xc2, 0xc6, 0x4c, 0xe5, 0x05, 0x01, 0xd9, 0xed, 0x57, 0xfc, 0xc1, 0x23, 0x79, 0xfc, +0xfa, 0xc8, 0x24, 0x83, 0x95, 0xf3, 0xb5, 0x6a, 0x51, 0x01, 0xd0, 0x77, 0xd6, 0xe9, 0x12, 0xa1, +0xf9, 0x1a, 0x83, 0xfb, 0x82, 0x1b, 0xb9, 0xb0, 0x97, 0xf4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xa0, +0xff, 0x0b, 0xb5, 0xfa, 0xb5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x80, 0x30, 0x7e, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcb, 0x0f, 0xc6, 0xdf, 0x42, +0x43, 0xcc, 0x3d, 0xcb, 0xb5, 0x48, 0x23, 0xa1, 0x1a, 0x7a, 0xa6, 0x2a, 0xbb, 0x34, 0x68, 0x30, +0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xcb, 0x0f, 0xc6, 0xdf, +0x42, 0x43, 0xcc, 0x3d, 0xcb, 0xb5, 0x48, 0x23, 0xa1, 0x1a, 0x7a, 0xa6, 0x2a, 0xbb, 0x34, 0x68, +0x30, 0x1b, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x14, 0x30, 0x12, 0x81, 0x10, 0x69, 0x6e, 0x66, +0x6f, 0x40, 0x65, 0x2d, 0x73, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x2e, 0x68, 0x75, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, +0x00, 0xc9, 0xd1, 0x0e, 0x5e, 0x2e, 0xd5, 0xcc, 0xb3, 0x7c, 0x3e, 0xcb, 0xfc, 0x3d, 0xff, 0x0d, +0x28, 0x95, 0x93, 0x04, 0xc8, 0xbf, 0xda, 0xcd, 0x79, 0xb8, 0x43, 0x90, 0xf0, 0xa4, 0xbe, 0xef, +0xf2, 0xef, 0x21, 0x98, 0xbc, 0xd4, 0xd4, 0x5d, 0x06, 0xf6, 0xee, 0x42, 0xec, 0x30, 0x6c, 0xa0, +0xaa, 0xa9, 0xca, 0xf1, 0xaf, 0x8a, 0xfa, 0x3f, 0x0b, 0x73, 0x6a, 0x3e, 0xea, 0x2e, 0x40, 0x7e, +0x1f, 0xae, 0x54, 0x61, 0x79, 0xeb, 0x2e, 0x08, 0x37, 0xd7, 0x23, 0xf3, 0x8c, 0x9f, 0xbe, 0x1d, +0xb1, 0xe1, 0xa4, 0x75, 0xdb, 0xa0, 0xe2, 0x54, 0x14, 0xb1, 0xba, 0x1c, 0x29, 0xa4, 0x18, 0xf6, +0x12, 0xba, 0xa2, 0x14, 0x14, 0xe3, 0x31, 0x35, 0xc8, 0x40, 0xff, 0xb7, 0xe0, 0x05, 0x76, 0x57, +0xc1, 0x1c, 0x59, 0xf2, 0xf8, 0xbf, 0xe4, 0xed, 0x25, 0x62, 0x5c, 0x84, 0xf0, 0x7e, 0x7e, 0x1f, +0xb3, 0xbe, 0xf9, 0xb7, 0x21, 0x11, 0xcc, 0x03, 0x01, 0x56, 0x70, 0xa7, 0x10, 0x92, 0x1e, 0x1b, +0x34, 0x81, 0x1e, 0xad, 0x9c, 0x1a, 0xc3, 0x04, 0x3c, 0xed, 0x02, 0x61, 0xd6, 0x1e, 0x06, 0xf3, +0x5f, 0x3a, 0x87, 0xf2, 0x2b, 0xf1, 0x45, 0x87, 0xe5, 0x3d, 0xac, 0xd1, 0xc7, 0x57, 0x84, 0xbd, +0x6b, 0xae, 0xdc, 0xd8, 0xf9, 0xb6, 0x1b, 0x62, 0x70, 0x0b, 0x3d, 0x36, 0xc9, 0x42, 0xf2, 0x32, +0xd7, 0x7a, 0x61, 0xe6, 0xd2, 0xdb, 0x3d, 0xcf, 0xc8, 0xa9, 0xc9, 0x9b, 0xdc, 0xdb, 0x58, 0x44, +0xd7, 0x6f, 0x38, 0xaf, 0x7f, 0x78, 0xd3, 0xa3, 0xad, 0x1a, 0x75, 0xba, 0x1c, 0xc1, 0x36, 0x7c, +0x8f, 0x1e, 0x6d, 0x1c, 0xc3, 0x75, 0x46, 0xae, 0x35, 0x05, 0xa6, 0xf6, 0x5c, 0x3d, 0x21, 0xee, +0x56, 0xf0, 0xc9, 0x82, 0x22, 0x2d, 0x7a, 0x54, 0xab, 0x70, 0xc3, 0x7d, 0x22, 0x65, 0x82, 0x70, +0x96, 0x30, 0x82, 0x03, 0xbc, 0x30, 0x82, 0x02, 0xa4, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, +0x07, 0x56, 0x22, 0xa4, 0xe8, 0xd4, 0x8a, 0x89, 0x4d, 0xf4, 0x13, 0xc8, 0xf0, 0xf8, 0xea, 0xa5, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, +0x4a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x20, +0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, +0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x53, 0x65, 0x63, 0x75, 0x72, +0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, +0x36, 0x31, 0x31, 0x30, 0x37, 0x31, 0x39, 0x34, 0x32, 0x32, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x39, +0x31, 0x32, 0x33, 0x31, 0x31, 0x39, 0x35, 0x32, 0x30, 0x36, 0x5a, 0x30, 0x4a, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, +0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, +0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6c, +0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, +0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xaf, 0x35, 0x2e, 0xd8, 0xac, 0x6c, 0x55, 0x69, +0x06, 0x71, 0xe5, 0x13, 0x68, 0x24, 0xb3, 0x4f, 0xd8, 0xcc, 0x21, 0x47, 0xf8, 0xf1, 0x60, 0x38, +0x89, 0x89, 0x03, 0xe9, 0xbd, 0xea, 0x5e, 0x46, 0x53, 0x09, 0xdc, 0x5c, 0xf5, 0x5a, 0xe8, 0xf7, +0x45, 0x2a, 0x02, 0xeb, 0x31, 0x61, 0xd7, 0x29, 0x33, 0x4c, 0xce, 0xc7, 0x7c, 0x0a, 0x37, 0x7e, +0x0f, 0xba, 0x32, 0x98, 0xe1, 0x1d, 0x97, 0xaf, 0x8f, 0xc7, 0xdc, 0xc9, 0x38, 0x96, 0xf3, 0xdb, +0x1a, 0xfc, 0x51, 0xed, 0x68, 0xc6, 0xd0, 0x6e, 0xa4, 0x7c, 0x24, 0xd1, 0xae, 0x42, 0xc8, 0x96, +0x50, 0x63, 0x2e, 0xe0, 0xfe, 0x75, 0xfe, 0x98, 0xa7, 0x5f, 0x49, 0x2e, 0x95, 0xe3, 0x39, 0x33, +0x64, 0x8e, 0x1e, 0xa4, 0x5f, 0x90, 0xd2, 0x67, 0x3c, 0xb2, 0xd9, 0xfe, 0x41, 0xb9, 0x55, 0xa7, +0x09, 0x8e, 0x72, 0x05, 0x1e, 0x8b, 0xdd, 0x44, 0x85, 0x82, 0x42, 0xd0, 0x49, 0xc0, 0x1d, 0x60, +0xf0, 0xd1, 0x17, 0x2c, 0x95, 0xeb, 0xf6, 0xa5, 0xc1, 0x92, 0xa3, 0xc5, 0xc2, 0xa7, 0x08, 0x60, +0x0d, 0x60, 0x04, 0x10, 0x96, 0x79, 0x9e, 0x16, 0x34, 0xe6, 0xa9, 0xb6, 0xfa, 0x25, 0x45, 0x39, +0xc8, 0x1e, 0x65, 0xf9, 0x93, 0xf5, 0xaa, 0xf1, 0x52, 0xdc, 0x99, 0x98, 0x3d, 0xa5, 0x86, 0x1a, +0x0c, 0x35, 0x33, 0xfa, 0x4b, 0xa5, 0x04, 0x06, 0x15, 0x1c, 0x31, 0x80, 0xef, 0xaa, 0x18, 0x6b, +0xc2, 0x7b, 0xd7, 0xda, 0xce, 0xf9, 0x33, 0x20, 0xd5, 0xf5, 0xbd, 0x6a, 0x33, 0x2d, 0x81, 0x04, +0xfb, 0xb0, 0x5c, 0xd4, 0x9c, 0xa3, 0xe2, 0x5c, 0x1d, 0xe3, 0xa9, 0x42, 0x75, 0x5e, 0x7b, 0xd4, +0x77, 0xef, 0x39, 0x54, 0xba, 0xc9, 0x0a, 0x18, 0x1b, 0x12, 0x99, 0x49, 0x2f, 0x88, 0x4b, 0xfd, +0x50, 0x62, 0xd1, 0x73, 0xe7, 0x8f, 0x7a, 0x43, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x9d, +0x30, 0x81, 0x9a, 0x30, 0x13, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, +0x04, 0x06, 0x1e, 0x04, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, +0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, +0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, +0x14, 0xaf, 0x44, 0x04, 0xc2, 0x41, 0x7e, 0x48, 0x83, 0xdb, 0x4e, 0x39, 0x02, 0xec, 0xec, 0x84, +0x7a, 0xe6, 0xce, 0xc9, 0xa4, 0x30, 0x34, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2d, 0x30, 0x2b, +0x30, 0x29, 0xa0, 0x27, 0xa0, 0x25, 0x86, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, +0x72, 0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, +0x6f, 0x6d, 0x2f, 0x53, 0x47, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, 0x06, 0x09, 0x2b, +0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, +0x00, 0x63, 0x1a, 0x08, 0x40, 0x7d, 0xa4, 0x5e, 0x53, 0x0d, 0x77, 0xd8, 0x7a, 0xae, 0x1f, 0x0d, +0x0b, 0x51, 0x16, 0x03, 0xef, 0x18, 0x7c, 0xc8, 0xe3, 0xaf, 0x6a, 0x58, 0x93, 0x14, 0x60, 0x91, +0xb2, 0x84, 0xdc, 0x88, 0x4e, 0xbe, 0x39, 0x8a, 0x3a, 0xf3, 0xe6, 0x82, 0x89, 0x5d, 0x01, 0x37, +0xb3, 0xab, 0x24, 0xa4, 0x15, 0x0e, 0x92, 0x35, 0x5a, 0x4a, 0x44, 0x5e, 0x4e, 0x57, 0xfa, 0x75, +0xce, 0x1f, 0x48, 0xce, 0x66, 0xf4, 0x3c, 0x40, 0x26, 0x92, 0x98, 0x6c, 0x1b, 0xee, 0x24, 0x46, +0x0c, 0x17, 0xb3, 0x52, 0xa5, 0xdb, 0xa5, 0x91, 0x91, 0xcf, 0x37, 0xd3, 0x6f, 0xe7, 0x27, 0x08, +0x3a, 0x4e, 0x19, 0x1f, 0x3a, 0xa7, 0x58, 0x5c, 0x17, 0xcf, 0x79, 0x3f, 0x8b, 0xe4, 0xa7, 0xd3, +0x26, 0x23, 0x9d, 0x26, 0x0f, 0x58, 0x69, 0xfc, 0x47, 0x7e, 0xb2, 0xd0, 0x8d, 0x8b, 0x93, 0xbf, +0x29, 0x4f, 0x43, 0x69, 0x74, 0x76, 0x67, 0x4b, 0xcf, 0x07, 0x8c, 0xe6, 0x02, 0xf7, 0xb5, 0xe1, +0xb4, 0x43, 0xb5, 0x4b, 0x2d, 0x14, 0x9f, 0xf9, 0xdc, 0x26, 0x0d, 0xbf, 0xa6, 0x47, 0x74, 0x06, +0xd8, 0x88, 0xd1, 0x3a, 0x29, 0x30, 0x84, 0xce, 0xd2, 0x39, 0x80, 0x62, 0x1b, 0xa8, 0xc7, 0x57, +0x49, 0xbc, 0x6a, 0x55, 0x51, 0x67, 0x15, 0x4a, 0xbe, 0x35, 0x07, 0xe4, 0xd5, 0x75, 0x98, 0x37, +0x79, 0x30, 0x14, 0xdb, 0x29, 0x9d, 0x6c, 0xc5, 0x69, 0xcc, 0x47, 0x55, 0xa2, 0x30, 0xf7, 0xcc, +0x5c, 0x7f, 0xc2, 0xc3, 0x98, 0x1c, 0x6b, 0x4e, 0x16, 0x80, 0xeb, 0x7a, 0x78, 0x65, 0x45, 0xa2, +0x00, 0x1a, 0xaf, 0x0c, 0x0d, 0x55, 0x64, 0x34, 0x48, 0xb8, 0x92, 0xb9, 0xf1, 0xb4, 0x50, 0x29, +0xf2, 0x4f, 0x23, 0x1f, 0xda, 0x6c, 0xac, 0x1f, 0x44, 0xe1, 0xdd, 0x23, 0x78, 0x51, 0x5b, 0xc7, +0x16, 0x30, 0x82, 0x03, 0xb8, 0x30, 0x82, 0x02, 0xa0, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, +0x0c, 0xf0, 0x8e, 0x5c, 0x08, 0x16, 0xa5, 0xad, 0x42, 0x7f, 0xf0, 0xeb, 0x27, 0x18, 0x59, 0xd0, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, +0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x20, +0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, +0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, +0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, +0x31, 0x30, 0x37, 0x31, 0x39, 0x33, 0x31, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x31, 0x32, +0x33, 0x31, 0x31, 0x39, 0x34, 0x30, 0x35, 0x35, 0x5a, 0x30, 0x48, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, +0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, +0x55, 0x04, 0x03, 0x13, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, +0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, +0x82, 0x01, 0x01, 0x00, 0xab, 0xa4, 0x81, 0xe5, 0x95, 0xcd, 0xf5, 0xf6, 0x14, 0x8e, 0xc2, 0x4f, +0xca, 0xd4, 0xe2, 0x78, 0x95, 0x58, 0x9c, 0x41, 0xe1, 0x0d, 0x99, 0x40, 0x24, 0x17, 0x39, 0x91, +0x33, 0x66, 0xe9, 0xbe, 0xe1, 0x83, 0xaf, 0x62, 0x5c, 0x89, 0xd1, 0xfc, 0x24, 0x5b, 0x61, 0xb3, +0xe0, 0x11, 0x11, 0x41, 0x1c, 0x1d, 0x6e, 0xf0, 0xb8, 0xbb, 0xf8, 0xde, 0xa7, 0x81, 0xba, 0xa6, +0x48, 0xc6, 0x9f, 0x1d, 0xbd, 0xbe, 0x8e, 0xa9, 0x41, 0x3e, 0xb8, 0x94, 0xed, 0x29, 0x1a, 0xd4, +0x8e, 0xd2, 0x03, 0x1d, 0x03, 0xef, 0x6d, 0x0d, 0x67, 0x1c, 0x57, 0xd7, 0x06, 0xad, 0xca, 0xc8, +0xf5, 0xfe, 0x0e, 0xaf, 0x66, 0x25, 0x48, 0x04, 0x96, 0x0b, 0x5d, 0xa3, 0xba, 0x16, 0xc3, 0x08, +0x4f, 0xd1, 0x46, 0xf8, 0x14, 0x5c, 0xf2, 0xc8, 0x5e, 0x01, 0x99, 0x6d, 0xfd, 0x88, 0xcc, 0x86, +0xa8, 0xc1, 0x6f, 0x31, 0x42, 0x6c, 0x52, 0x3e, 0x68, 0xcb, 0xf3, 0x19, 0x34, 0xdf, 0xbb, 0x87, +0x18, 0x56, 0x80, 0x26, 0xc4, 0xd0, 0xdc, 0xc0, 0x6f, 0xdf, 0xde, 0xa0, 0xc2, 0x91, 0x16, 0xa0, +0x64, 0x11, 0x4b, 0x44, 0xbc, 0x1e, 0xf6, 0xe7, 0xfa, 0x63, 0xde, 0x66, 0xac, 0x76, 0xa4, 0x71, +0xa3, 0xec, 0x36, 0x94, 0x68, 0x7a, 0x77, 0xa4, 0xb1, 0xe7, 0x0e, 0x2f, 0x81, 0x7a, 0xe2, 0xb5, +0x72, 0x86, 0xef, 0xa2, 0x6b, 0x8b, 0xf0, 0x0f, 0xdb, 0xd3, 0x59, 0x3f, 0xba, 0x72, 0xbc, 0x44, +0x24, 0x9c, 0xe3, 0x73, 0xb3, 0xf7, 0xaf, 0x57, 0x2f, 0x42, 0x26, 0x9d, 0xa9, 0x74, 0xba, 0x00, +0x52, 0xf2, 0x4b, 0xcd, 0x53, 0x7c, 0x47, 0x0b, 0x36, 0x85, 0x0e, 0x66, 0xa9, 0x08, 0x97, 0x16, +0x34, 0x57, 0xc1, 0x66, 0xf7, 0x80, 0xe3, 0xed, 0x70, 0x54, 0xc7, 0x93, 0xe0, 0x2e, 0x28, 0x15, +0x59, 0x87, 0xba, 0xbb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, +0x13, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x06, 0x1e, 0x04, +0x00, 0x43, 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, +0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x42, 0x32, 0xb6, +0x16, 0xfa, 0x04, 0xfd, 0xfe, 0x5d, 0x4b, 0x7a, 0xc3, 0xfd, 0xf7, 0x4c, 0x40, 0x1d, 0x5a, 0x43, +0xaf, 0x30, 0x34, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2d, 0x30, 0x2b, 0x30, 0x29, 0xa0, 0x27, +0xa0, 0x25, 0x86, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x73, +0x65, 0x63, 0x75, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, +0x54, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, +0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x30, 0xed, 0x4f, +0x4a, 0xe1, 0x58, 0x3a, 0x52, 0x72, 0x5b, 0xb5, 0xa6, 0xa3, 0x65, 0x18, 0xa6, 0xbb, 0x51, 0x3b, +0x77, 0xe9, 0x9d, 0xea, 0xd3, 0x9f, 0x5c, 0xe0, 0x45, 0x65, 0x7b, 0x0d, 0xca, 0x5b, 0xe2, 0x70, +0x50, 0xb2, 0x94, 0x05, 0x14, 0xae, 0x49, 0xc7, 0x8d, 0x41, 0x07, 0x12, 0x73, 0x94, 0x7e, 0x0c, +0x23, 0x21, 0xfd, 0xbc, 0x10, 0x7f, 0x60, 0x10, 0x5a, 0x72, 0xf5, 0x98, 0x0e, 0xac, 0xec, 0xb9, +0x7f, 0xdd, 0x7a, 0x6f, 0x5d, 0xd3, 0x1c, 0xf4, 0xff, 0x88, 0x05, 0x69, 0x42, 0xa9, 0x05, 0x71, +0xc8, 0xb7, 0xac, 0x26, 0xe8, 0x2e, 0xb4, 0x8c, 0x6a, 0xff, 0x71, 0xdc, 0xb8, 0xb1, 0xdf, 0x99, +0xbc, 0x7c, 0x21, 0x54, 0x2b, 0xe4, 0x58, 0xa2, 0xbb, 0x57, 0x29, 0xae, 0x9e, 0xa9, 0xa3, 0x19, +0x26, 0x0f, 0x99, 0x2e, 0x08, 0xb0, 0xef, 0xfd, 0x69, 0xcf, 0x99, 0x1a, 0x09, 0x8d, 0xe3, 0xa7, +0x9f, 0x2b, 0xc9, 0x36, 0x34, 0x7b, 0x24, 0xb3, 0x78, 0x4c, 0x95, 0x17, 0xa4, 0x06, 0x26, 0x1e, +0xb6, 0x64, 0x52, 0x36, 0x5f, 0x60, 0x67, 0xd9, 0x9c, 0xc5, 0x05, 0x74, 0x0b, 0xe7, 0x67, 0x23, +0xd2, 0x08, 0xfc, 0x88, 0xe9, 0xae, 0x8b, 0x7f, 0xe1, 0x30, 0xf4, 0x37, 0x7e, 0xfd, 0xc6, 0x32, +0xda, 0x2d, 0x9e, 0x44, 0x30, 0x30, 0x6c, 0xee, 0x07, 0xde, 0xd2, 0x34, 0xfc, 0xd2, 0xff, 0x40, +0xf6, 0x4b, 0xf4, 0x66, 0x46, 0x06, 0x54, 0xa6, 0xf2, 0x32, 0x0a, 0x63, 0x26, 0x30, 0x6b, 0x9b, +0xd1, 0xdc, 0x8b, 0x47, 0xba, 0xe1, 0xb9, 0xd5, 0x62, 0xd0, 0xa2, 0xa0, 0xf4, 0x67, 0x05, 0x78, +0x29, 0x63, 0x1a, 0x6f, 0x04, 0xd6, 0xf8, 0xc6, 0x4c, 0xa3, 0x9a, 0xb1, 0x37, 0xb4, 0x8d, 0xe5, +0x28, 0x4b, 0x1d, 0x9e, 0x2c, 0xc2, 0xb8, 0x68, 0xbc, 0xed, 0x02, 0xee, 0x31, 0x30, 0x82, 0x05, +0xba, 0x30, 0x82, 0x03, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xbb, 0x40, 0x1c, +0x43, 0xf5, 0x5e, 0x4f, 0xb0, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x53, 0x77, +0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x41, 0x47, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x04, 0x03, 0x13, 0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x47, +0x6f, 0x6c, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x30, +0x36, 0x31, 0x30, 0x32, 0x35, 0x30, 0x38, 0x33, 0x30, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x36, +0x31, 0x30, 0x32, 0x35, 0x30, 0x38, 0x33, 0x30, 0x33, 0x35, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0c, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x41, +0x47, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x53, 0x77, 0x69, 0x73, +0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x47, 0x6f, 0x6c, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, +0x47, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, +0x02, 0x01, 0x00, 0xaf, 0xe4, 0xee, 0x7e, 0x8b, 0x24, 0x0e, 0x12, 0x6e, 0xa9, 0x50, 0x2d, 0x16, +0x44, 0x3b, 0x92, 0x92, 0x5c, 0xca, 0xb8, 0x5d, 0x84, 0x92, 0x42, 0x13, 0x2a, 0xbc, 0x65, 0x57, +0x82, 0x40, 0x3e, 0x57, 0x24, 0xcd, 0x50, 0x8b, 0x25, 0x2a, 0xb7, 0x6f, 0xfc, 0xef, 0xa2, 0xd0, +0xc0, 0x1f, 0x02, 0x24, 0x4a, 0x13, 0x96, 0x8f, 0x23, 0x13, 0xe6, 0x28, 0x58, 0x00, 0xa3, 0x47, +0xc7, 0x06, 0xa7, 0x84, 0x23, 0x2b, 0xbb, 0xbd, 0x96, 0x2b, 0x7f, 0x55, 0xcc, 0x8b, 0xc1, 0x57, +0x1f, 0x0e, 0x62, 0x65, 0x0f, 0xdd, 0x3d, 0x56, 0x8a, 0x73, 0xda, 0xae, 0x7e, 0x6d, 0xba, 0x81, +0x1c, 0x7e, 0x42, 0x8c, 0x20, 0x35, 0xd9, 0x43, 0x4d, 0x84, 0xfa, 0x84, 0xdb, 0x52, 0x2c, 0xf3, +0x0e, 0x27, 0x77, 0x0b, 0x6b, 0xbf, 0x11, 0x2f, 0x72, 0x78, 0x9f, 0x2e, 0xd8, 0x3e, 0xe6, 0x18, +0x37, 0x5a, 0x2a, 0x72, 0xf9, 0xda, 0x62, 0x90, 0x92, 0x95, 0xca, 0x1f, 0x9c, 0xe9, 0xb3, 0x3c, +0x2b, 0xcb, 0xf3, 0x01, 0x13, 0xbf, 0x5a, 0xcf, 0xc1, 0xb5, 0x0a, 0x60, 0xbd, 0xdd, 0xb5, 0x99, +0x64, 0x53, 0xb8, 0xa0, 0x96, 0xb3, 0x6f, 0xe2, 0x26, 0x77, 0x91, 0x8c, 0xe0, 0x62, 0x10, 0x02, +0x9f, 0x34, 0x0f, 0xa4, 0xd5, 0x92, 0x33, 0x51, 0xde, 0xbe, 0x8d, 0xba, 0x84, 0x7a, 0x60, 0x3c, +0x6a, 0xdb, 0x9f, 0x2b, 0xec, 0xde, 0xde, 0x01, 0x3f, 0x6e, 0x4d, 0xe5, 0x50, 0x86, 0xcb, 0xb4, +0xaf, 0xed, 0x44, 0x40, 0xc5, 0xca, 0x5a, 0x8c, 0xda, 0xd2, 0x2b, 0x7c, 0xa8, 0xee, 0xbe, 0xa6, +0xe5, 0x0a, 0xaa, 0x0e, 0xa5, 0xdf, 0x05, 0x52, 0xb7, 0x55, 0xc7, 0x22, 0x5d, 0x32, 0x6a, 0x97, +0x97, 0x63, 0x13, 0xdb, 0xc9, 0xdb, 0x79, 0x36, 0x7b, 0x85, 0x3a, 0x4a, 0xc5, 0x52, 0x89, 0xf9, +0x24, 0xe7, 0x9d, 0x77, 0xa9, 0x82, 0xff, 0x55, 0x1c, 0xa5, 0x71, 0x69, 0x2b, 0xd1, 0x02, 0x24, +0xf2, 0xb3, 0x26, 0xd4, 0x6b, 0xda, 0x04, 0x55, 0xe5, 0xc1, 0x0a, 0xc7, 0x6d, 0x30, 0x37, 0x90, +0x2a, 0xe4, 0x9e, 0x14, 0x33, 0x5e, 0x16, 0x17, 0x55, 0xc5, 0x5b, 0xb5, 0xcb, 0x34, 0x89, 0x92, +0xf1, 0x9d, 0x26, 0x8f, 0xa1, 0x07, 0xd4, 0xc6, 0xb2, 0x78, 0x50, 0xdb, 0x0c, 0x0c, 0x0b, 0x7c, +0x0b, 0x8c, 0x41, 0xd7, 0xb9, 0xe9, 0xdd, 0x8c, 0x88, 0xf7, 0xa3, 0x4d, 0xb2, 0x32, 0xcc, 0xd8, +0x17, 0xda, 0xcd, 0xb7, 0xce, 0x66, 0x9d, 0xd4, 0xfd, 0x5e, 0xff, 0xbd, 0x97, 0x3e, 0x29, 0x75, +0xe7, 0x7e, 0xa7, 0x62, 0x58, 0xaf, 0x25, 0x34, 0xa5, 0x41, 0xc7, 0x3d, 0xbc, 0x0d, 0x50, 0xca, +0x03, 0x03, 0x0f, 0x08, 0x5a, 0x1f, 0x95, 0x73, 0x78, 0x62, 0xbf, 0xaf, 0x72, 0x14, 0x69, 0x0e, +0xa5, 0xe5, 0x03, 0x0e, 0x78, 0x8e, 0x26, 0x28, 0x42, 0xf0, 0x07, 0x0b, 0x62, 0x20, 0x10, 0x67, +0x39, 0x46, 0xfa, 0xa9, 0x03, 0xcc, 0x04, 0x38, 0x7a, 0x66, 0xef, 0x20, 0x83, 0xb5, 0x8c, 0x4a, +0x56, 0x8e, 0x91, 0x00, 0xfc, 0x8e, 0x5c, 0x82, 0xde, 0x88, 0xa0, 0xc3, 0xe2, 0x68, 0x6e, 0x7d, +0x8d, 0xef, 0x3c, 0xdd, 0x65, 0xf4, 0x5d, 0xac, 0x51, 0xef, 0x24, 0x80, 0xae, 0xaa, 0x56, 0x97, +0x6f, 0xf9, 0xad, 0x7d, 0xda, 0x61, 0x3f, 0x98, 0x77, 0x3c, 0xa5, 0x91, 0xb6, 0x1c, 0x8c, 0x26, +0xda, 0x65, 0xa2, 0x09, 0x6d, 0xc1, 0xe2, 0x54, 0xe3, 0xb9, 0xca, 0x4c, 0x4c, 0x80, 0x8f, 0x77, +0x7b, 0x60, 0x9a, 0x1e, 0xdf, 0xb6, 0xf2, 0x48, 0x1e, 0x0e, 0xba, 0x4e, 0x54, 0x6d, 0x98, 0xe0, +0xe1, 0xa2, 0x1a, 0xa2, 0x77, 0x50, 0xcf, 0xc4, 0x63, 0x92, 0xec, 0x47, 0x19, 0x9d, 0xeb, 0xe6, +0x6b, 0xce, 0xc1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xac, 0x30, 0x81, 0xa9, 0x30, 0x0e, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x5b, 0x25, 0x7b, 0x96, 0xa4, 0x65, +0x51, 0x7e, 0xb8, 0x39, 0xf3, 0xc0, 0x78, 0x66, 0x5e, 0xe8, 0x3a, 0xe7, 0xf0, 0xee, 0x30, 0x1f, +0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x5b, 0x25, 0x7b, 0x96, 0xa4, +0x65, 0x51, 0x7e, 0xb8, 0x39, 0xf3, 0xc0, 0x78, 0x66, 0x5e, 0xe8, 0x3a, 0xe7, 0xf0, 0xee, 0x30, +0x46, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x09, 0x60, 0x85, +0x74, 0x01, 0x59, 0x01, 0x02, 0x01, 0x01, 0x30, 0x2e, 0x30, 0x2c, 0x06, 0x08, 0x2b, 0x06, 0x01, +0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x72, 0x65, +0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x73, 0x77, 0x69, 0x73, 0x73, 0x73, 0x69, +0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x27, 0xba, 0xe3, 0x94, 0x7c, +0xf1, 0xae, 0xc0, 0xde, 0x17, 0xe6, 0xe5, 0xd8, 0xd5, 0xf5, 0x54, 0xb0, 0x83, 0xf4, 0xbb, 0xcd, +0x5e, 0x05, 0x7b, 0x4f, 0x9f, 0x75, 0x66, 0xaf, 0x3c, 0xe8, 0x56, 0x7e, 0xfc, 0x72, 0x78, 0x38, +0x03, 0xd9, 0x2b, 0x62, 0x1b, 0x00, 0xb9, 0xf8, 0xe9, 0x60, 0xcd, 0xcc, 0xce, 0x51, 0x8a, 0xc7, +0x50, 0x31, 0x6e, 0xe1, 0x4a, 0x7e, 0x18, 0x2f, 0x69, 0x59, 0xb6, 0x3d, 0x64, 0x81, 0x2b, 0xe3, +0x83, 0x84, 0xe6, 0x22, 0x87, 0x8e, 0x7d, 0xe0, 0xee, 0x02, 0x99, 0x61, 0xb8, 0x1e, 0xf4, 0xb8, +0x2b, 0x88, 0x12, 0x16, 0x84, 0xc2, 0x31, 0x93, 0x38, 0x96, 0x31, 0xa6, 0xb9, 0x3b, 0x53, 0x3f, +0xc3, 0x24, 0x93, 0x56, 0x5b, 0x69, 0x92, 0xec, 0xc5, 0xc1, 0xbb, 0x38, 0x00, 0xe3, 0xec, 0x17, +0xa9, 0xb8, 0xdc, 0xc7, 0x7c, 0x01, 0x83, 0x9f, 0x32, 0x47, 0xba, 0x52, 0x22, 0x34, 0x1d, 0x32, +0x7a, 0x09, 0x56, 0xa7, 0x7c, 0x25, 0x36, 0xa9, 0x3d, 0x4b, 0xda, 0xc0, 0x82, 0x6f, 0x0a, 0xbb, +0x12, 0xc8, 0x87, 0x4b, 0x27, 0x11, 0xf9, 0x1e, 0x2d, 0xc7, 0x93, 0x3f, 0x9e, 0xdb, 0x5f, 0x26, +0x6b, 0x52, 0xd9, 0x2e, 0x8a, 0xf1, 0x14, 0xc6, 0x44, 0x8d, 0x15, 0xa9, 0xb7, 0xbf, 0xbd, 0xde, +0xa6, 0x1a, 0xee, 0xae, 0x2d, 0xfb, 0x48, 0x77, 0x17, 0xfe, 0xbb, 0xec, 0xaf, 0x18, 0xf5, 0x2a, +0x51, 0xf0, 0x39, 0x84, 0x97, 0x95, 0x6c, 0x6e, 0x1b, 0xc3, 0x2b, 0xc4, 0x74, 0x60, 0x79, 0x25, +0xb0, 0x0a, 0x27, 0xdf, 0xdf, 0x5e, 0xd2, 0x39, 0xcf, 0x45, 0x7d, 0x42, 0x4b, 0xdf, 0xb3, 0x2c, +0x1e, 0xc5, 0xc6, 0x5d, 0xca, 0x55, 0x3a, 0xa0, 0x9c, 0x69, 0x9a, 0x8f, 0xda, 0xef, 0xb2, 0xb0, +0x3c, 0x9f, 0x87, 0x6c, 0x12, 0x2b, 0x65, 0x70, 0x15, 0x52, 0x31, 0x1a, 0x24, 0xcf, 0x6f, 0x31, +0x23, 0x50, 0x1f, 0x8c, 0x4f, 0x8f, 0x23, 0xc3, 0x74, 0x41, 0x63, 0x1c, 0x55, 0xa8, 0x14, 0xdd, +0x3e, 0xe0, 0x51, 0x50, 0xcf, 0xf1, 0x1b, 0x30, 0x56, 0x0e, 0x92, 0xb0, 0x82, 0x85, 0xd8, 0x83, +0xcb, 0x22, 0x64, 0xbc, 0x2d, 0xb8, 0x25, 0xd5, 0x54, 0xa2, 0xb8, 0x06, 0xea, 0xad, 0x92, 0xa4, +0x24, 0xa0, 0xc1, 0x86, 0xb5, 0x4a, 0x13, 0x6a, 0x47, 0xcf, 0x2e, 0x0b, 0x56, 0x95, 0x54, 0xcb, +0xce, 0x9a, 0xdb, 0x6a, 0xb4, 0xa6, 0xb2, 0xdb, 0x41, 0x08, 0x86, 0x27, 0x77, 0xf7, 0x6a, 0xa0, +0x42, 0x6c, 0x0b, 0x38, 0xce, 0xd7, 0x75, 0x50, 0x32, 0x92, 0xc2, 0xdf, 0x2b, 0x30, 0x22, 0x48, +0xd0, 0xd5, 0x41, 0x38, 0x25, 0x5d, 0xa4, 0xe9, 0x5d, 0x9f, 0xc6, 0x94, 0x75, 0xd0, 0x45, 0xfd, +0x30, 0x97, 0x43, 0x8f, 0x90, 0xab, 0x0a, 0xc7, 0x86, 0x73, 0x60, 0x4a, 0x69, 0x2d, 0xde, 0xa5, +0x78, 0xd7, 0x06, 0xda, 0x6a, 0x9e, 0x4b, 0x3e, 0x77, 0x3a, 0x20, 0x13, 0x22, 0x01, 0xd0, 0xbf, +0x68, 0x9e, 0x63, 0x60, 0x6b, 0x35, 0x4d, 0x0b, 0x6d, 0xba, 0xa1, 0x3d, 0xc0, 0x93, 0xe0, 0x7f, +0x23, 0xb3, 0x55, 0xad, 0x72, 0x25, 0x4e, 0x46, 0xf9, 0xd2, 0x16, 0xef, 0xb0, 0x64, 0xc1, 0x01, +0x9e, 0xe9, 0xca, 0xa0, 0x6a, 0x98, 0x0e, 0xcf, 0xd8, 0x60, 0xf2, 0x2f, 0x49, 0xb8, 0xe4, 0x42, +0xe1, 0x38, 0x35, 0x16, 0xf4, 0xc8, 0x6e, 0x4f, 0xf7, 0x81, 0x56, 0xe8, 0xba, 0xa3, 0xbe, 0x23, +0xaf, 0xae, 0xfd, 0x6f, 0x03, 0xe0, 0x02, 0x3b, 0x30, 0x76, 0xfa, 0x1b, 0x6d, 0x41, 0xcf, 0x01, +0xb1, 0xe9, 0xb8, 0xc9, 0x66, 0xf4, 0xdb, 0x26, 0xf3, 0x3a, 0xa4, 0x74, 0xf2, 0x49, 0x24, 0x5b, +0xc9, 0xb0, 0xd0, 0x57, 0xc1, 0xfa, 0x3e, 0x7a, 0xe1, 0x97, 0xc9, 0x30, 0x82, 0x02, 0x40, 0x30, +0x82, 0x01, 0xe5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0c, 0x01, 0x54, 0x48, 0xef, 0x21, 0xfd, +0x97, 0x59, 0x0d, 0xf5, 0x04, 0x0a, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, +0x03, 0x02, 0x30, 0x71, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, +0x55, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, +0x70, 0x65, 0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, +0x69, 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x17, 0x30, 0x15, +0x06, 0x03, 0x55, 0x04, 0x61, 0x0c, 0x0e, 0x56, 0x41, 0x54, 0x48, 0x55, 0x2d, 0x32, 0x33, 0x35, +0x38, 0x34, 0x34, 0x39, 0x37, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, +0x65, 0x2d, 0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, +0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x38, 0x32, 0x32, 0x31, +0x32, 0x30, 0x37, 0x30, 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x38, 0x32, 0x32, 0x31, 0x32, +0x30, 0x37, 0x30, 0x36, 0x5a, 0x30, 0x71, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, +0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x0d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, +0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0c, 0x0e, 0x56, 0x41, 0x54, 0x48, 0x55, 0x2d, +0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x15, 0x65, 0x2d, 0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, +0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, +0x42, 0x00, 0x04, 0x96, 0xdc, 0x3d, 0x8a, 0xd8, 0xb0, 0x7b, 0x6f, 0xc6, 0x27, 0xbe, 0x44, 0x90, +0xb1, 0xb3, 0x56, 0x15, 0x7b, 0x8e, 0x43, 0x24, 0x7d, 0x1a, 0x84, 0x59, 0xee, 0x63, 0x68, 0xb2, +0xc6, 0x5e, 0x87, 0xd0, 0x15, 0x48, 0x1e, 0xa8, 0x90, 0xad, 0xbd, 0x53, 0xa2, 0xda, 0xde, 0x3a, +0x90, 0xa6, 0x60, 0x5f, 0x68, 0x32, 0xb5, 0x86, 0x41, 0xdf, 0x87, 0x5b, 0x2c, 0x7b, 0xc5, 0xfe, +0x7c, 0x7a, 0xda, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, +0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, +0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, +0x16, 0x04, 0x14, 0x87, 0x11, 0x15, 0x08, 0xd1, 0xaa, 0xc1, 0x78, 0x0c, 0xb1, 0xaf, 0xce, 0xc6, +0xc9, 0x90, 0xef, 0xbf, 0x30, 0x04, 0xc0, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, +0x30, 0x16, 0x80, 0x14, 0x87, 0x11, 0x15, 0x08, 0xd1, 0xaa, 0xc1, 0x78, 0x0c, 0xb1, 0xaf, 0xce, +0xc6, 0xc9, 0x90, 0xef, 0xbf, 0x30, 0x04, 0xc0, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, +0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xb5, 0x57, 0xdd, 0xd7, +0x8a, 0x55, 0x0b, 0x36, 0xe1, 0x86, 0x44, 0xfa, 0xd4, 0xd9, 0x68, 0x8d, 0xb8, 0xdc, 0x23, 0x8a, +0x8a, 0x0d, 0xd4, 0x2f, 0x7d, 0xea, 0x73, 0xec, 0xbf, 0x4d, 0x6c, 0xa8, 0x02, 0x21, 0x00, 0xcb, +0xa5, 0xb4, 0x12, 0xfa, 0xe7, 0xb5, 0xe8, 0xcf, 0x7e, 0x93, 0xfc, 0xf3, 0x35, 0x8f, 0x6f, 0x4e, +0x5a, 0x7c, 0xb4, 0xbc, 0x4e, 0xb2, 0xfc, 0x72, 0xaa, 0x5b, 0x59, 0xf9, 0xe7, 0xdc, 0x31, 0x30, +0x82, 0x02, 0x60, 0x30, 0x82, 0x02, 0x07, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0c, 0x0d, 0x6a, +0x5f, 0x08, 0x3f, 0x28, 0x5c, 0x3e, 0x51, 0x95, 0xdf, 0x5d, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, +0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, +0x08, 0x49, 0x6c, 0x6c, 0x69, 0x6e, 0x6f, 0x69, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x04, 0x07, 0x13, 0x07, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x31, 0x21, 0x30, 0x1f, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, +0x48, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3a, +0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, +0x76, 0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x32, +0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, +0x30, 0x38, 0x32, 0x33, 0x31, 0x39, 0x33, 0x35, 0x31, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, +0x38, 0x32, 0x33, 0x31, 0x39, 0x33, 0x35, 0x31, 0x30, 0x5a, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x04, 0x08, 0x13, 0x08, 0x49, 0x6c, 0x6c, 0x69, 0x6e, 0x6f, 0x69, 0x73, 0x31, 0x10, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x31, +0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, +0x61, 0x76, 0x65, 0x20, 0x48, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x49, 0x6e, +0x63, 0x2e, 0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, +0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x45, 0x43, +0x43, 0x20, 0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x59, +0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x7e, 0xfb, 0x6c, 0xe6, 0x23, 0xe3, 0x73, +0x32, 0x08, 0xca, 0x60, 0xe6, 0x53, 0x9c, 0xba, 0x74, 0x8d, 0x18, 0xb0, 0x78, 0x90, 0x52, 0x80, +0xdd, 0x38, 0xc0, 0x4a, 0x1d, 0xd1, 0xa8, 0xcc, 0x93, 0xa4, 0x97, 0x06, 0x38, 0xca, 0x0d, 0x15, +0x62, 0xc6, 0x8e, 0x01, 0x2a, 0x65, 0x9d, 0xaa, 0xdf, 0x34, 0x91, 0x2e, 0x81, 0xc1, 0xe4, 0x33, +0x92, 0x31, 0xc4, 0xfd, 0x09, 0x3a, 0xa6, 0x3f, 0xad, 0xa3, 0x43, 0x30, 0x41, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x05, 0x03, 0x03, 0x07, 0x06, 0x00, 0x30, +0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa3, 0x41, 0x06, 0xac, 0x90, 0x6d, +0xd1, 0x4a, 0xeb, 0x75, 0xa5, 0x4a, 0x10, 0x99, 0xb3, 0xb1, 0xa1, 0x8b, 0x4a, 0xf7, 0x30, 0x0a, +0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, +0x20, 0x07, 0xe6, 0x54, 0xda, 0x0e, 0xa0, 0x5a, 0xb2, 0xae, 0x11, 0x9f, 0x87, 0xc5, 0xb6, 0xff, +0x69, 0xde, 0x25, 0xbe, 0xf8, 0xa0, 0xb7, 0x08, 0xf3, 0x44, 0xce, 0x2a, 0xdf, 0x08, 0x21, 0x0c, +0x37, 0x02, 0x20, 0x2d, 0x26, 0x03, 0xa0, 0x05, 0xbd, 0x6b, 0xd1, 0xf6, 0x5c, 0xf8, 0x65, 0xcc, +0x86, 0x6d, 0xb3, 0x9c, 0x34, 0x48, 0x63, 0x84, 0x09, 0xc5, 0x8d, 0x77, 0x1a, 0xe2, 0xcc, 0x9c, +0xe1, 0x74, 0x7b, 0x30, 0x82, 0x05, 0xda, 0x30, 0x82, 0x03, 0xc2, 0xa0, 0x03, 0x02, 0x01, 0x02, +0x02, 0x0c, 0x05, 0xf7, 0x0e, 0x86, 0xda, 0x49, 0xf3, 0x46, 0x35, 0x2e, 0xba, 0xb2, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x88, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x49, 0x6c, 0x6c, 0x69, 0x6e, 0x6f, 0x69, 0x73, +0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x43, 0x68, 0x69, 0x63, 0x61, +0x67, 0x6f, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x54, 0x72, 0x75, +0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x48, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, +0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x28, +0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, +0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x38, +0x32, 0x33, 0x31, 0x39, 0x33, 0x34, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x38, 0x32, +0x33, 0x31, 0x39, 0x33, 0x34, 0x31, 0x32, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, +0x08, 0x0c, 0x08, 0x49, 0x6c, 0x6c, 0x69, 0x6e, 0x6f, 0x69, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x31, 0x21, 0x30, +0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, +0x65, 0x20, 0x48, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, +0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, +0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, +0x69, 0x74, 0x79, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, +0x82, 0x02, 0x01, 0x00, 0xb9, 0x5d, 0x51, 0x28, 0x4b, 0x3c, 0x37, 0x92, 0xd1, 0x82, 0xce, 0xbd, +0x1d, 0xbd, 0xcd, 0xdd, 0xb8, 0xab, 0xcf, 0x0a, 0x3e, 0xe1, 0x5d, 0xe5, 0xdc, 0xaa, 0x09, 0xb9, +0x57, 0x02, 0x3e, 0xe6, 0x63, 0x61, 0xdf, 0xf2, 0x0f, 0x82, 0x63, 0xae, 0xa3, 0xf7, 0xac, 0x73, +0xd1, 0x7c, 0xe7, 0xb3, 0x0b, 0xaf, 0x08, 0x00, 0x09, 0x59, 0x7f, 0xcd, 0x29, 0x2a, 0x88, 0x93, +0x87, 0x17, 0x18, 0x80, 0xed, 0x88, 0xb2, 0xb4, 0xb6, 0x10, 0x1f, 0x2d, 0xd6, 0x5f, 0x55, 0xa2, +0x13, 0x5d, 0xd1, 0xc6, 0xeb, 0x06, 0x56, 0x89, 0x88, 0xfe, 0xac, 0x32, 0x9d, 0xfd, 0x5c, 0xc3, +0x05, 0xc7, 0x6e, 0xee, 0x86, 0x89, 0xba, 0x88, 0x03, 0x9d, 0x72, 0x21, 0x86, 0x90, 0xae, 0x8f, +0x03, 0xa5, 0xdc, 0x9f, 0x88, 0x28, 0xcb, 0xa3, 0x92, 0x49, 0x0f, 0xec, 0xd0, 0x0f, 0xe2, 0x6d, +0x44, 0x4f, 0x80, 0x6a, 0xb2, 0xd4, 0xe7, 0xa0, 0x0a, 0x53, 0x01, 0xba, 0x8e, 0x97, 0x91, 0x76, +0x6e, 0xbc, 0xfc, 0xd5, 0x6b, 0x36, 0xe6, 0x40, 0x88, 0xd6, 0x7b, 0x2f, 0x5f, 0x05, 0xe8, 0x2c, +0x6d, 0x11, 0xf3, 0xe7, 0xb2, 0xbe, 0x92, 0x44, 0x4c, 0xd2, 0x97, 0xa4, 0xfe, 0xd2, 0x72, 0x81, +0x43, 0x07, 0x9c, 0xe9, 0x11, 0x3e, 0xf5, 0x8b, 0x1a, 0x59, 0x7d, 0x1f, 0x68, 0x58, 0xdd, 0x04, +0x00, 0x2c, 0x96, 0xf3, 0x43, 0xb3, 0x7e, 0x98, 0x19, 0x74, 0xd9, 0x9c, 0x73, 0xd9, 0x18, 0xbe, +0x41, 0xc7, 0x34, 0x79, 0xd9, 0xf4, 0x62, 0xc2, 0x43, 0xb9, 0xb3, 0x27, 0xb0, 0x22, 0xcb, 0xf9, +0x3d, 0x52, 0xc7, 0x30, 0x47, 0xb3, 0xc9, 0x3e, 0xb8, 0x6a, 0xe2, 0xe7, 0xe8, 0x81, 0x70, 0x5e, +0x42, 0x8b, 0x4f, 0x26, 0xa5, 0xfe, 0x3a, 0xc2, 0x20, 0x6e, 0xbb, 0xf8, 0x16, 0x8e, 0xcd, 0x0c, +0xa9, 0xb4, 0x1b, 0x6c, 0x76, 0x10, 0xe1, 0x58, 0x79, 0x46, 0x3e, 0x54, 0xce, 0x80, 0xa8, 0x57, +0x09, 0x37, 0x29, 0x1b, 0x99, 0x13, 0x8f, 0x0c, 0xc8, 0xd6, 0x2c, 0x1c, 0xfb, 0x05, 0xe8, 0x08, +0x95, 0x3d, 0x65, 0x46, 0xdc, 0xee, 0xcd, 0x69, 0xe2, 0x4d, 0x8f, 0x87, 0x28, 0x4e, 0x34, 0x0b, +0x3e, 0xcf, 0x14, 0xd9, 0xbb, 0xdd, 0xb6, 0x50, 0x9a, 0xad, 0x77, 0xd4, 0x19, 0xd6, 0xda, 0x1a, +0x88, 0xc8, 0x4e, 0x1b, 0x27, 0x75, 0xd8, 0xb2, 0x08, 0xf1, 0xae, 0x83, 0x30, 0xb9, 0x11, 0x0e, +0xcd, 0x87, 0xf0, 0x84, 0x8d, 0x15, 0x72, 0x7c, 0xa1, 0xef, 0xcc, 0xf2, 0x88, 0x61, 0xba, 0xf4, +0x69, 0xbb, 0x0c, 0x8c, 0x0b, 0x75, 0x57, 0x04, 0xb8, 0x4e, 0x2a, 0x14, 0x2e, 0x3d, 0x0f, 0x1c, +0x1e, 0x32, 0xa6, 0x62, 0x36, 0xee, 0x66, 0xe2, 0x22, 0xb8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xf3, +0x33, 0x1d, 0x74, 0x72, 0x8a, 0x2c, 0xf5, 0x39, 0x29, 0xa0, 0xd3, 0xe7, 0x1b, 0x80, 0x84, 0x2d, +0xc5, 0x3d, 0xe3, 0x4d, 0xb1, 0xfd, 0x1a, 0x6f, 0xba, 0x65, 0x07, 0x3b, 0x58, 0xec, 0x42, 0x45, +0x26, 0xfb, 0xd8, 0xda, 0x25, 0x72, 0xc4, 0xf6, 0x00, 0xb1, 0x22, 0x79, 0xbd, 0xe3, 0x7c, 0x59, +0x62, 0x4a, 0x9c, 0x05, 0x6f, 0x3d, 0xce, 0xe6, 0xd6, 0x47, 0x63, 0x99, 0xc6, 0x24, 0x6f, 0x72, +0x12, 0xc8, 0xac, 0x7f, 0x90, 0xb4, 0x0b, 0x91, 0x70, 0xe8, 0xb7, 0xe6, 0x16, 0x10, 0x71, 0x17, +0xce, 0xde, 0x06, 0x4f, 0x48, 0x41, 0x7d, 0x35, 0x4a, 0xa3, 0x89, 0xf2, 0xc9, 0x4b, 0x7b, 0x41, +0x11, 0x6d, 0x67, 0xb7, 0x08, 0x98, 0x4c, 0xe5, 0x11, 0x19, 0xae, 0x42, 0x80, 0xdc, 0xfb, 0x90, +0x05, 0xd4, 0xf8, 0x50, 0xca, 0xbe, 0xe4, 0xad, 0xc7, 0xc2, 0x94, 0xd7, 0x16, 0x9d, 0xe6, 0x17, +0x8f, 0xaf, 0x36, 0xfb, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x99, 0xe0, 0x19, 0x67, 0x0d, 0x62, 0xdb, +0x76, 0xb3, 0xda, 0x3d, 0xb8, 0x5b, 0xe8, 0xfd, 0x42, 0xd2, 0x31, 0x0e, 0x87, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, +0x00, 0x98, 0x73, 0x70, 0xe2, 0xb0, 0xd3, 0xed, 0x39, 0xec, 0x4c, 0x60, 0xd9, 0xa9, 0x12, 0x86, +0x17, 0x1e, 0x96, 0xd0, 0xe8, 0x54, 0x28, 0x3b, 0x64, 0x2d, 0x21, 0xa6, 0xf8, 0x9d, 0x56, 0x13, +0x6a, 0x48, 0x3d, 0x4f, 0xc7, 0x3e, 0x29, 0xdb, 0x6d, 0x58, 0x83, 0x54, 0x3d, 0x87, 0x7d, 0x23, +0x05, 0xd4, 0xe4, 0x1c, 0xdc, 0xe8, 0x38, 0x65, 0x86, 0xc5, 0x75, 0xa7, 0x5a, 0xdb, 0x35, 0x05, +0xbd, 0x77, 0xde, 0xbb, 0x29, 0x37, 0x40, 0x05, 0x07, 0xc3, 0x94, 0x52, 0x9f, 0xca, 0x64, 0xdd, +0xf1, 0x1b, 0x2b, 0xdc, 0x46, 0x0a, 0x10, 0x02, 0x31, 0xfd, 0x4a, 0x68, 0x0d, 0x07, 0x64, 0x90, +0xe6, 0x1e, 0xf5, 0x2a, 0xa1, 0xa8, 0xbb, 0x3c, 0x5d, 0xf9, 0xa3, 0x08, 0x0b, 0x11, 0x0c, 0xf1, +0x3f, 0x2d, 0x10, 0x94, 0x6f, 0xfe, 0xe2, 0x34, 0x87, 0x83, 0xd6, 0xcf, 0xe5, 0x1b, 0x35, 0x6d, +0xd2, 0x03, 0xe1, 0xb0, 0x0d, 0xa8, 0xa0, 0xaa, 0x46, 0x27, 0x82, 0x36, 0xa7, 0x15, 0xb6, 0x08, +0xa6, 0x42, 0x54, 0x57, 0xb6, 0x99, 0x5a, 0xe2, 0x0b, 0x79, 0x90, 0xd7, 0x57, 0x12, 0x51, 0x35, +0x19, 0x88, 0x41, 0x68, 0x25, 0xd4, 0x37, 0x17, 0x84, 0x15, 0xfb, 0x01, 0x72, 0xdc, 0x95, 0xde, +0x52, 0x26, 0x20, 0x98, 0x26, 0xe2, 0x76, 0xf5, 0x27, 0x6f, 0xfa, 0x00, 0x3b, 0x4a, 0x61, 0xd9, +0x0d, 0xcb, 0x51, 0x93, 0x2a, 0xfd, 0x16, 0x06, 0x96, 0xa7, 0x23, 0x9a, 0x23, 0x48, 0xfe, 0x51, +0xbd, 0xb6, 0xc4, 0xb0, 0xb1, 0x54, 0xce, 0xde, 0x6c, 0x41, 0xad, 0x16, 0x67, 0x7e, 0xdb, 0xfd, +0x38, 0xcd, 0xb9, 0x38, 0x4e, 0xb2, 0xc1, 0x60, 0xcb, 0x9d, 0x17, 0xdf, 0x58, 0x9e, 0x7a, 0x62, +0xb2, 0x26, 0x8f, 0x74, 0x95, 0x9b, 0xe4, 0x5b, 0x1d, 0xd2, 0x0f, 0xdd, 0x98, 0x1c, 0x9b, 0x59, +0xb9, 0x23, 0xd3, 0x31, 0xa0, 0xa6, 0xff, 0x38, 0xdd, 0xcf, 0x20, 0x4f, 0xe9, 0x58, 0x56, 0x3a, +0x67, 0xc3, 0xd1, 0xf6, 0x99, 0x99, 0x9d, 0xba, 0x36, 0xb6, 0x80, 0x2f, 0x88, 0x47, 0x4f, 0x86, +0xbf, 0x44, 0x3a, 0x80, 0xe4, 0x37, 0x1c, 0xa6, 0xba, 0xea, 0x97, 0x98, 0x11, 0xd0, 0x84, 0x62, +0x47, 0x64, 0x1e, 0xaa, 0xee, 0x40, 0xbf, 0x34, 0xb1, 0x9c, 0x8f, 0x4e, 0xe1, 0xf2, 0x92, 0x4f, +0x1f, 0x8e, 0xf3, 0x9e, 0x97, 0xde, 0xf3, 0xa6, 0x79, 0x6a, 0x89, 0x71, 0x4f, 0x4b, 0x27, 0x17, +0x48, 0xfe, 0xec, 0xf4, 0x50, 0x0f, 0x4f, 0x49, 0x7d, 0xcc, 0x45, 0xe3, 0xbd, 0x7a, 0x40, 0xc5, +0x41, 0xdc, 0x61, 0x56, 0x27, 0x06, 0x69, 0xe5, 0x72, 0x41, 0x81, 0xd3, 0xb6, 0x01, 0x89, 0xa0, +0x2f, 0x3a, 0x72, 0x79, 0xfe, 0x3a, 0x30, 0xbf, 0x41, 0xec, 0xc7, 0x62, 0x3e, 0x91, 0x4b, 0xc7, +0xd9, 0x31, 0x76, 0x42, 0xf9, 0xf7, 0x3c, 0x63, 0xec, 0x26, 0x8c, 0x73, 0x0c, 0x7d, 0x1a, 0x1d, +0xea, 0xa8, 0x7c, 0x87, 0xa8, 0xc2, 0x27, 0x7c, 0xe1, 0x33, 0x41, 0x0f, 0xcf, 0xcf, 0xfc, 0x00, +0xa0, 0x22, 0x80, 0x9e, 0x4a, 0xa7, 0x6f, 0x00, 0xb0, 0x41, 0x45, 0xb7, 0x22, 0xca, 0x68, 0x48, +0xc5, 0x42, 0xa2, 0xae, 0xdd, 0x1d, 0xf2, 0xe0, 0x6e, 0x4e, 0x05, 0x58, 0xb1, 0xc0, 0x90, 0x16, +0x2a, 0xa4, 0x3d, 0x10, 0x40, 0xbe, 0x8f, 0x62, 0x63, 0x83, 0xa9, 0x9c, 0x82, 0x7d, 0x2d, 0x02, +0xe9, 0x83, 0x30, 0x7c, 0xcb, 0x27, 0xc9, 0xfd, 0x1e, 0x66, 0x00, 0xb0, 0x2e, 0xd3, 0x21, 0x2f, +0x8e, 0x33, 0x16, 0x6c, 0x98, 0xed, 0x10, 0xa8, 0x07, 0xd6, 0xcc, 0x93, 0xcf, 0xdb, 0xd1, 0x69, +0x1c, 0xe4, 0xca, 0xc9, 0xe0, 0xb6, 0x9c, 0xe9, 0xce, 0x71, 0x71, 0xde, 0x6c, 0x3f, 0x16, 0xa4, +0x79, 0x30, 0x82, 0x02, 0x9d, 0x30, 0x82, 0x02, 0x24, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0c, +0x08, 0xbd, 0x85, 0x97, 0x6c, 0x99, 0x27, 0xa4, 0x80, 0x68, 0x47, 0x3b, 0x30, 0x0a, 0x06, 0x08, +0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, +0x08, 0x13, 0x08, 0x49, 0x6c, 0x6c, 0x69, 0x6e, 0x6f, 0x69, 0x73, 0x31, 0x10, 0x30, 0x0e, 0x06, +0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x31, 0x21, 0x30, +0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, +0x65, 0x20, 0x48, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, +0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, +0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x45, 0x43, 0x43, 0x20, +0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, +0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, +0x31, 0x37, 0x30, 0x38, 0x32, 0x33, 0x31, 0x39, 0x33, 0x36, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x34, +0x32, 0x30, 0x38, 0x32, 0x33, 0x31, 0x39, 0x33, 0x36, 0x34, 0x33, 0x5a, 0x30, 0x81, 0x91, 0x31, +0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, +0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x08, 0x49, 0x6c, 0x6c, 0x69, 0x6e, 0x6f, 0x69, 0x73, 0x31, +0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, +0x6f, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, +0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x48, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, +0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x31, 0x54, +0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, +0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, +0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x6b, 0xda, 0x0d, 0x75, 0x35, 0x08, 0x31, 0x47, +0x05, 0xae, 0x45, 0x99, 0x55, 0xf1, 0x11, 0x13, 0x2e, 0x4a, 0xf8, 0x10, 0x31, 0x23, 0xa3, 0x7e, +0x83, 0xd3, 0x7f, 0x28, 0x08, 0x3a, 0x26, 0x1a, 0x3a, 0xcf, 0x97, 0x82, 0x1f, 0x80, 0xb7, 0x27, +0x09, 0x8f, 0xd1, 0x8e, 0x30, 0xc4, 0x0a, 0x9b, 0x0e, 0xac, 0x58, 0x04, 0xab, 0xf7, 0x36, 0x7d, +0x94, 0x23, 0xa4, 0x9b, 0x0a, 0x8a, 0x8b, 0xab, 0xeb, 0xfd, 0x39, 0x25, 0x66, 0xf1, 0x5e, 0xfe, +0x8c, 0xae, 0x8d, 0x41, 0x79, 0x9d, 0x09, 0x60, 0xce, 0x28, 0xa9, 0xd3, 0x8a, 0x6d, 0xf3, 0xd6, +0x45, 0xd4, 0xf2, 0x98, 0x84, 0x38, 0x65, 0xa0, 0xa3, 0x43, 0x30, 0x41, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0f, 0x06, +0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x05, 0x03, 0x03, 0x07, 0x06, 0x00, 0x30, 0x1d, +0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, 0xa9, 0x84, 0x89, 0xd2, 0xc1, 0x32, +0xbd, 0x18, 0xcb, 0x6c, 0xa6, 0x07, 0x4e, 0xc8, 0xe7, 0x9d, 0xbe, 0x82, 0x90, 0x30, 0x0a, 0x06, +0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, 0x30, 0x64, 0x02, 0x30, +0x37, 0x01, 0x92, 0x97, 0x45, 0x12, 0x7e, 0xa0, 0xf3, 0x3e, 0xad, 0x19, 0x3a, 0x72, 0xdd, 0xf4, +0x50, 0x93, 0x03, 0x12, 0xbe, 0x44, 0xd2, 0x4f, 0x41, 0xa4, 0x8c, 0x9c, 0x9d, 0x1f, 0xa3, 0xf6, +0xc2, 0x92, 0xe7, 0x48, 0x14, 0xfe, 0x4e, 0x9b, 0xa5, 0x91, 0x57, 0xae, 0xc6, 0x37, 0x72, 0xbb, +0x02, 0x30, 0x67, 0x25, 0x0a, 0xb1, 0x0c, 0x5e, 0xee, 0xa9, 0x63, 0x92, 0x6f, 0xe5, 0x90, 0x0b, +0xfe, 0x66, 0x22, 0xca, 0x47, 0xfd, 0x8a, 0x31, 0xf7, 0x83, 0xfe, 0x7a, 0xbf, 0x10, 0xbe, 0x18, +0x2b, 0x1e, 0x8f, 0xf6, 0x29, 0x1e, 0x94, 0x59, 0xef, 0x8e, 0x21, 0x37, 0xcb, 0x51, 0x98, 0xa5, +0x6e, 0x4b, 0x30, 0x82, 0x04, 0x33, 0x30, 0x82, 0x03, 0x1b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x03, 0x09, 0x83, 0xf3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x30, 0x4d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x44, 0x2d, 0x54, +0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, +0x04, 0x03, 0x0c, 0x1e, 0x44, 0x2d, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, +0x30, 0x39, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 0x31, 0x31, 0x30, 0x35, 0x30, 0x38, 0x33, 0x35, +0x35, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x31, 0x31, 0x30, 0x35, 0x30, 0x38, 0x33, 0x35, 0x35, +0x38, 0x5a, 0x30, 0x4d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, +0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x44, 0x2d, 0x54, 0x72, +0x75, 0x73, 0x74, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, +0x03, 0x0c, 0x1e, 0x44, 0x2d, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, +0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30, 0x30, +0x39, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, +0x01, 0x00, 0xd3, 0xb2, 0x4a, 0xcf, 0x7a, 0x47, 0xef, 0x75, 0x9b, 0x23, 0xfa, 0x3a, 0x2f, 0xd6, +0x50, 0x45, 0x89, 0x35, 0x3a, 0xc6, 0x6b, 0xdb, 0xfe, 0xdb, 0x00, 0x68, 0xa8, 0xe0, 0x03, 0x11, +0x1d, 0x37, 0x50, 0x08, 0x9f, 0x4d, 0x4a, 0x68, 0x94, 0x35, 0xb3, 0x53, 0xd1, 0x94, 0x63, 0xa7, +0x20, 0x56, 0xaf, 0xde, 0x51, 0x78, 0xec, 0x2a, 0x3d, 0xf3, 0x48, 0x48, 0x50, 0x3e, 0x0a, 0xdf, +0x46, 0x55, 0x8b, 0x27, 0x6d, 0xc3, 0x10, 0x4d, 0x0d, 0x91, 0x52, 0x43, 0xd8, 0x87, 0xe0, 0x5d, +0x4e, 0x36, 0xb5, 0x21, 0xca, 0x5f, 0x39, 0x40, 0x04, 0x5f, 0x5b, 0x7e, 0xcc, 0xa3, 0xc6, 0x2b, +0xa9, 0x40, 0x1e, 0xd9, 0x36, 0x84, 0xd6, 0x48, 0xf3, 0x92, 0x1e, 0x34, 0x46, 0x20, 0x24, 0xc1, +0xa4, 0x51, 0x8e, 0x4a, 0x1a, 0xef, 0x50, 0x3f, 0x69, 0x5d, 0x19, 0x7f, 0x45, 0xc3, 0xc7, 0x01, +0x8f, 0x51, 0xc9, 0x23, 0xe8, 0x72, 0xae, 0xb4, 0xbc, 0x56, 0x09, 0x7f, 0x12, 0xcb, 0x1c, 0xb1, +0xaf, 0x29, 0x90, 0x0a, 0xc9, 0x55, 0xcc, 0x0f, 0xd3, 0xb4, 0x1a, 0xed, 0x47, 0x35, 0x5a, 0x4a, +0xed, 0x9c, 0x73, 0x04, 0x21, 0xd0, 0xaa, 0xbd, 0x0c, 0x13, 0xb5, 0x00, 0xca, 0x26, 0x6c, 0xc4, +0x6b, 0x0c, 0x94, 0x5a, 0x95, 0x94, 0xda, 0x50, 0x9a, 0xf1, 0xff, 0xa5, 0x2b, 0x66, 0x31, 0xa4, +0xc9, 0x38, 0xa0, 0xdf, 0x1d, 0x1f, 0xb8, 0x09, 0x2e, 0xf3, 0xa7, 0xe8, 0x67, 0x52, 0xab, 0x95, +0x1f, 0xe0, 0x46, 0x3e, 0xd8, 0xa4, 0xc3, 0xca, 0x5a, 0xc5, 0x31, 0x80, 0xe8, 0x48, 0x9a, 0x9f, +0x94, 0x69, 0xfe, 0x19, 0xdd, 0xd8, 0x73, 0x7c, 0x81, 0xca, 0x96, 0xde, 0x8e, 0xed, 0xb3, 0x32, +0x05, 0x65, 0x84, 0x34, 0xe6, 0xe6, 0xfd, 0x57, 0x10, 0xb5, 0x5f, 0x76, 0xbf, 0x2f, 0xb0, 0x10, +0x0d, 0xc5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x1a, 0x30, 0x82, 0x01, 0x16, 0x30, +0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, +0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfd, 0xda, 0x14, 0xc4, 0x9f, +0x30, 0xde, 0x21, 0xbd, 0x1e, 0x42, 0x39, 0xfc, 0xab, 0x63, 0x23, 0x49, 0xe0, 0xf1, 0x84, 0x30, +0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, +0x81, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x81, 0xcb, 0x30, 0x81, 0xc8, 0x30, 0x81, 0x80, +0xa0, 0x7e, 0xa0, 0x7c, 0x86, 0x7a, 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x69, 0x72, +0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x64, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, +0x65, 0x74, 0x2f, 0x43, 0x4e, 0x3d, 0x44, 0x2d, 0x54, 0x52, 0x55, 0x53, 0x54, 0x25, 0x32, 0x30, +0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x25, 0x32, 0x30, 0x33, +0x25, 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x25, 0x32, 0x30, 0x32, 0x30, 0x30, 0x39, +0x2c, 0x4f, 0x3d, 0x44, 0x2d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x25, 0x32, 0x30, 0x47, 0x6d, 0x62, +0x48, 0x2c, 0x43, 0x3d, 0x44, 0x45, 0x3f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, +0x74, 0x65, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6c, 0x69, 0x73, 0x74, +0x30, 0x43, 0xa0, 0x41, 0xa0, 0x3f, 0x86, 0x3d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, +0x77, 0x77, 0x2e, 0x64, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x63, +0x72, 0x6c, 0x2f, 0x64, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, +0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x33, 0x5f, 0x63, 0x61, 0x5f, 0x32, 0x5f, 0x32, 0x30, 0x30, +0x39, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7f, 0x97, 0xdb, 0x30, 0xc8, 0xdf, 0xa4, +0x9c, 0x7d, 0x21, 0x7a, 0x80, 0x70, 0xce, 0x14, 0x12, 0x69, 0x88, 0x14, 0x95, 0x60, 0x44, 0x01, +0xac, 0xb2, 0xe9, 0x30, 0x4f, 0x9b, 0x50, 0xc2, 0x66, 0xd8, 0x7e, 0x8d, 0x30, 0xb5, 0x70, 0x31, +0xe9, 0xe2, 0x69, 0xc7, 0xf3, 0x70, 0xdb, 0x20, 0x15, 0x86, 0xd0, 0x0d, 0xf0, 0xbe, 0xac, 0x01, +0x75, 0x84, 0xce, 0x7e, 0x9f, 0x4d, 0xbf, 0xb7, 0x60, 0x3b, 0x9c, 0xf3, 0xca, 0x1d, 0xe2, 0x5e, +0x68, 0xd8, 0xa3, 0x9d, 0x97, 0xe5, 0x40, 0x60, 0xd2, 0x36, 0x21, 0xfe, 0xd0, 0xb4, 0xb8, 0x17, +0xda, 0x74, 0xa3, 0x7f, 0xd4, 0xdf, 0xb0, 0x98, 0x02, 0xac, 0x6f, 0x6b, 0x6b, 0x2c, 0x25, 0x24, +0x72, 0xa1, 0x65, 0xee, 0x25, 0x5a, 0xe5, 0xe6, 0x32, 0xe7, 0xf2, 0xdf, 0xab, 0x49, 0xfa, 0xf3, +0x90, 0x69, 0x23, 0xdb, 0x04, 0xd9, 0xe7, 0x5c, 0x58, 0xfc, 0x65, 0xd4, 0x97, 0xbe, 0xcc, 0xfc, +0x2e, 0x0a, 0xcc, 0x25, 0x2a, 0x35, 0x04, 0xf8, 0x60, 0x91, 0x15, 0x75, 0x3d, 0x41, 0xff, 0x23, +0x1f, 0x19, 0xc8, 0x6c, 0xeb, 0x82, 0x53, 0x04, 0xa6, 0xe4, 0x4c, 0x22, 0x4d, 0x8d, 0x8c, 0xba, +0xce, 0x5b, 0x73, 0xec, 0x64, 0x54, 0x50, 0x6d, 0xd1, 0x9c, 0x55, 0xfb, 0x69, 0xc3, 0x36, 0xc3, +0x8c, 0xbc, 0x3c, 0x85, 0xa6, 0x6b, 0x0a, 0x26, 0x0d, 0xe0, 0x93, 0x98, 0x60, 0xae, 0x7e, 0xc6, +0x24, 0x97, 0x8a, 0x61, 0x5f, 0x91, 0x8e, 0x66, 0x92, 0x09, 0x87, 0x36, 0xcd, 0x8b, 0x9b, 0x2d, +0x3e, 0xf6, 0x51, 0xd4, 0x50, 0xd4, 0x59, 0x28, 0xbd, 0x83, 0xf2, 0xcc, 0x28, 0x7b, 0x53, 0x86, +0x6d, 0xd8, 0x26, 0x88, 0x70, 0xd7, 0xea, 0x91, 0xcd, 0x3e, 0xb9, 0xca, 0xc0, 0x90, 0x6e, 0x5a, +0xc6, 0x5e, 0x74, 0x65, 0xd7, 0x5c, 0xfe, 0xa3, 0xe2, 0x30, 0x82, 0x04, 0x43, 0x30, 0x82, 0x03, +0x2b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x09, 0x83, 0xf4, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x50, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x0c, 0x0c, 0x44, 0x2d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6d, 0x62, 0x48, +0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x44, 0x2d, 0x54, 0x52, 0x55, +0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, +0x43, 0x41, 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39, 0x30, 0x1e, 0x17, 0x0d, +0x30, 0x39, 0x31, 0x31, 0x30, 0x35, 0x30, 0x38, 0x35, 0x30, 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x32, +0x39, 0x31, 0x31, 0x30, 0x35, 0x30, 0x38, 0x35, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x50, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, +0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x44, 0x2d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6d, +0x62, 0x48, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x44, 0x2d, 0x54, +0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, +0x33, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39, 0x30, 0x82, +0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, +0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x99, +0xf1, 0x84, 0x34, 0x70, 0xba, 0x2f, 0xb7, 0x30, 0xa0, 0x8e, 0xbd, 0x7c, 0x04, 0xcf, 0xbe, 0x62, +0xbc, 0x99, 0xfd, 0x82, 0x97, 0xd2, 0x7a, 0x0a, 0x67, 0x96, 0x38, 0x09, 0xf6, 0x10, 0x4e, 0x95, +0x22, 0x73, 0x99, 0x8d, 0xda, 0x15, 0x2d, 0xe7, 0x05, 0xfc, 0x19, 0x73, 0x22, 0xb7, 0x8e, 0x98, +0x00, 0xbc, 0x3c, 0x3d, 0xac, 0xa1, 0x6c, 0xfb, 0xd6, 0x79, 0x25, 0x4b, 0xad, 0xf0, 0xcc, 0x64, +0xda, 0x88, 0x3e, 0x29, 0xb8, 0x0f, 0x09, 0xd3, 0x34, 0xdd, 0x33, 0xf5, 0x62, 0xd1, 0xe1, 0xcd, +0x19, 0xe9, 0xee, 0x18, 0x4f, 0x4c, 0x58, 0xae, 0xe2, 0x1e, 0xd6, 0x0c, 0x5b, 0x15, 0x5a, 0xd8, +0x3a, 0xb8, 0xc4, 0x18, 0x64, 0x1e, 0xe3, 0x33, 0xb2, 0xb5, 0x89, 0x77, 0x4e, 0x0c, 0xbf, 0xd9, +0x94, 0x6b, 0x13, 0x97, 0x6f, 0x12, 0xa3, 0xfe, 0x99, 0xa9, 0x04, 0xcc, 0x15, 0xec, 0x60, 0x68, +0x36, 0xed, 0x08, 0x7b, 0xb7, 0xf5, 0xbf, 0x93, 0xed, 0x66, 0x31, 0x83, 0x8c, 0xc6, 0x71, 0x34, +0x87, 0x4e, 0x17, 0xea, 0xaf, 0x8b, 0x91, 0x8d, 0x1c, 0x56, 0x41, 0xae, 0x22, 0x37, 0x5e, 0x37, +0xf2, 0x1d, 0xd9, 0xd1, 0x2d, 0x0d, 0x2f, 0x69, 0x51, 0xa7, 0xbe, 0x66, 0xa6, 0x8a, 0x3a, 0x2a, +0xbd, 0xc7, 0x1a, 0xb1, 0xe1, 0x14, 0xf0, 0xbe, 0x3a, 0x1d, 0xb9, 0xcf, 0x5b, 0xb1, 0x6a, 0xfe, +0xb4, 0xb1, 0x46, 0x20, 0xa2, 0xfb, 0x1e, 0x3b, 0x70, 0xef, 0x93, 0x98, 0x7d, 0x8c, 0x73, 0x96, +0xf2, 0xc5, 0xef, 0x85, 0x70, 0xad, 0x29, 0x26, 0xfc, 0x1e, 0x04, 0x3e, 0x1c, 0xa0, 0xd8, 0x0f, +0xcb, 0x52, 0x83, 0x62, 0x7c, 0xee, 0x8b, 0x53, 0x95, 0x90, 0xa9, 0x57, 0xa2, 0xea, 0x61, 0x05, +0xd8, 0xf9, 0x4d, 0xc4, 0x27, 0xfa, 0x6e, 0xad, 0xed, 0xf9, 0xd7, 0x51, 0xf7, 0x6b, 0xa5, 0x02, +0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x24, 0x30, 0x82, 0x01, 0x20, 0x30, 0x0f, 0x06, 0x03, +0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, +0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd3, 0x94, 0x8a, 0x4c, 0x62, 0x13, 0x2a, 0x19, +0x2e, 0xcc, 0xaf, 0x72, 0x8a, 0x7d, 0x36, 0xd7, 0x9a, 0x1c, 0xdc, 0x67, 0x30, 0x0e, 0x06, 0x03, +0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x81, 0xdd, 0x06, +0x03, 0x55, 0x1d, 0x1f, 0x04, 0x81, 0xd5, 0x30, 0x81, 0xd2, 0x30, 0x81, 0x87, 0xa0, 0x81, 0x84, +0xa0, 0x81, 0x81, 0x86, 0x7f, 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x69, 0x72, 0x65, +0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x64, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, +0x74, 0x2f, 0x43, 0x4e, 0x3d, 0x44, 0x2d, 0x54, 0x52, 0x55, 0x53, 0x54, 0x25, 0x32, 0x30, 0x52, +0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x25, 0x32, 0x30, 0x33, 0x25, +0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x25, 0x32, 0x30, 0x45, 0x56, 0x25, 0x32, 0x30, +0x32, 0x30, 0x30, 0x39, 0x2c, 0x4f, 0x3d, 0x44, 0x2d, 0x54, 0x72, 0x75, 0x73, 0x74, 0x25, 0x32, +0x30, 0x47, 0x6d, 0x62, 0x48, 0x2c, 0x43, 0x3d, 0x44, 0x45, 0x3f, 0x63, 0x65, 0x72, 0x74, 0x69, +0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x6c, 0x69, 0x73, 0x74, 0x30, 0x46, 0xa0, 0x44, 0xa0, 0x42, 0x86, 0x40, 0x68, 0x74, 0x74, 0x70, +0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, +0x65, 0x74, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x64, 0x2d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x72, +0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x33, 0x5f, 0x63, 0x61, 0x5f, 0x32, +0x5f, 0x65, 0x76, 0x5f, 0x32, 0x30, 0x30, 0x39, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, +0x34, 0xed, 0x7b, 0x5a, 0x3c, 0xa4, 0x94, 0x88, 0xef, 0x1a, 0x11, 0x75, 0x07, 0x2f, 0xb3, 0xfe, +0x3c, 0xfa, 0x1e, 0x51, 0x26, 0xeb, 0x87, 0xf6, 0x29, 0xde, 0xe0, 0xf1, 0xd4, 0xc6, 0x24, 0x09, +0xe9, 0xc1, 0xcf, 0x55, 0x1b, 0xb4, 0x30, 0xd9, 0xce, 0x1a, 0xfe, 0x06, 0x51, 0xa6, 0x15, 0xa4, +0x2d, 0xef, 0xb2, 0x4b, 0xbf, 0x20, 0x28, 0x25, 0x49, 0xd1, 0xa6, 0x36, 0x77, 0x34, 0xe8, 0x64, +0xdf, 0x52, 0xb1, 0x11, 0xc7, 0x73, 0x7a, 0xcd, 0x39, 0x9e, 0xc2, 0xad, 0x8c, 0x71, 0x21, 0xf2, +0x5a, 0x6b, 0xaf, 0xdf, 0x3c, 0x4e, 0x55, 0xaf, 0xb2, 0x84, 0x65, 0x14, 0x89, 0xb9, 0x77, 0xcb, +0x2a, 0x31, 0xbe, 0xcf, 0xa3, 0x6d, 0xcf, 0x6f, 0x48, 0x94, 0x32, 0x46, 0x6f, 0xe7, 0x71, 0x8c, +0xa0, 0xa6, 0x84, 0x19, 0x37, 0x07, 0xf2, 0x03, 0x45, 0x09, 0x2b, 0x86, 0x75, 0x7c, 0xdf, 0x5f, +0x69, 0x57, 0x00, 0xdb, 0x6e, 0xd8, 0xa6, 0x72, 0x22, 0x4b, 0x50, 0xd4, 0x75, 0x98, 0x56, 0xdf, +0xb7, 0x18, 0xff, 0x43, 0x43, 0x50, 0xae, 0x7a, 0x44, 0x7b, 0xf0, 0x79, 0x51, 0xd7, 0x43, 0x3d, +0xa7, 0xd3, 0x81, 0xd3, 0xf0, 0xc9, 0x4f, 0xb9, 0xda, 0xc6, 0x97, 0x86, 0xd0, 0x82, 0xc3, 0xe4, +0x42, 0x6d, 0xfe, 0xb0, 0xe2, 0x64, 0x4e, 0x0e, 0x26, 0xe7, 0x40, 0x34, 0x26, 0xb5, 0x08, 0x89, +0xd7, 0x08, 0x63, 0x63, 0x38, 0x27, 0x75, 0x1e, 0x33, 0xea, 0x6e, 0xa8, 0xdd, 0x9f, 0x99, 0x4f, +0x74, 0x4d, 0x81, 0x89, 0x80, 0x4b, 0xdd, 0x9a, 0x97, 0x29, 0x5c, 0x2f, 0xbe, 0x81, 0x41, 0xb9, +0x8c, 0xff, 0xea, 0x7d, 0x60, 0x06, 0x9e, 0xcd, 0xd7, 0x3d, 0xd3, 0x2e, 0xa3, 0x15, 0xbc, 0xa8, +0xe6, 0x26, 0xe5, 0x6f, 0xc3, 0xdc, 0xb8, 0x03, 0x21, 0xea, 0x9f, 0x16, 0xf1, 0x2c, 0x54, 0xb5, +0x30, 0x82, 0x06, 0x4b, 0x30, 0x82, 0x04, 0x33, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x6a, +0x68, 0x3e, 0x9c, 0x51, 0x9b, 0xcb, 0x53, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xb2, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, +0x04, 0x06, 0x13, 0x02, 0x54, 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, +0x06, 0x41, 0x6e, 0x6b, 0x61, 0x72, 0x61, 0x31, 0x40, 0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x37, 0x45, 0x2d, 0x54, 0x75, 0xc4, 0x9f, 0x72, 0x61, 0x20, 0x45, 0x42, 0x47, 0x20, 0x42, +0x69, 0x6c, 0x69, 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x54, 0x65, 0x6b, 0x6e, 0x6f, 0x6c, 0x6f, 0x6a, +0x69, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x76, 0x65, 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74, 0x6c, +0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, 0x9e, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x0c, 0x1d, 0x45, 0x2d, 0x54, 0x75, 0x67, 0x72, 0x61, 0x20, 0x53, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x6b, 0x61, 0x73, 0x79, 0x6f, 0x6e, 0x20, 0x4d, 0x65, 0x72, 0x6b, 0x65, 0x7a, +0x69, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1f, 0x45, 0x2d, 0x54, 0x75, +0x67, 0x72, 0x61, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, +0x33, 0x30, 0x33, 0x30, 0x35, 0x31, 0x32, 0x30, 0x39, 0x34, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x33, +0x30, 0x33, 0x30, 0x33, 0x31, 0x32, 0x30, 0x39, 0x34, 0x38, 0x5a, 0x30, 0x81, 0xb2, 0x31, 0x0b, +0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, +0x03, 0x55, 0x04, 0x07, 0x0c, 0x06, 0x41, 0x6e, 0x6b, 0x61, 0x72, 0x61, 0x31, 0x40, 0x30, 0x3e, +0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x37, 0x45, 0x2d, 0x54, 0x75, 0xc4, 0x9f, 0x72, 0x61, 0x20, +0x45, 0x42, 0x47, 0x20, 0x42, 0x69, 0x6c, 0x69, 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x54, 0x65, 0x6b, +0x6e, 0x6f, 0x6c, 0x6f, 0x6a, 0x69, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x76, 0x65, 0x20, 0x48, 0x69, +0x7a, 0x6d, 0x65, 0x74, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, 0x9e, 0x2e, 0x31, 0x26, +0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x45, 0x2d, 0x54, 0x75, 0x67, 0x72, 0x61, +0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6b, 0x61, 0x73, 0x79, 0x6f, 0x6e, 0x20, 0x4d, +0x65, 0x72, 0x6b, 0x65, 0x7a, 0x69, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, +0x1f, 0x45, 0x2d, 0x54, 0x75, 0x67, 0x72, 0x61, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, +0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, +0x00, 0xe2, 0xf5, 0x3f, 0x93, 0x05, 0x51, 0x1e, 0x85, 0x62, 0x54, 0x5e, 0x7a, 0x0b, 0xf5, 0x18, +0x07, 0x83, 0xae, 0x7e, 0xaf, 0x7c, 0xf7, 0xd4, 0x8a, 0x6b, 0xa5, 0x63, 0x43, 0x39, 0xb9, 0x4b, +0xf7, 0xc3, 0xc6, 0x64, 0x89, 0x3d, 0x94, 0x2e, 0x54, 0x80, 0x52, 0x39, 0x39, 0x07, 0x4b, 0x4b, +0xdd, 0x85, 0x07, 0x76, 0x87, 0xcc, 0xbf, 0x2f, 0x95, 0x4c, 0xcc, 0x7d, 0xa7, 0x3d, 0xbc, 0x47, +0x0f, 0x98, 0x70, 0xf8, 0x8c, 0x85, 0x1e, 0x74, 0x8e, 0x92, 0x6d, 0x1b, 0x40, 0xd1, 0x99, 0x0d, +0xbb, 0x75, 0x6e, 0xc8, 0xa9, 0x6b, 0x9a, 0xc0, 0x84, 0x31, 0xaf, 0xca, 0x43, 0xcb, 0xeb, 0x2b, +0x34, 0xe8, 0x8f, 0x97, 0x6b, 0x01, 0x9b, 0xd5, 0x0e, 0x4a, 0x08, 0xaa, 0x5b, 0x92, 0x74, 0x85, +0x43, 0xd3, 0x80, 0xae, 0xa1, 0x88, 0x5b, 0xae, 0xb3, 0xea, 0x5e, 0xcb, 0x16, 0x9a, 0x77, 0x44, +0xc8, 0xa1, 0xf6, 0x54, 0x68, 0xce, 0xde, 0x8f, 0x97, 0x2b, 0xba, 0x5b, 0x40, 0x02, 0x0c, 0x64, +0x17, 0xc0, 0xb5, 0x93, 0xcd, 0xe1, 0xf1, 0x13, 0x66, 0xce, 0x0c, 0x79, 0xef, 0xd1, 0x91, 0x28, +0xab, 0x5f, 0xa0, 0x12, 0x52, 0x30, 0x73, 0x19, 0x8e, 0x8f, 0xe1, 0x8c, 0x07, 0xa2, 0xc3, 0xbb, +0x4a, 0xf0, 0xea, 0x1f, 0x15, 0xa8, 0xee, 0x25, 0xcc, 0xa4, 0x46, 0xf8, 0x1b, 0x22, 0xef, 0xb3, +0x0e, 0x43, 0xba, 0x2c, 0x24, 0xb8, 0xc5, 0x2c, 0x5c, 0xd4, 0x1c, 0xf8, 0x5d, 0x64, 0xbd, 0xc3, +0x93, 0x5e, 0x28, 0xa7, 0x3f, 0x27, 0xf1, 0x8e, 0x1e, 0xd3, 0x2a, 0x50, 0x05, 0xa3, 0x55, 0xd9, +0xcb, 0xe7, 0x39, 0x53, 0xc0, 0x98, 0x9e, 0x8c, 0x54, 0x62, 0x8b, 0x26, 0xb0, 0xf7, 0x7d, 0x8d, +0x7c, 0xe4, 0xc6, 0x9e, 0x66, 0x42, 0x55, 0x82, 0x47, 0xe7, 0xb2, 0x58, 0x8d, 0x66, 0xf7, 0x07, +0x7c, 0x2e, 0x36, 0xe6, 0x50, 0x1c, 0x3f, 0xdb, 0x43, 0x24, 0xc5, 0xbf, 0x86, 0x47, 0x79, 0xb3, +0x79, 0x1c, 0xf7, 0x5a, 0xf4, 0x13, 0xec, 0x6c, 0xf8, 0x3f, 0xe2, 0x59, 0x1f, 0x95, 0xee, 0x42, +0x3e, 0xb9, 0xad, 0xa8, 0x32, 0x85, 0x49, 0x97, 0x46, 0xfe, 0x4b, 0x31, 0x8f, 0x5a, 0xcb, 0xad, +0x74, 0x47, 0x1f, 0xe9, 0x91, 0xb7, 0xdf, 0x28, 0x04, 0x22, 0xa0, 0xd4, 0x0f, 0x5d, 0xe2, 0x79, +0x4f, 0xea, 0x6c, 0x85, 0x86, 0xbd, 0xa8, 0xa6, 0xce, 0xe4, 0xfa, 0xc3, 0xe1, 0xb3, 0xae, 0xde, +0x3c, 0x51, 0xee, 0xcb, 0x13, 0x7c, 0x01, 0x7f, 0x84, 0x0e, 0x5d, 0x51, 0x94, 0x9e, 0x13, 0x0c, +0xb6, 0x2e, 0xa5, 0x4c, 0xf9, 0x39, 0x70, 0x36, 0x6f, 0x96, 0xca, 0x2e, 0x0c, 0x44, 0x55, 0xc5, +0xca, 0xfa, 0x5d, 0x02, 0xa3, 0xdf, 0xd6, 0x64, 0x8c, 0x5a, 0xb3, 0x01, 0x0a, 0xa9, 0xb5, 0x0a, +0x47, 0x17, 0xff, 0xef, 0x91, 0x40, 0x2a, 0x8e, 0xa1, 0x46, 0x3a, 0x31, 0x98, 0xe5, 0x11, 0xfc, +0xcc, 0xbb, 0x49, 0x56, 0x8a, 0xfc, 0xb9, 0xd0, 0x61, 0x9a, 0x6f, 0x65, 0x6c, 0xe6, 0xc3, 0xcb, +0x3e, 0x75, 0x49, 0xfe, 0x8f, 0xa7, 0xe2, 0x89, 0xc5, 0x67, 0xd7, 0x9d, 0x46, 0x13, 0x4e, 0x31, +0x76, 0x3b, 0x24, 0xb3, 0x9e, 0x11, 0x65, 0x86, 0xab, 0x7f, 0xef, 0x1d, 0xd4, 0xf8, 0xbc, 0xe7, +0xac, 0x5a, 0x5c, 0xb7, 0x5a, 0x47, 0x5c, 0x55, 0xce, 0x55, 0xb4, 0x22, 0x71, 0x5b, 0x5b, 0x0b, +0xf0, 0xcf, 0xdc, 0xa0, 0x61, 0x64, 0xea, 0xa9, 0xd7, 0x68, 0x0a, 0x63, 0xa7, 0xe0, 0x0d, 0x3f, +0xa0, 0xaf, 0xd3, 0xaa, 0xd2, 0x7e, 0xef, 0x51, 0xa0, 0xe6, 0x51, 0x2b, 0x55, 0x92, 0x15, 0x17, +0x53, 0xcb, 0xb7, 0x66, 0x0e, 0x66, 0x4c, 0xf8, 0xf9, 0x75, 0x4c, 0x90, 0xe7, 0x12, 0x70, 0xc7, +0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0x2e, 0xe3, 0xdb, 0xb2, 0x49, 0xd0, 0x9c, 0x54, 0x79, 0x5c, 0xfa, +0x27, 0x2a, 0xfe, 0xcc, 0x4e, 0xd2, 0xe8, 0x4e, 0x54, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, +0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, +0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x2e, 0xe3, 0xdb, 0xb2, 0x49, 0xd0, 0x9c, 0x54, 0x79, +0x5c, 0xfa, 0x27, 0x2a, 0xfe, 0xcc, 0x4e, 0xd2, 0xe8, 0x4e, 0x54, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x05, +0x37, 0x3a, 0xf4, 0x4d, 0xb7, 0x45, 0xe2, 0x45, 0x75, 0x24, 0x8f, 0xb6, 0x77, 0x52, 0xe8, 0x1c, +0xd8, 0x10, 0x93, 0x65, 0xf3, 0xf2, 0x59, 0x06, 0xa4, 0x3e, 0x1e, 0x29, 0xec, 0x5d, 0xd1, 0xd0, +0xab, 0x7c, 0xe0, 0x0a, 0x90, 0x48, 0x78, 0xed, 0x4e, 0x98, 0x03, 0x99, 0xfe, 0x28, 0x60, 0x91, +0x1d, 0x30, 0x1d, 0xb8, 0x63, 0x7c, 0xa8, 0xe6, 0x35, 0xb5, 0xfa, 0xd3, 0x61, 0x76, 0xe6, 0xd6, +0x07, 0x4b, 0xca, 0x69, 0x9a, 0xb2, 0x84, 0x7a, 0x77, 0x93, 0x45, 0x17, 0x15, 0x9f, 0x24, 0xd0, +0x98, 0x13, 0x12, 0xff, 0xbb, 0xa0, 0x2e, 0xfd, 0x4e, 0x4c, 0x87, 0xf8, 0xce, 0x5c, 0xaa, 0x98, +0x1b, 0x05, 0xe0, 0x00, 0x46, 0x4a, 0x82, 0x80, 0xa5, 0x33, 0x8b, 0x28, 0xdc, 0xed, 0x38, 0xd3, +0xdf, 0xe5, 0x3e, 0xe9, 0xfe, 0xfb, 0x59, 0xdd, 0x61, 0x84, 0x4f, 0xd2, 0x54, 0x96, 0x13, 0x61, +0x13, 0x3e, 0x8f, 0x80, 0x69, 0xbe, 0x93, 0x47, 0xb5, 0x35, 0x43, 0xd2, 0x5a, 0xbb, 0x3d, 0x5c, +0xef, 0xb3, 0x42, 0x47, 0xcd, 0x3b, 0x55, 0x13, 0x06, 0xb0, 0x09, 0xdb, 0xfd, 0x63, 0xf6, 0x3a, +0x88, 0x0a, 0x99, 0x6f, 0x7e, 0xe1, 0xce, 0x1b, 0x53, 0x6a, 0x44, 0x66, 0x23, 0x51, 0x08, 0x7b, +0xbc, 0x5b, 0x52, 0xa2, 0xfd, 0x06, 0x37, 0x38, 0x40, 0x61, 0x8f, 0x4a, 0x96, 0xb8, 0x90, 0x37, +0xf8, 0x66, 0xc7, 0x78, 0x90, 0x00, 0x15, 0x2e, 0x8b, 0xad, 0x51, 0x35, 0x53, 0x07, 0xa8, 0x6b, +0x68, 0xae, 0xf9, 0x4e, 0x3c, 0x07, 0x26, 0xcd, 0x08, 0x05, 0x70, 0xcc, 0x39, 0x3f, 0x76, 0xbd, +0xa5, 0xd3, 0x67, 0x26, 0x01, 0x86, 0xa6, 0x53, 0xd2, 0x60, 0x3b, 0x7c, 0x43, 0x7f, 0x55, 0x8a, +0xbc, 0x95, 0x1a, 0xc1, 0x28, 0x39, 0x4c, 0x1f, 0x43, 0xd2, 0x91, 0xf4, 0x72, 0x59, 0x8a, 0xb9, +0x56, 0xfc, 0x3f, 0xb4, 0x9d, 0xda, 0x70, 0x9c, 0x76, 0x5a, 0x8c, 0x43, 0x50, 0xee, 0x8e, 0x30, +0x72, 0x4d, 0xdf, 0xff, 0x49, 0xf7, 0xc6, 0xa9, 0x67, 0xd9, 0x6d, 0xac, 0x02, 0x11, 0xe2, 0x3a, +0x16, 0x25, 0xa7, 0x58, 0x08, 0xcb, 0x6f, 0x53, 0x41, 0x9c, 0x48, 0x38, 0x47, 0x68, 0x33, 0xd1, +0xd7, 0xc7, 0x8f, 0xd4, 0x74, 0x21, 0xd4, 0xc3, 0x05, 0x90, 0x7a, 0xff, 0xce, 0x96, 0x88, 0xb1, +0x15, 0x29, 0x5d, 0x23, 0xab, 0xd0, 0x60, 0xa1, 0x12, 0x4f, 0xde, 0xf4, 0x17, 0xcd, 0x32, 0xe5, +0xc9, 0xbf, 0xc8, 0x43, 0xad, 0xfd, 0x2e, 0x8e, 0xf1, 0xaf, 0xe2, 0xf4, 0x98, 0xfa, 0x12, 0x1f, +0x20, 0xd8, 0xc0, 0xa7, 0x0c, 0x85, 0xc5, 0x90, 0xf4, 0x3b, 0x2d, 0x96, 0x26, 0xb1, 0x2c, 0xbe, +0x4c, 0xab, 0xeb, 0xb1, 0xd2, 0x8a, 0xc9, 0xdb, 0x78, 0x13, 0x0f, 0x1e, 0x09, 0x9d, 0x6d, 0x8f, +0x00, 0x9f, 0x02, 0xda, 0xc1, 0xfa, 0x1f, 0x7a, 0x7a, 0x09, 0xc4, 0x4a, 0xe6, 0x88, 0x2a, 0x97, +0x9f, 0x89, 0x8b, 0xfd, 0x37, 0x5f, 0x5f, 0x3a, 0xce, 0x38, 0x59, 0x86, 0x4b, 0xaf, 0x71, 0x0b, +0xb4, 0xd8, 0xf2, 0x70, 0x4f, 0x9f, 0x32, 0x13, 0xe3, 0xb0, 0xa7, 0x57, 0xe5, 0xda, 0xda, 0x43, +0xcb, 0x84, 0x34, 0xf2, 0x28, 0xc4, 0xea, 0x6d, 0xf4, 0x2a, 0xef, 0xc1, 0x6b, 0x76, 0xda, 0xfb, +0x7e, 0xbb, 0x85, 0x3c, 0xd2, 0x53, 0xc2, 0x4d, 0xbe, 0x71, 0xe1, 0x45, 0xd1, 0xfd, 0x23, 0x67, +0x0d, 0x13, 0x75, 0xfb, 0xcf, 0x65, 0x67, 0x22, 0x9d, 0xae, 0xb0, 0x09, 0xd1, 0x09, 0xff, 0x1d, +0x34, 0xbf, 0xfe, 0x23, 0x97, 0x37, 0xd2, 0x39, 0xfa, 0x3d, 0x0d, 0x06, 0x0b, 0xb4, 0xdb, 0x3b, +0xa3, 0xab, 0x6f, 0x5c, 0x1d, 0xb6, 0x7e, 0xe8, 0xb3, 0x82, 0x34, 0xed, 0x06, 0x5c, 0x24, 0x30, +0x82, 0x05, 0xbd, 0x30, 0x82, 0x03, 0xa5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4f, 0x1b, +0xd4, 0x2f, 0x54, 0xbb, 0x2f, 0x4b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x53, +0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x41, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, +0x53, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x1e, +0x17, 0x0d, 0x30, 0x36, 0x31, 0x30, 0x32, 0x35, 0x30, 0x38, 0x33, 0x32, 0x34, 0x36, 0x5a, 0x17, +0x0d, 0x33, 0x36, 0x31, 0x30, 0x32, 0x35, 0x30, 0x38, 0x33, 0x32, 0x34, 0x36, 0x5a, 0x30, 0x47, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31, 0x15, 0x30, +0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, +0x6e, 0x20, 0x41, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x53, +0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x53, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x20, +0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, +0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, +0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc4, 0xf1, 0x87, 0x7f, 0xd3, 0x78, 0x31, 0xf7, +0x38, 0xc9, 0xf8, 0xc3, 0x99, 0x43, 0xbc, 0xc7, 0xf7, 0xbc, 0x37, 0xe7, 0x4e, 0x71, 0xba, 0x4b, +0x8f, 0xa5, 0x73, 0x1d, 0x5c, 0x6e, 0x98, 0xae, 0x03, 0x57, 0xae, 0x38, 0x37, 0x43, 0x2f, 0x17, +0x3d, 0x1f, 0xc8, 0xce, 0x68, 0x10, 0xc1, 0x78, 0xae, 0x19, 0x03, 0x2b, 0x10, 0xfa, 0x2c, 0x79, +0x83, 0xf6, 0xe8, 0xb9, 0x68, 0xb9, 0x55, 0xf2, 0x04, 0x44, 0xa7, 0x39, 0xf9, 0xfc, 0x04, 0x8b, +0x1e, 0xf1, 0xa2, 0x4d, 0x27, 0xf9, 0x61, 0x7b, 0xba, 0xb7, 0xe5, 0xa2, 0x13, 0xb6, 0xeb, 0x61, +0x3e, 0xd0, 0x6c, 0xd1, 0xe6, 0xfb, 0xfa, 0x5e, 0xed, 0x1d, 0xb4, 0x9e, 0xa0, 0x35, 0x5b, 0xa1, +0x92, 0xcb, 0xf0, 0x49, 0x92, 0xfe, 0x85, 0x0a, 0x05, 0x3e, 0xe6, 0xd9, 0x0b, 0xe2, 0x4f, 0xbb, +0xdc, 0x95, 0x37, 0xfc, 0x91, 0xe9, 0x32, 0x35, 0x22, 0xd1, 0x1f, 0x3a, 0x4e, 0x27, 0x85, 0x9d, +0xb0, 0x15, 0x94, 0x32, 0xda, 0x61, 0x0d, 0x47, 0x4d, 0x60, 0x42, 0xae, 0x92, 0x47, 0xe8, 0x83, +0x5a, 0x50, 0x58, 0xe9, 0x8a, 0x8b, 0xb9, 0x5d, 0xa1, 0xdc, 0xdd, 0x99, 0x4a, 0x1f, 0x36, 0x67, +0xbb, 0x48, 0xe4, 0x83, 0xb6, 0x37, 0xeb, 0x48, 0x3a, 0xaf, 0x0f, 0x67, 0x8f, 0x17, 0x07, 0xe8, +0x04, 0xca, 0xef, 0x6a, 0x31, 0x87, 0xd4, 0xc0, 0xb6, 0xf9, 0x94, 0x71, 0x7b, 0x67, 0x64, 0xb8, +0xb6, 0x91, 0x4a, 0x42, 0x7b, 0x65, 0x2e, 0x30, 0x6a, 0x0c, 0xf5, 0x90, 0xee, 0x95, 0xe6, 0xf2, +0xcd, 0x82, 0xec, 0xd9, 0xa1, 0x4a, 0xec, 0xf6, 0xb2, 0x4b, 0xe5, 0x45, 0x85, 0xe6, 0x6d, 0x78, +0x93, 0x04, 0x2e, 0x9c, 0x82, 0x6d, 0x36, 0xa9, 0xc4, 0x31, 0x64, 0x1f, 0x86, 0x83, 0x0b, 0x2a, +0xf4, 0x35, 0x0a, 0x78, 0xc9, 0x55, 0xcf, 0x41, 0xb0, 0x47, 0xe9, 0x30, 0x9f, 0x99, 0xbe, 0x61, +0xa8, 0x06, 0x84, 0xb9, 0x28, 0x7a, 0x5f, 0x38, 0xd9, 0x1b, 0xa9, 0x38, 0xb0, 0x83, 0x7f, 0x73, +0xc1, 0xc3, 0x3b, 0x48, 0x2a, 0x82, 0x0f, 0x21, 0x9b, 0xb8, 0xcc, 0xa8, 0x35, 0xc3, 0x84, 0x1b, +0x83, 0xb3, 0x3e, 0xbe, 0xa4, 0x95, 0x69, 0x01, 0x3a, 0x89, 0x00, 0x78, 0x04, 0xd9, 0xc9, 0xf4, +0x99, 0x19, 0xab, 0x56, 0x7e, 0x5b, 0x8b, 0x86, 0x39, 0x15, 0x91, 0xa4, 0x10, 0x2c, 0x09, 0x32, +0x80, 0x60, 0xb3, 0x93, 0xc0, 0x2a, 0xb6, 0x18, 0x0b, 0x9d, 0x7e, 0x8d, 0x49, 0xf2, 0x10, 0x4a, +0x7f, 0xf9, 0xd5, 0x46, 0x2f, 0x19, 0x92, 0xa3, 0x99, 0xa7, 0x26, 0xac, 0xbb, 0x8c, 0x3c, 0xe6, +0x0e, 0xbc, 0x47, 0x07, 0xdc, 0x73, 0x51, 0xf1, 0x70, 0x64, 0x2f, 0x08, 0xf9, 0xb4, 0x47, 0x1d, +0x30, 0x6c, 0x44, 0xea, 0x29, 0x37, 0x85, 0x92, 0x68, 0x66, 0xbc, 0x83, 0x38, 0xfe, 0x7b, 0x39, +0x2e, 0xd3, 0x50, 0xf0, 0x1f, 0xfb, 0x5e, 0x60, 0xb6, 0xa9, 0xa6, 0xfa, 0x27, 0x41, 0xf1, 0x9b, +0x18, 0x72, 0xf2, 0xf5, 0x84, 0x74, 0x4a, 0xc9, 0x67, 0xc4, 0x54, 0xae, 0x48, 0x64, 0xdf, 0x8c, +0xd1, 0x6e, 0xb0, 0x1d, 0xe1, 0x07, 0x8f, 0x08, 0x1e, 0x99, 0x9c, 0x71, 0xe9, 0x4c, 0xd8, 0xa5, +0xf7, 0x47, 0x12, 0x1f, 0x74, 0xd1, 0x51, 0x9e, 0x86, 0xf3, 0xc2, 0xa2, 0x23, 0x40, 0x0b, 0x73, +0xdb, 0x4b, 0xa6, 0xe7, 0x73, 0x06, 0x8c, 0xc1, 0xa0, 0xe9, 0xc1, 0x59, 0xac, 0x46, 0xfa, 0xe6, +0x2f, 0xf8, 0xcf, 0x71, 0x9c, 0x46, 0x6d, 0xb9, 0xc4, 0x15, 0x8d, 0x38, 0x79, 0x03, 0x45, 0x48, +0xef, 0xc4, 0x5d, 0xd7, 0x08, 0xee, 0x87, 0x39, 0x22, 0x86, 0xb2, 0x0d, 0x0f, 0x58, 0x43, 0xf7, +0x71, 0xa9, 0x48, 0x2e, 0xfd, 0xea, 0xd6, 0x1f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xac, +0x30, 0x81, 0xa9, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x17, +0xa0, 0xcd, 0xc1, 0xe4, 0x41, 0xb6, 0x3a, 0x5b, 0x3b, 0xcb, 0x45, 0x9d, 0xbd, 0x1c, 0xc2, 0x98, +0xfa, 0x86, 0x58, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, +0x17, 0xa0, 0xcd, 0xc1, 0xe4, 0x41, 0xb6, 0x3a, 0x5b, 0x3b, 0xcb, 0x45, 0x9d, 0xbd, 0x1c, 0xc2, +0x98, 0xfa, 0x86, 0x58, 0x30, 0x46, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, +0x3b, 0x06, 0x09, 0x60, 0x85, 0x74, 0x01, 0x59, 0x01, 0x03, 0x01, 0x01, 0x30, 0x2e, 0x30, 0x2c, +0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x20, 0x68, 0x74, 0x74, 0x70, +0x3a, 0x2f, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x73, 0x77, +0x69, 0x73, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, +0x73, 0xc6, 0x81, 0xe0, 0x27, 0xd2, 0x2d, 0x0f, 0xe0, 0x95, 0x30, 0xe2, 0x9a, 0x41, 0x7f, 0x50, +0x2c, 0x5f, 0x5f, 0x62, 0x61, 0xa9, 0x86, 0x6a, 0x69, 0x18, 0x0c, 0x74, 0x49, 0xd6, 0x5d, 0x84, +0xea, 0x41, 0x52, 0x18, 0x6f, 0x58, 0xad, 0x50, 0x56, 0x20, 0x6a, 0xc6, 0xbd, 0x28, 0x69, 0x58, +0x91, 0xdc, 0x91, 0x11, 0x35, 0xa9, 0x3a, 0x1d, 0xbc, 0x1a, 0xa5, 0x60, 0x9e, 0xd8, 0x1f, 0x7f, +0x45, 0x91, 0x69, 0xd9, 0x7e, 0xbb, 0x78, 0x72, 0xc1, 0x06, 0x0f, 0x2a, 0xce, 0x8f, 0x85, 0x70, +0x61, 0xac, 0xa0, 0xcd, 0x0b, 0xb8, 0x39, 0x29, 0x56, 0x84, 0x32, 0x4e, 0x86, 0xbb, 0x3d, 0xc4, +0x2a, 0xd9, 0xd7, 0x1f, 0x72, 0xee, 0xfe, 0x51, 0xa1, 0x22, 0x41, 0xb1, 0x71, 0x02, 0x63, 0x1a, +0x82, 0xb0, 0x62, 0xab, 0x5e, 0x57, 0x12, 0x1f, 0xdf, 0xcb, 0xdd, 0x75, 0xa0, 0xc0, 0x5d, 0x79, +0x90, 0x8c, 0x1b, 0xe0, 0x50, 0xe6, 0xde, 0x31, 0xfe, 0x98, 0x7b, 0x70, 0x5f, 0xa5, 0x90, 0xd8, +0xad, 0xf8, 0x02, 0xb6, 0x6f, 0xd3, 0x60, 0xdd, 0x40, 0x4b, 0x22, 0xc5, 0x3d, 0xad, 0x3a, 0x7a, +0x9f, 0x1a, 0x1a, 0x47, 0x91, 0x79, 0x33, 0xba, 0x82, 0xdc, 0x32, 0x69, 0x03, 0x96, 0x6e, 0x1f, +0x4b, 0xf0, 0x71, 0xfe, 0xe3, 0x67, 0x72, 0xa0, 0xb1, 0xbf, 0x5c, 0x8b, 0xe4, 0xfa, 0x99, 0x22, +0xc7, 0x84, 0xb9, 0x1b, 0x8d, 0x23, 0x97, 0x3f, 0xed, 0x25, 0xe0, 0xcf, 0x65, 0xbb, 0xf5, 0x61, +0x04, 0xef, 0xdd, 0x1e, 0xb2, 0x5a, 0x41, 0x22, 0x5a, 0xa1, 0x9f, 0x5d, 0x2c, 0xe8, 0x5b, 0xc9, +0x6d, 0xa9, 0x0c, 0x0c, 0x78, 0xaa, 0x60, 0xc6, 0x56, 0x8f, 0x01, 0x5a, 0x0c, 0x68, 0xbc, 0x69, +0x19, 0x79, 0xc4, 0x1f, 0x7e, 0x97, 0x05, 0xbf, 0xc5, 0xe9, 0x24, 0x51, 0x5e, 0xd4, 0xd5, 0x4b, +0x53, 0xed, 0xd9, 0x23, 0x5a, 0x36, 0x03, 0x65, 0xa3, 0xc1, 0x03, 0xad, 0x41, 0x30, 0xf3, 0x46, +0x1b, 0x85, 0x90, 0xaf, 0x65, 0xb5, 0xd5, 0xb1, 0xe4, 0x16, 0x5b, 0x78, 0x75, 0x1d, 0x97, 0x7a, +0x6d, 0x59, 0xa9, 0x2a, 0x8f, 0x7b, 0xde, 0xc3, 0x87, 0x89, 0x10, 0x99, 0x49, 0x73, 0x78, 0xc8, +0x3d, 0xbd, 0x51, 0x35, 0x74, 0x2a, 0xd5, 0xf1, 0x7e, 0x69, 0x1b, 0x2a, 0xbb, 0x3b, 0xbd, 0x25, +0xb8, 0x9a, 0x5a, 0x3d, 0x72, 0x61, 0x90, 0x66, 0x87, 0xee, 0x0c, 0xd6, 0x4d, 0xd4, 0x11, 0x74, +0x0b, 0x6a, 0xfe, 0x0b, 0x03, 0xfc, 0xa3, 0x55, 0x57, 0x89, 0xfe, 0x4a, 0xcb, 0xae, 0x5b, 0x17, +0x05, 0xc8, 0xf2, 0x8d, 0x23, 0x31, 0x53, 0x38, 0xd2, 0x2d, 0x6a, 0x3f, 0x82, 0xb9, 0x8d, 0x08, +0x6a, 0xf7, 0x5e, 0x41, 0x74, 0x6e, 0xc3, 0x11, 0x7e, 0x07, 0xac, 0x29, 0x60, 0x91, 0x3f, 0x38, +0xca, 0x57, 0x10, 0x0d, 0xbd, 0x30, 0x2f, 0xc7, 0xa5, 0xe6, 0x41, 0xa0, 0xda, 0xae, 0x05, 0x87, +0x9a, 0xa0, 0xa4, 0x65, 0x6c, 0x4c, 0x09, 0x0c, 0x89, 0xba, 0xb8, 0xd3, 0xb9, 0xc0, 0x93, 0x8a, +0x30, 0xfa, 0x8d, 0xe5, 0x9a, 0x6b, 0x15, 0x01, 0x4e, 0x67, 0xaa, 0xda, 0x62, 0x56, 0x3e, 0x84, +0x08, 0x66, 0xd2, 0xc4, 0x36, 0x7d, 0xa7, 0x3e, 0x10, 0xfc, 0x88, 0xe0, 0xd4, 0x80, 0xe5, 0x00, +0xbd, 0xaa, 0xf3, 0x4e, 0x06, 0xa3, 0x7a, 0x6a, 0xf9, 0x62, 0x72, 0xe3, 0x09, 0x4f, 0xeb, 0x9b, +0x0e, 0x01, 0x23, 0xf1, 0x9f, 0xbb, 0x7c, 0xdc, 0xdc, 0x6c, 0x11, 0x97, 0x25, 0xb2, 0xf2, 0xb4, +0x63, 0x14, 0xd2, 0x06, 0x2a, 0x67, 0x8c, 0x83, 0xf5, 0xce, 0xea, 0x07, 0xd8, 0x9a, 0x6a, 0x1e, +0xec, 0xe4, 0x0a, 0xbb, 0x2a, 0x4c, 0xeb, 0x09, 0x60, 0x39, 0xce, 0xca, 0x62, 0xd8, 0x2e, 0x6e, +0x30, 0x82, 0x04, 0x30, 0x30, 0x82, 0x03, 0x18, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x50, +0x94, 0x6c, 0xec, 0x18, 0xea, 0xd5, 0x9c, 0x4d, 0xd5, 0x97, 0xef, 0x75, 0x8f, 0xa0, 0xad, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, +0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, +0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2e, 0x78, 0x72, 0x61, +0x6d, 0x70, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x24, +0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x58, 0x52, 0x61, 0x6d, 0x70, 0x20, 0x53, +0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, +0x20, 0x49, 0x6e, 0x63, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x58, +0x52, 0x61, 0x6d, 0x70, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74, +0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, +0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, 0x31, 0x31, 0x30, 0x31, 0x31, 0x37, 0x31, +0x34, 0x30, 0x34, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x31, 0x30, 0x31, 0x30, 0x35, 0x33, 0x37, +0x31, 0x39, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, +0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x77, 0x77, +0x77, 0x2e, 0x78, 0x72, 0x61, 0x6d, 0x70, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2e, +0x63, 0x6f, 0x6d, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x58, 0x52, +0x61, 0x6d, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x53, 0x65, 0x72, +0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, +0x04, 0x03, 0x13, 0x24, 0x58, 0x52, 0x61, 0x6d, 0x70, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, +0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, +0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x98, 0x24, 0x1e, 0xbd, 0x15, 0xb4, 0xba, +0xdf, 0xc7, 0x8c, 0xa5, 0x27, 0xb6, 0x38, 0x0b, 0x69, 0xf3, 0xb6, 0x4e, 0xa8, 0x2c, 0x2e, 0x21, +0x1d, 0x5c, 0x44, 0xdf, 0x21, 0x5d, 0x7e, 0x23, 0x74, 0xfe, 0x5e, 0x7e, 0xb4, 0x4a, 0xb7, 0xa6, +0xad, 0x1f, 0xae, 0xe0, 0x06, 0x16, 0xe2, 0x9b, 0x5b, 0xd9, 0x67, 0x74, 0x6b, 0x5d, 0x80, 0x8f, +0x29, 0x9d, 0x86, 0x1b, 0xd9, 0x9c, 0x0d, 0x98, 0x6d, 0x76, 0x10, 0x28, 0x58, 0xe4, 0x65, 0xb0, +0x7f, 0x4a, 0x98, 0x79, 0x9f, 0xe0, 0xc3, 0x31, 0x7e, 0x80, 0x2b, 0xb5, 0x8c, 0xc0, 0x40, 0x3b, +0x11, 0x86, 0xd0, 0xcb, 0xa2, 0x86, 0x36, 0x60, 0xa4, 0xd5, 0x30, 0x82, 0x6d, 0xd9, 0x6e, 0xd0, +0x0f, 0x12, 0x04, 0x33, 0x97, 0x5f, 0x4f, 0x61, 0x5a, 0xf0, 0xe4, 0xf9, 0x91, 0xab, 0xe7, 0x1d, +0x3b, 0xbc, 0xe8, 0xcf, 0xf4, 0x6b, 0x2d, 0x34, 0x7c, 0xe2, 0x48, 0x61, 0x1c, 0x8e, 0xf3, 0x61, +0x44, 0xcc, 0x6f, 0xa0, 0x4a, 0xa9, 0x94, 0xb0, 0x4d, 0xda, 0xe7, 0xa9, 0x34, 0x7a, 0x72, 0x38, +0xa8, 0x41, 0xcc, 0x3c, 0x94, 0x11, 0x7d, 0xeb, 0xc8, 0xa6, 0x8c, 0xb7, 0x86, 0xcb, 0xca, 0x33, +0x3b, 0xd9, 0x3d, 0x37, 0x8b, 0xfb, 0x7a, 0x3e, 0x86, 0x2c, 0xe7, 0x73, 0xd7, 0x0a, 0x57, 0xac, +0x64, 0x9b, 0x19, 0xeb, 0xf4, 0x0f, 0x04, 0x08, 0x8a, 0xac, 0x03, 0x17, 0x19, 0x64, 0xf4, 0x5a, +0x25, 0x22, 0x8d, 0x34, 0x2c, 0xb2, 0xf6, 0x68, 0x1d, 0x12, 0x6d, 0xd3, 0x8a, 0x1e, 0x14, 0xda, +0xc4, 0x8f, 0xa6, 0xe2, 0x23, 0x85, 0xd5, 0x7a, 0x0d, 0xbd, 0x6a, 0xe0, 0xe9, 0xec, 0xec, 0x17, +0xbb, 0x42, 0x1b, 0x67, 0xaa, 0x25, 0xed, 0x45, 0x83, 0x21, 0xfc, 0xc1, 0xc9, 0x7c, 0xd5, 0x62, +0x3e, 0xfa, 0xf2, 0xc5, 0x2d, 0xd3, 0xfd, 0xd4, 0x65, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, +0x9f, 0x30, 0x81, 0x9c, 0x30, 0x13, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, +0x02, 0x04, 0x06, 0x1e, 0x04, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, +0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, +0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, +0x04, 0x14, 0xc6, 0x4f, 0xa2, 0x3d, 0x06, 0x63, 0x84, 0x09, 0x9c, 0xce, 0x62, 0xe4, 0x04, 0xac, +0x8d, 0x5c, 0xb5, 0xe9, 0xb6, 0x1b, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, +0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, +0x63, 0x72, 0x6c, 0x2e, 0x78, 0x72, 0x61, 0x6d, 0x70, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, +0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x58, 0x47, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, +0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x01, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, +0x82, 0x01, 0x01, 0x00, 0x91, 0x15, 0x39, 0x03, 0x01, 0x1b, 0x67, 0xfb, 0x4a, 0x1c, 0xf9, 0x0a, +0x60, 0x5b, 0xa1, 0xda, 0x4d, 0x97, 0x62, 0xf9, 0x24, 0x53, 0x27, 0xd7, 0x82, 0x64, 0x4e, 0x90, +0x2e, 0xc3, 0x49, 0x1b, 0x2b, 0x9a, 0xdc, 0xfc, 0xa8, 0x78, 0x67, 0x35, 0xf1, 0x1d, 0xf0, 0x11, +0xbd, 0xb7, 0x48, 0xe3, 0x10, 0xf6, 0x0d, 0xdf, 0x3f, 0xd2, 0xc9, 0xb6, 0xaa, 0x55, 0xa4, 0x48, +0xba, 0x02, 0xdb, 0xde, 0x59, 0x2e, 0x15, 0x5b, 0x3b, 0x9d, 0x16, 0x7d, 0x47, 0xd7, 0x37, 0xea, +0x5f, 0x4d, 0x76, 0x12, 0x36, 0xbb, 0x1f, 0xd7, 0xa1, 0x81, 0x04, 0x46, 0x20, 0xa3, 0x2c, 0x6d, +0xa9, 0x9e, 0x01, 0x7e, 0x3f, 0x29, 0xce, 0x00, 0x93, 0xdf, 0xfd, 0xc9, 0x92, 0x73, 0x89, 0x89, +0x64, 0x9e, 0xe7, 0x2b, 0xe4, 0x1c, 0x91, 0x2c, 0xd2, 0xb9, 0xce, 0x7d, 0xce, 0x6f, 0x31, 0x99, +0xd3, 0xe6, 0xbe, 0xd2, 0x1e, 0x90, 0xf0, 0x09, 0x14, 0x79, 0x5c, 0x23, 0xab, 0x4d, 0xd2, 0xda, +0x21, 0x1f, 0x4d, 0x99, 0x79, 0x9d, 0xe1, 0xcf, 0x27, 0x9f, 0x10, 0x9b, 0x1c, 0x88, 0x0d, 0xb0, +0x8a, 0x64, 0x41, 0x31, 0xb8, 0x0e, 0x6c, 0x90, 0x24, 0xa4, 0x9b, 0x5c, 0x71, 0x8f, 0xba, 0xbb, +0x7e, 0x1c, 0x1b, 0xdb, 0x6a, 0x80, 0x0f, 0x21, 0xbc, 0xe9, 0xdb, 0xa6, 0xb7, 0x40, 0xf4, 0xb2, +0x8b, 0xa9, 0xb1, 0xe4, 0xef, 0x9a, 0x1a, 0xd0, 0x3d, 0x69, 0x99, 0xee, 0xa8, 0x28, 0xa3, 0xe1, +0x3c, 0xb3, 0xf0, 0xb2, 0x11, 0x9c, 0xcf, 0x7c, 0x40, 0xe6, 0xdd, 0xe7, 0x43, 0x7d, 0xa2, 0xd8, +0x3a, 0xb5, 0xa9, 0x8d, 0xf2, 0x34, 0x99, 0xc4, 0xd4, 0x10, 0xe1, 0x06, 0xfd, 0x09, 0x84, 0x10, +0x3b, 0xee, 0xc4, 0x4c, 0xf4, 0xec, 0x27, 0x7c, 0x42, 0xc2, 0x74, 0x7c, 0x82, 0x8a, 0x09, 0xc9, +0xb4, 0x03, 0x25, 0xbc, 0x30, 0x82, 0x01, 0xe1, 0x30, 0x82, 0x01, 0x87, 0xa0, 0x03, 0x02, 0x01, +0x02, 0x02, 0x11, 0x2a, 0x38, 0xa4, 0x1c, 0x96, 0x0a, 0x04, 0xde, 0x42, 0xb2, 0x28, 0xa5, 0x0b, +0xe8, 0x34, 0x98, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, +0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1b, 0x47, 0x6c, 0x6f, +0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, +0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x31, 0x13, 0x30, +0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, +0x67, 0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x31, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x30, +0x37, 0x5a, 0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1b, 0x47, +0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x31, +0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, +0x53, 0x69, 0x67, 0x6e, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, +0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xb8, +0xc6, 0x79, 0xd3, 0x8f, 0x6c, 0x25, 0x0e, 0x9f, 0x2e, 0x39, 0x19, 0x1c, 0x03, 0xa4, 0xae, 0x9a, +0xe5, 0x39, 0x07, 0x09, 0x16, 0xca, 0x63, 0xb1, 0xb9, 0x86, 0xf8, 0x8a, 0x57, 0xc1, 0x57, 0xce, +0x42, 0xfa, 0x73, 0xa1, 0xf7, 0x65, 0x42, 0xff, 0x1e, 0xc1, 0x00, 0xb2, 0x6e, 0x73, 0x0e, 0xff, +0xc7, 0x21, 0xe5, 0x18, 0xa4, 0xaa, 0xd9, 0x71, 0x3f, 0xa8, 0xd4, 0xb9, 0xce, 0x8c, 0x1d, 0xa3, +0x42, 0x30, 0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, +0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, +0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x54, +0xb0, 0x7b, 0xad, 0x45, 0xb8, 0xe2, 0x40, 0x7f, 0xfb, 0x0a, 0x6e, 0xfb, 0xbe, 0x33, 0xc9, 0x3c, +0xa3, 0x84, 0xd5, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, +0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xdc, 0x92, 0xa1, 0xa0, 0x13, 0xa6, 0xcf, 0x03, 0xb0, +0xe6, 0xc4, 0x21, 0x97, 0x90, 0xfa, 0x14, 0x57, 0x2d, 0x03, 0xec, 0xee, 0x3c, 0xd3, 0x6e, 0xca, +0xa8, 0x6c, 0x76, 0xbc, 0xa2, 0xde, 0xbb, 0x02, 0x20, 0x27, 0xa8, 0x85, 0x27, 0x35, 0x9b, 0x56, +0xc6, 0xa3, 0xf2, 0x47, 0xd2, 0xb7, 0x6e, 0x1b, 0x02, 0x00, 0x17, 0xaa, 0x67, 0xa6, 0x15, 0x91, +0xde, 0xfa, 0x94, 0xec, 0x7b, 0x0b, 0xf8, 0x9f, 0x84, 0x30, 0x82, 0x06, 0x4b, 0x30, 0x82, 0x04, +0x33, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xd9, 0xb5, 0x43, 0x7f, 0xaf, 0xa9, 0x39, +0x0f, 0x00, 0x00, 0x00, 0x00, 0x55, 0x65, 0xad, 0x58, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xbe, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, +0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, +0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, 0x65, 0x20, 0x77, +0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, +0x65, 0x67, 0x61, 0x6c, 0x2d, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x30, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x35, 0x20, 0x45, 0x6e, +0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x66, 0x6f, +0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, +0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, +0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, +0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, +0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x34, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, +0x35, 0x32, 0x37, 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x32, +0x32, 0x37, 0x31, 0x31, 0x34, 0x31, 0x31, 0x36, 0x5a, 0x30, 0x81, 0xbe, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x0d, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, +0x2e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x53, 0x65, 0x65, 0x20, +0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, +0x6c, 0x65, 0x67, 0x61, 0x6c, 0x2d, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x31, 0x39, 0x30, 0x37, 0x06, +0x03, 0x55, 0x04, 0x0b, 0x13, 0x30, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x35, 0x20, 0x45, +0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x66, +0x6f, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x75, 0x73, +0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, +0x29, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, +0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x34, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, +0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb1, 0xec, 0x2c, 0x42, 0xee, +0xe2, 0xd1, 0x30, 0xff, 0xa5, 0x92, 0x47, 0xe2, 0x2d, 0xc3, 0xba, 0x64, 0x97, 0x6d, 0xca, 0xf7, +0x0d, 0xb5, 0x59, 0xc1, 0xb3, 0xcb, 0xa8, 0x68, 0x19, 0xd8, 0xaf, 0x84, 0x6d, 0x30, 0x70, 0x5d, +0x7e, 0xf3, 0x2e, 0xd2, 0x53, 0x99, 0xe1, 0xfe, 0x1f, 0x5e, 0xd9, 0x48, 0xaf, 0x5d, 0x13, 0x8d, +0xdb, 0xff, 0x63, 0x33, 0x4d, 0xd3, 0x00, 0x02, 0xbc, 0xc4, 0xf8, 0xd1, 0x06, 0x08, 0x94, 0x79, +0x58, 0x8a, 0x15, 0xde, 0x29, 0xb3, 0xfd, 0xfd, 0xc4, 0x4f, 0xe8, 0xaa, 0xe2, 0xa0, 0x3b, 0x79, +0xcd, 0xbf, 0x6b, 0x43, 0x32, 0xdd, 0xd9, 0x74, 0x10, 0xb9, 0xf7, 0xf4, 0x68, 0xd4, 0xbb, 0xd0, +0x87, 0xd5, 0xaa, 0x4b, 0x8a, 0x2a, 0x6f, 0x2a, 0x04, 0xb5, 0xb2, 0xa6, 0xc7, 0xa0, 0x7a, 0xe6, +0x48, 0xab, 0xd2, 0xd1, 0x59, 0xcc, 0xd6, 0x7e, 0x23, 0xe6, 0x97, 0x6c, 0xf0, 0x42, 0xe5, 0xdc, +0x51, 0x4b, 0x15, 0x41, 0xed, 0x49, 0x4a, 0xc9, 0xde, 0x10, 0x97, 0xd6, 0x76, 0xc1, 0xef, 0xa5, +0xb5, 0x36, 0x14, 0x97, 0x35, 0xd8, 0x78, 0x22, 0x35, 0x52, 0xef, 0x43, 0xbd, 0xdb, 0x27, 0xdb, +0x61, 0x56, 0x82, 0x34, 0xdc, 0xcb, 0x88, 0x60, 0x0c, 0x0b, 0x5a, 0xe5, 0x2c, 0x01, 0xc6, 0x54, +0xaf, 0xd7, 0xaa, 0xc1, 0x10, 0x7b, 0xd2, 0x05, 0x5a, 0xb8, 0x40, 0x9e, 0x86, 0xa7, 0xc3, 0x90, +0x86, 0x02, 0x56, 0x52, 0x09, 0x7a, 0x9c, 0xd2, 0x27, 0x82, 0x53, 0x4a, 0x65, 0x52, 0x6a, 0xf5, +0x3c, 0xe7, 0xa8, 0xf2, 0x9c, 0xaf, 0x8b, 0xbd, 0xd3, 0x0e, 0xd4, 0xd4, 0x5e, 0x6e, 0x87, 0x9e, +0x6a, 0x3d, 0x45, 0x1d, 0xd1, 0x5d, 0x1b, 0xf4, 0xe9, 0x0a, 0xac, 0x60, 0x99, 0xfb, 0x89, 0xb4, +0xff, 0x98, 0x2c, 0xcf, 0x7c, 0x1d, 0xe9, 0x02, 0xaa, 0x04, 0x9a, 0x1e, 0xb8, 0xdc, 0x88, 0x6e, +0x25, 0xb3, 0x6c, 0x66, 0xf7, 0x3c, 0x90, 0xf3, 0x57, 0xc1, 0xb3, 0x2f, 0xf5, 0x6d, 0xf2, 0xfb, +0xca, 0xa1, 0xf8, 0x29, 0x9d, 0x46, 0x8b, 0xb3, 0x6a, 0xf6, 0xe6, 0x67, 0x07, 0xbe, 0x2c, 0x67, +0x0a, 0x2a, 0x1f, 0x5a, 0xb2, 0x3e, 0x57, 0xc4, 0xd3, 0x21, 0x21, 0x63, 0x65, 0x52, 0x91, 0x1b, +0xb1, 0x99, 0x8e, 0x79, 0x7e, 0xe6, 0xeb, 0x8d, 0x00, 0xd9, 0x5a, 0xaa, 0xea, 0x73, 0xe8, 0xa4, +0x82, 0x02, 0x47, 0x96, 0xfe, 0x5b, 0x8e, 0x54, 0x61, 0xa3, 0xeb, 0x2f, 0x4b, 0x30, 0xb0, 0x8b, +0x23, 0x75, 0x72, 0x7c, 0x21, 0x3c, 0xc8, 0xf6, 0xf1, 0x74, 0xd4, 0x1c, 0x7b, 0xa3, 0x05, 0x55, +0xee, 0xbb, 0x4d, 0x3b, 0x32, 0xbe, 0x9a, 0x77, 0x66, 0x9e, 0xac, 0x69, 0x90, 0x22, 0x07, 0x1f, +0x61, 0x3a, 0x96, 0xbe, 0xe5, 0x9a, 0x4f, 0xcc, 0x05, 0x3c, 0x28, 0x59, 0xd3, 0xc1, 0x0c, 0x54, +0xa8, 0x59, 0x61, 0xbd, 0xc8, 0x72, 0x4c, 0xe8, 0xdc, 0x9f, 0x87, 0x7f, 0xbd, 0x9c, 0x48, 0x36, +0x5e, 0x95, 0xa3, 0x0e, 0xb9, 0x38, 0x24, 0x55, 0xfc, 0x75, 0x66, 0xeb, 0x02, 0xe3, 0x08, 0x34, +0x29, 0x4a, 0xc6, 0xe3, 0x2b, 0x2f, 0x33, 0xa0, 0xda, 0xa3, 0x86, 0xa5, 0x12, 0x97, 0xfd, 0x80, +0x2b, 0xda, 0x14, 0x42, 0xe3, 0x92, 0xbd, 0x3e, 0xf2, 0x5d, 0x5e, 0x67, 0x74, 0x2e, 0x1c, 0x88, +0x47, 0x29, 0x34, 0x5f, 0xe2, 0x32, 0xa8, 0x9c, 0x25, 0x37, 0x8c, 0xba, 0x98, 0x00, 0x97, 0x8b, +0x49, 0x96, 0x1e, 0xfd, 0x25, 0x8a, 0xac, 0xdc, 0xda, 0xd8, 0x5d, 0x74, 0x6e, 0x66, 0xb0, 0xff, +0x44, 0xdf, 0xa1, 0x18, 0xc6, 0xbe, 0x48, 0x2f, 0x37, 0x94, 0x78, 0xf8, 0x95, 0x4a, 0x3f, 0x7f, +0x13, 0x5e, 0x5d, 0x59, 0xfd, 0x74, 0x86, 0x43, 0x63, 0x73, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, +0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0x9f, 0x38, 0xc4, 0x56, 0x23, 0xc3, 0x39, 0xe8, 0xa0, 0x71, 0x6c, 0xe8, 0x54, 0x4c, 0xe4, 0xe8, +0x3a, 0xb1, 0xbf, 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, +0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x12, 0xe5, 0x42, 0xa6, 0x7b, 0x8b, 0x0f, 0x0c, +0xe4, 0x46, 0xa5, 0xb6, 0x60, 0x40, 0x87, 0x8c, 0x25, 0x7e, 0xad, 0xb8, 0x68, 0x2e, 0x5b, 0xc6, +0x40, 0x76, 0x3c, 0x03, 0xf8, 0xc9, 0x59, 0xf4, 0xf3, 0xab, 0x62, 0xce, 0x10, 0x8d, 0xb4, 0x5a, +0x64, 0x8c, 0x68, 0xc0, 0xb0, 0x72, 0x43, 0x34, 0xd2, 0x1b, 0x0b, 0xf6, 0x2c, 0x53, 0xd2, 0xca, +0x90, 0x4b, 0x86, 0x66, 0xfc, 0xaa, 0x83, 0x22, 0xf4, 0x8b, 0x1a, 0x6f, 0x26, 0x48, 0xac, 0x76, +0x77, 0x08, 0xbf, 0xc5, 0x98, 0x5c, 0xf4, 0x26, 0x89, 0x9e, 0x7b, 0xc3, 0xb9, 0x64, 0x32, 0x01, +0x7f, 0xd3, 0xc3, 0xdd, 0x58, 0x6d, 0xec, 0xb1, 0xab, 0x84, 0x55, 0x74, 0x77, 0x84, 0x04, 0x27, +0x52, 0x6b, 0x86, 0x4c, 0xce, 0xdd, 0xb9, 0x65, 0xff, 0xd6, 0xc6, 0x5e, 0x9f, 0x9a, 0x10, 0x99, +0x4b, 0x75, 0x6a, 0xfe, 0x6a, 0xe9, 0x97, 0x20, 0xe4, 0xe4, 0x76, 0x7a, 0xc6, 0xd0, 0x24, 0xaa, +0x90, 0xcd, 0x20, 0x90, 0xba, 0x47, 0x64, 0xfb, 0x7f, 0x07, 0xb3, 0x53, 0x78, 0xb5, 0x0a, 0x62, +0xf2, 0x73, 0x43, 0xce, 0x41, 0x2b, 0x81, 0x6a, 0x2e, 0x85, 0x16, 0x94, 0x53, 0xd4, 0x6b, 0x5f, +0x72, 0x22, 0xab, 0x51, 0x2d, 0x42, 0xd5, 0x00, 0x9c, 0x99, 0xbf, 0xde, 0xbb, 0x94, 0x3b, 0x57, +0xfd, 0x9a, 0xf5, 0x86, 0xcb, 0x56, 0x3b, 0x5b, 0x88, 0x01, 0xe5, 0x7c, 0x28, 0x4b, 0x03, 0xf9, +0x49, 0x83, 0x7c, 0xb2, 0x7f, 0x7c, 0xe3, 0xed, 0x8e, 0xa1, 0x7f, 0x60, 0x53, 0x8e, 0x55, 0x9d, +0x50, 0x34, 0x12, 0x0f, 0xb7, 0x97, 0x7b, 0x6c, 0x87, 0x4a, 0x44, 0xe7, 0xf5, 0x6d, 0xec, 0x80, +0x37, 0xf0, 0x58, 0x19, 0x6e, 0x4a, 0x68, 0x76, 0xf0, 0x1f, 0x92, 0xe4, 0xea, 0xb5, 0x92, 0xd3, +0x61, 0x51, 0x10, 0x0b, 0xad, 0xa7, 0xd9, 0x5f, 0xc7, 0x5f, 0xdc, 0x1f, 0xa3, 0x5c, 0x8c, 0xa1, +0x7e, 0x9b, 0xb7, 0x9e, 0xd3, 0x56, 0x6f, 0x66, 0x5e, 0x07, 0x96, 0x20, 0xed, 0x0b, 0x74, 0xfb, +0x66, 0x4e, 0x8b, 0x11, 0x15, 0xe9, 0x81, 0x49, 0x7e, 0x6f, 0xb0, 0xd4, 0x50, 0x7f, 0x22, 0xd7, +0x5f, 0x65, 0x02, 0x0d, 0xa6, 0xf4, 0x85, 0x1e, 0xd8, 0xae, 0x06, 0x4b, 0x4a, 0xa7, 0xd2, 0x31, +0x66, 0xc2, 0xf8, 0xce, 0xe5, 0x08, 0xa6, 0xa4, 0x02, 0x96, 0x44, 0x68, 0x57, 0xc4, 0xd5, 0x33, +0xcf, 0x19, 0x2f, 0x14, 0xc4, 0x94, 0x1c, 0x7b, 0xa4, 0xd9, 0xf0, 0x9f, 0x0e, 0xb1, 0x80, 0xe2, +0xd1, 0x9e, 0x11, 0x64, 0xa9, 0x88, 0x11, 0x3a, 0x76, 0x82, 0xe5, 0x62, 0xc2, 0x80, 0xd8, 0xa4, +0x83, 0xed, 0x93, 0xef, 0x7c, 0x2f, 0x90, 0xb0, 0x32, 0x4c, 0x96, 0x15, 0x68, 0x48, 0x52, 0xd4, +0x99, 0x08, 0xc0, 0x24, 0xe8, 0x1c, 0xe3, 0xb3, 0xa5, 0x21, 0x0e, 0x92, 0xc0, 0x90, 0x1f, 0xcf, +0x20, 0x5f, 0xca, 0x3b, 0x38, 0xc7, 0xb7, 0x6d, 0x3a, 0xf3, 0xe6, 0x44, 0xb8, 0x0e, 0x31, 0x6b, +0x88, 0x8e, 0x70, 0xeb, 0x9c, 0x17, 0x52, 0xa8, 0x41, 0x94, 0x2e, 0x87, 0xb6, 0xe7, 0xa6, 0x12, +0xc5, 0x75, 0xdf, 0x5b, 0xc0, 0x0a, 0x6e, 0x7b, 0xa4, 0xe4, 0x5e, 0x86, 0xf9, 0x36, 0x94, 0xdf, +0x77, 0xc3, 0xe9, 0x0d, 0xc0, 0x39, 0xf1, 0x79, 0xbb, 0x46, 0x8e, 0xab, 0x43, 0x59, 0x27, 0xb7, +0x20, 0xbb, 0x23, 0xe9, 0x56, 0x40, 0x21, 0xec, 0x31, 0x3d, 0x65, 0xaa, 0x43, 0xf2, 0x3d, 0xdf, +0x70, 0x44, 0xe1, 0xba, 0x4d, 0x26, 0x10, 0x3b, 0x98, 0x9f, 0xf3, 0xc8, 0x8e, 0x1b, 0x38, 0x56, +0x21, 0x6a, 0x51, 0x93, 0xd3, 0x91, 0xca, 0x46, 0xda, 0x89, 0xb7, 0x3d, 0x53, 0x83, 0x2c, 0x08, +0x1f, 0x8b, 0x8f, 0x53, 0xdd, 0xff, 0xac, 0x1f, 0x30, 0x82, 0x03, 0x94, 0x30, 0x82, 0x02, 0x7c, +0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x31, 0xf5, 0xe4, 0x62, 0x0c, 0x6c, 0x58, 0xed, 0xd6, +0xd8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, +0x30, 0x67, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4e, 0x31, +0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, +0x20, 0x50, 0x4b, 0x49, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x65, +0x4d, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, +0x69, 0x65, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1c, 0x30, 0x1a, 0x06, +0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, +0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, +0x32, 0x31, 0x38, 0x31, 0x38, 0x33, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x32, +0x31, 0x38, 0x31, 0x38, 0x33, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x67, 0x31, 0x0b, 0x30, 0x09, 0x06, +0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, +0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x50, 0x4b, 0x49, 0x31, 0x25, 0x30, +0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x65, 0x4d, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, +0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4c, 0x69, 0x6d, +0x69, 0x74, 0x65, 0x64, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, +0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, +0x47, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, +0x01, 0x01, 0x00, 0x93, 0x4b, 0xbb, 0xe9, 0x66, 0x8a, 0xee, 0x9d, 0x5b, 0xd5, 0x34, 0x93, 0xd0, +0x1b, 0x1e, 0xc3, 0xe7, 0x9e, 0xb8, 0x64, 0x33, 0x7f, 0x63, 0x78, 0x68, 0xb4, 0xcd, 0x2e, 0x71, +0x75, 0xd7, 0x9b, 0x20, 0xc6, 0x4d, 0x29, 0xbc, 0xb6, 0x68, 0x60, 0x8a, 0xf7, 0x21, 0x9a, 0x56, +0x35, 0x5a, 0xf3, 0x76, 0xbd, 0xd8, 0xcd, 0x9a, 0xff, 0x93, 0x56, 0x4b, 0xa5, 0x59, 0x06, 0xa1, +0x93, 0x34, 0x29, 0xdd, 0x16, 0x34, 0x75, 0x4e, 0xf2, 0x81, 0xb4, 0xc7, 0x96, 0x4e, 0xad, 0x19, +0x15, 0x52, 0x4a, 0xfe, 0x3c, 0x70, 0x75, 0x70, 0xcd, 0xaf, 0x2b, 0xab, 0x15, 0x9a, 0x33, 0x3c, +0xaa, 0xb3, 0x8b, 0xaa, 0xcd, 0x43, 0xfd, 0xf5, 0xea, 0x70, 0xff, 0xed, 0xcf, 0x11, 0x3b, 0x94, +0xce, 0x4e, 0x32, 0x16, 0xd3, 0x23, 0x40, 0x2a, 0x77, 0xb3, 0xaf, 0x3c, 0x01, 0x2c, 0x6c, 0xed, +0x99, 0x2c, 0x8b, 0xd9, 0x4e, 0x69, 0x98, 0xb2, 0xf7, 0x8f, 0x41, 0xb0, 0x32, 0x78, 0x61, 0xd6, +0x0d, 0x5f, 0xc3, 0xfa, 0xa2, 0x40, 0x92, 0x1d, 0x5c, 0x17, 0xe6, 0x70, 0x3e, 0x35, 0xe7, 0xa2, +0xb7, 0xc2, 0x62, 0xe2, 0xab, 0xa4, 0x38, 0x4c, 0xb5, 0x39, 0x35, 0x6f, 0xea, 0x03, 0x69, 0xfa, +0x3a, 0x54, 0x68, 0x85, 0x6d, 0xd6, 0xf2, 0x2f, 0x43, 0x55, 0x1e, 0x91, 0x0d, 0x0e, 0xd8, 0xd5, +0x6a, 0xa4, 0x96, 0xd1, 0x13, 0x3c, 0x2c, 0x78, 0x50, 0xe8, 0x3a, 0x92, 0xd2, 0x17, 0x56, 0xe5, +0x35, 0x1a, 0x40, 0x1c, 0x3e, 0x8d, 0x2c, 0xed, 0x39, 0xdf, 0x42, 0xe0, 0x83, 0x41, 0x74, 0xdf, +0xa3, 0xcd, 0xc2, 0x86, 0x60, 0x48, 0x68, 0xe3, 0x69, 0x0b, 0x54, 0x00, 0x8b, 0xe4, 0x76, 0x69, +0x21, 0x0d, 0x79, 0x4e, 0x34, 0x08, 0x5e, 0x14, 0xc2, 0xcc, 0xb1, 0xb7, 0xad, 0xd7, 0x7c, 0x70, +0x8a, 0xc7, 0x85, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, +0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfb, 0xef, 0x0d, 0x86, 0x9e, 0xb0, 0xe3, 0xdd, 0xa9, +0xb9, 0xf1, 0x21, 0x17, 0x7f, 0x3e, 0xfc, 0xf0, 0x77, 0x2b, 0x1a, 0x30, 0x0e, 0x06, 0x03, 0x55, +0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, +0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, +0x59, 0xff, 0xf2, 0x8c, 0xf5, 0x87, 0x7d, 0x71, 0x3d, 0xa3, 0x9f, 0x1b, 0x5b, 0xd1, 0xda, 0xf8, +0xd3, 0x9c, 0x6b, 0x36, 0xbd, 0x9b, 0xa9, 0x61, 0xeb, 0xde, 0x16, 0x2c, 0x74, 0x3d, 0x9e, 0xe6, +0x75, 0xda, 0xd7, 0xba, 0xa7, 0xbc, 0x42, 0x17, 0xe7, 0x3d, 0x91, 0xeb, 0xe5, 0x7d, 0xdd, 0x3e, +0x9c, 0xf1, 0xcf, 0x92, 0xac, 0x6c, 0x48, 0xcc, 0xc2, 0x22, 0x3f, 0x69, 0x3b, 0xc5, 0xb6, 0x15, +0x2f, 0xa3, 0x35, 0xc6, 0x68, 0x2a, 0x1c, 0x57, 0xaf, 0x39, 0xef, 0x8d, 0xd0, 0x35, 0xc3, 0x18, +0x0c, 0x7b, 0x00, 0x56, 0x1c, 0xcd, 0x8b, 0x19, 0x74, 0xde, 0xbe, 0x0f, 0x12, 0xe0, 0xd0, 0xaa, +0xa1, 0x3f, 0x02, 0x34, 0xb1, 0x70, 0xce, 0x9d, 0x18, 0xd6, 0x08, 0x03, 0x09, 0x46, 0xee, 0x60, +0xe0, 0x7e, 0xb6, 0xc4, 0x49, 0x04, 0x51, 0x7d, 0x70, 0x60, 0xbc, 0xaa, 0xb2, 0xff, 0x79, 0x72, +0x7a, 0xa6, 0x1d, 0x3d, 0x5f, 0x2a, 0xf8, 0xca, 0xe2, 0xfd, 0x39, 0xb7, 0x47, 0xb9, 0xeb, 0x7e, +0xdf, 0x04, 0x23, 0xaf, 0xfa, 0x9c, 0x06, 0x07, 0xe9, 0xfb, 0x63, 0x93, 0x80, 0x40, 0xb5, 0xc6, +0x6c, 0x0a, 0x31, 0x28, 0xce, 0x0c, 0x9f, 0xcf, 0xb3, 0x23, 0x35, 0x80, 0x41, 0x8d, 0x6c, 0xc4, +0x37, 0x7b, 0x81, 0x2f, 0x80, 0xa1, 0x40, 0x42, 0x85, 0xe9, 0xd9, 0x38, 0x8d, 0xe8, 0xa1, 0x53, +0xcd, 0x01, 0xbf, 0x69, 0xe8, 0x5a, 0x06, 0xf2, 0x45, 0x0b, 0x90, 0xfa, 0xae, 0xe1, 0xbf, 0x9d, +0xf2, 0xae, 0x57, 0x3c, 0xa5, 0xae, 0xb2, 0x56, 0xf4, 0x8b, 0x65, 0x40, 0xe9, 0xfd, 0x31, 0x81, +0x2c, 0xf4, 0x39, 0x09, 0xd8, 0xee, 0x6b, 0xa7, 0xb4, 0xa6, 0x1d, 0x15, 0xa5, 0x98, 0xf7, 0x01, +0x81, 0xd8, 0x85, 0x7d, 0xf3, 0x51, 0x5c, 0x71, 0x88, 0xde, 0xba, 0xcc, 0x1f, 0x80, 0x7e, 0x4a, +0x30, 0x82, 0x02, 0x4e, 0x30, 0x82, 0x01, 0xd3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x3c, +0xf6, 0x07, 0xa9, 0x68, 0x70, 0x0e, 0xda, 0x8b, 0x84, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, +0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, +0x13, 0x02, 0x49, 0x4e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x65, +0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x50, 0x4b, 0x49, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, +0x04, 0x0a, 0x13, 0x1c, 0x65, 0x4d, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, +0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, +0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6d, 0x53, 0x69, 0x67, +0x6e, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, +0x47, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x32, 0x31, 0x38, 0x31, 0x38, 0x33, 0x30, +0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x32, 0x31, 0x38, 0x31, 0x38, 0x33, 0x30, 0x30, +0x30, 0x5a, 0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, +0x4e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, 0x69, +0x67, 0x6e, 0x20, 0x50, 0x4b, 0x49, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, +0x1c, 0x65, 0x4d, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, +0x6f, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x20, 0x30, +0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x45, +0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, +0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, +0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x23, 0xa5, 0x0c, 0xb8, 0x2d, 0x12, 0xf5, 0x28, 0xf3, +0xb1, 0xb2, 0xdd, 0xe2, 0x02, 0x12, 0x80, 0x9e, 0x39, 0x5f, 0x49, 0x4d, 0x9f, 0xc9, 0x25, 0x34, +0x59, 0x74, 0xec, 0xbb, 0x06, 0x1c, 0xe7, 0xc0, 0x72, 0xaf, 0xe8, 0xae, 0x2f, 0xe1, 0x41, 0x54, +0x87, 0x14, 0xa8, 0x4a, 0xb2, 0xe8, 0x7c, 0x82, 0xe6, 0x5b, 0x6a, 0xb5, 0xdc, 0xb3, 0x75, 0xce, +0x8b, 0x06, 0xd0, 0x86, 0x23, 0xbf, 0x46, 0xd5, 0x8e, 0x0f, 0x3f, 0x04, 0xf4, 0xd7, 0x1c, 0x92, +0x7e, 0xf6, 0xa5, 0x63, 0xc2, 0xf5, 0x5f, 0x8e, 0x2e, 0x4f, 0xa1, 0x18, 0x19, 0x02, 0x2b, 0x32, +0x0a, 0x82, 0x64, 0x7d, 0x16, 0x93, 0xd1, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, +0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7c, 0x5d, 0x02, 0x84, 0x13, 0xd4, 0xcc, 0x8a, 0x9b, 0x81, +0xce, 0x17, 0x1c, 0x2e, 0x29, 0x1e, 0x9c, 0x48, 0x63, 0x42, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, +0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, +0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, +0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xbe, +0xf3, 0x61, 0xcf, 0x02, 0x10, 0x1d, 0x64, 0x95, 0x07, 0xb8, 0x18, 0x6e, 0x88, 0x85, 0x05, 0x2f, +0x83, 0x08, 0x17, 0x90, 0xca, 0x1f, 0x8a, 0x4c, 0xe8, 0x0d, 0x1b, 0x7a, 0xb1, 0xad, 0xd5, 0x81, +0x09, 0x47, 0xef, 0x3b, 0xac, 0x08, 0x04, 0x7c, 0x5c, 0x99, 0xb1, 0xed, 0x47, 0x07, 0xd2, 0x02, +0x31, 0x00, 0x9d, 0xba, 0x55, 0xfc, 0xa9, 0x4a, 0xe8, 0xed, 0xed, 0xe6, 0x76, 0x01, 0x42, 0x7b, +0xc8, 0xf8, 0x60, 0xd9, 0x8d, 0x51, 0x8b, 0x55, 0x3b, 0xfb, 0x8c, 0x7b, 0xeb, 0x65, 0x09, 0xc3, +0xf8, 0x96, 0xcd, 0x47, 0xa8, 0x82, 0xf2, 0x16, 0x55, 0x77, 0x24, 0x7e, 0x12, 0x10, 0x95, 0x04, +0x2c, 0xa3, 0x30, 0x82, 0x03, 0x73, 0x30, 0x82, 0x02, 0x5b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, +0x0b, 0x00, 0xae, 0xcf, 0x00, 0xba, 0xc4, 0xcf, 0x32, 0xf8, 0x43, 0xb2, 0x30, 0x0d, 0x06, 0x09, +0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x56, 0x31, 0x0b, 0x30, +0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, +0x55, 0x04, 0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x50, 0x4b, 0x49, 0x31, +0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x65, 0x4d, 0x75, 0x64, 0x68, 0x72, +0x61, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, +0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, +0x20, 0x43, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x32, 0x31, 0x38, 0x31, 0x38, 0x33, +0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x32, 0x31, 0x38, 0x31, 0x38, 0x33, 0x30, +0x30, 0x30, 0x5a, 0x30, 0x56, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, +0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, +0x69, 0x67, 0x6e, 0x20, 0x50, 0x4b, 0x49, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x13, 0x0b, 0x65, 0x4d, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x1c, 0x30, +0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x52, +0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x43, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, +0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xcf, 0xeb, 0xa9, 0xb9, +0xf1, 0x99, 0x05, 0xcc, 0xd8, 0x28, 0x21, 0x4a, 0xf3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xf5, +0xa0, 0x4f, 0x2c, 0x12, 0xe3, 0xfa, 0x13, 0x9a, 0x27, 0xd0, 0xcf, 0xf9, 0x79, 0x1a, 0x74, 0x5f, +0x1d, 0x79, 0x39, 0xfc, 0x5b, 0xf8, 0x70, 0x8e, 0xe0, 0x92, 0x52, 0xf7, 0xe4, 0x25, 0xf9, 0x54, +0x83, 0xd9, 0x1d, 0xd3, 0xc8, 0x5a, 0x85, 0x3f, 0x5e, 0xc7, 0xb6, 0x07, 0xee, 0x3e, 0xc0, 0xce, +0x9a, 0xaf, 0xac, 0x56, 0x42, 0x2a, 0x39, 0x25, 0x70, 0xd6, 0xbf, 0xb5, 0x7b, 0x36, 0xad, 0xac, +0xf6, 0x73, 0xdc, 0xcd, 0xd7, 0x1d, 0x8a, 0x83, 0xa5, 0xfb, 0x2b, 0x90, 0x15, 0x37, 0x6b, 0x1c, +0x26, 0x47, 0xdc, 0x3b, 0x29, 0x56, 0x93, 0x6a, 0xb3, 0xc1, 0x6a, 0x3a, 0x9d, 0x3d, 0xf5, 0xc1, +0x97, 0x38, 0x58, 0x05, 0x8b, 0x1c, 0x11, 0xe3, 0xe4, 0xb4, 0xb8, 0x5d, 0x85, 0x1d, 0x83, 0xfe, +0x78, 0x5f, 0x0b, 0x45, 0x68, 0x18, 0x48, 0xa5, 0x46, 0x73, 0x34, 0x3b, 0xfe, 0x0f, 0xc8, 0x76, +0xbb, 0xc7, 0x18, 0xf3, 0x05, 0xd1, 0x86, 0xf3, 0x85, 0xed, 0xe7, 0xb9, 0xd9, 0x32, 0xad, 0x55, +0x88, 0xce, 0xa6, 0xb6, 0x91, 0xb0, 0x4f, 0xac, 0x7e, 0x15, 0x23, 0x96, 0xf6, 0x3f, 0xf0, 0x20, +0x34, 0x16, 0xde, 0x0a, 0xc6, 0xc4, 0x04, 0x45, 0x79, 0x7f, 0xa7, 0xfd, 0xbe, 0xd2, 0xa9, 0xa5, +0xaf, 0x9c, 0xc5, 0x23, 0x2a, 0xf7, 0x3c, 0x21, 0x6c, 0xbd, 0xaf, 0x8f, 0x4e, 0xc5, 0x3a, 0xb2, +0xf3, 0x34, 0x12, 0xfc, 0xdf, 0x80, 0x1a, 0x49, 0xa4, 0xd4, 0xa9, 0x95, 0xf7, 0x9e, 0x89, 0x5e, +0xa2, 0x89, 0xac, 0x94, 0xcb, 0xa8, 0x68, 0x9b, 0xaf, 0x8a, 0x65, 0x27, 0xcd, 0x89, 0xee, 0xdd, +0x8c, 0xb5, 0x6b, 0x29, 0x70, 0x43, 0xa0, 0x69, 0x0b, 0xe4, 0xb9, 0x0f, 0x02, 0x03, 0x01, 0x00, +0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, +0xfe, 0xa1, 0xe0, 0x70, 0x1e, 0x2a, 0x03, 0x39, 0x52, 0x5a, 0x42, 0xbe, 0x5c, 0x91, 0x85, 0x7a, +0x18, 0xaa, 0x4d, 0xb5, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, +0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, +0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xc2, 0x4a, 0x56, 0xfa, 0x15, 0x21, 0x7b, +0x28, 0xa2, 0xe9, 0xe5, 0x1d, 0xfb, 0xf8, 0x2d, 0xc4, 0x39, 0x96, 0x41, 0x4c, 0x3b, 0x27, 0x2c, +0xc4, 0x6c, 0x18, 0x15, 0x80, 0xc6, 0xac, 0xaf, 0x47, 0x59, 0x2f, 0x26, 0x0b, 0xe3, 0x36, 0xb0, +0xef, 0x3b, 0xfe, 0x43, 0x97, 0x49, 0x32, 0x99, 0x12, 0x15, 0x5b, 0xdf, 0x11, 0x29, 0xff, 0xab, +0x53, 0xf8, 0xbb, 0xc1, 0x78, 0x0f, 0xac, 0x9c, 0x53, 0xaf, 0x57, 0xbd, 0x68, 0x8c, 0x3d, 0x69, +0x33, 0xf0, 0xa3, 0xa0, 0x23, 0x63, 0x3b, 0x64, 0x67, 0x22, 0x44, 0xad, 0xd5, 0x71, 0xcb, 0x56, +0x2a, 0x78, 0x92, 0xa3, 0x4f, 0x12, 0x31, 0x36, 0x36, 0xe2, 0xde, 0xfe, 0x00, 0xc4, 0xa3, 0x60, +0x0f, 0x27, 0xad, 0xa0, 0xb0, 0x8a, 0xb5, 0x36, 0x7a, 0x52, 0xa1, 0xbd, 0x27, 0xf4, 0x20, 0x27, +0x62, 0xe8, 0x4d, 0x94, 0x24, 0x13, 0xe4, 0x0a, 0x04, 0xe9, 0x3c, 0xab, 0x2e, 0xc8, 0x43, 0x09, +0x4a, 0xc6, 0x61, 0x04, 0xe5, 0x49, 0x34, 0x7e, 0xd3, 0xc4, 0xc8, 0xf5, 0x0f, 0xc0, 0xaa, 0xe9, +0xba, 0x54, 0x5e, 0xf3, 0x63, 0x2b, 0x4f, 0x4f, 0x50, 0xd4, 0xfe, 0xb9, 0x7b, 0x99, 0x8c, 0x3d, +0xc0, 0x2e, 0xbc, 0x02, 0x2b, 0xd3, 0xc4, 0x40, 0xe4, 0x8a, 0x07, 0x31, 0x1e, 0x9b, 0xce, 0x26, +0x99, 0x13, 0xfb, 0x11, 0xea, 0x9a, 0x22, 0x0c, 0x11, 0x19, 0xc7, 0x5e, 0x1b, 0x81, 0x50, 0x30, +0xc8, 0x96, 0x12, 0x6e, 0xe7, 0xcb, 0x41, 0x7f, 0x91, 0x3b, 0xa2, 0x47, 0xb7, 0x54, 0x80, 0x1b, +0xdc, 0x00, 0xcc, 0x9a, 0x90, 0xea, 0xc3, 0xc3, 0x50, 0x06, 0x62, 0x0c, 0x30, 0xc0, 0x15, 0x48, +0xa7, 0xa8, 0x59, 0x7c, 0xe1, 0xae, 0x22, 0xa2, 0xe2, 0x0a, 0x7a, 0x0f, 0xfa, 0x62, 0xab, 0x52, +0x4c, 0xe1, 0xf1, 0xdf, 0xca, 0xbe, 0x83, 0x0d, 0x42, 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, +0xb1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x7b, 0x71, 0xb6, 0x82, 0x56, 0xb8, 0x12, 0x7c, +0x9c, 0xa8, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x5a, +0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, +0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x50, +0x4b, 0x49, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x65, 0x4d, 0x75, +0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, +0x03, 0x13, 0x17, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, +0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x43, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, +0x30, 0x32, 0x31, 0x38, 0x31, 0x38, 0x33, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, +0x32, 0x31, 0x38, 0x31, 0x38, 0x33, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, +0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, +0x04, 0x0b, 0x13, 0x0a, 0x65, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x50, 0x4b, 0x49, 0x31, 0x14, +0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x65, 0x4d, 0x75, 0x64, 0x68, 0x72, 0x61, +0x20, 0x49, 0x6e, 0x63, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, +0x6d, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, +0x41, 0x20, 0x2d, 0x20, 0x43, 0x33, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, +0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xfd, 0xa5, +0x61, 0xae, 0x7b, 0x26, 0x10, 0x1d, 0xe9, 0xb7, 0x22, 0x30, 0xae, 0x06, 0xf4, 0x81, 0xb3, 0xb1, +0x42, 0x71, 0x95, 0x39, 0xbc, 0xd3, 0x52, 0xe3, 0xaf, 0xaf, 0xf9, 0xf2, 0x97, 0x35, 0x92, 0x36, +0x46, 0x0e, 0x87, 0x95, 0x8d, 0xb9, 0x39, 0x5a, 0xe9, 0xbb, 0xdf, 0xd0, 0xfe, 0xc8, 0x07, 0x41, +0x3c, 0xbb, 0x55, 0x6f, 0x83, 0xa3, 0x6a, 0xfb, 0x62, 0xb0, 0x81, 0x89, 0x02, 0x70, 0x7d, 0x48, +0xc5, 0x4a, 0xe3, 0xe9, 0x22, 0x54, 0x22, 0x4d, 0x93, 0xbb, 0x42, 0x0c, 0xaf, 0x77, 0x9c, 0x23, +0xa6, 0x7d, 0xd7, 0x61, 0x11, 0xce, 0x65, 0xc7, 0xf8, 0x7f, 0xfe, 0xf5, 0xf2, 0xa9, 0xa3, 0x42, +0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfb, 0x5a, 0x48, +0xd0, 0x80, 0x20, 0x40, 0xf2, 0xa8, 0xe9, 0x00, 0x07, 0x69, 0x19, 0x77, 0xa7, 0xe6, 0xc3, 0xf4, +0xcf, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, +0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, +0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, +0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xb4, 0xd8, 0x2f, 0x02, 0x89, 0xfd, 0xb6, 0x4c, 0x62, 0xba, +0x43, 0x4e, 0x13, 0x84, 0x72, 0xb5, 0xae, 0xdd, 0x1c, 0xde, 0xd6, 0xb5, 0xdc, 0x56, 0x8f, 0x58, +0x40, 0x5a, 0x2d, 0xde, 0x20, 0x4c, 0x22, 0x83, 0xca, 0x93, 0xa8, 0x7e, 0xee, 0x12, 0x40, 0xc7, +0xd6, 0x87, 0x4f, 0xf8, 0xdf, 0x85, 0x02, 0x30, 0x1c, 0x14, 0x64, 0xe4, 0x7c, 0x96, 0x83, 0x11, +0x9c, 0xb0, 0xd1, 0x5a, 0x61, 0x4b, 0xa6, 0x0f, 0x49, 0xd3, 0x00, 0xfc, 0xa1, 0xfc, 0xe4, 0xa5, +0xff, 0x7f, 0xad, 0xd7, 0x30, 0xd0, 0xc7, 0x77, 0x7f, 0xbe, 0x81, 0x07, 0x55, 0x30, 0x50, 0x20, +0x14, 0xf5, 0x57, 0x38, 0x0a, 0xa8, 0x31, 0x51, 0x05, 0x86, 0x02, 0x5d, 0x05, 0xac, 0x05, 0xf3, +0x02, 0x69, 0x05, 0xc4, 0x05, 0xd3, 0x05, 0xef, 0x05, 0x4b, 0x02, 0x6d, 0x03, 0xb9, 0x03, 0x76, +0x05, 0xd6, 0x02, 0x72, 0x05, 0x6f, 0x04, 0x67, 0x01, 0xba, 0x05, 0x8c, 0x05, 0x45, 0x03, 0x45, +0x01, 0xf6, 0x06, 0x0f, 0x02, 0xc7, 0x06, 0x5f, 0x04, 0x24, 0x06, 0x33, 0x04, 0x34, 0x05, 0x5e, +0x05, 0x4a, 0x02, 0x98, 0x02, 0x91, 0x05, 0xe1, 0x05, 0x87, 0x05, 0x91, 0x04, 0x19, 0x03, 0x4e, +0x03, 0xea, 0x05, 0x64, 0x05, 0xbb, 0x05, 0x64, 0x06, 0xa1, 0x05, 0x64, 0x03, 0x71, 0x03, 0x5e, +0x03, 0x7b, 0x05, 0xdc, 0x04, 0x13, 0x03, 0xe1, 0x03, 0xf3, 0x05, 0xe2, 0x02, 0x93, 0x04, 0x95, +0x05, 0x5a, 0x04, 0x2e, 0x04, 0x36, 0x07, 0xd7, 0x05, 0xbf, 0x03, 0x50, 0x05, 0xb4, 0x05, 0x4a, +0x02, 0x02, 0x03, 0x50, 0x06, 0x18, 0x03, 0x7b, 0x05, 0x5d, 0x03, 0x7b, 0x05, 0x5d, 0x05, 0x6d, +0x03, 0xac, 0x05, 0x3c, 0x05, 0x64, 0x05, 0x6a, 0x05, 0x74, 0x04, 0x42, 0x02, 0xfd, 0x03, 0x3c, +0x03, 0xbf, 0x04, 0x21, 0x03, 0xa5, 0x02, 0x8d, 0x03, 0xbb, 0x03, 0x9a, 0x03, 0xb3, 0x03, 0x92, +0x02, 0x43, 0x03, 0xc9, 0x05, 0x94, 0x02, 0x4a, 0x04, 0x04, 0x03, 0xc9, 0x04, 0x35, 0x03, 0x34, +0x05, 0xf5, 0x03, 0xc7, 0x03, 0xc7, 0x05, 0x45, 0x03, 0x7f, 0x05, 0xa6, 0x05, 0x5e, 0x02, 0x10, +0x02, 0x0e, 0x05, 0x5e, 0x05, 0x5e, 0x02, 0x0f, 0x03, 0xbe, 0x03, 0x63, 0x03, 0x79, 0x02, 0x22, +0x05, 0x87, 0x04, 0x0e, 0x03, 0xc0, 0x03, 0xbc, 0x05, 0xbe, 0x02, 0x44, 0x02, 0x64, 0x05, 0xde, +0x02, 0xa1, 0x04, 0x37, 0x04, 0x47, 0x06, 0x4f, 0x05, 0xc1, 0x04, 0x34, 0x01, 0xe5, 0x06, 0x4f, +0x03, 0x98, 0x02, 0x52, 0x03, 0x77, 0x02, 0x2f, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x00, 0x14, 0x14, 0x14, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xdc, 0x2e, 0x1f, 0xd1, 0x61, 0x37, 0x79, 0xe4, +0xab, 0xd5, 0xd5, 0xb3, 0x12, 0x71, 0x68, 0x3d, 0x6a, 0x68, 0x9c, 0x22, 0xc8, 0xcb, 0x99, 0x72, +0x70, 0x52, 0x0c, 0xf8, 0xe6, 0xbe, 0xb2, 0x04, 0x57, 0x29, 0x2a, 0xcf, 0x42, 0x10, 0xed, 0x35, +0x09, 0xcb, 0x59, 0x7f, 0x86, 0xb2, 0x70, 0x8f, 0x1a, 0xc3, 0x39, 0xe3, 0xc0, 0xd9, 0xe9, 0xbf, +0xbb, 0x4d, 0xb2, 0x23, 0x9c, 0x5f, 0xd0, 0x6c, 0x63, 0xa3, 0x5f, 0x93, 0xca, 0x93, 0x98, 0x08, +0xad, 0x8c, 0x87, 0xa5, 0x2c, 0x5c, 0xc1, 0x37, 0x8d, 0x06, 0x66, 0x74, 0x24, 0x76, 0x3a, 0xf3, +0x89, 0xf7, 0xbc, 0xd6, 0xbd, 0x47, 0x7d, 0x2f, 0xbc, 0x10, 0x5f, 0x4b, 0x8c, 0xfb, 0x1c, 0x75, +0xbc, 0x02, 0xd3, 0x9f, 0x4e, 0x2e, 0x48, 0xd9, 0xf9, 0x60, 0x54, 0xaa, 0xc4, 0xb3, 0x4f, 0xfa, +0x17, 0x9d, 0xcd, 0x1e, 0x8b, 0xd6, 0x39, 0x2b, 0x70, 0xd3, 0x5c, 0xd4, 0xa0, 0xb8, 0x1f, 0xb0, +0x00, 0xfc, 0xc5, 0x61, 0xf9, 0x60, 0xbb, 0xd4, 0xe3, 0xd5, 0x34, 0xf6, 0xb8, 0xf5, 0x06, 0x80, +0x25, 0xa7, 0x73, 0xdb, 0x46, 0x69, 0xa8, 0x9e, 0x82, 0x21, 0x2d, 0x66, 0xc6, 0xd7, 0xa0, 0xe0, +0x15, 0xeb, 0xce, 0x4c, 0x09, 0x77, 0xc4, 0x60, 0x9e, 0x54, 0x6e, 0x03, 0x48, 0x87, 0x14, 0xac, +0xe3, 0xc3, 0x9e, 0x90, 0x60, 0x3a, 0xd7, 0xca, 0x89, 0xee, 0xd3, 0xad, 0x8c, 0xb4, 0x50, 0x66, +0x35, 0x0f, 0xc8, 0x36, 0x63, 0x5e, 0xe2, 0xa3, 0xec, 0xf9, 0x3b, 0x66, 0x15, 0xce, 0x51, 0x52, +0xe3, 0x91, 0x9a, 0x3d, 0x2e, 0x16, 0xa9, 0x4a, 0x18, 0xb5, 0xcb, 0xcc, 0xf5, 0x6f, 0x50, 0xf3, +0x23, 0x5f, 0xf8, 0x5d, 0xe7, 0xac, 0xf0, 0xc8, 0xb6, 0xa1, 0x54, 0x39, 0x02, 0xc3, 0xa0, 0x3f, +0x8e, 0x8a, 0xbc, 0xfa, 0xd4, 0xf8, 0x1c, 0xa6, 0xd1, 0x3a, 0x0e, 0xfd, 0x01, 0xb9, 0x2f, 0xef, +0xbf, 0x11, 0x86, 0x60, 0xf2, 0x4f, 0xd0, 0x41, 0x6e, 0xab, 0x73, 0x1f, 0xe7, 0xd2, 0x6e, 0x49, +0x79, 0xb4, 0x59, 0xe6, 0x7b, 0xb6, 0xe5, 0xe4, 0x01, 0x73, 0x80, 0x08, 0x88, 0xc8, 0x1a, 0x58, +0xf6, 0xe9, 0x9b, 0x6e, 0x65, 0x3f, 0xc7, 0x8a, 0x86, 0xc6, 0x3c, 0xdd, 0x3c, 0x54, 0x5c, 0x35, +0xf8, 0x3a, 0xed, 0x52, 0x0c, 0x47, 0x57, 0xc8, 0xab, 0xb6, 0xdb, 0xd7, 0x06, 0x9e, 0x37, 0xac, +0x30, 0x86, 0x07, 0x91, 0x70, 0xc7, 0x9c, 0xc4, 0x19, 0xb1, 0x78, 0xc0, 0xe2, 0xc9, 0x40, 0x9f, +0x4d, 0xce, 0xe8, 0x9a, 0xa1, 0x7c, 0xcf, 0x0e, 0x3f, 0x65, 0xc5, 0x29, 0x88, 0x6a, 0x19, 0x51, +0xb0, 0x0c, 0xf0, 0x4c, 0x30, 0xf4, 0x05, 0x58, 0x02, 0x48, 0xfd, 0x33, 0xe5, 0x52, 0xaf, 0x4b, +0x84, 0xe3, 0x66, 0x52, 0x84, 0x18, 0xcc, 0x85, 0x34, 0xec, 0xbc, 0x0c, 0x94, 0x94, 0x2e, 0x08, +0x59, 0x9c, 0xc7, 0xb2, 0x10, 0x4e, 0x0a, 0x08, 0xd3, 0xec, 0xc7, 0x3a, 0x65, 0x6e, 0xcc, 0xe1, +0xda, 0x76, 0x9a, 0x56, 0xfb, 0x9c, 0xf3, 0x86, 0x6d, 0x57, 0xe5, 0x81, 0x71, 0x15, 0x67, 0xc8, +0xc8, 0xc9, 0xbd, 0x75, 0x5d, 0x72, 0xd0, 0x38, 0x18, 0x6a, 0x9d, 0xf3, 0x71, 0x24, 0x54, 0x0b, +0xb4, 0x22, 0x0b, 0x82, 0x99, 0x24, 0x01, 0x0e, 0x9c, 0xbb, 0xe4, 0x0e, 0xfd, 0xbf, 0xfb, 0x97, +0x20, 0x93, 0x99, 0x2a, 0x18, 0x87, 0x56, 0xe0, 0x6e, 0x77, 0xee, 0x24, 0x35, 0x3c, 0x4e, 0x73, +0x9a, 0x1f, 0xd6, 0xe1, 0xe2, 0x79, 0x7e, 0x2b, 0x44, 0x9e, 0x48, 0xf5, 0xcc, 0x6d, 0x48, 0xd4, +0xa0, 0x4b, 0x7f, 0xfe, 0x59, 0x24, 0x2f, 0x83, 0x97, 0x99, 0x9a, 0x86, 0xd9, 0xfe, 0x21, 0x40, +0x6e, 0x94, 0x9e, 0xbc, 0x9b, 0x3d, 0x9c, 0x7d, 0x98, 0x20, 0x19, 0xe5, 0x8c, 0x30, 0x62, 0xb2, +0xee, 0x6b, 0x49, 0x3c, 0x7a, 0x3f, 0x0d, 0xe3, 0xb1, 0x09, 0xb7, 0x8a, 0xc8, 0xab, 0x19, 0x9f, +0x73, 0x33, 0x50, 0xe7, 0xd9, 0x74, 0x3a, 0xe4, 0x30, 0x3d, 0x0d, 0xf7, 0x12, 0xdc, 0x7e, 0x5a, +0x05, 0x9f, 0x1e, 0x34, 0x9a, 0xf7, 0xe1, 0x14, 0x81, 0xc4, 0x8c, 0xcc, 0xf5, 0xe4, 0x30, 0xff, +0xa5, 0x0c, 0x08, 0x5f, 0x8c, 0x15, 0x67, 0x21, 0x74, 0x01, 0xdf, 0xdf, 0x5b, 0xca, 0x5e, 0xe5, +0xde, 0xd2, 0x81, 0xaa, 0xcd, 0xa8, 0x2d, 0x64, 0x51, 0xb6, 0xd9, 0x72, 0x9b, 0x97, 0xe6, 0x4f, +0x82, 0xd1, 0x85, 0x73, 0x30, 0xe7, 0x35, 0x04, 0xd3, 0x8e, 0x02, 0x92, 0xfb, 0xe5, 0xa4, 0xd1, +0xc4, 0x21, 0xe8, 0xcd, 0xdd, 0x04, 0x09, 0x07, 0xa2, 0xf5, 0x7a, 0x7d, 0x52, 0x53, 0x12, 0x92, +0x95, 0xee, 0x38, 0x80, 0x25, 0x0d, 0xa6, 0x59, 0xf7, 0x7d, 0xc5, 0xfd, 0xc4, 0xe8, 0x9a, 0x1b, +0x77, 0x64, 0xa7, 0xf5, 0x1d, 0xa0, 0xcc, 0xbf, 0x87, 0x60, 0x9a, 0x6d, 0xe3, 0xfe, 0x2d, 0xfd, +0x28, 0xd0, 0x0b, 0xb5, 0xba, 0xb6, 0xa2, 0xc4, 0xbf, 0x06, 0xaa, 0x05, 0x8c, 0x93, 0xfb, 0x2f, +0xcc, 0xfa, 0x67, 0x93, 0xf0, 0xb6, 0xb8, 0xd0, 0xa5, 0xc0, 0x1e, 0xf3, 0x53, 0xfd, 0x8c, 0x53, +0xdf, 0x83, 0xd7, 0x96, 0xc4, 0xa7, 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, +0x75, 0xff, 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x21, 0x30, 0xc9, 0xfb, 0x00, 0xd7, 0x4e, 0x98, +0xda, 0x87, 0xaa, 0x2a, 0xd0, 0xa7, 0x2e, 0xb1, 0x40, 0x31, 0xa7, 0x4c, 0xa3, 0x97, 0xd6, 0xf3, +0x5e, 0xa2, 0x10, 0xe1, 0xab, 0x45, 0x9f, 0x3c, 0x17, 0x64, 0x3c, 0xee, 0x01, 0x70, 0x9c, 0xcc, +0x1a, 0x84, 0x62, 0xbc, 0x48, 0x4c, 0x33, 0x25, 0x04, 0xd4, 0xee, 0xd0, 0xf6, 0x03, 0xc4, 0x19, +0x46, 0xd1, 0x94, 0x6b, 0xed, 0xe7, 0x6f, 0x76, 0x5a, 0xbf, 0x60, 0xec, 0x49, 0x5b, 0xc6, 0xa5, +0x77, 0xbb, 0x72, 0x16, 0x71, 0x9b, 0xc4, 0x3d, 0xf2, 0xc0, 0x13, 0xe0, 0x82, 0x43, 0x3e, 0xfb, +0xee, 0x2f, 0x67, 0x32, 0x96, 0x35, 0x5c, 0xdb, 0xb8, 0xcb, 0x02, 0xd0, 0xc6, 0x17, 0xd0, 0xbc, +0xa8, 0xea, 0x02, 0x43, 0xf2, 0x1b, 0x06, 0x99, 0x5d, 0x2b, 0x90, 0x20, 0xb9, 0xd7, 0x9c, 0xe4, +0x5b, 0xf8, 0x4d, 0x4f, 0xb2, 0xa5, 0x86, 0xd4, 0x3a, 0xd2, 0xf1, 0x63, 0x9a, 0xa0, 0xbe, 0x09, +0xf6, 0x57, 0xb7, 0xde, 0xa0, 0x73, 0x49, 0x99, 0x68, 0xdc, 0x85, 0x5b, 0x65, 0xe3, 0x9b, 0x28, +0x2f, 0x57, 0x9f, 0xbd, 0x33, 0xbc, 0x07, 0x48, 0x0a, 0x85, 0xa9, 0x77, 0x65, 0x05, 0x98, 0x7c, +0x40, 0x81, 0xf8, 0x0f, 0x97, 0x2c, 0x38, 0xf1, 0x0a, 0xec, 0x3c, 0xcf, 0xbb, 0xaf, 0x7e, 0x02, +0x3d, 0xfa, 0xa6, 0xf1, 0x3c, 0x84, 0x8e, 0xad, 0xee, 0x38, 0x98, 0xec, 0xd9, 0x32, 0x32, 0xd4, +0xbf, 0x5f, 0xb7, 0xd1, 0xce, 0xdd, 0x1f, 0x86, 0xf4, 0x5b, 0x55, 0xac, 0xdc, 0xd7, 0x10, 0xc2, +0x0e, 0xa9, 0x88, 0xe7, 0x7c, 0x0c, 0x32, 0x1f, 0xa7, 0xd9, 0x30, 0x7f, 0xc4, 0x7d, 0x68, 0xa3, +0x62, 0xa8, 0xa1, 0xce, 0xab, 0x07, 0x5b, 0x27, 0x9c, 0x5f, 0x00, 0xdf, 0xaa, 0x01, 0xd7, 0x30, +0x2b, 0x38, 0x88, 0xa2, 0xb8, 0x6d, 0x4a, 0x9c, 0xf2, 0x11, 0x91, 0x83, 0x53, 0x79, 0xbf, 0x5a, +0xaa, 0x2b, 0x4a, 0xcf, 0x54, 0x80, 0xe1, 0xd8, 0x9b, 0xc0, 0x9d, 0xf2, 0xb2, 0x03, 0x66, 0xcb, +0x3a, 0xe1, 0x09, 0x86, 0xd4, 0xcf, 0x19, 0xc2, 0x96, 0x76, 0x74, 0x49, 0x76, 0xdc, 0xe0, 0x35, +0xc6, 0x63, 0x63, 0x9a, 0x68, 0x90, 0xe4, 0x67, 0xa4, 0xa6, 0x53, 0x80, 0xc7, 0x86, 0x66, 0xa4, +0xf1, 0xf7, 0x4b, 0x43, 0xfb, 0x84, 0xbd, 0x6d, 0xa0, 0xc3, 0x8b, 0x44, 0xaa, 0x37, 0xa5, 0x45, +0xbf, 0x97, 0x80, 0x5a, 0xd1, 0xf1, 0x78, 0xa2, 0x9b, 0xe9, 0x5d, 0x8d, 0x55, 0xe4, 0x81, 0xd1, +0x11, 0x80, 0xbe, 0xd8, 0x89, 0xb9, 0x08, 0xa3, 0x31, 0xf9, 0xa1, 0x24, 0x09, 0x16, 0xb9, 0x70, +0xa0, 0x11, 0x0a, 0x23, 0x3e, 0x96, 0xf1, 0x07, 0xec, 0xe2, 0xaf, 0x29, 0xef, 0x82, 0xa5, 0x7f, +0xd0, 0x30, 0xa4, 0xb4, 0xd2, 0x87, 0xb4, 0xe3, 0xdf, 0x37, 0x27, 0x93, 0x55, 0xf6, 0x56, 0xea, +0x81, 0xe5, 0x36, 0xcc, 0x8c, 0x1e, 0x3f, 0xbd, 0x52, 0xd8, 0x88, 0x3a, 0xc8, 0x9f, 0x78, 0x66, +0xed, 0x89, 0xf3, 0x7b, 0x38, 0x70, 0x94, 0xc9, 0x02, 0x02, 0x36, 0xd0, 0x9d, 0x93, 0xc6, 0x53, +0x8b, 0x5e, 0xca, 0xaf, 0x3f, 0x9f, 0x1e, 0x0f, 0xe5, 0x99, 0x95, 0xbc, 0x24, 0xf6, 0x94, 0x8f, +0x1e, 0x0c, 0xf7, 0xb6, 0x67, 0xf2, 0xe1, 0x92, 0x26, 0x09, 0x45, 0xc0, 0x55, 0x39, 0x2e, 0x77, +0x3f, 0x42, 0x4a, 0xa2, 0x9d, 0xc0, 0x67, 0xa6, 0x0c, 0x22, 0xd9, 0x26, 0xf5, 0x45, 0xab, 0xa6, +0x65, 0x52, 0x11, 0x27, 0xd8, 0x45, 0xac, 0x63, 0x9a, 0xaf, 0x29, 0x7a, 0xc0, 0x11, 0x35, 0x35, +0x26, 0x51, 0x30, 0x00, 0xc3, 0x6a, 0xfe, 0x40, 0xd5, 0xae, 0xd6, 0x3c, 0x07, 0x1f, 0xd2, 0xe7, +0x9c, 0xda, 0xc2, 0x6e, 0xa2, 0x40, 0xb4, 0xb0, 0x7a, 0x50, 0x10, 0x50, 0x74, 0xc4, 0xc8, 0xbd, +0x65, 0xcd, 0xeb, 0xab, 0x35, 0x1e, 0x00, 0x3e, 0x7e, 0xd5, 0x74, 0xc0, 0x1c, 0xb4, 0x73, 0x47, +0x0e, 0x1a, 0x64, 0x2f, 0xe5, 0x9d, 0x59, 0x30, 0x82, 0x47, 0x58, 0xcc, 0xac, 0xfa, 0x08, 0x54, +0x36, 0x86, 0x7b, 0x3a, 0xb5, 0x04, 0x4d, 0xf0, 0xc9, 0x80, 0x77, 0xe0, 0x62, 0x92, 0x82, 0xf5, +0x46, 0x9c, 0xf3, 0xba, 0xf7, 0x4c, 0xc3, 0xde, 0xb8, 0xa3, 0xad, 0x39, 0xa7, 0xa5, 0x06, 0xb1, +0x2c, 0xa6, 0x09, 0x60, 0xee, 0xd1, 0x97, 0xe9, 0x70, 0xae, 0xbc, 0x3b, 0x19, 0x6c, 0xdb, 0x21, +0x47, 0xb8, 0xcd, 0xff, 0xe5, 0x6f, 0xee, 0xf8, 0xb2, 0xec, 0x2f, 0x4e, 0x0e, 0xf9, 0x25, 0xb0, +0x8e, 0x3c, 0x6b, 0xc3, 0xb5, 0x99, 0xf8, 0xaf, 0xb0, 0x94, 0xf5, 0xe3, 0x20, 0xd6, 0x0a, 0xad, +0xce, 0x4e, 0x56, 0xa4, 0x2e, 0x6e, 0x42, 0xed, 0x1a, 0xed, 0xfe, 0x41, 0x39, 0x90, 0xb4, 0x24, +0x59, 0xbe, 0x01, 0xf2, 0x52, 0xd5, 0x45, 0xf6, 0x5a, 0x39, 0xdc, 0x11, 0xf0, 0x8f, 0x59, 0x38, +0x00, 0xb3, 0xf5, 0x8f, 0x9a, 0x96, 0x0c, 0xd5, 0xeb, 0xfa, 0x7b, 0xaa, 0x17, 0xe8, 0x13, 0x12, +0xed, 0x44, 0x19, 0xc0, 0xd3, 0xf0, 0x06, 0x8b, 0xee, 0xa4, 0x7b, 0xbe, 0x42, 0xe7, 0x26, 0x54, +0xc8, 0x8e, 0x36, 0x76, 0xe3, 0x71, 0xe0, 0x9e, 0xd8, 0xa7, 0x42, 0xd9, 0xdb, 0x71, 0x91, 0x6b, +0x94, 0x93, 0xeb, 0xc3, 0xa3, 0xd1, 0x14, 0xa3, 0xfe, 0xab, 0x00, 0x90, 0x98, 0x9e, 0x24, 0xfc, +0xa9, 0xcc, 0x1a, 0x8a, 0xfb, 0x27, 0xb8, 0xbf, 0x30, 0x6e, 0xa8, 0x3b, 0x6a, 0x72, 0x26, 0x7a, +0xd0, 0x1e, 0xef, 0x7d, 0xe7, 0x3b, 0x69, 0x51, 0xd4, 0x6c, 0x8d, 0x9f, 0x90, 0x12, 0x66, 0xab, +0xb7, 0x63, 0xe7, 0x1a, 0xdd, 0x8d, 0xe9, 0x08, 0xa6, 0x55, 0x83, 0xa4, 0xe0, 0x6a, 0x50, 0x41, +0x65, 0x11, 0x42, 0x49, 0xe0, 0x8c, 0x9b, 0xdb, 0x25, 0x49, 0xb3, 0xf1, 0x7c, 0x86, 0xd6, 0xb2, +0x42, 0x87, 0x0b, 0xd0, 0x6b, 0xa0, 0xd9, 0xe4, 0x08, 0x76, 0xcd, 0xcb, 0x07, 0xff, 0x24, 0xf6, +0xc5, 0xcd, 0xed, 0xbb, 0x90, 0xbc, 0xe2, 0x84, 0x37, 0x46, 0x75, 0xf7, 0x0b, 0x58, 0xe5, 0x8b, +0xc6, 0x4c, 0x15, 0x37, 0xa4, 0x40, 0xa9, 0x30, 0xa9, 0x21, 0xbe, 0x47, 0x36, 0x5a, 0x56, 0xff, +0xb6, 0x08, 0x7b, 0x0d, 0x7a, 0xcc, 0xac, 0x20, 0x4c, 0x86, 0x56, 0x32, 0x5e, 0xcf, 0xab, 0x6e, +0x85, 0x2d, 0x70, 0x57, 0x75, 0x71, 0xa7, 0x19, 0x48, 0x19, 0xbc, 0x9d, 0x9d, 0xea, 0x41, 0x47, +0xdf, 0x94, 0xc4, 0x48, 0x77, 0x99, 0xd3, 0x79, 0x45, 0xeb, 0xa2, 0xaf, 0xf4, 0x92, 0xcb, 0x82, +0x31, 0x2d, 0x51, 0x8b, 0xa7, 0xa7, 0x21, 0x9d, 0xf3, 0x6d, 0xc8, 0x0f, 0xce, 0xc3, 0x4a, 0xb9, +0x99, 0x55, 0xf2, 0xb8, 0xdb, 0x60, 0xbf, 0xa9, 0x7e, 0xbd, 0x56, 0xb5, 0x97, 0x36, 0xa7, 0xd6, +0x03, 0xde, 0x50, 0x35, 0x56, 0xd1, 0x4c, 0xbb, 0x66, 0xf0, 0xa3, 0xe2, 0x1b, 0x1b, 0xc3, 0x97, +0xb2, 0x3d, 0xd1, 0x55, 0x4e, 0x22, 0x54, 0x20, 0x18, 0x95, 0xe6, 0xe3, 0x6e, 0xe6, 0x0f, 0xfa, +0xfa, 0xb9, 0x12, 0xed, 0x06, 0x17, 0x8f, 0x39, 0xb3, 0xdb, 0x48, 0xa4, 0xf9, 0xa1, 0xc5, 0xd8, +0xae, 0x36, 0x41, 0xcc, 0x11, 0x63, 0x69, 0x62, 0x29, 0xbc, 0x4b, 0xc6, 0xb1, 0x3e, 0xc3, 0x69, +0x03, 0xf8, 0xbf, 0x47, 0x01, 0xd4, 0x98, 0x26, 0x1a, 0x08, 0x02, 0xef, 0x63, 0x64, 0x2b, 0xc3, +0xec, 0xd7, 0xe3, 0x82, 0xd2, 0x71, 0x5d, 0x64, 0x4c, 0xdf, 0x2e, 0x67, 0x3f, 0xe7, 0xba, 0x98, +0xae, 0x1c, 0x0f, 0x4f, 0xcb, 0xd0, 0xbd, 0xa9, 0xe1, 0x98, 0x05, 0x51, 0xa1, 0x4d, 0x37, 0xa2, +0x83, 0x79, 0xce, 0x8d, 0x1d, 0x2a, 0xe4, 0x84, 0xd2, 0xc4, 0xb0, 0xd2, 0x91, 0xd4, 0x4c, 0x11, +0x71, 0xb3, 0x61, 0xcb, 0x3d, 0xa1, 0xfe, 0xdd, 0xa8, 0x6a, 0xd4, 0xe3, 0x3a, 0x9a, 0x85, 0x07, +0x10, 0x67, 0x28, 0xb6, 0xef, 0xf6, 0xbd, 0x05, 0x41, 0x6e, 0x20, 0xc1, 0x94, 0xda, 0x0f, 0xde, +0xa6, 0x91, 0x42, 0xfd, 0x13, 0x61, 0x4a, 0x23, 0x9e, 0x08, 0xa4, 0x29, 0xe5, 0xd8, 0x13, 0x04, +0x23, 0xee, 0x41, 0x25, 0x1d, 0x1c, 0x65, 0x0e, 0xa8, 0xf2, 0x25, 0x7b, 0xb4, 0x91, 0xcf, 0xe4, +0xb1, 0xb1, 0xe6, 0xbd, 0x55, 0x74, 0x6c, 0x05, 0xbf, 0x59, 0x20, 0x36, 0x00, 0x79, 0xa0, 0xa0, +0x22, 0x6b, 0x8c, 0xd5, 0xf2, 0x61, 0xd2, 0xb8, 0x2c, 0xcb, 0x82, 0x4a, 0xb5, 0x03, 0xf7, 0x76, +0x3b, 0x61, 0x82, 0x6a, 0x12, 0xaa, 0x18, 0x53, 0xeb, 0x03, 0x21, 0x94, 0xbf, 0xfe, 0xce, 0xca, +0x6a, 0x38, 0x5b, 0x26, 0x8d, 0xde, 0x8b, 0x5a, 0xf2, 0x4f, 0x7a, 0x54, 0x83, 0x19, 0x18, 0xe3, +0x08, 0x35, 0xa6, 0xba, 0xd2, 0x9f, 0x88, 0xdf, 0xa1, 0xcd, 0x2c, 0xbd, 0xec, 0xf5, 0x3b, 0x01, +0x01, 0x93, 0x33, 0x27, 0xb2, 0xeb, 0x60, 0x4b, 0xbb, 0xff, 0xca, 0x8e, 0x23, 0x9f, 0x4f, 0x99, +0xca, 0xdb, 0xe2, 0x68, 0xa6, 0xa5, 0x15, 0x27, 0x17, 0x1e, 0xd9, 0x0e, 0xc1, 0xf1, 0x26, 0xba, +0xa0, 0x2d, 0xae, 0x85, 0x81, 0xcf, 0xd3, 0xf1, 0x2a, 0x12, 0xbd, 0xb8, 0x0a, 0x67, 0xfd, 0xbc, +0x80, 0x4c, 0xd6, 0xeb, 0x74, 0xff, 0x49, 0x36, 0xa3, 0xd5, 0xd8, 0xfc, 0xb5, 0x3e, 0xc5, 0x6a, +0xf0, 0x94, 0x1d, 0x8c, 0xe4, 0xaf, 0x2b, 0x26, 0x71, 0x1a, 0x2b, 0x48, 0x27, 0x85, 0x2f, 0x52, +0x66, 0x2c, 0xef, 0xf0, 0x89, 0x13, 0x71, 0x3e, 0x03, 0x5c, 0xab, 0x73, 0x81, 0x87, 0xa8, 0xcc, +0xb0, 0xa6, 0xd5, 0x94, 0xe2, 0x36, 0x96, 0x49, 0xff, 0x05, 0x99, 0x2c, 0x31, 0x0a, 0x90, 0x8f, +0xb6, 0xc6, 0x9d, 0xd2, 0x44, 0x4b, 0x80, 0xb5, 0xa2, 0xe6, 0x1f, 0xb1, 0x12, 0x4f, 0x1b, 0x95, +0x9b, 0xe2, 0x07, 0x57, 0x67, 0x1c, 0x1e, 0xc0, 0x6a, 0x06, 0xde, 0x59, 0xb4, 0x9a, 0x2d, 0xdf, +0xdc, 0x19, 0x86, 0x2e, 0x8f, 0xf0, 0x4b, 0x7f, 0xa8, 0x2e, 0x45, 0x24, 0xae, 0x4d, 0x50, 0xfa, +0x63, 0x9a, 0x8b, 0xde, 0xe2, 0xdd, 0x1b, 0xbc, 0x60, 0x7b, 0x66, 0x1a, 0x45, 0x0d, 0x97, 0xca, +0x89, 0x50, 0x2f, 0x7d, 0x04, 0xcd, 0x34, 0xa8, 0xff, 0xfc, 0xfd, 0x4b, 0x3d, 0xe6, 0x29, 0x48, +0x9b, 0xea, 0x07, 0xca, 0x21, 0x44, 0x4a, 0x26, 0xde, 0x6e, 0xde, 0xd2, 0x83, 0xd0, 0x9f, 0x59, +0xae, 0x6c, 0x05, 0xa3, 0x93, 0x13, 0xe2, 0xa2, 0xe7, 0xe2, 0xd7, 0x1c, 0xd6, 0xc7, 0xf0, 0x7f, +0xc8, 0x67, 0x53, 0xa0, 0xcb, 0x0f, 0xc6, 0xdf, 0x42, 0x43, 0xcc, 0x3d, 0xcb, 0xb5, 0x48, 0x23, +0xa1, 0x1a, 0x7a, 0xa6, 0x2a, 0xbb, 0x34, 0x68, 0xaf, 0x44, 0x04, 0xc2, 0x41, 0x7e, 0x48, 0x83, +0xdb, 0x4e, 0x39, 0x02, 0xec, 0xec, 0x84, 0x7a, 0xe6, 0xce, 0xc9, 0xa4, 0x42, 0x32, 0xb6, 0x16, +0xfa, 0x04, 0xfd, 0xfe, 0x5d, 0x4b, 0x7a, 0xc3, 0xfd, 0xf7, 0x4c, 0x40, 0x1d, 0x5a, 0x43, 0xaf, +0x5b, 0x25, 0x7b, 0x96, 0xa4, 0x65, 0x51, 0x7e, 0xb8, 0x39, 0xf3, 0xc0, 0x78, 0x66, 0x5e, 0xe8, +0x3a, 0xe7, 0xf0, 0xee, 0x87, 0x11, 0x15, 0x08, 0xd1, 0xaa, 0xc1, 0x78, 0x0c, 0xb1, 0xaf, 0xce, +0xc6, 0xc9, 0x90, 0xef, 0xbf, 0x30, 0x04, 0xc0, 0xa3, 0x41, 0x06, 0xac, 0x90, 0x6d, 0xd1, 0x4a, +0xeb, 0x75, 0xa5, 0x4a, 0x10, 0x99, 0xb3, 0xb1, 0xa1, 0x8b, 0x4a, 0xf7, 0x99, 0xe0, 0x19, 0x67, +0x0d, 0x62, 0xdb, 0x76, 0xb3, 0xda, 0x3d, 0xb8, 0x5b, 0xe8, 0xfd, 0x42, 0xd2, 0x31, 0x0e, 0x87, +0x55, 0xa9, 0x84, 0x89, 0xd2, 0xc1, 0x32, 0xbd, 0x18, 0xcb, 0x6c, 0xa6, 0x07, 0x4e, 0xc8, 0xe7, +0x9d, 0xbe, 0x82, 0x90, 0xfd, 0xda, 0x14, 0xc4, 0x9f, 0x30, 0xde, 0x21, 0xbd, 0x1e, 0x42, 0x39, +0xfc, 0xab, 0x63, 0x23, 0x49, 0xe0, 0xf1, 0x84, 0xd3, 0x94, 0x8a, 0x4c, 0x62, 0x13, 0x2a, 0x19, +0x2e, 0xcc, 0xaf, 0x72, 0x8a, 0x7d, 0x36, 0xd7, 0x9a, 0x1c, 0xdc, 0x67, 0x2e, 0xe3, 0xdb, 0xb2, +0x49, 0xd0, 0x9c, 0x54, 0x79, 0x5c, 0xfa, 0x27, 0x2a, 0xfe, 0xcc, 0x4e, 0xd2, 0xe8, 0x4e, 0x54, +0x17, 0xa0, 0xcd, 0xc1, 0xe4, 0x41, 0xb6, 0x3a, 0x5b, 0x3b, 0xcb, 0x45, 0x9d, 0xbd, 0x1c, 0xc2, +0x98, 0xfa, 0x86, 0x58, 0xc6, 0x4f, 0xa2, 0x3d, 0x06, 0x63, 0x84, 0x09, 0x9c, 0xce, 0x62, 0xe4, +0x04, 0xac, 0x8d, 0x5c, 0xb5, 0xe9, 0xb6, 0x1b, 0x54, 0xb0, 0x7b, 0xad, 0x45, 0xb8, 0xe2, 0x40, +0x7f, 0xfb, 0x0a, 0x6e, 0xfb, 0xbe, 0x33, 0xc9, 0x3c, 0xa3, 0x84, 0xd5, 0x9f, 0x38, 0xc4, 0x56, +0x23, 0xc3, 0x39, 0xe8, 0xa0, 0x71, 0x6c, 0xe8, 0x54, 0x4c, 0xe4, 0xe8, 0x3a, 0xb1, 0xbf, 0x67, +0xfb, 0xef, 0x0d, 0x86, 0x9e, 0xb0, 0xe3, 0xdd, 0xa9, 0xb9, 0xf1, 0x21, 0x17, 0x7f, 0x3e, 0xfc, +0xf0, 0x77, 0x2b, 0x1a, 0x7c, 0x5d, 0x02, 0x84, 0x13, 0xd4, 0xcc, 0x8a, 0x9b, 0x81, 0xce, 0x17, +0x1c, 0x2e, 0x29, 0x1e, 0x9c, 0x48, 0x63, 0x42, 0xfe, 0xa1, 0xe0, 0x70, 0x1e, 0x2a, 0x03, 0x39, +0x52, 0x5a, 0x42, 0xbe, 0x5c, 0x91, 0x85, 0x7a, 0x18, 0xaa, 0x4d, 0xb5, 0xfb, 0x5a, 0x48, 0xd0, +0x80, 0x20, 0x40, 0xf2, 0xa8, 0xe9, 0x00, 0x07, 0x69, 0x19, 0x77, 0xa7, 0xe6, 0xc3, 0xf4, 0xcf, diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/warmcat.com.cer new file mode 100644 index 00000000..01ad0dc7 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-jit-trust/warmcat.com.cer @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +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= +-----END CERTIFICATE----- + diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt index 9122a9e4..22d138cc 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt @@ -13,6 +13,7 @@ set(MBEDTLS 0) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) require_lws_config(LWS_WITH_TLS 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) require_lws_config(LWS_WITH_MBEDTLS 1 MBEDTLS) @@ -119,17 +120,17 @@ endif() add_test(NAME http-client-multi-h1 COMMAND lws-minimal-http-client-multi --h1 -l --port ${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-pipe COMMAND lws-minimal-http-client-multi - -p -l --port ${PORT_HCM_SRV}) + -p -l --port ${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-h1-pipe COMMAND lws-minimal-http-client-multi - --h1 -p -l --port ${PORT_HCM_SRV}) + --h1 -p -l --port ${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-stag COMMAND lws-minimal-http-client-multi - -s -l --port ${PORT_HCM_SRV}) + -s -l --port ${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-stag-h1 COMMAND lws-minimal-http-client-multi - --h1 -s -l --port ${PORT_HCM_SRV}) + --h1 -s -l --port ${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-stag-pipe COMMAND lws-minimal-http-client-multi - -p -s -l --port ${PORT_HCM_SRV}) + -p -s -l --port ${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-stag-h1-pipe COMMAND lws-minimal-http-client-multi - --h1 -p -s -l --port ${PORT_HCM_SRV}) + --h1 -p -s -l --port ${PORT_HCM_SRV} -d1151) # 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}) @@ -137,9 +138,9 @@ endif() 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}) + add_test(NAME http-client-multi-restrict-nopipe-fail COMMAND lws-minimal-http-client-multi --limit 1 -l --port ${PORT_HCM_SRV} -d1151) 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}) + add_test(NAME http-client-multi-restrict-h1-nopipe-fail COMMAND lws-minimal-http-client-multi --limit 1 --h1 -l --port ${PORT_HCM_SRV} -d1151) set_property(TEST http-client-multi-restrict-h1-nopipe-fail PROPERTY WILL_FAIL TRUE) set_tests_properties(http-client-multi-restrict-pipe @@ -163,21 +164,26 @@ endif() # 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}) + --post -l --port 1${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-post-h1 COMMAND lws-minimal-http-client-multi - --post --h1 -l --port 1${PORT_HCM_SRV}) + --post --h1 -l --port 1${PORT_HCM_SRV} -d1151) 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}) + --post -p -l --port 1${PORT_HCM_SRV} -d1151) + if (VALGRIND) + add_test(NAME http-client-multi-post-h1-pipe COMMAND ${VALGRIND} --tool=memcheck $ + --post --h1 -p -l --port 1${PORT_HCM_SRV} -d1151) + else() + add_test(NAME http-client-multi-post-h1-pipe COMMAND lws-minimal-http-client-multi + --post --h1 -p -l --port 1${PORT_HCM_SRV} -d1151) + endif() add_test(NAME http-client-multi-post-stag COMMAND lws-minimal-http-client-multi - --post -s -l -d1151 --port 1${PORT_HCM_SRV}) + --post -s -l -d1151 --port 1${PORT_HCM_SRV} -d1151) 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}) + --post --h1 -d1151 -s -l --port 1${PORT_HCM_SRV} -d1151) add_test(NAME http-client-multi-post-stag-pipe COMMAND lws-minimal-http-client-multi - --post -p -s -l --port 1${PORT_HCM_SRV}) + --post -p -s -l --port 1${PORT_HCM_SRV} -d1151) 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}) + --post --h1 -p -s -l --port 1${PORT_HCM_SRV} -d1151) set_tests_properties(http-client-multi-post http-client-multi-post-h1 http-client-multi-post-pipe diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c index f2a247fb..f30ee589 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c @@ -52,7 +52,10 @@ struct cliuser { }; static int completed, failed, numbered, stagger_idx, posting, count = COUNT, - reuse; +#if defined(LWS_WITH_TLS_SESSIONS) + reuse, +#endif + staggered; static lws_sorted_usec_list_t sul_stagger; static struct lws_client_connect_info i; static struct lws *client_wsi[COUNT]; @@ -164,19 +167,19 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; int n, idx = (int)(intptr_t)lws_get_opaque_user_data(wsi); struct pss *pss = (struct pss *)user; switch (reason) { case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - lwsl_user("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: idx: %d, resp %u: tls-session-reuse: %d\n", - idx, lws_http_client_http_response(wsi), lws_tls_session_is_reused(wsi)); + lwsl_user("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: idx: %d, resp %u\n", + idx, lws_http_client_http_response(wsi)); +#if defined(LWS_WITH_TLS_SESSIONS) && !defined(LWS_WITH_MBEDTLS) && !defined(WIN32) if (lws_tls_session_is_reused(wsi)) reuse++; -#if defined(LWS_WITH_TLS_SESSIONS) && !defined(LWS_WITH_MBEDTLS) && !defined(WIN32) else /* * Attempt to store any new session into @@ -344,8 +347,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, } static const struct lws_protocols protocols[] = { - { "http", callback_http, sizeof(struct pss), 0, }, - { NULL, NULL, 0, 0 } + { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; #if defined(LWS_WITH_SYS_METRICS) @@ -372,6 +375,65 @@ static const lws_system_ops_t system_ops = { #endif +static void +stagger_cb(lws_sorted_usec_list_t *sul); + +static void +lws_try_client_connection(struct lws_client_connect_info *i, int m) +{ + char path[128]; + + if (numbered) { + lws_snprintf(path, sizeof(path), "/%d.png", m + 1); + i->path = path; + } else + i->path = urlpath; + + i->pwsi = &client_wsi[m]; + i->opaque_user_data = (void *)(intptr_t)m; + + if (!lws_client_connect_via_info(i)) { + failed++; + lwsl_user("%s: failed: conn idx %d\n", __func__, m); + if (++completed == count) { + lwsl_user("Done: failed: %d\n", failed); + lws_context_destroy(context); + } + } else + lwsl_user("started connection %s: idx %d (%s)\n", + lws_wsi_tag(client_wsi[m]), m, i->path); +} + + +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; + int m; + + if (current != LWS_SYSTATE_OPERATIONAL || target != LWS_SYSTATE_OPERATIONAL) + return 0; + + /* all the system prerequisites are ready */ + + if (!staggered) + /* + * just pile on all the connections at once, testing the + * pipeline queuing before the first is connected + */ + for (m = 0; m < count; m++) + lws_try_client_connection(&i, m); + else + /* + * delay the connections slightly + */ + lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, + 50 * LWS_US_PER_MS); + + return 0; +} + static void signal_cb(void *handle, int signum) { @@ -424,32 +486,6 @@ unsigned long long us(void) return ((unsigned long long)t.tv_sec * 1000000ull) + (unsigned long long)t.tv_usec; } -static void -lws_try_client_connection(struct lws_client_connect_info *i, int m) -{ - char path[128]; - - if (numbered) { - lws_snprintf(path, sizeof(path), "/%d.png", m + 1); - i->path = path; - } else - i->path = urlpath; - - i->pwsi = &client_wsi[m]; - i->opaque_user_data = (void *)(intptr_t)m; - - if (!lws_client_connect_via_info(i)) { - failed++; - lwsl_user("%s: failed: conn idx %d\n", __func__, m); - if (++completed == count) { - lwsl_user("Done: failed: %d\n", failed); - lws_context_destroy(context); - } - } else - lwsl_user("started connection %s: idx %d (%s)\n", - lws_wsi_tag(client_wsi[m]), m, i->path); -} - static void stagger_cb(lws_sorted_usec_list_t *sul) { @@ -479,14 +515,15 @@ stagger_cb(lws_sorted_usec_list_t *sul) int main(int argc, const char **argv) { + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; struct lws_context_creation_info info; - int m, staggered = 0 -#if defined(LWS_WITH_TLS_SESSIONS) - , pl = 0 -#endif - ; unsigned long long start; const char *p; +#if defined(LWS_WITH_TLS_SESSIONS) + int pl = 0; +#endif memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ @@ -526,6 +563,7 @@ int main(int argc, const char **argv) * network wsi) that we will use. */ info.fd_limit_per_thread = 1 + COUNT + 1; + info.register_notifier_list = na; info.pcontext = &context; #if defined(LWS_WITH_SYS_METRICS) @@ -548,6 +586,12 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "--limit"))) info.simultaneous_ssl_restriction = atoi(p); + if ((p = lws_cmdline_option(argc, argv, "--ssl-handshake-serialize"))) + /* We only consider simultaneous_ssl_restriction > 1 use cases. + * If ssl isn't limited or only 1 is allowed, we don't care. + */ + info.simultaneous_ssl_handshake_restriction = atoi(p); + context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); @@ -638,20 +682,6 @@ int main(int argc, const char **argv) lwsl_warn("%s: session load failed\n", __func__); #endif - if (!staggered) - /* - * just pile on all the connections at once, testing the - * pipeline queuing before the first is connected - */ - for (m = 0; m < count; m++) - lws_try_client_connection(&i, m); - else - /* - * delay the connections slightly - */ - lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, - 50 * LWS_US_PER_MS); - start = us(); while (!intr && !lws_service(context, 0)) ; diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c index 2cd5d3d2..063f8f1c 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c @@ -30,7 +30,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, { struct pss *pss = (struct pss *)user; char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; int n; switch (reason) { @@ -173,9 +173,9 @@ static const struct lws_protocols protocols[] = { "http", callback_http, sizeof(struct pss), - 0, + 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/CMakeLists.txt index eeb26a90..8c42ae9f 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/CMakeLists.txt @@ -14,6 +14,7 @@ set(has_plugins 1) set(has_ss_policy_parse 1) set(has_no_system_vhost 1) set(has_async_dns 1) +set(has_mbedtls 1) set(requirements 1) @@ -34,6 +35,7 @@ require_lws_config(LWS_WITH_SYS_NTPCLIENT 0 has_no_system_vhost) require_lws_config(LWS_WITH_SYS_DHCP_CLIENT 0 has_no_system_vhost) require_lws_config(LWS_WITH_SYS_ASYNC_DNS 1 has_async_dns) +require_lws_config(LWS_WITH_MBEDTLS 1 has_mbedtls) if (requirements) add_executable(${SAMP} ${SRCS}) @@ -51,9 +53,6 @@ if (requirements) add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --h1) - set_tests_properties(${mytests} PROPERTIES - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client - TIMEOUT 20) if (has_fault_injection) @@ -127,7 +126,7 @@ if (requirements) if (has_async_dns) list(APPEND mytests http-client-fi-connfail) - add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi=user/connfail") + add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 2 --fault-injection "wsi=user/connfail") else() list(APPEND mytests http-client-fi-connfail) add_test(NAME http-client-fi-connfail COMMAND lws-minimal-http-client --expected-exit 2 --fault-injection "wsi=user/connfail") @@ -135,10 +134,19 @@ if (requirements) list(APPEND mytests http-client-fi-user-est-fail) add_test(NAME http-client-fi-user-est-fail COMMAND lws-minimal-http-client --expected-exit 3 --fault-injection "wsi/user_reject_at_est") - endif() - + if (has_mbedtls) + list(APPEND mytests http-client-mbedtls-wrong-ca) + add_test(NAME http-client-mbedtls-wrong-ca COMMAND lws-minimal-http-client -w --expected-exit 3) + message("... adding mbedtls wrong CA test") + else() + message("... skipping mbedtls wrong CA test") + endif() + + set_tests_properties(${mytests} PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client + TIMEOUT 20) if (DEFINED ENV{SAI_OVN}) set_tests_properties(${mytests} PROPERTIES diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/README.md b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/README.md index 9387f8c7..09df8ef0 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/README.md +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/README.md @@ -21,6 +21,9 @@ Commandline option|Meaning -j|Apply tls option LCCSCF_ALLOW_SELFSIGNED -m|Apply tls option LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK -e|Apply tls option LCCSCF_ALLOW_EXPIRED +-b|Apply tls option LCCSCF_CACHE_COOKIES +-w|For mbedtls/wolfssl, load wrong CA cert (expected to fail) +-c |Set filepath used for cookie jar -v|Connection validity use 3s / 10s instead of default 5m / 5m10s --nossl| disable ssl connection --user | Set Basic Auth username diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/minimal-http-client.c b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/minimal-http-client.c index 01243e5a..f151356f 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/minimal-http-client.c +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/minimal-http-client.c @@ -1,7 +1,7 @@ /* * lws-minimal-http-client * - * Written in 2010-2019 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -62,6 +62,11 @@ dump_conmon_data(struct lws *wsi) } #endif +static const char *ua = "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/51.0.2704.103 Safari/537.36", + *acc = "*/*"; + static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -104,12 +109,20 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, break; -#if defined(LWS_WITH_HTTP_BASIC_AUTH) - /* you only need this if you need to do Basic Auth */ case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: { unsigned char **p = (unsigned char **)in, *end = (*p) + len; + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_USER_AGENT, + (unsigned char *)ua, (int)strlen(ua), p, end)) + return -1; + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ACCEPT, + (unsigned char *)acc, (int)strlen(acc), p, end)) + return -1; +#if defined(LWS_WITH_HTTP_BASIC_AUTH) + { char b[128]; if (!ba_user || !ba_password) @@ -120,10 +133,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_AUTHORIZATION, (unsigned char *)b, (int)strlen(b), p, end)) return -1; - + } +#endif break; } -#endif /* chunks of chunked content, with header removed */ case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: @@ -186,10 +199,9 @@ static const struct lws_protocols protocols[] = { { "http", callback_http, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void @@ -243,9 +255,10 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, i.ssl_connection = 0; i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | + LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS | LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; - i.alpn = "h2"; + i.alpn = "h2,http/1.1"; if (lws_cmdline_option(a->argc, a->argv, "--h1")) i.alpn = "http/1.1"; @@ -266,6 +279,9 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, if (lws_cmdline_option(a->argc, a->argv, "-k")) i.ssl_connection |= LCCSCF_ALLOW_INSECURE; + if (lws_cmdline_option(a->argc, a->argv, "-b")) + i.ssl_connection |= LCCSCF_CACHE_COOKIES; + if (lws_cmdline_option(a->argc, a->argv, "-m")) i.ssl_connection |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; @@ -321,7 +337,8 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, int main(int argc, const char **argv) { - lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; lws_state_notify_link_t *na[] = { ¬ifier, NULL }; struct lws_context_creation_info info; struct lws_context *context; @@ -348,6 +365,12 @@ int main(int argc, const char **argv) info.register_notifier_list = na; info.connect_timeout_secs = 30; +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) + info.http_nsc_filepath = "./cookies.txt"; + if ((p = lws_cmdline_option(argc, argv, "-c"))) + info.http_nsc_filepath = p; +#endif + /* * 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 @@ -362,7 +385,11 @@ int main(int argc, const char **argv) * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. */ - info.client_ssl_ca_filepath = "./warmcat.com.cer"; + if (lws_cmdline_option(argc, argv, "-w")) + /* option to confirm we are validating against the right cert */ + info.client_ssl_ca_filepath = "./wrong.cer"; + else + info.client_ssl_ca_filepath = "./warmcat.com.cer"; #endif #if 0 n = open("./warmcat.com.cer", O_RDONLY); diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/wrong.cer b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/wrong.cer new file mode 100644 index 00000000..35035667 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-client/minimal-http-client/wrong.cer @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c index 06f500d5..4ffe32c1 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c @@ -37,7 +37,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; struct pss *pss = (struct pss *)user; char value[32], *pr = &pss->result[LWS_PRE]; size_t e = sizeof(pss->result) - LWS_PRE; @@ -105,8 +105,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "http", callback_http, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static const struct lws_http_mount mount_dyn = { diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c index 3a9db09d..97902acf 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c @@ -23,7 +23,7 @@ static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_DEADDROP, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c index 7ead9fe8..daade23b 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c @@ -42,7 +42,7 @@ callback_dynamic_http(struct lws *wsi, enum lws_callback_reasons reason, { struct pss *pss = (struct pss *)user; uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; time_t t; int n; #if defined(LWS_HAVE_CTIME_R) @@ -216,8 +216,8 @@ callback_dynamic_http(struct lws *wsi, enum lws_callback_reasons reason, } static const struct lws_protocols defprot = - { "defprot", lws_callback_http_dummy, 0, 0 }, protocol = - { "http", callback_dynamic_http, sizeof(struct pss), 0 }; + { "defprot", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, protocol = + { "http", callback_dynamic_http, sizeof(struct pss), 0, 0, NULL, 0 }; static const struct lws_protocols *pprotocols[] = { &defprot, &protocol, NULL }; diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/CMakeLists.txt new file mode 100644 index 00000000..5f023f96 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/CMakeLists.txt @@ -0,0 +1,28 @@ +project(lws-minimal-http-server-eventlib-custom C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-http-server-eventlib-custom) +set(SRCS minimal-http-server.c) + +if (WIN32) +else() + set(requirements 1) + require_lws_config(LWS_ROLE_H1 1 requirements) + require_lws_config(LWS_WITH_SERVER 1 requirements) + require_lws_config(LWS_WITH_CLIENT 1 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() +endif() diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/README.md b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/README.md new file mode 100644 index 00000000..cc8794b8 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/README.md @@ -0,0 +1,18 @@ +# lws minimal http server + +## build + +``` + $ cmake . && make +``` + +## usage + +``` + $ ./lws-minimal-http-server +[2018/03/04 09:30:02:7986] USER: LWS minimal http server | visit http://localhost:7681 +[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on +``` + +Visit http://localhost:7681 + diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c new file mode 100644 index 00000000..e969fea2 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c @@ -0,0 +1,464 @@ +/* + * lws-minimal-http-server-eventlib-custom + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates a minimal http server using lws, on top of a custom "event + * library" that uses an existing application POLL loop. + * + * To keep it simple, it serves stuff from the subdirectory "./mount-origin" of + * the dir it was started in. Change mount.origin to serve from elsewhere. + */ + +#include +#include +#include + +static int interrupted; +static struct lws_context *context; + +#define MAX_CUSTOM_POLLFDS 64 + +/* this represents the existing application poll loop context we want lws + * to cooperate with */ + +typedef struct custom_poll_ctx { + struct lws_pollfd pollfds[MAX_CUSTOM_POLLFDS]; + int count_pollfds; +} custom_poll_ctx_t; + +/* for this example we just have the one, but it is passed into lws as a + * foreign loop pointer, and all callbacks have access to it via that, so it + * is not needed to be defined at file scope. */ +static custom_poll_ctx_t a_cpcx; + +/* + * These are the custom event loop operators that just make the custom event + * loop able to work by itself. These would already exist in some form in an + * existing application. + */ + +static struct lws_pollfd * +custom_poll_find_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd) +{ + int n; + + for (n = 0; n < cpcx->count_pollfds; n++) + if (cpcx->pollfds[n].fd == fd) + return &cpcx->pollfds[n]; + + return NULL; +} + +static int +custom_poll_add_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd, int events) +{ + struct lws_pollfd *pfd; + + lwsl_info("%s: ADD fd %d, ev %d\n", __func__, fd, events); + + pfd = custom_poll_find_fd(cpcx, fd); + if (pfd) { + lwsl_err("%s: ADD fd %d already in ext table\n", __func__, fd); + return 1; + } + + if (cpcx->count_pollfds == LWS_ARRAY_SIZE(cpcx->pollfds)) { + lwsl_err("%s: no room left\n", __func__); + return 1; + } + + pfd = &cpcx->pollfds[cpcx->count_pollfds++]; + pfd->fd = fd; + pfd->events = (short)events; + pfd->revents = 0; + + return 0; +} + +static int +custom_poll_del_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd) +{ + struct lws_pollfd *pfd; + + lwsl_info("%s: DEL fd %d\n", __func__, fd); + + pfd = custom_poll_find_fd(cpcx, fd); + if (!pfd) { + lwsl_err("%s: DEL fd %d missing in ext table\n", __func__, fd); + return 1; + } + + if (cpcx->count_pollfds > 1) + *pfd = cpcx->pollfds[cpcx->count_pollfds - 1]; + + cpcx->count_pollfds--; + + return 0; +} + +static int +custom_poll_change_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd, + int events_add, int events_remove) +{ + struct lws_pollfd *pfd; + + lwsl_info("%s: CHG fd %d, ev_add %d, ev_rem %d\n", __func__, fd, + events_add, events_remove); + + pfd = custom_poll_find_fd(cpcx, fd); + if (!pfd) + return 1; + + pfd->events = (short)((pfd->events & (~events_remove)) | events_add); + + return 0; +} + +int +custom_poll_run(custom_poll_ctx_t *cpcx) +{ + int n; + + while (!interrupted) { + + /* + * Notice that the existing loop must consult with lws about + * the maximum wait timeout to use. Lws will reduce the + * timeout to the earliest scheduled event time if any earlier + * than the provided timeout. + */ + + n = lws_service_adjust_timeout(context, 5000, 0); + + lwsl_debug("%s: entering poll wait %dms\n", __func__, n); + + n = poll(cpcx->pollfds, (nfds_t)cpcx->count_pollfds, n); + + lwsl_debug("%s: exiting poll ret %d\n", __func__, n); + + if (n <= 0) + continue; + + for (n = 0; n < cpcx->count_pollfds; n++) { + lws_sockfd_type fd = cpcx->pollfds[n].fd; + int m; + + if (!cpcx->pollfds[n].revents) + continue; + + m = lws_service_fd(context, &cpcx->pollfds[n]); + + /* if something closed, retry this slot since may have been + * swapped with end fd */ + if (m && cpcx->pollfds[n].fd != fd) + n--; + + if (m < 0) + /* lws feels something bad happened, but + * the outer application may not care */ + continue; + if (!m) { + /* check if it is an fd owned by the + * application */ + } + } + } + + return 0; +} + + +/* + * These is the custom "event library" interface layer between lws event lib + * support and the custom loop implementation above. We only need to support + * a few key apis. + * + * We are user code, so all the internal lws objects are opaque. But there are + * enough public helpers to get everything done. + */ + +/* one of these is appended to each pt for our use */ +struct pt_eventlibs_custom { + custom_poll_ctx_t *io_loop; +}; + +/* + * During lws context creation, we get called with the foreign loop pointer + * that was passed in the creation info struct. Stash it in our private part + * of the pt, so we can reference it in the other callbacks subsequently. + */ + +static int +init_pt_custom(struct lws_context *cx, void *_loop, int tsi) +{ + struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) + lws_evlib_tsi_to_evlib_pt(cx, tsi); + + /* store the loop we are bound to in our private part of the pt */ + + priv->io_loop = (custom_poll_ctx_t *)_loop; + + return 0; +} + +static int +sock_accept_custom(struct lws *wsi) +{ + struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) + lws_evlib_wsi_to_evlib_pt(wsi); + + return custom_poll_add_fd(priv->io_loop, lws_get_socket_fd(wsi), POLLIN); +} + +static void +io_custom(struct lws *wsi, unsigned int flags) +{ + struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) + lws_evlib_wsi_to_evlib_pt(wsi); + int e_add = 0, e_remove = 0; + + if (flags & LWS_EV_START) { + if (flags & LWS_EV_WRITE) + e_add |= POLLOUT; + + if (flags & LWS_EV_READ) + e_add |= POLLIN; + } else { + if (flags & LWS_EV_WRITE) + e_remove |= POLLOUT; + + if (flags & LWS_EV_READ) + e_remove |= POLLIN; + } + + custom_poll_change_fd(priv->io_loop, lws_get_socket_fd(wsi), + e_add, e_remove); +} + +static int +wsi_logical_close_custom(struct lws *wsi) +{ + struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) + lws_evlib_wsi_to_evlib_pt(wsi); + return custom_poll_del_fd(priv->io_loop, lws_get_socket_fd(wsi)); +} + +static const struct lws_event_loop_ops event_loop_ops_custom = { + .name = "custom", + + .init_pt = init_pt_custom, + .init_vhost_listen_wsi = sock_accept_custom, + .sock_accept = sock_accept_custom, + .io = io_custom, + .wsi_logical_close = wsi_logical_close_custom, + + .evlib_size_pt = sizeof(struct pt_eventlibs_custom) +}; + +static const lws_plugin_evlib_t evlib_custom = { + .hdr = { + "custom event loop", + "lws_evlib_plugin", + LWS_BUILD_HASH, + LWS_PLUGIN_API_MAGIC + }, + + .ops = &event_loop_ops_custom +}; + +/* + * The rest is just the normal minimal example for lws, with a couple of extra + * lines wiring up the custom event library handlers above. + */ + +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 a client connection operating on the same loop + * It's optional... + */ + +static int +callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + switch (reason) { + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + lwsl_user("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: resp %u\n", + lws_http_client_http_response(wsi)); + break; + + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", + in ? (char *)in : "(null)"); + 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); + lwsl_hexdump_info(in, len); + 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 %s\n", + lws_wsi_tag(wsi)); + break; + + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + lwsl_info("%s: closed: %s\n", __func__, lws_wsi_tag(wsi)); + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { "httptest", callback_http, 0, 0, 0, NULL, 0}, + LWS_PROTOCOL_LIST_TERM +}; + +static int +do_client_conn(void) +{ + struct lws_client_connect_info i; + + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + + i.context = context; + + i.ssl_connection = LCCSCF_USE_SSL; + i.port = 443; + i.address = "warmcat.com"; + + i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | + LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; + i.path = "/"; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + i.protocol = protocols[0].name; +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + i.fi_wsi_name = "user"; +#endif + + if (!lws_client_connect_via_info(&i)) { + lwsl_err("Client creation failed\n"); + + return 1; + } + + lwsl_notice("Client creation OK\n"); + + return 0; +} + +/* + * End of client part + * + * Initialization part --> + */ + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + const char *p; + int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + void *foreign_loops[1]; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + /* + * init the existing custom event loop here if anything to do, don't + * run it yet. In our example, no init required. + */ + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal http server | visit http://localhost:7681\n"); + + 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_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + + info.event_lib_custom = &evlib_custom; /* bind lws to our custom event + * lib implementation above */ + foreign_loops[0] = &a_cpcx; /* pass in the custom poll object as the + * foreign loop object we will bind to */ + info.foreign_loops = foreign_loops; + + /* optional to demonstrate client connection */ + info.protocols = protocols; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* optional to demonstrate client connection */ + do_client_conn(); + + /* + * We're going to run the custom loop now, instead of the lws loop. + * We have told lws to cooperate with this loop to get stuff done. + * + * We only come back from this when interrupted gets set by SIGINT + */ + + custom_poll_run(&a_cpcx); + + /* clean up lws part */ + + lws_context_destroy(context); + + return 0; +} diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/404.html b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/404.html new file mode 100644 index 00000000..3e5a14b9 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/404.html @@ -0,0 +1,9 @@ + + + +
+

404

+ Sorry, that file doesn't exist. + + + diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/favicon.ico b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/favicon.ico new file mode 100644 index 00000000..c0cc2e3d Binary files /dev/null and b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/favicon.ico differ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/index.html b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/index.html new file mode 100644 index 00000000..bc9ffa44 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/index.html @@ -0,0 +1,15 @@ + + + + + + +
+ + Hello from the minimal http server example. +
+ You can confirm the 404 page handler by going to this + nonexistant page. + + + diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/libwebsockets.org-logo.svg b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/libwebsockets.org-logo.svg new file mode 100644 index 00000000..ef241b37 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/libwebsockets.org-logo.svg @@ -0,0 +1,66 @@ + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/strict-csp.svg b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/strict-csp.svg new file mode 100644 index 00000000..cd128f1d --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/strict-csp.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/symlink.html b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/symlink.html new file mode 120000 index 00000000..64233a9e --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-custom/mount-origin/symlink.html @@ -0,0 +1 @@ +index.html \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c index dd8e637c..be060da7 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c @@ -29,12 +29,12 @@ static struct lws_context *context; static struct lws_protocols protocols[] = { /* first protocol must always be HTTP handler */ - { "http-only", lws_callback_http_dummy, 0, 0, }, + { "http-only", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_LWS_STATUS, LWS_PLUGIN_PROTOCOL_POST_DEMO, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; /* @@ -59,8 +59,6 @@ static const struct lws_http_mount mount_ziptest_uncomm = { 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 */ @@ -80,7 +78,6 @@ static const struct lws_http_mount mount_ziptest_uncomm = { 8, /* strlen("/ziptest"), ie length of the mountpoint */ NULL, - { NULL, NULL } // sentinel }, mount_post = { (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ "/formtest", /* mountpoint in URL namespace on this vhost */ @@ -100,7 +97,6 @@ static const struct lws_http_mount mount_ziptest_uncomm = { 9, /* strlen("/formtest"), ie length of the mountpoint */ NULL, - { NULL, NULL } // sentinel }, mount = { /* .mount_next */ &mount_post, /* linked-list "next" */ /* .mountpoint */ "/", /* mountpoint URL */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c index b68b0430..a6c85108 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/libevent.c @@ -43,9 +43,9 @@ foreign_event_loop_init_and_run_libevent(void) tv.tv_sec = 1; tv.tv_usec = 0; + event_enable_debug_mode(); loop_event = event_base_new(); - sighandler_event = evsignal_new((struct event_base *)loop_event, SIGINT, signal_cb_event, (void*)SIGINT); diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c index 35aaaab1..a2a695db 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c @@ -126,8 +126,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, } static const struct lws_protocols protocols[] = { - { "httptest", callback_http, 0, 0, }, - { NULL, NULL, 0, 0 } + { "httptest", callback_http, 0, 0, 0, NULL, 0}, + LWS_PROTOCOL_LIST_TERM }; static int diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/minimal-http-server-form-get.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/minimal-http-server-form-get.c index b0ce321e..d0ce969e 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/minimal-http-server-form-get.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/minimal-http-server-form-get.c @@ -73,8 +73,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", callback_http, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", callback_http, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; /* default mount serves the URL space from ./mount-origin */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c index bdc6056f..0b41f404 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c @@ -188,8 +188,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", callback_http, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; /* default mount serves the URL space from ./mount-origin */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c index 59d2bc37..225cdd61 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c @@ -137,8 +137,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", callback_http, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; /* default mount serves the URL space from ./mount-origin */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c index 0f8082ed..58af16ee 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c @@ -134,8 +134,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", callback_http, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; /* default mount serves the URL space from ./mount-origin */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-fulltext-search/minimal-http-server.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-fulltext-search/minimal-http-server.c index 29b3ec31..010ef748 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-fulltext-search/minimal-http-server.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-fulltext-search/minimal-http-server.c @@ -21,7 +21,7 @@ static int interrupted; static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_FULLTEXT_DEMO, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static struct lws_protocol_vhost_options pvo_idx = { diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c index 36c8e06c..a47be0b2 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c @@ -57,7 +57,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, struct pss * pss = (struct pss *)user; uint8_t buf[LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE], *start = &buf[LWS_PRE], *p = start, - *end = p + sizeof(buf) - LWS_PRE; + *end = buf + sizeof(buf) - 1; int m, n; switch (reason) { @@ -101,8 +101,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", callback_http, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c index f32a48f0..b542c64c 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c @@ -108,7 +108,7 @@ int main(int argc, const char **argv) #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.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c index 41d2edd2..faef2f64 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c @@ -306,9 +306,9 @@ callback_sse(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, - { "sse", callback_sse, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, + { "sse", callback_sse, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; /* override the default mount for /sse in the URL space */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c index da620dd8..a87a7c2e 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c @@ -126,9 +126,9 @@ callback_sse(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, - { "sse", callback_sse, sizeof(struct pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, + { "sse", callback_sse, sizeof(struct pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; /* override the default mount for /sse in the URL space */ diff --git a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c index 0049980c..a72a2316 100644 --- a/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c +++ b/3rdparty/libwebsockets/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c @@ -126,6 +126,7 @@ int main(int argc, const char **argv) LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; + info.fo_listen_queue = 32; #if defined(LWS_WITH_PLUGINS) info.plugin_dirs = plugin_dirs; diff --git a/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c b/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c index 4a23f832..a523e096 100644 --- a/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c +++ b/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c @@ -53,6 +53,9 @@ static const lws_mqtt_client_connect_param_t client_connect_param = { .client_id = NULL, .keep_alive = 60, .clean_start = 1, + .client_id_nofree = 1, + .username_nofree = 1, + .password_nofree = 1, .will_param = { .topic = "good/bye", .message = "sign-off", @@ -374,12 +377,13 @@ static const struct lws_protocols protocols[] = { .callback = callback_mqtt, .per_session_data_size = sizeof(struct pss) }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; int main(int argc, const char **argv) { - lws_state_notify_link_t notifier = { {}, system_notify_cb, "app" }; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; lws_state_notify_link_t *na[] = { ¬ifier, NULL }; struct lws_context_creation_info info; struct lws_context *context; diff --git a/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer b/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer +++ b/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client-multi/warmcat.com.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c b/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c index c02ae813..5ff00c63 100644 --- a/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c +++ b/3rdparty/libwebsockets/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c @@ -41,6 +41,9 @@ static const lws_mqtt_client_connect_param_t client_connect_param = { .client_id = "lwsMqttClient", .keep_alive = 60, .clean_start = 1, + .client_id_nofree = 1, + .username_nofree = 1, + .password_nofree = 1, .will_param = { .topic = "good/bye", .message = "sign-off", @@ -183,6 +186,7 @@ callback_mqtt(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_MQTT_SUBSCRIBED: lwsl_user("%s: MQTT_SUBSCRIBED\n", __func__); + lws_callback_on_writable(wsi); break; case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: @@ -249,8 +253,10 @@ callback_mqtt(struct lws *wsi, enum lws_callback_reasons reason, */ pss->state++; - if (pss->state != STATE_TEST_FINISH) + if (pss->state != STATE_TEST_FINISH) { + lws_callback_on_writable(wsi); break; + } /* Oh we are done then */ @@ -296,12 +302,13 @@ static const struct lws_protocols protocols[] = { .callback = callback_mqtt, .per_session_data_size = sizeof(struct pss) }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; int main(int argc, const char **argv) { - lws_state_notify_link_t notifier = { {}, system_notify_cb, "app" }; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; lws_state_notify_link_t *na[] = { ¬ifier, NULL }; struct lws_context_creation_info info; struct lws_context *context; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c index 725ff630..a3ff2be0 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c @@ -76,8 +76,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "raw-test", callback_raw_test, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c index e93b5429..a2a74893 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c @@ -127,8 +127,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "raw-test", callback_raw_test, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-audio/audio.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-audio/audio.c index 639f34eb..6b595399 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-audio/audio.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-audio/audio.c @@ -171,7 +171,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, static struct lws_protocols protocols[] = { { "lws-audio-test", callback_raw_test, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c index 5a3e4b74..59f95afc 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c @@ -83,8 +83,8 @@ callback_raw_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user, } static const struct lws_protocols protocols[] = { - { "raw-echo", callback_raw_echo, sizeof(struct pss__raw_echo), 2048 }, - { NULL, NULL, 0, 0 } + { "raw-echo", callback_raw_echo, sizeof(struct pss__raw_echo), 2048, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; void sigint_handler(int sig) diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-file/minimal-raw-file.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-file/minimal-raw-file.c index f9759e97..7f1cb050 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-file/minimal-raw-file.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-file/minimal-raw-file.c @@ -98,8 +98,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "raw-test", callback_raw_test, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c index 489c030c..13c1ead6 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c @@ -128,8 +128,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "raw-test", callback_raw_test, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; void sigint_handler(int sig) diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c index ef94fad9..2d290ec4 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy-fallback/minimal-raw-proxy-fallback.c @@ -28,7 +28,7 @@ static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_RAW_PROXY, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static const struct lws_http_mount mount = { diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy/minimal-raw-proxy.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy/minimal-raw-proxy.c index 09997806..1634a803 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy/minimal-raw-proxy.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-proxy/minimal-raw-proxy.c @@ -22,7 +22,7 @@ static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_RAW_PROXY, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c index 4b15320b..57ba8f09 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c @@ -109,7 +109,11 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, #if defined(__linux__) CBAUD | #endif - CSIZE | CSTOPB | PARENB | CRTSCTS); + CSIZE | CSTOPB | PARENB +#if !defined(__QNX__) + | CRTSCTS +#endif + ); tio.c_cflag |= 0x1412 | CS8 | CREAD | CLOCAL; tcsetattr(vhd->filefd, TCSANOW, &tio); @@ -170,8 +174,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "raw-test", callback_raw_test, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c index d0f9e275..48267ba3 100644 --- a/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c +++ b/3rdparty/libwebsockets/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c @@ -100,8 +100,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "raw-test", callback_raw_test, sizeof(struct raw_pss), 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "raw-test", callback_raw_test, sizeof(struct raw_pss), 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c index 6728146a..bb453bfb 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c @@ -187,7 +187,7 @@ ss_avs_metadata_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, lwsl_info("%s: tx done\n", __func__); m->pos = (size_t)-1l; /* ban subsequent until new stream */ } else - lws_ss_request_tx(m->ss); + return lws_ss_request_tx(m->ss); lwsl_hexdump_info(buf, *len); @@ -211,7 +211,7 @@ ss_avs_metadata_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, if (m->pos == tot) { *flags |= LWSSS_FLAG_EOM; m->pos = 0; /* for next time */ - lws_ss_request_tx(m->ss); + return lws_ss_request_tx(m->ss); } lwsl_hexdump_info(buf, *len); diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/CMakeLists.txt new file mode 100644 index 00000000..e1f36476 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/CMakeLists.txt @@ -0,0 +1,27 @@ +project(lws-minimal-secure-streams-binance C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-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) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 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 --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/README.md b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/README.md new file mode 100644 index 00000000..5155ddd9 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/README.md @@ -0,0 +1,56 @@ +# lws minimal secure streams binance + +This is a Secure Streams version of minimal-ws-client-binance. + +"policy.json" contains all the information about endpoints, protocols and +connection validation, tagged by streamtype name. + +The example tries to load it from the cwd, it lives in +./minimal-examples/secure-streams/minimal-secure-streams-binance dir, so +either run it from there, or copy the policy.json to your cwd. It's also +possible to put the policy json in the code as a string and pass that at +context creation time. + +The secure stream object represents a nailed-up connection that outlives any +single socket connection, and can manage reconnections / retries according to +the policy to keep the connection nailed up automatically. + +Secure Streams provides the same simplified communication api without any +protocol dependencies. + +## build + +Lws must have been built with `LWS_ROLE_WS=1`, `LWS_WITH_SECURE_STREAMS=1`, and +`LWS_WITHOUT_EXTENSIONS=0` + +``` + $ cmake . && make +``` + +## Commandline Options + +Option|Meaning +---|--- +-d|Set logging verbosity + +## usage + +``` +$ ./bin/lws-minimal-ws-client-binance +[2021/08/15 06:42:40:8409] U: LWS minimal Secure Streams binance client +[2021/08/15 06:42:40:8410] N: LWS: 4.2.99-v4.2.0-156-g8f352f65e8, NET CLI SRV H1 H2 WS SS-JSON-POL SSPROX ConMon FLTINJ IPV6-on +[2021/08/15 06:42:40:8410] N: ++ [495958|wsi|0|pipe] (1) +[2021/08/15 06:42:40:8411] N: ++ [495958|vh|0|netlink] (1) +[2021/08/15 06:42:40:8433] N: ++ [495958|vh|1|digicert||-1] (2) +[2021/08/15 06:42:40:8471] N: ++ [495958|wsiSScli|0|binance] (1) +[2021/08/15 06:42:40:8471] N: [495958|wsiSScli|0|binance]: lws_ss_check_next_state_ss: (unset) -> LWSSSCS_CREATING +[2021/08/15 06:42:40:8472] N: [495958|wsiSScli|0|binance]: lws_ss_check_next_state_ss: LWSSSCS_CREATING -> LWSSSCS_CONNECTING +[2021/08/15 06:42:40:8472] N: ++ [495958|wsicli|0|WS/h1/fstream.binance.com/([495958|wsiSScli|0|binance])] (1) +[2021/08/15 06:42:41:8802] N: [495958|wsiSScli|0|binance]: lws_ss_check_next_state_ss: LWSSSCS_CONNECTING -> LWSSSCS_CONNECTED +[2021/08/15 06:42:42:8803] N: sul_hz_cb: price: min: 4669185¢, max: 4672159¢, avg: 4670061¢, (53 prices/s) +[2021/08/15 06:42:42:8803] N: sul_hz_cb: elatency: min: 131ms, max: 292ms, avg: 154ms, (53 msg/s) +[2021/08/15 06:42:43:8803] N: sul_hz_cb: price: min: 4669646¢, max: 4672159¢, avg: 4669953¢, (34 prices/s) +[2021/08/15 06:42:43:8803] N: sul_hz_cb: elatency: min: 130ms, max: 149ms, avg: 133ms, (34 msg/s) +[2021/08/15 06:42:44:8804] N: sul_hz_cb: price: min: 4669455¢, max: 4672159¢, avg: 4669904¢, (26 prices/s) +... +``` diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/main.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/main.c new file mode 100644 index 00000000..8327f3e6 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/main.c @@ -0,0 +1,266 @@ +/* + * lws-minimal-secure-streams-binance + * + * Written in 2010-2021 by Andy Green + * Kutoga + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates a Secure Streams implementation of a client that connects + * to binance ws server efficiently. + * + * Build lws with -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITHOUT_EXTENSIONS=0 + * + * "policy.json" contains all the information about endpoints, protocols and + * connection validation, tagged by streamtype name. + * + * The example tries to load it from the cwd, it lives + * in ./minimal-examples/secure-streams/minimal-secure-streams-binance dir, so + * either run it from there, or copy the policy.json to your cwd. It's also + * possible to put the policy json in the code as a string and pass that at + * context creation time. + */ + +#include +#include +#include +#include + +static int interrupted; + +typedef struct range { + uint64_t sum; + uint64_t lowest; + uint64_t highest; + + unsigned int samples; +} range_t; + +typedef struct binance { + struct lws_ss_handle *ss; + void *opaque_data; + + lws_sorted_usec_list_t sul_hz; /* 1hz summary dump */ + + range_t e_lat_range; + range_t price_range; +} binance_t; + +/****** Part 1 / 3: application data processing */ + +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 (uint64_t)((lws_usec_t)tv.tv_sec * LWS_US_PER_SEC) + + (uint64_t)tv.tv_usec; +} + +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 = price + (uint64_t)((10 * (s[1] - '0')) + (s[2] - '0')); + + return price; +} + +static void +sul_hz_cb(lws_sorted_usec_list_t *sul) +{ + binance_t *bin = lws_container_of(sul, binance_t, sul_hz); + + /* + * We are called once a second to dump statistics on the connection + */ + + lws_sul_schedule(lws_ss_get_context(bin->ss), 0, &bin->sul_hz, + sul_hz_cb, LWS_US_PER_SEC); + + if (bin->price_range.samples) + lwsl_notice("%s: price: min: %llu¢, max: %llu¢, avg: %llu¢, " + "(%d prices/s)\n", __func__, + (unsigned long long)bin->price_range.lowest, + (unsigned long long)bin->price_range.highest, + (unsigned long long)(bin->price_range.sum / + bin->price_range.samples), + bin->price_range.samples); + if (bin->e_lat_range.samples) + lwsl_notice("%s: elatency: min: %llums, max: %llums, " + "avg: %llums, (%d msg/s)\n", __func__, + (unsigned long long)bin->e_lat_range.lowest / 1000, + (unsigned long long)bin->e_lat_range.highest / 1000, + (unsigned long long)(bin->e_lat_range.sum / + bin->e_lat_range.samples) / 1000, + bin->e_lat_range.samples); + + range_reset(&bin->e_lat_range); + range_reset(&bin->price_range); +} + +/****** Part 2 / 3: communication */ + +static lws_ss_state_return_t +binance_rx(void *userobj, const uint8_t *in, size_t len, int flags) +{ + binance_t *bin = (binance_t *)userobj; + uint64_t latency_us, now_us; + char numbuf[16]; + uint64_t price; + const char *p; + size_t alen; + + now_us = (uint64_t)get_us_timeofday(); + + p = lws_json_simple_find((const char *)in, len, "\"depthUpdate\"", + &alen); + if (!p) + return LWSSSSRET_OK; + + p = lws_json_simple_find((const char *)in, len, "\"E\":", &alen); + if (!p) { + lwsl_err("%s: no E JSON\n", __func__); + return LWSSSSRET_OK; + } + + lws_strnncpy(numbuf, p, alen, sizeof(numbuf)); + latency_us = now_us - ((uint64_t)atoll(numbuf) * LWS_US_PER_MS); + + if (latency_us < bin->e_lat_range.lowest) + bin->e_lat_range.lowest = latency_us; + if (latency_us > bin->e_lat_range.highest) + bin->e_lat_range.highest = latency_us; + + bin->e_lat_range.sum += latency_us; + bin->e_lat_range.samples++; + + p = lws_json_simple_find((const char *)in, len, "\"a\":[[\"", &alen); + if (!p) + return LWSSSSRET_OK; + + lws_strnncpy(numbuf, p, alen, sizeof(numbuf)); + price = pennies(numbuf); + + if (price < bin->price_range.lowest) + bin->price_range.lowest = price; + if (price > bin->price_range.highest) + bin->price_range.highest = price; + + bin->price_range.sum += price; + bin->price_range.samples++; + + return LWSSSSRET_OK; +} + +static lws_ss_state_return_t +binance_state(void *userobj, void *h_src, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + binance_t *bin = (binance_t *)userobj; + + lwsl_ss_info(bin->ss, "%s (%d), ord 0x%x", + lws_ss_state_name((int)state), state, (unsigned int)ack); + + switch (state) { + + case LWSSSCS_CONNECTED: + lws_sul_schedule(lws_ss_get_context(bin->ss), 0, &bin->sul_hz, + sul_hz_cb, LWS_US_PER_SEC); + range_reset(&bin->e_lat_range); + range_reset(&bin->price_range); + + return LWSSSSRET_OK; + + case LWSSSCS_DISCONNECTED: + lws_sul_cancel(&bin->sul_hz); + break; + + default: + break; + } + + return LWSSSSRET_OK; +} + +static const lws_ss_info_t ssi_binance = { + .handle_offset = offsetof(binance_t, ss), + .opaque_user_data_offset = offsetof(binance_t, opaque_data), + .rx = binance_rx, + .state = binance_state, + .user_alloc = sizeof(binance_t), + .streamtype = "binance", /* bind to corresponding policy */ +}; + +/****** Part 3 / 3: init and event loop */ + +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 */ } +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *cx; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS minimal Secure Streams binance client\n"); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | + LWS_SERVER_OPTION_EXPLICIT_VHOSTS; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.fd_limit_per_thread = 1 + 1 + 1; + info.extensions = extensions; + info.pss_policies_json = "policy.json"; /* literal JSON, or path */ + + cx = lws_create_context(&info); + if (!cx) { + lwsl_err("lws init failed\n"); + return 1; + } + + if (lws_ss_create(cx, 0, &ssi_binance, NULL, NULL, NULL, NULL)) { + lwsl_cx_err(cx, "failed to create secure stream"); + interrupted = 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(cx, 0); + + lws_context_destroy(cx); + + lwsl_user("Completed\n"); + + return 0; +} diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/policy.json b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/policy.json new file mode 100644 index 00000000..1ff4e041 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-binance/policy.json @@ -0,0 +1,38 @@ +{ + "release": "01234567", + "product": "myproduct", + "schema-version": 1, + "retry": [{ + "default": { + "backoff": [1000, 2000, 3000, 4000, 5000], + "conceal": 65535, + "jitterpc": 20, + "svalidping": 30, + "svalidhup": 35 + } + }], + "certs": [{ + "digicert_global_root": "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQkCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=" + } + ], + "trust_stores": [{ + "name": "digicert", + "stack": ["digicert_global_root"] + } + ], + "s": [ + { "binance": { + "endpoint": "fstream.binance.com", + "port": 443, + "protocol": "ws", + "http_url": "/stream?streams=btcusdt@depth@0ms/btcusdt@bookTicker/btcusdt@aggTrade", + "nailed_up": true, + "ws_prioritize_reads": true, + "tls": true, + "tls_trust_store": "digicert", + "retry": "default" + } + } + ] +} + diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/CMakeLists.txt new file mode 100644 index 00000000..7fc59dae --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/CMakeLists.txt @@ -0,0 +1,134 @@ +project(lws-minimal-secure-streams-blob C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-blob) + +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) +require_lws_config(LWS_WITH_GENCRYPTO 1 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + find_program(VALGRIND "valgrind") + + if (LWS_CTEST_INTERNET_AVAILABLE AND NOT WIN32) + + # + # When running in CI, wait for a lease on the resources + # before starting this test, so the server does not get + # thousands of simultaneous tls connection attempts + # + # sai-resource holds the lease on the resources until + # the time given in seconds or the sai-resource instance + # exits, whichever happens first + # + # If running under Sai, creates a lock test called "res_sspcmin" + # + + sai_resource(warmcat_conns 1 40 sspcminblob) + + # + # simple test not via proxy + # + + if (VALGRIND) + message("testing via valgrind") + add_test(NAME ssblob-warmcat COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $) + else() + add_test(NAME ssblob-warmcat COMMAND lws-minimal-secure-streams) + endif() + + set_tests_properties(ssblob-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams + TIMEOUT 40) + if (DEFINED ENV{SAI_OVN}) + set_tests_properties(ssblob-warmcat PROPERTIES FIXTURES_REQUIRED "res_sspcmin") + endif() + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) + + # + # Define test dep to bring up and take down the test + # proxy + # + + if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # uds abstract namespace for linux + set(CTEST_SOCKET_PATH "@ctest-ssblobproxy-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + else() + # filesystem socket for others + set(CTEST_SOCKET_PATH "/tmp/ctest-ssblobproxy-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + endif() + add_test(NAME st_ssblobproxy COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + ssblobproxy $ + -i ${CTEST_SOCKET_PATH} ) + set_tests_properties(st_ssblobproxy PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP ssblobproxy TIMEOUT 800) + + add_test(NAME ki_ssblobproxy COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + ssblobproxy $ + -i ${CTEST_SOCKET_PATH}) + set_tests_properties(ki_ssblobproxy PROPERTIES FIXTURES_CLEANUP ssblobproxy) + + # + # the client part that will connect to the proxy + # + + if (VALGRIND) + message("testing via valgrind") + add_test(NAME sspcblob-minimal COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ -i +${CTEST_SOCKET_PATH}) + else() + add_test(NAME sspcblob-minimal COMMAND lws-minimal-secure-streams-client -i +${CTEST_SOCKET_PATH}) + endif() + + set(fixlist "ssblobproxy") + if (DEFINED ENV{SAI_OVN}) + list(APPEND fixlist "res_ssblobproxy") + endif() + + set_tests_properties(sspcblob-minimal PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams + FIXTURES_REQUIRED "${fixlist}" + TIMEOUT 40) + + endif() + + 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.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 --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/README.md b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/README.md new file mode 100644 index 00000000..78f0a1bd --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/README.md @@ -0,0 +1,67 @@ +# 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 +--blob|Download a 50MiB blob from warmact.com, using flow control at the proxy + +``` +[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 --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/minimal-secure-streams.c new file mode 100644 index 00000000..8574e2e0 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-blob/minimal-secure-streams.c @@ -0,0 +1,643 @@ +/* + * 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 + +// #define FORCE_OS_TRUST_STORE + +/* + * 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, test_respmap, test_blob, test_ots; +static unsigned int timeout_ms = 3000; +static lws_state_notify_link_t nl; + +/* + * 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. + */ +#if !defined(FORCE_OS_TRUST_STORE) + "{\"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=" + "\"}" +#endif + "]," + "\"trust_stores\": [" /* named cert chains */ +#if !defined(FORCE_OS_TRUST_STORE) + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"" + "]" + "}" +#endif + "]," + "\"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-v4.2-v2.json\"," +#endif + "\"tls\":" "true," + "\"opportunistic\":" "true," +#if !defined(FORCE_OS_TRUST_STORE) + "\"tls_trust_store\":" "\"le_via_isrg\"," +#endif + "\"retry\":" "\"default\"" + "}},{" + /* + * "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 amt; + + struct lws_genhash_ctx hash_ctx; +} 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 const uint8_t expected_blob_hash[] = { + 0xed, 0x57, 0x20, 0xc1, 0x68, 0x30, 0x81, 0x0e, + 0x58, 0x29, 0xdf, 0xb9, 0xb6, 0x6c, 0x96, 0xb2, + 0xe2, 0x4e, 0xfc, 0x4f, 0x93, 0xaa, 0x5e, 0x38, + 0xc7, 0xff, 0x41, 0x50, 0xd3, 0x1c, 0xfb, 0xbf +}; + +static lws_ss_state_return_t +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + myss_t *m = (myss_t *)userobj; + const char *md_srv = "not set", *md_test = "not set"; + size_t md_srv_len = 7, md_test_len = 7; + + if (flags & LWSSS_FLAG_PERF_JSON) + return LWSSSSRET_OK; + + if (test_blob) { + + if (flags & LWSSS_FLAG_SOM) { + if (lws_genhash_init(&m->hash_ctx, LWS_GENHASH_TYPE_SHA256)) + lwsl_err("%s: hash init failed\n", __func__); + m->amt = 0; + } + + if (lws_genhash_update(&m->hash_ctx, buf, len)) + lwsl_err("%s: hash failed\n", __func__); + + if ((m->amt + len) / 102400 != (m->amt / 102400)) { + + lwsl_user("%s: blob test: rx %uKiB\n", __func__, + (unsigned int)((m->amt + len) / 1024)); + /* + * Let's make it hard for client to keep up with onward + * server, delay 50ms after every 100K received, so we + * are forcing the flow control action at the proxy + */ + usleep(50000); + } + + m->amt += len; + + if (flags & LWSSS_FLAG_EOM) { + uint8_t digest[32]; + lws_genhash_destroy(&m->hash_ctx, digest); + + if (!memcmp(expected_blob_hash, digest, 32)) { + lwsl_user("%s: SHA256 match\n", __func__); + bad = 0; + } + + interrupted = 1; + } + + return LWSSSSRET_OK; + } + + lws_ss_get_metadata(m->ss, "srv", (const void **)&md_srv, &md_srv_len); + lws_ss_get_metadata(m->ss, "test", (const void **)&md_test, &md_test_len); + + lwsl_user("%s: len %d, flags: %d, srv: %.*s, test: %.*s\n", __func__, + (int)len, flags, (int)md_srv_len, md_srv, + (int)md_test_len, md_test); + 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 LWSSSSRET_OK; +} + +static lws_ss_state_return_t +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + //myss_t *m = (myss_t *)userobj; + + /* in this example, we don't send stuff */ + + return LWSSSSRET_TX_DONT_SEND; +} + +static lws_ss_state_return_t +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 (%d), ord 0x%x\n", __func__, + lws_ss_state_name((int)state), state, (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + return lws_ss_client_connect(m->ss); + + case LWSSSCS_CONNECTING: + lws_ss_start_timeout(m->ss, timeout_ms); + + if (!test_blob) { + if (lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + + if (lws_ss_set_metadata(m->ss, "ctype", "myctype", 7)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + } + break; + + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + bad = 2; + 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__); + /* if we're out of time */ + interrupted = 1; + bad = 3; + break; + + case LWSSSCS_USER_BASE: + lwsl_notice("%s: LWSSSCS_USER_BASE\n", __func__); + break; + + default: + break; + } + + return LWSSSSRET_OK; +} + +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) + + /* + * 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) + 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 = test_ots ? "mintest-ots" : + (test_blob ? "bulkproxflow" : + (test_respmap ? "respmap" : "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 +}; + +#if defined(LWS_WITH_SYS_METRICS) + +static int +my_metric_report(lws_metric_pub_t *mp) +{ + lws_metric_bucket_t *sub = mp->u.hist.head; + char buf[192]; + + do { + if (lws_metrics_format(mp, &sub, buf, sizeof(buf))) + lwsl_user("%s: %s\n", __func__, buf); + } while ((mp->flags & LWSMTFL_REPORT_HIST) && sub); + + /* 0 = leave metric to accumulate, 1 = reset the metric */ + + return 1; +} + +static const lws_system_ops_t system_ops = { + .metric_report = my_metric_report, +}; + +#endif + +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, expected = 0; + const char *p; + + 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 (lws_cmdline_option(argc, argv, "--respmap")) + test_respmap = 1; + + if (lws_cmdline_option(argc, argv, "--ots")) + /* + * Use a streamtype that relies on the OS trust store for + * validation + */ + test_ots = 1; + + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) + timeout_ms = (unsigned int)atoi(p); + + if (lws_cmdline_option(argc, argv, "--blob")) { + test_blob = 1; + if (timeout_ms == 3000) + /* + * Don't use default 3s, we're going to be a lot + * slower + */ + timeout_ms = 60000; + } + + 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 = (uint16_t)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_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#endif + +#if defined(LWS_WITH_MBEDTLS) + + /* uncomment to force mbedtls to load a system trust store like + * openssl does + * + * info.mbedtls_client_preload_filepath = + * "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"; + */ +#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; + + +#if defined(LWS_WITH_SYS_METRICS) + info.system_ops = &system_ops; + info.metrics_prefix = "ssmex"; +#endif + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + goto bail; + } + +#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); + +bail: + if ((p = lws_cmdline_option(argc, argv, "--expected-exit"))) + expected = atoi(p); + + if (bad == expected) { + lwsl_user("Completed: OK (seen expected %d)\n", expected); + return 0; + } else + lwsl_err("Completed: failed: exit %d, expected %d\n", bad, expected); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt index 272c8d9c..1a943b93 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt @@ -13,7 +13,7 @@ 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_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c index 4f34ced5..46fbd905 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c @@ -82,32 +82,43 @@ static const char * const default_ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" - "\"}" + "{\"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=" + "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -121,7 +132,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"," + "\"tls_trust_store\":" "\"le_via_isrg\"," "\"metadata\": [" "{\"servername\": \"\"}" "]" diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metrics-proxy/metrics-proxy-policy.json b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metrics-proxy/metrics-proxy-policy.json index 078b025c..d7420145 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metrics-proxy/metrics-proxy-policy.json +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-metrics-proxy/metrics-proxy-policy.json @@ -11,11 +11,12 @@ "svalidhup":310 }}], "certs": [{ - "dst_root_x3": "MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ"},{"self_localhost": "MIIF5jCCA86gAwIBAgIJANq50IuwPFKgMA0GCSqGSIb3DQEBCwUAMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwIBcNMTgwMzIwMDQxNjA3WhgPMjExODAyMjQwNDE2MDdaMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjYtuWaICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABo1MwUTAdBgNVHQ4EFgQU9mYU23tW2zsomkKTAXarjr2vjuswHwYDVR0jBBgwFoAU9mYU23tW2zsomkKTAXarjr2vjuswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANjIBMrowYNCbhAJdP7dhlhT2RUFRdeRUJD0IxrH/hkvb6myHHnK8nOYezFPjUlmRKUgNEDuAxbnXZzPdCRNV9V2mShbXvCyiDY7WCQE2Bn44z26O0uWVk+7DNNLH9BnkwUtOnM9PwtmD9phWexm4q2GnTsiL6Ul6cy0QlTJWKVLEUQQ6yda582e23J1AXqtqFcpfoE34H3afEiGy882b+ZBiwkeV+oq6XVF8sFyr9zYrv9CvWTYlkpTQfLTZSsgPdEHYVcjvxQ2D+XyDR0aRLRlvxUa9dHGFHLICG34Juq5Ai6lM1EsoD8HSsJpMcmrH7MWw2cKkujC3rMdFTtte83wF1uuF4FjUC72+SmcQN7A386BC/nk2TTsJawTDzqwOu/VdZv2g1WpTHlumlClZeP+G/jkSyDwqNnTu1aodDmUa4xZodfhP1HWPwUKFcq8oQr148QYAAOlbUOJQU7QwRWd1VbnwhDtQWXC92A2w1n/xkZSR1BM/NUSDhkBSUU1WjMbWg6GgmnIZLRerQCu1Oozr87rOQqQakPkyt8BUSNK3K42j2qcfhAONdRl8Hq8Qs5pupy+s8sdCGDlwR3JNCMv6u48OK87F4mcIxhkSefFJUFII25pCGN5WtE4p5l+9cnO1GrIXe2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE="},{"self_localhost_key": "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCjYtuWaICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABAoICAFWe8MQZb37k2gdAV3Y6aq8fqokKQqbCNLd3giGFwYkezHXoJfg6Di7oZxNcKyw35LFEghkgtQqErQqo35VPIoH+vXUpWOjnCmM4muFA9/cX6mYMc8TmJsg0ewLdBCOZVw+wPABlaqz+0UOiSMMftpk9fz9JwGd8ERyBsT+tk3Qi6D0vPZVsC1KqxxL/cwIFd3Hf2ZBtJXe0KBn1pktWht5AKqx9mld2Ovl7NjgiC1Fx9r+fZw/iOabFFwQA4dr+R8mEMK/7bd4VXfQ1o/QGGbMTG+ulFrsiDyP+rBIAaGC0i7gDjLAIBQeDhP409ZhswIEc/GBtODU372a2CQK/u4Q/HBQvuBtKFNkGUooLgCCbFxzgNUGc83GB/6IwbEM7R5uXqsFiE71LpmroDyjKTlQ8YZkpIcLNVLw0usoGYHFm2rvCyEVlfsE3Ub8cFyTFk50SeOcF2QL2xzKmmbZEpXglxBHR0hjgon0IKJDGfor4bHO7Nt+1Ece8u2oTEKvpz5aIn44OeC5mApRGy83/0bvsesnWjDE/bGpoT8qFuy+0urDEPNId44XcJm1IRIlG56ErxC3l0s11wrIpTmXXckqwzFR9s2z7f0zjeyxqZg4NTPI7wkM3M8BXlvp2GTBIeoxrWB4V3YArwu8QF80QBgVzmgHl24nTg00UH1OjZsABAoIBAQDOxftSDbSqGytcWqPYP3SZHAWDA0O4ACEM+eCwau9ASutl0IDlNDMJ8nC2ph25BMe5hHDWp2cGQJog7pZ/3qQogQho2gUniKDifN7740QdykllTzTVROqmP8+efreIvqlzHmuqaGfGs5oTkZaWj5su+B+bT+9rIwZcwfs5YRINhQRx17qa++xh5mfE25c+M9fiIBTiNSo4lTxWMBShnK8xrGaMEmN7W0qTMbFHPgQz5FcxRjCCqwHilwNBeLDTp/ZECEB7y34khVh531mBE2mNzSVIQcGZP1I/DvXjW7UUNdgFwii/GW+6M0uUDy23UVQpbFzcV8o1C2nZc4Fb4zwBAoIBAQDKSJkFwwuRnaVJS6WxOKjX8MCu9/cKPnwBv2mmI2jgGxHTw5sr3ahmF5eTb8Zo19BowytN+tr62ZFoIBA9Ubc9esEAU8l3fggdfM82cuR9sGcfQVoCh8tMg6BP8IBLOmbSUhN3PG2m39I802u0fFNVQCJKhx1m1MFFLOu7lVcDS9JN+oYVPb6MDfBLm5jOiPuYkFZ4gH79J7gXI0/YKhaJ7yXthYVkdrSF6Eooer4RZgma62Dd1VNzSq3JBo6rYjF7Lvd+RwDCR1thHrmf/IXplxpNVkoMVxtzbrrbgnC25QmvRYc0rlS/kvM4yQhMH3eA7IycDZMpY+0xm7I7jTT7AoIBAGKzKIMDXdCxBWKhNYJ8z7hiItNl1IZZMW2TPUiY0rl6yaChBVXjM9W0r07QPnHZsUiByqb743adkbTUjmxdJzjaVtxN7ZXwZvOVrY7I7fPWYnCEfXCr4+IVpZI/ZHZWpGX6CGSgT6EOjCZ5IUufIvEpqVSmtF8MqfXO9o9uIYLokrWQx1dBl5UnuTLDqw8bChq7O5y6yfuWaOWvL7nxI8NvSsfj4y635gIa/0dFeBYZEfHIUlGdNVomwXwYEzgE/c19ruIowX7HU/NgxMWTMZhpazlxgesXybel+YNcfDQ4e3RMOMz3ZFiaMaJsGGNf4++d9TmMgk4Ns6oDs6Tb9AECggEBAJYzd+SOYo26iBu3nw3L65uEeh6xou8pXH0Tu4gQrPQTRZZ/nT3iNgOwqu1gRuxcq7TOjt41UdqIKO8vN7/AaJavCpaKoIMowy/aGCbvAvjNPpU3unU8jdl/t08EXs79S5IKPcgAx87sTTi7KDN5SYt4tr2uPEe53NTXuSatilG5QCyExIELOuzWAMKzg7CAiIlNS9foWeLyVkBgCQ6Sme/L8ta+mUDy37K6vC34jh9vK9yrwF6X44ItRoOJafCaVfGI+175q/eWcqTX4q+IG4tKls4sL4mgOJLq+ra50aYMxbcuommctPMXU6CrrYyQpPTHMNVDQy2ttFdsq9iKTncCggEBAMmt/8yvPflS+xv3kg/ZBvR9JB1In2n3rUCYYD47ReKFqJ03Vmq5C9nY56s9w7OUO8perBXlJYmKZQhO4293lvxZD2Iq4NcZbVSCMoHAUzhzY3brdgtSIxa2gGveGAezZ38qKIU26dkz7deECY4vrsRkwhpTW0LGVCpjcQoaKvymAoCmAs8V2oMrZiw1YQ9uOUoWwOqm1wZqmVcOXvPIS2gWAs3fQlWjH9hkcQTMsUaXQDOD0aqkSY3ENqOvbCV1/oUpRi3076khCoAXI1bKSn/AvR3KDP14B5toHI/F5OTSEiGhhHesgRrsfBrpEY1IATtPq1taBZZogRqI3rOkkPk=" + "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="}, + {"self_localhost": "MIIF5jCCA86gAwIBAgIJANq50IuwPFKgMA0GCSqGSIb3DQEBCwUAMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwIBcNMTgwMzIwMDQxNjA3WhgPMjExODAyMjQwNDE2MDdaMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjYtuWaICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABo1MwUTAdBgNVHQ4EFgQU9mYU23tW2zsomkKTAXarjr2vjuswHwYDVR0jBBgwFoAU9mYU23tW2zsomkKTAXarjr2vjuswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANjIBMrowYNCbhAJdP7dhlhT2RUFRdeRUJD0IxrH/hkvb6myHHnK8nOYezFPjUlmRKUgNEDuAxbnXZzPdCRNV9V2mShbXvCyiDY7WCQE2Bn44z26O0uWVk+7DNNLH9BnkwUtOnM9PwtmD9phWexm4q2GnTsiL6Ul6cy0QlTJWKVLEUQQ6yda582e23J1AXqtqFcpfoE34H3afEiGy882b+ZBiwkeV+oq6XVF8sFyr9zYrv9CvWTYlkpTQfLTZSsgPdEHYVcjvxQ2D+XyDR0aRLRlvxUa9dHGFHLICG34Juq5Ai6lM1EsoD8HSsJpMcmrH7MWw2cKkujC3rMdFTtte83wF1uuF4FjUC72+SmcQN7A386BC/nk2TTsJawTDzqwOu/VdZv2g1WpTHlumlClZeP+G/jkSyDwqNnTu1aodDmUa4xZodfhP1HWPwUKFcq8oQr148QYAAOlbUOJQU7QwRWd1VbnwhDtQWXC92A2w1n/xkZSR1BM/NUSDhkBSUU1WjMbWg6GgmnIZLRerQCu1Oozr87rOQqQakPkyt8BUSNK3K42j2qcfhAONdRl8Hq8Qs5pupy+s8sdCGDlwR3JNCMv6u48OK87F4mcIxhkSefFJUFII25pCGN5WtE4p5l+9cnO1GrIXe2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE="},{"self_localhost_key": "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCjYtuWaICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABAoICAFWe8MQZb37k2gdAV3Y6aq8fqokKQqbCNLd3giGFwYkezHXoJfg6Di7oZxNcKyw35LFEghkgtQqErQqo35VPIoH+vXUpWOjnCmM4muFA9/cX6mYMc8TmJsg0ewLdBCOZVw+wPABlaqz+0UOiSMMftpk9fz9JwGd8ERyBsT+tk3Qi6D0vPZVsC1KqxxL/cwIFd3Hf2ZBtJXe0KBn1pktWht5AKqx9mld2Ovl7NjgiC1Fx9r+fZw/iOabFFwQA4dr+R8mEMK/7bd4VXfQ1o/QGGbMTG+ulFrsiDyP+rBIAaGC0i7gDjLAIBQeDhP409ZhswIEc/GBtODU372a2CQK/u4Q/HBQvuBtKFNkGUooLgCCbFxzgNUGc83GB/6IwbEM7R5uXqsFiE71LpmroDyjKTlQ8YZkpIcLNVLw0usoGYHFm2rvCyEVlfsE3Ub8cFyTFk50SeOcF2QL2xzKmmbZEpXglxBHR0hjgon0IKJDGfor4bHO7Nt+1Ece8u2oTEKvpz5aIn44OeC5mApRGy83/0bvsesnWjDE/bGpoT8qFuy+0urDEPNId44XcJm1IRIlG56ErxC3l0s11wrIpTmXXckqwzFR9s2z7f0zjeyxqZg4NTPI7wkM3M8BXlvp2GTBIeoxrWB4V3YArwu8QF80QBgVzmgHl24nTg00UH1OjZsABAoIBAQDOxftSDbSqGytcWqPYP3SZHAWDA0O4ACEM+eCwau9ASutl0IDlNDMJ8nC2ph25BMe5hHDWp2cGQJog7pZ/3qQogQho2gUniKDifN7740QdykllTzTVROqmP8+efreIvqlzHmuqaGfGs5oTkZaWj5su+B+bT+9rIwZcwfs5YRINhQRx17qa++xh5mfE25c+M9fiIBTiNSo4lTxWMBShnK8xrGaMEmN7W0qTMbFHPgQz5FcxRjCCqwHilwNBeLDTp/ZECEB7y34khVh531mBE2mNzSVIQcGZP1I/DvXjW7UUNdgFwii/GW+6M0uUDy23UVQpbFzcV8o1C2nZc4Fb4zwBAoIBAQDKSJkFwwuRnaVJS6WxOKjX8MCu9/cKPnwBv2mmI2jgGxHTw5sr3ahmF5eTb8Zo19BowytN+tr62ZFoIBA9Ubc9esEAU8l3fggdfM82cuR9sGcfQVoCh8tMg6BP8IBLOmbSUhN3PG2m39I802u0fFNVQCJKhx1m1MFFLOu7lVcDS9JN+oYVPb6MDfBLm5jOiPuYkFZ4gH79J7gXI0/YKhaJ7yXthYVkdrSF6Eooer4RZgma62Dd1VNzSq3JBo6rYjF7Lvd+RwDCR1thHrmf/IXplxpNVkoMVxtzbrrbgnC25QmvRYc0rlS/kvM4yQhMH3eA7IycDZMpY+0xm7I7jTT7AoIBAGKzKIMDXdCxBWKhNYJ8z7hiItNl1IZZMW2TPUiY0rl6yaChBVXjM9W0r07QPnHZsUiByqb743adkbTUjmxdJzjaVtxN7ZXwZvOVrY7I7fPWYnCEfXCr4+IVpZI/ZHZWpGX6CGSgT6EOjCZ5IUufIvEpqVSmtF8MqfXO9o9uIYLokrWQx1dBl5UnuTLDqw8bChq7O5y6yfuWaOWvL7nxI8NvSsfj4y635gIa/0dFeBYZEfHIUlGdNVomwXwYEzgE/c19ruIowX7HU/NgxMWTMZhpazlxgesXybel+YNcfDQ4e3RMOMz3ZFiaMaJsGGNf4++d9TmMgk4Ns6oDs6Tb9AECggEBAJYzd+SOYo26iBu3nw3L65uEeh6xou8pXH0Tu4gQrPQTRZZ/nT3iNgOwqu1gRuxcq7TOjt41UdqIKO8vN7/AaJavCpaKoIMowy/aGCbvAvjNPpU3unU8jdl/t08EXs79S5IKPcgAx87sTTi7KDN5SYt4tr2uPEe53NTXuSatilG5QCyExIELOuzWAMKzg7CAiIlNS9foWeLyVkBgCQ6Sme/L8ta+mUDy37K6vC34jh9vK9yrwF6X44ItRoOJafCaVfGI+175q/eWcqTX4q+IG4tKls4sL4mgOJLq+ra50aYMxbcuommctPMXU6CrrYyQpPTHMNVDQy2ttFdsq9iKTncCggEBAMmt/8yvPflS+xv3kg/ZBvR9JB1In2n3rUCYYD47ReKFqJ03Vmq5C9nY56s9w7OUO8perBXlJYmKZQhO4293lvxZD2Iq4NcZbVSCMoHAUzhzY3brdgtSIxa2gGveGAezZ38qKIU26dkz7deECY4vrsRkwhpTW0LGVCpjcQoaKvymAoCmAs8V2oMrZiw1YQ9uOUoWwOqm1wZqmVcOXvPIS2gWAs3fQlWjH9hkcQTMsUaXQDOD0aqkSY3ENqOvbCV1/oUpRi3076khCoAXI1bKSn/AvR3KDP14B5toHI/F5OTSEiGhhHesgRrsfBrpEY1IATtPq1taBZZogRqI3rOkkPk=" }], "trust_stores": [ - {"name": "le_via_dst", - "stack": ["dst_root_x3"] + {"name": "le_via_isrg", + "stack": ["isrg_root_x1"] } ], "s": [ { @@ -27,7 +28,7 @@ "http_url":"index.html", "tls":true, "retry":"default", - "tls_trust_store":"le_via_dst" + "tls_trust_store":"le_via_isrg" }},{ "forscraper": { "server":true, diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/CMakeLists.txt index 2be9464b..c0beb268 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/CMakeLists.txt @@ -51,7 +51,7 @@ if (requirements) set_tests_properties(ssperf-warmcat PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams - TIMEOUT 20) + TIMEOUT 40) if (DEFINED ENV{SAI_OVN}) set_tests_properties(ssperf-warmcat PROPERTIES FIXTURES_REQUIRED "res_ssperfpcmin") endif() diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/README.md b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/README.md index fada1d56..bddaacd2 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/README.md +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/README.md @@ -46,7 +46,7 @@ Commandline option|Meaning [2021/03/31 15:29:49:0716] N: lws_ss_deserialize_parse: RX METADATA srv [2021/03/31 15:29:49:0882] U: myss_rx: len 1380, flags: 1, srv: lwsws, test: hello [2021/03/31 15:29:49:0907] U: myss_rx: len 140, flags: 0, srv: lwsws, test: hello -[2021/03/31 15:29:49:0926] U: {"peer":"46.105.127.147","dns_us":536,"sockconn_us":30183,"tls_us":29343,"txn_resp_us:25990,"dns":["2001:41d0:2:ee93::1","46.105.127.147"]} +[2021/03/31 15:29:49:0926] U: {"peer":"46.105.127.147","dns_us":536,"sockconn_us":30183,"tls_us":29343,"txn_resp_us":25990,"dns":["2001:41d0:2:ee93::1","46.105.127.147"]} [2021/03/31 15:29:49:0937] U: myss_rx: len 1380, flags: 0, srv: lwsws, test: hello [2021/03/31 15:29:49:0938] U: myss_rx: len 140, flags: 0, srv: lwsws, test: hello [2021/03/31 15:29:49:0940] U: myss_rx: len 829, flags: 0, srv: lwsws, test: hello diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/minimal-secure-streams.c index be41e6b6..f3b9b9b7 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/minimal-secure-streams.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-perf/minimal-secure-streams.c @@ -39,6 +39,7 @@ static int interrupted, bad = 1, force_cpd_fail_portal, force_cpd_fail_no_internet, test_respmap; +static const char *streamtype = "mintest"; static unsigned int timeout_ms = 3000; static lws_state_notify_link_t nl; @@ -82,32 +83,43 @@ static const char * const default_ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" - "\"}" + "{\"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=" + "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -130,7 +142,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}},{" /* * "captive_portal_detect" describes @@ -363,7 +375,7 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, ssi.tx = myss_tx; ssi.state = myss_state; ssi.user_alloc = sizeof(myss_t); - ssi.streamtype = test_respmap ? "respmap" : "mintest"; + ssi.streamtype = test_respmap ? "respmap" : streamtype; if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { @@ -437,6 +449,15 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "--respmap")) test_respmap = 1; + if (lws_cmdline_option(argc, argv, "--test404")) + streamtype = "mintest404"; + + if (lws_cmdline_option(argc, argv, "--test404red")) + streamtype = "mintest404red"; + + if (lws_cmdline_option(argc, argv, "--test404redref")) + streamtype = "mintest404redref"; + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) timeout_ms = (unsigned int)atoi(p); diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index e06286e8..bb86d3d3 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -1,7 +1,7 @@ /* * lws-minimal-secure-streams-policy2c * - * Written in 2010-2020 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -347,6 +347,7 @@ int main(int argc, const char **argv) buf, sizeof(buf))); printf("\t.name = \"%s\",\n", pol->trust.store->name); + printf("\t.count = %d,\n", pol->trust.store->count); printf("\t.ssx509 = {\n"); for (n = pol->trust.store->count - 1; n >= 0 ; n--) @@ -426,8 +427,9 @@ int main(int argc, const char **argv) printf("\t.next = (void *)&%s,\n", prev); printf("\t.name = \"%s\",\n", auth->name); + printf("\t.type= \"%s\",\n", auth->type); printf("\t.streamtype = \"%s\",\n", auth->streamtype); - printf("\t.blob = %d,\n", auth->blob_index); + printf("\t.blob_index = %d,\n", auth->blob_index); printf("}"); if (auth->next) printf(","); @@ -522,7 +524,7 @@ int main(int argc, const char **argv) pol->u.http.auth_preamble); if (pol->u.http.respmap) { - printf("\t\t\t.respmap = &%s_http_respmap,\n", + printf("\t\t\t.respmap = (void *)&%s_http_respmap,\n", curr); printf("\t\t\t.count_respmap = %d,\n", pol->u.http.count_respmap); @@ -571,7 +573,24 @@ int main(int argc, const char **argv) if (pol->u.mqtt.will_message) printf("\t\t\t.will_message = \"%s\",\n", pol->u.mqtt.will_message); - + 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); + if (pol->u.mqtt.birth_topic) + printf("\t\t\t.birth_topic = \"%s\",\n", + pol->u.mqtt.birth_topic); + if (pol->u.mqtt.birth_message) + printf("\t\t\t.birth_message = \"%s\",\n", + pol->u.mqtt.birth_message); + if (pol->u.mqtt.birth_qos) + printf("\t\t\t.birth_qos = %u,\n", + pol->u.mqtt.birth_qos); + if (pol->u.mqtt.birth_retain) + printf("\t\t\t.birth_retain = %u,\n", + pol->u.mqtt.birth_retain); if (pol->u.mqtt.keep_alive) printf("\t\t\t.keep_alive = %u,\n", pol->u.mqtt.keep_alive); @@ -581,13 +600,12 @@ int main(int argc, const char **argv) 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); - + if (pol->u.mqtt.aws_iot) + printf("\t\t\t.aws_iot = %u,\n", + pol->u.mqtt.aws_iot); + if (pol->u.mqtt.retain) + printf("\t\t\t.retain = %u,\n", + pol->u.mqtt.retain); printf("\t\t}\n\t},\n"); break; @@ -634,6 +652,13 @@ int main(int argc, const char **argv) printf("\t.trust = {.store = &_ss_ts_%s},\n", purify_csymbol(pol->trust.store->name, buf, sizeof(buf))); +#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) + if (pol->aws_region) + printf("\t.aws_region= \"%s\",\n", pol->aws_region); + if (pol->aws_service) + printf("\t.aws_service= \"%s\",\n", pol->aws_service); + +#endif printf("}"); diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt index 652209c0..62404153 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt @@ -16,9 +16,21 @@ require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams-post.c) + + find_program(VALGRIND "valgrind") if (LWS_CTEST_INTERNET_AVAILABLE) - add_test(NAME sspost-warmcat COMMAND lws-minimal-secure-streams-post) + if (VALGRIND) + add_test(NAME sspost-warmcat COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + post_hcm_srv + ${VALGRIND} --tool=memcheck + $ + ) + else() + add_test(NAME sspost-warmcat + COMMAND lws-minimal-secure-streams-post) + endif() set_tests_properties(sspost-warmcat PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-post diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c index 39257e3e..b5a5f34a 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-post/minimal-secure-streams-post.c @@ -175,32 +175,43 @@ static const char * const default_ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" - "\"}" + "{\"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=" + "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -223,7 +234,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}},{" /* * "captive_portal_detect" describes @@ -318,13 +329,15 @@ myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, 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); + if (m->pos != m->len) + return lws_ss_request_tx(m->ss); + return 0; } @@ -353,11 +366,12 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, /* 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; + + return lws_ss_request_tx_len(m->ss, (unsigned long)strlen(postbody)); + case LWSSSCS_CONNECTED: - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); + case LWSSSCS_ALL_RETRIES_FAILED: /* if we're out of retries, we want to close the app and FAIL */ interrupted = 1; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c index 6b3a8072..0e1fbb59 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c @@ -66,32 +66,43 @@ static const char * const default_ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" + "{\"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=" "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -115,7 +126,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}}" "}" ; @@ -264,7 +275,7 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.fd_limit_per_thread = 1 + 6 + 1; + info.fd_limit_per_thread = 1 + 26 + 1; info.pss_policies_json = default_ss_policy; info.port = CONTEXT_PORT_NO_LISTEN; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c index c6a7abe3..0e21efb0 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c @@ -62,32 +62,43 @@ static const char * const default_ss_policy = * deployed in browsers. We use the ISRG path because that * way we can skip the extra IdenTrust root cert. */ - "{\"dst_root_x3\": \"" - "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" - "\"}" + "{\"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=" + "\"}" "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -102,7 +113,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}}," "{\"mintest-fail\": {" "\"endpoint\":" "\"warmcat.com\"," @@ -114,7 +125,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}}," "{\"minpost\": {" "\"endpoint\":" "\"warmcat.com\"," @@ -126,7 +137,7 @@ static const char * const default_ss_policy = "\"tls\":" "true," "\"opportunistic\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}}" "]" "}" @@ -182,8 +193,8 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); + case LWSSSCS_ALL_RETRIES_FAILED: /* if we're out of retries, we want to close the app and FAIL */ interrupted = 1; @@ -266,7 +277,7 @@ min_sec_str_sequencer_cb(struct lws_sequencer *seq, void *user, int event, case LWSSEQ_TIMED_OUT: /* current step timed out */ if (s->state == SEQ_RECONNECT_WAIT) - lws_ss_request_tx(s->ss); + return lws_ss_request_tx(s->ss); break; /* @@ -277,8 +288,8 @@ min_sec_str_sequencer_cb(struct lws_sequencer *seq, void *user, int event, case LWSSEQ_SS_STATE_BASE + LWSSSCS_CREATING: lwsl_info("%s: seq LWSSSCS_CREATING\n", __func__); - lws_ss_request_tx(s->ss); - break; + return lws_ss_request_tx(s->ss); + case LWSSEQ_SS_STATE_BASE + LWSSSCS_DISCONNECTED: lwsl_info("%s: seq LWSSSCS_DISCONNECTED\n", __func__); break; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c index 7ad0b84e..4d395d4c 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server-raw/ss-server.c @@ -54,9 +54,8 @@ 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, + if (!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); } @@ -90,8 +89,7 @@ myss_raw_state(void *userobj, void *sh, lws_ss_constate_t state, lws_sul_cancel(&m->sul); break; case LWSSSCS_CONNECTED: - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); default: break; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/main.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/main.c index 0b8a13be..167b0a2a 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/main.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/main.c @@ -45,26 +45,37 @@ static const char * const default_ss_policy = * deployed in browsers. We use the ISRG path because that * way we can skip the extra IdenTrust root cert. */ - "{\"dst_root_x3\": \"" - "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" - "\"}," + "{\"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=" + "\"}," /* * a selfsigned cert for localhost for 100 years */ @@ -160,9 +171,9 @@ static const char * const default_ss_policy = "]," "\"trust_stores\": [" /* named cert chains */ "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -179,7 +190,7 @@ static const char * const default_ss_policy = "\"http_url\":" "\"index.html\"," "\"tls\":" "true," "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" + "\"tls_trust_store\":" "\"le_via_isrg\"" "}}," /* @@ -226,6 +237,9 @@ smd_cb(void *opaque, lws_smd_class_t c, lws_usec_t ts, void *buf, size_t len) NULL, NULL)) { lwsl_err("%s: failed to create secure stream\n", __func__); + bad = 1; + interrupted = 1; + lws_cancel_service(context); return -1; } #if 0 diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c index 64834c37..58c0fd98 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-client.c @@ -62,7 +62,7 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_request_tx(m->ss); + return 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 */ diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c index 2a810920..1b045458 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-server/ss-server.c @@ -134,9 +134,8 @@ 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, + if (!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); } @@ -170,8 +169,8 @@ myss_srv_state(void *userobj, void *sh, lws_ss_constate_t state, lws_sul_cancel(&m->sul); break; case LWSSSCS_CREATING: - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); + case LWSSSCS_ALL_RETRIES_FAILED: /* if we're out of retries, we want to close the app and FAIL */ interrupted = 1; @@ -201,10 +200,9 @@ myss_srv_state(void *userobj, void *sh, lws_ss_constate_t state, /* * ...it's going to be whatever size it is (and request tx) */ - lws_ss_request_tx_len(m->ss, (unsigned long) + return lws_ss_request_tx_len(m->ss, (unsigned long) (multipart ? strlen(multipart_html) : strlen(html))); - break; case LWSSSCS_SERVER_UPGRADE: @@ -217,8 +215,8 @@ myss_srv_state(void *userobj, void *sh, lws_ss_constate_t state, 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; + return lws_ss_request_tx(m->ss); /* we want to start sending numbers */ + default: break; } diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/CMakeLists.txt index 7dab8b5e..47deb88f 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/CMakeLists.txt @@ -12,14 +12,13 @@ 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_AUTH_SIGV4 1 requirements) -require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} ss-s3-main.c ss-s3-ss.c) find_program(VALGRIND "valgrind") - if (LWS_CTEST_INTERNET_AVAILABLE AND NOT WIN32) + if (LWS_CTEST_INTERNET_AVAILABLE AND NOT WIN32 AND 0) if (VALGRIND) message("testing via valgrind") add_test(NAME ss-sigv4 COMMAND diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/policy.json b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/policy.json new file mode 100644 index 00000000..6e446852 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/policy.json @@ -0,0 +1 @@ +{"release":"01234567","product":"myproduct","schema-version":1,"retry": [{"default": {"backoff": [100,200,300,500,1000],"conceal":5,"jitterpc":20,"svalidping":30,"svalidhup":35}}],"certs": [{"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"},{"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"},{"baltimore_cybertrust_root": "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp"}],"trust_stores": [{"name": "s3-root-cert","stack": ["baltimore_cybertrust_root","amazon_root_ca_1","starfield_services_root_ca"]}],"auth": [{"name": "sigv4_br","type": "sigv4","blob": 0}],"s": [{"s3PutObj": {"endpoint":"${s3bucket}.s3.amazonaws.com","port":443,"protocol":"h1","http_method":"PUT","http_url":"${s3Obj}","http_no_content_length": false,"tls":true,"tls_trust_store":"s3-root-cert","opportunistic":true,"retry":"default","use_auth":"sigv4_br","aws_region":"region","aws_service":"service","metadata": [{"region": ""},{"service": ""},{"s3bucket": ""},{"s3Obj": ""},{"ctype": "content-type:"},{"xcsha256": "x-amz-content-sha256:"},{"xdate": "x-amz-date:"},{"xacl": "x-amz-acl:"}]}}]} \ No newline at end of file diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-main.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-main.c index d80bacc9..9ab99523 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-main.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-main.c @@ -1,7 +1,7 @@ /* * S3 Put Object via Secure Streams minimal sigv4 example * - * Written in 2010-2020 by Andy Green + * Written in 2010-2021 by Andy Green * Amit Pachore * securestreams-dev@amazon.com * @@ -15,6 +15,9 @@ #include #include "ss-s3-put.h" +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#include "static_policy.h" +#endif int interrupted, bad = 1; static lws_state_notify_link_t nl; @@ -22,6 +25,7 @@ extern const lws_ss_info_t s3_ssi; #if !defined(LWS_SS_USE_SSPC) +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) static const char * const default_ss_policy = "{" "\"release\":" "\"01234567\"," @@ -43,6 +47,50 @@ static const char * const default_ss_policy = "}}" "]," "\"certs\": [" /* named individual certificates in BASE64 DER */ + "{\"amazon_root_ca_1\": \"" + "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFA" + "DA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b2" + "4gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAk" + "GA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg" + "Q0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXjca9Hg" + "FB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM9O6II8" + "c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHr" + "QgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5" + "SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6" + "pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg" + "0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0" + "OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUAA4IBAQCY8jda" + "QZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PMCCjjmCXPI" + "6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbv" + "Xy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtP" + "HRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJi" + "oaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5W" + "TP468SQvvG5" + "\"}," + "{\"starfield_services_root_ca\": \"" + "MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx" + "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT" + "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs" + "ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5" + "MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD" + "VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy" + "ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy" + "dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI" + "hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p" + "OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2" + "8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K" + "Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe" + "hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk" + "6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw" + "DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q" + "AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI" + "bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB" + "ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z" + "qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd" + "iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn" + "0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN" + "sSi6" + "\"}," "{\"baltimore_cybertrust_root\": \"" /* LE X3 signed by ISRG X1 root */ "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ" "RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD" @@ -69,7 +117,9 @@ static const char * const default_ss_policy = "{" "\"name\": \"s3-root-cert\"," "\"stack\": [" - "\"baltimore_cybertrust_root\"" + "\"baltimore_cybertrust_root\"," + "\"amazon_root_ca_1\"," + "\"starfield_services_root_ca\"" "]" "}" "]," @@ -110,6 +160,7 @@ static const char * const default_ss_policy = "]" "}" ; +#endif static char *aws_keyid, *aws_key; #endif @@ -200,8 +251,12 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "-a"))) info.ss_proxy_address = p; } +#else +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + info.pss_policies = &_ss_static_policy_entry; #else info.pss_policies_json = default_ss_policy; +#endif info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c index b12f8f51..1acd4317 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/ss-s3-ss.c @@ -57,7 +57,7 @@ ss_s3_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, *flags |= LWSSS_FLAG_EOM; // m->pos = 0; /* we only want to send once */ } else - lws_ss_request_tx(m->ss); + return lws_ss_request_tx(m->ss); return LWSSSSRET_OK; } @@ -173,12 +173,10 @@ ss_s3_state(void *userobj, void *sh, lws_ss_constate_t state, timestamp, strlen(timestamp))) return LWSSSSRET_DESTROY_ME; - lws_ss_request_tx_len(m->ss, m->total); - break; + return lws_ss_request_tx_len(m->ss, m->total); case LWSSSCS_CONNECTED: - lws_ss_request_tx(m->ss); - break; + return lws_ss_request_tx(m->ss); case LWSSSCS_DISCONNECTED: return LWSSSSRET_DESTROY_ME; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/static_policy.h b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/static_policy.h new file mode 100644 index 00000000..0f94c5dc --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-sigv4/static_policy.h @@ -0,0 +1,492 @@ +/* + * Autogenerated from the following JSON policy + */ + +#if 0 +{"release":"01234567","product":"myproduct","schema-version":1,"retry": [{"default": {"backoff": [100,200,300,500,1000],"conceal":5,"jitterpc":20,"svalidping":30,"svalidhup":35}}],"certs": [{"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"},{"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"},{"baltimore_cybertrust_root": "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp"}],"trust_stores": [{"name": "s3-root-cert","stack": ["baltimore_cybertrust_root","amazon_root_ca_1","starfield_services_root_ca"]}],"auth": [{"name": "sigv4_br","type": "sigv4","blob": 0}],"s": [{"s3PutObj": {"endpoint":"${s3bucket}.s3.amazonaws.com","port":443,"protocol":"h1","http_method":"PUT","http_url":"${s3Obj}","http_no_content_length": false,"tls":true,"tls_trust_store":"s3-root-cert","opportunistic":true,"retry":"default","use_auth":"sigv4_br","aws_region":"region","aws_service":"service","metadata": [{"region": ""},{"service": ""},{"s3bucket": ""},{"s3Obj": ""},{"ctype": "content-type:"},{"xcsha256": "x-amz-content-sha256:"},{"xdate": "x-amz-date:"},{"xacl": "x-amz-acl:"}]}}]} + + Original JSON size: 4630 +#endif + + +static const lws_ss_metadata_t _md_s3PutObj_xacl = { + .name = "xacl", + .value__may_own_heap = (void *)"x-amz-acl:", + .value_length = 0xa, + .length = 0, + .value_is_http_token = 0xff, +}, +_md_s3PutObj_xdate = { + .next = (void *)&_md_s3PutObj_xacl, + .name = "xdate", + .value__may_own_heap = (void *)"x-amz-date:", + .value_length = 0xb, + .length = 1, + .value_is_http_token = 0xff, +}, +_md_s3PutObj_xcsha256 = { + .next = (void *)&_md_s3PutObj_xdate, + .name = "xcsha256", + .value__may_own_heap = (void *)"x-amz-content-sha256:", + .value_length = 0x15, + .length = 2, + .value_is_http_token = 0xff, +}, +_md_s3PutObj_ctype = { + .next = (void *)&_md_s3PutObj_xcsha256, + .name = "ctype", + .value__may_own_heap = (void *)"content-type:", + .value_length = 0xd, + .length = 3, + .value_is_http_token = 0x1c, +}, +_md_s3PutObj_s3Obj = { + .next = (void *)&_md_s3PutObj_ctype, + .name = "s3Obj", + .value__may_own_heap = (void *)"", + .value_length = 0x0, + .length = 4, + .value_is_http_token = 0x0, +}, +_md_s3PutObj_s3bucket = { + .next = (void *)&_md_s3PutObj_s3Obj, + .name = "s3bucket", + .value__may_own_heap = (void *)"", + .value_length = 0x0, + .length = 5, + .value_is_http_token = 0x0, +}, +_md_s3PutObj_service = { + .next = (void *)&_md_s3PutObj_s3bucket, + .name = "service", + .value__may_own_heap = (void *)"", + .value_length = 0x0, + .length = 6, + .value_is_http_token = 0x0, +}, +_md_s3PutObj_region = { + .next = (void *)&_md_s3PutObj_service, + .name = "region", + .value__may_own_heap = (void *)"", + .value_length = 0x0, + .length = 7, + .value_is_http_token = 0x0, +}; + +static const uint32_t _rbo_bo_0[] = { + 100, 200, 300, 500, 1000, +}; +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_baltimore_cybertrust_root[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x77, 0x30, 0x82, 0x02, 0x5F, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x02, + /* 0x 10 */ 0x00, 0x00, 0xB9, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x 18 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, + /* 0x 20 */ 0x05, 0x00, 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, + /* 0x 28 */ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, + /* 0x 30 */ 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x0A, 0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, + /* 0x 40 */ 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31, 0x13, 0x30, + /* 0x 48 */ 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, + /* 0x 50 */ 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, + /* 0x 58 */ 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, + /* 0x 60 */ 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, + /* 0x 68 */ 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, + /* 0x 70 */ 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, + /* 0x 78 */ 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, + /* 0x 80 */ 0x17, 0x0D, 0x30, 0x30, 0x30, 0x35, 0x31, 0x32, + /* 0x 88 */ 0x31, 0x38, 0x34, 0x36, 0x30, 0x30, 0x5A, 0x17, + /* 0x 90 */ 0x0D, 0x32, 0x35, 0x30, 0x35, 0x31, 0x32, 0x32, + /* 0x 98 */ 0x33, 0x35, 0x39, 0x30, 0x30, 0x5A, 0x30, 0x5A, + /* 0x a0 */ 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + /* 0x a8 */ 0x06, 0x13, 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, + /* 0x b0 */ 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x09, + /* 0x b8 */ 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, + /* 0x c0 */ 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + /* 0x c8 */ 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79, 0x62, 0x65, + /* 0x d0 */ 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, + /* 0x d8 */ 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + /* 0x e0 */ 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, + /* 0x e8 */ 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, + /* 0x f0 */ 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, + /* 0x f8 */ 0x6F, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, + /* 0x100 */ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + /* 0x108 */ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + /* 0x110 */ 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, + /* 0x118 */ 0x01, 0x01, 0x00, 0xA3, 0x04, 0xBB, 0x22, 0xAB, + /* 0x120 */ 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A, 0xB5, + /* 0x128 */ 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, + /* 0x130 */ 0xB1, 0xB0, 0xE3, 0x5B, 0x8E, 0x2B, 0x29, 0x9A, + /* 0x138 */ 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09, 0x05, + /* 0x140 */ 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, + /* 0x148 */ 0xFE, 0xB4, 0x88, 0xDA, 0x12, 0xEB, 0x38, 0xEB, + /* 0x150 */ 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52, 0x7B, + /* 0x158 */ 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, + /* 0x160 */ 0x88, 0xB5, 0x6A, 0x09, 0xE7, 0x73, 0xE8, 0x11, + /* 0x168 */ 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D, 0x2D, + /* 0x170 */ 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, + /* 0x178 */ 0xC3, 0x28, 0xEA, 0xF5, 0xAB, 0x25, 0x87, 0x8A, + /* 0x180 */ 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F, 0x0C, + /* 0x188 */ 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, + /* 0x190 */ 0xD5, 0x70, 0x70, 0xF0, 0x8F, 0xC0, 0x12, 0xCA, + /* 0x198 */ 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33, 0x7A, + /* 0x1a0 */ 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, + /* 0x1a8 */ 0x42, 0x48, 0x13, 0xD2, 0xC0, 0xC2, 0xA4, 0xAE, + /* 0x1b0 */ 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC, 0xB4, + /* 0x1b8 */ 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, + /* 0x1c0 */ 0x63, 0xF5, 0xA5, 0x63, 0xE0, 0x90, 0x0C, 0x7D, + /* 0x1c8 */ 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA, 0xEB, + /* 0x1d0 */ 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, + /* 0x1d8 */ 0x15, 0xED, 0x69, 0xBC, 0xF9, 0x39, 0x36, 0x72, + /* 0x1e0 */ 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9, 0x90, + /* 0x1e8 */ 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, + /* 0x1f0 */ 0x1F, 0x24, 0x98, 0x21, 0x5C, 0x07, 0x99, 0x29, + /* 0x1f8 */ 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86, 0x3A, + /* 0x200 */ 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, + /* 0x208 */ 0x31, 0xF0, 0x78, 0x8D, 0x76, 0xBF, 0xFC, 0x9E, + /* 0x210 */ 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90, 0xDC, + /* 0x218 */ 0x27, 0x1A, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, + /* 0x220 */ 0xA3, 0x45, 0x30, 0x43, 0x30, 0x1D, 0x06, 0x03, + /* 0x228 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xE5, + /* 0x230 */ 0x9D, 0x59, 0x30, 0x82, 0x47, 0x58, 0xCC, 0xAC, + /* 0x238 */ 0xFA, 0x08, 0x54, 0x36, 0x86, 0x7B, 0x3A, 0xB5, + /* 0x240 */ 0x04, 0x4D, 0xF0, 0x30, 0x12, 0x06, 0x03, 0x55, + /* 0x248 */ 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, + /* 0x250 */ 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x03, 0x30, + /* 0x258 */ 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, + /* 0x260 */ 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + /* 0x268 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x270 */ 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + /* 0x278 */ 0x01, 0x01, 0x00, 0x85, 0x0C, 0x5D, 0x8E, 0xE4, + /* 0x280 */ 0x6F, 0x51, 0x68, 0x42, 0x05, 0xA0, 0xDD, 0xBB, + /* 0x288 */ 0x4F, 0x27, 0x25, 0x84, 0x03, 0xBD, 0xF7, 0x64, + /* 0x290 */ 0xFD, 0x2D, 0xD7, 0x30, 0xE3, 0xA4, 0x10, 0x17, + /* 0x298 */ 0xEB, 0xDA, 0x29, 0x29, 0xB6, 0x79, 0x3F, 0x76, + /* 0x2a0 */ 0xF6, 0x19, 0x13, 0x23, 0xB8, 0x10, 0x0A, 0xF9, + /* 0x2a8 */ 0x58, 0xA4, 0xD4, 0x61, 0x70, 0xBD, 0x04, 0x61, + /* 0x2b0 */ 0x6A, 0x12, 0x8A, 0x17, 0xD5, 0x0A, 0xBD, 0xC5, + /* 0x2b8 */ 0xBC, 0x30, 0x7C, 0xD6, 0xE9, 0x0C, 0x25, 0x8D, + /* 0x2c0 */ 0x86, 0x40, 0x4F, 0xEC, 0xCC, 0xA3, 0x7E, 0x38, + /* 0x2c8 */ 0xC6, 0x37, 0x11, 0x4F, 0xED, 0xDD, 0x68, 0x31, + /* 0x2d0 */ 0x8E, 0x4C, 0xD2, 0xB3, 0x01, 0x74, 0xEE, 0xBE, + /* 0x2d8 */ 0x75, 0x5E, 0x07, 0x48, 0x1A, 0x7F, 0x70, 0xFF, + /* 0x2e0 */ 0x16, 0x5C, 0x84, 0xC0, 0x79, 0x85, 0xB8, 0x05, + /* 0x2e8 */ 0xFD, 0x7F, 0xBE, 0x65, 0x11, 0xA3, 0x0F, 0xC0, + /* 0x2f0 */ 0x02, 0xB4, 0xF8, 0x52, 0x37, 0x39, 0x04, 0xD5, + /* 0x2f8 */ 0xA9, 0x31, 0x7A, 0x18, 0xBF, 0xA0, 0x2A, 0xF4, + /* 0x300 */ 0x12, 0x99, 0xF7, 0xA3, 0x45, 0x82, 0xE3, 0x3C, + /* 0x308 */ 0x5E, 0xF5, 0x9D, 0x9E, 0xB5, 0xC8, 0x9E, 0x7C, + /* 0x310 */ 0x2E, 0xC8, 0xA4, 0x9E, 0x4E, 0x08, 0x14, 0x4B, + /* 0x318 */ 0x6D, 0xFD, 0x70, 0x6D, 0x6B, 0x1A, 0x63, 0xBD, + /* 0x320 */ 0x64, 0xE6, 0x1F, 0xB7, 0xCE, 0xF0, 0xF2, 0x9F, + /* 0x328 */ 0x2E, 0xBB, 0x1B, 0xB7, 0xF2, 0x50, 0x88, 0x73, + /* 0x330 */ 0x92, 0xC2, 0xE2, 0xE3, 0x16, 0x8D, 0x9A, 0x32, + /* 0x338 */ 0x02, 0xAB, 0x8E, 0x18, 0xDD, 0xE9, 0x10, 0x11, + /* 0x340 */ 0xEE, 0x7E, 0x35, 0xAB, 0x90, 0xAF, 0x3E, 0x30, + /* 0x348 */ 0x94, 0x7A, 0xD0, 0x33, 0x3D, 0xA7, 0x65, 0x0F, + /* 0x350 */ 0xF5, 0xFC, 0x8E, 0x9E, 0x62, 0xCF, 0x47, 0x44, + /* 0x358 */ 0x2C, 0x01, 0x5D, 0xBB, 0x1D, 0xB5, 0x32, 0xD2, + /* 0x360 */ 0x47, 0xD2, 0x38, 0x2E, 0xD0, 0xFE, 0x81, 0xDC, + /* 0x368 */ 0x32, 0x6A, 0x1E, 0xB5, 0xEE, 0x3C, 0xD5, 0xFC, + /* 0x370 */ 0xE7, 0x81, 0x1D, 0x19, 0xC3, 0x24, 0x42, 0xEA, + /* 0x378 */ 0x63, 0x39, 0xA9, +}; +static const lws_ss_x509_t _ss_x509_baltimore_cybertrust_root = { + .vhost_name = "baltimore_cybertrust_root", + .ca_der = _ss_der_baltimore_cybertrust_root, + .ca_der_len = 891, +}; +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_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_s3_root_cert = { + .name = "s3-root-cert", + .count = 3, + .ssx509 = { + &_ss_x509_starfield_services_root_ca, + &_ss_x509_amazon_root_ca_1, + &_ss_x509_baltimore_cybertrust_root, + } +}; + +static const lws_ss_auth_t _ssau_sigv4_br = { + .name = "sigv4_br", + .type= "sigv4", + .streamtype = "(null)", + .blob_index = 0, +}; + + +static const lws_ss_policy_t _ssp_s3PutObj = { + .streamtype = "s3PutObj", + .endpoint = "${s3bucket}.s3.amazonaws.com", + .auth = &_ssau_sigv4_br, + .metadata = (void *)&_md_s3PutObj_region, + .u = { + .http = { + .method = "PUT", + .url = "${s3Obj}", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .priority = 0x0, + .port = 443, + .metadata_count = 8, + .protocol = 0, + .trust = {.store = &_ss_ts_s3_root_cert}, + .aws_region= "region", + .aws_service= "service", +}; +#define _ss_static_policy_entry _ssp_s3PutObj +/* estimated footprint 3559 (when sizeof void * = 8) */ diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt index 3440a24e..db2f9ebc 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt @@ -13,6 +13,8 @@ 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) +require_lws_config(LWS_WITH_SYS_FAULT_INJECTION 1 has_fault_injection) + if (requirements) add_executable(${PROJECT_NAME} minimal-secure-streams-smd.c) @@ -32,7 +34,47 @@ if (requirements) PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-smd TIMEOUT 10) - endif() + + if (has_fault_injection) + if (VALGRIND) + add_test(NAME ss-smd-fi1 COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ + --fault-injection "ss/ss_create_smd" + --expected-exit 1) + add_test(NAME ss-smd-fi2 COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ + --fault-injection "ss/ss_create_smd_1" + --expected-exit 1) + add_test(NAME ss-smd-fi3 COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ + --fault-injection "ss/ss_create_smd_2" + --expected-exit 1) + else() + add_test(NAME ss-smd-fi1 COMMAND lws-minimal-secure-streams-smd + --fault-injection "ss/ss_create_smd" + --expected-exit 1) + add_test(NAME ss-smd-fi2 COMMAND lws-minimal-secure-streams-smd + --fault-injection "ss/ss_create_smd_1" + --expected-exit 1) + add_test(NAME ss-smd-fi3 COMMAND lws-minimal-secure-streams-smd + --fault-injection "ss/ss_create_smd_2" + --expected-exit 1) + endif() + + set_tests_properties(ss-smd-fi1 + ss-smd-fi2 + ss-smd-fi3 + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-smd + TIMEOUT 5) + endif() + + + + endif() if (websockets_shared) target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c index 741e6932..1abb0747 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c @@ -15,7 +15,7 @@ #include #include -static int interrupted, bad = 1, count_p1, count_p2, count_tx; +static int interrupted, bad = 1, count_p1, count_p2, count_tx, expected = 0; static unsigned int how_many_msg = 100, usec_interval = 1000; static lws_sorted_usec_list_t sul_timeout; @@ -94,7 +94,8 @@ sul_tx_periodic_cb(lws_sorted_usec_list_t *sul) myss_t *m = lws_container_of(sul, myss_t, sul); lwsl_info("%s: requesting TX\n", __func__); - lws_ss_request_tx(m->ss); + if (lws_ss_request_tx(m->ss)) + lwsl_info("%s: req failed\n", __func__); } static lws_ss_state_return_t @@ -224,7 +225,8 @@ direct_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, if (lws_ss_create(*pctx, 0, &ssi_lws_smd, NULL, NULL, NULL, NULL)) { lwsl_err("%s: failed to create secure stream\n", __func__); - + interrupted = 1; + lws_cancel_service(*pctx); return -1; } } @@ -323,7 +325,7 @@ int main(int argc, const char **argv) /* set up the test timeout */ lws_sul_schedule(context, 0, &sul_timeout, sul_timeout_cb, - (how_many_msg * (usec_interval + 1000)) + LWS_US_PER_SEC); + (how_many_msg * (usec_interval + 50000)) + LWS_US_PER_SEC); /* the event loop */ @@ -358,7 +360,15 @@ int main(int argc, const char **argv) #endif lws_context_destroy(context); - lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + if ((p = lws_cmdline_option(argc, argv, "--expected-exit"))) + expected = atoi(p); + + if (bad == expected) { + lwsl_user("Completed: OK (seen expected %d)\n", expected); + return 0; + } + + lwsl_err("Completed: failed: exit %d, expected %d\n", bad, expected); - return bad; + return 1; } diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/multi.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/multi.c index 1dfe3d60..fcf851d4 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/multi.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-smd/multi.c @@ -200,11 +200,11 @@ multi_myss_state(void *userobj, void *h_src, lws_ss_constate_t state, /* * Because in this test everybody is watching and counting * everybody else's messages from different forks, we have to - * hold off starting sending for 1s so all forks can join the + * hold off starting sending for 2s so all forks can join the * proxy first and not miss anything */ lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, - sul_multi_tx_periodic_cb, 1 * LWS_US_PER_SEC); + sul_multi_tx_periodic_cb, 2 * LWS_US_PER_SEC); m->starting = 0; return 0; case LWSSSCS_DISCONNECTED: diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c index 1cffe368..1d7b8690 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c @@ -1,7 +1,7 @@ /* * lws-minimal-secure-streams-staticpolicy * - * Written in 2010-2020 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -36,7 +36,7 @@ static lws_state_notify_link_t nl; typedef struct myss { - struct lws_ss_handle *ss; + struct lws_ss_handle *ss; void *opaque_data; /* ... application specific state ... */ lws_sorted_usec_list_t sul; @@ -98,8 +98,10 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10); - lws_ss_set_metadata(m->ss, "ctype", "myctype", 7); + if (lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10)) + lwsl_err("%s set metadata uptag failed\n", __func__); + if (lws_ss_set_metadata(m->ss, "ctype", "myctype", 7)) + lwsl_err("%s set metadata ctype failed\n", __func__); return lws_ss_client_connect(m->ss); case LWSSSCS_ALL_RETRIES_FAILED: diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/CMakeLists.txt new file mode 100644 index 00000000..6944e7fb --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/CMakeLists.txt @@ -0,0 +1,135 @@ +project(lws-minimal-secure-streams-stress C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-secure-streams-stress) + +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 (NOT WIN32) +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + find_program(VALGRIND "valgrind") + + if (LWS_CTEST_INTERNET_AVAILABLE AND NOT WIN32) + + # + # When running in CI, wait for a lease on the resources + # before starting this test, so the server does not get + # thousands of simultaneous tls connection attempts + # + # sai-resource holds the lease on the resources until + # the time given in seconds or the sai-resource instance + # exits, whichever happens first + # + # If running under Sai, creates a lock test called "res_sspcmin" + # + + sai_resource(warmcat_conns 1 40 sspcmin) + + # + # simple test not via proxy + # + + if (VALGRIND) + message("testing via valgrind") + add_test(NAME ssstress-warmcat COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ -c 4 --budget 5) + else() + add_test(NAME ssstress-warmcat COMMAND lws-minimal-secure-streams-stress -c 4 --budget 5) + endif() + + set_tests_properties(ssstress-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-stress + TIMEOUT 60) + if (DEFINED ENV{SAI_OVN}) + set_tests_properties(ssstress-warmcat PROPERTIES FIXTURES_REQUIRED "res_sspcmin") + endif() + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) + + # + # Define test dep to bring up and take down the test + # proxy + # + + if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # uds abstract namespace for linux + set(CTEST_SOCKET_PATH "@ctest-sspstress-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + else() + # filesystem socket for others + set(CTEST_SOCKET_PATH "/tmp/ctest-sspstress-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + endif() + add_test(NAME st_ssstressproxy COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + ssstressproxy $ + -i ${CTEST_SOCKET_PATH} ) + set_tests_properties(st_ssstressproxy PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP ssstressproxy TIMEOUT 800) + + add_test(NAME ki_ssstressproxy COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + ssstressproxy $ + -i ${CTEST_SOCKET_PATH}) + set_tests_properties(ki_ssstressproxy PROPERTIES FIXTURES_CLEANUP ssstressproxy) + + # + # the client part that will connect to the proxy + # + + if (VALGRIND) + message("testing via valgrind") + add_test(NAME sspc-minimalstress COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ -i +${CTEST_SOCKET_PATH} -c 4 --budget 5) + else() + add_test(NAME sspc-minimalstress COMMAND lws-minimal-secure-streams-stress-client -i +${CTEST_SOCKET_PATH} -c 4 --budget 5) + endif() + + set(fixlist "ssstressproxy") + if (DEFINED ENV{SAI_OVN}) + list(APPEND fixlist "res_ssproxy") + endif() + + set_tests_properties(sspc-minimalstress PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-stress + FIXTURES_REQUIRED "${fixlist}" + TIMEOUT 40) + + endif() + + 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.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() +endif() diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/README.md b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/README.md new file mode 100644 index 00000000..2b24f0f1 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/README.md @@ -0,0 +1,22 @@ +# lws minimal secure streams stress + +This is the same as minimal-secure-streams, except you can have it perform concurrent +SS connections and a budget of sequential connections. + +It basically forks as many times as `-c ` and each fork does `--budget ` +SS connections one after the other. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15| +-c |Fork this many times on init| +--budget |Each fork sequentially does this many SS connections (default 1)| +--pass-limit |By default the pass limit is the budget, but if doing fault injection you can set a lower limit here| diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/minimal-secure-streams.c new file mode 100644 index 00000000..ad5713a9 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-stress/minimal-secure-streams.c @@ -0,0 +1,756 @@ +/* + * lws-minimal-secure-streams + * + * Written in 2010-2021 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 + +// #define FORCE_OS_TRUST_STORE + +/* + * 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, test_respmap, test_ots, + budget = 1, predicted_good = 1, good, orig_budget; +static unsigned int timeout_ms = 8000; +static lws_state_notify_link_t nl; +struct lws_context *context; +static lws_sorted_usec_list_t sul_timeout; /* for each process to complete */ + +/* + * 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. + */ +#if !defined(FORCE_OS_TRUST_STORE) + "{\"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=" + "\"}" +#endif + "]," + "\"trust_stores\": [" /* named cert chains */ +#if !defined(FORCE_OS_TRUST_STORE) + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"" + "]" + "}" +#endif + "]," + "\"s\": [" +#if !defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + /* + * "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-v4.2-v2.json\"," +#endif + "\"tls\":" "true," + "\"opportunistic\":" "true," +#if !defined(FORCE_OS_TRUST_STORE) + "\"tls_trust_store\":" "\"le_via_isrg\"," +#endif + "\"retry\":" "\"default\"" +#else + "{\"mintest\": {" + "\"endpoint\": \"warmcat.com\"," + "\"port\": 443," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"http_url\": \"index.html?uptag=${uptag}\"," + "\"metadata\": [{" + " \"uptag\": \"X-Upload-Tag:\"" + "}, {" + " \"xctype\": \"X-Content-Type:\"" + "}]," + "\"tls\": true," + "\"opportunistic\": true," + "\"retry\": \"default\"," + "\"timeout_ms\": 2000," + "\"direct_proto_str\": true," + "\"tls_trust_store\": \"le_via_isrg\"" +#endif + "}},{" + /* + * "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 amt; + + struct lws_genhash_ctx hash_ctx; +} myss_t; + +static int +create_ss(struct lws_context *cx); + +#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 + +static void +process_timeout(lws_sorted_usec_list_t *sul) +{ + lwsl_err("%s: process timed out\n", __func__); + + exit(1); +} + +/* secure streams payload interface */ + +static lws_ss_state_return_t +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + + if (flags & LWSSS_FLAG_PERF_JSON) + return LWSSSSRET_OK; + +#if !defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + myss_t *m = (myss_t *)userobj; + const char *md_srv = "not set", *md_test = "not set"; + size_t md_srv_len = 7, md_test_len = 7; + + lws_ss_get_metadata(m->ss, "srv", (const void **)&md_srv, &md_srv_len); + lws_ss_get_metadata(m->ss, "test", (const void **)&md_test, &md_test_len); + lwsl_ss_user(m->ss, "len %d, flags: %d, srv: %.*s, test: %.*s", + (int)len, flags, (int)md_srv_len, md_srv, + (int)md_test_len, md_test); + + lwsl_hexdump_ss_info(m->ss, buf, len); +#endif + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + } + + return LWSSSSRET_OK; +} + +static lws_ss_state_return_t +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + //myss_t *m = (myss_t *)userobj; + + /* in this example, we don't send stuff */ + + return LWSSSSRET_TX_DONT_SEND; +} + +static lws_ss_state_return_t +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + const char *md_test = "not set"; + size_t md_test_len = 7; + int i; + static const char * imd_test_keys[8] = { + "server:", + "content-security-policy:", + "strict-transport-security:", + "test-custom-header:", + "x-xss-protection:", + "x-content-type-options:", + "x-frame-options:", + "x-non-exist:", + }; +#endif + + lwsl_ss_user(m->ss, "%s (%d), ord 0x%x", + lws_ss_state_name((int)state), state, (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + return lws_ss_client_connect(m->ss); + + case LWSSSCS_CONNECTING: + lws_ss_start_timeout(m->ss, timeout_ms); + + if (lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; +#if !defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + if (lws_ss_set_metadata(m->ss, "ctype", "myctype", 7)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; +#else + if (lws_ss_set_metadata(m->ss, "X-Test-Type1:", "myctype1", 8)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + if (lws_ss_set_metadata(m->ss, "X-Test-Type2:", "myctype2", 8)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + if (lws_ss_set_metadata(m->ss, "Content-Type:", "myctype", 7)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; +#endif + break; + + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + bad = 2; + break; + + case LWSSSCS_CONNECTED: +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + lwsl_cx_user(context, "get direct metadata"); + for (i = 0; i < 8; i++) { + md_test = "not set"; + lws_ss_get_metadata(m->ss, imd_test_keys[i], + (const void **)&md_test, &md_test_len); + lwsl_ss_user(m->ss, " test key:[%s], got [%s]", + imd_test_keys[i], md_test); + } +#endif + break; + + case LWSSSCS_QOS_ACK_REMOTE: /* transaction assertively succeeded */ + lwsl_ss_notice(m->ss, "LWSSSCS_QOS_ACK_REMOTE"); + good++; + break; /* disconnected will move us on */ + + case LWSSSCS_QOS_NACK_REMOTE: /* transaction assertively failed */ + lwsl_ss_notice(m->ss, "LWSSSCS_QOS_NACK_REMOTE"); + break; /* disconnected will move us on */ + + case LWSSSCS_DISCONNECTED: /* attempt is over */ + if (budget) + create_ss(context); + else + interrupted = 1; + return LWSSSSRET_DESTROY_ME; + + case LWSSSCS_TIMEOUT: + lwsl_ss_notice(m->ss, "LWSSSCS_TIMEOUT"); + bad = 3; + if (budget) + create_ss(context); + else + interrupted = 1; + return LWSSSSRET_DESTROY_ME; + + case LWSSSCS_USER_BASE: + lwsl_ss_notice(m->ss, "LWSSSCS_USER_BASE"); + break; + + default: + break; + } + + return LWSSSSRET_OK; +} + +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) +static void +myss_headers_dump(void *userobj, const uint8_t *buf, size_t len, int done) +{ + lwsl_cx_user(context, "%lu done: %s", len, done ? "true" : "false"); + + lwsl_hexdump_err(buf, len); +} +#endif + +static int +create_ss(struct lws_context *cx) +{ + lws_ss_info_t ssi; + + budget--; + lwsl_cx_notice(cx, "starting"); + + /* 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; +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) + ssi.dump = myss_headers_dump; +#endif + ssi.user_alloc = sizeof(myss_t); + ssi.streamtype = test_ots ? "mintest-ots" : + (test_respmap ? "respmap" : "mintest"); + + if (lws_ss_create(cx, 0, &ssi, NULL, NULL, NULL, NULL)) { + lwsl_cx_err(context, "failed to create ss"); + return -1; + } + + lwsl_cx_notice(cx, "started"); + + 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 *cx = 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) + + /* + * 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) + 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) { + create_ss(cx); + } + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +#if defined(LWS_WITH_SYS_METRICS) + +static int +my_metric_report(lws_metric_pub_t *mp) +{ + lws_metric_bucket_t *sub = mp->u.hist.head; + char buf[192]; + + do { + if (lws_metrics_format(mp, &sub, buf, sizeof(buf))) + lwsl_cx_user(context, "%s: %s\n", __func__, buf); + } while ((mp->flags & LWSMTFL_REPORT_HIST) && sub); + + /* 0 = leave metric to accumulate, 1 = reset the metric */ + + return 1; +} + +static const lws_system_ops_t system_ops = { + .metric_report = my_metric_report, +}; + +#endif + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +static lws_log_cx_t my_log_cx = { + .lll_flags = LLLF_LOG_CONTEXT_AWARE | + LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER, + .refcount_cb = lws_log_use_cx_file, + .u.emit_cx = lws_log_emit_cx_file, +}; + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + int n = 0, expected = 0, concurrent = 1; + char cxname[16], logpath[128]; + const char *p; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + if ((p = lws_cmdline_option(argc, argv, "-c"))) + concurrent = atoi(p); + + if (concurrent < 0 || concurrent > 100) + return 1; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + my_log_cx.lll_flags = (uint32_t)(LLLF_LOG_CONTEXT_AWARE | atoi(p)); + + lws_strncpy(cxname, "ctx0", sizeof(cxname)); + + for (n = 0; n < concurrent - 1; n++) { + if (fork()) { +#if defined(WIN32) + Sleep(1); +#else + usleep(1000); +#endif + lws_snprintf(cxname, sizeof(cxname), "ctx%d", n + 1); + break; + } + } + + /* + * Arrange that each process's context logs to a different file + */ + + info.log_cx = &my_log_cx; + info.vhost_name = cxname; + lws_snprintf(logpath, sizeof(logpath), "/tmp/%s.log", cxname); + my_log_cx.opaque = (void *)logpath; + + 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 (lws_cmdline_option(argc, argv, "--respmap")) + test_respmap = 1; + + if (lws_cmdline_option(argc, argv, "--ots")) + /* + * Use a streamtype that relies on the OS trust store for + * validation + */ + test_ots = 1; + + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) + timeout_ms = (unsigned int)atoi(p); + + if ((p = lws_cmdline_option(argc, argv, "--budget"))) + budget = atoi(p); + + predicted_good = budget; + orig_budget = budget; + + if ((p = lws_cmdline_option(argc, argv, "--pass-limit"))) + predicted_good = atoi(p); + + info.fd_limit_per_thread = 1 + 26 + 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 = (uint16_t)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_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#endif + +#if defined(LWS_WITH_MBEDTLS) + + /* uncomment to force mbedtls to load a system trust store like + * openssl does + * + * info.mbedtls_client_preload_filepath = + * "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"; + */ +#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; + +#if defined(LWS_WITH_SYS_METRICS) + info.system_ops = &system_ops; + info.metrics_prefix = "ssmex"; +#endif + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + goto bail; + } + + /* timeout for each forked process */ + + lws_sul_schedule(context, 0, &sul_timeout, process_timeout, + (lws_usec_t)((lws_usec_t)budget * + (lws_usec_t)timeout_ms * LWS_US_PER_MS)); + +#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 */ + + n = 0; + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_sul_cancel(&sul_timeout); + lws_context_destroy(context); + +bail: + lwsl_user(" good: %d / %d budget, pass limit %d\n", good, orig_budget, + predicted_good); + if (good < predicted_good) + bad = 1; + + if ((p = lws_cmdline_option(argc, argv, "--expected-exit"))) + expected = atoi(p); + + if (bad == expected) { + lwsl_user("Completed: OK (seen expected %d)\n", expected); + return 0; + } else + lwsl_err("Completed: failed: exit %d, expected %d\n", bad, expected); + + return 1; +} diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/CMakeLists.txt index 82444943..cd194e18 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/CMakeLists.txt @@ -53,11 +53,11 @@ if (requirements) -i ${CTEST_SOCKET_PATH} -d1039) set_tests_properties(st_sstfproxy PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP sstfproxy TIMEOUT 800) - add_test(NAME ki_ssproxy COMMAND + add_test(NAME ki_sstfproxy COMMAND ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh sstfproxy $ -i ${CTEST_SOCKET_PATH}) - set_tests_properties(ki_ssproxy PROPERTIES FIXTURES_CLEANUP sstfproxy) + set_tests_properties(ki_sstfproxy PROPERTIES FIXTURES_CLEANUP sstfproxy) # # the client part that will connect to the proxy diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/minimal-secure-streams-testsfail.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/minimal-secure-streams-testsfail.c index eee55046..7a09523a 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/minimal-secure-streams-testsfail.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-testsfail/minimal-secure-streams-testsfail.c @@ -63,26 +63,37 @@ static const char * const default_ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" - "\"},{" + "{\"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=" + "\"},{" "\"digicert_global_root_g2\": \"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7K" "GSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMR" "GlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDE" @@ -155,9 +166,9 @@ static const char * const default_ss_policy = "\"stack\": [\"digicert_global_ca_g2\", \"digicert_global_root_g2\"]" "}, { \"name\": \"arca1\", \"stack\": [\"amazon_root_ca_1\"]}," "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" "]," @@ -377,7 +388,7 @@ static const char * const default_ss_policy = "\"tls\": true," "\"opportunistic\": true," "\"retry\": \"default\"," - "\"tls_trust_store\": \"le_via_dst\"" + "\"tls_trust_store\": \"le_via_isrg\"" "}},{" "\"badcert_expired\": {" "\"endpoint\": \"warmcat.com\"," @@ -388,7 +399,7 @@ static const char * const default_ss_policy = "\"tls\": true," "\"opportunistic\": true," "\"retry\": \"default\"," - "\"tls_trust_store\": \"le_via_dst\"" + "\"tls_trust_store\": \"le_via_isrg\"" "}},{" "\"badcert_selfsigned\": {" "\"endpoint\": \"invalidca.badcert.warmcat.com\"," @@ -401,7 +412,7 @@ static const char * const default_ss_policy = "\"h2q_oflow_txcr\": true," "\"opportunistic\": true," "\"retry\": \"default\"," - "\"tls_trust_store\": \"le_via_dst\"" + "\"tls_trust_store\": \"le_via_isrg\"" "}}" "]}" ; @@ -433,19 +444,22 @@ struct tests_seq { "h1:80 just get 200", "t_h1", 5 * LWS_US_PER_SEC, LWSSSCS_QOS_ACK_REMOTE, (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, { "h1:443 just get 200", "t_h1_tls", 5 * LWS_US_PER_SEC, LWSSSCS_QOS_ACK_REMOTE, (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, { "h2:443 just get 200", "t_h2_tls", 5 * LWS_US_PER_SEC, LWSSSCS_QOS_ACK_REMOTE, (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, /* @@ -458,19 +472,22 @@ struct tests_seq { "h1:80 timeout after connection", "d_h1", 5 * LWS_US_PER_SEC, LWSSSCS_TIMEOUT, (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, { "h1:443 timeout after connection", "d_h1_tls", 5 * LWS_US_PER_SEC, LWSSSCS_TIMEOUT, (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, { "h2:443 timeout after connection", "d_h2_tls", 5 * LWS_US_PER_SEC, LWSSSCS_TIMEOUT, (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, /* @@ -482,19 +499,22 @@ struct tests_seq { "h1:80 NXDOMAIN", "nxd_h1", 65 * LWS_US_PER_SEC, LWSSSCS_UNREACHABLE, (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, { "h1:443 NXDOMAIN", "nxd_h1_tls", 35 * LWS_US_PER_SEC, LWSSSCS_UNREACHABLE, (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, { "h2:443 NXDOMAIN", "nxd_h2_tls", 35 * LWS_US_PER_SEC, LWSSSCS_UNREACHABLE, (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) | - (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_ALL_RETRIES_FAILED) + (1 << LWSSSCS_TIMEOUT) | (1 << LWSSSCS_ALL_RETRIES_FAILED), + 0 }, /* @@ -507,17 +527,20 @@ struct tests_seq { { "h1:80 NXDOMAIN exhaust retries", "nxd_h1", 65 * LWS_US_PER_SEC, LWSSSCS_ALL_RETRIES_FAILED, - (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) + (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE), + 0 }, { "h1:443 NXDOMAIN exhaust retries", "nxd_h1_tls", 65 * LWS_US_PER_SEC, LWSSSCS_ALL_RETRIES_FAILED, - (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) + (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE), + 0 }, { "h2:443 NXDOMAIN exhaust retries", "nxd_h2_tls", 65 * LWS_US_PER_SEC, LWSSSCS_ALL_RETRIES_FAILED, - (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE) + (1 << LWSSSCS_QOS_ACK_REMOTE) | (1 << LWSSSCS_QOS_NACK_REMOTE), + 0 }, /* @@ -553,17 +576,20 @@ struct tests_seq { { "h1:badcert_hostname", "badcert_hostname", 6 * LWS_US_PER_SEC, LWSSSCS_ALL_RETRIES_FAILED, - (1 << LWSSSCS_QOS_NACK_REMOTE) + (1 << LWSSSCS_QOS_NACK_REMOTE), + 0 }, { "h1:badcert_expired", "badcert_expired", 6 * LWS_US_PER_SEC, LWSSSCS_ALL_RETRIES_FAILED, - (1 << LWSSSCS_QOS_NACK_REMOTE) + (1 << LWSSSCS_QOS_NACK_REMOTE), + 0 }, { "h1:badcert_selfsigned", "badcert_selfsigned", 6 * LWS_US_PER_SEC, LWSSSCS_ALL_RETRIES_FAILED, - (1 << LWSSSCS_QOS_NACK_REMOTE) + (1 << LWSSSCS_QOS_NACK_REMOTE), + 0 }, }; diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/CMakeLists.txt new file mode 100644 index 00000000..5272d8f7 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/CMakeLists.txt @@ -0,0 +1,130 @@ +project(lws-minimal-secure-streams-threads C) +cmake_minimum_required(VERSION 2.8.12) +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_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 AND NOT WIN32) +# win32 has problems with pthreads.h and timespec struct redef + add_executable(${PROJECT_NAME} minimal-secure-streams-threads.c) + + find_program(VALGRIND "valgrind") + + if (LWS_CTEST_INTERNET_AVAILABLE AND NOT WIN32) + + if (VALGRIND) + add_test(NAME ss-threads COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $) + else() + + add_test(NAME ss-threads COMMAND lws-minimal-secure-streams-threads) + endif() + set_tests_properties(ss-threads + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-threads + 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-threads.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() + + # + # Define test dep to bring up and take down the test + # proxy + # + + if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # uds abstract namespace for linux + set(CTEST_SOCKET_PATH "@ctest-sspthreads_sspc-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + else() + # filesystem socket for others + set(CTEST_SOCKET_PATH "/tmp/ctest-sspthreads_sspc-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + endif() + + add_test(NAME st_ssprxthreads_sspc COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + ssproxythreads_sspc $ + -i ${CTEST_SOCKET_PATH} -d1039) + set_tests_properties(st_ssprxthreads_sspc PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP ssproxythreads_sspc TIMEOUT 800) + + add_test(NAME ki_ssprxthreads_sspc COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + ssproxythreads_sspc $ + -i ${CTEST_SOCKET_PATH} -d1039) + set_tests_properties(ki_ssprxthreads_sspc PROPERTIES FIXTURES_CLEANUP ssproxythreads_sspc) + + # + # the client part that will connect to the proxy + # + + if (VALGRIND) + message("testing via valgrind") + add_test(NAME sspcthreads_sspc COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ -i +${CTEST_SOCKET_PATH}) + else() + add_test(NAME sspcthreads_sspc COMMAND lws-minimal-secure-streams-threads-client -i +${CTEST_SOCKET_PATH}) + endif() + set_tests_properties(sspcthreads_sspc PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-threads + FIXTURES_REQUIRED "ssproxythreads_sspc" + TIMEOUT 80) + + + # + # Define test dep to bring up and take down the test + # proxy + # + + if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # uds abstract namespace for linux + set(CTEST_SOCKET_PATH "@ctest-mul-sspthreads_sspc-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + else() + # filesystem socket for others + set(CTEST_SOCKET_PATH "/tmp/ctest-mul-sspthreads_sspc-$ENV{SAI_PROJECT}-$ENV{SAI_OVN}") + endif() + + add_test(NAME st_mulssprxthreads_sspc COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + mulssproxythreads_sspc $ + -i ${CTEST_SOCKET_PATH} -d1039) + set_tests_properties(st_mulssprxthreads_sspc PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP mulssproxythreads_sspc TIMEOUT 800) + + add_test(NAME ki_mulssprxthreads_sspc COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + mulssproxythreads_sspc $ + -i ${CTEST_SOCKET_PATH} -d1039) + set_tests_properties(ki_mulssprxthreads_sspc PROPERTIES FIXTURES_CLEANUP mulssproxythreads_sspc) + + endif() + +endif() diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/README.md b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/README.md new file mode 100644 index 00000000..3f4cb1d7 --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/README.md @@ -0,0 +1,27 @@ +# lws minimal secure streams threads + +This application creates a thread and calls `lws_cancel_service()` +at 10Hz. + +It creates a Secure Stream and checks that it is getting the +`LWSSSCS_EVENT_WAIT_CANCELLED` state for each `lws_cancel_service()`. + +It also demonstrates how to protect a shared data area between the +thread(s) and the lws event loop thread to put data there that +describes what the thread wants the service loop to do. + +It exits after 3s with a 0 return code if the SS saw the expected +amount of messages. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/minimal-secure-streams-threads.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/minimal-secure-streams-threads.c new file mode 100644 index 00000000..bc4d42ff --- /dev/null +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams-threads/minimal-secure-streams-threads.c @@ -0,0 +1,296 @@ +/* + * lws-minimal-secure-streams-threads + * + * Written in 2010-2021 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates how other threads can wake the lws event loop and ask it + * to do things via lws_cancel_service(), notifying Secure Streams using the + * LWSSSCS_EVENT_WAIT_CANCELLED state callback. + * + * Because of what we're testing, we don't actually connect the SS just create + * it and wait for the states we are testing for to come at 10Hz. + * + * We run the test for 3s and check we got an appropriate amount of wakes + * to call it a success. + * + * You can use the same pattern to have any amount of shared data protected by + * the mutex, containing whatever the other threads want the lws event loop + * thread to do for them. + */ + +#include +#include +#include + +#include + +/* + * Define this to cause an ss api access from a foreign thread, it will + * assert. This is for testing lws, don't do this in your code. + */ +// #define DO_ILLEGAL_API_THREAD + +static int interrupted, bad = 1, finished; +static lws_sorted_usec_list_t sul_timeout; +static struct lws_context *context; +static pthread_t pthread_spam; +static int wakes, started_thread; + +#if defined(DO_ILLEGAL_API_THREAD) +static struct lws_ss_handle *ss; /* only needed for DO_ILLEGAL_API_THREAD */ +#endif + +/* the data shared between the spam thread and the lws event loop */ + +static pthread_mutex_t lock_shared; +static int shared_counter; + + +#if !defined(LWS_SS_USE_SSPC) +static const char * const default_ss_policy = + "{" + "\"schema-version\":1," + "\"s\": [" + "{" + "\"mintest\": {" + "\"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 ... */ +} myss_t; + +static void * +thread_spam(void *d) +{ + + do { + pthread_mutex_lock(&lock_shared); /* --------- shared lock { */ + + /* + * prepare the shared data area to indicate whatever it is that + * we want doing on the main event loop. In this case, we just + * bump a counter, but it can be any amount of data prepared, + * eg, whole info struct for a connection we want. + */ + + shared_counter++; + + lwsl_notice("%s: cancelling wait from spam thread: %d\n", + __func__, shared_counter); + lws_cancel_service(context); + +#if defined(DO_ILLEGAL_API_THREAD) + /* + * ILLEGAL... + * We cannot call any other lws api from a foreign thread + */ + + if (ss) + lws_ss_request_tx(ss); +#endif + + pthread_mutex_unlock(&lock_shared); /* } shared lock ------- */ + + usleep(100000); /* wait 100ms and signal main thread again */ + + } while (!finished); + + pthread_exit(NULL); + + return NULL; +} + + +static lws_ss_state_return_t +myss_state(void *userobj, void *h_src, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + // myss_t *m = (myss_t *)userobj; + void *retval; + + switch (state) { + case LWSSSCS_CREATING: + if (pthread_create(&pthread_spam, NULL, thread_spam, NULL)) { + lwsl_err("thread creation failed\n"); + return LWSSSSRET_DESTROY_ME; + } + started_thread = 1; + break; + case LWSSSCS_DESTROYING: + finished = 1; + if (started_thread) + pthread_join(pthread_spam, &retval); + break; + + case LWSSSCS_EVENT_WAIT_CANCELLED: + pthread_mutex_lock(&lock_shared); /* --------- shared lock { */ + lwsl_notice("%s: LWSSSCS_EVENT_WAIT_CANCELLED: %d, shared: %d\n", + __func__, ++wakes, shared_counter); + pthread_mutex_unlock(&lock_shared); /* } shared lock ------- */ + break; + + default: + break; + } + + return LWSSSSRET_OK; +} + +static const lws_ss_info_t ssi_lws_threads = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + /* we don't actually do any rx or tx in this test */ + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "mintest", + .manual_initial_tx_credit = 0, +}; + +static void +sul_timeout_cb(lws_sorted_usec_list_t *sul) +{ + lwsl_notice("%s: test finishing\n", __func__); + interrupted = 1; +} + + +static 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) +{ + if (current != LWS_SYSTATE_OPERATIONAL || target != LWS_SYSTATE_OPERATIONAL) + return 0; + + /* the test SS.. not going to connect it, just see if the cancel_service + * messages are coming + */ + + if (lws_ss_create(context, 0, &ssi_lws_threads, NULL, +#if defined(DO_ILLEGAL_API_THREAD) + &ss, +#else + NULL, +#endif + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + + return -1; + } + + /* set up the test timeout */ + + lws_sul_schedule(context, 0, &sul_timeout, sul_timeout_cb, + 3 * LWS_US_PER_SEC); + + return 0; +} + +int main(int argc, const char **argv) +{ + lws_state_notify_link_t notifier = { { NULL, NULL, NULL}, + system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + struct lws_context_creation_info info; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS Secure Streams threads 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; + { + 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 = (uint16_t)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; + } +#endif + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.register_notifier_list = na; + + /* 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 + + /* the event loop */ + + while (lws_service(context, 0) >= 0 && !interrupted) + ; + + /* compare what happened with what we expect */ + + if (wakes > 10) + /* OSX can do the usleep thread slower than 100ms */ + bad = 0; + + lwsl_notice("wakes %d\n", wakes); + +#if defined(LWS_SS_USE_SSPC) +bail: +#endif + lws_sul_cancel(&sul_timeout); + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt index 9559799a..7f576ed2 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt @@ -13,7 +13,8 @@ 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) -require_lws_config(LWS_WITH_GENCRYPTO 1 requirements) + +require_lws_config(LWS_WITH_SYS_FAULT_INJECTION 1 has_fault_injection) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) @@ -52,11 +53,41 @@ if (requirements) set_tests_properties(ss-warmcat PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams - TIMEOUT 20) + TIMEOUT 40) if (DEFINED ENV{SAI_OVN}) set_tests_properties(ss-warmcat PROPERTIES FIXTURES_REQUIRED "res_sspcmin") endif() + if (has_fault_injection) + if (VALGRIND) + add_test(NAME ss-warmcat-fi1 COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ + --fault-injection "ss/ss_create_destroy_me" + --expected-exit 1) + add_test(NAME ss-warmcat-fi2 COMMAND + ${VALGRIND} --tool=memcheck --leak-check=yes --num-callers=20 + $ + --fault-injection "ss/ss_no_streamtype_policy" + --expected-exit 1) + else() + add_test(NAME ss-warmcat-fi1 COMMAND lws-minimal-secure-streams + --fault-injection "ss/ss_create_destroy_me" + --expected-exit 1) + add_test(NAME ss-warmcat-fi2 COMMAND lws-minimal-secure-streams + --fault-injection "ss/ss_no_streamtype_policy" + --expected-exit 1) + endif() + + set_tests_properties(ss-warmcat-fi1 + ss-warmcat-fi2 + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams + TIMEOUT 5) + + endif() + + if (HAS_LWS_WITH_SECURE_STREAMS_PROXY_API OR LWS_WITH_SECURE_STREAMS_PROXY_API) # diff --git a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index 202a696a..260ec509 100644 --- a/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/3rdparty/libwebsockets/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -1,7 +1,7 @@ /* * lws-minimal-secure-streams * - * Written in 2010-2020 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -24,6 +24,8 @@ #include #include +// #define FORCE_OS_TRUST_STORE + /* * uncomment to force network traffic through 127.0.0.1:1080 * @@ -38,7 +40,7 @@ // #define VIA_LOCALHOST_SOCKS static int interrupted, bad = 1, force_cpd_fail_portal, - force_cpd_fail_no_internet, test_respmap, test_blob; + force_cpd_fail_no_internet, test_respmap, test_ots, test_local; static unsigned int timeout_ms = 3000; static lws_state_notify_link_t nl; @@ -82,37 +84,53 @@ static const char * const default_ss_policy = * We fetch the real policy from there using SS and switch to * using that. */ - "{\"dst_root_x3\": \"" - "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" +#if !defined(FORCE_OS_TRUST_STORE) + "{\"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=" "\"}" +#endif "]," "\"trust_stores\": [" /* named cert chains */ +#if !defined(FORCE_OS_TRUST_STORE) "{" - "\"name\": \"le_via_dst\"," + "\"name\": \"le_via_isrg\"," "\"stack\": [" - "\"dst_root_x3\"" + "\"isrg_root_x1\"" "]" "}" +#endif "]," "\"s\": [" - /* +#if !defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + /* * "fetch_policy" decides from where the real policy * will be fetched, if present. Otherwise the initial * policy is treated as the whole, hardcoded, policy. @@ -129,8 +147,40 @@ static const char * const default_ss_policy = #endif "\"tls\":" "true," "\"opportunistic\":" "true," - "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_dst\"" +#if !defined(FORCE_OS_TRUST_STORE) + "\"tls_trust_store\":" "\"le_via_isrg\"," +#endif + "\"retry\":" "\"default\"" +#else + "{\"mintest\": {" + "\"endpoint\": \"warmcat.com\"," + "\"port\": 443," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"http_url\": \"index.html?uptag=${uptag}\"," + "\"metadata\": [{" + " \"uptag\": \"X-Upload-Tag:\"" + "}, {" + " \"xctype\": \"X-Content-Type:\"" + "}]," + "\"tls\": true," + "\"opportunistic\": true," + "\"retry\": \"default\"," + "\"timeout_ms\": 2000," + "\"direct_proto_str\": true," + "\"tls_trust_store\": \"le_via_dst\"" + "}}," + "{\"mintest_local\": {" + "\"endpoint\": \"localhost\"," + "\"port\": 8000," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"tls\": false," + "\"opportunistic\": true," + "\"retry\": \"default\"," + "\"timeout_ms\": 2000," + "\"direct_proto_str\": true" +#endif "}},{" /* * "captive_portal_detect" describes @@ -157,7 +207,7 @@ static const char * const default_ss_policy = #endif typedef struct myss { - struct lws_ss_handle *ss; + struct lws_ss_handle *ss; void *opaque_data; /* ... application specific state ... */ lws_sorted_usec_list_t sul; @@ -186,70 +236,26 @@ static const char *canned_root_token_payload = /* secure streams payload interface */ -static const uint8_t expected_blob_hash[] = { - 0xed, 0x57, 0x20, 0xc1, 0x68, 0x30, 0x81, 0x0e, - 0x58, 0x29, 0xdf, 0xb9, 0xb6, 0x6c, 0x96, 0xb2, - 0xe2, 0x4e, 0xfc, 0x4f, 0x93, 0xaa, 0x5e, 0x38, - 0xc7, 0xff, 0x41, 0x50, 0xd3, 0x1c, 0xfb, 0xbf -}; - static lws_ss_state_return_t myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) { - myss_t *m = (myss_t *)userobj; - const char *md_srv = "not set", *md_test = "not set"; - size_t md_srv_len = 7, md_test_len = 7; if (flags & LWSSS_FLAG_PERF_JSON) return LWSSSSRET_OK; - if (test_blob) { - - if (flags & LWSSS_FLAG_SOM) { - if (lws_genhash_init(&m->hash_ctx, LWS_GENHASH_TYPE_SHA256)) - lwsl_err("%s: hash init failed\n", __func__); - m->amt = 0; - } - - if (lws_genhash_update(&m->hash_ctx, buf, len)) - lwsl_err("%s: hash failed\n", __func__); - - if ((m->amt + len) / 102400 != (m->amt / 102400)) { - - lwsl_user("%s: blob test: rx %uKiB\n", __func__, - (unsigned int)((m->amt + len) / 1024)); - /* - * Let's make it hard for client to keep up with onward - * server, delay 50ms after every 100K received, so we - * are forcing the flow control action at the proxy - */ - usleep(50000); - } - - m->amt += len; - - if (flags & LWSSS_FLAG_EOM) { - uint8_t digest[32]; - lws_genhash_destroy(&m->hash_ctx, digest); - - if (!memcmp(expected_blob_hash, digest, 32)) { - lwsl_user("%s: SHA256 match\n", __func__); - bad = 0; - } - - interrupted = 1; - } - - return LWSSSSRET_OK; - } +#if !defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + myss_t *m = (myss_t *)userobj; + const char *md_srv = "not set", *md_test = "not set"; + size_t md_srv_len = 7, md_test_len = 7; lws_ss_get_metadata(m->ss, "srv", (const void **)&md_srv, &md_srv_len); lws_ss_get_metadata(m->ss, "test", (const void **)&md_test, &md_test_len); - lwsl_user("%s: len %d, flags: %d, srv: %.*s, test: %.*s\n", __func__, (int)len, flags, (int)md_srv_len, md_srv, (int)md_test_len, md_test); + lwsl_hexdump_info(buf, len); +#endif /* * If we received the whole message, for our example it means @@ -274,11 +280,30 @@ myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, return LWSSSSRET_TX_DONT_SEND; } +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) +static const char * long_token_str = "{xxx:AWlKJMMISWJBQpAFqU0UqKNsnSY5usx2YtjOZJUQALNtapRxu/9VJqMk5IFVhxrNvMTj+RCGN6B5OlUK80lbbC8fAmQi7SoFB8DHN9UCRHkENriC62FjMNiBVfgkjMWx+60GioZy4bI2kCcyisd2CujQuSVllUmQFXhVq291cJhFfcKR4c3CUCuhouUfK2e1BY5InDMnzUXozOh+vhjJSeBIfp4HRUAgMpV7FXlHy8D5tgbmPbHs9X81MEsHTcERd3pG10B5fu1PzH+dJbr5F2WTK+VFWZI99B89ijEZWsPg447IK3F+0HHGseZfpRjKw2bY94id/TmncTxS0cqchDJlYg+Jt33U4HkUPqLdRiGIfJb6wSATx4S9ZKUumeJAgXpC6ytlUeqPpxzgnD7Tle5CDVb+eVzRk2FJfjiZdjbYxXhWYntPusLP/PGrorkqLw0ZKw+OJ+fhbkwF+0SCUelWEc8WPtfxCDAIdEQ7X5P4vUlBNEfuHprgHbZry680syFetY2q3ZtCmWemLHhqdDGu4lFgcQPCbb9b8eOE8oAbUQPm9AeV84RXSLevBG44JST/W2JuYguOk8SFlsRkfHb3dvxfB15Lg+mtH0tGRoumSMT0CFJL4ClTiKdpJo1LPgEd2/f13GcukEWirjqDRxpepJYWaVAMbxbaPBNfRHw9S8Fn8qU9/9eAxmbEqOopep5I/Zd99CT2PdE0Qyami1p05/BEc5dgvjg3SNDmAc/8kWC0AcvoSfApXI1TaVzbNh68b79h6IaIvXXorY5274u0lVB357JIRiYo29QbJgNn4bDbIr5ScM8GnFHQdKy29/TZoq4zbGMPX2X2t41vXRVeoZteu7vNWsMQD6eIomVq9qFWnoEEaR30woGF+8ZSIEu9JH5LKVZVFx46lipnjE8CDt5qrYCjwiGIswdLLMmIltxRmDt4aefTFpre7lhgUChv7ndJARvsn8rvtg2Hg1qKyfCAHa/LBblM29cRjLFqp7tWLJO7N27SWiqEhai6pmSmSYzqoPL+rnLS69rkdIuUwkA==}{yyy:jG8akvr66AXK+W1KSUyGIN3Yk4WNRLSIZHWTu8rsvQAuKwv9a/ZxrxIa+R1xW7cwmPSgINcJ4Jo7kGK9n7aDnsSDt3uMSHsu2iNg+UtIaJcO0XO6fPaLmOPLpOIU5AfG9HnbWUjeniNRrUGN8+26JH/9EB1h/X++Ow61CCHm8mKrgR1lXsKuNyqDYIrjoI3KCCVKZkdWygyFAXQ6l0sr+pUyNpv6H5w1xlC8dtI88091b/njuRlHsnoCa1zRtgqH0L4igLNu0zzOkH/ATsVS3Pyn4nsoRiGVFgzJZ0e2jT2McmDTxNeEHcafQSxeN7pztDFHT3ukUU9QFFtFDdzlug==}{vvv:VGbzgaVrLrJ+92ACJ0TEtQ==}{eeee:QURQVG9rZW6FbmNyeXB0aW6uS2v5}{sssss:mG+}"; +#endif + static lws_ss_state_return_t myss_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { myss_t *m = (myss_t *)userobj; +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + const char *md_test = "not set"; + size_t md_test_len = 7; + int i; + static const char * imd_test_keys[8] = { + "server:", + "content-security-policy:", + "strict-transport-security:", + "test-custom-header:", + "x-xss-protection:", + "x-content-type-options:", + "x-frame-options:", + "x-non-exist:", + }; +#endif lwsl_user("%s: %s (%d), ord 0x%x\n", __func__, lws_ss_state_name((int)state), state, (unsigned int)ack); @@ -290,15 +315,29 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, case LWSSSCS_CONNECTING: lws_ss_start_timeout(m->ss, timeout_ms); - if (!test_blob) { - if (lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10)) - /* can fail, eg due to OOM, retry later if so */ - return LWSSSSRET_DISCONNECT_ME; + if (lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; +#if !defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + if (lws_ss_set_metadata(m->ss, "ctype", "myctype", 7)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; +#else + if (lws_ss_set_metadata(m->ss, "X-Test-Type1:", "myctype1", 8)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + if (lws_ss_set_metadata(m->ss, "X-Test-Type2:", "myctype2", 8)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + if (lws_ss_set_metadata(m->ss, "Content-Type:", "myctype", 7)) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; + if (lws_ss_set_metadata(m->ss, "X-ADP-Authentication-Token:", + long_token_str, strlen(long_token_str))) + /* can fail, eg due to OOM, retry later if so */ + return LWSSSSRET_DISCONNECT_ME; - if (lws_ss_set_metadata(m->ss, "ctype", "myctype", 7)) - /* can fail, eg due to OOM, retry later if so */ - return LWSSSSRET_DISCONNECT_ME; - } +#endif break; case LWSSSCS_ALL_RETRIES_FAILED: @@ -306,6 +345,16 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, interrupted = 1; bad = 2; break; + case LWSSSCS_CONNECTED: +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + lwsl_user("%s: get direct metadata\n", __func__); + for (i = 0; i < 8; i++) { + md_test = "not set"; + lws_ss_get_metadata(m->ss, imd_test_keys[i], (const void **)&md_test, &md_test_len); + lwsl_user("%s test key:[%s], got [%s]\n", __func__, imd_test_keys[i], md_test); + } +#endif + break; case LWSSSCS_QOS_ACK_REMOTE: lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); @@ -329,6 +378,15 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, return LWSSSSRET_OK; } +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) +static void +myss_headers_dump(void *userobj, const uint8_t *buf, size_t len, int done) +{ + lwsl_user("%s: %lu done: %s\n", __func__, len, done?"true":"false"); + + lwsl_hexdump_err(buf, len); +} +#endif static int app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, int current, int target) @@ -412,14 +470,21 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, ssi.rx = myss_rx; ssi.tx = myss_tx; ssi.state = myss_state; +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) + ssi.dump = myss_headers_dump; +#endif ssi.user_alloc = sizeof(myss_t); - ssi.streamtype = test_blob ? "bulkproxflow" : - (test_respmap ? "respmap" : "mintest"); + ssi.streamtype = test_ots ? "mintest-ots" : + (test_respmap ? "respmap" : + (test_local ? "mintest_local" : + "mintest")); if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { lwsl_err("%s: failed to create secure stream\n", __func__); + interrupted = 1; + lws_cancel_service(context); return -1; } } @@ -475,6 +540,8 @@ int main(int argc, const char **argv) memset(&info, 0, sizeof info); lws_cmdline_option_handle_builtin(argc, argv, &info); + //lws_set_log_level(LLL_USER | LLL_ERR | LLL_DEBUG | LLL_NOTICE | LLL_INFO, NULL); + lwsl_user("LWS secure streams test client [-d]\n"); /* these options are mutually exclusive if given */ @@ -488,19 +555,19 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "--respmap")) test_respmap = 1; + if (lws_cmdline_option(argc, argv, "--ots")) + /* + * Use a streamtype that relies on the OS trust store for + * validation + */ + test_ots = 1; + + if (lws_cmdline_option(argc, argv, "--local")) + test_local = 1; + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) timeout_ms = (unsigned int)atoi(p); - if (lws_cmdline_option(argc, argv, "--blob")) { - test_blob = 1; - if (timeout_ms == 3000) - /* - * Don't use default 3s, we're going to be a lot - * slower - */ - timeout_ms = 60000; - } - info.fd_limit_per_thread = 1 + 6 + 1; info.port = CONTEXT_PORT_NO_LISTEN; #if defined(LWS_SS_USE_SSPC) @@ -530,6 +597,16 @@ int main(int argc, const char **argv) LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif +#if defined(LWS_WITH_MBEDTLS) + + /* uncomment to force mbedtls to load a system trust store like + * openssl does + * + * info.mbedtls_client_preload_filepath = + * "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"; + */ +#endif + /* integrate us with lws system state management when context created */ nl.name = "app"; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-binance/main.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-binance/main.c index 2aa31ca1..152d393e 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-binance/main.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-binance/main.c @@ -326,8 +326,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, } static const struct lws_protocols protocols[] = { - { "lws-minimal-client", callback_minimal, 0, 0, }, - { NULL, NULL, 0, 0 } + { "lws-minimal-client", callback_minimal, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/minimal-ws-client-echo.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/minimal-ws-client-echo.c index a74d4541..285d17f1 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/minimal-ws-client-echo.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/minimal-ws-client-echo.c @@ -19,7 +19,7 @@ static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_MINIMAL_CLIENT_ECHO, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static struct lws_context *context; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c index 6f98e31d..fceee133 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c @@ -87,10 +87,9 @@ static const struct lws_protocols protocols[] = { { "lws-ping-test", callback_minimal_pingtest, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c index 1f6aa47a..bdc7058b 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c @@ -27,9 +27,9 @@ #include "protocol_lws_minimal_pmd_bulk.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted, options; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c index 6883caec..281a841a 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c @@ -60,10 +60,9 @@ static const struct lws_protocols protocols[] = { { "dumb-increment-protocol", callback_dumb_increment, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c index ce223c32..19a22cc2 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c @@ -128,7 +128,7 @@ callback(struct lws *wsi, enum lws_callback_reasons reason, static const struct lws_protocols protocols[] = { { "spam-rx-tx", callback, 4096, 4096, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void @@ -179,13 +179,18 @@ int main(int argc, const char **argv) LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; } - if ((p = lws_cmdline_option(argc, argv, "-p"))) + if ((p = lws_cmdline_option(argc, argv, "-p"))) { port = atoi(p); + if (port > 65535 || port < 0) + return 1; + } if ((p = lws_cmdline_option(argc, argv, "-n"))) { n = atoi(p); if (n < 1) n = 1; + if (n > LWS_MAX_SMP) + n = LWS_MAX_SMP; if (n < nclients) nclients = n; lwsl_notice("Start test clients: %d\n", nclients); diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c index 20b89df2..62580eed 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c @@ -1,7 +1,7 @@ /* * lws-minimal-ws-client-spam * - * Written in 2010-2019 by Andy Green + * Written in 2010-2021 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -110,8 +110,10 @@ callback_minimal_spam(struct lws *wsi, enum lws_callback_reasons reason, break; } } - if (tries == closed + errors) + if (tries == closed + errors) { interrupted = 1; + lws_cancel_service(lws_get_context(wsi)); + } break; /* --- client callbacks --- */ @@ -126,8 +128,10 @@ callback_minimal_spam(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CLOSED: closed++; - if (tries == closed + errors) + if (tries == closed + errors) { interrupted = 1; + lws_cancel_service(lws_get_context(wsi)); + } if (tries == limit) { lwsl_user("%s: leaving CLOSED (try %d, est %d, sent %d, closed %d, err %d)\n", __func__, tries, est, sent, closed, errors); @@ -171,9 +175,16 @@ static const struct lws_protocols protocols[] = { "lws-spam-test", callback_minimal_spam, sizeof(struct pss), - 0, + 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM +}; + +static struct lws_protocol_vhost_options pvo = { + NULL, /* "next" pvo linked-list */ + NULL, /* "child" pvo linked-list */ + "lws-spam-test", /* protocol name we belong to on this vhost */ + "OK" /* ignored */ }; static void @@ -206,6 +217,7 @@ int main(int argc, const char **argv) 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.pvo = &pvo; #if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) /* * OpenSSL uses the system trust store. mbedTLS has to be told which diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c index d31beb13..dd8757cb 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c @@ -284,10 +284,9 @@ static const struct lws_protocols protocols[] = { { "lws-minimal-broker", callback_minimal_broker, - 0, - 0, + 0, 0, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/README.md b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/README.md index bf87ab36..5cf297b3 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/README.md +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/README.md @@ -20,6 +20,7 @@ Option|Meaning -j|Allow selfsigned tls cert -k|Allow insecure certs -m|Skip server hostname check +-n|Skip tls usage -e|Allow expired certs --protocol|Use a specific ws subprotocol rather than dumb-increment-protocol, eg, `--protocol myprotocol` diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer index 8dc39efc..01ad0dc7 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/libwebsockets.org.cer @@ -1,21 +1,32 @@ - -----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 +-----BEGIN CERTIFICATE----- +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= -----END CERTIFICATE----- diff --git a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c index 8c46739d..70b24614 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c @@ -137,8 +137,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, } static const struct lws_protocols protocols[] = { - { "lws-minimal-client", callback_minimal, 0, 0, }, - { NULL, NULL, 0, 0 } + { "lws-minimal-client", callback_minimal, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static void diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-broker/minimal-ws-broker.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-broker/minimal-ws-broker.c index 88ee988b..cab9af55 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-broker/minimal-ws-broker.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-broker/minimal-ws-broker.c @@ -22,9 +22,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-raw-proxy/minimal-ws-raw-proxy.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-raw-proxy/minimal-ws-raw-proxy.c index 4fd5cb8e..6f66c445 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-raw-proxy/minimal-ws-raw-proxy.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-raw-proxy/minimal-ws-raw-proxy.c @@ -362,10 +362,10 @@ callback_proxy_raw_client(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, - { "lws-ws-raw-ws", callback_proxy_ws_server, 0, 1024 }, - { "lws-ws-raw-raw", callback_proxy_raw_client, 0, 1024 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, + { "lws-ws-raw-ws", callback_proxy_ws_server, 0, 1024, 0, NULL, 0 }, + { "lws-ws-raw-raw", callback_proxy_raw_client, 0, 1024, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static const lws_retry_bo_t retry = { diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/minimal-ws-server-echo.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/minimal-ws-server-echo.c index e3b217f9..7a8e9462 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/minimal-ws-server-echo.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/minimal-ws-server-echo.c @@ -19,7 +19,7 @@ static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_MINIMAL_SERVER_ECHO, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted, port = 7681, options; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c index 6f655c4f..fbda4612 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c @@ -21,9 +21,9 @@ #include "protocol_lws_minimal_pmd_bulk.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted, options; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c index 7a31a1f3..06ecb679 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c @@ -21,9 +21,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/minimal-ws-server-pmd.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/minimal-ws-server-pmd.c index 2b7b567f..4496a351 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/minimal-ws-server-pmd.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/minimal-ws-server-pmd.c @@ -21,9 +21,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c index c87ad201..f4e02a28 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c @@ -22,9 +22,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c index 61beb54d..63a12024 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c @@ -33,9 +33,9 @@ #include "protocol_lws_minimal_threadpool.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c index b9b7d35d..1b8299a4 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c @@ -36,9 +36,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static struct lws_context *context; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt index 4fedb04d..098a174e 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt @@ -13,6 +13,7 @@ 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_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c index 8a74eb74..43c5ea37 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c @@ -35,13 +35,14 @@ #define COUNT_THREADS 2 static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static struct lws_context *context; -static int interrupted; +static int interrupted, started; +static pthread_t pthread_service[COUNT_THREADS]; static const struct lws_http_mount mount = { /* .mount_next */ NULL, /* linked-list "next" */ @@ -98,18 +99,58 @@ void *thread_service(void *threadid) return NULL; } +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; + void *retval; + + if (current != target) + return 0; + + switch (current) { + case LWS_SYSTATE_OPERATIONAL: + lwsl_notice(" Service threads: %d\n", + lws_get_count_threads(context)); + + /* start all the service threads */ + + for (started = 1; started < lws_get_count_threads(context); + started++) + if (pthread_create(&pthread_service[started], NULL, + thread_service, + (void *)(lws_intptr_t)started)) + lwsl_err("Failed to start service thread\n"); + break; + case LWS_SYSTATE_CONTEXT_DESTROYING: + /* wait for all the service threads to exit */ + + while ((--started) >= 1) + pthread_join(pthread_service[started], &retval); + + break; + } + + return 0; +} + +lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; +lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + void sigint_handler(int sig) { interrupted = 1; + lws_cancel_service(context); } int main(int argc, const char **argv) { - int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; - pthread_t pthread_service[COUNT_THREADS]; + int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; struct lws_context_creation_info info; const char *p; - void *retval; + int n = 0; signal(SIGINT, sigint_handler); @@ -125,6 +166,7 @@ int main(int argc, const char **argv) info.protocols = protocols; info.pvo = &pvo; /* per-vhost options */ info.count_threads = COUNT_THREADS; + info.register_notifier_list = na; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; @@ -134,19 +176,8 @@ int main(int argc, const char **argv) 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); + while (n >= 0 && !interrupted) + n = lws_service(context, 0); lws_context_destroy(context); diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c index fb96a1bf..9e4627e6 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c @@ -33,9 +33,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static int interrupted; diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c index de97e6c7..a7f0d1ac 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c @@ -48,9 +48,9 @@ callback_protocol(struct lws *wsi, enum lws_callback_reasons reason, } static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, - { "timer", callback_protocol, 0, 0 }, - { NULL, NULL, 0, 0 } /* terminator */ + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 }, + { "timer", callback_protocol, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM }; static const lws_retry_bo_t retry = { diff --git a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c index 741d1741..6cfce7f9 100644 --- a/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c +++ b/3rdparty/libwebsockets/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c @@ -22,9 +22,9 @@ #include "protocol_lws_minimal.c" static struct lws_protocols protocols[] = { - { "http", lws_callback_http_dummy, 0, 0 }, + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0}, LWS_PLUGIN_PROTOCOL_MINIMAL, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; static const lws_retry_bo_t retry = { @@ -54,6 +54,11 @@ static const struct lws_http_mount mount = { /* .basic_auth_login_file */ NULL, }; +#if defined(LWS_WITH_PLUGINS) +/* if plugins enabled, only protocols explicitly named in pvo bind to vhost */ +static struct lws_protocol_vhost_options pvo = { NULL, NULL, "lws-minimal", "" }; +#endif + void sigint_handler(int sig) { interrupted = 1; @@ -85,6 +90,9 @@ int main(int argc, const char **argv) info.mounts = &mount; info.protocols = protocols; info.vhost_name = "localhost"; +#if defined(LWS_WITH_PLUGINS) + info.pvo = &pvo; +#endif info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; diff --git a/3rdparty/libwebsockets/plugins/acme-client/protocol_lws_acme_client.c b/3rdparty/libwebsockets/plugins/acme-client/protocol_lws_acme_client.c index d202085b..729c4482 100644 --- a/3rdparty/libwebsockets/plugins/acme-client/protocol_lws_acme_client.c +++ b/3rdparty/libwebsockets/plugins/acme-client/protocol_lws_acme_client.c @@ -1,7 +1,7 @@ /* * libwebsockets ACME client protocol plugin * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2022 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 @@ -21,16 +21,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * - * Acme is in a big messy transition at the moment from a homebrewed api - * to an IETF one. The old repo for the homebrew api (they currently - * implement) is marked up as deprecated and "not accurate[ly] reflect[ing]" - * what they implement, but the IETF standard, currently at v7 is not yet - * implemented at let's encrypt (ETA Jan 2018). - * * This implementation follows draft 7 of the IETF standard, and falls back - * to whatever differences exist for Boulder's tls-sni-01 challenge. The - * tls-sni-02 support is there but nothing to test it against at the time of - * writing (Nov 1 2017). + * to whatever differences exist for Boulder's tls-sni-01 challenge. + * tls-sni-02 is also supported. */ #if !defined (LWS_PLUGIN_STATIC) @@ -143,16 +136,16 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, struct lws_vhost *vhost = lws_get_vhost(wsi); struct acme_connection *ac = lws_vhost_user(vhost); uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; int n; switch (reason) { case LWS_CALLBACK_HTTP: - lwsl_notice("%s: ca connection received, key_auth %s\n", - __func__, ac->key_auth); + lwsl_wsi_notice(wsi, "CA connection received, key_auth %s", + ac->key_auth); if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) { - lwsl_notice("%s: add status failed\n", __func__); + lwsl_wsi_warn(wsi, "add status failed"); return -1; } @@ -160,14 +153,13 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/plain", 10, &p, end)) { - lwsl_notice("%s: add content_type failed\n", __func__); + lwsl_wsi_warn(wsi, "add content_type failed"); return -1; } n = (int)strlen(ac->key_auth); if (lws_add_http_header_content_length(wsi, (lws_filepos_t)n, &p, end)) { - lwsl_notice("%s: add content_length failed\n", - __func__); + lwsl_wsi_warn(wsi, "add content_length failed"); return -1; } @@ -175,13 +167,12 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, WSI_TOKEN_HTTP_CONTENT_DISPOSITION, (unsigned char *)"attachment", 10, &p, end)) { - lwsl_notice("%s: add content_dispo failed\n", __func__); + lwsl_wsi_warn(wsi, "add content_dispo failed"); return -1; } if (lws_finalize_write_http_header(wsi, start, &p, end)) { - lwsl_notice("%s: finalize http header failed\n", - __func__); + lwsl_wsi_warn(wsi, "finalize http header failed"); return -1; } @@ -190,10 +181,10 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_HTTP_WRITEABLE: p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "%s", ac->key_auth); - lwsl_notice("%s: len %d\n", __func__, lws_ptr_diff(p, start)); + // lwsl_notice("%s: len %d\n", __func__, lws_ptr_diff(p, start)); if (lws_write(wsi, (uint8_t *)start, lws_ptr_diff_size_t(p, start), LWS_WRITE_HTTP_FINAL) != lws_ptr_diff(p, start)) { - lwsl_err("_write content failed\n"); + lwsl_wsi_err(wsi, "_write content failed"); return 1; } @@ -234,7 +225,7 @@ jws_create_packet(struct lws_jwe *jwe, const char *payload, size_t len, n = LWS_PRE + 2048; buf = malloc((unsigned int)n); if (!buf) { - lwsl_notice("%s: malloc %d failed\n", __func__, n); + lwsl_warn("%s: malloc %d failed\n", __func__, n); return -1; } @@ -680,14 +671,14 @@ lws_acme_load_create_auth_keys(struct per_vhost_data__lws_acme_client *vhd, n = lws_genrsa_new_keypair(vhd->context, &vhd->rsactx, LGRSAM_PKCS1_1_5, vhd->jwk.e, bits); if (n) { - lwsl_notice("failed to create keypair\n"); + lwsl_vhost_warn(vhd->vhost, "failed to create keypair"); return 1; } lwsl_notice("...keypair generated\n"); if (lws_jwk_save(&vhd->jwk, vhd->pvop[LWS_TLS_SET_AUTH_PATH])) { - lwsl_notice("unable to save %s\n", + lwsl_vhost_warn(vhd->vhost, "unable to save %s", vhd->pvop[LWS_TLS_SET_AUTH_PATH]); return 1; } @@ -709,8 +700,8 @@ lws_acme_start_acquisition(struct per_vhost_data__lws_acme_client *vhd, /* * ...well... we should try to do something about it then... */ - lwsl_notice("%s: ACME cert needs creating / updating: " - "vhost %s\n", __func__, lws_get_vhost_name(vhd->vhost)); + lwsl_vhost_notice(vhd->vhost, "ACME cert needs creating / updating: " + "vhost %s", lws_get_vhost_name(vhd->vhost)); vhd->ac = malloc(sizeof(*vhd->ac)); memset(vhd->ac, 0, sizeof(*vhd->ac)); @@ -795,11 +786,13 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, switch ((int)reason) { case LWS_CALLBACK_PROTOCOL_INIT: + if (vhd) + return 0; vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), lws_get_protocol(wsi), sizeof(struct per_vhost_data__lws_acme_client)); - if (vhd) - return 0; + if (!vhd) + return -1; vhd->context = lws_get_context(wsi); vhd->protocol = lws_get_protocol(wsi); @@ -867,7 +860,12 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, vhd->pvop[LWS_TLS_SET_CERT_PATH]); vhd->fd_updated_cert = lws_open(buf, LWS_O_WRONLY | LWS_O_CREAT | - LWS_O_TRUNC, 0600); + LWS_O_TRUNC + /*do not replace \n to \r\n on Windows */ + #ifdef WIN32 + | O_BINARY + #endif + , 0600); if (vhd->fd_updated_cert < 0) { lwsl_err("unable to create update cert file %s\n", buf); return -1; @@ -875,9 +873,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", vhd->pvop[LWS_TLS_SET_KEY_PATH]); vhd->fd_updated_key = lws_open(buf, LWS_O_WRONLY | LWS_O_CREAT | - LWS_O_TRUNC, 0600); + /*do not replace \n to \r\n on Windows */ + #ifdef WIN32 + O_BINARY | + #endif + LWS_O_TRUNC, 0600); if (vhd->fd_updated_key < 0) { - lwsl_err("unable to create update key file %s\n", buf); + lwsl_vhost_err(vhd->vhost, "unable to create update key file %s", buf); + return -1; } #endif @@ -929,35 +932,18 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, * Client */ - case LWS_CALLBACK_CLIENT_ESTABLISHED: - lwsl_notice("%s: CLIENT_ESTABLISHED\n", __func__); - break; - - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_notice("%s: CLIENT_CONNECTION_ERROR: %p\n", __func__, wsi); - break; - - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - lwsl_notice("%s: CLOSED_CLIENT_HTTP: %p\n", __func__, wsi); - break; - - case LWS_CALLBACK_CLOSED: - lwsl_notice("%s: CLOSED: %p\n", __func__, wsi); - break; - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - lwsl_notice("%s: ESTABLISHED_CLIENT_HTTP:" - "%p, state:%d, status:%d\n", __func__, wsi, - ac->state, lws_http_client_http_response(wsi)); if (!ac) break; + ac->resp = (int)lws_http_client_http_response(wsi); + /* we get a new nonce each time */ if (lws_hdr_total_length(wsi, WSI_TOKEN_REPLAY_NONCE) && lws_hdr_copy(wsi, ac->replay_nonce, sizeof(ac->replay_nonce), WSI_TOKEN_REPLAY_NONCE) < 0) { - lwsl_notice("%s: nonce too large\n", __func__); + lwsl_vhost_warn(vhd->vhost, "nonce too large"); goto failed; } @@ -967,11 +953,12 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lejp_construct(&ac->jctx, cb_dir, vhd, jdir_tok, LWS_ARRAY_SIZE(jdir_tok)); break; + case ACME_STATE_NEW_NONCE: /* - * we try to * register our keys next. - * It's OK if it ends up * they're already registered, - * this eliminates any * gaps where we stored the key + * we try to register our keys next. + * It's OK if it ends up they're already registered, + * this eliminates any gaps where we stored the key * but registration did not complete for some reason... */ ac->state = ACME_STATE_NEW_ACCOUNT; @@ -981,8 +968,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, cwsi = lws_acme_client_connect(vhd->context, vhd->vhost, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "failed to connect to acme"); goto failed; } @@ -991,28 +977,26 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_NEW_ACCOUNT: if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_LOCATION)) { - lwsl_notice("%s: no Location\n", __func__); + lwsl_vhost_warn(vhd->vhost, "no Location"); goto failed; } if (lws_hdr_copy(wsi, ac->acct_id, sizeof(ac->acct_id), WSI_TOKEN_HTTP_LOCATION) < 0) { - lwsl_notice("%s: Location too large\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Location too large"); goto failed; } ac->kid = ac->acct_id; - lwsl_notice("Location: %s\n", ac->acct_id); + lwsl_vhost_notice(vhd->vhost, "Location: %s", ac->acct_id); break; case ACME_STATE_NEW_ORDER: if (lws_hdr_copy(wsi, ac->order_url, sizeof(ac->order_url), WSI_TOKEN_HTTP_LOCATION) < 0) { - lwsl_notice("%s: missing cert location:\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "missing cert location"); goto failed; } @@ -1061,7 +1045,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ",\"contact\": [\"mailto:%s\"]}", vhd->pvop_active[LWS_TLS_REQ_ELEMENT_EMAIL]); - puts(start); strcpy(ac->active_url, ac->urls[JAD_NEW_ACCOUNT_URL]); pkt_add_hdrs: if (lws_gencrypto_jwe_alg_to_definition("RSA1_5", @@ -1096,7 +1079,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, WSI_TOKEN_HTTP_CONTENT_TYPE, (uint8_t *)content_type, 21, pp, pend)) { - lwsl_notice("could not add content type\n"); + lwsl_vhost_warn(vhd->vhost, "could not add content type"); goto failed; } @@ -1104,7 +1087,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (uint8_t *)buf, n, pp, pend)) { - lwsl_notice("could not add content length\n"); + lwsl_vhost_warn(vhd->vhost, "could not add content length"); goto failed; } @@ -1122,12 +1105,10 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, "}", vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME]); - puts(start); strcpy(ac->active_url, ac->urls[JAD_NEW_ORDER_URL]); goto pkt_add_hdrs; case ACME_STATE_AUTHZ: - puts(start); strcpy(ac->active_url, ac->authz_url); goto pkt_add_hdrs; @@ -1136,7 +1117,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, end = &buf[sizeof(buf) - 1]; p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{}"); - puts(start); strcpy(ac->active_url, ac->challenge_uri); goto pkt_add_hdrs; @@ -1147,7 +1127,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_POLLING_CSR: if (ac->goes_around) break; - + lwsl_vhost_notice(vhd->vhost, "Generating ACME CSR... may take a little while"); p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{\"csr\":\""); n = lws_tls_acme_sni_csr_create(vhd->context, &vhd->pvop_active[0], @@ -1155,12 +1135,11 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->alloc_privkey_pem, &ac->len_privkey_pem); if (n < 0) { - lwsl_notice("CSR generation failed\n"); + lwsl_vhost_warn(vhd->vhost, "CSR generation failed"); goto failed; } p += n; p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"}"); - puts(start); strcpy(ac->active_url, ac->finalize_url); goto pkt_add_hdrs; @@ -1175,7 +1154,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: - lwsl_notice("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n"); if (!ac) break; @@ -1187,7 +1165,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (lws_write(wsi, (uint8_t *)ac->buf + LWS_PRE, (size_t)ac->len, LWS_WRITE_HTTP_FINAL) < 0) return -1; - lwsl_notice("wrote %d\n", ac->len); + ac->pos = ac->len; lws_client_http_body_pending(wsi, 0); break; @@ -1204,28 +1182,29 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_AUTHZ: case ACME_STATE_NEW_ORDER: case ACME_STATE_DIRECTORY: - ((char *)in)[len] = '\0'; - puts(in); + m = lejp_parse(&ac->jctx, (uint8_t *)in, (int)len); if (m < 0 && m != LEJP_CONTINUE) { lwsl_notice("lejp parse failed %d\n", m); goto failed; } break; + case ACME_STATE_NEW_ACCOUNT: - ((char *)in)[len] = '\0'; - puts(in); break; + case ACME_STATE_DOWNLOAD_CERT: - ((char *)in)[len] = '\0'; - puts(in); - /* it should be the DER cert! */ - if ((unsigned int)ac->cpos + len > sizeof(ac->buf)) { - lwsl_notice("Incoming cert is too large!\n"); - goto failed; + /* + * It should be the DER cert... + * ACME 2.0 can send certs chain with 3 certs, store only first bytes + */ + if ((unsigned int)ac->cpos + len > sizeof(ac->buf)) + len = sizeof(ac->buf) - (unsigned int)ac->cpos; + + if (len) { + memcpy(&ac->buf[ac->cpos], in, len); + ac->cpos += (int)len; } - memcpy(&ac->buf[ac->cpos], in, len); - ac->cpos += (int)len; break; default: break; @@ -1234,9 +1213,9 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, /* unchunked content */ case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - lwsl_notice("%s: LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n", __func__); if (!ac) return -1; + switch (ac->state) { default: { @@ -1252,7 +1231,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - lwsl_notice("%s: COMPLETED_CLIENT_HTTP\n", __func__); if (!ac) return -1; @@ -1281,7 +1259,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_NEW_ACCOUNT: if ((ac->resp >= 200 && ac->resp < 299) || - ac->resp == 409) { + ac->resp == 409) { /* * Our account already existed, or exists now. * @@ -1324,8 +1302,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, vhd->vhost, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) - lwsl_notice("%s: failed to connect\n", - __func__); + lwsl_notice("%s: failed to connect\n", __func__); return -1; /* close the completed client connection */ @@ -1335,13 +1312,12 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lws_snprintf(buf, sizeof(buf), "Auth failed: %s", ac->detail); failreason = buf; - lwsl_notice("auth failed\n"); + lwsl_vhost_warn(vhd->vhost, "auth failed"); goto failed; } - lwsl_notice("chall: %s (%d)\n", ac->chall_token, - ac->resp); + lwsl_vhost_info(vhd->vhost, "chall: %s (%d)\n", ac->chall_token, ac->resp); if (!ac->chall_token[0]) { - lwsl_notice("no challenge\n"); + lwsl_vhost_warn(vhd->vhost, "no challenge"); goto failed; } @@ -1362,7 +1338,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (n < 0) goto failed; - lwsl_notice("key_auth: '%s'\n", ac->key_auth); + lwsl_vhost_notice(vhd->vhost, "key_auth: '%s'", ac->key_auth); lws_snprintf(ac->http01_mountpoint, sizeof(ac->http01_mountpoint), @@ -1378,8 +1354,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->ci.mounts = &ac->mount; - /* listen on the same port as the vhost that triggered - * us */ + /* listen on the same port as the vhost that triggered us */ ac->ci.port = 80; /* make ourselves protocols[0] for the new vhost */ @@ -1396,7 +1371,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (!ac->vhost) goto failed; - lwsl_notice("challenge_uri %s\n", ac->challenge_uri); + lwsl_vhost_notice(vhd->vhost, "challenge_uri %s", ac->challenge_uri); /* * The challenge-specific vhost is up... let the ACME @@ -1408,14 +1383,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->challenge_uri, "POST"); if (!cwsi) { - lwsl_notice("%s: connect failed\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Connect failed"); goto failed; } return -1; /* close the completed client connection */ case ACME_STATE_START_CHALL: - lwsl_notice("%s: COMPLETED start chall: %s\n", - __func__, ac->challenge_uri); + lwsl_vhost_notice(vhd->vhost, "COMPLETED start chall: %s", + ac->challenge_uri); poll_again: ac->state = ACME_STATE_POLLING; lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE, @@ -1433,8 +1408,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "failed to connect to acme"); goto failed; } @@ -1443,18 +1417,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_POLLING: if (ac->resp == 202 && strcmp(ac->status, "invalid") && - strcmp(ac->status, "valid")) { - lwsl_notice("status: %s\n", ac->status); + strcmp(ac->status, "valid")) goto poll_again; - } - if (!strcmp(ac->status, "pending")) { - lwsl_notice("status: %s\n", ac->status); + if (!strcmp(ac->status, "pending")) goto poll_again; - } if (!strcmp(ac->status, "invalid")) { - lwsl_notice("%s: Challenge failed\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Challenge failed"); lws_snprintf(buf, sizeof(buf), "Challenge Invalid: %s", ac->detail); @@ -1462,7 +1432,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, goto failed; } - lwsl_notice("Challenge passed\n"); + lwsl_vhost_notice(vhd->vhost, "ACME challenge passed"); /* * The challenge was validated... so delete the @@ -1487,8 +1457,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Failed to connect to acme"); goto failed; } @@ -1503,8 +1472,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (ac->resp != 200) { if (ac->goes_around++ == 30) { - lwsl_notice("%s: too many retries\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Too many retries"); goto failed; } @@ -1514,9 +1482,8 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: " - "failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, + "Failed to connect to acme"); goto failed; } @@ -1531,8 +1498,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Failed to connect to acme"); goto failed; } @@ -1541,11 +1507,11 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_DOWNLOAD_CERT: if (ac->resp != 200) { - lwsl_notice("download cert failed on resp %d\n", + lwsl_vhost_warn(vhd->vhost, "Download cert failed on resp %d", ac->resp); goto failed; } - lwsl_notice("The cert was sent..\n"); + lwsl_vhost_notice(vhd->vhost, "The cert was sent.."); lws_acme_report_status(vhd->vhost, LWS_CUS_ISSUE, NULL); @@ -1554,13 +1520,25 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, * ac->buf, length in ac->cpos; and the key in * ac->alloc_privkey_pem, length in * ac->len_privkey_pem. + * ACME 2.0 can send certs chain with 3 certs, we need save only first */ + { + char *end_cert = strstr(ac->buf, "END CERTIFICATE-----"); + + if (end_cert) { + ac->cpos = (int)(lws_ptr_diff_size_t(end_cert, ac->buf) + sizeof("END CERTIFICATE-----") - 1); + } else { + ac->cpos = 0; + lwsl_vhost_err(vhd->vhost, "Unable to find ACME cert!"); + goto failed; + } + } n = lws_plat_write_cert(vhd->vhost, 0, vhd->fd_updated_cert, ac->buf, (size_t)ac->cpos); if (n) { - lwsl_err("unable to write ACME cert! %d\n", n); + lwsl_vhost_err(vhd->vhost, "unable to write ACME cert! %d", n); goto failed; } @@ -1572,16 +1550,16 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, vhd->fd_updated_key, ac->alloc_privkey_pem, ac->len_privkey_pem)) { - lwsl_err("unable to write ACME key!\n"); + lwsl_vhost_err(vhd->vhost, "unable to write ACME key!"); goto failed; } /* * we have written the persistent copies */ - lwsl_notice("%s: Updated certs written for %s " - "to %s.upd and %s.upd\n", __func__, - vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME], + lwsl_vhost_notice(vhd->vhost, "Updated certs written for %s " + "to %s.upd and %s.upd", + vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME], vhd->pvop_active[LWS_TLS_SET_CERT_PATH], vhd->pvop_active[LWS_TLS_SET_KEY_PATH]); @@ -1593,7 +1571,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->buf, (size_t)ac->cpos, ac->alloc_privkey_pem, ac->len_privkey_pem)) { - lwsl_notice("problem setting certs\n"); + lwsl_vhost_warn(vhd->vhost, "problem setting certs"); } lws_acme_finished(vhd); @@ -1615,7 +1593,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->challenge_uri, "GET"); if (!cwsi) { - lwsl_notice("%s: failed to connect\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Failed to connect"); goto failed; } break; @@ -1627,7 +1605,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, return 0; failed: - lwsl_notice("%s: failed out\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Failed out"); lws_acme_report_status(vhd->vhost, LWS_CUS_FAILED, failreason); lws_acme_finished(vhd); diff --git a/3rdparty/libwebsockets/plugins/deaddrop/protocol_lws_deaddrop.c b/3rdparty/libwebsockets/plugins/deaddrop/protocol_lws_deaddrop.c index 79f736c0..0e51507b 100644 --- a/3rdparty/libwebsockets/plugins/deaddrop/protocol_lws_deaddrop.c +++ b/3rdparty/libwebsockets/plugins/deaddrop/protocol_lws_deaddrop.c @@ -383,7 +383,7 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason, struct pss_deaddrop *pss = (struct pss_deaddrop *)user; uint8_t buf[LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; char fname[256], *wp; const char *cp; int n, m, was; diff --git a/3rdparty/libwebsockets/plugins/protocol_client_loopback_test.c b/3rdparty/libwebsockets/plugins/protocol_client_loopback_test.c index 067738f1..ca9b4290 100644 --- a/3rdparty/libwebsockets/plugins/protocol_client_loopback_test.c +++ b/3rdparty/libwebsockets/plugins/protocol_client_loopback_test.c @@ -174,6 +174,7 @@ LWS_VISIBLE const struct lws_protocols client_loopback_test_protocols[] = { callback_client_loopback_test, sizeof(struct per_session_data__client_loopback_test), 1024, /* rx buf size must be >= permessage-deflate rx size */ + 0, NULL, 0 }, }; diff --git a/3rdparty/libwebsockets/plugins/protocol_fulltext_demo.c b/3rdparty/libwebsockets/plugins/protocol_fulltext_demo.c index 0d780993..35d91e19 100644 --- a/3rdparty/libwebsockets/plugins/protocol_fulltext_demo.c +++ b/3rdparty/libwebsockets/plugins/protocol_fulltext_demo.c @@ -65,7 +65,7 @@ callback_fts(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_get_protocol(wsi)); struct pss_fts_demo *pss = (struct pss_fts_demo *)user; uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; struct lws_fts_search_params params; const char *ccp = (const char *)in; struct lws_fts_result *result; diff --git a/3rdparty/libwebsockets/plugins/protocol_lws_openmetrics_export.c b/3rdparty/libwebsockets/plugins/protocol_lws_openmetrics_export.c index ba79fef3..f6b1850b 100644 --- a/3rdparty/libwebsockets/plugins/protocol_lws_openmetrics_export.c +++ b/3rdparty/libwebsockets/plugins/protocol_lws_openmetrics_export.c @@ -626,7 +626,7 @@ callback_lws_openmetrics_prox_agg(struct lws *wsi, } } else { lwsl_warn("%s: proxy-side-bind-name required\n", __func__); - return 1; + return 0; } break; @@ -802,7 +802,7 @@ callback_lws_openmetrics_prox_server(struct lws *wsi, } } else { lwsl_warn("%s: proxy-side-bind-name required\n", __func__); - return 1; + return 0; } break; @@ -971,10 +971,10 @@ callback_lws_openmetrics_prox_client(struct lws *wsi, /* the proxy server uri */ - if (lws_pvo_get_str(in, "ws-server-uri", &cp)) { - lwsl_err("%s: ws-server-uri pvo required\n", __func__); + if (lws_pvo_get_str(in, "ws-server-uri", &cp) || !cp) { + lwsl_warn("%s: ws-server-uri pvo required\n", __func__); - return 1; + return 0; } lws_strncpy(vhd->ws_server_uri, cp, sizeof(vhd->ws_server_uri)); @@ -1162,19 +1162,19 @@ LWS_VISIBLE const struct lws_protocols lws_openmetrics_export_protocols[] = { "lws-openmetrics", callback_lws_openmetrics_export, sizeof(struct pss), - 1024, + 1024, 0, NULL, 0 }, { /* for scraper via ws proxy: http export on listen socket */ "lws-openmetrics-prox-agg", callback_lws_openmetrics_prox_agg, sizeof(struct pss), - 1024, + 1024, 0, NULL, 0 }, { /* metrics proxy server side: ws server for clients to connect to */ "lws-openmetrics-prox-server", callback_lws_openmetrics_prox_server, sizeof(struct pss), - 1024, + 1024, 0, NULL, 0 }, #endif #if defined(LWS_WITH_CLIENT) && defined(LWS_ROLE_WS) @@ -1182,7 +1182,7 @@ LWS_VISIBLE const struct lws_protocols lws_openmetrics_export_protocols[] = { "lws-openmetrics-prox-client", callback_lws_openmetrics_prox_client, sizeof(struct pss), - 1024, + 1024, 0, NULL, 0 }, #endif }; diff --git a/3rdparty/libwebsockets/plugins/protocol_lws_raw_test.c b/3rdparty/libwebsockets/plugins/protocol_lws_raw_test.c index 329663a3..78bb8acd 100644 --- a/3rdparty/libwebsockets/plugins/protocol_lws_raw_test.c +++ b/3rdparty/libwebsockets/plugins/protocol_lws_raw_test.c @@ -278,7 +278,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, void *user, "protocol-lws-raw-test", \ callback_raw_test, \ sizeof(struct per_session_data__raw_test), \ - 1024, /* rx buf size must be >= permessage-deflate rx size */ \ + 1024, /* rx buf size must be >= permessage-deflate rx size */ 0, NULL, 0\ } #if !defined (LWS_PLUGIN_STATIC) diff --git a/3rdparty/libwebsockets/plugins/protocol_post_demo.c b/3rdparty/libwebsockets/plugins/protocol_post_demo.c index 80411889..55ce4eb3 100644 --- a/3rdparty/libwebsockets/plugins/protocol_post_demo.c +++ b/3rdparty/libwebsockets/plugins/protocol_post_demo.c @@ -132,6 +132,12 @@ format_result(struct per_session_data__post_demo *pss) start = p; end = p + sizeof(pss->result) - LWS_PRE - 1; + if (!pss->spa) { + p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), + "pss->spa already NULL"); + goto bail; + } + p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "" ""); +bail: return (int)lws_ptr_diff(p, start); } diff --git a/3rdparty/libwebsockets/plugins/raw-proxy/protocol_lws_raw_proxy.c b/3rdparty/libwebsockets/plugins/raw-proxy/protocol_lws_raw_proxy.c index c0b1ceaa..91d676d1 100644 --- a/3rdparty/libwebsockets/plugins/raw-proxy/protocol_lws_raw_proxy.c +++ b/3rdparty/libwebsockets/plugins/raw-proxy/protocol_lws_raw_proxy.c @@ -194,10 +194,10 @@ callback_raw_proxy(struct lws *wsi, enum lws_callback_reasons reason, if (!vhd) return 0; if (lws_pvo_get_str(in, "onward", &cp)) { - lwsl_err("%s: vh %s: pvo 'onward' required\n", __func__, + lwsl_warn("%s: vh %s: pvo 'onward' required\n", __func__, lws_get_vhost_name(lws_get_vhost(wsi))); - return -1; + return 0; } lws_tokenize_init(&ts, cp, LWS_TOKENIZE_F_DOT_NONTERM | LWS_TOKENIZE_F_MINUS_NONTERM | diff --git a/3rdparty/libwebsockets/plugins/ssh-base/crypto/sc25519.c b/3rdparty/libwebsockets/plugins/ssh-base/crypto/sc25519.c index a12995bc..53acc3e4 100644 --- a/3rdparty/libwebsockets/plugins/ssh-base/crypto/sc25519.c +++ b/3rdparty/libwebsockets/plugins/ssh-base/crypto/sc25519.c @@ -68,8 +68,8 @@ static void barrett_reduce(sc25519 *r, const uint32_t x[64]) if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; carry = q2[31] >> 8; q2[32] += carry; - //carry = q2[32] >> 8; - //q2[33] += carry; + carry = q2[32] >> 8; + q2[33] += carry; for(i=0;i<33;i++)r1[i] = x[i]; for(i=0;i<32;i++) diff --git a/3rdparty/libwebsockets/plugins/ssh-base/include/lws-ssh.h b/3rdparty/libwebsockets/plugins/ssh-base/include/lws-ssh.h index 029d2fc0..8796dd28 100644 --- a/3rdparty/libwebsockets/plugins/ssh-base/include/lws-ssh.h +++ b/3rdparty/libwebsockets/plugins/ssh-base/include/lws-ssh.h @@ -25,6 +25,10 @@ #if !defined(__LWS_SSH_H__) #define __LWS_SSH_H__ +#if defined(LWS_HAVE_SYS_TYPES_H) +#include +#endif + #if defined(LWS_WITH_MBEDTLS) #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" @@ -275,6 +279,11 @@ enum { SSHS_NVC_CHRQ_SUBSYSTEM, + SSHS_NVC_CHRQ_WNDCHANGE_TW, + SSHS_NVC_CHRQ_WNDCHANGE_TH, + SSHS_NVC_CHRQ_WNDCHANGE_TWP, + SSHS_NVC_CHRQ_WNDCHANGE_THP, + SSHS_NVC_CH_EOF, SSHS_NVC_CH_CLOSE, diff --git a/3rdparty/libwebsockets/plugins/ssh-base/sshd.c b/3rdparty/libwebsockets/plugins/ssh-base/sshd.c index d934f3af..cab174f6 100644 --- a/3rdparty/libwebsockets/plugins/ssh-base/sshd.c +++ b/3rdparty/libwebsockets/plugins/ssh-base/sshd.c @@ -533,7 +533,10 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l struct lws_genrsa_ctx ctx; struct lws_ssh_channel *ch; struct lws_subprotocol_scp *scp; - uint8_t *pp, *ps, hash[64], *otmp; + uint8_t *pp, *ps, hash[64]; +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 + uint8_t *otmp = NULL; +#endif uint32_t m; int n; @@ -1247,7 +1250,6 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l LGRSAM_PKCS1_1_5, LWS_GENHASH_TYPE_UNKNOWN)) goto ua_fail; - /* * point to the encrypted signature payload we * were sent @@ -1256,6 +1258,7 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l m = lws_g32(&pp); pp += m; m = lws_g32(&pp); +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 /* * decrypt it, resulting in an error, or some ASN1 @@ -1290,6 +1293,12 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l } free(otmp); + #else + ctx.ctx->MBEDTLS_PRIVATE(len) = m; + n = lws_genrsa_hash_sig_verify(&ctx, hash, + (enum lws_genhash_types)rsa_hash_alg_from_ident(pss->ua->alg), + pp, m) == 0 ? 1 : 0; + #endif lws_genrsa_destroy(&ctx); /* @@ -1474,6 +1483,12 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l SSHS_NVC_CHRQ_SUBSYSTEM); break; } + if (!strcmp(pss->name, "window-change")) { + lwsl_info("%s: window-change\n", __func__); + state_get_u32(pss, + SSHS_NVC_CHRQ_WNDCHANGE_TW); + break; + } if (pss->rq_want_reply) goto chrq_fail; @@ -1629,6 +1644,34 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l break; #endif + /* CHRQ window-change */ + + case SSHS_NVC_CHRQ_WNDCHANGE_TW: + pss->args.pty.width_ch = pss->len; + state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_TH); + break; + case SSHS_NVC_CHRQ_WNDCHANGE_TH: + pss->args.pty.height_ch = pss->len; + state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_TWP); + break; + case SSHS_NVC_CHRQ_WNDCHANGE_TWP: + pss->args.pty.width_px = pss->len; + state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_THP); + break; + case SSHS_NVC_CHRQ_WNDCHANGE_THP: + pss->args.pty.height_px = pss->len; + pss->args.pty.term[0] = 0; + pss->args.pty.modes = NULL; + pss->args.pty.modes_len = 0; + n = 0; + if (pss->vhd->ops && pss->vhd->ops->pty_req) + n = pss->vhd->ops->pty_req(pss->ch_temp->priv, + &pss->args.pty); + if (n) + goto chrq_fail; + pss->parser_state = SSHS_MSG_EAT_PADDING; + break; + /* SSH_MSG_CHANNEL_DATA */ case SSHS_NVC_CD_RECIP: @@ -1822,7 +1865,9 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l pss->parser_state = SSH_KEX_STATE_SKIP; break; +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 ua_fail1: +#endif lws_genrsa_destroy(&ctx); ua_fail: write_task(pss, NULL, SSH_WT_UA_FAILURE); @@ -1969,7 +2014,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, const struct lws_protocol_vhost_options *pvo; const struct lws_protocols *prot; struct lws_ssh_channel *ch; - char lang[10]; + char lang[10] = ""; int n, m, o; /* @@ -2045,7 +2090,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RAW_ADOPT: lwsl_info("LWS_CALLBACK_RAW_ADOPT\n"); - if (!vhd) + if (!vhd || !pss) return -1; pss->next = vhd->live_pss_list; vhd->live_pss_list = pss; @@ -2067,7 +2112,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, * * The RECOMMENDED timeout period is 10 minutes. */ - lws_set_timeout(wsi, + lws_set_timeout(wsi, (enum pending_timeout) SSH_PENDING_TIMEOUT_CONNECT_TO_SUCCESSFUL_AUTH, 10 * 60); break; @@ -2257,10 +2302,10 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_OPEN_CONF: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; - lws_p32(pp, pss->ch_temp->server_ch); - pp += 4; lws_p32(pp, pss->ch_temp->sender_ch); pp += 4; + lws_p32(pp, pss->ch_temp->server_ch); + pp += 4; /* tx initial window size towards us */ lws_p32(pp, LWS_SSH_INITIAL_WINDOW); pp += 4; @@ -2275,10 +2320,10 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_FAILURE: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_OPEN_FAILURE; - lws_p32(pp, ch->server_ch); - pp += 4; lws_p32(pp, ch->sender_ch); pp += 4; + lws_p32(pp, ch->server_ch); + pp += 4; lws_cstr(&pp, "reason", 64); lws_cstr(&pp, "en/US", 64); lwsl_info("SSH_WT_CH_FAILURE\n"); @@ -2287,7 +2332,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CHRQ_SUCC: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_SUCCESS; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); lwsl_info("SSH_WT_CHRQ_SUCC\n"); pp += 4; goto pac; @@ -2295,7 +2340,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CHRQ_FAILURE: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_FAILURE; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); pp += 4; lwsl_info("SSH_WT_CHRQ_FAILURE\n"); goto pac; @@ -2303,7 +2348,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_CLOSE: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_CLOSE; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); lwsl_info("SSH_WT_CH_CLOSE\n"); pp += 4; goto pac; @@ -2311,7 +2356,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_EOF: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_EOF; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); lwsl_info("SSH_WT_CH_EOF\n"); pp += 4; goto pac; @@ -2393,7 +2438,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, else *pp++ = SSH_MSG_CHANNEL_EXTENDED_DATA; /* ps + 6 */ - lws_p32(pp, pss->ch_list->server_ch); + lws_p32(pp, pss->ch_list->sender_ch); m = 14; if (n == LWS_STDERR) { pp += 4; diff --git a/3rdparty/libwebsockets/scripts/ahrefs-topsites.sh b/3rdparty/libwebsockets/scripts/ahrefs-topsites.sh new file mode 100755 index 00000000..4cc922d8 --- /dev/null +++ b/3rdparty/libwebsockets/scripts/ahrefs-topsites.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +wget -O- https://ahrefs.com/blog/most-visited-websites/ | grep most-visited-websites-us | \ + sed -E 's/class="column-2">/|/g' | tr '|' '\n' | \ + sed 's/<.*//g' | grep -v Domain | grep -v Josh | sort | uniq + diff --git a/3rdparty/libwebsockets/scripts/client-ca/create-client-cert.sh b/3rdparty/libwebsockets/scripts/client-ca/create-client-cert.sh index cee8cbd3..1546d83f 100755 --- a/3rdparty/libwebsockets/scripts/client-ca/create-client-cert.sh +++ b/3rdparty/libwebsockets/scripts/client-ca/create-client-cert.sh @@ -5,8 +5,9 @@ if [ -z "$1" ] ; then exit 1 fi +mkdir -p certs openssl genrsa -out $1.key 4096 && \ -printf "\\n\\n\\n\\n\\nlocalhost\\n\\n1234\\n\\n" | \ +printf "\\n\\n\\n\\n\\n$1\\n\\n1234\\n\\n" | \ openssl req -config tmp.cnf -new -key $1.key -out $1.csr && \ openssl ca -config tmp.cnf \ -keyfile ca.key \ diff --git a/3rdparty/libwebsockets/scripts/client-ca/create-server-cert.sh b/3rdparty/libwebsockets/scripts/client-ca/create-server-cert.sh index 46a15900..fd5dc202 100755 --- a/3rdparty/libwebsockets/scripts/client-ca/create-server-cert.sh +++ b/3rdparty/libwebsockets/scripts/client-ca/create-server-cert.sh @@ -5,6 +5,7 @@ if [ -z "$1" ] ; then exit 1 fi +mkdir -p certs openssl genrsa -out $1.key 4096 && \ printf "\\n\\n\\n\\n\\nlocalhost\\n\\n1234\\n\\n" | \ openssl req -config tmp.cnf -new -key $1.key -out $1.csr && \ diff --git a/3rdparty/libwebsockets/scripts/mozilla-trust-gen.sh b/3rdparty/libwebsockets/scripts/mozilla-trust-gen.sh new file mode 100755 index 00000000..4a38963e --- /dev/null +++ b/3rdparty/libwebsockets/scripts/mozilla-trust-gen.sh @@ -0,0 +1,194 @@ +#!/bin/bash + +# This script fetches the current list of trusted CAs blessed by Mozilla +# for web tls validation, and processes it into two outputs +# +# - ./trust/webroot/* consisting of ./_trust/webroot/der a static, serveable set +# of trusted DER certs, with symlinks in ./_trust/webroot/by-skid and +# ./_trust/webroot/by-iss allowing serving the DER matching a given +# SubjectKeyIdentifier or Issuer + serial combination (suitably encoded) +# +# - ./_trust/blob-XXXX.bin a single blob containing indexes and DER CA certs +# +# - ./_trust/trust_blob.h a C uint8_t array formatted copy of blob-XXXX.bin + +# The trust blob layout is currently +# +# 54 42 4c 42 Magic "TBLB" +# 00 01 MSB-first trust blob layout version +# XX XX MSB-first count of certificates +# XX XX XX XX MSB-first trust blob generation unix time +# XX XX XX XX MSB-first offset of cert length table (MSB-first 16-bit length-per-cert) +# XX XX XX XX MSB-first offset of SKID length table (8-bit length-per-cert) +# XX XX XX XX MSB-first offset of SKID table +# XX XX XX XX MSB-first total blob length +# +# XX .. XX DER certs (start at +0x1c) +# XX .. XX DER cert length table (MSB-first 16-bit per cert) +# XX .. XX SKID length table (8-bit per cert) +# XX .. XX SKID table (variable per cert) +# + +echo "Mozilla trust bundle for TLS validation processing Andy Green " +echo + +rm -rf _trust +mkdir _trust + +wget -O _trust/trusted.txt "https://ccadb-public.secure.force.com/mozilla/IncludedRootsPEMTxt?TrustBitsInclude=Websites" +#cp ~/Downloads/IncludedRootsPEM.txt _trust/trusted.txt + +if [ $? -ne 0 ]; then + echo "Failed to get current website trust bundle" + exit 1 +fi + +mkdir -p _trust/webroot/by-skid _trust/webroot/by-iss _trust/webroot/der + +echo 0 > _trust/ofs +echo 0 > _trust/count +echo 0 > _trust/skidtab + +GT=`date +%s` +BN=_trust/blob-$GT.bin + +cat _trust/trusted.txt | while read _line ; do + line=`echo -n $_line | sed 's/\r$//g'` + if [ "$line" == "-----BEGIN CERTIFICATE-----" ] ; then + echo $line > _trust/single + else + echo $line >> _trust/single + + if [ "$line" == "-----END CERTIFICATE-----" ] ; then + openssl x509 -in _trust/single -text -noout > _trust/c1 + if [ $? -ne 0 ] ; then + echo "FAILED" + exit 1 + fi + + ISS=`cat _trust/c1 | grep Issuer: | sed "s/.*://g" | sed "s/^\ *//g"` + SER=`cat _trust/c1 | grep "Serial Number:" | sed "s/.*://g" | sed "s/^\ *//g" | sed "s/\ .*//g"` + if [ -z "$SER" ] ; then + SER=`cat _trust/c1 | sed -e "1,/.*Serial Number:/ d" | head -n 1 | sed "s/^\ *//g" | sed "s/\ .*//g"` + fi + SKID=`cat _trust/c1 | sed -e '1,/.*X509v3 Subject Key Identifier:/ d' | sed -n '/Signature.*/q;p' | \ + grep ':' | grep -v ': ' | grep -v ':$' | grep -v U | grep -v k | grep -v T | grep -v "i" | \ + grep -v "S" | grep -v "V" | sed "s/^\ *//g"` + SKID_NO_COLONS=`echo -n $SKID | sed "s/://g"` + + na=`cat _trust/c1 | grep "Not\ After\ :" | sed "s/.*\ :\ //g"` + ct=`date +%s` + ts=`date --date="$na" +%s` + life_days=`echo -n "$(( ( $ts - $ct ) / 86400 ))"` + + echo "$life_days $safe" >> _trust/life + if [ $life_days -lt 1095 ] ; then + echo "$life_days $safe" >> _trust/life_lt_3y + fi + + echo "issuer=\"$ISS\", serial=\"${SER^^}\", skid=\"${SKID_NO_COLONS^^}\", life_days=\"${life_days}\"" + + issname=`echo -n "$ISS"_"$SER" | tr -cd '[a-zA-Z0-9]_'` + skidname=`echo -n "$SKID_NO_COLONS" | tr -cd '[a-zA-Z0-9]_'` + safe=$issname"_"$skidname + + cat _trust/single | grep -v -- '---' | base64 -d > _trust/webroot/der/$safe + cd _trust/webroot/by-skid + ln -sf ../der/$safe $SKID_NO_COLONS + cd ../../.. + cd _trust/webroot/by-iss + ln -sf ../der/$safe $issname + cd ../../.. + + DERSIZ=`cat _trust/single | grep -v -- '---' | base64 -d | wc -c | cut -d' ' -f1` + + cat _trust/single | grep -v -- '---' | base64 -d | hexdump -C | tr -s ' ' | sed 's/\ $//g' | \ + cut -d' ' -f 2-17 | cut -d'|' -f1 | grep -v 000 | sed "s/\ //g" | sed ':a;N;$!ba;s/\n//g' | xxd -r -p >> _trust/_ders + + printf "%04x" $DERSIZ | xxd -r -p >> _trust/_derlens + +echo $SKID + + if [ ! -z "$SKID" ] ; then + echo -n "$SKID_NO_COLONS" | xxd -r -p >> _trust/_skid + fi + SKIDSIZ=`echo -n $SKID_NO_COLONS | xxd -r -p | wc -c | cut -d' ' -f1` + printf "%02x" $SKIDSIZ | xxd -r -p >> _trust/_skidlens + + OFS=`cat _trust/ofs` + echo -n $(( $OFS + $DERSIZ )) > _trust/ofs + COUNT=`cat _trust/count` + echo -n $(( $COUNT +1 )) > _trust/count + ST=`cat _trust/skidtab` + echo -n $(( $ST + ( `echo -n $skidname | wc -c | cut -d' ' -f1` / 2 ) )) > _trust/skidtab + + rm -f _trust/single + + fi + fi + +done + + COUNT=`cat _trust/count` + OFS=`cat _trust/ofs` + ST=`cat _trust/skidtab` + + # everything in the layout framing is MSB-first + + # magic + echo -n "TBLB" > $BN + # blob layout version + echo -n 0001 | xxd -r -p >> $BN + # number of certs in the blob + printf "%04x" $COUNT | xxd -r -p >> $BN + # unix time blob was created + printf "%08x" $GT | xxd -r -p >> $BN + + POS=28 + POS=$(( $POS + `cat _trust/_ders | wc -c | cut -d' ' -f1` )) + + # blob offset of start of cert length table + printf "%08x" $POS | xxd -r -p >> $BN + + POS=$(( $POS + `cat _trust/_derlens | wc -c | cut -d' ' -f1` )) + + # blob offset of start of SKID length table + printf "%08x" $POS | xxd -r -p >> $BN + + POS=$(( $POS + `cat _trust/_skidlens | wc -c | cut -d' ' -f1` )) + + # blob offset of start of SKID table + printf "%08x" $POS | xxd -r -p >> $BN + + POS=$(( $POS + `cat _trust/_skid | wc -c | cut -d' ' -f1` )) + + # blob total length + printf "%08x" $POS | xxd -r -p >> $BN + + + # the DER table, start at +0x1c + cat _trust/_ders >> $BN + # the DER length table + cat _trust/_derlens >> $BN + # the SKID length table + cat _trust/_skidlens >> $BN + # the SKID table + cat _trust/_skid >> $BN + +# produce a C-friendly version of the blob + + cat $BN | hexdump -v -C | tr -s ' ' | sed 's/\ $//g' | \ + cut -d' ' -f 2-17 | cut -d'|' -f1 | grep -v 000 | sed "s/\ /,\ 0x/g" | sed "s/^/0x/g" | \ + sed 's/\, 0x$//g' | sed 's/$/,/g' >> _trust/trust_blob.h + + + echo + echo "$COUNT CA certs, $POS byte blob" + echo + echo "CAs expiring in less than 3 years (days left):" + sort -h _trust/life_lt_3y + + rm -f _trust/count _trust/_idx _trust/_idx_skid _trust/ofs _trust/_skid _trust/skidtab _trust/life _trust/life_lt_3y _trust/c1 _trust/single _trust/_derlens _trust/_ders _trust/_skid _trust/_skidlens + +exit 0 + diff --git a/3rdparty/libwebsockets/test-apps/CMakeLists.txt b/3rdparty/libwebsockets/test-apps/CMakeLists.txt index cb3c9804..9ffed9f8 100644 --- a/3rdparty/libwebsockets/test-apps/CMakeLists.txt +++ b/3rdparty/libwebsockets/test-apps/CMakeLists.txt @@ -185,6 +185,19 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2)) target_compile_definitions(test-lejp PRIVATE LWS_BUILDING_STATIC) endif() + if (LWS_WITH_CBOR) + create_test_app( + test-lecp + "test-lecp.c" + "" + "" + "" + "" + "") + target_compile_definitions(test-lecp PRIVATE LWS_BUILDING_STATIC) + endif() + + # Data files for running the test server. list(APPEND TEST_SERVER_DATA "${PROJECT_SOURCE_DIR}/test-apps/favicon.ico" diff --git a/3rdparty/libwebsockets/test-apps/test-client.c b/3rdparty/libwebsockets/test-apps/test-client.c index 2c3e97ce..05d08ed7 100644 --- a/3rdparty/libwebsockets/test-apps/test-client.c +++ b/3rdparty/libwebsockets/test-apps/test-client.c @@ -125,7 +125,7 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, #endif #endif const char *which = "http"; - char which_wsi[10], buf[50 + LWS_PRE]; + char which_wsi[50], buf[80 + LWS_PRE]; int n; switch (reason) { @@ -515,21 +515,18 @@ static const struct lws_protocols protocols[] = { { "dumb-increment-protocol", callback_dumb_increment, - 0, - 20, + 0, 20, 0, NULL, 0 }, { "lws-mirror-protocol", callback_lws_mirror, - 0, - 4096, + 0, 4096, 0, NULL, 0 }, { "lws-test-raw-client", callback_test_raw_client, - 0, - 128 + 0, 128, 0, NULL, 0 }, - { NULL, NULL, 0, 0 } /* end */ + LWS_PROTOCOL_LIST_TERM }; #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) diff --git a/3rdparty/libwebsockets/test-apps/test-lecp.c b/3rdparty/libwebsockets/test-apps/test-lecp.c new file mode 100644 index 00000000..f10f0d2a --- /dev/null +++ b/3rdparty/libwebsockets/test-apps/test-lecp.c @@ -0,0 +1,170 @@ +/* + * lejp test app + * + * Written in 2010-2019 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates a minimal http server that performs a form GET with a couple + * of parameters. It dumps the parameters to the console log and redirects + * to another page. + */ + +#include +#include + + +static const char * const reason_names[] = { + "LECPCB_CONSTRUCTED", + "LECPCB_DESTRUCTED", + "LECPCB_START", + "LECPCB_COMPLETE", + "LECPCB_FAILED", + "LECPCB_PAIR_NAME", + "LECPCB_VAL_TRUE", + "LECPCB_VAL_FALSE", + "LECPCB_VAL_NULL", + "LECPCB_VAL_NUM_INT", + "LECPCB_VAL_RESERVED", /* float in lejp */ + "LECPCB_VAL_STR_START", + "LECPCB_VAL_STR_CHUNK", + "LECPCB_VAL_STR_END", + "LECPCB_ARRAY_START", + "LECPCB_ARRAY_END", + "LECPCB_OBJECT_START", + "LECPCB_OBJECT_END", + "LECPCB_TAG_START", + "LECPCB_TAG_END", + "LECPCB_VAL_NUM_UINT", + "LECPCB_VAL_UNDEFINED", + "LECPCB_VAL_FLOAT16", + "LECPCB_VAL_FLOAT32", + "LECPCB_VAL_FLOAT64", + "LECPCB_VAL_SIMPLE", + "LECPCB_VAL_BLOB_START", + "LECPCB_VAL_BLOB_CHUNK", + "LECPCB_VAL_BLOB_END", +}; + +static const char * const tok[] = { + "dummy___" +}; + +static signed char +cb(struct lecp_ctx *ctx, char reason) +{ + char buf[1024], *p = buf, *end = &buf[sizeof(buf)]; + int n; + + for (n = 0; n < ctx->sp; n++) + *p++ = ' '; + *p = '\0'; + + lwsl_notice("%s%s: path %s match %d statckp %d\r\n", buf, + reason_names[(unsigned int)(reason) & + (LEJP_FLAG_CB_IS_VALUE - 1)], ctx->path, + ctx->path_match, ctx->pst[ctx->pst_sp].ppos); + + if (reason & LECP_FLAG_CB_IS_VALUE) { + + switch (reason) { + case LECPCB_VAL_NUM_UINT: + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + " value %llu ", + (unsigned long long)ctx->item.u.u64); + break; + case LECPCB_VAL_STR_START: + case LECPCB_VAL_STR_CHUNK: + case LECPCB_VAL_STR_END: + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + " value '%s' ", ctx->buf); + break; + + case LECPCB_VAL_BLOB_START: + case LECPCB_VAL_BLOB_CHUNK: + case LECPCB_VAL_BLOB_END: + if (ctx->npos) + lwsl_hexdump_notice(ctx->buf, (size_t)ctx->npos); + break; + + case LECPCB_VAL_NUM_INT: + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + " value %lld ", + (long long)ctx->item.u.i64); + break; + case LECPCB_VAL_FLOAT16: + case LECPCB_VAL_FLOAT32: + case LECPCB_VAL_FLOAT64: + break; + + case LECPCB_VAL_SIMPLE: + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), + " simple %llu ", + (unsigned long long)ctx->item.u.u64); + break; + } + if (ctx->ipos) { + int n; + + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "(array indexes: "); + for (n = 0; n < ctx->ipos; n++) + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%d ", ctx->i[n]); + p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), ") "); + } + + lwsl_notice("%s \r\n", buf); + + (void)reason_names; /* NO_LOGS... */ + return 0; + } + + switch (reason) { + case LECPCB_COMPLETE: + lwsl_notice("%sParsing Completed (LEJPCB_COMPLETE)\n", buf); + break; + case LECPCB_PAIR_NAME: + lwsl_notice("%spath: '%s' (LEJPCB_PAIR_NAME)\n", buf, ctx->path); + break; + case LECPCB_TAG_START: + lwsl_notice("LECPCB_TAG_START: %llu\r\n", (unsigned long long)ctx->item.u.u64); + return 0; + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + int fd, n = 1, ret = 1, m = 0; + struct lecp_ctx ctx; + char buf[128]; + + lws_set_log_level(7, NULL); + + lwsl_notice("libwebsockets-test-lecp (C) 2017 - 2021 andy@warmcat.com\n"); + lwsl_notice(" usage: cat my.cbor | libwebsockets-test-lecp\n\n"); + + lecp_construct(&ctx, cb, NULL, tok, LWS_ARRAY_SIZE(tok)); + + fd = 0; + + while (n > 0) { + n = (int)read(fd, buf, sizeof(buf)); + if (n <= 0) + continue; + + m = lecp_parse(&ctx, (uint8_t *)buf, (size_t)n); + if (m < 0 && m != LEJP_CONTINUE) { + lwsl_err("parse failed %d\n", m); + goto bail; + } + } + lwsl_notice("okay (%d)\n", m); + ret = 0; +bail: + lecp_destruct(&ctx); + + return ret; +} diff --git a/3rdparty/libwebsockets/test-apps/test-server.c b/3rdparty/libwebsockets/test-apps/test-server.c index 2272fb5f..36fec50e 100644 --- a/3rdparty/libwebsockets/test-apps/test-server.c +++ b/3rdparty/libwebsockets/test-apps/test-server.c @@ -107,10 +107,10 @@ lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, return -1; } pfd->fd = pa->fd; - pfd->events = pa->events; + pfd->events = (short)pa->events; pfd->revents = 0; /* high water mark... */ - count_pollfds = (pfd - pollfds) + 1; + count_pollfds = (int)((pfd - pollfds) + 1); break; case LWS_CALLBACK_DEL_POLL_FD: pa = (struct lws_pollargs *)in; @@ -128,7 +128,7 @@ lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_err("%s: unknown fd %d\n", __func__, pa->fd); return -1; } - pfd->events = pa->events; + pfd->events = (short)pa->events; break; #endif case LWS_CALLBACK_HTTP: @@ -187,14 +187,14 @@ lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, static struct lws_protocols protocols[] = { /* first protocol must always be HTTP handler */ - { "http-only", lws_callback_http, 0, 0, }, + { "http-only", lws_callback_http, 0, 0, 0, NULL, 0 }, #if defined(LWS_ROLE_WS) LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_LWS_STATUS, #endif LWS_PLUGIN_PROTOCOL_POST_DEMO, - { NULL, NULL, 0, 0 } /* terminator */ + LWS_PROTOCOL_LIST_TERM }; @@ -278,8 +278,6 @@ static const struct lws_http_mount mount_ziptest_uncomm = { 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 */ @@ -298,8 +296,6 @@ static const struct lws_http_mount mount_ziptest_uncomm = { LWSMPRO_FILE, /* origin points to a callback */ 8, /* strlen("/ziptest"), ie length of the mountpoint */ NULL, - - { NULL, NULL } // sentinel }, mount_post = { (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ "/formtest", /* mountpoint in URL namespace on this vhost */ @@ -318,8 +314,6 @@ static const struct lws_http_mount mount_ziptest_uncomm = { 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 */ @@ -570,8 +564,8 @@ int main(int argc, char **argv) #else max_poll_elements = sysconf(_SC_OPEN_MAX); #endif - pollfds = malloc(max_poll_elements * sizeof (struct lws_pollfd)); - fd_lookup = malloc(max_poll_elements * sizeof (int)); + pollfds = malloc((unsigned int)max_poll_elements * sizeof (struct lws_pollfd)); + fd_lookup = malloc((unsigned int)max_poll_elements * sizeof (int)); if (pollfds == NULL || fd_lookup == NULL) { lwsl_err("Out of memory pollfds=%d\n", max_poll_elements); return -1; @@ -699,7 +693,7 @@ int main(int argc, char **argv) /* 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); + n = poll(pollfds, (nfds_t)count_pollfds, n); if (n < 0) continue; diff --git a/src/websockets/libwebsockets/LibWebsocketClient.cpp b/src/websockets/libwebsockets/LibWebsocketClient.cpp index d628cfcf..2d13abd3 100644 --- a/src/websockets/libwebsockets/LibWebsocketClient.cpp +++ b/src/websockets/libwebsockets/LibWebsocketClient.cpp @@ -374,14 +374,16 @@ int LibWebsocketClient::eventCallback(struct lws* wsi, enum lws_callback_reasons case LWS_CALLBACK_CLIENT_WRITEABLE: { // Send data if any ready + bool error = false; SendMsg* msg = nullptr; - if (client->m_send_msgs.pop(msg, 0)) + while (client->m_send_msgs.pop(msg, 0) && !error) { if (lws_write(wsi, msg->payload, msg->size, LWS_WRITE_TEXT) < static_cast(msg->size)) { // Error client->disconnect(); client->m_listener->wsClientError(); + error = true; } // Free message memory @@ -390,6 +392,13 @@ int LibWebsocketClient::eventCallback(struct lws* wsi, enum lws_callback_reasons } break; + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + if (client->m_retry_interval != 0) + { + retry = true; + } + break; + case LWS_CALLBACK_CLIENT_CLOSED: client->m_connected = false; client->m_listener->wsClientDisconnected(); diff --git a/src/websockets/libwebsockets/LibWebsocketServer.cpp b/src/websockets/libwebsockets/LibWebsocketServer.cpp index c468c5e8..13607390 100644 --- a/src/websockets/libwebsockets/LibWebsocketServer.cpp +++ b/src/websockets/libwebsockets/LibWebsocketServer.cpp @@ -422,10 +422,10 @@ int LibWebsocketServer::eventCallback(struct lws* wsi, enum lws_callback_reasons Client* client = dynamic_cast(iter_client->second.get()); if (client->m_connected) { - // Send data if any ready + bool error = false; SendMsg* msg = nullptr; - if (client->m_send_msgs.pop(msg, 0)) + while (client->m_send_msgs.pop(msg, 0) && !error) { if (lws_write(client->m_wsi, msg->payload, msg->size, LWS_WRITE_TEXT) < static_cast(msg->size)) { @@ -435,6 +435,7 @@ int LibWebsocketServer::eventCallback(struct lws* wsi, enum lws_callback_reasons { client->m_listener->wsClientError(); } + error = true; } // Free message memory diff --git a/tests/deploy/CMakeLists.txt b/tests/deploy/CMakeLists.txt index 0e4b5b88..389a9df5 100644 --- a/tests/deploy/CMakeLists.txt +++ b/tests/deploy/CMakeLists.txt @@ -34,7 +34,8 @@ target_link_libraries(test_install_dynamic OpenSSL::Crypto sqlite3 pthread - + ev + uv ) add_test( NAME test_install_dynamic @@ -53,7 +54,9 @@ target_link_libraries(PkgConfig::PKG_OPEN_OCPP_STATIC INTERFACE OpenSSL::Crypto sqlite3 pthread - ) + ev + uv +) add_test( NAME test_install_static COMMAND test_install_static