diff -Nru srt-1.5.0/.appveyor.yml srt-1.5.1/.appveyor.yml --- srt-1.5.0/.appveyor.yml 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/.appveyor.yml 2022-09-21 14:29:01.000000000 +0000 @@ -14,9 +14,9 @@ build_script: - ps: $VSIMG = $Env:APPVEYOR_BUILD_WORKER_IMAGE; $CNFG = $Env:CONFIGURATION # use a few differing arguments depending on VS version to exercise different options during builds - - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON } + - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON } - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON } - - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON } + - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } - ps: if ($VSIMG -match '2013' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -CXX11 OFF -BUILD_APPS ON } - ps: if ($VSIMG -match '2013' -and $CNFG -eq "Debug") { Exit-AppveyorBuild } # just skip 2013 debug build for speed diff -Nru srt-1.5.0/CMakeLists.txt srt-1.5.1/CMakeLists.txt --- srt-1.5.0/CMakeLists.txt 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/CMakeLists.txt 2022-09-21 14:29:01.000000000 +0000 @@ -8,20 +8,20 @@ # cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) -set (SRT_VERSION 1.5.0) +set (SRT_VERSION 1.5.1) set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/scripts") include(haiUtil) # needed for set_version_variables # CMake version 3.0 introduced the VERSION option of the project() command # to specify a project version as well as the name. if(${CMAKE_VERSION} VERSION_LESS "3.0.0") - project(SRT C CXX) - # Sets SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH - set_version_variables(SRT_VERSION ${SRT_VERSION}) + project(SRT C CXX) + # Sets SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH + set_version_variables(SRT_VERSION ${SRT_VERSION}) else() - cmake_policy(SET CMP0048 NEW) - # Also sets SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH - project(SRT VERSION ${SRT_VERSION} LANGUAGES C CXX) + cmake_policy(SET CMP0048 NEW) + # Also sets SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH + project(SRT VERSION ${SRT_VERSION} LANGUAGES C CXX) endif() include(FindPkgConfig) @@ -43,15 +43,9 @@ set_if(SUNOS "${SYSNAME_LC}" MATCHES "sunos") set_if(POSIX LINUX OR DARWIN OR BSD OR SUNOS OR ANDROID OR (CYGWIN AND CYGWIN_USE_POSIX)) set_if(SYMLINKABLE LINUX OR DARWIN OR BSD OR SUNOS OR CYGWIN OR GNU) +set_if(NEED_DESTINATION ${CMAKE_VERSION} VERSION_LESS "3.14.0") -# Not sure what to do in case of compiling by MSVC. -# This will make installdir in C:\Program Files\SRT then -# inside "bin" and "lib64" directories. At least this maintains -# the current status. Shall this be not desired, override values -# of CMAKE_INSTALL_BINDIR, CMAKE_INSTALL_LIBDIR and CMAKE_INSTALL_INCLUDEDIR. -if (NOT DEFINED CMAKE_INSTALL_LIBDIR) - include(GNUInstallDirs) -endif() +include(GNUInstallDirs) # The CMAKE_BUILD_TYPE seems not to be always set, weird. if (NOT DEFINED ENABLE_DEBUG) @@ -63,15 +57,28 @@ endif() endif() -# Set CMAKE_BUILD_TYPE properly, now that you know -# that ENABLE_DEBUG is set as it should. +# XXX This is a kind of workaround - this part to set the build +# type and associated other flags should not be done for build +# systems (cmake generators) that generate a multi-configuration +# build definition. At least it is known that MSVC does it and it +# sets _DEBUG and NDEBUG flags itself, so this shouldn't be done +# at all in this case. +if (NOT MICROSOFT) + + # Set CMAKE_BUILD_TYPE properly, now that you know + # that ENABLE_DEBUG is set as it should. + if (ENABLE_DEBUG EQUAL 2) + set (CMAKE_BUILD_TYPE "RelWithDebInfo") + add_definitions(-DNDEBUG) + elseif (ENABLE_DEBUG) # 1, ON, YES, TRUE, Y, or any other non-zero number + set (CMAKE_BUILD_TYPE "Debug") -if (ENABLE_DEBUG EQUAL 2) - set (CMAKE_BUILD_TYPE "RelWithDebInfo") -elseif (ENABLE_DEBUG) # 1, ON, YES, TRUE, Y, or any other non-zero number - set (CMAKE_BUILD_TYPE "Debug") -else() - set (CMAKE_BUILD_TYPE "Release") + # Add _DEBUG macro in debug mode only, to enable SRT_ASSERT(). + add_definitions(-D_DEBUG) + else() + set (CMAKE_BUILD_TYPE "Release") + add_definitions(-DNDEBUG) + endif() endif() message(STATUS "BUILD TYPE: ${CMAKE_BUILD_TYPE}") @@ -339,8 +346,9 @@ set(SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} "-l${LIB}") endif() endforeach() - else() # openssl - add_definitions(-DUSE_OPENSSL=1) + elseif ("${USE_ENCLIB}" STREQUAL "openssl-evp") + # Openssl-EVP requires CRYSPR2 + add_definitions(-DUSE_OPENSSL_EVP=1 -DCRYSPR2) set (SSL_REQUIRED_MODULES "openssl libcrypto") # Try using pkg-config method first if enabled, # fall back to find_package method otherwise @@ -375,6 +383,39 @@ set (SSL_LIBRARIES ${OPENSSL_LIBRARIES}) message(STATUS "SSL via find_package(OpenSSL): -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}") endif() + else() # openssl + # Openssl (Direct-AES API) can use CRYSPR2 + add_definitions(-DUSE_OPENSSL=1 -DCRYSPR2) + set (SSL_REQUIRED_MODULES "openssl libcrypto") + # Try using pkg-config method first if enabled, + # fall back to find_package method otherwise + if (USE_OPENSSL_PC) + pkg_check_modules(SSL ${SSL_REQUIRED_MODULES}) + endif() + if (SSL_FOUND) + # We have some cases when pkg-config is improperly configured + # When it doesn't ship the -L and -I options, and the CMAKE_PREFIX_PATH + # is set (also through `configure`), then we have this problem. If so, + # set forcefully the -I and -L contents to prefix/include and + # prefix/lib. + if ("${SSL_LIBRARY_DIRS}" STREQUAL "") + if (NOT "${CMAKE_PREFIX_PATH}" STREQUAL "") + message(STATUS "WARNING: pkg-config has incorrect prefix - enforcing target path prefix: ${CMAKE_PREFIX_PATH}") + set (SSL_LIBRARY_DIRS ${CMAKE_PREFIX_PATH}/${CMAKE_INSTALL_LIBDIR}) + set (SSL_INCLUDE_DIRS ${CMAKE_PREFIX_PATH}/include) + endif() + endif() + + link_directories( + ${SSL_LIBRARY_DIRS} + ) + message(STATUS "SSL via pkg-config: -L ${SSL_LIBRARY_DIRS} -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}") + else() + find_package(OpenSSL REQUIRED) + set (SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + set (SSL_LIBRARIES ${OPENSSL_LIBRARIES}) + message(STATUS "SSL via find_package(OpenSSL): -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}") + endif() endif() @@ -1033,15 +1074,29 @@ endif() message(STATUS "INSTALL DIRS: bin=${CMAKE_INSTALL_BINDIR} lib=${CMAKE_INSTALL_LIBDIR} shlib=${INSTALL_SHARED_DIR} include=${CMAKE_INSTALL_INCLUDEDIR}") - -install(TARGETS ${INSTALL_TARGETS} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +if (NEED_DESTINATION) + if (DEFINED CMAKE_INSTALL_BINDIR AND DEFINED CMAKE_INSTALL_LIBDIR AND NOT INSTALL_SHARED_DIR STREQUAL "") + install(TARGETS ${INSTALL_TARGETS} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${INSTALL_SHARED_DIR} + ) + else() + message(WARNING "No location to install ${INSTALL_TARGETS}") + endif() +elseif (NOT INSTALL_SHARED_DIR STREQUAL "") + install(TARGETS ${INSTALL_TARGETS} LIBRARY DESTINATION ${INSTALL_SHARED_DIR} -) -install(FILES ${HEADERS_srt} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/srt) -if (WIN32) - install(FILES ${HEADERS_srt_win32} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/srt/win) + ) +else() + install(TARGETS ${INSTALL_TARGETS}) +endif() + +if (DEFINED CMAKE_INSTALL_INCLUDEDIR) + install(FILES ${HEADERS_srt} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/srt) + if (WIN32) + install(FILES ${HEADERS_srt_win32} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/srt/win) + endif() endif() # --- @@ -1077,11 +1132,13 @@ join_arguments(SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE}) -# haisrt.pc left temporarily for backward compatibility. To be removed in future! -configure_file(scripts/srt.pc.in haisrt.pc @ONLY) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/haisrt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -configure_file(scripts/srt.pc.in srt.pc @ONLY) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/srt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +if (DEFINED CMAKE_INSTALL_LIBDIR) + # haisrt.pc left temporarily for backward compatibility. To be removed in future! + configure_file(scripts/srt.pc.in haisrt.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/haisrt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + configure_file(scripts/srt.pc.in srt.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/srt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif() # Applications @@ -1107,7 +1164,13 @@ macro(srt_add_program name) srt_add_program_dont_install(${name} ${ARGN}) - install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + if(NOT NEED_DESTINATION) + install(TARGETS ${name} RUNTIME) + elseif (DEFINED CMAKE_INSTALL_BINDIR) + install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + else() + message(WARNING "No location to install program ${name}") + endif() endmacro() macro(srt_make_application name) @@ -1146,7 +1209,13 @@ macro(srt_add_application name) # ARGN=sources... srt_add_program(${name} apps/${name}.cpp ${ARGN}) srt_make_application(${name}) - install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + if(NOT NEED_DESTINATION) + install(TARGETS ${name} RUNTIME) + elseif (DEFINED CMAKE_INSTALL_BINDIR) + install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + else() + message(WARNING "No location to install program ${name}") + endif() endmacro() ## FIXME: transmitmedia.cpp does not build on OpenBSD @@ -1339,7 +1408,13 @@ endif() -install(PROGRAMS scripts/srt-ffplay DESTINATION ${CMAKE_INSTALL_BINDIR}) +if(NOT NEED_DESTINATION) + install(PROGRAMS scripts/srt-ffplay TYPE BIN) +elseif (DEFINED CMAKE_INSTALL_BINDIR) + install(PROGRAMS scripts/srt-ffplay DESTINATION ${CMAKE_INSTALL_BINDIR}) +else() + message(WARNING "No location to install scripts/srt-ffplay") +endif() if (DEFINED SRT_EXTRA_APPS_INC) diff -Nru srt-1.5.0/debian/changelog srt-1.5.1/debian/changelog --- srt-1.5.0/debian/changelog 2022-07-02 09:41:50.000000000 +0000 +++ srt-1.5.1/debian/changelog 2022-09-28 14:46:38.000000000 +0000 @@ -1,3 +1,13 @@ +srt (1.5.1-1) unstable; urgency=medium + + * [cd32285] New upstream version 1.5.1 + * [73df5e2] debian/patches/*.patch: refresh, dropping now-obsolete + include(GNUInstallDirs) + * [952b715] debian/*.lintian-overrides: match other archs and newer versions + as well + + -- Florian Ernst Wed, 28 Sep 2022 16:46:38 +0200 + srt (1.5.0-2) unstable; urgency=medium * Uploading to unstable to start the transition (cf. #1013670) diff -Nru srt-1.5.0/debian/libsrt1.5-gnutls.lintian-overrides srt-1.5.1/debian/libsrt1.5-gnutls.lintian-overrides --- srt-1.5.0/debian/libsrt1.5-gnutls.lintian-overrides 2022-06-17 11:16:08.000000000 +0000 +++ srt-1.5.1/debian/libsrt1.5-gnutls.lintian-overrides 2022-09-28 14:46:04.000000000 +0000 @@ -1,4 +1,4 @@ # package name also reflects the library used to enable encryption libsrt1.5-gnutls: package-name-doesnt-match-sonames libsrt-gnutls1.5 # C++ library with over 1000 exported symbols, so let's stick with shlibs -libsrt1.5-gnutls: no-symbols-control-file usr/lib/x86_64-linux-gnu/libsrt-gnutls.so.1.5.0 +libsrt1.5-gnutls: no-symbols-control-file usr/lib/*/libsrt-gnutls.so.1.5.* diff -Nru srt-1.5.0/debian/libsrt1.5-openssl.lintian-overrides srt-1.5.1/debian/libsrt1.5-openssl.lintian-overrides --- srt-1.5.0/debian/libsrt1.5-openssl.lintian-overrides 2022-06-17 11:16:30.000000000 +0000 +++ srt-1.5.1/debian/libsrt1.5-openssl.lintian-overrides 2022-09-28 14:46:04.000000000 +0000 @@ -1,4 +1,4 @@ # package name also reflects the library used to enable encryption libsrt1.5-openssl: package-name-doesnt-match-sonames libsrt1.5 # C++ library with over 1000 exported symbols, so let's stick with shlibs -libsrt1.5-openssl: no-symbols-control-file usr/lib/x86_64-linux-gnu/libsrt.so.1.5.0 +libsrt1.5-openssl: no-symbols-control-file usr/lib/*/libsrt.so.1.5.* diff -Nru srt-1.5.0/debian/patches/001-multiarch-rpath.patch srt-1.5.1/debian/patches/001-multiarch-rpath.patch --- srt-1.5.0/debian/patches/001-multiarch-rpath.patch 2022-06-17 11:02:35.000000000 +0000 +++ srt-1.5.1/debian/patches/001-multiarch-rpath.patch 2022-09-28 14:23:21.000000000 +0000 @@ -6,16 +6,7 @@ =================================================================== --- libsrt.orig/CMakeLists.txt +++ libsrt/CMakeLists.txt -@@ -10,6 +10,8 @@ - cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) - set (SRT_VERSION 1.5.0) - -+include(GNUInstallDirs) -+ - set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/scripts") - include(haiUtil) # needed for set_version_variables - # CMake version 3.0 introduced the VERSION option of the project() command -@@ -1134,6 +1136,8 @@ macro(srt_make_application name) +@@ -1197,6 +1197,8 @@ macro(srt_make_application name) set_target_properties(${name} PROPERTIES ${FORCE_RPATH}) endif() diff -Nru srt-1.5.0/debian/patches/test_failures.patch srt-1.5.1/debian/patches/test_failures.patch --- srt-1.5.0/debian/patches/test_failures.patch 2022-07-02 09:11:54.000000000 +0000 +++ srt-1.5.1/debian/patches/test_failures.patch 2022-09-28 14:24:05.000000000 +0000 @@ -6,7 +6,7 @@ =================================================================== --- libsrt.orig/test/test_sync.cpp +++ libsrt/test/test_sync.cpp -@@ -419,115 +419,6 @@ TEST(SyncEvent, WaitNotifyOne) +@@ -420,115 +420,6 @@ TEST(SyncEvent, WaitNotifyOne) cond.destroy(); } diff -Nru srt-1.5.0/docs/API/API-functions.md srt-1.5.1/docs/API/API-functions.md --- srt-1.5.0/docs/API/API-functions.md 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/docs/API/API-functions.md 2022-09-21 14:29:01.000000000 +0000 @@ -1734,7 +1734,7 @@ - [IN] Sender only. Specifies the application-provided timestamp to be associated with the packet. If not provided (specified as 0), the current time of SRT internal clock is used. - - For details on how to use `srctime` please refer to the (Time Access)[#time-access] section. + - For details on how to use `srctime` please refer to the [Time Access](#time-access) section. - `pktseq`: Receiver only. Reports the sequence number for the packet carrying out the payload being returned. If the payload is carried out by more than one @@ -2189,7 +2189,7 @@ **IMPORTANT**: The [`srt_epoll_wait`](#srt_epoll_wait) function does not report [`SRT_EPOLL_UPDATE`](#SRT_EPOLL_UPDATE) events. If you need the ability to get -any possible flag, you must use [`srt_epoll_wait`](#srt_epoll_wait). Note that +any possible flag, you must use [`srt_epoll_uwait`](#srt_epoll_uwait). Note that this function doesn't work with system file descriptors. | Returns | | diff -Nru srt-1.5.0/docs/build/build-macOS.md srt-1.5.1/docs/build/build-macOS.md --- srt-1.5.0/docs/build/build-macOS.md 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/docs/build/build-macOS.md 2022-09-21 14:29:01.000000000 +0000 @@ -1,6 +1,6 @@ # Building SRT on macOS -[Homebrew](https://brew.sh/) supports the **srt** formula. +[Homebrew](https://brew.sh/) supports the [`srt`](https://formulae.brew.sh/formula/srt) formula. ```shell brew update diff -Nru srt-1.5.0/docs/build/build-options.md srt-1.5.1/docs/build/build-options.md --- srt-1.5.0/docs/build/build-options.md 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/docs/build/build-options.md 2022-09-21 14:29:01.000000000 +0000 @@ -23,51 +23,51 @@ Option details are given further below. -| Option Name | Since | Type | Default | Short Description | -| :----------------------------------------------------------- | :---: | :-------: | :--------: | ----------------- | -| [`CMAKE_INSTALL_PREFIX`](#cmake_install_prefix) | 1.3.0 | `STRING` | OFF | Standard CMake variable that establishes the root directory for installation, inside of which a GNU/POSIX compatible directory layout will be used. | -| [`CYGWIN_USE_POSIX`](#cygwin_use_posix) | 1.2.0 | `BOOL` | OFF | Determines when to compile on Cygwin using POSIX API. | -| [`ENABLE_APPS`](#enable_apps) | 1.3.3 | `BOOL` | ON | Enables compiling sample applications (srt-live-trasnmit, etc.). | -| [`ENABLE_BONDING`](#enable_bonding) | 1.5.0 | `BOOL` | OFF | Enables the [Connection Bonding](../features/bonding-quick-start.md) feature. | -| [`ENABLE_CXX_DEPS`](#enable_cxx_deps) | 1.3.2 | `BOOL` | OFF | The `pkg-confg` file (`srt.pc`) will be generated with the `libstdc++` library as a dependency. | -| [`ENABLE_CXX11`](#enable_cxx11) | 1.2.0 | `BOOL` | ON | Enable compiling in C++11 mode for those parts that may require it. Default: ON except for GCC<4.7 | -| [`ENABLE_CODE_COVERAGE`](#enable_code_coverage) | 1.4.0 | `BOOL` | OFF | Enables instrumentation for code coverage. | -| [`ENABLE_DEBUG`](#enable_debug>) | 1.2.0 | `INT` | ON | Allows release/debug control through the `CMAKE_BUILD_TYPE` variable. | -| [`ENABLE_ENCRYPTION`](#enable_encryption) | 1.3.3 | `BOOL` | ON | Enables encryption feature enabled, with dependency on an external encryption library. | -| [`ENABLE_GETNAMEINFO`](#enable_getnameinfo) | 1.3.0 | `BOOL` | OFF | Enables the use of `getnameinfo` to allow using reverse DNS to resolve an internal IP address into a readable internet domain name. | -| [`ENABLE_HAICRYPT_LOGGING`](#enable_haicrypt_logging) | 1.3.1 | `BOOL` | OFF | Enables logging in the *haicrypt* module, which serves as a connector to an encryption library. | -| [`ENABLE_HEAVY_LOGGING`](#enable_heavy_logging) | 1.3.0 | `BOOL` | OFF | Enables heavy logging instructions in the code that occur often and cover many detailed aspects of library behavior. Default: OFF in release mode. | -| [`ENABLE_INET_PTON`](#enable_inet_pton) | 1.3.2 | `BOOL` | ON | Enables usage of the `inet_pton` function used to resolve the network endpoint name into an IP address. | -| [`ENABLE_LOGGING`](#enable_logging) | 1.2.0 | `BOOL` | ON | Enables normal logging, including errors. | -| [`ENABLE_MONOTONIC_CLOCK`](#enable_monotonic_clock) | 1.4.0 | `BOOL` | ON* | Enforces the use of `clock_gettime` with a monotonic clock that is independent of the currently set time in the system. | -| [`ENABLE_NEW_RCVBUFFER`](#enable_new_rcvbuffer) | 1.5.0 | `BOOL` | ON | Enables the new implementation of the receiver buffer with behavior and code improvements. | -| [`ENABLE_PROFILE`](#enable_profile) | 1.2.0 | `BOOL` | OFF | Enables code instrumentation for profiling (only for GNU-compatible compilers). | -| [`ENABLE_RELATIVE_LIBPATH`](#enable_relative_libpath) | 1.3.2 | `BOOL` | OFF | Enables adding a relative path to a library for linking against a shared SRT library by reaching out to a sibling directory. | -| [`ENABLE_SHARED`](#enable_shared--enable_static) | 1.2.0 | `BOOL` | ON | Enables building SRT as a shared library | -| [`ENABLE_SHOW_PROJECT_CONFIG`](#enable_show_project_config) | 1.5.0 | `BOOL` | OFF | When ON, the project configuration is displayed at the end of the CMake Configuration Step. | -| [`ENABLE_STATIC`](#enable_shared--enable_static) | 1.3.0 | `BOOL` | ON | Enables building SRT as a tatic library | -| [`ENABLE_STDCXX_SYNC`](#enable_stdcxx_sync) | 1.4.2 | `BOOL` | ON* | Enables the standard C++11 `thread` and `chrono` libraries to be used by SRT instead of the `pthreads`. | -| [`ENABLE_TESTING`](#enable_testing) | 1.3.0 | `BOOL` | OFF | Enables compiling of developer testing applications (srt-test-live, etc.). | -| [`ENABLE_THREAD_CHECK`](#enable_thread_check) | 1.3.0 | `BOOL` | OFF | Enables `#include `, which implements `THREAD_*` macros" to support better thread debugging. | -| [`ENABLE_UNITTESTS`](#enable_unittests) | 1.3.2 | `BOOL` | OFF | Enables building unit tests. | -| [`OPENSSL_CRYPTO_LIBRARY`](#openssl_crypto_library) | 1.3.0 | `STRING` | OFF | Configures the path to an OpenSSL Crypto library. | -| [`OPENSSL_INCLUDE_DIR`](#openssl_include_dir) | 1.3.0 | `STRING` | OFF | Configures the path to include files for an OpenSSL library. | -| [`OPENSSL_SSL_LIBRARY`](#openssl_ssl_library) | 1.3.0 | `STRING` | OFF | Configures the path to an OpenSSL SSL library. | -| [`PKG_CONFIG_EXECUTABLE`](#pkg_config_executable) | 1.3.0 | `BOOL` | OFF | Configures the path to the `pkg-config` tool. | -| [`PTHREAD_INCLUDE_DIR`](#pthread_include_dir) | 1.3.0 | `STRING` | OFF | Configures the path to include files for a pthread library. | -| [`PTHREAD_LIBRARY`](#pthread_library) | 1.3.0 | `STRING` | OFF | Configures the path to a pthread library. | -| [`USE_BUSY_WAITING`](#use_busy_waiting) | 1.3.3 | `BOOL` | OFF | Enables more accurate sending times at the cost of potentially higher CPU load. | -| [`USE_CXX_STD`](#use_cxx_std) | 1.4.2 | `STRING` | OFF | Enforces using a particular C++ standard (11, 14, 17, etc.) when compiling. | -| [`USE_ENCLIB`](#use_enclib) | 1.3.3 | `STRING` | openssl | Encryption library to be used (`openssl`, `gnutls`, `mbedtls`). | -| [`USE_GNUSTL`](#use_gnustl) | 1.3.4 | `BOOL` | OFF | Use `pkg-config` with the `gnustl` package name to extract the header and library path for the C++ standard library. | -| [`USE_OPENSSL_PC`](#use_openssl_pc) | 1.3.0 | `BOOL` | ON | Use `pkg-config` to find OpenSSL libraries. | -| [`OPENSSL_USE_STATIC_LIBS`](#openssl_use_static_libs) | 1.5.0 | `BOOL` | OFF | Link OpenSSL statically. | -| [`USE_STATIC_LIBSTDCXX`](#use_static_libstdcxx) | 1.2.0 | `BOOL` | OFF | Enforces linking the SRT library against the static libstdc++ library. | -| [`WITH_COMPILER_PREFIX`](#with_compiler_prefix) | 1.3.0 | `STRING` | OFF | Sets C/C++ toolchains as `` and ``, overriding the default compiler. | -| [`WITH_COMPILER_TYPE`](#with_compiler_type) | 1.3.0 | `STRING` | OFF | Sets the compiler type to be used (values: gcc, cc, clang, etc.). | +| Option Name | Since | Type | Default | Short Description | +| :----------------------------------------------------------- | :---: | :-------: | :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`CMAKE_INSTALL_PREFIX`](#cmake_install_prefix) | 1.3.0 | `STRING` | OFF | Standard CMake variable that establishes the root directory for installation, inside of which a GNU/POSIX compatible directory layout will be used. | +| [`CYGWIN_USE_POSIX`](#cygwin_use_posix) | 1.2.0 | `BOOL` | OFF | Determines when to compile on Cygwin using POSIX API. | +| [`ENABLE_APPS`](#enable_apps) | 1.3.3 | `BOOL` | ON | Enables compiling sample applications (`srt-live-transmit`, etc.). | +| [`ENABLE_BONDING`](#enable_bonding) | 1.5.0 | `BOOL` | OFF | Enables the [Connection Bonding](../features/bonding-quick-start.md) feature. | +| [`ENABLE_CXX_DEPS`](#enable_cxx_deps) | 1.3.2 | `BOOL` | OFF | The `pkg-confg` file (`srt.pc`) will be generated with the `libstdc++` library as a dependency. | +| [`ENABLE_CXX11`](#enable_cxx11) | 1.2.0 | `BOOL` | ON | Enable compiling in C++11 mode for those parts that may require it. Default: ON except for GCC<4.7 | +| [`ENABLE_CODE_COVERAGE`](#enable_code_coverage) | 1.4.0 | `BOOL` | OFF | Enables instrumentation for code coverage. | +| [`ENABLE_DEBUG`](#enable_debug) | 1.2.0 | `INT` | ON | Allows release/debug control through the `CMAKE_BUILD_TYPE` variable. | +| [`ENABLE_ENCRYPTION`](#enable_encryption) | 1.3.3 | `BOOL` | ON | Enables encryption feature enabled, with dependency on an external encryption library. | +| [`ENABLE_GETNAMEINFO`](#enable_getnameinfo) | 1.3.0 | `BOOL` | OFF | Enables the use of `getnameinfo` to allow using reverse DNS to resolve an internal IP address into a readable internet domain name. | +| [`ENABLE_HAICRYPT_LOGGING`](#enable_haicrypt_logging) | 1.3.1 | `BOOL` | OFF | Enables logging in the *haicrypt* module, which serves as a connector to an encryption library. | +| [`ENABLE_HEAVY_LOGGING`](#enable_heavy_logging) | 1.3.0 | `BOOL` | OFF | Enables heavy logging instructions in the code that occur often and cover many detailed aspects of library behavior. Default: OFF in release mode. | +| [`ENABLE_INET_PTON`](#enable_inet_pton) | 1.3.2 | `BOOL` | ON | Enables usage of the `inet_pton` function used to resolve the network endpoint name into an IP address. | +| [`ENABLE_LOGGING`](#enable_logging) | 1.2.0 | `BOOL` | ON | Enables normal logging, including errors. | +| [`ENABLE_MONOTONIC_CLOCK`](#enable_monotonic_clock) | 1.4.0 | `BOOL` | ON* | Enforces the use of `clock_gettime` with a monotonic clock that is independent of the currently set time in the system. | +| [`ENABLE_NEW_RCVBUFFER`](#enable_new_rcvbuffer) | 1.5.0 | `BOOL` | ON | Enables the new implementation of the receiver buffer with behavior and code improvements. | +| [`ENABLE_PROFILE`](#enable_profile) | 1.2.0 | `BOOL` | OFF | Enables code instrumentation for profiling (only for GNU-compatible compilers). | +| [`ENABLE_RELATIVE_LIBPATH`](#enable_relative_libpath) | 1.3.2 | `BOOL` | OFF | Enables adding a relative path to a library for linking against a shared SRT library by reaching out to a sibling directory. | +| [`ENABLE_SHARED`](#enable_shared--enable_static) | 1.2.0 | `BOOL` | ON | Enables building SRT as a shared library. | +| [`ENABLE_SHOW_PROJECT_CONFIG`](#enable_show_project_config) | 1.5.0 | `BOOL` | OFF | When ON, the project configuration is displayed at the end of the CMake Configuration Step. | +| [`ENABLE_STATIC`](#enable_shared--enable_static) | 1.3.0 | `BOOL` | ON | Enables building SRT as a static library. | +| [`ENABLE_STDCXX_SYNC`](#enable_stdcxx_sync) | 1.4.2 | `BOOL` | ON* | Enables the standard C++11 `thread` and `chrono` libraries to be used by SRT instead of the `pthreads`. | +| [`ENABLE_TESTING`](#enable_testing) | 1.3.0 | `BOOL` | OFF | Enables compiling of developer testing applications (`srt-test-live`, etc.). | +| [`ENABLE_THREAD_CHECK`](#enable_thread_check) | 1.3.0 | `BOOL` | OFF | Enables `#include `, which implements `THREAD_*` macros" to support better thread debugging. | +| [`ENABLE_UNITTESTS`](#enable_unittests) | 1.3.2 | `BOOL` | OFF | Enables building unit tests. | +| [`OPENSSL_CRYPTO_LIBRARY`](#openssl_crypto_library) | 1.3.0 | `STRING` | OFF | Configures the path to an OpenSSL crypto library. | +| [`OPENSSL_INCLUDE_DIR`](#openssl_include_dir) | 1.3.0 | `STRING` | OFF | Configures the path to include files for an OpenSSL library. | +| [`OPENSSL_SSL_LIBRARY`](#openssl_ssl_library) | 1.3.0 | `STRING` | OFF | Configures the path to an OpenSSL SSL library. | +| [`PKG_CONFIG_EXECUTABLE`](#pkg_config_executable) | 1.3.0 | `BOOL` | OFF | Configures the path to the `pkg-config` tool. | +| [`PTHREAD_INCLUDE_DIR`](#pthread_include_dir) | 1.3.0 | `STRING` | OFF | Configures the path to include files for a `pthread` library. | +| [`PTHREAD_LIBRARY`](#pthread_library) | 1.3.0 | `STRING` | OFF | Configures the path to a `pthread` library. | +| [`USE_BUSY_WAITING`](#use_busy_waiting) | 1.3.3 | `BOOL` | OFF | Enables more accurate sending times at the cost of potentially higher CPU load. | +| [`USE_CXX_STD`](#use_cxx_std) | 1.4.2 | `STRING` | OFF | Enforces using a particular C++ standard (11, 14, 17, etc.) when compiling. | +| [`USE_ENCLIB`](#use_enclib) | 1.3.3 | `STRING` | openssl | Encryption library to be used (`openssl`, `openssl-evp` (since 1.5.1), `gnutls`, `mbedtls`). | +| [`USE_GNUSTL`](#use_gnustl) | 1.3.4 | `BOOL` | OFF | Use `pkg-config` with the `gnustl` package name to extract the header and library path for the C++ standard library. | +| [`USE_OPENSSL_PC`](#use_openssl_pc) | 1.3.0 | `BOOL` | ON | Use `pkg-config` to find OpenSSL libraries. | +| [`OPENSSL_USE_STATIC_LIBS`](#openssl_use_static_libs) | 1.5.0 | `BOOL` | OFF | Link OpenSSL statically. | +| [`USE_STATIC_LIBSTDCXX`](#use_static_libstdcxx) | 1.2.0 | `BOOL` | OFF | Enforces linking the SRT library against the static `libstdc++` library. | +| [`WITH_COMPILER_PREFIX`](#with_compiler_prefix) | 1.3.0 | `STRING` | OFF | Sets C/C++ toolchains as `` and ``, overriding the default compiler. | +| [`WITH_COMPILER_TYPE`](#with_compiler_type) | 1.3.0 | `STRING` | OFF | Sets the compiler type to be used (values: gcc, cc, clang, etc.). | | [`WITH_EXTRALIBS`](#with_extralibs) | 1.3.0 | `STRING` | OFF | Option required for unusual situations when a platform-specific workaround is needed and some extra libraries must be passed explicitly for linkage. | -| [`WITH_SRT_NAME`](#with_srt_name) | 1.3.0 | `STRING` | OFF | Configure the SRT library name adding a custom `` | -| | | | | | +| [`WITH_SRT_NAME`](#with_srt_name) | 1.3.0 | `STRING` | OFF | Configure the SRT library name adding a custom ``. | +| | | | | | \* See the option description for more details. @@ -456,12 +456,7 @@ **`--openssl-crypto-library=`** Used to configure the path to an OpenSSL crypto library. Ignored when encryption -is disabled (ENABLE_ENCRYPTION = OFF). Supported libraries are: - - - openssl (default) - - gnutls - - mbedtls - +is disabled (ENABLE_ENCRYPTION = OFF). See [`USE_ENCLIB`](#use_enclib) for the list of supported libraries. [:arrow_up:   Back to List of Build Options](#list-of-build-options) @@ -534,6 +529,7 @@ Encryption library to be used. Possible options for ``: * openssl (default) +* openssl-evp (OpenSSL EVP API, since 1.5.1) * gnutls (with nettle) * mbedtls diff -Nru srt-1.5.0/docs/build/package-managers.md srt-1.5.1/docs/build/package-managers.md --- srt-1.5.0/docs/build/package-managers.md 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/docs/build/package-managers.md 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,31 @@ +# Package Managers + +The SRT library can be installed with the help of the following package managers: + +- [Vcpkg](https://github.com/Microsoft/vcpkg) + + The SRT library package name is `libsrt`. For example, to install the library on Unix systems, run: + + ``` + ./vcpkg install libsrt + ``` + + The `libsrt` port in `vcpkg` is kept up to date by Microsoft team members and community contributors. If the SRT version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the `vcpkg` repository. + +- [Homebrew](https://brew.sh/) + + The `Homebrew` formula is [`srt`](https://formulae.brew.sh/formula/srt). See also ["Building SRT on macOS"](./build-macOS.md). + + ``` + brew install srt + ``` + +- [Apt](https://ubuntu.com/server/docs/package-management) + + ``` + sudo apt install libsrt + ``` + +- [Conan](https://conan.io/) + + The SRT library package name is [`srt`](https://conan.io/center/srt). diff -Nru srt-1.5.0/docs/README.md srt-1.5.1/docs/README.md --- srt-1.5.0/docs/README.md 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/docs/README.md 2022-09-21 14:29:01.000000000 +0000 @@ -2,35 +2,36 @@ ## SRT API Documents -| Document Title | Folder | File Name | Description | -| :----------------------------------------------------- | :---------------------------- | :------------------------------------------------- | :--------------------------------------------------- | -| [SRT API](API/API.md) | [API](API/) | [API.md](API/API.md) | Detailed description of the SRT C API. | -| [SRT API Functions](API/API-functions.md) | [API](API/) | [API-functions.md](API/API-functions.md) | Reference document for SRT API functions. | -| [SRT API Socket Options](API/API-socket-options.md) | [API](API/) | [API-socket-options.md](API/API-socket-options.md) | Instructions and list of socket options for SRT API. | -| [SRT Statistics](API/statistics.md) | [API](API/) | [statistics.md](API/statistics.md) | How to use SRT socket and socket group statistics. | -| [Configuration Guidelines](API/configuration-guidelines.md) | [API](API/) | [configuration-guidelines.md](API/configuration-guidelines.md) | How to configure SRT buffers. | -| | | | | +| Document Title | Folder | File Name | Description | +| :---------------------------------------------------------- | :---------------------------- | :------------------------------------------------------------- | :--------------------------------------------------- | +| [SRT API](API/API.md) | [API](API/) | [API.md](API/API.md) | Detailed description of the SRT C API. | +| [SRT API Functions](API/API-functions.md) | [API](API/) | [API-functions.md](API/API-functions.md) | Reference document for SRT API functions. | +| [SRT API Socket Options](API/API-socket-options.md) | [API](API/) | [API-socket-options.md](API/API-socket-options.md) | Instructions and list of socket options for SRT API. | +| [SRT Statistics](API/statistics.md) | [API](API/) | [statistics.md](API/statistics.md) | How to use SRT socket and socket group statistics. | +| [Configuration Guidelines](API/configuration-guidelines.md) | [API](API/) | [configuration-guidelines.md](API/configuration-guidelines.md) | How to configure SRT buffers. | +| | | | | ## Build Instructions -| Document Title | Folder | File Name | Description | -| :----------------------------------------------------------- | :---------------------------- | :----------------------------------------- | :----------------------------------------------------------- | -| [SRT Build Options](build/build-options.md) | [build](build/) | [build-options.md](build/build-options.md) | Description of CMake build system, configure script, and build options. | -| [Building SRT on Linux (Ubuntu/CentOS)](build/build-linux.md) | [build](build/) | [build-linux.md](build/build-linux.md) | Build instructions for Linux (Ubuntu/CentOS). | -| [Building SRT on Windows](build/build-win.md) | [build](build/) | [build-win.md](build/build-win.md) | Build instructions for Windows. | -| [Building SRT on macOS](build/build-macOS.md) | [build](build/) | [build-macOS.md](build/build-macOS.md) | Build instructions for macOS. | -| [Building SRT on iOS](build/build-iOS.md) | [build](build/) | [build-iOS.md](build/build-iOS.md) | Build instructions for iOS. | -| [Building SRT on Android](build/build-android.md) | [build](build/) | [build-android.md](build/build-android.md) | Build instructions for Android. | -| | | | | +| Document Title | Folder | File Name | Description | +| :------------------------------------------------------------ | :---------------------------- | :----------------------------------------------- | :---------------------------------------------------------------------- | +| [SRT Build Options](build/build-options.md) | [build](build/) | [build-options.md](build/build-options.md) | Description of CMake build system, configure script, and build options. | +| [Building SRT on Linux (Ubuntu/CentOS)](build/build-linux.md) | [build](build/) | [build-linux.md](build/build-linux.md) | Build instructions for Linux (Ubuntu/CentOS). | +| [Building SRT on Windows](build/build-win.md) | [build](build/) | [build-win.md](build/build-win.md) | Build instructions for Windows. | +| [Building SRT on macOS](build/build-macOS.md) | [build](build/) | [build-macOS.md](build/build-macOS.md) | Build instructions for macOS. | +| [Building SRT on iOS](build/build-iOS.md) | [build](build/) | [build-iOS.md](build/build-iOS.md) | Build instructions for iOS. | +| [Building SRT on Android](build/build-android.md) | [build](build/) | [build-android.md](build/build-android.md) | Build instructions for Android. | +| [Package Managers](build/package-managers.md) | [build](build/) | [package-managers.md](build/package-managers.md) | Package managers supporting SRT library. | +| | | | | ## Development Documents -| Document Title | Folder | File Name | Description | -| :----------------------------------------------- | :---------------------------- | :----------------------------------------------- | :----------------------------------------------------------- | -| [SRT Developer's Guide](dev/developers-guide.md) | [dev](dev/) | [developers-guide.md](dev/developers-guide.md) | Development setup, project structure, coding rules,
submitting issues & PRs, etc. | -| [Low Level Info](dev/low-level-info.md) | [dev](dev/) | [low-level-info.md](dev/low-level-info.md) | Low level information for the SRT project (only
mutex locking). | -| [Making SRT Better](dev/making-srt-better.md) | [dev](dev/) | [making-srt-better.md](dev/making-srt-better.md) | Guidelines for problem reporting, collecting debug logs
and pcaps. | -| | | | | +| Document Title | Folder | File Name | Description | +| :----------------------------------------------- | :---------------------------- | :----------------------------------------------- | :------------------------------------------------------------------------------------- | +| [SRT Developer's Guide](dev/developers-guide.md) | [dev](dev/) | [developers-guide.md](dev/developers-guide.md) | Development setup, project structure, coding rules,
submitting issues & PRs, etc. | +| [Low Level Info](dev/low-level-info.md) | [dev](dev/) | [low-level-info.md](dev/low-level-info.md) | Low level information for the SRT project (only
mutex locking). | +| [Making SRT Better](dev/making-srt-better.md) | [dev](dev/) | [making-srt-better.md](dev/making-srt-better.md) | Guidelines for problem reporting, collecting debug logs
and pcaps. | +| | | | | ## Features diff -Nru srt-1.5.0/haicrypt/cryspr.c srt-1.5.1/haicrypt/cryspr.c --- srt-1.5.0/haicrypt/cryspr.c 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr.c 2022-09-21 14:29:01.000000000 +0000 @@ -31,11 +31,13 @@ } int crysprStub_AES_SetKey( + int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR|AESGDM] */ bool bEncrypt, /* true Enxcrypt key, false: decrypt */ const unsigned char *kstr, /* key sttring*/ size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */ CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */ { + (void)cipher_type; (void)bEncrypt; (void)kstr; (void)kstr_len; @@ -122,10 +124,10 @@ static int crysprFallback_KmSetKey(CRYSPR_cb *cryspr_cb, bool bWrap, const unsigned char *kek, size_t kek_len) { - CRYSPR_AESCTX *aes_kek = &cryspr_cb->aes_kek; + CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb); - if (cryspr_cb->cryspr->aes_set_key(bWrap, kek, kek_len, aes_kek)) { - HCRYPT_LOG(LOG_ERR, "AES_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt"); + if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESECB, bWrap, kek, kek_len, aes_kek)) { + HCRYPT_LOG(LOG_ERR, "aes_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt"); return(-1); } return(0); @@ -163,7 +165,9 @@ memcpy(B + 8, R, 8); { size_t outlen = 16; - cryspr_cb->cryspr->aes_ecb_cipher(true, &cryspr_cb->aes_kek, B, 16, B, &outlen); + CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb); + + cryspr_cb->cryspr->aes_ecb_cipher(true, aes_kek, B, 16, B, &outlen); } A[7] ^= (unsigned char)(t & 0xff); if (t > 0xff) @@ -211,7 +215,9 @@ memcpy(B + 8, R, 8); { size_t outlen = 16; - cryspr_cb->cryspr->aes_ecb_cipher(false, &cryspr_cb->aes_kek, B, 16, B, &outlen); + CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb); + + cryspr_cb->cryspr->aes_ecb_cipher(false, aes_kek, B, 16, B, &outlen); } memcpy(R, B + 8, 8); } @@ -237,20 +243,23 @@ return(out_buf); } -static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len) +CRYSPR_cb *crysprHelper_Open(CRYSPR_methods *cryspr, size_t cb_len, size_t max_len) { CRYSPR_cb *cryspr_cb; unsigned char *membuf; size_t memsiz, padded_len = hcryptMsg_PaddedLen(max_len, 128/8); - HCRYPT_LOG(LOG_DEBUG, "%s", "Using OpenSSL AES\n"); - - memsiz = sizeof(*cryspr_cb) + (CRYSPR_OUTMSGMAX * padded_len); + if(cb_len < sizeof(*cryspr_cb)) { + HCRYPT_LOG(LOG_ERR, "crysprHelper_Open() cb_len too small (%zd < %zd)n", + cb_len, sizeof(*cryspr_cb)); + return(NULL); + } + memsiz = cb_len + (CRYSPR_OUTMSGMAX * padded_len); #if !CRYSPR_HAS_AESCTR memsiz += HCRYPT_CTR_STREAM_SZ; #endif /* !CRYSPR_HAS_AESCTR */ - cryspr_cb = malloc(memsiz); + cryspr_cb = calloc(1, memsiz); if (NULL == cryspr_cb) { HCRYPT_LOG(LOG_ERR, "malloc(%zd) failed\n", memsiz); return(NULL); @@ -258,6 +267,9 @@ membuf = (unsigned char *)cryspr_cb; membuf += sizeof(*cryspr_cb); + /*reserve cryspr's private data that caller will initialize */ + membuf += (cb_len-sizeof(CRYSPR_cb)); + #if !CRYSPR_HAS_AESCTR cryspr_cb->ctr_stream = membuf; membuf += HCRYPT_CTR_STREAM_SZ; @@ -275,24 +287,37 @@ return(cryspr_cb); } +int crysprHelper_Close(CRYSPR_cb *cryspr_cb) +{ + free(cryspr_cb); + return(0); +} + +static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len) +{ + CRYSPR_cb *cryspr_cb; + + cryspr_cb = crysprHelper_Open(cryspr, sizeof(CRYSPR_cb), max_len); + return(cryspr_cb); +} + static int crysprFallback_Close(CRYSPR_cb *cryspr_cb) { - free(cryspr_cb); - return(0); + return(crysprHelper_Close(cryspr_cb)); } static int crysprFallback_MsSetKey(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx, const unsigned char *key, size_t key_len) { - CRYSPR_AESCTX *aes_sek = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; /* Ctx tells if it's for odd or even key */ + CRYSPR_AESCTX *aes_sek = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */ if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT) /* Encrypt key */ || (ctx->mode == HCRYPT_CTX_MODE_AESCTR)) { /* CTR mode decrypts using encryption methods */ - if (cryspr_cb->cryspr->aes_set_key(true, key, key_len, aes_sek)) { + if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESCTR, true, key, key_len, aes_sek)) { HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_encrypt_key(sek) failed\n"); return(-1); } } else { /* Decrypt key */ - if (cryspr_cb->cryspr->aes_set_key(false, key, key_len, aes_sek)) { + if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESCTR, false, key, key_len, aes_sek)) { HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_decrypt_key(sek) failed\n"); return(-1); } @@ -374,135 +399,78 @@ /* Get buffer room from the internal circular output buffer */ out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, in_data[0].len); - if (NULL != out_msg) { - switch(ctx->mode) { - case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */ - { -#if CRYSPR_HAS_AESCTR - /* Get current key (odd|even) from context */ - CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; - unsigned char iv[CRYSPR_AESBLKSZ]; + if (NULL == out_msg) { + /* input data too big */ + return(-1); + } - /* Get input packet index (in network order) */ - hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1); + switch(ctx->mode) { + case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */ + { + /* Get current key (odd|even) from context */ + CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */ - /* - * Compute the Initial Vector - * IV (128-bit): - * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | 0s | pki | ctr | - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * XOR - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | nonce + - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * - * pki (32-bit): packet index - * ctr (16-bit): block counter - * nonce (112-bit): number used once (salt) - */ - hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv); + unsigned char iv[CRYSPR_AESBLKSZ]; - cryspr_cb->cryspr->aes_ctr_cipher(true, aes_key, iv, in_data[0].payload, in_data[0].len, - &out_msg[pfx_len]); -#else /*CRYSPR_HAS_AESCTR*/ - /* Get current key (odd|even) from context */ - CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; - unsigned char iv[CRYSPR_AESBLKSZ]; - int iret = 0; + /* Get input packet index (in network order) */ + hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1); - /* Get input packet index (in network order) */ - hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1); + /* + * Compute the Initial Vector + * IV (128-bit): + * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | 0s | pki | ctr | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * XOR + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | nonce + + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * pki (32-bit): packet index + * ctr (16-bit): block counter + * nonce (112-bit): number used once (salt) + */ + hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv); - /* - * Compute the Initial Vector - * IV (128-bit): - * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | 0s | pki | ctr | - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * XOR - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | nonce + - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * - * pki (32-bit): packet index - * ctr (16-bit): block counter - * nonce (112-bit): number used once (salt) - */ - hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv); +#if CRYSPR_HAS_AESCTR + cryspr_cb->cryspr->aes_ctr_cipher(true, aes_key, iv, in_data[0].payload, in_data[0].len, + &out_msg[pfx_len]); +#else /*CRYSPR_HAS_AESCTR*/ + /* Create CtrStream. May be longer than in_len (next cryspr block size boundary) */ + int iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv); + if (iret) { + return(iret); + } + /* Reserve output buffer for cryspr */ + out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, cryspr_cb->ctr_stream_len); - /* Create CtrStream. May be longer than in_len (next cryspr block size boundary) */ - iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv); - if (iret) { - return(iret); - } - /* Reserve output buffer for cryspr */ - out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, cryspr_cb->ctr_stream_len); - - /* Create KeyStream (encrypt CtrStream) */ - iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key, - cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len, - &out_msg[pfx_len], &out_len); - if (iret) { - HCRYPT_LOG(LOG_ERR, "%s", "hcOpenSSL_AES_ecb_cipher(encrypt, failed\n"); - return(iret); - } -#endif/*CRYSPR_HAS_AESCTR*/ - /* Prepend packet prefix (clear text) in output buffer */ - memcpy(out_msg, in_data[0].pfx, pfx_len); - /* CTR mode output length is same as input, no padding */ - out_len = in_data[0].len; - break; + /* Create KeyStream (encrypt CtrStream) */ + iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key, + cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len, + &out_msg[pfx_len], &out_len); + if (iret) { + HCRYPT_LOG(LOG_ERR, "%s", "hcOpenSSL_AES_ecb_cipher(encrypt, failed\n"); + return(iret); } - case HCRYPT_CTX_MODE_CLRTXT: /* Clear text mode (transparent mode for tests) */ - memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len); - memcpy(out_msg, in_data[0].pfx, pfx_len); - out_len = in_data[0].len; - break; - default: - /* Unsupported cipher mode */ - return(-1); +#endif/*CRYSPR_HAS_AESCTR*/ + /* Prepend packet prefix (clear text) in output buffer */ + memcpy(out_msg, in_data[0].pfx, pfx_len); + /* CTR mode output length is same as input, no padding */ + out_len = in_data[0].len; + break; } - } else { - /* input data too big */ - return(-1); + case HCRYPT_CTX_MODE_CLRTXT: /* Clear text mode (transparent mode for tests) */ + memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len); + memcpy(out_msg, in_data[0].pfx, pfx_len); + out_len = in_data[0].len; + break; + default: + /* Unsupported cipher mode */ + return(-1); } - if (out_len > 0) { - /* Encrypted messages have been produced */ - if (NULL == out_p) { - /* - * Application did not provided output buffer, - * so copy encrypted message back in input buffer - */ - memcpy(in_data[0].pfx, out_msg, pfx_len); -#if !CRYSPR_HAS_AESCTR - if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) { - /* XOR KeyStream with input text directly in input buffer */ - hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len); - }else{ - /* Copy output data back in input buffer */ - memcpy(in_data[0].payload, &out_msg[pfx_len], out_len); - } -#else /* CRYSPR_HAS_AESCTR */ - /* Copy output data back in input buffer */ - memcpy(in_data[0].payload, &out_msg[pfx_len], out_len); -#endif /* CRYSPR_HAS_AESCTR */ - } else { - /* Copy header in output buffer if needed */ - if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len); -#if !CRYSPR_HAS_AESCTR - if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) { - hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len); - } -#endif /* CRYSPR_HAS_AESCTR */ - out_p[0] = out_msg; - out_len_p[0] = pfx_len + out_len; - *nbout_p = 1; - } - } else { + if (out_len <= 0) { /* * Nothing out * This is not an error for implementations using deferred/async processing @@ -512,6 +480,39 @@ if (nbout_p != NULL) *nbout_p = 0; return(-1); } + + /* Encrypted messages have been produced */ + if (NULL == out_p) { + /* + * Application did not provided output buffer, + * so copy encrypted message back in input buffer + */ + memcpy(in_data[0].pfx, out_msg, pfx_len); +#if !CRYSPR_HAS_AESCTR + if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) { + /* XOR KeyStream with input text directly in input buffer */ + hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len); + }else{ + /* Copy output data back in input buffer */ + memcpy(in_data[0].payload, &out_msg[pfx_len], out_len); + } +#else /* CRYSPR_HAS_AESCTR */ + /* Copy output data back in input buffer */ + memcpy(in_data[0].payload, &out_msg[pfx_len], out_len); +#endif /* CRYSPR_HAS_AESCTR */ + } else { + /* Copy header in output buffer if needed */ + if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len); +#if !CRYSPR_HAS_AESCTR + if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) { + hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len); + } +#endif /* CRYSPR_HAS_AESCTR */ + out_p[0] = out_msg; + out_len_p[0] = pfx_len + out_len; + *nbout_p = 1; + } + return(0); } @@ -535,7 +536,7 @@ { #if CRYSPR_HAS_AESCTR /* Get current key (odd|even) from context */ - CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; + CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); unsigned char iv[CRYSPR_AESBLKSZ]; /* Get input packet index (in network order) */ @@ -564,7 +565,7 @@ out_len = in_data[0].len; #else /*CRYSPR_HAS_AESCTR*/ /* Get current key (odd|even) from context */ - CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; + CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); unsigned char iv[CRYSPR_AESBLKSZ]; int iret = 0; diff -Nru srt-1.5.0/haicrypt/cryspr-config.h srt-1.5.1/haicrypt/cryspr-config.h --- srt-1.5.0/haicrypt/cryspr-config.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-config.h 2022-09-21 14:29:01.000000000 +0000 @@ -9,6 +9,10 @@ #include "cryspr-openssl.h" #define cryspr4SRT() crysprOpenSSL() #define CRYSPR_IMPL_DESC "OpenSSL-AES" +#elif defined(USE_OPENSSL_EVP) +#include "cryspr-openssl-evp.h" +#define cryspr4SRT() crysprOpenSSL_EVP() +#define CRYSPR_IMPL_DESC "OpenSSL-EVP" #elif defined(USE_GNUTLS) #include "cryspr-gnutls.h" #define cryspr4SRT() crysprGnuTLS() diff -Nru srt-1.5.0/haicrypt/cryspr-gnutls.c srt-1.5.1/haicrypt/cryspr-gnutls.c --- srt-1.5.0/haicrypt/cryspr-gnutls.c 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-gnutls.c 2022-09-21 14:29:01.000000000 +0000 @@ -13,6 +13,8 @@ written by Haivision Systems Inc. + 2022-05-19 (jdube) + CRYSPR2 adaptation 2019-06-27 (jdube) GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT) *****************************************************************************/ @@ -24,6 +26,10 @@ typedef struct tag_crysprGnuTLS_AES_cb { CRYSPR_cb ccb; /* CRYSPR control block */ /* Add other cryptolib specific data here */ +#ifdef CRYSPR2 + CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */ + CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */ +#endif } crysprGnuTLS_cb; @@ -33,11 +39,14 @@ } int crysprGnuTLS_AES_SetKey( + int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */ bool bEncrypt, /* true:encrypt key, false:decrypt key*/ const unsigned char *kstr, /* key string */ size_t kstr_len, /* kstr length in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */ CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */ { + (void)cipher_type; + if (bEncrypt) { /* Encrypt key */ if (!(kstr_len == 16 || kstr_len == 24 || kstr_len == 32)) { HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) bad length\n"); @@ -114,6 +123,31 @@ return 0; } +#ifdef CRYSPR2 +static CRYSPR_cb *crysprGnuTLS_Open(CRYSPR_methods *cryspr, size_t max_len) +{ + crysprGnuTLS_cb *aes_data; + CRYSPR_cb *cryspr_cb; + + aes_data = (crysprGnuTLS_cb *)crysprHelper_Open(cryspr, sizeof(crysprGnuTLS_cb), max_len); + if (NULL == aes_data) { + HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprGnuTLS_cb), max_len); + return(NULL); + } + + aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key + aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key + aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key + + return(&aes_data->ccb); +} + +static int crysprGnuTLS_Close(CRYSPR_cb *cryspr_cb) +{ + return(crysprHelper_Close(cryspr_cb)); +} +#endif /* CRYSPR2 */ + #ifdef CRYSPR_HAS_PBKDF2 /* * Password-based Key Derivation Function @@ -157,8 +191,13 @@ #endif //--Crypto Session (Top API) + #ifdef CRYSPR2 + crysprGnuTLS_methods.open = crysprGnuTLS_Open; + crysprGnuTLS_methods.close = crysprGnuTLS_Close; + #else /* CRYSPR2 */ // crysprGnuTLS_methods.open = // crysprGnuTLS_methods.close = + #endif /* CRYSPR2 */ //--Keying material (km) encryption #if CRYSPR_HAS_PBKDF2 crysprGnuTLS_methods.km_pbkdf2 = crysprGnuTLS_KmPbkdf2; diff -Nru srt-1.5.0/haicrypt/cryspr.h srt-1.5.1/haicrypt/cryspr.h --- srt-1.5.0/haicrypt/cryspr.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr.h 2022-09-21 14:29:01.000000000 +0000 @@ -39,8 +39,17 @@ #include "cryspr-config.h" typedef struct tag_CRYSPR_cb { +#ifdef CRYSPR2 + CRYSPR_AESCTX *aes_kek; /* Key Encrypting Key (KEK) */ + CRYSPR_AESCTX *aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */ +#define CRYSPR_GETKEK(cb) ((cb)->aes_kek) +#define CRYSPR_GETSEK(cb,kk) ((cb)->aes_sek[kk]) +#else /*CRYSPR2*/ CRYSPR_AESCTX aes_kek; /* Key Encrypting Key (KEK) */ CRYSPR_AESCTX aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */ +#define CRYSPR_GETKEK(cb) (&((cb)->aes_kek)) +#define CRYSPR_GETSEK(cb,kk) (&((cb)->aes_sek[kk])) +#endif /*CRYSPR2*/ struct tag_CRYSPR_methods *cryspr; @@ -69,6 +78,7 @@ int rn_len); int (*aes_set_key)( + int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR|AESGDM] */ bool bEncrypt, /* true Enxcrypt key, false: decrypt */ const unsigned char *kstr,/* key string*/ size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */ @@ -194,6 +204,9 @@ } CRYSPR_methods; +CRYSPR_cb *crysprHelper_Open(CRYSPR_methods *cryspr, size_t cb_len, size_t max_len); +int crysprHelper_Close(CRYSPR_cb *cryspr_cb); + CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr); #ifdef __cplusplus diff -Nru srt-1.5.0/haicrypt/cryspr-mbedtls.c srt-1.5.1/haicrypt/cryspr-mbedtls.c --- srt-1.5.0/haicrypt/cryspr-mbedtls.c 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-mbedtls.c 2022-09-21 14:29:01.000000000 +0000 @@ -13,6 +13,8 @@ written by Haivision Systems Inc. + 2022-05-19 (jdube) + CRYSPR2 adaptation 2019-06-27 (jdube) GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT) *****************************************************************************/ @@ -29,11 +31,14 @@ // Static members of cryspr::mbedtls class. static mbedtls_ctr_drbg_context crysprMbedtls_ctr_drbg; static mbedtls_entropy_context crysprMbedtls_entropy; -static mbedtls_md_context_t crysprMbedtls_mdctx; typedef struct tag_crysprGnuTLS_AES_cb { CRYSPR_cb ccb; /* CRYSPR control block */ /* Add other cryptolib specific data here */ +#ifdef CRYSPR2 + CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */ + CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */ +#endif } crysprMbedtls_cb; @@ -49,18 +54,23 @@ } int crysprMbedtls_AES_SetKey( + int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */ bool bEncrypt, /* true:encrypt key, false:decrypt key*/ const unsigned char *kstr, /* key string */ size_t kstr_len, /* kstr length in bytes (16, 24, or 32 bytes, for AES128,AES192, or AES256) */ CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */ { + (void)cipher_type; + if (!(kstr_len == 16 || kstr_len == 24 || kstr_len == 32)) { HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) bad length\n"); return -1; } int ret; - +#ifdef CRYSPR2 + (void)cipher_type; +#endif // mbedtls uses the "bits" convention (128, 192, 254), just like openssl. // kstr_len is in "bytes" convention (16, 24, 32). @@ -146,6 +156,31 @@ return 0; } +#ifdef CRYSPR2 +static CRYSPR_cb *crysprMbedtls_Open(CRYSPR_methods *cryspr, size_t max_len) +{ + crysprMbedtls_cb *aes_data; + CRYSPR_cb *cryspr_cb; + + aes_data = (crysprMbedtls_cb *)crysprHelper_Open(cryspr, sizeof(crysprMbedtls_cb), max_len); + if (NULL == aes_data) { + HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprMbedtls_cb), max_len); + return(NULL); + } + + aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key + aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key + aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key + + return(&aes_data->ccb); +} + +static int crysprMbedtls_Close(CRYSPR_cb *cryspr_cb) +{ + return(crysprHelper_Close(cryspr_cb)); +} +#endif /* CRYSPR2 */ + /* * Password-based Key Derivation Function */ @@ -161,10 +196,30 @@ { (void)cryspr_cb; - int ret = mbedtls_pkcs5_pbkdf2_hmac(&crysprMbedtls_mdctx, + const mbedtls_md_info_t* ifo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + if ( ifo == NULL ) { + // XXX report error, log? + return -1; + } + + mbedtls_md_context_t mdctx; + mbedtls_md_init(&mdctx); + + const int yes_use_hmac = 1; + int ret; + if ( (ret = mbedtls_md_setup(&mdctx, ifo, yes_use_hmac)) != 0 ) { + mbedtls_md_free(&mdctx); + + // XXX report error, log? + return ret; + } + + ret = mbedtls_pkcs5_pbkdf2_hmac(&mdctx, (unsigned char*)passwd, passwd_len, salt, salt_len, itr, key_len, out); + mbedtls_md_free(&mdctx); + if (ret == 0) return 0; @@ -196,8 +251,13 @@ #endif //--Crypto Session (Top API) +#ifdef CRYSPR2 + crysprMbedtls_methods.open = crysprMbedtls_Open; + crysprMbedtls_methods.close = crysprMbedtls_Close; +#else // crysprMbedtls_methods.open = // crysprMbedtls_methods.close = +#endif //--Keying material (km) encryption crysprMbedtls_methods.km_pbkdf2 = crysprMbedtls_KmPbkdf2; // crysprMbedtls_methods.km_setkey = @@ -220,14 +280,6 @@ return NULL; } - // Ok, mbedtls with all flexibility you couldn't make it more complicated. - - mbedtls_md_init(&crysprMbedtls_mdctx); - const mbedtls_md_info_t* ifo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - const int yes_use_hmac = 1; - mbedtls_md_setup(&crysprMbedtls_mdctx, ifo, yes_use_hmac); - - return(&crysprMbedtls_methods); } diff -Nru srt-1.5.0/haicrypt/cryspr-mbedtls.h srt-1.5.1/haicrypt/cryspr-mbedtls.h --- srt-1.5.0/haicrypt/cryspr-mbedtls.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-mbedtls.h 2022-09-21 14:29:01.000000000 +0000 @@ -52,7 +52,7 @@ /* #define CRYSPR_AESCTX to the CRYSPR specifix AES key context object. This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK -It is set from hte keystring through CRYSPR_methods.aes_set_key and passed +It is set from the keystring through CRYSPR_methods.aes_set_key and passed to CRYSPR_methods.aes_XXX. */ typedef mbedtls_aes_context CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */ diff -Nru srt-1.5.0/haicrypt/cryspr-openssl.c srt-1.5.1/haicrypt/cryspr-openssl.c --- srt-1.5.0/haicrypt/cryspr-openssl.c 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-openssl.c 2022-09-21 14:29:01.000000000 +0000 @@ -13,18 +13,23 @@ written by Haivision Systems Inc. + 2022-05-19 (jdube) + CRYSPR2 adaptation 2019-06-26 (jdube) - OpenSSL CRYSPR/4SRT (CRYypto Service PRovider for SRT). + OpenSSL Direct AES CRYSPR/4SRT (CRYypto Service PRovider for SRT). *****************************************************************************/ #include "hcrypt.h" #include - typedef struct tag_crysprOpenSSL_AES_cb { - CRYSPR_cb ccb; - /* Add cryptolib specific data here */ + CRYSPR_cb ccb; + /* Add cryptolib specific data here */ +#ifdef CRYSPR2 + CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */ + CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */ +#endif } crysprOpenSSL_cb; @@ -34,11 +39,14 @@ } int crysprOpenSSL_AES_SetKey( + int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */ bool bEncrypt, /* true Enxcrypt key, false: decrypt */ const unsigned char *kstr, /* key sttring*/ size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */ CRYSPR_AESCTX *aes_key) /* CRYpto Service PRovider AES Key context */ { + (void)cipher_type; + if (bEncrypt) { /* Encrypt key */ if (AES_set_encrypt_key(kstr, kstr_len * 8, aes_key)) { HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) failed\n"); @@ -123,7 +131,24 @@ #endif return 0; } +#ifdef CRYSPR2 +static CRYSPR_cb *crysprOpenSSL_Open(CRYSPR_methods *cryspr, size_t max_len) +{ + crysprOpenSSL_cb *aes_data; + + aes_data = (crysprOpenSSL_cb *)crysprHelper_Open(cryspr, sizeof(crysprOpenSSL_cb), max_len); + if (NULL == aes_data) { + HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprOpenSSL_cb), max_len); + return(NULL); + } + + aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key + aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key + aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key + return(&aes_data->ccb); +} +#endif /* CRYSPR2 */ /* * Password-based Key Derivation Function */ @@ -148,8 +173,7 @@ const unsigned char *sek, unsigned int seklen) { - crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb; - AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key + AES_KEY *kek = CRYSPR_GETKEK(cryspr_cb); //key encrypting key return(((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1); } @@ -160,8 +184,7 @@ const unsigned char *wrap, unsigned int wraplen) { - crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb; - AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key + AES_KEY *kek = CRYSPR_GETKEK(cryspr_cb); //key encrypting key return(((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0 : -1); } @@ -192,7 +215,11 @@ #endif //--Crypto Session API----------------------------------------- +#ifdef CRYSPR2 + crysprOpenSSL_methods.open = crysprOpenSSL_Open; +#else // crysprOpenSSL_methods.open = +#endif // crysprOpenSSL_methods.close = //--Keying material (km) encryption diff -Nru srt-1.5.0/haicrypt/cryspr-openssl-evp.c srt-1.5.1/haicrypt/cryspr-openssl-evp.c --- srt-1.5.0/haicrypt/cryspr-openssl-evp.c 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-openssl-evp.c 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,335 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + + 2022-05-19 (jdube) + OpenSSL EVP CRYSPR/4SRT (CRYypto Service PRovider for SRT). +*****************************************************************************/ + +#include "hcrypt.h" + +#include + +typedef struct tag_crysprOpenSSL_EVP_cb +{ + CRYSPR_cb ccb; + /* Add cryptolib specific data here */ +} crysprOpenSSL_EVP_cb; + +int crysprOpenSSL_EVP_Prng(unsigned char* rn, int len) +{ + return (RAND_bytes(rn, len) <= 0 ? -1 : 0); +} + +const EVP_CIPHER* (*Xcipher_fnptr)(void) = EVP_aes_128_ecb; + +const EVP_CIPHER* (*_crysprOpenSSL_EVP_cipher_fnptr[][3])(void) = { + {NULL, NULL, NULL}, + {EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb}, + {EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr}, +}; + +int crysprOpenSSL_EVP_AES_SetKey( + int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */ + bool bEncrypt, /* true Enxcrypt key, false: decrypt */ + const unsigned char* kstr, /* key sttring*/ + size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128, AES192, or AES256) */ + CRYSPR_AESCTX* aes_key) /* CRYpto Service PRovider AES Key context */ +{ + const EVP_CIPHER* cipher = NULL; + int idxKlen = (kstr_len / 8) - 2; /* key_len index in cipher_fnptr array in [0,1,2] range */ + + switch (cipher_type) + { + case HCRYPT_CTX_MODE_CLRTXT: + return 0; + case HCRYPT_CTX_MODE_AESECB: + break; + case HCRYPT_CTX_MODE_AESCTR: +#if !CRYSPR_HAS_AESCTR + /* internal implementation of AES-CTR using crypto lib's AES-ECB */ + cipher_type = HCRYPT_CTX_MODE_AESECB; +#endif + break; + default: + HCRYPT_LOG(LOG_ERR, + "invalid cipher type (%d). Expected: [%d..%d]\n", + cipher_type, + HCRYPT_CTX_MODE_AESECB, + HCRYPT_CTX_MODE_AESCTR); + return (-1); + } + switch (kstr_len) + { + case 128 / 8: + case 192 / 8: + case 256 / 8: + break; + default: + HCRYPT_LOG(LOG_ERR, "invalid key length (%d). Expected: 16, 24, 32\n", (int)kstr_len); + return -1; + } + cipher = _crysprOpenSSL_EVP_cipher_fnptr[cipher_type][idxKlen](); + + if (bEncrypt) + { /* Encrypt key */ + if (!EVP_EncryptInit_ex(aes_key, cipher, NULL, kstr, NULL)) + { + HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n"); + return (-1); + } + } + else + { /* Decrypt key */ + if (!EVP_DecryptInit_ex(aes_key, cipher, NULL, kstr, NULL)) + { + HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n"); + return (-1); + } + } + return (0); +} + +static CRYSPR_cb* crysprOpenSSL_EVP_Open(CRYSPR_methods* cryspr, size_t max_len) +{ + CRYSPR_cb* cryspr_cb = crysprHelper_Open(cryspr, sizeof(*cryspr_cb), max_len); + if (NULL == cryspr_cb) + { + HCRYPT_LOG(LOG_ERR, "crysprFallback_Open(%p, %zd) failed\n", cryspr, max_len); + return (NULL); + } + + cryspr_cb->aes_kek = EVP_CIPHER_CTX_new(); + + cryspr_cb->aes_sek[0] = EVP_CIPHER_CTX_new(); + + cryspr_cb->aes_sek[1] = EVP_CIPHER_CTX_new(); + + return (cryspr_cb); +} + +static int crysprOpenSSL_EVP_Close(CRYSPR_cb* cryspr_cb) +{ + if (NULL != cryspr_cb) + { + EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[0]); + EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[1]); + EVP_CIPHER_CTX_free(cryspr_cb->aes_kek); + } + return (crysprHelper_Close(cryspr_cb)); +} + +#if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) + +int crysprOpenSSL_EVP_AES_EcbCipher(bool bEncrypt, /* true:encrypt, false:decrypt */ + CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */ + const unsigned char* indata, /* src (clear text if encrypt, cipher text otherwise)*/ + size_t inlen, /* indata length */ + unsigned char* out_txt, /* dst (cipher text if encrypt, clear text otherwise) */ + size_t* outlen_p) /* in/out dst len */ +{ + int nmore = inlen % CRYSPR_AESBLKSZ; /* bytes in last incomplete block */ + int nblk = inlen / CRYSPR_AESBLKSZ + (nmore ? 1 : 0); /* blocks including incomplete */ + size_t outsiz = (outlen_p ? *outlen_p : 0); + int c_len = 0, f_len = 0; + + (void)bEncrypt; // not needed, alreadydefined in context + + if (outsiz % CRYSPR_AESBLKSZ) + { + HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding"); + return (-1); /* output buf size must be a multiple of AES block size (16) */ + } + if ((outsiz > 16) && ((int)outsiz < (nblk * CRYSPR_AESBLKSZ))) + { + HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding"); + return (-1); /* output buf size must have room for PKCS7 padding */ + } + /* allows reusing of 'e' for multiple encryption cycles */ + if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, NULL, -1)) + { + HCRYPT_LOG(LOG_ERR, "EVP_CipherInit_ex(%p,NULL,...,-1) failed\n", aes_key); + return -1; + } + if (!EVP_CIPHER_CTX_set_padding(aes_key, 0)) + { + HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding(%p) failed", aes_key); + return -1; + } + + /* update ciphertext, c_len is filled with the length of ciphertext generated, + * cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes + */ + if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, inlen)) + { + HCRYPT_LOG(LOG_ERR, "EVP_CipherUpdate(%p, out, %d, in, %d) failed\n", aes_key, c_len, inlen); + return -1; + } + + /* update ciphertext with the final remaining bytes */ + /* Useless with pre-padding */ + f_len = 0; + if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len)) + { +#if ENABLE_HAICRYPT_LOGGING + char szErrBuf[256]; + HCRYPT_LOG(LOG_ERR, + "EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n", + c_len, + f_len, + ERR_error_string(ERR_get_error(), szErrBuf)); +#endif /*ENABLE_HAICRYPT_LOGGING*/ + return -1; + } + if (outlen_p != NULL) *outlen_p = nblk * CRYSPR_AESBLKSZ; + return 0; +} +#endif /* !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) */ + +int crysprOpenSSL_EVP_AES_CtrCipher(bool bEncrypt, /* true:encrypt, false:decrypt */ + CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */ + unsigned char* iv, /* iv */ + const unsigned char* indata, /* src */ + size_t inlen, /* length */ + unsigned char* out_txt) /* dest */ + +{ + int c_len, f_len; + + (void)bEncrypt; + + /* allows reusing of 'e' for multiple encryption cycles */ + if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, iv, -1)) + { + HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherInit_ex() failed"); + return -1; + } + if (!EVP_CIPHER_CTX_set_padding(aes_key, 0)) + { + HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding() failed"); + return -1; + } + + /* update ciphertext, c_len is filled with the length of ciphertext generated, + * cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes + */ + if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, inlen)) + { + HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherUpdate() failed"); + return -1; + } + + /* update ciphertext with the final remaining bytes */ + /* Useless with pre-padding */ + f_len = 0; + if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len)) + { +#if ENABLE_HAICRYPT_LOGGING + char szErrBuf[256]; + HCRYPT_LOG(LOG_ERR, + "EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n", + c_len, + f_len, + ERR_error_string(ERR_get_error(), szErrBuf)); +#endif /*ENABLE_HAICRYPT_LOGGING*/ + return -1; + } + return 0; +} + +/* + * Password-based Key Derivation Function + */ +int crysprOpenSSL_EVP_KmPbkdf2(CRYSPR_cb* cryspr_cb, + char* passwd, /* passphrase */ + size_t passwd_len, /* passphrase len */ + unsigned char* salt, /* salt */ + size_t salt_len, /* salt_len */ + int itr, /* iterations */ + size_t key_len, /* key_len */ + unsigned char* out) /* derived key */ +{ + (void)cryspr_cb; + int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd, passwd_len, salt, salt_len, itr, key_len, out); + return (rc == 1 ? 0 : -1); +} + +#if CRYSPR_HAS_AESKWRAP +int crysprOpenSSL_EVP_KmWrap(CRYSPR_cb* cryspr_cb, unsigned char* wrap, const unsigned char* sek, unsigned int seklen) +{ + crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb; + EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key + + return (((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1); +} + +int crysprOpenSSL_EVP_KmUnwrap(CRYSPR_cb* cryspr_cb, + unsigned char* sek, // Stream encrypting key + const unsigned char* wrap, + unsigned int wraplen) +{ + crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb; + EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key + + return (((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0 + : -1); +} +#endif /*CRYSPR_HAS_AESKWRAP*/ + +static CRYSPR_methods crysprOpenSSL_EVP_methods; + +CRYSPR_methods* crysprOpenSSL_EVP(void) +{ + if (NULL == crysprOpenSSL_EVP_methods.open) + { + crysprInit(&crysprOpenSSL_EVP_methods); // Default/fallback methods + + crysprOpenSSL_EVP_methods.prng = crysprOpenSSL_EVP_Prng; + //--CryptoLib Primitive API----------------------------------------------- + crysprOpenSSL_EVP_methods.aes_set_key = crysprOpenSSL_EVP_AES_SetKey; +#if CRYSPR_HAS_AESCTR + crysprOpenSSL_EVP_methods.aes_ctr_cipher = crysprOpenSSL_EVP_AES_CtrCipher; +#endif +#if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) + /* AES-ECB only required if cryspr has no AES-CTR and no AES KeyWrap */ + /* OpenSSL has both AESCTR and AESKWRP and the AESECB wrapper is only used + to test the falback methods */ + crysprOpenSSL_EVP_methods.aes_ecb_cipher = crysprOpenSSL_EVP_AES_EcbCipher; +#endif +#if !CRYSPR_HAS_PBKDF2 + crysprOpenSSL_EVP_methods.sha1_msg_digest = NULL; // Required to use eventual default/fallback KmPbkdf2 +#endif + + //--Crypto Session API----------------------------------------- + crysprOpenSSL_EVP_methods.open = crysprOpenSSL_EVP_Open; + crysprOpenSSL_EVP_methods.close = crysprOpenSSL_EVP_Close; + //--Keying material (km) encryption + +#if CRYSPR_HAS_PBKDF2 + crysprOpenSSL_EVP_methods.km_pbkdf2 = crysprOpenSSL_EVP_KmPbkdf2; +#else +#error There is no default/fallback method for PBKDF2 +#endif + // crysprOpenSSL_EVP_methods.km_setkey = +#if CRYSPR_HAS_AESKWRAP + crysprOpenSSL_EVP_methods.km_wrap = crysprOpenSSL_EVP_KmWrap; + crysprOpenSSL_EVP_methods.km_unwrap = crysprOpenSSL_EVP_KmUnwrap; +#endif + + //--Media stream (ms) encryption + // crysprOpenSSL_EVP_methods.ms_setkey = + // crysprOpenSSL_EVP_methods.ms_encrypt = + // crysprOpenSSL_EVP_methods.ms_decrypt = + } + return (&crysprOpenSSL_EVP_methods); +} diff -Nru srt-1.5.0/haicrypt/cryspr-openssl-evp.h srt-1.5.1/haicrypt/cryspr-openssl-evp.h --- srt-1.5.0/haicrypt/cryspr-openssl-evp.h 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/haicrypt/cryspr-openssl-evp.h 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2019 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + + 2022-05-19 (jdube) + OpenSSL EVP AES CRYSPR/4SRT (CRYypto Service PRovider for SRT). +*****************************************************************************/ + +#ifndef CRYSPR_OPENSSL_H +#define CRYSPR_OPENSSL_H + +#include /* PKCS5_xxx() */ +#include /* AES_xxx() */ +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)) +#include /* CRYPTO_xxx() */ +#endif +#include +#include +#include /* OPENSSL_VERSION_NUMBER */ + +/* Define CRYSPR_HAS_AESCTR to 1 if this CRYSPR has AESCTR cipher mode + if not set it 0 to use enable CTR cipher mode implementation using ECB cipher mode + and provide the aes_ecb_cipher method. +*/ +#define CRYSPR_HAS_AESCTR 1 + +/* Define CRYSPR_HAS_AESKWRAP to 1 if this CRYSPR has AES Key Wrap + if not set to 0 to enable default/fallback crysprFallback_AES_WrapKey/crysprFallback_AES_UnwrapKey methods + and provide the aes_ecb_cipher method . +*/ +#if 1 // Force internal AES-WRAP (using AES-ECB) until implemented with EVP (OPENSSL_VERSION_NUMBER < 0x00xxxxxxL) +#define CRYSPR_HAS_AESKWRAP 0 +#else +#define CRYSPR_HAS_AESKWRAP 1 +#endif + +/* Define CRYSPR_HAS_PBKDF2 to 1 if this CRYSPR has SHA1-HMAC Password-based Key Derivaion Function 2 + if not set to 0 to enable not-yet-implemented/fallback crysprFallback.km_pbkdf2 method + and provide the sha1_msg_digest method. +*/ +#define CRYSPR_HAS_PBKDF2 1 /* Define to 1 if CRYSPR has Password-based Key Derivaion Function 2 */ + +/* +#define CRYSPR_AESCTX to the CRYSPR specifix AES key context object. +This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK +It is set from hte keystring through CRYSPR_methods.aes_set_key and passed +to CRYSPR_methods.aes_*. +*/ +typedef EVP_CIPHER_CTX CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */ + +struct tag_CRYSPR_methods* crysprOpenSSL_EVP(void); + +#endif /* CRYSPR_OPENSSL_H */ diff -Nru srt-1.5.0/haicrypt/filelist-openssl-evp.maf srt-1.5.1/haicrypt/filelist-openssl-evp.maf --- srt-1.5.0/haicrypt/filelist-openssl-evp.maf 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/haicrypt/filelist-openssl-evp.maf 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,24 @@ +# HaiCrypt library contents + +PUBLIC HEADERS +haicrypt.h +hcrypt_ctx.h +hcrypt_msg.h + +PRIVATE HEADERS +hcrypt.h +cryspr.h +cryspr-openssl-evp.h +haicrypt_log.h + +SOURCES +cryspr.c +cryspr-openssl-evp.c +hcrypt.c +hcrypt_ctx_rx.c +hcrypt_ctx_tx.c +hcrypt_rx.c +hcrypt_sa.c +hcrypt_tx.c +hcrypt_xpt_srt.c +haicrypt_log.cpp diff -Nru srt-1.5.0/haicrypt/hcrypt_sa.c srt-1.5.1/haicrypt/hcrypt_sa.c --- srt-1.5.0/haicrypt/hcrypt_sa.c 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/haicrypt/hcrypt_sa.c 2022-09-21 14:29:01.000000000 +0000 @@ -37,7 +37,7 @@ ctx->cfg.pwd_len = 0; /* KEK: Key Encrypting Key */ if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, - (HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false), + ((HCRYPT_CTX_F_ENCRYPT & ctx->flags) ? true : false), secret->str, secret->len))) { HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", secret->len, iret); return(-1); @@ -87,7 +87,7 @@ HCRYPT_PRINTKEY(kek, kek_len, "kek"); /* KEK: Key Encrypting Key */ - if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, (HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false), kek, kek_len))) { + if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, ((HCRYPT_CTX_F_ENCRYPT & ctx->flags) ? true : false), kek, kek_len))) { HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", kek_len, iret); return(-1); } diff -Nru srt-1.5.0/README.md srt-1.5.1/README.md --- srt-1.5.0/README.md 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/README.md 2022-09-21 14:29:01.000000000 +0000 @@ -1,6 +1,6 @@ # Secure Reliable Transport (SRT) Protocol -[About SRT](#what-is-srt) | [Features](#features) | [Getting Started](#getting-started-with-srt) | [Builds](#build-instructions) | [Sample Apps and Tools](#sample-applications-and-tools) | [Contribute](#contributing) | [License](#license) | [Releases](#release-history) +[About SRT](#what-is-srt) | [Features](#features) | [Getting Started](#getting-started-with-srt) | [Build Instructions](#build-instructions) | [Sample Apps and Tools](#sample-applications-and-tools) | [Contribute](#contributing) | [License](#license) | [Releases](#release-history)

@@ -29,7 +29,7 @@ | **R**eliable | Recovers from severe packet loss | | **T**ransport | Dynamically adapts to changing network conditions | -In live streaming configurations, the SRT protocol maintains a constant end-to-end latency. This allows the live stream’s signal characteristics to be recreated on the receiver side, reducing the need for buffering. As packets are streamed from source to destination, SRT detects and adapts to real-time network conditions between the two endpoints. It helps compensate for jitter and bandwidth fluctuations due to congestion over noisy networks. +In live streaming configurations, the SRT protocol maintains a constant end-to-end latency. This allows the live stream's signal characteristics to be recreated on the receiver side, reducing the need for buffering. As packets are streamed from source to destination, SRT detects and adapts to real-time network conditions between the two endpoints. It helps compensate for jitter and bandwidth fluctuations due to congestion over noisy networks. [SRT implements AES encryption](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-6) to protect the payload of the media streams, and offers various error recovery mechanisms for minimizing the packet loss that is typical of Internet connections, of which Automatic Repeat reQuest (ARQ) is the primary method. With ARQ, when a receiver detects that a packet is missing it sends an alert to the sender requesting retransmission of this missing packet. [Forward Error Correction (FEC)](./docs/features/packet-filtering-and-fec.md) and [Connection Bonding](./docs/features/bonding-quick-start.md), which adds seamless stream protection and hitless failover, are also supported by the protocol. @@ -157,7 +157,7 @@ ## Build Instructions -[Linux (Ubuntu/CentOS)](./docs/build/build-linux.md) | [Windows](./docs/build/build-win.md) | [macOS](./docs/build/build-macOS.md) | [iOS](./docs/build/build-iOS.md) | [Android](./docs/build/build-android.md) +[Linux (Ubuntu/CentOS)](./docs/build/build-linux.md) | [Windows](./docs/build/build-win.md) | [macOS](./docs/build/build-macOS.md) | [iOS](./docs/build/build-iOS.md) | [Android](./docs/build/build-android.md) | [Package Managers](./docs/build/package-managers.md) ### Requirements @@ -224,5 +224,5 @@ [github releases]: https://github.com/Haivision/srt/releases [release-badge]: https://img.shields.io/github/release/Haivision/srt.svg -[debian-badge]: https://badges.debian.net/badges/debian/testing/libsrt1/version.svg -[debian-package]: https://packages.debian.org/testing/libsrt1 +[debian-badge]: https://badges.debian.net/badges/debian/testing/libsrt1.5-gnutls/version.svg +[debian-package]: https://packages.debian.org/testing/libs/libsrt1.5-gnutls diff -Nru srt-1.5.0/scripts/build-windows.ps1 srt-1.5.1/scripts/build-windows.ps1 --- srt-1.5.0/scripts/build-windows.ps1 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/scripts/build-windows.ps1 2022-09-21 14:29:01.000000000 +0000 @@ -19,13 +19,14 @@ [Parameter()][String]$BUILD_APPS = "ON", [Parameter()][String]$UNIT_TESTS = "OFF", [Parameter()][String]$BUILD_DIR = "_build", - [Parameter()][String]$VCPKG_OPENSSL = "OFF" + [Parameter()][String]$VCPKG_OPENSSL = "OFF", + [Parameter()][String]$BONDING = "OFF" ) # cmake can be optionally installed (useful when running interactively on a developer station). # The URL for automatic download is defined later in the script, but it should be possible to just vary the # specific version set below and the URL should be stable enough to still work - you have been warned. -$cmakeVersion = "3.17.3" +$cmakeVersion = "3.23.2" # make all errors trigger a script stop, rather than just carry on $ErrorActionPreference = "Stop" @@ -136,6 +137,7 @@ "-DENABLE_STDCXX_SYNC=$CXX11 " + "-DENABLE_APPS=$BUILD_APPS " + "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + + "-DENABLE_BONDING=$BONDING " + "-DENABLE_UNITTESTS=$UNIT_TESTS" # if VCPKG is flagged to provide OpenSSL, checkout VCPKG and install package diff -Nru srt-1.5.0/scripts/changelog/changelog.py srt-1.5.1/scripts/changelog/changelog.py --- srt-1.5.0/scripts/changelog/changelog.py 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/scripts/changelog/changelog.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -import enum - -import click -import numpy as np -import pandas as pd - - -@enum.unique -class Area(enum.Enum): - core = 'core' - tests = 'tests' - build = 'build' - apps = 'apps' - docs = 'docs' - - -def define_area(msg): - areas = [e.value for e in Area] - - for area in areas: - if msg.startswith(f'[{area}] '): - return area - - return np.NaN - - -def delete_prefix(msg): - prefixes = [f'[{e.value}] ' for e in Area] - - for prefix in prefixes: - if msg.startswith(prefix): - return msg[len(prefix):] - - return msg[:] - - -def write_into_changelog(df, f): - f.write('\n') - for _, row in df.iterrows(): - f.write(f"\n{row['commit']} {row['message']}") - f.write('\n') - - -@click.command() -@click.argument( - 'git_log', - type=click.Path(exists=True) -) -def main(git_log): - """ Script designed to create changelog out of .csv SRT git log """ - - df = pd.read_csv(git_log, sep = '|', names = ['commit', 'message', 'author', 'email']) - df['area'] = df['message'].apply(define_area) - df['message'] = df['message'].apply(delete_prefix) - - core = df[df['area']=='core'] - tests = df[df['area']=='tests'] - build = df[df['area']=='build'] - apps = df[df['area']=='apps'] - docs = df[df['area']=='docs'] - other = df[df['area'].isna()] - - with open('changelog.md', 'w') as f: - f.write('# Release Notes\n') - - f.write('\n## Changelog\n') - f.write('\n

Click to expand/collapse') - f.write('\n

') - f.write('\n') - - if not core.empty: - f.write('\n### Core Functionality') - write_into_changelog(core, f) - - if not tests.empty: - f.write('\n### Unit Tests') - write_into_changelog(tests, f) - - if not build.empty: - f.write('\n### Build Scripts (CMake, etc.)') - write_into_changelog(build, f) - - if not apps.empty: - f.write('\n### Sample Applications') - write_into_changelog(apps, f) - - if not docs.empty: - f.write('\n### Documentation') - write_into_changelog(docs, f) - - if not other.empty: - f.write('\n### Other') - write_into_changelog(other, f) - - f.write('\n

') - f.write('\n
') - - -if __name__ == '__main__': - main() diff -Nru srt-1.5.0/scripts/changelog/README.md srt-1.5.1/scripts/changelog/README.md --- srt-1.5.0/scripts/changelog/README.md 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/scripts/changelog/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -# Changelog - -Script designed to create changelog out of `.csv` SRT git log. The output `changelog.md` is generated in the root folder. - -In order to generate git log file since the previous release (e.g., v1.4.0), use the following command: - -``` -git log --pretty=format:"%h|%s|%an|%ae" v1.4.0...HEAD^ > commits.csv -``` - -## Requirements - -* python 3.6+ - -To install python libraries use: -``` -pip install -r requirements.txt -``` diff -Nru srt-1.5.0/scripts/changelog/requirements.txt srt-1.5.1/scripts/changelog/requirements.txt --- srt-1.5.0/scripts/changelog/requirements.txt 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/scripts/changelog/requirements.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -click>=7.1.2 -numpy>=1.19.1 -pandas>=0.25.3 \ No newline at end of file diff -Nru srt-1.5.0/scripts/release-notes/generate_release_notes.py srt-1.5.1/scripts/release-notes/generate_release_notes.py --- srt-1.5.0/scripts/release-notes/generate_release_notes.py 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/scripts/release-notes/generate_release_notes.py 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,120 @@ +import enum + +import click +import numpy as np +import pandas as pd + + +@enum.unique +class Area(enum.Enum): + core = 'core' + tests = 'tests' + build = 'build' + apps = 'apps' + docs = 'docs' + + +def define_area(msg): + areas = [e.value for e in Area] + + for area in areas: + if msg.startswith(f'[{area}] '): + return area + + return np.NaN + + +def delete_prefix(msg): + prefixes = [f'[{e.value}] ' for e in Area] + + for prefix in prefixes: + if msg.startswith(prefix): + return msg[len(prefix):] + + return msg[:] + + +def write_into_changelog(df, f): + f.write('\n') + for _, row in df.iterrows(): + f.write(f"\n{row['commit']} {row['message']}") + f.write('\n') + + +@click.command() +@click.argument( + 'git_log', + type=click.Path(exists=True) +) +def main(git_log): + """ + Script designed to generate release notes template with main sections, + contributors list, and detailed changelog out of .csv SRT git log file. + """ + df = pd.read_csv(git_log, sep = '|', names = ['commit', 'message', 'author', 'email']) + df['area'] = df['message'].apply(define_area) + df['message'] = df['message'].apply(delete_prefix) + + # Split commits by areas + core = df[df['area']==Area.core.value] + tests = df[df['area']==Area.tests.value] + build = df[df['area']==Area.build.value] + apps = df[df['area']==Area.apps.value] + docs = df[df['area']==Area.docs.value] + other = df[df['area'].isna()] + + # Define individual contributors + contributors = df.groupby(['author', 'email']) + contributors = list(contributors.groups.keys()) + + with open('release-notes.md', 'w') as f: + f.write('# Release Notes\n') + + f.write('\n## API / ABI / Integration Changes\n') + f.write('\n**API/ABI version: 1.x.**\n') + + f.write('\n## New Features and Improvements\n') + f.write('\n## Important Bug Fixes\n') + f.write('\n## Build\n') + f.write('\n## Documentation\n') + + f.write('\n## Contributors\n') + for name, email in contributors: + f.write(f'\n{name} <{email}>') + f.write('\n') + + f.write('\n## Changelog\n') + f.write('\n
Click to expand/collapse') + f.write('\n

') + f.write('\n') + + if not core.empty: + f.write('\n### Core Functionality') + write_into_changelog(core, f) + + if not tests.empty: + f.write('\n### Unit Tests') + write_into_changelog(tests, f) + + if not build.empty: + f.write('\n### Build Scripts (CMake, etc.)') + write_into_changelog(build, f) + + if not apps.empty: + f.write('\n### Sample Applications') + write_into_changelog(apps, f) + + if not docs.empty: + f.write('\n### Documentation') + write_into_changelog(docs, f) + + if not other.empty: + f.write('\n### Other') + write_into_changelog(other, f) + + f.write('\n

') + f.write('\n
') + + +if __name__ == '__main__': + main() diff -Nru srt-1.5.0/scripts/release-notes/README.md srt-1.5.1/scripts/release-notes/README.md --- srt-1.5.0/scripts/release-notes/README.md 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/scripts/release-notes/README.md 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,18 @@ +# Script Description + +Script designed to generate release notes template with main sections, contributors list, and detailed changelog out of `.csv` SRT git log file. The output `release-notes.md` file is generated in the root folder. + +In order to obtain the git log file since the previous release (e.g., v1.4.0), use the following command: + +``` +git log --pretty=format:"%h|%s|%an|%ae" v1.4.0...HEAD^ > commits.csv +``` + +## Requirements + +* Python 3.6+ + +To install Python libraries use: +``` +pip install -r requirements.txt +``` diff -Nru srt-1.5.0/scripts/release-notes/requirements.txt srt-1.5.1/scripts/release-notes/requirements.txt --- srt-1.5.0/scripts/release-notes/requirements.txt 1970-01-01 00:00:00.000000000 +0000 +++ srt-1.5.1/scripts/release-notes/requirements.txt 2022-09-21 14:29:01.000000000 +0000 @@ -0,0 +1,3 @@ +click>=7.1.2 +numpy>=1.19.1 +pandas>=0.25.3 \ No newline at end of file diff -Nru srt-1.5.0/srtcore/api.cpp srt-1.5.1/srtcore/api.cpp --- srt-1.5.0/srtcore/api.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/api.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -254,6 +254,8 @@ throw CUDTException(MJ_SETUP, MN_NONE, WSAGetLastError()); #endif + CCryptoControl::globalInit(); + PacketFilter::globalInit(); if (m_bGCStatus) @@ -298,7 +300,7 @@ // after which the m_bClosing flag is cheched, which // is set here above. Worst case secenario, this // pthread_join() call will block for 1 second. - CSync::signal_relaxed(m_GCStopCond); + CSync::notify_one_relaxed(m_GCStopCond); m_GCThread.join(); m_bGCStatus = false; @@ -776,7 +778,7 @@ } // wake up a waiting accept() call - CSync::lock_signal(ls->m_AcceptCond, ls->m_AcceptLock); + CSync::lock_notify_one(ls->m_AcceptCond, ls->m_AcceptLock); } else { @@ -1867,10 +1869,10 @@ { s->core().startConnect(target_addr, forced_isn); } - catch (CUDTException& e) // Interceptor, just to change the state. + catch (const CUDTException&) // Interceptor, just to change the state. { s->m_Status = SRTS_OPENED; - throw e; + throw; } return 0; @@ -1973,7 +1975,7 @@ s->core().notListening(); // broadcast all "accept" waiting - CSync::lock_broadcast(s->m_AcceptCond, s->m_AcceptLock); + CSync::lock_notify_all(s->m_AcceptCond, s->m_AcceptLock); } else { @@ -2682,6 +2684,8 @@ // remove those timeout sockets for (vector::iterator l = tbr.begin(); l != tbr.end(); ++l) removeSocket(*l); + + HLOGC(smlog.Debug, log << "checkBrokenSockets: after removal: m_ClosedSockets.size()=" << m_ClosedSockets.size()); } // [[using locked(m_GlobControlLock)]] @@ -2766,9 +2770,13 @@ s->core().closeInternal(); HLOGC(smlog.Debug, log << "GC/removeSocket: DELETING SOCKET @" << u); delete s; + HLOGC(smlog.Debug, log << "GC/removeSocket: socket @" << u << " DELETED. Checking muxer."); if (mid == -1) + { + HLOGC(smlog.Debug, log << "GC/removeSocket: no muxer found, finishing."); return; + } map::iterator m; m = m_mMultiplexer.find(mid); @@ -2781,8 +2789,7 @@ CMultiplexer& mx = m->second; mx.m_iRefCount--; - // HLOGF(smlog.Debug, "unrefing underlying socket for %u: %u\n", - // u, mx.m_iRefCount); + HLOGC(smlog.Debug, log << "unrefing underlying muxer " << mid << " for @" << u << ", ref=" << mx.m_iRefCount); if (0 == mx.m_iRefCount) { HLOGC(smlog.Debug, @@ -2983,7 +2990,7 @@ m.m_pSndQueue = new CSndQueue; m.m_pSndQueue->init(m.m_pChannel, m.m_pTimer); m.m_pRcvQueue = new CRcvQueue; - m.m_pRcvQueue->init(32, s->core().maxPayloadSize(), m.m_iIPversion, 1024, m.m_pChannel, m.m_pTimer); + m.m_pRcvQueue->init(128, s->core().maxPayloadSize(), m.m_iIPversion, 1024, m.m_pChannel, m.m_pTimer); // Rewrite the port here, as it might be only known upon return // from CChannel::open. @@ -3161,6 +3168,7 @@ if (empty) break; + HLOGC(inlog.Debug, log << "GC: checkBrokenSockets didn't wipe all sockets, repeating after 1s sleep"); srt::sync::this_thread::sleep_for(milliseconds_from(1)); } diff -Nru srt-1.5.0/srtcore/api.h srt-1.5.1/srtcore/api.h --- srt-1.5.0/srtcore/api.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/api.h 2022-09-21 14:29:01.000000000 +0000 @@ -216,6 +216,7 @@ friend class CUDT; friend class CUDTGroup; friend class CRendezvousQueue; + friend class CCryptoControl; public: CUDTUnited(); diff -Nru srt-1.5.0/srtcore/buffer.cpp srt-1.5.1/srtcore/buffer.cpp --- srt-1.5.0/srtcore/buffer.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/buffer.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -162,7 +162,7 @@ } } -CSndBuffer::CSndBuffer(int size, int mss) +CSndBuffer::CSndBuffer(int size, int maxpld) : m_BufLock() , m_pBlock(NULL) , m_pFirstBlock(NULL) @@ -171,35 +171,34 @@ , m_pBuffer(NULL) , m_iNextMsgNo(1) , m_iSize(size) - , m_iMSS(mss) + , m_iBlockLen(maxpld) , m_iCount(0) , m_iBytesCount(0) { // initial physical buffer of "size" m_pBuffer = new Buffer; - m_pBuffer->m_pcData = new char[m_iSize * m_iMSS]; + m_pBuffer->m_pcData = new char[m_iSize * m_iBlockLen]; m_pBuffer->m_iSize = m_iSize; m_pBuffer->m_pNext = NULL; // circular linked list for out bound packets m_pBlock = new Block; Block* pb = m_pBlock; - for (int i = 1; i < m_iSize; ++i) - { - pb->m_pNext = new Block; - pb->m_iMsgNoBitset = 0; - pb = pb->m_pNext; - } - pb->m_pNext = m_pBlock; + char* pc = m_pBuffer->m_pcData; - pb = m_pBlock; - char* pc = m_pBuffer->m_pcData; for (int i = 0; i < m_iSize; ++i) { - pb->m_pcData = pc; - pb = pb->m_pNext; - pc += m_iMSS; + pb->m_iMsgNoBitset = 0; + pb->m_pcData = pc; + pc += m_iBlockLen; + + if (i < m_iSize - 1) + { + pb->m_pNext = new Block; + pb = pb->m_pNext; + } } + pb->m_pNext = m_pBlock; m_pFirstBlock = m_pCurrBlock = m_pLastBlock = m_pBlock; @@ -230,31 +229,31 @@ void CSndBuffer::addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl) { - int32_t& w_msgno = w_mctrl.msgno; - int32_t& w_seqno = w_mctrl.pktseq; + int32_t& w_msgno = w_mctrl.msgno; + int32_t& w_seqno = w_mctrl.pktseq; int64_t& w_srctime = w_mctrl.srctime; const int& ttl = w_mctrl.msgttl; - int size = len / m_iMSS; - if ((len % m_iMSS) != 0) - size++; + const int iPktLen = m_iBlockLen; // Payload length per packet. + int iNumBlocks = len / iPktLen; + if ((len % m_iBlockLen) != 0) + ++iNumBlocks; HLOGC(bslog.Debug, - log << "addBuffer: size=" << m_iCount << " reserved=" << m_iSize << " needs=" << size << " buffers for " - << len << " bytes"); + log << "addBuffer: needs=" << iNumBlocks << " buffers for " << len << " bytes. Taken=" << m_iCount << "/" << m_iSize); // Retrieve current time before locking the mutex to be closer to packet submission event. const steady_clock::time_point tnow = steady_clock::now(); ScopedLock bufferguard(m_BufLock); // Dynamically increase sender buffer if there is not enough room. - while (size + m_iCount >= m_iSize) + while (iNumBlocks + m_iCount >= m_iSize) { - HLOGC(bslog.Debug, log << "addBuffer: ... still lacking " << (size + m_iCount - m_iSize) << " buffers..."); + HLOGC(bslog.Debug, log << "addBuffer: ... still lacking " << (iNumBlocks + m_iCount - m_iSize) << " buffers..."); increase(); } const int32_t inorder = w_mctrl.inorder ? MSGNO_PACKET_INORDER::mask : 0; HLOGC(bslog.Debug, - log << CONID() << "addBuffer: adding " << size << " packets (" << len << " bytes) to send, msgno=" + log << CONID() << "addBuffer: adding " << iNumBlocks << " packets (" << len << " bytes) to send, msgno=" << (w_msgno > 0 ? w_msgno : m_iNextMsgNo) << (inorder ? "" : " NOT") << " in order"); // Calculate origin time (same for all blocks of the message). @@ -281,16 +280,16 @@ m_iNextMsgNo = w_msgno; } - for (int i = 0; i < size; ++i) + for (int i = 0; i < iNumBlocks; ++i) { - int pktlen = len - i * m_iMSS; - if (pktlen > m_iMSS) - pktlen = m_iMSS; + int pktlen = len - i * iPktLen; + if (pktlen > iPktLen) + pktlen = iPktLen; HLOGC(bslog.Debug, - log << "addBuffer: %" << w_seqno << " #" << w_msgno << " spreading from=" << (i * m_iMSS) + log << "addBuffer: %" << w_seqno << " #" << w_msgno << " offset=" << (i * iPktLen) << " size=" << pktlen << " TO BUFFER:" << (void*)s->m_pcData); - memcpy((s->m_pcData), data + i * m_iMSS, pktlen); + memcpy((s->m_pcData), data + i * iPktLen, pktlen); s->m_iLength = pktlen; s->m_iSeqNo = w_seqno; @@ -299,7 +298,7 @@ s->m_iMsgNoBitset = m_iNextMsgNo | inorder; if (i == 0) s->m_iMsgNoBitset |= PacketBoundaryBits(PB_FIRST); - if (i == size - 1) + if (i == iNumBlocks - 1) s->m_iMsgNoBitset |= PacketBoundaryBits(PB_LAST); // NOTE: if i is neither 0 nor size-1, it resuls with PB_SUBSEQUENT. // if i == 0 == size-1, it results with PB_SOLO. @@ -318,10 +317,10 @@ } m_pLastBlock = s; - m_iCount += size; + m_iCount += iNumBlocks; m_iBytesCount += len; - m_rateEstimator.updateInputRate(m_tsLastOriginTime, size, len); + m_rateEstimator.updateInputRate(m_tsLastOriginTime, iNumBlocks, len); updAvgBufSize(m_tsLastOriginTime); // MSGNO_SEQ::mask has a form: 00000011111111... @@ -337,39 +336,40 @@ int CSndBuffer::addBufferFromFile(fstream& ifs, int len) { - int size = len / m_iMSS; - if ((len % m_iMSS) != 0) - size++; + const int iPktLen = m_iBlockLen; // Payload length per packet. + int iNumBlocks = len / iPktLen; + if ((len % m_iBlockLen) != 0) + ++iNumBlocks; HLOGC(bslog.Debug, - log << "addBufferFromFile: size=" << m_iCount << " reserved=" << m_iSize << " needs=" << size + log << "addBufferFromFile: size=" << m_iCount << " reserved=" << m_iSize << " needs=" << iPktLen << " buffers for " << len << " bytes"); // dynamically increase sender buffer - while (size + m_iCount >= m_iSize) + while (iPktLen + m_iCount >= m_iSize) { HLOGC(bslog.Debug, - log << "addBufferFromFile: ... still lacking " << (size + m_iCount - m_iSize) << " buffers..."); + log << "addBufferFromFile: ... still lacking " << (iPktLen + m_iCount - m_iSize) << " buffers..."); increase(); } HLOGC(bslog.Debug, - log << CONID() << "addBufferFromFile: adding " << size << " packets (" << len + log << CONID() << "addBufferFromFile: adding " << iPktLen << " packets (" << len << " bytes) to send, msgno=" << m_iNextMsgNo); Block* s = m_pLastBlock; int total = 0; - for (int i = 0; i < size; ++i) + for (int i = 0; i < iPktLen; ++i) { if (ifs.bad() || ifs.fail() || ifs.eof()) break; - int pktlen = len - i * m_iMSS; - if (pktlen > m_iMSS) - pktlen = m_iMSS; + int pktlen = len - i * iPktLen; + if (pktlen > iPktLen) + pktlen = iPktLen; HLOGC(bslog.Debug, - log << "addBufferFromFile: reading from=" << (i * m_iMSS) << " size=" << pktlen + log << "addBufferFromFile: reading from=" << (i * iPktLen) << " size=" << pktlen << " TO BUFFER:" << (void*)s->m_pcData); ifs.read(s->m_pcData, pktlen); if ((pktlen = int(ifs.gcount())) <= 0) @@ -379,7 +379,7 @@ s->m_iMsgNoBitset = m_iNextMsgNo | MSGNO_PACKET_INORDER::mask; if (i == 0) s->m_iMsgNoBitset |= PacketBoundaryBits(PB_FIRST); - if (i == size - 1) + if (i == iPktLen - 1) s->m_iMsgNoBitset |= PacketBoundaryBits(PB_LAST); // NOTE: PB_FIRST | PB_LAST == PB_SOLO. // none of PB_FIRST & PB_LAST == PB_SUBSEQUENT. @@ -393,7 +393,7 @@ m_pLastBlock = s; enterCS(m_BufLock); - m_iCount += size; + m_iCount += iPktLen; m_iBytesCount += total; leaveCS(m_BufLock); @@ -588,7 +588,7 @@ } w_packet.m_pcData = p->m_pcData; - int readlen = p->m_iLength; + const int readlen = p->m_iLength; w_packet.setLength(readlen); // XXX Here the value predicted to be applied to PH_MSGNO field is extracted. @@ -750,7 +750,7 @@ try { nbuf = new Buffer; - nbuf->m_pcData = new char[unitsize * m_iMSS]; + nbuf->m_pcData = new char[unitsize * m_iBlockLen]; } catch (...) { @@ -794,13 +794,13 @@ { pb->m_pcData = pc; pb = pb->m_pNext; - pc += m_iMSS; + pc += m_iBlockLen; } m_iSize += unitsize; HLOGC(bslog.Debug, - log << "CSndBuffer: BUFFER FULL - adding " << (unitsize * m_iMSS) << " bytes spread to " << unitsize + log << "CSndBuffer: BUFFER FULL - adding " << (unitsize * m_iBlockLen) << " bytes spread to " << unitsize << " blocks" << " (total size: " << m_iSize << " bytes)"); } @@ -1886,9 +1886,9 @@ m_tsbpd.setTsbPdMode(timebase, no_wrap_check, delay); } -bool CRcvBuffer::addRcvTsbPdDriftSample(uint32_t timestamp_us, int rtt) +bool CRcvBuffer::addRcvTsbPdDriftSample(uint32_t timestamp_us, const time_point& tsPktArrival, int rtt) { - return m_tsbpd.addDriftSample(timestamp_us, rtt); + return m_tsbpd.addDriftSample(timestamp_us, tsPktArrival, rtt); } int CRcvBuffer::readMsg(char* data, int len) diff -Nru srt-1.5.0/srtcore/buffer.h srt-1.5.1/srtcore/buffer.h --- srt-1.5.0/srtcore/buffer.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/buffer.h 2022-09-21 14:29:01.000000000 +0000 @@ -155,7 +155,10 @@ // Currently just "unimplemented". std::string CONID() const { return ""; } - CSndBuffer(int size = 32, int mss = 1500); + /// @brief CSndBuffer constructor. + /// @param size initial number of blocks (each block to store one packet payload). + /// @param maxpld maximum packet payload. + CSndBuffer(int size = 32, int maxpld = 1500); ~CSndBuffer(); public: @@ -256,7 +259,7 @@ struct Block { char* m_pcData; // pointer to the data block - int m_iLength; // length of the block + int m_iLength; // payload length of the block. int32_t m_iMsgNoBitset; // message number int32_t m_iSeqNo; // sequence number for scheduling @@ -292,7 +295,7 @@ int32_t m_iNextMsgNo; // next message number int m_iSize; // buffer size (number of packets) - int m_iMSS; // maximum seqment/packet size + const int m_iBlockLen; // maximum length of a block holding packet payload (excluding packet header). int m_iCount; // number of used blocks int m_iBytesCount; // number of payload bytes in queue @@ -449,8 +452,9 @@ /// Add packet timestamp for drift caclculation and compensation /// @param [in] timestamp packet time stamp + /// @param [in] tsPktArrival arrival time of the packet used to extract the drift sample. /// @param [in] rtt RTT sample - bool addRcvTsbPdDriftSample(uint32_t timestamp, int rtt); + bool addRcvTsbPdDriftSample(uint32_t timestamp, const time_point& tsPktArrival, int rtt); #ifdef SRT_DEBUG_TSBPD_DRIFT void printDriftHistogram(int64_t iDrift); diff -Nru srt-1.5.0/srtcore/buffer_rcv.cpp srt-1.5.1/srtcore/buffer_rcv.cpp --- srt-1.5.0/srtcore/buffer_rcv.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/buffer_rcv.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -1,5 +1,6 @@ #if ENABLE_NEW_RCVBUFFER #include +#include #include "buffer_rcv.h" #include "logging.h" @@ -87,7 +88,7 @@ , m_iPktsCount(0) , m_uAvgPayloadSz(SRT_LIVE_DEF_PLSIZE) { - SRT_ASSERT(size < INT_MAX); // All position pointers are integers + SRT_ASSERT(size < size_t(std::numeric_limits::max())); // All position pointers are integers } CRcvBufferNew::~CRcvBufferNew() @@ -135,7 +136,7 @@ m_iMaxPosInc = offset + 1; // Packet already exists - SRT_ASSERT(pos >= 0 && pos < m_szSize); + SRT_ASSERT(pos >= 0 && pos < int(m_szSize)); if (m_entries[pos].status != EntryState_Empty) { IF_RCVBUF_DEBUG(scoped_log.ss << " returns -1"); @@ -968,9 +969,9 @@ return -1; } -bool CRcvBufferNew::addRcvTsbPdDriftSample(uint32_t usTimestamp, int usRTTSample) +bool CRcvBufferNew::addRcvTsbPdDriftSample(uint32_t usTimestamp, const time_point& tsPktArrival, int usRTTSample) { - return m_tsbpd.addDriftSample(usTimestamp, usRTTSample); + return m_tsbpd.addDriftSample(usTimestamp, tsPktArrival, usRTTSample); } void CRcvBufferNew::setTsbPdMode(const steady_clock::time_point& timebase, bool wrap, duration delay) diff -Nru srt-1.5.0/srtcore/buffer_rcv.h srt-1.5.1/srtcore/buffer_rcv.h --- srt-1.5.0/srtcore/buffer_rcv.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/buffer_rcv.h 2022-09-21 14:29:01.000000000 +0000 @@ -337,7 +337,7 @@ void applyGroupDrift(const time_point& timebase, bool wrp, const duration& udrift); - bool addRcvTsbPdDriftSample(uint32_t usTimestamp, int usRTTSample); + bool addRcvTsbPdDriftSample(uint32_t usTimestamp, const time_point& tsPktArrival, int usRTTSample); time_point getPktTsbPdTime(uint32_t usPktTimestamp) const; diff -Nru srt-1.5.0/srtcore/channel.cpp srt-1.5.1/srtcore/channel.cpp --- srt-1.5.0/srtcore/channel.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/channel.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -878,7 +878,7 @@ { HLOGC(krlog.Debug, log << CONID() << "NET ERROR: packet size=" << recv_size << " msg_flags=0x" << hex << msg_flags - << ", possibly MSG_TRUNC (0x" << hex << int(MSG_TRUNC) << ")"); + << ", possibly MSG_TRUNC)"); status = RST_AGAIN; goto Return_error; } diff -Nru srt-1.5.0/srtcore/core.cpp srt-1.5.1/srtcore/core.cpp --- srt-1.5.0/srtcore/core.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/core.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -1367,7 +1367,7 @@ { m_RejectReason = SRT_REJ_IPE; LOGC(cnlog.Fatal, log << "createSrtHandshake: IPE: srtkm_cmd=SRT_CMD_KMRSP and no kmdata!"); - return false; + return 0; } ra_size = kmdata_wordsize; keydata = reinterpret_cast(kmdata); @@ -1767,6 +1767,12 @@ } } + if (ra_size == 0) + { + // m_RejectReason is expected to be set by fillHsExtKMRSP(..) in this case. + return false; + } + // ra_size + offset has a value in element unit. // Switch it again to byte unit. w_pkt.setLength((ra_size + offset) * sizeof(int32_t)); @@ -3842,7 +3848,7 @@ if (m_SrtHsSide != HSD_DRAW) return; - LOGC(cnlog.Error, log << "cookieContest: agent=" << m_ConnReq.m_iCookie << " peer=" << m_ConnRes.m_iCookie); + LOGC(cnlog.Debug, log << "cookieContest: agent=" << m_ConnReq.m_iCookie << " peer=" << m_ConnRes.m_iCookie); // Here m_ConnReq.m_iCookie is a local cookie value sent in connection request to the peer. // m_ConnRes.m_iCookie is a cookie value sent by the peer in its connection request. @@ -5164,9 +5170,8 @@ CUDTUnited::GroupKeeper gkeeper(self->uglobal(), self->m_parent); #endif - UniqueLock recv_lock(self->m_RecvLock); - CSync recvdata_cc(self->m_RecvDataCond, recv_lock); - CSync tsbpd_cc(self->m_RcvTsbPdCond, recv_lock); + CUniqueSync recvdata_lcc (self->m_RecvLock, self->m_RecvDataCond); + CSync tsbpd_cc(self->m_RcvTsbPdCond, recvdata_lcc.locker()); self->m_bTsbPdAckWakeup = true; while (!self->m_bClosing) @@ -5229,7 +5234,7 @@ */ if (self->m_config.bSynRecving) { - recvdata_cc.signal_locked(recv_lock); + recvdata_lcc.notify_one(); } /* * Set EPOLL_IN to wakeup any thread waiting on epoll @@ -5345,7 +5350,7 @@ enterCS(m_StatsLock); // Estimate dropped bytes from average payload size. const uint64_t avgpayloadsz = m_pRcvBuffer->getRcvAvgPayloadSize(); - m_stats.rcvr.dropped.count(stats::BytesPackets(iDropCnt * avgpayloadsz, (size_t)iDropCnt)); + m_stats.rcvr.dropped.count(stats::BytesPackets(iDropCnt * avgpayloadsz, (uint32_t) iDropCnt)); leaveCS(m_StatsLock); } return iDropCnt; @@ -5475,7 +5480,7 @@ */ if (self->m_config.bSynRecving) { - recvdata_cc.signal_locked(recv_lock); + recvdata_cc.notify_one_locked(recv_lock); } /* * Set EPOLL_IN to wakeup any thread waiting on epoll @@ -5590,7 +5595,7 @@ const int iDropCnt = m_pRcvBuffer->dropAll(); const uint64_t avgpayloadsz = m_pRcvBuffer->getRcvAvgPayloadSize(); sync::ScopedLock sl(m_StatsLock); - m_stats.rcvr.dropped.count(stats::BytesPackets(iDropCnt * avgpayloadsz, (size_t)iDropCnt)); + m_stats.rcvr.dropped.count(stats::BytesPackets(iDropCnt * avgpayloadsz, (uint32_t) iDropCnt)); } m_pRcvBuffer->setStartSeqNo(m_iRcvLastSkipAck); @@ -5603,7 +5608,7 @@ enterCS(m_StatsLock); // Estimate dropped bytes from average payload size. const uint64_t avgpayloadsz = m_pRcvBuffer->getRcvAvgPayloadSize(); - m_stats.rcvr.dropped.count(stats::BytesPackets(seqlen * avgpayloadsz, (size_t) seqlen)); + m_stats.rcvr.dropped.count(stats::BytesPackets(seqlen * avgpayloadsz, (uint32_t) seqlen)); leaveCS(m_StatsLock); dropFromLossLists(lastack, CSeqNo::decseq(skiptoseqno)); //remove(from,to-inclusive) @@ -5645,9 +5650,9 @@ m_pSndBuffer = new CSndBuffer(32, m_iMaxSRTPayloadSize); #if ENABLE_NEW_RCVBUFFER SRT_ASSERT(m_iISN != -1); - m_pRcvBuffer = new srt::CRcvBufferNew(m_iISN, m_config.iRcvBufSize, &(m_pRcvQueue->m_UnitQueue), m_config.bMessageAPI); + m_pRcvBuffer = new srt::CRcvBufferNew(m_iISN, m_config.iRcvBufSize, m_pRcvQueue->m_pUnitQueue, m_config.bMessageAPI); #else - m_pRcvBuffer = new CRcvBuffer(&(m_pRcvQueue->m_UnitQueue), m_config.iRcvBufSize); + m_pRcvBuffer = new CRcvBuffer(m_pRcvQueue->m_pUnitQueue, m_config.iRcvBufSize); #endif // after introducing lite ACK, the sndlosslist may not be cleared in time, so it requires twice space. m_pSndLossList = new CSndLossList(m_iFlowWindowSize * 2); @@ -5883,7 +5888,7 @@ // Write back this value, when it was just determined. m_SrtHsSide = side; - m_pCryptoControl.reset(new CCryptoControl(this, m_SocketID)); + m_pCryptoControl.reset(new CCryptoControl(m_SocketID)); // XXX These below are a little bit controversial. // These data should probably be filled only upon @@ -5897,7 +5902,7 @@ m_pCryptoControl->setCryptoKeylen(m_config.iSndCryptoKeyLen); } - return m_pCryptoControl->init(side, bidirectional); + return m_pCryptoControl->init(side, m_config, bidirectional); } SRT_REJECT_REASON srt::CUDT::setupCC() @@ -5937,7 +5942,7 @@ { // The filter configurer is build the way that allows to quit immediately // exit by exception, but the exception is meant for the filter only. - status = m_PacketFilter.configure(this, &(m_pRcvQueue->m_UnitQueue), m_config.sPacketFilterConfig.str()); + status = m_PacketFilter.configure(this, m_pRcvQueue->m_pUnitQueue, m_config.sPacketFilterConfig.str()); } catch (CUDTException& ) { @@ -6057,7 +6062,7 @@ // if this side is RESPONDER. This shall be called only with // regeneration request, which is required by the sender. if (m_pCryptoControl) - m_pCryptoControl->sendKeysToPeer(regen); + m_pCryptoControl->sendKeysToPeer(this, SRTT(), regen); } } @@ -6355,7 +6360,7 @@ if (m_bTsbPd) { HLOGP(tslog.Debug, "Ping TSBPD thread to schedule wakeup"); - tscond.signal_locked(recvguard); + tscond.notify_one_locked(recvguard); } else { @@ -6388,7 +6393,7 @@ } const time_point tnow = steady_clock::now(); - const int buffdelay_ms = count_milliseconds(m_pSndBuffer->getBufferingDelay(tnow)); + const int buffdelay_ms = (int) count_milliseconds(m_pSndBuffer->getBufferingDelay(tnow)); // high threshold (msec) at tsbpd_delay plus sender/receiver reaction time (2 * 10ms) // Minimum value must accomodate an I-Frame (~8 x average frame size) @@ -6883,7 +6888,7 @@ if (m_bTsbPd) { HLOGP(tslog.Debug, "Ping TSBPD thread to schedule wakeup"); - tscond.signal_locked(recvguard); + tscond.notify_one_locked(recvguard); } else { @@ -6934,7 +6939,7 @@ if (m_bTsbPd) { HLOGP(arlog.Debug, "receiveMessage: nothing to read, kicking TSBPD, return AGAIN"); - tscond.signal_locked(recvguard); + tscond.notify_one_locked(recvguard); } else { @@ -6955,7 +6960,7 @@ if (m_bTsbPd) { HLOGP(arlog.Debug, "receiveMessage: DATA READ, but nothing more - kicking TSBPD."); - tscond.signal_locked(recvguard); + tscond.notify_one_locked(recvguard); } else { @@ -7005,7 +7010,7 @@ // bool spurious = (tstime != 0); HLOGC(tslog.Debug, log << CONID() << "receiveMessage: KICK tsbpd"); - tscond.signal_locked(recvguard); + tscond.notify_one_locked(recvguard); } THREAD_PAUSED(); @@ -7086,7 +7091,7 @@ if (m_bTsbPd) { HLOGP(tslog.Debug, "recvmsg: KICK tsbpd() (buffer empty)"); - tscond.signal_locked(recvguard); + tscond.notify_one_locked(recvguard); } // Shut up EPoll if no more messages in non-blocking mode @@ -7395,7 +7400,7 @@ perf->byteRecv = m_stats.rcvr.recvd.trace.bytesWithHdr(); perf->byteRecvUnique = m_stats.rcvr.recvdUnique.trace.bytesWithHdr(); perf->byteRetrans = m_stats.sndr.sentRetrans.trace.bytesWithHdr(); - perf->byteRcvLoss = m_stats.rcvr.recvd.trace.bytesWithHdr(); + perf->byteRcvLoss = m_stats.rcvr.lost.trace.bytesWithHdr(); perf->pktSndDrop = m_stats.sndr.dropped.trace.count(); perf->pktRcvDrop = m_stats.rcvr.dropped.trace.count() + m_stats.rcvr.undecrypted.trace.count(); @@ -7495,7 +7500,7 @@ if (m_pRcvBuffer) { ScopedLock lck(m_RcvBufferLock); - perf->byteAvailRcvBuf = getAvailRcvBufferSizeNoLock() * m_config.iMSS; + perf->byteAvailRcvBuf = (int) getAvailRcvBufferSizeNoLock() * m_config.iMSS; if (instantaneous) // no need for historical API for Rcv side { perf->pktRcvBuf = m_pRcvBuffer->getRcvDataSize(perf->byteRcvBuf, perf->msRcvBuf); @@ -7555,7 +7560,7 @@ EInitEvent only_input = arg.get(); // false = TEV_INIT_RESET: in the beginning, or when MAXBW was changed. - if (only_input && m_config.llMaxBW) + if (only_input != TEV_INIT_RESET && m_config.llMaxBW) { HLOGC(rslog.Debug, log << CONID() << "updateCC/TEV_INIT: non-RESET stage and m_config.llMaxBW already set to " << m_config.llMaxBW); // Don't change @@ -7689,14 +7694,14 @@ { SRT_ASSERT(m_bClosing); // wake up user calls - CSync::lock_signal(m_SendBlockCond, m_SendBlockLock); + CSync::lock_notify_one(m_SendBlockCond, m_SendBlockLock); enterCS(m_SendLock); leaveCS(m_SendLock); // Awake tsbpd() and srt_recv*(..) threads for them to check m_bClosing. - CSync::lock_signal(m_RecvDataCond, m_RecvLock); - CSync::lock_signal(m_RcvTsbPdCond, m_RecvLock); + CSync::lock_notify_one(m_RecvDataCond, m_RecvLock); + CSync::lock_notify_one(m_RcvTsbPdCond, m_RecvLock); // Azquiring m_RcvTsbPdStartupLock protects race in starting // the tsbpd() thread in CUDT::processData(). @@ -8064,17 +8069,15 @@ if (m_bTsbPd) { /* Newly acknowledged data, signal TsbPD thread */ - UniqueLock rcvlock(m_RecvLock); - CSync tscond(m_RcvTsbPdCond, rcvlock); + CUniqueSync tslcc (m_RecvLock, m_RcvTsbPdCond); // m_bTsbPdAckWakeup is protected by m_RecvLock in the tsbpd() thread if (m_bTsbPdAckWakeup) - tscond.signal_locked(rcvlock); + tslcc.notify_one(); } else { { - UniqueLock rdlock (m_RecvLock); - CSync rdcond (m_RecvDataCond, rdlock); + CUniqueSync rdcc (m_RecvLock, m_RecvDataCond); #if ENABLE_NEW_RCVBUFFER // Locks m_RcvBufferLock, which is unlocked above by InvertedLock un_bufflock. @@ -8085,7 +8088,7 @@ if (m_config.bSynRecving) { // signal a waiting "recv" call if there is any data available - rdcond.signal_locked(rdlock); + rdcc.notify_one(); } // acknowledge any waiting epolls to read // fix SRT_EPOLL_IN event loss but rcvbuffer still have data: @@ -8156,7 +8159,7 @@ data[ACKD_RCVLASTACK] = m_iRcvLastAck; data[ACKD_RTT] = m_iSRTT; data[ACKD_RTTVAR] = m_iRTTVar; - data[ACKD_BUFFERLEFT] = getAvailRcvBufferSizeNoLock(); + data[ACKD_BUFFERLEFT] = (int) getAvailRcvBufferSizeNoLock(); // a minimum flow window of 2 is used, even if buffer is full, to break potential deadlock if (data[ACKD_BUFFERLEFT] < 2) data[ACKD_BUFFERLEFT] = 2; @@ -8288,7 +8291,7 @@ if (m_config.bSynSending) { - CSync::lock_signal(m_SendBlockCond, m_SendBlockLock); + CSync::lock_notify_one(m_SendBlockCond, m_SendBlockLock); } // record total time used for sending @@ -8622,7 +8625,7 @@ // srt_recvfile (which doesn't make any sense), you'll have a deadlock. if (m_config.bDriftTracer) { - const bool drift_updated SRT_ATR_UNUSED = m_pRcvBuffer->addRcvTsbPdDriftSample(ctrlpkt.getMsgTimeStamp(), rtt); + const bool drift_updated SRT_ATR_UNUSED = m_pRcvBuffer->addRcvTsbPdDriftSample(ctrlpkt.getMsgTimeStamp(), tsArrival, rtt); #if ENABLE_BONDING if (drift_updated && m_parent->m_GroupOf) { @@ -8897,7 +8900,7 @@ const int32_t* dropdata = (const int32_t*) ctrlpkt.m_pcData; { - UniqueLock rlock(m_RecvLock); + CUniqueSync rcvtscc (m_RecvLock, m_RcvTsbPdCond); // With both TLPktDrop and TsbPd enabled, a message always consists only of one packet. // It will be dropped as too late anyway. Not dropping it from the receiver buffer // in advance reduces false drops if the packet somehow manages to arrive. @@ -8918,7 +8921,7 @@ enterCS(m_StatsLock); // Estimate dropped bytes from average payload size. const uint64_t avgpayloadsz = m_pRcvBuffer->getRcvAvgPayloadSize(); - m_stats.rcvr.dropped.count(stats::BytesPackets(iDropCnt * avgpayloadsz, (size_t)iDropCnt)); + m_stats.rcvr.dropped.count(stats::BytesPackets(iDropCnt * avgpayloadsz, (uint32_t) iDropCnt)); leaveCS(m_StatsLock); } #else @@ -8931,8 +8934,7 @@ if (m_bTsbPd) { HLOGP(inlog.Debug, "DROPREQ: signal TSBPD"); - CSync cc(m_RcvTsbPdCond, rlock); - cc.signal_locked(rlock); + rcvtscc.notify_one(); } } @@ -9033,7 +9035,7 @@ break; case UMSG_KEEPALIVE: // 001 - Keep-alive - handleKeepalive(ctrlpkt.m_pcData, ctrlpkt.getLength()); + processKeepalive(ctrlpkt, currtime); break; case UMSG_HANDSHAKE: // 000 - Handshake @@ -9699,7 +9701,7 @@ // Note that the packet header must have a valid seqno set, as it is used as a counter for encryption. // Other fields of the data packet header (e.g. timestamp, destination socket ID) are not used for the counter. // Cypher may change packet length! - if (m_pCryptoControl->encrypt((w_packet))) + if (m_pCryptoControl->encrypt((w_packet)) != ENCS_CLEAR) { // Encryption failed //>>Add stats for crypto failure @@ -9732,7 +9734,7 @@ if (m_bTsbPd) { HLOGP(smlog.Debug, "processClose: lock-and-signal TSBPD"); - CSync::lock_signal(m_RcvTsbPdCond, m_RecvLock); + CSync::lock_notify_one(m_RcvTsbPdCond, m_RecvLock); } // Signal the sender and recver if they are waiting for data. @@ -9979,7 +9981,7 @@ const int loss = diff - 1; // loss is all that is above diff == 1 ScopedLock lg(m_StatsLock); const uint64_t avgpayloadsz = m_pRcvBuffer->getRcvAvgPayloadSize(); - m_stats.rcvr.lost.count(stats::BytesPackets(loss * avgpayloadsz, loss)); + m_stats.rcvr.lost.count(stats::BytesPackets(loss * avgpayloadsz, (uint32_t) loss)); HLOGC(qrlog.Debug, log << "LOSS STATS: n=" << loss << " SEQ: [" << CSeqNo::incseq(m_iRcvCurrPhySeqNo) << " " @@ -10061,9 +10063,9 @@ // Loop over all incoming packets that were filtered out. // In case when there is no filter, there's just one packet in 'incoming', // the one that came in the input of this function. - for (vector::iterator i = incoming.begin(); i != incoming.end(); ++i) + for (vector::iterator unitIt = incoming.begin(); unitIt != incoming.end(); ++unitIt) { - CUnit * u = *i; + CUnit * u = *unitIt; CPacket &rpkt = u->m_Packet; // m_iRcvLastSkipAck is the base sequence number for the receiver buffer. @@ -10093,7 +10095,7 @@ continue; } - const int avail_bufsize = getAvailRcvBufferSizeNoLock(); + const int avail_bufsize = (int) getAvailRcvBufferSizeNoLock(); if (offset >= avail_bufsize) { // This is already a sequence discrepancy. Probably there could be found @@ -10113,7 +10115,7 @@ " seq=" << rpkt.m_iSeqNo << " buffer=(" << m_iRcvLastSkipAck << ":" << m_iRcvCurrSeqNo // -1 = size to last index - << "+" << CSeqNo::incseq(m_iRcvLastSkipAck, m_pRcvBuffer->capacity()-1) + << "+" << CSeqNo::incseq(m_iRcvLastSkipAck, int(m_pRcvBuffer->capacity()) - 1) << "), " << (offset-avail_bufsize+1) << " past max. Reception no longer possible. REQUESTING TO CLOSE."); @@ -10145,9 +10147,9 @@ bool adding_successful = true; #if ENABLE_NEW_RCVBUFFER - if (m_pRcvBuffer->insert(*i) < 0) + if (m_pRcvBuffer->insert(u) < 0) #else - if (m_pRcvBuffer->addData(*i, offset) < 0) + if (m_pRcvBuffer->addData(u, offset) < 0) #endif { // addData returns -1 if at the m_iLastAckPos+offset position there already is a packet. @@ -10159,7 +10161,7 @@ { IF_HEAVY_LOGGING(exc_type = "ACCEPTED"); excessive = false; - if (u->m_Packet.getMsgCryptoFlags()) + if (u->m_Packet.getMsgCryptoFlags() != EK_NOENC) { EncryptionStatus rc = m_pCryptoControl ? m_pCryptoControl->decrypt((u->m_Packet)) : ENCS_NOTSUP; if (rc != ENCS_CLEAR) @@ -10319,7 +10321,7 @@ if (m_bTsbPd) { HLOGC(qrlog.Debug, log << "loss: signaling TSBPD cond"); - CSync::lock_signal(m_RcvTsbPdCond, m_RecvLock); + CSync::lock_notify_one(m_RcvTsbPdCond, m_RecvLock); } else { @@ -10340,7 +10342,7 @@ if (m_bTsbPd) { HLOGC(qrlog.Debug, log << "loss: signaling TSBPD cond"); - CSync::lock_signal(m_RcvTsbPdCond, m_RecvLock); + CSync::lock_notify_one(m_RcvTsbPdCond, m_RecvLock); } } @@ -11724,7 +11726,7 @@ return true; } -void srt::CUDT::handleKeepalive(const char* /*data*/, size_t /*size*/) +void srt::CUDT::processKeepalive(const CPacket& ctrlpkt, const time_point& tsArrival) { // Here can be handled some protocol definition // for extra data sent through keepalive. @@ -11744,8 +11746,15 @@ // Whether anything is to be done with this socket // about the fact that keepalive arrived, let the // group handle it - pg->handleKeepalive(m_parent->m_GroupMemberData); + pg->processKeepalive(m_parent->m_GroupMemberData); } } #endif + +#if ENABLE_NEW_RCVBUFFER + ScopedLock lck(m_RcvBufferLock); + m_pRcvBuffer->updateTsbPdTimeBase(ctrlpkt.getMsgTimeStamp()); + if (m_config.bDriftTracer) + m_pRcvBuffer->addRcvTsbPdDriftSample(ctrlpkt.getMsgTimeStamp(), tsArrival, -1); +#endif } diff -Nru srt-1.5.0/srtcore/core.h srt-1.5.1/srtcore/core.h --- srt-1.5.0/srtcore/core.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/core.h 2022-09-21 14:29:01.000000000 +0000 @@ -170,7 +170,6 @@ friend class CRcvUList; friend class PacketFilter; friend class CUDTGroup; - friend struct FByOldestActive; // this functional will use private fields friend class TestMockCUDT; // unit tests typedef sync::steady_clock::time_point time_point; @@ -829,13 +828,13 @@ duration m_tdNAKInterval; // NAK interval SRT_ATTR_GUARDED_BY(m_RecvAckLock) atomic_time_point m_tsLastRspTime; // Timestamp of last response from the peer - time_point m_tsLastRspAckTime; // Timestamp of last ACK from the peer + time_point m_tsLastRspAckTime; // (SND) Timestamp of last ACK from the peer atomic_time_point m_tsLastSndTime; // Timestamp of last data/ctrl sent (in system ticks) time_point m_tsLastWarningTime; // Last time that a warning message is sent atomic_time_point m_tsLastReqTime; // last time when a connection request is sent time_point m_tsRcvPeerStartTime; time_point m_tsLingerExpiration; // Linger expiration time (for GC to close a socket with data in sending buffer) - time_point m_tsLastAckTime; // Timestamp of last ACK + time_point m_tsLastAckTime; // (RCV) Timestamp of last ACK duration m_tdMinNakInterval; // NAK timeout lower bound; too small value can cause unnecessary retransmission duration m_tdMinExpInterval; // Timeout lower bound threshold: too small timeout can cause problem @@ -915,9 +914,9 @@ int32_t m_iDebugPrevLastAck; #endif int32_t m_iRcvLastSkipAck; // Last dropped sequence ACK - int32_t m_iRcvLastAckAck; // Last sent ACK that has been acknowledged + int32_t m_iRcvLastAckAck; // (RCV) Latest packet seqno in a sent ACK acknowledged by ACKACK. RcvQTh (sendCtrlAck {r}, processCtrlAckAck {r}, processCtrlAck {r}, connection {w}). int32_t m_iAckSeqNo; // Last ACK sequence number - sync::atomic m_iRcvCurrSeqNo; // Largest received sequence number + sync::atomic m_iRcvCurrSeqNo; // (RCV) Largest received sequence number. RcvQTh, TSBPDTh. int32_t m_iRcvCurrPhySeqNo; // Same as m_iRcvCurrSeqNo, but physical only (disregarding a filter) int32_t m_iPeerISN; // Initial Sequence Number of the peer side @@ -1087,7 +1086,7 @@ void dropToGroupRecvBase(); #endif - void handleKeepalive(const char* data, size_t lenghth); + void processKeepalive(const CPacket& ctrlpkt, const time_point& tsArrival); /// Locks m_RcvBufferLock and retrieves the available size of the receiver buffer. SRT_ATTR_EXCLUDES(m_RcvBufferLock) diff -Nru srt-1.5.0/srtcore/crypto.cpp srt-1.5.1/srtcore/crypto.cpp --- srt-1.5.0/srtcore/crypto.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/crypto.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -26,6 +26,7 @@ #include "crypto.h" #include "logging.h" #include "core.h" +#include "api.h" using namespace srt_logging; @@ -69,6 +70,15 @@ using srt_logging::KmStateStr; +void srt::CCryptoControl::globalInit() +{ +#ifdef SRT_ENABLE_ENCRYPTION + // We need to force the Cryspr to be initialized during startup to avoid the + // possibility of multiple threads initialzing the same static data later on. + HaiCryptCryspr_Get_Instance(); +#endif +} + #if ENABLE_LOGGING std::string srt::CCryptoControl::FormatKmMessage(std::string hdr, int cmd, size_t srtlen) { @@ -125,8 +135,6 @@ HtoNLA((pw_srtdata_out), srtdata, w_srtlen); unsigned char* kmdata = reinterpret_cast(pw_srtdata_out); - std::vector kmcopy(kmdata, kmdata + bytelen); - // The side that has received KMREQ is always an HSD_RESPONDER, regardless of // what has called this function. The HSv5 handshake only enforces bidirectional // connection. @@ -419,9 +427,9 @@ return retstatus; } -void srt::CCryptoControl::sendKeysToPeer(Whether2RegenKm regen SRT_ATR_UNUSED) +void srt::CCryptoControl::sendKeysToPeer(CUDT* sock SRT_ATR_UNUSED, int iSRTT SRT_ATR_UNUSED, Whether2RegenKm regen SRT_ATR_UNUSED) { - if ( !m_hSndCrypto || m_SndKmState == SRT_KM_S_UNSECURED) + if (!m_hSndCrypto || m_SndKmState == SRT_KM_S_UNSECURED) { HLOGC(cnlog.Debug, log << "sendKeysToPeer: NOT sending/regenerating keys: " << (m_hSndCrypto ? "CONNECTION UNSECURED" : "NO TX CRYPTO CTX created")); @@ -439,7 +447,7 @@ * then (re-)send handshake request. */ if (((m_SndKmMsg[0].iPeerRetry > 0) || (m_SndKmMsg[1].iPeerRetry > 0)) - && ((m_SndKmLastTime + srt::sync::microseconds_from((m_parent->SRTT() * 3)/2)) <= now)) + && ((m_SndKmLastTime + srt::sync::microseconds_from((iSRTT * 3)/2)) <= now)) { for (int ki = 0; ki < 2; ki++) { @@ -449,7 +457,7 @@ HLOGC(cnlog.Debug, log << "sendKeysToPeer: SENDING ki=" << ki << " len=" << m_SndKmMsg[ki].MsgLen << " retry(updated)=" << m_SndKmMsg[ki].iPeerRetry); m_SndKmLastTime = now; - m_parent->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen / sizeof(uint32_t)); + sock->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen / sizeof(uint32_t)); } } } @@ -458,7 +466,7 @@ if (regen) { regenCryptoKm( - true, // send UMSG_EXT + SRT_CMD_KMREQ to the peer, if regenerated the key + sock, // send UMSG_EXT + SRT_CMD_KMREQ to the peer using this socket false // Do not apply the regenerated key to the to the receiver context ); // regenerate and send } @@ -466,7 +474,7 @@ } #ifdef SRT_ENABLE_ENCRYPTION -void srt::CCryptoControl::regenCryptoKm(bool sendit, bool bidirectional) +void srt::CCryptoControl::regenCryptoKm(CUDT* sock, bool bidirectional) { if (!m_hSndCrypto) return; @@ -477,7 +485,7 @@ int sent = 0; HLOGC(cnlog.Debug, log << "regenCryptoKm: regenerating crypto keys nbo=" << nbo << - " THEN=" << (sendit ? "SEND" : "KEEP") << " DIR=" << (bidirectional ? "BOTH" : "SENDER")); + " THEN=" << (sock ? "SEND" : "KEEP") << " DIR=" << (bidirectional ? "BOTH" : "SENDER")); for (int i = 0; i < nbo && i < 2; i++) { @@ -505,7 +513,7 @@ m_SndKmMsg[ki].MsgLen = out_len_p[i]; m_SndKmMsg[ki].iPeerRetry = SRT_MAX_KMRETRY; - if (bidirectional && !sendit) + if (bidirectional && !sock) { // "Send" this key also to myself, just to be applied to the receiver crypto, // exactly the same way how this key is interpreted on the peer side into its receiver crypto @@ -518,11 +526,11 @@ } } - if (sendit) + if (sock) { HLOGC(cnlog.Debug, log << "regenCryptoKm: SENDING ki=" << ki << " len=" << m_SndKmMsg[ki].MsgLen << " retry(updated)=" << m_SndKmMsg[ki].iPeerRetry); - m_parent->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen / sizeof(uint32_t)); + sock->sendSrtMsg(SRT_CMD_KMREQ, (uint32_t *)m_SndKmMsg[ki].Msg, m_SndKmMsg[ki].MsgLen / sizeof(uint32_t)); sent++; } } @@ -544,9 +552,8 @@ } #endif -srt::CCryptoControl::CCryptoControl(CUDT* parent, SRTSOCKET id) - : m_parent(parent) // should be initialized in createCC() - , m_SocketID(id) +srt::CCryptoControl::CCryptoControl(SRTSOCKET id) + : m_SocketID(id) , m_iSndKmKeyLen(0) , m_iRcvKmKeyLen(0) , m_SndKmState(SRT_KM_S_UNSECURED) @@ -567,7 +574,7 @@ m_hRcvCrypto = NULL; } -bool srt::CCryptoControl::init(HandshakeSide side, bool bidirectional SRT_ATR_UNUSED) +bool srt::CCryptoControl::init(HandshakeSide side, const CSrtConfig& cfg, bool bidirectional SRT_ATR_UNUSED) { // NOTE: initiator creates m_hSndCrypto. When bidirectional, // it creates also m_hRcvCrypto with the same key length. @@ -584,8 +591,8 @@ // Set security-pending state, if a password was set. m_SndKmState = hasPassphrase() ? SRT_KM_S_SECURING : SRT_KM_S_UNSECURED; - m_KmPreAnnouncePkt = m_parent->m_config.uKmPreAnnouncePkt; - m_KmRefreshRatePkt = m_parent->m_config.uKmRefreshRatePkt; + m_KmPreAnnouncePkt = cfg.uKmPreAnnouncePkt; + m_KmRefreshRatePkt = cfg.uKmRefreshRatePkt; if ( side == HSD_INITIATOR ) { @@ -620,9 +627,9 @@ } regenCryptoKm( - false, // Do not send the key (will be attached it to the HSv5 handshake) - bidirectional // replicate the key to the receiver context, if bidirectional - ); + NULL, // Do not send the key (the KM msg will be attached to the HSv5 handshake) + bidirectional // replicate the key to the receiver context, if bidirectional + ); #else // This error would be a consequence of setting the passphrase, while encryption // is turned off at compile time. Setting the password itself should be not allowed diff -Nru srt-1.5.0/srtcore/crypto.h srt-1.5.1/srtcore/crypto.h --- srt-1.5.0/srtcore/crypto.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/crypto.h 2022-09-21 14:29:01.000000000 +0000 @@ -41,6 +41,7 @@ namespace srt { class CUDT; +struct CSrtConfig; // For KMREQ/KMRSP. Only one field is used. @@ -53,7 +54,6 @@ class CCryptoControl { - CUDT* m_parent; SRTSOCKET m_SocketID; size_t m_iSndKmKeyLen; //Key length @@ -85,6 +85,7 @@ bool m_bErrorReported; public: + static void globalInit(); bool sendingAllowed() { @@ -109,9 +110,11 @@ } private: - #ifdef SRT_ENABLE_ENCRYPTION - void regenCryptoKm(bool sendit, bool bidirectional); + /// Regenerate cryptographic key material. + /// @param[in] sock If not null, the socket will be used to send the KM message to the peer (e.g. KM refresh). + /// @param[in] bidirectional If true, the key material will be regenerated for both directions (receiver and sender). + void regenCryptoKm(CUDT* sock, bool bidirectional); #endif public: @@ -195,25 +198,24 @@ return false; } - CCryptoControl(CUDT* parent, SRTSOCKET id); + CCryptoControl(SRTSOCKET id); // DEBUG PURPOSES: std::string CONID() const; std::string FormatKmMessage(std::string hdr, int cmd, size_t srtlen); - bool init(HandshakeSide, bool); + bool init(HandshakeSide, const CSrtConfig&, bool); void close(); - // This function is used in: - // - HSv4 (initial key material exchange - in HSv5 it's attached to handshake) - // - case of key regeneration, which should be then exchanged again - void sendKeysToPeer(Whether2RegenKm regen); - + /// @return True if the handshake is in progress. + /// This function is used in: + /// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake) + /// - case of key regeneration, which should be then exchanged again. + void sendKeysToPeer(CUDT* sock, int iSRTT, Whether2RegenKm regen); void setCryptoSecret(const HaiCrypt_Secret& secret) { m_KmSecret = secret; - //memcpy(&m_KmSecret, &secret, sizeof(m_KmSecret)); } void setCryptoKeylen(size_t keylen) diff -Nru srt-1.5.0/srtcore/fec.cpp srt-1.5.1/srtcore/fec.cpp --- srt-1.5.0/srtcore/fec.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/fec.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -1472,8 +1472,7 @@ if (tp == Group::SINGLE) return; - // This flips HORIZ/VERT - Group::Type crosstype = Group::Type(!tp); + Group::Type crosstype = Group::FlipType(tp); EHangStatus stat; if (crosstype == Group::HORIZ) diff -Nru srt-1.5.0/srtcore/fec.h srt-1.5.1/srtcore/fec.h --- srt-1.5.0/srtcore/fec.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/fec.h 2022-09-21 14:29:01.000000000 +0000 @@ -70,6 +70,12 @@ SINGLE // Horizontal-only with no recursion }; + static Type FlipType(Type t) + { + SRT_ASSERT(t != SINGLE); + return (t == HORIZ) ? VERT : HORIZ; + } + }; struct RcvGroup: Group diff -Nru srt-1.5.0/srtcore/group.cpp srt-1.5.1/srtcore/group.cpp --- srt-1.5.0/srtcore/group.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/group.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -780,16 +780,6 @@ return ps->core().getOpt(optname, (pw_optval), (w_optlen)); } -struct HaveState : public unary_function, bool> -{ - SRT_SOCKSTATUS s; - HaveState(SRT_SOCKSTATUS ss) - : s(ss) - { - } - bool operator()(pair i) const { return i.second == s; } -}; - SRT_SOCKSTATUS CUDTGroup::getStatus() { typedef vector > states_t; @@ -979,7 +969,7 @@ // XXX This looks like a dead code. Group receiver functions // do not use any lock on m_RcvDataLock, it is likely a remainder // of the old, internal impementation. - // CSync::lock_signal(m_RcvDataCond, m_RcvDataLock); + // CSync::lock_notify_one(m_RcvDataCond, m_RcvDataLock); } // [[using locked(m_Global->m_GlobControlLock)]] @@ -1517,8 +1507,6 @@ CUDT::uglobal().epoll_add_usock_INTERNAL(m_SndEID, (*b)->ps, &modes); } - const int blocklen = blocked.size(); - int blst = 0; CEPoll::fmap_t sready; @@ -1582,8 +1570,8 @@ // This must be wrapped in try-catch because on error it throws an exception. // Possible return values are only 0, in case when len was passed 0, or a positive // >0 value that defines the size of the data that it has sent, that is, in case - // of Live mode, equal to 'blocklen'. - stat = d->ps->core().sendmsg2(buf, blocklen, (w_mc)); + // of Live mode, equal to 'len'. + stat = d->ps->core().sendmsg2(buf, len, (w_mc)); } catch (CUDTException& e) { @@ -1605,7 +1593,7 @@ // NOTE: m_GroupLock is continuously locked - you can safely use Sendstate::it field. for (vector::iterator is = sendstates.begin(); is != sendstates.end(); ++is) { - if (is->stat == blocklen) + if (is->stat == len) { // Successful. successful.push_back(is->mb); @@ -3787,18 +3775,6 @@ // TODO: all broken members are to be removed from the context now??? } -struct FByOldestActive -{ - typedef CUDTGroup::gli_t gli_t; - bool operator()(gli_t a, gli_t b) - { - CUDT& x = a->ps->core(); - CUDT& y = b->ps->core(); - - return x.m_tsFreshActivation < y.m_tsFreshActivation; - } -}; - // [[using locked(this->m_GroupLock)]] void CUDTGroup::sendBackup_RetryWaitBlocked(SendBackupCtx& w_sendBackupCtx, int& w_final_stat, @@ -4474,7 +4450,7 @@ m_iSndAckedMsgNo = msgno; } -void CUDTGroup::handleKeepalive(CUDTGroup::SocketData* gli) +void CUDTGroup::processKeepalive(CUDTGroup::SocketData* gli) { // received keepalive for that group member // In backup group it means that the link went IDLE. diff -Nru srt-1.5.0/srtcore/group.h srt-1.5.1/srtcore/group.h --- srt-1.5.0/srtcore/group.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/group.h 2022-09-21 14:29:01.000000000 +0000 @@ -391,7 +391,7 @@ #endif void ackMessage(int32_t msgno); - void handleKeepalive(SocketData*); + void processKeepalive(SocketData*); void internalKeepalive(SocketData*); private: diff -Nru srt-1.5.0/srtcore/handshake.cpp srt-1.5.1/srtcore/handshake.cpp --- srt-1.5.0/srtcore/handshake.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/handshake.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -139,6 +139,8 @@ "MESSAGEAPI", "CONGESTION", "FILTER", + "GROUP", + "TIMEOUT" }; } @@ -149,7 +151,7 @@ std::ostringstream rt; rt << "ERROR:"; int id = RejectReasonForURQ(rq); - if (id < SRT_REJ_E_SIZE) + if (id < (int) Size(srt_rejectreason_name)) rt << srt_rejectreason_name[id]; else if (id < SRT_REJC_USERDEFINED) { diff -Nru srt-1.5.0/srtcore/packet.cpp srt-1.5.1/srtcore/packet.cpp --- srt-1.5.0/srtcore/packet.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/packet.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -1,11 +1,11 @@ /* * SRT - Secure, Reliable, Transport * Copyright (c) 2018 Haivision Systems Inc. - * + * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * */ /***************************************************************************** @@ -50,7 +50,6 @@ Haivision Systems Inc. *****************************************************************************/ - ////////////////////////////////////////////////////////////////////////////// // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -137,9 +136,9 @@ // Add. Info: Error code // Control Info: None // 0x7FFF: Explained by bits 16 - 31 (UMSG_EXT) -// +// // bit 16 - 31: -// This space is used for future expansion or user defined control packets. +// This space is used for future expansion or user defined control packets. // // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -169,19 +168,19 @@ namespace srt_logging { - extern Logger inlog; +extern Logger inlog; } using namespace srt_logging; // Set up the aliases in the constructure -srt::CPacket::CPacket(): - m_extra_pad(), - m_data_owned(false), - m_iSeqNo((int32_t&)(m_nHeader[SRT_PH_SEQNO])), - m_iMsgNo((int32_t&)(m_nHeader[SRT_PH_MSGNO])), - m_iTimeStamp((int32_t&)(m_nHeader[SRT_PH_TIMESTAMP])), - m_iID((int32_t&)(m_nHeader[SRT_PH_ID])), - m_pcData((char*&)(m_PacketVector[PV_DATA].dataRef())) +srt::CPacket::CPacket() + : m_extra_pad() + , m_data_owned(false) + , m_iSeqNo((int32_t&)(m_nHeader[SRT_PH_SEQNO])) + , m_iMsgNo((int32_t&)(m_nHeader[SRT_PH_MSGNO])) + , m_iTimeStamp((int32_t&)(m_nHeader[SRT_PH_TIMESTAMP])) + , m_iID((int32_t&)(m_nHeader[SRT_PH_ID])) + , m_pcData((char*&)(m_PacketVector[PV_DATA].dataRef())) { m_nHeader.clear(); @@ -208,7 +207,7 @@ return; // already allocated // Would be nice to reallocate; for now just allocate again. - delete [] m_pcData; + delete[] m_pcData; } m_PacketVector[PV_DATA].set(new char[alloc_buffer_size], alloc_buffer_size); m_data_owned = true; @@ -217,7 +216,7 @@ void srt::CPacket::deallocate() { if (m_data_owned) - delete [] (char*)m_PacketVector[PV_DATA].data(); + delete[](char*) m_PacketVector[PV_DATA].data(); m_PacketVector[PV_DATA].set(NULL, 0); } @@ -227,7 +226,7 @@ char* buffer = NULL; if (m_data_owned) { - buffer = getData(); + buffer = getData(); m_data_owned = false; } @@ -240,129 +239,129 @@ // PV_HEADER is always owned, PV_DATA may use a "borrowed" buffer. // Delete the internal buffer only if it was declared as owned. if (m_data_owned) - delete[](char*)m_PacketVector[PV_DATA].data(); + delete[](char*) m_PacketVector[PV_DATA].data(); } - size_t srt::CPacket::getLength() const { - return m_PacketVector[PV_DATA].size(); + return m_PacketVector[PV_DATA].size(); } void srt::CPacket::setLength(size_t len) { - m_PacketVector[PV_DATA].setLength(len); + m_PacketVector[PV_DATA].setLength(len); } void srt::CPacket::pack(UDTMessageType pkttype, const int32_t* lparam, void* rparam, size_t size) { // Set (bit-0 = 1) and (bit-1~15 = type) setControl(pkttype); - HLOGC(inlog.Debug, log << "pack: type=" << MessageTypeStr(pkttype) - << " ARG=" << (lparam ? Sprint(*lparam) : std::string("NULL")) - << " [ " << (rparam ? Sprint(*(int32_t*)rparam) : std::string()) << " ]"); - - // Set additional information and control information field - switch (pkttype) - { - case UMSG_ACK: //0010 - Acknowledgement (ACK) - // ACK packet seq. no. - if (NULL != lparam) - m_nHeader[SRT_PH_MSGNO] = *lparam; - - // data ACK seq. no. - // optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated link capacity (packets per second) - m_PacketVector[PV_DATA].set(rparam, size); - - break; - - case UMSG_ACKACK: //0110 - Acknowledgement of Acknowledgement (ACK-2) - // ACK packet seq. no. - m_nHeader[SRT_PH_MSGNO] = *lparam; - - // control info field should be none - // but "writev" does not allow this - m_PacketVector[PV_DATA].set((void *)&m_extra_pad, 4); - - break; - - case UMSG_LOSSREPORT: //0011 - Loss Report (NAK) - // loss list - m_PacketVector[PV_DATA].set(rparam, size); - - break; - - case UMSG_CGWARNING: //0100 - Congestion Warning - // control info field should be none - // but "writev" does not allow this - m_PacketVector[PV_DATA].set((void *)&m_extra_pad, 4); - - break; - - case UMSG_KEEPALIVE: //0001 - Keep-alive - if (lparam) - { - // XXX EXPERIMENTAL. Pass the 32-bit integer here. - m_nHeader[SRT_PH_MSGNO] = *lparam; - } - // control info field should be none - // but "writev" does not allow this - m_PacketVector[PV_DATA].set((void *)&m_extra_pad, 4); - - break; - - case UMSG_HANDSHAKE: //0000 - Handshake - // control info filed is handshake info - m_PacketVector[PV_DATA].set(rparam, size); - - break; - - case UMSG_SHUTDOWN: //0101 - Shutdown - // control info field should be none - // but "writev" does not allow this - m_PacketVector[PV_DATA].set((void *)&m_extra_pad, 4); - - break; - - case UMSG_DROPREQ: //0111 - Message Drop Request - // msg id - m_nHeader[SRT_PH_MSGNO] = *lparam; - - //first seq no, last seq no - m_PacketVector[PV_DATA].set(rparam, size); - - break; - - case UMSG_PEERERROR: //1000 - Error Signal from the Peer Side - // Error type - m_nHeader[SRT_PH_MSGNO] = *lparam; - - // control info field should be none - // but "writev" does not allow this - m_PacketVector[PV_DATA].set((void *)&m_extra_pad, 4); - - break; - - case UMSG_EXT: //0x7FFF - Reserved for user defined control packets - // for extended control packet - // "lparam" contains the extended type information for bit 16 - 31 - // "rparam" is the control information - m_nHeader[SRT_PH_SEQNO] |= *lparam; - - if (NULL != rparam) - { - m_PacketVector[PV_DATA].set(rparam, size); - } - else - { - m_PacketVector[PV_DATA].set((void *)&m_extra_pad, 4); - } - - break; - - default: - break; - } + HLOGC(inlog.Debug, + log << "pack: type=" << MessageTypeStr(pkttype) << " ARG=" << (lparam ? Sprint(*lparam) : std::string("NULL")) + << " [ " << (rparam ? Sprint(*(int32_t*)rparam) : std::string()) << " ]"); + + // Set additional information and control information field + switch (pkttype) + { + case UMSG_ACK: // 0010 - Acknowledgement (ACK) + // ACK packet seq. no. + if (NULL != lparam) + m_nHeader[SRT_PH_MSGNO] = *lparam; + + // data ACK seq. no. + // optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated + // link capacity (packets per second) + m_PacketVector[PV_DATA].set(rparam, size); + + break; + + case UMSG_ACKACK: // 0110 - Acknowledgement of Acknowledgement (ACK-2) + // ACK packet seq. no. + m_nHeader[SRT_PH_MSGNO] = *lparam; + + // control info field should be none + // but "writev" does not allow this + m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4); + + break; + + case UMSG_LOSSREPORT: // 0011 - Loss Report (NAK) + // loss list + m_PacketVector[PV_DATA].set(rparam, size); + + break; + + case UMSG_CGWARNING: // 0100 - Congestion Warning + // control info field should be none + // but "writev" does not allow this + m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4); + + break; + + case UMSG_KEEPALIVE: // 0001 - Keep-alive + if (lparam) + { + // XXX EXPERIMENTAL. Pass the 32-bit integer here. + m_nHeader[SRT_PH_MSGNO] = *lparam; + } + // control info field should be none + // but "writev" does not allow this + m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4); + + break; + + case UMSG_HANDSHAKE: // 0000 - Handshake + // control info filed is handshake info + m_PacketVector[PV_DATA].set(rparam, size); + + break; + + case UMSG_SHUTDOWN: // 0101 - Shutdown + // control info field should be none + // but "writev" does not allow this + m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4); + + break; + + case UMSG_DROPREQ: // 0111 - Message Drop Request + // msg id + m_nHeader[SRT_PH_MSGNO] = *lparam; + + // first seq no, last seq no + m_PacketVector[PV_DATA].set(rparam, size); + + break; + + case UMSG_PEERERROR: // 1000 - Error Signal from the Peer Side + // Error type + m_nHeader[SRT_PH_MSGNO] = *lparam; + + // control info field should be none + // but "writev" does not allow this + m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4); + + break; + + case UMSG_EXT: // 0x7FFF - Reserved for user defined control packets + // for extended control packet + // "lparam" contains the extended type information for bit 16 - 31 + // "rparam" is the control information + m_nHeader[SRT_PH_SEQNO] |= *lparam; + + if (NULL != rparam) + { + m_PacketVector[PV_DATA].set(rparam, size); + } + else + { + m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4); + } + + break; + + default: + break; + } } void srt::CPacket::toNL() @@ -396,14 +395,13 @@ if (isControl()) { for (ptrdiff_t l = 0, n = getLength() / 4; l < n; ++l) - *((uint32_t*) m_pcData + l) = ntohl(*((uint32_t*) m_pcData + l)); + *((uint32_t*)m_pcData + l) = ntohl(*((uint32_t*)m_pcData + l)); } } - srt::IOVector* srt::CPacket::getPacketVector() { - return m_PacketVector; + return m_PacketVector; } srt::UDTMessageType srt::CPacket::getType() const @@ -418,11 +416,11 @@ int32_t srt::CPacket::getAckSeqNo() const { - // read additional information field - // This field is used only in UMSG_ACK and UMSG_ACKACK, - // so 'getAckSeqNo' symbolically defines the only use of it - // in case of CONTROL PACKET. - return m_nHeader[SRT_PH_MSGNO]; + // read additional information field + // This field is used only in UMSG_ACK and UMSG_ACKACK, + // so 'getAckSeqNo' symbolically defines the only use of it + // in case of CONTROL PACKET. + return m_nHeader[SRT_PH_MSGNO]; } uint16_t srt::CPacket::getControlFlags() const @@ -441,12 +439,12 @@ bool srt::CPacket::getMsgOrderFlag() const { - return 0!= MSGNO_PACKET_INORDER::unwrap(m_nHeader[SRT_PH_MSGNO]); + return 0 != MSGNO_PACKET_INORDER::unwrap(m_nHeader[SRT_PH_MSGNO]); } int32_t srt::CPacket::getMsgSeq(bool has_rexmit) const { - if ( has_rexmit ) + if (has_rexmit) { return MSGNO_SEQ::unwrap(m_nHeader[SRT_PH_MSGNO]); } @@ -459,7 +457,7 @@ bool srt::CPacket::getRexmitFlag() const { // return false; // - return 0 != MSGNO_REXMIT::unwrap(m_nHeader[SRT_PH_MSGNO]); + return 0 != MSGNO_REXMIT::unwrap(m_nHeader[SRT_PH_MSGNO]); } srt::EncryptionKeySpec srt::CPacket::getMsgCryptoFlags() const @@ -472,28 +470,29 @@ // crypto flags after encrypting a packet. void srt::CPacket::setMsgCryptoFlags(EncryptionKeySpec spec) { - int32_t clr_msgno = m_nHeader[SRT_PH_MSGNO] & ~MSGNO_ENCKEYSPEC::mask; + int32_t clr_msgno = m_nHeader[SRT_PH_MSGNO] & ~MSGNO_ENCKEYSPEC::mask; m_nHeader[SRT_PH_MSGNO] = clr_msgno | EncryptionKeyBits(spec); } uint32_t srt::CPacket::getMsgTimeStamp() const { - // SRT_DEBUG_TSBPD_WRAP may enable smaller timestamp for faster wraparoud handling tests - return (uint32_t)m_nHeader[SRT_PH_TIMESTAMP] & TIMESTAMP_MASK; + // SRT_DEBUG_TSBPD_WRAP may enable smaller timestamp for faster wraparoud handling tests + return (uint32_t)m_nHeader[SRT_PH_TIMESTAMP] & TIMESTAMP_MASK; } srt::CPacket* srt::CPacket::clone() const { - CPacket* pkt = new CPacket; - memcpy((pkt->m_nHeader), m_nHeader, HDR_SIZE); - pkt->m_pcData = new char[m_PacketVector[PV_DATA].size()]; - memcpy((pkt->m_pcData), m_pcData, m_PacketVector[PV_DATA].size()); - pkt->m_PacketVector[PV_DATA].setLength(m_PacketVector[PV_DATA].size()); + CPacket* pkt = new CPacket; + memcpy((pkt->m_nHeader), m_nHeader, HDR_SIZE); + pkt->m_pcData = new char[m_PacketVector[PV_DATA].size()]; + memcpy((pkt->m_pcData), m_pcData, m_PacketVector[PV_DATA].size()); + pkt->m_PacketVector[PV_DATA].setLength(m_PacketVector[PV_DATA].size()); - return pkt; + return pkt; } -namespace srt { +namespace srt +{ // Useful for debugging std::string PacketMessageFlagStr(uint32_t msgno_field) @@ -502,10 +501,10 @@ stringstream out; - static const char* const boundary [] = { "PB_SUBSEQUENT", "PB_LAST", "PB_FIRST", "PB_SOLO" }; - static const char* const order [] = { "ORD_RELAXED", "ORD_REQUIRED" }; - static const char* const crypto [] = { "EK_NOENC", "EK_EVEN", "EK_ODD", "EK*ERROR" }; - static const char* const rexmit [] = { "SN_ORIGINAL", "SN_REXMIT" }; + static const char* const boundary[] = {"PB_SUBSEQUENT", "PB_LAST", "PB_FIRST", "PB_SOLO"}; + static const char* const order[] = {"ORD_RELAXED", "ORD_REQUIRED"}; + static const char* const crypto[] = {"EK_NOENC", "EK_EVEN", "EK_ODD", "EK*ERROR"}; + static const char* const rexmit[] = {"SN_ORIGINAL", "SN_REXMIT"}; out << boundary[MSGNO_PACKET_BOUNDARY::unwrap(msgno_field)] << " "; out << order[MSGNO_PACKET_INORDER::unwrap(msgno_field)] << " "; @@ -557,8 +556,8 @@ // display all numbers in the array with the following restrictions: // - all data contained in the buffer are considered 32-bit integer // - sign flag will be cleared before displaying, with additional mark - size_t wordlen = getLength()/4; // drop any remainder if present - int32_t* array = (int32_t*)m_pcData; + size_t wordlen = getLength() / 4; // drop any remainder if present + int32_t* array = (int32_t*)m_pcData; os << " [ "; for (size_t i = 0; i < wordlen; ++i) { @@ -574,10 +573,8 @@ // This is only a log, nothing crucial, so we can risk displaying incorrect message number. // Declaring that the peer supports rexmit flag cuts off the highest bit from // the displayed number. - os << "DATA: size=" << getLength() - << " " << BufferStamp(m_pcData, getLength()) - << " #" << getMsgSeq(true) << " %" << getSeqNo() - << " " << MessageFlagStr(); + os << "DATA: size=" << getLength() << " " << BufferStamp(m_pcData, getLength()) << " #" << getMsgSeq(true) + << " %" << getSeqNo() << " " << MessageFlagStr(); } return os.str(); diff -Nru srt-1.5.0/srtcore/packet.h srt-1.5.1/srtcore/packet.h --- srt-1.5.0/srtcore/packet.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/packet.h 2022-09-21 14:29:01.000000000 +0000 @@ -1,11 +1,11 @@ /* - * SRT - Secure, Reliable, Transport + * SRT - Secure Reliable Transport * Copyright (c) 2018 Haivision Systems Inc. - * + * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * */ /***************************************************************************** @@ -59,12 +59,13 @@ #include "netinet_any.h" #include "packetfilter_api.h" -namespace srt { +namespace srt +{ ////////////////////////////////////////////////////////////////////////////// // The purpose of the IOVector class is to proide a platform-independet interface // to the WSABUF on Windows and iovec on Linux, that can be easilly converted -// to the native structure for use in WSARecvFrom() and recvmsg(...) functions +// to the native structure for use in WSARecvFrom() and recvmsg(...) functions class IOVector #ifdef _WIN32 : public WSABUF @@ -73,15 +74,14 @@ #endif { public: - - inline void set(void *buffer, size_t length) + inline void set(void* buffer, size_t length) { #ifdef _WIN32 len = (ULONG)length; buf = (CHAR*)buffer; #else iov_base = (void*)buffer; - iov_len = length; + iov_len = length; #endif } @@ -90,7 +90,7 @@ #ifdef _WIN32 return buf; #else - return (char*&) iov_base; + return (char*&)iov_base; #endif } @@ -106,7 +106,7 @@ inline size_t size() const { #ifdef _WIN32 - return (size_t) len; + return (size_t)len; #else return iov_len; #endif @@ -115,24 +115,20 @@ inline void setLength(size_t length) { #ifdef _WIN32 - len = (ULONG) length; + len = (ULONG)length; #else iov_len = length; #endif } }; - /// To define packets in order in the buffer. This is public due to being used in buffer. enum PacketBoundary { - PB_SUBSEQUENT = 0, // 00 -/// 01: last packet of a message - PB_LAST = 1, // 01 -/// 10: first packet of a message - PB_FIRST = 2, // 10 -/// 11: solo message packet - PB_SOLO = 3, // 11 + PB_SUBSEQUENT = 0, // 00: a packet in the middle of a message, neither the first, not the last. + PB_LAST = 1, // 01: last packet of a message + PB_FIRST = 2, // 10: first packet of a message + PB_SOLO = 3, // 11: solo message packet }; // Breakdown of the PM_SEQNO field in the header: @@ -140,7 +136,7 @@ typedef Bits<31> SEQNO_CONTROL; // 1|T T T T T T T T T T T T T T T|E E...E typedef Bits<30, 16> SEQNO_MSGTYPE; -typedef Bits<15, 0> SEQNO_EXTTYPE; +typedef Bits<15, 0> SEQNO_EXTTYPE; // 0|S S ... S typedef Bits<30, 0> SEQNO_VALUE; @@ -164,11 +160,11 @@ // MSGNO breakdown: B B|O|K K|R|M M M M M M M M M M...M typedef Bits<31, 30> MSGNO_PACKET_BOUNDARY; -typedef Bits<29> MSGNO_PACKET_INORDER; +typedef Bits<29> MSGNO_PACKET_INORDER; typedef Bits<28, 27> MSGNO_ENCKEYSPEC; #if 1 // can block rexmit flag // New bit breakdown - rexmit flag supported. -typedef Bits<26> MSGNO_REXMIT; +typedef Bits<26> MSGNO_REXMIT; typedef Bits<25, 0> MSGNO_SEQ; // Old bit breakdown - no rexmit flag typedef Bits<26, 0> MSGNO_SEQ_OLD; @@ -176,35 +172,36 @@ // The message should be extracted as PMASK_MSGNO_SEQ, if REXMIT is supported, and PMASK_MSGNO_SEQ_OLD otherwise. const uint32_t PACKET_SND_NORMAL = 0, PACKET_SND_REXMIT = MSGNO_REXMIT::mask; -const int MSGNO_SEQ_MAX = MSGNO_SEQ::mask; +const int MSGNO_SEQ_MAX = MSGNO_SEQ::mask; #else // Old bit breakdown - no rexmit flag typedef Bits<26, 0> MSGNO_SEQ; #endif -typedef RollNumber MsgNo; - +typedef RollNumber MsgNo; // constexpr in C++11 ! -inline int32_t PacketBoundaryBits(PacketBoundary o) { return MSGNO_PACKET_BOUNDARY::wrap(int32_t(o)); } - +inline int32_t PacketBoundaryBits(PacketBoundary o) +{ + return MSGNO_PACKET_BOUNDARY::wrap(int32_t(o)); +} enum EncryptionKeySpec { EK_NOENC = 0, - EK_EVEN = 1, - EK_ODD = 2 + EK_EVEN = 1, + EK_ODD = 2 }; enum EncryptionStatus { - ENCS_CLEAR = 0, + ENCS_CLEAR = 0, ENCS_FAILED = -1, ENCS_NOTSUP = -2 }; -const int32_t PMASK_MSGNO_ENCKEYSPEC = MSGNO_ENCKEYSPEC::mask; +const int32_t PMASK_MSGNO_ENCKEYSPEC = MSGNO_ENCKEYSPEC::mask; inline int32_t EncryptionKeyBits(EncryptionKeySpec f) { return MSGNO_ENCKEYSPEC::wrap(int32_t(f)); @@ -220,213 +217,165 @@ class CPacket { -friend class CChannel; -friend class CSndQueue; -friend class CRcvQueue; + friend class CChannel; + friend class CSndQueue; + friend class CRcvQueue; public: - CPacket(); - ~CPacket(); - - void allocate(size_t size); - void deallocate(); - - /// Get the payload or the control information field length. - /// @return the payload or the control information field length. - - size_t getLength() const; - - /// Set the payload or the control information field length. - /// @param len [in] the payload or the control information field length. - - void setLength(size_t len); + CPacket(); + ~CPacket(); - /// Pack a Control packet. - /// @param pkttype [in] packet type filed. - /// @param lparam [in] pointer to the first data structure, explained by the packet type. - /// @param rparam [in] pointer to the second data structure, explained by the packet type. - /// @param size [in] size of rparam, in number of bytes; + void allocate(size_t size); + void deallocate(); - void pack(UDTMessageType pkttype, const int32_t* lparam = NULL, void* rparam = NULL, size_t size = 0); + /// Get the payload or the control information field length. + /// @return the payload or the control information field length. + size_t getLength() const; - /// Read the packet vector. - /// @return Pointer to the packet vector. + /// Set the payload or the control information field length. + /// @param len [in] the payload or the control information field length. + void setLength(size_t len); - IOVector* getPacketVector(); + /// Pack a Control packet. + /// @param pkttype [in] packet type filed. + /// @param lparam [in] pointer to the first data structure, explained by the packet type. + /// @param rparam [in] pointer to the second data structure, explained by the packet type. + /// @param size [in] size of rparam, in number of bytes; + void pack(UDTMessageType pkttype, const int32_t* lparam = NULL, void* rparam = NULL, size_t size = 0); - uint32_t* getHeader() { return m_nHeader; } + /// Read the packet vector. + /// @return Pointer to the packet vector. + IOVector* getPacketVector(); - /// Read the packet flag. - /// @return packet flag (0 or 1). + uint32_t* getHeader() { return m_nHeader; } - // XXX DEPRECATED. Use isControl() instead - ATR_DEPRECATED - int getFlag() const - { - return isControl() ? 1 : 0; - } + /// Read the packet type. + /// @return packet type filed (000 ~ 111). + UDTMessageType getType() const; - /// Read the packet type. - /// @return packet type filed (000 ~ 111). + bool isControl(UDTMessageType type) const { return isControl() && type == getType(); } - UDTMessageType getType() const; + bool isControl() const { return 0 != SEQNO_CONTROL::unwrap(m_nHeader[SRT_PH_SEQNO]); } - bool isControl(UDTMessageType type) const - { - return isControl() && type == getType(); - } + void setControl(UDTMessageType type) { m_nHeader[SRT_PH_SEQNO] = SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(type); } - bool isControl() const - { - // read bit 0 - return 0!= SEQNO_CONTROL::unwrap(m_nHeader[SRT_PH_SEQNO]); - } + /// Read the extended packet type. + /// @return extended packet type filed (0x000 ~ 0xFFF). + int getExtendedType() const; - void setControl(UDTMessageType type) - { - m_nHeader[SRT_PH_SEQNO] = SEQNO_CONTROL::mask | SEQNO_MSGTYPE::wrap(type); - } + /// Read the ACK-2 seq. no. + /// @return packet header field (bit 16~31). + int32_t getAckSeqNo() const; - /// Read the extended packet type. - /// @return extended packet type filed (0x000 ~ 0xFFF). + uint16_t getControlFlags() const; - int getExtendedType() const; + // Note: this will return a "singular" value, if the packet + // contains the control message + int32_t getSeqNo() const { return m_nHeader[SRT_PH_SEQNO]; } - /// Read the ACK-2 seq. no. - /// @return packet header field (bit 16~31). + /// Read the message boundary flag bit. + /// @return packet header field [1] (bit 0~1). + PacketBoundary getMsgBoundary() const; - int32_t getAckSeqNo() const; - uint16_t getControlFlags() const; + /// Read the message inorder delivery flag bit. + /// @return packet header field [1] (bit 2). + bool getMsgOrderFlag() const; - // Note: this will return a "singular" value, if the packet - // contains the control message - int32_t getSeqNo() const - { - return m_nHeader[SRT_PH_SEQNO]; - } + /// Read the rexmit flag (true if the packet was sent due to retransmission). + /// If the peer does not support retransmission flag, the current agent cannot use it as well + /// (because the peer will understand this bit as a part of MSGNO field). + bool getRexmitFlag() const; - /// Read the message boundary flag bit. - /// @return packet header field [1] (bit 0~1). + /// Read the message sequence number. + /// @return packet header field [1] + int32_t getMsgSeq(bool has_rexmit = true) const; - PacketBoundary getMsgBoundary() const; + /// Read the message crypto key bits. + /// @return packet header field [1] (bit 3~4). + EncryptionKeySpec getMsgCryptoFlags() const; - /// Read the message inorder delivery flag bit. - /// @return packet header field [1] (bit 2). + void setMsgCryptoFlags(EncryptionKeySpec spec); - bool getMsgOrderFlag() const; + /// Read the message time stamp. + /// @return packet header field [2] (bit 0~31, bit 0-26 if SRT_DEBUG_TSBPD_WRAP). + uint32_t getMsgTimeStamp() const; - /// Read the rexmit flag (true if the packet was sent due to retransmission). - /// If the peer does not support retransmission flag, the current agent cannot use it as well - /// (because the peer will understand this bit as a part of MSGNO field). - - bool getRexmitFlag() const; - - /// Read the message sequence number. - /// @return packet header field [1] - - int32_t getMsgSeq(bool has_rexmit = true) const; - - /// Read the message crypto key bits. - /// @return packet header field [1] (bit 3~4). - - EncryptionKeySpec getMsgCryptoFlags() const; - void setMsgCryptoFlags(EncryptionKeySpec spec); - - /// Read the message time stamp. - /// @return packet header field [2] (bit 0~31, bit 0-26 if SRT_DEBUG_TSBPD_WRAP). - - uint32_t getMsgTimeStamp() const; - -#ifdef SRT_DEBUG_TSBPD_WRAP //Receiver - static const uint32_t MAX_TIMESTAMP = 0x07FFFFFF; //27 bit fast wraparound for tests (~2m15s) +#ifdef SRT_DEBUG_TSBPD_WRAP // Receiver + static const uint32_t MAX_TIMESTAMP = 0x07FFFFFF; // 27 bit fast wraparound for tests (~2m15s) #else - static const uint32_t MAX_TIMESTAMP = 0xFFFFFFFF; //Full 32 bit (01h11m35s) + static const uint32_t MAX_TIMESTAMP = 0xFFFFFFFF; // Full 32 bit (01h11m35s) #endif protected: - static const uint32_t TIMESTAMP_MASK = MAX_TIMESTAMP; // this value to be also used as a mask + static const uint32_t TIMESTAMP_MASK = MAX_TIMESTAMP; // this value to be also used as a mask public: + /// Clone this packet. + /// @return Pointer to the new packet. + CPacket* clone() const; - /// Clone this packet. - /// @return Pointer to the new packet. - - CPacket* clone() const; - - enum PacketVectorFields - { - PV_HEADER = 0, - PV_DATA = 1, + enum PacketVectorFields + { + PV_HEADER = 0, + PV_DATA = 1, - PV_SIZE = 2 - }; + PV_SIZE = 2 + }; public: void toNL(); void toHL(); protected: - // Length in bytes + // DynamicStruct is the same as array of given type and size, just it + // enforces that you index it using a symbol from symbolic enum type, not by a bare integer. + typedef DynamicStruct HEADER_TYPE; + HEADER_TYPE m_nHeader; //< The 128-bit header field - // DynamicStruct is the same as array of given type and size, just it - // enforces that you index it using a symbol from symbolic enum type, not by a bare integer. + IOVector m_PacketVector[PV_SIZE]; //< The two-dimensional vector of an SRT packet [header, data] - typedef DynamicStruct HEADER_TYPE; - HEADER_TYPE m_nHeader; //< The 128-bit header field - - // XXX NOTE: iovec here is not portable. On Windows there's a different - // (although similar) structure defined, which means that this way the - // Windows function that is an equivalent of `recvmsg` cannot be used. - // For example, something like that: - // class IoVector: public iovec { public: size_t size() { return iov_len; } char* data() { return iov_base; } }; - // class IoVector: public WSAMSG { public: size_t size() { return len; } char* data() { return buf; } }; - IOVector m_PacketVector[PV_SIZE]; //< The 2-demension vector of UDT packet [header, data] - - int32_t m_extra_pad; - bool m_data_owned; + int32_t m_extra_pad; + bool m_data_owned; protected: - CPacket& operator=(const CPacket&); - CPacket (const CPacket&); + CPacket& operator=(const CPacket&); + CPacket(const CPacket&); public: - - int32_t& m_iSeqNo; // alias: sequence number - int32_t& m_iMsgNo; // alias: message number - int32_t& m_iTimeStamp; // alias: timestamp - int32_t& m_iID; // alias: socket ID - char*& m_pcData; // alias: data/control information - - // Experimental: sometimes these references don't work! - char* getData(); - char* release(); - - //static const int m_iPktHdrSize; // packet header size - static const size_t HDR_SIZE = sizeof(HEADER_TYPE); // packet header size = SRT_PH_E_SIZE * sizeof(uint32_t) - - // Used in many computations - // Actually this can be also calculated as: sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr). - static const size_t UDP_HDR_SIZE = 28; // 20 bytes IPv4 + 8 bytes of UDP { u16 sport, dport, len, csum }. - - static const size_t SRT_DATA_HDR_SIZE = UDP_HDR_SIZE + HDR_SIZE; - - // Some well known data - static const size_t ETH_MAX_MTU_SIZE = 1500; - - // And derived - static const size_t SRT_MAX_PAYLOAD_SIZE = ETH_MAX_MTU_SIZE - SRT_DATA_HDR_SIZE; - - // Packet interface - char* data() { return m_pcData; } - const char* data() const { return m_pcData; } - size_t size() const { return getLength(); } - uint32_t header(SrtPktHeaderFields field) const { return m_nHeader[field]; } + int32_t& m_iSeqNo; // alias: sequence number + int32_t& m_iMsgNo; // alias: message number + int32_t& m_iTimeStamp; // alias: timestamp + int32_t& m_iID; // alias: destination SRT socket ID + char*& m_pcData; // alias: payload (data packet) / control information fields (control packet) + + // Experimental: sometimes these references don't work! + char* getData(); + char* release(); + + static const size_t HDR_SIZE = sizeof(HEADER_TYPE); // packet header size = SRT_PH_E_SIZE * sizeof(uint32_t) + + // Can also be calculated as: sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr). + static const size_t UDP_HDR_SIZE = 28; // 20 bytes IPv4 + 8 bytes of UDP { u16 sport, dport, len, csum }. + + static const size_t SRT_DATA_HDR_SIZE = UDP_HDR_SIZE + HDR_SIZE; + + // Maximum transmission unit size. 1500 in case of Ethernet II (RFC 1191). + static const size_t ETH_MAX_MTU_SIZE = 1500; + + // Maximum payload size of an SRT packet. + static const size_t SRT_MAX_PAYLOAD_SIZE = ETH_MAX_MTU_SIZE - SRT_DATA_HDR_SIZE; + + // Packet interface + char* data() { return m_pcData; } + const char* data() const { return m_pcData; } + size_t size() const { return getLength(); } + uint32_t header(SrtPktHeaderFields field) const { return m_nHeader[field]; } #if ENABLE_LOGGING - std::string MessageFlagStr() { return PacketMessageFlagStr(m_nHeader[SRT_PH_MSGNO]); } - std::string Info(); + std::string MessageFlagStr() { return PacketMessageFlagStr(m_nHeader[SRT_PH_MSGNO]); } + std::string Info(); #else - std::string MessageFlagStr() { return std::string(); } - std::string Info() { return std::string(); } + std::string MessageFlagStr() { return std::string(); } + std::string Info() { return std::string(); } #endif }; diff -Nru srt-1.5.0/srtcore/queue.cpp srt-1.5.1/srtcore/queue.cpp --- srt-1.5.0/srtcore/queue.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/queue.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -65,15 +65,22 @@ using namespace srt::sync; using namespace srt_logging; -srt::CUnitQueue::CUnitQueue() - : m_pQEntry(NULL) - , m_pCurrQueue(NULL) - , m_pLastQueue(NULL) - , m_iSize(0) - , m_iCount(0) - , m_iMSS() - , m_iIPversion() +srt::CUnitQueue::CUnitQueue(int initNumUnits, int mss) + : m_iNumTaken(0) + , m_iMSS(mss) + , m_iBlockSize(initNumUnits) { + CQEntry* tempq = allocateEntry(m_iBlockSize, m_iMSS); + + if (tempq == NULL) + throw CUDTException(MJ_SYSTEMRES, MN_MEMORY); + + m_pQEntry = m_pCurrQueue = m_pLastQueue = tempq; + m_pQEntry->m_pNext = m_pQEntry; + + m_pAvailUnit = m_pCurrQueue->m_pUnit; + + m_iSize = m_iBlockSize; } srt::CUnitQueue::~CUnitQueue() @@ -94,17 +101,17 @@ } } -int srt::CUnitQueue::init(int size, int mss, int version) +srt::CUnitQueue::CQEntry* srt::CUnitQueue::allocateEntry(const int iNumUnits, const int mss) { CQEntry* tempq = NULL; - CUnit* tempu = NULL; - char* tempb = NULL; + CUnit* tempu = NULL; + char* tempb = NULL; try { tempq = new CQEntry; - tempu = new CUnit[size]; - tempb = new char[size * mss]; + tempu = new CUnit[iNumUnits]; + tempb = new char[iNumUnits * mss]; } catch (...) { @@ -112,109 +119,52 @@ delete[] tempu; delete[] tempb; - return -1; + LOGC(rslog.Error, log << "CUnitQueue: failed to allocate " << iNumUnits << " units."); + return NULL; } - for (int i = 0; i < size; ++i) + for (int i = 0; i < iNumUnits; ++i) { - tempu[i].m_iFlag = CUnit::FREE; + tempu[i].m_iFlag = CUnit::FREE; tempu[i].m_Packet.m_pcData = tempb + i * mss; } + tempq->m_pUnit = tempu; tempq->m_pBuffer = tempb; - tempq->m_iSize = size; - - m_pQEntry = m_pCurrQueue = m_pLastQueue = tempq; - m_pQEntry->m_pNext = m_pQEntry; - - m_pAvailUnit = m_pCurrQueue->m_pUnit; - - m_iSize = size; - m_iMSS = mss; - m_iIPversion = version; + tempq->m_iSize = iNumUnits; - return 0; + return tempq; } -// XXX Lots of common code with CUnitQueue:init. -// Consider merging. -int srt::CUnitQueue::increase() -{ - // adjust/correct m_iCount - int real_count = 0; - CQEntry* p = m_pQEntry; - while (p != NULL) - { - CUnit* u = p->m_pUnit; - for (CUnit* end = u + p->m_iSize; u != end; ++u) - if (u->m_iFlag != CUnit::FREE) - ++real_count; - - if (p == m_pLastQueue) - p = NULL; - else - p = p->m_pNext; - } - m_iCount = real_count; - if (double(m_iCount) / m_iSize < 0.9) - return -1; - - CQEntry* tempq = NULL; - CUnit* tempu = NULL; - char* tempb = NULL; - - // all queues have the same size - const int size = m_pQEntry->m_iSize; - - try - { - tempq = new CQEntry; - tempu = new CUnit[size]; - tempb = new char[size * m_iMSS]; - } - catch (...) - { - delete tempq; - delete[] tempu; - delete[] tempb; +int srt::CUnitQueue::increase_() +{ + const int numUnits = m_iBlockSize; + HLOGC(qrlog.Debug, log << "CUnitQueue::increase: Capacity" << capacity() << " + " << numUnits << " new units, " << m_iNumTaken << " in use."); - LOGC(rslog.Error, - log << "CUnitQueue:increase: failed to allocate " << size << " new units." - << " Current size=" << m_iSize); + CQEntry* tempq = allocateEntry(numUnits, m_iMSS); + if (tempq == NULL) return -1; - } - - for (int i = 0; i < size; ++i) - { - tempu[i].m_iFlag = CUnit::FREE; - tempu[i].m_Packet.m_pcData = tempb + i * m_iMSS; - } - tempq->m_pUnit = tempu; - tempq->m_pBuffer = tempb; - tempq->m_iSize = size; m_pLastQueue->m_pNext = tempq; m_pLastQueue = tempq; m_pLastQueue->m_pNext = m_pQEntry; - m_iSize += size; + m_iSize += numUnits; return 0; } -int srt::CUnitQueue::shrink() -{ - // currently queue cannot be shrunk. - return -1; -} - srt::CUnit* srt::CUnitQueue::getNextAvailUnit() { - if (m_iCount * 10 > m_iSize * 9) - increase(); + const int iNumUnitsTotal = capacity(); + if (m_iNumTaken * 10 > iNumUnitsTotal * 9) // 90% or more are in use. + increase_(); - if (m_iCount >= m_iSize) + if (m_iNumTaken >= capacity()) + { + LOGC(qrlog.Error, log << "CUnitQueue: No free units to take. Capacity" << capacity() << "."); return NULL; + } int units_checked = 0; do @@ -232,8 +182,6 @@ m_pAvailUnit = m_pCurrQueue->m_pUnit; } while (units_checked < m_iSize); - increase(); - return NULL; } @@ -241,18 +189,18 @@ { SRT_ASSERT(unit != NULL); SRT_ASSERT(unit->m_iFlag != CUnit::FREE); - unit->m_iFlag = CUnit::FREE; + unit->m_iFlag.store(CUnit::FREE); - --m_iCount; + --m_iNumTaken; } void srt::CUnitQueue::makeUnitGood(CUnit* unit) { - ++m_iCount; + ++m_iNumTaken; SRT_ASSERT(unit != NULL); SRT_ASSERT(unit->m_iFlag == CUnit::FREE); - unit->m_iFlag = CUnit::GOOD; + unit->m_iFlag.store(CUnit::GOOD); } srt::CSndUList::CSndUList(sync::CTimer* pTimer) @@ -1134,11 +1082,12 @@ // srt::CRcvQueue::CRcvQueue() : m_WorkerThread() - , m_UnitQueue() + , m_pUnitQueue(NULL) , m_pRcvUList(NULL) , m_pHash(NULL) , m_pChannel(NULL) , m_pTimer(NULL) + , m_iIPversion() , m_szPayloadSize() , m_bClosing(false) , m_LSLock() @@ -1163,6 +1112,7 @@ } releaseCond(m_BufferCond); + delete m_pUnitQueue; delete m_pRcvUList; delete m_pHash; delete m_pRendezvousQueue; @@ -1181,14 +1131,16 @@ } #if ENABLE_LOGGING -int srt::CRcvQueue::m_counter = 0; +srt::sync::atomic srt::CRcvQueue::m_counter(0); #endif void srt::CRcvQueue::init(int qsize, size_t payload, int version, int hsize, CChannel* cc, CTimer* t) { + m_iIPversion = version; m_szPayloadSize = payload; - m_UnitQueue.init(qsize, (int)payload, version); + SRT_ASSERT(m_pUnitQueue == NULL); + m_pUnitQueue = new CUnitQueue(qsize, (int)payload); m_pHash = new CHash; m_pHash->init(hsize); @@ -1200,8 +1152,8 @@ m_pRendezvousQueue = new CRendezvousQueue; #if ENABLE_LOGGING - ++m_counter; - const std::string thrname = "SRT:RcvQ:w" + Sprint(m_counter); + const int cnt = ++m_counter; + const std::string thrname = "SRT:RcvQ:w" + Sprint(cnt); #else const std::string thrname = "SRT:RcvQ:w"; #endif @@ -1215,7 +1167,7 @@ void* srt::CRcvQueue::worker(void* param) { CRcvQueue* self = (CRcvQueue*)param; - sockaddr_any sa(self->m_UnitQueue.getIPversion()); + sockaddr_any sa(self->getIPversion()); int32_t id = 0; #if ENABLE_LOGGING @@ -1367,7 +1319,7 @@ } } // find next available slot for incoming packet - w_unit = m_UnitQueue.getNextAvailUnit(); + w_unit = m_pUnitQueue->getNextAvailUnit(); if (!w_unit) { // no space, skip this packet @@ -1647,8 +1599,7 @@ int srt::CRcvQueue::recvfrom(int32_t id, CPacket& w_packet) { - UniqueLock bufferlock(m_BufferLock); - CSync buffercond(m_BufferCond, bufferlock); + CUniqueSync buffercond(m_BufferLock, m_BufferCond); map >::iterator i = m_mBuffer.find(id); @@ -1777,15 +1728,14 @@ void srt::CRcvQueue::storePkt(int32_t id, CPacket* pkt) { - UniqueLock bufferlock(m_BufferLock); - CSync passcond(m_BufferCond, bufferlock); + CUniqueSync passcond(m_BufferLock, m_BufferCond); map >::iterator i = m_mBuffer.find(id); if (i == m_mBuffer.end()) { m_mBuffer[id].push(pkt); - passcond.signal_locked(bufferlock); + passcond.notify_one(); } else { diff -Nru srt-1.5.0/srtcore/queue.h srt-1.5.1/srtcore/queue.h --- srt-1.5.0/srtcore/queue.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/queue.h 2022-09-21 14:29:01.000000000 +0000 @@ -78,51 +78,36 @@ PASSACK = 2, DROPPED = 3 }; - Flag m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped - // TODO: Transition to the new RcvBuffer allows to use bool here. + + // TODO: The new RcvBuffer allows to use atomic_bool here. + sync::atomic m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped }; class CUnitQueue { - public: - CUnitQueue(); + /// @brief Construct a unit queue. + /// @param mss Initial number of units to allocate. + /// @param mss Maximum segment size meaning the size of each unit. + /// @throws CUDTException SRT_ENOBUF. + CUnitQueue(int initNumUnits, int mss); ~CUnitQueue(); -public: // Storage size operations - /// Initialize the unit queue. - /// @param [in] size queue size - /// @param [in] mss maximum segment size - /// @param [in] version IP version - /// @return 0: success, -1: failure. - int init(int size, int mss, int version); - - /// Increase (double) the unit queue size. - /// @return 0: success, -1: failure. - - int increase(); - - /// Decrease (halve) the unit queue size. - /// @return 0: success, -1: failure. - - int shrink(); - public: - int size() const { return m_iSize - m_iCount; } int capacity() const { return m_iSize; } + int size() const { return m_iSize - m_iNumTaken; } -public: // Operations on units - /// find an available unit for incoming packet. - /// @return Pointer to the available unit, NULL if not found. +public: + /// @brief Find an available unit for incoming packet. Allocate new units if 90% or more are in use. + /// @note This function is not thread-safe. Currently only CRcvQueue::worker thread calls it, thus + /// it is not an issue. However, must be protected if used from several threads in the future. + /// @return Pointer to the available unit, NULL if not found. CUnit* getNextAvailUnit(); void makeUnitFree(CUnit* unit); void makeUnitGood(CUnit* unit); -public: - inline int getIPversion() const { return m_iIPversion; } - private: struct CQEntry { @@ -131,17 +116,28 @@ int m_iSize; // size of each queue CQEntry* m_pNext; - } * m_pQEntry, // pointer to the first unit queue - *m_pCurrQueue, // pointer to the current available queue - *m_pLastQueue; // pointer to the last unit queue + }; - CUnit* m_pAvailUnit; // recent available unit + /// Increase the unit queue size (by @a m_iBlockSize units). + /// Uses m_mtx to protect access and changes of the queue state. + /// @return 0: success, -1: failure. + int increase_(); - int m_iSize; // total size of the unit queue, in number of packets - sync::atomic m_iCount; // total number of valid (occupied) packets in the queue + /// @brief Allocated a CQEntry of iNumUnits with each unit of mss bytes. + /// @param iNumUnits a number of units to allocate + /// @param mss the size of each unit in bytes. + /// @return a pointer to a newly allocated entry on success, NULL otherwise. + static CQEntry* allocateEntry(const int iNumUnits, const int mss); - int m_iMSS; // unit buffer size - int m_iIPversion; // IP version +private: + CQEntry* m_pQEntry; // pointer to the first unit queue + CQEntry* m_pCurrQueue; // pointer to the current available queue + CQEntry* m_pLastQueue; // pointer to the last unit queue + CUnit* m_pAvailUnit; // recent available unit + int m_iSize; // total size of the unit queue, in number of packets + sync::atomic m_iNumTaken; // total number of valid (occupied) packets in the queue + const int m_iMSS; // unit buffer size + const int m_iBlockSize; // Number of units in each CQEntry. private: CUnitQueue(const CUnitQueue&); @@ -510,20 +506,20 @@ /// @param [in] hsize hash table size /// @param [in] c UDP channel to be associated to the queue /// @param [in] t timer - void init(int size, size_t payload, int version, int hsize, CChannel* c, sync::CTimer* t); /// Read a packet for a specific UDT socket id. /// @param [in] id Socket ID /// @param [out] packet received packet /// @return Data size of the packet - int recvfrom(int32_t id, CPacket& to_packet); void stopWorker(); void setClosing() { m_bClosing = true; } + int getIPversion() { return m_iIPversion; } + private: static void* worker(void* param); sync::CThread m_WorkerThread; @@ -534,17 +530,18 @@ EConnectStatus worker_ProcessAddressedPacket(int32_t id, CUnit* unit, const sockaddr_any& sa); private: - CUnitQueue m_UnitQueue; // The received packet queue - CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue - CHash* m_pHash; // Hash table for UDT socket looking up - CChannel* m_pChannel; // UDP channel for receving packets - sync::CTimer* m_pTimer; // shared timer with the snd queue + CUnitQueue* m_pUnitQueue; // The received packet queue + CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue + CHash* m_pHash; // Hash table for UDT socket looking up + CChannel* m_pChannel; // UDP channel for receving packets + sync::CTimer* m_pTimer; // shared timer with the snd queue - size_t m_szPayloadSize; // packet payload size + int m_iIPversion; // IP version + size_t m_szPayloadSize; // packet payload size sync::atomic m_bClosing; // closing the worker #if ENABLE_LOGGING - static int m_counter; + static srt::sync::atomic m_counter; // A static counter to log RcvQueue worker thread number. #endif private: diff -Nru srt-1.5.0/srtcore/srt.h srt-1.5.1/srtcore/srt.h --- srt-1.5.0/srtcore/srt.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/srt.h 2022-09-21 14:29:01.000000000 +0000 @@ -46,17 +46,14 @@ // VC 6.0 does not support unsigned __int64: may cause potential problems. typedef __int64 uint64_t; #endif - - #ifdef SRT_DYNAMIC - #ifdef SRT_EXPORTS - #define SRT_API __declspec(dllexport) - #else - #define SRT_API __declspec(dllimport) - #endif + #endif + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) #else - #define SRT_API + #define SRT_API __declspec(dllimport) #endif - #else // __MINGW32__ + #else // !SRT_DYNAMIC #define SRT_API #endif #else @@ -477,8 +474,8 @@ // Stupid, but effective. This will be #undefined, so don't worry. -#define MJ(major) (1000 * MJ_##major) -#define MN(major, minor) (1000 * MJ_##major + MN_##minor) +#define SRT_EMJ(major) (1000 * MJ_##major) +#define SRT_EMN(major, minor) (1000 * MJ_##major + MN_##minor) // Some better way to define it, and better for C language. typedef enum SRT_ERRNO @@ -486,57 +483,56 @@ SRT_EUNKNOWN = -1, SRT_SUCCESS = MJ_SUCCESS, - SRT_ECONNSETUP = MJ(SETUP), - SRT_ENOSERVER = MN(SETUP, TIMEOUT), - SRT_ECONNREJ = MN(SETUP, REJECTED), - SRT_ESOCKFAIL = MN(SETUP, NORES), - SRT_ESECFAIL = MN(SETUP, SECURITY), - SRT_ESCLOSED = MN(SETUP, CLOSED), - - SRT_ECONNFAIL = MJ(CONNECTION), - SRT_ECONNLOST = MN(CONNECTION, CONNLOST), - SRT_ENOCONN = MN(CONNECTION, NOCONN), - - SRT_ERESOURCE = MJ(SYSTEMRES), - SRT_ETHREAD = MN(SYSTEMRES, THREAD), - SRT_ENOBUF = MN(SYSTEMRES, MEMORY), - SRT_ESYSOBJ = MN(SYSTEMRES, OBJECT), - - SRT_EFILE = MJ(FILESYSTEM), - SRT_EINVRDOFF = MN(FILESYSTEM, SEEKGFAIL), - SRT_ERDPERM = MN(FILESYSTEM, READFAIL), - SRT_EINVWROFF = MN(FILESYSTEM, SEEKPFAIL), - SRT_EWRPERM = MN(FILESYSTEM, WRITEFAIL), - - SRT_EINVOP = MJ(NOTSUP), - SRT_EBOUNDSOCK = MN(NOTSUP, ISBOUND), - SRT_ECONNSOCK = MN(NOTSUP, ISCONNECTED), - SRT_EINVPARAM = MN(NOTSUP, INVAL), - SRT_EINVSOCK = MN(NOTSUP, SIDINVAL), - SRT_EUNBOUNDSOCK = MN(NOTSUP, ISUNBOUND), - SRT_ENOLISTEN = MN(NOTSUP, NOLISTEN), - SRT_ERDVNOSERV = MN(NOTSUP, ISRENDEZVOUS), - SRT_ERDVUNBOUND = MN(NOTSUP, ISRENDUNBOUND), - SRT_EINVALMSGAPI = MN(NOTSUP, INVALMSGAPI), - SRT_EINVALBUFFERAPI = MN(NOTSUP, INVALBUFFERAPI), - SRT_EDUPLISTEN = MN(NOTSUP, BUSY), - SRT_ELARGEMSG = MN(NOTSUP, XSIZE), - SRT_EINVPOLLID = MN(NOTSUP, EIDINVAL), - SRT_EPOLLEMPTY = MN(NOTSUP, EEMPTY), - SRT_EBINDCONFLICT = MN(NOTSUP, BUSYPORT), - - SRT_EASYNCFAIL = MJ(AGAIN), - SRT_EASYNCSND = MN(AGAIN, WRAVAIL), - SRT_EASYNCRCV = MN(AGAIN, RDAVAIL), - SRT_ETIMEOUT = MN(AGAIN, XMTIMEOUT), - SRT_ECONGEST = MN(AGAIN, CONGESTION), + SRT_ECONNSETUP = SRT_EMJ(SETUP), + SRT_ENOSERVER = SRT_EMN(SETUP, TIMEOUT), + SRT_ECONNREJ = SRT_EMN(SETUP, REJECTED), + SRT_ESOCKFAIL = SRT_EMN(SETUP, NORES), + SRT_ESECFAIL = SRT_EMN(SETUP, SECURITY), + SRT_ESCLOSED = SRT_EMN(SETUP, CLOSED), + + SRT_ECONNFAIL = SRT_EMJ(CONNECTION), + SRT_ECONNLOST = SRT_EMN(CONNECTION, CONNLOST), + SRT_ENOCONN = SRT_EMN(CONNECTION, NOCONN), + + SRT_ERESOURCE = SRT_EMJ(SYSTEMRES), + SRT_ETHREAD = SRT_EMN(SYSTEMRES, THREAD), + SRT_ENOBUF = SRT_EMN(SYSTEMRES, MEMORY), + SRT_ESYSOBJ = SRT_EMN(SYSTEMRES, OBJECT), + + SRT_EFILE = SRT_EMJ(FILESYSTEM), + SRT_EINVRDOFF = SRT_EMN(FILESYSTEM, SEEKGFAIL), + SRT_ERDPERM = SRT_EMN(FILESYSTEM, READFAIL), + SRT_EINVWROFF = SRT_EMN(FILESYSTEM, SEEKPFAIL), + SRT_EWRPERM = SRT_EMN(FILESYSTEM, WRITEFAIL), + + SRT_EINVOP = SRT_EMJ(NOTSUP), + SRT_EBOUNDSOCK = SRT_EMN(NOTSUP, ISBOUND), + SRT_ECONNSOCK = SRT_EMN(NOTSUP, ISCONNECTED), + SRT_EINVPARAM = SRT_EMN(NOTSUP, INVAL), + SRT_EINVSOCK = SRT_EMN(NOTSUP, SIDINVAL), + SRT_EUNBOUNDSOCK = SRT_EMN(NOTSUP, ISUNBOUND), + SRT_ENOLISTEN = SRT_EMN(NOTSUP, NOLISTEN), + SRT_ERDVNOSERV = SRT_EMN(NOTSUP, ISRENDEZVOUS), + SRT_ERDVUNBOUND = SRT_EMN(NOTSUP, ISRENDUNBOUND), + SRT_EINVALMSGAPI = SRT_EMN(NOTSUP, INVALMSGAPI), + SRT_EINVALBUFFERAPI = SRT_EMN(NOTSUP, INVALBUFFERAPI), + SRT_EDUPLISTEN = SRT_EMN(NOTSUP, BUSY), + SRT_ELARGEMSG = SRT_EMN(NOTSUP, XSIZE), + SRT_EINVPOLLID = SRT_EMN(NOTSUP, EIDINVAL), + SRT_EPOLLEMPTY = SRT_EMN(NOTSUP, EEMPTY), + SRT_EBINDCONFLICT = SRT_EMN(NOTSUP, BUSYPORT), + + SRT_EASYNCFAIL = SRT_EMJ(AGAIN), + SRT_EASYNCSND = SRT_EMN(AGAIN, WRAVAIL), + SRT_EASYNCRCV = SRT_EMN(AGAIN, RDAVAIL), + SRT_ETIMEOUT = SRT_EMN(AGAIN, XMTIMEOUT), + SRT_ECONGEST = SRT_EMN(AGAIN, CONGESTION), - SRT_EPEERERR = MJ(PEERERROR) + SRT_EPEERERR = SRT_EMJ(PEERERROR) } SRT_ERRNO; - -#undef MJ -#undef MN +#undef SRT_EMJ +#undef SRT_EMN enum SRT_REJECT_REASON { diff -Nru srt-1.5.0/srtcore/stats.h srt-1.5.1/srtcore/stats.h --- srt-1.5.0/srtcore/stats.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/stats.h 2022-09-21 14:29:01.000000000 +0000 @@ -54,7 +54,7 @@ , m_packets(0) {} - BytesPackets(uint64_t bytes, size_t n = 1) + BytesPackets(uint64_t bytes, uint32_t n = 1) : m_bytes(bytes) , m_packets(n) {} diff -Nru srt-1.5.0/srtcore/sync.cpp srt-1.5.1/srtcore/sync.cpp --- srt-1.5.0/srtcore/sync.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/sync.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -318,7 +318,7 @@ int srt::sync::genRandomInt(int minVal, int maxVal) { // This Meyers singleton initialization is thread-safe since C++11, but is not thread-safe in C++03. - // A mutex to protect simulteneout access to the random device. + // A mutex to protect simultaneous access to the random device. // Thread-local storage could be used here instead to store the seed / random device. // However the generator is not used often (Initial Socket ID, Initial sequence number, FileCC), // so sharing a single seed among threads should not impact the performance. diff -Nru srt-1.5.0/srtcore/sync.h srt-1.5.1/srtcore/sync.h --- srt-1.5.0/srtcore/sync.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/sync.h 2022-09-21 14:29:01.000000000 +0000 @@ -489,6 +489,7 @@ // This should provide a cleaner API around locking with debug-logging inside. class CSync { +protected: Condition* m_cond; UniqueLock* m_locker; @@ -536,40 +537,46 @@ } // Static ad-hoc version - static void lock_signal(Condition& cond, Mutex& m) + static void lock_notify_one(Condition& cond, Mutex& m) { ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! cond.notify_one(); } - static void lock_broadcast(Condition& cond, Mutex& m) + static void lock_notify_all(Condition& cond, Mutex& m) { ScopedLock lk(m); // XXX with thread logging, don't use ScopedLock directly! cond.notify_all(); } - void signal_locked(UniqueLock& lk SRT_ATR_UNUSED) + void notify_one_locked(UniqueLock& lk SRT_ATR_UNUSED) { // EXPECTED: lk.mutex() is LOCKED. m_cond->notify_one(); } - // The signal_relaxed and broadcast_relaxed functions are to be used in case - // when you don't care whether the associated mutex is locked or not (you - // accept the case that a mutex isn't locked and the signal gets effectively - // missed), or you somehow know that the mutex is locked, but you don't have - // access to the associated UniqueLock object. This function, although it does - // the same thing as signal_locked() and broadcast_locked(), is here for - // the user to declare explicitly that the signal/broadcast is done without - // being prematurely certain that the associated mutex is locked. + void notify_all_locked(UniqueLock& lk SRT_ATR_UNUSED) + { + // EXPECTED: lk.mutex() is LOCKED. + m_cond->notify_all(); + } + + // The *_relaxed functions are to be used in case when you don't care + // whether the associated mutex is locked or not (you accept the case that + // a mutex isn't locked and the condition notification gets effectively + // missed), or you somehow know that the mutex is locked, but you don't + // have access to the associated UniqueLock object. This function, although + // it does the same thing as CSync::notify_one_locked etc. here for the + // user to declare explicitly that notifying is done without being + // prematurely certain that the associated mutex is locked. // // It is then expected that whenever these functions are used, an extra - // comment is provided to explain, why the use of the relaxed signaling is - // correctly used. + // comment is provided to explain, why the use of the relaxed notification + // is correctly used. - void signal_relaxed() { signal_relaxed(*m_cond); } - static void signal_relaxed(Condition& cond) { cond.notify_one(); } - static void broadcast_relaxed(Condition& cond) { cond.notify_all(); } + void notify_one_relaxed() { notify_one_relaxed(*m_cond); } + static void notify_one_relaxed(Condition& cond) { cond.notify_one(); } + static void notify_all_relaxed(Condition& cond) { cond.notify_all(); } }; //////////////////////////////////////////////////////////////////////////////// @@ -578,6 +585,9 @@ // //////////////////////////////////////////////////////////////////////////////// +// XXX Do not use this class now, there's an unknown issue +// connected to object management with the use of release* functions. +// Until this is solved, stay with separate *Cond and *Lock fields. class CEvent { public: @@ -586,6 +596,7 @@ public: Mutex& mutex() { return m_lock; } + Condition& cond() { return m_cond; } public: /// Causes the current thread to block until @@ -625,12 +636,64 @@ void notify_all(); + void lock_notify_one() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_one(); + } + + void lock_notify_all() + { + ScopedLock lk(m_lock); // XXX with thread logging, don't use ScopedLock directly! + m_cond.notify_all(); + } + private: Mutex m_lock; Condition m_cond; }; +// This class binds together the functionality of +// UniqueLock and CSync. It provides a simple interface of CSync +// while having already the UniqueLock applied in the scope, +// so a safe statement can be made about the mutex being locked +// when signalling or waiting. +class CUniqueSync: public CSync +{ + UniqueLock m_ulock; + +public: + + UniqueLock& locker() { return m_ulock; } + + CUniqueSync(Mutex& mut, Condition& cnd) + : CSync(cnd, m_ulock) + , m_ulock(mut) + { + } + + CUniqueSync(CEvent& event) + : CSync(event.cond(), m_ulock) + , m_ulock(event.mutex()) + { + } + + // These functions can be used safely because + // this whole class guarantees that whatever happens + // while its object exists is that the mutex is locked. + + void notify_one() + { + m_cond->notify_one(); + } + + void notify_all() + { + m_cond->notify_all(); + } +}; + class CTimer { public: diff -Nru srt-1.5.0/srtcore/tsbpd_time.cpp srt-1.5.1/srtcore/tsbpd_time.cpp --- srt-1.5.0/srtcore/tsbpd_time.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/tsbpd_time.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -103,13 +103,11 @@ #endif // SRT_DEBUG_TRACE_DRIFT -bool CTsbpdTime::addDriftSample(uint32_t usPktTimestamp, int usRTTSample) +bool CTsbpdTime::addDriftSample(uint32_t usPktTimestamp, const time_point& tsPktArrival, int usRTTSample) { if (!m_bTsbPdMode) return false; - const time_point tsNow = steady_clock::now(); - ScopedLock lck(m_mtxRW); // Remember the first RTT sample measured. Ideally we need RTT0 - the one from the handshaking phase, @@ -123,9 +121,9 @@ // A change in network delay has to be taken into account. The only way to get some estimation of it // is to estimate RTT change and assume that the change of the one way network delay is // approximated by the half of the RTT change. - const duration tdRTTDelta = microseconds_from((usRTTSample - m_iFirstRTT) / 2); + const duration tdRTTDelta = usRTTSample >= 0 ? microseconds_from((usRTTSample - m_iFirstRTT) / 2) : duration(0); const time_point tsPktBaseTime = getPktTsbPdBaseTime(usPktTimestamp); - const steady_clock::duration tdDrift = tsNow - tsPktBaseTime - tdRTTDelta; + const steady_clock::duration tdDrift = tsPktArrival - tsPktBaseTime - tdRTTDelta; const bool updated = m_DriftTracer.update(count_microseconds(tdDrift)); diff -Nru srt-1.5.0/srtcore/tsbpd_time.h srt-1.5.1/srtcore/tsbpd_time.h --- srt-1.5.0/srtcore/tsbpd_time.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/tsbpd_time.h 2022-09-21 14:29:01.000000000 +0000 @@ -66,10 +66,11 @@ /// and can be used to estimate clock drift. /// /// @param [in] pktTimestamp Timestamp of the arrived ACKACK packet. - /// @param [in] usRTTSample RTT sample from an ACK-ACKACK pair. + /// @param [in] tsPktArrival packet arrival time. + /// @param [in] usRTTSample RTT sample from an ACK-ACKACK pair. If no sample, pass '-1'. /// /// @return true if TSBPD base time has changed, false otherwise. - bool addDriftSample(uint32_t pktTimestamp, int usRTTSample); + bool addDriftSample(uint32_t pktTimestamp, const time_point& tsPktArrival, int usRTTSample); /// @brief Handle timestamp of data packet when 32-bit integer carryover is about to happen. /// When packet timestamp approaches CPacket::MAX_TIMESTAMP, the TSBPD base time should be diff -Nru srt-1.5.0/srtcore/utilities.h srt-1.5.1/srtcore/utilities.h --- srt-1.5.0/srtcore/utilities.h 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/srtcore/utilities.h 2022-09-21 14:29:01.000000000 +0000 @@ -301,7 +301,7 @@ struct BitsetMask { static const bool correct = true; - static const uint32_t value = 1 << R; + static const uint32_t value = 1u << R; }; // This is a trap for a case that BitsetMask::correct in the master template definition diff -Nru srt-1.5.0/test/test_bonding.cpp srt-1.5.1/test/test_bonding.cpp --- srt-1.5.0/test/test_bonding.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/test/test_bonding.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -46,15 +46,20 @@ }, ss); std::cout << "srt_connect_group calling " << std::endl; - const int st = srt_connect_group(ss, targets.data(), targets.size()); - std::cout << "srt_connect_group returned " << st << std::endl; + const int st = srt_connect_group(ss, targets.data(), (int) targets.size()); + std::cout << "srt_connect_group returned " << st << ", waiting for srt_close() to finish" << std::endl; closing_promise.wait(); + + std::cout << "TEST: closing future has exit. Deleting all other resources\n"; + // Delete config objects before prospective exception for (auto& gd: targets) srt_delete_config(gd.config); int res = srt_close(ss); + + std::cout << "TEST: closing ss has exit. Cleaning up\n"; if (res == SRT_ERROR) { std::cerr << "srt_close: " << srt_getlasterror_str() << std::endl; @@ -264,15 +269,15 @@ } std::cout << "Returned from connecting two sockets " << std::endl; - const int default_len = 3; - int rlen = default_len; - SRTSOCKET read[default_len]; - - int wlen = default_len; - SRTSOCKET write[default_len]; - for (int j = 0; j < 2; ++j) { + const int default_len = 3; + int rlen = default_len; + SRTSOCKET read[default_len]; + + int wlen = default_len; + SRTSOCKET write[default_len]; + const int epoll_res = srt_epoll_wait(poll_id, read, &rlen, write, &wlen, 5000, /* timeout */ @@ -280,6 +285,9 @@ std::cout << "Epoll result: " << epoll_res << '\n'; std::cout << "Epoll rlen: " << rlen << ", wlen: " << wlen << '\n'; + if (epoll_res < 0) + continue; + for (int i = 0; i < rlen; ++i) { std::cout << "Epoll read[" << i << "]: " << read[i] << '\n'; diff -Nru srt-1.5.0/test/test_buffer.cpp srt-1.5.1/test/test_buffer.cpp --- srt-1.5.0/test/test_buffer.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/test/test_buffer.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -27,17 +27,16 @@ void SetUp() override { // make_unique is unfortunatelly C++14 - m_unit_queue = unique_ptr(new CUnitQueue); + m_unit_queue.reset(new CUnitQueue(m_buff_size_pkts, 1500)); ASSERT_NE(m_unit_queue.get(), nullptr); - m_unit_queue->init(m_buff_size_pkts, 1500, AF_INET); #if ENABLE_NEW_RCVBUFFER const bool enable_msg_api = m_use_message_api; const bool enable_peer_rexmit = true; - m_rcv_buffer = unique_ptr(new CRcvBufferNew(m_init_seqno, m_buff_size_pkts, m_unit_queue.get(), enable_msg_api)); + m_rcv_buffer.reset(new CRcvBufferNew(m_init_seqno, m_buff_size_pkts, m_unit_queue.get(), enable_msg_api)); m_rcv_buffer->setPeerRexmitFlag(enable_peer_rexmit); #else - m_rcv_buffer = unique_ptr(new CRcvBuffer(m_unit_queue.get(), m_buff_size_pkts)); + m_rcv_buffer.reset(new CRcvBuffer(m_unit_queue.get(), m_buff_size_pkts)); #endif ASSERT_NE(m_rcv_buffer.get(), nullptr); } diff -Nru srt-1.5.0/test/test_cryspr.cpp srt-1.5.1/test/test_cryspr.cpp --- srt-1.5.0/test/test_cryspr.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/test/test_cryspr.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -139,11 +139,11 @@ /* CRYSPR control block test */ -class TestCRYSPRcypto +class TestCRYSPRcrypto : public ::testing::Test { protected: - TestCRYSPRcypto() + TestCRYSPRcrypto() { // initialization code here cryspr_m = NULL; @@ -151,7 +151,7 @@ cryspr_cb = NULL; } - ~TestCRYSPRcypto() + ~TestCRYSPRcrypto() { // cleanup any pending stuff, but no exceptions allowed } @@ -192,7 +192,7 @@ CRYSPR_cb *cryspr_cb; /* Control block */ }; -TEST_F(TestCRYSPRcypto, CtrlBlock) +TEST_F(TestCRYSPRcrypto, CtrlBlock) { EXPECT_EQ(cryspr_m, cryspr_cb->cryspr); //methods set in control block } @@ -306,37 +306,37 @@ } -TEST_F(TestCRYSPRcypto, PBKDF2_tv1_k128) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv1_k128) { test_pbkdf2(cryspr_m, cryspr_cb, 0); } -TEST_F(TestCRYSPRcypto, PBKDF2_tv1_k192) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv1_k192) { test_pbkdf2(cryspr_m, cryspr_cb, 1); } -TEST_F(TestCRYSPRcypto, PBKDF2_tv1_k256) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv1_k256) { test_pbkdf2(cryspr_m, cryspr_cb, 2); } -TEST_F(TestCRYSPRcypto, PBKDF2_tv2_i1) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv2_i1) { test_pbkdf2(cryspr_m, cryspr_cb, 3); } -TEST_F(TestCRYSPRcypto, PBKDF2_tv2_i20) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv2_i20) { test_pbkdf2(cryspr_m, cryspr_cb, 4); } -TEST_F(TestCRYSPRcypto, PBKDF2_tv2_i4096) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv2_i4096) { test_pbkdf2(cryspr_m, cryspr_cb, 5); } -TEST_F(TestCRYSPRcypto, PBKDF2_tv3_0) +TEST_F(TestCRYSPRcrypto, PBKDF2_tv3_0) { test_pbkdf2(cryspr_m, cryspr_cb, 6); } @@ -457,28 +457,28 @@ } -TEST_F(TestCRYSPRcypto, KMWRAP_tv1_k128) +TEST_F(TestCRYSPRcrypto, KMWRAP_tv1_k128) { test_kmwrap(cryspr_m, cryspr_cb, 0); } -TEST_F(TestCRYSPRcypto, KMWRAP_tv1_k192) +TEST_F(TestCRYSPRcrypto, KMWRAP_tv1_k192) { test_kmwrap(cryspr_m, cryspr_cb, 1); } -TEST_F(TestCRYSPRcypto, KMWRAP_tv1_k256) +TEST_F(TestCRYSPRcrypto, KMWRAP_tv1_k256) { test_kmwrap(cryspr_m, cryspr_cb, 2); } -TEST_F(TestCRYSPRcypto, KMUNWRAP_tv1_k128) +TEST_F(TestCRYSPRcrypto, KMUNWRAP_tv1_k128) { test_kmunwrap(cryspr_m, cryspr_cb, 0); } -TEST_F(TestCRYSPRcypto, KMUNWRAP_tv1_k192) +TEST_F(TestCRYSPRcrypto, KMUNWRAP_tv1_k192) { test_kmunwrap(cryspr_m, cryspr_cb, 1); } -TEST_F(TestCRYSPRcypto, KMUNWRAP_tv1_k256) +TEST_F(TestCRYSPRcrypto, KMUNWRAP_tv1_k256) { test_kmunwrap(cryspr_m, cryspr_cb, 2); } @@ -574,14 +574,11 @@ ASSERT_NE(cryspr_m->aes_ecb_cipher, nullPtr); rc1 = cryspr_m->aes_set_key( + HCRYPT_CTX_MODE_AESECB, bEncrypt, tv->sek, /* Stream encrypting Key */ tv->seklen, -#if WITH_FIPSMODE - cryspr_cb->aes_sek[0]); -#else - &cryspr_cb->aes_sek[0]); -#endif + CRYSPR_GETSEK(cryspr_cb, 0)); if(bEncrypt) { intxt=(unsigned char *)tv->cleartxt; outtxt=(unsigned char *)tv->ciphertxt; @@ -592,11 +589,7 @@ rc2 = cryspr_m->aes_ecb_cipher( bEncrypt, /* true:encrypt, false:decrypt */ -#if WITH_FIPSMODE - cryspr_cb->aes_sek[0], /* CRYpto Service PRovider AES Key context */ -#else - &cryspr_cb->aes_sek[0], /* CRYpto Service PRovider AES Key context */ -#endif + CRYSPR_GETSEK(cryspr_cb, 0),/* CRYpto Service PRovider AES Key context */ intxt, /* src */ txtlen, /* length */ result, /* dest */ @@ -613,51 +606,51 @@ #define ENCRYPT true #define DECRYPT false -TEST_F(TestCRYSPRcypto, EncryptAESecb_tv1_128) +TEST_F(TestCRYSPRcrypto, EncryptAESecb_tv1_128) { test_AESecb(cryspr_m, cryspr_cb, 0, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESecb_tv1_192) +TEST_F(TestCRYSPRcrypto, EncryptAESecb_tv1_192) { test_AESecb(cryspr_m, cryspr_cb, 1, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESecb_tv1_256) +TEST_F(TestCRYSPRcrypto, EncryptAESecb_tv1_256) { test_AESecb(cryspr_m, cryspr_cb, 2, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESecb_tv2_128) +TEST_F(TestCRYSPRcrypto, EncryptAESecb_tv2_128) { test_AESecb(cryspr_m, cryspr_cb, 3, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESecb_tv2_192) +TEST_F(TestCRYSPRcrypto, EncryptAESecb_tv2_192) { test_AESecb(cryspr_m, cryspr_cb, 4, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESecb_tv2_256) +TEST_F(TestCRYSPRcrypto, EncryptAESecb_tv2_256) { test_AESecb(cryspr_m, cryspr_cb, 5, ENCRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESecb_tv1_128) +TEST_F(TestCRYSPRcrypto, DecryptAESecb_tv1_128) { test_AESecb(cryspr_m, cryspr_cb, 0, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESecb_tv1_192) +TEST_F(TestCRYSPRcrypto, DecryptAESecb_tv1_192) { test_AESecb(cryspr_m, cryspr_cb, 1, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESecb_tv1_256) +TEST_F(TestCRYSPRcrypto, DecryptAESecb_tv1_256) { test_AESecb(cryspr_m, cryspr_cb, 2, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESecb_tv2_128) +TEST_F(TestCRYSPRcrypto, DecryptAESecb_tv2_128) { test_AESecb(cryspr_m, cryspr_cb, 3, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESecb_tv2_192) +TEST_F(TestCRYSPRcrypto, DecryptAESecb_tv2_192) { test_AESecb(cryspr_m, cryspr_cb, 4, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESecb_tv2_256) +TEST_F(TestCRYSPRcrypto, DecryptAESecb_tv2_256) { test_AESecb(cryspr_m, cryspr_cb, 5, DECRYPT); } @@ -729,14 +722,11 @@ ASSERT_NE(cryspr_m->aes_ctr_cipher, nullPtr); rc1 = cryspr_m->aes_set_key( + HCRYPT_CTX_MODE_AESCTR, true, //For CTR, Encrypt key is used for both encryption and decryption tv->sek, /* Stream encrypting Key */ tv->seklen, -#if WITH_FIPSMODE - cryspr_cb->aes_sek[0]); -#else - &cryspr_cb->aes_sek[0]); -#endif + CRYSPR_GETSEK(cryspr_cb, 0)); if(bEncrypt) { intxt=(unsigned char *)tv->cleartxt; outtxt=(unsigned char *)tv->ciphertxt; @@ -748,11 +738,7 @@ memcpy(ivec, tv->iv, sizeof(ivec)); //cipher ivec not const rc2 = cryspr_m->aes_ctr_cipher( bEncrypt, /* true:encrypt, false:decrypt */ -#if WITH_FIPSMODE - cryspr_cb->aes_sek[0], /* CRYpto Service PRovider AES Key context */ -#else - &cryspr_cb->aes_sek[0], /* CRYpto Service PRovider AES Key context */ -#endif + CRYSPR_GETSEK(cryspr_cb, 0),/* CRYpto Service PRovider AES Key context */ ivec, /* iv */ intxt, /* src */ txtlen, /* length */ @@ -768,27 +754,27 @@ #define ENCRYPT true #define DECRYPT false -TEST_F(TestCRYSPRcypto, EncryptAESctr_tv1_128) +TEST_F(TestCRYSPRcrypto, EncryptAESctr_tv1_128) { test_AESctr(cryspr_m, cryspr_cb, 0, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESctr_tv1_192) +TEST_F(TestCRYSPRcrypto, EncryptAESctr_tv1_192) { test_AESctr(cryspr_m, cryspr_cb, 1, ENCRYPT); } -TEST_F(TestCRYSPRcypto, EncryptAESctr_tv1_256) +TEST_F(TestCRYSPRcrypto, EncryptAESctr_tv1_256) { test_AESctr(cryspr_m, cryspr_cb, 2, ENCRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESctr_tv1_128) +TEST_F(TestCRYSPRcrypto, DecryptAESctr_tv1_128) { test_AESctr(cryspr_m, cryspr_cb, 0, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESctr_tv1_192) +TEST_F(TestCRYSPRcrypto, DecryptAESctr_tv1_192) { test_AESctr(cryspr_m, cryspr_cb, 1, DECRYPT); } -TEST_F(TestCRYSPRcypto, DecryptAESctr_tv1_256) +TEST_F(TestCRYSPRcrypto, DecryptAESctr_tv1_256) { test_AESctr(cryspr_m, cryspr_cb, 2, DECRYPT); } diff -Nru srt-1.5.0/test/test_ipv6.cpp srt-1.5.1/test/test_ipv6.cpp --- srt-1.5.0/test/test_ipv6.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/test/test_ipv6.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -31,6 +31,8 @@ m_caller_sock = srt_create_socket(); ASSERT_NE(m_caller_sock, SRT_ERROR); + // IPv6 calling IPv4 would otherwise fail if the system-default net.ipv6.bindv6only=1. + ASSERT_NE(srt_setsockflag(m_caller_sock, SRTO_IPV6ONLY, &no, sizeof no), SRT_ERROR); m_listener_sock = srt_create_socket(); ASSERT_NE(m_listener_sock, SRT_ERROR); diff -Nru srt-1.5.0/test/test_sync.cpp srt-1.5.1/test/test_sync.cpp --- srt-1.5.0/test/test_sync.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/test/test_sync.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -151,13 +151,13 @@ TEST(SyncRandom, GenRandomInt) { - array mn = {}; + array mn = {}; // Check generated values are in the specified range. const size_t n = 2048; for (size_t i = 0; i < n; ++i) { - const int rand_val = genRandomInt(0, mn.size() - 1); + const int rand_val = genRandomInt(0, int(mn.size()) - 1); ASSERT_GE(rand_val, 0); ASSERT_LT(rand_val, mn.size()); ++mn[rand_val]; @@ -166,14 +166,15 @@ // Check the distribution is more or less uniform. // 100% uniform if each value is generated (n / (2 * mn.size())) times. // We expect at least half of that value for a random uniform distribution. - const int min_value = n / (2 * mn.size()) - 1; - cout << "min value: " << min_value << endl; + ASSERT_GT(n / (2 * mn.size()), 4u); + const size_t min_value = n / (2 * mn.size()) - 4u; // Subtracting 4 to tolerate possible deviations. for (size_t i = 0; i < mn.size(); ++i) { EXPECT_GE(mn[i], min_value) << "i=" << i << ". Ok-ish if the count is non-zero."; } // Uncomment to see the distribution. + //cout << "min value: " << min_value << endl; //for (size_t i = 0; i < mn.size(); ++i) //{ // cout << i << '\t'; @@ -385,8 +386,8 @@ const steady_clock::duration timeout = seconds_from(5); auto wait_async = [](Condition* cond, Mutex* mutex, const steady_clock::duration& timeout) { - UniqueLock lock(*mutex); - return cond->wait_for(lock, timeout); + CUniqueSync cc (*mutex, *cond); + return cc.wait_for(timeout); }; auto wait_async_res = async(launch::async, wait_async, &cond, &mutex, timeout); diff -Nru srt-1.5.0/test/test_unitqueue.cpp srt-1.5.1/test/test_unitqueue.cpp --- srt-1.5.0/test/test_unitqueue.cpp 2022-06-15 07:33:53.000000000 +0000 +++ srt-1.5.1/test/test_unitqueue.cpp 2022-09-21 14:29:01.000000000 +0000 @@ -16,8 +16,7 @@ TEST(CUnitQueue, Increase) { const int buffer_size_pkts = 4; - CUnitQueue unit_queue; - unit_queue.init(buffer_size_pkts, 1500, AF_INET); + CUnitQueue unit_queue(buffer_size_pkts, 1500); vector taken_units; for (int i = 0; i < 5 * buffer_size_pkts; ++i) @@ -37,8 +36,7 @@ TEST(CUnitQueue, IncreaseAndFree) { const int buffer_size_pkts = 4; - CUnitQueue unit_queue; - unit_queue.init(buffer_size_pkts, 1500, AF_INET); + CUnitQueue unit_queue(buffer_size_pkts, 1500); CUnit* taken_unit = nullptr; for (int i = 0; i < 5 * buffer_size_pkts; ++i) @@ -62,8 +60,7 @@ TEST(CUnitQueue, IncreaseAndFreeGrouped) { const int buffer_size_pkts = 4; - CUnitQueue unit_queue; - unit_queue.init(buffer_size_pkts, 1500, AF_INET); + CUnitQueue unit_queue(buffer_size_pkts, 1500); vector taken_units; for (int i = 0; i < 5 * buffer_size_pkts; ++i)