diff --git a/.appveyor.yml b/.appveyor.yml index e496d6344..1254c9c16 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -3,9 +3,9 @@ configuration: - Debug image: + - Visual Studio 2022 - Visual Studio 2019 - Visual Studio 2015 - - Visual Studio 2013 platform: - x64 @@ -14,15 +14,11 @@ platform: 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 "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 "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 + - ps: if ($CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON} + - ps: if ($CNFG -eq "Debug") { if ($VSIMG -match '2015') { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } else {.\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON }} test_script: - - ps: if ( $Env:RUN_UNIT_TESTS ) { cd ./_build; ctest --extra-verbose -C $Env:CONFIGURATION; cd ../ } + - ps: if ( $Env:RUN_UNIT_TESTS ) { cd ./_build; ctest -E "TestIPv6.v6_calls_v4" --extra-verbose -C $Env:CONFIGURATION; cd ../ } after_build: - cmd: >- diff --git a/.github/workflows/abi.yml b/.github/workflows/abi.yml new file mode 100644 index 000000000..2c05cc06b --- /dev/null +++ b/.github/workflows/abi.yml @@ -0,0 +1,61 @@ +name: ABI checks + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +env: + SRT_BASE: v1.5.0 + +jobs: + build: + name: ABI checks + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v3 + with: + path: pull_request + - name: configure + run: | + cd pull_request + mkdir _build && cd _build + cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_UNITTESTS=ON ../ + - name: build + run: | + sudo apt install -y abi-dumper + cd pull_request/_build && cmake --build ./ + make install DESTDIR=./installdir + SRT_TAG_VERSION=$(cat version.h |grep SRT_VERSION_MINOR |head -n1 |awk {'print $3'}) + abi-dumper libsrt.so -o libsrt-pr.dump -public-headers installdir/usr/local/include/srt/ -lver 0 + SRT_BASE="v1.$SRT_TAG_VERSION.0" + echo "SRT_BASE=$SRT_BASE" >> "$GITHUB_ENV" + - uses: actions/checkout@v3 + with: + path: tag + ref: ${{ env.SRT_BASE }} + - name: configure_tag + run: | + echo $SRT_TAG_VERSION + cd tag + mkdir _build && cd _build + cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_UNITTESTS=ON ../ + - name: build_tag + run: | + cd tag + cd _build && cmake --build ./ + make install DESTDIR=./installdir + abi-dumper libsrt.so -o libsrt-tag.dump -public-headers installdir/usr/local/include/srt/ -lver 1 + - name: abi-check + run: | + git clone https://github.com/lvc/abi-compliance-checker.git + cd abi-compliance-checker && sudo make install && cd ../ + abi-compliance-checker -l libsrt -old tag/_build/libsrt-tag.dump -new pull_request/_build/libsrt-pr.dump + RES=$? + if (( $RES != 0 )) + then + echo "ABI/API Compatibility check failed with value $?" + exit $RES + fi diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml new file mode 100644 index 000000000..0af85fda3 --- /dev/null +++ b/.github/workflows/android.yaml @@ -0,0 +1,26 @@ +name: Android + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + name: NDK-R23 + runs-on: ubuntu-20.04 + + steps: + - name: Setup Android NDK R23 + uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r23 + add-to-path: false + - uses: actions/checkout@v3 + - name: build + run: | + cd ./scripts/build-android/ + echo ${{ steps.setup-ndk.outputs.ndk-path }} + source ./build-android -n ${{ steps.setup-ndk.outputs.ndk-path }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..4a337b6ca --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,43 @@ +name: "CodeQL" + +on: + push: + branches: [ "master", "experimental/socket-groups" ] + pull_request: + branches: [ "master" ] + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ cpp ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Configure + run: cmake -DENABLE_HEAVY_LOGGING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fpermissive -DENABLE_BONDING=1 . + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Build + run: | + make + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/cxx11-macos.yaml b/.github/workflows/cxx11-macos.yaml index 57cc5af79..e3e6b1f8a 100644 --- a/.github/workflows/cxx11-macos.yaml +++ b/.github/workflows/cxx11-macos.yaml @@ -1,4 +1,4 @@ -name: cxx11_win +name: cxx11 on: push: @@ -8,15 +8,17 @@ on: jobs: build: - name: macos-cxx11 + name: macos runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - name: GoogleTest + run: brew install googletest + - uses: actions/checkout@v3 - name: configure run: | mkdir _build && cd _build - cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON -DENABLE_EXPERIMENTAL_BONDING=ON + cmake ../ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DUSE_CXX_STD=14 - name: build run: cd _build && cmake --build ./ - name: test diff --git a/.github/workflows/cxx11-ubuntu.yaml b/.github/workflows/cxx11-ubuntu.yaml index 44dd06ce0..918bbcd22 100644 --- a/.github/workflows/cxx11-ubuntu.yaml +++ b/.github/workflows/cxx11-ubuntu.yaml @@ -1,23 +1,38 @@ -name: cxx11_win +name: cxx11 on: push: branches: [ master ] pull_request: branches: [ master ] - + types: [opened, synchronize, reopened] jobs: build: - name: ubuntu-cxx11 - runs-on: ubuntu-18.04 - + name: ubuntu + runs-on: ubuntu-20.04 + env: + BUILD_WRAPPER_OUT_DIR: sonar-output # Directory where build-wrapper output will be placed steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - name: Install sonar-scanner and build-wrapper + uses: sonarsource/sonarcloud-github-c-cpp@v2 - name: configure run: | mkdir _build && cd _build - cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_UNITTESTS=ON -DENABLE_EXPERIMENTAL_BONDING=ON + cmake ../ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=ON -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DENABLE_TESTING=ON -DENABLE_EXAMPLES=ON -DENABLE_CODE_COVERAGE=ON - name: build - run: cd _build && cmake --build ./ + run: cd _build && build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build . - name: test - run: cd _build && ctest --extra-verbose + run: | + cd _build && ctest --extra-verbose + - name: codecov + run: | + source ./scripts/collect-gcov.sh + bash <(curl -s https://codecov.io/bash) + - name: Run SonarCloud Scan for C and C++ + if: ${{ !github.event.pull_request.head.repo.fork }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + # Consult https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarscanner-cli/ for more information and options. + run: sonar-scanner --define sonar.cfamily.build-wrapper-output=_build/"${{ env.BUILD_WRAPPER_OUT_DIR }}" diff --git a/.github/workflows/cxx11-win.yaml b/.github/workflows/cxx11-win.yaml index cf9dcd871..f1554053d 100644 --- a/.github/workflows/cxx11-win.yaml +++ b/.github/workflows/cxx11-win.yaml @@ -1,4 +1,4 @@ -name: cxx11_win +name: cxx11 on: push: @@ -9,16 +9,16 @@ on: jobs: build: - name: windows-cxx11 + name: windows runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: configure run: | md _build && cd _build - cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON -DENABLE_EXPERIMENTAL_BONDING=ON + cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DUSE_CXX_STD=c++11 - name: build - run: cd _build && cmake --build ./ --config Release + run: cd _build && cmake --build ./ --config Release --verbose - name: test - run: cd _build && ctest --extra-verbose -C Release + run: cd _build && ctest -E "TestIPv6.v6_calls_v4|TestConnectionTimeout.BlockingLoop" --extra-verbose -C Release diff --git a/.github/workflows/iOS.yaml b/.github/workflows/iOS.yaml new file mode 100644 index 000000000..0fb11542b --- /dev/null +++ b/.github/workflows/iOS.yaml @@ -0,0 +1,25 @@ +name: iOS + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + strategy: + matrix: + cxxstdsync: [OFF, ON] + + name: iOS-cxxsync${{ matrix.cxxstdsync }} + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + - name: configure + run: | + mkdir _build && cd _build + cmake ../ -DENABLE_ENCRYPTION=OFF -DENABLE_STDCXX_SYNC=${{matrix.cxxstdsync}} -DENABLE_UNITTESTS=OFF -DENABLE_BONDING=ON --toolchain scripts/iOS.cmake + - name: build + run: cd _build && cmake --build ./ diff --git a/.github/workflows/s390x-focal.yaml b/.github/workflows/s390x-focal.yaml new file mode 100644 index 000000000..f1b6c7508 --- /dev/null +++ b/.github/workflows/s390x-focal.yaml @@ -0,0 +1,41 @@ +name: QEMU to run s390x-focal + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + Tests: + runs-on: ubuntu-latest + steps: + - name: Setup multiarch/qemu-user-static + run: | + docker run --rm --privileged multiarch/qemu-user-static:register --reset + - name: ubuntu-core:s390x-focal + uses: docker://multiarch/ubuntu-core:s390x-focal + with: + args: > + bash -c + "uname -a && + lscpu | grep Endian + " + - name: Checkout + uses: actions/checkout@v3 + - name: configure + uses: docker://multiarch/ubuntu-core:s390x-focal + with: + args: > + bash -c + "apt-get -y update && + export DEBIAN_FRONTEND=noninteractive && + export TZ=Etc/UTC && + apt-get -y install tzdata && + uname -a && + lscpu | grep Endian && + apt-get -y install cmake g++ libssl-dev git && + mkdir _build && cd _build && + cmake ../ -DENABLE_ENCRYPTION=ON -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DENABLE_TESTING=ON -DENABLE_EXAMPLES=ON && + cmake --build ./ && + ./test-srt -disable-ipv6" diff --git a/.gitignore b/.gitignore index e179ad146..b4e22ff8d 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,13 @@ _*/ # Ignode Visual Studio Code temp folder .vs/ .vscode/ + +# Ignore vcpkg submodule +vcpkg/ + +# LSP +compile_commands.json + +# ignore files generated by clion and cmake +.idea/ +cmake-build-debug/ diff --git a/.lgtm.yml b/.lgtm.yml index 5d42eec3e..4df28afb9 100644 --- a/.lgtm.yml +++ b/.lgtm.yml @@ -2,4 +2,4 @@ extraction: cpp: configure: command: - - cmake . -DENABLE_HEAVY_LOGGING=1 -DENABLE_EXPERIMENTAL_BONDING=1 + - cmake . -DENABLE_HEAVY_LOGGING=1 -DENABLE_BONDING=1 diff --git a/.travis.yml b/.travis.yml index 4d27056a6..94d5dac3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: cpp -dist: trusty +dist: xenial addons: apt: @@ -9,12 +9,10 @@ addons: - cmake - libssl-dev - build-essential - sonarcloud: - organization: "haivision" - token: - secure: "wJZC0kyyjuf4SZyonZ6p/5Ga9asEqSnKWF9NpRbu6S6ceERO7vbebuSJF5qX3A6ivPuw0TTk5WASOdnvIyfA28FU/D0MWRdH8K7T3w77wdE9EgAEYTUXzdrbzJY18+9pxjljHwWXWALPSGf3MClg4irWrdk1e6uHK+68R39+ZvBGBFpWeeZy/+at9+xwhtAGKBlSHe8zc+3wPxuYdvviLVJ25qbpNmnzkUR0X89G+UBl90raCPSN32EHFdImHZ5DxfEQQJgZFRjzQUY4EW/iYwaMel7jufAq0ClgV4psKujl9Lz8cPqx3WgqRfJyiIthOMTsac7G4zAw8LK2CI0VsssBp0JalLXaumi6vG7o6c3rIwKckzSKccq3pHa7h45praIVVn9s3nq+Q/JGA11FMkKQxdQtmwgFsLhbi6ZxabgsUi5KtWoWY2z6MgpJuROuAjNxZi9XJzUoJs7zSTUtRRW7V8Q2lRiOnknYh25N6TCA5bpyy1EZmRdJErm071YNI9P01gbFz5137FWJFiJzro9TGF0KoHSGiCIdUt3WlMzwr/i/wFLxFBQOZQ2rjTXvhs4hxONxMZV3gzxA1NdLaf9i5Mh6jxVMV+ujaRSV7JmPGzxqiAlpT9cJUhTCYuar9diLLeDrpe7RawEZR8V1xVDQ7yT8ruDNQ78VbSn/sC0=" + - libmbedtls-dev + - gdb homebrew: - update: true # TODO: this should be removed once this bug is fixed: https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296 + update: false packages: - openssl @@ -23,20 +21,22 @@ matrix: - os: linux env: - BUILD_TYPE=Debug - - BUILD_OPTS='-DENABLE_CODE_COVERAGE=ON -DENABLE_EXPERIMENTAL_BONDING=ON' - - RUN_SONARCUBE=1 - - RUN_CODECOV=1 + - BUILD_OPTS='-DENABLE_BONDING=ON -DCMAKE_CXX_FLAGS="-Werror"' - env: - BUILD_TYPE=Debug - - BUILD_OPTS='-DENABLE_LOGGING=OFF -DENABLE_MONOTONIC_CLOCK=ON -DENABLE_EXPERIMENTAL_BONDING=ON' + - BUILD_OPTS='-DENABLE_LOGGING=OFF -DUSE_ENCLIB=mbedtls -DENABLE_MONOTONIC_CLOCK=ON -DENABLE_BONDING=ON -DCMAKE_CXX_FLAGS="-Werror"' - os: linux env: BUILD_TYPE=Release - os: osx - osx_image: xcode10.2 - env: BUILD_TYPE=Debug + osx_image: xcode11.1 + env: + - BUILD_TYPE=Debug + - BUILD_OPTS='-DCMAKE_CXX_FLAGS="-Werror"' - os: osx - osx_image: xcode10.2 - env: BUILD_TYPE=Release + osx_image: xcode11.1 + env: + - BUILD_TYPE=Release + - BUILD_OPTS='-DCMAKE_CXX_FLAGS="-Werror"' - os: linux compiler: x86_64-w64-mingw32-g++ addons: @@ -48,41 +48,38 @@ matrix: - gcc-mingw-w64 - g++-mingw-w64-x86-64 before_script: - - git clone -b OpenSSL_1_1_1-stable https://github.com/openssl/openssl.git openssl + - git clone -b OpenSSL_1_1_1g https://github.com/openssl/openssl.git openssl - cd openssl - ./Configure --cross-compile-prefix=x86_64-w64-mingw32- mingw64 - make - cd .. env: BUILD_TYPE=Release + + # Power jobs + - os: linux + arch: ppc64le + env: + - BUILD_TYPE=Debug + - arch: ppc64le + env: + - BUILD_TYPE=Release + - BUILD_OPTS='-DENABLE_MONOTONIC_CLOCK=ON' script: - if [ "$TRAVIS_COMPILER" == "x86_64-w64-mingw32-g++" ]; then export CC="x86_64-w64-mingw32-gcc"; export CXX="x86_64-w64-mingw32-g++"; - cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="ON" -DUSE_OPENSSL_PC="OFF" -DOPENSSL_ROOT_DIR="$PWD/openssl" -DCMAKE_SYSTEM_NAME="Windows"; + cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="OFF" -DUSE_OPENSSL_PC="OFF" -DOPENSSL_ROOT_DIR="$PWD/openssl" -DCMAKE_SYSTEM_NAME="Windows"; elif [ "$TRAVIS_OS_NAME" == "linux" ]; then cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="ON"; elif [ "$TRAVIS_OS_NAME" == "osx" ]; then export PKG_CONFIG_PATH=$(brew --prefix openssl)"/lib/pkgconfig"; cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="ON"; fi - - echo "TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG" - - echo "TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST" - - if [[ "$TRAVIS_REPO_SLUG" != "Haivision/srt" || "$TRAVIS_PULL_REQUEST" -gt 0 ]]; then - export RUN_SONARCUBE=0; - fi - - echo "RUN_SONARCUBE=$RUN_SONARCUBE" - - if (( "$RUN_SONARCUBE" )); then - build-wrapper-linux-x86-64 --out-dir bw-output make; - else - make -j$(nproc); - fi + - make -j$(nproc); - if [ "$TRAVIS_COMPILER" != "x86_64-w64-mingw32-g++" ]; then - ./test-srt --gtest_filter="-TestMuxer.IPv4_and_IPv6"; - fi - - source ./scripts/collect-gcov.sh - - if (( "$RUN_CODECOV" )); then - bash <(curl -s https://codecov.io/bash); - fi - - if (( "$RUN_SONARCUBE" )); then - sonar-scanner -D"sonar.cfamily.gcov.reportPath=."; + ulimit -c unlimited; + ./test-srt -disable-ipv6; + SUCCESS=$?; + if [ -f core ]; then gdb -batch ./test-srt -c core -ex bt -ex "info thread" -ex quit; else echo "NO CORE - NO CRY!"; fi; + test $SUCCESS == 0; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 2270ce380..9a2fc63d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,14 +8,26 @@ # cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) -# XXX This can be potentially done in future, but there still exist -# some dependent project using cmake 2.8 - this can't be done this way. -#cmake_minimum_required (VERSION 3.0.2 FATAL_ERROR) -#project(SRT VERSION "1.4.2") -project(SRT C CXX) +set (SRT_VERSION 1.5.4) set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/scripts") -include(haiUtil) +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}) +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) +endif() + +if (NOT ${CMAKE_VERSION} VERSION_LESS "3.28.1") + cmake_policy(SET CMP0054 NEW) +endif () + include(FindPkgConfig) # XXX See 'if (MINGW)' condition below, may need fixing. include(FindThreads) @@ -26,25 +38,19 @@ string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSNAME_LC) set_if(DARWIN (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") OR (${CMAKE_SYSTEM_NAME} MATCHES "iOS") OR (${CMAKE_SYSTEM_NAME} MATCHES "tvOS") - OR (${CMAKE_SYSTEM_NAME} MATCHES "watchOS")) + OR (${CMAKE_SYSTEM_NAME} MATCHES "watchOS") + OR (${CMAKE_SYSTEM_NAME} MATCHES "visionOS")) set_if(LINUX ${CMAKE_SYSTEM_NAME} MATCHES "Linux") set_if(BSD ${SYSNAME_LC} MATCHES "bsd$") set_if(MICROSOFT WIN32 AND (NOT MINGW AND NOT CYGWIN)) set_if(GNU ${CMAKE_SYSTEM_NAME} MATCHES "GNU") -set_if(POSIX LINUX OR DARWIN OR BSD OR (CYGWIN AND CYGWIN_USE_POSIX)) -set_if(SYMLINKABLE LINUX OR DARWIN OR BSD OR CYGWIN OR GNU) - -# 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() +set_if(ANDROID ${SYSNAME_LC} MATCHES "android") +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") -set (SRT_VERSION 1.4.2) -set_version_variables(SRT_VERSION ${SRT_VERSION}) +include(GNUInstallDirs) # The CMAKE_BUILD_TYPE seems not to be always set, weird. if (NOT DEFINED ENABLE_DEBUG) @@ -56,15 +62,33 @@ if (NOT DEFINED ENABLE_DEBUG) 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") + if (ENABLE_ASSERT) + # Add _DEBUG macro if explicitly requested, to enable SRT_ASSERT(). + add_definitions(-D_DEBUG) + else() + add_definitions(-DNDEBUG) + endif() + 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}") @@ -87,11 +111,14 @@ endforeach() # SRT_ENABLE_ECN 1 /* Early Congestion Notification (for source bitrate control) */ # SRT_DEBUG_TSBPD_OUTJITTER 1 /* Packet Delivery histogram */ -# SRT_DEBUG_TSBPD_DRIFT 1 /* Debug Encoder-Decoder Drift) */ +# SRT_DEBUG_TRACE_DRIFT 1 /* Create a trace log for Encoder-Decoder Clock Drift */ # SRT_DEBUG_TSBPD_WRAP 1 /* Debug packet timestamp wraparound */ # SRT_DEBUG_TLPKTDROP_DROPSEQ 1 # SRT_DEBUG_SNDQ_HIGHRATE 1 +# SRT_DEBUG_BONDING_STATES 1 +# SRT_DEBUG_RTT 1 /* RTT trace */ # SRT_MAVG_SAMPLING_RATE 40 /* Max sampling rate */ +# SRT_ENABLE_FREQUENT_LOG_TRACE 0 : set to 1 to enable printing reason for suppressed freq logs # option defaults set(ENABLE_HEAVY_LOGGING_DEFAULT OFF) @@ -101,12 +128,29 @@ if (ENABLE_DEBUG) set(ENABLE_HEAVY_LOGGING_DEFAULT ON) endif() +# Note that the IP_PKTINFO has a limited portability and may not work on some platforms +# (Windows, FreeBSD, ...). +set (ENABLE_PKTINFO_DEFAULT OFF) + +set(ENABLE_STDCXX_SYNC_DEFAULT OFF) +set(ENABLE_MONOTONIC_CLOCK_DEFAULT OFF) +set(MONOTONIC_CLOCK_LINKLIB "") +if (MICROSOFT) + set(ENABLE_STDCXX_SYNC_DEFAULT ON) +elseif (POSIX) + test_requires_clock_gettime(ENABLE_MONOTONIC_CLOCK_DEFAULT MONOTONIC_CLOCK_LINKLIB) +endif() + # options option(CYGWIN_USE_POSIX "Should the POSIX API be used for cygwin. Ignored if the system isn't cygwin." OFF) -option(ENABLE_CXX11 "Should the c++11 parts (srt-live-transmit) be enabled" ON) +if (CMAKE_CXX_COMPILER_ID MATCHES "^GNU$" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) + option(ENABLE_CXX11 "Should the c++11 parts (srt-live-transmit) be enabled" OFF) +else() + option(ENABLE_CXX11 "Should the c++11 parts (srt-live-transmit) be enabled" ON) +endif() option(ENABLE_APPS "Should the Support Applications be Built?" ON) -option(ENABLE_EXPERIMENTAL_BONDING "Should the EXPERIMENTAL bonding functionality be enabled?" OFF) +option(ENABLE_BONDING "Should the bonding functionality be enabled?" OFF) option(ENABLE_TESTING "Should the Developer Test Applications be Built?" OFF) option(ENABLE_PROFILE "Should instrument the code for profiling. Ignored for non-GNU compiler." $ENV{HAI_BUILD_PROFILE}) option(ENABLE_LOGGING "Should logging be enabled" ON) @@ -114,20 +158,34 @@ option(ENABLE_HEAVY_LOGGING "Should heavy debug logging be enabled" ${ENABLE_HEA option(ENABLE_HAICRYPT_LOGGING "Should logging in haicrypt be enabled" 0) option(ENABLE_SHARED "Should libsrt be built as a shared library" ON) option(ENABLE_STATIC "Should libsrt be built as a static library" ON) +option(ENABLE_PKTINFO "Enable using IP_PKTINFO to allow the listener extracting the target IP address from incoming packets" ${ENABLE_PKTINFO_DEFAULT}) option(ENABLE_RELATIVE_LIBPATH "Should application contain relative library paths, like ../lib" OFF) option(ENABLE_GETNAMEINFO "In-logs sockaddr-to-string should do rev-dns" OFF) option(ENABLE_UNITTESTS "Enable unit tests" OFF) option(ENABLE_ENCRYPTION "Enable encryption in SRT" ON) +option(ENABLE_AEAD_API_PREVIEW "Enable AEAD API preview in SRT" Off) +option(ENABLE_MAXREXMITBW "Enable SRTO_MAXREXMITBW (v1.6.0 API preview)" Off) option(ENABLE_CXX_DEPS "Extra library dependencies in srt.pc for the CXX libraries useful with C language" ON) option(USE_STATIC_LIBSTDCXX "Should use static rather than shared libstdc++" OFF) option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON) option(ENABLE_CODE_COVERAGE "Enable code coverage reporting" OFF) -option(ENABLE_MONOTONIC_CLOCK "Enforced clock_gettime with monotonic clock on GC CV /temporary fix for #729/" OFF) -option(ENABLE_STDCXX_SYNC "Use C++11 chrono and threads for timing instead of pthreads" OFF) +option(ENABLE_MONOTONIC_CLOCK "Enforced clock_gettime with monotonic clock on GC CV" ${ENABLE_MONOTONIC_CLOCK_DEFAULT}) +option(ENABLE_STDCXX_SYNC "Use C++11 chrono and threads for timing instead of pthreads" ${ENABLE_STDCXX_SYNC_DEFAULT}) option(USE_OPENSSL_PC "Use pkg-config to find OpenSSL libraries" ON) +option(OPENSSL_USE_STATIC_LIBS "Link OpenSSL libraries statically." OFF) option(USE_BUSY_WAITING "Enable more accurate sending times at a cost of potentially higher CPU load" OFF) option(USE_GNUSTL "Get c++ library/headers from the gnustl.pc" OFF) option(ENABLE_SOCK_CLOEXEC "Enable setting SOCK_CLOEXEC on a socket" ON) +option(ENABLE_SHOW_PROJECT_CONFIG "Enable show Project Configuration" OFF) + +option(ENABLE_CLANG_TSA "Enable Clang Thread Safety Analysis" OFF) + +# NOTE: Use ATOMIC_USE_SRT_SYNC_MUTEX and will override the auto-detection of the +# Atomic implemetation in srtcore/atomic.h. +option(ATOMIC_USE_SRT_SYNC_MUTEX "Use srt::sync::Mutex to Implement Atomics" OFF) +if (ATOMIC_USE_SRT_SYNC_MUTEX) + add_definitions(-DATOMIC_USE_SRT_SYNC_MUTEX=1) +endif() set(TARGET_srt "srt" CACHE STRING "The name for the SRT library") @@ -158,6 +216,16 @@ else() message(STATUS "USE_BUSY_WAITING: OFF (default)") endif() +# Reduce the frequency of some frequent logs, milliseconds +set(SRT_LOG_SLOWDOWN_FREQ_MS_DEFAULT 1000) # 1s +if (NOT DEFINED SRT_LOG_SLOWDOWN_FREQ_MS) + if (ENABLE_HEAVY_LOGGING) + set(SRT_LOG_SLOWDOWN_FREQ_MS 0) # Just show every log message. + else() + set(SRT_LOG_SLOWDOWN_FREQ_MS ${SRT_LOG_SLOWDOWN_FREQ_MS_DEFAULT}) + endif() +endif() + if ( CYGWIN AND NOT CYGWIN_USE_POSIX ) set(WIN32 1) set(CMAKE_LEGACY_CYGWIN_WIN32 1) @@ -170,13 +238,12 @@ if (NOT USE_ENCLIB) message("NOTE: USE_GNUTLS is deprecated. Use -DUSE_ENCLIB=gnutls instead.") set (USE_ENCLIB gnutls) else() - set (USE_ENCLIB openssl) + set (USE_ENCLIB openssl-evp) endif() - endif() set(USE_ENCLIB "${USE_ENCLIB}" CACHE STRING "The crypto library that SRT uses") -set_property(CACHE USE_ENCLIB PROPERTY STRINGS "openssl" "gnutls" "mbedtls") +set_property(CACHE USE_ENCLIB PROPERTY STRINGS "openssl" "openssl-evp" "gnutls" "mbedtls" "botan") # Make sure DLLs and executabes go to the same path regardles of subdirectory set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) @@ -244,7 +311,13 @@ if(WIN32) if(ENABLE_INET_PTON) set(CMAKE_REQUIRED_LIBRARIES ws2_32) check_function_exists(inet_pton HAVE_INET_PTON) - add_definitions(-D_WIN32_WINNT=0x0600) + try_compile(AT_LEAST_VISTA + ${CMAKE_BINARY_DIR} + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/test_vista.c") + if(NOT AT_LEAST_VISTA) + # force targeting Vista + add_definitions(-D_WIN32_WINNT=0x0600) + endif() else() add_definitions(-D_WIN32_WINNT=0x0501) endif() @@ -255,7 +328,15 @@ if (DEFINED HAVE_INET_PTON) add_definitions(-DHAVE_INET_PTON=1) endif() +# Defines HAVE_PTHREAD_GETNAME_* and HAVE_PTHREAD_SETNAME_* +include(FindPThreadGetSetName) +FindPThreadGetSetName() + if (ENABLE_MONOTONIC_CLOCK) + if (NOT ENABLE_MONOTONIC_CLOCK_DEFAULT) + message(FATAL_ERROR "Your platform does not support CLOCK_MONOTONIC. Build with -DENABLE_MONOTONIC_CLOCK=OFF.") + endif() + set (WITH_EXTRALIBS "${WITH_EXTRALIBS} ${MONOTONIC_CLOCK_LINKLIB}") add_definitions(-DENABLE_MONOTONIC_CLOCK=1) endif() @@ -277,18 +358,41 @@ if (ENABLE_ENCRYPTION) link_directories( ${SSL_LIBRARY_DIRS} ) - else() # Common for mbedtls and openssl - if ("${USE_ENCLIB}" STREQUAL "mbedtls") - add_definitions(-DUSE_MBEDTLS=1) - set (SSL_REQUIRED_MODULES "mbedtls mbedcrypto") - else() - add_definitions(-DUSE_OPENSSL=1) - set (SSL_REQUIRED_MODULES "openssl libcrypto") + elseif ("${USE_ENCLIB}" STREQUAL "mbedtls") + add_definitions(-DUSE_MBEDTLS=1) + if ("${SSL_LIBRARY_DIRS}" STREQUAL "") + set(MBEDTLS_PREFIX "${CMAKE_PREFIX_PATH}" CACHE PATH "The path of mbedtls") + find_package(MbedTLS REQUIRED) + set (SSL_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) + set (SSL_LIBRARIES ${MBEDTLS_LIBRARIES}) endif() + if (WIN32) + set (SSL_LIBRARIES ${SSL_LIBRARIES} bcrypt) + endif() + if ("${SSL_LIBRARIES}" STREQUAL "") + set (SSL_LIBRARIES mbedtls mbedcrypto) + endif() + message(STATUS "SSL enforced mbedtls: -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}") + + foreach(LIB ${SSL_LIBRARIES}) + if(IS_ABSOLUTE ${LIB} AND EXISTS ${LIB}) + set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ${LIB}) + else() + set(SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} "-l${LIB}") + endif() + endforeach() + 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 if (USE_OPENSSL_PC) pkg_check_modules(SSL ${SSL_REQUIRED_MODULES}) + if (OPENSSL_USE_STATIC_LIBS) + # use `pkg-config --static xxx` found libs + set(SSL_LIBRARIES ${SSL_STATIC_LIBRARIES}) + endif() endif() if (SSL_FOUND) # We have some cases when pkg-config is improperly configured @@ -309,31 +413,105 @@ if (ENABLE_ENCRYPTION) ) message(STATUS "SSL via pkg-config: -L ${SSL_LIBRARY_DIRS} -I ${SSL_INCLUDE_DIRS} -l;${SSL_LIBRARIES}") else() - if ("${USE_ENCLIB}" STREQUAL "mbedtls") - if ("${SSL_LIBRARY_DIRS}" STREQUAL "") - set(MBEDTLS_PREFIX "${CMAKE_PREFIX_PATH}" CACHE PATH "The path of mbedtls") - find_package(MbedTLS REQUIRED) - set (SSL_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) - set (SSL_LIBRARIES ${MBEDTLS_LIBRARIES}) - endif() - if ("${SSL_LIBRARIES}" STREQUAL "") - set (SSL_LIBRARIES mbedtls mbedcrypto) - endif() - message(STATUS "SSL enforced mbedtls: -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}") + 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() + elseif ("${USE_ENCLIB}" STREQUAL "botan") + add_definitions(-DUSE_BOTAN=1 -DCRYSPR2) + set (SSL_REQUIRED_MODULES "botan") + find_package(Botan 3.0.0 REQUIRED) + botan_generate( + botan + ffi + nist_keywrap + aes_armv8 + aes_ni + aes_power8 + aes_vperm + idea_sse2 + serpent_avx2 + shacal2_armv8 + shacal2_avx2 + shacal2_x86 + sm4_armv8 + rdseed + sha1_armv8 + sha1_sse2 + sha1_x86 + sha2_32_armv8 + sha2_32_bmi2 + sha2_32_x86 + sha2_64_bmi2 + sha3_bmi2 + zfec_sse2 + zfec_vperm + argon2_avx2 + argon2_ssse3 + processor_rng + chacha_avx2 + ghash_cpu + ghash_vperm + simd + simd_avx2) + target_compile_features("botan" PRIVATE "cxx_std_20") + set (SSL_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) + set (SSL_LIBRARIES "botan") + 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() add_definitions(-DSRT_ENABLE_ENCRYPTION) message(STATUS "ENCRYPTION: ENABLED, using: ${SSL_REQUIRED_MODULES}") message (STATUS "SSL libraries: ${SSL_LIBRARIES}") + + if (ENABLE_AEAD_API_PREVIEW) + if (("${USE_ENCLIB}" STREQUAL "openssl-evp") OR ("${USE_ENCLIB}" STREQUAL "botan")) + add_definitions(-DENABLE_AEAD_API_PREVIEW) + message(STATUS "ENCRYPTION AEAD API: ENABLED") + else() + message(FATAL_ERROR "ENABLE_AEAD_API_PREVIEW is only available with USE_ENCLIB=[openssl-evp | botan]!") + endif() + else() + message(STATUS "ENCRYPTION AEAD API: DISABLED") + endif() + else() message(STATUS "ENCRYPTION: DISABLED") + message(STATUS "ENCRYPTION AEAD API: N/A") endif() if (USE_GNUSTL) @@ -343,8 +521,15 @@ if (USE_GNUSTL) set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ${GNUSTL_LIBRARIES} ${GNUSTL_LDFLAGS}) endif() +if (ENABLE_MAXREXMITBW) + add_definitions(-DENABLE_MAXREXMITBW) + message(STATUS "MAXREXMITBW API: ENABLED") +else() + message(STATUS "MAXREXMITBW API: DISABLED") +endif() + if (USING_DEFAULT_COMPILER_PREFIX) -# Detect if the compiler is GNU compatable for flags +# Detect if the compiler is GNU compatible for flags if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Intel|Clang|AppleClang") message(STATUS "COMPILER: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) - GNU compat") set(HAVE_COMPILER_GNU_COMPAT 1) @@ -374,6 +559,29 @@ else() # Compiler altered by WITH_COMPILER_TYPE/PREFIX - can't rely on CMAKE_CXX message(STATUS "COMPILER CHANGED TO: ${COMPILER_TYPE} - forcing C++11 standard for apps") endif() +# Check for GCC Atomic Intrinsics and C++11 Atomics. +# Sets: +# HAVE_LIBATOMIC +# HAVE_LIBATOMIC_COMPILES +# HAVE_LIBATOMIC_COMPILES_STATIC +# HAVE_GCCATOMIC_INTRINSICS +# HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC +include(CheckGCCAtomicIntrinsics) +CheckGCCAtomicIntrinsics() +# HAVE_CXX_ATOMIC +# HAVE_CXX_ATOMIC_STATIC +include(CheckCXXAtomic) +CheckCXXAtomic() + +# Check for std::put_time(): +# Sets: +# HAVE_CXX_STD_PUT_TIME +include(CheckCXXStdPutTime) +CheckCXXStdPutTime() +if (HAVE_CXX_STD_PUT_TIME) + add_definitions(-DHAVE_CXX_STD_PUT_TIME=1) +endif() + if (DISABLE_CXX11) set (ENABLE_CXX11 0) elseif( DEFINED ENABLE_CXX11 ) @@ -409,9 +617,6 @@ if (NOT ENABLE_CXX11) if (ENABLE_STDCXX_SYNC) message(FATAL_ERROR "ENABLE_STDCXX_SYNC is set, but C++11 is disabled by ENABLE_CXX11") endif() - if (DEFINED USE_CXX_STD) - message(FATAL_ERROR "USE_CXX_STD can be set only when ENABLE_CXX11 is on") - endif() elseif (ENABLE_STDCXX_SYNC) add_definitions(-DENABLE_STDCXX_SYNC=1) if (DEFINED USE_CXX_STD) @@ -426,6 +631,7 @@ elseif (ENABLE_STDCXX_SYNC) endif() message(STATUS "STDCXX_SYNC: ${ENABLE_STDCXX_SYNC}") +message(STATUS "MONOTONIC_CLOCK: ${ENABLE_MONOTONIC_CLOCK}") if (ENABLE_SOCK_CLOEXEC) add_definitions(-DENABLE_SOCK_CLOEXEC=1) @@ -455,9 +661,14 @@ if (DEFINED USE_CXX_STD) # Set this through independent flags set (USE_CXX_STD_LIB ${STDCXX}) - set (USE_CXX_STD_APP "") set (FORCE_CXX_STANDARD 1) - message(STATUS "C++ STANDARD: library: C++${STDCXX}, but apps still at least C++11") + if (NOT ENABLE_APPS) + set (USE_CXX_STD_APP ${STDCXX}) + message(STATUS "C++ STANDARD: library: C++${STDCXX}, apps disabled (examples will follow C++${STDCXX})") + else() + set (USE_CXX_STD_APP "") + message(STATUS "C++ STANDARD: library: C++${STDCXX}, but apps still at least C++11") + endif() elseif (FORCE_CXX_STANDARD_GNUONLY) # CMake is too old to handle CMAKE_CXX_STANDARD, # use bare GNU options. @@ -499,6 +710,9 @@ endif() # add extra warning flags for gccish compilers if (HAVE_COMPILER_GNU_COMPAT) set (SRT_GCC_WARN "-Wall -Wextra") + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set (SRT_GCC_WARN "${SRT_GCC_WARN} -Wshadow=local") + endif() else() # cpp debugging on Windows :D #set (SRT_GCC_WARN "/showIncludes") @@ -512,14 +726,6 @@ if (USE_STATIC_LIBSTDCXX) endif() endif() -# We need clock_gettime, but on some systems this is only provided -# by librt. Check if librt is required. -if (ENABLE_MONOTONIC_CLOCK AND LINUX) - # "requires" - exits on FATAL_ERROR when clock_gettime not available - test_requires_clock_gettime(NEED_CLOCK_GETTIME) - set (WITH_EXTRALIBS "${WITH_EXTRALIBS} ${NEED_CLOCK_GETTIME}") -endif() - # This options is necessary on some systems; on a cross-ARM compiler it # has been detected, for example, that -lrt is necessary for some applications @@ -571,6 +777,9 @@ elseif(CYGWIN) elseif(GNU) add_definitions(-DGNU=1) message(STATUS "DETECTED SYSTEM: GNU; GNU=1" ) +elseif(SUNOS) + add_definitions(-DSUNOS=1) + message(STATUS "DETECTED SYSTEM: SunOS|Solaris; SUNOS=1" ) else() message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}") endif() @@ -610,8 +819,26 @@ if (ENABLE_GETNAMEINFO) list(APPEND SRT_EXTRA_CFLAGS "-DENABLE_GETNAMEINFO=1") endif() +if (ENABLE_PKTINFO) + if (WIN32 OR BSD) + message(FATAL_ERROR "PKTINFO is not implemented on Windows or *BSD.") + endif() + + list(APPEND SRT_EXTRA_CFLAGS "-DSRT_ENABLE_PKTINFO=1") +endif() + + +# ENABLE_EXPERIMENTAL_BONDING is deprecated. Use ENABLE_BONDING. ENABLE_EXPERIMENTAL_BONDING is be removed in v1.6.0. if (ENABLE_EXPERIMENTAL_BONDING) - list(APPEND SRT_EXTRA_CFLAGS "-DENABLE_EXPERIMENTAL_BONDING=1") + message(DEPRECATION "ENABLE_EXPERIMENTAL_BONDING is deprecated. Please use ENABLE_BONDING instead.") + set (ENABLE_BONDING ON) +endif() + +if (ENABLE_BONDING) + list(APPEND SRT_EXTRA_CFLAGS "-DENABLE_BONDING=1") + message(STATUS "ENABLE_BONDING: ON") +else() + message(STATUS "ENABLE_BONDING: OFF") endif() if (ENABLE_THREAD_CHECK) @@ -622,6 +849,11 @@ if (ENABLE_THREAD_CHECK) ) endif() +if (ENABLE_CLANG_TSA) + list(APPEND SRT_EXTRA_CFLAGS "-Wthread-safety") + message(STATUS "Clang TSA: Enabled") +endif() + if (ENABLE_PROFILE) if (HAVE_COMPILER_GNU_COMPAT) # They are actually cflags, not definitions, but CMake is stupid enough. @@ -775,14 +1007,17 @@ MafReadDir(srtcore filelist.maf PRIVATE_HEADERS HEADERS_srt_private ) -message(STATUS "SRT Sources: ${SOURCES_srt}") - # Auto generated version file and add it to the HEADERS_srt list. if(DEFINED ENV{APPVEYOR_BUILD_NUMBER}) set(SRT_VERSION_BUILD ON) - set(APPVEYOR_BUILD_NUMBER_STRING $ENV{APPVEYOR_BUILD_NUMBER}) + set(CI_BUILD_NUMBER_STRING $ENV{APPVEYOR_BUILD_NUMBER}) message(STATUS "AppVeyor build environment detected: Adding build number to version header") endif() +if(DEFINED ENV{TEAMCITY_VERSION}) + set(SRT_VERSION_BUILD ON) + set(CI_BUILD_NUMBER_STRING $ENV{CI_BUILD_COUNTER}) + message(STATUS "TeamCity build environment detected: Adding build counter to version header") +endif() configure_file("srtcore/version.h.in" "version.h" @ONLY) @@ -801,10 +1036,10 @@ macro(srt_set_stdcxx targetname spec) if (NOT "${stdcxxspec}" STREQUAL "") if (FORCE_CXX_STANDARD_GNUONLY) target_compile_options(${targetname} PRIVATE -std=c++${stdcxxspec}) - #message(STATUS "C++ STD: ${targetname}: forced C++${stdcxxspec} standard - GNU option: -std=c++${stdcxxspec}") + message(STATUS "C++ STD: ${targetname}: forced C++${stdcxxspec} standard - GNU option: -std=c++${stdcxxspec}") else() set_target_properties(${targetname} PROPERTIES CXX_STANDARD ${stdcxxspec}) - #message(STATUS "C++ STD: ${targetname}: forced C++${stdcxxspec} standard - portable way") + message(STATUS "C++ STD: ${targetname}: forced C++${stdcxxspec} standard - portable way") endif() else() message(STATUS "APP: ${targetname}: using default C++ standard") @@ -821,20 +1056,22 @@ if (srt_libspec_shared) # shared libraries need PIC set (CMAKE_POSITION_INDEPENDENT_CODE ON) set_property(TARGET ${TARGET_srt}_shared PROPERTY OUTPUT_NAME ${TARGET_srt}) - set_target_properties (${TARGET_srt}_shared PROPERTIES VERSION ${SRT_VERSION} SOVERSION ${SRT_VERSION_MAJOR}) + set_target_properties (${TARGET_srt}_shared PROPERTIES VERSION ${SRT_VERSION} SOVERSION ${SRT_VERSION_MAJOR}.${SRT_VERSION_MINOR}) list (APPEND INSTALL_TARGETS ${TARGET_srt}_shared) if (ENABLE_ENCRYPTION) target_link_libraries(${TARGET_srt}_shared PRIVATE ${SSL_LIBRARIES}) endif() if (MICROSOFT) target_link_libraries(${TARGET_srt}_shared PRIVATE ws2_32.lib) - if (OPENSSL_USE_STATIC_LIBS) - target_link_libraries(${TARGET_srt}_shared PRIVATE crypt32.lib) - else() - set_target_properties(${TARGET_srt}_shared PROPERTIES LINK_FLAGS "/DELAYLOAD:libeay32.dll") + if (NOT (ENABLE_ENCRYPTION AND "${USE_ENCLIB}" STREQUAL "botan")) + if (OPENSSL_USE_STATIC_LIBS) + target_link_libraries(${TARGET_srt}_shared PRIVATE crypt32.lib) + else() + set_target_properties(${TARGET_srt}_shared PROPERTIES LINK_FLAGS "/DELAYLOAD:libeay32.dll") + endif() endif() elseif (MINGW) - target_link_libraries(${TARGET_srt}_shared PRIVATE wsock32.lib ws2_32.lib) + target_link_libraries(${TARGET_srt}_shared PRIVATE wsock32 ws2_32) elseif (APPLE) set_property(TARGET ${TARGET_srt}_shared PROPERTY MACOSX_RPATH ON) endif() @@ -866,7 +1103,7 @@ if (srt_libspec_static) endif() if (MICROSOFT) target_link_libraries(${TARGET_srt}_static PRIVATE ws2_32.lib) - if (OPENSSL_USE_STATIC_LIBS) + if (OPENSSL_USE_STATIC_LIBS) target_link_libraries(${TARGET_srt}_static PRIVATE crypt32.lib) endif() elseif (MINGW) @@ -879,8 +1116,8 @@ endif() target_include_directories(srt_virtual PRIVATE ${SSL_INCLUDE_DIRS}) -if (MICROSOFT) - if (OPENSSL_USE_STATIC_LIBS) +if (MICROSOFT) + if (OPENSSL_USE_STATIC_LIBS) set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ws2_32.lib crypt32.lib) else() set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ws2_32.lib) @@ -913,15 +1150,43 @@ if (ENABLE_SHARED) target_compile_definitions(srt_virtual PUBLIC -DSRT_DYNAMIC) endif() +target_compile_definitions(srt_virtual PRIVATE -DSRT_LOG_SLOWDOWN_FREQ_MS=${SRT_LOG_SLOWDOWN_FREQ_MS}) + +if (ENABLE_ENCRYPTION AND "${USE_ENCLIB}" STREQUAL "botan") + add_dependencies(srt_virtual botan) +endif() + if (srt_libspec_shared) if (MICROSOFT) target_link_libraries(${TARGET_srt}_shared PUBLIC Ws2_32.lib) - if (OPENSSL_USE_STATIC_LIBS) + if (OPENSSL_USE_STATIC_LIBS) target_link_libraries(${TARGET_srt}_shared PUBLIC crypt32.lib) endif() endif() endif() +# Required by some toolchains when statically linking this library if the +# GCC Atomic Intrinsics are being used. +if (HAVE_GCCATOMIC_INTRINSICS_REQUIRES_LIBATOMIC AND HAVE_LIBATOMIC) + if (srt_libspec_static) + target_link_libraries(${TARGET_srt}_static PUBLIC atomic) + endif() + if (srt_libspec_shared) + target_link_libraries(${TARGET_srt}_shared PUBLIC atomic) + endif() +elseif (HAVE_LIBATOMIC AND HAVE_LIBATOMIC_COMPILES_STATIC) + # This is a workaround for ANDROID NDK<17 builds, which need to link + # to libatomic when linking statically to the SRT library. + if (srt_libspec_static) + target_link_libraries(${TARGET_srt}_static PUBLIC atomic) + endif() +elseif (LINUX AND HAVE_LIBATOMIC AND HAVE_LIBATOMIC_COMPILES) + # This is a workaround for some older Linux Toolchains. + if (srt_libspec_static) + target_link_libraries(${TARGET_srt}_static PUBLIC atomic) + endif() +endif() + # Cygwin installs the *.dll libraries in bin directory and uses PATH. set (INSTALL_SHARED_DIR ${CMAKE_INSTALL_LIBDIR}) @@ -930,15 +1195,29 @@ if (CYGWIN) 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() # --- @@ -964,7 +1243,7 @@ endif() # obtained by `pkg-config --libs`. if(ENABLE_CXX_DEPS) foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES}) - if(IS_ABSOLUTE ${LIB} AND EXISTS ${LIB}) + if((IS_ABSOLUTE ${LIB} AND EXISTS ${LIB}) OR (${LIB} MATCHES "^-l")) set(SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ${LIB}) else() set(SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} "-l${LIB}") @@ -974,11 +1253,13 @@ endif() 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 @@ -996,11 +1277,21 @@ else() message(FATAL_ERROR "Either ENABLE_STATIC or ENABLE_SHARED has to be ON!") endif() -macro(srt_add_program name) +macro(srt_add_program_dont_install name) add_executable(${name} ${ARGN}) target_include_directories(${name} PRIVATE apps) target_include_directories(${name} PRIVATE common) - install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endmacro() + +macro(srt_add_program name) + srt_add_program_dont_install(${name} ${ARGN}) + 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) @@ -1039,7 +1330,13 @@ endmacro() 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 @@ -1086,7 +1383,6 @@ if (ENABLE_APPS) # srt-multiplex temporarily blocked #srt_add_application(srt-multiplex ${VIRTUAL_srtsupport}) srt_add_application(srt-tunnel ${VIRTUAL_srtsupport}) - target_compile_definitions(srt-tunnel PUBLIC -DSRT_ENABLE_VERBOSE_LOCK) endif() if (ENABLE_TESTING) @@ -1103,7 +1399,7 @@ if (ENABLE_APPS) # For testing applications, every application has its exclusive # list of source files in its own Manifest file. MafReadDir(testing ${name}.maf SOURCES SOURCES_app) - srt_add_program(${name} ${SOURCES_app}) + srt_add_program_dont_install(${name} ${SOURCES_app}) endmacro() srt_add_testprogram(utility-test) @@ -1124,12 +1420,11 @@ if (ENABLE_APPS) srt_add_testprogram(srt-test-relay) srt_make_application(srt-test-relay) - target_compile_definitions(srt-test-relay PUBLIC -DSRT_ENABLE_VERBOSE_LOCK) srt_add_testprogram(srt-test-multiplex) srt_make_application(srt-test-multiplex) - if (ENABLE_EXPERIMENTAL_BONDING) + if (ENABLE_BONDING) srt_add_testprogram(srt-test-mpbond) srt_make_application(srt-test-mpbond) endif() @@ -1148,41 +1443,56 @@ if (ENABLE_EXAMPLES) # No examples should need C++11 macro(srt_add_example mainsrc) get_filename_component(name ${mainsrc} NAME_WE) - srt_add_program(${name} examples/${mainsrc} ${ARGN}) + srt_add_program_dont_install(${name} examples/${mainsrc} ${ARGN}) + target_link_libraries(${name} ${srt_link_library} ${DEPENDS_srt}) endmacro() - srt_add_example(sendfile.cpp) - srt_make_application(sendfile) + srt_add_example(recvlive.cpp) + srt_add_example(sendfile.cpp) + srt_add_example(recvfile.cpp) - srt_make_application(recvfile) - srt_add_example(recvlive.cpp) - srt_make_application(recvlive) + srt_add_example(sendmsg.cpp) + + srt_add_example(recvmsg.cpp) srt_add_example(test-c-client.c) - srt_make_application(test-c-client) + + srt_add_example(example-client-nonblock.c) srt_add_example(test-c-server.c) - srt_make_application(test-c-server) -if (ENABLE_EXPERIMENTAL_BONDING) +if (ENABLE_BONDING) srt_add_example(test-c-client-bonding.c) - srt_make_application(test-c-client-bonding) srt_add_example(test-c-server-bonding.c) - srt_make_application(test-c-server-bonding) endif() srt_add_example(testcapi-connect.c) - target_link_libraries(testcapi-connect ${srt_link_library} ${DEPENDS_srt}) endif() if (ENABLE_UNITTESTS AND ENABLE_CXX11) + + if (${CMAKE_VERSION} VERSION_LESS "3.10.0") + message(STATUS "VERSION < 3.10 -- adding test using the old method") + set (USE_OLD_ADD_METHOD 1) + else() + message(STATUS "VERSION > 3.10 -- using NEW POLICY for in_list operator") + cmake_policy(SET CMP0057 NEW) # Support the new IN_LIST operator. + endif() + + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - find_package(GTest 1.8) + # Version ranges are only supported with CMake 3.19 or later. + # Need GTest v1.10 or higher to support GTEST_SKIP. + if (${CMAKE_VERSION} VERSION_LESS "3.19.0") + find_package(GTest 1.10) + else() + find_package(GTest 1.10...1.12) + endif() if (NOT GTEST_FOUND) message(STATUS "GTEST not found! Fetching from git.") include(googletest) @@ -1194,12 +1504,11 @@ if (ENABLE_UNITTESTS AND ENABLE_CXX11) endif() MafReadDir(test filelist.maf + HEADERS SOURCES_unittests SOURCES SOURCES_unittests ) - - message(STATUS "Unit test sources: ${SOURCES_unittests}") - srt_add_program(test-srt ${SOURCES_unittests}) + srt_add_program_dont_install(test-srt ${SOURCES_unittests}) srt_make_application(test-srt) target_include_directories(test-srt PRIVATE ${SSL_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}) @@ -1210,19 +1519,28 @@ if (ENABLE_UNITTESTS AND ENABLE_CXX11) ${PTHREAD_LIBRARY} ) - add_test( - NAME - test-srt - COMMAND - ${CMAKE_BINARY_DIR}/test-srt - ) + if (USE_OLD_ADD_METHOD) + add_test( + NAME test-srt + COMMAND ${CMAKE_BINARY_DIR}/test-srt + ) + #set_tests_properties(test-srt PROPERTIES RUN_SERIAL TRUE) + else() + set_tests_properties(${tests_srt} PROPERTIES RUN_SERIAL TRUE) + gtest_discover_tests(test-srt) + endif() enable_testing() - 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) @@ -1230,3 +1548,8 @@ if (DEFINED SRT_EXTRA_APPS_INC) # No extra variables expected. Just use the variables # already provided and define additional targets. endif() + +if (ENABLE_SHOW_PROJECT_CONFIG) + include(ShowProjectConfig) + ShowProjectConfig() +endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b6f226602..239e25a2c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ Submit a pull request at any time, whether an issue has been created or not. It * SRT protocol definitions * portability and platform-specific parts -Please follow the [Developer's guide](./docs/DevelopersGuide.md). +Please follow the [SRT Developer's Guide](docs/dev/developers-guide.md). ## Code Style diff --git a/README.md b/README.md index 70bcefbb1..0bf810144 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Secure Reliable Transport (SRT) Protocol +[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) +

SRT @@ -8,127 +10,209 @@ [![License: MPLv2.0][license-badge]](./LICENSE) [![Latest release][release-badge]][github releases] -[![Debian Badge][debian-badge]][debian-package] -[![LGTM Code Quality][lgtm-quality-badge]][lgtm-project] -[![LGTM Alerts][lgtm-alerts-badge]][lgtm-project] -[![codecov][codecov-badge]][codecov-project] +[![Quality Gate Status][sonarcloud-badge]][sonarcloud-project] +[![codecov][codecov-badge]][codecov-project] [![Build Status Linux and macOS][travis-badge]][travis] [![Build Status Windows][appveyor-badge]][appveyor] -## Introduction +[![Ubuntu 23.04][Ubuntu-badge]][Ubuntu-package] +[![Fedora 37][fedora-badge]][fedora-package] +[![Debian][debian-badge]][debian-package] +[![Homebrew][Homebrew-badge]][Homebrew-package] +[![Vcpkg][Vcpkg-badge]][Vcpkg-package] +[![ConanCenter][ConanCenter-badge]][ConanCenter-package] -Secure Reliable Transport (SRT) is an open source transport technology that optimizes streaming performance across unpredictable networks, such as the Internet. -| | | -| --- | --- | -| **S**ecure | Encrypts video streams | -| **R**eliable | Recovers from severe packet loss | -| **T**ransport | Dynamically adapts to changing network conditions | +## What is SRT? + +**Secure Reliable Transport (SRT)** is a transport protocol for ultra low (sub-second) latency live video and audio streaming, as well as for generic bulk data transfer[^1]. SRT is available as an open-source technology with the code on GitHub, a published [Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01), and a growing [community of SRT users](https://www.srtalliance.org/). SRT is applied to contribution and distribution endpoints as part of a video stream workflow to deliver the best quality and lowest latency video at all times. -As audio/video packets are streamed from a source to a destination device, SRT detects and adapts to the real-time network conditions between the two endpoints. SRT helps compensate for jitter and bandwidth fluctuations due to congestion over noisy networks, such as the Internet. Its error recovery mechanism minimizes the packet loss typical of Internet connections. And SRT supports AES encryption for end-to-end security, keeping your streams safe from prying eyes. +| | | +| ------------- | ------------------------------------------------- | +| **S**ecure | Encrypts video streams | +| **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. + +[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. + +

To learn more about the protocol subscribe to the Innovation Labs Blog on  slack logo

+ +

To ask a question join the conversation in the #development channel on  slack logo

+ +## Features + +> :point_down: Click on the ► button to expand a feature description. + +
+ Pristine Quality and Reliability + +

+ + No matter how unreliable your network, SRT can recover from severe packet loss and jitter, ensuring the integrity and quality of your video streams. + +

+
+ +
+ Low Latency + +

+ + SRT’s stream error correction is configurable to accommodate a user’s deployment conditions. Leveraging real-time IP communications development to extend traditional network error recovery practices, SRT delivers media with significantly lower latency than TCP/IP, while offering the speed of UDP transmission with greatly improved reliability. + +

+
+ +
+ Content Agnostic + +

+ + Unlike some other streaming protocols that only support specific video and audio formats, SRT is payload agnostic. Because SRT operates at the network transport level, acting as a wrapper around your content, it can transport any type of video format, codec, resolution, or frame rate. + +

+
+ +
+ Easy Firewall Traversal with Rendezvous Mode + +

+ + The handshaking process used by SRT supports outbound connections without the potential risks and dangers of permanent exterior ports being opened in a firewall, thereby maintaining corporate LAN security policies and minimizing the need for IT intervention. + +

+
+ +
+ AES Encryption -[Join the conversation](https://slackin-srtalliance.azurewebsites.net/) in the `#development` channel on [Slack](https://srtalliance.slack.com). +

-### Guides + Using 128/192/256-bit AES encryption trusted by governments and organizations around the world, SRT ensures that valuable content is protected end-to-end from contribution to distribution so that no unauthorized parties can listen. -* [Why SRT Was Created](docs/why-srt-was-created.md) -* [SRT Protocol Technical Overview](https://github.com/Haivision/srt/files/2489142/SRT_Protocol_TechnicalOverview_DRAFT_2018-10-17.pdf) -* SRT Cookbook: [website](https://srtlab.github.io/srt-cookbook), [GitHub](https://github.com/SRTLab/srt-cookbook) -* SRT RFC: [txt](https://haivision.github.io/srt-rfc/draft-sharabayko-mops-srt.txt), [html](https://haivision.github.io/srt-rfc/draft-sharabayko-mops-srt.html), [GitHub](https://github.com/Haivision/srt-rfc) -* [Using the `srt-live-transmit` App](docs/srt-live-transmit.md) -* [Contributing](docs/Contributing.md) -* [Developer's Guide](docs/DevelopersGuide.md) -* [SRT Encryption](docs/encryption.md) -* [API](docs/API.md) -* [Reporting problems](docs/reporting.md) +

+
-## Requirements +
+ Forward Error Correction (FEC) and Packet Filter API -* cmake (as build system) -* Tcl 8.5 (optional for user-friendly build system) -* OpenSSL -* Pthreads (for POSIX systems it's builtin, for Windows there's a library) +

-For detailed description of the build system and options, please read [BuildOptions.md](docs/BuildOptions.md). + [SRT 1.4](https://github.com/Haivision/srt/releases/tag/v1.4.0) sees the introduction of the _packet filter API_. This mechanism allows custom processing to be performed on network packets on the sender side before they are sent, and on the receiver side once received from the network. The API allows users to write their own plugin, thereby extending the SRT protocol's capabilities even further with all kinds of different packet filtering. Users can manipulate the resulting packet filter data in any way, such as for custom encryption, packet inspection, or accessing data before it is sent. -### Build on Linux + The first plugin created as an example of what can be achieved with the packet filter API is for Forward Error Correction (FEC) which, in certain use cases, can offer slightly lower latency than Automatic Repeat reQuest (ARQ). This plugin allows three different modes: -Install cmake and openssl-devel (or similar name) package. For pthreads -there should be -lpthreads linker flag added. + - ARQ only – retransmits lost packets, + - FEC only – provides the overhead needed for FEC recovery on the receiver side, + - FEC and ARQ – retransmits lost packets that FEC fails to recover. -Default installation path prefix of `make install` is `/usr/local`. +

+
-To define a different installation path prefix, use the `--prefix` option with `configure` -or [`-DCMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html) CMake option. +
+ Connection Bonding -To uninstall, call `make -n install` to list all the dependencies, and then pass the list to `rm`. +

-#### Ubuntu 14 + Similar to SMPTE-2022-7 over managed networks, Connection Bonding adds seamless stream protection and hitless failover to the SRT protocol. This technology relies on more than one IP network path to prevent disruption to live video streams in the event of network congestion or outages, maintaining continuity of service. -```shell -sudo apt-get update -sudo apt-get upgrade -sudo apt-get install tclsh pkg-config cmake libssl-dev build-essential -./configure -make -``` + This is accomplished using the [socket groups](./docs/features/socket-groups.md) introduced in [SRT v1.5](https://github.com/Haivision/srt/releases/tag/v1.5.0). The general concept of socket groups means having a group that contains multiple sockets, where one operation for sending one data signal is applied to the group. Single sockets inside the group will take over this operation and do what is necessary to deliver the signal to the receiver. -#### CentOS 7 + Two modes are supported: -```shell -sudo yum update -sudo yum install tcl pkgconfig openssl-devel cmake gcc gcc-c++ make automake -./configure -make -``` + - [Broadcast](./docs/features/socket-groups.md#1-broadcast) - In *Broadcast* mode, data is sent redundantly over all the member links in a group. If one of the links fails or experiences network jitter and/or packet loss, the missing data will be received over another link in the group. Redundant packets are simply discarded at the receiver side. -#### CentOS 6 + - [Main/Backup](./docs/features/bonding-main-backup.md) - In *Main/Backup* mode, only one (main) link at a time is used for data transmission while other (backup) connections are on standby to ensure the transmission will continue if the main link fails. The goal of Main/Backup mode is to identify a potential link break before it happens, thus providing a time window within which to seamlessly switch to one of the backup links. -```shell -sudo yum update -sudo yum install tcl pkgconfig openssl-devel cmake gcc gcc-c++ make automake -sudo yum install centos-release-scl-rh devtoolset-3-gcc devtoolset-3-gcc-c++ -scl enable devtoolset-3 bash -./configure --use-static-libstdc++ --with-compiler-prefix=/opt/rh/devtoolset-3/root/usr/bin/ -make -``` +

+
-### Build on Mac (Darwin, iOS) +
+ Access Control (Stream ID) -[Homebrew](https://brew.sh/) supports "srt" formula. +

-```shell -brew update -brew install srt -``` + Access Control enables the upstream application to assign a Stream ID to individual SRT streams. By using a unique Stream ID, either automatically generated or customized, the upstream application can send multiple SRT streams to a single IP address and UDP port. The Stream IDs can then be used by a receiver to identify and differentiate between ingest streams, apply user password access methods, and in some cases even apply automation based on the naming of the Stream ID. For example, contribution could be sent to a video production workflow and monitoring to a monitoring service. -If you prefer using a head commit of `master` branch, you should add `--HEAD` option -to `brew` command. + For broadcasters, Stream ID is key to replacing RTMP for ingesting video streams, especially HEVC/H.265 content, into cloud service or CDNs that have a single IP socket (address + port) open for incoming video. -```shell -brew install --HEAD srt -``` +

+
-Also, SRT can be built with `cmake` and `make` on Mac. -Install cmake and openssl with development files from "brew". Note that the -system version of OpenSSL is inappropriate, although you should be able to -use any newer version compiled from sources, if you prefer. +## Getting Started with SRT -```shell -brew install cmake -brew install openssl -export OPENSSL_ROOT_DIR=$(brew --prefix openssl) -export OPENSSL_LIB_DIR=$(brew --prefix openssl)"/lib" -export OPENSSL_INCLUDE_DIR=$(brew --prefix openssl)"/include" -./configure -make -``` +| | | | +|:-----------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------:| +| [The SRT API](./docs#srt-api-documents) | [IETF Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) | [Sample Apps](./docs#sample-applications) | +| Reference documentation for the SRT library API | The SRT Protocol Internet Draft | Instructions for using test apps (`srt-live-transmit`, `srt-file-transmit`, etc.) | +| [SRT Technical Overview](https://github.com/Haivision/srt/files/2489142/SRT_Protocol_TechnicalOverview_DRAFT_2018-10-17.pdf) | [SRT Deployment Guide](https://www.srtalliance.org/srt-deployment-guide/) | [SRT CookBook](https://srtlab.github.io/srt-cookbook) | +| Early draft technical overview (precursor to the Internet Draft) | A comprehensive overview of the protocol with deployment guidelines | Development notes on the SRT protocol | +| [Innovation Labs Blog](https://medium.com/innovation-labs-blog/tagged/secure-reliable-transport) | [SRTLab YouTube Channel](https://www.youtube.com/channel/UCr35JJ32jKKWIYymR1PTdpA) | [Slack](https://srtalliance.slack.com) | +| The blog on Medium with SRT-related technical articles | Technical YouTube channel with useful videos | Slack channels to get the latest updates and ask questions
[Join SRT Alliance on Slack](https://slackin-srtalliance.azurewebsites.net/) | -### Build on Windows +### Additional Documentation + +- [Why SRT?](./docs/misc/why-srt-was-created.md) - A brief history and rationale for SRT by Marc Cymontkowski. +- [RTMP vs. SRT: Comparing Latency and Maximum Bandwidth](https://www.haivision.com/resources/white-paper/srt-versus-rtmp/) White Paper. +- [Documentation on GitHub](./docs#documentation-overview) with SRT API documents, features decsriptions, etc. +- The SRT Protocol Internet Draft: [Datatracker](https://datatracker.ietf.org/doc/draft-sharabayko-srt/) | [Latest Version](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) | [Latest Working Copy](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html) | [GitHub Repo](https://github.com/Haivision/srt-rfc) + +## 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) | [Package Managers](./docs/build/package-managers.md) + +### Requirements + +* C++03 or above compliant compiler. +* CMake 2.8.12 or above as a build system. +* OpenSSL 1.1 to enable encryption, otherwise build with [`-DENABLE_ENCRYPTION=OFF`](./docs/build/build-options.md#enable_encryption). +* Multithreading is provided by either of the following: + * C++11: standard library (`std` by [`-DENABLE_STDCXX_SYNC=ON`](./docs/build/build-options.md#enable_stdcxx_sync) CMake option), + * C++03: Pthreads (for POSIX systems it's built in, for Windows there is a ported library). +* Tcl 8.5 is optional and is used by `./configure` script. Otherwise, use CMake directly. + +### Build Options + +For detailed descriptions of the build system and options, please read the [SRT Build Options](./docs/build/build-options.md) document. + +## Sample Applications and Tools + +The current repo provides [sample applications](./apps) and [code examples](./examples) that demonstrate the usage of the SRT library API. Among them are [`srt-live-transmit`](./apps/srt-live-transmit.cpp), [`srt-file-transmit`](./apps/srt-file-transmit.cpp), and other applications. The respective documentation can be found [here](./docs#sample-applications). Note that all samples are provided for instructional purposes, and should not be used in a production environment. + +The [`srt-xtransmit`](https://github.com/maxsharabayko/srt-xtransmit) utility is actively used for internal testing and performance evaluation. Among other features it supports dummy payload generation, traffic routings, and connection bonding. Additional details are available in the [`srt-xtransmit`](https://github.com/maxsharabayko/srt-xtransmit) repo itself. + +Python tools that might be useful during development are: + +- [`srt-stats-plotting`](https://github.com/mbakholdina/srt-stats-plotting) - A script designed to plot graphs based on SRT `.csv` statistics. +- [`lib-tcpdump-processing`](https://github.com/mbakholdina/lib-tcpdump-processing) - A library designed to process `.pcap(ng)` [tcpdump](https://www.tcpdump.org/) or [Wireshark](https://www.wireshark.org/) trace files and extract SRT packets of interest for further analysis. +- [`lib-srt-utils`](https://github.com/mbakholdina/lib-srt-utils) - A Python library containing supporting code for running SRT tests based on an experiment configuration. + +## Contributing + +Anyone is welcome to contribute. If you decide to get involved, please take a moment to review the guidelines: + +* [SRT Developer's Guide](docs/dev/developers-guide.md) +* [Contributing](CONTRIBUTING.md) +* [Reporting Issues](docs/dev/making-srt-better.md) + +For information on contributing to the [Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) or to submit issues please go to the following [repo](https://github.com/Haivision/srt-rfc). The repo for contributing in [SRT CookBook](https://srtlab.github.io/srt-cookbook/) can be found [here](https://github.com/SRTLab/srt-cookbook/). + +## License + +By contributing code to the SRT project, you agree to license your contribution under the [MPLv2.0 License](LICENSE). + +## Release History + +- [Release notes](https://github.com/Haivision/srt/releases) +- [SRT versioning](./docs/dev/developers-guide.md#versioning) + + +[^1]: The term “live streaming” refers to continuous data transmission (MPEG-TS or equivalent) with latency management. Live streaming based on segmentation and transmission of files like in the HTTP Live Streaming (HLS) protocol (as described in RFC8216) is not part of this use case. File transmission in either message or buffer mode should be considered in this case. See [Section 7. Best Practices and Configuration Tips for Data Transmission via SRT](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-7) of the Internet Draft for details. Note that SRT is content agnostic, meaning that any type of data can be transmitted via its payload. -Follow the [Windows build instructions](docs/build-win.md). [appveyor-badge]: https://img.shields.io/appveyor/ci/Haivision/srt/master.svg?label=Windows [appveyor]: https://ci.appveyor.com/project/Haivision/srt @@ -136,9 +220,14 @@ Follow the [Windows build instructions](docs/build-win.md). [travis]: https://travis-ci.org/Haivision/srt [license-badge]: https://img.shields.io/badge/License-MPLv2.0-blue -[lgtm-alerts-badge]: https://img.shields.io/lgtm/alerts/github/Haivision/srt -[lgtm-quality-badge]: https://img.shields.io/lgtm/grade/cpp/github/Haivision/srt -[lgtm-project]: https://lgtm.com/projects/g/Haivision/srt/ +[Vcpkg-package]: https://repology.org/project/srt/versions +[Vcpkg-badge]: https://repology.org/badge/version-for-repo/vcpkg/srt.svg + +[ConanCenter-package]: https://repology.org/project/srt/versions +[ConanCenter-badge]: https://repology.org/badge/version-for-repo/conancenter/srt.svg + +[sonarcloud-project]: https://sonarcloud.io/project/overview?id=srt +[sonarcloud-badge]: https://sonarcloud.io/api/project_badges/measure?project=srt&metric=alert_status [codecov-project]: https://codecov.io/gh/haivision/srt [codecov-badge]: https://codecov.io/gh/haivision/srt/branch/master/graph/badge.svg @@ -146,5 +235,14 @@ Follow the [Windows build instructions](docs/build-win.md). [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 + +[fedora-package]: https://repology.org/project/srt/versions +[fedora-badge]: https://repology.org/badge/version-for-repo/fedora_37/srt.svg + +[homebrew-package]: https://repology.org/project/srt/versions +[homebrew-badge]: https://repology.org/badge/version-for-repo/homebrew/srt.svg + +[Ubuntu-package]: https://repology.org/project/srt/versions +[Ubuntu-badge]: https://repology.org/badge/version-for-repo/ubuntu_23_04/srt.svg diff --git a/apps/apputil.cpp b/apps/apputil.cpp index ecce703e8..22c31521b 100644 --- a/apps/apputil.cpp +++ b/apps/apputil.cpp @@ -16,11 +16,13 @@ #include #include +#include "srt.h" // Required for SRT_SYNC_CLOCK_* definitions. #include "apputil.hpp" #include "netinet_any.h" #include "srt_compat.h" using namespace std; +using namespace srt; // NOTE: MINGW currently does not include support for inet_pton(). See @@ -47,9 +49,12 @@ int inet_pton(int af, const char * src, void * dst) ZeroMemory(&ss, sizeof(ss)); // work around non-const API - strncpy(srcCopy, src, INET6_ADDRSTRLEN + 1); +#ifdef _MSC_VER + strncpy_s(srcCopy, INET6_ADDRSTRLEN + 1, src, _TRUNCATE); +#else + strncpy(srcCopy, src, INET6_ADDRSTRLEN); srcCopy[INET6_ADDRSTRLEN] = '\0'; - +#endif if (WSAStringToAddress( srcCopy, af, NULL, (struct sockaddr *)&ss, &ssSize) != 0) { @@ -205,7 +210,10 @@ options_t ProcessOptions(char* const* argv, int argc, std::vector isoption = true; // If a[0] isn't NUL - because it is dash - then // we can safely check a[1]. - if (a[1] && isdigit(a[1])) + // An expression starting with a dash is not + // an option marker if it is a single dash or + // a negative number. + if (!a[1] || isdigit(a[1])) isoption = false; } @@ -248,7 +256,7 @@ options_t ProcessOptions(char* const* argv, int argc, std::vector } // Find the key in the scheme. If not found, treat it as ARG_NONE. - for (auto s: scheme) + for (const auto& s: scheme) { if (s.names().count(current_key)) { @@ -349,224 +357,35 @@ string OptionHelpItem(const OptionName& o) return out; } -// Stats module - -class SrtStatsJson : public SrtStatsWriter -{ -public: - string WriteStats(int sid, const CBytePerfMon& mon) override - { - std::ostringstream output; - output << "{"; - output << "\"sid\":" << sid << ","; - output << "\"time\":" << mon.msTimeStamp << ","; - output << "\"window\":{"; - output << "\"flow\":" << mon.pktFlowWindow << ","; - output << "\"congestion\":" << mon.pktCongestionWindow << ","; - output << "\"flight\":" << mon.pktFlightSize; - output << "},"; - output << "\"link\":{"; - output << "\"rtt\":" << mon.msRTT << ","; - output << "\"bandwidth\":" << mon.mbpsBandwidth << ","; - output << "\"maxBandwidth\":" << mon.mbpsMaxBW; - output << "},"; - output << "\"send\":{"; - output << "\"packets\":" << mon.pktSent << ","; - output << "\"packetsUnique\":" << mon.pktSentUnique << ","; - output << "\"packetsLost\":" << mon.pktSndLoss << ","; - output << "\"packetsDropped\":" << mon.pktSndDrop << ","; - output << "\"packetsRetransmitted\":" << mon.pktRetrans << ","; - output << "\"packetsFilterExtra\":" << mon.pktSndFilterExtra << ","; - output << "\"bytes\":" << mon.byteSent << ","; - output << "\"bytesUnique\":" << mon.byteSentUnique << ","; - output << "\"bytesDropped\":" << mon.byteSndDrop << ","; - output << "\"mbitRate\":" << mon.mbpsSendRate; - output << "},"; - output << "\"recv\": {"; - output << "\"packets\":" << mon.pktRecv << ","; - output << "\"packetsUnique\":" << mon.pktRecvUnique << ","; - output << "\"packetsLost\":" << mon.pktRcvLoss << ","; - output << "\"packetsDropped\":" << mon.pktRcvDrop << ","; - output << "\"packetsRetransmitted\":" << mon.pktRcvRetrans << ","; - output << "\"packetsBelated\":" << mon.pktRcvBelated << ","; - output << "\"packetsFilterExtra\":" << mon.pktRcvFilterExtra << ","; - output << "\"packetsFilterSupply\":" << mon.pktRcvFilterSupply << ","; - output << "\"packetsFilterLoss\":" << mon.pktRcvFilterLoss << ","; - output << "\"bytes\":" << mon.byteRecv << ","; - output << "\"bytesUnique\":" << mon.byteRecvUnique << ","; - output << "\"bytesLost\":" << mon.byteRcvLoss << ","; - output << "\"bytesDropped\":" << mon.byteRcvDrop << ","; - output << "\"mbitRate\":" << mon.mbpsRecvRate; - output << "}"; - output << "}" << endl; - return output.str(); - } - - string WriteBandwidth(double mbpsBandwidth) override - { - std::ostringstream output; - output << "{\"bandwidth\":" << mbpsBandwidth << '}' << endl; - return output.str(); - } -}; - -class SrtStatsCsv : public SrtStatsWriter -{ -private: - bool first_line_printed; - -public: - SrtStatsCsv() : first_line_printed(false) {} - - string WriteStats(int sid, const CBytePerfMon& mon) override - { - // Note: std::put_time is supported only in GCC 5 and higher -#if !defined(__GNUC__) || defined(__clang__) || (__GNUC__ >= 5) -#define HAS_PUT_TIME -#endif - std::ostringstream output; - if (!first_line_printed) - { -#ifdef HAS_PUT_TIME - output << "Timepoint,"; -#endif - output << "Time,SocketID,pktFlowWindow,pktCongestionWindow,pktFlightSize,"; - output << "msRTT,mbpsBandwidth,mbpsMaxBW,pktSent,pktSndLoss,pktSndDrop,"; - output << "pktRetrans,byteSent,byteSndDrop,mbpsSendRate,usPktSndPeriod,"; - output << "pktRecv,pktRcvLoss,pktRcvDrop,pktRcvRetrans,pktRcvBelated,"; - output << "byteRecv,byteRcvLoss,byteRcvDrop,mbpsRecvRate,RCVLATENCYms,"; - // Filter stats - output << "pktSndFilterExtra,pktRcvFilterExtra,pktRcvFilterSupply,pktRcvFilterLoss"; - output << endl; - first_line_printed = true; - } - int rcv_latency = 0; - int int_len = sizeof rcv_latency; - srt_getsockopt(sid, 0, SRTO_RCVLATENCY, &rcv_latency, &int_len); - -#ifdef HAS_PUT_TIME - // Follows ISO 8601 - auto print_timestamp = [&output]() { - using namespace std; - using namespace std::chrono; - - const auto systime_now = system_clock::now(); - const time_t time_now = system_clock::to_time_t(systime_now); - - // SysLocalTime returns zeroed tm_now on failure, which is ok for put_time. - const tm tm_now = SysLocalTime(time_now); - output << std::put_time(&tm_now, "%FT%T.") << std::setfill('0') << std::setw(6); - const auto since_epoch = systime_now.time_since_epoch(); - const seconds s = duration_cast(since_epoch); - output << duration_cast(since_epoch - s).count(); - output << std::put_time(&tm_now, "%z"); - output << ","; - }; - - print_timestamp(); -#endif // HAS_PUT_TIME - - output << mon.msTimeStamp << ","; - output << sid << ","; - output << mon.pktFlowWindow << ","; - output << mon.pktCongestionWindow << ","; - output << mon.pktFlightSize << ","; - output << mon.msRTT << ","; - output << mon.mbpsBandwidth << ","; - output << mon.mbpsMaxBW << ","; - output << mon.pktSent << ","; - output << mon.pktSndLoss << ","; - output << mon.pktSndDrop << ","; - output << mon.pktRetrans << ","; - output << mon.byteSent << ","; - output << mon.byteSndDrop << ","; - output << mon.mbpsSendRate << ","; - output << mon.usPktSndPeriod << ","; - output << mon.pktRecv << ","; - output << mon.pktRcvLoss << ","; - output << mon.pktRcvDrop << ","; - output << mon.pktRcvRetrans << ","; - output << mon.pktRcvBelated << ","; - output << mon.byteRecv << ","; - output << mon.byteRcvLoss << ","; - output << mon.byteRcvDrop << ","; - output << mon.mbpsRecvRate << ","; - output << rcv_latency << ","; - // Filter stats - output << mon.pktSndFilterExtra << ","; - output << mon.pktRcvFilterExtra << ","; - output << mon.pktRcvFilterSupply << ","; - output << mon.pktRcvFilterLoss; //<< ","; - output << endl; - return output.str(); - } - - string WriteBandwidth(double mbpsBandwidth) override - { - std::ostringstream output; - output << "+++/+++SRT BANDWIDTH: " << mbpsBandwidth << endl; - return output.str(); - } -}; - -class SrtStatsCols : public SrtStatsWriter +const char* SRTClockTypeStr() { -public: - string WriteStats(int sid, const CBytePerfMon& mon) override - { - std::ostringstream output; - output << "======= SRT STATS: sid=" << sid << endl; - output << "PACKETS SENT: " << setw(11) << mon.pktSent << " RECEIVED: " << setw(11) << mon.pktRecv << endl; - output << "LOST PKT SENT: " << setw(11) << mon.pktSndLoss << " RECEIVED: " << setw(11) << mon.pktRcvLoss << endl; - output << "REXMIT SENT: " << setw(11) << mon.pktRetrans << " RECEIVED: " << setw(11) << mon.pktRcvRetrans << endl; - output << "DROP PKT SENT: " << setw(11) << mon.pktSndDrop << " RECEIVED: " << setw(11) << mon.pktRcvDrop << endl; - output << "FILTER EXTRA TX: " << setw(11) << mon.pktSndFilterExtra << " RX: " << setw(11) << mon.pktRcvFilterExtra << endl; - output << "FILTER RX SUPPL: " << setw(11) << mon.pktRcvFilterSupply << " RX LOSS: " << setw(11) << mon.pktRcvFilterLoss << endl; - output << "RATE SENDING: " << setw(11) << mon.mbpsSendRate << " RECEIVING: " << setw(11) << mon.mbpsRecvRate << endl; - output << "BELATED RECEIVED: " << setw(11) << mon.pktRcvBelated << " AVG TIME: " << setw(11) << mon.pktRcvAvgBelatedTime << endl; - output << "REORDER DISTANCE: " << setw(11) << mon.pktReorderDistance << endl; - output << "WINDOW FLOW: " << setw(11) << mon.pktFlowWindow << " CONGESTION: " << setw(11) << mon.pktCongestionWindow << " FLIGHT: " << setw(11) << mon.pktFlightSize << endl; - output << "LINK RTT: " << setw(9) << mon.msRTT << "ms BANDWIDTH: " << setw(7) << mon.mbpsBandwidth << "Mb/s " << endl; - output << "BUFFERLEFT: SND: " << setw(11) << mon.byteAvailSndBuf << " RCV: " << setw(11) << mon.byteAvailRcvBuf << endl; - return output.str(); - } - - string WriteBandwidth(double mbpsBandwidth) override - { - std::ostringstream output; - output << "+++/+++SRT BANDWIDTH: " << mbpsBandwidth << endl; - return output.str(); - } -}; + const int clock_type = srt_clock_type(); -shared_ptr SrtStatsWriterFactory(SrtStatsPrintFormat printformat) -{ - switch (printformat) + switch (clock_type) { - case SRTSTATS_PROFMAT_JSON: - return make_shared(); - case SRTSTATS_PROFMAT_CSV: - return make_shared(); - case SRTSTATS_PROFMAT_2COLS: - return make_shared(); + case SRT_SYNC_CLOCK_STDCXX_STEADY: + return "CXX11_STEADY"; + case SRT_SYNC_CLOCK_GETTIME_MONOTONIC: + return "GETTIME_MONOTONIC"; + case SRT_SYNC_CLOCK_WINQPC: + return "WIN_QPC"; + case SRT_SYNC_CLOCK_MACH_ABSTIME: + return "MACH_ABSTIME"; + case SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY: + return "POSIX_GETTIMEOFDAY"; default: break; } - return nullptr; + + return "UNKNOWN VALUE"; } -SrtStatsPrintFormat ParsePrintFormat(string pf) +void PrintLibVersion() { - if (pf == "default") - return SRTSTATS_PROFMAT_2COLS; - - if (pf == "json") - return SRTSTATS_PROFMAT_JSON; - - if (pf == "csv") - return SRTSTATS_PROFMAT_CSV; - - return SRTSTATS_PROFMAT_INVALID; + cerr << "Built with SRT Library version: " << SRT_VERSION << endl; + const uint32_t srtver = srt_getversion(); + const int major = srtver / 0x10000; + const int minor = (srtver / 0x100) % 0x100; + const int patch = srtver % 0x100; + cerr << "SRT Library version: " << major << "." << minor << "." << patch << ", clock type: " << SRTClockTypeStr() << endl; } - - diff --git a/apps/apputil.hpp b/apps/apputil.hpp index 1c8f4a0bb..1a0b158e0 100644 --- a/apps/apputil.hpp +++ b/apps/apputil.hpp @@ -19,6 +19,8 @@ #include #include "netinet_any.h" +#include "utilities.h" +#include "srt.h" #if _WIN32 @@ -57,23 +59,51 @@ inline void SysCleanupNetwork() #include #include +// Fixes Android build on NDK r16b and earlier. +#if defined(__ANDROID__) && (__ANDROID__ == 1) + #include + #if !defined(__NDK_MAJOR__) || (__NDK_MAJOR__ <= 16) + struct ip_mreq_sourceFIXED { + struct in_addr imr_multiaddr; + struct in_addr imr_interface; + struct in_addr imr_sourceaddr; + }; + #define ip_mreq_source ip_mreq_sourceFIXED + #endif +#endif + // Nothing needs to be done on POSIX; this is a Windows problem. inline bool SysInitializeNetwork() {return true;} inline void SysCleanupNetwork() {} #endif -#include "srt.h" // Required for stats module - #ifdef _WIN32 inline int SysError() { return ::GetLastError(); } +const int SysAGAIN = WSAEWOULDBLOCK; #else inline int SysError() { return errno; } +const int SysAGAIN = EAGAIN; #endif -sockaddr_any CreateAddr(const std::string& name, unsigned short port = 0, int pref_family = AF_UNSPEC); +srt::sockaddr_any CreateAddr(const std::string& name, unsigned short port = 0, int pref_family = AF_UNSPEC); std::string Join(const std::vector& in, std::string sep); +template +struct OnReturnSetter +{ + VarType& var; + ValType value; + + OnReturnSetter(VarType& target, ValType v): var(target), value(v) {} + ~OnReturnSetter() { var = value; } +}; + +template +OnReturnSetter OnReturnSet(VarType& target, ValType v) +{ return OnReturnSetter(target, v); } + +// ---- OPTIONS MODULE inline bool CheckTrue(const std::vector& in) { @@ -181,15 +211,15 @@ struct OptionScheme enum Args { ARG_NONE, ARG_ONE, ARG_VAR } type; OptionScheme(const OptionScheme&) = default; - OptionScheme(OptionScheme&& src) - : pid(src.pid) - , type(src.type) - { - } + OptionScheme(OptionScheme&& src) + : pid(src.pid) + , type(src.type) + { + } OptionScheme(const OptionName& id, Args tp); - const std::set& names(); + const std::set& names() const; }; struct OptionName @@ -234,7 +264,7 @@ struct OptionName }; inline OptionScheme::OptionScheme(const OptionName& id, Args tp): pid(&id), type(tp) {} -inline const std::set& OptionScheme::names() { return pid->names; } +inline const std::set& OptionScheme::names() const { return pid->names; } template inline typename OutType::type Option(const options_t&, OutValue deflt=OutValue()) { return deflt; } @@ -304,27 +334,63 @@ inline bool OptionPresent(const options_t& options, const std::set& options_t ProcessOptions(char* const* argv, int argc, std::vector scheme); std::string OptionHelpItem(const OptionName& o); -// Statistics module +const char* SRTClockTypeStr(); +void PrintLibVersion(); -enum SrtStatsPrintFormat -{ - SRTSTATS_PROFMAT_INVALID = -1, - SRTSTATS_PROFMAT_2COLS = 0, - SRTSTATS_PROFMAT_JSON, - SRTSTATS_PROFMAT_CSV -}; -SrtStatsPrintFormat ParsePrintFormat(std::string pf); +namespace srt +{ -class SrtStatsWriter +struct OptionSetterProxy { -public: - virtual std::string WriteStats(int sid, const CBytePerfMon& mon) = 0; - virtual std::string WriteBandwidth(double mbpsBandwidth) = 0; - virtual ~SrtStatsWriter() { }; -}; + SRTSOCKET s; + int result = -1; + + OptionSetterProxy(SRTSOCKET ss): s(ss) {} + + struct OptionProxy + { + OptionSetterProxy& parent; + SRT_SOCKOPT opt; + +#define SPEC(type) \ + OptionProxy& operator=(const type& val)\ + {\ + parent.result = srt_setsockflag(parent.s, opt, &val, sizeof val);\ + return *this;\ + } + + SPEC(int32_t); + SPEC(int64_t); + SPEC(bool); +#undef SPEC + + template + OptionProxy& operator=(const char (&val)[N]) + { + parent.result = srt_setsockflag(parent.s, opt, val, N-1); + return *this; + } + + OptionProxy& operator=(const std::string& val) + { + parent.result = srt_setsockflag(parent.s, opt, val.c_str(), val.size()); + return *this; + } + }; + + OptionProxy operator[](SRT_SOCKOPT opt) + { + return OptionProxy {*this, opt}; + } -std::shared_ptr SrtStatsWriterFactory(SrtStatsPrintFormat printformat); + operator int() { return result; } +}; +inline OptionSetterProxy setopt(SRTSOCKET socket) +{ + return OptionSetterProxy(socket); +} +} #endif // INC_SRT_APPCOMMON_H diff --git a/apps/logsupport.cpp b/apps/logsupport.cpp index 2acbf64cc..fbd70c47e 100644 --- a/apps/logsupport.cpp +++ b/apps/logsupport.cpp @@ -171,4 +171,35 @@ set SrtParseLogFA(string fa, set* punknown) return fas; } +void ParseLogFASpec(const vector& speclist, string& w_on, string& w_off) +{ + std::ostringstream son, soff; + + for (auto& s: speclist) + { + string name; + bool on = true; + if (s[0] == '+') + name = s.substr(1); + else if (s[0] == '~') + { + name = s.substr(1); + on = false; + } + else + name = s; + + if (on) + son << "," << name; + else + soff << "," << name; + } + + const string& sons = son.str(); + const string& soffs = soff.str(); + + w_on = sons.empty() ? string() : sons.substr(1); + w_off = soffs.empty() ? string() : soffs.substr(1); +} + diff --git a/apps/logsupport.hpp b/apps/logsupport.hpp index 63e732560..79115d726 100644 --- a/apps/logsupport.hpp +++ b/apps/logsupport.hpp @@ -13,11 +13,13 @@ #include #include +#include #include "../srtcore/srt.h" #include "../srtcore/logging_api.h" srt_logging::LogLevel::type SrtParseLogLevel(std::string level); std::set SrtParseLogFA(std::string fa, std::set* punknown = nullptr); +void ParseLogFASpec(const std::vector& speclist, std::string& w_on, std::string& w_off); const std::map SrtLogFAList(); SRT_API extern std::map srt_level_names; diff --git a/apps/socketoptions.cpp b/apps/socketoptions.cpp index 31825ecb6..68df7291e 100644 --- a/apps/socketoptions.cpp +++ b/apps/socketoptions.cpp @@ -102,7 +102,7 @@ SocketOption::Mode SrtConfigurePre(SRTSOCKET socket, string host, map options, vector dummy; vector& fails = failures ? *failures : dummy; - for (auto o: srt_options) + for (const auto &o: srt_options) { if ( o.binding == SocketOption::POST && options.count(o.name) ) { diff --git a/apps/socketoptions.hpp b/apps/socketoptions.hpp index 6f6305b4c..b8aa67b86 100644 --- a/apps/socketoptions.hpp +++ b/apps/socketoptions.hpp @@ -70,7 +70,7 @@ inline int SocketOption::setso(int socket, int /*ignored return srt_setsockopt(socket, 0, SRT_SOCKOPT(sym), data, (int) size); } -#if ENABLE_EXPERIMENTAL_BONDING +#if ENABLE_BONDING template<> inline int SocketOption::setso(SRT_SOCKOPT_CONFIG* obj, int /*ignored*/, int sym, const void* data, size_t size) { @@ -211,7 +211,7 @@ extern const std::map enummap_transtype; namespace { const SocketOption srt_options [] { { "transtype", 0, SRTO_TRANSTYPE, SocketOption::PRE, SocketOption::ENUM, &enummap_transtype }, - { "maxbw", 0, SRTO_MAXBW, SocketOption::PRE, SocketOption::INT64, nullptr}, + { "maxbw", 0, SRTO_MAXBW, SocketOption::POST, SocketOption::INT64, nullptr}, { "pbkeylen", 0, SRTO_PBKEYLEN, SocketOption::PRE, SocketOption::INT, nullptr}, { "passphrase", 0, SRTO_PASSPHRASE, SocketOption::PRE, SocketOption::STRING, nullptr}, @@ -224,6 +224,7 @@ const SocketOption srt_options [] { { "ipttl", 0, SRTO_IPTTL, SocketOption::PRE, SocketOption::INT, nullptr}, { "iptos", 0, SRTO_IPTOS, SocketOption::PRE, SocketOption::INT, nullptr}, { "inputbw", 0, SRTO_INPUTBW, SocketOption::POST, SocketOption::INT64, nullptr}, + { "mininputbw", 0, SRTO_MININPUTBW, SocketOption::POST, SocketOption::INT64, nullptr}, { "oheadbw", 0, SRTO_OHEADBW, SocketOption::POST, SocketOption::INT, nullptr}, { "latency", 0, SRTO_LATENCY, SocketOption::PRE, SocketOption::INT, nullptr}, { "tsbpdmode", 0, SRTO_TSBPDMODE, SocketOption::PRE, SocketOption::BOOL, nullptr}, @@ -232,7 +233,7 @@ const SocketOption srt_options [] { { "nakreport", 0, SRTO_NAKREPORT, SocketOption::PRE, SocketOption::BOOL, nullptr}, { "conntimeo", 0, SRTO_CONNTIMEO, SocketOption::PRE, SocketOption::INT, nullptr}, { "drifttracer", 0, SRTO_DRIFTTRACER, SocketOption::POST, SocketOption::BOOL, nullptr}, - { "lossmaxttl", 0, SRTO_LOSSMAXTTL, SocketOption::PRE, SocketOption::INT, nullptr}, + { "lossmaxttl", 0, SRTO_LOSSMAXTTL, SocketOption::POST, SocketOption::INT, nullptr}, { "rcvlatency", 0, SRTO_RCVLATENCY, SocketOption::PRE, SocketOption::INT, nullptr}, { "peerlatency", 0, SRTO_PEERLATENCY, SocketOption::PRE, SocketOption::INT, nullptr}, { "minversion", 0, SRTO_MINVERSION, SocketOption::PRE, SocketOption::INT, nullptr}, @@ -246,16 +247,20 @@ const SocketOption srt_options [] { { "ipv6only", 0, SRTO_IPV6ONLY, SocketOption::PRE, SocketOption::INT, nullptr }, { "peeridletimeo", 0, SRTO_PEERIDLETIMEO, SocketOption::PRE, SocketOption::INT, nullptr }, { "packetfilter", 0, SRTO_PACKETFILTER, SocketOption::PRE, SocketOption::STRING, nullptr }, -#if ENABLE_EXPERIMENTAL_BONDING +#if ENABLE_BONDING { "groupconnect", 0, SRTO_GROUPCONNECT, SocketOption::PRE, SocketOption::INT, nullptr}, + { "groupminstabletimeo", 0, SRTO_GROUPMINSTABLETIMEO, SocketOption::PRE, SocketOption::INT, nullptr}, #endif #ifdef SRT_ENABLE_BINDTODEVICE { "bindtodevice", 0, SRTO_BINDTODEVICE, SocketOption::PRE, SocketOption::STRING, nullptr}, -#endif -#if ENABLE_EXPERIMENTAL_BONDING - { "groupstabtimeo", 0, SRTO_GROUPSTABTIMEO, SocketOption::PRE, SocketOption::INT, nullptr}, #endif { "retransmitalgo", 0, SRTO_RETRANSMITALGO, SocketOption::PRE, SocketOption::INT, nullptr } +#ifdef ENABLE_AEAD_API_PREVIEW + ,{ "cryptomode", 0, SRTO_CRYPTOMODE, SocketOption::PRE, SocketOption::INT, nullptr } +#endif +#ifdef ENABLE_MAXREXMITBW + ,{ "maxrexmitbw", 0, SRTO_MAXREXMITBW, SocketOption::POST, SocketOption::INT64, nullptr } +#endif }; } diff --git a/apps/srt-file-transmit.cpp b/apps/srt-file-transmit.cpp index 521060cb5..327ad6809 100644 --- a/apps/srt-file-transmit.cpp +++ b/apps/srt-file-transmit.cpp @@ -52,7 +52,6 @@ void OnINT_ForceExit(int) interrupt = true; } - struct FileTransmitConfig { unsigned long chunk_size; @@ -144,12 +143,7 @@ int parse_args(FileTransmitConfig &cfg, int argc, char** argv) if (print_help) { cout << "SRT sample application to transmit files.\n"; - cerr << "Built with SRT Library version: " << SRT_VERSION << endl; - const uint32_t srtver = srt_getversion(); - const int major = srtver / 0x10000; - const int minor = (srtver / 0x100) % 0x100; - const int patch = srtver % 0x100; - cerr << "SRT Library version: " << major << "." << minor << "." << patch << endl; + PrintLibVersion(); cerr << "Usage: srt-file-transmit [options] \n"; cerr << "\n"; @@ -182,7 +176,7 @@ int parse_args(FileTransmitConfig &cfg, int argc, char** argv) if (Option(params, false, o_version)) { - cerr << "SRT Library version: " << SRT_VERSION << endl; + PrintLibVersion(); return 2; } @@ -321,7 +315,7 @@ bool DoUpload(UriParser& ut, string path, string filename, << tar->GetSRTSocket() << endl; goto exit; } - UDT::setstreamid(tar->GetSRTSocket(), filename); + srt::setstreamid(tar->GetSRTSocket(), filename); } s = tar->GetSRTSocket(); @@ -449,7 +443,7 @@ bool DoUpload(UriParser& ut, string path, string filename, } Verb() << "Sending buffer still: bytes=" << bytes << " blocks=" << blocks; - this_thread::sleep_for(chrono::milliseconds(250)); + srt::sync::this_thread::sleep_for(srt::sync::milliseconds_from(250)); } } @@ -539,7 +533,7 @@ bool DoDownload(UriParser& us, string directory, string filename, cerr << "Failed to add SRT client to poll" << endl; goto exit; } - id = UDT::getstreamid(s); + id = srt::getstreamid(s); cerr << "Source connected (listener), id [" << id << "]" << endl; connected = true; @@ -550,14 +544,21 @@ bool DoDownload(UriParser& us, string directory, string filename, { if (!connected) { - id = UDT::getstreamid(s); + id = srt::getstreamid(s); cerr << "Source connected (caller), id [" << id << "]" << endl; connected = true; } } break; + + // No need to do any special action in case of broken. + // The app will just try to read and in worst case it will + // get an error. case SRTS_BROKEN: + cerr << "Connection closed, reading buffer remains\n"; + break; + case SRTS_NONEXIST: case SRTS_CLOSED: { @@ -601,7 +602,7 @@ bool DoDownload(UriParser& us, string directory, string filename, if (n == 0) { result = true; - cerr << "Download COMPLETE."; + cerr << "Download COMPLETE.\n"; break; } @@ -707,7 +708,7 @@ int main(int argc, char** argv) } else { - UDT::setlogstream(logfile_stream); + srt::setlogstream(logfile_stream); } } diff --git a/apps/srt-live-transmit.cpp b/apps/srt-live-transmit.cpp index b1ec637e9..0a918e6b0 100644 --- a/apps/srt-live-transmit.cpp +++ b/apps/srt-live-transmit.cpp @@ -65,7 +65,7 @@ #include #include - +#include "srt_compat.h" #include "apputil.hpp" // CreateAddr #include "uriparser.hpp" // UriParser #include "socketoptions.hpp" @@ -100,8 +100,8 @@ struct AlarmExit: public std::runtime_error } }; -volatile bool int_state = false; -volatile bool timer_state = false; +srt::sync::atomic int_state; +srt::sync::atomic timer_state; void OnINT_ForceExit(int) { Verb() << "\n-------- REQUESTED INTERRUPT!\n"; @@ -164,7 +164,6 @@ void PrintOptionHelp(const OptionName& opt_names, const string &value, const str cerr << "\t- " << desc << "\n"; } - int parse_args(LiveTransmitConfig &cfg, int argc, char** argv) { const OptionName @@ -269,12 +268,7 @@ int parse_args(LiveTransmitConfig &cfg, int argc, char** argv) } cout << "SRT sample application to transmit live streaming.\n"; - cerr << "Built with SRT Library version: " << SRT_VERSION << endl; - const uint32_t srtver = srt_getversion(); - const int major = srtver / 0x10000; - const int minor = (srtver / 0x100) % 0x100; - const int patch = srtver % 0x100; - cerr << "SRT Library version: " << major << "." << minor << "." << patch << endl; + PrintLibVersion(); cerr << "Usage: srt-live-transmit [options] \n"; cerr << "\n"; #ifndef _WIN32 @@ -290,7 +284,7 @@ int parse_args(LiveTransmitConfig &cfg, int argc, char** argv) PrintOptionHelp(o_statsout, "", "output stats to file"); PrintOptionHelp(o_statspf, "", "stats printing format {json, csv, default}"); PrintOptionHelp(o_statsfull, "", "full counters in stats-report (prints total statistics)"); - PrintOptionHelp(o_loglevel, "", "log level {fatal,error,info,note,warning}"); + PrintOptionHelp(o_loglevel, "", "log level {fatal,error,warn,note,info,debug}"); PrintOptionHelp(o_logfa, "", "log functional area (see '-h logging' for more info)"); //PrintOptionHelp(o_log_internal, "", "use internal logger"); PrintOptionHelp(o_logfile, "", "write logs to file"); @@ -313,7 +307,7 @@ int parse_args(LiveTransmitConfig &cfg, int argc, char** argv) if (print_version) { - cerr << "SRT Library version: " << SRT_VERSION << endl; + PrintLibVersion(); return 2; } @@ -335,7 +329,8 @@ int parse_args(LiveTransmitConfig &cfg, int argc, char** argv) cfg.stats_report = Option(params, o_statsrep); cfg.stats_out = Option(params, o_statsout); const string pf = Option(params, "default", o_statspf); - cfg.stats_pf = ParsePrintFormat(pf); + string pfext; + cfg.stats_pf = ParsePrintFormat(pf, (pfext)); if (cfg.stats_pf == SRTSTATS_PROFMAT_INVALID) { cfg.stats_pf = SRTSTATS_PROFMAT_2COLS; @@ -344,7 +339,7 @@ int parse_args(LiveTransmitConfig &cfg, int argc, char** argv) } cfg.full_stats = OptionPresent(params, o_statsfull); - cfg.loglevel = SrtParseLogLevel(Option(params, "error", o_loglevel)); + cfg.loglevel = SrtParseLogLevel(Option(params, "warn", o_loglevel)); cfg.logfas = SrtParseLogFA(Option(params, "", o_logfa)); cfg.log_internal = OptionPresent(params, o_log_internal); cfg.logfile = Option(params, o_logfile); @@ -433,7 +428,7 @@ int main(int argc, char** argv) } else { - UDT::setlogstream(logfile_stream); + srt::setlogstream(logfile_stream); } } @@ -531,11 +526,13 @@ int main(int argc, char** argv) } break; case UriParser::UDP: + case UriParser::RTP: if (srt_epoll_add_ssock(pollid, src->GetSysSocket(), &events)) { - cerr << "Failed to add UDP source to poll, " - << src->GetSysSocket() << endl; + cerr << "Failed to add " << src->uri.proto() + << " source to poll, " << src->GetSysSocket() + << endl; return 1; } break; @@ -857,8 +854,14 @@ int main(int argc, char** argv) void TestLogHandler(void* opaque, int level, const char* file, int line, const char* area, const char* message) { char prefix[100] = ""; - if ( opaque ) - strncpy(prefix, (char*)opaque, 99); + if ( opaque ) { +#ifdef _MSC_VER + strncpy_s(prefix, sizeof(prefix), (char*)opaque, _TRUNCATE); +#else + strncpy(prefix, (char*)opaque, sizeof(prefix) - 1); + prefix[sizeof(prefix) - 1] = '\0'; +#endif + } time_t now; time(&now); char buf[1024]; diff --git a/apps/srt-tunnel.cpp b/apps/srt-tunnel.cpp index 0567b5764..90bd43eae 100644 --- a/apps/srt-tunnel.cpp +++ b/apps/srt-tunnel.cpp @@ -27,6 +27,7 @@ #include #include +#include "srt_compat.h" #include "apputil.hpp" // CreateAddr #include "uriparser.hpp" // UriParser #include "socketoptions.hpp" @@ -59,6 +60,7 @@ testmedia.cpp */ using namespace std; +using namespace srt; const srt_logging::LogFA SRT_LOGFA_APP = 10; namespace srt_logging @@ -94,7 +96,7 @@ class Medium bool m_eof = false; bool m_broken = false; - mutex access; // For closing + std::mutex access; // For closing template static Medium* CreateAcceptor(DerivedMedium* self, const sockaddr_any& sa, SocketType sock, size_t chunk) @@ -223,25 +225,25 @@ class Engine Engine(Tunnel* p, Medium* m1, Medium* m2, const std::string& nid) : #ifdef HAVE_FULL_CXX11 - media {m1, m2}, + media {m1, m2}, #endif - parent_tunnel(p), nameid(nid) + parent_tunnel(p), nameid(nid) { #ifndef HAVE_FULL_CXX11 - // MSVC is not exactly C++11 compliant and complains around - // initialization of an array. - // Leaving this method of initialization for clarity and - // possibly more preferred performance. - media[0] = m1; - media[1] = m2; + // MSVC is not exactly C++11 compliant and complains around + // initialization of an array. + // Leaving this method of initialization for clarity and + // possibly more preferred performance. + media[0] = m1; + media[1] = m2; #endif } void Start() { Verb() << "START: " << media[DIR_IN]->uri() << " --> " << media[DIR_OUT]->uri(); - std::string thrn = media[DIR_IN]->id() + ">" + media[DIR_OUT]->id(); - ThreadName tn(thrn.c_str()); + const std::string thrn = media[DIR_IN]->id() + ">" + media[DIR_OUT]->id(); + srt::ThreadName tn(thrn); thr = thread([this]() { Worker(); }); } @@ -286,8 +288,8 @@ class Tunnel Tunnelbox* parent_box; std::unique_ptr med_acp, med_clr; Engine acp_to_clr, clr_to_acp; - volatile bool running = true; - mutex access; + srt::sync::atomic running{true}; + std::mutex access; public: @@ -298,7 +300,7 @@ class Tunnel Tunnel(Tunnelbox* m, std::unique_ptr&& acp, std::unique_ptr&& clr): parent_box(m), - med_acp(move(acp)), med_clr(move(clr)), + med_acp(std::move(acp)), med_clr(std::move(clr)), acp_to_clr(this, med_acp.get(), med_clr.get(), med_acp->id() + ">" + med_clr->id()), clr_to_acp(this, med_clr.get(), med_acp.get(), med_clr->id() + ">" + med_acp->id()) { @@ -324,7 +326,7 @@ class Tunnel /* { - lock_guard lk(access); + lock_guard lk(access); if (acp_to_clr.stat() == -1 && clr_to_acp.stat() == -1) { Verb() << "Tunnel: Both engine decommissioned, will stop the tunnel."; @@ -438,7 +440,7 @@ class SrtMedium: public Medium void CloseSrt() { Verb() << "Closing SRT socket for " << uri(); - lock_guard lk(access); + lock_guard lk(access); if (m_socket == SRT_ERROR) return; srt_close(m_socket); @@ -528,7 +530,7 @@ class TcpMedium: public Medium void CloseTcp() { Verb() << "Closing TCP socket for " << uri(); - lock_guard lk(access); + lock_guard lk(access); if (m_socket == -1) return; tcp_close(m_socket); @@ -648,7 +650,7 @@ void TcpMedium::CreateListener() sockaddr_any sa = CreateAddr(m_uri.host(), m_uri.portno()); - m_socket = socket(sa.get()->sa_family, SOCK_STREAM, IPPROTO_TCP); + m_socket = (int)socket(sa.get()->sa_family, SOCK_STREAM, IPPROTO_TCP); ConfigurePre(); int stat = ::bind(m_socket, sa.get(), sa.size()); @@ -693,7 +695,7 @@ unique_ptr SrtMedium::Accept() unique_ptr TcpMedium::Accept() { sockaddr_any sa; - int s = ::accept(m_socket, (sa.get()), (&sa.syslen())); + int s = (int)::accept(m_socket, (sa.get()), (&sa.syslen())); if (s == -1) { Error(errno, "accept"); @@ -701,10 +703,10 @@ unique_ptr TcpMedium::Accept() // Configure 1s timeout timeval timeout_1s { 1, 0 }; - int st = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout_1s, sizeof timeout_1s); + int st SRT_ATR_UNUSED = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout_1s, sizeof timeout_1s); timeval re; socklen_t size = sizeof re; - int st2 = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&re, &size); + int st2 SRT_ATR_UNUSED = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&re, &size); LOGP(applog.Debug, "Setting SO_RCVTIMEO to @", m_socket, ": ", st == -1 ? "FAILED" : "SUCCEEDED", ", read-back value: ", st2 == -1 ? int64_t(-1) : (int64_t(re.tv_sec)*1000000 + re.tv_usec)/1000, "ms"); @@ -725,7 +727,7 @@ void SrtMedium::CreateCaller() void TcpMedium::CreateCaller() { - m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + m_socket = (int)::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ConfigurePre(); } @@ -849,7 +851,7 @@ Medium::ReadStatus Medium::Read(bytevector& w_output) size_t pred_size = shift + m_chunk; w_output.resize(pred_size); - int st = ReadInternal((w_output.data() + shift), m_chunk); + int st = ReadInternal((w_output.data() + shift), (int)m_chunk); if (st == -1) { if (IsErrorAgain()) @@ -883,7 +885,7 @@ Medium::ReadStatus Medium::Read(bytevector& w_output) void SrtMedium::Write(bytevector& w_buffer) { - int st = srt_send(m_socket, w_buffer.data(), w_buffer.size()); + int st = srt_send(m_socket, w_buffer.data(), (int)w_buffer.size()); if (st == SRT_ERROR) { Error(UDT::getlasterror(), "srt_send"); @@ -906,7 +908,7 @@ void SrtMedium::Write(bytevector& w_buffer) void TcpMedium::Write(bytevector& w_buffer) { - int st = ::send(m_socket, w_buffer.data(), w_buffer.size(), DEF_SEND_FLAG); + int st = ::send(m_socket, w_buffer.data(), (int)w_buffer.size(), DEF_SEND_FLAG); if (st == -1) { Error(errno, "send"); @@ -954,23 +956,23 @@ std::unique_ptr Medium::Create(const std::string& url, size_t chunk, Med struct Tunnelbox { list> tunnels; - mutex access; + std::mutex access; condition_variable decom_ready; bool main_running = true; thread thr; void signal_decommission() { - lock_guard lk(access); + lock_guard lk(access); decom_ready.notify_one(); } void install(std::unique_ptr&& acp, std::unique_ptr&& clr) { - lock_guard lk(access); + lock_guard lk(access); Verb() << "Tunnelbox: Starting tunnel: " << acp->uri() << " <-> " << clr->uri(); - tunnels.emplace_back(new Tunnel(this, move(acp), move(clr))); + tunnels.emplace_back(new Tunnel(this, std::move(acp), std::move(clr))); // Note: after this instruction, acp and clr are no longer valid! auto& it = tunnels.back(); @@ -992,7 +994,7 @@ struct Tunnelbox void CleanupWorker() { - unique_lock lk(access); + unique_lock lk(access); while (main_running) { @@ -1027,7 +1029,7 @@ void Tunnel::Stop() if (!running) return; // already stopped - lock_guard lk(access); + lock_guard lk(access); // Ok, you are the first to make the tunnel // not running and inform the tunnelbox. @@ -1037,7 +1039,7 @@ void Tunnel::Stop() bool Tunnel::decommission_if_dead(bool forced) { - lock_guard lk(access); + lock_guard lk(access); if (running && !forced) return false; // working, not to be decommissioned @@ -1115,21 +1117,21 @@ int main( int argc, char** argv ) string loglevel = Option(params, "error", o_loglevel); string logfa = Option(params, "", o_logfa); srt_logging::LogLevel::type lev = SrtParseLogLevel(loglevel); - UDT::setloglevel(lev); + srt::setloglevel(lev); if (logfa == "") { - UDT::addlogfa(SRT_LOGFA_APP); + srt::addlogfa(SRT_LOGFA_APP); } else { // Add only selected FAs set unknown_fas; set fas = SrtParseLogFA(logfa, &unknown_fas); - UDT::resetlogfa(fas); + srt::resetlogfa(fas); // The general parser doesn't recognize the "app" FA, we check it here. if (unknown_fas.count("app")) - UDT::addlogfa(SRT_LOGFA_APP); + srt::addlogfa(SRT_LOGFA_APP); } string verbo = Option(params, "no", o_verbose); @@ -1190,7 +1192,7 @@ int main( int argc, char** argv ) Verb() << "Connected. Establishing pipe."; // No exception, we are free to pass :) - g_tunnels.install(move(accepted), move(caller)); + g_tunnels.install(std::move(accepted), std::move(caller)); } catch (...) { diff --git a/apps/statswriter.cpp b/apps/statswriter.cpp new file mode 100644 index 000000000..f1aa343b5 --- /dev/null +++ b/apps/statswriter.cpp @@ -0,0 +1,351 @@ +/* + * 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/. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "statswriter.hpp" +#include "netinet_any.h" +#include "srt_compat.h" + + +using namespace std; + + +template +inline SrtStatData* make_stat(SrtStatCat cat, const string& name, const string& longname, + TYPE CBytePerfMon::*field) +{ + return new SrtStatDataType(cat, name, longname, field); +} + +#define STATX(catsuf, sname, lname, field) s.emplace_back(make_stat(SSC_##catsuf, #sname, #lname, &CBytePerfMon:: field)) +#define STAT(catsuf, sname, field) STATX(catsuf, sname, field, field) + +vector> g_SrtStatsTable; + +struct SrtStatsTableInit +{ + SrtStatsTableInit(vector>& s) + { + STATX(GEN, time, Time, msTimeStamp); + + STAT(WINDOW, flow, pktFlowWindow); + STAT(WINDOW, congestion, pktCongestionWindow); + STAT(WINDOW, flight, pktFlightSize); + + STAT(LINK, rtt, msRTT); + STAT(LINK, bandwidth, mbpsBandwidth); + STAT(LINK, maxBandwidth, mbpsMaxBW); + + STAT(SEND, packets, pktSent); + STAT(SEND, packetsUnique, pktSentUnique); + STAT(SEND, packetsLost, pktSndLoss); + STAT(SEND, packetsDropped, pktSndDrop); + STAT(SEND, packetsRetransmitted, pktRetrans); + STAT(SEND, packetsFilterExtra, pktSndFilterExtra); + STAT(SEND, bytes, byteSent); + STAT(SEND, bytesUnique, byteSentUnique); + STAT(SEND, bytesDropped, byteSndDrop); + STAT(SEND, byteAvailBuf, byteAvailSndBuf); + STAT(SEND, msBuf, msSndBuf); + STAT(SEND, mbitRate, mbpsSendRate); + STAT(SEND, sendPeriod, usPktSndPeriod); + + STAT(RECV, packets, pktRecv); + STAT(RECV, packetsUnique, pktRecvUnique); + STAT(RECV, packetsLost, pktRcvLoss); + STAT(RECV, packetsDropped, pktRcvDrop); + STAT(RECV, packetsRetransmitted, pktRcvRetrans); + STAT(RECV, packetsBelated, pktRcvBelated); + STAT(RECV, packetsFilterExtra, pktRcvFilterExtra); + STAT(RECV, packetsFilterSupply, pktRcvFilterSupply); + STAT(RECV, packetsFilterLoss, pktRcvFilterLoss); + STAT(RECV, bytes, byteRecv); + STAT(RECV, bytesUnique, byteRecvUnique); + STAT(RECV, bytesLost, byteRcvLoss); + STAT(RECV, bytesDropped, byteRcvDrop); + STAT(RECV, byteAvailBuf, byteAvailRcvBuf); + STAT(RECV, msBuf, msRcvBuf); + STAT(RECV, mbitRate, mbpsRecvRate); + STAT(RECV, msTsbPdDelay, msRcvTsbPdDelay); + } +} g_SrtStatsTableInit (g_SrtStatsTable); + + +#undef STAT +#undef STATX + +string srt_json_cat_names [] = { + "", + "window", + "link", + "send", + "recv" +}; + +#ifdef HAVE_CXX_STD_PUT_TIME +// Follows ISO 8601 +std::string SrtStatsWriter::print_timestamp() +{ + using namespace std; + using namespace std::chrono; + + const auto systime_now = system_clock::now(); + const time_t time_now = system_clock::to_time_t(systime_now); + + std::ostringstream output; + + // SysLocalTime returns zeroed tm_now on failure, which is ok for put_time. + const tm tm_now = SysLocalTime(time_now); + output << std::put_time(&tm_now, "%FT%T.") << std::setfill('0') << std::setw(6); + const auto since_epoch = systime_now.time_since_epoch(); + const seconds s = duration_cast(since_epoch); + output << duration_cast(since_epoch - s).count(); + output << std::put_time(&tm_now, "%z"); + return output.str(); +} +#else + +// This is a stub. The error when not defining it would be too +// misleading, so this stub will work if someone mistakenly adds +// the item to the output format without checking that HAVE_CXX_STD_PUT_TIME +string SrtStatsWriter::print_timestamp() +{ return ""; } +#endif // HAVE_CXX_STD_PUT_TIME + + +class SrtStatsJson : public SrtStatsWriter +{ + static string quotekey(const string& name) + { + if (name == "") + return ""; + + return R"(")" + name + R"(":)"; + } + + static string quote(const string& name) + { + if (name == "") + return ""; + + return R"(")" + name + R"(")"; + } + +public: + string WriteStats(int sid, const CBytePerfMon& mon) override + { + std::ostringstream output; + + string pretty_cr, pretty_tab; + if (Option("pretty")) + { + pretty_cr = "\n"; + pretty_tab = "\t"; + } + + SrtStatCat cat = SSC_GEN; + + // Do general manually + output << quotekey(srt_json_cat_names[cat]) << "{" << pretty_cr; + + // SID is displayed manually + output << pretty_tab << quotekey("sid") << sid; + + // Extra Timepoint is also displayed manually +#ifdef HAVE_CXX_STD_PUT_TIME + // NOTE: still assumed SSC_GEN category + output << "," << pretty_cr << pretty_tab + << quotekey("timepoint") << quote(print_timestamp()); +#endif + + // Now continue with fields as specified in the table + for (auto& i: g_SrtStatsTable) + { + if (i->category == cat) + { + output << ","; // next item in same cat + output << pretty_cr; + output << pretty_tab; + if (cat != SSC_GEN) + output << pretty_tab; + } + else + { + if (cat != SSC_GEN) + { + // DO NOT close if general category, just + // enter the depth. + output << pretty_cr << pretty_tab << "}"; + } + cat = i->category; + output << ","; + output << pretty_cr; + if (cat != SSC_GEN) + output << pretty_tab; + + output << quotekey(srt_json_cat_names[cat]) << "{" << pretty_cr << pretty_tab; + if (cat != SSC_GEN) + output << pretty_tab; + } + + // Print the current field + output << quotekey(i->name); + i->PrintValue(output, mon); + } + + // Close the previous subcategory + if (cat != SSC_GEN) + { + output << pretty_cr << pretty_tab << "}" << pretty_cr; + } + + // Close the general category entity + output << "}" << pretty_cr << endl; + + return output.str(); + } + + string WriteBandwidth(double mbpsBandwidth) override + { + std::ostringstream output; + output << "{\"bandwidth\":" << mbpsBandwidth << '}' << endl; + return output.str(); + } +}; + +class SrtStatsCsv : public SrtStatsWriter +{ +private: + bool first_line_printed; + +public: + SrtStatsCsv() : first_line_printed(false) {} + + string WriteStats(int sid, const CBytePerfMon& mon) override + { + std::ostringstream output; + + // Header + if (!first_line_printed) + { +#ifdef HAVE_CXX_STD_PUT_TIME + output << "Timepoint,"; +#endif + output << "Time,SocketID"; + + for (auto& i: g_SrtStatsTable) + { + output << "," << i->longname; + } + output << endl; + first_line_printed = true; + } + + // Values +#ifdef HAVE_CXX_STD_PUT_TIME + // HDR: Timepoint + output << print_timestamp() << ","; +#endif // HAVE_CXX_STD_PUT_TIME + + // HDR: Time,SocketID + output << mon.msTimeStamp << "," << sid; + + // HDR: the loop of all values in g_SrtStatsTable + for (auto& i: g_SrtStatsTable) + { + output << ","; + i->PrintValue(output, mon); + } + + output << endl; + return output.str(); + } + + string WriteBandwidth(double mbpsBandwidth) override + { + std::ostringstream output; + output << "+++/+++SRT BANDWIDTH: " << mbpsBandwidth << endl; + return output.str(); + } +}; + +class SrtStatsCols : public SrtStatsWriter +{ +public: + string WriteStats(int sid, const CBytePerfMon& mon) override + { + std::ostringstream output; + output << "======= SRT STATS: sid=" << sid << endl; + output << "PACKETS SENT: " << setw(11) << mon.pktSent << " RECEIVED: " << setw(11) << mon.pktRecv << endl; + output << "LOST PKT SENT: " << setw(11) << mon.pktSndLoss << " RECEIVED: " << setw(11) << mon.pktRcvLoss << endl; + output << "REXMIT SENT: " << setw(11) << mon.pktRetrans << " RECEIVED: " << setw(11) << mon.pktRcvRetrans << endl; + output << "DROP PKT SENT: " << setw(11) << mon.pktSndDrop << " RECEIVED: " << setw(11) << mon.pktRcvDrop << endl; + output << "FILTER EXTRA TX: " << setw(11) << mon.pktSndFilterExtra << " RX: " << setw(11) << mon.pktRcvFilterExtra << endl; + output << "FILTER RX SUPPL: " << setw(11) << mon.pktRcvFilterSupply << " RX LOSS: " << setw(11) << mon.pktRcvFilterLoss << endl; + output << "RATE SENDING: " << setw(11) << mon.mbpsSendRate << " RECEIVING: " << setw(11) << mon.mbpsRecvRate << endl; + output << "BELATED RECEIVED: " << setw(11) << mon.pktRcvBelated << " AVG TIME: " << setw(11) << mon.pktRcvAvgBelatedTime << endl; + output << "REORDER DISTANCE: " << setw(11) << mon.pktReorderDistance << endl; + output << "WINDOW FLOW: " << setw(11) << mon.pktFlowWindow << " CONGESTION: " << setw(11) << mon.pktCongestionWindow << " FLIGHT: " << setw(11) << mon.pktFlightSize << endl; + output << "LINK RTT: " << setw(9) << mon.msRTT << "ms BANDWIDTH: " << setw(7) << mon.mbpsBandwidth << "Mb/s " << endl; + output << "BUFFERLEFT: SND: " << setw(11) << mon.byteAvailSndBuf << " RCV: " << setw(11) << mon.byteAvailRcvBuf << endl; + return output.str(); + } + + string WriteBandwidth(double mbpsBandwidth) override + { + std::ostringstream output; + output << "+++/+++SRT BANDWIDTH: " << mbpsBandwidth << endl; + return output.str(); + } +}; + +shared_ptr SrtStatsWriterFactory(SrtStatsPrintFormat printformat) +{ + switch (printformat) + { + case SRTSTATS_PROFMAT_JSON: + return make_shared(); + case SRTSTATS_PROFMAT_CSV: + return make_shared(); + case SRTSTATS_PROFMAT_2COLS: + return make_shared(); + default: + break; + } + return nullptr; +} + +SrtStatsPrintFormat ParsePrintFormat(string pf, string& w_extras) +{ + size_t havecomma = pf.find(','); + if (havecomma != string::npos) + { + w_extras = pf.substr(havecomma+1); + pf = pf.substr(0, havecomma); + } + + if (pf == "default") + return SRTSTATS_PROFMAT_2COLS; + + if (pf == "json") + return SRTSTATS_PROFMAT_JSON; + + if (pf == "csv") + return SRTSTATS_PROFMAT_CSV; + + return SRTSTATS_PROFMAT_INVALID; +} diff --git a/apps/statswriter.hpp b/apps/statswriter.hpp new file mode 100644 index 000000000..1b4fd4fbc --- /dev/null +++ b/apps/statswriter.hpp @@ -0,0 +1,107 @@ +/* + * 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/. + * + */ + + +#ifndef INC_SRT_APPS_STATSWRITER_H +#define INC_SRT_APPS_STATSWRITER_H + +#include +#include +#include +#include + +#include "srt.h" +#include "utilities.h" + +enum SrtStatsPrintFormat +{ + SRTSTATS_PROFMAT_INVALID = -1, + SRTSTATS_PROFMAT_2COLS = 0, + SRTSTATS_PROFMAT_JSON, + SRTSTATS_PROFMAT_CSV +}; + +SrtStatsPrintFormat ParsePrintFormat(std::string pf, std::string& w_extras); + +enum SrtStatCat +{ + SSC_GEN, //< General + SSC_WINDOW, // flow/congestion window + SSC_LINK, //< Link data + SSC_SEND, //< Sending + SSC_RECV //< Receiving +}; + +struct SrtStatData +{ + SrtStatCat category; + std::string name; + std::string longname; + + SrtStatData(SrtStatCat cat, std::string n, std::string l): category(cat), name(n), longname(l) {} + virtual ~SrtStatData() {} + + virtual void PrintValue(std::ostream& str, const CBytePerfMon& mon) = 0; +}; + +template +struct SrtStatDataType: public SrtStatData +{ + typedef TYPE CBytePerfMon::*pfield_t; + pfield_t pfield; + + SrtStatDataType(SrtStatCat cat, const std::string& name, const std::string& longname, pfield_t field) + : SrtStatData (cat, name, longname), pfield(field) + { + } + + void PrintValue(std::ostream& str, const CBytePerfMon& mon) override + { + str << mon.*pfield; + } +}; + +class SrtStatsWriter +{ +public: + virtual std::string WriteStats(int sid, const CBytePerfMon& mon) = 0; + virtual std::string WriteBandwidth(double mbpsBandwidth) = 0; + virtual ~SrtStatsWriter() {} + + // Only if HAS_PUT_TIME. Specified in the imp file. + std::string print_timestamp(); + + void Option(const std::string& key, const std::string& val) + { + options[key] = val; + } + + bool Option(const std::string& key, std::string* rval = nullptr) + { + const std::string* out = map_getp(options, key); + if (!out) + return false; + + if (rval) + *rval = *out; + return true; + } + +protected: + std::map options; +}; + +extern std::vector> g_SrtStatsTable; + +std::shared_ptr SrtStatsWriterFactory(SrtStatsPrintFormat printformat); + + + +#endif diff --git a/apps/support.maf b/apps/support.maf index 19ac894b4..e5aa77b8e 100644 --- a/apps/support.maf +++ b/apps/support.maf @@ -9,6 +9,7 @@ SOURCES apputil.cpp +statswriter.cpp logsupport.cpp logsupport_appdefs.cpp socketoptions.cpp diff --git a/apps/transmitbase.hpp b/apps/transmitbase.hpp index 3b3c7d0b9..bd0af916d 100644 --- a/apps/transmitbase.hpp +++ b/apps/transmitbase.hpp @@ -19,11 +19,11 @@ #include "srt.h" #include "uriparser.hpp" #include "apputil.hpp" +#include "statswriter.hpp" typedef std::vector bytevector; extern bool transmit_total_stats; extern bool g_stats_are_printed_to_stdout; -extern volatile bool transmit_throw_on_interrupt; extern unsigned long transmit_bw_report; extern unsigned long transmit_stats_report; extern unsigned long transmit_chunk_size; @@ -69,8 +69,8 @@ class Source: public Location } }; - virtual SRTSOCKET GetSRTSocket() const { return SRT_INVALID_SOCK; }; - virtual int GetSysSocket() const { return -1; }; + virtual SRTSOCKET GetSRTSocket() const { return SRT_INVALID_SOCK; } + virtual int GetSysSocket() const { return -1; } virtual bool AcceptNewClient() { return false; } }; diff --git a/apps/transmitmedia.cpp b/apps/transmitmedia.cpp index 7ab167c9f..275295173 100644 --- a/apps/transmitmedia.cpp +++ b/apps/transmitmedia.cpp @@ -22,9 +22,12 @@ #if !defined(_WIN32) #include #else -#include +#include #include #endif +#if defined(SUNOS) +#include +#endif #include "netinet_any.h" #include "apputil.hpp" @@ -35,6 +38,7 @@ #include "verbose.hpp" using namespace std; +using namespace srt; bool g_stats_are_printed_to_stdout = false; bool transmit_total_stats = false; @@ -117,6 +121,24 @@ void SrtCommon::InitParameters(string host, map par) } } + if (par.count("bind")) + { + string bindspec = par.at("bind"); + UriParser u (bindspec, UriParser::EXPECT_HOST); + if ( u.scheme() != "" + || u.path() != "" + || !u.parameters().empty() + || u.portno() == 0) + { + Error("Invalid syntax in 'bind' option"); + } + + if (u.host() != "") + par["adapter"] = u.host(); + par["port"] = u.port(); + par.erase("bind"); + } + string adapter; if (par.count("adapter")) { @@ -302,7 +324,7 @@ int SrtCommon::ConfigurePost(SRTSOCKET sock) SrtConfigurePost(sock, m_options); - for (auto o: srt_options) + for (const auto &o: srt_options) { if ( o.binding == SocketOption::POST && m_options.count(o.name) ) { @@ -374,9 +396,9 @@ void SrtCommon::OpenClient(string host, int port) { PrepareClient(); - if ( m_outgoing_port ) + if (m_outgoing_port || m_adapter != "") { - SetupAdapter("", m_outgoing_port); + SetupAdapter(m_adapter, m_outgoing_port); } ConnectClient(host, port); @@ -398,7 +420,7 @@ void SrtCommon::ConnectClient(string host, int port) { sockaddr_any sa = CreateAddr(host, port); - sockaddr* psa = sa.get(); + sockaddr* psa = sa.get(); Verb() << "Connecting to " << host << ":" << port; @@ -624,7 +646,7 @@ void SrtModel::Establish(std::string& w_name) if (w_name != "") { Verb() << "Connect with requesting stream [" << w_name << "]"; - UDT::setstreamid(m_sock, w_name); + srt::setstreamid(m_sock, w_name); } else { @@ -667,7 +689,7 @@ void SrtModel::Establish(std::string& w_name) Verb() << "Accepting a client..."; AcceptNewClient(); // This rewrites m_sock with a new SRT socket ("accepted" socket) - w_name = UDT::getstreamid(m_sock); + w_name = srt::getstreamid(m_sock); Verb() << "... GOT CLIENT for stream [" << w_name << "]"; } } @@ -783,7 +805,7 @@ class UdpCommon void Setup(string host, int port, map attr) { - m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + m_sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (m_sock == -1) Error(SysError(), "UdpCommon::Setup: socket"); @@ -826,7 +848,6 @@ class UdpCommon if (is_multicast) { - ip_mreq_source mreq_ssm; ip_mreq mreq; sockaddr_any maddr (AF_INET); int opt_name; @@ -850,6 +871,7 @@ class UdpCommon if (attr.count("source")) { #ifdef IP_ADD_SOURCE_MEMBERSHIP + ip_mreq_source mreq_ssm; /* this is an ssm. we need to use the right struct and opt */ opt_name = IP_ADD_SOURCE_MEMBERSHIP; mreq_ssm.imr_multiaddr.s_addr = sadr.sin.sin_addr.s_addr; @@ -963,6 +985,7 @@ class UdpCommon class UdpSource: public Source, public UdpCommon { +protected: bool eof = true; public: @@ -1012,6 +1035,9 @@ class UdpTarget: public Target, public UdpCommon public: UdpTarget(string host, int port, const map& attr ) { + if (host.empty()) + cerr << "\nWARN Host for UDP target is not provided. Will send to localhost:" << port << ".\n"; + Setup(host, port, attr); if (adapter != "") { @@ -1057,6 +1083,74 @@ template <> struct Udp { typedef UdpTarget type; }; template Iface* CreateUdp(const string& host, int port, const map& par) { return new typename Udp::type (host, port, par); } +class RtpSource: public UdpSource +{ + // for now, make no effort to parse the header, just assume it is always + // fixed length and either a user-configurable value, or twelve bytes. + const int MINIMUM_RTP_HEADER_SIZE = 12; + int bytes_to_skip = MINIMUM_RTP_HEADER_SIZE; +public: + RtpSource(string host, int port, const map& attr) : + UdpSource { host, port, attr } + { + if (attr.count("rtpheadersize")) + { + const int header_size = stoi(attr.at("rtpheadersize"), 0, 0); + if (header_size < MINIMUM_RTP_HEADER_SIZE) + { + cerr << "Invalid RTP header size provided: " << header_size + << ", minimum allowed is " << MINIMUM_RTP_HEADER_SIZE + << endl; + throw invalid_argument("Invalid RTP header size"); + } + bytes_to_skip = header_size; + } + } + + int Read(size_t chunk, MediaPacket& pkt, ostream & ignored SRT_ATR_UNUSED = cout) override + { + const int length = UdpSource::Read(chunk, pkt); + + if (length < 1 || !bytes_to_skip) + { + // something went wrong, or we're not skipping bytes for some + // reason, just return the length read via the base method + return length; + } + + // we got some data and we're supposed to skip some of it + // check there's enough bytes for our intended skip + if (length < bytes_to_skip) + { + // something went wrong here + cerr << "RTP packet too short (" << length + << " bytes) to remove headers (needed " + << bytes_to_skip << ")" << endl; + throw std::runtime_error("Unexpected RTP packet length"); + } + + pkt.payload.erase( + pkt.payload.begin(), + pkt.payload.begin() + bytes_to_skip + ); + + return length - bytes_to_skip; + } +}; + +class RtpTarget : public UdpTarget { +public: + RtpTarget(string host, int port, const map& attr ) : + UdpTarget { host, port, attr } {} +}; + +template struct Rtp; +template <> struct Rtp { typedef RtpSource type; }; +template <> struct Rtp { typedef RtpTarget type; }; + +template +Iface* CreateRtp(const string& host, int port, const map& par) { return new typename Rtp::type (host, port, par); } + template inline bool IsOutput() { return false; } @@ -1116,10 +1210,24 @@ extern unique_ptr CreateMedium(const string& uri) ptr.reset( CreateUdp(u.host(), iport, u.parameters()) ); break; + case UriParser::RTP: + if (IsOutput()) + { + cerr << "RTP not supported as an output\n"; + throw invalid_argument("Invalid output protocol: RTP"); + } + iport = atoi(u.port().c_str()); + if ( iport < 1024 ) + { + cerr << "Port value invalid: " << iport << " - must be >=1024\n"; + throw invalid_argument("Invalid port number"); + } + ptr.reset( CreateRtp(u.host(), iport, u.parameters()) ); + break; } if (ptr.get()) - ptr->uri = move(u); + ptr->uri = std::move(u); return ptr; } diff --git a/apps/transmitmedia.hpp b/apps/transmitmedia.hpp index 604a8dfba..527f005d9 100644 --- a/apps/transmitmedia.hpp +++ b/apps/transmitmedia.hpp @@ -56,7 +56,7 @@ class SrtCommon SRTSOCKET Socket() const { return m_sock; } SRTSOCKET Listener() const { return m_bindsock; } - virtual void Close(); + void Close(); protected: @@ -109,7 +109,6 @@ class SrtSource: public Source, public SrtCommon bool IsOpen() override { return IsUsable(); } bool End() override { return IsBroken(); } - void Close() override { return SrtCommon::Close(); } SRTSOCKET GetSRTSocket() const override { @@ -137,7 +136,6 @@ class SrtTarget: public Target, public SrtCommon int Write(const char* data, size_t size, int64_t src_time, ostream &out_stats = cout) override; bool IsOpen() override { return IsUsable(); } bool Broken() override { return IsBroken(); } - void Close() override { return SrtCommon::Close(); } size_t Still() override { @@ -181,18 +179,8 @@ class SrtModel: public SrtCommon string m_host; int m_port = 0; - SrtModel(string host, int port, map par); void Establish(std::string& name); - - void Close() - { - if (m_sock != SRT_INVALID_SOCK) - { - srt_close(m_sock); - m_sock = SRT_INVALID_SOCK; - } - } }; diff --git a/apps/uriparser.cpp b/apps/uriparser.cpp index 4dae60a8b..6b8c80713 100644 --- a/apps/uriparser.cpp +++ b/apps/uriparser.cpp @@ -25,24 +25,27 @@ using namespace std; -map types; +map g_types; +// Map construction using the initializer list is only available starting from C++11. +// This dummy structure is used instead. struct UriParserInit { UriParserInit() { - types["file"] = UriParser::FILE; - types["udp"] = UriParser::UDP; - types["tcp"] = UriParser::TCP; - types["srt"] = UriParser::SRT; - types["rtmp"] = UriParser::RTMP; - types["http"] = UriParser::HTTP; - types["rtp"] = UriParser::RTP; - types[""] = UriParser::UNKNOWN; + g_types["file"] = UriParser::FILE; + g_types["udp"] = UriParser::UDP; + g_types["tcp"] = UriParser::TCP; + g_types["srt"] = UriParser::SRT; + g_types["rtmp"] = UriParser::RTMP; + g_types["http"] = UriParser::HTTP; + g_types["rtp"] = UriParser::RTP; + g_types[""] = UriParser::UNKNOWN; } } g_uriparser_init; UriParser::UriParser(const string& strUrl, DefaultExpect exp) + : m_uriType(UNKNOWN) { m_expect = exp; Parse(strUrl, exp); @@ -145,6 +148,41 @@ string UriParser::queryValue(const string& strKey) const return m_mapQuery.at(strKey); } +// NOTE: handles percent encoded single byte ASCII / Latin-1 characters but not unicode characters and encodings + +static string url_decode(const string& str) +{ + string ret; + size_t prev_idx; + size_t idx; + + for (prev_idx = 0; string::npos != (idx = str.find('%', prev_idx)); prev_idx = idx + 3) + { + char tmp[3]; + unsigned hex; + + if (idx + 2 >= str.size()) // bad percent encoding + break; + + tmp[0] = str[idx + 1]; + tmp[1] = str[idx + 2]; + tmp[2] = '\0'; + + if (!isxdigit((unsigned char) tmp[0]) || // bad percent encoding + !isxdigit((unsigned char) tmp[1]) || + 1 != sscanf(tmp, "%x", &hex) || + 0 == hex) + break; + + ret += str.substr(prev_idx, idx - prev_idx); + ret += (char) hex; + } + + ret += str.substr(prev_idx, str.size() - prev_idx); + + return ret; +} + void UriParser::Parse(const string& strUrl, DefaultExpect exp) { int iQueryStart = -1; @@ -153,7 +191,7 @@ void UriParser::Parse(const string& strUrl, DefaultExpect exp) if (idx != string::npos) { m_host = strUrl.substr(0, idx); - iQueryStart = idx + 1; + iQueryStart = (int)(idx + 1); } else { @@ -196,7 +234,7 @@ void UriParser::Parse(const string& strUrl, DefaultExpect exp) // Check special things in the HOST entry. size_t atp = m_host.find('@'); - if ( atp != string::npos ) + if (atp != string::npos) { string realhost = m_host.substr(atp+1); string prehost; @@ -294,22 +332,22 @@ void UriParser::Parse(const string& strUrl, DefaultExpect exp) if (idx != string::npos) { strQueryPair = strUrl.substr(iQueryStart, idx - iQueryStart); - iQueryStart = idx + 1; + iQueryStart = (int)(idx + 1); } else { strQueryPair = strUrl.substr(iQueryStart, strUrl.size() - iQueryStart); - iQueryStart = idx; + iQueryStart = (int)idx; } idx = strQueryPair.find("="); if (idx != string::npos) { - m_mapQuery[strQueryPair.substr(0, idx)] = strQueryPair.substr(idx + 1, strQueryPair.size() - (idx + 1)); + m_mapQuery[url_decode(strQueryPair.substr(0, idx))] = url_decode(strQueryPair.substr(idx + 1, strQueryPair.size() - (idx + 1))); } } - if ( m_proto == "file" ) + if (m_proto == "file") { if ( m_path.size() > 3 && m_path.substr(0, 3) == "/./" ) m_path = m_path.substr(3); @@ -317,14 +355,19 @@ void UriParser::Parse(const string& strUrl, DefaultExpect exp) // Post-parse fixes // Treat empty protocol as a file. In this case, merge the host and path. - if ( exp == EXPECT_FILE && m_proto == "" && m_port == "" ) + if (exp == EXPECT_FILE && m_proto == "" && m_port == "") { m_proto = "file"; m_path = m_host + m_path; m_host = ""; } - m_uriType = types[m_proto]; // default-constructed UNKNOWN will be used if not found (although also inserted) + const auto proto_it = g_types.find(m_proto); + // Default-constructed UNKNOWN will be used if not found. + if (proto_it != g_types.end()) + { + m_uriType = proto_it->second; + } m_origUri = strUrl; } diff --git a/apps/verbose.cpp b/apps/verbose.cpp index 58cf83fbe..4ea3b47dc 100644 --- a/apps/verbose.cpp +++ b/apps/verbose.cpp @@ -9,14 +9,13 @@ */ #include "verbose.hpp" +#include "sync.h" // srt::sync namespace Verbose { bool on = false; std::ostream* cverb = &std::cerr; -#if SRT_ENABLE_VERBOSE_LOCK - std::mutex vlock; -#endif + srt::sync::Mutex vlock; Log& Log::operator<<(LogNoEol) { @@ -28,19 +27,16 @@ namespace Verbose return *this; } -#if SRT_ENABLE_VERBOSE_LOCK Log& Log::operator<<(LogLock) { lockline = true; return *this; } -#endif Log::~Log() { if (on && !noeol) { -#if SRT_ENABLE_VERBOSE_LOCK if (lockline) { // Lock explicitly, as requested, and wait for the opportunity. @@ -48,7 +44,7 @@ namespace Verbose } else if (vlock.try_lock()) { - // Successfully locked, so unlock immediately, locking wasn't requeted. + // Successfully locked, so unlock immediately, locking wasn't requested. vlock.unlock(); } else @@ -62,15 +58,12 @@ namespace Verbose vlock.lock(); vlock.unlock(); } -#endif (*cverb) << std::endl; -#if SRT_ENABLE_VERBOSE_LOCK // If lockline is set, the lock was requested and WAS DONE, so unlock. // Otherwise locking WAS NOT DONE. if (lockline) vlock.unlock(); -#endif } } } diff --git a/apps/verbose.hpp b/apps/verbose.hpp index ec0276c12..e3d20732a 100644 --- a/apps/verbose.hpp +++ b/apps/verbose.hpp @@ -12,9 +12,7 @@ #define INC_SRT_VERBOSE_HPP #include -#if SRT_ENABLE_VERBOSE_LOCK -#include -#endif +#include "atomic.h" namespace Verbose { @@ -23,22 +21,22 @@ extern bool on; extern std::ostream* cverb; struct LogNoEol { LogNoEol() {} }; -#if SRT_ENABLE_VERBOSE_LOCK struct LogLock { LogLock() {} }; -#endif class Log { bool noeol = false; -#if SRT_ENABLE_VERBOSE_LOCK - bool lockline = false; -#endif + srt::sync::atomic lockline; // Disallow creating dynamic objects - void* operator new(size_t); + void* operator new(size_t) = delete; public: + Log() {} + Log(const Log& ) {} + + template Log& operator<<(const V& arg) { @@ -50,9 +48,7 @@ class Log } Log& operator<<(LogNoEol); -#if SRT_ENABLE_VERBOSE_LOCK Log& operator<<(LogLock); -#endif ~Log(); }; @@ -74,15 +70,38 @@ class ErrLog: public Log } }; +// terminal +inline void Print(Log& ) {} + +template +inline void Print(Log& out, Arg1&& arg1, Args&&... args) +{ + out << arg1; + Print(out, args...); +} + } inline Verbose::Log Verb() { return Verbose::Log(); } inline Verbose::ErrLog Verror() { return Verbose::ErrLog(); } +template +inline void Verb(Args&&... args) +{ + Verbose::Log log; + Verbose::Print(log, args...); +} + +template +inline void Verror(Args&&... args) +{ + Verbose::ErrLog log; + Verbose::Print(log, args...); +} + + // Manipulator tags static const Verbose::LogNoEol VerbNoEOL; -#if SRT_ENABLE_VERBOSE_LOCK static const Verbose::LogLock VerbLock; -#endif #endif diff --git a/codecov.yml b/codecov.yml index f91e5c1fe..2716c7f60 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,3 +6,7 @@ coverage: threshold: null patch: false changes: false +ignore: + - "testing" + - "apps" + - "example" \ No newline at end of file diff --git a/configure-data.tcl b/configure-data.tcl index 66902324a..3510a9645 100644 --- a/configure-data.tcl +++ b/configure-data.tcl @@ -25,47 +25,56 @@ # Options processed here internally, not passed to cmake set internal_options { - with-compiler-prefix= "set C/C++ toolchains gcc and g++" - with-compiler-type= "compiler type: gcc(default), cc, others simply add ++ for C++" - with-srt-name= "Override srt library name" - with-haicrypt-name= "Override haicrypt library name (if compiled separately)" + with-compiler-prefix= "set C/C++ toolchains gcc and g++" + with-compiler-type= "compiler type: gcc(default), cc, others simply add ++ for C++" + with-srt-name= "Override srt library name" + with-haicrypt-name= "Override haicrypt library name (if compiled separately)" + with-atomic= "Select implementation for atomics (compiler-intrinsics or sync-mutex)" } # Options that refer directly to variables used in CMakeLists.txt set cmake_options { cygwin-use-posix "Should the POSIX API be used for cygwin. Ignored if the system isn't cygwin. (default: OFF)" - enable-encryption "Should encryption features be enabled (default: ON)" - enable-c++11 "Should the c++11 parts (srt-live-transmit) be enabled (default: ON)" + enable-c++11 "Should the c++11 parts (srt-live-transmit) be enabled (default: ON, with gcc < 4.7 OFF)" enable-apps "Should the Support Applications be Built? (default: ON)" + enable-bonding "Enable 'bonding' SRT feature (default: OFF)" enable-testing "Should developer testing applications be built (default: OFF)" - enable-c++-deps "Extra library dependencies in srt.pc for C language (default: OFF)" - enable-heavy-logging "Should heavy debug logging be enabled (default: OFF)" + enable-profile "Should instrument the code for profiling. Ignored for non-GNU compiler. (default: OFF)" enable-logging "Should logging be enabled (default: ON)" - enable-debug=<0,1,2> "Enable debug mode (0=disabled, 1=debug, 2=rel-with-debug)" + enable-heavy-logging "Should heavy debug logging be enabled (default: OFF)" enable-haicrypt-logging "Should logging in haicrypt be enabled (default: OFF)" - enable-inet-pton "Set to OFF to prevent usage of inet_pton when building against modern SDKs (default: ON)" - enable-code-coverage "Enable code coverage reporting (default: OFF)" - enable-monotonic-clock "Enforced clock_gettime with monotonic clock on GC CV /temporary fix for #729/ (default: OFF)" - enable-profile "Should instrument the code for profiling. Ignored for non-GNU compiler. (default: OFF)" - enable-relative-libpath "Should applications contain relative library paths, like ../lib (default: OFF)" + enable-pktinfo "Should pktinfo reading and using be enabled (POSIX only) (default: OFF)" enable-shared "Should libsrt be built as a shared library (default: ON)" enable-static "Should libsrt be built as a static library (default: ON)" - enable-suflip "Should suflip tool be built (default: OFF)" + enable-relative-libpath "Should applications contain relative library paths, like ../lib (default: OFF)" enable-getnameinfo "In-logs sockaddr-to-string should do rev-dns (default: OFF)" - enable-unittests "Enable unit tests (default: OFF)" + enable-unittests "Enable Unit Tests (will download Google UT) (default: OFF)" + enable-encryption "Should encryption features be enabled (default: ON)" + enable-c++-deps "Extra library dependencies in srt.pc for C language (default: ON)" + use-static-libstdc++ "Should use static rather than shared libstdc++ (default: OFF)" + enable-inet-pton "Set to OFF to prevent usage of inet_pton when building against modern SDKs (default: ON)" + enable-code-coverage "Enable code coverage reporting (default: OFF)" + enable-monotonic-clock "Enforced clock_gettime with monotonic clock on GC CV /temporary fix for #729/ (default: OFF)" enable-thread-check "Enable #include that implements THREAD_* macros" - openssl-crypto-library= "Path to a library." - openssl-include-dir= "Path to a file." - openssl-ssl-library= "Path to a library." - pkg-config-executable= "pkg-config executable" - pthread-include-dir= "Path to a file." - pthread-library= "Path to a library." + enable-stdc++-sync "Use standard C++11 chrono/threads instead of pthread wrapper (default: OFF, on Windows: ON)" + use-openssl-pc "Use pkg-config to find OpenSSL libraries (default: ON)" + openssl-use-static-libs "Link OpenSSL statically (default: OFF)." use-busy-waiting "Enable more accurate sending times at a cost of potentially higher CPU load (default: OFF)" use-gnustl "Get c++ library/headers from the gnustl.pc" - use-enclib "Encryption library to be used: openssl(default), gnutls, mbedtls" - use-gnutls "DEPRECATED. Use USE_ENCLIB=openssl|gnutls|mbedtls instead" - use-openssl-pc "Use pkg-config to find OpenSSL libraries (default: ON)" - use-static-libstdc++ "Should use static rather than shared libstdc++ (default: OFF)" + enable-sock-cloexec "Enable setting SOCK_CLOEXEC on a socket (default: ON)" + enable-show-project-config "Enables use of ShowProjectConfig() in cmake (default: OFF)" + enable-new-rcvbuffer "Enables the new receiver buffer implementation (default: ON)" + enable-clang-tsa "Enable Clang's Thread-Safety-Analysis (default: OFF)" + atomic-use-srt-sync-mutex "Use mutex to implement atomics (alias: --with-atomic=sync-mutex) (default: OFF)" + + use-enclib "Encryption library to be used: openssl(default), gnutls, mbedtls, botan" + enable-debug=<0,1,2> "Enable debug mode (0=disabled, 1=debug, 2=rel-with-debug)" + pkg-config-executable= "pkg-config executable" + openssl-crypto-library= "OpenSSL: Path to a libcrypto library." + openssl-include-dir= "OpenSSL: Path to includes." + openssl-ssl-library= "OpenSSL: Path to a libssl library." + pthread-include-dir= "PThread: Path to includes" + pthread-library= "PThread: Path to the pthread library." } set options $internal_options$cmake_options @@ -162,9 +171,75 @@ proc preprocess {} { set ::haicrypt_name $::optval(--with-haicrypt-name) unset ::optval(--with-haicrypt-name) } + + if { "--with-atomic" in $::optkeys } { + switch -- $::optval(--with-atomic) { + compiler-intrinsics { + } + + sync-mutex { + set ::optval(--atomic-use-srt-sync-mutex) 1 + } + + default { + puts "ERROR: --with-atomic option accepts two values: compiler-intrinsics (default) or sync-mutex" + exit 1 + } + } + + unset ::optval(--with-atomic) + } } -proc GetCompilerCommand {} { +# Added also the Intel compiler names, just in case. +set compiler_map { + cc c++ + gcc g++ + icc icpc + icx icpx +} + +proc SplitCompilerVersionSuffix {cmd} { + # If there's no version suffix, return just $cmd. + # Otherwise return a list with cmd cut and version suffix + + set parts [split $cmd -] + if {[llength $parts] == 1} { + return $cmd + } + + set last [lindex $parts end] + if {![regexp {[0-9]+.*} $last]} { + return $cmd + } + + # Got the version + if {[llength $parts] == 2} { + set first [lindex $parts 0] + } else { + set first [join [lrange $parts 0 end-1] -] + } + + return [list $first -$last] +} + +# This uses 'compiler' in the form of the C compiler +# command line. For C++ it returns the C++ command line, +# which is normally the C compiler command with ++. +proc GetCompilerCmdName {compiler lang} { + lassign [SplitCompilerVersionSuffix $compiler] compiler suffix + if {$lang == "c++"} { + if { [dict exists $::compiler_map $compiler] } { + return [dict get $::compiler_map $compiler]$suffix + } + + return ${compiler}++${suffix} + } + + return $compiler${suffix} +} + +proc GetCompilerCommand { {lang {}} } { # Expect that the compiler was set through: # --with-compiler-prefix # --cmake-c[++]-compiler @@ -177,21 +252,25 @@ proc GetCompilerCommand {} { if { [info exists ::optval(--with-compiler-prefix)] } { set prefix $::optval(--with-compiler-prefix) - return ${prefix}$compiler + return ${prefix}[GetCompilerCmdName $compiler $lang] } else { - return $compiler + return [GetCompilerCmdName $compiler $lang] } - if { [info exists ::optval(--cmake-c-compiler)] } { - return $::optval(--cmake-c-compiler) + if { $lang != "c++" } { + if { [info exists ::optval(--cmake-c-compiler)] } { + return $::optval(--cmake-c-compiler) + } } - if { [info exists ::optval(--cmake-c++-compiler)] } { - return $::optval(--cmake-c++-compiler) - } + if { $lang != "c" } { + if { [info exists ::optval(--cmake-c++-compiler)] } { + return $::optval(--cmake-c++-compiler) + } - if { [info exists ::optval(--cmake-cxx-compiler)] } { - return $::optval(--cmake-cxx-compiler) + if { [info exists ::optval(--cmake-cxx-compiler)] } { + return $::optval(--cmake-cxx-compiler) + } } puts "NOTE: Cannot obtain compiler, assuming toolchain file will do what's necessary" @@ -257,6 +336,18 @@ proc postprocess {} { } else { puts "CONFIGURE: default compiler used" } + + # Complete the variables before calling cmake, otherwise it might not work + + if { [info exists ::optval(--with-compiler-type)] } { + if { ![info exists ::optval(--cmake-c-compiler)] } { + lappend ::cmakeopt "-DCMAKE_C_COMPILER=[GetCompilerCommand c]" + } + + if { ![info exists ::optval(--cmake-c++-compiler)] } { + lappend ::cmakeopt "-DCMAKE_CXX_COMPILER=[GetCompilerCommand c++]" + } + } } if { $::srt_name != "" } { @@ -343,8 +434,23 @@ proc postprocess {} { # Otherwise don't set PKG_CONFIG_PATH and we'll see. } - if { $::HAVE_DARWIN && !$toolchain_changed} { + set use_brew 0 + if { $::HAVE_DARWIN && !$toolchain_changed } { + set use_brew 1 + } + if { [info exists ::optval(--use-enclib)] && $::optval(--use-enclib) == "botan"} { + set use_brew 0 + } + if { $use_brew } { + foreach item $::cmakeopt { + if { [string first "Android" $item] != -1 } { + set use_brew 0 + break + } + } + } + if { $use_brew } { if { $have_gnutls } { # Use gnutls explicitly, as found in brew set er [catch {exec brew info gnutls} res] diff --git a/docs/API-functions.md b/docs/API-functions.md deleted file mode 100644 index 0c50c62de..000000000 --- a/docs/API-functions.md +++ /dev/null @@ -1,2549 +0,0 @@ -# SRT API Functions - -- [**Library Initialization**](#Library-Initialization) - * [srt_startup](#srt_startup) - * [srt_cleanup](#srt_cleanup) -- [**Creating and configuring sockets**](#Creating-and-configuring-sockets) - * [srt_socket](#srt_socket) - * [srt_create_socket](#srt_create_socket) - * [srt_bind](#srt_bind) - * [srt_bind_acquire](#srt_bind_acquire) - * [srt_getsockstate](#srt_getsockstate) - * [srt_getsndbuffer](#srt_getsndbuffer) - * [srt_close](#srt_close) -- [**Connecting**](#Connecting) - * [srt_listen](#srt_listen) - * [srt_accept](#srt_accept) - * [srt_accept_bond](#srt_accept_bond) - * [srt_listen_callback](#srt_listen_callback) - * [srt_connect](#srt_connect) - * [srt_connect_bind](#srt_connect_bind) - * [srt_connect_debug](#srt_connect_debug) - * [srt_rendezvous](#srt_rendezvous) - * [srt_connect_callback](#srt_connect_callback) -- [**Socket group management**](#Socket-group-management) - * [SRT_GROUP_TYPE](#SRT_GROUP_TYPE) - * [SRT_SOCKGROUPCONFIG](#SRT_SOCKGROUPCONFIG) - * [SRT_SOCKGROUPDATA](#SRT_SOCKGROUPDATA) - * [SRT_MEMBERSTATUS](#SRT_MEMBERSTATUS) - * [srt_create_group](#srt_create_group) - * [srt_include](#srt_include) - * [srt_exclude](#srt_exclude) - * [srt_groupof](#srt_groupof) - * [srt_group_data](#srt_group_data) - * [srt_connect_group](#srt_connect_group) - * [srt_prepare_endpoint](#srt_prepare_endpoint) - * [srt_create_config](#srt_create_config) - * [srt_delete_config](#srt_delete_config) - * [srt_config_add](#srt_config_add) -- [**Options and properties**](#Options-and-properties) - * [srt_getpeername](#srt_getpeername) - * [srt_getsockname](#srt_getsockname) - * [srt_getsockopt, srt_getsockflag](#srt_getsockopt-srt_getsockflag) - * [srt_setsockopt, srt_setsockflag](#srt_setsockopt-srt_setsockflag) - * [srt_getversion](#srt_getversion) -- [**Helper data types for transmission**](#Helper-data-types-for-transmission) - * [SRT_MSGCTRL](#SRT_MSGCTRL) -- [**Transmission**](#Transmission) - * [srt_send, srt_sendmsg, srt_sendmsg2](#srt_send-srt_sendmsg-srt_sendmsg2) - * [srt_recv, srt_recvmsg, srt_recvmsg2](#srt_recv-srt_recvmsg-srt_recvmsg2) - * [srt_sendfile, srt_recvfile](#srt_sendfile-srt_recvfile) -- [**Diagnostics**](#Diagnostics) - * [srt_getlasterror_str](#srt_getlasterror_str) - * [srt_getlasterror](#srt_getlasterror) - * [srt_strerror](#srt_strerror) - * [srt_clearlasterror](#srt_clearlasterror) - * [srt_getrejectreason](#srt_getrejectreason) - * [srt_rejectreason_str](#srt_rejectreason_str) - * [srt_setrejectreason](#srt_setrejectreason) - * [Error Codes](#error-codes) -- [**Performance tracking**](#Performance-tracking) - * [srt_bstats, srt_bistats](#srt_bstats-srt_bistats) -- [**Asynchronous operations (epoll)**](#Asynchronous-operations-epoll) - * [srt_epoll_create](#srt_epoll_create) - * [srt_epoll_add_usock, srt_epoll_add_ssock, srt_epoll_update_usock, srt_epoll_update_ssock](#srt_epoll_add_usock-srt_epoll_add_ssock-srt_epoll_update_usock-srt_epoll_update_ssock) - * [srt_epoll_remove_usock, srt_epoll_remove_ssock](#srt_epoll_remove_usock-srt_epoll_remove_ssock) - * [srt_epoll_wait](#srt_epoll_wait) - * [srt_epoll_uwait](#srt_epoll_uwait) - * [srt_epoll_clear_usocks](#srt_epoll_clear_usocks) - * [srt_epoll_set](#srt_epoll_set) - * [srt_epoll_release](#srt_epoll_release) -- [**Logging control**](#Logging-control) - * [srt_setloglevel](#srt_setloglevel) - * [srt_addlogfa, srt_dellogfa, srt_resetlogfa](#srt_addlogfa-srt_dellogfa-srt_resetlogfa) - * [srt_setloghandler](#srt_setloghandler) - * [srt_setlogflags](#srt_setlogflags) -- [**Time Access**](#time-access) - * [srt_time_now](#srt_time_now) - * [srt_connection_time](#srt_connection_time) - - -## Library initialization - -### srt_startup -``` -int srt_startup(void); -``` - -This function shall be called at the start of an application that uses the SRT -library. It provides all necessary platform-specific initializations, sets up -global data, and starts the SRT GC thread. If this function isn't explicitly -called, it will be called automatically when creating the first socket. However, -relying on this behavior is strongly discouraged. - -- Returns: - - * 0 = successfully run, or already started - * 1 = this is the first startup, but the GC thread is already running - * -1 = failed - -- Errors: - - * `SRT_ECONNSETUP` (with error code set): Reported when required system -resource(s) failed to initialize. This is currently used only on Windows to -report a failure from `WSAStartup`. - -### srt_cleanup -``` -int srt_cleanup(void); -``` - -This function cleans up all global SRT resources and shall be called just before -exiting the application that uses the SRT library. This cleanup function will still -be called from the C++ global destructor, if not called by the application, although -relying on this behavior is stronly discouraged. - -- Returns: - - * 0 (A possibility to return other values is reserved for future use) - -**IMPORTANT**: Note that the startup/cleanup calls have an instance counter. -This means that if you call `srt_startup` multiple times, you need to call the -`srt_cleanup` function exactly the same number of times. - -## Creating and configuring sockets - -### srt_socket -``` -SRTSOCKET srt_socket(int af, int type, int protocol); -``` - -Old and deprecated version of `srt_create_socket`. All arguments are ignored. - -**NOTE** changes with respect to UDT version: - -* In UDT (and SRT versions before 1.4.2) the `af` parameter was specifying the -socket family (`AF_INET` or `AF_INET6`). This is now not required; this parameter -is decided at the call of `srt_conenct` or `srt_bind`. - -* In UDT the `type` parameter was used to specify the file or message mode -using `SOCK_STREAM` or `SOCK_DGRAM` symbols (with the latter being misleading, -as the message mode has nothing to do with UDP datagrams and it's rather -similar to the SCTP protocol). In SRT these two modes are available by setting -`SRTO_TRANSTYPE`. The default is `SRTT_LIVE`. If, however, you set -`SRTO_TRANSTYPE` to `SRTT_FILE` for file mode, you can then leave the -`SRTO_MESSAGEAPI` option as false (default), which corresponds to "stream" mode -(TCP-like), or set it to true, which corresponds to "message" mode (SCTP-like). - - -### srt_create_socket -``` -SRTSOCKET srt_create_socket(); -``` - -Creates an SRT socket. - -Note that socket IDs always have the `SRTGROUP_MASK` bit clear. - -- Returns: - - * a valid socket ID on success - * `SRT_INVALID_SOCK` (`-1`) on error - -- Errors: - - * `SRT_ENOTBUF`: not enough memory to allocate required resources - -**NOTE:** This is probably a design flaw (**BUG?**). Usually underlying system -errors are reported by `SRT_ECONNSETUP`. - - -### srt_bind -``` -int srt_bind(SRTSOCKET u, const struct sockaddr* name, int namelen); -``` - -Binds a socket to a local address and port. Binding specifies the local network -interface and the UDP port number to be used for the socket. When the local -address is a form of `INADDR_ANY`, then it's bound to all interfaces. When the -port number is 0, then the port number will be system-allocated if necessary. - -This call is obligatory for a listening socket before calling `srt_listen` -and for rendezvous mode before calling `srt_connect`, otherwise it's optional. -For a listening socket it defines the network interface and the port where the -listener should expect a call request. In case of rendezvous mode (when the -socket has set `SRTO_RENDEZVOUS` to true, in this mode both parties connect -to one another) it defines the network interface and port from which packets -will be sent to the peer and to which the peer is expected to send packets. - -For a connecting socket this call can set up the outgoing port to be used in -the communication. It is allowed that multiple SRT sockets share one local -outgoing port, as long as `SRTO_REUSEADDR` is set to *true* (default). Without -this call the port will be automatically selected by the system. - -NOTE: This function cannot be called on socket group. If you need to -have the group-member socket bound to the specified source address before -connecting, use `srt_connect_bind` for that purpose. - -- Returns: - - * `SRT_ERROR` (-1) on error, otherwise 0 - -- Errors: - - * `SRT_EINVSOCK`: Socket passed as `u` designates no valid socket - * `SRT_EINVOP`: Socket already bound - * `SRT_ECONNSETUP`: Internal creation of a UDP socket failed - * `SRT_ESOCKFAIL`: Internal configuration of a UDP socket (`bind`, `setsockopt`) failed - -### srt_bind_acquire - -``` -int srt_bind_acquire(SRTSOCKET u, UDPSOCKET udpsock); -``` - -A version of `srt_bind` that acquires a given UDP socket instead of creating one. - -### srt_getsockstate - -``` -SRT_SOCKSTATUS srt_getsockstate(SRTSOCKET u); -``` - -Gets the current status of the socket. Possible states are: - -* `SRTS_INIT`: Created, but not bound -* `SRTS_OPENED`: Created and bound, but not in use yet. -* `SRTS_LISTENING`: Socket is in listening state -* `SRTS_CONNECTING`: The connect operation was initiated, but not yet -finished. This may also mean that it has timed out; you can only know -that after getting a socket error report from `srt_epoll_wait`. In blocking -mode it's not possible because `srt_connect` does not return until the -socket is connected or failed due to timeout or interrupted call. -* `SRTS_CONNECTED`: The socket is connected and ready for transmission. -* `SRTS_BROKEN`: The socket was connected, but the connection was broken -* `SRTS_CLOSING`: The socket may still be open and active, but closing -is requested, so no further operations will be accepted (active operations will -be completed before closing) -* `SRTS_CLOSED`: The socket has been closed, but not yet removed by the GC -thread -* `SRTS_NONEXIST`: The specified number does not correspond to a valid socket. - -### srt_getsndbuffer - -``` -int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); -``` - -Retrieves information about the sender buffer. - -* `sock`: Socket to test -* `blocks`: Written information about buffer blocks in use -* `bytes`: Written information about bytes in use - -This function can be used for diagnostics. It is especially useful when the -socket needs to be closed asynchronously. - -### srt_close - -``` -int srt_close(SRTSOCKET u); -``` - -Closes the socket or group and frees all used resources. Note that underlying -UDP sockets may be shared between sockets, so these are freed only with the -last user closed. - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0 - -- Errors: - - * `SRT_EINVSOCK`: Socket `u` indicates no valid socket ID - -## Connecting - -### srt_listen -``` -int srt_listen(SRTSOCKET u, int backlog); -``` - -This sets up the listening state on a socket with a backlog setting that -defines how many sockets may be allowed to wait until they are accepted -(excessive connection requests are rejected in advance). - -The following important options may change the behavior of the listener -socket and the `srt_accept` function: - -* `srt_listen_callback` installs a user function that will be called -before `srt_accept` can happen -* `SRTO_GROUPCONNECT` option allows the listener socket to accept group -connections - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0. - -- Errors: - - * `SRT_EINVPARAM`: Value of `backlog` is 0 or negative. - * `SRT_EINVSOCK`: Socket `u` indicates no valid SRT socket. - * `SRT_EUNBOUNDSOCK`: `srt_bind` has not yet been called on that socket. - * `SRT_ERDVNOSERV`: `SRTO_RENDEZVOUS` flag is set to true on specified socket. - * `SRT_EINVOP`: Internal error (should not happen when `SRT_EUNBOUNDSOCK` is reported). - * `SRT_ECONNSOCK`: The socket is already connected. - * `SRT_EDUPLISTEN`: The address used in `srt_bind` by this socket is already -occupied by another listening socket. Binding multiple sockets to one IP address -and port is allowed, as long as `SRTO_REUSEADDR` is set to true, but only one of -these sockets can be set up as a listener. - -### srt_accept - -``` -SRTSOCKET srt_accept(SRTSOCKET lsn, struct sockaddr* addr, int* addrlen); -``` - -Accepts a pending connection, then creates and returns a new socket or -group ID that handles this connection. The group and socket can be -distinguished by checking the `SRTGROUP_MASK` bit on the returned ID. - -* `lsn`: the listener socket previously configured by `srt_listen` -* `addr`: the IP address and port specification for the remote party -* `addrlen`: INPUT: size of `addr` pointed object. OUTPUT: real size of the -returned object - -**NOTE:** `addr` is allowed to be NULL, in which case it's understood that the -application is not interested in the address from which the connection originated. -Otherwise `addr` should specify an object into which the address will be written, -and `addrlen` must also specify a variable to contain the object size. Note also -that in the case of group connection only the initial connection that -establishes the group connection is returned, together with its address. As -member connections are added or broken within the group, you can obtain this -information through `srt_group_data` or the data filled by `srt_sendmsg2` and -`srt_recvmsg2`. - -If the pending connection is a group connection (initiated on the peer side -by calling the connection function using a group ID, and permitted on the -listener socket by `SRTO_GROUPCONNECT` flag), then the value returned is a -group ID. This function then creates a new group, as well as a new socket for -this very connection, that will be added to the group. Once the group is -created this way, further connections within the same group, as well as sockets -for them, will be created in the background. The `SRT_EPOLL_UPDATE` event is -raised on the `lsn` socket when a new background connection is attached to the -group, although it's usually for internal use only. - -- Returns: - - * On success, a valid SRT socket or group ID to be used for transmission - * `SRT_ERROR` (-1) on failure - -- Errors: - - * `SRT_EINVPARAM`: NULL specified as `addrlen`, when `addr` is not NULL - * `SRT_EINVSOCK`: `lsn` designates no valid socket ID. - * `SRT_ENOLISTEN`: `lsn` is not set up as a listener (`srt_listen` not called) - * `SRT_EASYNCRCV`: No connection reported so far. This error is reported only -when the `lsn` listener socket was configured as non-blocking for reading -(`SRTO_RCVSYN` set to false); otherwise the call blocks until a connection -is reported or an error occurs - * `SRT_ESCLOSED`: The `lsn` socket has been closed while the function was -blocking the call (if `SRTO_RCVSYN` is set to default true). This includes a -situation when the socket was closed just at the moment when a connection was -made and the socket got closed during processing - - -### srt_accept_bond - -``` -SRTSOCKET srt_accept_bond(const SRTSOCKET listeners[], int nlisteners, int msTimeOut); -``` - -Accepts a pending connection, like `srt_accept`, but pending on any of the -listener sockets passed in the `listeners` array of `nlisteners` size. - -* `listeners`: array of listener sockets (all must be setup by `srt_listen`) -* `nlisteners`: size of the `listeners` array -* `msTimeOut`: timeout in [ms] or -1 to block forever - -This function is for blocking mode only - for non-blocking mode you should -simply call `srt_accept` on the first listener socket that reports readiness, -and this function is actually a friendly shortcut that uses waiting on epoll -and `srt_accept` internally. This function supports an important use case for -accepting a group connection, for which every member connection is expected to -be established over a different listener socket. - -Note that there's no special set of settings required or rejected for this -function. The group-member connections for the same group can be established -over various different listener sockets always when all those listeners are -hosted by the same application, as the group management is global for the -application, so a connection reporting in for an already connected group -gets discovered and the connection will be handled in the background, -regardless to which listener socket the call was done - as long as the -connection is accepted according to any additional conditions. - -This function has still nothing to do with the groups - you can use it in -any case when you have one service that accepts connections to multiple -endpoints. Note also that the settings as to whether listeners should -accept or reject socket or group connections, should be applied to the -listener sockets appropriately prior to calling this function. - -- Returns: - - * On success, a valid SRT socket or group ID to be used for transmission - * `SRT_ERROR` (-1) on failure - -- Errors: - - * `SRT_EINVPARAM`: NULL specified as `listeners` or `nlisteners` < 1 - - * `SRT_EINVSOCK`: any socket in `listeners` designates no valid socket ID. -Can also mean Internal Error when an error occurred while creating an -accepted socket (**BUG?**) - - * `SRT_ENOLISTEN`: any socket in `listeners` is not set up as a listener -(`srt_listen` not called, or the listener socket has already been closed) - - * `SRT_EASYNCRCV`: No connection reported on any listener socket as the -timeout has been reached. This error is only reported when msTimeOut is -not -1 - - -### srt_listen_callback - -``` -int srt_listen_callback(SRTSOCKET lsn, srt_listen_callback_fn* hook_fn, void* hook_opaque); -``` - -This call installs a callback hook, which will be executed on a socket that is -automatically created to handle the incoming connection on the listening -socket (and is about to be returned by `srt_accept`), but before the connection -has been accepted. - -* `lsn`: Listening socket where you want to install the callback hook -* `hook_fn`: The callback hook function pointer -* `hook_opaque`: The pointer value that will be passed to the callback function - -- Returns: - - * 0, if successful - * -1, on error - -- Errors: - - * `SRT_EINVPARAM` reported when `hook_fn` is a null pointer - -The callback function has the signature as per this type definition: -``` -typedef int srt_listen_callback_fn(void* opaque, SRTSOCKET ns, int hs_version - const struct sockaddr* peeraddr, const char* streamid); -``` - -The callback function gets the following parameters passed: - -* `opaque`: The pointer passed as `hook_opaque` when registering -* `ns`: The freshly created socket to handle the incoming connection -* `hs_version`: The handshake version (usually 5, pre-1.3 versions use 4) -* `peeraddr`: The address of the incoming connection -* `streamid`: The value set to `SRTO_STREAMID` option set on the peer side - -(Note that versions that use handshake version 4 are incapable of using -any extensions, such as streamid, however they do support encryption. -Note also that the SRT version isn't yet extracted, however you can -prevent too old version connections using `SRTO_MINVERSION` option). - -The callback function is given an opportunity to: - -* use the passed information (streamid and peer address) to decide - what to do with this connection -* alter any options on the socket, which could not be set properly - before on the listening socket to be derived by the accepted socket, - and won't be allowed to be altered after the socket is returned by - `srt_accept` - -Note that the returned socket has already set all derived options from the -listener socket, as it happens normally, and the moment when this callback is -called is when the conclusion handshake has been already received from the -caller party, but not yet interpreted (the streamid field is extracted from it -prematurely). When you, for example, set a passphrase on the socket at this -very moment, the Key Material processing will happen against this already set -passphrase, after the callback function is finished. - -The callback function shall return 0, if the connection is to be accepted. -If you return -1, **or** if the function throws an exception, this will be -understood as a request to reject the incoming connection - in which case the -about-to-be-accepted socket will be silently deleted and `srt_accept` will not -report it. Note that in case of non-blocking mode the epoll bits for read-ready -on the listener socket will not be set if the connection is rejected, including -when rejected from this user function. - -**IMPORTANT**: This function is called in the receiver worker thread, which -means that it must do its checks and operations as quickly as possible and keep -the minimum possible time, as every delay you do in this function will burden -the processing of the incoming data on the associated UDP socket, which in case -of a listener socket means the listener socket itself and every socket accepted -off this listener socket. Avoid any extensive search operations, best cache in -memory whatever database you have to check against the data received in -streamid or peeraddr. - - -### srt_connect - -``` -int srt_connect(SRTSOCKET u, const struct sockaddr* name, int namelen); -``` - -Connects a socket or a group to a remote party with a specified address and port. - -* `u`: can be an SRT socket or SRT group, both freshly created and not yet - used for any connection, except possibly `srt_bind` on the socket -* `name`: specification of the remote address and port -* `namelen`: size of the object passed by `name` - -**NOTES:** -1. The socket used here may be bound from upside (or binding and connection can -be done in one function, `srt_connect_bind`) so that it uses a predefined -network interface or local outgoing port. If not, it behaves as if it was -bound to `INADDR_ANY` (which binds on all interfaces) and port 0 (which -makes the system assign the port automatically). -2. When `u` is a group, then this call can be done multiple times, each time -for another member connection, and a new member SRT socket will be created -automatically for every call of this function. -3. If you want to connect a group to multiple links at once and use blocking -mode, you might want to use `srt_connect_group` instead. - -- Returns: - - * `SRT_ERROR` (-1) in case of error - * 0 in case when used for `u` socket - * Socket ID created for connection for `u` group - -- Errors: - - * `SRT_EINVSOCK`: Socket `u` indicates no valid socket ID - * `SRT_ERDVUNBOUND`: Socket `u` has set `SRTO_RENDEZVOUS` to true, but `srt_bind` -hasn't yet been called on it. The `srt_connect` function is also used to connect a -rendezvous socket, but rendezvous sockets must be explicitly bound to a local -interface prior to connecting. Non-rendezvous sockets (caller sockets) can be -left without binding - the call to `srt_connect` will bind them automatically. - * `SRT_ECONNSOCK`: Socket `u` is already connected - * `SRT_ECONNREJ`: Connection has been rejected - * `SRT_ENOSERVER`: Connection has been timed out (see `SRTO_CONNTIMEO`) - * `SRT_ESCLOSED`: The socket `u` has been closed while the function was -blocking the call (if `SRTO_RCVSYN` is set to default true) - -When `SRT_ECONNREJ` error is reported, you can get the reason for -a rejected connection from `srt_getrejectreason`. In non-blocking -mode (when `SRTO_RCVSYN` is set to false), only `SRT_EINVSOCK`, -`SRT_ERDVUNBOUND` and `SRT_ECONNSOCK` can be reported. In all other cases -the function returns immediately with a success, and the only way to obtain -the connecting status is through the epoll flag with `SRT_EPOLL_ERR`. -In this case you can also call `srt_getrejectreason` to get the detailed -reason for the error, including connection timeout (`SRT_REJ_TIMEOUT`). - - -### srt_connect_bind - -``` -int srt_connect_bind(SRTSOCKET u, const struct sockaddr* source, - const struct sockaddr* target, int len); -``` - -This function does the same as first `srt_bind` then `srt_connect`, if called -with `u` being a socket. If `u` is a group, then it will execute `srt_bind` -first on the automatically created socket for the connection. - -* `u`: Socket or group to connect -* `source`: Address to bind `u` to -* `target`: Address to connect -* `len`: size of the original structure of `source` and `target` - -- Returns: - - * `SRT_ERROR` (-1) in case of error - * 0 in case when used for `u` socket - * Socket ID created for connection for `u` group - -- Errors: - - * `SRT_EINVSOCK`: Socket passed as `u` designates no valid socket - * `SRT_EINVOP`: Socket already bound - * `SRT_ECONNSETUP`: Internal creation of a UDP socket failed - * `SRT_ESOCKFAIL`: Internal configuration of a UDP socket (`bind`, `setsockopt`) failed - * `SRT_ERDVUNBOUND`: Internal error (`srt_connect` should not report it after `srt_bind` was called) - * `SRT_ECONNSOCK`: Socket `u` is already connected - * `SRT_ECONNREJ`: Connection has been rejected - -IMPORTANT: It's not allowed to bind and connect the same socket to two -different families (that is, both `source` and `target` must be `AF_INET` or -`AF_INET6`), although you may mix links over IPv4 and IPv6 in one group. - -### srt_connect_debug - -``` -int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); -``` - -This function is for developers only and can be used for testing. It does the -same thing as [`srt_connect`](#srt_connect), with the exception that it allows -specifying the Initial Sequence Number for data transmission. Normally this value -is generated randomly. - -### srt_rendezvous -``` -int srt_rendezvous(SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, - const struct sockaddr* remote_name, int remote_namelen); -``` -Performs a rendezvous connection. This is a shortcut for doing bind locally, -setting the `SRTO_RENDEZVOUS` option to true, and doing `srt_connect`. - -* `u`: socket to connect -* `local_name`: specifies the local network interface and port to bind -* `remote_name`: specifies the remote party's IP address and port - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0 - -- Errors: - - * `SRT_EINVSOCK`: Socket passed as `u` designates no valid socket - * `SRT_EINVOP`: Socket already bound - * `SRT_ECONNSETUP`: Internal creation of a UDP socket failed - * `SRT_ESOCKFAIL`: Internal configuration of a UDP socket (`bind`, `setsockopt`) failed - * `SRT_ERDVUNBOUND`: Internal error (`srt_connect` should not report it after `srt_bind` was called) - * `SRT_ECONNSOCK`: Socket `u` is already connected - * `SRT_ECONNREJ`: Connection has been rejected - -IMPORTANT: It's not allowed to perform a rendezvous connection to two -different families (that is, both `local_name` and `remote_name` must be `AF_INET` or -`AF_INET6`). - -### srt_connect_callback -``` -int srt_connect_callback(SRTSOCKET u, srt_connect_callback_fn* hook_fn, void* hook_opaque); -``` - -This call installs a callback hook, which will be executed on a given `u` -socket or all member sockets of `u` group, just after the pending connection -situation in the background has been resolved and the connection has failed. -Note that this function is not guaranteed to be called if the `u` socket is set -to blocking mode (`SRTO_RCVSYN` option set to true). It is guaranteed to be -called when a socket is in non-blocking mode, or when you use a group. - -This function is mainly intended to be used with group connections. Note that -even if you use a group connection in blocking mode, after the group is considered -connected the member connections still continue in background. Also, when -some connections are still pending and others have failed, the blocking -call for `srt_connect_group` will not exit until at least one of them succeeds -or all fail - in such a case those failures also happen only in the background, -while the connecting function blocks until all connections are resolved. -When all links fail, you will only get a general error code for the group. -This mechanism allows you to get individual errors for particular member -connection failures. - -You can also use this mechanism as an alternative method for a single-socket -connection in non-blocking mode to trigger an action when the connection -process is finished. It is recommended, however, that you use this callback -only to collect failure information, as the call will happen in one of the -internal SRT threads. - -* `u`: Socket or group that will be used for connecting and for which the hook is installed -* `hook_fn`: The callback hook function pointer -* `hook_opaque`: The pointer value that will be passed to the callback function - -- Returns: - - * 0, if successful - * -1, on error - -- Errors: - - * `SRT_EINVPARAM` reported when `hook_fn` is a null pointer - -The callback function signature has the following type definition: - -``` -typedef void srt_connect_callback_fn(void* opaq, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token); -``` -where: - -* `opaq`: The pointer passed as `hook_opaque` when registering -* `ns`: The socket for which the connection process was resolved -* `errorcode`: The error code, same as for `srt_connect` for blocking mode -* `peeraddr`: The target address passed to `srt_connect` call -* `token`: The token value, if it was used for group connection, otherwise -1 - - -## Socket group management - -### SRT_GROUP_TYPE - -The following group types are collected in an `SRT_GROUP_TYPE` enum: - -* `SRT_GTYPE_BROADCAST`: broadcast type, all links are actively used at once -* `SRT_GTYPE_BACKUP`: backup type, idle links take over connection on disturbance -* `SRT_GTYPE_BALANCING`: balancing type, share bandwidth usage between links - -### SRT_SOCKGROUPCONFIG - -This structure is used to define entry points for connections for the -`srt_connect_group` function: - -``` -typedef struct SRT_GroupMemberConfig_ -{ - SRTSOCKET id; - struct sockaddr_storage srcaddr; - struct sockaddr_storage peeraddr; - int weight; - SRT_SOCKOPT_CONFIG* config; - int errorcode; - int token; -} SRT_SOCKGROUPCONFIG; -``` - -where: - -* `id`: member socket ID (filled back as output) -* `srcaddr`: address to which `id` should be bound -* `peeraddr`: address to which `id` should be connected -* `weight`: the weight parameter for the link (group-type dependent) -* `config`: the configuration object, if used (see [`srt_create_config()`](#srt_create_config)) -* `errorcode`: status of the connecting operation -* `token`: An integer value unique for every connection, or -1 if unused - -The `srt_perpare_endpoint` sets these fields to default values. After that -you can change the value of `weight` and `config` and `token` fields. The -`weight` parameter's meaning is dependent on the group type: - -* BROADCAST: not used -* BACKUP: positive value of link priority (the greater, the more preferred) -* BALANCING: relative expected load on this link for fixed algorithm - -In any case, the allowed value ranges for `weight` is between 0 and 32767. - -The `config` parameter is used to provide options to be set separately -on a socket for a particular connection (see [`srt_create_config()`](#srt_create_config)). - -The `token` value is intended to allow the application to more easily identify -a particular connection. If you don't use it and leave the default value of -1, -the library will set a unique value for the next connection (a 32-bit unsigned -number that will overflow by itself; the default value will be skipped). -The application can also set a unique value by itself and keep the same -value for the same connection. - - -### SRT_SOCKGROUPDATA - -The most important structure for the group member status is `SRT_SOCKGROUPDATA`: - -```c++ -typedef struct SRT_SocketGroupData_ -{ - SRTSOCKET id; - struct sockaddr_storage peeraddr; - SRT_SOCKSTATUS sockstate; - uint16_t weight; - SRT_MEMBERSTATUS memberstate; - int result; - int token; -} SRT_SOCKGROUPDATA; -``` - -where: - -* `id`: member socket ID -* `peeraddr`: address to which `id` should be connected -* `sockstate`: current connection status (see [`srt_getsockstate`](#srt_getsockstate)) -* `weight`: current weight value set on the link -* `memberstate`: current state of the member (see below) -* `result`: result of the operation (if this operation recently updated this structure) -* `token`: A token value set for that connection (see [`SRT_SOCKGROUPCONFIG`](#srt_sockgroupconfig)) - -### SRT_MEMBERSTATUS - -The enumeration type that defines the state of the member -connection in the group: - -* `SRT_GST_PENDING`: The connection is in progress, so the socket -is not currently being used for transmission, even potentially, -and still has a chance to fail and transit into `SRT_GST_BROKEN` -without turning into `SRT_GST_IDLE` - -* `SRT_GST_IDLE`: The connection is established and ready to -take over transmission, but it's not used for transmission at -the moment. This state may last for a short moment in case of -broadcast or balancing groups. In backup groups this state -defines a backup link that is ready to take over when the -currently active (running) link gets unstable. - -* `SRT_GST_RUNNING`: The connection is established and at least -one packet has already been sent or received over it. - -* `SRT_GST_BROKEN`: The connection was broken. Broken connections -are not to be revived. Note also that it is only possible to see this -state if it is read by `srt_sendmsg2` or `srt_recvmsg2` just after -the link failure has been detected. Otherwise, the broken link simply -disappears from the member list. - -Note that internally the member state is separate for sending and -receiving. If the `memberstate` field of `SRT_SOCKGROUPDATA` is -`SRT_GST_RUNNING`, it means that this is the state in at least one -direction, while in the other direction it may be `SRT_GST_IDLE`. In all -other cases the states should be the same in both directions. - -States should normally start with `SRT_GST_PENDING` and then -turn into `SRT_GST_IDLE`. Once a new link is used for sending data, -the state becomes `SRT_GST_RUNNING`. -In case of `SRT_GTYPE_BACKUP` type group, if a link is in -`SRT_GST_RUNNING` state, but another link is chosen to remain -as the only active one, this link will be "silenced" (its state will -become `SRT_GST_IDLE`). - - -## Functions to be used on groups: - -### srt_create_group - -``` -SRTSOCKET srt_create_group(SRT_GROUP_TYPE type); -``` - -Creates a new group of type `type`. This is typically called on the -caller side to be next used for connecting to the listener peer side. -The group ID is of the same domain as socket ID, with the exception that -the `SRTGROUP_MASK` bit is set on it, unlike for socket ID. - -### srt_include - -``` -int srt_include(SRTSOCKET socket, SRTSOCKET group); -``` - -This function adds a socket to a group. This is only allowed for unmanaged -groups. No such group type is currently implemented. - -### srt_exclude - -``` -int srt_exclude(SRTSOCKET socket); -``` -This function removes a socket from a group to which it currently belongs. -This is only allowed for unmanaged groups. No such group type is currently -implemented. - -### srt_groupof - -``` -SRTSOCKET srt_groupof(SRTSOCKET socket); -``` - -Returns the group ID of the socket, or `SRT_INVALID_SOCK` if the socket -doesn't exist or it's not a member of any group. - -### srt_group_data - -``` -int srt_group_data(SRTSOCKET socketgroup, SRT_SOCKGROUPDATA output[], size_t* inoutlen); -``` - -* `socketgroup` an existing socket group ID -* `output` points to an output array -* `inoutlen` points to a variable that stores the size of the `output` array, - and is set to the filled array's size - -This function obtains the current member state of the group specified in -`socketgroup`. The `output` should point to an array large enough to hold -all the elements. The `inoutlen` should point to a variable initially set -to the size of the `output` array. -The current number of members will be written back to `inoutlen`. - -If the size of the `output` array is enough for the current number of members, -the `output` array will be filled with group data and the function will return -the number of elements filled. -Otherwise the array will not be filled and `SRT_ERROR` will be returned. - -This function can be used to get the group size by setting `output` to `NULL`, -and providing `socketgroup` and `inoutlen`. - -- Returns: - - * the number of data elements filled, on success - * -1, on error - -- Errors: - - * `SRT_EINVPARAM` reported if `socketgroup` is not an existing group ID - * `SRT_ELARGEMSG` reported if `inoutlen` if less than the size of the group - -| in:output | in:inoutlen | returns | out:output | out:inoutlen | Error | -|-----------|----------------|--------------|-----------|--------------|--------| -| NULL | NULL | -1 | NULL | NULL | `SRT_EINVPARAM` | -| NULL | ptr | 0 | NULL | group.size() | ✖️ | -| ptr | NULL | -1 | ✖️ | NULL | `SRT_EINVPARAM` | -| ptr | ≥ group.size | group.size() | group.data | group.size | ✖️ | -| ptr | < group.size | -1 | ✖️ | group.size | `SRT_ELARGEMSG` | - - -### srt_connect_group - -``` -int srt_connect_group(SRTSOCKET group, - SRT_SOCKGROUPCONFIG name [], int arraysize); -``` - -This function does almost the same as calling `srt_connect` or `srt_connect_bind` -(when the source was specified for `srt_prepare_endpoint`) in a loop for every -item specified in `name` array. However if you did this in blocking mode, the -first call to `srt_connect` would block until the connection is established, -whereas this function blocks until any of the specified connections is -established. - -If you set the group nonblocking mode (`SRTO_RCVSYN` option), there's no -difference, except that the `SRT_SOCKGROUPCONFIG` structure allows you -to add extra configuration data used by groups. Note also that this function -accepts only groups, not sockets. - -The elements of the `name` array need to be prepared with the use of the -[`srt_prepare_endpoint`](#srt_prepare_endpoint) function. Note that it is -**NOT** required that every target address you specify for it is of the same -family. - -Return value and errors in this function are the same as in `srt_connect`, -although this function reports success when at least one connection has -succeeded. If none has succeeded, this function reports `SRT_ECONNLOST` -error. Particular connection states can be obtained from the `name` -array upon return from the `errorcode` field. - -The fields of `SRT_SOCKGROUPCONFIG` structure have the following meaning: - -Input: - -* `id`: unused, should be -1 (default when created by `srt_prepare_endpoint`) -* `srcaddr`: address to bind before connecting, if specified (see below for details) -* `peeraddr`: target address to connect -* `weight`: weight value to be set on the link -* `config`: socket options to be set on the socket before connecting -* `errorcode`: unused, should be `SRT_SUCCESS` (default) -* `token`: An integer value unique for every connection, or -1 if unused - -Output: - -* `id`: The socket created for that connection (-1 if failed to create) -* `srcaddr`: unchanged -* `peeraddr`: unchanged -* `weight`: unchanged -* `config`: unchanged (the object should be manually deleted upon return) -* `errorcode`: status of connection for that link (`SRT_SUCCESS` if succeeded) -* `token`: same as in input, or a newly created token value if input was -1 - -The procedure of connecting for every connection definition specified -in the `name` array is performed the following way: - -1. The socket for this connection is first created - -2. Socket options derived from the group are set on that socket. - -3. If `config` is not NULL, configuration options stored there are set on that socket. - -4. If source address is specified (that is `srcaddr` value is **not** -default empty, as described in [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG)), -then the binding operation is being done on the socket (see `srt_bind`). - -5. The socket is added to the group as a member. - -6. The socket is being connected to the target address, as specified -in the `peeraddr` field. - -During this process there can be errors at any stage. There are two -possibilities as to what may happen in this case: - -1. If creation of a new socket has failed, which may only happen due to -problems with system resources, then the whole loop is interrupted and no -further items in the array are processed. All sockets that got created until -then, and for which the connection attempt has at least successfully started, -remain group members, although the function will return immediately with an -error status (that is, without waiting for the first successful connection). If -your application wants to do any partial recovery from this situation, it can -only use epoll mechanism to wait for readiness. - -2. In any other case, if an error occurs at any stage of the above process, the -processing is interrupted for this very array item only, the socket used for it -is immediately closed, and the processing of the next elements continues. In case -of connection process, it also passes two stages - parameter check and the process -itself. Failure at the parameter check breaks this process, while if this check -passed, this item is considered correctly processed, even if the connection -attempt is going to fail later. If this function is called in the blocking mode, -it then blocks until at least one connection reports success or if all of them -fail. Connections that continue in the background after this function exits can -be then checked status by [`srt_group_data`](#srt_group_data). - -As member socket connections are running in the background, for determining -if a particular connection has succeeded or failed it is recommended -to use [`srt_connect_callback`](#srt_connect_callback). In this case the -`token` callback function parameter will be the same as the `token` value used -for the particular item in the `name` connection table. - -The `token` value doesn't have any limitations except that the -1 value is -a "trap representation", that is, when set on input it will make the internals -define a unique value for the `token`. Your application can also set unique values, -in which case the `token` value will be preserved. - - -### srt_prepare_endpoint - -``` -SRT_SOCKGROUPCONFIG srt_prepare_endpoint(const struct sockaddr* src /*nullable*/, - const struct sockaddr* adr, int namelen); -``` - -This function prepares a default `SRT_SOCKGROUPCONFIG` object as an element -of the array you can prepare for `srt_connect_group` function, filled with -additional data: - -* `src`: address to which the newly created socket should be bound -* `adr`: address to which the newly created socket should connect -* `namelen`: size of both `src` and `adr` - -The following fields are set by this function: - -* `id`: -1 (unused for input) -* `srcaddr`: default empty (see below) or copied from `src` -* `peeraddr`: copied from `adr` -* `weight`: 0 -* `config`: `NULL` -* `errorcode`: `SRT_SUCCESS` - -The default empty `srcaddr` is set the following way: - -* `ss_family` set to the same value as `adr->sa_family` -* empty address (`INADDR_ANY` for IPv4 and `in6addr_any` for IPv6) -* port number 0 - -If `src` is not NULL, then `srcaddr` is copied from `src`. Otherwise -it will remain as default empty. - -The `adr` parameter is obligatory. If `src` parameter is not NULL, -then both `adr` and `src` must have the same value of `sa_family`. - -Note though that this function has no possibility of reporting errors - these -would be reported only by `srt_connect_group`, separately for every individual -connection, and the status can be obtained from `errorcode` field. - - -### srt_create_config - -``` -SRT_SOCKOPT_CONFIG* srt_create_config(); -``` - -Creates a dynamic object for specifying the socket options. You can -add options to be set on the socket by `srt_config_add` and then -mount this object into the `config` field in `SRT_SOCKGROUPCONFIG` -object for that particular connection. After the object is no -longer needed, you should delete it using `srt_delete_config`. - -Returns: - -* The pointer to the created object (memory allocation errors apply) - - -### srt_delete_config - -``` -void srt_delete_config(SRT_SOCKOPT_CONFIG* c); -``` - -Deletes the configurartion object. - - -### srt_config_add - -``` -int srt_config_add(SRT_SOCKOPT_CONFIG* c, SRT_SOCKOPT opt, void* val, int len); -``` - -Adds a configuration option to the configuration object. -Parameters have meanings similar to `srt_setsockflag`. Note -that not every option is allowed to be set this way. However, -the option (if allowed) isn't checked if it doesn't -violate other preconditions. This will be checked when the -option is being set on the socket, which may fail as a part -of the connection process done by `srt_connect_group`. - -This function should be used when this option must be set -individually on a socket and differently for particular link. -If you need to set some option the same way on every socket, -you should rather set this option on the whole group. - -The following options are allowed to be set on the member socket: - -* `SRTO_SNDBUF`: Allows for larger sender buffer for slower links -* `SRTO_RCVBUF`: Allows for larger receiver buffer for longer recovery -* `SRTO_UDP_RCVBUF`: UDP receiver buffer, if this link has a big flight window -* `SRTO_UDP_SNDBUF`: UDP sender buffer, if this link has a big flight window -* `SRTO_SNDDROPDELAY`: When particular link tends to drop too eagerly -* `SRTO_NAKREPORT`: If you don't want NAKREPORT to work for this link -* `SRTO_CONNTIMEO`: If you want to give more time to connect on this link -* `SRTO_LOSSMAXTTL`: If this link tends to suffer from UDP reordering -* `SRTO_PEERIDLETIMEO`: If you want to be more tolerant for temporary outages -* `SRTO_GROUPSTABTIMEO`: To set ACK jitter tolerance per individual link - - -Returns: 0 if succeeded, -1 when failed - -Errors: - -* `SRT_EINVPARAM`: this option is not allowed to be set on a socket -being a group member - -## Options and properties - -### srt_getpeername -``` -int srt_getpeername(SRTSOCKET u, struct sockaddr* name, int* namelen); -``` - -Retrieves the remote address to which the socket is connected. - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0 - -- Errors: - - * `SRT_EINVSOCK`: Socket `u` indicates no valid socket ID - * `SRT_ENOCONN`: Socket `u` isn't connected, so there's no remote address to return - -### srt_getsockname -``` -int srt_getsockname(SRTSOCKET u, struct sockaddr* name, int* namelen); -``` - -Extracts the address to which the socket was bound. Although you should know -the address(es) that you have used for binding yourself, this function can be -useful for extracting the local outgoing port number when it was specified as 0 -with binding for system autoselection. With this function you can extract the -port number after it has been autoselected. - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0 - -- Errors: - - * `SRT_EINVSOCK`: Socket `u` indicates no valid socket ID - * `SRT_ENOCONN`: Socket `u` isn't bound, so there's no local -address to return (**BUG?** It should rather be `SRT_EUNBOUNDSOCK`) - -### srt_getsockopt, srt_getsockflag -``` -int srt_getsockopt(SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT opt, void* optval, int* optlen); -int srt_getsockflag(SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen); -``` - -Gets the value of the given socket option (from a socket or a group). The first -version (`srt_getsockopt`) respects the BSD socket API convention, although the -"level" parameter is ignored. The second version (`srt_getsockflag`) omits the -"level" parameter completely. - -Options correspond to various data types, so you need to know what data type is -assigned to a particular option, and to pass a variable of the appropriate data -type. Specifications are provided in the `apps/socketoptions.hpp` file at the -`srt_options` object declaration. - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0 - -- Errors: - - * `SRT_EINVSOCK`: Socket `u` indicates no valid socket ID - * `SRT_EINVOP`: Option `opt` indicates no valid option - -### srt_setsockopt, srt_setsockflag - -``` -int srt_setsockopt(SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT opt, const void* optval, int optlen); -int srt_setsockflag(SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int optlen); -``` - -Sets a value for a socket option in the socket or group. The first version -(`srt_setsockopt`) respects the BSD socket API convention, although the "level" -parameter is ignored. The second version (`srt_setsockflag`) omits the "level" -parameter completely. - -Options correspond to various data types, so you need to know what data type is -assigned to a particular option, and to pass a variable of the appropriate data -type with the option value to be set. - -Please note that some of the options can only be set on sockets or only on -groups, although most of the options can be set on the groups so that they -are then derived by the member sockets. - -- Returns: - - * `SRT_ERROR` (-1) in case of error, otherwise 0 - --Errors: - - * `SRT_EINVSOCK`: Socket `u` indicates no valid socket ID - * `SRT_EINVOP`: Option `opt` indicates no valid option - * Various other errors that may result from problems when setting a specific - option (see option description for details). - -### srt_getversion - -``` -uint32_t srt_getversion(); -``` - -Get SRT version value. The version format in hex is 0xXXYYZZ for x.y.z in human readable form, -where x = ("%d", (version>>16) & 0xff), etc. - -- Returns: - - * srt version as an unsigned 32-bit integer - - -## Helper data types for transmission - -### SRT_MSGCTRL - -The `SRT_MSGCTRL` structure: - -```c++ -typedef struct SRT_MsgCtrl_ -{ - int flags; // Left for future - int msgttl; // TTL for a message, default -1 (no TTL limitation) - int inorder; // Whether a message is allowed to supersede partially lost one. Unused in stream and live mode. - int boundary; // 0:mid pkt, 1(01b):end of frame, 2(11b):complete frame, 3(10b): start of frame - int64_t srctime; // source time (microseconds since SRT internal clock epoch) - int32_t pktseq; // sequence number of the first packet in received message (unused for sending) - int32_t msgno; // message number (output value for both sending and receiving) - SRT_SOCKGROUPDATA* grpdata; // pointer to group data array - size_t grpdata_size; // size of the group array -} SRT_MSGCTRL; -``` - -The `SRT_MSGCTRL` structure is used in `srt_sendmsg2` and `srt_recvmsg2` calls -and specifies some special extra parameters: - -- `flags`: [IN, OUT]. RESERVED FOR FUTURE USE (should be 0). This is -intended to specify some special options controlling the details of how the -called function should work. - -- `msgttl`: [IN]. In **message** and **live mode** only, specifies the TTL for -sending messages (in `[ms]`). Not used for receiving messages. If this value -is not negative, it defines the maximum time up to which this message should -stay scheduled for sending for the sake of later retransmission. A message -is always sent for the first time, but the UDP packet carrying it may be -(also partially) lost, and if so, lacking packets will be retransmitted. If -the message is not successfully resent before TTL expires, further retransmission -is given up and the message is discarded. - -- `inorder`: [IN]. In **message mode** only, specifies that sent messages should -be extracted by the receiver in the order of sending. This can be meaningful if -a packet loss has happened, and a particular message must wait for retransmission -so that it can be reassembled and then delivered. When this flag is false, the -message can be delivered even if there are any previous messages still waiting -for completion. - -- `boundary`: RESERVED FOR FUTURE USE. Intended to be used in a special mode -when you are allowed to send or retrieve a part of the message. - -- `srctime`: - - [OUT] Receiver only. Specifies the time when the packet was intended to be -delivered to the receiving application (in microseconds since SRT clock epoch). - - [IN] Sender only. Specifies the application-provided timestamp to be asociated -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 (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 -UDP packet, only the sequence of the first one is reported. Note that in -**live mode** there's always one UDP packet per message. - -- `msgno`: Message number that can be sent by both sender and receiver, -although it is required that this value remain monotonic in subsequent send calls. -Normally message numbers start with 1 and increase with every message sent. - -- 'grpdata' and 'grpdata_size': Pointer and size of the group array. For single -socket connections these values should remain NULL and 0 respectively. When you -call `srt_sendmsg2` or `srt_recvmsg2` function for a group, you should pass an -array here so that you can retrieve the status of particular member sockets. -If you pass an array that is too small, your `grpdata_size` field will be rewritten with -the current number of members, but without filling in the array. For details, -see (Bonding introduction)[bonding-intro.md] and (Socket Groups)[socket-groups.md] -documents. - -**Helpers for `SRT_MSGCTRL`:** - -``` -void srt_msgctrl_init(SRT_MSGCTRL* mctrl); -const SRT_MSGCTRL srt_msgctrl_default; -``` - -Helpers for getting an object of `SRT_MSGCTRL` type ready to use. The first is -a function that fills the object with default values. The second is a constant -object and can be used as a source for assignment. Note that you cannot pass -this constant object into any of the API functions because they require it to be -mutable, as they use some fields to output values. - -## Transmission - -### srt_send, srt_sendmsg, srt_sendmsg2 -``` -int srt_send(SRTSOCKET u, const char* buf, int len); -int srt_sendmsg(SRTSOCKET u, const char* buf, int len, int ttl/* = -1*/, int inorder/* = false*/); -int srt_sendmsg2(SRTSOCKET u, const char* buf, int len, SRT_MSGCTRL *mctrl); -``` - -Sends a payload to a remote party over a given socket. - -* `u`: Socket used to send. The socket must be connected for this operation. -* `buf`: Points to the buffer containing the payload to send. -* `len`: Size of the payload specified in `buf`. -* `ttl`: Time (in `[ms]`) to wait for a successful delivery. See description of -the [`SRT_MSGCTRL::msgttl`](#SRT_MSGCTRL) field. -* `inorder`: Required to be received in the order of sending. See -[`SRT_MSGCTRL::inorder`](#SRT_MSGCTRL). -* `mctrl`: An object of [`SRT_MSGCTRL`](#SRT_MSGCTRL) type that contains extra -parameters, including `ttl` and `inorder`. - -The way this function works is determined by the mode set in options, and it has -specific requirements: - -1. In **file/stream mode**, the payload is byte-based. You are not required to -know the size of the data, although they are only guaranteed to be received -in the same byte order. - -2. In **file/message mode**, the payload that you send using this function is -a single message that you intend to be received as a whole. In other words, a -single call to this function determines a message's boundaries. - -3. In **live mode**, you are only allowed to send up to the length of -`SRTO_PAYLOADSIZE`, which can't be larger than 1456 bytes (1316 default). - -- Returns: - - * Size of the data sent, if successful. Note that in **file/stream mode** the -returned size may be less than `len`, which means that it didn't send the -whole contents of the buffer. You would need to call this function again -with the rest of the buffer next time to send it completely. In both -**file/message** and **live mode** the successful return is always equal to `len` - * In case of error, `SRT_ERROR` (-1) - -- Errors: - - * `SRT_ENOCONN`: Socket `u` used when the operation is not connected. - * `SRT_ECONNLOST`: Socket `u` used for the operation has lost its connection. - * `SRT_EINVALMSGAPI`: Incorrect API usage in **message mode**: - * **live mode**: trying to send more bytes at once than `SRTO_PAYLOADSIZE` - or wrong source time was provided. - * `SRT_EINVALBUFFERAPI`: Incorrect API usage in **stream mode**: - * Reserved for future use. The congestion controller object - used for this mode doesn't use any restrictions on this call for now, - but this may change in future. - * `SRT_ELARGEMSG`: Message to be sent can't fit in the sending buffer (that is, -it exceeds the current total space in the sending buffer in bytes). This means -that the sender buffer is too small, or the application is trying to send -a larger message than initially predicted. - * `SRT_EASYNCSND`: There's no free space currently in the buffer to schedule -the payload. This is only reported in non-blocking mode (`SRTO_SNDSYN` set -to false); in blocking mode the call is blocked until enough free space in -the sending buffer becomes available. - * `SRT_ETIMEOUT`: The condition described above still persists and the timeout -has passed. This is only reported in blocking mode when `SRTO_SNDTIMEO` is -set to a value other than -1. - * `SRT_EPEERERR`: This is reported only in the case where, as a stream is being - received by a peer, the `srt_recvfile` function encounters an error during a - write operation on a file. This is reported by a `UMSG_PEERERROR` message from - the peer, and the agent sets the appropriate flag internally. This flag - persists up to the moment when the connection is broken or closed. - -### srt_recv, srt_recvmsg, srt_recvmsg2 - -``` -int srt_recv(SRTSOCKET u, char* buf, int len); -int srt_recvmsg(SRTSOCKET u, char* buf, int len); -int srt_recvmsg2(SRTSOCKET u, char *buf, int len, SRT_MSGCTRL *mctrl); -``` - -Extracts the payload waiting to be received. Note that `srt_recv` and `srt_recvmsg` -are identical functions, two different names being kept for historical reasons. -In the UDT predecessor the application was required to use either the `UDT::recv` -version for **stream mode** and `UDT::recvmsg` for **message mode**. In SRT this -distinction is resolved internally by the `SRTO_MESSAGEAPI` flag. - -* `u`: Socket used to send. The socket must be connected for this operation. -* `buf`: Points to the buffer to which the payload is copied -* `len`: Size of the payload specified in `buf` -* `mctrl`: An object of [`SRT_MSGCTRL`](#SRT_MSGCTRL) type that contains extra -parameters - -The way this function works is determined by the mode set in options, and it has -specific requirements: - -1. In **file/stream mode**, as many bytes as possible are retrieved, that is, -only so many bytes that fit in the buffer and are currently available. Any -data that is available but not extracted this time will be available next time. - -2. In **file/message mode**, exactly one message is retrieved, with the -boundaries defined at the moment of sending. If some parts of the messages are -already retrieved, but not the whole message, nothing will be received (the -function blocks or returns `SRT_EASYNCRCV`). If the message to be returned does -not fit in the buffer, nothing will be received and the error is reported. - -3. In **live mode**, the function behaves as in **file/message mode**, although -the number of bytes retrieved will be at most the size of `SRTO_PAYLOADSIZE`. In -this mode, however, with default settings of `SRTO_TSBPDMODE` and `SRTO_TLPKTDROP`, -the message will be received only when its time to play has come, and until then -it will be kept in the receiver buffer; also, when the time to play has come -for a message that is next to the currently lost one, it will be delivered -and the lost one dropped. - -- Returns: - - * Size (\>0) of the data received, if successful. - * 0, if the connection has been closed - * `SRT_ERROR` (-1) when an error occurs - -- Errors: - - * `SRT_ENOCONN`: Socket `u` used for the operation is not connected. - * `SRT_ECONNLOST`: Socket `u` used for the operation has lost connection -(this is reported only if the connection was unexpectedly broken, not -when it was closed by the foreign host). - * `SRT_EINVALMSGAPI`: Incorrect API usage in **message mode**: - * **live mode**: size of the buffer is less than `SRTO_PAYLOADSIZE` - * `SRT_EINVALBUFFERAPI`: Incorrect API usage in **stream mode**: - * Currently not in use. File congestion control used for **stream mode** - does not restrict the parameters. **???** - * `SRT_ELARGEMSG`: Message to be sent can't fit in the sending buffer (that is, -it exceeds the current total space in the sending buffer in bytes). This means -that the sender buffer is too small, or the application is trying to send -a larger message than initially intended. - * `SRT_EASYNCRCV`: There are no data currently waiting for delivery. This -happens only in non-blocking mode (when `SRTO_RCVSYN` is set to false). In -blocking mode the call is blocked until the data are ready. How this is defined, -depends on the mode: - * In **live mode** (with `SRTO_TSBPDMODE` on), at least one packet must - be present in the receiver buffer and its time to play be in the past - * In **file/message mode**, one full message must be available, - * the next one waiting if there are no messages with `inorder` = false, or - possibly the first message ready with `inorder` = false - * In **file/stream mode**, it is expected to have at least one byte of data - still not extracted - * `SRT_ETIMEOUT`: The readiness condition described above is still not achieved -and the timeout has passed. This is only reported in blocking mode when -`SRTO_RCVTIMEO` is set to a value other than -1. - -### srt_sendfile, srt_recvfile - -``` -int64_t srt_sendfile(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block); -int64_t srt_recvfile(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block); -``` - -These are functions dedicated to sending and receiving a file. You need to call -this function just once for the whole file, although you need to know the size of -the file prior to sending and also define the size of a single block that should -be internally retrieved and written into a file in a single step. This influences -only the performance of the internal operations; from the application perspective -you just have one call that exits only when the transmission is complete. - -* `u`: Socket used for transmission. The socket must be connected. -* `path`: Path to the file that should be read or written. -* `offset`: Needed to pass or retrieve the offset used to read or write to a file -* `size`: Size of transfer (file size, if offset is at 0) -* `block`: Size of the single block to read at once before writing it to a file - -The following values are recommended for the `block` parameter: - -``` -#define SRT_DEFAULT_SENDFILE_BLOCK 364000 -#define SRT_DEFAULT_RECVFILE_BLOCK 7280000 -``` - -You need to pass them to the `srt_sendfile` or `srt_recvfile` function if you -don't know what value to chose. - -- Returns: - - * Size (\>0) of the transmitted data of a file. It may be less than `size`, if - the size was greater than the free space in the buffer, in which case you have - to send rest of the file next time. - * -1 in case of error. - -- Errors: - - * `SRT_ENOCONN`: Socket `u` used for the operation is not connected. - * `SRT_ECONNLOST`: Socket `u` used for the operation has lost its connection. - * `SRT_EINVALBUFFERAPI`: When socket has `SRTO_MESSAGEAPI` = true or - `SRTO_TSBPDMODE` = true. -(**BUG?**: Looxlike MESSAGEAPI isn't checked) - * `SRT_EINVRDOFF`: There is a mistake in `offset` or `size` parameters, which - should match the index availability and size of the bytes available since - `offset` index. This is actually reported for `srt_sendfile` when the `seekg` - or `tellg` operations resulted in error. - * `SRT_EINVWROFF`: Like above, reported for `srt_recvfile` and `seekp`/`tellp`. - * `SRT_ERDPERM`: The read from file operation has failed (`srt_sendfile`). - * `SRT_EWRPERM`: The write to file operation has failed (`srt_recvfile`). - -## Diagnostics - -General notes concerning the "getlasterror" diagnostic functions: when an API -function ends up with error, this error information is stored in a thread-local -storage. This means that you'll get the error of the operation that was last -performed as long as you call this diagnostic function just after the failed -function has returned. In any other situation the information provided by the -diagnostic function is undefined. - -### srt_getlasterror - -``` -int srt_getlasterror(int* errno_loc); -``` - -Get the numeric code of the last error. Additionally, in the variable passed as -`errno_loc` the system error value is returned, or 0 if there was no system error -associated with the last error. The system error is: - - * On POSIX systems, the value from `errno` - * On Windows, the result from `GetLastError()` call - - -### srt_strerror -``` -const char* srt_strerror(int code, int errnoval); -``` - -Returns a string message that represents a given SRT error code and possibly the -`errno` value, if not 0. - -**NOTE:** *This function isn't thread safe. It uses a static variable to hold the -error description. There's no problem with using it in a multithreaded environment, -as long as only one thread in the whole application calls this function at the -moment* - -### srt_getlasterror_str -``` -const char* srt_getlasterror_str(void); -``` - -Get the text message for the last error. It's a shortcut to calling first -`srt_getlasterror` and then passing the returned value into `srt_strerror`. -Note that, in contradiction to `srt_strerror`, this function is thread safe. - - -### srt_clearlasterror - -``` -void srt_clearlasterror(void); -``` - -This function clears the last error. After this call, the `srt_getlasterror` will -report a "successful" code. - -### srt_getrejectreason - -``` -int srt_getrejectreason(SRTSOCKET sock); -``` -This function provides a more detailed reason for the failed connection attempt. -It shall be called after a connecting function (such as `srt_connect`) -has returned an error, the code for which is `SRT_ECONNREJ`. If `SRTO_RCVSYN` -has been set on the socket used for the connection, the function should also be -called when the `SRT_EPOLL_ERR` event is set for this socket. It returns a -numeric code, which can be translated into a message by `srt_rejectreason_str`. -The following codes are currently reported: - -#### SRT_REJ_UNKNOWN - -A fallback value for cases when there was no connection rejected. - -#### SRT_REJ_SYSTEM - -One of system function reported a failure. Usually this means some system -error or lack of system resources to complete the task. - -#### SRT_REJ_PEER - -The connection has been rejected by peer, but no further details are available. -This usually means that the peer doesn't support rejection reason reporting. - -#### SRT_REJ_RESOURCE - -A problem with resource allocation (usually memory). - -#### SRT_REJ_ROGUE - -The data sent by one party to another cannot be properly interpreted. This -should not happen during normal usage, unless it's a bug, or some weird -events are happening on the network. - -#### SRT_REJ_BACKLOG - -The listener's backlog has exceeded (there are many other callers waiting for -the opportunity of being connected and wait in the queue, which has reached -its limit). - -#### SRT_REJ_IPE - -Internal Program Error. This should not happen during normal usage and it -usually means a bug in the software (although this can be reported by both -local and foreign host). - -#### SRT_REJ_CLOSE - -The listener socket was able to receive your request, but at this moment it -is being closed. It's likely that your next attempt will result with timeout. - -#### SRT_REJ_VERSION - -Any party of the connection has set up minimum version that is required for -that connection, and the other party didn't satisfy this requirement. - -#### SRT_REJ_RDVCOOKIE - -Rendezvous cookie collision. This normally should never happen, or the -probability that this will really happen is negligible. However this can -be also a result of a misconfiguration that you are trying to make a -rendezvous connection where both parties try to bind to the same IP -address, or both are local addresses of the same host - in which case -the sent handshake packets are returning to the same host as if they -were sent by the peer, who is this party itself. When this happens, -this reject reason will be reported by every attempt. - -#### SRT_REJ_BADSECRET - -Both parties have defined a passprhase for connection and they differ. - -#### SRT_REJ_UNSECURE - -Only one connection party has set up a password. See also -`SRTO_ENFORCEDENCRYPTION` flag in API.md. - -#### SRT_REJ_MESSAGEAPI - -The value for `SRTO_MESSAGEAPI` flag is different on both connection -parties. - -#### SRT_REJ_CONGESTION - -The `SRTO_CONGESTION` option has been set up differently on both -connection parties. - -#### SRT_REJ_FILTER - -The `SRTO_PACKETFILTER` option has been set differently on both connection -parties. - -#### SRT_REJ_GROUP - -The group type or some group settings are incompatible for both connection parties. -While every connection within a bonding group may have different target addresses, -they should all designate the same endpoint and the same SRT application. If this -condition isn't satisfied, then the peer will respond with a different peer group -ID for the connection that is trying to contact a machine/application that is -completely different from the existing connections in the bonding group. - -#### SRT_REJ_TIMEOUT - -The connection wasn't rejected, but it timed out. This code is always set on -connection timeout, but this is the only way to get this state in non-blocking -mode (see `SRTO_RCVSYN`). - -There may also be server and user rejection codes, -as defined by the `SRT_REJC_INTERNAL`, `SRT_REJC_PREDEFINED` and `SRT_REJC_USERDEFINED` -constants. Note that the number space from the value of `SRT_REJC_PREDEFINED` -and above is reserved for "predefined codes" (`SRT_REJC_PREDEFINED` value plus -adopted HTTP codes). Values above `SRT_REJC_USERDEFINED` are freely defined by -the application. - -### srt_rejectreason_str - -``` -const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); -``` - -Returns a constant string for the reason of the connection rejected, -as per given code ID. It provides a system-defined message for -values below `SRT_REJ_E_SIZE`. For other values below -`SRT_REJC_PREDEFINED` it returns the string for `SRT_REJ_UNKNOWN`. -For values since `SRT_REJC_PREDEFINED` on, returns -"Application-defined rejection reason". - -The actual messages assigned to the internal rejection codes, that is, -less than `SRT_REJ_E_SIZE`, can be also obtained from `srt_rejectreason_msg` -array. - -### srt_setrejectreason - -``` -int srt_setrejectreason(SRTSOCKET sock, int value); -``` - -Sets the rejection code on the socket. This call is only useful in the -listener callback. The code from `value` set this way will be set as a -rejection reason for the socket. After the callback rejects -the connection, the code will be passed back to the caller peer with the -handshake response. - -Note that allowed values for this function begin with `SRT_REJC_PREDEFINED` -(that is, you cannot set a system rejection code). -For example, your application can inform the calling side that the resource -specified under the `r` key in the StreamID string (see `SRTO_STREAMID`) -is not availble - it then sets the value to `SRT_REJC_PREDEFINED + 404`. - -- Returns: - * 0 in case of success. - * -1 in case of error. - -- Errors: - - * `SRT_EINVSOCK`: Socket `sock` is not an ID of a valid socket - * `SRT_EINVPARAM`: `value` is less than `SRT_REJC_PREDEFINED` - -### Error codes - -All functions that return the status via `int` value return -1 (designated as -`SRT_ERROR`) always when the call has failed (in case of resource creation -functions an appropriate symbol is defined, like `SRT_INVALID_SOCK` for -`SRTSOCKET`). When this happens, the error code can be obtained from the -`srt_getlasterror` function. The values for the error are collected in an -`SRT_ERRNO` enum: - -#### `SRT_EUNKNOWN` - -Internal error when setting the right error code. - -#### `SRT_SUCCESS` - -The value set when the last error was cleared and no error has occurred since then. - -#### `SRT_ECONNSETUP` - -General setup error resulting from internal system state. - -#### `SRT_ENOSERVER` - -Connection timed out while attempting to connect to the remote address. Note -that when this happens, `srt_getrejectreason` also reports the timeout reason. - -#### `SRT_ECONNREJ` - -Connection has been rejected. Additional reject reason can be obtained through -`srt_getrejectreason` (see above). - -#### `SRT_ESOCKFAIL` - -An error occurred when trying to call a system function on an internally used -UDP socket. Note that the detailed system error is available in the extra variable -passed by pointer to `srt_getlasterror`. - -#### `SRT_ESECFAIL` - -A possible tampering with the handshake packets was detected, or encryption -request wasn't properly fulfilled. - -#### `SRT_ESCLOSED` - -A socket that was vital for an operation called in blocking mode -has been closed during the operation. Please note that this situation is -handled differently than the system calls for `connect` and `accept` -functions for TCP, which simply block indefinitely (or until the standard -timeout) when the key socket was closed during an operation. When this -error is reported, it usually means that the socket passed as the first -parameter to `srt_connect*` or `srt_accept` is no longer usable. - - -#### `SRT_ECONNFAIL` - -General connection failure of unknown details. - -#### `SRT_ECONNLOST` - -The socket was properly connected, but the connection has been broken. -This specialzation is reported from the transmission functions. - -#### `SRT_ENOCONN` - -The socket is not connected. This can be reported also when the -connection was broken for a function that checks some characteristic -socket data. - -#### `SRT_ERESOURCE` - -System or standard library error reported unexpectedly for unknown purpose. -Usually it means some internal error. - -#### `SRT_ETHREAD` - -System was unable to spawn a new thread when requried. - -#### `SRT_ENOBUF` - -System was unable to allocate memory for buffers. - -#### `SRT_ESYSOBJ` - -System was unable to allocate system specific objects (such as -sockets, mutexes or condition variables). - -#### `SRT_EFILE` - -General filesystem error (for functions operating with file transmission). - -#### `SRT_EINVRDOFF` - -Failure when trying to read from a given position in the file (file could -be modified while it was read from). - -#### `SRT_ERDPERM` - -Read permission was denied when trying to read from file. - -#### `SRT_EINVWROFF` - -Failed to set position in the written file. - -#### `SRT_EWRPERM` - -Write permission was denied when trying to write to a file. - -#### `SRT_EINVOP` - -Invalid operation performed for the current state of a socket. This mainly -concerns performing `srt_bind*` operations on a socket that -is already bound. Once a socket has been been bound, it cannot be bound -again. - -#### `SRT_EBOUNDSOCK` - -The socket is currently bound and the required operation cannot be -performed in this state. Usually it's about an option that can only -be set on the socket before binding (`srt_bind*`). Note that a socket -that is currently connected is also considered bound. - -#### `SRT_ECONNSOCK` - -The socket is currently connected and therefore performing the required -operation is not possible. Usually concerns setting an option that must -be set before connecting (although it is allowed to be altered after -binding), or when trying to start a connecting operation (`srt_connect*`) -while the socket isn't in a state that allows it (only `SRTS_INIT` or -`SRTS_OPENED` are allowed). - -#### `SRT_EINVPARAM` - -This error is reported in a variety of situations when call parameters -for API functions have some requirements defined and these were not -satisfied. This error should be reported after an initial check of the -parameters of the call before even performing any operation. This error -can be easily avoided if you set the values correctly. - -#### `SRT_EINVSOCK` - -The API function required an ID of an entity (socket or group) and -it was invalid. Note that some API functions work only with socket or -only with group, so they would also return this error if inappropriate -type of entity was passed, even if it was valid. - -#### `SRT_EUNBOUNDSOCK` - -The operation to be performed on a socket requires that it first be -explicitly bound (using `srt_bind*` functions). Currently it applies when -calling `srt_listen`, which cannot work with an implicitly bound socket. - -#### `SRT_ENOLISTEN` - -The socket passed for the operation is required to be in the listen -state (`srt_listen` must be called first). - -#### `SRT_ERDVNOSERV` - -The required operation cannot be performed when the socket is set to -rendezvous mode (`SRTO_RENDEZVOUS` set to true). Usually applies when -trying to call `srt_listen` on such a socket. - -#### `SRT_ERDVUNBOUND` - -An attempt was made to connect to a socket set to rendezvous mode -(`SRTO_RENDEZVOUS` set to true) that was not first bound. A -rendezvous connection requires setting up two addresses and ports -on both sides of the connection, then setting the local one with `srt_bind` -and using the remote one with `srt_connect` (or you can simply -use `srt_rendezvous`). Calling `srt_connect*` on an unbound socket -(in `SRTS_INIT` state) that is to be bound implicitly is only allowed -for regular caller sockets (not rendezvous). - -#### `SRT_EINVALMSGAPI` - -The function was used incorrectly in the message API. This can happen if: - -* The parameters specific for the message API in `SRT_MSGCTRL` type parameter -were incorrectly specified - -* The extra parameter check performed by the congestion controller has -failed - -* The socket is a member of a self-managing group, therefore you should -perform the operation on the group, not on this socket - - -#### `SRT_EINVALBUFFERAPI` - -The function was used incorrectly in the stream (buffer) API, that is, -either the stream-only functions were used with set message API -(`srt_sendfile`/`srt_recvfile`) or TSBPD mode was used with buffer API -(`SRTO_TSBPDMODE` set to true) or the congestion controller has failed -to check call parameters. - -#### `SRT_EDUPLISTEN` - -The port tried to be bound for listening is already busy. Note that binding -to the same port is allowed in general (when `SRTO_REUSEADDR` is true on -every socket that bound it), but only one such socket can be a listener. - -#### `SRT_ELARGEMSG` - -Size exceeded. This is reported in the following situations: - -* Trying to receive a message, but the read-ready message is larger than -the buffer passed to the receiving function - -* Trying to send a message, but the size of this message exceeds the -size of the preset sender buffer, so it cannot be stored in the sender buffer. - -* With getting group data, the array to be filled is too small. - - -#### `SRT_EINVPOLLID` - -The epoll ID passed to an epoll function is invalid - -#### `SRT_EPOLLEMPTY` - -The epoll container currently has no subscribed sockets. This is reported by an -epoll waiting function that would in this case block forever. This problem -might be reported both in a situation where you have created a new epoll -container and didn't subscribe any sockets to it, or you did, but these -sockets have been closed (including when closed in a separate thread while the -waiting function was blocking). Note that this situation can be prevented -by setting the `SRT_EPOLL_ENABLE_EMPTY` flag, which may be useful when -you use multiple threads and start waiting without subscribed sockets, so that -you can subscribe them later from another thread. - -#### `SRT_EASYNCFAIL` - -General asynchronous failure (not in use currently). - - -#### `SRT_EASYNCSND` - -Sending operation is not ready to perform. This error is reported -when trying to perform a sending operation on a socket that is not -ready for sending, but `SRTO_SNDSYN` was set to false (when true, -the function would block the call otherwise). - -#### `SRT_EASYNCRCV` - -Receiving operation is not ready to perform. This error is reported -when trying to perform a receiving operation or accept a new socket from the -listener socket, when the socket is not ready for that operation, but -`SRTO_RCVSYN` was set to false (when true, the function would block -the call otherwise). - -#### `SRT_ETIMEOUT` - -The operation timed out. This can happen if you have a timeout -set by an option (`SRTO_RCVTIMEO` or `SRTO_SNDTIMEO`), or passed -as an extra argument (`srt_epoll_wait` or `srt_accept_bond`) and -the function call was blocking, but the required timeout time has passed. - -#### `SRT_ECONGEST` - -NOTE: This error is used only in an experimental version that requires -setting the `SRT_ENABLE_ECN` macro at compile time. Otherwise the -situation described below results in the usual successful report. - -This error should be reported by the sending function when, with -`SRTO_TSBPDMODE` and `SRTO_TLPKTDROP` set to true, some packets were dropped at -the sender side (see the description of `SRTO_TLPKTDROP` for details). This -doesn't concern the data that were passed for sending by the sending function -(these data are placed at the back of the sender buffer, while the dropped -packets are at the front). In other words, the operation done by the sending -function is successful, but the application might want to slow down the sending -rate to avoid congestion. - -#### `SRT_EPEERERR` - -This error is reported in a situation when the receiver peer is -writing to a file that the agent is sending. When the peer encounters -an error when writing the received data to a file, it sends the -`UMSG_PEERERROR` message back to the sender, and the sender reports -this error from the API sending function. - - - -## Performance tracking - -General note concerning sequence numbers used in SRT: they are 32-bit "circular -numbers" with the most significant bit not included. For example 0x7FFFFFFF -shifted forward by 3 becomes 2. As far as any comparison is concerned, it can -be thought of as a "distance" which is an integer -value expressing an offset to be added to one sequence in order to get the -second one. This distance is only valid as long as the threshold value isn't -exceeded, so it's stated that all sequence numbers that are anywhere taken into -account were systematically updated and they are kept in the range between 0 -and half of the maximum 0x7FFFFFFF. Hence the distance counting procedure -always assumes that the sequence number are in the required range already, so -for a numbers like 0x7FFFFFF0 and 0x10, for which the "numeric difference" -would be 0x7FFFFFE0, the "distance" is 0x20. - -### srt_bstats, srt_bistats -``` -// Performance monitor with Byte counters for better bitrate estimation. -int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear); - -// Performance monitor with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. -int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous); -``` - -Reports the current statistics - -* `u`: Socket from which to get statistics -* `perf`: Pointer to an object to be written with the statistics -* `clear`: 1 if the statistics should be cleared after retrieval -* `instantaneous`: 1 if the statistics should use instant data, not moving averages - -`SRT_TRACEBSTATS` is an alias to `struct CBytePerfMon`. For a complete description -of the fields please refer to the document [statistics.md](statistics.md). - -## Asynchronous operations (epoll) - -The epoll system is currently the only method for using multiple sockets in one -thread with having the blocking operation moved to epoll waiting so that it can -block on multiple sockets at once. That is, instead of blocking a single reading -or writing operation, as it's in blocking mode, it blocks until at least one of -the sockets subscribed for a single waiting call in given operation mode is ready -to do this operation without blocking. It's usually combined with setting the -nonblocking mode on a socket, which in SRT is set separately for reading and -writing (`SRTO_RCVSYN` and `SRTO_SNDSYN` respectively) in order to ensure that -in case of some internal error in the application (or even possibly a bug in SRT -that has reported a spurious readiness report) the operation will end up with -error rather than cause blocking, which would be more dangerous for the application -in this case (`SRT_EASYNCRCV` and `SRT_EASYNCRCV` respectively). - -The epoll system, similar to the one on Linux, relies on `eid` objects managed -internally in SRT, which can be subscribed to particular sockets and the -readiness status of particular operations. The `srt_epoll_wait` function can -then be used to block until any readiness status in the whole `eid` is set. - -### srt_epoll_create -``` -int srt_epoll_create(void); -``` - -Creates a new epoll container. - -- Returns: - - * valid EID on success - * -1 on failure - -- Errors: - - * `SRT_ECONNSETUP`: System operation failed or not enough space to create a new epoll. -System error might happen on systems that use a -special method for the system part of epoll (`epoll_create()`, `kqueue()`), and therefore associated resources, -like epoll on Linux. - -### srt_epoll_add_usock, srt_epoll_add_ssock, srt_epoll_update_usock, srt_epoll_update_ssock - -``` -int srt_epoll_add_usock(int eid, SRTSOCKET u, const int* events); -int srt_epoll_add_ssock(int eid, SYSSOCKET s, const int* events); -int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events); -int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events); -``` - -Adds a socket to a container, or updates an existing socket subscription. - -The `_usock` suffix refers to a user socket (SRT socket). -The `_ssock` suffix refers to a system socket. - -The `_add_` functions add new sockets. The `_update_` functions act on a socket -that is in the container already and just allow changes in the subscription -details. For example, if you have already subscribed a socket with `SRT_EPOLL_OUT` -to wait until it's connected, to change it into poll for read-readiness, you use -this function on that same socket with a variable set to `SRT_EPOLL_IN`. This -will not only change the event type which is polled on the socket, but also -remove any readiness status for flags that are no longer set. It is discouraged -to perform socket removal and adding back (instead of using `_update_`) because -this way you may miss an event that could happen in a short moment between -these two calls. - -* `eid`: epoll container id -* `u`: SRT socket -* `s`: system socket -* `events`: points to - * a variable set to epoll flags (see below) to use only selected events - * NULL if you want to subscribe a socket for all events in level-triggered mode - -Possible epoll flags are the following: - - * `SRT_EPOLL_IN`: report readiness for reading or incoming connection on a listener socket - * `SRT_EPOLL_OUT`: report readiness for writing or a successful connection - * `SRT_EPOLL_ERR`: report errors on the socket - * `SRT_EPOLL_UPDATE`: an important event has happened that requires attention - * `SRT_EPOLL_ET`: the event will be edge-triggered - -All flags except `SRT_EPOLL_ET` are event type flags (important for functions -that expect only event types and not other flags). - -The `SRT_EPOLL_IN`, `SRT_EPOLL_OUT` and `SRT_EPOLL_ERR` events are by default -**level-triggered**. With `SRT_EPOLL_ET` flag they become **edge-triggered**. - -The `SRT_EPOLL_UPDATE` flag is always edge-triggered. It designates a -special event that happens on a group, or on a listener socket that has the -`SRTO_GROUPCONNECT` flag set to allow group connections. This flag -is triggered in the following situations: - -* for group connections, when a new link has been established for a group that is already -connected (that is, has at least one connection established), `SRT_EPOLL_UPDATE` is -reported for the listener socket accepting the connection. This is intended for internal -use only. An initial connection results in reporting the group connection on that listener. -But when the group is already connected, `SRT_EPOLL_UPDATE` is reported instead. - -* when one of group member connection has been broken - -Note that at this time the edge-triggered mode is supported only for SRT -sockets, not for system sockets. - -In the **edge-triggered** mode the function will only return socket states that -have changed since the last call of the waiting function. All events reported -in particular call of the waiting function will be cleared in the internal -flags and will not be reported until the internal signaling logic clears this -state and raises it again. - -In the **level-triggered** mode the function will always return the readiness -state as long as it lasts, until the internal signaling logic clear it. - -Note that when you use `SRT_EPOLL_ET` flag in one subscription call, it defines -edge-triggered mode for all events passed together with it. However, if you -want to have some events reported as edge-triggered and others as -level-triggered, you can do two separate subscriptions for the same socket. - -**IMPORTANT**: The `srt_epoll_wait` function does not report -`SRT_EPOLL_UPDATE` events. If you need the ability to get any possible flag, -you must use `srt_epoll_uwait`. Note that this function doesn't work with -system file descriptors. - -- Returns: - - * 0 if successful, otherwise -1 - -- Errors: - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - -**BUG?**: for `add_ssock` the system error results in an empty `CUDTException()` -call which actually results in `SRT_SUCCESS`. For cases like that the -`SRT_ECONNSETUP` code is predicted. - -### srt_epoll_remove_usock, srt_epoll_remove_ssock - -``` -int srt_epoll_remove_usock(int eid, SRTSOCKET u); -int srt_epoll_remove_ssock(int eid, SYSSOCKET s); -``` - -Removes a specified socket from an epoll container and clears all readiness -states recorded for that socket. - -The `_usock` suffix refers to a user socket (SRT socket). -The `_ssock` suffix refers to a system socket. - -- Returns: - - * 0 if successful, otherwise -1 - -- Errors: - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - -### srt_epoll_wait -``` -int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, - SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); -``` - -Blocks the call until any readiness state occurs in the epoll container. - -Readiness can be on a socket in the container for the event type as per -subscription. Note that in case when particular event was subscribed with -`SRT_EPOLL_ET` flag, this event, when once reported in this function, will -be cleared internally. - -The first readiness state causes this function to exit, but all ready sockets -are reported. This function blocks until the timeout specified in `msTimeOut` -parameter. If timeout is 0, it exits immediately after checking. If timeout is --1, it blocks indefinitely until a readiness state occurs. - -* `eid`: epoll container -* `readfds` and `rnum`: A pointer and length of an array to write SRT sockets that are read-ready -* `writefds` and `wnum`: A pointer and length of an array to write SRT sockets that are write-ready -* `msTimeOut`: Timeout specified in milliseconds, or special values (0 or -1) -* `lwfds` and `lwnum`:A pointer and length of an array to write system sockets that are read-ready -* `lwfds` and `lwnum`:A pointer and length of an array to write system sockets that are write-ready - -Note that the following flags are reported: - -* `SRT_EPOLL_IN` as read-ready (also a listener socket ready to accept) -* `SRT_EPOLL_OUT` as write-ready (also a connected socket) -* `SRT_EPOLL_ERR` as both read-ready and write-ready -* `SRT_EPOLL_UPDATE` is not reported - -There is no space here to report sockets for which it's already known -that the operation will end up with error (athough such a state is known -internally). If an error occurred on a socket then that socket is reported in -both read-ready and write-ready arrays, regardless of what event types it was -subscribed for. Usually then you subscribe given socket for only read readiness, -for example (`SRT_EPOLL_IN`), but pass both arrays for read and write readiness. -This socket will not be reported in the write readiness array even if it's write -ready (because this isn't what it was subscribed for), but it will be reported -there, if the next operation on this socket is about to be erroneous. On such -sockets you can still perform an operation, just you should expect that it will -always report and error. On the other hand that's the only way to know what kind -of error has occurred on the socket. - -- Returns: - - * The number (\>0) of ready sockets, of whatever kind (if any) - * -1 in case of error - -- Errors: - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - * `SRT_ETIMEOUT`: Up to `msTimeOut` no sockets subscribed in `eid` were ready. -This is reported only if `msTimeOut` was \>=0, otherwise the function waits -indefinitely. - -### srt_epoll_uwait -``` -int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); -``` - -This function blocks a call until any readiness state occurs in the epoll -container. Unlike `srt_epoll_wait`, it can only be used with `eid` subscribed -to user sockets (SRT sockets), not system sockets. - -This function blocks until the timeout specified in `msTimeOut` parameter. If -timeout is 0, it exits immediately after checking. If timeout is -1, it blocks -indefinitely until a readiness state occurs. - -* `eid`: epoll container -* `fdsSet` : A pointer to an array of `SRT_EPOLL_EVENT` -* `fdsSize` : The size of the fdsSet array -* `msTimeOut` : Timeout specified in milliseconds, or special values (0 or -1): - * 0: Don't wait, return immediately (report any sockets currently ready) - * -1: Wait indefinitely. - -- Returns: - - * The number of user socket (SRT socket) state changes that have been reported -in `fdsSet`, if this number isn't greater than `fdsSize` - - * Otherwise the return value is `fdsSize` + 1. This means that there was not -enough space in the output array to report all events. For events subscribed with -`SRT_EPOLL_ET` flag only those will be cleared that were reported. Others will -wait for the next call. - - * If no readiness state was found on any socket and the timeout has passed, 0 -is returned (this is not possible when waiting indefinitely) - - * -1 in case of error - - -- Errors: - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - * `SRT_EINVPARAM`: One of possible usage errors: - * `fdsSize` is < 0 - * `fdsSize` is > 0 and `fdsSet` is a null pointer - * `eid` was subscribed to any system socket - -(IMPORTANT: this function reports timeout by returning 0, not by `SRT_ETIMEOUT` error.) - -The `SRT_EPOLL_EVENT` structure: - -``` -typedef struct SRT_EPOLL_EVENT_ -{ - SRTSOCKET fd; - int events; -} SRT_EPOLL_EVENT; -``` - -* `fd` : the user socket (SRT socket) -* `events` : event flags that report readiness of this socket - a combination -of `SRT_EPOLL_IN`, `SRT_EPOLL_OUT` and `SRT_EPOLL_ERR` - see [srt_epoll_add_usock](#srt_epoll_add_usock) -for details - -Note that when the `SRT_EPOLL_ERR` is set, the underlying socket error -can't be retrieved with `srt_getlasterror()`. The socket will be automatically -closed and its state can be verified with a call to `srt_getsockstate`. - -### srt_epoll_clear_usocks -``` -int srt_epoll_clear_usocks(int eid); -``` - -This function removes all SRT ("user") socket subscriptions from the epoll -container identified by `eid`. - -- Returns: - * 0 on success - * -1 in case of error - -- Errors: - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - -### srt_epoll_set -``` -int32_t srt_epoll_set(int eid, int32_t flags); -``` - -This function allows to set or retrieve flags that change the default -behavior of the epoll functions. All default values for these flags are 0. -The following flags are available: - -* `SRT_EPOLL_ENABLE_EMPTY`: allows the `srt_epoll_wait` and `srt_epoll_uwait` -functions to be called with the EID not subscribed to any socket. The default -behavior of these function is to report error in this case. - -* `SRT_EPOLL_ENABLE_OUTPUTCHECK`: Forces the `srt_epoll_wait` and `srt_epoll_uwait` -functions to check if the output array is not empty. For `srt_epoll_wait` it -is still allowed that either system or user array is empty, as long as EID -isn't subscribed to this type of socket/fd. `srt_epoll_uwait` only checks if -the general output array is not empty. - -- Parameters: - - * `eid`: the epoll container id - * `flags`: a nonzero set of the above flags, or special values: - * 0: clear all flags (set all defaults) - * -1: do not modify any flags - -- Returns: - -This function returns the state of the flags at the time before the call, -or a special value -1 in case when an error occurred. - -- Errors: - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - - -### srt_epoll_release -``` -int srt_epoll_release(int eid); -``` - -Deletes the epoll container. - -- Returns: - - * The number (\>0) of ready sockets, of whatever kind (if any) - * -1 in case of error - -- Errors: - - - * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container - -## Logging control - -SRT has a widely used system of logs, as this is usually the only way to determine -how the internals are working, without changing the rules by the act of tracing. -Logs are split into levels (5 levels out of those defined by syslog are in use) -and additional filtering is possible on FA (functional area). By default only -up to the *Note* log level are displayed and from all FAs. - -Logging can only be manipulated globally, with no regard to a specific -socket. This is because lots of operations in SRT are not dedicated to any -particular socket, and some are shared between sockets. - -### srt_setloglevel - -``` -void srt_setloglevel(int ll); -``` - -Sets the minimum severity for logging. A particular log entry is displayed only -if it has a severity greater than or equal to the minimum. Setting this value -to `LOG_DEBUG` turns on all levels. - -The constants for this value are those from `` -(for Windows, refer to `common/win/syslog_defs.h`). The only meaningful are: - -* `LOG_DEBUG`: Highly detailed and very frequent messages -* `LOG_NOTICE`: Occasionally displayed information -* `LOG_WARNING`: Unusual behavior -* `LOG_ERR`: Abnormal behavior -* `LOG_CRIT`: Error that makes the current socket unusable - -### srt_addlogfa, srt_dellogfa, srt_resetlogfa - -```c++ -void srt_addlogfa(int fa); -void srt_dellogfa(int fa); -void srt_resetlogfa(const int* fara, size_t fara_size); -``` - -A functional area (FA) is an additional filtering mechanism for logging. You can -set up logging to display logs only from selected FAs. The list of FAs is -collected in `srt.h` file, as identified by the `SRT_LOGFA_` prefix. They are not -enumerated here because they may be changed very often. - - -All FAs are turned on by default, except potentially dangerous ones -(such as `SRT_LOGFA_HAICRYPT`). The reaons is that they may display either -some security information that shall remain in the memory only (so, only -if strictly required for the development), or some duplicated information -(so you may want to turn this FA on, while turning off the others). - -### srt_setloghandler - -```c++ -void srt_setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); -typedef void SRT_LOG_HANDLER_FN(void* opaque, int level, const char* file, int line, const char* area, const char* message); -``` - -By default logs are printed to standard error stream. This function replaces -the sending to a stream with a handler function that will receive them. - -### srt_setlogflags - -```c++ -void srt_setlogflags(int flags); -``` - -When you set a log handler with `srt_setloghandler`, you may also want to -configure which parts of the log information you do not wish to be passed -in the log line (the `message` parameter). A user's logging facility may, -for example, not wish to get the current time or log level marker, as it -will provide this information on its own. - - -The following flags are available, as collected in `logging_api.h` public header: - -- `SRT_LOGF_DISABLE_TIME`: Do not provide the time in the header -- `SRT_LOGF_DISABLE_THREADNAME`: Do not provide the thread name in the header -- `SRT_LOGF_DISABLE_SEVERITY`: Do not provide severity information in the header -- `SRT_LOGF_DISABLE_EOL`: Do not add the end-of-line character to the log line - -## Time Access - -The following set of functions is intended to retrieve timestamps from the clock used by SRT. -The sender can pass the timestamp in `MSGCTRL::srctime` of the `srt_sendmsg2(..)` -function together with the packet being submitted to SRT. -If the `srctime` value is not provided (the default value of 0 is set), SRT will use internal -clock and assign the packet submission time as the packet timestamp. -If the sender wants to explicitly assign a timestamp -to a certain packet. this timestamp MUST be taken from SRT Time Access functions. -The time value provided MUST equal or exceed the connection start time (`srt_connection_time(..)`) -of the SRT socket passed to `srt_sendmsg2(..)`. - -The current time value as of the SRT internal clock can be retrieved using the `srt_time_now()` function. - -There are two known cases where you might want to use `srctime`: - -1. SRT passthrough (for stream gateways). -You may wish to simply retrieve packets from an SRT source and pass them transparently -to an SRT output (possibly re-encrypting). In that case, every packet you read -should preserve the original value of `srctime` as obtained from `srt_recvmsg2`, -and the original `srctime` for each packet should be then passed to `srt_sendmsg2`. -This mechanism could be used to avoid jitter resulting from varying differences between -the time of receiving and sending the same packet. - -2. Stable timing source. -In the case of a live streaming procedure, when spreading packets evenly into the stream, -you might want to predefine times for every single packet to keep time intervals perfectly equal. -Or, if you believe that your input signal delivers packets at the exact times that should be -assigned to them, you might want to preserve these times at the SRT receiving side -to avoid jitter that may result from varying time differences between the packet arrival -and the moment when sending it over SRT. In such cases you might do the following: - - - At the packet arrival time, grab the current time at that moment using `srt_time_now()`. - - - When you want a precalculated packet time, use a private relative time counter - set at the moment when the connection was made. From the moment when your first packet - is ready, start precalculating packet times relative to the connection start time obtained - from `srt_connection_time()`. Although you still have to synchronize sending times with these - predefined times, by explicitly specifying the source time you avoid the jitter - resulting from a lost accuracy due to waiting time and unfortunate thread scheduling. - -Note that `srctime` uses an internally defined clock -that is intended to be monotonic (the definition depends on the build flags, -see below). Because of that **the application should not define this time basing -on values obtained from the system functions for getting the current system time** -(such as `time`, `ftime` or `gettimeofday`). To avoid problems and -misunderstanding you should rely exclusively on time values provided by -`srt_time_now()` and `srt_connection_time()` functions. - -The clock used by SRT internal clock, is determined by the following build flags: -- `ENABLE_MONOTONIC` makes use of `CLOCK_MONOTONIC` with `clock_gettime` function. -- `ENABLE_STDXXX_SYNC` makes use of `std::chrono::steady_clock`. - -The default is currently to use the system clock as internal SRT clock, -although it's highly recommended to use one of the above monotonic clocks, -as system clock is vulnerable to time modifications during transmission. - -### srt_time_now - -```c++ -int64_t srt_time_now(); -``` - -Get time in microseconds elapsed since epoch using SRT internal clock (steady or monotonic clock). - -- Returns: - - Current time in microseconds elapsed since epoch of SRT internal clock. - -### srt_connection_time - -```c++ -int64_t srt_connection_time(SRTSOCKET sock); -``` - -Get connection time in microseconds elapsed since epoch using SRT internal clock (steady or monotonic clock). -The connection time represents the time when SRT socket was open to establish a connection. -Milliseconds elapsed since connection start time can be determined using [**Performance tracking**](#Performance-tracking) -functions and `msTimeStamp` value of the `SRT_TRACEBSTATS` (see [statistics.md](statistics.md)). - -- Returns: - - Connection time in microseconds elapsed since epoch of SRT internal clock. - - -1 in case of error - -- Errors: - - `SRT_EINVSOCK`: Socket `sock` is not an ID of a valid SRT socket - -[RETURN TO TOP OF PAGE](#SRT-API-Functions) diff --git a/docs/API/API-functions.md b/docs/API/API-functions.md new file mode 100644 index 000000000..74fbc506f --- /dev/null +++ b/docs/API/API-functions.md @@ -0,0 +1,3446 @@ +# SRT API Functions + +

Library Initialization

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_startup](#srt_startup) | Called at the start of an application that uses the SRT library | +| [srt_cleanup](#srt_cleanup) | Cleans up global SRT resources before exiting an application | +| | | + + +

Creating and Configuring Sockets

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_socket](#srt_socket) | Deprecated | +| [srt_create_socket](#srt_create_socket) | Creates an SRT socket | +| [srt_bind](#srt_bind) | Binds a socket to a local address and port | +| [srt_bind_acquire](#srt_bind_acquire) | Acquires a given UDP socket instead of creating one | +| [srt_getsockstate](#srt_getsockstate) | Gets the current status of the socket | +| [srt_getsndbuffer](#srt_getsndbuffer) | Retrieves information about the sender buffer | +| [srt_close](#srt_close) | Closes the socket or group and frees all used resources | +| | | + +

Connecting

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_listen](#srt_listen) | Sets up the listening state on a socket | +| [srt_accept](#srt_accept) | Accepts a connection; creates/returns a new socket or group ID | +| [srt_accept_bond](#srt_accept_bond) | Accepts a connection pending on any sockets passed in the `listeners` array
of `nlisteners` size | +| [srt_listen_callback](#srt_listen_callback) | Installs/executes a callback hook on a socket created to handle the incoming connection
on a listening socket | +| [srt_connect](#srt_connect) | Connects a socket or a group to a remote party with a specified address and port | +| [srt_connect_bind](#srt_connect_bind) | Same as [`srt_bind`](#srt_bind) then [`srt_connect`](#srt_connect) if called with socket [`u`](#u) | +| [srt_connect_debug](#srt_connect_debug) | Same as [`srt_connect`](#srt_connect)but allows specifying ISN (developers only) | +| [srt_rendezvous](#srt_rendezvous) | Performs a rendezvous connection | +| [srt_connect_callback](#srt_connect_callback) | Installs/executes a callback hook on socket/group [`u`](#u) after connection resolution/failure | +| | | + +

Socket Group Management

+ +Since SRT v1.5.0. + +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [SRT_GROUP_TYPE](#SRT_GROUP_TYPE) | Group types collected in an [`SRT_GROUP_TYPE`](#SRT_GROUP_TYPE) enum | +| [SRT_SOCKGROUPCONFIG](#SRT_SOCKGROUPCONFIG) | Structure used to define entry points for connections for [`srt_connect_group`](#srt_connect_group) | +| [SRT_SOCKGROUPDATA](#SRT_SOCKGROUPDATA) | Most important structure for group member status | +| [SRT_MEMBERSTATUS](#SRT_MEMBERSTATUS) | Enumeration type that defines the state of a member connection in the group | +| [srt_create_group](#srt_create_group) | Creates a new group of type `type` | +| [srt_groupof](#srt_groupof) | Returns the group ID of a socket, or `SRT_INVALID_SOCK` | +| [srt_group_data](#srt_group_data) | Obtains the current member state of the group specified in `socketgroup` | +| [srt_connect_group](#srt_connect_group) | Similar to calling [`srt_connect`](#srt_connect) or [`srt_connect_bind`](#srt_connect_bind)
in a loop for every item in an array. | +| [srt_prepare_endpoint](#srt_prepare_endpoint) | Prepares a default [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG) object as an element of
an array for [`srt_connect_group`](#srt_connect_group) | +| [srt_create_config](#srt_create_config) | Creates a dynamic object for specifying socket options | +| [srt_delete_config](#srt_delete_config) | Deletes the configuration object | +| [srt_config_add](#srt_config_add) | Adds a configuration option to the configuration object | +| | | + +

Options and Properties

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_getpeername](#srt_getpeername) | Retrieves the remote address to which the socket is connected | +| [srt_getsockname](#srt_getsockname) | Extracts the address to which the socket was bound | +| [srt_getsockopt](#srt_getsockopt) | Gets the value of the given socket option (from a socket or a group) | +| [srt_getsockflag](#srt_getsockflag) | Gets the value of the given socket option (from a socket or a group) | +| [srt_setsockopt](#srt_setsockopt) | Sets a value for a socket option in the socket or group | +| [srt_setsockflag](#srt_setsockflag) | Sets a value for a socket option in the socket or group | +| [srt_getversion](#srt_getversion) | Get SRT version value | +| | | + +

Helper Data Types for Transmission

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [SRT_MSGCTRL](#SRT_MSGCTRL) | Used in [`srt_sendmsg2`](#srt_sendmsg) and [`srt_recvmsg2`](#srt_recvmsg2) calls;
specifies some extra parameters | +| | | + +

Transmission

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_send](#srt_send) | Sends a payload to a remote party over a given socket | +| [srt_sendmsg](#srt_sendmsg) | Sends a payload to a remote party over a given socket | +| [srt_sendmsg2](#srt_sendmsg2) | Sends a payload to a remote party over a given socket | +| [srt_recv](#srt_recv) | Extracts the payload waiting to be received | +| [srt_recvmsg](#srt_recvmsg) | Extracts the payload waiting to be received | +| [srt_recvmsg2](#srt_recvmsg2) | Extracts the payload waiting to be received | +| [srt_sendfile](#srt_sendfile) | Function dedicated to sending a file | +| [srt_recvfile](#srt_recvfile) | Function dedicated to receiving a file | +| | | + +

Performance Tracking

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_bstats](#srt_bstats) | Reports the current statistics | +| [srt_bistats](#srt_bistats) | Reports the current statistics | +| | | + +

Asynchronous Operations (Epoll)

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_epoll_create](#srt_epoll_create) | Creates a new epoll container | +| [srt_epoll_add_usock](#srt_epoll_add_usock) | Adds a user socket to a container, or updates an existing socket subscription | +| [srt_epoll_add_ssock](#srt_epoll_add_ssock) | Adds a system socket to a container, or updates an existing socket subscription | +| [srt_epoll_update_usock](#srt_epoll_update_usock) | Adds a user socket to a container, or updates an existing socket subscription | +| [srt_epoll_update_ssock](#srt_epoll_update_ssock) | Adds a system socket to a container, or updates an existing socket subscription | +| [srt_epoll_remove_usock](#srt_epoll_remove_usock) | Removes a specified user socket from an epoll container; clears all readiness states for that socket | +| [srt_epoll_remove_ssock](#srt_epoll_remove_ssock) | Removes a specified system socket from an epoll container; clears all readiness states for that socket | +| [srt_epoll_wait](#srt_epoll_wait) | Blocks the call until any readiness state occurs in the epoll container | +| [srt_epoll_uwait](#srt_epoll_uwait) | Blocks a call until any readiness state occurs in the epoll container | +| [srt_epoll_clear_usocks](#srt_epoll_clear_usocks) | removes all SRT ("user") socket subscriptions from the epoll container identified by [`eid`](#eid) | +| [srt_epoll_set](#srt_epoll_set) | Allows setting or retrieving flags that change the default behavior of the epoll functions | +| [srt_epoll_release](#srt_epoll_release) | Deletes the epoll container | +| | | + +

Logging Control

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_setloglevel](#srt_setloglevel) | Sets the minimum severity for logging | +| [srt_addlogfa](#srt_addlogfa) | Add a functional area (FA), which is an additional filtering mechanism for logging | +| [srt_dellogfa](#srt_dellogfa) | Delete a functional area (FA), which is an additional filtering mechanism for logging | +| [srt_resetlogfa](#srt_resetlogfa) | Reset a functional area (FA), which is an additional filtering mechanism for logging | +| [srt_setloghandler](#srt_setloghandler) | Replaces default standard stream for error logging | +| [srt_setlogflags](#srt_setlogflags) | Allows configuring parts of log information that are not to be passed | +| | | + +

Time Access

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_time_now](#srt_time_now) | Get time in microseconds elapsed since epoch using SRT internal clock
(steady or monotonic clock) | +| [srt_connection_time](#srt_connection_time) | Get connection time in microseconds elapsed since epoch using SRT internal clock
(steady or monotonic clock) | +| [srt_clock_type](#srt_clock_type) | Get the type of clock used internally by SRT | +| | | + +

Diagnostics

+ +| *Function / Structure* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +| [srt_getlasterror](#srt_getlasterror) | Get the numeric code of the last error | +| [srt_strerror](#srt_strerror) | Returns a string message that represents a given SRT error code and possibly
the `errno` value, if not 0 | +| [srt_getlasterror_str](#srt_getlasterror_str) | Gets the text message for the last error | +| [srt_clearlasterror](#srt_clearlasterror) | Clears the last error | +| [srt_rejectreason_str](#srt_rejectreason_str) | Returns a constant string for the reason of the connection rejected, as per given code ID | +| [srt_setrejectreason](#srt_setrejectreason) | Sets the rejection code on the socket | +| [srt_getrejectreason](#srt_getrejectreason) | Provides a detailed reason for a failed connection attempt | +| | | + +

Rejection Reasons

+ +| *Rejection Reason* | *Since* | *Description* | +|:-------------------------------------------- |:--------- |:-------------------------------------------------------------------------------------------------------------- | +| [SRT_REJ_UNKNOWN](#SRT_REJ_UNKNOWN) | 1.3.4 | A fallback value for cases when there was no connection rejected | +| [SRT_REJ_SYSTEM](#SRT_REJ_SYSTEM) | 1.3.4 | A system function reported a failure | +| [SRT_REJ_PEER](#SRT_REJ_PEER) | 1.3.4 | The connection has been rejected by peer, but no further details are available | +| [SRT_REJ_RESOURCE](#SRT_REJ_RESOURCE) | 1.3.4 | A problem with resource allocation (usually memory) | +| [SRT_REJ_ROGUE](#SRT_REJ_ROGUE) | 1.3.4 | The data sent by one party to another cannot be properly interpreted | +| [SRT_REJ_BACKLOG](#SRT_REJ_BACKLOG) | 1.3.4 | The listener's backlog has exceeded | +| [SRT_REJ_IPE](#SRT_REJ_IPE) | 1.3.4 | Internal Program Error | +| [SRT_REJ_CLOSE](#SRT_REJ_CLOSE) | 1.3.4 | The listener socket received a request as it is being closed | +| [SRT_REJ_VERSION](#SRT_REJ_VERSION) | 1.3.4 | A party did not satisfy the minimum version requirement that had been set up for a connection | +| [SRT_REJ_RDVCOOKIE](#SRT_REJ_RDVCOOKIE) | 1.3.4 | Rendezvous cookie collision | +| [SRT_REJ_BADSECRET](#SRT_REJ_BADSECRET) | 1.3.4 | Both parties have defined a passphrase for connection and they differ | +| [SRT_REJ_UNSECURE](#SRT_REJ_UNSECURE) | 1.3.4 | Only one connection party has set up a password | +| [SRT_REJ_MESSAGEAPI](#SRT_REJ_MESSAGEAPI) | 1.3.4 | The value for [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) flag is different on both connection parties | +| [SRT_REJ_FILTER](#SRT_REJ_FILTER) | 1.3.4 | The [`SRTO_PACKETFILTER`](API-socket-options.md#SRTO_PACKETFILTER) option has been set differently on both connection parties | +| [SRT_REJ_GROUP](#SRT_REJ_GROUP) | 1.4.2 | The group type or some group settings are incompatible for both connection parties | +| [SRT_REJ_TIMEOUT](#SRT_REJ_TIMEOUT) | 1.4.2 | The connection wasn't rejected, but it timed out | +| [SRT_REJ_CRYPTO](#SRT_REJ_CRYPTO) | 1.5.2 | The connection was rejected due to an unsupported or mismatching encryption mode | +| | | | + +See the full list in [Rejection Reason Codes](./rejection-codes.md). + +

Error Codes

+ +| *Error Code* | *Description* | +|:------------------------------------------------- |:-------------------------------------------------------------------------------------------------------------- | +[`SRT_EUNKNOWN`](#srt_eunknown) | Internal error when setting the right error code | +[`SRT_SUCCESS`](#srt_success) | The value set when the last error was cleared and no error has occurred since then | +[`SRT_ECONNSETUP`](#srt_econnsetup) | General setup error resulting from internal system state | +[`SRT_ENOSERVER`](#srt_enoserver) | Connection timed out while attempting to connect to the remote address | +[`SRT_ECONNREJ`](#srt_econnrej) | Connection has been rejected | +[`SRT_ESOCKFAIL`](#srt_esockfail) | An error occurred when trying to call a system function on an internally used UDP socket | +[`SRT_ESECFAIL`](#srt_esecfail) | A possible tampering with the handshake packets was detected, or encryption request
wasn't properly fulfilled. | +[`SRT_ESCLOSED`](#srt_esclosed) | A socket that was vital for an operation called in blocking mode has been closed
during the operation | +[`SRT_ECONNFAIL`](#srt_econnfail) | General connection failure of unknown details | +[`SRT_ECONNLOST`](#srt_econnlost) | The socket was properly connected, but the connection has been broken | +[`SRT_ENOCONN`](#srt_enoconn) | The socket is not connected | +[`SRT_ERESOURCE`](#srt_eresource) | System or standard library error reported unexpectedly for unknown purpose | +[`SRT_ETHREAD`](#srt_ethread) | System was unable to spawn a new thread when required | +[`SRT_ENOBUF`](#srt_enobuf) | System was unable to allocate memory for buffers | +[`SRT_ESYSOBJ`](#srt_esysobj) | System was unable to allocate system specific objects | +[`SRT_EFILE`](#srt_efile) | General filesystem error (for functions operating with file transmission) | +[`SRT_EINVRDOFF`](#srt_einvrdoff) | Failure when trying to read from a given position in the file | +[`SRT_ERDPERM`](#srt_erdperm) | Read permission was denied when trying to read from file | +[`SRT_EINVWROFF`](#srt_einvwroff) | Failed to set position in the written file | +[`SRT_EWRPERM`](#srt_ewrperm) | Write permission was denied when trying to write to a file | +[`SRT_EINVOP`](#srt_einvop) | Invalid operation performed for the current state of a socket | +[`SRT_EBOUNDSOCK`](#srt_eboundsock) | The socket is currently bound and the required operation cannot be performed in this state | +[`SRT_ECONNSOCK`](#srt_econnsock) | The socket is currently connected and therefore performing the required operation is not possible | +[`SRT_EINVPARAM`](#srt_einvparam) | Call parameters for API functions have some requirements that were not satisfied | +[`SRT_EINVSOCK`](#srt_einvsock) | The API function required an ID of an entity (socket or group) and it was invalid | +[`SRT_EUNBOUNDSOCK`](#srt_eunboundsock) | The operation to be performed on a socket requires that it first be explicitly bound | +[`SRT_ENOLISTEN`](#srt_enolisten) | The socket passed for the operation is required to be in the listen state | +[`SRT_ERDVNOSERV`](#srt_erdvnoserv) | The required operation cannot be performed when the socket is set to rendezvous mode | +[`SRT_ERDVUNBOUND`](#srt_erdvunbound) | An attempt was made to connect to a socket set to rendezvous mode that was not first bound | +[`SRT_EINVALMSGAPI`](#srt_einvalmsgapi) | The function was used incorrectly in the message API | +[`SRT_EINVALBUFFERAPI`](#srt_einvalbufferapi) | The function was used incorrectly in the stream (buffer) API | +[`SRT_EDUPLISTEN`](#srt_eduplisten) | The port tried to be bound for listening is already busy | +[`SRT_ELARGEMSG`](#srt_elargemsg) | Size exceeded | +[`SRT_EINVPOLLID`](#srt_einvpollid) | The epoll ID passed to an epoll function is invalid | +[`SRT_EPOLLEMPTY`](#srt_epollempty) | The epoll container currently has no subscribed sockets | +[`SRT_EASYNCFAIL`](#srt_easyncfail) | General asynchronous failure (not in use currently) | +[`SRT_EASYNCSND`](#srt_easyncsnd) | Sending operation is not ready to perform | +[`SRT_EASYNCRCV`](#srt_easyncrcv) | Receiving operation is not ready to perform | +[`SRT_ETIMEOUT`](#srt_etimeout) | The operation timed out | +[`SRT_ECONGEST`](#srt_econgest) | With [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) and [`SRTO_TLPKTDROP`](API-socket-options.md#SRTO_TLPKTDROP) set to true,
some packets were dropped by sender | +[`SRT_EPEERERR`](#srt_epeererr) | Receiver peer is writing to a file that the agent is sending | +| | | + + + +## Library Initialization + +* [srt_startup](#srt_startup) +* [srt_cleanup](#srt_cleanup) + + +### srt_startup +``` +int srt_startup(void); +``` + +This function shall be called at the start of an application that uses the SRT +library. It provides all necessary platform-specific initializations, sets up +global data, and starts the SRT GC thread. If this function isn't explicitly +called, it will be called automatically when creating the first socket. However, +relying on this behavior is strongly discouraged. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------------- | +| 0 | Successfully run, or already started | +| 1 | This is the first startup, but the GC thread is already running | +| -1 | Failed | +| | | + +| Errors | | +|:----------------------------- |:--------------------------------------------------------------- | +| [`SRT_ECONNSETUP`](#srt_econnsetup) | With error code set, reported when required system resource(s) failed to initialize.
This is currently used only on Windows to report a failure from `WSAStartup`. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_cleanup +``` +int srt_cleanup(void); +``` + +This function cleans up all global SRT resources and shall be called just before +exiting the application that uses the SRT library. This cleanup function will still +be called from the C++ global destructor, if not called by the application, although +relying on this behavior is strongly discouraged. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------------- | +| 0 | A possibility to return other values is reserved for future use | +| | | + +**IMPORTANT**: Note that the startup/cleanup calls have an instance counter. +This means that if you call [`srt_startup`](#srt_startup) multiple times, you need to call the +`srt_cleanup` function exactly the same number of times. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Creating and Configuring Sockets + +* [srt_socket](#srt_socket) +* [srt_create_socket](#srt_create_socket) +* [srt_bind](#srt_bind) +* [srt_bind_acquire](#srt_bind_acquire) +* [srt_getsockstate](#srt_getsockstate) +* [srt_getsndbuffer](#srt_getsndbuffer) +* [srt_close](#srt_close) + + +### srt_socket +``` +SRTSOCKET srt_socket(int af, int type, int protocol); +``` + +Old and deprecated version of [`srt_create_socket`](#srt_create_socket). All arguments are ignored. + +**NOTE** changes with respect to UDT version: + +* In UDT (and SRT versions before 1.4.2) the `af` parameter was specifying the +socket family (`AF_INET` or `AF_INET6`). This is now not required; this parameter +is decided at the call of [`srt_connect`](#srt_connect) or [`srt_bind`](#srt_bind). + +* In UDT the `type` parameter was used to specify the file or message mode +using `SOCK_STREAM` or `SOCK_DGRAM` symbols (with the latter being misleading, +as the message mode has nothing to do with UDP datagrams and it's rather +similar to the SCTP protocol). In SRT these two modes are available by setting +[`SRTO_TRANSTYPE`](API-socket-options.md#SRTO_TRANSTYPE). The default is `SRTT_LIVE`. If, however, you set +[`SRTO_TRANSTYPE`](API-socket-options.md#SRTO_TRANSTYPE) to `SRTT_FILE` for file mode, you can then leave the +[`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) option as false (default), which corresponds to "stream" mode +(TCP-like), or set it to true, which corresponds to "message" mode (SCTP-like). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_create_socket +``` +SRTSOCKET srt_create_socket(); +``` + +Creates an SRT socket. + +Note that socket IDs always have the `SRTGROUP_MASK` bit clear. + +| Returns | | +|:----------------------------- |:------------------------------------------------------- | +| Socket ID | A valid socket ID on success | +| `SRT_INVALID_SOCK` | (`-1`) on error | +| | | + +| Errors | | +|:----------------------------- |:------------------------------------------------------------ | +| [`SRT_ENOBUF`](#srt_enobuf) | Not enough memory to allocate required resources . | +| | | + +**NOTE:** This is probably a design flaw (:warning:   **BUG?**). Usually underlying system +errors are reported by [`SRT_ECONNSETUP`](#srt_econnsetup). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + + +--- + +### srt_bind +``` +int srt_bind(SRTSOCKET u, const struct sockaddr* name, int namelen); +``` + +Binds a socket to a local address and port. Binding specifies the local network +interface and the UDP port number to be used for the socket. When the local +address is a wildcard (`INADDR_ANY` for IPv4 or `in6addr_any` for IPv6), then +it's bound to all interfaces. + +**IMPORTANT**: When you bind an IPv6 wildcard address, note that the +`SRTO_IPV6ONLY` option must be set on the socket explicitly to 1 or 0 prior to +calling this function. See +[`SRTO_IPV6ONLY`](API-socket-options.md#SRTO_IPV6ONLY) for more details. + +Binding is necessary for every socket to be used for communication. If the socket +is to be used to initiate a connection to a listener socket, which can be done, +for example, by the [`srt_connect`](#srt_connect) function, the socket is bound +implicitly to the wildcard address according to the IP family (`INADDR_ANY` for +`AF_INET` or `in6addr_any` for `AF_INET6`) and port number 0. In all other cases, +a socket must be bound explicitly by using the functionality of this function first. + +When the port number parameter is 0, then the effective port number will be +system-allocated. To obtain this effective port number you can use +[`srt_getsockname`](#srt_getsockname). + +This call is obligatory for a listening socket before calling [`srt_listen`](#srt_listen) +and for rendezvous mode before calling [`srt_connect`](#srt_connect); otherwise it's +optional. For a listening socket it defines the network interface and the port where +the listener should expect a call request. + +In the case of rendezvous mode there are two parties that connect to one another. +For every party there must be chosen a local binding endpoint (local address and port) +to which they expect connection from the peer. Let's say, we have a Party 1 +that selects an endpoint A and a Party 2 that selects an endpoint B. In this case the Party 1 +binds the socket to the endpoint A and then connects to the endpoint B, and the Party 2 +the other way around. Both sockets must be set +[`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) to *true* to make +this connection possible. + +For a connecting socket the call to `srt_bind` is optional, but can be used to set up the +outgoing port for communication as well as the local interface through which +it should reach out to the remote endpoint, should that be necessary. + +Whether binding is possible depends on some runtime conditions, in particular: + +* No socket in the system has been bound to this port ("free binding"), or + +* A socket bound to this port is bound to a certain address, and this binding is + using a different non-wildcard address ("side binding"), or + +* A socket bound to this port is bound to a wildcard address for a different IP + version than the version requested for this binding ("side wildcard binding", + see also `SRTO_IPV6ONLY` socket option). + +It is also possible to bind to the already busy port as long as the existing +binding ("shared binding") is possessed by an SRT socket created in the same +application, and: + +* Its binding address and UDP-related socket options match the socket to be bound. +* Its [`SRTO_REUSEADDR`](API-socket-options.md#SRTO_REUSEADDRS) is set to *true* (default). + +If none of the free, side and shared binding options is currently possible, this function +will fail. If the socket blocking the requested endpoint is an SRT +socket in the current application, it will report the `SRT_EBINDCONFLICT` error, +while if it was another socket in the system, or the problem was in the system +in general, it will report `SRT_ESOCKFAIL`. Here is the table that shows possible situations: + +| Requested binding | vs. Existing bindings... | | | | | +|---------------------|------------------------------|-----------|-----------------------------|---------------|---------------| +| | A.B.C.D | 0.0.0.0 | ::X | :: / V6ONLY=1 | :: / V6ONLY=0 | +| 1.2.3.4 | 1.2.3.4 shareable, else free | blocked | free | free | blocked | +| 0.0.0.0 | blocked | shareable | free | free | blocked | +| 8080::1 | free | free | 8080::1 sharable, else free | blocked | blocked | +| :: / V6ONLY=1 | free | free | blocked | sharable | blocked | +| :: / V6ONLY=0 | blocked | blocked | blocked | blocked | sharable | + +Where: + +* free: This binding can coexist with the requested binding. + +* blocked: This binding conflicts with the requested binding. + +* shareable: This binding can be shared with the requested binding if it's compatible. + +* (ADDRESS) shareable, else free: this binding is shareable if the existing binding address is +equal to the requested ADDRESS. Otherwise it's free. + +If the binding is shareable, then the operation will succeed if the socket that currently +occupies the binding has the `SRTO_REUSEADDR` option set to true (default) and all UDP +settings are the same as in the current socket. Otherwise it will fail. Shared binding means +sharing the underlying UDP socket and communication queues between SRT sockets. If +all existing bindings on the same port are "free" then the requested binding will +allocate a distinct UDP socket for this SRT socket ("side binding"). + +**NOTE**: This function cannot be called on a socket group. If you need to +have the group-member socket bound to the specified source address before +connecting, use [`srt_connect_bind`](#srt_connect_bind) for that purpose +or set the appropriate source address using +[`srt_prepare_endpoint`](#srt_prepare_endpoint). + +**IMPORTANT information about IPv6**: If you are going to bind to the +`in6addr_any` IPv6 wildcard address (known as `::`), the `SRTO_IPV6ONLY` +option must be first set explicitly to 0 or 1, otherwise the binding +will fail. In all other cases this option is meaningless. See `SRTO_IPV6ONLY` +option for more information. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) on error, otherwise 0 | +| | | + +| Errors | | +|:---------------------------------------- |:-------------------------------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket passed as [`u`](#u) designates no valid socket | +| [`SRT_EINVOP`](#srt_einvop) | Socket already bound | +| [`SRT_EINVPARAM`](#srt_einvparam) | Invalid `name`/`namelen` or invalid `SRTO_IPV6ONLY` flag in `u` | +| [`SRT_ECONNSETUP`](#srt_econnsetup) | Internal creation of a UDP socket failed | +| [`SRT_ESOCKFAIL`](#srt_esockfail) | Internal configuration of a UDP socket (`bind`, `setsockopt`) failed | +| [`SRT_EBINDCONFLICT`](#srt_ebindconflict)| Binding specification conflicts with existing one | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_bind_acquire + +``` +int srt_bind_acquire(SRTSOCKET u, UDPSOCKET udpsock); +``` + +A version of [`srt_bind`](#srt_bind) that acquires a given UDP socket instead of creating one. + +The UDP socket being acquired MUST NOT be a [connected socket](https://man7.org/linux/man-pages/man2/connect.2.html) +(not associated with the socket name of a peer), +because SRT needs to be able to set the destination address by itself. +See [#2178](https://github.com/Haivision/srt/issues/2178) for more information. + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getsockstate + +``` +SRT_SOCKSTATUS srt_getsockstate(SRTSOCKET u); +``` + +Gets the current status of the socket. Possible states are: + +| State | Description | +|:----------------------------------------------- |:----------------------------------------------------------------- | +| `SRTS_INIT` | Created, but not bound. | +| `SRTS_OPENED` | Created and bound, but not in use yet. | +| `SRTS_LISTENING` | Socket is in listening state. | +| `SRTS_CONNECTING` | The connect operation was initiated, but not yet finished. This may also mean that it has timed out;
you can only know that after getting a socket error report from [`srt_epoll_wait`](#srt_epoll_wait). In blocking mode
it's not possible because [`srt_connect`](#srt_connect) does not return until the socket is connected or failed due
to timeout or interrupted call. | +| `SRTS_CONNECTED` | The socket is connected and ready for transmission. | +| `SRTS_BROKEN` | The socket was connected, but the connection was broken. | +| `SRTS_CLOSING` | The socket may still be open and active, but closing is requested, so no further operations will
be accepted (active operations will be completed before closing) | +| `SRTS_CLOSED` | The socket has been closed, but not yet removed by the GC thread. | +| `SRTS_NONEXIST` | The specified number does not correspond to a valid socket. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getsndbuffer + +``` +int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); +``` + +Retrieves information about the sender buffer. + +**Arguments**: + +* `sock`: Socket to test +* `blocks`: Written information about buffer blocks in use +* `bytes`: Written information about bytes in use + +This function can be used for diagnostics. It is especially useful when the +socket needs to be closed asynchronously. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_close + +``` +int srt_close(SRTSOCKET u); +``` + +Closes the socket or group and frees all used resources. Note that underlying +UDP sockets may be shared between sockets, so these are freed only with the +last user closed. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0 | +| | | + +| Errors | | +|:------------------------------- |:----------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid socket ID | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Connecting + +* [srt_listen](#srt_listen) +* [srt_accept](#srt_accept) +* [srt_accept_bond](#srt_accept_bond) +* [srt_listen_callback](#srt_listen_callback) +* [srt_connect](#srt_connect) +* [srt_connect_bind](#srt_connect_bind) +* [srt_connect_debug](#srt_connect_debug) +* [srt_rendezvous](#srt_rendezvous) +* [srt_connect_callback](#srt_connect_callback) + +### srt_listen +``` +int srt_listen(SRTSOCKET u, int backlog); +``` + +This sets up the listening state on a socket with a backlog setting that +defines how many sockets may be allowed to wait until they are accepted +(excessive connection requests are rejected in advance). + +The following important options may change the behavior of the listener +socket and the [`srt_accept`](#srt_accept) function: + +* [`srt_listen_callback`](#srt_listen_callback) installs a user function that will +be called before [`srt_accept`](#srt_accept) can happen +* [`SRTO_GROUPCONNECT`](API-socket-options.md#SRTO_GROUPCONNECT) option allows +the listener socket to accept group connections + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0. | +| | | + +| Errors | | +|:--------------------------------------- |:-------------------------------------------------------------------------------------------- | +| [`SRT_EINVPARAM`](#srt_einvparam) | Value of `backlog` is 0 or negative. | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid SRT socket. | +| [`SRT_EUNBOUNDSOCK`](#srt_eunboundsock) | [`srt_bind`](#srt_bind) has not yet been called on that socket. | +| [`SRT_ERDVNOSERV`](#srt_erdvnoserv) | [`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) flag is set to true on specified socket. | +| [`SRT_EINVOP`](#srt_einvop) | Internal error (should not happen when [`SRT_EUNBOUNDSOCK`](#srt_eunboundsock) is reported). | +| [`SRT_ECONNSOCK`](#srt_econnsock) | The socket is already connected. | +| [`SRT_EDUPLISTEN`](#srt_eduplisten) | The address used in [`srt_bind`](#srt_bind) by this socket is already occupied by another listening socket.
Binding multiple sockets to one IP address and port is allowed, as long as
[`SRTO_REUSEADDR`](API-socket-options.md#SRTO_REUSEADDRS) is set to true, but only one of these sockets can be set up as a listener. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_accept + +``` +SRTSOCKET srt_accept(SRTSOCKET lsn, struct sockaddr* addr, int* addrlen); +``` + +Accepts a pending connection, then creates and returns a new socket or +group ID that handles this connection. The group and socket can be +distinguished by checking the `SRTGROUP_MASK` bit on the returned ID. + +* `lsn`: the listener socket previously configured by [`srt_listen`](#srt_listen) +* `addr`: the IP address and port specification for the remote party +* `addrlen`: INPUT: size of `addr` pointed object. OUTPUT: real size of the +returned object + +**NOTE:** `addr` is allowed to be NULL, in which case it's understood that the +application is not interested in the address from which the connection originated. +Otherwise `addr` should specify an object into which the address will be written, +and `addrlen` must also specify a variable to contain the object size. Note also +that in the case of group connection only the initial connection that +establishes the group connection is returned, together with its address. As +member connections are added or broken within the group, you can obtain this +information through [`srt_group_data`](#srt_group_data) or the data filled by +[`srt_sendmsg2`](#srt_sendmsg) and [`srt_recvmsg2`](#srt_recvmsg2). + +If the `lsn` listener socket is configured for blocking mode +([`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) set to true, default), +the call will block until the incoming connection is ready. Otherwise, the +call always returns immediately. The `SRT_EPOLL_IN` epoll event should be +checked on the `lsn` socket prior to calling this function in that case. + +If the pending connection is a group connection (initiated on the peer side by +calling the connection function using a group ID, and permitted on the listener +socket by the [`SRTO_GROUPCONNECT`](API-socket-options.md#SRTO_GROUPCONNECT) +flag), then the value returned is a group ID. This function then creates a new +group, as well as a new socket for this connection, that will be added to the +group. Once the group is created this way, further connections within the same +group, as well as sockets for them, will be created in the background. The +[`SRT_EPOLL_UPDATE`](#SRT_EPOLL_UPDATE) event is raised on the `lsn` socket when +a new background connection is attached to the group, although it's usually for +internal use only. + +| Returns | | +|:----------------------------- |:----------------------------------------------------------------------- | +| socket/group ID | On success, a valid SRT socket or group ID to be used for transmission. | +| `SRT_INVALID_SOCK` | (-1) on failure | +| | | + +| Errors | | +|:--------------------------------- |:----------------------------------------------------------------------- | +| [`SRT_EINVPARAM`](#srt_einvparam) | NULL specified as `addrlen`, when `addr` is not NULL | +| [`SRT_EINVSOCK`](#srt_einvsock) | `lsn` designates no valid socket ID. | +| [`SRT_ENOLISTEN`](#srt_enolisten) | `lsn` is not set up as a listener ([`srt_listen`](#srt_listen) not called). | +| [`SRT_EASYNCRCV`](#srt_easyncrcv) | No connection reported so far. This error is reported only in the non-blocking mode | +| [`SRT_ESCLOSED`](#srt_esclosed) | The `lsn` socket has been closed while the function was blocking the call. Including when the socket was closed just at the
moment when a connection was made (i.e., the socket got closed during processing) | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_accept_bond + +``` +SRTSOCKET srt_accept_bond(const SRTSOCKET listeners[], int nlisteners, int msTimeOut); +``` + +Accepts a pending connection, like [`srt_accept`](#srt_accept), but pending on any of the +listener sockets passed in the `listeners` array of `nlisteners` size. + +**Arguments**: + +* `listeners`: array of listener sockets (all must be setup by [`srt_listen`](#srt_listen)) +* `nlisteners`: size of the `listeners` array +* `msTimeOut`: timeout in [ms] or -1 to block forever + +This function is for blocking mode only - for non-blocking mode you should simply +call [`srt_accept`](#srt_accept) on the first listener socket that reports readiness, +and this function is actually a friendly shortcut that uses waiting on epoll and +[`srt_accept`](#srt_accept) internally. This function supports an important use +case for accepting a group connection, for which every member connection is expected +to be established over a different listener socket. + +Note that there's no special set of settings required or rejected for this function. +Group-member connections for the same group can always be established over various +different listener sockets when all those listeners are hosted by the same application. +The group management is global for the application, so a connection reporting in for +an already connected group gets discovered, and the connection will be handled in the +background. This occurs regardless of which listener socket the call was made to, +as long as the connection is accepted according to any additional conditions. + +This function has nothing to do with the groups. You can use it in any case when +you have one service that accepts connections to multiple endpoints. Note also +that the settings as to whether listeners should accept or reject socket or group +connections should be applied to the listener sockets appropriately prior to +calling this function. + +| Returns | | +|:----------------------------- |:---------------------------------------------------------------------- | +| SRT socket
group ID | On success, a valid SRT socket or group ID to be used for transmission | +| `SRT_INVALID_SOCK` | (-1) on failure | +| | | + +| Errors | | +|:--------------------------------- |:------------------------------------------------------------ | +| [`SRT_EINVPARAM`](#srt_einvparam) | NULL specified as `listeners` or `nlisteners` < 1 | +| [`SRT_EINVSOCK`](#srt_einvsock) | Any socket in `listeners` designates no valid socket ID. Can also mean *Internal Error* when
an error occurred while creating an accepted socket (:warning:   **BUG?**) | +| [`SRT_ENOLISTEN`](#srt_enolisten) | Any socket in `listeners` is not set up as a listener ([`srt_listen`](#srt_listen) not called, or the listener socket
has already been closed) | +| [`SRT_ETIMEOUT`](#srt_etimeout) | No connection reported on any listener socket as the timeout has been reached. This error is only
reported when `msTimeOut` is not -1 | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_listen_callback + +``` +int srt_listen_callback(SRTSOCKET lsn, srt_listen_callback_fn* hook_fn, void* hook_opaque); +``` + +This call installs a callback hook, which will be executed on a socket that is +automatically created to handle the incoming connection on the listening socket +(and is about to be returned by [`srt_accept`](#srt_accept)), but before the +connection has been accepted. + +**Arguments**: + +* `lsn`: Listening socket where you want to install the callback hook +* `hook_fn`: The callback hook function pointer (or NULL to remove the callback) +* `hook_opaque`: The pointer value that will be passed to the callback function + +| Returns | | +|:----------------------------- |:---------------------------------------------------------- | +| 0 | Successful | +| -1 | Error | +| | | + +| Errors | | +|:--------------------------------- |:----------------------------------------- | +| [`SRT_ECONNSOCK`](#srt_econnsock) | It can't be modified in a connected socket| +| | | + +The callback function has the signature as per this type definition: +``` +typedef int srt_listen_callback_fn(void* opaque, SRTSOCKET ns, int hs_version + const struct sockaddr* peeraddr, const char* streamid); +``` + +The callback function gets the following parameters passed: + +* `opaque`: The pointer passed as `hook_opaque` when registering +* `ns`: The freshly created socket to handle the incoming connection +* `hs_version`: The handshake version (usually 5, pre-1.3 versions of SRT use 4) +* `peeraddr`: The address of the incoming connection +* `streamid`: The value set to [`SRTO_STREAMID`](API-socket-options.md#SRTO_STREAMID) option set on the peer side + +Note that SRT versions that use handshake version 4 are incapable of using +any extensions, such as `streamid`. However they do support encryption. +Note also that the SRT version isn't extracted at this point. However you can +prevent connections with versions that are too old by using the +[`SRTO_MINVERSION`](API-socket-options.md#SRTO_MINVERSION) option. + +The callback function is given an opportunity to: + +* use the passed information (`streamid` and peer address) to decide + what to do with this connection +* alter any options on the socket, which could not be set properly + beforehand on the listening socket to be derived by the accepted socket, + and won't be allowed to be altered after the socket is returned by + [`srt_accept`](#srt_accept) + +Note that normally the returned socket has already set all derived options from +the listener socket. The moment when this callback is called is when the conclusion +handshake has been already received from the caller party, but not yet interpreted +(the `streamid` field is extracted from it prematurely). When, for example, you set +a passphrase on the socket at this point, the Key Material processing will happen +against this passphrase, after the callback function is finished. + +The callback function shall return 0, if the connection is to be accepted. +If you return -1, **or** if the function throws an exception, this will be +understood as a request to reject the incoming connection. In this case the +about-to-be-accepted socket will be silently deleted and [`srt_accept`](#srt_accept) +will not report it. Note that in case of non-blocking mode the epoll bits for +read-ready on the listener socket will not be set if the connection is rejected, +including when rejected from this user function. + +**IMPORTANT**: This function is called in the receiver worker thread, which +means that it must do its checks and operations as quickly as possible. Every +delay you create in this function will burden the processing of the incoming data +on the associated UDP socket. In the case of a listener socket this means the +listener socket itself and every socket accepted off this listener socket. +Avoid any extensive search operations. It is best to cache in memory whatever +database you have to check against the data received in `streamid` or `peeraddr`. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_connect + +``` +int srt_connect(SRTSOCKET u, const struct sockaddr* name, int namelen); +``` + +Connects a socket or a group to a remote party with a specified address and port. + +**Arguments**: + +* [`u`](#u): can be an SRT socket or SRT group, both freshly created and not yet + used for any connection, except possibly [`srt_bind`](#srt_bind) on the socket +* `name`: specification of the remote address and port +* `namelen`: size of the object passed by `name` + +**NOTES:** + +1. The socket used here may be [bound by `srt_bind`](#srt_bind) before connecting, +or binding and connection can be done in one function ([`srt_connect_bind`](#srt_connect_bind)), +such that it uses a predefined network interface or local outgoing port. This is optional +in the case of a caller-listener arrangement, but obligatory for a rendezvous arrangement. +If not used, the binding will be done automatically to `INADDR_ANY` (which binds on all +interfaces) and port 0 (which makes the system assign the port automatically). + +2. This function is used for both connecting to the listening peer in a caller-listener +arrangement, and calling the peer in rendezvous mode. For the latter, the +[`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) flag must be set +to true prior to calling this function, and binding, as described in #1, +is in this case obligatory (see `SRT_ERDVUNBOUND` below). + +3. When [`u`](#u) is a group, then this call can be done multiple times, each time +for another member connection, and a new member SRT socket will be created +automatically for every call of this function. + +4. If you want to connect a group to multiple links at once and use blocking +mode, you might want to use [`srt_connect_group`](#srt_connect_group) instead. +This function also allows you to use additional settings, available only for groups. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error | +| 0 | In case when used for [`u`](#u) socket | +| Socket ID | Created for connection for [`u`](#u) group | +| | | + +| Errors | | +|:------------------------------------- |:----------------------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid socket ID | +| [`SRT_ERDVUNBOUND`](#srt_erdvunbound) | Socket [`u`](#u) is in rendezvous mode, but it wasn't bound (see note #2) | +| [`SRT_ECONNSOCK`](#srt_econnsock) | Socket [`u`](#u) is already connected | +| [`SRT_ECONNREJ`](#srt_econnrej) | Connection has been rejected | +| [`SRT_ENOSERVER`](#srt_enoserver) | Connection has been timed out (see [`SRTO_CONNTIMEO`](API-socket-options.md#SRTO_CONNTIMEO)) | +| [`SRT_ESCLOSED`](#srt_esclosed) | The socket [`u`](#u) has been closed while the function was blocking the call | +| | | + +If the `u` socket is configured for blocking mode (when +[`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) is set to true, default), +the call will block until the connection succeeds or fails. The "early" errors +[`SRT_EINVSOCK`](#srt_einvsock), [`SRT_ERDVUNBOUND`](#srt_erdvunbound) and +[`SRT_ECONNSOCK`](#srt_econnsock) are reported in both modes immediately. Other +errors are "late" failures and can only be reported in blocking mode. + +In non-blocking mode, a successful connection can be recognized by the +`SRT_EPOLL_OUT` epoll event flag and a "late" failure by the `SRT_EPOLL_ERR` +flag. Note that the socket state in the case of a failed connection remains +`SRTS_CONNECTING` in that case. + +In the case of "late" failures you can additionally call +[`srt_getrejectreason`](#srt_getrejectreason) to get detailed error +information. Note that in blocking mode only for the `SRT_ECONNREJ` error +this function may return any additional information. In non-blocking +mode a detailed "late" failure cannot be distinguished, and therefore it +can also be obtained from this function. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_connect_bind + +``` +int srt_connect_bind(SRTSOCKET u, const struct sockaddr* source, + const struct sockaddr* target, int len); +``` + +This function does the same as first [`srt_bind`](#srt_bind) then +[`srt_connect`](#srt_connect), if called with [`u`](#u) being a socket. +If [`u`](#u) is a group, then it will execute [`srt_bind`](#srt_bind) +first on the automatically created socket for the connection. + +**Arguments**: + +* [`u`](#u): Socket or group to connect +* `source`: Address to bind [`u`](#u) to +* `target`: Address to connect +* `len`: size of the original structure of `source` and `target` + +| Returns | | +|:----------------------------- |:-------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error | +| 0 | In case when used for [`u`](#u) socket | +| Socket ID | Created for connection for [`u`](#u) group | +| | | + +| Errors | | +|:---------------------------------------- |:-------------------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket passed as [`u`](#u) designates no valid socket | +| [`SRT_EINVOP`](#srt_einvop) | Socket already bound | +| [`SRT_ECONNSETUP`](#srt_econnsetup) | Internal creation of a UDP socket failed | +| [`SRT_ESOCKFAIL`](#srt_esockfail) | Internal configuration of a UDP socket (`bind`, `setsockopt`) failed | +| [`SRT_ERDVUNBOUND`](#srt_erdvunbound) | Internal error ([`srt_connect`](#srt_connect) should not report it after [`srt_bind`](#srt_bind) was called) | +| [`SRT_ECONNSOCK`](#srt_econnsock) | Socket [`u`](#u) is already connected | +| [`SRT_ECONNREJ`](#srt_econnrej) | Connection has been rejected | +| [`SRT_EBINDCONFLICT`](#srt_ebindconflict)| Binding specification conflicts with existing one | +| | | + + +**IMPORTANT**: It's not allowed to bind and connect the same socket to two +different families (that is, both `source` and `target` must be `AF_INET` or +`AF_INET6`), although you may mix links over IPv4 and IPv6 in one group. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_connect_debug + +``` +int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +``` + +This function is for developers only and can be used for testing. It does the +same thing as [`srt_connect`](#srt_connect), with the exception that it allows +specifying the Initial Sequence Number for data transmission. Normally this value +is generated randomly. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_rendezvous +``` +int srt_rendezvous(SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, + const struct sockaddr* remote_name, int remote_namelen); +``` +Performs a rendezvous connection. This is a shortcut for doing bind locally, +setting the [`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) option +to true, and doing [`srt_connect`](#srt_connect). + +**Arguments**: + +* [`u`](#u): socket to connect +* `local_name`: specifies the local network interface and port to bind +* `remote_name`: specifies the remote party's IP address and port + +| Returns | | +|:----------------------------- |:-------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0 | +| | | + +| Errors | | +|:------------------------------------- |:-------------------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket passed as [`u`](#u) designates no valid socket | +| [`SRT_EINVOP`](#srt_einvop) | Socket already bound | +| [`SRT_ECONNSETUP`](#srt_econnsetup) | Internal creation of a UDP socket failed | +| [`SRT_ESOCKFAIL`](#srt_esockfail) | Internal configuration of a UDP socket (`bind`, `setsockopt`) failed | +| [`SRT_ERDVUNBOUND`](#srt_erdvunbound) | Internal error ([`srt_connect`](#srt_connect) should not report it after [`srt_bind`](#srt_bind) was called) | +| [`SRT_ECONNSOCK`](#srt_econnsock) | Socket [`u`](#u) is already connected | +| [`SRT_ECONNREJ`](#srt_econnrej) | Connection has been rejected | +| | | + +**IMPORTANT**: Establishing a rendezvous connection to two different families is not +allowed (that is, both `local_name` and `remote_name` must be `AF_INET` or `AF_INET6`). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_connect_callback +``` +int srt_connect_callback(SRTSOCKET u, srt_connect_callback_fn* hook_fn, void* hook_opaque); +``` + +This call installs a callback hook, which will be executed on a given [`u`](#u) +socket or all member sockets of a [`u`](#u) group, just after a pending connection +in the background has been resolved and the connection has failed. Note that this +function is not guaranteed to be called if the [`u`](#u) socket is set to blocking +mode ([`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) option set to true). +It is guaranteed to be called when a socket is in non-blocking mode, or when you +use a group. + +This function is mainly intended to be used with group connections. Note that even +if you use a group connection in blocking mode, after the group is considered +connected the member connections still continue in background. Also, when some +connections are still pending and others have failed, the blocking call for +[`srt_connect_group`](#srt_connect_group) will not exit until at least one of +them succeeds or all fail - in such a case those failures also happen only in +the background, while the connecting function blocks until all connections are +resolved. When all links fail, you will only get a general error code for the +group. This mechanism allows you to get individual errors for particular member +connection failures. + +**Arguments**: + +* [`u`](#u): Socket or group that will be used for connecting and for which the hook is installed +* `hook_fn`: The callback hook function pointer (or NULL to remove the callback) +* `hook_opaque`: The pointer value that will be passed to the callback function + + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Successful | +| -1 | Error | +| | | + +| Errors | | +|:---------------------------------- |:------------------------------------------| +| [`SRT_ECONNSOCK`](#srt_econnsock) | It can't be modified in a connected socket| +| | | + + +The callback function signature has the following type definition: + +``` +typedef void srt_connect_callback_fn(void* opaq, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token); +``` + +**Arguments**: + +* `opaq`: The pointer passed as `hook_opaque` when registering +* `ns`: The socket for which the connection process was resolved +* [`errorcode`](#error-codes): The error code, same as for [`srt_connect`](#srt_connect) for blocking mode +* `peeraddr`: The target address passed to [`srt_connect`](#srt_connect) call +* `token`: The token value, if it was used for group connection, otherwise -1 + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Socket Group Management + + * [SRT_GROUP_TYPE](#SRT_GROUP_TYPE) + * [SRT_SOCKGROUPCONFIG](#SRT_SOCKGROUPCONFIG) + * [SRT_SOCKGROUPDATA](#SRT_SOCKGROUPDATA) + * [SRT_MEMBERSTATUS](#SRT_MEMBERSTATUS) + +### SRT_GROUP_TYPE + +The following group types are collected in an [`SRT_GROUP_TYPE`](#SRT_GROUP_TYPE) enum: + +* `SRT_GTYPE_BROADCAST`: broadcast type, all links are actively used at once; +* `SRT_GTYPE_BACKUP`: backup type, idle links take over connection on disturbance. + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### SRT_SOCKGROUPCONFIG + +This structure is used to define entry points for connections for the +[`srt_connect_group`](#srt_connect_group) function: + +``` +typedef struct SRT_GroupMemberConfig_ +{ + SRTSOCKET id; + struct sockaddr_storage srcaddr; + struct sockaddr_storage peeraddr; + uint16_t weight; + SRT_SOCKOPT_CONFIG* config; + int errorcode; + int token; +} SRT_SOCKGROUPCONFIG; +``` + +where: + +* `id`: member socket ID (filled back as output) +* `srcaddr`: address to which `id` should be bound +* `peeraddr`: address to which `id` should be connected +* `weight`: the weight parameter for the link (group-type dependent) +* `config`: the configuration object, if used (see [`srt_create_config()`](#srt_create_config)) +* [`errorcode`](#error-codes): status of the connecting operation +* `token`: An integer value unique for every connection, or -1 if unused + +The `srt_prepare_endpoint` sets these fields to default values. After that +you can change the value of `weight` and `config` and `token` fields. The +`weight` parameter's meaning is dependent on the group type: + +* BROADCAST: not used +* BACKUP: positive value of link priority (the greater, the more preferred) + +In any case, the allowed value for `weight` is between 0 and 32767. + +The `config` parameter is used to provide options to be set separately on a socket +for a particular connection (see [`srt_create_config()`](#srt_create_config)). + +The `token` value is intended to allow the application to more easily identify +a particular connection. If you don't use it and leave the default value of -1, +the library will set a unique value for the next connection (a 32-bit unsigned +number that will overflow by itself; the default value will be skipped). +The application can also set a unique value by itself and keep the same +value for the same connection. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### SRT_SOCKGROUPDATA + +The most important structure for the group member status is [`SRT_SOCKGROUPDATA`](#SRT_SOCKGROUPDATA): + +```c++ +typedef struct SRT_SocketGroupData_ +{ + SRTSOCKET id; + struct sockaddr_storage peeraddr; + SRT_SOCKSTATUS sockstate; + uint16_t weight; + SRT_MEMBERSTATUS memberstate; + int result; + int token; +} SRT_SOCKGROUPDATA; +``` + +where: + +* `id`: member socket ID +* `peeraddr`: address to which `id` should be connected +* `sockstate`: current connection status (see [`srt_getsockstate`](#srt_getsockstate) +* `weight`: current weight value set on the link +* `memberstate`: current state of the member (see below) +* `result`: result of the operation (if this operation recently updated this structure) +* `token`: A token value set for that connection (see [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG)) + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### SRT_MEMBERSTATUS + +The enumeration type that defines the state of a member +connection in a group: + +* `SRT_GST_PENDING`: The connection is in progress, so the socket +is not currently being used for transmission, even potentially, +and still has a chance to fail and transit into `SRT_GST_BROKEN` +without turning into `SRT_GST_IDLE` + +* `SRT_GST_IDLE`: The connection is established and ready to +take over transmission, but it's not used for transmission at +the moment. This state may last for a short moment in the case of +broadcast group. In backup group this state +defines a backup link that is ready to take over when the +currently active (running) link becomes unstable. + +* `SRT_GST_RUNNING`: The connection is established and at least +one packet has already been sent or received over it. + +* `SRT_GST_BROKEN`: The connection was broken. Broken connections are not to be +revived. Note also that it is only possible to see this state if it is read by +[`srt_sendmsg2`](#srt_sendmsg) or [`srt_recvmsg2`](#srt_recvmsg2) just after +the link failure has been detected. Otherwise, the broken link simply +disappears from the member list. + +Note that internally the member state is separate for sending and receiving. If +the `memberstate` field of [`SRT_SOCKGROUPDATA`](#SRT_SOCKGROUPDATA) is +`SRT_GST_RUNNING`, it means that this is the state in at least one +direction, while in the other direction it may be `SRT_GST_IDLE`. In all +other cases the states should be the same in both directions. + +States should normally start with `SRT_GST_PENDING` and then turn into +`SRT_GST_IDLE`. Once a new link is used for sending data, the state becomes +`SRT_GST_RUNNING`. In the case of the `SRT_GTYPE_BACKUP` type group, if a link +is in the `SRT_GST_RUNNING` state, but another link is chosen to remain +as the only active one, this link will be "silenced" (its state will +become `SRT_GST_IDLE`). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### Functions to Be Used on Groups + + * [srt_create_group](#srt_create_group) + * [srt_groupof](#srt_groupof) + * [srt_group_data](#srt_group_data) + * [srt_connect_group](#srt_connect_group) + * [srt_prepare_endpoint](#srt_prepare_endpoint) + * [srt_create_config](#srt_create_config) + * [srt_delete_config](#srt_delete_config) + * [srt_config_add](#srt_config_add) + +#### srt_create_group + +``` +SRTSOCKET srt_create_group(SRT_GROUP_TYPE type); +``` + +Creates a new group of type `type`. Is typically called on the +caller side to be next used for connecting to a remote SRT listener. +The group ID is of the same domain as the socket ID, with the exception that +the `SRTGROUP_MASK` bit is set on it, unlike for socket ID. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRTSOCKET` | Group SRT socket ID. | +| `SRT_INVALID_SOCK` | On error or if bonding API is disabled. | +| | | + + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_groupof + +``` +SRTSOCKET srt_groupof(SRTSOCKET member); +``` + +Retrieves the group SRT socket ID that corresponds to the member socket ID `member`. + + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRTSOCKET` | Corresponding group SRT socket ID of the member socket. | +| `SRT_INVALID_SOCK` | The socket doesn't exist, it is not a member of any group, or bonding API is disabled. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_group_data + +``` +int srt_group_data(SRTSOCKET socketgroup, SRT_SOCKGROUPDATA output[], size_t* inoutlen); +``` + +**Arguments**: + +* `socketgroup` an existing socket group ID +* `output` points to an output array +* `inoutlen` points to a variable that stores the size of the `output` array, + and is set to the filled array's size + +This function obtains the current member state of the group specified in +`socketgroup`. The `output` should point to an array large enough to hold all +the elements. The `inoutlen` should point to a variable initially set to the size +of the `output` array. The current number of members will be written back to `inoutlen`. + +If the size of the `output` array is enough for the current number of members, +the `output` array will be filled with group data and the function will return +the number of elements filled. Otherwise the array will not be filled and +`SRT_ERROR` will be returned. + +This function can be used to get the group size by setting `output` to `NULL`, +and providing `socketgroup` and `inoutlen`. + +| Returns | | +|:----------------------------- |:-------------------------------------------------- | +| # of elements | The number of data elements filled, on success | +| -1 | Error | +| | | + + +| Errors | | +|:---------------------------------- |:--------------------------------------------------------- | +| [`SRT_EINVPARAM`](#srt_einvparam) | Reported if `socketgroup` is not an existing group ID. Or if bonding API is disabled. | +| [`SRT_ELARGEMSG`](#srt_elargemsg) | Reported if `inoutlen` if less than the size of the group | +| | | + + +| in:output | in:inoutlen | returns | out:output | out:inoutlen | Error | +|:---------:|:--------------:|:------------:|:----------:|:------------:|:---------------------------------:| +| NULL | NULL | -1 | NULL | NULL | [`SRT_EINVPARAM`](#srt_einvparam) | +| NULL | ptr | 0 | NULL | group.size() | ✖️ | +| ptr | NULL | -1 | ✖️ | NULL | [`SRT_EINVPARAM`](#srt_einvparam) | +| ptr | ≥ group.size | group.size() | group.data | group.size | ✖️ | +| ptr | < group.size | -1 | ✖️ | group.size | [`SRT_ELARGEMSG`](#srt_elargemsg) | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_connect_group + +``` +int srt_connect_group(SRTSOCKET group, + SRT_SOCKGROUPCONFIG name [], int arraysize); +``` + +This function does almost the same as calling [`srt_connect`](#srt_connect) or +[`srt_connect_bind`](#srt_connect_bind) (when the source was specified for +[`srt_prepare_endpoint`](#srt_prepare_endpoint)) in a loop for every item specified +in the `name` array. However if blocking mode is being used, the first call to +[`srt_connect`](#srt_connect) would block until the connection is established, +whereas this function blocks until any of the specified connections is established. + +If the group nonblocking mode is set ([`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) +option), there's no difference, except that the [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG) +structure allows adding extra configuration data used by groups. Note also that +this function accepts only groups, not sockets. + +The elements of the `name` array need to be prepared with the use of the +[`srt_prepare_endpoint`](#srt_prepare_endpoint) function. Note that it is +**NOT** required that every target address specified is of the same family. + +Return value and errors in this function are the same as in [`srt_connect`](#srt_connect), +although this function reports success when at least one connection has +succeeded. If none has succeeded, this function reports an [`SRT_ECONNLOST`](#srt_econnlost) +error. Particular connection states can be obtained from the `name` +array upon return from the [`errorcode`](#error-codes) field. + +The fields of [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG) structure have the following meaning: + +**Input**: + +* `id`: unused, should be -1 (default when created by [`srt_prepare_endpoint`](#srt_prepare_endpoint)) +* `srcaddr`: address to bind before connecting, if specified (see below for details) +* `peeraddr`: target address to connect +* `weight`: weight value to be set on the link +* `config`: socket options to be set on the socket before connecting +* [`errorcode`](#error-codes): unused, should be [`SRT_SUCCESS`](#srt_success) (default) +* `token`: An integer value unique for every connection, or -1 if unused + +**Output**: + +* `id`: The socket created for that connection (-1 if failed to create) +* `srcaddr`: unchanged +* `peeraddr`: unchanged +* `weight`: unchanged +* `config`: unchanged (the object should be manually deleted upon return) +* [`errorcode`](#error-codes): status of connection for that link ([`SRT_SUCCESS`](#srt_success) if succeeded) +* `token`: same as in input, or a newly created token value if input was -1 + +| Returns | | +|:----------------------------- |:-------------------------------------------------- | +| `SRT_SOCKET` | The socket ID of the first connected member. | +| -1 | Error | +| | | + + +| Errors | | +|:---------------------------------- |:--------------------------------------------------------- | +| [`SRT_EINVPARAM`](#srt_einvparam) | Reported if `socketgroup` is not an existing group ID. Or if bonding API is disabled. | +| [`SRT_ECONNLOST`](#srt_econnlost) | Reported if none of member sockets has connected. | +| | | + +The procedure of connecting for every connection definition specified +in the `name` array is performed the following way: + +1. The socket for this connection is first created + +2. Socket options derived from the group are set on that socket. + +3. If `config` is not NULL, configuration options stored there are set on that socket. + +4. If source address is specified (that is `srcaddr` value is **not** +default empty, as described in [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG), +then the binding operation is done on the socket (see [`srt_bind`](#srt_bind)). + +5. The socket is added to the group as a member. + +6. The socket is connected to the target address, as specified +in the `peeraddr` field. + +During this process there can be errors at any stage. There are two +possibilities as to what may happen in this case: + +1. If creation of a new socket has failed, which may only happen due to +problems with system resources, then the whole loop is interrupted and no +further items in the array are processed. All sockets that got created until +then, and for which the connection attempt has at least successfully started, +remain group members, although the function will return immediately with an +error status (that is, without waiting for the first successful connection). If +your application wants to do any partial recovery from this situation, it can +only use the epoll mechanism to wait for readiness. + +2. In any other case, if an error occurs at any stage of the above process, the +processing is interrupted for this very array item only, the socket used for it +is immediately closed, and the processing of the next elements continues. In the case +of a connection process, it also passes two stages - parameter check and the process +itself. Failure at the parameter check breaks this process, while if the check +passes, this item is considered correctly processed, even if the connection +attempt is going to fail later. If this function is called in blocking mode, +it then blocks until at least one connection reports success, or if all of them +fail. The status of connections that continue in the background after this function +exits can then be checked by [`srt_group_data`](#srt_group_data). + +As member socket connections are running in the background, for determining +if a particular connection has succeeded or failed it is recommended +to use [`srt_connect_callback`](#srt_connect_callback). In this case the +`token` callback function parameter will be the same as the `token` value used +for the particular item in the `name` connection table. + +The `token` value doesn't have any limitations except that the -1 value is +a "trap representation", that is, when set on input it will make the internals +define a unique value for the `token`. Your application can also set unique values, +in which case the `token` value will be preserved. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_prepare_endpoint + +``` +SRT_SOCKGROUPCONFIG srt_prepare_endpoint(const struct sockaddr* src /*nullable*/, + const struct sockaddr* dst, int namelen); +``` + +This function prepares a default [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG) object as an element +of the array you can prepare for [`srt_connect_group`](#srt_connect_group) function, filled with +additional data: + +**Arguments**: + +* `src`: address to which the newly created socket should be bound +* `dst`: address to which the newly created socket should connect +* `namelen`: size of both `src` and `dst` + +The following fields are set by this function: + +* `id`: -1 (unused for input) +* `srcaddr`: default empty (see below) or copied from `src` +* `peeraddr`: copied from `dst` +* `weight`: 0 +* `config`: `NULL` +* [`errorcode`](#error-codes): [`SRT_SUCCESS`](#srt_success) + +The default empty `srcaddr` is set the following way: + +* `ss_family` set to the same value as `dst->sa_family` +* empty address (`INADDR_ANY` for IPv4 and `in6addr_any` for IPv6) +* port number 0 + +If `src` is not NULL, then `srcaddr` is copied from `src`. Otherwise +it will remain as default empty. + +The `dst` parameter is obligatory. If `src` parameter is not NULL, +then both `dst` and `src` must have the same value of `sa_family`. + +Note though that this function has no possibility of reporting errors - these +would be reported only by [`srt_connect_group`](#srt_connect_group), separately +for every individual connection, and the status can be obtained from +the [`errorcode`](#error-codes) field. + +Note that the `errorcode` field of the `SRT_SOCKGROUPCONFIG` returned would be set to `SRT_EINVOP` +if the bonding API is disabled (`ENABLE_BONDING=OFF`). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_create_config + +``` +SRT_SOCKOPT_CONFIG* srt_create_config(); +``` + +Creates a dynamic object for specifying the socket options. You can add options +to be set on the socket by [`srt_config_add`](#srt_config_add) and then mount this +object into the `config` field in [`SRT_SOCKGROUPCONFIG`](#SRT_SOCKGROUPCONFIG) +object for that particular connection. After the object is no longer needed, you +should delete it using [`srt_delete_config`](#srt_delete_config). + +| Returns | | +|:----------------------------- |:------------------------------------------------------------------ | +| Pointer | The pointer to the created object (memory allocation errors apply) | +| NULL | If bonding API is disabled. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_delete_config + +``` +void srt_delete_config(SRT_SOCKOPT_CONFIG* c); +``` + +Deletes the configuration object. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +#### srt_config_add + +``` +int srt_config_add(SRT_SOCKOPT_CONFIG* c, SRT_SOCKOPT opt, void* val, int len); +``` + +Adds a configuration option to the configuration object. + +Parameters have meanings similar to [`srt_setsockflag`](#srt_setsockflag). Note +that not every option is allowed to be set this way. However, the option (if allowed) +isn't checked if it doesn't violate other preconditions. This will be checked when +the option is being set on the socket, which may fail as a part of the connection +process done by [`srt_connect_group`](#srt_connect_group). + +This function should be used when this option must be set individually on a socket +and differently for a particular link. If you need to set some option the same way +on every socket, you should instead set this option on the whole group. + +The following options are allowed to be set on the member socket: + +* [`SRTO_BINDTODEVICE`](API-socket-options.md#SRTO_BINDTODEVICE): If you want to limit binding for this link (Linux only) +* [`SRTO_CONNTIMEO`](API-socket-options.md#SRTO_CONNTIMEO): If you want to give more time to connect on this link +* [`SRTO_GROUPMINSTABLETIMEO`](API-socket-options.md#SRTO_GROUPMINSTABLETIMEO): To set ACK jitter tolerance per individual link +* [`SRTO_LOSSMAXTTL`](API-socket-options.md#SRTO_LOSSMAXTTL): If this link tends to suffer from UDP reordering +* [`SRTO_NAKREPORT`](API-socket-options.md#SRTO_NAKREPORT): If you don't want NAKREPORT to work for this link +* [`SRTO_PEERIDLETIMEO`](API-socket-options.md#SRTO_PEERIDLETIMEO): If you want to be more tolerant for temporary outages +* [`SRTO_RCVBUF`](API-socket-options.md#SRTO_RCVBUF): Allows for larger receiver buffer for longer recovery +* [`SRTO_SNDBUF`](API-socket-options.md#SRTO_SNDBUF): Allows for larger sender buffer for slower links +* [`SRTO_SNDDROPDELAY`](API-socket-options.md#SRTO_SNDDROPDELAY): When particular link tends to drop too eagerly +* [`SRTO_UDP_RCVBUF`](API-socket-options.md#SRTO_UDP_RCVBUF): UDP receiver buffer, if this link has a big flight window +* [`SRTO_UDP_SNDBUF`](API-socket-options.md#SRTO_UDP_SNDBUF): UDP sender buffer, if this link has a big flight window + + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Success | +| -1 | Failure | +| | | + +| Errors | | +|:---------------------------------- |:--------------------------------------------------------------------- | +| [`SRT_EINVPARAM`](#srt_einvparam) | This option is not allowed to be set on a socket being a group member. Or if bonding API is disabled. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Options and Properties + +* [srt_getpeername](#srt_getpeername) +* [srt_getsockname](#srt_getsockname) +* [srt_getsockopt, srt_getsockflag](#srt_getsockopt-srt_getsockflag) +* [srt_setsockopt, srt_setsockflag](#srt_setsockopt-srt_setsockflag) +* [srt_getversion](#srt_getversion) + +**NOTE**: For more information, see [SRT API Socket Options, Getting and Setting Options](API-socket-options.md#getting-and-setting-options). + +### srt_getpeername +``` +int srt_getpeername(SRTSOCKET u, struct sockaddr* name, int* namelen); +``` + +Retrieves the remote address to which the socket is connected. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0 | +| | | + +| Errors | | +|:------------------------------- |:------------------------------------------------------------------------ | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid socket ID | +| [`SRT_ENOCONN`](#srt_enoconn) | Socket [`u`](#u) isn't connected, so there's no remote address to return | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getsockname +``` +int srt_getsockname(SRTSOCKET u, struct sockaddr* name, int* namelen); +``` + +Extracts the address to which the socket was bound. Although you should know +the address(es) that you have used for binding yourself, this function can be +useful for extracting the local outgoing port number when it was specified as 0 +with binding for system autoselection. With this function you can extract the +port number after it has been autoselected. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0 | +| | | + +| Errors | | +|:------------------------------- |:---------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid socket ID | +| [`SRT_ENOCONN`](#srt_enoconn) | Socket [`u`](#u) isn't bound, so there's no local address to return
(:warning:   **BUG?** It should rather be [`SRT_EUNBOUNDSOCK`](#srt_eunboundsock)) | +| | | + +Example + +```c++ +sockaddr_storage name; +int namelen = sizeof sockaddr_storage; +int res = srt_getsockname(m_listener_sock, (sockaddr*) &name, &namelen); +// IPv4: namelen == sockaddr_in. +// IPv6: namelen == sockaddr_in6. +if (res < 0) { + std::cerr << "Error " << srt_getlasterror_str() << '\n'; +} +``` + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getsockopt +### srt_getsockflag + +```c++ +int srt_getsockopt(SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT opt, void* optval, int* optlen); +int srt_getsockflag(SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen); +``` + +Gets the value of the given socket option (from a socket or a group). + +The first version ([`srt_getsockopt`](#srt_getsockopt)) follows the BSD socket +API convention, although the "level" parameter is ignored. The second version +([`srt_getsockflag`](#srt_getsockflag)) omits the "level" parameter completely. + +Options correspond to various data types (see [API-socket-options.md](./API-socket-options.md)). +A variable `optval` of the appropriate data type has to be passed. +The integer value of `optlen` should originally contain the size of the `optval` type provided; +on return, it will be set to the size of the value returned. +For most options, it will be the size of an integer. Some options, however, use types `bool`, `int64_t`, `C string`, etc. +(see [API-socket-options.md](./API-socket-options.md#sockopt_types)). + +The application is responsible for allocating sufficient memory space as defined and pointed to by `optval`. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0 | +| | | + +| Errors | | +|:-------------------------------- |:---------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid socket ID | +| [`SRT_EINVOP`](#srt_einvop) | Option `opt` indicates no valid option | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- +### srt_setsockopt +### srt_setsockflag + +```c++ +int srt_setsockopt(SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT opt, const void* optval, int optlen); +int srt_setsockflag(SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int optlen); +``` + +Sets a value for a socket option in the socket or group. + +The first version ([`srt_setsockopt`](#srt_setsockopt)) follows the BSD socket +API convention, although the "level" parameter is ignored. The second version +([`srt_setsockflag`](#srt_setsockflag)) omits the "level" parameter completely. + +Options correspond to various data types, so you need to know what data type is +assigned to a particular option, and to pass a variable of the appropriate data +type with the option value to be set. + +Please note that some of the options can only be set on sockets or only on +groups, although most of the options can be set on the groups so that they +are then derived by the member sockets. + +| Returns | | +|:----------------------------- |:----------------------------------------------- | +| `SRT_ERROR` | (-1) in case of error, otherwise 0 | +| | | + +| Errors | | +|:----------------------------------- |:--------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket [`u`](#u) indicates no valid socket ID | +| [`SRT_EINVPARAM`](#srt_einvparam) | Option `opt` indicates no valid option | +| [`SRT_EBOUNDSOCK`](#srt_eboundsock) | Tried to set an option with PRE_BIND restriction on a bound socket. | +| [`SRT_ECONNSOCK`](#srt_econnsock) | Tried to set an option with PRE_BIND or PRE restriction on a socket in connecting/listening/connected state. | +| | | + +**NOTE*: Various other errors may result from problems when setting a +specific option (see option description in [API-socket-options.md](./API-socket-options.md) for details). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getversion + +``` +uint32_t srt_getversion(); +``` + +Get SRT version value. The version format in hex is 0xXXYYZZ for x.y.z in human +readable form, where x = ("%d", (version>>16) & 0xff), etc. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| SRT Version | Unsigned 32-bit integer | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Helper Data Types for Transmission + +* [SRT_MSGCTRL](#SRT_MSGCTRL) + +**NOTE:** There might be a difference in terminology used in [Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) and current documentation. +Please consult [Data Transmission Modes](https://tools.ietf.org/html/draft-sharabayko-srt-01#section-4.2) +and [Best Practices and Configuration Tips for Data Transmission via SRT](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-7) +sections of the Internet Draft additionally. The current section is going to be reworked accordingly. + +### SRT_MSGCTRL + +The [`SRT_MSGCTRL`](#SRT_MSGCTRL) structure: + +```c++ +typedef struct SRT_MsgCtrl_ +{ + int flags; // Left for future + int msgttl; // TTL for a message, default -1 (no TTL limitation) + int inorder; // Whether a message is allowed to supersede a partially lost one. Unused in stream and live mode + int boundary; // 0:mid pkt, 1(01b):end of frame, 2(11b):complete frame, 3(10b): start of frame + int64_t srctime; // Source time, in microseconds since SRT internal clock epoch + int32_t pktseq; // Sequence number of the first packet in received message (unused for sending) + int32_t msgno; // Message number (output value for both sending and receiving) + SRT_SOCKGROUPDATA* grpdata; // Pointer to group data array + size_t grpdata_size; // Size of the group array +} SRT_MSGCTRL; +``` + +The [`SRT_MSGCTRL`](#SRT_MSGCTRL) structure is used in [`srt_sendmsg2`](#srt_sendmsg) +and [`srt_recvmsg2`](#srt_recvmsg2) calls and specifies some special extra parameters: + +- `flags`: [IN, OUT]. RESERVED FOR FUTURE USE (should be 0). This is +intended to specify some special options controlling the details of how the +called function should work. + +- `msgttl`: [IN]. In **message** and **live mode** only, specifies the TTL for +sending messages (in `[ms]`). Not used for receiving messages. If this value +is not negative, it defines the maximum time up to which this message should +stay scheduled for sending. If TTL has expired, the message sending and further retransmissions are discarded, even +if it has never been sent so far. + +- `inorder`: [IN]. In **message mode** only, specifies that sent messages should +be extracted by the receiver in the order of sending. This can be meaningful if +a packet loss has happened, and a particular message must wait for retransmission +so that it can be reassembled and then delivered. When this flag is false, the +message can be delivered even if there are any previous messages still waiting +for completion. + +- `boundary`: RESERVED FOR FUTURE USE. Intended to be used in a special mode +when you are allowed to send or retrieve a part of the message. + +- `srctime`: + - [OUT] Receiver only. Specifies the time when the packet was intended to be +delivered to the receiving application (in microseconds since SRT clock epoch). + - [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. + +- `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 +UDP packet, only the sequence of the first one is reported. Note that in +**live mode** there's always one UDP packet per message. + +- `msgno`: Message number that can be sent by both sender and receiver, +although it is required that this value remain monotonic in subsequent send calls. +Normally message numbers start with 1 and increase with every message sent. + +- `grpdata` and `grpdata_size`: Pointer and size of the group array. For single +socket connections these values should remain NULL and 0 respectively. When you +call [`srt_sendmsg2`](#srt_sendmsg) or [`srt_recvmsg2`](#srt_recvmsg2) function +for a group, you should pass an array here so that you can retrieve the status of +particular member sockets. If you pass an array that is too small, your `grpdata_size` +field will be rewritten with the current number of members, but without filling in +the array; otherwise both fields are updated to reflect the current connection state +of the group. For details, see the [SRT Connection Bonding: Quick Start](../features/bonding-intro.md) and +[SRT Connection Bonding: Socket Groups](../features/socket-groups.md) documents. + +**Helpers for [`SRT_MSGCTRL`](#SRT_MSGCTRL):** + +``` +void srt_msgctrl_init(SRT_MSGCTRL* mctrl); +const SRT_MSGCTRL srt_msgctrl_default; +``` + +Helpers for getting an object of [`SRT_MSGCTRL`](#SRT_MSGCTRL) type ready to use. +The first is a function that fills the object with default values. The second is +a constant object and can be used as a source for assignment. Note that you cannot +pass this constant object into any of the API functions because they require it +to be mutable, as they use some fields to output values. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Transmission + +* [srt_send, srt_sendmsg, srt_sendmsg2](#srt_send-srt_sendmsg-srt_sendmsg2) +* [srt_recv, srt_recvmsg, srt_recvmsg2](#srt_recv-srt_recvmsg-srt_recvmsg2) +* [srt_sendfile, srt_recvfile](#srt_sendfile-srt_recvfile) + +**NOTE:** There might be a difference in terminology used in [Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) and current documentation. +Please consult [Data Transmission Modes](https://tools.ietf.org/html/draft-sharabayko-srt-01#section-4.2) +and [Best Practices and Configuration Tips for Data Transmission via SRT](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-7) +sections of the Internet Draft additionally. The current section is going to be reworked accordingly. + + +### srt_send +### srt_sendmsg +### srt_sendmsg2 + +``` +int srt_send(SRTSOCKET u, const char* buf, int len); +int srt_sendmsg(SRTSOCKET u, const char* buf, int len, int ttl/* = -1*/, int inorder/* = false*/); +int srt_sendmsg2(SRTSOCKET u, const char* buf, int len, SRT_MSGCTRL *mctrl); +``` + +Sends a payload to a remote party over a given socket. + +**Arguments**: + +* [`u`](#u): Socket used to send. The socket must be connected for this operation. +* `buf`: Points to the buffer containing the payload to send. +* `len`: Size of the payload specified in `buf`. +* `ttl`: Time (in `[ms]`) to wait for a successful delivery. See description of +the [`SRT_MSGCTRL::msgttl`](#SRT_MSGCTRL) field. +* `inorder`: Required to be received in the order of sending. See +[`SRT_MSGCTRL::inorder`](#SRT_MSGCTRL). +* `mctrl`: An object of [`SRT_MSGCTRL`](#SRT_MSGCTRL) type that contains extra +parameters, including `ttl` and `inorder`. + +The way this function works is determined by the mode set in options, and it has +specific requirements: + +1. In **file/stream mode**, the payload is byte-based. You are not required to +know the size of the data, although they are only guaranteed to be received +in the same byte order. + +2. In **file/message mode**, the payload that you send using this function is +a single message that you intend to be received as a whole. In other words, a +single call to this function determines a message's boundaries. + +3. In **live mode**, you are only allowed to send up to the length of +`SRTO_PAYLOADSIZE`, which can't be larger than 1456 bytes (1316 default). + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| Size | Size of the data sent, if successful | +| `SRT_ERROR` | In case of error (-1) | +| | | + +**NOTE**: Note that in **file/stream mode** the returned size may be less than `len`, +which means that it didn't send the whole contents of the buffer. You would need to +call this function again with the rest of the buffer next time to send it completely. +In both **file/message** and **live mode** the successful return is always equal to `len`. + +| Errors | | +|:--------------------------------------------- |:------------------------------------------------------------------------------------------------------------------- | +| [`SRT_ENOCONN`](#srt_enoconn) | Socket [`u`](#u) used when the operation is not connected. | +| [`SRT_ECONNLOST`](#srt_econnlost) | Socket [`u`](#u) used for the operation has lost its connection. | +| [`SRT_EINVALMSGAPI`](#srt_einvalmsgapi) | Incorrect API usage in **message mode**:
**live mode**: trying to send more bytes at once than `SRTO_PAYLOADSIZE` or wrong source time
was provided. | +| [`SRT_EINVALBUFFERAPI`](#srt_einvalbufferapi) | Incorrect API usage in **stream mode** (reserved for future use):
The congestion controller object used for this mode doesn't use any restrictions on this call,
but this may change. | +| [`SRT_ELARGEMSG`](#srt_elargemsg) | Message to be sent can't fit in the sending buffer (that is, it exceeds the current total space in the
sending buffer in bytes). This means that the sender buffer is too small, or the application is
trying to send a larger message than initially predicted. | +| [`SRT_EASYNCSND`](#srt_easyncsnd) | There's no free space currently in the buffer to schedule the payload. This is only reported in
non-blocking mode ([`SRTO_SNDSYN`](API-socket-options.md#SRTO_SNDSYN) set to false); in blocking mode the call is blocked until
enough free space in the sending buffer becomes available. | +| [`SRT_ETIMEOUT`](#srt_etimeout) | The condition described above still persists and the timeout has passed. This is only reported in
blocking mode when [`SRTO_SNDTIMEO`](API-socket-options.md#SRTO_SNDTIMEO) is set to a value other than -1. | +| [`SRT_EPEERERR`](#srt_epeererr) | This is reported only in the case where, as a stream is being received by a peer, the
[`srt_recvfile`](#srt_recvfile) function encounters an error during a write operation on a file. This is reported by
a `UMSG_PEERERROR` message from the peer, and the agent sets the appropriate flag internally.
This flag persists up to the moment when the connection is broken or closed. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_recv +### srt_recvmsg +### srt_recvmsg2 + + +``` +int srt_recv(SRTSOCKET u, char* buf, int len); +int srt_recvmsg(SRTSOCKET u, char* buf, int len); +int srt_recvmsg2(SRTSOCKET u, char *buf, int len, SRT_MSGCTRL *mctrl); +``` + +Extracts the payload waiting to be received. Note that [`srt_recv`](#srt_recv) and +[`srt_recvmsg`](#srt_recvmsg) are identical functions, two different names being +kept for historical reasons. In the UDT predecessor the application was required +to use either the `UDT::recv` version for **stream mode** and `UDT::recvmsg` for +**message mode**. In SRT this distinction is resolved internally by the +[`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) flag. + +**Arguments**: + +* [`u`](#u): Socket used to send. The socket must be connected for this operation. +* `buf`: Points to the buffer to which the payload is copied. +* `len`: Size of the payload specified in `buf`. +* `mctrl`: An object of [`SRT_MSGCTRL`](#SRT_MSGCTRL) type that contains extra +parameters. + +The way this function works is determined by the mode set in options, and it has +specific requirements: + +1. In **file/stream mode**, as many bytes as possible are retrieved, that is, +only so many bytes that fit in the buffer and are currently available. Any +data that is available but not extracted this time will be available next time. + +2. In **file/message mode**, exactly one message is retrieved, with the +boundaries defined at the moment of sending. If some parts of the messages are +already retrieved, but not the whole message, nothing will be received (the +function blocks or returns [`SRT_EASYNCRCV`](#srt_easyncrcv)). If the message +to be returned does not fit in the buffer, nothing will be received and +the error is reported. + +3. In **live mode**, the function behaves as in **file/message mode**, although the +number of bytes retrieved will be at most the maximum payload of one MTU. +The [`SRTO_PAYLOADSIZE`](API-socket-options.md#SRTO_PAYLOADSIZE) value configured by the sender +is not negotiated, and not known to the receiver. +The [`SRTO_PAYLOADSIZE`](API-socket-options.md#SRTO_PAYLOADSIZE) value set on the SRT receiver +is mainly used for heuristics. However, the receiver is prepared to receive +the whole MTU as configured with [`SRTO_MSS`](API-socket-options.md#SRTO_MSS). +In this mode, however, with default settings of [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) +and [`SRTO_TLPKTDROP`](API-socket-options.md#SRTO_TLPKTDROP), the message will be +received only when its time to play has come, and until then it will be kept in the +receiver buffer. Also, when the time to play has come for a message that is next to +the currently lost one, it will be delivered and the lost one dropped. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| Size | Size (\>0) of the data received, if successful. | +| 0 | If the connection has been closed | +| `SRT_ERROR` | (-1) when an error occurs | +| | | + +| Errors | | +|:--------------------------------------------- |:--------------------------------------------------------- | +| [`SRT_ENOCONN`](#srt_enoconn) | Socket [`u`](#u) used for the operation is not connected. | +| [`SRT_ECONNLOST`](#srt_econnlost) | Socket [`u`](#u) used for the operation has lost connection (this is reported only if the connection
was unexpectedly broken, not when it was closed by the foreign host). | +| [`SRT_EINVALMSGAPI`](#srt_einvalmsgapi) | Incorrect API usage in **message mode**:
-- **live mode**: size of the buffer is less than [`SRTO_PAYLOADSIZE`](API-socket-options.md#SRTO_PAYLOADSIZE) | +| [`SRT_EINVALBUFFERAPI`](#srt_einvalbufferapi) | Incorrect API usage in **stream mode**:
• Currently not in use. File congestion control used for **stream mode** does not restrict
the parameters. :warning:   **???** | +| [`SRT_ELARGEMSG`](#srt_elargemsg) | Message to be sent can't fit in the sending buffer (that is, it exceeds the current total space in
the sending buffer in bytes). This means that the sender buffer is too small, or the application
is trying to send a larger message than initially intended. | +| [`SRT_EASYNCRCV`](#srt_easyncrcv) | There are no data currently waiting for delivery. This happens only in non-blocking mode
(when [`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) is set to false). In blocking mode the call is blocked until the data are ready.
How this is defined, depends on the mode:
• In **live mode** (with [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) on), at least one packet must be present in the receiver
buffer and its time to play be in the past
• In **file/message mode**, one full message must be available, the next one waiting if there are no
messages with `inorder` = false, or possibly the first message ready with `inorder` = false
• In **file/stream mode**, it is expected to have at least one byte of data still not extracted | +| [`SRT_ETIMEOUT`](#srt_etimeout) | The readiness condition described above is still not achieved and the timeout has passed.
This is only reported in blocking mode when[`SRTO_RCVTIMEO`](API-socket-options.md#SRTO_RCVTIMEO) is set to a value other than -1. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_sendfile +### srt_recvfile + +``` +int64_t srt_sendfile(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block); +int64_t srt_recvfile(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block); +``` + +These are functions dedicated to sending and receiving a file. You need to call +this function just once for the whole file, although you need to know the size of +the file prior to sending, and also define the size of a single block that should +be internally retrieved and written into a file in a single step. This influences +only the performance of the internal operations; from the application perspective +you just have one call that exits only when the transmission is complete. + +**Arguments**: + +* [`u`](#u): Socket used for transmission. The socket must be connected. +* `path`: Path to the file that should be read or written. +* `offset`: Needed to pass or retrieve the offset used to read or write to a file +* `size`: Size of transfer (file size, if offset is at 0) +* `block`: Size of the single block to read at once before writing it to a file + +The following values are recommended for the `block` parameter: + +``` +#define SRT_DEFAULT_SENDFILE_BLOCK 364000 +#define SRT_DEFAULT_RECVFILE_BLOCK 7280000 +``` + +You need to pass them to the [`srt_sendfile`](#srt_sendfile) or +[`srt_recvfile`](#srt_recvfile) function if you don't know what value to chose. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| Size | The size (\>0) of the transmitted data of a file. It may be less than `size`, if the size was greater
than the free space in the buffer, in which case you have to send rest of the file next time. | +| -1 | in case of error | +| | | + +| Errors | | +|:--------------------------------------------- |:----------------------------------------------------------------------------- | +| [`SRT_ENOCONN`](#srt_enoconn) | Socket [`u`](#u) used for the operation is not connected. | +| [`SRT_ECONNLOST`](#srt_econnlost) | Socket [`u`](#u) used for the operation has lost its connection. | +| [`SRT_EINVALBUFFERAPI`](#srt_einvalbufferapi) | When socket has [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) = true or [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) = true.
(:warning:   **BUG?**: Looxlike MESSAGEAPI isn't checked) | +| [`SRT_EINVRDOFF`](#srt_einvrdoff) | There is a mistake in `offset` or `size` parameters, which should match the index availability
and size of the bytes available since `offset` index. This is actually reported for [`srt_sendfile`](#srt_sendfile)
when the `seekg` or `tellg` operations resulted in error. | +| [`SRT_EINVWROFF`](#srt_einvwroff) | Like above, reported for [`srt_recvfile`](#srt_recvfile) and `seekp`/`tellp`. | +| [`SRT_ERDPERM`](#srt_erdperm) | The read from file operation has failed ([`srt_sendfile`](#srt_sendfile)). | +| [`SRT_EWRPERM`](#srt_ewrperm) | The write to file operation has failed ([`srt_recvfile`](#srt_recvfile)). | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Performance Tracking + +* [srt_bstats, srt_bistats](#srt_bstats-srt_bistats) + +**Sequence Numbers:** +The sequence numbers used in SRT are 32-bit "circular numbers" with the most significant +bit not included. For example 0x7FFFFFFF shifted forward by 3 becomes 2. As far as +any comparison is concerned, it can be thought of as a "distance" which is an integer +value expressing an offset to be added to one sequence number in order to get the +second one. This distance is only valid as long as the threshold value isn't exceeded, +so it's understood that all sequence numbers that are anywhere taken into account are +systematically updated and kept in the range between 0 and half of the maximum 0x7FFFFFFF. +Hence, the distance counting procedure always assumes that the sequence number are in +the required range already, so for a numbers like 0x7FFFFFF0 and 0x10, for which the +"numeric difference" would be 0x7FFFFFE0, the "distance" is 0x20. + + +### srt_bstats +### srt_bistats +``` +// Performance monitor with Byte counters for better bitrate estimation. +int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear); + +// Performance monitor with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. +int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous); +``` + +Reports the current statistics + +**Arguments**: + +* [`u`](#u): Socket from which to get statistics +* `perf`: Pointer to an object to be written with the statistics +* `clear`: 1 if the statistics should be cleared after retrieval +* `instantaneous`: 1 if the statistics should use instant data, not moving averages + +`SRT_TRACEBSTATS` is an alias to `struct CBytePerfMon`. For a complete description +of the fields please refer to [SRT Statistics](statistics.md). + + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Success | +| -1 | Failure | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Invalid socket ID provided. +| [`SRT_ECONNLOST`](#srt_econnlost) | Connection lost (group socket). +| [`SRT_ENOCONN`](#srt_enoconn) | Not connected (group socket). +| | | + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Asynchronous Operations (Epoll) + +* [srt_epoll_create](#srt_epoll_create) +* [srt_epoll_add_usock, srt_epoll_add_ssock, srt_epoll_update_usock, srt_epoll_update_ssock](#srt_epoll_add_usock-srt_epoll_add_ssock-srt_epoll_update_usock-srt_epoll_update_ssock) +* [srt_epoll_remove_usock, srt_epoll_remove_ssock](#srt_epoll_remove_usock-srt_epoll_remove_ssock) +* [srt_epoll_wait](#srt_epoll_wait) +* [srt_epoll_uwait](#srt_epoll_uwait) +* [srt_epoll_clear_usocks](#srt_epoll_clear_usocks) +* [srt_epoll_set](#srt_epoll_set) +* [srt_epoll_release](#srt_epoll_release) + +The epoll system is currently the only method for using multiple sockets in one +thread with having the blocking operation moved to epoll waiting so that it can +block on multiple sockets at once. That is, instead of blocking a single reading +or writing operation, as it's in blocking mode, it blocks until at least one of +the sockets subscribed for a single waiting call in given operation mode is ready +to do this operation without blocking. It's usually combined with setting the +nonblocking mode on a socket. In SRT this is set separately for reading and +writing ([`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) and +[`SRTO_SNDSYN`](API-socket-options.md#SRTO_SNDSYN) respectively). This is +to ensure that if there is internal error in the application (or even possibly +a bug in SRT that has reported a spurious readiness report) the operation will end +up with an error rather than cause blocking, which would be more dangerous for the +application ([`SRT_EASYNCRCV`](#srt_easyncrcv) and [`SRT_EASYNCSND`](#srt_easyncsnd) +respectively). + +The epoll system, similar to the one on Linux, relies on [`eid`](#eid) objects +managed internally in SRT, which can be subscribed to particular sockets and the +readiness status of particular operations. The [`srt_epoll_wait`](#srt_epoll_wait) +function can then be used to block until any readiness status in the whole +[`eid`](#eid) is set. + + +### srt_epoll_create +``` +int srt_epoll_create(void); +``` + +Creates a new epoll container. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| valid EID | Success | +| -1 | Failure | +| | | + +| Errors | | +|:----------------------------------- |:--------------------------------------------------------------------- | +| [`SRT_ECONNSETUP`](#srt_econnsetup) | System operation failed or not enough space to create a new epoll. System error might happen on
systems that use a special method for the system part of epoll (`epoll_create()`, `kqueue()`),
and therefore associated resources, like epoll on Linux. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_add_usock +### srt_epoll_add_ssock +### srt_epoll_update_usock +### srt_epoll_update_ssock + +``` +int srt_epoll_add_usock(int eid, SRTSOCKET u, const int* events); +int srt_epoll_add_ssock(int eid, SYSSOCKET s, const int* events); +int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events); +int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events); +``` + +Adds a socket to a container, or updates an existing socket subscription. + +The `_usock` suffix refers to a user socket (SRT socket). +The `_ssock` suffix refers to a system socket. + +The `_add_` functions add new sockets. The `_update_` functions act on a socket that +is in the container already and just allow changes in the subscription details. For +example, if you have already subscribed a socket with [`SRT_EPOLL_OUT`](#SRT_EPOLL_OUT) +to wait until it's connected, to change it into poll for read-readiness, you use this +function on that same socket with a variable set to [`SRT_EPOLL_IN`](#SRT_EPOLL_IN). +This will not only change the event type which is polled on the socket, but also +remove any readiness status for flags that are no longer set. It is discouraged +to perform socket removal and adding back (instead of using `_update_`) because +this way you may miss an event that could happen in the brief moment between +these two calls. + +**Arguments**: + +* `eid`: epoll container id +* `u`: SRT socket +* `s`(#s): system socket +* `events`: points to + * a variable set to epoll flags (see below) to use only selected events + * NULL if you want to subscribe a socket for all events in level-triggered mode + +Possible epoll flags are the following: + + * `SRT_EPOLL_IN`: report readiness for reading or incoming connection on a listener socket + * `SRT_EPOLL_OUT`: report readiness for writing or a successful connection + * `SRT_EPOLL_ERR`: report errors on the socket + * `SRT_EPOLL_UPDATE`: an important event has happened that requires attention + * `SRT_EPOLL_ET`: the event will be edge-triggered + +All flags except [`SRT_EPOLL_ET`](#SRT_EPOLL_ET) are event type flags (important for functions +that expect only event types and not other flags). + +The [`SRT_EPOLL_IN`](#SRT_EPOLL_IN), [`SRT_EPOLL_OUT`](#SRT_EPOLL_OUT) and +[`SRT_EPOLL_ERR`](#SRT_EPOLL_ERR) events are by default **level-triggered**. +With [`SRT_EPOLL_ET`](#SRT_EPOLL_ET) flag they become **edge-triggered**. + +The [`SRT_EPOLL_UPDATE`](#SRT_EPOLL_UPDATE) flag is always edge-triggered. It +designates a special event that happens on a group, or on a listener socket that +has the [`SRTO_GROUPCONNECT`](API-socket-options.md#SRTO_GROUPCONNECT) flag +set to allow group connections. This flag is triggered in the following situations: + +* for group connections, when a new link has been established for a group that +is already connected (that is, has at least one connection established), +[`SRT_EPOLL_UPDATE`](#SRT_EPOLL_UPDATE) is reported for the listener socket +accepting the connection. This is intended for internal use only. An initial +connection results in reporting the group connection on that listener. But +when the group is already connected, [`SRT_EPOLL_UPDATE`](#SRT_EPOLL_UPDATE) +is reported instead. + +* when one of a group's member connection has been broken + +Note that at this time the edge-triggered mode is supported only for SRT +sockets, not for system sockets. + +In the **edge-triggered** mode the function will only return socket states that +have changed since the last call of the waiting function. All events reported +in a particular call of the waiting function will be cleared in the internal +flags and will not be reported until the internal signalling logic clears this +state and raises it again. + +In the **level-triggered** mode the function will always return the readiness +state as long as it lasts, until the internal signalling logic clears it. + +Note that when you use [`SRT_EPOLL_ET`](#SRT_EPOLL_ET) flag in one subscription +call, it defines edge-triggered mode for all events passed together with it. +However, if you want to have some events reported as edge-triggered and others +as level-triggered, you can do two separate subscriptions for the same socket. + +**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_uwait`](#srt_epoll_uwait). Note that +this function doesn't work with system file descriptors. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Success | +| -1 | Failure | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| | | + +:warning:   **BUG?**: for `add_ssock` the system error results in an empty `CUDTException()` +call which actually results in [`SRT_SUCCESS`](#srt_success). For cases like that +the [`SRT_ECONNSETUP`](#srt_econnsetup) code is predicted. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_remove_usock +### srt_epoll_remove_ssock + +``` +int srt_epoll_remove_usock(int eid, SRTSOCKET u); +int srt_epoll_remove_ssock(int eid, SYSSOCKET s); +``` + +Removes a specified socket from an epoll container and clears all readiness +states recorded for that socket. + +The `_usock` suffix refers to a user socket (SRT socket). +The `_ssock` suffix refers to a system socket. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Success | +| -1 | Failure | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_wait +``` +int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, + SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); +``` + +Blocks the call until any readiness state occurs in the epoll container. + +Readiness can be on a socket in the container for the event type as per +subscription. Note that in the case when a particular event was subscribed with +[`SRT_EPOLL_ET`](#SRT_EPOLL_ET) flag, this event, once reported in this function, +will be cleared internally. + +The first readiness state causes this function to exit, but all ready sockets +are reported. This function blocks until the timeout specified in the `msTimeOut` +parameter. If timeout is 0, it exits immediately after checking. If timeout is +-1, it blocks indefinitely until a readiness state occurs. + +**Arguments**: + +* `eid`: epoll container +* `readfds` and `rnum`: A pointer and length of an array to write SRT sockets that are read-ready +* `writefds` and `wnum`: A pointer and length of an array to write SRT sockets that are write-ready +* `msTimeOut`: Timeout specified in milliseconds, or special values (0 or -1) +* `lwfds` and `lwnum`: A pointer and length of an array to write system sockets that are read-ready +* `lwfds` and `lwnum`: A pointer and length of an array to write system sockets that are write-ready + +Note that the following flags are reported: + +* [`SRT_EPOLL_IN`](#SRT_EPOLL_IN) as read-ready (also a listener socket ready to accept) +* [`SRT_EPOLL_OUT`](#SRT_EPOLL_OUT) as write-ready (also a connected socket) +* [`SRT_EPOLL_ERR`](#SRT_EPOLL_ERR) as both read-ready and write-ready +* [`SRT_EPOLL_UPDATE`](#SRT_EPOLL_UPDATE) is not reported + +There is no space here to report sockets for which it's already known that the operation +will end up with error (although such a state is known internally). If an error occurred +on a socket then that socket is reported in both read-ready and write-ready arrays, +regardless of what event types it was subscribed for. Usually then you subscribe the +given socket for only read readiness, for example ([`SRT_EPOLL_IN`](#SRT_EPOLL_IN)), +but pass both arrays for read and write readiness.This socket will not be reported +in the write readiness array even if it's write ready (because this isn't what it +was subscribed for), but it will be reported there, if the next operation on this +socket is about to be erroneous. On such sockets you can still perform an operation, +just you should expect that it will always report an error. On the other hand that's +the only way to know what kind of error has occurred on the socket. + +| Returns | | +|:----------------------------- |:------------------------------------------------------------ | +| Number | The number (\>0) of ready sockets, of whatever kind (if any) | +| -1 | Error | +| | | + +| Errors | | +|:----------------------------------- |:------------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| [`SRT_ETIMEOUT`](#srt_etimeout) | Up to `msTimeOut` no sockets subscribed in [`eid`](#eid) were ready. This is reported only if `msTimeOut`
was \>=0, otherwise the function waits indefinitely. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_uwait +``` +int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +``` + +This function blocks a call until any readiness state occurs in the epoll container. +Unlike [`srt_epoll_wait`](#srt_epoll_wait), it can only be used with [`eid`](#eid) +subscribed to user sockets (SRT sockets), not system sockets. + +This function blocks until the timeout specified in `msTimeOut` parameter. If +timeout is 0, it exits immediately after checking. If timeout is -1, it blocks +indefinitely until a readiness state occurs. + +**Arguments**: + +* `eid`: epoll container +* `fdsSet` : A pointer to an array of `SRT_EPOLL_EVENT` +* `fdsSize` : The size of the fdsSet array +* `msTimeOut` : Timeout specified in milliseconds, or special values (0 or -1): + * 0: Don't wait, return immediately (report any sockets currently ready) + * -1: Wait indefinitely. + +| Returns | | +|:----------------------------- |:-------------------------------------------------------------------------------------------------------------------------------------- | +| Number | The number of user socket (SRT socket) state changes that have been reported in `fdsSet`,
if this number isn't greater than `fdsSize` | +| `fdsSize` + 1 | This means that there was not enough space in the output array to report all events.
For events subscribed with the [`SRT_EPOLL_ET`](#SRT_EPOLL_ET) flag only those will be cleared that were reported.
Others will wait for the next call. | +| 0 | If no readiness state was found on any socket and the timeout has passed
(this is not possible when waiting indefinitely) | +| -1 | Error | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| [`SRT_EINVPARAM`](#srt_einvparam) | One of possible usage errors:
* `fdsSize` is < 0
* `fdsSize` is > 0 and `fdsSet` is a null pointer
* [`eid`](#eid) was subscribed to any system socket | +| | | + +**IMPORTANT**: This function reports timeout by returning 0, not by [`SRT_ETIMEOUT`](#srt_etimeout) error. + +The `SRT_EPOLL_EVENT` structure: + +``` +typedef struct SRT_EPOLL_EVENT_ +{ + SRTSOCKET fd; + int events; +} SRT_EPOLL_EVENT; +``` + +* `fd`: the user socket (SRT socket) +* [`events`](#events): event flags that report readiness of this socket - a combination +of [`SRT_EPOLL_IN`](#SRT_EPOLL_IN), [`SRT_EPOLL_OUT`](#SRT_EPOLL_OUT) and [`SRT_EPOLL_ERR`](#SRT_EPOLL_ERR). +See [srt_epoll_add_usock](#srt_epoll_add_usock) for details. + +Note that when [`SRT_EPOLL_ERR`](#SRT_EPOLL_ERR) is set, the underlying socket error +can't be retrieved with `srt_getlasterror()`. The socket will be automatically +closed and its state can be verified with a call to [`srt_getsockstate`](#srt_getsockstate). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_clear_usocks +``` +int srt_epoll_clear_usocks(int eid); +``` + +This function removes all SRT ("user") socket subscriptions from the epoll +container identified by [`eid`](#eid). + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Success | +| -1 | Failure | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_set +``` +int32_t srt_epoll_set(int eid, int32_t flags); +``` + +This function allows setting or retrieving flags that change the default +behavior of the epoll functions. All default values for these flags are 0. +The following flags are available: + +* `SRT_EPOLL_ENABLE_EMPTY`: allows the [`srt_epoll_wait`](#srt_epoll_wait) and +[`srt_epoll_uwait`](#srt_epoll_uwait) functions to be called with the EID not +subscribed to any socket. The default behavior of these function is to report +error in this case. + +* `SRT_EPOLL_ENABLE_OUTPUTCHECK`: Forces the [`srt_epoll_wait`](#srt_epoll_wait) +and [`srt_epoll_uwait`](#srt_epoll_uwait) functions to check if the output array +is not empty. For [`srt_epoll_wait`](#srt_epoll_wait) it is still allowed that +either system or user array is empty, as long as EID isn't subscribed to this +type of socket/fd. [`srt_epoll_uwait`](#srt_epoll_uwait) only checks if +the general output array is not empty. + +**Arguments**: + + * `eid`: the epoll container id + * `flags`: a nonzero set of the above flags, or special values: + * 0: clear all flags (set all defaults) + * -1: do not modify any flags + +| Returns | | +|:----------------------------- |:-------------------------------------------------------------------------- | +| | This function returns the state of the flags at the time before the call | +| -1 | Special value in case when an error occurred | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_epoll_release +``` +int srt_epoll_release(int eid); +``` + +Deletes the epoll container. + +| Returns | | +|:----------------------------- |:-------------------------------------------------------------- | +| | The number (\>0) of ready sockets, of whatever kind (if any) | +| -1 | Error | +| | | + +| Errors | | +|:----------------------------------- |:----------------------------------------------------------------- | +| [`SRT_EINVPOLLID`](#srt_einvpollid) | [`eid`](#eid) parameter doesn't refer to a valid epoll container | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + + + +## Logging Control + +* [srt_setloglevel](#srt_setloglevel) +* [srt_addlogfa, srt_dellogfa, srt_resetlogfa](#srt_addlogfa-srt_dellogfa-srt_resetlogfa) +* [srt_setloghandler](#srt_setloghandler) +* [srt_setlogflags](#srt_setlogflags) + +SRT has a widely used system of logs, as this is usually the only way to determine +how the internals are working without changing the rules by the act of tracing. +Logs are split into levels (5 levels out of those defined by syslog are in use) +and additional filtering is possible on an FA (functional area). By default only +entries up to the *Note* log level are displayed and from all FAs. + +Logging can only be manipulated globally, with no regard to a specific +socket. This is because lots of operations in SRT are not dedicated to any +particular socket, and some are shared between sockets. + +### srt_setloglevel + +``` +void srt_setloglevel(int ll); +``` + +Sets the minimum severity for logging. A particular log entry is displayed only +if it has a severity greater than or equal to the minimum. Setting this value +to `LOG_DEBUG` turns on all levels. + +The constants for this value are those from `` +(for Windows, refer to `common/win/syslog_defs.h`). The only meaningful ones are: + +* `LOG_DEBUG`: Highly detailed and very frequent messages +* `LOG_NOTICE`: Occasionally displayed information +* `LOG_WARNING`: Unusual behavior +* `LOG_ERR`: Abnormal behavior +* `LOG_CRIT`: Error that makes the current socket unusable + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_addlogfa +### srt_dellogfa +### srt_resetlogfa + +```c++ +void srt_addlogfa(int fa); +void srt_dellogfa(int fa); +void srt_resetlogfa(const int* fara, size_t fara_size); +``` + +A functional area (FA) is an additional filtering mechanism for logging. You can +set up logging to display logs only from selected FAs. The list of FAs is +collected in the `srt.h` file, as identified by the `SRT_LOGFA_` prefix. They are +not enumerated here because they may be changed very often. + +All FAs are turned on by default, except potentially dangerous ones +(such as `SRT_LOGFA_HAICRYPT`). The reason is that they may display either +some security information that shall remain in memory only (so, only +if strictly required for development), or some duplicated information +(so you may want to turn one FA on, while turning off the others). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_setloghandler + +```c++ +void srt_setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); +typedef void SRT_LOG_HANDLER_FN(void* opaque, int level, const char* file, int line, const char* area, const char* message); +``` + +By default logs are printed to standard error stream. This function replaces +the sending to a stream with a handler function that will receive them. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_setlogflags + +```c++ +void srt_setlogflags(int flags); +``` + +When you set a log handler with [`srt_setloghandler`](#srt_setloghandler), you +may also want to configure which parts of the log information you do not wish to +be passed in the log line (the `message` parameter). A user's logging facility may, +for example, not wish to get the current time or log level marker, as it +will provide this information on its own. + +The following flags are available, as collected in the `logging_api.h` public header: + +- `SRT_LOGF_DISABLE_TIME`: Do not provide the time in the header +- `SRT_LOGF_DISABLE_THREADNAME`: Do not provide the thread name in the header +- `SRT_LOGF_DISABLE_SEVERITY`: Do not provide severity information in the header +- `SRT_LOGF_DISABLE_EOL`: Do not add the end-of-line character to the log line + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + +## Time Access + +* [srt_time_now](#srt_time_now) +* [srt_connection_time](#srt_connection_time) + +The following set of functions is intended to retrieve timestamps from the clock +used by SRT. + +The sender can pass the timestamp in `MSGCTRL::srctime` of the `srt_sendmsg2(..)` +function together with the packet being submitted to SRT. If the `srctime` value +is not provided (the default value of 0 is set), SRT will use the internal clock +and assign packet submission time as the packet timestamp. If the sender wants to +explicitly assign a timestamp to a certain packet this timestamp MUST be taken +from SRT Time Access functions. The time value provided MUST equal or exceed the +connection start time (`srt_connection_time(..)`) of the SRT socket passed +to `srt_sendmsg2(..)`. + +The current time value of the SRT internal clock can be retrieved using +the `srt_time_now()` function. + +There are two known cases where you might want to use `srctime`: + +1. SRT passthrough (for stream gateways). +You may wish to simply retrieve packets from an SRT source and pass them transparently +to an SRT output (possibly re-encrypting). In that case, every packet you read should +preserve the original value of `srctime` as obtained from [`srt_recvmsg2`](#srt_recvmsg2), +and the original `srctime` for each packet should be then passed to [`srt_sendmsg2`](#srt_sendmsg). +This mechanism could be used to avoid jitter resulting from varying differences between +the time of receiving and sending the same packet. + +2. Stable timing source. +In the case of a live streaming procedure, when spreading packets evenly into the stream, +you might want to predefine times for every single packet to keep time intervals perfectly equal. +Or, if you believe that your input signal delivers packets at the exact times that should be +assigned to them, you might want to preserve these times at the SRT receiving side +to avoid jitter that may result from varying time differences between the packet arrival +and the moment when sending it over SRT. In such cases you might do the following: + + - At the packet arrival time, grab the current time at that moment using `srt_time_now()`. + + - When you want a pre-calculated packet time, use a private relative time counter + set at the moment when the connection was made. From the moment when your first packet + is ready, start pre-calculating packet times relative to the connection start time obtained + from `srt_connection_time()`. Although you still have to synchronize sending times with these + predefined times, by explicitly specifying the source time you avoid the jitter + resulting from a lost accuracy due to waiting time and unfortunate thread scheduling. + +Note that `srctime` uses an internally defined clock that is intended to be monotonic +(the definition depends on the build flags, see below). Because of that **the application +should not define this time basing on values obtained from the system functions for getting +the current system time** (such as `time`, `ftime` or `gettimeofday`). To avoid problems and +misunderstanding you should rely exclusively on time values provided by the +`srt_time_now()` and `srt_connection_time()` functions. + +The clock used by the SRT internal clock is determined by the following build flags: +- `ENABLE_MONOTONIC` makes use of `CLOCK_MONOTONIC` with `clock_gettime` function. +- `ENABLE_STDXXX_SYNC` makes use of `std::chrono::steady_clock`. + +The default is currently to use the system clock as the internal SRT clock, +although it's highly recommended to use one of the above monotonic clocks, +as system clock is vulnerable to time modifications during transmission. + +### srt_time_now + +```c++ +int64_t srt_time_now(); +``` + +Get time in microseconds elapsed since epoch using SRT internal clock (steady or monotonic clock). + +| Returns | | +|:----------------------------- |:------------------------------------------------------------------------ | +| | Current time in microseconds elapsed since epoch of SRT internal clock. | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_connection_time + +```c++ +int64_t srt_connection_time(SRTSOCKET sock); +``` + +Get connection time in microseconds elapsed since epoch using SRT internal clock +(steady or monotonic clock). The connection time represents the time when SRT socket +was open to establish a connection. Milliseconds elapsed since connection start time +can be determined using [**Performance tracking**](#Performance-tracking) functions +and `msTimeStamp` value of the `SRT_TRACEBSTATS` (see [SRT Statistics](statistics.md)). + +| Returns | | +|:----------------------------- |:--------------------------------------------------------------------------- | +| | Connection time in microseconds elapsed since epoch of SRT internal clock | +| -1 | Error | +| | | + +| Errors | | +|:--------------------------------- |:---------------------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket `sock` is not an ID of a valid SRT socket | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_clock_type + +```c +int srt_clock_type(void); +``` + +Get the type of clock used internally by SRT to be used only for informational purposes. +Using any time source except for [`srt_time_now()`](#srt_time_now) and [`srt_connection_time(SRTSOCKET)`](#srt_connection_time) +to timestamp packets submitted to SRT is not recommended and must be done with awareness and at your own risk. + +| Returns | Clock Type | Description | +| :------ | :---------------------------------- | :------------------------------------------| +| 0 | `SRT_SYNC_CLOCK_STDCXX_STEADY` | C++11 `std::chrono::steady_clock` | +| 1 | `SRT_SYNC_CLOCK_GETTIME_MONOTONIC` | `clock_gettime` with `CLOCK_MONOTONIC` | +| 2 | `SRT_SYNC_CLOCK_WINQPC` | Windows `QueryPerformanceCounter(..)` | +| 3 | `SRT_SYNC_CLOCK_MACH_ABSTIME` | `mach_absolute_time()` | +| 4 | `SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY` | POSIX `gettimeofday(..)` | +| 5 | `SRT_SYNC_CLOCK_AMD64_RDTSC` | `asm("rdtsc" ..)` | +| 6 | `SRT_SYNC_CLOCK_IA32_RDTSC` | `asm volatile("rdtsc" ..)` | +| 7 | `SRT_SYNC_CLOCK_IA64_ITC` | `asm("mov %0=ar.itc" ..)` | + +| Errors | | +|:--------------------------------- |:---------------------------------------------------------- | +| None | | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + + +## Diagnostics + +* [srt_getlasterror_str](#srt_getlasterror_str) +* [srt_getlasterror](#srt_getlasterror) +* [srt_strerror](#srt_strerror) +* [srt_clearlasterror](#srt_clearlasterror) +* [srt_getrejectreason](#srt_getrejectreason) +* [srt_rejectreason_str](#srt_rejectreason_str) +* [srt_setrejectreason](#srt_setrejectreason) + +General notes concerning the `getlasterror` diagnostic functions: when an API +function ends up with error, this error information is stored in a thread-local +storage. This means that you'll get the error of the operation that was last +performed as long as you call this diagnostic function just after the failed +function has returned. In any other situation the information provided by the +diagnostic function is undefined. + +**NOTE**: There are lists of rejection reasons and error codes at the bottom of this section. + + +### srt_getlasterror + +``` +int srt_getlasterror(int* errno_loc); +``` + +Get the numeric code of the last error. Additionally, in the variable passed as +`errno_loc` the system error value is returned, or 0 if there was no system error +associated with the last error. The system error is: + + * On POSIX systems, the value from `errno` + * On Windows, the result from `GetLastError()` call + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_strerror +``` +const char* srt_strerror(int code, int errnoval); +``` + +Returns a string message that represents a given SRT error code and possibly the +`errno` value, if not 0. + +**NOTE:** *This function isn't thread safe. It uses a static variable to hold the +error description. There's no problem with using it in a multithreaded environment, +as long as only one thread in the whole application calls this function at the +moment* + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getlasterror_str +``` +const char* srt_getlasterror_str(void); +``` + +Get the text message for the last error. It's a shortcut to calling first +`srt_getlasterror` and then passing the returned value into [`srt_strerror`](#srt_strerror). +Note that, contrary to [`srt_strerror`](#srt_strerror), this function is thread safe. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_clearlasterror + +``` +void srt_clearlasterror(void); +``` + +This function clears the last error. After this call, `srt_getlasterror` will +report a "successful" code. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_rejectreason_str + +``` +const char* srt_rejectreason_str(enum SRT_REJECT_REASON id); +``` + +Returns a constant string for the reason of the connection rejected, as per given +code ID. It provides a system-defined message for values below `SRT_REJ_E_SIZE`. +For other values below `SRT_REJC_PREDEFINED` it returns the string for +[`SRT_REJ_UNKNOWN`](#SRT_REJ_UNKNOWN). For values since `SRT_REJC_PREDEFINED` on, +returns "Application-defined rejection reason". + +The actual messages assigned to the internal rejection codes, that is, less than +`SRT_REJ_E_SIZE`, can be also obtained from the `srt_rejectreason_msg` array. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_setrejectreason + +``` +int srt_setrejectreason(SRTSOCKET sock, int value); +``` + +Sets the rejection code on the socket. This call is only useful in the listener +callback. The code from `value` set this way will be set as a rejection reason +for the socket. After the callback rejects the connection, the code will be passed +back to the caller peer with the handshake response. + +Note that allowed values for this function begin with `SRT_REJC_PREDEFINED` +(that is, you cannot set a system rejection code). For example, your application +can inform the calling side that the resource specified under the `r` key in the +StreamID string (see [`SRTO_STREAMID`](API-socket-options.md#SRTO_STREAMID)) +is not available - it then sets the value to `SRT_REJC_PREDEFINED + 404`. + +| Returns | | +|:----------------------------- |:--------------------------------------------------------- | +| 0 | Error | +| -1 | Success | +| | | + +| Errors | | +|:--------------------------------- |:-------------------------------------------- | +| [`SRT_EINVSOCK`](#srt_einvsock) | Socket `sock` is not an ID of a valid socket | +| [`SRT_EINVPARAM`](#srt_einvparam) | `value` is less than `SRT_REJC_PREDEFINED` | +| | | + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### srt_getrejectreason + +``` +int srt_getrejectreason(SRTSOCKET sock); +``` +This function provides a more detailed reason for a failed connection attempt. It +shall be called after a connecting function (such as [`srt_connect`](#srt_connect)) +has returned an error, the code for which is [`SRT_ECONNREJ`](#srt_econnrej). If +[`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) has been set on the socket +used for the connection, the function should also be called when the +[`SRT_EPOLL_ERR`](#SRT_EPOLL_ERR) event is set for this socket. It returns +a numeric code, which can be translated into a message by +[`srt_rejectreason_str`](#srt_rejectreason_str). + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### Rejection Reasons + + +#### SRT_REJ_UNKNOWN + +A fallback value for cases when there was no connection rejected. + + +#### SRT_REJ_SYSTEM + +One system function reported a failure. Usually this means some system +error or lack of system resources to complete the task. + + +#### SRT_REJ_PEER + +The connection has been rejected by peer, but no further details are available. +This usually means that the peer doesn't support rejection reason reporting. + + +#### SRT_REJ_RESOURCE + +A problem with resource allocation (usually memory). + + +#### SRT_REJ_ROGUE + +The data sent by one party to another cannot be properly interpreted. This +should not happen during normal usage, unless it's a bug, or some weird +events are happening on the network. + + +#### SRT_REJ_BACKLOG + +The listener's backlog has exceeded its queue limit (there are many other callers +waiting for the opportunity of being connected and wait in the queue, which has +reached its limit). + + +#### SRT_REJ_IPE + +Internal Program Error. This should not happen during normal usage and it +usually means a bug in the software (although this can be reported by both +local and foreign host). + + +#### SRT_REJ_CLOSE + +The listener socket was able to receive your request, but at this moment it +is being closed. It's likely that your next attempt will result in a timeout. + + +#### SRT_REJ_VERSION + +One party of the connection has set up a minimum version that is required for +that connection, but the other party didn't satisfy this requirement. + + +#### SRT_REJ_RDVCOOKIE + +Rendezvous cookie collision. This normally should never happen, or the +probability that it will happen is negligible. However this can also be +a result of a misconfiguration in that you are trying to make a +rendezvous connection where both parties try to bind to the same IP +address, or both are local addresses of the same host. In such a case +the sent handshake packets are returning to the same host as if they +were sent by the peer (i.e. a party is sending to itself). When this happens, +this reject reason will be reported by every attempt. + + +#### SRT_REJ_BADSECRET + +Both parties have defined a passphrase for connection, but they differ. + + +#### SRT_REJ_UNSECURE + +Only one connection party has set up a password. See also the +[`SRTO_ENFORCEDENCRYPTION`](API-socket-options.md#SRTO_ENFORCEDENCRYPTION) flag. + + +#### SRT_REJ_MESSAGEAPI + +The value of the [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) +flag is different on both connection parties. + + +#### SRT_REJ_CONGESTION + +The [`SRTO_CONGESTION`](API-socket-options.md#SRTO_CONGESTION)option has +been set up differently on both connection parties. + + +#### SRT_REJ_FILTER + +The [`SRTO_PACKETFILTER`](API-socket-options.md#SRTO_PACKETFILTER) option +has been set differently on both connection parties. + + +#### SRT_REJ_GROUP + +The group type or some group settings are incompatible for both connection parties. +While every connection within a bonding group may have different target addresses, +they should all designate the same endpoint and the same SRT application. If this +condition isn't satisfied, then the peer will respond with a different peer group +ID for the connection that is trying to contact a machine/application that is +completely different from the existing connections in the bonding group. + + +#### SRT_REJ_TIMEOUT + +The connection wasn't rejected, but it timed out. This code is always set on +connection timeout, but this is the only way to get this state in non-blocking +mode (see [`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN)). + +There may also be server and user rejection codes, as defined by the +`SRT_REJC_INTERNAL`, `SRT_REJC_PREDEFINED` and `SRT_REJC_USERDEFINED` +constants. Note that the number space from the value of `SRT_REJC_PREDEFINED` +and above is reserved for "predefined codes" (`SRT_REJC_PREDEFINED` value plus +adopted HTTP codes). Values above `SRT_REJC_USERDEFINED` are freely defined by +the application. + + +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- + +### Error Codes + +All functions that return the status via `int` value return -1 (designated as +`SRT_ERROR`) always when the call has failed (in case of resource creation +functions an appropriate symbol is defined, like `SRT_INVALID_SOCK` for +`SRTSOCKET`). When this happens, the error code can be obtained from the +`srt_getlasterror` function. The values for the error are collected in an +`SRT_ERRNO` enum: + + +#### SRT_EUNKNOWN + +Internal error when setting the right error code. + + +#### SRT_SUCCESS + +The value set when the last error was cleared and no error has occurred since then. + + +#### SRT_ECONNSETUP + +General setup error resulting from internal system state. + + +#### SRT_ENOSERVER + +Connection timed out while attempting to connect to the remote address. Note +that when this happens, [`srt_getrejectreason`](#srt_getrejectreason) also reports +the timeout reason. + + +#### SRT_ECONNREJ + +Connection has been rejected. Additional reject reason can be obtained through +[`srt_getrejectreason`](#srt_getrejectreason) (see above). + + +#### SRT_ESOCKFAIL + +An error occurred when trying to call a system function on an internally used +UDP socket. Note that the detailed system error is available in the extra variable +passed by pointer to `srt_getlasterror`. + + +#### SRT_ESECFAIL + +A possible tampering with the handshake packets was detected, or an encryption +request wasn't properly fulfilled. + + +#### SRT_ESCLOSED + +A socket that was vital for an operation called in blocking mode +has been closed during the operation. Please note that this situation is +handled differently than the system calls for `connect` and `accept` +functions for TCP, which simply block indefinitely (or until the standard +timeout) when the key socket was closed during an operation. When this +error is reported, it usually means that the socket passed as the first +parameter to [`srt_connect*`](#srt_connect) or [`srt_accept`](#srt_accept) +is no longer usable. + + +#### SRT_ECONNFAIL + +General connection failure of unknown details. + + +#### SRT_ECONNLOST + +The socket was properly connected, but the connection has been broken. +This specialization is reported from the transmission functions. + + +#### SRT_ENOCONN + +The socket is not connected. This can be reported also when the connection was +broken for a function that checks some characteristic socket data. + + +#### SRT_ERESOURCE + +System or standard library error reported unexpectedly for unknown purpose. +Usually it means some internal error. + + +#### SRT_ETHREAD + +System was unable to spawn a new thread when required. + + +#### SRT_ENOBUF + +System was unable to allocate memory for buffers. + + +#### SRT_ESYSOBJ + +System was unable to allocate system specific objects (such as +sockets, mutexes or condition variables). + + +#### SRT_EFILE + +General filesystem error (for functions operating with file transmission). + + +#### SRT_EINVRDOFF + +Failure when trying to read from a given position in the file (file could +be modified while it was read from). + + +#### SRT_ERDPERM + +Read permission was denied when trying to read from file. + + +#### SRT_EINVWROFF + +Failed to set position in the written file. + + +#### SRT_EWRPERM + +Write permission was denied when trying to write to a file. + + +#### SRT_EINVOP + +Invalid operation performed for the current state of a socket. This mainly +concerns performing `srt_bind*` operations on a socket that is already bound. +Once a socket has been been bound, it cannot be bound again. + + +#### SRT_EBOUNDSOCK + +The socket is currently bound and the required operation cannot be +performed in this state. Usually it's about an option that can only +be set on the socket before binding (`srt_bind*`). Note that a socket +that is currently connected is also considered bound. + + +#### SRT_ECONNSOCK + +The socket is currently connected and therefore performing the required operation +is not possible. Usually concerns setting an option that must be set before +connecting (although it is allowed to be altered after binding), or when trying +to start a connecting operation ([`srt_connect*`](#srt_connect)) while the socket +isn't in a state that allows it (only [`SRTS_INIT`](#SRTS_INIT) or +[`SRTS_OPENED`](#SRTS_OPENED) are allowed). + + +#### SRT_EINVPARAM + +This error is reported in a variety of situations when call parameters +for API functions have some requirements defined and these were not +satisfied. This error should be reported after an initial check of the +parameters of the call before even performing any operation. This error +can be easily avoided if you set the values correctly. + + +#### SRT_EINVSOCK + +The API function required an ID of an entity (socket or group) and +it was invalid. Note that some API functions work only with socket or +only with group, so they would also return this error if inappropriate +type of entity was passed, even if it was valid. + + +#### SRT_EUNBOUNDSOCK + +The operation to be performed on a socket requires that it first be explicitly +bound (using [`srt_bind*`](#srt_bind) functions). Currently it applies when +calling [`srt_listen`](#srt_listen), which cannot work with an implicitly +bound socket. + + +#### SRT_ENOLISTEN + +The socket passed for the operation is required to be in the listen +state ([`srt_listen`](#srt_listen) must be called first). + + +#### SRT_ERDVNOSERV + +The required operation cannot be performed when the socket is set to rendezvous +mode ([`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) set to true). +Usually applies when trying to call [`srt_listen`](#srt_listen) on such a socket. + + +#### SRT_ERDVUNBOUND + +An attempt was made to connect to a socket set to rendezvous mode +([`SRTO_RENDEZVOUS`](API-socket-options.md#SRTO_RENDEZVOUS) set to true) +that was not first bound. A rendezvous connection requires setting up two addresses +and ports on both sides of the connection, then setting the local one with +[`srt_bind`](#srt_bind) and using the remote one with [`srt_connect`](#srt_connect) +(or you can simply use [`srt_rendezvous`](#srt_rendezvous)). Calling +[`srt_connect*`](#srt_connect) on an unbound socket (in [`SRTS_INIT`](#SRTS_INIT) +state) that is to be bound implicitly is only allowed for regular caller sockets +(not rendezvous). + + +#### SRT_EINVALMSGAPI + +The function was used incorrectly in the message API. This can happen if: + +* The parameters specific for the message API in [`SRT_MSGCTRL`](#SRT_MSGCTRL) +type parameter were incorrectly specified. + +* The extra parameter check performed by the congestion controller has failed. + +* The socket is a member of a self-managing group, therefore you should +perform the operation on the group, not on this socket. + + +#### SRT_EINVALBUFFERAPI + +The function was used incorrectly in the stream (buffer) API, that is, either the +stream-only functions were used with set message API ([`srt_sendfile`](#srt_sendfile)/[`srt_recvfile`](#srt_recvfile)) +or TSBPD mode was used with buffer API ([`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) set to true) +or the congestion controller has failed to check call parameters. + + +#### SRT_EDUPLISTEN + +The port tried to be bound for listening is already busy. Note that binding to the same port +is allowed in general (when [`SRTO_REUSEADDR`](API-socket-options.md#SRTO_REUSEADDRS) +is true on every socket that has bound it), but only one such socket can be a listener. + + +#### SRT_ELARGEMSG + +Size exceeded. This is reported in the following situations: + +* Trying to receive a message, but the read-ready message is larger than +the buffer passed to the receiving function. + +* Trying to send a message, but the size of this message exceeds the +size of the preset sender buffer, so it cannot be stored in the sender buffer. + +* When getting group data, the array to be filled is too small. + + +#### SRT_EINVPOLLID + +The epoll ID passed to an epoll function is invalid. + + +#### SRT_EPOLLEMPTY + +The epoll container currently has no subscribed sockets. This is reported by an +epoll waiting function that would in this case block forever. This problem +might be reported both in a situation where you have created a new epoll +container and didn't subscribe any sockets to it, or you did, but these +sockets have been closed (including when closed in a separate thread while the +waiting function was blocking). Note that this situation can be prevented +by setting the `SRT_EPOLL_ENABLE_EMPTY` flag, which may be useful when +you use multiple threads and start waiting without subscribed sockets, so that +you can subscribe them later from another thread. + + +#### `SRT_EBINDCONFLICT` + +The binding you are attempting to set up a socket with cannot be completed because +it conflicts with another existing binding. This is because an intersecting binding +was found that cannot be reused according to the specification in `srt_bind` call. + +A binding is considered intersecting if the existing binding has the same port +and covers at least partially the range as that of the attempted binding. These +ranges can be split in three groups: + +1. An explicitly specified IP address (both IPv4 and IPv6) covers this address only. +2. An IPv4 wildcard 0.0.0.0 covers all IPv4 addresses (but not IPv6). +3. An IPv6 wildcard :: covers: + * if `SRTO_IPV6ONLY` is true - all IPv6 addresses (but not IPv4) + * if `SRTO_IPV6ONLY` is false - all IP addresses. + +Example 1: + +* Socket 1: bind to IPv4 0.0.0.0 +* Socket 2: bind to IPv6 :: with `SRTO_IPV6ONLY` = true +* Result: NOT intersecting + +Example 2: + +* Socket 1: bind to IPv4 1.2.3.4 +* Socket 2: bind to IPv4 0.0.0.0 +* Result: intersecting (and conflicting) + +Example 3: + +* Socket 1: bind to IPv4 1.2.3.4 +* Socket 2: bind to IPv6 :: with `SRTO_IPV6ONLY` = false +* Result: intersecting (and conflicting) + +If any common range coverage is found between the attempted binding specification +(in `srt_bind` call) and the found existing binding with the same port number, +then all of the following conditions must be satisfied between them: + +1. The `SRTO_REUSEADDR` must be true (default) in both. + +2. The IP address specification (in case of IPv6, also including the value of +`SRTO_IPV6ONLY` flag) must be exactly identical. + +3. The UDP-specific settings must be identical. + +If any of these conditions isn't satisfied, the `srt_bind` function results +in conflict and report this error. + +#### SRT_EASYNCFAIL + +General asynchronous failure (not in use currently). + + +#### SRT_EASYNCSND + +Sending operation is not ready to perform. This error is reported when trying to +perform a sending operation on a socket that is not ready for sending, but +[`SRTO_SNDSYN`](API-socket-options.md#SRTO_SNDSYN) was set to false (when +true, the function would block the call otherwise). + + +#### SRT_EASYNCRCV + +Receiving operation is not ready to perform. This error is reported when trying to +perform a receiving operation or accept a new socket from the listener socket, when +the socket is not ready for that operation, but [`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) +was set to false (when true, the function would block the call otherwise). + + +#### SRT_ETIMEOUT + +The operation timed out. This can happen if you have a timeout set by an option +([`SRTO_RCVTIMEO`](API-socket-options.md#SRTO_RCVTIMEO) or +[`SRTO_SNDTIMEO`](API-socket-options.md#SRTO_SNDTIMEO)), or passed as an +extra argument ([`srt_epoll_wait`](#srt_epoll_wait) or [`srt_accept_bond`](#srt_accept_bond)) +and the function call was blocking, but the required timeout time has passed. + + +#### SRT_ECONGEST + +**NOTE**: This error is used only in an experimental version that requires +setting the `SRT_ENABLE_ECN` macro at compile time. Otherwise the situation +described below results in the usual successful report. + +This error should be reported by the sending function when, with +[`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) and +[`SRTO_TLPKTDROP`](API-socket-options.md#SRTO_TLPKTDROP) set to true, some +packets were dropped at the sender side (see the description of +[`SRTO_TLPKTDROP`](API-socket-options.md#SRTO_TLPKTDROP) for details). This +doesn't concern the data that were passed for sending by the sending function +(these data are placed at the back of the sender buffer, while the dropped +packets are at the front). In other words, the operation done by the sending +function is successful, but the application might want to slow down the sending +rate to avoid congestion. + + +#### SRT_EPEERERR + +This error is reported when a receiver peer is writing to a file that an agent +is sending. When the peer encounters an error when writing the received data to +a file, it sends the `UMSG_PEERERROR` message back to the sender, and the sender +reports this error from the API sending function. + + +[Return to Top of Page](#SRT-API-Functions) diff --git a/docs/API/API-socket-options.md b/docs/API/API-socket-options.md new file mode 100644 index 000000000..a06f8556d --- /dev/null +++ b/docs/API/API-socket-options.md @@ -0,0 +1,1727 @@ +# SRT API Socket Options + +There is a general method of setting options on a socket in the SRT C API, similar +to the system `setsockopt/getsockopt` functions. + +- [Types Used in Socket Options](#types-used-in-socket-options) +- [Getting and Setting Options](#getting-and-setting-options) +- [List of Options](#list-of-options) + +## Types Used in Socket Options + +Possible types of socket options are: + +- `int32_t` - a 32-bit integer. On most systems similar to `int`. +In some cases the value is expressed using an enumeration type +(see [Enumeration types...](#enumeration_types) section below). + +- `int64_t` - a 64-bit integer. + +- `bool` - a Boolean type (`` for C, or built-in +for C++). When *setting* an option, passing the value through an `int` type is +also properly recognized. When *getting* an option, however, the`bool` type +should be used. It is also possible to pass a variable of `int` type initialized +with 0 and then comparing the resulting value with 0 (just don't compare +the result with 1 or `true`). + +- `string` - a C string. When *setting* an option, a `const char*` character array pointer +is expected to be passed in `optval` and the array length in `optlen` **without the terminating NULL character**. +When *getting*, an array is expected to be passed in `optval` with a +sufficient size **with an extra space for the terminating NULL character** provided in `optlen`. +The return value of `optlen` does not count the terminating NULL character. + +- `linger` - Linger structure. Used exclusively with `SRTO_LINGER`. + +### Enumeration Types Used in Options + +#### `SRT_TRANSTYPE` + +Used by `SRTO_TRANSTYPE` option: + +- `SRTT_LIVE`: Live mode. +- `SRTT_FILE`: File mode. + +See [Transmission Types](API.md#transmission-types) for details. + +#### `SRT_KM_STATE` + +The defined encryption state as performed by the Key Material Exchange, used +by `SRTO_RCVKMSTATE`, `SRTO_SNDKMSTATE` and `SRTO_KMSTATE` options: + +- `SRT_KM_S_UNSECURED` (`0`): no encryption/decryption. If this state is only on +the receiver, received encrypted packets will be dropped. + +- `SRT_KM_S_SECURING`(`1`): pending security (HSv4 only). This is a temporary state +used only if the connection uses HSv4 and the Key Material Exchange is +not finished yet. On HSv5 this is not possible because the Key Material +Exchange for the initial key is done in the handshake. + +- `SRT_KM_S_SECURED` (`2`): KM exchange was successful and the data will be sent +encrypted and will be decrypted by the receiver. This state is only possible on +both sides in both directions simultaneously. Any unencrypted packet will be dropped by the receiver. + +- `SRT_KM_S_NOSECRET` (`3`): If this state is in the sending direction (`SRTO_SNDKMSTATE`), +then it means that the sending party has set a passphrase, but the peer did not. +In this case the sending party can receive unencrypted packets from the peer, but +packets it sends to the peer will be encrypted and the peer will not be able to +decrypt them. This state is only possible in HSv5. + +- `SRT_KM_S_BADSECRET` (`4`): The password is wrong (set differently on each party); +encrypted payloads won't be decrypted in either direction. + +- `SRT_KM_S_BADCRYPTOMODE` (`5`): The crypto mode mode configuration is either not supported +or mismatches the configuration of the peer. + + +Note that with the default value of `SRTO_ENFORCEDENCRYPTION` option (true), +the state is equal on both sides in both directions, and it can be only +`SRT_KM_S_UNSECURED` or `SRT_KM_S_SECURED` (in other cases the connection +is rejected). Otherwise it may happen that either both sides have different +passwords and the state is `SRT_KM_S_BADSECRET` in both directions, or only +one party has set a password, in which case the KM state is as follows: + +| | `SRTO_RCVKMSTATE` | `SRTO_SNDKMSTATE` | +|--------------------------|----------------------|----------------------| +| Party with no password: | `SRT_KM_S_NOSECRET` | `SRT_KM_S_UNSECURED` | +| Party with password: | `SRT_KM_S_UNSECURED` | `SRT_KM_S_NOSECRET` | + +## Getting and Setting Options + +Legacy version: + + int srt_getsockopt(SRTSOCKET socket, int level, SRT_SOCKOPT optName, void* optval, int& optlen); + int srt_setsockopt(SRTSOCKET socket, int level, SRT_SOCKOPT optName, const void* optval, int optlen); + +New version: + + int srt_getsockflag(SRTSOCKET socket, SRT_SOCKOPT optName, void* optval, int& optlen); + int srt_setsockflag(SRTSOCKET socket, SRT_SOCKOPT optName, const void* optval, int optlen); + +In the legacy version, there's an additional unused `level` parameter. It was +there in the original UDT API just to mimic the system `setsockopt` function, +but it's ignored. + +Some options require a value of type `bool` while others require type `integer`, +which is not the same -- they differ in size, and mistaking them may end up +causing a crash. This must be kept in mind especially in any C wrapper. For +convenience, the *setting* option function may accept both `int32_t` and `bool` +types, but this is not so in the case of *getting* an option value. + +**UDT project legacy note**: Almost all options from the UDT library are +derived (there are a few deleted, including some deprecated already in UDT). +Many new SRT options have been added. All options are available exclusively +with the `SRTO_` prefix. Old names are provided as alias names in the `udt.h` +legacy/C++ API file. Note the translation rules: + +* `UDT_` prefix from UDT options was changed to the prefix `SRTO_` +* `UDP_` prefix from UDT options was changed to the prefix `SRTO_UDP_` +* `SRT_` prefix in older SRT versions was changed to `SRTO_` + +The [table below](#list-of-options) provides a complete list of SRT options and +their characteristics according to the following legend: + +1. **Since**: Defines the SRT version when this option was first introduced. If this field +is empty, it's an option derived from UDT. "Version 0.0.0" is the oldest version +of SRT ever created and put into use. + +2. **Restrict**: Defines restrictions on setting the option. The field is empty if the option +is not settable (see **Dir** column): + + - `pre-bind`: The option cannot be altered on a socket that is already bound (by calling +`srt_bind()` or any other function doing this, including automatic binding when trying to +connect, as well as accepted sockets). In other words, once an SRT socket has transitioned from +`SRTS_INIT` to `SRTS_OPENED` socket state. + + - `pre`: The option cannot be altered on a socket that is in `SRTS_LISTENING`, `SRTS_CONNECTING` +or `SRTS_CONNECTED` state. If an option was set on a listener socket, it will be inherited +by a socket returned by `srt_accept()` (except for `SRTO_STREAMID`). + + - `post`: The option is unrestricted and can be altered at any time, including when the +socket is connected, as well as on an accepted socket. The setting of this flag on a listening +socket is usually derived by the accepted socket, but this isn't a rule for all options. +Note though that there are some unrestricted options that have an important meaning when +set prior to connecting (different one than for a connected socket). + + **NOTE**: The `pre-bind` characteristic applies exclusively to options that: + + - Change the behavior and functionality of the `srt_bind` call + - Concern or set an option on the internally used UDP socket + - Concern any kind of resource used by the multiplexer + +3. **Type**: The data type of the option (see above). + +4. **Units**: Roughly specified unit, if the value defines things like length or time. +It can also define more precisely what kind of specialization can be used +when the type is integer: + + - `enum`: the possible values are defined in an enumeration type + - `flags`: the integer value is a collection of bit flags + - `B/s` - bytes per second. + +5. **Default**: The exact default value, if it can be easily specified. A more complicated +default state of a particular option will be explained in the [description](#option-descriptions) +(when marked by asterisk). For non-settable options this field is empty. + +6. **Range**: If a value of an integer type has a limited range, or only a certain value +allowed, it will be specified here (otherwise empty). A range value can be +specified as: + + - `X-... `: specifies only a minimum value + - `X-Y,Z `: values between X and Y are allowed, and additionally Z + + - If the value is of `string` type, this field will contain its maximum size +in square brackets. + + - If the range contains additionally an asterisk, it means that more elaborate +restrictions on the value apply, as explained in the [description](#option-descriptions). + +7. **Dir**: Option direction: W if can be set, R if can be retrieved, RW if both. + +8. **Entity**: This describes whether the option can be set on the socket or the group. +The G and S options may appear together, in which case both possibilities apply. +The D and I options, mutually exclusive, appear always with G. +The + marker can only coexist with GS. Possible specifications are: + + - S: This option can be set on a single socket (exclusively, if not GS) + + - G: This option can be set on a group (exclusively, if not GS) + + - D: If set on a group, it will be derived by the member socket + + - I: If set on a group, it will be taken and managed exclusively by the group + + - +: This option is also allowed to be set individually on a group member + socket through a configuration object in `SRT_SOCKGROUPCONFIG` prepared by + `srt_create_config`. Note that this setting may override the setting derived + from the group. + +## List of Options + +The following table lists SRT API socket options in alphabetical order. Option details are given further below. + +| Option Name | Since | Restrict | Type | Units | Default | Range | Dir |Entity | +| :------------------------------------------------------ | :---: | :------: | :-------: | :-----: | :---------------: | :------: |:---:|:-----:| +| [`SRTO_BINDTODEVICE`](#SRTO_BINDTODEVICE) | 1.4.2 | pre-bind | `string` | | | | RW | GSD+ | +| [`SRTO_CONGESTION`](#SRTO_CONGESTION) | 1.3.0 | pre | `string` | | "live" | \* | W | S | +| [`SRTO_CONNTIMEO`](#SRTO_CONNTIMEO) | 1.1.2 | pre | `int32_t` | ms | 3000 | 0.. | W | GSD+ | +| [`SRTO_CRYPTOMODE`](#SRTO_CRYPTOMODE) | 1.5.2 | pre | `int32_t` | | 0 (Auto) | [0, 2] | W | GSD | +| [`SRTO_DRIFTTRACER`](#SRTO_DRIFTTRACER) | 1.4.2 | post | `bool` | | true | | RW | GSD | +| [`SRTO_ENFORCEDENCRYPTION`](#SRTO_ENFORCEDENCRYPTION) | 1.3.2 | pre | `bool` | | true | | W | GSD | +| [`SRTO_EVENT`](#SRTO_EVENT) | | | `int32_t` | flags | | | R | S | +| [`SRTO_FC`](#SRTO_FC) | | pre | `int32_t` | pkts | 25600 | 32.. | RW | GSD | +| [`SRTO_GROUPCONNECT`](#SRTO_GROUPCONNECT) | 1.5.0 | pre | `int32_t` | | 0 | 0...1 | W | S | +| [`SRTO_GROUPMINSTABLETIMEO`](#SRTO_GROUPMINSTABLETIMEO) | 1.5.0 | pre | `int32_t` | ms | 60 | 60-... | W | GDI+ | +| [`SRTO_GROUPTYPE`](#SRTO_GROUPTYPE) | 1.5.0 | | `int32_t` | enum | | | R | S | +| [`SRTO_INPUTBW`](#SRTO_INPUTBW) | 1.0.5 | post | `int64_t` | B/s | 0 | 0.. | RW | GSD | +| [`SRTO_IPTOS`](#SRTO_IPTOS) | 1.0.5 | pre-bind | `int32_t` | | (system) | 0..255 | RW | GSD | +| [`SRTO_IPTTL`](#SRTO_IPTTL) | 1.0.5 | pre-bind | `int32_t` | hops | (system) | 1..255 | RW | GSD | +| [`SRTO_IPV6ONLY`](#SRTO_IPV6ONLY) | 1.4.0 | pre-bind | `int32_t` | | (system) | -1..1 | RW | GSD | +| [`SRTO_ISN`](#SRTO_ISN) | 1.3.0 | | `int32_t` | | | | R | S | +| [`SRTO_KMPREANNOUNCE`](#SRTO_KMPREANNOUNCE) | 1.3.2 | pre | `int32_t` | pkts | 0: 212 | 0.. \* | RW | GSD | +| [`SRTO_KMREFRESHRATE`](#SRTO_KMREFRESHRATE) | 1.3.2 | pre | `int32_t` | pkts | 0: 224 | 0.. | RW | GSD | +| [`SRTO_KMSTATE`](#SRTO_KMSTATE) | 1.0.2 | | `int32_t` | enum | | | R | S | +| [`SRTO_LATENCY`](#SRTO_LATENCY) | 1.0.2 | pre | `int32_t` | ms | 120 \* | 0.. | RW | GSD | +| [`SRTO_LINGER`](#SRTO_LINGER) | | post | `linger` | s | off \* | 0.. | RW | GSD | +| [`SRTO_LOSSMAXTTL`](#SRTO_LOSSMAXTTL) | 1.2.0 | post | `int32_t` | packets | 0 | 0.. | RW | GSD+ | +| [`SRTO_MAXBW`](#SRTO_MAXBW) | | post | `int64_t` | B/s | -1 | -1.. | RW | GSD | +| [`SRTO_MAXREXMITBW`](#SRTO_MAXREXMITBW) | 1.5.3 | post | `int64_t` | B/s | -1 | -1.. | RW | GSD | +| [`SRTO_MESSAGEAPI`](#SRTO_MESSAGEAPI) | 1.3.0 | pre | `bool` | | true | | W | GSD | +| [`SRTO_MININPUTBW`](#SRTO_MININPUTBW) | 1.4.3 | post | `int64_t` | B/s | 0 | 0.. | RW | GSD | +| [`SRTO_MINVERSION`](#SRTO_MINVERSION) | 1.3.0 | pre | `int32_t` | version | 0x010000 | \* | RW | GSD | +| [`SRTO_MSS`](#SRTO_MSS) | | pre-bind | `int32_t` | bytes | 1500 | 76.. | RW | GSD | +| [`SRTO_NAKREPORT`](#SRTO_NAKREPORT) | 1.1.0 | pre | `bool` | | \* | | RW | GSD+ | +| [`SRTO_OHEADBW`](#SRTO_OHEADBW) | 1.0.5 | post | `int32_t` | % | 25 | 5..100 | RW | GSD | +| [`SRTO_PACKETFILTER`](#SRTO_PACKETFILTER) | 1.4.0 | pre | `string` | | "" | [512] | RW | GSD | +| [`SRTO_PASSPHRASE`](#SRTO_PASSPHRASE) | 0.0.0 | pre | `string` | | "" | [10..80] | W | GSD | +| [`SRTO_PAYLOADSIZE`](#SRTO_PAYLOADSIZE) | 1.3.0 | pre | `int32_t` | bytes | \* | 0.. \* | W | GSD | +| [`SRTO_PBKEYLEN`](#SRTO_PBKEYLEN) | 0.0.0 | pre | `int32_t` | bytes | 0 | \* | RW | GSD | +| [`SRTO_PEERIDLETIMEO`](#SRTO_PEERIDLETIMEO) | 1.3.3 | pre | `int32_t` | ms | 5000 | 0.. | RW | GSD+ | +| [`SRTO_PEERLATENCY`](#SRTO_PEERLATENCY) | 1.3.0 | pre | `int32_t` | ms | 0 | 0.. | RW | GSD | +| [`SRTO_PEERVERSION`](#SRTO_PEERVERSION) | 1.1.0 | | `int32_t` | * | | | R | GS | +| [`SRTO_RCVBUF`](#SRTO_RCVBUF) | | pre-bind | `int32_t` | bytes | 8192 payloads | \* | RW | GSD+ | +| [`SRTO_RCVDATA`](#SRTO_RCVDATA) | | | `int32_t` | pkts | | | R | S | +| [`SRTO_RCVKMSTATE`](#SRTO_RCVKMSTATE) | 1.2.0 | | `int32_t` | enum | | | R | S | +| [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY) | 1.3.0 | pre | `int32_t` | msec | \* | 0.. | RW | GSD | +| [`SRTO_RCVSYN`](#SRTO_RCVSYN) | | post | `bool` | | true | | RW | GSI | +| [`SRTO_RCVTIMEO`](#SRTO_RCVTIMEO) | | post | `int32_t` | ms | -1 | -1, 0.. | RW | GSI | +| [`SRTO_RENDEZVOUS`](#SRTO_RENDEZVOUS) | | pre | `bool` | | false | | RW | S | +| [`SRTO_RETRANSMITALGO`](#SRTO_RETRANSMITALGO) | 1.4.2 | pre | `int32_t` | | 1 | [0, 1] | RW | GSD | +| [`SRTO_REUSEADDR`](#SRTO_REUSEADDR) | | pre-bind | `bool` | | true | | RW | GSD | +| [`SRTO_SENDER`](#SRTO_SENDER) | 1.0.4 | pre | `bool` | | false | | W | S | +| [`SRTO_SNDBUF`](#SRTO_SNDBUF) | | pre-bind | `int32_t` | bytes | 8192 payloads | \* | RW | GSD+ | +| [`SRTO_SNDDATA`](#SRTO_SNDDATA) | | | `int32_t` | pkts | | | R | S | +| [`SRTO_SNDDROPDELAY`](#SRTO_SNDDROPDELAY) | 1.3.2 | post | `int32_t` | ms | \* | -1.. | W | GSD+ | +| [`SRTO_SNDKMSTATE`](#SRTO_SNDKMSTATE) | 1.2.0 | | `int32_t` | enum | | | R | S | +| [`SRTO_SNDSYN`](#SRTO_SNDSYN) | | post | `bool` | | true | | RW | GSI | +| [`SRTO_SNDTIMEO`](#SRTO_SNDTIMEO) | | post | `int32_t` | ms | -1 | -1.. | RW | GSI | +| [`SRTO_STATE`](#SRTO_STATE) | | | `int32_t` | enum | | | R | S | +| [`SRTO_STREAMID`](#SRTO_STREAMID) | 1.3.0 | pre | `string` | | "" | [512] | RW | GSD | +| [`SRTO_TLPKTDROP`](#SRTO_TLPKTDROP) | 1.0.6 | pre | `bool` | | \* | | RW | GSD | +| [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) | 1.3.0 | pre | `int32_t` | enum |`SRTT_LIVE` | \* | W | S | +| [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE) | 0.0.0 | pre | `bool` | | \* | | W | S | +| [`SRTO_UDP_RCVBUF`](#SRTO_UDP_RCVBUF) | | pre-bind | `int32_t` | bytes | 8192 payloads | \* | RW | GSD+ | +| [`SRTO_UDP_SNDBUF`](#SRTO_UDP_SNDBUF) | | pre-bind | `int32_t` | bytes | 65536 | \* | RW | GSD+ | +| [`SRTO_VERSION`](#SRTO_VERSION) | 1.1.0 | | `int32_t` | | | | R | S | + +### Option Descriptions + +#### SRTO_BINDTODEVICE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir |Entity| +| --------------------- | ----- | -------- | -------- | ------ | -------- | ------ |-----|------| +| `SRTO_BINDTODEVICE` | 1.4.2 | pre-bind | `string` | | | | RW | GSD+ | + +Refers to the `SO_BINDTODEVICE` system socket option for `SOL_SOCKET` level. +This effectively limits the packets received by this socket to only those +that are targeted to that device. The device is specified by name passed as +string. The setting becomes effective after binding the socket (including +default-binding when connecting). + +NOTE: This option is only available on Linux and available there by default. +On all other platforms setting this option will always fail. + +NOTE: With the default system configuration, this option is only available +for a process that runs as root. Otherwise the function that applies the setting +(`srt_bind`, `srt_connect` etc.) will fail. + +[Return to list](#list-of-options) + +--- + +#### SRTO_CONGESTION + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_CONGESTION` | 1.3.0 | pre | `string` | | "live" | * | W | S | + +The type of congestion controller used for the transmission for that socket. + +Its type must be exactly the same on both connecting parties, otherwise the +connection is rejected - **however** you may also change the value of this +option for the accepted socket in the listener callback (see `srt_listen_callback`) +if an appropriate instruction was given in the Stream ID. + +Currently supported congestion controllers are designated as "live" and "file", +which correspond to the Live and File modes. + +Note that it is not recommended to change this option manually, but you should +rather change the whole set of options using the [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) option. + +[Return to list](#list-of-options) + +--- + +#### SRTO_CONNTIMEO + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ------------------ | ----- | -------- | --------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_CONNTIMEO` | 1.1.2 | pre | `int32_t` | msec | 3000 | 0.. | W | GSD+ | + +Connect timeout. This option applies to the caller and rendezvous connection +modes. For the rendezvous mode (see `SRTO_RENDEZVOUS`) the effective connection timeout +will be 10 times the value set with `SRTO_CONNTIMEO`. + +[Return to list](#list-of-options) + +--- + +#### SRTO_CRYPTOMODE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ------------------ | --------- | -------- | --------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_CRYPTOMODE` | 1.5.2 | pre | `int32_t` | | 0 (Auto) | [0, 2] | RW | GSD | + +The encryption mode to be used if the [`SRTO_PASSPHRASE`](#SRTO_PASSPHRASE) is set. + +The feature is a part of the AEAD Preview API of SRT v1.5.2, and is disabled by default. +To enable use [`ENABLE_AEAD_API_PREVIEW`](../build/build-options.md#enable_aead_api_preview) build option. + +Crypto modes: + +- `0`: SRT listener accepts any mode from the caller. SRT Caller or SRT Rendezvous effectively negotiate AES-CTR (1). +- `1`: regular AES-CTR (without message integrity authentication). +- `2`: AES-GCM mode with message integrity authentication (AEAD). + +The AES-GCM mode (2) is only allowed if TSBPD is enabled ([`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE)). +Auto (0) is equivalent to AES-CTR (1) in Rendezvous and for a Caller. + +Once a connection is established, reading `SRTO_CRYPTOMODE` shows the negotiated crypto mode: +AES-CTR (1) or AES-GCM (2). + +When [Listener callback](./API-functions.md##srt_listen_callback) is used, the value of +`SRTO_CRYPTOMODE` read on the new SRT socket to be accepted is not yet the +negotiated one. It is the value to be negotiated, and is inherited from the listener SRT socket. +If a specific behavior for each individual connection request is desired based on +[the user ID or anything else](../features/access-control.md), +the intended behavior can be achieved by setting the `SRTO_CRYPTOMODE` on the new SRT socket to a specific value. + +For example, let's say the initial value set on the listener socket is Auto (0). The listener callback is called, +signalling the new connection request. The user ID is extracted, and the server wants to force AES-GCM only +for the connection from this specific user. In this case AES-GCM (2) can be set on the new socket. + +There is no way to check the crypto mode being requested by the SRT caller at this point. + +| Caller | Listener | Negotiated | | Rdv In-tor | Rdv Res-der | Negotiated | +| ----------- | ----------- | ----------- |-| ----------- | ----------- | ----------- | +| 0 (auto) | 0 (auto) | AES-CTR (1) | | 0 (auto) | 0 (auto) | AES-CTR (1) | +| 0 (auto) | AES-CTR (1) | AES-CTR (1) | | 0 (auto) | AES-CTR (1) | AES-CTR (1) | +| 0 (auto) | AES-GCM (2) | reject | | 0 (auto) | AES-GCM (2) | reject | +| AES-CTR (1) | 0 (auto) | AES-CTR (1) | | AES-CTR (1) | 0 (auto) | AES-CTR (1) | +| AES-CTR (1) | AES-CTR (1) | AES-CTR (1) | | AES-CTR (1) | AES-CTR (1) | AES-CTR (1) | +| AES-CTR (1) | AES-GCM (2) | reject | | AES-CTR (1) | AES-GCM (2) | reject | +| AES-GCM (2) | 0 (auto) | AES-GCM (2) | | AES-GCM (2) | 0 (auto) | reject | +| AES-GCM (2) | AES-CTR (1) | reject | | AES-GCM (2) | AES-CTR (1) | reject | +| AES-GCM (2) | AES-GCM (2) | AES-GCM (2) | | AES-GCM (2) | AES-GCM (2) | AES-GCM (2) | + +* Rdv - Rendezvous; In-tor - initiator; Res-der - responder. + +[Return to list](#list-of-options) + +--- + +#### SRTO_DRIFTTRACER + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | --------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_DRIFTTRACER`| 1.4.2 | post | `bool` | | true | | RW | GSD | + +Enables or disables time drift tracer (receiver). + +[Return to list](#list-of-options) + +--- + +#### SRTO_ENFORCEDENCRYPTION + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_ENFORCEDENCRYPTION` | 1.3.2 | pre | `bool` | | true | | W | GSD | + +This option enforces that both connection parties have the same passphrase +set, or both do not set the passphrase, otherwise the connection is rejected. + +When this option is set to FALSE **on both connection parties**, the +connection is allowed even if the passphrase differs on both parties, +or it was set only on one party. Note that the party that has set a passphrase +is still allowed to send data over the network. However, the receiver will not +be able to decrypt that data and will not deliver it to the application. The +party that has set no passphrase can send (unencrypted) data that will be +successfully received by its peer. + +This option can be used in some specific situations when the user knows +both parties of the connection, so there's no possible situation of a rogue +sender and can be useful in situations where it is important to know whether a +connection is possible. The inability to decrypt an incoming transmission can +be then reported as a different kind of problem. + +**IMPORTANT**: There is unusual and unobvious behavior when this flag is TRUE +on the caller and FALSE on the listener, and the passphrase was mismatched. On +the listener side the connection will be established and broken right after, +resulting in a short-lived "spurious" connection report on the listener socket. +This way, a socket will be available for retrieval from an `srt_accept` call +for a very short time, after which it will be removed from the listener backlog +just as if no connection attempt was made at all. If the application is fast +enough to react on an incoming connection, it will retrieve it, only to learn +that it is already broken. This also makes possible a scenario where +`SRT_EPOLL_IN` is reported on a listener socket, but then an `srt_accept` call +reports an `SRT_EASYNCRCV` error. How fast the connection gets broken depends +on the network parameters -- in particular, whether the `UMSG_SHUTDOWN` message +sent by the caller is delivered (which takes one RTT in this case) or missed +during the interval from its creation up to the connection timeout (default = 5 +seconds). It is therefore strongly recommended that you only set this flag to +FALSE on the listener when you are able to ensure that it is also set to FALSE +on the caller side. + +[Return to list](#list-of-options) + +--- + +#### SRTO_EVENT + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | --------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_EVENT` | | | `int32_t` | flags | | | R | S | + +Returns bit flags set according to the current active events on the socket. + +Possible values are those defined in `SRT_EPOLL_OPT` enum (a combination of +`SRT_EPOLL_IN`, `SRT_EPOLL_OUT` and `SRT_EPOLL_ERR`). + +[Return to list](#list-of-options) + +--- + +#### SRTO_FC + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | --------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_FC` | | pre | `int32_t` | pkts | 25600 | 32.. | RW | GSD | + +Flow Control limits the maximum number of packets "in flight" - payload (data) packets that were sent +but reception is not yet acknowledged with an ACK control packet. +It also includes data packets already received, but that can't be acknowledged due to loss of preceding data packet(s). +In other words, if a data packet with sequence number `A` was lost, then acknowledgement of the following `SRTO_FC` packets +is blocked until packet `A` is either successfully retransmitted or dropped by the +[Too-Late Packet Drop mechanism](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-00#section-4.6). +Thus the sender will have `SRTO_FC` packets in flight, and will not be allowed to send further data packets. +Therefore, when establishing the value of `SRTO_FC`, it is recommend taking into consideration possible delays due to packet loss and retransmission. + +There is a restriction that the receiver buffer size ([SRTO_RCVBUF](#SRTO_RCVBUF)) must not be greater than `SRTO_FC` +([#700](https://github.com/Haivision/srt/issues/700)). +Therefore, it is recommended to set the value of `SRTO_FC` first, and then the value of `SRTO_RCVBUF`. + +The default flow control window size is 25600 packets. It is approximately: +- 270 Mbits of payload in the default live streaming configuration with an SRT payload size of 1316 bytes; +- 300 Mbits of payload with an SRT payload size of 1456 bytes. + +The minimum number of packets in flight should be (assuming max payload size): +`FCmin = bps / 8 × RTTsec / (MSS - 44)`, +where +- `bps` - is the payload bitrate of the stream in bits per second; +- `RTTsec` - RTT of the network connection in seconds; +- `MSS` - Maximum segment size (aka MTU), see [SRTO_MSS](#SRTO_MSS); +- 44 - size of headers (20 bytes IPv4 + 8 bytes of UDP + 16 bytes of SRT packet header). + +To avoid blocking the sending of further packets in case of packet loss, the recommended flow control window is +`FC = bps / 8 × (RTTsec + latency_sec) / (MSS - 44)`, +where `latency_sec` is the receiver buffering delay ([SRTO_RCVLATENCY](#SRTO_RCVLATENCY)) **in seconds**. + +[Return to list](#list-of-options) + +--- + +#### SRTO_GROUPCONNECT + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | --------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_GROUPCONNECT` | 1.5.0 | pre | `int32_t` | | 0 | 0...1 | W | S | + +When this flag is set to 1 on a listener socket, it allows this socket to +accept group connections. When set to the default 0, group connections will be +rejected. Keep in mind that if the `SRTO_GROUPCONNECT` flag is set to 1 (i.e. +group connections are allowed) `srt_accept` may return a socket **or** a group +ID. A call to `srt_accept` on a listener socket that has group connections +allowed must take this into consideration. It's up to the caller of this +function to make this distinction and to take appropriate action depending on +the type of entity returned. + +When this flag is set to 1 on an accepted socket that is passed to the +listener callback handler, it means that this socket is created for a group +connection and it will become a member of a group. Note that in this case +only the first connection within the group will result in reporting from +`srt_accept` (further connections are handled in the background), and this +function will return the group, not this socket ID. + +[Return to list](#list-of-options) + +--- + +#### SRTO_GROUPMINSTABLETIMEO + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_GROUPMINSTABLETIMEO` | 1.5.0 | pre | `int32_t` | ms | 60 | 60-... | W | GDI+ | + +The option is used for groups of type `SRT_GTYPE_BACKUP`. It defines the **minimum** value of the stability +timeout for all active member sockets in a group. +The actual timeout value is determined in runtime based on the RTT estimate of an individual member socket. +If there is no response from the peer for the calculated timeout, +the member is considered unstable, triggering activation of an idle backup member. + +The smaller the value is, the earlier a backup member might be activated to prepare transition to that path. +However, it may also lead to spurious activations of backup paths. +The higher the value is, the later the backup link would be activated. All unacknowledged payload packets +have to be retransmitted through the backup path. If they don't reach the receiver in time, they would be dropped. +Therefore, an appropriate adjustment of the SRT buffering delay +(`SRTO_PEERLATENCY` on sender, `SRTO_RCVLATENCY` on receiver) should also be considered. + +Normally the receiver should send an ACK back to the sender every 10 ms. In the case of congestion, +in the live streaming configuration of SRT a loss report is expected to be sent every RTT/2. +The network jitter and increase of RTT on the public internet causes +these intervals to be stretched. +The default minimum value of 60 ms is selected as a general fit for most of the use cases. + +Please refer to the [SRT Connection Bonding: Main/Backup](../features/bonding-main-backup.md) document for more details. + +Note that the value of this option is not allowed to exceed the value of +`SRTO_PEERIDLETIMEO`, which determines the timeout to actually break an idle (irresponsive) connection. + +[Return to list](#list-of-options) + +--- + +#### SRTO_GROUPTYPE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_GROUPTYPE` | 1.5.0 | | `int32_t` | enum | | | R | S | + +This option is read-only and it is intended to be called inside the listener +callback handler (see `srt_listen_callback`). Possible values are defined in +the `SRT_GROUP_TYPE` enumeration type. + +This option returns the group type that is declared in the incoming connection. +If the incoming connection is not going to make a group-member connection, then +the value returned is `SRT_GTYPE_UNDEFINED`. If this option is read in any other +context than inside the listener callback handler, the value is undefined. + +[Return to list](#list-of-options) + +--- + +#### SRTO_INPUTBW + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ---------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_INPUTBW` | 1.0.5 | post | `int64_t` | B/s | 0 | 0.. | RW | GSD | + +This option is effective only if [`SRTO_MAXBW`](#SRTO_MAXBW) is set to 0 (relative). It +controls the maximum bandwidth together with [`SRTO_OHEADBW`](#SRTO_OHEADBW) option according +to the formula: `MAXBW = INPUTBW * (100 + OHEADBW) / 100`. When this option +is set to 0 (automatic) then the real INPUTBW value will be estimated from +the rate of the input (cases when the application calls the `srt_send*` +function) during transmission. The minimum allowed estimate value is restricted +by [`SRTO_MININPUTBW`](#SRTO_MININPUTBW), meaning `INPUTBW = MAX(INPUTBW_ESTIMATE; MININPUTBW)`. + +*Recommended: set this option to the anticipated bitrate of your live stream +and keep the default 25% value for `SRTO_OHEADBW`*. + +[Return to list](#list-of-options) + +--- + +#### SRTO_MININPUTBW + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_MININPUTBW` | 1.4.3 | post | `int64_t` | B/s | 0 | 0.. | RW | GSD | + +This option is effective only if both `SRTO_MAXBW` and `SRTO_INPUTBW` are set to 0. +It controls the minimum allowed value of the input bitrate estimate. + +See [`SRTO_INPUTBW`](#SRTO_INPUTBW). + +[Return to list](#list-of-options) + +--- + +#### SRTO_IPTOS + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ---------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_IPTOS` | 1.0.5 | pre-bind | `int32_t` | | (system) | 0..255 | RW | GSD | + +IPv4 Type of Service (see `IP_TOS` option for IP) or IPv6 Traffic Class (see `IPV6_TCLASS` +of IPv6) depending on socket address family. Applies to sender only. + +When *getting*, the returned value is the user preset for non-connected sockets +and the actual value for connected sockets. + +*Sender*: user configurable, default: `0xB8`. + +[Return to list](#list-of-options) + +--- + +#### SRTO_IPTTL + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ---------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_IPTTL` | 1.0.5 | pre-bind | `int32_t` | hops | (system) | 1..255 | RW | GSD | + +IPv4 Time To Live (see `IP_TTL` option for IP) or IPv6 unicast hops (see +`IPV6_UNICAST_HOPS` for IPv6) depending on socket address family. Applies to sender only. + +When *getting*, the returned value is the user preset for non-connected sockets +and the actual value for connected sockets. + +*Sender*: user configurable, default: 64 + +[Return to list](#list-of-options) + +--- + +#### SRTO_IPV6ONLY + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ---------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_IPV6ONLY` | 1.4.0 | pre-bind | `int32_t` | | (system) | -1..1 | RW | GSD | + +Set system socket option level `IPPROTO_IPV6` named `IPV6_V6ONLY`. This is meaningful +only when the socket is going to be bound to the IPv6 wildcard address `in6addr_any` +(known also as `::`). If you bind to a wildcard address, you have the following +possibilities: + +* IPv4 only: bind to an IPv4 wildcard address +* IPv6 only: bind to an IPv6 wildcard address and set this option to 1 +* IPv4 and IPv6: bind to an IPv6 wildcard address and set this option to 0 + +This option's default value is -1 because it is not possible to determine the default +value on the current platform, and if you bind to an IPv6 wildcard address, this value +is required prior to binding. When you bind implicitly by calling `srt_connect` on the +socket, this isn't a problem -- binding will be done using the system-default value and then +extracted afterwards. But if you want to bind explicitly using `srt_bind`, this +option must be set explicitly to 0 or 1 because this information is vital for +determining any potential bind conflicts with other sockets. + +Possible values are: + +* -1: (default) use system-default value (can be used when not binding to IPv6 wildcard `::`) +* 0: The binding to `in6addr_any` will bind to both IPv6 and IPv4 wildcard address +* 1: The binding to `in6addr_any` will bind only to IPv6 and not IPv4 wildcard address + + +[Return to list](#list-of-options) + +--- + +#### SRTO_ISN + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ---------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_ISN` | 1.3.0 | | `int32_t` | | | | R | S | + +The value of the ISN (Initial Sequence Number), which is the first sequence +number put on the first UDP packets sent that are carrying an SRT data payload. + +*This value is useful for developers of some more complicated methods of flow +control, possibly with multiple SRT sockets at a time. It is not intended to be +used in any regular development.* + +[Return to list](#list-of-options) + +--- + +#### SRTO_KMPREANNOUNCE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| --------------------- | ----- | -------- | ---------- | ------ | ----------------- | ------ | --- | ------ | +| `SRTO_KMPREANNOUNCE` | 1.3.2 | pre | `int32_t` | pkts | 0: 212 | 0.. * | RW | GSD | + +The interval (defined in packets) between when a new Stream Encrypting Key +(SEK) is sent and when switchover occurs. This value also applies to the +subsequent interval between when switchover occurs and when the old SEK is +decommissioned. + +At `SRTO_KMPREANNOUNCE` packets before switchover the new key is sent +(repeatedly, if necessary, until it is confirmed by the receiver). + +At the switchover point (see `SRTO_KMREFRESHRATE`), the sender starts +encrypting and sending packets using the new key. The old key persists in case +it is needed to decrypt packets that were in the flight window, or +retransmitted packets. + +The old key is decommissioned at `SRTO_KMPREANNOUNCE` packets after switchover. + +**The allowed range** for this value is between 1 and half of the current value of +`SRTO_KMREFRESHRATE`. The minimum value should never be less than the flight +window [`SRTO_FC`](#SRTO_FC) (i.e. the number of packets that have already left the sender but have +not yet arrived at the receiver). + +The value of `SRTO_KMPREANNOUNCE must not exceed `(SRTO_KMREFRESHRATE - 1) / 2`. + +**Default value:** `0` - corresponds to 4096 packets (212 or 0x1000). + +[Return to list](#list-of-options) + +--- + +#### SRTO_KMREFRESHRATE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| --------------------- | ----- | -------- | ---------- | ------ | ---------------- | ------ | --- | ------ | +| `SRTO_KMREFRESHRATE` | 1.3.2 | pre | `int32_t` | pkts | 0: 224| 0.. | RW | GSD | + +The number of packets to be transmitted after which the Stream Encryption Key +(SEK), used to encrypt packets, will be switched to the new one. Note that +the old and new keys live in parallel for a certain period of time (see +`SRTO_KMPREANNOUNCE`) before and after the switchover. + +Having a preannounce period before switchover ensures the new SEK is installed +at the receiver before the first packet encrypted with the new SEK is received. +The old key remains active after switchover in order to decrypt packets that +might still be in flight, or packets that have to be retransmitted. + +**Default value:** `0` - corresponds to 16777216 packets (224 or 0x1000000). + +[Return to list](#list-of-options) + +--- + +#### SRTO_KMSTATE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| --------------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_KMSTATE` | 1.0.2 | | `int32_t` | enum | | | R | S | + +Keying Material state. This is a legacy option that is equivalent to +`SRTO_SNDKMSTATE`, if the socket has set `SRTO_SENDER` to true, and +`SRTO_RCVKMSTATE` otherwise. This option is then equal to `SRTO_RCVKMSTATE` +always if your application disregards possible cooperation with a peer older +than 1.3.0, but then with the default value of `SRTO_ENFORCEDENCRYPTION` the +value returned by both options is always the same. See [`SRT_KM_STATE`](#srt_km_state) +for more details. + +[Return to list](#list-of-options) + +--- + +#### SRTO_LATENCY + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| --------------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_LATENCY` | 1.0.2 | pre | `int32_t` | ms | 120 * | 0.. | RW | GSD | + +This option sets both [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY) and [`SRTO_PEERLATENCY`](#SRTO_PEERLATENCY) +to the same value specified. Note that the default value for `SRTO_RCVLATENCY` is modified by the +[`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) option. + +Prior to SRT version 1.3.0 `SRTO_LATENCY` was the only option to set the latency. +However it is effectively equivalent to setting `SRTO_PEERLATENCY` in the sending direction +(see [`SRTO_SENDER`](#SRTO_SENDER)), and `SRTO_RCVLATENCY` in the receiving direction. +SRT version 1.3.0 and higher support bidirectional transmission, so that each side can +be sender and receiver at the same time, and `SRTO_SENDER` became redundant. + +[Return to list](#list-of-options) + +--- + +#### SRTO_LINGER + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------ | -------- | ------ | --- | ------ | +| `SRTO_LINGER` | | pre | `linger` | s | off \* | 0.. | RW | GSD | + +SRT socket linger time on close (similar to [SO\_LINGER](http://man7.org/linux/man-pages/man7/socket.7.html)). +The defulat value in [the live streaming configuration](./API.md#transmission-types) is OFF. In this type of workflow there is no point for wait for all the data +to be delivered after a connection is closed. +The default value in [the file transfer configuration](./API.md#transmission-types) is 180 s. + + +*SRT recommended value*: off (0). + +[Return to list](#list-of-options) + +--- + +#### SRTO_LOSSMAXTTL + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_LOSSMAXTTL` | 1.2.0 | post | `int32_t` | packets | 0 | 0.. | RW | GSD+ | + +The value up to which the *Reorder Tolerance* may grow. The *Reorder Tolerance* +is the number of packets that must follow the experienced "gap" in sequence numbers +of incoming packets so that the loss report is sent (in the hope that the gap is due +to packet reordering rather than because of loss). The value of *Reorder Tolerance* +starts from 0 and is set to a greater value when packet reordering is detected +This happens when a "belated" packet, with sequence number older than the latest +received, has been received, but without retransmission flag. When this is detected +the *Reorder Tolerance* is set to the value of the interval between latest sequence +and this packet's sequence, but not more than the value set by `SRTO_LOSSMAXTTL`. +By default this value is set to 0, which means that this mechanism is off. + +[Return to list](#list-of-options) + +--- + +#### SRTO_MAXBW + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_MAXBW` | 1.0.5 | post | `int64_t` | B/s | -1 | -1.. | RW | GSD | + +Maximum send bandwidth: + +- `-1`: infinite (the limit in Live Mode is 1 Gbps); +- `0`: relative to input rate (see [`SRTO_INPUTBW`](#SRTO_INPUTBW)); +- `>0`: absolute limit in B/s. + +**NOTE**: This option has a default value of -1, regardless of the mode. +For live streams it is typically recommended to set the value 0 here and rely +on `SRTO_INPUTBW` and `SRTO_OHEADBW` options. However, if you want to do so, +you should make sure that your stream has a fairly constant bitrate, or that +changes are not abrupt, as high bitrate changes may work against the +measurement. SRT cannot ensure that this is always the case for a live stream, +therefore the default -1 remains even in live mode. + +[Return to list](#list-of-options) + +--- + +#### SRTO_MAXREXMITBW + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_MAXREXMITBW` | 1.5.3 | post | `int64_t` | B/s | -1 | -1.. | RW | GSD | + +Maximum BW limit for retransmissions: + +- `-1`: unlimited; +- `0`: do not allow retransmissions. +- `>0`: BW usage limit in Bytes/sec for packet retransmissions (including 16 bytes of SRT header). + +[Return to list](#list-of-options) + +--- + +#### SRTO_MESSAGEAPI + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_MESSAGEAPI` | 1.3.0 | pre | `bool` | | true | | W | GSD | + +When set, this socket uses the Message API[\*], otherwise it uses the +Stream API. Note that in live mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) option) only the +Message API is available. In File mode you can chose to use one of two modes +(note that the default for this option is changed with `SRTO_TRANSTYPE` +option): + +- **Stream API** (default for file mode): In this mode you may send +as many data as you wish with one sending instruction, or even use dedicated +functions that operate directly on a file. The internal facility will take care +of any speed and congestion control. When receiving, you can also receive as +many data as desired. The data not extracted will be waiting for the next call. +There is no boundary between data portions in Stream mode. + +- **Message API**: In this mode your single sending instruction passes exactly +one piece of data that has boundaries (a message). Contrary to Live mode, +this message may span multiple UDP packets, and the only size limitation +is that it shall fit as a whole in the sending buffer. The receiver shall use +as large a buffer as necessary to receive the message, otherwise reassembling +and delivering the message might not be possible. When the message is not +complete (not all packets received or there was a packet loss) it will not be +copied to the application's buffer. Messages that are sent later, but were +earlier reassembled by the receiver, will be delivered once ready, if the +`inorder` flag was set to false. +See [`srt_sendmsg`](API.md#sending-and-receiving). + +As a comparison to the standard system protocols, the Stream API does +transmission similar to TCP, whereas the Message API functions like the +SCTP protocol. + +[Return to list](#list-of-options) + +--- + +#### SRTO_MINVERSION + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_MINVERSION` | 1.3.0 | pre | `int32_t` | version | 0x010000 | * | RW | GSD | + +The minimum SRT version that is required from the peer. A connection to a +peer that does not satisfy the minimum version requirement will be rejected. +See [`SRTO_VERSION`](#SRTO_VERSION) for the version format. + +The default value is 0x010000 (SRT v1.0.0). + +[Return to list](#list-of-options) + +--- + +#### SRTO_MSS + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_MSS` | | pre-bind | `int32_t` | bytes | 1500 | 76.. | RW | GSD | + +Maximum Segment Size. Used for buffer allocation and rate calculation using +packet counter assuming fully filled packets. Each party can set its own MSS +value independently. During a handshake the parties exchange MSS values, and +the lowest is used. + +*Generally on the internet MSS is 1500 by default. This is the maximum +size of a UDP packet and can be only decreased, unless you have some unusual +dedicated network settings. MSS is not to be confused with the size of the UDP +payload or SRT payload - this size is the size of the IP packet, including the +UDP and SRT headers* + +THe value of `SRTO_MSS` must not exceed `SRTO_UDP_SNDBUF` or `SRTO_UDP_RCVBUF`. + +[Return to list](#list-of-options) + +--- + +#### SRTO_NAKREPORT + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_NAKREPORT` | 1.1.0 | pre | `bool` | | * | | RW | GSD+ | + +When set to true, every report for a detected loss will be repeated when the +timeout for the expected retransmission of this loss has expired and the +missing packet still wasn't recovered, or wasn't conditionally dropped (see +[`SRTO_TLPKTDROP`](#SRTO_TLPKTDROP)). + +The default is true for Live mode, and false for File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)). + +[Return to list](#list-of-options) + +--- + +#### SRTO_OHEADBW + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_OHEADBW` | 1.0.5 | post | `int32_t` | % | 25 | 5..100 | RW | GSD | + +Recovery bandwidth overhead above input rate (see [`SRTO_INPUTBW`](#SRTO_INPUTBW)), +in percentage of the input rate. It is effective only if `SRTO_MAXBW` is set to 0. + +*Sender*: user configurable, default: 25%. + +Recommendations: + +- Overhead is intended to give you extra bandwidth for the case when a packet +has taken part of the bandwidth, but then was lost and has to be retransmitted. +Therefore the effective maximum bandwidth should be appropriately higher than +your stream's bitrate so that there's some room for retransmission, but still +limited so that the retransmitted packets don't cause the bandwidth usage to +skyrocket when larger groups of packets are lost + +- Don't configure it too low and avoid 0 in the case when you have the +`SRTO_INPUTBW` option set to 0 (automatic). Otherwise your stream will choke +and break quickly at any rise in packet loss. + +- ***To do: set-only; get should be supported.*** + +[Return to list](#list-of-options) + +--- + +#### SRTO_PACKETFILTER + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PACKETFILTER` | 1.4.0 | pre | `string` | | "" | [512] | RW | GSD | + +Set up the packet filter. The string must match appropriate syntax for packet +filter setup. Note also that: + +* The configuration is case-sentitive (e.g. "FEC,Cols:20" is not valid). +* Setting this option will fail if you use an unknown filter type. + +An empty value for this option means that for this connection the filter isn't +required, but it will accept any filter settings if provided by the peer. If +this option is changed by both parties simultaneously, the result will be a +configuration integrating parameters from both parties, that is: + +* parameters provided by both parties are accepted, if they are identical +* parameters that are set only on one side will have the value defined by that side +* parameters not set in either side will be set as default + +The connection will be rejected with `SRT_REJ_FILTER` code in the following cases: + +* both sides define a different packet filter type +* for the same key two different values were provided by both sides +* mandatory parameters weren't provided by either side + +In case of the built-in `fec` filter, the mandatory parameter is `cols`, all +others have their default values. For example, the configuration specified +as `fec,cols:10` is `fec,cols:10,rows:1,arq:onreq,layout:even`. See how to +configure the FEC filter in [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md#configuring-the-fec-filter). + +Below in the table are examples for the built-in `fec` filter. Note that the +negotiated config need not have parameters in the given order. + +Cases when negotiation succeeds: + +| Peer A | Peer B | Negotiated Config +|----------------------|---------------------|------------------------------------------------------ +| (no filter) | (no filter) | +| fec,cols:10 | fec | fec,cols:10,rows:1,arq:onreq,layout:even +| fec,cols:10 | fec,cols:10,rows:20 | fec,cols:10,rows:20,arq:onreq,layout:even +| fec,layout:staircase | fec,cols:10 | fec,cols:10,rows:1,arq:onreq,layout:staircase + +In these cases the configuration is rejected with SRT_REJ_FILTER code: + +| Peer A | Peer B | Error reason +|-----------------------|---------------------|-------------------------- +| fec | (no filter) | missing `cols` parameter +| fec,rows:20,arq:never | fec,layout:even | missing `cols` parameter +| fec,cols:20 | fec,cols:10 | `cols` parameter value conflict +| fec,cols:20,rows:20 | fec,cols:20,rows:10 | `rows` parameter value conflict + +In general it is recommended that one party defines the full configuration, +while the other keeps this value empty. + +Reading this option after the connection is established will return the full +configuration that has been agreed upon by both parties (including default +values). + +For details, see [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md). + +[Return to list](#list-of-options) + +--- + +#### SRTO_PASSPHRASE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PASSPHRASE` | 0.0.0 | pre | `string` | | "" |[10..80]| W | GSD | + +Sets the passphrase for encryption. This enables encryption on this party (or +disables it, if an empty passphrase is passed). The password must be minimum +10 and maximum 79 characters long. + +The passphrase is the shared secret between the sender and the receiver. It is +used to generate the Key Encrypting Key using [PBKDF2](http://en.wikipedia.org/wiki/PBKDF2) +(Password-Based Key Derivation Function 2). + +When a socket with configured passphrase is being connected, the peer must +have the same password set, or the connection is rejected. This behavior can be +changed by [`SRTO_ENFORCEDENCRYPTION`](#SRTO_ENFORCEDENCRYPTION). + +Note that since the introduction of bidirectional support, there's only one +initial encryption key to encrypt the stream (new keys after refreshing will be +updated independently), and there's no distinction between "service party that +defines the password" and "client party that is required to set matching +password" - both parties are equivalent, and in order to have a working +encrypted connection, they have to simply set the same passphrase. + +[Return to list](#list-of-options) + +--- + +#### SRTO_PAYLOADSIZE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PAYLOADSIZE` | 1.3.0 | pre | `int32_t` | bytes | \* | 0.. \* | W | GSD | + +Sets the maximum declared size of a single call to sending function in Live +mode. When set to 0, there's no limit for a single sending call. + +For Live mode: Default value is 1316, but can be increased up to 1456. Note that +with the `SRTO_PACKETFILTER` option additional header space is usually required, +which decreases the maximum possible value for `SRTO_PAYLOADSIZE`. + +For File mode: Default value is 0 and it's recommended not to be changed. + +[Return to list](#list-of-options) + +--- + +#### SRTO_PBKEYLEN + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PBKEYLEN` | 0.0.0 | pre | `int32_t` | bytes | 0 | * | RW | GSD | + +Encryption key length. + +Possible values: + +- 0 =`PBKEYLEN` (default value) +- 16 = AES-128 (effective value) +- 24 = AES-192 +- 32 = AES-256 + +The use is slightly different in 1.2.0 (HSv4), and since 1.3.0 (HSv5): + +- **HSv4**: This is set on the sender and enables encryption, if not 0. The receiver +shall not set it and will agree on the length as defined by the sender. Being a +sender is defined by the `SRTO_SENDER` socket option set to true; otherwise the +party is a receiver. + +- **HSv5**: The "default value" for `PBKEYLEN` is 0, which means that the +`PBKEYLEN` won't be advertised. The "effective value" for `PBKEYLEN` is 16, but +this applies only when neither party has set the value explicitly (i.e. when +both are initially at the default value of 0). If any party *has* set an +explicit value (16, 24, 32) it will be advertised in the handshake. If the other +party remains at the default 0, it will accept the peer's value. The situation +where both parties set a value should be treated carefully. Actually there are +three intended methods of defining it, and all other uses are considered +undefined behavior: + + - **Unidirectional**: the sender shall set `PBKEYLEN` and the receiver shall + not alter the default value 0. The effective `PBKEYLEN` will be the one set + on the sender. The receiver need not know the sender's `PBKEYLEN`, just the + passphrase, `PBKEYLEN` will be correctly passed. + + - **Bidirectional in Caller-Listener arrangement**: it is recommended to use + a rule whereby you will be setting the `PBKEYLEN` exclusively either on the + Listener (the service defines the encryption rules strictly) or on the Caller + (the service allows all clients to freely decide about encryption, or the + server uses more elaborate rules for encryption). + + - **Bidirectional in Rendezvous mode**: In Rendezvous mode it is assumed that the settings (including `PBKEYLEN`) are known at both ends. + as it is with Listener mode, so both parties should set the same passphrase and the same key length, + or both should leave the `SRTO_PBKEYLEN` option unchanged (which results in default 16). + + - **Unwanted behavior cases**: if both parties set `PBKEYLEN` and the value + on both sides is different, this is considered a conflict. It is resolved by + the Initiator party, which takes its own value, if the `SRTO_SENDER` + option is set to true. Otherwise, it takes the value from the Responder party. The + assignment of Initiator-Responder roles matches the Caller-Listener layout. + In the case of Rendezvous this assignment depends on the result of + the cookie comparison. **It is highly recommended to never allow this to + happen**, as this may result in having one party's setting of length = 32 be + overridden by the other party's setting of length = 16. + +| Initiator | | Responder | | Result | +|---------------|-------------|---------------|-------------|---------| +| SRTO_PBKEYLEN | SRTO_SENDER | SRTO_PBKEYLEN | SRTO_SENDER | | +| 0 | any | 0 | any | AES-128 | +| 0 | any | AES-128 | any | AES-128 | +| 0 | any | AES-192 | any | AES-192 | +| 0 | any | AES-256 | any | AES-256 | +| AES-128 | any | 0 | any | AES-128 | +| AES-128 | any | AES-128 | any | AES-128 | +| AES-128 | 0 | AES-192 | any | AES-192 | +| AES-128 | 0 | AES-256 | any | AES-256 | +| AES-128 | 1 | AES-192 | any | AES-128 | +| AES-128 | 1 | AES-256 | any | AES-128 | +| AES-192 | any | 0 | any | AES-192 | +| AES-192 | 0 | AES-128 | any | AES-128 | +| AES-192 | any | AES-192 | any | AES-192 | +| AES-192 | 0 | AES-256 | any | AES-256 | +| AES-192 | 1 | AES-128 | any | AES-192 | +| AES-192 | 1 | AES-256 | any | AES-192 | +| AES-256 | any | 0 | any | AES-256 | +| AES-256 | 0 | AES-128 | any | AES-128 | +| AES-256 | 0 | AES-192 | any | AES-192 | +| AES-256 | any | AES-256 | any | AES-256 | +| AES-256 | 1 | AES-128 | any | AES-256 | +| AES-256 | 1 | AES-192 | any | AES-256 | + +[Return to list](#list-of-options) + +--- + +#### SRTO_PEERIDLETIMEO + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PEERIDLETIMEO` | 1.3.3 | pre | `int32_t` | ms | 5000 | 0.. | RW | GSD+ | + +The maximum time in `[ms]` to wait until another packet is received from a peer +since the last such packet reception. If this time is passed, the connection is +considered broken on timeout. + +[Return to list](#list-of-options) + +--- + +#### SRTO_PEERLATENCY + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PEERLATENCY` | 1.3.0 | pre | `int32_t` | ms | 0 | 0.. | RW | GSD | + +The latency value (as described in [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY)) provided by the sender +side as a minimum value for the receiver. + +This value is only significant when [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE) is enabled. + +Reading the value of the option on an unconnected socket reports the configured value. +Reading the value on a connected socket reports the effective receiver buffering latency of the peer. + +**The `SRTO_PEERLATENCY` option in versions prior to 1.3.0 is only available as** +[`SRTO_LATENCY`](#SRTO_LATENCY). + +See also [`SRTO_LATENCY`](#SRTO_LATENCY). + +[Return to list](#list-of-options) + +--- + +#### SRTO_PEERVERSION + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | -------- | ------ | --- | ------ | +| `SRTO_PEERVERSION` | 1.1.0 | | `int32_t` | * | | | R | GS | + +SRT version used by the peer. The value 0 is returned if not connected, SRT +handshake not yet performed (HSv4 only), or if peer is not SRT. +See [`SRTO_VERSION`](#SRTO_VERSION) for the version format. + +[Return to list](#list-of-options) + +--- + +#### SRTO_RCVBUF + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RCVBUF` | | pre-bind | `int32_t` | bytes | 8192 bufs | * | RW | GSD+ | + +Receive Buffer Size, in bytes. Note, however, that the internal setting of this +value is in the number of buffers, each one of size equal to SRT payload size, +which is the value of `SRTO_MSS` decreased by UDP and SRT header sizes (28 and 16). +The value set here will be effectively aligned to the multiple of payload size. + +- **Minimum value**: 32 buffers (46592 with default value of `SRTO_MSS`). + +- **Maximum value**: [`SRTO_FC`](#SRTO_FC) number of buffers (receiver buffer must not be greater +than the Flight Flag size). + +[Return to list](#list-of-options) + +--- + +#### SRTO_RCVDATA + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RCVDATA` | | | `int32_t` | pkts | | | R | S | + +Size of the available data in the receive buffer. + +[Return to list](#list-of-options) + +--- + +#### SRTO_RCVKMSTATE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RCVKMSTATE` | 1.2.0 | | `int32_t` | enum | | | R | S | + +KM state on the agent side when it's a receiver. + +Values defined in enum [`SRT_KM_STATE`](#srt_km_state). + +[Return to list](#list-of-options) + +--- + +#### SRTO_RCVLATENCY + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RCVLATENCY` | 1.3.0 | pre | `int32_t` | ms | * | 0.. | RW | GSD | + +The latency value in the receiving direction of the socket. +This value is only significant when [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE) is enabled. + +**Default value**: 120 ms in Live mode, 0 in File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)). + +The latency value defines the **minimum** receiver buffering delay before delivering an SRT data packet +from a receiving SRT socket to a receiving application. + +The actual value of the receiver buffering delay `Ln` (the negotiated latency) used on a connection +is determined by the negotiation in the connection establishment (handshake exchange) phase as the maximum of the +`SRTO_RCVLATENCY` value and the value of [`SRTO_PEERLATENCY`](#SRTO_PEERLATENCY) set by the peer. + +The general idea for the latency mechanism is to keep the time distance between two consecutive +received packets the same as the time when these same packets were scheduled for sending by the +sender application (or per the time explicitly declared when sending - see +[`srt_sendmsg2`](API-functions.md#srt_sendmsg2) for details). This keeps any packets that have arrived +earlier than their delivery time in the receiver buffer until their delivery time comes. This should +compensate for any jitter in the network and provides an extra delay needed for a packet retransmission. + +For detailed information on how the latency setting influences the actual packet delivery time and +how this time is defined, refer to the [latency documentation](../features/latency.md). + +Reading the `SRTO_RCVLATENCY` value on a socket after the connection is established provides the actual (negotiated) +latency value `Ln`. + +The receiver's buffer must be large enough to store the `L` segment of the stream, +i.e. `L × Bitrate` bytes. Refer to [`SRTO_RCVBUF`](#SRTO_RCVBUF). + +The sender's buffer must be large enough to store a packet up until it is either delivered (and acknowledged) +or dropped by the sender due to it becoming too late to be delivered. +In other words, `D × Bitrate` bytes, where `D` is the sender's drop delay value configured with [`SRTO_SNDDROPDELAY`](#SRTO_SNDDROPDELAY). + +Buffering of data packets on the receiving side makes it possible to recover from packet losses using the ARQ +(Automatic Repeat Request) technique, and to deal with varying RTT times (network jitter) in the network, providing +a (close to) **constant end-to-end latency of the transmission**. + +See also [`SRTO_LATENCY`](#SRTO_LATENCY). + +[Return to list](#list-of-options) + +--- + +#### SRTO_RCVSYN + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RCVSYN` | | post | `bool` | | true | | RW | GSI | + +When true, sets blocking mode on reading function when it's not ready to +perform the operation. When false ("non-blocking mode"), the reading function +will in this case report error `SRT_EASYNCRCV` and return immediately. Details +depend on the tested entity: + +On a connected socket or group this applies to a receiving function +(`srt_recv` and others) and a situation when there are no data available for +reading. The readiness state for this operation can be tested by checking the +`SRT_EPOLL_IN` flag on the aforementioned socket or group. + +On a freshly created socket or group that is about to be connected to a peer +listener this applies to any `srt_connect` call (and derived), which in +"non-blocking mode" always returns immediately. The connected state for that +socket or group can be tested by checking the `SRT_EPOLL_OUT` flag. Note +that a socket that failed to connect doesn't change the `SRTS_CONNECTING` +state and can be found out only by testing the `SRT_EPOLL_ERR` flag. + +On a listener socket this applies to `srt_accept` call. The readiness state +for this operation can be tested by checking the `SRT_EPOLL_IN` flag on +this listener socket. This flag is also derived from the listener socket +by the accepted socket or group, although the meaning of this flag is +effectively different. + +Note that when this flag is set only on a group, it applies to a +specific receiving operation being done on that group (i.e. it is not +derived from the socket of which the group is a member). + +[Return to list](#list-of-options) + +--- + +#### SRTO_RCVTIMEO + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RCVTIMEO` | | post | `int32_t` | ms | -1 | -1, 0..| RW | GSI | + +Limits the time up to which the receiving operation will block (see +[`SRTO_RCVSYN`](#SRTO_RCVSYN) for details), such that when this time is exceeded, +it will behave as if in "non-blocking mode". The -1 value means no time limit. + +[Return to list](#list-of-options) + +--- + +#### SRTO_RENDEZVOUS + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_RENDEZVOUS` | | pre | `bool` | | false | | RW | S | + +Use Rendezvous connection mode (both sides must set this and both must use the +procedure of `srt_bind` and then `srt_connect` (or `srt_rendezvous`) to one another. + +[Return to list](#list-of-options) + +--- + +#### SRTO_RETRANSMITALGO + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| --------------------- | ----- | -------- | --------- | ------ | ------- | ------ | --- | ------ | +| `SRTO_RETRANSMITALGO` | 1.4.2 | pre | `int32_t` | | 1 | [0, 1] | RW | GSD | + +An SRT sender option to choose between two retransmission algorithms: + +- 0 - aggressive retransmission algorithm (default until SRT v1.4.4), and +- 1 - efficient retransmission algorithm (introduced in SRT v1.4.2; default since SRT v1.4.4). + +The aggressive retransmission algorithm causes the SRT sender to schedule a packet for retransmission each time it receives a negative acknowledgement (NAK). On a network characterized by low packet loss levels and link capacity high enough to accommodate extra retransmission overhead, this algorithm increases the chances of recovering from packet loss with a minimum delay, and may better suit end-to-end latency constraints. + +The new efficient algorithm optimizes the bandwidth usage by producing fewer retransmissions per lost packet. It takes SRT statistics into account to determine if a retransmitted packet is still in flight and could reach the receiver in time, so that some of the NAK reports are ignored by the sender. This algorithm better fits general use cases, as well as cases where channel bandwidth is limited. + +To learn more about the algorithms, read ["Improving SRT Retransmissions — Experiments with Simulated Live Streaming (Part 1)"](https://medium.com/innovation-labs-blog/improving-srt-retransmissions-experiments-with-simulated-live-streaming-part-1-7d192483bba4) article. + +NOTE: This option is effective only on the sending side. It influences the decision +as to whether a particular reported lost packet should be retransmitted at a +certain time or not. + +NOTE: The efficient retransmission algorithm can only be used when a receiver sends +Periodic NAK reports. See [SRTO_NAKREPORT](#SRTO_NAKREPORT). + +[Return to list](#list-of-options) + +--- + +#### SRTO_REUSEADDR + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_REUSEADDR` | | pre-bind | `bool` | | true | | RW | GSD | + +When true, allows the SRT socket to use the binding address used already by +another SRT socket in the same application. Note that SRT socket uses an +intermediate object called Multiplexer to access the underlying UDP sockets, +so multiple SRT sockets may share one UDP socket, and the packets received by this +UDP socket will be correctly dispatched to the SRT socket to which they are +currently destined. This has some similarities to the `SO_REUSEADDR` system socket +option, although it's only used inside SRT. + +*TODO: This option weirdly only allows the socket used in **bind()** to use the +local address that another socket is already using, but not to disallow another +socket in the same application to use the binding address that the current +socket is already using. What it actually changes is that when given an address in +**bind()** is already used by another socket, this option will make the binding +fail instead of adding the socket to the shared group of that socket that +already has bound this address - but it will not disallow another socket to reuse +its address.* + +[Return to list](#list-of-options) + +--- + +#### SRTO_SENDER + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | ---------- | ------ | --- | ------ | +| `SRTO_SENDER` | 1.0.4 | pre | `bool` | | false | | W | S | + +Set sender side. The side that sets this flag is expected to be a sender. This +flag is only required when communicating with a receiver that uses SRT version +less than 1.3.0 (and hence *HSv4* handshake), in which case if not set properly, +the TSBPD mode (see [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE)) or encryption will not +work. Setting `SRTO_MINVERSION` to 1.3.0 is therefore recommended. + +This flag in versions above 1.3.0 also influences the conflict resolution for +`SRTO_PBKEYLEN` in the case where this flag is forcefully set on both connection +parties simultaneously. + +[Return to list](#list-of-options) + +--- + +#### SRTO_SNDBUF + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_SNDBUF` | | pre-bind | `int32_t` | bytes |8192 bufs | * | RW | GSD+ | + +Sender Buffer Size. See [`SRTO_RCVBUF`](#SRTO_RCVBUF) for more information. + +[Return to list](#list-of-options) + +--- + +#### SRTO_SNDDATA + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_SNDDATA` | | | `int32_t` | pkts | | | R | S | + +Size of the unacknowledged data in send buffer. + +[Return to list](#list-of-options) + +--- + +#### SRTO_SNDDROPDELAY + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_SNDDROPDELAY` | 1.3.2 | post | `int32_t` | ms | * | -1.. | W | GSD+ | + +Sets an extra delay before `TLPKTDROP` is triggered on the data sender. +This delay is added to the default drop delay time interval value. Keep in mind +that the longer the delay, the more probable it becomes that packets would be +retransmitted uselessly because they will be dropped by the receiver anyway. + +`TLPKTDROP` discards packets reported as lost if it is already too late to send +them (the receiver would discard them even if received). The delay before the +`TLPKTDROP` mechanism is triggered consists of the SRT latency (`SRTO_PEERLATENCY`), +plus `SRTO_SNDDROPDELAY`, plus `2 * interval between sending ACKs` (where the +default `interval between sending ACKs` is 10 milliseconds). +The minimum delay is `1000 + 2 * interval between sending ACKs` milliseconds. + +**Special value -1**: Do not drop packets on the sender at all (retransmit them +always when requested). + +**Default:** 0 in Live mode, -1 in File mode. + +[Return to list](#list-of-options) + +--- + +#### SRTO_SNDKMSTATE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_SNDKMSTATE` | 1.2.0 | | `int32_t` | enum | | | R | S | + +Peer KM state on receiver side for `SRTO_KMSTATE` + +Values defined in enum [`SRT_KM_STATE`](#srt_km_state). + +[Return to list](#list-of-options) + +--- + +#### SRTO_SNDSYN + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_SNDSYN` | | post | `bool` | | true | | RW | GSI | + +When true, sets blocking mode on writing function when it's not ready to +perform the operation. When false ("non-blocking mode"), the writing function +will in this case report error `SRT_EASYNCSND` and return immediately. + +On a connected socket or group this applies to a sending function +(`srt_send` and others) and a situation when there's no free space in +the sender buffer, caused by inability to send all the scheduled data over +the network. Readiness for this operation can be tested by checking the +`SRT_EPOLL_OUT` flag. + +On a freshly created socket or group it will have no effect until the socket +enters a connected state. + +On a listener socket it will be derived by the accepted socket or group, +but will have no effect on the listener socket itself. + +[Return to list](#list-of-options) + +--- + +#### SRTO_SNDTIMEO + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_SNDTIMEO` | | post | `int32_t` | ms | -1 | -1.. | RW | GSI | + +limit the time up to which the sending operation will block (see +`SRTO_SNDSYN` for details), so when this time is exceeded, it will behave as +if in "non-blocking mode". The -1 value means no time limit. + +[Return to list](#list-of-options) + +--- + +#### SRTO_STATE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_STATE` | | | `int32_t` | enum | | | R | S | + +Returns the current socket state, same as `srt_getsockstate`. + +[Return to list](#list-of-options) + +--- + +#### SRTO_STREAMID + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| -------------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_STREAMID` | 1.3.0 | pre | `string` | | "" | [512] | RW | GSD | + +- A string that can be set on the socket prior to connecting. The listener side +will be able to retrieve this stream ID from the socket that is returned from +`srt_accept` (for a connected socket with that stream ID). You usually use SET +on the socket used for `srt_connect`, and GET on the socket retrieved from +`srt_accept`. This string can be used completely free-form. However, it's highly +recommended to follow the [SRT Access Control (Stream ID) Guidlines](../features/access-control.md). + +- As this uses internally the `std::string` type, there are additional functions +for it in the legacy/C++ API (udt.h): `srt::setstreamid` and `srt::getstreamid`. + +- This option is not useful for a Rendezvous connection, since one side would +override the value from the other side resulting in an arbitrary winner. Also +in this connection both peers are known to one another and both have equivalent +roles in the connection. + +- **IMPORTANT**: This option is not derived by the accepted socket from the listener +socket, and setting it on a listener socket (see `srt_listen` function) doesn't +influence anything. + +[Return to list](#list-of-options) + +--- + +#### SRTO_TLPKTDROP + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_TLPKTDROP` | 1.0.6 | pre | `bool` | | * | | RW | GSD | + +Too-late Packet Drop. When enabled on receiver, it skips missing packets that +have not been delivered in time and delivers the subsequent packets to the +application when their time-to-play has come. It also sends a fake ACK to the +sender. When enabled on sender and enabled on the receiving peer, sender drops +the older packets that have no chance to be delivered in time. It is automatically +enabled in sender if receiver supports it. + +**Default:** true in Live mode, false in File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)) + +[Return to list](#list-of-options) + +--- + +#### SRTO_TRANSTYPE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_TRANSTYPE` | 1.3.0 | pre | `int32_t` | enum |`SRTT_LIVE`| \* | W | S | + +Sets the transmission type for the socket, in particular, setting this option +sets multiple other parameters to their default values as required for a +particular transmission type. This sets the following options to their defaults +in particular mode: + +* [`SRTO_CONGESTION`](#SRTO_CONGESTION) +* [`SRTO_MESSAGEAPI`](#SRTO_MESSAGEAPI) +* [`SRTO_NAKREPORT`](#SRTO_NAKREPORT) +* [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY), also set as [`SRTO_LATENCY`](#SRTO_LATENCY) +* [`SRTO_TLPKTDROP`](#SRTO_TLPKTDROP) +* [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE) + + + +Values defined by enum [`SRT_TRANSTYPE`](#SRT_TRANSTYPE). + +[Return to list](#list-of-options) + +--- + +#### SRTO_TSBPDMODE + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_TSBPDMODE` | 0.0.0 | pre | `bool` | | \* | | W | S | + +When true, use Timestamp-based Packet Delivery mode. In this mode the +packet's time is assigned at the sending time (or allowed to be predefined), +transmitted in the packet's header, and then restored on the receiver side so that +the time intervals between consecutive packets are preserved when delivering to +the application. + +**Default:** true in Live mode, false in File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)). + +[Return to list](#list-of-options) + +--- + +#### SRTO_UDP_RCVBUF + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_UDP_RCVBUF` | | pre-bind | `int32_t` | bytes | 8192 bufs | * | RW | GSD+ | + +UDP Socket Receive Buffer Size. Configured in bytes, maintained in packets +based on MSS value. Receive buffer must not be greater than FC size. + +[Return to list](#list-of-options) + +--- + +#### SRTO_UDP_SNDBUF + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_UDP_SNDBUF` | | pre-bind | `int32_t` | bytes | 65536 | * | RW | GSD+ | + +UDP Socket Send Buffer Size. Configured in bytes, maintained in packets based +on `SRTO_MSS` value. + +[Return to list](#list-of-options) + +--- + +#### SRTO_VERSION + +| OptName | Since | Restrict | Type | Units | Default | Range | Dir | Entity | +| ----------------- | ----- | -------- | ---------- | ------- | --------- | ------ | --- | ------ | +| `SRTO_VERSION` | 1.1.0 | | `int32_t` | | | | R | S | + +Local SRT version. This is the highest local version supported if not +connected, or the highest version supported by the peer if connected. + +The version format in hex is `0x00XXYYZZ` for x.y.z in human readable form. +For example, version 1.4.2 is encoded as `0x010402`. + +[Return to list](#list-of-options) + +--- diff --git a/docs/API.md b/docs/API/API.md similarity index 59% rename from docs/API.md rename to docs/API/API.md index 182ecc41a..3bd303830 100644 --- a/docs/API.md +++ b/docs/API/API.md @@ -1,116 +1,94 @@ # SRT API -The SRT C API (defined in `srt.h` file) is largely based in design on the legacy -UDT API, with some important changes. The `udt.h` file contains the legacy UDT API -plus some minor optional functions that require the C++ standard library to be used. -There are a few optional C++ API functions stored there, as there is no real C++ API +The SRT C API (defined in `srt.h` file) is largely based in design on the legacy +UDT API, with some important changes. The `udt.h` file contains the legacy UDT API +plus some minor optional functions that require the C++ standard library to be used. +There are a few optional C++ API functions stored there, as there is no real C++ API for SRT. These functions may be useful in certain situations. -There are some example applications so that you can see how the API is being used, -including `srt-live-transmit` and `srt-file-transmit`. All SRT related material is contained -in `transmitmedia.*` files in the `apps` directory -which is used by all applications. See `SrtSource::Read` and `SrtTarget::Write` +There are some example applications so that you can see how the API is being used, +including `srt-live-transmit` and `srt-file-transmit`. All SRT related material is contained +in `transmitmedia.*` files in the `apps` directory +which is used by all applications. See `SrtSource::Read` and `SrtTarget::Write` as examples of how data are read and written in SRT. - - [Setup and teardown](#setup-and-teardown) - - [Creating and destroying a socket](#creating-and-destroying-a-socket) - - [Synopsis](#synopsis) - - [Usage](#usage) - - [Important Remarks](#important-remarks) - - [Binding and connecting](#binding-and-connecting) - - [Synopsis](#synopsis) - - [SRT Usage - listener (server)](#srt-usage---listener-server) - - [SRT Usage - rendezvous](#srt-usage---rendezvous) - - [Sending and Receiving](#sending-and-receiving) - - [Synopsis](#synopsis) - - [Usage](#usage) - - [Transmission types available in SRT](#transmission-types-available-in-srt) - - [Blocking and Non-blocking Mode](#blocking-and-non-blocking-mode) - - [EPoll (Non-blocking Mode Events)](#epoll-non-blocking-mode-events)) - - [Synopsis](#synopsis) - - [SRT Usage](#srt-usage) - - [Transmission types](#transmission-types) - - [Terminology](#terminology) - - [Transmission method: Live](#transmission-method-live) - - [Transmission method: Buffer](#transmission-method-buffer) - - [Transmission method: Message](#transmission-method-message) - - -**NOTE**: The socket option descriptions originally contained in this document -have been moved to [APISocketOptions.md](https://github.com/Haivision/srt/blob/master/docs/APISocketOptions.md) - - -Setup and teardown -================== +- [Setup and Teardown](#setup-and-teardown) +- [Creating and Destroying a Socket](#creating-and-destroying-a-socket) +- [Binding and Connecting](#binding-and-connecting) +- [Sending and Receiving](#sending-and-receiving) +- [Blocking and Non-blocking Modes](#blocking-and-non-blocking-modes) + - [EPoll (Non-blocking Mode Events)](#epoll-non-blocking-mode-events) +- [Transmission Types](#transmission-types) + - [Transmission Method: Live](#transmission-method-live) + - [Transmission Method: Buffer](#transmission-method-buffer) + - [Transmission Method: Message](#transmission-method-message) + +## Setup and Teardown Before any part of the SRT C API can be used, the user should call the `srt_startup()` function. Likewise, before the application exits, the `srt_cleanup()` function -should be called. Note that one of the things the startup function does is to create +should be called. Note that one of the things the startup function does is to create a new thread, so choose the point of execution for these functions carefully. -Creating and destroying a socket -================================ +## Creating and Destroying a Socket -To do anything with SRT, you first have to create an SRT socket. The term "socket" -in this case is used because of its logical similarity to system-wide sockets. -An SRT socket is not directly related to system sockets, but like a system socket +To do anything with SRT, you first have to create an SRT socket. The term "socket" +in this case is used because of its logical similarity to system-wide sockets. +An SRT socket is not directly related to system sockets, but like a system socket it is used to define a point of communication. -Synopsis --------- - - SRTSOCKET srt_socket(int af, int, int); - int srt_close(SRTSOCKET s); +### Synopsis -The `srt_socket` function is based on the legacy UDT API except -the first parameter. The other two are ignored. +```c++ +SRTSOCKET srt_create_socket(); +int srt_close(SRTSOCKET s); +``` Note that `SRTSOCKET` is just an alias for `int`; this is a legacy naming convention from UDT, which is here only for clarity. -Usage ------ +### Usage - sock = srt_socket(AF_INET, SOCK_DGRAM, 0); +```c++ +sock = srt_create_socket(); +``` This creates a socket, which can next be configured and then used for communication. - srt_close(sock); +```c++ +srt_close(sock); +``` This closes the socket and frees all its resources. Note that the true life of the socket does not end exactly after this function exits - some details are being -finished in a separate "SRT GC" thread. Still, at least all shared system resources +finished in a separate "SRT GC" thread. Still, at least all shared system resources (such as listener port) should be released after this function exits. +### Important Remarks -Important Remarks ------------------ - -1. Please note that the use of SRT with `AF_INET6` has not been fully tested; -use at your own risk. -2. SRT uses the system UDP protocol as an underlying communication layer, and so -it uses also UDP sockets. The underlying communication layer is used only -instrumentally, and SRT manages UDP sockets as its own system resource as it -pleases - so in some cases it may be reasonable for multiple SRT sockets to share +1. SRT uses the system UDP protocol as an underlying communication layer, and so +it uses also UDP sockets. The underlying communication layer is used only +instrumentally, and SRT manages UDP sockets as its own system resource as it +pleases - so in some cases it may be reasonable for multiple SRT sockets to share one UDP socket, or for one SRT socket to use multiple UDP sockets. -3. The term "port" used in SRT is occasionally identical to the term "UDP -port". However SRT offers more flexibility than UDP (or TCP, the more logical -similarity) because it manages ports as its own resources. For example, one port -may be shared between various services. +2. The term "port" used in SRT is occasionally identical to the term "UDP +port". However SRT offers more flexibility than UDP (or TCP, the more logical +similarity) because it manages ports as its own resources. For example, one port +may be shared between various services. -Binding and connecting -====================== +## Binding and Connecting -Connections are established using the same philosophy as TCP, using functions -with names and signatures similar to the BSD Socket API. What is new here is +Connections are established using the same philosophy as TCP, using functions +with names and signatures similar to the BSD Socket API. What is new here is the _rendezvous_ mode. -Synopsis --------- +### Synopsis - int srt_bind(SRTSOCKET u, const struct sockaddr* name, int namelen); - int srt_bind_peerof(SRTSOCKET u, UDPSOCKET udpsock); +```c++ +int srt_bind(SRTSOCKET u, const struct sockaddr* name, int namelen); +int srt_bind_acquire(SRTSOCKET u, UDPSOCKET udpsock); +``` This function sets up the "sockname" for the socket, that is, the local IP address of the network device (use `INADDR_ANY` for using any device) and port. Note that @@ -118,24 +96,30 @@ this can be done on both listening and connecting sockets; for the latter it wil define the outgoing port. If you don't set up the outgoing port by calling this function (or use port number 0), a unique port number will be selected automatically. -The `*_peerof` version simply copies the bound address setting from an existing -UDP socket. +The `*_acquire` version simply takes over the given UDP socket and copies the +bound address setting from it. - int srt_listen(SRTSOCKET u, int backlog); +```c++ +int srt_listen(SRTSOCKET u, int backlog); +``` This sets the backlog (maximum allowed simultaneously pending connections) and puts the socket into a listening state -- that is, incoming connections will be accepted in the call `srt_accept`. - SRTSOCKET srt_accept(SRTSOCKET u, struct sockaddr* addr, int* addrlen); +```c++ +SRTSOCKET srt_accept(SRTSOCKET u, struct sockaddr* addr, int* addrlen); +``` This function accepts the incoming connection (the peer should do `srt_connect`) and returns a socket that is exclusively bound to an opposite socket at the peer. The peer's address is returned in the `addr` argument. - int srt_connect(SRTSOCKET u, const struct sockaddr* name, int namelen); - int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +```c++ +int srt_connect(SRTSOCKET u, const struct sockaddr* name, int namelen); +int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +``` This function initiates the connection of a given socket with its peer's counterpart (the peer gets the new socket for this connection from `srt_accept`). The @@ -143,8 +127,10 @@ address for connection is passed in 'name'. The `connect_debug` version allows for enforcing the ISN (initial sequence number); this is used only for debugging or unusual experiments. - int srt_rendezvous(SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, - const struct sockaddr* remote_name, int remote_namelen); +```c++ +int srt_rendezvous(SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, + const struct sockaddr* remote_name, int remote_namelen); +``` A convenience function that combines the calls to bind, setting the `SRTO_RENDEZVOUS` flag, and connecting to the rendezvous counterpart. For simplest usage, the `local_name` should @@ -153,52 +139,61 @@ and `remote_name` must use the same port. The peer to which this is going to con should call the same function, with appropriate local and remote addresses. A rendezvous connection means that both parties connect to one another simultaneously. +**IMPORTANT**: The connection may fail, but the socket that was used for connecting +is not automatically closed and it's also not in broken state (broken state can be +only if a socket was first successfully connected and then broken). When using blocking +mode, the connection failure will result in reporting an error from this function call. +In non-blocking mode the connection failure is designated by the `SRT_EPOLL_ERR` flag +set for this socket in the epoll container. After that failure you can read an extra +information from the socket using `srt_getrejectreason` function, and then you should +close the socket. + +### Listener (Server) Example + +```c++ +sockaddr_in sa = { ... }; // set local listening port and possibly interface's IP +int st = srt_bind(sock, (sockaddr*)&sa, sizeof sa); +srt_listen(sock, 5); +while ( !finish ) { + int sa_len = sizeof sa; + newsocket = srt_accept(sock, (sockaddr*)&sa, &sa_len); + HandleNewClient(newsocket, sa); +} +``` +### Caller (Client) Example -SRT Usage - listener (server) ------------------------------ - - sockaddr_in sa = { ... }; // set local listening port and possibly interface's IP - int st = srt_bind(sock, (sockaddr*)&sa, sizeof sa); - srt_listen(sock, 5); - while ( !finish ) { - int sa_len = sizeof sa; - newsocket = srt_accept(sock, (sockaddr*)&sa, &sa_len); - HandleNewClient(newsocket, sa); - } - -SRT Usage - caller (client) ---------------------------- - - sockaddr_in sa = { ... }; // set target IP and port - - int st = srt_connect(sock, (sockaddr*)&sa, sizeof sa); - HandleConnection(sock); +```c++ +sockaddr_in sa = { ... }; // set target IP and port +int st = srt_connect(sock, (sockaddr*)&sa, sizeof sa); +HandleConnection(sock); +``` -SRT Usage - rendezvous ----------------------- +### Rendezvous Example - sockaddr_in lsa = { ... }; // set local listening IP/port - sockaddr_in rsa = { ... }; // set remote IP/port +```c++ +sockaddr_in lsa = { ... }; // set local listening IP/port +sockaddr_in rsa = { ... }; // set remote IP/port - srt_setsockopt(m_sock, 0, SRTO_RENDEZVOUS, &yes, sizeof yes); - int stb = srt_bind(sock, (sockaddr*)&lsa, sizeof lsa); - int stc = srt_connect(sock, (sockaddr*)&rsa, sizeof rsa); - HandleConnection(sock); +srt_setsockopt(m_sock, 0, SRTO_RENDEZVOUS, &yes, sizeof yes); +int stb = srt_bind(sock, (sockaddr*)&lsa, sizeof lsa); +int stc = srt_connect(sock, (sockaddr*)&rsa, sizeof rsa); +HandleConnection(sock); +``` or simpler - sockaddr_in lsa = { ... }; // set local listening IP/port - sockaddr_in rsa = { ... }; // set remote IP/port - - int stc = srt_rendezvous(sock, (sockaddr*)&lsa, sizeof lsa, - (sockaddr*)&rsa, sizeof rsa); - HandleConnection(sock); +```c++ +sockaddr_in lsa = { ... }; // set local listening IP/port +sockaddr_in rsa = { ... }; // set remote IP/port +int stc = srt_rendezvous(sock, (sockaddr*)&lsa, sizeof lsa, + (sockaddr*)&rsa, sizeof rsa); +HandleConnection(sock); +``` -Sending and Receiving -===================== +## Sending and Receiving The SRT API for sending and receiving is split into three categories: *simple*, *rich*, and *for files only*. @@ -210,103 +205,100 @@ and `write` functions. The **rich API** includes the `srt_sendmsg` and `srt_recvmsg` functions. Actually `srt_recvmsg` is provided for convenience and backward compatibility, as it is identical to `srt_recv`. The `srt_sendmsg` receives more parameters, specifically -for messages. The `srt_sendmsg2` and `srt_recvmsg2` functions receive the socket, -buffer, and the `SRT_MSGCTRL` object, which is an input-output object specifying +for messages. The `srt_sendmsg2` and `srt_recvmsg2` functions receive the socket, +buffer, and the `SRT_MSGCTRL` object, which is an input-output object specifying extra data for the operation. Functions with the `msg2` suffix use the `SRT_MSGCTRL` object, and have the following interpretation (except `flags` and `boundary` which are reserved for future use and should be 0): -* `srt_sendmsg2`: - * `msgttl`: [IN] maximum time (in ms) to wait for successful delivery (-1: indefinitely) - * `inorder`: [IN] if false, the later sent message is allowed to be delivered earlier - * `srctime`: [IN] timestamp to be used for sending (0 if current time) - * `pktseq`: unused - * `msgno`: [OUT] message number assigned to the currently sent message - -* `srt_recvmsg2` - * `msgttl`: unused - * `inorder`: unused - * `srctime`: [OUT] timestamp set for this dataset when sending - * `pktseq`: [OUT] packet sequence number (first packet from the message, if it spans multiple UDP packets) - * `msgno`: [OUT] message number assigned to the currently received message - -Please note that the `msgttl` and `inorder` arguments and fields in `SRT_MSGCTRL` -are meaningful only when you use the message API in file mode (this will be explained -later). In live mode, which is the SRT default, packets are always delivered when -the time comes (always in order), where you don't want a packet to be dropped +- `srt_sendmsg2`: + - `msgttl`: [IN] maximum time (in ms) to wait for successful delivery (-1: indefinitely) + - `inorder`: [IN] if false, the later sent message is allowed to be delivered earlier + - `srctime`: [IN] timestamp to be used for sending (0 if current time) + - `pktseq`: unused + - `msgno`: [OUT] message number assigned to the currently sent message + +- `srt_recvmsg2` + - `msgttl`: unused + - `inorder`: unused + - `srctime`: [OUT] timestamp set for this dataset when sending + - `pktseq`: [OUT] packet sequence number (first packet from the message, if it spans multiple UDP packets) + - `msgno`: [OUT] message number assigned to the currently received message + +Please note that the `msgttl` and `inorder` arguments and fields in `SRT_MSGCTRL` +are meaningful only when you use the message API in file mode (this will be explained +later). In live mode, which is the SRT default, packets are always delivered when +the time comes (always in order), where you don't want a packet to be dropped before sending (so -1 should be passed here). The `srctime` parameter is an SRT addition for applications (i.e. gateways) -forwarding SRT streams. It permits pulling and pushing of the sender's original -time stamp, converted to local time and drift adjusted. The `srctime` parameter -is the number of usec (since epoch) in local SRT clock time. If the connection -is not between SRT peers or if **Timestamp-Based Packet Delivery mode (TSBPDMODE)** -is not enabled (see [APISocketOptions.md](https://github.com/Haivision/srt/blob/master/docs/APISocketOptions.md)), -the extracted `srctime` will be 0. Passing `srctime = 0` in `sendmsg` is like using -the API without `srctime` and the local send time will be used (if TSBPDMODE is +forwarding SRT streams. It permits pulling and pushing of the sender's original +time stamp, converted to local time and drift adjusted. The `srctime` parameter +is the number of usec (since epoch) in local SRT clock time. If the connection +is not between SRT peers or if **Timestamp-Based Packet Delivery mode (TSBPDMODE)** +is not enabled (see [SRT API Socket Options](API-socket-options.md)), +the extracted `srctime` will be 0. Passing `srctime = 0` in `sendmsg` is like using +the API without `srctime` and the local send time will be used (if TSBPDMODE is enabled and receiver supports it). +### Synopsis -Synopsis --------- +```c++ +int srt_send(SRTSOCKET s, const char* buf, int len); +int srt_sendmsg(SRTSOCKET s, const char* buf, int len, int msgttl, bool inorder, uint64_t srctime); +int srt_sendmsg2(SRTSOCKET s, const char* buf, int len, SRT_MSGCTRL* msgctrl); - int srt_send(SRTSOCKET s, const char* buf, int len); - int srt_sendmsg(SRTSOCKET s, const char* buf, int len, int msgttl, bool inorder, uint64_t srctime); - int srt_sendmsg2(SRTSOCKET s, const char* buf, int len, SRT_MSGCTRL* msgctrl); - - int srt_recv(SRTSOCKET s, char* buf, int len); - int srt_recvmsg(SRTSOCKET s, char* buf, int len); - int srt_recvmsg2(SRTSOCKET s, char* buf, int len, SRT_MSGCTRL* msgctrl); +int srt_recv(SRTSOCKET s, char* buf, int len); +int srt_recvmsg(SRTSOCKET s, char* buf, int len); +int srt_recvmsg2(SRTSOCKET s, char* buf, int len, SRT_MSGCTRL* msgctrl); +``` -Usage ------ +### Usage Sending a payload: - nb = srt_sendmsg(u, buf, nb, -1, true); - - nb = srt_send(u, buf, nb); +```c++ +nb = srt_sendmsg(u, buf, nb, -1, true); - SRT_MSGCTRL mc = srt_msgctrl_default; - nb = srt_sendmsg2(u, buf, nb, &mc); +nb = srt_send(u, buf, nb); +SRT_MSGCTRL mc = srt_msgctrl_default; +nb = srt_sendmsg2(u, buf, nb, &mc); +``` Receiving a payload: - nb = srt_recvmsg(u, buf, nb); - nb = srt_recv(u, buf, nb); - - SRT_MSGCTRL mc = srt_msgctrl_default; - nb = srt_recvmsg2(u, buf, nb, &mc); +```c++ +nb = srt_recvmsg(u, buf, nb); +nb = srt_recv(u, buf, nb); +SRT_MSGCTRL mc = srt_msgctrl_default; +nb = srt_recvmsg2(u, buf, nb, &mc); +``` -Transmission types available in SRT ------------------------------------ +### Transmission Types Available in SRT -Mode settings determine how the sender and receiver functions work. The main -[socket options](APISocketOptions.md) -that control it are: +Mode settings determine how the sender and receiver functions work. The main +SRT [socket options](API-socket-options.md) that control it are: -* `SRTO_TRANSTYPE`. Sets several parameters in accordance with the selected +- `SRTO_TRANSTYPE`. Sets several parameters in accordance with the selected mode: - * `SRTT_LIVE` (default) the Live mode (for live stream transmissions) - * `SRTT_FILE` the File mode (for "no time controlled" fastest data transmission) -* `SRTO_MESSAGEAPI` - * true: (default in Live mode): use Message API - * false: (default in File mode): use Buffer API + - `SRTT_LIVE` (default) the Live mode (for live stream transmissions) + - `SRTT_FILE` the File mode (for "no time controlled" fastest data transmission) +- `SRTO_MESSAGEAPI` + - true: (default in Live mode): use Message API + - false: (default in File mode): use Buffer API See [Transmission types](#transmission-types) below. +## Blocking and Non-blocking Modes -Blocking and Non-blocking Mode -============================== - -SRT functions can also work in blocking and non-blocking mode, for which +SRT functions can also work in blocking and non-blocking modes, for which there are two separate options for sending and receiving: `SRTO_SNDSYN` and `SRTO_RCVSYN`. When blocking mode is used, a function will not exit until -the availability condition is satisfied. In non-blocking mode the function +the availability condition is satisfied. In non-blocking mode the function always exits immediately, and in case of lack of resource availability, it returns an error with an appropriate code. The use of non-blocking mode usually requires using some polling mechanism, which in SRT is **EPoll**. @@ -316,28 +308,25 @@ and receiving. For example, `SNDSYN` defines blocking for `srt_connect` and `RCVSYN` defines blocking for `srt_accept`. The `SNDSYN` also makes `srt_close` exit only after the sending buffer is completely empty. - -EPoll (Non-blocking Mode Events) -================================ +### EPoll (Non-blocking Mode Events) EPoll is a mechanism to track the events happening on the sockets, both "system sockets" (see `SYSSOCKET` type) and SRT Sockets. Note that `SYSSOCKET` is also an alias for `int`, used only for clarity. +#### Synopsis -Synopsis --------- - - int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); - int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); - int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, - int64_t msTimeOut, - SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); - int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); - int srt_epoll_clear_usocks(int eid); +```c++ +int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); +int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); +int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, + int64_t msTimeOut, + SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); +int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +int srt_epoll_clear_usocks(int eid); +``` -SRT Usage ---------- +#### Usage SRT socket being a user level concept, the system epoll (or other select) cannot be used to handle SRT non-blocking mode events. Instead, SRT provides a @@ -367,22 +356,24 @@ is raised on any of the subscribed sockets. This function will exit as soon as at least one event is detected or a timeout occurs. The timeout is specified in `[ms]`, with two special values: - - 0: check and report immediately (don't wait) - - -1: wait indefinitely (not interruptible, even by a system signal) +- 0: check and report immediately (don't wait) +- -1: wait indefinitely (not interruptible, even by a system signal) There are some differences in the synopsis between these two: -1. `srt_epoll_wait`: Both system and SRT sockets can be subscribed. This +#### `srt_epoll_wait` + +Both system and SRT sockets can be subscribed. This function reports events on both socket types according to subscriptions, in these arrays: - - `readfds` and `lrfds`: subscribed for `IN` and `ERR` - - `writefds` and `lwfds`: subscribed for `OUT` and `ERR` +- `readfds` and `lrfds`: subscribed for `IN` and `ERR` +- `writefds` and `lwfds`: subscribed for `OUT` and `ERR` where: - - `readfds` and `writefds` report SRT sockets ("user" socket) - - `lrfds` and `lwfds` report system sockets +- `readfds` and `writefds` report SRT sockets ("user" socket) +- `lrfds` and `lwfds` report system sockets **NOTE**: this function provides no straightforward possibility to report sockets with an error. If you want to distinguish a report of readiness @@ -393,8 +384,8 @@ in the array in the direction for which the socket wasn't subscribed. For example, when an SRT socket is subscribed for `SRT_EPOLL_OUT | SRT_EPOLL_ERR`, its presence in `readfds` means that an error is reported for it. This need not be a big problem, because when an error is reported on -a socket, making it appear as if it were ready for an operation, then when that -operation occurs it will simply result in an error. You can use this as an +a socket, making it appear as if it were ready for an operation, then when that +operation occurs it will simply result in an error. You can use this as an alternative error check method. This function also reports an error of type `SRT_ETIMEOUT` when no socket is @@ -407,13 +398,14 @@ when system sockets are involved, is also 10ms. The return time from a poll function can only be quicker when there is an event raised on one of the active SRT sockets. +#### `srt_epoll_uwait` -2. `srt_epoll_uwait`: In this function only the SRT sockets can be subscribed +In this function only the SRT sockets can be subscribed (it reports error if you pass an epoll id that is subscribed to system sockets). This function waits for the first event on subscribed SRT sockets and reports all events collected at that moment in an array with the following structure: -``` +```c++ typedef struct SRT_EPOLL_EVENT_ { SRTSOCKET fd; @@ -433,112 +425,112 @@ the epoll container. The SRT EPoll system does not supports all features of Linux epoll. For example, it only supports level-triggered events for system sockets. +## Transmission Types -Transmission types ------------------- +**NOTE:** There might be a difference in terminology used in [Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) and current documentation. +Please consult [Data Transmission Modes](https://tools.ietf.org/html/draft-sharabayko-srt-01#section-4.2) +and [Best Practices and Configuration Tips for Data Transmission via SRT](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-7) +sections of the Internet Draft additionally. The current section is going to be reworked accordingly. -SRT was originally intended to be used for Live Streaming and therefore its main +SRT was originally intended to be used for Live Streaming and therefore its main and default transmission type is "live". However, SRT supports the modes that the original UDT library supported, that is, *file* and *message* transmission. -There are two general modes: **Live** and **File** transmission. Inside File -transmission mode, there are also two possibilities: **Buffer API** and -**Message API**. The Live mode uses Message API. However it doesn't exactly match -the description of the Message API because it uses a maximum single sending buffer +There are two general modes: **Live** and **File** transmission. Inside File +transmission mode, there are also two possibilities: **Buffer API** and +**Message API**. The Live mode uses Message API. However it doesn't exactly match +the description of the Message API because it uses a maximum single sending buffer up to the size that fits in one UDP packet. There are two options to set a particular type: -* `SRTO_TRANSTYPE`: uses the enum value with `SRTT_LIVE` for live mode - and `SRTT_FILE` for file mode. This option actually changes several parameters - to their default values for that mode. After this is done, additional parameters, +- `SRTO_TRANSTYPE`: uses the enum value with `SRTT_LIVE` for live mode + and `SRTT_FILE` for file mode. This option actually changes several parameters + to their default values for that mode. After this is done, additional parameters, including those that are set here, can be further changed. -* `SRTO_MESSAGEAPI`: This sets the Message API (true) or Buffer API (false) + +- `SRTO_MESSAGEAPI`: This sets the Message API (true) or Buffer API (false) This makes possible a total of three data transmission methods: -* [Live](#transmission-method-live) -* [Buffer](#transmission-method-buffer) -* [Message](#transmission-method-message) +- [Live](#transmission-method-live) +- [Buffer](#transmission-method-buffer) +- [Message](#transmission-method-message) ### Terminology The following terms are used in the description of transmission types: **HANGUP / RESUME**: These terms have different meanings depending on the blocking -state. They describe how a particular function behaves when performing an operation +state. They describe how a particular function behaves when performing an operation requires a specific readiness condition to be satisfied. -In blocking mode HANGUP means that the function blocks until a condition is -satisfied. RESUME means that the condition is satisfied and the function performs +In blocking mode HANGUP means that the function blocks until a condition is +satisfied. RESUME means that the condition is satisfied and the function performs the required operation. -In non-blocking mode the only difference is that HANGUP, instead of blocking, makes +In non-blocking mode the only difference is that HANGUP, instead of blocking, makes the function exit immediately with an appropriate error code (such as SRT_EASYNC*, -SRT_ETIMEOUT or SRT_ECONGEST) explaining why the function is not ready to perform -the operation. Refer to the error descriptions in [API-funtions.md](API-funtions.md) +SRT_ETIMEOUT or SRT_ECONGEST) explaining why the function is not ready to perform +the operation. Refer to the error descriptions in [API-functions.md](API-functions.md) for details. The following types of operations are involved: 1. Reading data: `srt_recv`, `srt_recvmsg`, `srt_recvmsg2`, `srt_recvfile`. - -The function HANGS UP if there are no available data to read, and RESUMES when -readable data become available (`SRT_EPOLL_IN` flag set in epoll). Use `SRTO_RCVSYN` -to control blocking mode here. + The function HANGS UP if there are no available data to read, and RESUMES when + readable data become available (`SRT_EPOLL_IN` flag set in epoll). Use `SRTO_RCVSYN` + to control blocking mode here. 2. Writing data: `srt_send`, `srt_sendmsg`, `srt_sendmsg2`, `srt_sendfile`. - -The function HANGS UP if the sender buffer becomes full and unable to store -any additional data, and RESUMES if the data scheduled for sending have been -removed from the sender buffer (after being sent and acknowledged) and there -is enough free space in the sender buffer to store data (`SRT_EPOLL_OUT` flag -set in epoll). Use `SRTO_SNDSYN` to control blocking mode here. + The function HANGS UP if the sender buffer becomes full and unable to store + any additional data, and RESUMES if the data scheduled for sending have been + removed from the sender buffer (after being sent and acknowledged) and there + is enough free space in the sender buffer to store data (`SRT_EPOLL_OUT` flag + set in epoll). Use `SRTO_SNDSYN` to control blocking mode here. 3. Accepting an incoming connection: `srt_accept` - -The function HANGS UP if there are no new connections reporting in, and -RESUMES when a new connection has been processed and a new socket or group -has been created to handle it. Note that this function requires the listener -socket to get the connection (the flag `SRTO_RCVSYN` set on -the listener socket controls the blocking mode for this operation). Note also -that the blocking mode for a similar `srt_accept_bond` function is controlled -exclusively by its timeout parameter because it can work with multiple listener -sockets, potentially with different settings. + The function HANGS UP if there are no new connections reporting in, and + RESUMES when a new connection has been processed and a new socket or group + has been created to handle it. Note that this function requires the listener + socket to get the connection (the flag `SRTO_RCVSYN` set on + the listener socket controls the blocking mode for this operation). Note also + that the blocking mode for a similar `srt_accept_bond` function is controlled + exclusively by its timeout parameter because it can work with multiple listener + sockets, potentially with different settings. 4. Connecting: `srt_connect` and its derivatives - -The function HANGS UP in the beginning, and RESUMES when the socket used for -connecting is either ready to perform transmission operations or has failed to -connect. It behaves a little differently in non-blocking mode -- the function -should be called only once, and it simply returns a success result as a "HANGUP". -Calling it again with the same socket would be an error. Calling it with a group -would start a completely new connection. It is only possible to determine whether -an operation has finished ("has RESUMED") from epoll flags. The socket, when -successfully connected, would have `SRT_EPOLL_OUT` set, that is, becomes ready -to send data, and `SRT_EPOLL_ERR` when it failed to connect. - -**BLIND / FAST / LATE REXMIT**: BLIND REXMIT is a situation where packets that -were sent are still not acknowledged, either in the expected time frame, or when -another ACK has come for the same number, but no packets have been reported as -lost, or at least not for all still unacknowledged packets. The congestion control -class is responsible for the algorithm for taking care of this situation, which is + The function HANGS UP in the beginning, and RESUMES when the socket used for + connecting is either ready to perform transmission operations or has failed to + connect. It behaves a little differently in non-blocking mode -- the function + should be called only once, and it simply returns a success result as a "HANGUP". + Calling it again with the same socket would be an error. Calling it with a group + would start a completely new connection. It is only possible to determine whether + an operation has finished ("has RESUMED") from epoll flags. The socket, when + successfully connected, would have `SRT_EPOLL_OUT` set, that is, becomes ready + to send data, and `SRT_EPOLL_ERR` when it failed to connect. + +**BLIND / FAST / LATE REXMIT**: BLIND REXMIT is a situation where packets that +were sent are still not acknowledged, either in the expected time frame, or when +another ACK has come for the same number, but no packets have been reported as +lost, or at least not for all still unacknowledged packets. The congestion control +class is responsible for the algorithm for taking care of this situation, which is either `FASTREXMIT` or `LATEREXMIT`. This will be explained below. +### Transmission Method: Live -Transmission method: Live -------------------------- +Setting `SRTO_TRANSTYPE` to `SRTT_LIVE` sets the following [socket options](API-socket-options.md): -Setting `SRTO_TRANSTYPE` to `SRTT_LIVE` sets the following [parameters](APISocketOptions.md): - -* `SRTO_TSBPDMODE` = true -* `SRTO_RCVLATENCY` = 120 -* `SRTO_PEERLATENCY` = 0 -* `SRTO_TLPKTDROP` = true -* `SRTO_MESSAGEAPI` = true -* `SRTO_NAKREPORT` = true -* `SRTO_PAYLOADSIZE` = 1316 -* `SRTO_CONGESTION` = "live" +- [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) = true +- [`SRTO_RCVLATENCY`](API-socket-options.md#SRTO_RCVLATENCY) = 120 +- [`SRTO_PEERLATENCY`](API-socket-options.md#SRTO_PEERLATENCY) = 0 +- [`SRTO_TLPKTDROP`](API-socket-options.md#SRTO_TLPKTDROP) = true +- [`SRTO_LINGER`](API-socket-options.md#SRTO_LINGER) = 0 +- [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) = true +- [`SRTO_NAKREPORT`](API-socket-options.md#SRTO_NAKREPORT) = true +- [`SRTO_RETRANSMITALGO`](API-socket-options.md#SRTO_RETRANSMITALGO) = 1 +- [`SRTO_PAYLOADSIZE`](API-socket-options.md#SRTO_PAYLOADSIZE) = 1316 +- [`SRTO_CONGESTION`](API-socket-options.md#SRTO_CONGESTION) = "live" In this mode, every call to a sending function is allowed to send only so much data, as declared by `SRTO_PAYLOADSIZE`, whose value is still @@ -553,71 +545,75 @@ the time comes for the packet to "play"). This mode uses the `LiveCC` congestion control class, which puts only a slight limitation on the bandwidth, if needed (i.e. by adding extra time if the interval -between two consecutive packets would otherwise be too short for the defined speed -limit). Note that it is not intended to work with "virtually infinite" ingest -speeds (such as, for example, reading directly from a file). Therefore the -application is not allowed to stream data with maximum speed -- it must take care +between two consecutive packets would otherwise be too short for the defined speed +limit). Note that it is not intended to work with "virtually infinite" ingest +speeds (such as, for example, reading directly from a file). Therefore the +application is not allowed to stream data with maximum speed -- it must take care that the speed of data being sent is in rhythm with timestamps in the live stream. Otherwise the behavior is undefined and might be surprisingly disappointing. The reading function will always return only a payload that was sent, and it will HANGUP until the time to play has come for this packet (if TSBPD mode is on) or when it is available without gaps of -lost packets (if TSBPD mode is off - see [`SRTO_TSBPDMODE`](APISocketOptions.md#SRTO_TSBPDMODE)). +lost packets (if TSBPD mode is off - see [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE)). You may wish to tweak some of the parameters below: -* `SRTO_TSBPDMODE`: You can turn off controlled latency if your application uses +- `SRTO_TSBPDMODE`: You can turn off controlled latency if your application uses its own method of latency control. -* `SRTO_RCVLATENCY`: You can increase the latency time, if this is +- `SRTO_RCVLATENCY`: You can increase the latency time, if this is too short. Setting a shorter latency than the default is strongly discouraged, although in some very specific and dedicated networks this may still be reasonable. Note that `SRTO_PEERLATENCY` is an option for the sending party, which is the minimum possible value for a receiver. -* `SRTO_TLPKTDROP`: When true (default), this will drop the packets +- `SRTO_TLPKTDROP`: When true (default), this will drop the packets that haven't been retransmitted on time, that is, before the next packet -that is already received becomes ready to play. You can turn this off to always +that is already received becomes ready to play. You can turn this off to always ensure a clean delivery. However, a lost packet can simply pause a delivery for some longer, potentially undefined time, and cause even worse tearing for the player. Setting higher latency will help much more in the case when TLPKTDROP causes packet drops too often. -* `SRTO_NAKREPORT`: Turns on repeated sending of loss reports, when the lost +- `SRTO_NAKREPORT`: Turns on repeated sending of loss reports, when the lost packet was not recovered quickly enough, which raises suspicions that the loss report itself was lost. Without it, the loss report will be always reported just once and never repeated again, and then the lost payload packet will be probably dropped by the TLPKTDROP mechanism. -* `SRTO_PAYLOADSIZE`: Default value is for MPEG TS. If you are going -to use SRT to send any different kind of payload, such as, for example, +- `SRTO_RETRANSMITALGO`: Given the receiver sends periodic NAK reports, +the sender can reduce the retransmission overhead by not retransmitting a loss +more often than once per RTT (value 1). + +- `SRTO_PAYLOADSIZE`: Default value is for MPEG TS. If you are going +to use SRT to send any different kind of payload, such as, for example, wrapping a live stream in very small frames, then you can use a bigger maximum frame size, though not greater than 1456 bytes. -Parameters from the modified for transmission type list, not mentioned in the +Parameters from the modified for transmission type list, not mentioned in the list above, are crucial for Live mode and shall not be changed. -The BLIND REXMIT situation is resolved using the FASTREXMIT algorithm by LiveCC: -sending non-acknowledged packets blindly on the premise that the receiver lingers -too long before acknowledging them. This mechanism isn't used (i.e. the BLIND REXMIT -situation isn't handled at all) when `SRTO_NAKREPORT` is set by the peer -- the +The BLIND REXMIT situation is resolved using the FASTREXMIT algorithm by LiveCC: +sending non-acknowledged packets blindly on the premise that the receiver lingers +too long before acknowledging them. This mechanism isn't used (i.e. the BLIND REXMIT +situation isn't handled at all) when `SRTO_NAKREPORT` is set by the peer -- the NAKREPORT method is considered so effective that FASTREXMIT isn't necessary. +### Transmission Method: Buffer -Transmission method: Buffer ---------------------------- - -Setting `SRTO_TRANSTYPE` to `SRTT_FILE` sets the following [parameters](APISocketOptions.md): +Setting `SRTO_TRANSTYPE` to `SRTT_FILE` sets the following [socket options](API-socket-options.md): -* `SRTO_TSBPDMODE` = false -* `SRTO_RCVLATENCY` = 0 -* `SRTO_PEERLATENCY` = 0 -* `SRTO_TLPKTDROP` = false -* `SRTO_MESSAGEAPI` = false -* `SRTO_NAKREPORT` = false -* `SRTO_PAYLOADSIZE` = 0 -* `SRTO_CONGESTION` = "file" +- [`SRTO_TSBPDMODE`](API-socket-options.md#SRTO_TSBPDMODE) = false +- [`SRTO_RCVLATENCY`](API-socket-options.md#SRTO_RCVLATENCY) = 0 +- [`SRTO_PEERLATENCY`](API-socket-options.md#SRTO_PEERLATENCY) = 0 +- [`SRTO_TLPKTDROP`](API-socket-options.md#SRTO_TLPKTDROP) = false +- [`SRTO_LINGER`](API-socket-options.md#SRTO_LINGER) = 180 s +- [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) = false +- [`SRTO_NAKREPORT`](API-socket-options.md#SRTO_NAKREPORT) = false +- [`SRTO_RETRANSMITALGO`](API-socket-options.md#SRTO_RETRANSMITALGO) = 0 +- [`SRTO_PAYLOADSIZE`](API-socket-options.md#SRTO_PAYLOADSIZE) = 0 +- [`SRTO_CONGESTION`](API-socket-options.md#SRTO_CONGESTION) = "file" In this mode, calling a sending function is allowed to potentially send virtually any size of data. The sending function will HANGUP only if the @@ -631,16 +627,16 @@ From the receiving function there will be retrieved as many data as the minimum of the passed buffer size and available data; data still available and not retrieved by this call will be available for retrieval in the next call. -There is also a dedicated pair of functions that can only be used in this mode: -`srt_sendfile` and `srt_recvfile`. These functions can be used to transmit the +There is also a dedicated pair of functions that can only be used in this mode: +`srt_sendfile` and `srt_recvfile`. These functions can be used to transmit the whole file, or a fragment of it, based on the offset and size. -This mode uses the `FileCC` congestion control class, which is a direct copy of +This mode uses the `FileCC` congestion control class, which is a direct copy of UDT's `CUDTCC` congestion control class, adjusted to the needs of SRT's congestion control framework. This class generally sends the data with maximum speed in the beginning, until the flight window is full, and then keeps the speed at the edge of the flight window, only slowing down in the case where -packet loss was detected. The bandwidth usage can be directly limited by the +packet loss was detected. The bandwidth usage can be directly limited by the `SRTO_MAXBW` option. The BLIND REXMIT situation is resolved in FileCC using the LATEREXMIT @@ -649,71 +645,67 @@ loss list is empty and the flight window is full, all packets since the last ACK are sent again (that's more or less the TCP behavior, but in contrast to TCP, this is done as a very low probability fallback). -Most of the parameters described above have `false` or `0` values as they usually -designate features used in Live mode. None are used with File mode. The only option -that makes sense to modify after the `SRTT_FILE` type was set is `SRTO_MESSAGEAPI`, +Most of the parameters described above have `false` or `0` values as they usually +designate features used in Live mode. None are used with File mode. The only option +that makes sense to modify after the `SRTT_FILE` type was set is `SRTO_MESSAGEAPI`, which is described below. - -Transmission method: Message ----------------------------- +### Transmission Method: Message Setting `SRTO_TRANSTYPE` to `SRTT_FILE` and then setting `SRTO_MESSAGEAPI` to `true` implies usage of the Message transmission method. Parameters are set as -described above for the Buffer method, with the exception of `SRTO_MESSAGEAPI`. +described above for the Buffer method, with the exception of `SRTO_MESSAGEAPI`. The "file" congestion controller is also used in this mode. It differs from the Buffer method, however, in terms of the rules concerning sending and receiving. **HISTORICAL INFO**: The library on which SRT was based (UDT) somewhat misleadingly -used the terms `STREAM` and `DGRAM`, and used the system symbols `SOCK_STREAM` and -`SOCK_DGRAM` in the socket creation function. A "datagram" in the UDT terminology -has nothing to do with the "datagram" term in networking terminology, where its -size is limited to as much it can fit in one MTU. In UDT it is actually a message, -which may span multiple UDP packets and has clearly defined boundaries. It's rather -similar to the **SCTP** protocol. Also, in UDP the API functions were strictly bound +used the terms `STREAM` and `DGRAM`, and used the system symbols `SOCK_STREAM` and +`SOCK_DGRAM` in the socket creation function. A "datagram" in the UDT terminology +has nothing to do with the "datagram" term in networking terminology, where its +size is limited to as much it can fit in one MTU. In UDT it is actually a message, +which may span multiple UDP packets and has clearly defined boundaries. It's rather +similar to the **SCTP** protocol. Also, in UDP the API functions were strictly bound to `DGRAM` or `STREAM` mode: `UDT::send/UDT::recv` were only for `STREAM` and -`UDT::sendmsg/UDT::recvmsg` only for `DGRAM`. In SRT this is changed: all functions -can be used in all modes, except `srt_sendfile/srt_recvfile`, and how the functions +`UDT::sendmsg/UDT::recvmsg` only for `DGRAM`. In SRT this is changed: all functions +can be used in all modes, except `srt_sendfile/srt_recvfile`, and how the functions actually work is controlled by the `SRTO_MESSAGEAPI` flag. -In message mode, every sending function sends **exactly** as much data as it is -passed in a single sending function call. The receiver also receives not less than -**exactly** the number of bytes that was sent (although every message may have a +In message mode, every sending function sends **exactly** as much data as it is +passed in a single sending function call. The receiver also receives not less than +**exactly** the number of bytes that was sent (although every message may have a different size). Every message may also have extra parameters: - - **TTL** defines how much time (in ms) the message should wait in the sending - buffer for the opportunity to be picked up by the sender thread and sent over - the network; otherwise it is dropped. Note that this TTL only applies to packets that - have been lost and should be retransmitted. - - - **INORDER**, when true, means the messages must be read by the receiver in - exactly the same order in which they were sent. In the situation where a message - suffers a packet loss, this prevents any subsequent messages from achieving - completion status prior to recovery of the preceding message. - -The sending function will HANGUP when the free space in the sending buffer does -not exactly fit the whole message, and it will only RESUME if the free space in -the sending buffer grows up to this size. The call to the sending function also -returns with an error when the size of the message exceeds the total size of the -buffer (this can be modified by the `SRTO_SNDBUF` option). In other words, it is -not designed to send just a part of the message -- either the whole message is +- **TTL** defines how much time (in ms) the message should wait in the sending +buffer for the opportunity to be picked up by the sender thread and sent over +the network; otherwise it is dropped. Note that this TTL only applies to packets that +have been lost and should be retransmitted. + +- **INORDER**, when true, means the messages must be read by the receiver in +exactly the same order in which they were sent. In the situation where a message +suffers a packet loss, this prevents any subsequent messages from achieving +completion status prior to recovery of the preceding message. + +The sending function will HANGUP when the free space in the sending buffer does +not exactly fit the whole message, and it will only RESUME if the free space in +the sending buffer grows up to this size. The call to the sending function also +returns with an error when the size of the message exceeds the total size of the +buffer (this can be modified by the `SRTO_SNDBUF` option). In other words, it is +not designed to send just a part of the message -- either the whole message is sent, or nothing at all. -The receiving function will HANGUP until the whole message is available for reading; -if the message spans multiple UDP packets, then the function RESUMES only when -every single packet from the message has been received, including recovered packets, -if any. When the INORDER flag is set to false and parts of multiple messages are -currently available, the first message that is complete (possibly recovered) is -returned. Otherwise the function does a HANGUP until the next message is complete. -The call to the receiving function is rejected if the buffer size is too small +The receiving function will HANGUP until the whole message is available for reading; +if the message spans multiple UDP packets, then the function RESUMES only when +every single packet from the message has been received, including recovered packets, +if any. When the INORDER flag is set to false and parts of multiple messages are +currently available, the first message that is complete (possibly recovered) is +returned. Otherwise the function does a HANGUP until the next message is complete. +The call to the receiving function is rejected if the buffer size is too small for a single message to fit in it. -Note that you can use any of the sending and receiving functions for sending and -receiving messages, except `sendfile/recvfile`, which are dedicated exclusively -for Buffer API. - -For more information, see [APISocketOptions.md](APISocketOptions.md) +Note that you can use any of the sending and receiving functions for sending and +receiving messages, except `sendfile/recvfile`, which are dedicated exclusively +for Buffer API. +For more information, see [SRT API Socket Options](API-socket-options.md). -[Return to top](#srt-api) - +[Return to Top of Page](#srt-api) diff --git a/docs/API/configuration-guidelines.md b/docs/API/configuration-guidelines.md new file mode 100644 index 000000000..76565331b --- /dev/null +++ b/docs/API/configuration-guidelines.md @@ -0,0 +1,115 @@ +# Configuration Guidelines + +## Receiver Buffer Size + +The receiver buffer can be configured with the [`SRTO_RCVBUF`](./API-socket-options.md#SRTO_RCVBUF) socket option. +Buffer size in bytes is expected to be passed in the `optval` argument of the `srt_setsockopt(..)` function. +However, internally the value will be converted into the number of packets stored in the receiver buffer. + +The allowed value of `SRTO_RCVBUF` is also limited by the value of the flow control window size [`SRTO_FC`](./API-socket-options.md#SRTO_FC) socket option. +See issue [#700](https://github.com/Haivision/srt/issues/700). + +The default flow control window size is 25600 packets. It is approximately: + +- **270 Mbits** of payload in the default live streaming configuration with an SRT payload size of **1316 bytes**; +- **300 Mbits** of payload in the default file transfer configuration with an SRT payload size of **1456 bytes**. + +The default receiver buffer size is 8192 packets. It is approximately: +- **86 Mbits** of payload with the effective SRT payload size of **1316 bytes**. + +### Setting Receiver Buffer Size + +When the `SRTO_RCVBUF` option value is set using the `srt_setsockopt(..)` function, +the provided size in bytes is internally converted to the corresponding size in packets. +The size of a cell for a single packet in the buffer is defined by the +`SRTO_MSS` option, which is 1500 by default. This value, decreased by 28 in +the case of IPv4 (20 bytes for the IPv4 header and 8 bytes for the UDP header), gives 1472 +bytes per packet to be allocated. The actual memory occupied by the receiver +buffer will be a multiple of that value. For the default 8192 packets it +will be 11776 kB (11.5 MB). + +Note that every cell has 16 bytes for the SRT header. The remaining space +is for the payload. + +As already mentioned, the maximum allowed size of the receiver buffer is limited by the value of `SRTO_FC`. + +The following function returns the configured buffer size in packets depending on the SRTO_RCVBUF, SRTO_MSS and SRTO_FC values set: + +```c++ +int getRbufSizePkts(int SRTO_RCVBUF, int SRTO_MSS, int SRTO_FC) +{ + // UDP/IPv4 header size is assumed to be 28 bytes + // 20 bytes IPv4 + 8 bytes of UDP + const int UDP_IPv4_HDR= 28; + const int pkts = (rbuf_size / (SRTO_MSS - UDP_IPv4_HDR)); + + return min(pkts, SRTO_FC); +} +``` + +If the value of `SRTO_RCVBUF` in packets exceeds `SRTO_FC`, then it is silently set to the value in bytes corresponding to `SRTO_FC`. +Therefore, to set higher values of `SRTO_RCVBUF` the value of `SRTO_FC` must be increased first. + +### Calculating Target Size in Packets + +The minimum size of the receiver buffer in packets can be calculated as follows: + +`pktsRBufSize = bps / 8 × (RTTsec + latency_sec) / bytePayloadSize` + +where + +- `bps` is the payload bitrate of the stream in bits per second; +- `RTTsec` is the RTT of the network connection in seconds; + +- `bytePayloadSize` is the expected size of the payload of the SRT data packet. + +If the whole remainder of the MTU is expected to be used, payload size is calculated as follows: + +`bytePayloadSize = MSS - UDP_IPv4_HDR - SRT_HDR` + +where + +- `MSS`: Maximum Segment Size (size of the MTU); see `SRTO_MSS` (default: 1500) +- `UDP_IPv4_HDR`: 20 bytes for IPv4 + 8 bytes for UDP +- `SRT_HDR`: 16 bytes of SRT header (belonging to the user space) + +### Calculating Target Size to Set + +To determine the value to pass in `srt_setsockopt(..)` with `SRTO_RCVBUF` +the size in packets `pktsRBufSize` must be converted to the size in bytes +assuming the internal conversion of the `srt_setsockopt(..)` function. + +The target size of the payload stored by the receiver buffer would be: + +`SRTO_RCVBUF = pktsRBufSize × (SRTO_MSS - UDPHDR_SIZE)` + +where + +- `UDPHDR_SIZE` = 28 (20 bytes IPv4, 8 bytes of UDP) +- `SRTO_MSS` is the corresponding socket option value at the moment of setting `SRTO_RCVBUF`. + + +### Summing Up + + +```c++ +auto CalculateTargetRBufSize(int msRTT, int bpsRate, int bytesPayloadSize, int msLatency, int SRTO_MSS) +{ + const int UDPHDR_SIZE = 28; + const long long targetPayloadBytes = static_cast(msLatency + msRTT / 2) * bpsRate / 1000 / 8; + const long long targetNumPackets = targetPayloadBytes / bytesPayloadSize; + const long long targetSizeValue = targetNumPackets * (SRTO_MSS - UDPHDR_SIZE); + return {targetNumPackets, targetSizeValue}; +} + +// Configuring + +const auto [fc, rcvbuf] = CalculateTargetRBufSize(msRTT, bpsRate, bytesPayloadSize, SRTO_RCVLATENCY, SRTO_MSS); + +int optval = fc; +int optlen = sizeof optval; +srt_setsockopt(sock, 0, SRTO_FC, (void*) &optval, optlen); + +optval = rcvbuf; +srt_setsockopt(sock, 0, SRTO_RCVBUF, (void*) &optval, optlen); +``` diff --git a/docs/API/rejection-codes.md b/docs/API/rejection-codes.md new file mode 100644 index 000000000..0b8418b5f --- /dev/null +++ b/docs/API/rejection-codes.md @@ -0,0 +1,473 @@ +# SRT Rejection Codes + +This document provides an overview of the rejection (error) codes used by and supported within SRT and SRT-based applications. For information on other types of error codes refer to the [API Socket Options](./docs/API/API-socket-options.md) document. + +[:arrow_down:   Jump to list of rejection codes](#api-function-rejection-codes) + + +## Summary of Rejection Codes + +Rejection codes are used in the SRT API, and are transferred on the wire as a part of a Handshake packet (refer to the `Handshake Type` field of the [Handshake](./docs/features/handshake.md) packet). +The rejection codes are divided into several ranges: + + - SRT internal + - Predefined application level codes + - User defined (custom) codes + +In the SRT API these ranges are marked with the following constants (preprocessor definitions): + + - `SRT_REJC_INTERNAL` = 0 + - `SRT_REJC_PREDEFINED` = 1000 + - `SRT_REJC_USERDEFINED` = 2000 + +When transferred on the wire, the API value is incremented by 1000 to become the `Handshake Type` field value. In the following sections the values of rejection reason codes are given in accordance with the API values. + + +### SRT Internal Rejection Codes + +Defined in [**srt.h**](srtcore/srt.h), these codes provide the reason why a connection is rejected by SRT. They cover the reserved range 0 - 999 (below `SRT_REJC_PREDEFINED`). These codes cannot be used by applications to report a rejection reason. + +Naming: `SRT_REJ_*` + + - `SRT_REJ_UNKNOWN` = 0 + - `SRT_REJ_SYSTEM` = 1 + - ... + - `SRT_REJ_CRYPTO` = 17 +See [the list below](#api-function-rejection-codes) for details. + +### Extended Rejection Codes + +As defined in [**access_control.h**](srtcore/access_control.h), these are standard server error codes including those adopted from HTTP. They provide the reason why an application rejects a connection. The value is expected to be set by an application via the listener callback if it wants to reject an incoming connection request. These codes cover the reserved range 1000 - 1999 (`SRT_REJC_PREDEFINED` - `SRT_REJC_USERDEFINED`). + + +Subranges (1000 + value): + + - **0 - 99**: Reserved for unique SRT-specific codes (unused by HTTP) + - **100 - 399**: Info, Success, and Redirection in HTTP (unused by SRT) + - **400 - 599**: Client and server errors in HTTP (adopted by SRT) + +Naming: `SRT_REJX_*` + +Example: + + - `SRT_REJX_KEY_NOTSUP` (1001): The key used in the StreamID keyed string is not supported by the service. + - `SRT_REJX_BAD_REQUEST` (1400) + - ... + +### User Defined Rejection Codes + +These codes can be freely defined by an application. They can be custom codes, not adopted by other vendors. For example, `2005: “Makito license expired”`. They cover the reserved range 2000 - 2999 (higher than `SRT_REJC_USERDEFINED`). + + +## API Function Rejection Codes + +SRT's API function rejection codes refer to system-level error conditions caused by SRT-specific settings or operating conditions. They are uninfluenced by application-related events, and applications are not permitted to use or simulate these codes. + +The table below lists the rejection codes as defined in [**srt.h**](srtcore/srt.h) (click the *Rejection Reason* link to view a complete description). + +| *Code* | *Rejection Reason* | *Since* | *Description* | +|:------:|:-------------------------------------------------- |:-------:|:-------------------------------------------------------------------------------------------------------------- | +| 0 | [SRT_REJ_UNKNOWN](#SRT_REJ_UNKNOWN) | 1.3.4 | Fallback value for cases where connection is not rejected. | +| 1 | [SRT_REJ_SYSTEM](#SRT_REJ_SYSTEM) | 1.3.4 | System function reported a failure. | +| 2 | [SRT_REJ_PEER](#SRT_REJ_PEER) | 1.3.4 | Connection rejected by peer, with no additional details. | +| 3 | [SRT_REJ_RESOURCE](#SRT_REJ_RESOURCE) | 1.3.4 | Problem with resource allocation (usually memory). | +| 4 | [SRT_REJ_ROGUE](#SRT_REJ_ROGUE) | 1.3.4 | Data sent by one party cannot be interpreted. | +| 5 | [SRT_REJ_BACKLOG](#SRT_REJ_BACKLOG) | 1.3.4 | Listener's backlog has been exceeded. | +| 6 | [SRT_REJ_IPE](#SRT_REJ_IPE) | 1.3.4 | Internal Program Error. | +| 7 | [SRT_REJ_CLOSE](#SRT_REJ_CLOSE) | 1.3.4 | Listener socket received a request as it is being closed. | +| 8 | [SRT_REJ_VERSION](#SRT_REJ_VERSION) | 1.3.4 | Minimum version requirement for a connection not satisfied by one party. | +| 9 | [SRT_REJ_RDVCOOKIE](#SRT_REJ_RDVCOOKIE) | 1.3.4 | Rendezvous cookie collision. | +| 10 | [SRT_REJ_BADSECRET](#SRT_REJ_BADSECRET) | 1.3.4 | Both parties have defined connection passphrases that differ. | +| 11 | [SRT_REJ_UNSECURE](#SRT_REJ_UNSECURE) | 1.3.4 | Only one party has set up a connection password. | +| 12 | [SRT_REJ_MESSAGEAPI](#SRT_REJ_MESSAGEAPI) | 1.3.4 | [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) flag is different on both connection parties. | +| 13 | [SRT_REJ_CONGESTION](#SRT_REJ_CONGESTION) | 1.3.4 | Incompatible congestion-controller type. | +| 14 | [SRT_REJ_FILTER](#SRT_REJ_FILTER) | 1.3.4 | [`SRTO_PACKETFILTER`](API-socket-options.md#SRTO_PACKETFILTER) option is different on both connection parties. | +| 15 | [SRT_REJ_GROUP](#SRT_REJ_GROUP) | 1.4.2 | Group type or group settings are incompatible between connection parties. | +| 16 | [SRT_REJ_TIMEOUT](#SRT_REJ_TIMEOUT) | 1.4.2 | Connection not rejected, but timed out. | +| 17 | [SRT_REJ_CRYPTO](#SRT_REJ_CRYPTO) | 1.5.2 | Connection rejected due to unsupported or mismatching encryption mode. | +| | | | | + + +## Access Control Rejection Codes + +SRT's access control rejection codes are intended for use by applications to forcefully reject connections in SRT listener callbacks. They are intended only as a guide to promote standardization. If they are used in an application, a description of their specific implementation should be published (the descriptions in this documentation are not definitive). + +The table below lists the rejection codes as defined in [**access_control.h**](srtcore/access_control.h) (click the *Rejection Reason* link to view a complete description). + +| *Code* | *Rejection Reason* | *Since* | *Description* | +|:------:|:------------------------------------------------- |:-------:|:-------------------------------------------------------------------------------------------------------------- | +| 1000 | [SRT_REJX_FALLBACK](#SRT_REJX_FALLBACK) | 1.4.2 | Callback handler has interrupted an incoming connection. | +| 1001 | [SRT_REJX_KEY_NOTSUP](#SRT_REJX_KEY_NOTSUP) | 1.4.2 | Key specified in StreamID string not supported by application. | +| 1002 | [SRT_REJX_FILEPATH](#SRT_REJX_FILEPATH) | 1.4.2 | Resource type designates file where path has wrong syntax or is not found. | +| 1003 | [SRT_REJX_HOSTNOTFOUND](#SRT_REJX_HOSTNOTFOUND) | 1.4.2 | The host specified in the `h` key cannot be identified. | +| 1400 | [SRT_REJX_BAD_REQUEST](#SRT_REJX_BAD_REQUEST) | 1.4.2 | General syntax error. | +| 1401 | [SRT_REJX_UNAUTHORIZED](#SRT_REJX_UNAUTHORIZED) | 1.4.2 | Authentication failed; client unauthorized to access the resource. | +| 1402 | [SRT_REJX_OVERLOAD](#SRT_REJX_OVERLOAD) | 1.4.2 | Server load too heavy to process request, or credit limit exceeded. | +| 1403 | [SRT_REJX_FORBIDDEN](#SRT_REJX_FORBIDDEN) | 1.4.2 | Access denied to the resource for any reason. | +| 1404 | [SRT_REJX_NOTFOUND](#SRT_REJX_NOTFOUND) | 1.4.2 | Resource specified by `r` and `h` keys cannot be found. | +| 1405 | [SRT_REJX_BAD_MODE](#SRT_REJX_BAD_MODE) | 1.4.2 | Mode specified in the `m` key in StreamID is not supported for this request. | +| 1406 | [SRT_REJX_UNACCEPTABLE](#SRT_REJX_UNACCEPTABLE) | 1.4.2 | Unavailable parameters in `StreamID`, or `m=publish` data format not supported. | +| 1409 | [SRT_REJX_CONFLICT](#SRT_REJX_CONFLICT) | 1.4.2 | Resource specified by `r` and `h` keys is locked for modification. | +| 1415 | [SRT_REJX_NOTSUP_MEDIA](#SRT_REJX_NOTSUP_MEDIA) | 1.4.2 | Media type not supported by the application. | +| 1423 | [SRT_REJX_LOCKED](#SRT_REJX_LOCKED) | 1.4.2 | Resource is locked against any access. | +| 1424 | [SRT_REJX_FAILED_DEPEND](#SRT_REJX_FAILED_DEPEND) | 1.4.2 | Dependent entity for the request is not present. | +| 1500 | [SRT_REJX_ISE](#SRT_REJX_ISE) | 1.4.2 | Internal server error. | +| 1501 | [SRT_REJX_UNIMPLEMENTED](#SRT_REJX_UNIMPLEMENTED) | 1.4.2 | Request not supported by current version of the service. | +| 1502 | [SRT_REJX_GW](#SRT_REJX_GW) | 1.4.2 | Target endpoint rejected connection from gateway server | +| 1503 | [SRT_REJX_DOWN](#SRT_REJX_DOWN) | 1.4.2 | Service is down for maintenance. | +| 1505 | [SRT_REJX_VERSION](#SRT_REJX_VERSION) | 1.4.2 | SRT application version not supported. | +| 1507 | [SRT_REJX_NOROOM](#SRT_REJX_NOROOM) | 1.4.2 | Data stream cannot be archived due to lack of storage space. | +| | | | | + + +**NOTE**: SRT rejection codes follow this prefix convention: + + - `SRT_REJ`: standard rejection codes from SRT API functions (0 - 99) + - `SRT_REJC`: mark the border values between ranges. + - `SRT_REJX`: extended rejection codes (code values above 1000).above)?* + + +## API Function Rejection Reasons + + +#### SRT_REJ_UNKNOWN + +A fallback value for cases when there was no connection rejected. + + +#### SRT_REJ_SYSTEM + +One system function reported a failure. Usually this means some system +error or lack of system resources to complete the task. + + +#### SRT_REJ_PEER + +The connection has been rejected by the peer, but no further details are available. +This usually means that the peer doesn't support rejection reason reporting. + + +#### SRT_REJ_RESOURCE + +A problem with resource allocation (usually memory). + + +#### SRT_REJ_ROGUE + +The data sent by one party to another cannot be properly interpreted. This +should not happen during normal usage, unless it's a bug, or some weird +events are happening on the network. + + +#### SRT_REJ_BACKLOG + +The listener's backlog has exceeded its queue limit (there are many other callers +waiting for the opportunity to be connected and the "wait queue" has +reached its limit). + + +#### SRT_REJ_IPE + +Internal Program Error. This should not happen during normal usage. It +usually indicates a bug in the software (although this can be reported by both +local and foreign hosts). + + +#### SRT_REJ_CLOSE + +The listener socket was able to receive the request, but is currently +being closed. It's likely that the next request will result in a timeout. + + +#### SRT_REJ_VERSION + +One party in the connection has set up a minimum version that is required for +that connection, but the other party doesn't satisfy this requirement. + + +#### SRT_REJ_RDVCOOKIE + +Rendezvous cookie collision. Normally, the probability that this will happen is +negligible. However, it *can* result from a misconfiguration when, in attempting +to make a rendezvous connection, both parties try to bind to the same IP address, +or both are local addresses of the same host. In such a case the sent handshake +packets are returned to the same host as if they were sent by the peer (i.e. a +party is sending to itself). In such situations, this reject reason will be +reported for every attempt. + + +#### SRT_REJ_BADSECRET + +Both parties have defined a passphrase for a connection, but they differ. + + +#### SRT_REJ_UNSECURE + +Only one connection party has set up a password. See also the +[`SRTO_ENFORCEDENCRYPTION`](API-socket-options.md#SRTO_ENFORCEDENCRYPTION) flag. + + +#### SRT_REJ_MESSAGEAPI + +The value of the [`SRTO_MESSAGEAPI`](API-socket-options.md#SRTO_MESSAGEAPI) +flag is different on both parties in a connection. + + +#### SRT_REJ_CONGESTION + +The [`SRTO_CONGESTION`](API-socket-options.md#SRTO_CONGESTION)option has +been set up differently on both parties in a connection. + + +#### SRT_REJ_FILTER + +The [`SRTO_PACKETFILTER`](API-socket-options.md#SRTO_PACKETFILTER) option +has been set differently on both parties in a connection. + + +#### SRT_REJ_GROUP + +The group type or some group settings are incompatible between connection parties. +While every connection within a bonding group may have different target addresses, +they should all designate the same endpoint and the same SRT application. If this +condition isn't satisfied, then the peer will respond with a different peer group +ID for the connection that is trying to contact a machine/application that is +completely different from the existing connections in the bonding group. + + +#### SRT_REJ_TIMEOUT + +The connection wasn't rejected, but it timed out. This code is always sent on +a connection timeout, but this is the only way to get this state in non-blocking +mode (see [`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN)). + +There may also be server and user rejection codes, as defined by the +`SRT_REJC_INTERNAL`, `SRT_REJC_PREDEFINED`, and `SRT_REJC_USERDEFINED` +constants. Note that the number space from the value of `SRT_REJC_PREDEFINED` +and above is reserved for "predefined codes" (`SRT_REJC_PREDEFINED` value plus +adopted HTTP codes). Values above `SRT_REJC_USERDEFINED` are freely defined by +the application. + +#### SRT_REJ_CRYPTO + +The connection was rejected due to a mismatch in crypto modes. See `SRTO_CRYPTOMODE`. + +[:arrow_up:   Back to top](#srt-rejection-codes) + + +## Access Control Rejection Reasons + +An SRT listener callback handler can decide to reject an incoming connection. +Under normal circumstances, the rejection code is predefined as `SRT_REJ_RESOURCE`. +The handler can, however, set its own rejection code. There are two numbered spaces +intended for this purpose (as the range below `SRT_REJC_PREDEFINED` is reserved +for internal codes): + +- `SRT_REJC_PREDEFINED` and above: These are predefined errors. Errors from this +range (that is, below `SRT_REJC_USERDEFINED`) have their definitions provided in +the `access_control.h` public header file. The intention is that applications +using these codes understand the situations they describe in a standard way. + +- `SRT_REJC_USERDEFINED` and above: These are errors that are freely defined by +the application. Codes from this range can be only understood if each application +knows the code definitions of the other. These codes should be used only after +making sure that the applications at either end of a connection understand them. + +The intention here is for the predefined codes to be consistent with the HTTP +standard codes. Such code can be set by using the [`srt_setrejectreason`](docs/api/api-functions.md#srt-setrejectreason) function. + +The SRT-specific codes are: + +#### SRT_REJX_FALLBACK + +This code should be set by the callback handler in the beginning in case +the application needs to be informed that the callback handler +actually has interpreted the incoming connection, but hasn't set a +more appropriate code describing the situation. + +#### SRT_REJX_KEY_NOTSUP + +Indicates there was a key specified in the StreamID string that this application +doesn't support. Note that it's not obligatory for the application to +react this way - it may chose to ignore unknown keys completely, or +to have some keys in the ignore list (which it won't interpret, but tolerate) +while rejecting any others. It is also up to the application +to decide to return this specific error, or more generally report +the syntax error with `SRT_REJX_BAD_REQUEST`. + +#### SRT_REJX_FILEPATH + +The resource type designates a file, and the path either has the wrong syntax +or is not found. In the case where `t=file`, the path should be specified under +the `r` key, and the file specified there must be able to be saved this way. +It's up to the application to decide how to treat this path, how to parse it, +and what this path specifically means. For the `r` key, the application should +at least handle the single filename, and have storage space available to save +it (provided a file of the same name does not already exist there). The +application should decide whether and how to handle all other situations (like +directory path, special markers in the path to be interpreted by the +application, etc.), or to report this error. + +#### SRT_REJX_HOSTNOTFOUND + +The host specified in the `h` key cannot be identified. The `h` key is +generally for a situation when you have multiple DNS names for a host, +so an application may want to extract the name from the URI and set it +to the `h` key so that the application can distinguish the request also by +the target host name. The application may, however, limit the number of +recognized services by host name to some predefined names and not +handle the others, even if this is properly resolved by DNS. In this +case it should report this error. + +The other error codes are HTTP codes adapted for SRT: + +#### SRT_REJX_BAD_REQUEST + +General syntax error. This can be reported in any case when parsing +the StreamID contents failed, or it cannot be properly interpreted. + +#### SRT_REJX_UNAUTHORIZED + +Authentication failed, which makes the client unauthorized to access the +resource. This error, however, confirms that the syntax is correct and +the resource has been properly identified. Note that this cannot be +reported when you use a simple user-password authentication +method because in this case the password is verified only after the +listener callback handler accepts the connection. This error is rather +intended to be reported in the case of `t=auth` when the authentication +process has generated some valid session ID, but then the session +connection has specified a resource that is not within the frames +of that authentication. + +#### SRT_REJX_OVERLOAD + +The server is too heavily loaded to process the request, or the credit limit +for accessing the service and the resource has been exceeded. +In HTTP the description mentions payment for a service, but +it is also used by some services for general "credit" management +for a client. In SRT it should be used when the service is doing +any kind of credit management to limit access to selected clients +that "have" enough credit, even if the credit is something the client +can recharge itself, or that can be granted depending on available +service resources. + +#### SRT_REJX_FORBIDDEN + +Access denied to the resource for any reason. This error is +independent of an authorization or authentication error (as reported +by `SRT_REJX_UNAUTHORIZED`). The application can decide which +is more appropriate. This error is usually intended for +a resource that should only be accessed after a successful +authorization over a separate auth-only connection, where the query +in StreamID has correctly specified the resource identity and mode, +but the session ID (in the `s` key) is either (a) not specified, or +(b) specifies a valid session, but the authorization region for this +session does not include the specified resource. + +#### SRT_REJX_NOTFOUND + +The resource specified in the `r` key (in combination with the `h` key) +is not found at this time. This error should be only reported if the +information about resource accessibility is allowed to be publicly +visible. Otherwise, the application might report authorization +errors. + +#### SRT_REJX_BAD_MODE + +The mode specified in the `m` key in StreamID is not supported for this request. +This may apply to read-only or write-only resources, as well when interactive +(bidirectional) access is not valid for a resource. + +#### SRT_REJX_UNACCEPTABLE + +Applies when the parameters specified in StreamID cannot be satisfied for the +requested resource, or when `m=publish` but the data format is not acceptable. +This is a general error reporting an unsupported format for data that appears to +be wrong when sending, or a restriction on the data format (as specified in the +details of the resource specification) such that it cannot be provided +when receiving. + +#### SRT_REJX_CONFLICT + +The resource being accessed (as specified by `r` and `h` keys) is locked for +modification. This error should only be reported for `m=publish` when the +resource being accessed is read-only because another client (not necessarily +connected through SRT): + +- is currently publishing into this resource +- has reserved this resource ID for publishing + +Note that this error should be reported when there is no other reason for +having a problem accessing the resource. + +#### SRT_REJX_NOTSUP_MEDIA + +The media type is not supported by the application. The media type is +specified in the `t` key. The currently standard types are +`stream`, `file` and `auth`. An application may extend this list, and +is not obliged to support all of the standard types. + +#### SRT_REJX_LOCKED + +The resource being accessed is locked against any access. This is similar to +`SRT_REJX_CONFLICT`, but in this case the resource is locked for reading +and writing. This is for when the resource should be shown as existing and +available to the client, but access is temporarily blocked. + +#### SRT_REJX_FAILED_DEPEND + +The dependent entity for the request is not present. In this case the +dependent entity is the session, which should be specified in the `s` +key. This means that the specified session ID is nonexistent, or it +has already expired. + +#### SRT_REJX_ISE + +Internal server error. This is for a general case when a request has +been correctly verified, with no related problems found, but an +unexpected error occurs after the processing of the request has started. + +#### SRT_REJX_UNIMPLEMENTED + +The request was correctly recognized, but the current software version +of the service (be it SRT or any other software component) doesn't +support it. This should be reported for a case where some features to +be specified in the StreamID request are supposed to be supported in a +predictable future, but the current version of the server does not +support it, or the support for this feature in this version has been +temporarily blocked. This shouldn't be reported for existing features that are +being deprecated, or older features that are no longer supported +(for this case the general `SRT_REJX_BAD_REQUEST` is more appropriate). + +#### SRT_REJX_GW + +The server acts as a gateway and the target endpoint rejected the +connection. The reason the connection was rejected is unspecified. +The gateway cannot forward the original rejection code from the +target endpoint because this would suggest the error was on the +gateway itself. Use this error with some other mechanism to report +the original target error, if possible. + +#### SRT_REJX_DOWN + +The service is down for maintenance. This can only be reported +when the service has been temporarily replaced by a stub that is only +reporting this error, while the real service is down for maintenance. + +#### SRT_REJX_VERSION + +Application version not supported. This can refer to an application feature +that is unsupported (possibly from an older SRT version), or to a feature +that is no longer supported because of backward compatibility requirements. + +#### SRT_REJX_NOROOM + +The data stream cannot be archived due to a lack of storage space. This is +reported when a request to send a file or a live stream to be archived is +unsuccessful. Note that the length of a file transmission is usually +pre-declared, so this error can be reported early. It can also be reported when +the stream is of undefined length, and there is no more storage space +available. + + +[:arrow_up:   Back to top](#srt-rejection-codes) diff --git a/docs/statistics.md b/docs/API/statistics.md similarity index 88% rename from docs/statistics.md rename to docs/API/statistics.md index 62a37bcbf..bc34ecca8 100644 --- a/docs/statistics.md +++ b/docs/API/statistics.md @@ -23,7 +23,7 @@ The following API functions can be used to retrieve statistics on an SRT socket: * `int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear)` * `int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous)` -Refer to the documentation of the [API functions](API-functions.md) for usage instructions. +Refer to the documentation of the [SRT API Functions](API-functions.md) for usage instructions. ### Summary Table @@ -32,7 +32,7 @@ The table below provides a summary of SRT socket statistics: name, type, unit of There are three types of statistics: - **Accumulated:** the statistic is accumulated since the time an SRT socket has been created (after the successful call to `srt_connect(...)` or `srt_bind(...)` function), e.g., [pktSentTotal](#pktSentTotal), etc., -- **Interval-based:** the statistic is accumulated during a specified time interval (e.g., 100 milliseconds if SRT statistics is collected each 100 milliseconds) from the time an SRT socket has been created, e.g., [pktSent](#pktSent), etc. The value of the statistic can be reset by calling the `srt_bstats(..., int clear)` function with `clear = 1`, +- **Interval-based:** the statistic is accumulated during a specified time interval (e.g., 100 milliseconds if SRT statistics is collected each 100 milliseconds) from the time an SRT socket has been created, e.g., [pktSent](#pktSent), etc. The value of the statistic can be reset by calling the `srt_bstats(..., int clear)` function with `clear = 1`, - **Instantaneous:** the statistic is obtained at the moment the `srt_bistats()` function is called, e.g., [msRTT](#msRTT), etc. See sections [Accumulated Statistics](#accumulated-statistics), [Interval-Based Statistics](#interval-based-statistics), and [Instantaneous Statistics](#instantaneous-statistics) for a detailed description of each statistic. @@ -134,19 +134,19 @@ The time elapsed, in milliseconds, since the SRT socket has been created (after The total number of sent DATA packets, including retransmitted packets ([pktRetransTotal](#pktRetransTotal)). Available for sender. -If the `SRTO_PACKETFILTER` socket option is enabled (refer to [API.md](API.md)), this statistic counts sent packet filter control packets ([pktSndFilterExtraTotal](#pktSndFilterExtraTotal)) as well. Introduced in SRT v1.4.0. +If the `SRTO_PACKETFILTER` socket option is enabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic counts sent packet filter control packets ([pktSndFilterExtraTotal](#pktSndFilterExtraTotal)) as well. Introduced in SRT v1.4.0. #### pktRecvTotal The total number of received DATA packets, including retransmitted packets ([pktRcvRetransTotal](#pktRcvRetransTotal)). Available for receiver. -If the `SRTO_PACKETFILTER` socket option is enabled (refer to [API.md](API.md)), this statistic counts received packet filter control packets ([pktRcvFilterExtraTotal](#pktRcvFilterExtraTotal)) as well. Introduced in SRT v1.4.0. +If the `SRTO_PACKETFILTER` socket option is enabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic counts received packet filter control packets ([pktRcvFilterExtraTotal](#pktRcvFilterExtraTotal)) as well. Introduced in SRT v1.4.0. -#### pktSentUniqueTotal +#### pktSentUniqueTotal -The total number of *unique* DATA packets sent by the SRT sender. Available for sender. +The total number of *unique* DATA packets sent by the SRT sender. Available for sender. -This value contains only *unique* *original* DATA packets. Retransmitted DATA packets ([pktRetransTotal](#pktRetransTotal)) are not taken into account. If the `SRTO_PACKETFILTER` socket option is enabled (refer to [API.md](https://cac-word-edit.officeapps.live.com/we/API.md)), packet filter control packets ([pktSndFilterExtraTotal](#pktSndFilterExtraTotal)) are also not taken into account. +This value contains only *unique* *original* DATA packets. Retransmitted DATA packets ([pktRetransTotal](#pktRetransTotal)) are not taken into account. If the `SRTO_PACKETFILTER` socket option is enabled (refer to [SRT API Socket Options](API-socket-options.md)), packet filter control packets ([pktSndFilterExtraTotal](#pktSndFilterExtraTotal)) are also not taken into account. This value corresponds to the number of original DATA packets sent by the SRT sender. It counts every packet sent over the network for the first time, and can be calculated as follows: `pktSentUniqueTotal = pktSentTotal – pktRetransTotal`, or by `pktSentUniqueTotal = pktSentTotal – pktRetransTotal - pktSndFilterExtraTotal` if the `SRTO_PACKETFILTER` socket option is enabled. The original DATA packets are sent only once. @@ -154,21 +154,21 @@ This value corresponds to the number of original DATA packets sent by the SRT se The total number of *unique* original, retransmitted or recovered by the packet filter DATA packets *received in time*, *decrypted without errors* and, as a result, scheduled for delivery to the upstream application by the SRT receiver. Available for receiver. -Unique means "first arrived" DATA packets. There is no difference whether a packet is original or, in case of loss, retransmitted or recovered by the packet filter. Whichever packet comes first is taken into account. +Unique means "first arrived" DATA packets. There is no difference whether a packet is original or, in case of loss, retransmitted or recovered by the packet filter. Whichever packet comes first is taken into account. This statistic doesn't count -- duplicate packets (retransmitted or sent several times by defective hardware/software), +- duplicate packets (retransmitted or sent several times by defective hardware/software), - arrived too late packets (retransmitted or original packets arrived out of order) that were already dropped by the TLPKTDROP mechanism (see [pktRcvDropTotal](#pktRcvDropTotal) statistic), - arrived in time packets, but decrypted with errors (see [pktRcvUndecryptTotal](#pktRcvUndecryptTotal) statistic), and, as a result, dropped by the TLPKTDROP mechanism (see [pktRcvDropTotal](#pktRcvDropTotal) statistic). -DATA packets recovered by the packet filter ([pktRcvFilterSupplyTotal](#pktRcvFilterSupplyTotal)) are taken into account if the `SRTO_PACKETFILTER` socket option is enabled (refer to [API.md](API.md)). Do not mix up with the control packets received by the packet filter ([pktRcvFilterExtraTotal](#pktRcvFilterExtraTotal)). +DATA packets recovered by the packet filter ([pktRcvFilterSupplyTotal](#pktRcvFilterSupplyTotal)) are taken into account if the `SRTO_PACKETFILTER` socket option is enabled (refer to [SRT API Socket Options](API-socket-options.md)). Do not mix up with the control packets received by the packet filter ([pktRcvFilterExtraTotal](#pktRcvFilterExtraTotal)). #### pktSndLossTotal The total number of data packets considered or reported as lost at the sender side. Does not correspond to the packets detected as lost at the receiver side. Available for sender. -A packet is considered lost in two cases: +A packet is considered lost in two cases: 1. Sender receives a loss report from a receiver, 2. Sender initiates retransmission after not receiving an ACK packet for a certain timeout. Refer to `FASTREXMIT` and `LATEREXMIT` algorithms. @@ -222,55 +222,59 @@ The total accumulated time in microseconds, during which the SRT sender has some #### pktSndDropTotal -The total number of _dropped_ by the SRT sender DATA packets that have no chance to be delivered in time (refer to [TLPKTDROP](https://github.com/Haivision/srt-rfc/blob/master/draft-sharabayko-mops-srt.md#too-late-packet-drop-too-late-packet-drop) mechanism). Available for sender. +The total number of _dropped_ by the SRT sender DATA packets that have no chance to be delivered in time (refer to [Too-Late Packet Drop](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-4.6) mechanism). Available for sender. -Packets may be dropped conditionally when both `SRTO_TSBPDMODE` and `SRTO_TLPKTDROP` socket options are enabled, refer to [API.md](API.md). +Packets may be dropped conditionally when both `SRTO_TSBPDMODE` and `SRTO_TLPKTDROP` socket options are enabled, refer to [SRT API Socket Options](API-socket-options.md). -The delay before TLPKTDROP mechanism is triggered is calculated as follows +The delay before TLPKTDROP mechanism is triggered is calculated as follows `SRTO_PEERLATENCY + SRTO_SNDDROPDELAY + 2 * interval between sending ACKs`, -where `SRTO_PEERLATENCY` is the configured SRT latency, `SRTO_SNDDROPDELAY` adds an extra to `SRTO_PEERLATENCY` delay, the default `interval between sending ACKs` is 10 milliseconds. The minimum delay is `1000 + 2 * interval between sending ACKs` milliseconds. Refer to `SRTO_PEERLATENCY`, `SRTO_SNDDROPDELAY` socket options in [API.md](API.md). +where `SRTO_PEERLATENCY` is the configured SRT latency, `SRTO_SNDDROPDELAY` adds an extra to `SRTO_PEERLATENCY` delay, the default `interval between sending ACKs` is 10 milliseconds. The minimum delay is `1000 + 2 * interval between sending ACKs` milliseconds. Refer to `SRTO_PEERLATENCY`, `SRTO_SNDDROPDELAY` socket options in [SRT API Socket Options](API-socket-options.md). #### pktRcvDropTotal -The total number of _dropped_ by the SRT receiver and, as a result, not delivered to the upstream application DATA packets (refer to [TLPKTDROP](https://github.com/Haivision/srt-rfc/blob/master/draft-sharabayko-mops-srt.md#too-late-packet-drop-too-late-packet-drop) mechanism). Available for receiver. +The total number of _dropped_ by the SRT receiver and, as a result, not delivered to the upstream application DATA packets (refer to [Too-Late Packet Drop](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-4.6) mechanism). Available for receiver. This statistic counts + +- not arrived packets including those signalled for dropping by the sender, that were dropped in favor of the subsequent existing packets, - arrived too late packets (retransmitted or original packets arrived out of order), - arrived in time packets, but decrypted with errors (see also [pktRcvUndecryptTotal](#pktRcvUndecryptTotal) statistic). -Packets may be dropped conditionally when both `SRTO_TSBPDMODE` and `SRTO_TLPKTDROP` socket options are enabled, refer to [API.md](API.md). +Packets may be dropped conditionally when both `SRTO_TSBPDMODE` and `SRTO_TLPKTDROP` socket options are enabled, refer to [SRT API Socket Options](API-socket-options.md). #### pktRcvUndecryptTotal The total number of packets that failed to be decrypted at the receiver side. Available for receiver. +The statistic also counts unencrypted packets that were expected to be uncrypted on a secured connection (see [SRTO_KM_S_SECURED](API-socket-options.md#srt_km_state)) +and hence dropped as not encrypted (undecrypted). #### pktSndFilterExtraTotal -The total number of packet filter control packets generated by the packet filter (refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md)). Available for sender. +The total number of packet filter control packets generated by the packet filter (refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md)). Available for sender. Packet filter control packets contain only control information necessary for the packet filter. The type of these packets is DATA. -If the `SRTO_PACKETFILTER` socket option is disabled (refer to [API.md](API.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. +If the `SRTO_PACKETFILTER` socket option is disabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. #### pktRcvFilterExtraTotal -The total number of packet filter control packets received by the packet filter (refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md)). Available for receiver. +The total number of packet filter control packets received by the packet filter (refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md)). Available for receiver. Packet filter control packets contain only control information necessary for the packet filter. The type of these packets is DATA. -If the `SRTO_PACKETFILTER` socket option is disabled (refer to [API.md](API.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. +If the `SRTO_PACKETFILTER` socket option is disabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. #### pktRcvFilterSupplyTotal -The total number of lost DATA packets recovered by the packet filter at the receiver side (e.g., FEC rebuilt packets; refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md)). Available for receiver. +The total number of lost DATA packets recovered by the packet filter at the receiver side (e.g., FEC rebuilt packets; refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md)). Available for receiver. -If the `SRTO_PACKETFILTER` socket option is disabled (refer to [API.md](API.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. +If the `SRTO_PACKETFILTER` socket option is disabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. #### pktRcvFilterLossTotal -The total number of lost DATA packets **not** recovered by the packet filter at the receiver side (refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md)). Available for receiver. +The total number of lost DATA packets **not** recovered by the packet filter at the receiver side (refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md)). Available for receiver. -If the `SRTO_PACKETFILTER` socket option is disabled (refer to [API.md](API.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. +If the `SRTO_PACKETFILTER` socket option is disabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic is equal to 0. Introduced in SRT v1.4.0. #### byteSentTotal @@ -363,25 +367,25 @@ Same as [pktRecvNAKTotal](#pktRecvNAKTotal), but for a specified interval. Same as [pktSndFilterExtraTotal](#pktSndFilterExtraTotal), but for a specified interval. -Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md). +Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md). #### pktRcvFilterExtra Same as [pktRcvFilterExtraTotal](#pktRcvFilterExtraTotal), but for a specified interval. -Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md). +Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md). #### pktRcvFilterSupply Same as [pktRcvFilterSupplyTotal](#pktRcvFilterSupplyTotal), but for a specified interval. -Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md). +Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md). #### pktRcvFilterLoss Same as [pktRcvFilterLossTotal](#pktRcvFilterLossTotal), but for a specified interval. -Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](packet-filtering-and-fec.md). +Introduced in v1.4.0. Refer to [SRT Packet Filtering & FEC](../features/packet-filtering-and-fec.md). #### mbpsSendRate @@ -408,9 +412,9 @@ The number of packets received but IGNORED due to having arrived too late. Makes sense only if TSBPD and TLPKTDROP are enabled. -An offset between sequence numbers of the newly arrived DATA packet and latest +An offset between sequence numbers of the newly arrived DATA packet and latest acknowledged DATA packet is calculated. -If the offset is negative, the packet is considered late, meaning that it was +If the offset is negative, the packet is considered late, meaning that it was either already acknowledged or dropped by TSBPD as too late to be delivered. Retransmitted packets can also be considered late. @@ -468,7 +472,7 @@ Same as [byteRcvUndecryptTotal](#byteRcvUndecryptTotal), but for a specified int #### usPktSndPeriod -Current minimum time interval between which consecutive packets are sent, in +Current minimum time interval between which consecutive packets are sent, in microseconds. Sender only. Note that several sockets sharing one outgoing port use the same sending queue. @@ -477,8 +481,8 @@ be placed in the same sending queue, which may affect the send timing. `usPktSndPeriod` is the minimum time (sending period) that must be kept between two packets sent consecutively over the link used by an SRT socket. -It is not the EXACT time interval between two consecutive packets. In the case where the time spent by an -application between sending two consecutive packets exceeds `usPktSndPeriod`, the next +It is not the EXACT time interval between two consecutive packets. In the case where the time spent by an +application between sending two consecutive packets exceeds `usPktSndPeriod`, the next packet will be sent faster, or even immediately, to preserve the average sending rate. **Note**: Does not apply to probing packets. @@ -520,8 +524,8 @@ The number of packets in flight. Sender only. `pktFlightSize <= pktFlowWindow` and `pktFlightSize <= pktCongestionWindow` -This is the distance -between the packet sequence number that was last reported by an ACK message and +This is the distance +between the packet sequence number that was last reported by an ACK message and the sequence number of the latest packet sent (at the moment when the statistics are being read). @@ -539,21 +543,10 @@ at that moment. #### msRTT -Calculated Round trip time (RTT), in milliseconds. Sender and Receiver. \ -The value is calculated by the receiver based on the incoming ACKACK control packets -(used by sender to acknowledge ACKs from receiver). - -The RTT (Round-Trip time) is the sum of two STT (Single-Trip time) -values, one from agent to peer, and one from peer to agent. Note that **the -measurement method is different than in TCP**. SRT measures only the "reverse -RTT", that is, the time measured at the receiver between sending a `UMSG_ACK` -message until receiving the sender's `UMSG_ACKACK` response message (with the -same journal). This happens to be a little different from the "forward RTT" -measured in TCP, which is the time between sending a data packet of a particular -sequence number and receiving `UMSG_ACK` with a sequence number that is later -by 1. Forward RTT isn't being measured or reported in SRT, although some -research works have shown that these values, even though they should be the same, -happen to differ; "reverse RTT" seems to be more optimistic. +Smoothed round-trip time (SRTT), an exponentially-weighted moving average (EWMA) of an endpoint's RTT samples, in milliseconds. +Available both for sender and receiver. + +See [Section 4.10. Round-Trip Time Estimation](https://tools.ietf.org/html/draft-sharabayko-srt-01#section-4.10) of the [Internet Draft](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01) and [[RFC6298] Paxson, V., Allman, M., Chu, J., and M. Sargent, "Computing TCP's Retransmission Timer"](https://datatracker.ietf.org/doc/html/rfc6298) for more details. #### mbpsBandwidth @@ -571,8 +564,8 @@ The receiver then sends back a running average calculation to the sender with an The available space in the sender's buffer, in bytes. Sender only. -This value decreases with data scheduled for sending by the application, and increases -with every ACK received from the receiver, after the packets are sent over +This value decreases with data scheduled for sending by the application, and increases +with every ACK received from the receiver, after the packets are sent over the UDP link. #### byteAvailRcvBuf @@ -586,13 +579,13 @@ from the sender over the UDP link. #### mbpsMaxBW Transmission bandwidth limit, in Mbps. Sender only. -Usually this is the setting from -the `SRTO_MAXBW` option, which may include the value 0 (unlimited). Under certain -conditions a nonzero value might be be provided by a congestion -control module, although none of the built-in congestion control modules +Usually this is the setting from +the `SRTO_MAXBW` option, which may include the value 0 (unlimited). Under certain +conditions a nonzero value might be be provided by a congestion +control module, although none of the built-in congestion control modules currently use it. -Refer to `SRTO_MAXBW` and `SRTO_INPUTBW` in [API.md](API.md). +Refer to `SRTO_MAXBW` and `SRTO_INPUTBW` in [SRT API Socket Options](API-socket-options.md). #### byteMSS @@ -602,11 +595,11 @@ Should not exceed the size of the maximum transmission unit (MTU), in bytes. Sen The default size of the UDP packet used for transport, including all possible headers (Ethernet, IP and UDP), is 1500 bytes. -Refer to `SRTO_MSS` in [API.md](API.md). +Refer to `SRTO_MSS` in [SRT API Socket Options](API-socket-options.md). #### pktSndBuf -The number of packets in the sender's buffer that are already +The number of packets in the sender's buffer that are already scheduled for sending or even possibly sent, but not yet acknowledged. Sender only. @@ -638,7 +631,7 @@ The current state is returned if `srt_bistats(...)` is called with `instantaneou #### msSndTsbPdDelay Timestamp-based Packet Delivery Delay value of the peer. -If `SRTO_TSBPDMODE` is on (default for **live mode**), it +If `SRTO_TSBPDMODE` is on (default for **live mode**), it returns the value of `SRTO_PEERLATENCY`, otherwise 0. The sender reports the TSBPD delay value of the receiver. The receiver reports the TSBPD delay of the sender. @@ -666,7 +659,7 @@ The timespan (msec) of acknowledged packets in the receiver's buffer. Receiver s If TSBPD mode is enabled (defualt for **live mode**), a packet can be acknowledged, but not yet ready to play. -This range includes all packets regardless of whether +This range includes all packets regardless of whether they are ready to play or not. A moving average value is reported when the value is retrieved by calling @@ -719,20 +712,15 @@ The packet with sequence number 9 is reported lost. #### pktRcvAvgBelatedTime -Accumulated difference between the current time and the time-to-play of a packet +Accumulated difference between the current time and the time-to-play of a packet that is received late. ## SRT Group Statistics -SRT group statistics are implemented for SRT Connection Bonding feature and available since SRT v1.5.0. Check the following documentation and code examples for details: +SRT group statistics are implemented for [SRT Connection Bonding](../features/bonding-quick-start.md) feature and available since SRT v1.5.0. -- [Introduction in SRT Connection Bonding feature](https://github.com/Haivision/srt/blob/master/docs/bonding-intro.md), -- [The concept of socket groups](https://github.com/Haivision/srt/blob/master/docs/socket-groups.md). Here you will also find the information regarding `srt-test-live` application for testing Connection Bonding, -- Check also [API](https://github.com/Haivision/srt/blob/master/docs/API.md) and [API functions](https://github.com/Haivision/srt/blob/master/docs/API-functions.md) documentation for Connection Bonding related updates, -- Code examples: simple [client](https://github.com/Haivision/srt/blob/master/examples/test-c-client-bonding.c) and [server](https://github.com/Haivision/srt/blob/master/examples/test-c-server-bonding.c) implementation. - -`srt_bistats(SRTSOCKET u, ...)` function can be used with a socket group ID as a first argument to get statistics for a group. Most values of the `SRT_TRACEBSTATS` will be filled with zeros except for the fields listed in [Summary Table](#group-summary-table) below. Refer to the documentation of the [API functions](API-functions.md) for usage instructions. +The `srt_bistats(SRTSOCKET u, ...)` function can be used with a socket group ID as the first argument to get statistics for a group. `SRT_TRACEBSTATS` values will mostly be zeros, except for the fields listed in the [Summary Table](#group-summary-table) below. Refer to the [SRT API Functions](../API/API-functions.md#socket-group-management) documentation for usage instructions. ### Summary Table @@ -758,7 +746,7 @@ The table below provides a summary of SRT group statistics: name, type, unit of #### msTimeStamp -The time elapsed, in milliseconds, since the time ("connection" time) when the initial group connection has been initiated (the time when the first connection in the group has been made and therefore made the group connected). This "connection" time will be then set in this statistic in every next socket that will become a member of the group as the new connections are established. A new connection to an already connected group doesn’t change the value of "connection" time. Available both for sender and receiver. +The time elapsed, in milliseconds, since the time ("connection" time) when the initial group connection has been initiated (the time when the first connection in the group has been made and therefore made the group connected). This "connection" time will be then set in this statistic in every next socket that will become a member of the group as the new connections are established. A new connection to an already connected group doesn’t change the value of "connection" time. Available both for sender and receiver. #### pktSentUniqueTotal @@ -768,7 +756,7 @@ This value counts every *original* DATA packet sent over the network for the fir This statistic does not count retransmitted DATA packets that are individual per socket connection within the group. See the corresponding [pktRetransTotal](#pktRetransTotal) socket statistic. -If the `SRTO_PACKETFILTER` socket option is enabled (refer to [API.md](API.md)), this statistic does not count packet filter control packets that are individual per socket connection within the group. See the corresponding [pktSndFilterExtraTotal](#pktSndFilterExtraTotal) socket statistic. +If the `SRTO_PACKETFILTER` socket option is enabled (refer to [SRT API Socket Options](API-socket-options.md)), this statistic does not count packet filter control packets that are individual per socket connection within the group. See the corresponding [pktSndFilterExtraTotal](#pktSndFilterExtraTotal) socket statistic. #### pktRecvUniqueTotal @@ -835,5 +823,5 @@ The ratio of unrecovered by the socket group packets `Dropped Packets Ratio` can ``` Dropped Packets Ratio = pktRcvDropTotal / pktSentUniqueTotal; in case both sender and receiver statistics is available -Dropped Packets Ratio = pktRcvDropTotal / (pktRecvUniqueTotal + pktRcvDropTotal); in case receiver only statistics is available -``` \ No newline at end of file +Dropped Packets Ratio = pktRcvDropTotal / (pktRecvUniqueTotal + pktRcvDropTotal); in case receiver only statistics is available +``` diff --git a/docs/APISocketOptions.md b/docs/APISocketOptions.md deleted file mode 100644 index 82da159cf..000000000 --- a/docs/APISocketOptions.md +++ /dev/null @@ -1,1466 +0,0 @@ -# SRT Socket Options - -There is a general method of setting options on a socket in the SRT C API, similar -to the system `setsockopt/getsockopt` functions. - -**NOTE**: This document replaces the socket option description originally -in [api.md](https://github.com/Haivision/srt/blob/master/docs/API.md) - -**Sections:** - -- [Types used in socket options](#types-used-in-socket-options) -- [Getting and setting options](#getting-and-setting-options) -- [List of options](#list-of-options) - -## Types used in socket options - -Possible types of socket options are: - -- `int32_t` - This type can usually be treated as an `int` equivalent since it -does not change size on 64-bit systems. For clarity, options use this fixed size -integer. In some cases the value is expressed using an enumeration type (see below). - -- `int64_t` - Some options need the parameter specified as 64-bit integer - -- `bool` - Requires the use of a boolean type (`` for C, or built-in -for C++). When *setting* an option, passing the value through an `int` type is -also properly recognized. When *getting* an option, however, you should use the -`bool` type, although you can risk passing a variable of `int` type initialized -with 0 and then checking if the resulting value is equal to 0 (just don't compare -the result with 1). - -- `string` - When *setting* an option, pass the character array pointer as value -and the string length as length. When *getting*, pass an array of sufficient size -(as specified in the size variable). Every option with this type that can be -read should specify the maximum length of that array. - -- `linger` - Linger structure. Used exclusively with `SRTO_LINGER`. - -### Enumeration types used in options - -#### `SRT_TRANSTYPE` - -Used by `SRTO_TRANSTYPE` option: - -- `SRTT_LIVE`: Live mode. -- `SRTT_FILE`: File mode. - -See [Transmission types](./API.md#transmission-types) for details. - -#### `SRT_KM_STATE` - -The defined encryption state as performed by the Key Material Exchange, used -by `SRTO_RCVKMSTATE`, `SRTO_SNDKMSTATE` and `SRTO_KMSTATE` options: - -- `SRT_KM_S_UNSECURED`: no encryption/decryption. If this state is only on -the receiver, received encrypted packets will be dropped. - -- `SRT_KM_S_SECURING`: pending security (HSv4 only). This is a temporary state -used only if the connection uses HSv4 and the Key Material Exchange is -not finished yet. On HSv5 this is not possible because the Key Material -Exchange for the initial key is done in the handshake. - -- `SRT_KM_S_SECURED`: KM exchange was successful and the data will be sent -encrypted and will be decrypted by the receiver. This state is only possible on -both sides in both directions simultaneously. - -- `SRT_KM_S_NOSECRET`: If this state is in the sending direction (`SRTO_SNDKMSTATE`), -then it means that the sending party has set a passphrase, but the peer did not. -In this case the sending party can receive unencrypted packets from the peer, but -packets it sends to the peer will be encrypted and the peer will not be able to -decrypt them. This state is only possible in HSv5. - -- `SRT_KM_S_BADSECRET`: The password is wrong (set differently on each party); -encrypted payloads won't be decrypted in either direction. - -Note that with the default value of `SRTO_ENFORCEDENCRYPTION` option (true), -the state is equal on both sides in both directions, and it can be only -`SRT_KM_S_UNSECURED` or `SRT_KM_S_SECURED` (in other cases the connection -is rejected). Otherwise it may happen that either both sides have different -passwords and the state is `SRT_KM_S_BADSECRET` in both directions, or only -one party has set a password, in which case the KM state is as follows: - -| | `SRTO_RCVKMSTATE` | `SRTO_SNDKMSTATE` | -|--------------------------|----------------------|----------------------| -| Party with no password: | `SRT_KM_S_NOSECRET` | `SRT_KM_S_UNSECURED` | -| Party with password: | `SRT_KM_S_UNSECURED` | `SRT_KM_S_NOSECRET` | - -## Getting and setting options - -Legacy version: - - int srt_getsockopt(SRTSOCKET socket, int level, SRT_SOCKOPT optName, void* optval, int& optlen); - int srt_setsockopt(SRTSOCKET socket, int level, SRT_SOCKOPT optName, const void* optval, int optlen); - -New version: - - int srt_getsockflag(SRTSOCKET socket, SRT_SOCKOPT optName, void* optval, int& optlen); - int srt_setsockflag(SRTSOCKET socket, SRT_SOCKOPT optName, const void* optval, int optlen); - -In the legacy version, there's an additional unused `level` parameter. It was -there in the original UDT API just to mimic the system `setsockopt` function, -but it's ignored. - -Some options require a value of type `bool` while others require type `integer`, -which is not the same -- they differ in size, and mistaking them may end up -causing a crash. This must be kept in mind especially in any C wrapper. For -convenience, the *setting* option function may accept both `int32_t` and `bool` -types, but this is not so in the case of *getting* an option value. - -**UDT project legacy note**: Almost all options from the UDT library are -derived (there are a few deleted, including some deprecated already in UDT). -Many new SRT options have been added. All options are available exclusively -with the `SRTO_` prefix. Old names are provided as alias names in the `udt.h` -legacy/C++ API file. Note the translation rules: - -* `UDT_` prefix from UDT options was changed to the prefix `SRTO_` -* `UDP_` prefix from UDT options was changed to the prefix `SRTO_UDP_` -* `SRT_` prefix in older SRT versions was changed to `SRTO_` - -The [table below](#list-of-options) provides a complete list of SRT options and -their characteristics according to the following legend: - -1. **Since**: Defines the SRT version when this option was first introduced. If this field -is empty, it's an option derived from UDT. "Version 0.0.0" is the oldest version -of SRT ever created and put into use. - -2. **Binding**: Defines limitation on setting the option. The field is empty if the option -is not settable (see **Dir** column): - - - `pre`: A connecting socket (both as caller and rendezvous) must be set -prior to calling `srt_connect()` or `srt_bind()` and never changed thereafter. -A listener socket should be set to "listening" and it will be -derived by every socket returned by `srt_accept()`. - - - `post`: This flag can be changed any time, including after the socket is -connected (as well as on an accepted socket). Setting this flag on a listening -socket is effective only on that socket itself. Note though that there are some -post-bound options that have important meaning when set prior to connecting. - -3. **Type**: The data type of the option (see above). - -4. **Units**: Roughly specified unit, if the value defines things like length or time. -It can also define more precisely what kind of specialization can be used -when the type is integer: - - - `enum`: the possible values are defined in an enumeration type - - `flags`: the integer value is a collection of bit flags - - `B/s` - bytes per second. - -5. **Default**: The exact default value, if it can be easily specified. A more complicated -default state of a particular option will be explained in the [description](#option-descriptions) -(when marked by asterisk). For non-settable options this field is empty. - -6. **Range**: If a value of an integer type has a limited range, or only a certain value -allowed, it will be specified here (otherwise empty). A range value can be -specified as: - - - `X-... `: specifies only a minimum value - - `X-Y,Z `: values between X and Y are allowed, and additionally Z - - - If the value is of `string` type, this field will contain its maximum size -in square brackets. - - - If the range contains additionally an asterisk, it means that more elaborate -restrictions on the value apply, as explained in the [description](#option-descriptions). - -7. **Dir**: Option direction: W if can be set, R if can be retrieved, RW if both. - -8. **Entity**: This describes whether the option can be set on the socket or the group. -The G and S options may appear together, in which case both possibilities apply. -The D and I options, mutually exclusive, appear always with G. -The + marker can only coexist with GS. Possible specifications are: - - - S: This option can be set on a single socket (exclusively, if not GS) - - - G: This option can be set on a group (exclusively, if not GS) - - - D: If set on a group, it will be derived by the member socket - - - I: If set on a group, it will be taken and managed exclusively by the group - - - +: This option is also allowed to be set individually on a group member - socket through a configuration object in `SRT_SOCKGROUPCONFIG` prepared by - `srt_create_config`. Note that this setting may override the setting derived - from the group. - -## List of options - -The following table lists SRT socket options in alphabetical order. Option details are given further below. - -| Option Name | Since | Binding | Type | Units | Default | Range | Dir |Entity | -| :----------------------------------------------------- | :---: | :-----: | :-------: | :-----: | :-----------: | :------: |:---:|:-----:| -| [`SRTO_BINDTODEVICE`](#SRTO_BINDTODEVICE) | 1.4.2 | pre | `string` | | | | RW | GSD+ | -| [`SRTO_CONGESTION`](#SRTO_CONGESTION) | 1.3.0 | pre | `string` | | "live" | * | W | S | -| [`SRTO_CONNTIMEO`](#SRTO_CONNTIMEO) | 1.1.2 | pre | `int32_t` | ms | 3000 | 0.. | W | GSD+ | -| [`SRTO_DRIFTTRACER`](#SRTO_DRIFTTRACER) | 1.4.2 | post | `bool` | | true | | RW | GSD | -| [`SRTO_ENFORCEDENCRYPTION`](#SRTO_ENFORCEDENCRYPTION) | 1.3.2 | pre | `bool` | | true | | W | GSD | -| [`SRTO_EVENT`](#SRTO_EVENT) | | | `int32_t` | flags | | | R | S | -| [`SRTO_FC`](#SRTO_FC) | | pre | `int32_t` | pkts | 25600 | 32.. | RW | GSD | -| [`SRTO_GROUPCONNECT`](#SRTO_GROUPCONNECT) | 1.5.0 | pre | `int32_t` | | 0 | 0...1 | W | S | -| [`SRTO_GROUPSTABTIMEO`](#SRTO_GROUPSTABTIMEO) | 1.5.0 | pre | `int32_t` | ms | 80 | 10-... | W | GSD+ | -| [`SRTO_GROUPTYPE`](#SRTO_GROUPTYPE) | 1.5.0 | pre | `int32_t` | enum | | | R | S | -| [`SRTO_INPUTBW`](#SRTO_INPUTBW) | 1.0.5 | post | `int64_t` | B/s | 0 | 0.. | RW | GSD | -| [`SRTO_IPTOS`](#SRTO_IPTOS) | 1.0.5 | pre | `int32_t` | | (system) | 0..255 | RW | GSD | -| [`SRTO_IPTTL`](#SRTO_IPTTL) | 1.0.5 | pre | `int32_t` | hops | (system) | 1..255 | RW | GSD | -| [`SRTO_IPV6ONLY`](#SRTO_IPV6ONLY) | 1.4.0 | pre | `int32_t` | | (system) | -1..1 | RW | GSD | -| [`SRTO_ISN`](#SRTO_ISN) | 1.3.0 | | `int32_t` | | | | R | S | -| [`SRTO_KMPREANNOUNCE`](#SRTO_KMPREANNOUNCE) | 1.3.2 | pre | `int32_t` | pkts | 0x1000 | 0.. * | RW | GSD | -| [`SRTO_KMREFRESHRATE`](#SRTO_KMREFRESHRATE) | 1.3.2 | pre | `int32_t` | pkts | 0x1000000 | 0.. | RW | GSD | -| [`SRTO_KMSTATE`](#SRTO_KMSTATE) | 1.0.2 | | `int32_t` | enum | | | R | S | -| [`SRTO_LATENCY`](#SRTO_LATENCY) | 1.0.2 | pre | `int32_t` | ms | 120 * | 0.. | RW | GSD | -| [`SRTO_LINGER`](#SRTO_LINGER) | | pre | `linger` | s | on, 180 | 0.. | RW | GSD | -| [`SRTO_LOSSMAXTTL`](#SRTO_LOSSMAXTTL) | 1.2.0 | pre | `int32_t` | packets | 0 | 0.. | RW | GSD+ | -| [`SRTO_MAXBW`](#SRTO_MAXBW) | 1.0.5 | pre | `int64_t` | B/s | -1 | -1.. | RW | GSD | -| [`SRTO_MESSAGEAPI`](#SRTO_MESSAGEAPI) | 1.3.0 | pre | `bool` | | true | | W | GSD | -| [`SRTO_MINVERSION`](#SRTO_MINVERSION) | 1.3.0 | pre | `int32_t` | version | 0 | * | W | GSD | -| [`SRTO_MSS`](#SRTO_MSS) | | pre | `int32_t` | bytes | 1500 | 76.. | RW | GSD | -| [`SRTO_NAKREPORT`](#SRTO_NAKREPORT) | 1.1.0 | pre | `bool` | | * | | RW | GSD+ | -| [`SRTO_OHEADBW`](#SRTO_OHEADBW) | 1.0.5 | post | `int32_t` | % | 25 | 5..100 | RW | GSD | -| [`SRTO_PACKETFILTER`](#SRTO_PACKETFILTER) | 1.4.0 | pre | `string` | | "" | [512] | W | GSD | -| [`SRTO_PASSPHRASE`](#SRTO_PASSPHRASE) | 0.0.0 | pre | `string` | | "" | [10..79] | W | GSD | -| [`SRTO_PAYLOADSIZE`](#SRTO_PAYLOADSIZE) | 1.3.0 | pre | `int32_t` | bytes | \* | \* | W | GSD | -| [`SRTO_PBKEYLEN`](#SRTO_PBKEYLEN) | 0.0.0 | pre | `int32_t` | bytes | 0 | * | RW | GSD | -| [`SRTO_PEERIDLETIMEO`](#SRTO_PEERIDLETIMEO) | 1.3.3 | pre | `int32_t` | ms | 5000 | 0.. | RW | GSD+ | -| [`SRTO_PEERLATENCY`](#SRTO_PEERLATENCY) | 1.3.0 | pre | `int32_t` | ms | 0 | 0.. | RW | GSD | -| [`SRTO_PEERVERSION`](#SRTO_PEERVERSION) | 1.1.0 | | `int32_t` | * | | | R | GS | -| [`SRTO_RCVBUF`](#SRTO_RCVBUF) | | pre | `int32_t` | bytes | 8192 payloads | * | RW | GSD+ | -| [`SRTO_RCVDATA`](#SRTO_RCVDATA) | | | `int32_t` | pkts | | | R | S | -| [`SRTO_RCVKMSTATE`](#SRTO_RCVKMSTATE) | 1.2.0 | | `int32_t` | enum | | | R | S | -| [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY) | 1.3.0 | pre | `int32_t` | msec | * | 0.. | RW | GSD | -| [`SRTO_RCVSYN`](#SRTO_RCVSYN) | | post | `bool` | | true | | RW | GSI | -| [`SRTO_RCVTIMEO`](#SRTO_RCVTIMEO) | | post | `int32_t` | ms | -1 | -1, 0.. | RW | GSI | -| [`SRTO_RENDEZVOUS`](#SRTO_RENDEZVOUS) | | pre | `bool` | | false | | RW | S | -| [`SRTO_RETRANSMITALGO`](#SRTO_RETRANSMITALGO) | 1.4.2 | pre | `int32_t` | | 0 | [0, 1] | RW | GSD | -| [`SRTO_REUSEADDR`](#SRTO_REUSEADDR) | | pre | `bool` | | true | | RW | GSD | -| [`SRTO_SENDER`](#SRTO_SENDER) | 1.0.4 | pre | `bool` | | false | | W | S | -| [`SRTO_SNDBUF`](#SRTO_SNDBUF) | | pre | `int32_t` | bytes | 8192 payloads | * | RW | GSD+ | -| [`SRTO_SNDDATA`](#SRTO_SNDDATA) | | | `int32_t` | pkts | | | R | S | -| [`SRTO_SNDDROPDELAY`](#SRTO_SNDDROPDELAY) | 1.3.2 | pre | `int32_t` | ms | * | -1.. | W | GSD+ | -| [`SRTO_SNDKMSTATE`](#SRTO_SNDKMSTATE) | 1.2.0 | post | `int32_t` | enum | | | R | S | -| [`SRTO_SNDSYN`](#SRTO_SNDSYN) | | post | `bool` | | true | | RW | GSI | -| [`SRTO_SNDTIMEO`](#SRTO_SNDTIMEO) | | post | `int32_t` | ms | -1 | -1.. | RW | GSI | -| [`SRTO_STATE`](#SRTO_STATE) | | | `int32_t` | enum | | | R | S | -| [`SRTO_STREAMID`](#SRTO_STREAMID) | 1.3.0 | pre | `string` | | "" | [512] | RW | GSD | -| [`SRTO_TLPKTDROP`](#SRTO_TLPKTDROP) | 1.0.6 | pre | `bool` | | * | | RW | GSD | -| [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) | 1.3.0 | pre | `int32_t` | enum |`SRTT_LIVE` | * | W | S | -| [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE) | 0.0.0 | pre | `bool` | | * | | W | S | -| [`SRTO_UDP_RCVBUF`](#SRTO_UDP_RCVBUF) | | pre | `int32_t` | bytes | 8192 payloads | * | RW | GSD+ | -| [`SRTO_UDP_SNDBUF`](#SRTO_UDP_SNDBUF) | | pre | `int32_t` | bytes | 65536 | * | RW | GSD+ | -| [`SRTO_VERSION`](#SRTO_VERSION) | 1.1.0 | | `int32_t` | | | | R | S | - -### Option Descriptions - -#### SRTO_BINDTODEVICE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir |Entity| -| --------------------- | ----- | ------- | -------- | ------ | -------- | ------ |-----|------| -| `SRTO_BINDTODEVICE` | 1.4.2 | pre | `string` | | | | RW | GSD+ | - -Refers to the `SO_BINDTODEVICE` system socket option for `SOL_SOCKET` level. -This effectively limits the packets received by this socket to only those -that are targeted to that device. The device is specified by name passed as -string. The setting becomes effective after binding the socket (including -default-binding when connecting). - -NOTE: This option is only available on Linux and available there by default. -On all other platforms setting this option will always fail. - -NOTE: With the default system configuration, this option is only available -for a process that runs as root. Otherwise the function that applies the setting -(`srt_bind`, `srt_connect` etc.) will fail. - -[Return to list](#list-of-options) - ---- - -#### SRTO_CONGESTION - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_CONGESTION` | 1.3.0 | pre | `string` | | "live" | * | W | S | - -The type of congestion controller used for the transmission for that socket. - -Its type must be exactly the same on both connecting parties, otherwise the -connection is rejected - **however** you may also change the value of this -option for the accepted socket in the listener callback (see `srt_listen_callback`) -if an appropriate instruction was given in the Stream ID. - -Currently supported congestion controllers are designated as "live" and "file" - -Note that it is not recommended to change this option manually, but you should -rather change the whole set of options using the [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) option. - -[Return to list](#list-of-options) - ---- - -#### SRTO_CONNTIMEO - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ------------------ | ----- | ------- | --------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_CONNTIMEO` | 1.1.2 | pre | `int32_t` | msec | 3000 | 0.. | W | GSD+ | - -Connect timeout. This option applies to the caller and rendezvous connection -modes. For the rendezvous mode (see `SRTO_RENDEZVOUS`) the effective connection timeout -will be 10 times the value set with `SRTO_CONNTIMEO`. - -[Return to list](#list-of-options) - ---- - -#### SRTO_DRIFTTRACER - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | --------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_DRIFTTRACER`| 1.4.2 | post | `bool` | | true | | RW | GSD | - -Enables or disables time drift tracer (receiver). - -[Return to list](#list-of-options) - ---- - -#### SRTO_ENFORCEDENCRYPTION - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_ENFORCEDENCRYPTION` | 1.3.2 | pre | `bool` | | true | | W | GSD | - -This option enforces that both connection parties have the same passphrase -set, or both do not set the passphrase, otherwise the connection is rejected. - -When this option is set to FALSE **on both connection parties**, the -connection is allowed even if the passphrase differs on both parties, -or it was set only on one party. Note that the party that has set a passphrase -is still allowed to send data over the network. However, the receiver will not -be able to decrypt that data and will not deliver it to the application. The -party that has set no passphrase can send (unencrypted) data that will be -successfully received by its peer. - -This option can be used in some specific situations when the user knows -both parties of the connection, so there's no possible situation of a rogue -sender and can be useful in situations where it is important to know whether a -connection is possible. The inability to decrypt an incoming transmission can -be then reported as a different kind of problem. - -**IMPORTANT**: There is unusual and unobvious behavior when this flag is TRUE -on the caller and FALSE on the listener, and the passphrase was mismatched. On -the listener side the connection will be established and broken right after, -resulting in a short-lived "spurious" connection report on the listener socket. -This way, a socket will be available for retrieval from an `srt_accept` call -for a very short time, after which it will be removed from the listener backlog -just as if no connection attempt was made at all. If the application is fast -enough to react on an incoming connection, it will retrieve it, only to learn -that it is already broken. This also makes possible a scenario where -`SRT_EPOLL_IN` is reported on a listener socket, but then an `srt_accept` call -reports an `SRT_EASYNCRCV` error. How fast the connection gets broken depends -on the network parameters -- in particular, whether the `UMSG_SHUTDOWN` message -sent by the caller is delivered (which takes one RTT in this case) or missed -during the interval from its creation up to the connection timeout (default = 5 -seconds). It is therefore strongly recommended that you only set this flag to -FALSE on the listener when you are able to ensure that it is also set to FALSE -on the caller side. - -[Return to list](#list-of-options) - ---- - -#### SRTO_EVENT - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | --------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_EVENT` | | | `int32_t` | flags | | | R | S | - -Returns bit flags set according to the current active events on the socket. - -Possible values are those defined in `SRT_EPOLL_OPT` enum (a combination of -`SRT_EPOLL_IN`, `SRT_EPOLL_OUT` and `SRT_EPOLL_ERR`). - -[Return to list](#list-of-options) - ---- - -#### SRTO_FC - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | --------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_FC` | | pre | `int32_t` | pkts | 25600 | 32.. | RW | GSD | - -Flight Flag Size (maximum number of bytes that can be sent without -being acknowledged) - -[Return to list](#list-of-options) - ---- - -#### SRTO_GROUPCONNECT - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | --------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_GROUPCONNECT` | 1.5.0 | pre | `int32_t` | | 0 | 0...1 | W | S | - -When this flag is set to 1 on a listener socket, it allows this socket to -accept group connections. When set to the default 0, group connections will be -rejected. Keep in mind that if the `SRTO_GROUPCONNECT` flag is set to 1 (i.e. -group connections are allowed) `srt_accept` may return a socket **or** a group -ID. A call to `srt_accept` on a listener socket that has group connections -allowed must take this into consideration. It's up to the caller of this -function to make this distinction and to take appropriate action depending on -the type of entity returned. - -When this flag is set to 1 on an accepted socket that is passed to the -listener callback handler, it means that this socket is created for a group -connection and it will become a member of a group. Note that in this case -only the first connection within the group will result in reporting from -`srt_accept` (further connections are handled in the background), and this -function will return the group, not this socket ID. - -[Return to list](#list-of-options) - ---- - -#### SRTO_GROUPSTABTIMEO - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| --------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_GROUPSTABTIMEO` | 1.5.0 | pre | `int32_t` | ms | 80 | 10-... | W | GSD+ | - -This setting is used for groups of type `SRT_GTYPE_BACKUP`. It defines the stability -timeout, which is the maximum interval between two consecutive packets retrieved from -the peer on the currently active link. These two packets can be of any type, -but this setting usually refers to control packets while the agent is a sender. -Idle links exchange only keepalive messages once per second, so they do not -count. Note that this option is meaningless on sockets that are not members of -the Backup-type group. - -This value should be set with a thoroughly selected balance and correspond to -the maximum stretched response time between two consecutive ACK messages. By default -ACK messages are sent every 10ms (so this interval is not dependent on the network -latency), and so should be the interval between two consecutive received ACK -messages. Note, however, that the network jitter on the public internet causes -these intervals to be stretched, even to multiples of that interval. Both large -and small values of this option have consequences: - -Large values of this option prevent overreaction on highly stretched response -times, but introduce a latency penalty - the latency must be greater -than this value (otherwise switching to another link won't preserve -smooth signal sending). Large values will also contribute to higher packet -bursts sent at the moment when an idle link is activated. - -Smaller values of this option respect low latency requirements very -well, but may cause overreaction on even slightly stretched response times. This is -unwanted, as a link switch should ideally happen only when the currently active -link is really broken, as every link switch costs extra overhead (it counts -for 100% for a time of one ACK interval). - -Note that the value of this option is not allowed to exceed the value of -`SRTO_PEERIDLETIMEO`. Usually it is only meaningful if you change the latter -option, as the default value of it is way above any sensible value of -`SRTO_GROUPSTABTIMEO`. - -[Return to list](#list-of-options) - ---- - -#### SRTO_GROUPTYPE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_GROUPTYPE` | 1.5.0 | pre | `int32_t` | enum | | | R | S | - -This option is read-only and it is intended to be called inside the listener -callback handler (see `srt_listen_callback`). Possible values are defined in -the `SRT_GROUP_TYPE` enumeration type. - -This option returns the group type that is declared in the incoming connection. -If the incoming connection is not going to make a group-member connection, then -the value returned is `SRT_GTYPE_UNDEFINED`. If this option is read in any other -context than inside the listener callback handler, the value is undefined. - -[Return to list](#list-of-options) - ---- - -#### SRTO_INPUTBW - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ---------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_INPUTBW` | 1.0.5 | post | `int64_t` | B/s | 0 | 0.. | RW | GSD | - -This option is effective only if `SRTO_MAXBW` is set to 0 (relative). It -controls the maximum bandwidth together with `SRTO_OHEADBW` option according -to the formula: `MAXBW = INPUTBW * (100 + OHEADBW) / 100`. When this option -is set to 0 (automatic) then the real INPUTBW value will be estimated from -the rate of the input (cases when the application calls the `srt_send*` -function) during transmission. - -*Recommended: set this option to the anticipated bitrate of your live stream -and keep the default 25% value for `SRTO_OHEADBW`*. - -[Return to list](#list-of-options) - ---- - -#### SRTO_IPTOS - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ---------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_IPTOS` | 1.0.5 | pre | `int32_t` | | (system) | 0..255 | RW | GSD | - -IPv4 Type of Service (see `IP_TOS` option for IP) or IPv6 Traffic Class (see `IPV6_TCLASS` -of IPv6) depending on socket address family. Applies to sender only. - -When *getting*, the returned value is the user preset for non-connected sockets -and the actual value for connected sockets. - -*Sender*: user configurable, default: `0xB8`. - -[Return to list](#list-of-options) - ---- - -#### SRTO_IPTTL - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ---------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_IPTTL` | 1.0.5 | pre | `int32_t` | hops | (system) | 1..255 | RW | GSD | - -IPv4 Time To Live (see `IP_TTL` option for IP) or IPv6 unicast hops (see -`IPV6_UNICAST_HOPS` for IPv6) depending on socket address family. Applies to sender only. - -When *getting*, the returned value is the user preset for non-connected sockets -and the actual value for connected sockets. - -*Sender*: user configurable, default: 64 - -[Return to list](#list-of-options) - ---- - -#### SRTO_IPV6ONLY - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ---------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_IPV6ONLY` | 1.4.0 | pre | `int32_t` | | (system) | -1..1 | RW | GSD | - -Set system socket flag `IPV6_V6ONLY`. When set to 0 a listening socket binding an -IPv6 address accepts also IPv4 clients (their addresses will be formatted as -IPv4-mapped IPv6 addresses). By default (-1) this option is not set and the -platform default value is used. - -[Return to list](#list-of-options) - ---- - -#### SRTO_ISN - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ---------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_ISN` | 1.3.0 | | `int32_t` | | | | R | S | - -The value of the ISN (Initial Sequence Number), which is the first sequence -number put on the first UDP packets sent that are carrying an SRT data payload. - -*This value is useful for developers of some more complicated methods of flow -control, possibly with multiple SRT sockets at a time. It is not intended to be -used in any regular development.* - -[Return to list](#list-of-options) - ---- - -#### SRTO_KMPREANNOUNCE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| --------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_KMPREANNOUNCE` | 1.3.2 | pre | `int32_t` | pkts | 0x1000 | 0.. * | RW | GSD | - -The interval (defined in packets) between when a new Stream Encrypting Key -(SEK) is sent and when switchover occurs. This value also applies to the -subsequent interval between when switchover occurs and when the old SEK is -decommissioned. - -At `SRTO_KMPREANNOUNCE` packets before switchover the new key is sent -(repeatedly, if necessary, until it is confirmed by the receiver). - -At the switchover point (see `SRTO_KMREFRESHRATE`), the sender starts -encrypting and sending packets using the new key. The old key persists in case -it is needed to decrypt packets that were in the flight window, or -retransmitted packets. - -The old key is decommissioned at `SRTO_KMPREANNOUNCE` packets after switchover. - -The allowed range for this value is between 1 and half of the current value of -`SRTO_KMREFRESHRATE`. The minimum value should never be less than the flight -window (i.e. the number of packets that have already left the sender but have -not yet arrived at the receiver). - -[Return to list](#list-of-options) - ---- - -#### SRTO_KMREFRESHRATE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| --------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_KMREFRESHRATE` | 1.3.2 | pre | `int32_t` | pkts | 0x1000000| 0.. | RW | GSD | - -The number of packets to be transmitted after which the Stream Encryption Key -(SEK), used to encrypt packets, will be switched to the new one. Note that -the old and new keys live in parallel for a certain period of time (see -`SRTO_KMPREANNOUNCE`) before and after the switchover. - -Having a preannounce period before switchover ensures the new SEK is installed -at the receiver before the first packet encrypted with the new SEK is received. -The old key remains active after switchover in order to decrypt packets that -might still be in flight, or packets that have to be retransmitted. - -[Return to list](#list-of-options) - ---- - -#### SRTO_KMSTATE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| --------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_KMSTATE` | 1.0.2 | | `int32_t` | enum | | | R | S | - -Keying Material state. This is a legacy option that is equivalent to -`SRTO_SNDKMSTATE`, if the socket has set `SRTO_SENDER` to true, and -`SRTO_RCVKMSTATE` otherwise. This option is then equal to `SRTO_RCVKMSTATE` -always if your application disregards possible cooperation with a peer older -than 1.3.0, but then with the default value of `SRTO_ENFORCEDENCRYPTION` the -value returned by both options is always the same. See [`SRT_KM_STATE`](#2-srt_km_state) -for more details. - -[Return to list](#list-of-options) - ---- - -#### SRTO_LATENCY - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| --------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_LATENCY` | 1.0.2 | pre | `int32_t` | ms | 120 * | 0.. | RW | GSD | - -This option sets both [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY) and [`SRTO_PEERLATENCY`](#SRTO_PEERLATENCY) -to the same value specified. - -Prior to SRT version 1.3.0 `SRTO_LATENCY` was the only option to set the latency. -However it is effectively equivalent to setting `SRTO_PEERLATENCY` in the sending direction -(see [`SRTO_SENDER`](#SRTO_SENDER)), and `SRTO_RCVLATENCY` in the receiving direction. -SRT version 1.3.0 and higher support bidirectional transmission, so that each side can -be sender and receiver at the same time, and `SRTO_SENDER` became redundant. - -[Return to list](#list-of-options) - ---- - -#### SRTO_LINGER - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------ | -------- | ------ | --- | ------ | -| `SRTO_LINGER` | | pre | `linger` | s | on, 180 | 0.. | RW | GSD | - -Linger time on close (see [SO\_LINGER](http://man7.org/linux/man-pages/man7/socket.7.html)). - -*SRT recommended value*: off (0). - -[Return to list](#list-of-options) - ---- - -#### SRTO_LOSSMAXTTL - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_LOSSMAXTTL` | 1.2.0 | pre | `int32_t` | packets | 0 | 0.. | RW | GSD+ | - -The value up to which the *Reorder Tolerance* may grow. The *Reorder Tolerance* -is the number of packets that must follow the experienced "gap" in sequence numbers -of incoming packets so that the loss report is sent (in the hope that the gap is due -to packet reordering rather than because of loss). The value of *Reorder Tolerance* -starts from 0 and is set to a greater value when packet reordering is detected -This happens when a "belated" packet, with sequence number older than the latest -received, has been received, but without retransmission flag. When this is detected -the *Reorder Tolerance* is set to the value of the interval between latest sequence -and this packet's sequence, but not more than the value set by `SRTO_LOSSMAXTTL`. -By default this value is set to 0, which means that this mechanism is off. - -[Return to list](#list-of-options) - ---- - -#### SRTO_MAXBW - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_MAXBW` | 1.0.5 | pre | `int64_t` | B/s | -1 | -1.. | RW | GSD | - -Maximum send bandwidth: - -- `-1`: infinite (the limit in Live Mode is 1 Gbps); -- `0`: relative to input rate (see [`SRTO_INPUTBW`](#SRTO_INPUTBW)); -- `>0`: absolute limit in B/s. - -**NOTE**: This option has a default value of -1, regardless of the mode. -For live streams it is typically recommended to set the value 0 here and rely -on `SRTO_INPUTBW` and `SRTO_OHEADBW` options. However, if you want to do so, -you should make sure that your stream has a fairly constant bitrate, or that -changes are not abrupt, as high bitrate changes may work against the -measurement. SRT cannot ensure that this is always the case for a live stream, -therefore the default -1 remains even in live mode. - -[Return to list](#list-of-options) - ---- - -#### SRTO_MESSAGEAPI - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_MESSAGEAPI` | 1.3.0 | pre | `bool` | | true | | W | GSD | - -When set, this socket uses the Message API[\*], otherwise it uses the -Stream API. Note that in live mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE) option) only the -Message API is available. In File mode you can chose to use one of two modes -(note that the default for this option is changed with `SRTO_TRANSTYPE` -option): - -- **Stream API** (default for file mode): In this mode you may send -as many data as you wish with one sending instruction, or even use dedicated -functions that operate directly on a file. The internal facility will take care -of any speed and congestion control. When receiving, you can also receive as -many data as desired. The data not extracted will be waiting for the next call. -There is no boundary between data portions in Stream mode. - -- **Message API**: In this mode your single sending instruction passes exactly -one piece of data that has boundaries (a message). Contrary to Live mode, -this message may span multiple UDP packets, and the only size limitation -is that it shall fit as a whole in the sending buffer. The receiver shall use -as large a buffer as necessary to receive the message, otherwise reassembling -and delivering the message might not be possible. When the message is not -complete (not all packets received or there was a packet loss) it will not be -copied to the application's buffer. Messages that are sent later, but were -earlier reassembled by the receiver, will be delivered once ready, if the -`inorder` flag was set to false. -See [`srt_sendmsg`](https://github.com/Haivision/srt/blob/master/docs/API.md#sending-and-receiving)). - -As a comparison to the standard system protocols, the Stream API does -transmission similar to TCP, whereas the Message API functions like the -SCTP protocol. - -[Return to list](#list-of-options) - ---- - -#### SRTO_MINVERSION - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_MINVERSION` | 1.3.0 | pre | `int32_t` | version | 0 | * | W | GSD | - -The minimum SRT version that is required from the peer. A connection to a -peer that does not satisfy the minimum version requirement will be rejected. -See [`SRTO_VERSION`](#SRTO_VERSION) for the version format. - -[Return to list](#list-of-options) - ---- - -#### SRTO_MSS - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_MSS` | | pre | `int32_t` | bytes | 1500 | 76.. | RW | GSD | - -Maximum Segment Size. Used for buffer allocation and rate calculation using -packet counter assuming fully filled packets. Each party can set its own MSS -value independently. During a handshake the parties exchange MSS values, and -the lowest is used. - -*Generally on the internet MSS is 1500 by default. This is the maximum -size of a UDP packet and can be only decreased, unless you have some unusual -dedicated network settings. MSS is not to be confused with the size of the UDP -payload or SRT payload - this size is the size of the IP packet, including the -UDP and SRT headers* - -[Return to list](#list-of-options) - ---- - -#### SRTO_NAKREPORT - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_NAKREPORT` | 1.1.0 | pre | `bool` | | * | | RW | GSD+ | - -When set to true, every report for a detected loss will be repeated when the -timeout for the expected retransmission of this loss has expired and the -missing packet still wasn't recovered, or wasn't conditionally dropped (see -[`SRTO_TLPKTDROP`](#SRTO_TLPKTDROP)). - -The default is true for Live mode, and false for File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)). - -[Return to list](#list-of-options) - ---- - -#### SRTO_OHEADBW - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_OHEADBW` | 1.0.5 | post | `int32_t` | % | 25 | 5..100 | RW | GSD | - -Recovery bandwidth overhead above input rate (see [`SRTO_INPUTBW`](#SRTO_INPUTBW)), -in percentage of the input rate. It is effective only if `SRTO_MAXBW` is set to 0. - -*Sender*: user configurable, default: 25%. - -Recommendations: - -- Overhead is intended to give you extra bandwidth for the case when a packet -has taken part of the bandwidth, but then was lost and has to be retransmitted. -Therefore the effective maximum bandwidth should be appropriately higher than -your stream's bitrate so that there's some room for retransmission, but still -limited so that the retransmitted packets don't cause the bandwidth usage to -skyrocket when larger groups of packets are lost - -- Don't configure it too low and avoid 0 in the case when you have the -`SRTO_INPUTBW` option set to 0 (automatic). Otherwise your stream will choke -and break quickly at any rise in packet loss. - -- ***To do: set-only; get should be supported.*** - -[Return to list](#list-of-options) - ---- - -#### SRTO_PACKETFILTER - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PACKETFILTER` | 1.4.0 | pre | `string` | | "" | [512] | W | GSD | - -Set up the packet filter. The string must match appropriate syntax for packet -filter setup. - -As there can only be one configuration for both parties, it is recommended that -one party defines the full configuration while the other only defines the matching -packet filter type (for example, one sets `fec,cols:10,rows:-5,layout:staircase` -and the other just `fec`). Both parties can also set this option to the same value. -The packet filter function will attempt to merge configuration definitions, but if -the options specified are in conflict, the connection will be rejected. - -For details, see [Packet Filtering & FEC](packet-filtering-and-fec.md). - -[Return to list](#list-of-options) - ---- - -#### SRTO_PASSPHRASE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PASSPHRASE` | 0.0.0 | pre | `string` | | "" |[10..79]| W | GSD | - -Sets the passphrase for encryption. This enables encryption on this party (or -disables it, if an empty passphrase is passed). - -The passphrase is the shared secret between the sender and the receiver. It is -used to generate the Key Encrypting Key using [PBKDF2](http://en.wikipedia.org/wiki/PBKDF2) -(Password-Based Key Derivation Function 2). It is used on the receiver only if -the received data is encrypted. - -Note that since the introduction of bidirectional support, there's only one -initial SEK to encrypt the stream (new keys after refreshing will be updated -independently), and there's no distinction between "service party that defines -the password" and "client party that is required to set matching password" - both -parties are equivalent, and in order to have a working encrypted connection, they -have to simply set the same passphrase. Otherwise the connection is rejected by -default (see also [`SRTO_ENFORCEDENCRYPTION`](#SRTO_ENFORCEDENCRYPTION)). - -[Return to list](#list-of-options) - ---- - -#### SRTO_PAYLOADSIZE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PAYLOADSIZE` | 1.3.0 | pre | `int32_t` | bytes | \* | \* | W | GSD | - -Sets the maximum declared size of a single call to sending function in Live -mode. When set to 0, there's no limit for a single sending call. - -For Live mode: Default value is 1316, but can be increased up to 1456. Note that -with the `SRTO_PACKETFILTER` option additional header space is usually required, -which decreases the maximum possible value for `SRTO_PAYLOADSIZE`. - -For File mode: Default value is 0 and it's recommended not to be changed. - -[Return to list](#list-of-options) - ---- - -#### SRTO_PBKEYLEN - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PBKEYLEN` | 0.0.0 | pre | `int32_t` | bytes | 0 | * | RW | GSD | - -Sender encryption key length. - -Possible values: - -- 0 =`PBKEYLEN` (default value) -- 16 = AES-128 (effective value) -- 24 = AES-192 -- 32 = AES-256 - -The use is slightly different in 1.2.0 (HSv4), and since 1.3.0 (HSv5): - -- **HSv4**: This is set on the sender and enables encryption, if not 0. The receiver -shall not set it and will agree on the length as defined by the sender. - -- **HSv5**: The "default value" for `PBKEYLEN` is 0, which means that the -`PBKEYLEN` won't be advertised. The "effective value" for `PBKEYLEN` is 16, but -this applies only when neither party has set the value explicitly (i.e. when -both are initially at the default value of 0). If any party *has* set an -explicit value (16, 24, 32) it will be advertised in the handshake. If the other -party remains at the default 0, it will accept the peer's value. The situation -where both parties set a value should be treated carefully. Actually there are -three intended methods of defining it, and all other uses are considered -undefined behavior: - - - **Unidirectional**: the sender shall set `PBKEYLEN` and the receiver shall - not alter the default value 0. The effective `PBKEYLEN` will be the one set - on the sender. The receiver need not know the sender's `PBKEYLEN`, just the - passphrase, `PBKEYLEN` will be correctly passed. - - - **Bidirectional in Caller-Listener arrangement**: it is recommended to use - a rule whereby you will be setting the `PBKEYLEN` exclusively either on the - Listener or on the Caller. The value set on the Listener will win, if set on - both parties. - - - **Bidirectional in Rendezvous arrangement**: you have to know the passphrases - for both parties, as well as `PBKEYLEN`. Set `PBKEYLEN` to the same value on - both parties (or leave the default value on both parties, which will - result in 16) - - - **Unwanted behavior cases**: if both parties set `PBKEYLEN` and the value - on both sides is different, the effective `PBKEYLEN` will be the one that is - set on the Responder party, which may also override the `PBKEYLEN` 32 set by - the sender to value 16 if such value was used by the receiver. The Responder - party is the Listener in a Caller-Listener arrangement. In Rendezvous it's a - matter of luck which party becomes the Responder. - -[Return to list](#list-of-options) - ---- - -#### SRTO_PEERIDLETIMEO - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PEERIDLETIMEO` | 1.3.3 | pre | `int32_t` | ms | 5000 | 0.. | RW | GSD+ | - -The maximum time in `[ms]` to wait until another packet is received from a peer -since the last such packet reception. If this time is passed, the connection is -considered broken on timeout. - -[Return to list](#list-of-options) - ---- - -#### SRTO_PEERLATENCY - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PEERLATENCY` | 1.3.0 | pre | `int32_t` | ms | 0 | 0.. | RW | GSD | - -The latency value (as described in [`SRTO_RCVLATENCY`](#SRTO_RCVLATENCY)) provided by the sender -side as a minimum value for the receiver. - -Reading the value of the option on an unconnected socket reports the configured value. -Reading the value on a connected socket reports the effective receiver buffering latency of the peer. - -**The `SRTO_PEERLATENCY` option in versions prior to 1.3.0 is only available as** -[`SRTO_LATENCY`](#SRTO_LATENCY). - -See also [`SRTO_LATENCY`](#SRTO_LATENCY). - -[Return to list](#list-of-options) - ---- - -#### SRTO_PEERVERSION - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | -------- | ------ | --- | ------ | -| `SRTO_PEERVERSION` | 1.1.0 | | `int32_t` | * | | | R | GS | - -SRT version used by the peer. The value 0 is returned if not connected, SRT -handshake not yet performed (HSv4 only), or if peer is not SRT. -See [`SRTO_VERSION`](#SRTO_VERSION) for the version format. - -[Return to list](#list-of-options) - ---- - -#### SRTO_RCVBUF - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RCVBUF` | | pre | `int32_t` | bytes | 8192 bufs | * | RW | GSD+ | - -Receive Buffer Size, in bytes. Note, however, that the internal setting of this -value is in the number of buffers, each one of size equal to SRT payload size, -which is the value of `SRTO_MSS` decreased by UDP and SRT header sizes (28 and 16). -The value set here will be effectively aligned to the multiple of payload size. - -- **Minimum value**: 32 buffers (46592 with default value of `SRTO_MSS`). - -- **Maximum value**: [`SRTO_FC`](#SRTO_FC) number of buffers (receiver buffer must not be greater -than the Flight Flag size). - -[Return to list](#list-of-options) - ---- - -#### SRTO_RCVDATA - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RCVDATA` | | | `int32_t` | pkts | | | R | S | - -Size of the available data in the receive buffer. - -[Return to list](#list-of-options) - ---- - -#### SRTO_RCVKMSTATE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RCVKMSTATE` | 1.2.0 | | `int32_t` | enum | | | R | S | - -KM state on the agent side when it's a receiver. - -Values defined in enum [`SRT_KM_STATE`](#srt_km_state). - -[Return to list](#list-of-options) - ---- - -#### SRTO_RCVLATENCY - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RCVLATENCY` | 1.3.0 | pre | `int32_t` | ms | * | 0.. | RW | GSD | - -The latency value in the receiving direction of the socket. -This value is only significant when [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE) is enabled. - -**Default value**: 120 ms (depicted as 0) in Live mode, 0 in File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)). - -The latency value defines the **minimum** receiver buffering delay before delivering an SRT data packet -from a receiving SRT socket to a receiving application. The provided value is used in the connection establishment (handshake exchange) stage -to fix the end-to-end latency of the transmission. The effective end-to-end latency `L` will be fixed -as the network transmission time of the final handshake packet (~1/2 RTT) plus the **negotiated** latency value `Ln`. -Data packets will stay in the receiver buffer for at least `L` microseconds since the timestamp of the -packet, independent of the actual network transmission times (RTT variations) of these packets. - -The actual value of the receiver buffering delay `Ln` (the negotiated latency) used on a connection -is determined by the negotiation in the connection establishment (handshake exchange) phase as the maximum of the -`SRTO_RCVLATENCY` value and the value of [`SRTO_PEERLATENCY`](#SRTO_PEERLATENCY) set by the peer. - -Reading the `SRTO_RCVLATENCY` value on a socket after the connection is established provides the actual (negotiated) -latency value `Ln`. - -The receiver's buffer must be large enough to store the `L` segment of the stream, -i.e. `L × Bitrate` bytes. Refer to [`SRTO_RCVBUF`](#SRTO_RCVBUF). - -The sender's buffer must be large enough to store a packet up until it is either delivered (and acknowledged) -or dropped by the sender due to it becoming too late to be delivered. -In other words, `D × Bitrate` bytes, where `D` is the sender's drop delay value configured with [`SRTO_SNDDROPDELAY`](#SRTO_SNDDROPDELAY). - -Buffering of data packets on the receiving side makes it possible to recover from packet losses using the ARQ -(Automatic Repeat Request) technique, and to deal with varying RTT times (network jitter) in the network, providing -a (close to) **constant end-to-end latency of the transmission**. - -See also [`SRTO_LATENCY`](#SRTO_LATENCY). - -[Return to list](#list-of-options) - ---- - -#### SRTO_RCVSYN - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RCVSYN` | | post | `bool` | | true | | RW | GSI | - -When true, sets blocking mode on reading function when it's not ready to -perform the operation. When false ("non-blocking mode"), the reading function -will in this case report error `SRT_EASYNCRCV` and return immediately. Details -depend on the tested entity: - -On a connected socket or group this applies to a receiving function -(`srt_recv` and others) and a situation when there are no data available for -reading. The readiness state for this operation can be tested by checking the -`SRT_EPOLL_IN` flag on the aforementioned socket or group. - -On a freshly created socket or group that is about to be connected to a peer -listener this applies to any `srt_connect` call (and derived), which in -"non-blocking mode" always returns immediately. The connected state for that -socket or group can be tested by checking the `SRT_EPOLL_OUT` flag. Note -that a socket that failed to connect doesn't change the `SRTS_CONNECTING` -state and can be found out only by testing the `SRT_EPOLL_ERR` flag. - -On a listener socket this applies to `srt_accept` call. The readiness state -for this operation can be tested by checking the `SRT_EPOLL_IN` flag on -this listener socket. This flag is also derived from the listener socket -by the accepted socket or group, although the meaning of this flag is -effectively different. - -Note that when this flag is set only on a group, it applies to a -specific receiving operation being done on that group (i.e. it is not -derived from the socket of which the group is a member). - -[Return to list](#list-of-options) - ---- - -#### SRTO_RCVTIMEO - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RCVTIMEO` | | post | `int32_t` | ms | -1 | -1, 0..| RW | GSI | - -Limits the time up to which the receiving operation will block (see -[`SRTO_RCVSYN`](#SRTO_RCVSYN) for details), such that when this time is exceeded, -it will behave as if in "non-blocking mode". The -1 value means no time limit. - -[Return to list](#list-of-options) - ---- - -#### SRTO_RENDEZVOUS - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_RENDEZVOUS` | | pre | `bool` | | false | | RW | S | - -Use Rendezvous connection mode (both sides must set this and both must use the -procedure of `srt_bind` and then `srt_connect` (or `srt_rendezvous`) to one another. - -[Return to list](#list-of-options) - ---- - -#### SRTO_RETRANSMITALGO - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| --------------------- | ----- | ------- | --------- | ------ | ------- | ------ | --- | ------ | -| `SRTO_RETRANSMITALGO` | 1.4.2 | pre | `int32_t` | | 0 | [0, 1] | RW | GSD | - -Retransmission algorithm to use (SENDER option): - -- 0 - Default (retransmit on every loss report). -- 1 - Reduced retransmissions (not more often than once per RTT); reduced - bandwidth consumption. - -This option is effective only on the sending side. It influences the decision -as to whether a particular reported lost packet should be retransmitted at a -certain time or not. - -The reduced retransmission algorithm (`SRTO_RETRANSMITALGO=1`) is only operational when receiver sends -Periodic NAK reports. See [SRTO_NAKREPORT](#SRTO_NAKREPORT). - -[Return to list](#list-of-options) - ---- - -#### SRTO_REUSEADDR - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_REUSEADDR` | | pre | `bool` | | true | | RW | GSD | - -When true, allows the SRT socket to use the binding address used already by -another SRT socket in the same application. Note that SRT socket uses an -intermediate object called Multiplexer to access the underlying UDP sockets, -so multiple SRT sockets may share one UDP socket, and the packets received by this -UDP socket will be correctly dispatched to the SRT socket to which they are -currently destined. This has some similarities to the `SO_REUSEADDR` system socket -option, although it's only used inside SRT. - -*TODO: This option weirdly only allows the socket used in **bind()** to use the -local address that another socket is already using, but not to disallow another -socket in the same application to use the binding address that the current -socket is already using. What it actually changes is that when given an address in -**bind()** is already used by another socket, this option will make the binding -fail instead of adding the socket to the shared group of that socket that -already has bound this address - but it will not disallow another socket to reuse -its address.* - -[Return to list](#list-of-options) - ---- - -#### SRTO_SENDER - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | ---------- | ------ | --- | ------ | -| `SRTO_SENDER` | 1.0.4 | pre | `bool` | | false | | W | S | - -Set sender side. The side that sets this flag is expected to be a sender. This -flag is only required when communicating with a receiver that uses SRT version -less than 1.3.0 (and hence *HSv4* handshake), in which case if not set properly, -the TSBPD mode (see [`SRTO_TSBPDMODE`](#SRTO_TSBPDMODE)) or encryption will not -work. Setting `SRTO_MINVERSION` to 1.3.0 is therefore recommended. - -[Return to list](#list-of-options) - ---- - -#### SRTO_SNDBUF - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_SNDBUF` | | pre | `int32_t` | bytes |8192 bufs | * | RW | GSD+ | - -Sender Buffer Size. See [`SRTO_RCVBUF`](#SRTO_RCVBUF) for more information. - -[Return to list](#list-of-options) - ---- - -#### SRTO_SNDDATA - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_SNDDATA` | | | `int32_t` | pkts | | | R | S | - -Size of the unacknowledged data in send buffer. - -[Return to list](#list-of-options) - ---- - -#### SRTO_SNDDROPDELAY - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_SNDDROPDELAY` | 1.3.2 | pre | `int32_t` | ms | * | -1.. | W | GSD+ | - -Sets an extra delay before `TLPKTDROP` is triggered on the data sender. -This delay is added to the default drop delay time interval value. Keep in mind -that the longer the delay, the more probable it becomes that packets would be -retransmitted uselessly because they will be dropped by the receiver anyway. - -`TLPKTDROP` discards packets reported as lost if it is already too late to send -them (the receiver would discard them even if received). The delay before the -`TLPKTDROP` mechanism is triggered consists of the SRT latency (`SRTO_PEERLATENCY`), -plus `SRTO_SNDDROPDELAY`, plus `2 * interval between sending ACKs` (where the -default `interval between sending ACKs` is 10 milliseconds). -The minimum delay is `1000 + 2 * interval between sending ACKs` milliseconds. - -**Special value -1**: Do not drop packets on the sender at all (retransmit them -always when requested). - -**Default:** 0 in Live mode, -1 in File mode. - -[Return to list](#list-of-options) - ---- - -#### SRTO_SNDKMSTATE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_SNDKMSTATE` | 1.2.0 | post | `int32_t` | enum | | | R | S | - -Peer KM state on receiver side for `SRTO_KMSTATE` - -Values defined in enum [`SRT_KM_STATE`](#srt_km_state). - -[Return to list](#list-of-options) - ---- - -#### SRTO_SNDSYN - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_SNDSYN` | | post | `bool` | | true | | RW | GSI | - -When true, sets blocking mode on writing function when it's not ready to -perform the operation. When false ("non-blocking mode"), the writing function -will in this case report error `SRT_EASYNCSND` and return immediately. - -On a connected socket or group this applies to a sending function -(`srt_send` and others) and a situation when there's no free space in -the sender buffer, caused by inability to send all the scheduled data over -the network. Readiness for this operation can be tested by checking the -`SRT_EPOLL_OUT` flag. - -On a freshly created socket or group it will have no effect until the socket -enters a connected state. - -On a listener socket it will be derived by the accepted socket or group, -but will have no effect on the listener socket itself. - -[Return to list](#list-of-options) - ---- - -#### SRTO_SNDTIMEO - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_SNDTIMEO` | | post | `int32_t` | ms | -1 | -1.. | RW | GSI | - -limit the time up to which the sending operation will block (see -`SRTO_SNDSYN` for details), so when this time is exceeded, it will behave as -if in "non-blocking mode". The -1 value means no time limit. - -[Return to list](#list-of-options) - ---- - -#### SRTO_STATE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_STATE` | | | `int32_t` | enum | | | R | S | - -Returns the current socket state, same as `srt_getsockstate`. - -[Return to list](#list-of-options) - ---- - -#### SRTO_STREAMID - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| -------------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_STREAMID` | 1.3.0 | pre | `string` | | "" | [512] | RW | GSD | - -- A string that can be set on the socket prior to connecting. The listener side -will be able to retrieve this stream ID from the socket that is returned from -`srt_accept` (for a connected socket with that stream ID). You usually use SET -on the socket used for `srt_connect`, and GET on the socket retrieved from -`srt_accept`. This string can be used completely free-form. However, it's highly -recommended to follow the [SRT Access Control guidlines](AccessControl.md). - -- As this uses internally the `std::string` type, there are additional functions -for it in the legacy/C++ API (udt.h): `srt::setstreamid` and `srt::getstreamid`. - -- This option is not useful for a Rendezvous connection, since one side would -override the value from the other side resulting in an arbitrary winner. Also -in this connection both peers are known to one another and both have equivalent -roles in the connection. - -[Return to list](#list-of-options) - ---- - -#### SRTO_TLPKTDROP - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_TLPKTDROP` | 1.0.6 | pre | `bool` | | * | | RW | GSD | - -Too-late Packet Drop. When enabled on receiver, it skips missing packets that -have not been delivered in time and delivers the subsequent packets to the -application when their time-to-play has come. It also sends a fake ACK to the -sender. When enabled on sender and enabled on the receiving peer, sender drops -the older packets that have no chance to be delivered in time. It is automatically -enabled in sender if receiver supports it. - -**Default:** true in Live mode, false in File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)) - -[Return to list](#list-of-options) - ---- - -#### SRTO_TRANSTYPE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_TRANSTYPE` | 1.3.0 | pre | `int32_t` | enum |`SRTT_LIVE`| \* | W | S | - -Sets the transmission type for the socket, in particular, setting this option -sets multiple other parameters to their default values as required for a -particular transmission type. - -Values defined by enum `SRT_TRANSTYPE` (see above for possible values) - -[Return to list](#list-of-options) - ---- - -#### SRTO_TSBPDMODE - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_TSBPDMODE` | 0.0.0 | pre | `bool` | | \* | | W | S | - -When true, use Timestamp-based Packet Delivery mode. In this mode the -packet's time is assigned at the sending time (or allowed to be predefined), -transmitted in the packet's header, and then restored on the receiver side so that -the time intervals between consecutive packets are preserved when delivering to -the application. - -**Default:** true in Live mode, false in File mode (see [`SRTO_TRANSTYPE`](#SRTO_TRANSTYPE)). - -[Return to list](#list-of-options) - ---- - -#### SRTO_UDP_RCVBUF - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_UDP_RCVBUF` | | pre | `int32_t` | bytes | 8192 bufs | * | RW | GSD+ | - -UDP Socket Receive Buffer Size. Configured in bytes, maintained in packets -based on MSS value. Receive buffer must not be greater than FC size. - -[Return to list](#list-of-options) - ---- - -#### SRTO_UDP_SNDBUF - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_UDP_SNDBUF` | | pre | `int32_t` | bytes | 65536 | * | RW | GSD+ | - -UDP Socket Send Buffer Size. Configured in bytes, maintained in packets based -on `SRTO_MSS` value. - -[Return to list](#list-of-options) - ---- - -#### SRTO_VERSION - -| OptName | Since | Binding | Type | Units | Default | Range | Dir | Entity | -| ----------------- | ----- | ------- | ---------- | ------- | --------- | ------ | --- | ------ | -| `SRTO_VERSION` | 1.1.0 | | `int32_t` | | | | R | S | - -Local SRT version. This is the highest local version supported if not -connected, or the highest version supported by the peer if connected. - -The version format in hex is `0x00XXYYZZ` for x.y.z in human readable form. -For example, version 1.4.2 is encoded as `0x010402`. - -[Return to list](#list-of-options) - ---- diff --git a/docs/AccessControl.md b/docs/AccessControl.md deleted file mode 100644 index df35e662c..000000000 --- a/docs/AccessControl.md +++ /dev/null @@ -1,431 +0,0 @@ -# SRT Access Control Guidelines - -## Motivation - -One type of information that can be interchanged when a connection is being -established in SRT is "Stream ID", which can be used in a caller-listener -connection layout. This is a string of maximum 512 characters set on the caller -side. It can be retrieved at the listener side on the newly accepted socket -through a socket option (see `SRTO_STREAMID` in [API.md](API.md)). - -As of SRT version 1.3.3 a callback can be registered on the listener socket for -an application to make decisions on incoming caller connections. This callback, -among others, is provided with the value of Stream ID from the incoming -connection. Based on this information, the application can accept or reject the -connection, select the desired data stream, or set an appropriate passphrase for -the connection. - -## Purpose - -The Stream ID value can be used as free-form, but there is a recommended -convention so that all SRT users speak the same language. The intent of the -convention is to: - -- promote readability and consistency among free-form names -- interpret some typical data in the key-value style - -In short, - -1. `SRTO_STREAMID` is designed for a caller (client) to be able to identify itself, and state what it wants. -2. `srt_listen_callback(...)` function is used by a listener (server) to check what a caller (client) has provided in `SRTO_STREAMID` **before** the connection is established. -For example, the listener (server) can check if it knows the user and set the corresponding passphrase for a connection to be accepted. -3. Even if `srt_listen_callback(...)` accepts the connection, SRT will still have one more step to check the PASSPHRASE, and reject on mismatch. -If a correct passphrase is not provided by the client (caller), the request from caller will be rejected by SRT library (not application or programmer). - -**Note!** `srt_listen_callback(...)` can't check the passphrase directly for security reasons. -The only way to make the app check the passphrase is to set the passphrase on the socket by using the `SRTO_PASSPHRASE` option. This lets SRT to reject connection on mismatch. - -## Character Encoding - -The Stream ID uses UTF-8 encoding. - -## General Syntax - -This recommended syntax starts with the characters known as an executable -specification in POSIX: `#!`. - -The next two characters are: - -- `:` - this marks the YAML format, the only one currently used -- The content format, which is either: - - `:` - the comma-separated keys with no nesting - - `{` - like above, but nesting is allowed and must end with `}` - -(Nesting means that you can have multiple level brace-enclosed parts inside.) - -The form of the key-value pair is: - -```js -key1=value1,key2=value2... -``` - -## Standard Keys - -Beside the general syntax, there are several top-level keys treated as standard -keys. All single letter key definitions, including those not listed in this section, -are reserved for future use. Users can additionally use custom key definitions -with `user_*` or `companyname_*` prefixes, where `user` and `companyname` are -to be replaced with an actual user or company name. - -The existing key values must not be extended, and must not differ from those described in this section. - -The following keys are standard: - -- `u`: **User Name**, or authorization name, that is expected to control which -password should be used for the connection. The application should interpret -it to distinguish which user should be used by the listener party to set up the -password. -- `r`: **Resource Name** identifies the name of the resource and facilitates -selection should the listener party be able to serve multiple resources. -- `h`: **Host Name** identifies the hostname of the resource. For example, -to request a stream with the URI `somehost.com/videos/querry.php?vid=366` the -`hostname` field should have `somehost.com`, and the resource name can have -`videos/querry.php?vid=366` or simply `366`. Note that this is still a key to be -specified explicitly. Support tools that apply simplifications and URI extraction -are expected to insert only the host portion of the URI here. -- `s`: **Session ID** is a temporary resource identifier negotiated with -the server, used just for verification. This is a one-shot identifier, invalidated -after the first use. The expected usage is when details for the resource and -authorization are negotiated over a separate connection first, and then the -session ID is used here alone. -- `t`: **Type** specifies the purpose of the connection. Several standard -types are defined, but users may extend the use: - - `stream` (default, if not specified): for exchanging the user-specified - payload for an application-defined purpose - - `file`: for transmitting a file, where `r` is the filename - - `auth`: for exchanging sensible data. The `r` value states its purpose. - No specific possible values for that are known so far (FUTURE USE] -- `m`: **Mode** expected for this connection: - - `request` (default): the caller wants to receive the stream - - `publish`: the caller wants to send the stream data - - `bidirectional`: bidirectional data exchange is expected - -Note that `m` is not required in the case where you don't use `streamid` to -distinguish authorization or resources, and your caller is expected to send the -data. This is only for cases where the listener can handle various purposes of the -connection and is therefore required to know what the caller is attempting to do. - -Examples: - -```js -#!::u=admin,r=bluesbrothers1_hi -``` - -This specifies the username and the resource name of the stream to be served -to the caller. - -```js -#!::u=johnny,t=file,m=publish,r=results.csv -``` - -This specifies that the file is expected to be transmitted from the caller to -the listener and its name is `results.csv`. - -### Rejection codes - -The listener callback handler is also able to decide about rejecting the -incoming connection. In a normal situation, the rejection code is predefined -as `SRT_REJ_RESOURCE`. The handler can, however, set its own rejection -code. There are two number spaces intended for this purpose (as the range -below `SRT_REJC_PREDEFINED` is reserved for internal codes): - -- `SRT_REJC_PREDEFINED` and above: predefined errors. Errors from this range -(that is, below `SRT_REJC_USERDEFINED`) have their definitions provided in -the `access_control.h` public header file. The intention is that applications -using these codes understand the situation described by these codes standard -way. - -- `SRT_REJC_USERDEFINED` and above: to be freely defined by the application. -Codes from this range can be only understood if each application knows the -code definitions of the other. These codes should be used only after making -sure that both applications understood them. - -The intention for the predefined codes is to be consistent with the HTTP -standard codes. Therefore the following sub-ranges are used: - -- 0 - 99: Reserved for unique SRT-specific codes (unused by HTTP) -- 100 - 399: Info, Success and Redirection in HTTP, unused in SRT -- 400 - 599: Client and server errors in HTTP, adopted by SRT -- 600 - 999: unused in SRT - -Such a code can be set by using the `srt_setrejectreason` function. - -The SRT-specific codes are: - -#### SRT_REJX_FALLBACK - -This code should be set by the callback handler in the beginning in case -the application needs to be informed that the callback handler -actually has interpreted the incoming connection, but hasn't set a -more appropriate code describing the situation. - -#### SRT_REJX_KEY_NOTSUP - -Indicates there was a key specified in the StreamID string that this application -doesn't support. Note that it's not obligatory for the application to -react this way - it may chose to ignore unknown keys completely, or -to have some keys in the ignore list (which it won't interpret, but tolerate) -while rejecting any others. It is also up to the application -to decide to return this specific error, or more generally report -the syntax error with `SRT_REJX_BAD_REQUEST`. - -#### SRT_REJX_FILEPATH - -The resource type designates a file, and the path either has the wrong syntax -or is not found. In the case where `t=file`, the path should be specified under -the `r` key, and the file specified there must be able to be saved this way. -It's up to the application to decide how to treat this path, how to parse it, -and what this path specifically means. For the `r` key, the application should -at least handle the single filename, and have storage space available to save -it (provided a file of the same name does not already exist there). The -application should decide whether and how to handle all other situations (like -directory path, special markers in the path to be interpreted by the -application, etc.), or to report this error. - -#### SRT_REJX_HOSTNOTFOUND - -The host specified in the `h` key cannot be identified. The `h` key is -generally for a situation when you have multiple DNS names for a host, -so an application may want to extract the name from the URI and set it -to `h` key so that the application can distinguish the request also by -the target host name. The application may however limit the number of -recognized services by host name to some predefined names and not -handle the others, even if this is properly resolved by DNS. In this -case it should report this error. - -The other error codes are HTTP codes adopted for SRT: - -#### SRT_REJX_BAD_REQUEST - -General syntax error. This can be reported in any case when parsing -the StreamID contents failed, or it cannot be properly interpreted. - -#### SRT_REJX_UNAUTHORIZED - -Authentication failed, which makes the client unauthorized to access the -resource. This error, however, confirms that the syntax is correct and -the resource has been properly identified. Note that this cannot be -reported when you use a simple user-password authentication -method because in this case the password is verified only after the -listener callback handler accepts the connection. This error is rather -intended to be reported in case of `t=auth` when the authentication -process has generated some valid session ID, but then the session -connection has specified a resource that is not within the frames -of that authentication. - -#### SRT_REJX_OVERLOAD - -The server is too heavily loaded to process your request, or you -have exceeded credits for accessing the service and the resource. -In HTTP the description mentions payment for a service, but -it is also used by some services for general "credit" management -for a client. In SRT it should be used when your service is doing -any kind of credit management to limit access to selected clients -that "have" enough credit, even if the credit is something the client -can recharge itself, or that can be granted depending on available -service resources. - -#### SRT_REJX_FORBIDDEN - -Access denied to the resource for any reason. This error is -independent of an authorization or authentication error (as reported -by `SRT_REJX_UNAUTHORIZED`). The application can decide which -is more appropriate. This error is usually intended for -a resource that should only be accessed after a successful -authorization over a separate auth-only connection, where the query -in StreamID has correctly specified the resource identity and mode, -but the session ID (in the `s` key) is either (a) not specified, or (b) does -specify a valid session, but the authorization region for this -session does not embrace the specified resource. - -#### SRT_REJX_NOTFOUND - -The resource specified in the `r` key (in combination with the `h` key) -is not found at this time. This error should be only reported if the -information about resource accessibility is allowed to be publicly -visible. Otherwise the application might report authorization -errors. - -#### SRT_REJX_BAD_MODE - -The mode specified in the `m` key in StreamID is not supported for this request. -This may apply to read-only or write-only resources, as well for when interactive -(bidirectional) access is not valid for a resource. - -#### SRT_REJX_UNACCEPTABLE - -Applies when the parameters specified in SocketID cannot be satisfied for the -requested resource, or when `m=publish` but the data format is not acceptable. -This is a general error reporting an unsupported format for data that appears to -be wrong when sending, or a restriction on the data format (as specified in the -details of the resource specification) such that it cannot be provided -when receiving. - -#### SRT_REJX_CONFLICT - -The resource being accessed (as specified by `r` and `h` keys) is locked for -modification. This error should only be reported for `m=publish` when the -resource being accessed is read-only because another client (not necessarily -connected through SRT): - -- is currently publishing into this resource -- has reserved this resource ID for publishing - -Note that this error should be reported when there is no other reason for -having a problem accessing the resource. - -#### SRT_REJX_NOTSUP_MEDIA - -The media type is not supported by the application. The media type is -specified in the `t` key. The currently standard types are -`stream`, `file` and `auth`. An application may extend this list, and -is not obliged to support all of the standard types. - -#### SRT_REJX_LOCKED - -The resource being accessed is locked against any access. This is similar to -`SRT_REJX_CONFLICT`, but in this case the resource is locked for reading -and writing. This is for when the resource should be shown as existing and -available to the client, but access is temporarily blocked. - -#### SRT_REJX_FAILED_DEPEND - -The dependent entity for the request is not present. In this case the -dependent entity is the session, which should be specified in the `s` -key. This means that the specified session ID is nonexistent or it -has already expired. - -#### SRT_REJX_ISE - -Internal server error. This is for a general case when a request has -been correctly verified, with no related problems found, but an -unexpected error occurs after the processing of the request has started. - -#### SRT_REJX_UNIMPLEMENTED - -The request was correctly recognized, but the current software version -of the service (be it SRT or any other software component) doesn't -support it. This should be reported for a case, when some features to -be specified in the StreamID request are supposed to be supported in a -predictable future, but the current version of the server does not -support it, or the support for this feature in this version has been -temporarily blocked. This shouldn't be reported for existing features that are -being deprecated, or older features that are no longer supported -(for this case the general `SRT_REJX_BAD_REQUEST` is more appropriate). - -#### SRT_REJX_GW - -The server acts as a gateway and the target endpoint rejected the -connection. The reason the connection was rejected is unspecified. -The gateway cannot forward the original rejection code from the -target endpoint because this would suggest the error was on the -gateway itself. Use this error with some other mechanism to report -the original target error, if possible. - -#### SRT_REJX_DOWN - -The service is down for maintenance. This can only be reported -when the service has been temporarily replaced by a stub that is only -reporting this error, while the real service is down for maintenance. - -#### SRT_REJX_VERSION - -Application version not supported. This can refer to an application feature -that is unsupported (possibly from an older SRT version), or to a feature -that is no longer supported because of backward compatibility requirements. - -#### SRT_REJX_NOROOM - -The data stream cannot be archived due to a lack of storage space. This is -reported when a request to send a file or a live stream to be archived is -unsuccessful. Note that the length of a file transmission is usually -pre-declared, so this error can be reported early. It can also be reported when -the stream is of undefined length, and there is no more storage space -available. - -## Example - -An example of Stream ID functionality and the listener callback can be -found under `tests/test_listen_callback.cpp`. - -A listener can register a callback to be called in the middle of accepting a -new socket connection: - -```c++ -srt_listen(server_sock, 5); -srt_listen_callback(server_sock, &SrtTestListenCallback, NULL); -``` - -A callback function has to be implemented by the upstream application. In the -example below, the function tries to interpret the Stream ID value first according -to the Access Control guidelines and to extract the username from the `u` key. -Otherwise it falls back to a free-form specified username. Depending on the user, -it sets the appropriate password for the expected connection so that it can be -rejected if the password isn't correct. If the user isn't found in the -database (`passwd` map) the function itself rejects the connection. Note that -this can be done by both returning -1 and by throwing an exception. - -```c++ -int SrtTestListenCallback(void* opaq, SRTSOCKET ns, int hsversion, - const struct sockaddr* peeraddr, const char* streamid) -{ - using namespace std; - - // opaq is used to pass some further chained callbacks - - // To reject a connection attempt, return -1. - - static const map passwd { - {"admin", "thelocalmanager"}, - {"user", "verylongpassword"} - }; - - // Try the "standard interpretation" with username at key u - string username; - - static const char stdhdr [] = "#!::"; - uint32_t* pattern = (uint32_t*)stdhdr; - bool found = -1; - - // Extract a username from the StreamID: - if (strlen(streamid) > 4 && *(uint32_t*)streamid == *pattern) - { - vector items; - Split(streamid+4, ',', back_inserter(items)); - for (auto& i: items) - { - vector kv; - Split(i, '=', back_inserter(kv)); - if (kv.size() == 2 && kv[0] == "u") - { - username = kv[1]; - found = true; - } - } - - if (!found) - { - cerr << "TEST: USER NOT FOUND, returning false.\n"; - return -1; - } - } - else - { - // By default the whole streamid is username - username = streamid; - } - - // When the username of the client is known, the passphrase can be set - // on the socket being accepted (SRTSOCKET ns). - // The remaining part of the SRT handshaking process will check the - // passphrase of the client and accept or reject the connection. - - // When not found, it will throw an exception - cerr << "TEST: Accessing user '" << username << "', might throw if not found\n"; - string exp_pw = passwd.at(username); - - cerr << "TEST: Setting password '" << exp_pw << "' as per user '" << username << "'\n"; - srt_setsockflag(ns, SRTO_PASSPHRASE, exp_pw.c_str(), exp_pw.size()); - return 0; -} -``` diff --git a/docs/Android/Compiling.md b/docs/Android/Compiling.md deleted file mode 100644 index fbfe8893c..000000000 --- a/docs/Android/Compiling.md +++ /dev/null @@ -1,18 +0,0 @@ -# Establishing a Build Environment -## Installing the Android NDK -The Android NDK is required to build native modules for Android. -Consider installing the latest version of cmake. The higher version of cmake the better. As of writing the current version of CMake is 3.18.4 -You can download Cmake from the following website: -[https://cmake.org/download](https://cmake.org/download/) - -Download the NDK r19 or newer archive from the following site: -[Download the Android NDK on developer.android.com](https://developer.android.com/ndk/downloads/index.html) -To install the Android NDK, simply expand the archive in the folder where you want to install it. -## OpenSSL -Google removed openssl from Android 7+. You must build openssl libs by yourself. -# Configure the NDK path -Edit the ```mkall``` script to configure NDK path. Set the ```NDK``` to the directory where the NDK is installed. -# Build SRT for Android -Run ```/bin/bash mkall > build.log``` script. Libraries will be installed to ```./target-architecture/lib```. -# Export SRT libraries -Run ```/bin/bash packjni``` to generate ```jniLibs``` archive for Android Studio. diff --git a/docs/Android/mkall b/docs/Android/mkall deleted file mode 100755 index dbfe386a3..000000000 --- a/docs/Android/mkall +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -NDK=/opt/android-ndk-r19c - -openssl_ver=1.1.1h -#srt_version=1.4.2 -#srt_branch=dev - -API_LEVEL=28 -# Determine the path of the executing script -BASE_DIR=$(readlink -f $0 | xargs dirname) - -#wget -N https://www.openssl.org/source/openssl-$openssl_ver.tar.gz - -if [ ! -d $BASE_DIR/srt ]; then - git clone https://github.com/Haivision/srt srt -# git -C $BASE_DIR/srt checkout v${srt_version} -# git -C $BASE_DIR/srt checkout -b $srt_branch origin/$srt_branch -fi - -# Clang, binutils, the sysroot, and other toolchain pieces are all installed to $NDK/toolchains/llvm/prebuilt/ -toolchain=$NDK/toolchains/llvm/prebuilt/linux-x86_64 - -# Cross-compiler tool prefix -declare -A target_hosts -target_hosts=( - [armeabi]=arm-linux-androideabi - [arm]=arm-linux-androideabi - [arm64]=aarch64-linux-android - [x86]=i686-linux-android - [x86_64]=x86_64-linux-android -) - -# Cross-compiler prefix for -clang and -clang++ has api version -declare -A target_api -target_api=( - [armeabi]=armv5te-linux-androideabi16 - [arm]=armv7a-linux-androideabi16 - [arm64]=aarch64-linux-android21 - [x86]=i686-linux-android16 - [x86_64]=x86_64-linux-android21 -) - -declare -A sysroots -sysroots=( - [armeabi]=$BASE_DIR/armeabi - [arm]=$BASE_DIR/armeabi-v7a - [arm64]=$BASE_DIR/arm64-v8a - [x86]=$BASE_DIR/x86 - [x86_64]=$BASE_DIR/x86_64 -) - -declare -A archabi -archabi=( - [armeabi]=armeabi - [arm]=armeabi-v7a - [arm64]=arm64-v8a - [x86]=x86 - [x86_64]=x86_64 -) - -$BASE_DIR/mkssl -n $NDK -o $openssl_ver -a $API_LEVEL - -for arch in armeabi arm arm64 x86 x86_64; do - #rm -rf $BASE_DIR/openssl-$openssl_ver - #tar xf $BASE_DIR/openssl-$openssl_ver.tar.gz - #$BASE_DIR/mkssl -t $toolchain -h ${target_hosts[$arch]} -a ${target_api[$arch]} -s $BASE_DIR/openssl-$openssl_ver -i ${sysroots[$arch]} - - git -C $BASE_DIR/srt clean -fd - $BASE_DIR/mksrt -t $toolchain -h ${target_hosts[$arch]} -a ${target_api[$arch]} -s $BASE_DIR/srt -i ${sysroots[$arch]} -b ${archabi[$arch]} -n $NDK -l $API_LEVEL -done diff --git a/docs/Android/mksrt b/docs/Android/mksrt deleted file mode 100755 index 4d45755a4..000000000 --- a/docs/Android/mksrt +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -source prepare_build - -./configure --use-openssl-pc=OFF --CMAKE_PREFIX_PATH=$install_dir --CMAKE_INSTALL_PREFIX=$install_dir --CMAKE_SYSTEM_NAME=Android --CMAKE_SYSTEM_VERSION=$api_lev --CMAKE_ANDROID_NDK=$NDK_HOME --CMAKE_ANDROID_ARCH_ABI=$arch_abi -make -make install diff --git a/docs/Android/mkssl b/docs/Android/mkssl deleted file mode 100755 index 726e4bb05..000000000 --- a/docs/Android/mkssl +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/sh - -while getopts n:o:a: option -do - case "${option}" - in - n) ndk_home=${OPTARG};; - o) ssl_ver=${OPTARG};; - a) api_lev=${OPTARG};; - *) twentytwo=${OPTARG};; - esac -done - - -ANDROID_NDK=$ndk_home -OPENSSL_VERSION=$ssl_ver - -API_LEVEL=$api_lev - -BUILD_DIR=/tmp/openssl_android_build -OUT_DIR=$(pwd) - -BUILD_TARGETS="armeabi armeabi-v7a arm64-v8a x86 x86_64" - -if [ ! -d openssl-${OPENSSL_VERSION} ] -then - if [ ! -f openssl-${OPENSSL_VERSION}.tar.gz ] - then - wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz || exit 128 - fi - tar xzf openssl-${OPENSSL_VERSION}.tar.gz || exit 128 -fi - -cd openssl-${OPENSSL_VERSION} || exit 128 - - -##### Prepare Files ##### -sed -i 's/.*-mandroid.*//' Configurations/15-android.conf -patch -p1 -N <{\$lib}. \$shlibvariant. '\$(SHLIB_EXT)'; -+ -+ if (windowsdll()) { -+ return \$lib . '\$(SHLIB_EXT_IMPORT)'; -+ } -+ return \$lib . '\$(SHLIB_EXT_SIMPLE)'; - } -- sub shlib_simple { -+ -+ sub shlib { - my \$lib = shift; - return () if \$disabled{shared} || \$lib =~ /\\.a$/; - -EOP - -##### remove output-directory ##### -#rm -rf $OUT_DIR - -##### export ndk directory. Required by openssl-build-scripts ##### -export ANDROID_NDK - -##### build-function ##### -build_the_thing() { - TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64 - export PATH=$TOOLCHAIN/$TRIBLE/bin:$TOOLCHAIN/bin:"$PATH" -echo $PATH - make clean - #./Configure $SSL_TARGET $OPTIONS -fuse-ld="$TOOLCHAIN/$TRIBLE/bin/ld" "-gcc-toolchain $TOOLCHAIN" && \ - ./Configure $SSL_TARGET $OPTIONS -fuse-ld="$TOOLCHAIN/$TRIBLE/bin/ld" && \ - make && \ - make install DESTDIR=$DESTDIR || exit 128 -} - -##### set variables according to build-tagret ##### -for build_target in $BUILD_TARGETS -do - case $build_target in - armeabi) - TRIBLE="arm-linux-androideabi" - TC_NAME="arm-linux-androideabi-4.9" - #OPTIONS="--target=armv5te-linux-androideabi -mthumb -fPIC -latomic -D__ANDROID_API__=$API_LEVEL" - OPTIONS="--target=armv5te-linux-androideabi -mthumb -fPIC -latomic -D__ANDROID_API__=$API_LEVEL" - DESTDIR="$BUILD_DIR/armeabi" - SSL_TARGET="android-arm" - ;; - armeabi-v7a) - TRIBLE="arm-linux-androideabi" - TC_NAME="arm-linux-androideabi-4.9" - OPTIONS="--target=armv7a-linux-androideabi -Wl,--fix-cortex-a8 -fPIC -D__ANDROID_API__=$API_LEVEL" - DESTDIR="$BUILD_DIR/armeabi-v7a" - SSL_TARGET="android-arm" - ;; - x86) - TRIBLE="i686-linux-android" - TC_NAME="x86-4.9" - OPTIONS="-fPIC -D__ANDROID_API__=${API_LEVEL}" - DESTDIR="$BUILD_DIR/x86" - SSL_TARGET="android-x86" - ;; - x86_64) - TRIBLE="x86_64-linux-android" - TC_NAME="x86_64-4.9" - OPTIONS="-fPIC -D__ANDROID_API__=${API_LEVEL}" - DESTDIR="$BUILD_DIR/x86_64" - SSL_TARGET="android-x86_64" - ;; - arm64-v8a) - TRIBLE="aarch64-linux-android" - TC_NAME="aarch64-linux-android-4.9" - OPTIONS="-fPIC -D__ANDROID_API__=${API_LEVEL}" - DESTDIR="$BUILD_DIR/arm64-v8a" - SSL_TARGET="android-arm64" - ;; - esac - - rm -rf $DESTDIR - build_the_thing -#### copy libraries and includes to output-directory ##### - mkdir -p $OUT_DIR/$build_target/include - cp -R $DESTDIR/usr/local/include/* $OUT_DIR/$build_target/include - cp -R $DESTDIR/usr/local/ssl/* $OUT_DIR/$build_target/ - mkdir -p $OUT_DIR/$build_target/lib - cp -R $DESTDIR/usr/local/lib/*.so $OUT_DIR/$build_target/lib - cp -R $DESTDIR/usr/local/lib/*.a $OUT_DIR/$build_target/lib -done - -echo Success diff --git a/docs/Android/packjni b/docs/Android/packjni deleted file mode 100755 index 80e19ac80..000000000 --- a/docs/Android/packjni +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -BASE_DIR=$(readlink -f $0 | xargs dirname) - -declare -A sysroots -sysroots=( - [armeabi]=$BASE_DIR/armeabi - [arm]=$BASE_DIR/armeabi-v7a - [arm64]=$BASE_DIR/arm64-v8a - [x86]=$BASE_DIR/x86 - [x86_64]=$BASE_DIR/x86_64 -) - -srt_version=1.4.2 -jni_dir=$BASE_DIR/jniLibs - -declare -A jnilibs -jnilibs=( - [armeabi=$jni_dir/armeabi - [arm]=$jni_dir/armeabi-v7a - [arm64]=$jni_dir/arm64-v8a - [x86]=$jni_dir/x86 - [x86_64]=$jni_dir/x86_64 -) - -jni_dir=$BASE_DIR/jniLibs - -# Android < 6.0 has an issue with loading versioned libraries -# The issue is because of library so-name libsrt.so.1 - -for arch in armeabi arm arm64 x86 x86_64; do - mkdir -p ${jnilibs[$arch]} - cp ${sysroots[$arch]}/lib/libsrt.so ${jnilibs[$arch]}/libsrt.so - /usr/local/bin/patchelf --set-soname libsrt.so ${jnilibs[$arch]}/libsrt.so - objdump -p ${jnilibs[$arch]}/libsrt.so | grep libsrt.so -done - -zip -r libsrt_$(date +%Y-%m-%d).zip jniLibs diff --git a/docs/Android/prepare_build b/docs/Android/prepare_build deleted file mode 100644 index c0b2cd987..000000000 --- a/docs/Android/prepare_build +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -while getopts t:h:a:s:i:b:n:l: option -do - case "${option}" - in - t) toolchain_dir=${OPTARG};; - h) target_host=${OPTARG};; - a) target_host_api=${OPTARG};; - s) src_dir=${OPTARG};; - i) install_dir=$OPTARG;; - b) arch_abi=${OPTARG};; - n) NDK_HOME=${OPTARG};; - l) api_lev=${OPTARG};; - *) twentytwo=${OPTARG};; - esac -done - -# Add toolchain to the search path. -export PATH=$PATH:$toolchain_dir/bin - -# Tell configure what tools to use. -export AR=$target_host-ar -export AS=$target_host-as -export LD=$target_host-ld -export STRIP=$target_host-strip - -# Tell configure which android api to use. -export CC=$target_host_api-clang -export CXX=$target_host_api-clang++ - -# Tell configure what flags Android requires. -export CFLAGS="-fPIE -fPIC" -export LDFLAGS="-pie" - -cd $src_dir diff --git a/docs/BuildOptions.md b/docs/BuildOptions.md deleted file mode 100644 index 2e1ec0b12..000000000 --- a/docs/BuildOptions.md +++ /dev/null @@ -1,399 +0,0 @@ -# Build System - -The main build system for SRT is provided by the `cmake` tool, which can be -used directly. There's also a wrapper script named `configure` (requires Tcl -interpreter) that can make operating with the options easier. - - -## Portability - -The `cmake` build system was tested on the following platforms: - - - Linux (various flavors) - - macOS (see this [separate document](build_iOS.md)) - - Windows with MinGW - - Windows with Microsoft Visual Studio (see this [separate document](build-win.md)) - - Android (see this [separate document](Android/Compiling.md)) - - Cygwin (only for testing) - -The `configure` script wasn't tested on Windows (other than on Cygwin). - - -## The `configure` Script - -This script is similar in design to the Autotools' `configure` script, and -so usually handles `--long-options`, possibly with values. It handles -two kinds of options: - -* special options to be resolved inside the script and that may do some -advanced checks; this should later turn into a set of specific `cmake` -variable declarations - -* options that are directly translated to `cmake` variables. - -The direct translate option always does a simple transformation: - -* all letters uppercase -* dash into underscore -* plus into X -* when no value is supplied, it defaults to 1 - -For example, `--enable-c++11` turns into `-DENABLE_CXX11=1` when passed -to `cmake`. - -Additionally, if you specify `--disable-`, the `configure` script -will automatically turn it into an associated `--enable-` option, - passing `0` as its value. For example, `--disable-encryption` will -be translated for `cmake` into `-DENABLE_ENCRYPTION=0`. - -### Build Options - -All options below are presented using the `configure` convention. They can all -be used in `cmake` with the appropriate format changes. - - -**`--cygwin-use-posix`** (default:OFF) - -When ON, compile on Cygwin using POSIX API (otherwise it will use MinGW environment). - - -**`--enable-apps`** (default: ON) - -Enables compiling user applications. - - -**`--enable-code-coverage`** (default: OFF) - -Enable instrumentation for code coverage. Note that this is only available -on platforms with GNU-compatible compiler. - - -**`--enable-c++-deps`** (default: OFF) - -The `pkg-confg` file (`srt.pc`) will be generated with the `libstdc++` library -as a dependency. This may be required in some cases where you have an application -written in C which therefore won't link against `libstdc++` by default. - -**`--enable-c++11`** (default: ON) - -Enable compiling in C++11 mode for those parts that may require it. -Parts that don't require it will still be compiled in C++03 mode, -although which parts are affected may change in future. - -If this option is turned OFF, it affects building a project in two ways: - -* an alternative C++03 implementation can be used, if available -* otherwise the component that requires it will be disabled - -Parts that currently require C++11 and have no alternative implementation -are: - -* unit tests -* user and testing applications (such as `srt-live-transmit`) -* some of the example applications - -It should be possible to compile the SRT library without C++11 support. However, -this alternative C++03 implementation may be unsupported on certain platforms. - - -**`--enable-debug=<0,1,2>`** - -This option allows control through the `CMAKE_BUILD_TYPE` variable: - -* 0 (default): `Release` (highly optimized, no debug info) -* 1: `Debug` (not optimized, full debug info) -* 2: `RelWithDebInfo` (highly optimized, but with debug info) - -Please note that when the value is other than 0, the -`--enable-heavy-logging` option is also turned ON by default. - - -**`--enable-encryption`** (default: ON) - -Encryption feature enabled, which involves dependency on an external encryption -library (default: openssl). If you disable encryption, the library will be unable -to set encryption options. It will be compatible with a peer that has -encryption enabled, but just won't use encryption for the connection. - - -**`--enable-getnameinfo`** (default: OFF) - -Enables the use of `getnameinfo` using options that allow using reverse DNS to -resolve an internal IP address into a readable internet domain name, so that it -can be shown nicely in the log file. This option is turned OFF by default -because it may have an impact on general performance. It is recommended only for -development when testing on a local network. - - -**`--enable-haicrypt-logging`** (default: OFF) - -Enables logging in the *haicrypt* module, which serves as a connector to -an encryption library. Logging here might be seen as unsafe, therefore this -option is turned OFF by default. - - -**`--enable-heavy-logging`** (default: OFF in release mode) - -This option enables the logging instructions in the code, which are considered -heavy as they occur often and cover many detailed aspects of library behavior. -Turning this option ON will allow you to use the `debug` level of logging and get -detailed information as to what happens inside the library. Note, however, that -this may influence processing by changing times, using less preferred thread -switching layouts, and generally worsen the functionality and performance of -the library. For these reasons this option is turned OFF by default. - - -**`--enable-inet-pton`** (default: ON) - -Enables usage of `inet_pton` function by the applications, which should be used -to resolve the network endpoint name into an IP address. This may be not -availabe on some version of Windows, in which case you can turn this OFF. -When this option is OFF, however, IP addresses cannot be resolved by name, -as the `inet_pton` function gets a poor-man's simple replacement that can -only resolve numeric IPv4 addresses. - - -**`--enable-logging`** (default: ON) - -Enables logging. When you turn this option OFF, the library will not report -any runtime information through the logging system, including errors. -This option may be useful if you suspect the logging system of -impairing performance. - - -**`--enable-monotonic-clock`** (default: OFF) - -This option enforces the use of `clock_gettime` to get the current -time, instead of `gettimeofday`. This function forces the use of a monotonic -clock that is independent of the currently set time in the system. -The condition variables (CV), for which the `*_timedwait()` functions are used -with time specification based on the time obtained from `clock_gettime` -must be appropriately configured. For now, this is only done for the -GarbageCollector controlling CV, not every CV used in SRT. The consequence -of enabling this option, however, may be portability issues resulting from -the fact that `clock_gettime` function may be unavailable in some SDKs or that an -extra `-lrt` option is sometimes required (this requirement will be autodetected). - -The problem is based on the fact that POSIX functions that use timeout -specification (all of `*_timedwait`) expect the absolute time value. -A relative timeout value can be then only specified by adding it to -the current time, which can be specified as either system or monotonic -clock (as configured in the resources used in the operation). -However the current time of the monotonic clock can only be obtained by -the `clock_gettime` function. - -**NOTE:** *This is a temporary fix for Issue #729* where the library could get -stuck if the system clock is modified during an SRT transmission. This option -will be removed when the problem is fixed globally. - - -**`--enable-stdcxx-sync`** (default: OFF) - -This option enables the standard C++ `thread` and `chrono` libraries (available since C++11) -to be used by SRT instead of the `pthreads`. - - -**`--enable-profile`** (default: OFF) - -Enables code instrumentation for profiling. - -This is available only for GNU-compatible compilers. - - -**`--enable-relative-libpath`** (default: OFF) - -Enables adding a relative path to a library. This allows applications to be -linked against a shared SRT library by reaching out to a sibling `../lib` -directory, provided that the library and applications are installed in POSIX/GNU -style directories. This might be useful when installing SRT and applications -in a directory, in which the library subdirectory is not explicitly defined -among the global library paths. Consider, for example, this application and its -required library: - -* `/opt/srt/bin/srt-live-transmit` -* `/opt/srt/lib64/libsrt.so` - -By using the `--enable-relative-libpath` option, the `srt-live-transmit` -application has a relative library path defined inside as `../lib64`. A dynamic -linker will find the required `libsrt.so` file by this path: `../lib64/libsrt.so`. -This way the dynamic linkage will work even if `/opt/srt/lib64` path isn't added -to the system paths in `/etc/ld.so.conf` or in the `LD_LIBRARY_PATH` environment -variable. - -This option is OFF by default because of reports that it may cause problems in -case of default installation. - - -**`--enable-shared`** and **`--enable-static`** (default for both: ON) - -Enables building SRT as a shared and/or static library, as required for your -application. In practice, you would only disable one or the other -(e.g. by `--disable-shared`). Note that you can't disable both at once. - - -**`--enable-testing`** (default: OFF) - -Enables compiling of developer testing applications. - - -**`--enable-thread-check`** (default: OFF) - -Enables `#include `, which implements `THREAD_*` macros" to -support better thread debugging. Included to support an existing project. - - -**`--enable-unittests`** (default: OFF) - -When ON, this option enables unit tests, possibly with the download -and installation of the Google test library in the build directory. The tests -will be run as part of the build process. This is intended for developers only. - - -**`--openssl-crypto-library=`** - -Configure the path to an OpenSSL Crypto library. - - -**`--openssl-include-dir=`** - -Configure the path to include files for an OpenSSL library. - - -**`--openssl-ssl-library=`** - -Configure the path to an OpenSSL SSL library. - - -**`--pkg-config-executable=`** - -Configure the path to the `pkg-config` tool. - - -**`--prefix=`** - -This is an alias to the `--cmake-install-prefix` variable that establishes the -root directory for installation, inside of which a GNU/POSIX compatible -directory layout will be used. As on all known build systems, this defaults to -`/usr/local` on GNU/POSIX compatible systems, with lower level GNU/POSIX -directories created inside: `/usr/local/bin`,`/usr/local/lib`, etc. - - -**`--pthread-include-dir=`** - -Configure the path to include files for a pthread library. Note that this -is useful only on Windows. On Linux and macOS this path should be available in -the system. - - -**`--pthread-library=`** - -Configure the path to a pthread library. - - -**`--use-busy-waiting`** (default: OFF) - -Enable more accurate sending times at the cost of potentially higher CPU load. - -This option will cause more empty loop running, which may cause more CPU usage. -Keep in mind, however, that when processing high bitrate streams the share of -empty loop runs will decrease as the bitrate increases. This way higher CPU -usage would still be productive, while without system-supported waiting this -option may increase the likelihood of switching to the right thread at the time -when it is expected to be revived. - -**`--use-c++-std=`** - - - -**`--use-gnustl`** - -Use `pkg-config` with the `gnustl` package name to extract the header and -library path for the C++ standard library (instead of using the compiler -built-in one). - - -**`--use-enclib=`** - -Encryption library to be used. Possible options for ``: - -* openssl (default) -* gnutls (with nettle) -* mbedtls - - -**`--use-openssl-pc`** (default: ON) - -Use `pkg-config` to find OpenSSL libraries. You can turn this OFF to force -`cmake` to find OpenSSL by its own preferred method. - - -**`--use-static-libstdc++`** (default: OFF) - -Enforces linking the SRT library against the static libstdc++ library. This may -be useful if you are using SRT library in an environment where it would by -default link against the wrong version of the C++ standard library, or when the -library in the version used by the compiler is not available as shared. - - -**`--with-compiler-prefix=`** - -Sets C/C++ toolchains as `` and ``. - -This option will override the default compiler autodetected by `cmake`. -It is handled inside `cmake`. It sets the variables `CMAKE_C_COMPILER` and -`CMAKE_CXX_COMPILER`. The values for the above `` and -`` are controlled by the `--with-compiler-type` option. -When this option is not supplied, a system-default compiler will be -used, that is: - -* On Mac OS (Darwin): clang -* On other POSIX systems: gcc -* On other systems: obtained from `CMAKE_C_COMPILER` variable - -Instead of `--with-compiler-prefix` you can use `--cmake-c-compiler` -and `--cmake-c++-compiler` options. This can be thought of as a -shortcut, useful when you have a long path to the compiler command. - -NOTE: The prefix is meant to simply precede the compiler type as pure -prefix, so if your prefix is a full path to the compiler, it must include -the terminal path separator character, as this can be also used as a -prefix for a platform-specific cross compiler. For example, if the path -to the C compiler is: `/opt/arm-tc/bin/arm-linux-gnu-gcc-7.4`, then -you should specify `--with-compiler-prefix=/opt/arm-tc/bin/arm-linux-gnu-` -and `--with-compiler-type=gcc-7.4`. - -**`--with-compiler-type=`** - -Sets the compiler type to be used as `` and `` -respectively: - -* gcc (default): gcc and g++ -* cc: cc and c++ -* others: use `` as C compiler and `++` as C++ compiler - -This should be the exact command used as a C compiler, possibly with -version suffix, e.g. `clang-1.7.0`. If this option is used together -with `--with-compiler-prefix`, its prefix will be added in front. - -**`--with-extralibs=`** - -This is an option required for unusual situations when a platform-specific -workaround is needed and some extra libraries must be passed explicitly -for linkage. The argument is a space-separated list of linker options -or library names. - -There are some known sitautions where it may be necessary: - -1. Some older Linux systems do not ship `clock_gettime` functions by -default in their libc, and need an extra librt. If you are using POSIX -monotonic clocks (see `--enable-monotonic-clock`), this might be required -to add `-lrd` through this option. Although this situation is tried to -be autodetected and this option added automatically, it might sometimes fail. - -2. On some systems (found so far on OpenSuSE), if you use C++11 sync -(see `--enable-stdc++-sync`), the gcc compiler relies on gthreads, which -relies on pthreads, and happens to define inline source functions in -the header that refers to `pthread_create`, the compiler however doesn't -link against pthreads by default. To work this around, add `-pthreads` -using this option. - diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..8c07ee515 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,77 @@ +# Documentation Overview + +## 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 Rejection Codes](API/rejections-codes.md) | [API](API/) | [rejection-codes.md](API/rejection-codes.md) | The list of SRT rejections codes. | +| [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. | +| [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. | +| | | | | + +## Features + +| Document Title | Folder | File Name | Description | +| :----------------------------------------------------------- | :---------------------------- | :----------------------------------------------------------- | :----------------------------------------------------------- | +| [SRT Access Control
(Stream ID) Guidelines](features/access-control.md) | [features](features/) | [access-control.md](features/access-control.md) | Access Control (Stream ID) guidelines. | +| [SRT Connection Bonding: Quick Start](features/bonding-quick-start.md) | [features](features/) | [bonding-quick-start.md](features/bonding-quick-start.md) | SRT Connection Bonding Quick Start. | +| [SRT Connection Bonding: Introduction](features/bonding-intro.md) | [features](features/) | [bonding-intro.md](features/bonding-intro.md) | Introduction to Connection Bonding. Description
of group (bonded) connections. | +| [SRT Connection Bonding: Socket Groups](features/socket-groups.md) | [features](features/) | [socket-groups.md](features/socket-groups.md) | Description of socket groups in SRT (Connection
Bonding). Here you will also find information
regarding the `srt-test-live` application for testing
Connection Bonding. | +| [SRT Connection Bonding: Main/Backup][main-backup] | [features](features/) | [bonding-main-backup.md][main-backup] | Main/Backup mode description. | +| [SRT Encryption](features/encryption.md) | [features](features/) | [encryption.md](features/encryption.md) | Description of SRT encryption mechanism. This
document might be outdated, please consult
[Section 6. Encryption][srt-internet-draft-sec-6] of the [Internet Draft][srt-internet-draft] additionally. | +| [SRT Handshake](features/handshake.md) | [features](features/) | [handshake.md](features/handshake.md) | Description of SRT handshake mechanism. This
document might be outdated, please consult
[Section 3.2.1 Handshake][srt-internet-draft-sec-3-2-1] and
[Section 4.3 Handshake Messages](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-4.3) of the
[Internet Draft][srt-internet-draft] additionally. | +| [Live Streaming
Guidelines](features/live-streaming.md) | [features](features/) | [live-streaming.md](features/live-streaming.md) | Guidelines for live streaming with SRT. See also
best practices and configuration tips in
[Section 7.1 Live Streaming](https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-7.1) of the [Internet Draft][srt-internet-draft]. | +| [SRT Packet
Filtering & FEC][packet-filter] | [features](features/) | [packet-filtering-and-fec.md][packet-filter] | Description of SRT packet filtering mechanism,
including FEC. | +| | | | | + +## Sample Applications + +| Document Title | Folder | File Name | Description | +| :--------------------------------------------------------------------- | :-------------------- | :-------------------------------------------------- | :------------------------------------------------------------ | +| [Using the
`srt-live-transmit` App](apps/srt-live-transmit.md) | [apps](apps/) | [srt-live-transmit.md](apps/srt-live-transmit.md) | A sample application to transmit a live stream from
source medium (UDP/SRT/`stdin`) to the target medium
(UDP/SRT/`stdout`). | +| [Using the
`srt-file-transmit` App](apps/srt-file-transmit.md) | [apps](apps/) | [srt-file-transmit.md](apps/srt-file-transmit.md) | A sample application to transmit a file over SRT | +| [Using the
`srt-tunnel` App](apps/srt-tunnel.md) | [apps](apps/) | [srt-tunnel.md](apps/srt-tunnel.md) | A sample application to set up an SRT tunnel for TCP traffic. | +| [Using the
`srt-test-multiplex` App](apps/srt-test-multiplex.md) | [apps](apps/) | [srt-test-multiplex.md](apps/srt-test-multiplex.md) | Testing application that allows to send multiple streams over one UDP link. | +| [Using the
`srt-test-relay` App](apps/srt-test-relay.md) | [apps](apps/) | [srt-test-relay.md](apps/srt-test-relay.md) | Testing application for bidirectional stream sending over one connection. | +| | | | | + +## Miscellaneous + +| Document Title | Folder | File Name | Description | +| :------------------------------------------------- | :---------------------------- | :---------------------------------------------------- | :----------------------------------------------------------- | +| [Why SRT Was Created](misc/why-srt-was-created.md) | [misc](misc/) | [why-srt-was-created.md](misc/why-srt-was-created.md) | Background and history of SRT. See also
[Section 1. Introduction][srt-internet-draft-sec-1] of the [Internet Draft][srt-internet-draft]. | +| | | | | + + +[srt-internet-draft]: https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01 +[srt-internet-draft-sec-1]: https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-1 +[srt-internet-draft-sec-3-2-1]: https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-3.2.1 +[srt-internet-draft-sec-6]: https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-6 + +[main-backup]: features/bonding-main-backup.md +[packet-filter]: features/packet-filtering-and-fec.md diff --git a/docs/SRT-Multiplex.md b/docs/SRT-Multiplex.md deleted file mode 100644 index 80dbd0411..000000000 --- a/docs/SRT-Multiplex.md +++ /dev/null @@ -1,98 +0,0 @@ -## srt-multiplex - -**srt-multiplex** (formerly called "SIPLEX") is a sample program that can send -multiple streams in one direction. This tool demonstrates two SRT features: - - the ability to use a single UDP link (a source and destination pair - specified by IP address and port) for multiple SRT connections - - the use of the `streamid` socket option to identify multiplexed resources - -NOTE: due to changes in the common code that can't be properly handled in the -current form of srt-multiplex, this application is temporarily blocked. Instead -the `srt-test-multiplex` application was added with the same functionality, -although it's recommended for testing purposes only. - -#### Usage - -`srt-multiplex -i [id] [id]...` - - - Multiplexes data from one or more input URIs to transmit as an SRT stream. - The application reads multiple streams (INPUT URIs), each using a separate SRT - connection. All of the traffic from these connections is sent through the - same UDP link. - -`srt-multiplex -o [id] [id]...` - - - Transmits data from a multiplexed SRT stream to the specified output URI(s). - -An `` can be identified as input or output using the **-i** or **-o** -options. When `-i` is specified, the URIs provided are used as input, and will -be output over the `` socket. The reverse is true for any output URIs -specified by `-o`. - -Separate connections will be created for every specified URI, although all will -be using the same UDP link. When SRT is in caller mode, the SRT socket created -for transmitting data for a given URI will be set to the `streamid` socket option -from this URI's `id` parameter. When SRT is in listener mode, the `streamid` -option will already be set on the accepted socket, and will be matched with a -URI that has the same value in its `id` parameter. - -This `streamid` is the SRT socket option (`SRTO_STREAMID` in the API). The idea -is that it can be set on a socket used for connecting. When a listener is -getting an accepted socket for that connection, the `streamid` socket option -can be read from it, with the result that it will be the same as was set on -the caller side. - -So, in caller mode, for every stream media URI (input or output) there will be -a separate SRT socket created. This socket will have its `socketid` option -set to the value that is given by user as the `id` parameter attached to a -particular URI. In listener mode this happens in the opposite direction — the -value of the `streamid` option is extracted from the accepted socket, and then -matched against all ids specified with the stream media URIs: -``` -URI1?id=a --> s1(streamid=a).connect(remhost:2000) -URI2?id=b --> s2(streamid=b).connect(remhost:2000) -URI3?id=c --> s3(streamid=c).connect(remhost:2000) -``` -And on the listener side: -``` -(remhost:2000) -> accept --> s(SRT socket) --> in URI array find such that uri.id == s.streamid -``` - -#### Examples - - - **Sender:** - - `srt-multiplex srt://remhost:2000 -i udp://:5000?id=low udp://:6000?id=high` - - **Receiver:** - - `srt-multiplex srt://:2000 -o output-high.ts?id=high output-low.ts?id=low` - -In this example a Sender is created which will connect to `remhost` port 2000 -using multiple SRT sockets, all of which will be using the same outgoing port. -Here the outgoing port is automatically selected when connecting. Subsequent -sockets will reuse that port. Alternatively you can enforce the outgoing port -using the `port` parameter with the ``. - - - **Sender:** - - `srt-multiplex srt://remhost:2000?port=5555 ...` - -A separate connection is made for every input resource. An appropriate resource -ID will be set to each socket assigned to that resource according to the `id` -parameter. -``` - +-- --+ - | id=1 id=1 | - | ------ ------- | - | \ -----> / | - | id=2 \ ---------------------------- / id=2 | -port=5555 -| --------- ( multiplexed UDP stream ) ---------- |- port=2000 - | / ---------------------------- \ | - | id=3 / \ id=3 | - | ------ ------ | - +-- --+ -``` -When a socket is accepted on the listener side (the Receiver in this example), -srt-multiplex will search for the resource ID among the registered resources -(input/output URIs) and set an ID that matches the one on the caller side. If -the resource is not found, the connection is closed immediately. - -The srt-multiplex program works the same way for connections initiated by a -caller or a listener. diff --git a/docs/apps/srt-file-transmit.md b/docs/apps/srt-file-transmit.md new file mode 100644 index 000000000..2bf3b1115 --- /dev/null +++ b/docs/apps/srt-file-transmit.md @@ -0,0 +1,55 @@ +# srt-file-transmit + +The `srt-file-transmit` tool is a tool for transmitting files over SRT. + +You need: + + - a file to transmit + - a destination to store it into + - this application run on both sides, one sending, one receiving + +## Introduction + +The `srt-file-transmit` application will transmit your file over the SRT connection, +the application on the other side will receive it and store to the desired location. +Both caller-listener and rendezvous arrangement of the connection are possible +and in whatever direction. + +The `streamid` socket option will be used to pass the filename to the other side +so that it is either written with this name or matched with the filename internally. + +The application the will be sending a file should use the file path as source and +SRT URI as a destination, and vice versa for receiving. + +## Caller mode + +If you use sender in caller mode, then the caller SRT URI destination should be +specified, and the "root name" from the file path will be set to `streamid`. +This will allow the listener to use it when writing. + +If a receiver is used as a caller, then the destination filepath's rootname +will be also passed as `streamid` so that the listener receiver can pick up the +file by name. + +In caller mode you must specify the full filename path of the received or sent +file. + +## Listener mode + +If you use sender in listener mode, then you start it with specifying either the +full filename path, or only the directory where the file is located; in the latter +case the filename will be tried from the `streamid` option extracted from the +connected socket (as set by the other side's caller). If the full filename was +specified, it must match the rootname extraced from this option, or otherwise +transmission will not be done. + +If you use receiver in listener mode, then you start it with specifying either +the full filename path, or just the directory. In the latter case the root name +will be extracted from `streamid` socket option, and this one will be transmitted. + +## Usage + +``` +srt-file-transmit [options] +``` + diff --git a/docs/srt-live-transmit.md b/docs/apps/srt-live-transmit.md similarity index 78% rename from docs/srt-live-transmit.md rename to docs/apps/srt-live-transmit.md index ec29a2f1c..48741df23 100644 --- a/docs/srt-live-transmit.md +++ b/docs/apps/srt-live-transmit.md @@ -17,6 +17,7 @@ The following medium types are handled by `srt-live-transmit`: - SRT - use SRT for reading or writing, in listener, caller or rendezvous mode, with possibly additional parameters - UDP - read or write the given UDP address (also multicast) +- RTP - read RTP from the given address (also multicast) - Local file - read or store the stream into the file - Process's pipeline - use the process's `stdin` and `stdout` standard streams @@ -62,6 +63,16 @@ You should see the stream connect in `srt-live-transmit`. Now you can test in VLC (make sure you're using the latest version!) - just go to file -> open network stream and enter `srt://127.0.0.1:4201` and you should see bars and tone right away. +Or you can test using ffplay or ffprobe to inspect the stream: + +```shell +ffplay srt://127.0.0.1:4201 +``` +-or- +```shell +ffprobe srt://127.0.0.1:4201 +``` + If you're having trouble, make sure this works, then add complexity one step at a time (multicast, push vs listen, etc.). ## URI Syntax @@ -76,6 +87,7 @@ The applications supports the following schemes: - `file` - for file or standard input and output - `udp` - UDP output (unicast and multicast) +- `rtp` - RTP input (unicast and multicast) - `srt` - SRT connection Note that this application doesn't support file as a medium, but this @@ -107,6 +119,16 @@ The specification and meaning of the fields in the URI depend on the mode. The **PORT** part is always mandatory and it designates either the port number for the target host or the port number to be bound to read from. +The following options are available through URI parameters: + +- **iptos**: sets the `IP_TOS` socket option +- **ttl**: sets the `IP_TTL` or `IP_MULTICAST_TTL` option, depending on mode +- **mcloop**: sets the `IP_MULTICAST_LOOP` option (multicast mode only) +- **rcvbuf**: sets the `SO_RCVBUF` socket option +- **sndbuf**: sets the `SO_SNDBUF` socket option +- **adapter**: sets the local binding address +- **source**: uses `IP_ADD_SOURCE_MEMBERSHIP`, see below for details + For sending to unicast: ```yaml @@ -163,6 +185,25 @@ instead of `IP_ADD_MEMBERSHIP` and the value is set to `imr_sourceaddr` field. Explanations for the symbols and terms used above can be found in POSIX manual pages, like `ip(7)` and on Microsoft docs pages under `IPPROTO_IP`. +### Medium: RTP + +RTP is supported for input only. + +All URI parameters described in the [Medium: UDP](#medium-udp) section above +also apply to RTP. A further RTP-specific option is available as an URI +parameter: + +- **rtpheadersize**: sets the number of bytes to drop from the beginning of +each received packet. Defaults to 12 if not provided. Minimum value is 12. + +A length of **rtpheadersize** bytes will always be dropped. If you wish to pass +the entire packet, including RTP header, to the output medium, you should +instead specify UDP as the input medium. + +> NOTE: No effort is made in the initial implementation to attempt to parse +the RTP headers in any way eg for validation, reordering, extracting timing, +length detection of checking. + ### Medium: SRT Most important about SRT is that it can be either input or output and in @@ -173,7 +214,7 @@ options that can be set through the parameters. SRT can be connected using one of three connection modes: - **caller**: the "agent" (this application) sends the connection request to - the peer, which must be **listener**, and this way it initiates the +the peer, which must be **listener**, and this way it initiates the connection. - **listener**: the "agent" waits to be contacted by any peer **caller**. @@ -182,50 +223,74 @@ does not use this ability; after the first connection, it no longer accepts new connections. - **rendezvous**: A one-to-one only connection where both parties are - equivalent and both connect to one another simultaneously. Whoever happened -to start first (or succeeded to punch through the firewall) is meant to have +equivalent and both attempt to initiate a connection simultaneously. Whichever party happens +to start first (or succeeds in punching through the firewall first) is considered to have initiated the connection. This mode can be specified explicitly using the **mode** parameter. When it's -not specified, then it is "deduced" the following way: +not specified, then it is derived based on the *host* part in the URI and +the presence of the **adapter** parameter: -- `srt://:1234` - the *port* is specified (1234), but *host* is empty. This assumes **listener** mode. -- `srt://remote.host.com:1234` - both *host* and *port* are specified. This assumes **caller** mode. +* Listener mode: if you leave the *host* part empty (**adapter** may be specified): + - `srt://:1234` +* Caller mode: if you specify *host* part, but not **adapter** parameter: + - `srt://remote.host.com:1234` +* Rendezvous mode: if you specify *host* AND **adapter** parameter: + - `srt://remote.host.com:1234&adapter=my.remote.addr` -When the `mode` parameter is specified explicitly, then the interpretation of the `host` part is the following: +Sometimes the required parameter specification results in a different mode +than desired; in this case you should specify the mode explicitly. -- For caller, it's always the destination host address. If this is empty, it is -resolved to 0.0.0.0, which usually should mean connecting to the local host +The interpretation of the *host* and *port* parts is the following: -- For listener, it defines the IP address of the local device on which the -socket should listen, e.g.: +- In **LISTENER** mode: + - *host* part: the local IP address to bind (default: 0.0.0.0 - "all devices") + - *port* part: the local port to bind (mandatory) + - **adapter** parameter: alternative for *host* part, e.g.: ```yaml srt://10.10.10.100:5001?mode=listener ``` -An alternative method to specify this IP address is the `adapter` parameter: +or ```yaml srt://:5001?adapter=10.10.10.100 ``` -The **rendezvous** mode is not deduced and it has to be specified -explicitly. Note also special cases of the **host** and **port** parts -specified in the URI: - -- **CALLER**: the *host* and *port* parts are mandatory and specify the remote host and port to be contacted. - - The **port** parameter can be used to enforce the local outgoing port (**not to be confused** with remote port!). - - The **adapter** parameter is not used. -- **LISTENER**: the *port* part is mandatory and it specifies the local listening port. - - The **adapter** parameter can be used to specify the adapter. - - The *host* part, if specified, can be also used to set the adapter - although in this case **mode=listener** must be set explicitly. - - The **port** parameter is not used. -- **RENDEZVOUS**: the *host* and *port* parts are mandatory. - - The *host* part specifies the remote host to contact. - - The *port* part specifies **both local and remote port**. Note that the local port is this way both listening port and outgoing port. - - The **adapter** parameter can be used to specify the adapter. - - The **port** parameter can be used to specify the local port to bind to. +- In **CALLER** mode: + - *host* part: remote IP address to connect to (mandatory) + - *port* part: remote port to connect to (mandatory) + - **port** parameter: the local port to bind (default: 0 - "system autoselection") + - **adapter** parameter: the local IP address to bind (default: 0.0.0.0 - "system selected device") + - **bind** parameter: a shortcut to set adapter or port by specifying ADAPTER:PORT + +```yaml +srt://remote.host.com:5001 +``` + +```yaml +srt://remote.host.com:5001?adapter=local1&port=4001&mode=caller +``` + +- In **RENDEZVOUS** mode: same as **CALLER** except that the local +port, if not specified by the **port** parameter, defaults to the +value of the remote port (specified in the *port* part in the URI). + +```yaml +srt://remote.host.com:5001?mode=rendezvous +``` +(uses `remote.host.com` port 5001 for a remote host and the default +network device for routing to this host; the connection from the peer is +expected on that device and port 5001) + + +```yaml +srt://remote.host.com:5001?port=4001&adapter=local1 +``` +(uses `remote.host.com` port 5001 for a remote host and the peer +is expected to connect to `local1` address and port 4001) + **IMPORTANT** information about IPv6. @@ -238,16 +303,18 @@ the following restrictions: 2. In listener mode, if you leave the host empty, the socket is bound to `INADDR_ANY` for IPv4 only. If you want to make it listen on IPv6, you need to specify the host as `::`. -NOTE: Don't use square brackets syntax in the adapter specification, -as in this case only the host is expected. - -3. If you want to listen for connections from both IPv4 and IPv6, mind the -`ipv6only` option. The default value for this option is system default (see -system manual for `IPV6_V6ONLY` socket option); if unsure, you might want to -enforce `ipv6only=0` in order to be able to accept both IPv4 and IPv6 -connections in the same listener. - -4. In rendezvous mode you may only interconnect both parties using IPv4, +NOTE: Don't use square brackets syntax in the **adapter** parameter +specification, as in this case only the host is expected. + +3. If you bind to an IPv6 wildcard address (with listener mode, or when using the `bind` +option), setting the `ipv6only` option to 0 or 1 is obligatory, as it is a part +of the binding definition. If you set it to 1, the binding will apply only to +IPv6 local addresses, and if you set it to 0, it will apply to both IPv4 and +IPv6 local addresses. See the +[`SRTO_IPV6ONLY`](../API/API-socket-options.md#SRTO_IPV6ONLY) option +description for details. + +4. In rendezvous mode you may only interconnect both parties using IPv4, or both using IPv6. Unlike listener mode, if you want to leave the socket default-bound (you don't specify `adapter`), the socket will be bound with the same IP version as the target address. If you do specify `adapter`, @@ -259,9 +326,8 @@ Examples: * `srt://[::]:5000` defines caller mode (!) with IPv6. -* `srt://[::]:5000?mode=listener` defines listener mode with IPv6. If the - default value for `IPV6_V6ONLY` system socket option is 0, it will accept - also IPv4 connections. +* `srt://[::]:5000?mode=listener&ipv6only=1` defines listener mode with IPv6. + Only connections from IPv6 callers will be accepted. * `srt://192.168.0.5:5000?mode=rendezvous` will make a rendezvous connection with local address `INADDR_ANY` (IPv4) and port 5000 to a destination with @@ -271,32 +337,34 @@ Examples: connection with local address `inaddr6_any` (IPv6) and port 4000 to a destination with port 5000. -* `srt://[::1]:5000?adapter=127.0.0.1&mode=rendezvous` - this URI is invalid - (different IP versions for binding and target address) +* `srt://[::1]:5000?adapter=127.0.0.1` - this URI is invalid + (different IP versions for binding and target address in rendezvous mode) -Some parameters handled for SRT medium are specific, all others are socket options. The following parameters are handled special way by `srt-live-transmit`: +Some parameters handled for SRT medium are specific, all others are socket options. The following parameters are handled in a special way by `srt-live-transmit`: - **mode**: enforce caller, listener or rendezvous mode -- **port**: enforce the **outgoing** port (the port number that will be set in the UDP packet as a source port when sent from this host). This can be used only in **caller mode**. +- **port**: enforce the **outgoing** port (the port number that will be set in the UDP packet as a source port when sent from this host). Not used in **listener** mode. - **blocking**: sets the `SRTO_RCVSYN` for input medium or `SRTO_SNDSYN` for output medium - **timeout**: sets `SRTO_RCVTIMEO` for input medium or `SRTO_SNDTIMEO` for output medium -- **adapter**: sets the adapter for listening in *listener* or *rendezvous* mode +- **adapter**: sets the local IP address to bind -All other parameters are SRT socket options. The following have the following value types: +All other parameters are SRT socket options. The Values column uses the +following type specification: - `bool`. Possible values: `yes`/`no`, `on`/`off`, `true`/`false`, `1`/`0`. -- `bytes` positive integer [1; INT32_MAX]. +- `bytes` positive integer `[1; INT32_MAX]`. - `ms` - positive integer value of milliseconds. | URI param | Values | SRT Option | Description | | -------------------- | ---------------- | ------------------------- | ----------- | | `congestion` | {`live`, `file`} | `SRTO_CONGESTION` | Type of congestion control. | | `conntimeo` | `ms` | `SRTO_CONNTIMEO` | Connection timeout. | +| `cryptomode` | 0..2 | `SRTO_CRYPTOMODE` | Cryptographic mode. | | `drifttracer` | `bool` | `SRTO_DRIFTTRACER` | Enable drift tracer. | | `enforcedencryption` | `bool` | `SRTO_ENFORCEDENCRYPTION` | Reject connection if parties set different passphrase. | | `fc` | `bytes` | `SRTO_FC` | Flow control window size. | | `groupconnect` | {`0`, `1`} | `SRTO_GROUPCONNECT` | Accept group connections. | -| `groupstabtimeo` | `ms` | `SRTO_GROUPSTABTIMEO` | Group stability timeout. | +| `groupminstabletimeo`| 60.. `ms` | `SRTO_GROUPMINSTABLETIMEO`| Group minimum stability timeout. | | `inputbw` | `bytes` | `SRTO_INPUTBW` | Input bandwidth. | | `iptos` | 0..255 | `SRTO_IPTOS` | IP socket type of service | | `ipttl` | 1..255 | `SRTO_IPTTL` | Defines IP socket "time to live" option. | @@ -307,13 +375,14 @@ All other parameters are SRT socket options. The following have the following va | `linger` | 0.. | `SRTO_LINGER` | Link linger value | | `lossmaxttl` | 0.. | `SRTO_LOSSMAXTTL` | Packet reorder tolerance. | | `maxbw` | 0.. | `SRTO_MAXBW` | Bandwidth limit in bytes | +| `mininputbw` | 0.. | `SRTO_MININPUTBW` | Minimum allowed estimate of `SRTO_INPUTBW` | | `messageapi` | `bool` | `SRTO_MESSAGEAPI` | Enable SRT message mode. | | `minversion` | maj.min.rev | `SRTO_MINVERSION` | Minimum SRT library version of a peer. | | `mss` | 76.. | `SRTO_MSS` | MTU size | | `nakreport` | `bool` | `SRTO_NAKREPORT` | Enables/disables periodic NAK reports | | `oheadbw` | 5..100 | `SRTO_OHEADBW` | limits bandwidth overhead, percents | | `packetfilter` | `string` | `SRTO_PACKETFILTER` | Set up the packet filter. | -| `passphrase` | `string` | `SRTO_PASSPHRASE` | Password for the encrypted transmission. | +| `passphrase` | `string` | `SRTO_PASSPHRASE` | Password for the encrypted transmission. (must be 10 to 79 characters) | | `payloadsize` | 0.. | `SRTO_PAYLOADSIZE` | Maximum payload size. | | `pbkeylen` | {16, 24, 32} | `SRTO_PBKEYLEN` | Crypto key length in bytes. | | `peeridletimeo` | `ms` | `SRTO_PEERIDLETIMEO` | Peer idle timeout. | @@ -358,7 +427,7 @@ but this space must be part of the parameter and not extracted by a shell (using **"** **"** quotes or backslash). - **-timeout, -t, -to** - Sets the timeout for any activity from any medium (in seconds). Default is 0 for infinite (that is, turn this mechanism off). The mechanism is such that the SIGALRM is set up to be called after the given time and it's reset after every reading succeeded. When the alarm expires due to no reading activity in defined time, it will break the application. **Notes:** - - The alarm is set up after the reading loop has started, **not when the application has started**. That is, a caller will still wait the standard timeout to connect, and a listener may wait infinitely until some peer connects; only after the connection is established is the alarm counting started. + - The alarm is set up after the reading loop has started, **not when the application has started**. That is, a caller will still wait the standard timeout to connect, and a listener may wait infinitely until some peer connects; only after the connection is established is the alarm counting started. - **The timeout mechanism doesn't work on Windows at all.** It behaves as if the timeout was set to **-1** and it's not modifiable. - **-timeout-mode, -tm** - Timeout mode used. Default is 0 - timeout will happen after the specified time. Mode 1 cancels the timeout if the connection was established. - **-st, -srctime, -sourcetime** - Enable source time passthrough. Default: disabled. It is recommended to build SRT with monotonic (`-DENABLE_MONOTONIC_CLOCK=ON`) or C++ 11 steady (`-DENABLE_STDCXX_SYNC=ON`) clock to use this feature. @@ -366,9 +435,9 @@ shell (using **"** **"** quotes or backslash). - **-chunk, -c** - use given size of the buffer. The default size is 1456 bytes, which is the maximum payload size for a single SRT packet. - **-verbose, -v** - Display additional information on the standard output. Note that it's not allowed to be combined with output specified as **file://con**. - **-statsout** - SRT statistics output: filename. Without this option specified, the statistics will be printed to the standard output. -- **-pf**, **-statspf** - SRT statistics print format. Values: json, csv, default. +- **-pf**, **-statspf** - SRT statistics print format. Values: json, csv, default. After a comma, options can be specified (e.g. "json,pretty"). - **-s**, **-stats**, **-stats-report-frequency** - The frequency of SRT statistics collection, based on the number of packets. -- **-loglevel** - lowest logging level for SRT, one of: *fatal, error, warning, note, debug* (default: *error*) +- **-loglevel** - lowest logging level for SRT, one of: *fatal, error, warn, note, debug* (default: *warn*) - **-logfa, -lfa** - selected FAs in SRT to be logged (default: all are enabled). See the list of FAs running `-help:logging`. - **-logfile:logs.txt** - Output of logs is written to file logs.txt instead of being printed to `stderr`. - **-help, -h** - Show help. @@ -401,7 +470,7 @@ The dedicated research showed that at high and bursty data rates (~60 Mbps) the `epoll_wait(udp_socket)` is not fast enough to signal about the possibility of reading from a socket. It results in losing data when the input bitrate is very high (above 20 Mbps). -PR [#1152](https://github.com/Haivision/srt/pull/1152) (v1.5.0 and above) adds the possibility +PR [#1152](https://github.com/Haivision/srt/pull/1152) (SRT v1.4.2 and above) adds the possibility of setting the buffer size of the UDP socket in `srt-live-transmit`. Having a bigger buffer of UDP socket to store incoming data, `srt-live-transmit` handles higher bitrates. diff --git a/docs/apps/srt-test-multiplex.md b/docs/apps/srt-test-multiplex.md new file mode 100644 index 000000000..1b3d724dd --- /dev/null +++ b/docs/apps/srt-test-multiplex.md @@ -0,0 +1,99 @@ +# srt-test-multiplex + +**srt-test-multiplex** (formerly called "SIPLEX") is a sample program that can +send multiple streams in one direction. This tool demonstrates two SRT features: + - the ability to use a single UDP link (a source and destination pair + specified by IP address and port) for multiple SRT connections + - the use of the `streamid` socket option to identify multiplexed resources + +NOTE: To make this application compiled, you need the `-DENABLE_TESTING=1` +cmake option. + +Note also that this application is intended for demonstration only. It can +simply exit with error message in case of wrong usage or broken connection. + + +## Usage + +`srt-test-multiplex -i [id1] [id2]...` + + - Reads all given input streams and sends them each one over a separate + SRT connection, all using the same remote address and source port (hence + using the same UDP link). + +`srt-test-multiplex -o [id] [id]...` + + - Transmits data from a multiplexed SRT stream to the specified output URI(s). + +An `` can be identified as input or output using the **-i** or **-o** +options. When `-i` is specified, the URIs provided are used as input, and will +be output over the `` socket. The reverse is true for any output URIs +specified by `-o`. + +If SRT-URI is caller mode, then for every declared input or output medium a +separate connection will be made, each one using the same source port (if +specified, the same will be used for all connections, otherwise the first one +will be automatically selected and then reused for all next ones) and with the +`streamid` socket option set to the value extracted from the medium's +`id` specified parameter: +``` +URI1?id=a --> s1(streamid=a).connect(remhost:2000) +URI2?id=b --> s2(streamid=b).connect(remhost:2000) +URI3?id=c --> s3(streamid=c).connect(remhost:2000) +``` + +If SRT-URI is listener mode, then it will extract the value from `streamid` +socket option and every accepted connection will be matched against the `id` +parameter of the specified input or output medium. +``` +(remhost:2000) -> accept --> s(SRT socket) --> in URI array find such that uri.id == s.streamid +``` + +Note that the rendezvous mode is not supported because you cannot make +multiple connections over the same UDP link in rendezvous mode. + +This `streamid` is the SRT socket option (`SRTO_STREAMID` in the API). The idea +is that it can be set on a socket used for connecting. When a listener is +getting an accepted socket for that connection, the `streamid` socket option +can be read from it, with the result that it will be the same as was set on +the caller side. + + +## Examples + + - **Sender:** + - `srt-test-multiplex srt://remhost:2000 -i udp://:5000?id=low udp://:6000?id=high` + - **Receiver:** + - `srt-test-multiplex srt://:2000 -o output-high.ts?id=high output-low.ts?id=low` + +In this example a Sender is created which will connect to `remhost` port 2000 +using multiple SRT sockets, all of which will be using the same outgoing port. +Here the outgoing port is automatically selected when connecting. Subsequent +sockets will reuse that port. Alternatively you can enforce the outgoing port +using the `port` parameter with the ``. + + - **Sender:** + - `srt-test-multiplex srt://remhost:2000?port=5555 ...` + +A separate connection is made for every input resource. An appropriate resource +ID will be set to each socket assigned to that resource according to the `id` +parameter. +``` + +-- --+ + | id=1 id=1 | + | ------ ------- | + | \ -----> / | + | id=2 \ ---------------------------- / id=2 | +port=5555 -| --------- ( multiplexed UDP stream ) ---------- |- port=2000 + | / ---------------------------- \ | + | id=3 / \ id=3 | + | ------ ------ | + +-- --+ +``` +When a socket is accepted on the listener side (the Receiver in this example), +srt-test-multiplex will search for the resource ID among the registered resources +(input/output URIs) and set an ID that matches the one on the caller side. If +the resource is not found, the connection is closed immediately. + +The srt-test-multiplex program works the same way for connections initiated by a +caller or a listener. diff --git a/docs/apps/srt-test-relay.md b/docs/apps/srt-test-relay.md new file mode 100644 index 000000000..85789b6db --- /dev/null +++ b/docs/apps/srt-test-relay.md @@ -0,0 +1,34 @@ +# srt-test-relay + +**srt-test-relay** is a sample program that can utilize SRT connection for +bidirectional traffic. Hence beside the SRT connection you can specify both +input and output media to and from which the traffic will be flipped. + +Effectively the specified input will be sent through the SRT connection as +output, and the input read from the SRT connection will be redirected to +the given output media. + +NOTE: To make this application compiled, you need the `-DENABLE_TESTING=1` +cmake option. + +Note also that this application is intended for demonstration only. It can +simply exit with error message in case of wrong usage or broken connection. + +## Usage + +`srt-test-relay -i -o ` + +Establish a connection, send to it the stream received from INPUT URI and +write the data read from the SRT connection to OUTPUT URI. + +`srt-test-relay -e -o ` + +Establish a connection, read the data from the SRT connection, and write +them back over the SRT connection, and additionally write them as well +to OUTPUT URI and OUTPUT URI2. + +Note that you can also control the single portion of data to be sent +at once by one sending call by `-c` option and you can use both live +and file mode for the connection (the latter should be simply enforced +by `transtype` socket option). + diff --git a/docs/srt-tunnel.md b/docs/apps/srt-tunnel.md similarity index 95% rename from docs/srt-tunnel.md rename to docs/apps/srt-tunnel.md index b38c80038..c664173bf 100644 --- a/docs/srt-tunnel.md +++ b/docs/apps/srt-tunnel.md @@ -1,8 +1,7 @@ -SRT Tunnel -========== +# srt-tunnel -Purpose -------- + +## Purpose SRT Tunnel is a typical tunnelling application, that is, it simply passes the transmission from a given endpoint to another endpoint in both directions. @@ -22,8 +21,7 @@ longer distance, leaving TCP close to the caller and listener locations: --> TCP> --> ``` -Usage ------ +## Usage The `srt-tunnel` command line accepts two argument, beside the options: * Listener: the URI at which this tunnel should await connections diff --git a/docs/build/build-android.md b/docs/build/build-android.md new file mode 100644 index 000000000..7c13c9404 --- /dev/null +++ b/docs/build/build-android.md @@ -0,0 +1,18 @@ +# Building SRT on Android + +**NOTE:** The scripts have been moved to [scripts/build-android](../../scripts/build-android/) folder. + +## Install the NDK and CMake + +The Android NDK is required to build native modules for Android. +[Install and configure the NDK](https://developer.android.com/studio/projects/install-ndk) + +Consider installing the latest version of cmake. The higher version of cmake the better. As of writing the current version of CMake is 3.18.4 +You can download Cmake from the following website: +[https://cmake.org/download](https://cmake.org/download/) + +## Build SRT for Android + +Run ```./build-android -n /path/to/ndk```. E.g. ```./build-android -n /home/username/Android/Sdk/ndk/21.4.7075529``` + +[Include prebuilt native libraries](https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs) from ```prebuilt``` folder into Android Studio project. diff --git a/docs/build_iOS.md b/docs/build/build-iOS.md similarity index 90% rename from docs/build_iOS.md rename to docs/build/build-iOS.md index 1ab7ac75a..a1fd48ba9 100644 --- a/docs/build_iOS.md +++ b/docs/build/build-iOS.md @@ -1,7 +1,7 @@ -# Building SRT for iOS +# Building SRT on iOS ## Prerequisites -* Xcode should be installed. Check in terminal whether `xcode-select -p` points to **/Applications/Xcode.app/Contents/Developer** +* Xcode should be installed. Check in terminal whether `xcode-select -p` points to **/Applications/Xcode.app/Contents/Developer** * Install Homebrew according to instructions on [https://brew.sh/](https://brew.sh/) * Install CMake and pkg-config with Homebrew: ``` @@ -15,7 +15,7 @@ There is [OpenSSL for iPhone](https://github.com/x2on/OpenSSL-for-iPhone) projec ./build-libssl.sh --archs="arm64" ``` -Results (both libraries and headers) will be placed in bin/<SDK_VERSION>-<ARCH>.sdk directory (for example, *bin/iPhoneOS11.2-arm64.sdk*). We assume you set **IOS_OPENSSL** variable to this path (e.g. `export IOS_OPENSSL="/Users/johndoe/sources/OpenSSL-for-iPhone/bin/iPhoneOS11.2-arm64.sdk"`). +Results (both libraries and headers) will be placed in bin/<SDK_VERSION>-<ARCH>.sdk directory (for example, *bin/iPhoneOS11.2-arm64.sdk*). We assume you set **IOS_OPENSSL** variable to this path (e.g. `export IOS_OPENSSL="/Users/johndoe/sources/OpenSSL-for-iPhone/bin/iPhoneOS11.2-arm64.sdk"`). ## Building SRT code Now you can build SRT providing path to OpenSSL library and toolchain file for iOS @@ -27,10 +27,10 @@ make Optionally you may add following iOS-specifc settings to configure: -* `--ios-disable-bitcode=1` - disable embedding bitcode to library. -* `--ios-arch=armv7|armv7s|arm64` - specify if you want to build for specific architecture (arm64 by default) -* `--ios-platform=OS|SIMULATOR|SIMULATOR64` - specify for build simulator code -* `--cmake-ios-developer-root=<path>`- specify path for platform directory; {XCODE_ROOT}/Platforms/iPhoneOS.platform/Developer by default +* `--ios-disable-bitcode=1` - disable embedding bitcode to library. +* `--ios-arch=armv7|armv7s|arm64` - specify if you want to build for specific architecture (arm64 by default) +* `--ios-platform=OS|SIMULATOR|SIMULATOR64` - specify for build simulator code +* `--cmake-ios-developer-root=<path>`- specify path for platform directory; {XCODE_ROOT}/Platforms/iPhoneOS.platform/Developer by default * `--cmake-ios-sdk-root=` - by default searches for latest SDK version within {CMAKE_IOS_DEVELOPER_ROOT}/SDKs, set if you want to use another SDK version Note that resulting .dylib file has install path @executable_path/Frameworks/libsrt.1.dylib, so if you need to place it in some other place with your application, you may change it with *install_name_tool* command: ``install_name_tool -id "" ``, for example ``install_name_tool -id "@executable_path/Frameworks/libsrt.1.3.0.dylib" libsrt.1.3.0.dylib`` @@ -40,5 +40,5 @@ In Xcode project settings in General tab, add libsrt to **Linked Frameworks and Click plus sign in **Embedded binaries** section and choose Frameworks/libsrt.1.dylib -In **Build settings** tab find **Header Search Paths** setting -and add paths to SRT library sources (you should add srt, srt/common and srt/common directories). +In **Build settings** tab find **Header Search Paths** setting +and add paths to SRT library sources (you should add srt, srt/common and srt/common directories). diff --git a/docs/build/build-linux.md b/docs/build/build-linux.md new file mode 100644 index 000000000..678e96615 --- /dev/null +++ b/docs/build/build-linux.md @@ -0,0 +1,44 @@ +# Building SRT on Linux + +Install `cmake` and `openssl-devel` (or equivalent) packages. For `pthreads`, add +the `-lpthreads` linker flag. + +Default installation path prefix of `make install` is `/usr/local`. + +To define a different installation path prefix, use the `--prefix` option with `configure` +or the [`-DCMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html) CMake option. + +To uninstall, call `make -n install` to list all the dependencies, and then pass the list to `rm`. + +Here is a link to a demo showing how CMake can be used to build SRT: +[Quickstart: Running SRT and FFmpeg on Ubuntu](https://www.youtube.com/watch?v=XOtUOVhussc&t=5s). + +## Ubuntu 14 + +```shell +sudo apt-get update +sudo apt-get upgrade +sudo apt-get install tclsh pkg-config cmake libssl-dev build-essential +./configure +make +``` + +## CentOS 7 + +```shell +sudo yum update +sudo yum install tcl pkgconfig openssl-devel cmake gcc gcc-c++ make automake +./configure +make +``` + +## CentOS 6 + +```shell +sudo yum update +sudo yum install tcl pkgconfig openssl-devel cmake gcc gcc-c++ make automake +sudo yum install centos-release-scl-rh devtoolset-3-gcc devtoolset-3-gcc-c++ +scl enable devtoolset-3 bash +./configure --use-static-libstdc++ --with-compiler-prefix=/opt/rh/devtoolset-3/root/usr/bin/ +make +``` diff --git a/docs/build/build-macOS.md b/docs/build/build-macOS.md new file mode 100644 index 000000000..b14a56197 --- /dev/null +++ b/docs/build/build-macOS.md @@ -0,0 +1,32 @@ +# Building SRT on macOS + +[Homebrew](https://brew.sh/) supports the [`srt`](https://formulae.brew.sh/formula/srt) formula. + +```shell +brew update +brew install srt +``` + +If you prefer using a head commit of `master` branch, add the `--HEAD` option +to `brew` command. + +```shell +brew install --HEAD srt +``` + +Install [CMake](https://cmake.org/) and OpenSSL with development files from `brew`. It is recommended to install the latest version of OpenSSL from the `brew` system rather than relying on the version that is presently installed in the system. + +```shell +brew install cmake +brew install openssl +``` + +SRT can be now built with `cmake` or `make` on Mac. + +```shell +export OPENSSL_ROOT_DIR=$(brew --prefix openssl) +export OPENSSL_LIB_DIR=$(brew --prefix openssl)"/lib" +export OPENSSL_INCLUDE_DIR=$(brew --prefix openssl)"/include" +./configure +make +``` diff --git a/docs/build/build-options.md b/docs/build/build-options.md new file mode 100644 index 000000000..529bd5cd7 --- /dev/null +++ b/docs/build/build-options.md @@ -0,0 +1,722 @@ +# Build System + +The SRT build system uses [`CMake`](https://cmake.org/) 2.8.12 or above. + +A wrapper script named [`configure`](https://github.com/Haivision/srt/blob/master/configure) +is also available. The `configure` script can simplify the build process, such as +by trying to automatically detect the OpenSSL path in a system. Note that you must +have the Tcl interpreter installed to use this script. + + +Here is a link to a demo showing how CMake can be used to build SRT: +[Quickstart: Running SRT and FFmpeg on Ubuntu](https://www.youtube.com/watch?v=XOtUOVhussc&t=5s). + + +Additional information on building for Windows is available in the +[Building SRT for Windows](https://github.com/Haivision/srt/blob/master/docs/build/build-win.md) +document and in the [SRT CookBook](https://srtlab.github.io/srt-cookbook/getting-started/build-on-windows/). + + +## List of Build Options + +The following table lists available build options in alphabetical order. +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-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, with dependency on an external encryption library. | +| [`ENABLE_AEAD_API_PREVIEW`](#enable_aead_api_preview) | 1.5.2 | `BOOL` | OFF | Enables AEAD preview API (encryption with integrity check). | +| [`ENABLE_MAXREXMITBW`](#enable_maxrexmitbw) | 1.5.3 | `BOOL` | OFF | Enables SRTO_MAXREXMITBW (v1.6.0 API). | +| [`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_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_PKTINFO`](#enable_pktinfo) | 1.5.2 | `BOOL` | OFF\* | Enables using `IP_PKTINFO` to allow the listener extracting the target IP address from incoming packets | +| [`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. | +| [`SRT_LOG_SLOWDOWN_FREQ_MS`](#SRT_LOG_SLOWDOWN_FREQ_MS) | 1.5.2 | `INT` | 1000\* | Reduce the frequency of some frequent logs, milliseconds. | +| [`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`, `botan` (since 1.6.0)). | +| [`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 ``. | +| | | | | | + + +\* See the option description for more details. + +## Using CMake + +If you choose to use CMake directly for the build configuration stage, you must +specify option values in the CMake format: + +`-D