├── .appveyor.yml ├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md └── workflows │ ├── cxx11-macos.yaml │ ├── cxx11-ubuntu.yaml │ └── cxx11-win.yaml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── apps ├── apputil.cpp ├── apputil.hpp ├── logsupport.cpp ├── logsupport.hpp ├── logsupport_appdefs.cpp ├── socketoptions.cpp ├── socketoptions.hpp ├── srt-file-transmit.cpp ├── srt-live-transmit.cpp ├── srt-tunnel.cpp ├── support.maf ├── transmitbase.hpp ├── transmitmedia.cpp ├── transmitmedia.hpp ├── uriparser.cpp ├── uriparser.hpp ├── verbose.cpp └── verbose.hpp ├── cmake_object_lib_support.c ├── common ├── filelist_win32.maf ├── win │ ├── syslog_defs.h │ ├── unistd.h │ └── wintime.h └── win_time.cpp ├── configure ├── configure-data.tcl ├── docs ├── API-functions.md ├── API.md ├── APISocketOptions.md ├── AccessControl.md ├── Android │ ├── Compiling.md │ ├── mkall │ ├── mksrt │ ├── mkssl │ ├── packjni │ └── prepare_build ├── BuildOptions.md ├── DevelopersGuide.md ├── SRT-Multiplex.md ├── bonding-intro.md ├── build-win.md ├── build_iOS.md ├── encryption.md ├── gstreamer.md ├── handshake.md ├── images │ ├── SRT_History_Good_Signal.png │ ├── SRT_Transmission_Bad_Signal.png │ ├── block-aligned-5rx10c.png │ ├── block-aligned.png │ ├── non-block-aligned-5rx10c-deleted-packets.png │ ├── non-block-aligned-5rx10c.png │ ├── non-block-aligned.png │ ├── packet-filter-mechanism.png │ ├── rebuild-missing-sequence.png │ ├── srt-encryption-1.png │ ├── srt-encryption-2.png │ └── staircase-pattern-5rx10c.png ├── live-streaming.md ├── packet-filtering-and-fec.md ├── reporting.md ├── socket-groups.md ├── srt-live-transmit.md ├── srt-tunnel.md ├── statistics.md └── why-srt-was-created.md ├── examples ├── recvfile.cpp ├── recvlive.cpp ├── sendfile.cpp ├── test-c-client-bonding.c ├── test-c-client.c ├── test-c-server-bonding.c ├── test-c-server.c └── testcapi-connect.c ├── haicrypt ├── cryspr-config.h ├── cryspr-gnutls.c ├── cryspr-gnutls.h ├── cryspr-mbedtls.c ├── cryspr-mbedtls.h ├── cryspr-openssl.c ├── cryspr-openssl.h ├── cryspr.c ├── cryspr.h ├── filelist-gnutls.maf ├── filelist-mbedtls.maf ├── filelist-openssl.maf ├── haicrypt.h ├── haicrypt_log.cpp ├── haicrypt_log.h ├── hcrypt.c ├── hcrypt.h ├── hcrypt_ctx.h ├── hcrypt_ctx_rx.c ├── hcrypt_ctx_tx.c ├── hcrypt_msg.h ├── hcrypt_rx.c ├── hcrypt_sa.c ├── hcrypt_tx.c ├── hcrypt_ut.c └── hcrypt_xpt_srt.c ├── nuget.config ├── scripts ├── FindMbedTLS.cmake ├── build-windows.bat ├── build-windows.ps1 ├── changelog │ ├── README.md │ ├── changelog.py │ └── requirements.txt ├── check-deps ├── collect-gcov.sh ├── gather-package.bat ├── generate-configure-options.tcl ├── generate-logging-defs.tcl ├── googletest-download.cmake ├── googletest.cmake ├── haiUtil.cmake ├── iOS.cmake ├── maf.vim ├── mafread.tcl ├── set-version-metadata.ps1 ├── srt-dev.lua ├── srt-ffplay ├── srt.pc.in ├── tcp-echo-client.tcl └── tcp-echo-server.tcl ├── sonar-project.properties ├── srt-ffplay ├── srtcore ├── README.md ├── access_control.h ├── api.cpp ├── api.h ├── buffer.cpp ├── buffer.h ├── cache.cpp ├── cache.h ├── channel.cpp ├── channel.h ├── common.cpp ├── common.h ├── congctl.cpp ├── congctl.h ├── core.cpp ├── core.h ├── crypto.cpp ├── crypto.h ├── epoll.cpp ├── epoll.h ├── fec.cpp ├── fec.h ├── filelist.maf ├── group.cpp ├── group.h ├── handshake.cpp ├── handshake.h ├── list.cpp ├── list.h ├── logger_default.cpp ├── logger_defs.cpp ├── logger_defs.h ├── logging.h ├── logging_api.h ├── md5.cpp ├── md5.h ├── netinet_any.h ├── packet.cpp ├── packet.h ├── packetfilter.cpp ├── packetfilter.h ├── packetfilter_api.h ├── packetfilter_builtin.h ├── platform_sys.h ├── queue.cpp ├── queue.h ├── srt.h ├── srt_c_api.cpp ├── srt_compat.c ├── srt_compat.h ├── srt_shared.rc ├── sync.cpp ├── sync.h ├── sync_cxx11.cpp ├── sync_posix.cpp ├── threadname.h ├── udt.h ├── utilities.h ├── version.h.in ├── window.cpp └── window.h ├── test ├── filelist.maf ├── test_buffer.cpp ├── test_connection_timeout.cpp ├── test_cryspr.cpp ├── test_enforced_encryption.cpp ├── test_epoll.cpp ├── test_fec_rebuilding.cpp ├── test_file_transmission.cpp ├── test_list.cpp ├── test_listen_callback.cpp ├── test_many_connections.cpp ├── test_muxer.cpp ├── test_seqno.cpp ├── test_socket_options.cpp ├── test_sync.cpp ├── test_timer.cpp ├── test_unitqueue.cpp └── test_utilities.cpp └── testing ├── README.md ├── srt-test-file.cpp ├── srt-test-file.maf ├── srt-test-live.cpp ├── srt-test-live.maf ├── srt-test-mpbond.cpp ├── srt-test-mpbond.maf ├── srt-test-multiplex.cpp ├── srt-test-multiplex.maf ├── srt-test-relay.cpp ├── srt-test-relay.maf ├── testmedia.cpp ├── testmedia.hpp ├── testmediabase.hpp ├── uriparser-test.maf ├── utility-test.cpp └── utility-test.maf /.appveyor.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | - Release 3 | - Debug 4 | 5 | image: 6 | - Visual Studio 2019 7 | - Visual Studio 2015 8 | - Visual Studio 2013 9 | 10 | platform: 11 | - x64 12 | - x86 13 | 14 | build_script: 15 | - ps: $VSIMG = $Env:APPVEYOR_BUILD_WORKER_IMAGE; $CNFG = $Env:CONFIGURATION 16 | # use a few differing arguments depending on VS version to exercise different options during builds 17 | - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -UNIT_TESTS ON } 18 | - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } 19 | - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } 20 | - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } 21 | - ps: if ($VSIMG -match '2013' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -CXX11 OFF -BUILD_APPS OFF } 22 | - ps: if ($VSIMG -match '2013' -and $CNFG -eq "Debug") { Exit-AppveyorBuild } # just skip 2013 debug build for speed 23 | 24 | test_script: 25 | - ps: if ( $Env:RUN_UNIT_TESTS ) { cd ./_build; ctest --extra-verbose -C $Env:CONFIGURATION; cd ../ } 26 | 27 | after_build: 28 | - cmd: >- 29 | scripts/gather-package.bat 30 | 7z a SRT-%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%-Win%PLATFORM%-%VS_VERSION%-%APPVEYOR_BUILD_VERSION%.zip %APPVEYOR_BUILD_FOLDER%\package\* 31 | appveyor PushArtifact SRT-%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%-Win%PLATFORM%-%VS_VERSION%-%APPVEYOR_BUILD_VERSION%.zip 32 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: LLVM 3 | AccessModifierOffset: -4 4 | # AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: true 6 | AlignConsecutiveDeclarations: true 7 | # AlignEscapedNewlinesLeft: false 8 | AlignOperands: true 9 | AlignTrailingComments: true 10 | # AllowAllArgumentsOnNextLine: true # Requires clang-format v9 and higher 11 | # AllowAllConstructorInitializersOnNextLine: false 12 | AllowAllParametersOfDeclarationOnNextLine: true 13 | AllowShortBlocksOnASingleLine: false 14 | # AllowShortCaseLabelsOnASingleLine: false 15 | AllowShortFunctionsOnASingleLine: Inline 16 | # AllowShortIfStatementsOnASingleLine: false 17 | # AllowShortLoopsOnASingleLine: false 18 | # AlwaysBreakAfterDefinitionReturnType: None 19 | # AlwaysBreakAfterReturnType: None 20 | # AlwaysBreakBeforeMultilineStrings: false 21 | AlwaysBreakTemplateDeclarations: true 22 | BinPackArguments: false 23 | BinPackParameters: false 24 | # BraceWrapping: 25 | # AfterClass: false 26 | # AfterControlStatement: false 27 | # AfterEnum: false 28 | # AfterFunction: false 29 | # AfterNamespace: false 30 | # AfterObjCDeclaration: false 31 | # AfterStruct: false 32 | # AfterUnion: false 33 | # BeforeCatch: false 34 | # BeforeElse: false 35 | # IndentBraces: false 36 | # BreakBeforeBinaryOperators: None 37 | BreakBeforeBraces: Allman 38 | # BreakInheritanceList: BeforeComma 39 | # BreakBeforeTernaryOperators: true 40 | BreakConstructorInitializers: BeforeComma 41 | # BreakAfterJavaFieldAnnotations: false 42 | # BreakStringLiterals: true 43 | ColumnLimit: 120 44 | # CommentPragmas: '^ IWYU pragma:' 45 | # ConstructorInitializerAllOnOneLineOrOnePerLine: false 46 | # ConstructorInitializerIndentWidth: 4 47 | # ContinuationIndentWidth: 4 48 | # Cpp11BracedListStyle: true 49 | # DerivePointerAlignment: false 50 | # DisableFormat: false 51 | # ExperimentalAutoDetectBinPacking: false 52 | FixNamespaceComments: true 53 | # ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 54 | # IncludeIsMainRegex: '$' 55 | # IndentCaseLabels: false 56 | IndentWidth: 4 57 | # IndentWrappedFunctionNames: false 58 | # JavaScriptQuotes: Leave 59 | # JavaScriptWrapImports: true 60 | # KeepEmptyLinesAtTheStartOfBlocks: true 61 | # MacroBlockBegin: '' 62 | # MacroBlockEnd: '' 63 | # MaxEmptyLinesToKeep: 1 64 | # NamespaceIndentation: None 65 | # ObjCBlockIndentWidth: 2 66 | # ObjCSpaceAfterProperty: false 67 | # ObjCSpaceBeforeProtocolList: true 68 | # PenaltyBreakBeforeFirstCallParameter: 19 69 | # PenaltyBreakComment: 300 70 | # PenaltyBreakFirstLessLess: 120 71 | # PenaltyBreakString: 1000 72 | # PenaltyExcessCharacter: 1000000 73 | # PenaltyReturnTypeOnItsOwnLine: 60 74 | PointerAlignment: Left 75 | # ReflowComments: true 76 | SortIncludes: false 77 | # SpaceAfterCStyleCast: false 78 | # SpaceAfterTemplateKeyword: true 79 | # SpaceBeforeAssignmentOperators: true 80 | SpaceBeforeParens: ControlStatements 81 | # SpaceInEmptyParentheses: false 82 | # SpacesBeforeTrailingComments: 1 83 | # SpacesInAngles: false 84 | # SpacesInContainerLiterals: true 85 | # SpacesInCStyleCastParentheses: false 86 | # SpacesInParentheses: false 87 | # SpacesInSquareBrackets: false 88 | Standard: Cpp03 89 | TabWidth: 4 90 | UseTab: Never 91 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: 'Type: Bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Configure '...' 16 | 2. Run '....' 17 | 3. See error 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Desktop (please provide the following information):** 26 | - OS: [e.g. Windows, Linux, macOS,...] 27 | - SRT Version / commit ID: 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FR]" 5 | labels: 'Type: Enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. For example: "When I try to do X, I am blocked by Y..." 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of how you would like to see this feature implemented. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question regarding SRT 4 | title: '' 5 | labels: 'Type: Question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | When asking a question please also include where you looked for an answer (so we can update the documentation if needed). 11 | 12 | You are encouraged to ask general questions regarding SRT in the [SRT Alliance Slack channel](https://slackin-srtalliance.azurewebsites.net/). 13 | -------------------------------------------------------------------------------- /.github/workflows/cxx11-macos.yaml: -------------------------------------------------------------------------------- 1 | name: cxx11_win 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | name: macos-cxx11 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: configure 17 | run: | 18 | mkdir _build && cd _build 19 | cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON 20 | - name: build 21 | run: cd _build && cmake --build ./ 22 | - name: test 23 | run: cd _build && ctest --extra-verbose 24 | -------------------------------------------------------------------------------- /.github/workflows/cxx11-ubuntu.yaml: -------------------------------------------------------------------------------- 1 | name: cxx11_win 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | name: ubuntu-cxx11 12 | runs-on: ubuntu-18.04 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: configure 17 | run: | 18 | mkdir _build && cd _build 19 | cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_UNITTESTS=ON 20 | - name: build 21 | run: cd _build && cmake --build ./ 22 | - name: test 23 | run: cd _build && ctest --extra-verbose 24 | -------------------------------------------------------------------------------- /.github/workflows/cxx11-win.yaml: -------------------------------------------------------------------------------- 1 | name: cxx11_win 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | name: windows-cxx11 13 | runs-on: windows-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: configure 18 | run: | 19 | md _build && cd _build 20 | cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON 21 | - name: build 22 | run: cd _build && cmake --build ./ --config Release 23 | - name: test 24 | run: cd _build && ctest --extra-verbose -C Release 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Ignore any folder starting from underscore 35 | _*/ 36 | 37 | # Ignode Visual Studio Code temp folder 38 | .vs/ 39 | .vscode/ 40 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: trusty 3 | 4 | addons: 5 | apt: 6 | packages: 7 | - tclsh 8 | - pkg-config 9 | - cmake 10 | - libssl-dev 11 | - build-essential 12 | sonarcloud: 13 | organization: "haivision" 14 | token: 15 | secure: "wJZC0kyyjuf4SZyonZ6p/5Ga9asEqSnKWF9NpRbu6S6ceERO7vbebuSJF5qX3A6ivPuw0TTk5WASOdnvIyfA28FU/D0MWRdH8K7T3w77wdE9EgAEYTUXzdrbzJY18+9pxjljHwWXWALPSGf3MClg4irWrdk1e6uHK+68R39+ZvBGBFpWeeZy/+at9+xwhtAGKBlSHe8zc+3wPxuYdvviLVJ25qbpNmnzkUR0X89G+UBl90raCPSN32EHFdImHZ5DxfEQQJgZFRjzQUY4EW/iYwaMel7jufAq0ClgV4psKujl9Lz8cPqx3WgqRfJyiIthOMTsac7G4zAw8LK2CI0VsssBp0JalLXaumi6vG7o6c3rIwKckzSKccq3pHa7h45praIVVn9s3nq+Q/JGA11FMkKQxdQtmwgFsLhbi6ZxabgsUi5KtWoWY2z6MgpJuROuAjNxZi9XJzUoJs7zSTUtRRW7V8Q2lRiOnknYh25N6TCA5bpyy1EZmRdJErm071YNI9P01gbFz5137FWJFiJzro9TGF0KoHSGiCIdUt3WlMzwr/i/wFLxFBQOZQ2rjTXvhs4hxONxMZV3gzxA1NdLaf9i5Mh6jxVMV+ujaRSV7JmPGzxqiAlpT9cJUhTCYuar9diLLeDrpe7RawEZR8V1xVDQ7yT8ruDNQ78VbSn/sC0=" 16 | homebrew: 17 | 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 18 | packages: 19 | - openssl 20 | 21 | matrix: 22 | include: 23 | - os: linux 24 | env: 25 | - BUILD_TYPE=Debug 26 | - BUILD_OPTS=-DENABLE_CODE_COVERAGE=ON 27 | - RUN_SONARCUBE=1 28 | - env: 29 | - BUILD_TYPE=Debug 30 | - BUILD_OPTS='-DENABLE_LOGGING=OFF -DENABLE_MONOTONIC_CLOCK=ON' 31 | - os: linux 32 | env: BUILD_TYPE=Release 33 | - os: osx 34 | osx_image: xcode10.2 35 | env: BUILD_TYPE=Debug 36 | - os: osx 37 | osx_image: xcode10.2 38 | env: BUILD_TYPE=Release 39 | - os: linux 40 | compiler: x86_64-w64-mingw32-g++ 41 | addons: 42 | apt: 43 | packages: 44 | - gcc-mingw-w64-base 45 | - binutils-mingw-w64-x86-64 46 | - gcc-mingw-w64-x86-64 47 | - gcc-mingw-w64 48 | - g++-mingw-w64-x86-64 49 | before_script: 50 | - git clone -b OpenSSL_1_1_1-stable https://github.com/openssl/openssl.git openssl 51 | - cd openssl 52 | - ./Configure --cross-compile-prefix=x86_64-w64-mingw32- mingw64 53 | - make 54 | - cd .. 55 | env: BUILD_TYPE=Release 56 | script: 57 | - if [ "$TRAVIS_COMPILER" == "x86_64-w64-mingw32-g++" ]; then 58 | export CC="x86_64-w64-mingw32-gcc"; 59 | export CXX="x86_64-w64-mingw32-g++"; 60 | cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="ON" -DUSE_OPENSSL_PC="OFF" -DOPENSSL_ROOT_DIR="$PWD/openssl" -DCMAKE_SYSTEM_NAME="Windows"; 61 | elif [ "$TRAVIS_OS_NAME" == "linux" ]; then 62 | cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="ON"; 63 | elif [ "$TRAVIS_OS_NAME" == "osx" ]; then 64 | export PKG_CONFIG_PATH=$(brew --prefix openssl)"/lib/pkgconfig"; 65 | cmake . -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_OPTS -DENABLE_UNITTESTS="ON"; 66 | fi 67 | - echo "TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG" 68 | - echo "TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST" 69 | - if [[ "$TRAVIS_REPO_SLUG" != "Haivision/srt" || "$TRAVIS_PULL_REQUEST" -gt 0 ]]; then 70 | export RUN_SONARCUBE=0; 71 | fi 72 | - echo "RUN_SONARCUBE=$RUN_SONARCUBE" 73 | - if (( "$RUN_SONARCUBE" )); then 74 | build-wrapper-linux-x86-64 --out-dir bw-output make; 75 | else 76 | make -j$(nproc); 77 | fi 78 | - if [ "$TRAVIS_COMPILER" != "x86_64-w64-mingw32-g++" ]; then 79 | ./test-srt --gtest_filter="-TestMuxer.IPv4_and_IPv6"; 80 | fi 81 | - if (( "$RUN_SONARCUBE" )); then source ./scripts/collect-gcov.sh; fi 82 | - if (( "$RUN_SONARCUBE" )); then sonar-scanner -D"sonar.cfamily.gcov.reportPath=."; fi 83 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | By contributing code to the [SRT project](https://github.com/Haivision/srt/), you agree to license your contribution under the [MPLv2.0 License](LICENSE). 4 | 5 | ## Issues 6 | 7 | Open a GitHub issue for anything you find or any questions you have. 8 | 9 | ## Comments 10 | 11 | Comment on any GitHub issue, open or closed. The only guidelines here are to be friendly and welcoming. If you see that a question has been asked and you think you know the answer, don't wait! 12 | 13 | ## Pull Requests 14 | 15 | Submit a pull request at any time, whether an issue has been created or not. It may be helpful to discuss your goals in an issue first, though many things can best be shown with code. Also do not hesitate to ask other users for opinion and discuss the ideas using the ticketing system before you start making your changes. This is especially important in these areas: 16 | 17 | * the build system and its variables 18 | * the SRT library public API 19 | * command line tools and their call syntax 20 | * the reusable parts (such as utilities) 21 | * SRT protocol definitions 22 | * portability and platform-specific parts 23 | 24 | Please follow the [Developer's guide](./docs/DevelopersGuide.md). 25 | 26 | ## Code Style 27 | 28 | Please follow existing style. 29 | 30 | ## Attribution 31 | 32 | This contributing guide is adapted from [VVV's guide](https://github.com/Varying-Vagrant-Vagrants/VVV/blob/develop/.github/CONTRIBUTING.md). 33 | 34 | ## Developer's Certificate of Origin 1.1 35 | 36 | By making a contribution to this project, I certify that: 37 | 38 | * (a) The contribution was created in whole or in part by me and I 39 | have the right to submit it under the open source license 40 | indicated in the file; or 41 | 42 | * (b) The contribution is based upon previous work that, to the best 43 | of my knowledge, is covered under an appropriate open source 44 | license and I have the right under that license to submit that 45 | work with modifications, whether created in whole or in part 46 | by me, under the same open source license (unless I am 47 | permitted to submit under a different license), as indicated 48 | in the file; or 49 | 50 | * (c) The contribution was provided directly to me by some other 51 | person who certified (a), (b) or (c) and I have not modified 52 | it. 53 | 54 | * (d) I understand and agree that this project and the contribution 55 | are public and that a record of the contribution (including all 56 | personal information I submit with it, including my sign-off) is 57 | maintained indefinitely and may be redistributed consistent with 58 | this project or the open source license(s) involved. 59 | -------------------------------------------------------------------------------- /apps/logsupport.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "logsupport.hpp" 18 | #include "../srtcore/srt.h" 19 | #include "../srtcore/utilities.h" 20 | 21 | using namespace std; 22 | 23 | // This is based on codes taken from 24 | // This is POSIX standard, so it's not going to change. 25 | // Haivision standard only adds one more severity below 26 | // DEBUG named DEBUG_TRACE to satisfy all possible needs. 27 | 28 | map srt_level_names 29 | { 30 | { "alert", LOG_ALERT }, 31 | { "crit", LOG_CRIT }, 32 | { "debug", LOG_DEBUG }, 33 | { "emerg", LOG_EMERG }, 34 | { "err", LOG_ERR }, 35 | { "error", LOG_ERR }, /* DEPRECATED */ 36 | { "fatal", LOG_CRIT }, // XXX Added for SRT 37 | { "info", LOG_INFO }, 38 | // WTF? Undefined symbol? { "none", INTERNAL_NOPRI }, /* INTERNAL */ 39 | { "notice", LOG_NOTICE }, 40 | { "note", LOG_NOTICE }, // XXX Added for SRT 41 | { "panic", LOG_EMERG }, /* DEPRECATED */ 42 | { "warn", LOG_WARNING }, /* DEPRECATED */ 43 | { "warning", LOG_WARNING }, 44 | //{ "", -1 } 45 | }; 46 | 47 | 48 | 49 | srt_logging::LogLevel::type SrtParseLogLevel(string level) 50 | { 51 | using namespace srt_logging; 52 | 53 | if ( level.empty() ) 54 | return LogLevel::fatal; 55 | 56 | if ( isdigit(level[0]) ) 57 | { 58 | long lev = strtol(level.c_str(), 0, 10); 59 | if ( lev >= SRT_LOG_LEVEL_MIN && lev <= SRT_LOG_LEVEL_MAX ) 60 | return LogLevel::type(lev); 61 | 62 | cerr << "ERROR: Invalid loglevel number: " << level << " - fallback to FATAL\n"; 63 | return LogLevel::fatal; 64 | } 65 | 66 | int (*ToLower)(int) = &std::tolower; // manual overload resolution 67 | transform(level.begin(), level.end(), level.begin(), ToLower); 68 | 69 | auto i = srt_level_names.find(level); 70 | if ( i == srt_level_names.end() ) 71 | { 72 | cerr << "ERROR: Invalid loglevel spec: " << level << " - fallback to FATAL\n"; 73 | return LogLevel::fatal; 74 | } 75 | 76 | return LogLevel::type(i->second); 77 | } 78 | 79 | struct ToLowerFormat 80 | { 81 | char operator()(char in) 82 | { 83 | if (islower(in)) 84 | return in; 85 | if (isupper(in)) 86 | return tolower(in); 87 | if (in == '_') 88 | return '-'; 89 | 90 | throw std::invalid_argument("Wrong FA name - please check the definition in scripts/generate-logging-defs.tcl file"); 91 | } 92 | }; 93 | 94 | void LogFANames::Install(string upname, int value) 95 | { 96 | string id; 97 | transform(upname.begin(), upname.end(), back_inserter(id), ToLowerFormat()); 98 | namemap[id] = value; 99 | } 100 | 101 | // See logsupport_appdefs.cpp for log FA definitions 102 | LogFANames srt_transmit_logfa_names; 103 | 104 | const map SrtLogFAList() 105 | { 106 | return srt_transmit_logfa_names.namemap; 107 | } 108 | 109 | set SrtParseLogFA(string fa, set* punknown) 110 | { 111 | using namespace srt_logging; 112 | 113 | set fas; 114 | 115 | // The split algo won't work on empty string. 116 | if ( fa == "" ) 117 | return fas; 118 | 119 | auto& names = srt_transmit_logfa_names.namemap; 120 | 121 | if ( fa == "all" ) 122 | { 123 | for (auto entry: names) 124 | { 125 | // Skip "general", it's always on 126 | if (entry.first == "general") 127 | continue; 128 | fas.insert(entry.second); 129 | } 130 | return fas; 131 | } 132 | 133 | int (*ToLower)(int) = &std::tolower; 134 | transform(fa.begin(), fa.end(), fa.begin(), ToLower); 135 | 136 | vector xfas; 137 | size_t pos = 0, ppos = 0; 138 | for (;;) 139 | { 140 | if ( fa[pos] != ',' ) 141 | { 142 | ++pos; 143 | if ( pos < fa.size() ) 144 | continue; 145 | } 146 | size_t n = pos - ppos; 147 | if ( n != 0 ) 148 | xfas.push_back(fa.substr(ppos, n)); 149 | ++pos; 150 | if ( pos >= fa.size() ) 151 | break; 152 | ppos = pos; 153 | } 154 | 155 | for (size_t i = 0; i < xfas.size(); ++i) 156 | { 157 | fa = xfas[i]; 158 | int* pfa = map_getp(names, fa); 159 | if (!pfa) 160 | { 161 | if (punknown) 162 | punknown->insert(fa); // If requested, add it back silently 163 | else 164 | cerr << "ERROR: Invalid log functional area spec: '" << fa << "' - skipping\n"; 165 | continue; 166 | } 167 | 168 | fas.insert(*pfa); 169 | } 170 | 171 | return fas; 172 | } 173 | 174 | 175 | -------------------------------------------------------------------------------- /apps/logsupport.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #ifndef INC_SRT_LOGSUPPORT_HPP 12 | #define INC_SRT_LOGSUPPORT_HPP 13 | 14 | #include 15 | #include 16 | #include "../srtcore/srt.h" 17 | #include "../srtcore/logging_api.h" 18 | 19 | srt_logging::LogLevel::type SrtParseLogLevel(std::string level); 20 | std::set SrtParseLogFA(std::string fa, std::set* punknown = nullptr); 21 | const std::map SrtLogFAList(); 22 | 23 | SRT_API extern std::map srt_level_names; 24 | 25 | struct LogFANames 26 | { 27 | std::map namemap; 28 | void Install(std::string upname, int value); 29 | LogFANames(); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /apps/logsupport_appdefs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WARNING: Generated from ../scripts/generate-logging-defs.tcl 3 | 4 | DO NOT MODIFY. 5 | 6 | Copyright applies as per the generator script. 7 | */ 8 | 9 | 10 | #include "logsupport.hpp" 11 | 12 | LogFANames::LogFANames() 13 | { 14 | Install("GENERAL", SRT_LOGFA_GENERAL); 15 | Install("SOCKMGMT", SRT_LOGFA_SOCKMGMT); 16 | Install("CONN", SRT_LOGFA_CONN); 17 | Install("XTIMER", SRT_LOGFA_XTIMER); 18 | Install("TSBPD", SRT_LOGFA_TSBPD); 19 | Install("RSRC", SRT_LOGFA_RSRC); 20 | 21 | Install("CONGEST", SRT_LOGFA_CONGEST); 22 | Install("PFILTER", SRT_LOGFA_PFILTER); 23 | 24 | Install("API_CTRL", SRT_LOGFA_API_CTRL); 25 | 26 | Install("QUE_CTRL", SRT_LOGFA_QUE_CTRL); 27 | 28 | Install("EPOLL_UPD", SRT_LOGFA_EPOLL_UPD); 29 | 30 | Install("API_RECV", SRT_LOGFA_API_RECV); 31 | Install("BUF_RECV", SRT_LOGFA_BUF_RECV); 32 | Install("QUE_RECV", SRT_LOGFA_QUE_RECV); 33 | Install("CHN_RECV", SRT_LOGFA_CHN_RECV); 34 | Install("GRP_RECV", SRT_LOGFA_GRP_RECV); 35 | 36 | Install("API_SEND", SRT_LOGFA_API_SEND); 37 | Install("BUF_SEND", SRT_LOGFA_BUF_SEND); 38 | Install("QUE_SEND", SRT_LOGFA_QUE_SEND); 39 | Install("CHN_SEND", SRT_LOGFA_CHN_SEND); 40 | Install("GRP_SEND", SRT_LOGFA_GRP_SEND); 41 | 42 | Install("INTERNAL", SRT_LOGFA_INTERNAL); 43 | 44 | Install("QUE_MGMT", SRT_LOGFA_QUE_MGMT); 45 | Install("CHN_MGMT", SRT_LOGFA_CHN_MGMT); 46 | Install("GRP_MGMT", SRT_LOGFA_GRP_MGMT); 47 | Install("EPOLL_API", SRT_LOGFA_EPOLL_API); 48 | 49 | Install("HAICRYPT", SRT_LOGFA_HAICRYPT); 50 | Install("APPLOG", SRT_LOGFA_APPLOG); 51 | } 52 | -------------------------------------------------------------------------------- /apps/socketoptions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #include "socketoptions.hpp" 12 | #include "verbose.hpp" 13 | 14 | using namespace std; 15 | 16 | 17 | extern const set true_names = { "1", "yes", "on", "true" }; 18 | extern const set false_names = { "0", "no", "off", "false" }; 19 | 20 | extern const std::map enummap_transtype = { 21 | { "live", SRTT_LIVE }, 22 | { "file", SRTT_FILE } 23 | }; 24 | 25 | 26 | const char* const SocketOption::mode_names[3] = { 27 | "listener", "caller", "rendezvous" 28 | }; 29 | 30 | SocketOption::Mode SrtInterpretMode(const string& modestr, const string& host, const string& adapter) 31 | { 32 | SocketOption::Mode mode = SocketOption::FAILURE; 33 | 34 | if (modestr == "client" || modestr == "caller") 35 | { 36 | mode = SocketOption::CALLER; 37 | } 38 | else if (modestr == "server" || modestr == "listener") 39 | { 40 | mode = SocketOption::LISTENER; 41 | } 42 | else if (modestr == "rendezvous") 43 | { 44 | mode = SocketOption::RENDEZVOUS; 45 | } 46 | else if (modestr == "default") 47 | { 48 | // Use the following convention: 49 | // 1. Server for source, Client for target 50 | // 2. If host is empty, then always server. 51 | if ( host == "" ) 52 | mode = SocketOption::LISTENER; 53 | //else if ( !dir_output ) 54 | //mode = "server"; 55 | else 56 | { 57 | // Host is given, so check also "adapter" 58 | if (adapter != "") 59 | mode = SocketOption::RENDEZVOUS; 60 | else 61 | mode = SocketOption::CALLER; 62 | } 63 | } 64 | else 65 | { 66 | mode = SocketOption::FAILURE; 67 | } 68 | 69 | return mode; 70 | } 71 | 72 | SocketOption::Mode SrtConfigurePre(SRTSOCKET socket, string host, map options, vector* failures) 73 | { 74 | vector dummy; 75 | vector& fails = failures ? *failures : dummy; 76 | 77 | string modestr = "default", adapter; 78 | 79 | if (options.count("mode")) 80 | { 81 | modestr = options["mode"]; 82 | } 83 | 84 | if (options.count("adapter")) 85 | { 86 | adapter = options["adapter"]; 87 | } 88 | 89 | SocketOption::Mode mode = SrtInterpretMode(modestr, host, adapter); 90 | if (mode == SocketOption::FAILURE) 91 | { 92 | fails.push_back("mode"); 93 | } 94 | 95 | if (options.count("linger")) 96 | { 97 | linger lin; 98 | lin.l_linger = stoi(options["linger"]); 99 | lin.l_onoff = lin.l_linger > 0 ? 1 : 0; 100 | srt_setsockopt(socket, SocketOption::PRE, SRTO_LINGER, &lin, sizeof(linger)); 101 | } 102 | 103 | 104 | bool all_clear = true; 105 | for (auto o: srt_options) 106 | { 107 | if ( o.binding == SocketOption::PRE && options.count(o.name) ) 108 | { 109 | string value = options.at(o.name); 110 | bool ok = o.apply(socket, value); 111 | if ( !ok ) 112 | { 113 | fails.push_back(o.name); 114 | all_clear = false; 115 | } 116 | } 117 | } 118 | 119 | return all_clear ? mode : SocketOption::FAILURE; 120 | } 121 | 122 | void SrtConfigurePost(SRTSOCKET socket, map options, vector* failures) 123 | { 124 | vector dummy; 125 | vector& fails = failures ? *failures : dummy; 126 | 127 | for (auto o: srt_options) 128 | { 129 | if ( o.binding == SocketOption::POST && options.count(o.name) ) 130 | { 131 | string value = options.at(o.name); 132 | Verb() << "Setting option: " << o.name << " = " << value; 133 | bool ok = o.apply(socket, value); 134 | if ( !ok ) 135 | fails.push_back(o.name); 136 | } 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /apps/support.maf: -------------------------------------------------------------------------------- 1 | # IMPORTANT! 2 | # 3 | # This file contains information about ALL files existing in this directory 4 | # and belonging to the shared file between official applications 5 | # so that the build definition file can take them all to link against the app. 6 | # Applications in the 'apps' directory will use them all. 7 | # Appliecaions in the 'testing' directory may use some of them and they will 8 | # take selectively whichever parts they need. 9 | 10 | SOURCES 11 | apputil.cpp 12 | logsupport.cpp 13 | logsupport_appdefs.cpp 14 | socketoptions.cpp 15 | transmitmedia.cpp 16 | uriparser.cpp 17 | verbose.cpp 18 | 19 | PRIVATE HEADERS 20 | apputil.hpp 21 | logsupport.hpp 22 | socketoptions.hpp 23 | transmitbase.hpp 24 | transmitmedia.hpp 25 | uriparser.hpp 26 | verbose.hpp 27 | -------------------------------------------------------------------------------- /apps/transmitbase.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #ifndef INC_SRT_COMMON_TRANMITBASE_HPP 12 | #define INC_SRT_COMMON_TRANMITBASE_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "srt.h" 20 | #include "uriparser.hpp" 21 | #include "apputil.hpp" 22 | 23 | typedef std::vector bytevector; 24 | extern bool transmit_total_stats; 25 | extern bool g_stats_are_printed_to_stdout; 26 | extern volatile bool transmit_throw_on_interrupt; 27 | extern unsigned long transmit_bw_report; 28 | extern unsigned long transmit_stats_report; 29 | extern unsigned long transmit_chunk_size; 30 | 31 | struct MediaPacket 32 | { 33 | bytevector payload; 34 | int64_t time = 0; 35 | 36 | MediaPacket(bytevector&& src) : payload(std::move(src)) {} 37 | MediaPacket(bytevector&& src, int64_t stime) : payload(std::move(src)), time(stime) {} 38 | 39 | MediaPacket(size_t payload_size) : payload(payload_size), time(0) {} 40 | MediaPacket(const bytevector& src) : payload(src) {} 41 | MediaPacket(const bytevector& src, int64_t stime) : payload(src), time(stime) {} 42 | MediaPacket() {} 43 | }; 44 | 45 | extern std::shared_ptr transmit_stats_writer; 46 | 47 | class Location 48 | { 49 | public: 50 | UriParser uri; 51 | Location() {} 52 | }; 53 | 54 | class Source: public Location 55 | { 56 | public: 57 | virtual int Read(size_t chunk, MediaPacket& pkt, std::ostream &out_stats = std::cout) = 0; 58 | virtual bool IsOpen() = 0; 59 | virtual bool End() = 0; 60 | static std::unique_ptr Create(const std::string& url); 61 | virtual void Close() {} 62 | virtual ~Source() {} 63 | 64 | class ReadEOF: public std::runtime_error 65 | { 66 | public: 67 | ReadEOF(const std::string& fn): std::runtime_error( "EOF while reading file: " + fn ) 68 | { 69 | } 70 | }; 71 | 72 | virtual SRTSOCKET GetSRTSocket() const { return SRT_INVALID_SOCK; }; 73 | virtual int GetSysSocket() const { return -1; }; 74 | virtual bool AcceptNewClient() { return false; } 75 | }; 76 | 77 | class Target: public Location 78 | { 79 | public: 80 | virtual int Write(const char* data, size_t size, int64_t src_time, std::ostream &out_stats = std::cout) = 0; 81 | virtual bool IsOpen() = 0; 82 | virtual bool Broken() = 0; 83 | virtual void Close() {} 84 | virtual size_t Still() { return 0; } 85 | static std::unique_ptr Create(const std::string& url); 86 | virtual ~Target() {} 87 | 88 | virtual SRTSOCKET GetSRTSocket() const { return SRT_INVALID_SOCK; } 89 | virtual int GetSysSocket() const { return -1; } 90 | virtual bool AcceptNewClient() { return false; } 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /apps/uriparser.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #ifndef INC_SRT_URL_PARSER_H 12 | #define INC_SRT_URL_PARSER_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include "utilities.h" 18 | 19 | 20 | //++ 21 | // UriParser 22 | //-- 23 | 24 | class UriParser 25 | { 26 | // Construction 27 | public: 28 | 29 | enum DefaultExpect { EXPECT_FILE, EXPECT_HOST }; 30 | enum Type 31 | { 32 | UNKNOWN, FILE, UDP, TCP, SRT, RTMP, HTTP, RTP 33 | }; 34 | 35 | UriParser(const std::string& strUrl, DefaultExpect exp = EXPECT_FILE); 36 | UriParser(): m_uriType(UNKNOWN) {} 37 | virtual ~UriParser(void); 38 | 39 | // Some predefined types 40 | Type type() const; 41 | 42 | typedef MapProxy ParamProxy; 43 | 44 | // Operations 45 | public: 46 | std::string uri() const { return m_origUri; } 47 | std::string proto() const; 48 | std::string scheme() const { return proto(); } 49 | std::string host() const; 50 | std::string port() const; 51 | unsigned short int portno() const; 52 | std::string hostport() const { return host() + ":" + port(); } 53 | std::string path() const; 54 | std::string queryValue(const std::string& strKey) const; 55 | std::string makeUri(); 56 | ParamProxy operator[](const std::string& key) { return ParamProxy(m_mapQuery, key); } 57 | const std::map& parameters() const { return m_mapQuery; } 58 | typedef std::map::const_iterator query_it; 59 | 60 | private: 61 | void Parse(const std::string& strUrl, DefaultExpect); 62 | 63 | // Overridables 64 | public: 65 | 66 | // Overrides 67 | public: 68 | 69 | // Data 70 | private: 71 | std::string m_origUri; 72 | std::string m_proto; 73 | std::string m_host; 74 | std::string m_port; 75 | std::string m_path; 76 | Type m_uriType; 77 | DefaultExpect m_expect; 78 | 79 | std::map m_mapQuery; 80 | }; 81 | 82 | //#define TEST1 1 83 | 84 | #endif // INC_SRT_URL_PARSER_H 85 | -------------------------------------------------------------------------------- /apps/verbose.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #include "verbose.hpp" 12 | 13 | namespace Verbose 14 | { 15 | bool on = false; 16 | std::ostream* cverb = &std::cerr; 17 | #if SRT_ENABLE_VERBOSE_LOCK 18 | std::mutex vlock; 19 | #endif 20 | 21 | Log& Log::operator<<(LogNoEol) 22 | { 23 | noeol = true; 24 | if (on) 25 | { 26 | (*cverb) << std::flush; 27 | } 28 | return *this; 29 | } 30 | 31 | #if SRT_ENABLE_VERBOSE_LOCK 32 | Log& Log::operator<<(LogLock) 33 | { 34 | lockline = true; 35 | return *this; 36 | } 37 | #endif 38 | 39 | Log::~Log() 40 | { 41 | if (on && !noeol) 42 | { 43 | #if SRT_ENABLE_VERBOSE_LOCK 44 | if (lockline) 45 | { 46 | // Lock explicitly, as requested, and wait for the opportunity. 47 | vlock.lock(); 48 | } 49 | else if (vlock.try_lock()) 50 | { 51 | // Successfully locked, so unlock immediately, locking wasn't requeted. 52 | vlock.unlock(); 53 | } 54 | else 55 | { 56 | // Failed to lock, which means that some other thread has locked it first. 57 | // This means that some other thread wants to print the whole line and doesn't 58 | // want to be disturbed during this process. Lock the thread then as this is 59 | // the only way to wait until it's unlocked. However, do not block your printing 60 | // with locking, because you were not requested to lock (treat this mutex as 61 | // an entry semaphore, which may only occasionally block the whole line). 62 | vlock.lock(); 63 | vlock.unlock(); 64 | } 65 | #endif 66 | (*cverb) << std::endl; 67 | #if SRT_ENABLE_VERBOSE_LOCK 68 | 69 | // If lockline is set, the lock was requested and WAS DONE, so unlock. 70 | // Otherwise locking WAS NOT DONE. 71 | if (lockline) 72 | vlock.unlock(); 73 | #endif 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /apps/verbose.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #ifndef INC_SRT_VERBOSE_HPP 12 | #define INC_SRT_VERBOSE_HPP 13 | 14 | #include 15 | #if SRT_ENABLE_VERBOSE_LOCK 16 | #include 17 | #endif 18 | 19 | namespace Verbose 20 | { 21 | 22 | extern bool on; 23 | extern std::ostream* cverb; 24 | 25 | struct LogNoEol { LogNoEol() {} }; 26 | #if SRT_ENABLE_VERBOSE_LOCK 27 | struct LogLock { LogLock() {} }; 28 | #endif 29 | 30 | class Log 31 | { 32 | bool noeol = false; 33 | #if SRT_ENABLE_VERBOSE_LOCK 34 | bool lockline = false; 35 | #endif 36 | 37 | // Disallow creating dynamic objects 38 | void* operator new(size_t); 39 | 40 | public: 41 | 42 | template 43 | Log& operator<<(const V& arg) 44 | { 45 | // Template - must be here; extern template requires 46 | // predefined specializations. 47 | if (on) 48 | (*cverb) << arg; 49 | return *this; 50 | } 51 | 52 | Log& operator<<(LogNoEol); 53 | #if SRT_ENABLE_VERBOSE_LOCK 54 | Log& operator<<(LogLock); 55 | #endif 56 | ~Log(); 57 | }; 58 | 59 | 60 | class ErrLog: public Log 61 | { 62 | public: 63 | 64 | template 65 | ErrLog& operator<<(const V& arg) 66 | { 67 | // Template - must be here; extern template requires 68 | // predefined specializations. 69 | if (on) 70 | (*cverb) << arg; 71 | else 72 | std::cerr << arg; 73 | return *this; 74 | } 75 | }; 76 | 77 | } 78 | 79 | inline Verbose::Log Verb() { return Verbose::Log(); } 80 | inline Verbose::ErrLog Verror() { return Verbose::ErrLog(); } 81 | 82 | // Manipulator tags 83 | static const Verbose::LogNoEol VerbNoEOL; 84 | #if SRT_ENABLE_VERBOSE_LOCK 85 | static const Verbose::LogLock VerbLock; 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /cmake_object_lib_support.c: -------------------------------------------------------------------------------- 1 | // DO NOT DELETE 2 | // This file is needed for Xcode to properly handle CMake OBJECT Libraries 3 | // From docs (https://cmake.org/cmake/help/latest/command/add_library.html#object-libraries): 4 | // 5 | // ... Some native build systems (such as Xcode) may not like targets that have only object files, 6 | // so consider adding at least one real source file to any target that references $. 7 | 8 | // Just a dummy symbol to avoid compiler warnings 9 | int srt_object_lib_dummy = 0; 10 | -------------------------------------------------------------------------------- /common/filelist_win32.maf: -------------------------------------------------------------------------------- 1 | 2 | PUBLIC HEADERS 3 | win/syslog_defs.h 4 | # 5 | # These are included by platform_sys.h header contained in ../srtcore/filelist.maf 6 | # 7 | win/unistd.h 8 | 9 | SOURCES 10 | win_time.cpp 11 | -------------------------------------------------------------------------------- /common/win/syslog_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef INC_SRT_WINDOWS_SYSLOG_DEFS_H 2 | #define INC_SRT_WINDOWS_SYSLOG_DEFS_H 3 | 4 | #define LOG_EMERG 0 5 | #define LOG_ALERT 1 6 | #define LOG_CRIT 2 7 | #define LOG_ERR 3 8 | #define LOG_WARNING 4 9 | #define LOG_NOTICE 5 10 | #define LOG_INFO 6 11 | #define LOG_DEBUG 7 12 | 13 | #define LOG_PRIMASK 0x07 14 | 15 | #define LOG_PRI(p) ((p) & LOG_PRIMASK) 16 | #define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) 17 | 18 | #define LOG_KERN (0<<3) 19 | #define LOG_USER (1<<3) 20 | #define LOG_MAIL (2<<3) 21 | #define LOG_DAEMON (3<<3) 22 | #define LOG_AUTH (4<<3) 23 | #define LOG_SYSLOG (5<<3) 24 | #define LOG_LPR (6<<3) 25 | #define LOG_NEWS (7<<3) 26 | #define LOG_UUCP (8<<3) 27 | #define LOG_CRON (9<<3) 28 | #define LOG_AUTHPRIV (10<<3) 29 | #define LOG_FTP (11<<3) 30 | 31 | /* Codes through 15 are reserved for system use */ 32 | #define LOG_LOCAL0 (16<<3) 33 | #define LOG_LOCAL1 (17<<3) 34 | #define LOG_LOCAL2 (18<<3) 35 | #define LOG_LOCAL3 (19<<3) 36 | #define LOG_LOCAL4 (20<<3) 37 | #define LOG_LOCAL5 (21<<3) 38 | #define LOG_LOCAL6 (22<<3) 39 | #define LOG_LOCAL7 (23<<3) 40 | 41 | #define LOG_NFACILITIES 24 42 | #define LOG_FACMASK 0x03f8 43 | #define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /common/win/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNISTD_H 2 | #define _UNISTD_H 1 3 | 4 | /* This file intended to serve as a drop-in replacement for 5 | * unistd.h on Windows 6 | * Please add functionality as neeeded 7 | */ 8 | 9 | #include 10 | #include 11 | //#include /* getopt at: https://gist.github.com/ashelly/7776712*/ 12 | #include /* for getpid() and the exec..() family */ 13 | #include /* for _getcwd() and _chdir() */ 14 | 15 | #define srandom srand 16 | #define random rand 17 | 18 | /* Values for the second argument to access. 19 | These may be OR'd together. */ 20 | #define R_OK 4 /* Test for read permission. */ 21 | #define W_OK 2 /* Test for write permission. */ 22 | //#define X_OK 1 /* execute permission - unsupported in windows*/ 23 | #define F_OK 0 /* Test for existence. */ 24 | 25 | #define access _access 26 | #define dup2 _dup2 27 | #define execve _execve 28 | #define ftruncate _chsize 29 | #define unlink _unlink 30 | #define fileno _fileno 31 | #define getcwd _getcwd 32 | #define chdir _chdir 33 | #define isatty _isatty 34 | #define lseek _lseek 35 | /* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ 36 | 37 | #define ssize_t int 38 | 39 | #define STDIN_FILENO 0 40 | #define STDOUT_FILENO 1 41 | #define STDERR_FILENO 2 42 | /* should be in some equivalent to */ 43 | typedef __int8 int8_t; 44 | typedef __int16 int16_t; 45 | typedef __int32 int32_t; 46 | typedef __int64 int64_t; 47 | typedef unsigned __int8 uint8_t; 48 | typedef unsigned __int16 uint16_t; 49 | typedef unsigned __int32 uint32_t; 50 | typedef unsigned __int64 uint64_t; 51 | 52 | #endif /* unistd.h */ 53 | -------------------------------------------------------------------------------- /common/win/wintime.h: -------------------------------------------------------------------------------- 1 | #ifndef INC_SRT_WIN_WINTIME 2 | #define INC_SRT_WIN_WINTIME 3 | 4 | #include 5 | #include 6 | // HACK: This include is a workaround for a bug in the MinGW headers 7 | // where pthread.h, which defines _POSIX_THREAD_SAFE_FUNCTIONS, 8 | // has to be included before time.h so that time.h defines 9 | // localtime_r correctly 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #if !defined(_MSC_VER) 17 | #define SRTCOMPAT_WINTIME_STATIC_INLINE_DECL static inline 18 | #else 19 | // NOTE: MVC Does not like static inline for C functions in some versions. 20 | // so just use static for MVC. 21 | #define SRTCOMPAT_WINTIME_STATIC_INLINE_DECL static 22 | #endif 23 | 24 | #ifndef _TIMEZONE_DEFINED /* also in sys/time.h */ 25 | #define _TIMEZONE_DEFINED 26 | struct timezone 27 | { 28 | int tz_minuteswest; /* minutes W of Greenwich */ 29 | int tz_dsttime; /* type of dst correction */ 30 | }; 31 | #endif 32 | 33 | void SRTCompat_timeradd( 34 | struct timeval *a, struct timeval *b, struct timeval *result); 35 | SRTCOMPAT_WINTIME_STATIC_INLINE_DECL void timeradd( 36 | struct timeval *a, struct timeval *b, struct timeval *result) 37 | { 38 | SRTCompat_timeradd(a, b, result); 39 | } 40 | 41 | int SRTCompat_gettimeofday( 42 | struct timeval* tp, struct timezone* tz); 43 | SRTCOMPAT_WINTIME_STATIC_INLINE_DECL int gettimeofday( 44 | struct timeval* tp, struct timezone* tz) 45 | { 46 | return SRTCompat_gettimeofday(tp, tz); 47 | } 48 | 49 | #undef SRTCOMPAT_WINTIME_STATIC_INLINE_DECL 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif // INC_SRT_WIN_WINTIME 56 | -------------------------------------------------------------------------------- /common/win_time.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | *****************************************************************************/ 15 | 16 | #include "win/wintime.h" 17 | #include 18 | 19 | void SRTCompat_timeradd(struct timeval *a, struct timeval *b, struct timeval *result) 20 | { 21 | result->tv_sec = a->tv_sec + b->tv_sec; 22 | result->tv_usec = a->tv_usec + b->tv_usec; 23 | if (result->tv_usec >= 1000000) 24 | { 25 | result->tv_sec++; 26 | result->tv_usec -= 1000000; 27 | } 28 | } 29 | 30 | int SRTCompat_gettimeofday(struct timeval* tp, struct timezone*) 31 | { 32 | struct timeb tb; 33 | ftime(&tb); 34 | tp->tv_sec = (long)tb.time; 35 | tp->tv_usec = 1000*tb.millitm; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /docs/Android/Compiling.md: -------------------------------------------------------------------------------- 1 | # Establishing a Build Environment 2 | ## Installing the Android NDK 3 | The Android NDK is required to build native modules for Android. 4 | Download the NDK r19 or newer archive from the following site: 5 | [Download the Android NDK on developer.android.com](https://developer.android.com/ndk/downloads/index.html) 6 | To install the Android NDK, simply expand the archive in the folder where you want to install it. 7 | ## OpenSSL 8 | Google removed openssl from Android 7+. You must build openssl libs by yourself. 9 | # Configure the NDK path 10 | Edit the ```mkall``` script to configure NDK path. Set the ```NDK``` to the directory where the NDK is installed. 11 | # Build SRT for Android 12 | Run ```/bin/bash mkall > build.log``` script. Libraries will be installed to ```./target-architecture/lib```. 13 | # Export SRT libraries 14 | Run ```/bin/bash packjni``` to generate ```jniLibs``` archive for Android Studio. 15 | -------------------------------------------------------------------------------- /docs/Android/mkall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NDK=/opt/android-ndk-r19 4 | 5 | openssl_ver=1.0.2q 6 | srt_version=1.3.1 7 | #srt_branch=dev 8 | 9 | # Determine the path of the executing script 10 | BASE_DIR=$(readlink -f $0 | xargs dirname) 11 | 12 | wget -N https://www.openssl.org/source/openssl-$openssl_ver.tar.gz 13 | 14 | if [ ! -d $BASE_DIR/srt ]; then 15 | git clone https://github.com/Haivision/srt srt 16 | # git -C $BASE_DIR/srt checkout v${srt_version} 17 | # git -C $BASE_DIR/srt checkout -b $srt_branch origin/$srt_branch 18 | fi 19 | 20 | # Clang, binutils, the sysroot, and other toolchain pieces are all installed to $NDK/toolchains/llvm/prebuilt/ 21 | toolchain=$NDK/toolchains/llvm/prebuilt/linux-x86_64 22 | 23 | # Cross-compiler tool prefix 24 | declare -A target_hosts 25 | target_hosts=( 26 | [arm]=arm-linux-androideabi 27 | [arm64]=aarch64-linux-android 28 | [x86]=i686-linux-android 29 | [x86_64]=x86_64-linux-android 30 | ) 31 | 32 | # Cross-compiler prefix for -clang and -clang++ has api version 33 | declare -A target_api 34 | target_api=( 35 | [arm]=armv7a-linux-androideabi16 36 | [arm64]=aarch64-linux-android21 37 | [x86]=i686-linux-android16 38 | [x86_64]=x86_64-linux-android21 39 | ) 40 | 41 | declare -A sysroots 42 | sysroots=( 43 | [arm]=$BASE_DIR/armeabi-v7a 44 | [arm64]=$BASE_DIR/arm64-v8a 45 | [x86]=$BASE_DIR/x86 46 | [x86_64]=$BASE_DIR/x86_64 47 | ) 48 | 49 | for arch in arm arm64 x86 x86_64; do 50 | rm -rf $BASE_DIR/openssl-$openssl_ver 51 | tar xf $BASE_DIR/openssl-$openssl_ver.tar.gz 52 | $BASE_DIR/mkssl -t $toolchain -h ${target_hosts[$arch]} -a ${target_api[$arch]} -s $BASE_DIR/openssl-$openssl_ver -i ${sysroots[$arch]} 53 | 54 | git -C $BASE_DIR/srt clean -fd 55 | $BASE_DIR/mksrt -t $toolchain -h ${target_hosts[$arch]} -a ${target_api[$arch]} -s $BASE_DIR/srt -i ${sysroots[$arch]} 56 | done 57 | -------------------------------------------------------------------------------- /docs/Android/mksrt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source prepare_build 4 | 5 | ./configure --use-openssl-pc=OFF --CMAKE_PREFIX_PATH=$install_dir --CMAKE_INSTALL_PREFIX=$install_dir 6 | make 7 | make install 8 | -------------------------------------------------------------------------------- /docs/Android/mkssl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source prepare_build 4 | 5 | ./Configure android --openssldir=$install_dir -fPIC 6 | # OpenSSL (1.0.2) adds -mandroid to the compile flags. This flag is not recognized by clang. 7 | sed -i 's/-mandroid//g' Makefile 8 | make 9 | make install 10 | -------------------------------------------------------------------------------- /docs/Android/packjni: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BASE_DIR=$(readlink -f $0 | xargs dirname) 4 | 5 | declare -A sysroots 6 | sysroots=( 7 | [arm]=$BASE_DIR/armeabi-v7a 8 | [arm64]=$BASE_DIR/arm64-v8a 9 | [x86]=$BASE_DIR/x86 10 | [x86_64]=$BASE_DIR/x86_64 11 | ) 12 | 13 | srt_version=1.3.1 14 | jni_dir=$BASE_DIR/jniLibs 15 | 16 | declare -A jnilibs 17 | jnilibs=( 18 | [arm]=$jni_dir/armeabi-v7a 19 | [arm64]=$jni_dir/arm64-v8a 20 | [x86]=$jni_dir/x86 21 | [x86_64]=$jni_dir/x86_64 22 | ) 23 | 24 | jni_dir=$BASE_DIR/jniLibs 25 | 26 | # Android < 6.0 has an issue with loading versioned libraries 27 | # The issue is because of library so-name libsrt.so.1 28 | 29 | for arch in arm arm64 x86 x86_64; do 30 | mkdir -p ${jnilibs[$arch]} 31 | cp ${sysroots[$arch]}/lib/libsrt.so.${srt_version} ${jnilibs[$arch]}/libsrt.so 32 | /usr/local/bin/patchelf --set-soname libsrt.so ${jnilibs[$arch]}/libsrt.so 33 | objdump -p ${jnilibs[$arch]}/libsrt.so | grep libsrt.so 34 | done 35 | 36 | zip -r libsrt_$(date +%Y-%m-%d).zip jniLibs 37 | -------------------------------------------------------------------------------- /docs/Android/prepare_build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while getopts t:h:a:s:i: option 4 | do 5 | case "${option}" 6 | in 7 | t) toolchain_dir=${OPTARG};; 8 | h) target_host=${OPTARG};; 9 | a) target_host_api=${OPTARG};; 10 | s) src_dir=${OPTARG};; 11 | i) install_dir=$OPTARG;; 12 | esac 13 | done 14 | 15 | # Add toolchain to the search path. 16 | export PATH=$PATH:$toolchain_dir/bin 17 | 18 | # Tell configure what tools to use. 19 | export AR=$target_host-ar 20 | export AS=$target_host-as 21 | export LD=$target_host-ld 22 | export STRIP=$target_host-strip 23 | 24 | # Tell configure which android api to use. 25 | export CC=$target_host_api-clang 26 | export CXX=$target_host_api-clang++ 27 | 28 | # Tell configure what flags Android requires. 29 | export CFLAGS="-fPIE -fPIC" 30 | export LDFLAGS="-pie" 31 | 32 | cd $src_dir 33 | -------------------------------------------------------------------------------- /docs/SRT-Multiplex.md: -------------------------------------------------------------------------------- 1 | ## srt-multiplex 2 | 3 | **srt-multiplex** (formerly called "SIPLEX") is a sample program that can send 4 | multiple streams in one direction. This tool demonstrates two SRT features: 5 | - the ability to use a single UDP link (a source and destination pair 6 | specified by IP address and port) for multiple SRT connections 7 | - the use of the `streamid` socket option to identify multiplexed resources 8 | 9 | NOTE: due to changes in the common code that can't be properly handled in the 10 | current form of srt-multiplex, this application is temporarily blocked. Instead 11 | the `srt-test-multiplex` application was added with the same functionality, 12 | although it's recommended for testing purposes only. 13 | 14 | #### Usage 15 | 16 | `srt-multiplex -i [id] [id]...` 17 | 18 | - Multiplexes data from one or more input URIs to transmit as an SRT stream. 19 | The application reads multiple streams (INPUT URIs), each using a separate SRT 20 | connection. All of the traffic from these connections is sent through the 21 | same UDP link. 22 | 23 | `srt-multiplex -o [id] [id]...` 24 | 25 | - Transmits data from a multiplexed SRT stream to the specified output URI(s). 26 | 27 | An `` can be identified as input or output using the **-i** or **-o** 28 | options. When `-i` is specified, the URIs provided are used as input, and will 29 | be output over the `` socket. The reverse is true for any output URIs 30 | specified by `-o`. 31 | 32 | Separate connections will be created for every specified URI, although all will 33 | be using the same UDP link. When SRT is in caller mode, the SRT socket created 34 | for transmitting data for a given URI will be set to the `streamid` socket option 35 | from this URI's `id` parameter. When SRT is in listener mode, the `streamid` 36 | option will already be set on the accepted socket, and will be matched with a 37 | URI that has the same value in its `id` parameter. 38 | 39 | This `streamid` is the SRT socket option (`SRTO_STREAMID` in the API). The idea 40 | is that it can be set on a socket used for connecting. When a listener is 41 | getting an accepted socket for that connection, the `streamid` socket option 42 | can be read from it, with the result that it will be the same as was set on 43 | the caller side. 44 | 45 | So, in caller mode, for every stream media URI (input or output) there will be 46 | a separate SRT socket created. This socket will have its `socketid` option 47 | set to the value that is given by user as the `id` parameter attached to a 48 | particular URI. In listener mode this happens in the opposite direction — the 49 | value of the `streamid` option is extracted from the accepted socket, and then 50 | matched against all ids specified with the stream media URIs: 51 | ``` 52 | URI1?id=a --> s1(streamid=a).connect(remhost:2000) 53 | URI2?id=b --> s2(streamid=b).connect(remhost:2000) 54 | URI3?id=c --> s3(streamid=c).connect(remhost:2000) 55 | ``` 56 | And on the listener side: 57 | ``` 58 | (remhost:2000) -> accept --> s(SRT socket) --> in URI array find such that uri.id == s.streamid 59 | ``` 60 | 61 | #### Examples 62 | 63 | - **Sender:** 64 | - `srt-multiplex srt://remhost:2000 -i udp://:5000?id=low udp://:6000?id=high` 65 | - **Receiver:** 66 | - `srt-multiplex srt://:2000 -o output-high.ts?id=high output-low.ts?id=low` 67 | 68 | In this example a Sender is created which will connect to `remhost` port 2000 69 | using multiple SRT sockets, all of which will be using the same outgoing port. 70 | Here the outgoing port is automatically selected when connecting. Subsequent 71 | sockets will reuse that port. Alternatively you can enforce the outgoing port 72 | using the `port` parameter with the ``. 73 | 74 | - **Sender:** 75 | - `srt-multiplex srt://remhost:2000?port=5555 ...` 76 | 77 | A separate connection is made for every input resource. An appropriate resource 78 | ID will be set to each socket assigned to that resource according to the `id` 79 | parameter. 80 | ``` 81 | +-- --+ 82 | | id=1 id=1 | 83 | | ------ ------- | 84 | | \ -----> / | 85 | | id=2 \ ---------------------------- / id=2 | 86 | port=5555 -| --------- ( multiplexed UDP stream ) ---------- |- port=2000 87 | | / ---------------------------- \ | 88 | | id=3 / \ id=3 | 89 | | ------ ------ | 90 | +-- --+ 91 | ``` 92 | When a socket is accepted on the listener side (the Receiver in this example), 93 | srt-multiplex will search for the resource ID among the registered resources 94 | (input/output URIs) and set an ID that matches the one on the caller side. If 95 | the resource is not found, the connection is closed immediately. 96 | 97 | The srt-multiplex program works the same way for connections initiated by a 98 | caller or a listener. 99 | -------------------------------------------------------------------------------- /docs/build_iOS.md: -------------------------------------------------------------------------------- 1 | # Building SRT for iOS 2 | 3 | ## Prerequisites 4 | * Xcode should be installed. Check in terminal whether `xcode-select -p` points to **/Applications/Xcode.app/Contents/Developer** 5 | * Install Homebrew according to instructions on [https://brew.sh/](https://brew.sh/) 6 | * Install CMake and pkg-config with Homebrew: 7 | ``` 8 | brew install cmake 9 | brew install pkg-config 10 | ``` 11 | 12 | ## Building OpenSSL 13 | There is [OpenSSL for iPhone](https://github.com/x2on/OpenSSL-for-iPhone) project which have all necessary to build OpenSSL for our needs. It fetches OpenSSL code by itself, so you don't need to download it separately. So simply clone it and build with command: 14 | ``` 15 | ./build-libssl.sh --archs="arm64" 16 | ``` 17 | 18 | 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"`). 19 | 20 | ## Building SRT code 21 | Now you can build SRT providing path to OpenSSL library and toolchain file for iOS 22 | 23 | ``` 24 | ./configure --cmake-prefix-path=$IOS_OPENSSL --use-openssl-pc=OFF --cmake-toolchain-file=scripts/iOS.cmake 25 | make 26 | ``` 27 | 28 | Optionally you may add following iOS-specifc settings to configure: 29 | 30 | * `--ios-disable-bitcode=1` - disable embedding bitcode to library. 31 | * `--ios-arch=armv7|armv7s|arm64` - specify if you want to build for specific architecture (arm64 by default) 32 | * `--ios-platform=OS|SIMULATOR|SIMULATOR64` - specify for build simulator code 33 | * `--cmake-ios-developer-root=<path>`- specify path for platform directory; {XCODE_ROOT}/Platforms/iPhoneOS.platform/Developer by default 34 | * `--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 35 | 36 | 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`` 37 | 38 | ## Adding to Xcode project 39 | In Xcode project settings in General tab, add libsrt to **Linked Frameworks and Libraries** section - click Plus sign, then click "Add Other" and find libsrt.1.dylib 40 | 41 | Click plus sign in **Embedded binaries** section and choose Frameworks/libsrt.1.dylib 42 | 43 | In **Build settings** tab find **Header Search Paths** setting 44 | and add paths to SRT library sources (you should add srt, srt/common and srt/common directories). 45 | -------------------------------------------------------------------------------- /docs/gstreamer.md: -------------------------------------------------------------------------------- 1 | # Using SRT with GStreamer 2 | 3 | Starting from ver. 1.14 GStreamer supports SRT (see the [v.1.14 release notes](https://gstreamer.freedesktop.org/releases/1.14/)). 4 | See the SRT plugin for GStreamer on [git](https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/tree/master/ext/srt). 5 | 6 | 7 | ## Using GStreamer and SRT to set up a screensharing 8 | 9 | Based on the description in [#7](https://github.com/Haivision/srt/issues/7). Note that the commands are likely to change slightly for gstreamer 1.16 (see this [issue](https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/874#note_106395)). 10 | 11 | If you don't want to build GSteamer, SRT, and all the plugins from source or don't have a distribution that has 1.14 readily available, you can use [`nix`](https://nixos.org/nix/) to reproduce what is shown further. 12 | 13 | Simply install `nix`; then use the command bellow to open a shell where the following commands work. 14 | 15 | ``` 16 | NIX_PATH=nixpkgs=https://github.com/nh2/nixpkgs/archive/a94ff5f6aaa.tar.gz nix-shell -p gst_all_1.gstreamer \ 17 | -p gst_all_1.gst-plugins-good -p gst_all_1.gst-plugins-base -p gst_all_1.gst-plugins-bad \ 18 | -p gst_all_1.gst-plugins-ugly -p gst_all_1.gst-libav 19 | ``` 20 | 21 | ### Sender server 22 | 23 | Set up a sender server that will grab a source raw video from a desktop or a webcam, encode it with x.264 (H.264/AVC) encoder, pack it in `MPEG-TS` ([more info about live streaming](live-streaming.md)). Then pipe it into the SRT sink that sends it over the network to the receiver client. The streaming URI should looks like `uri=srt://:`. In the examples below the streaming is sent to port 888 on a localhost by specifying `uri=srt://0.0.0.0:8888`. 24 | 25 | 26 | ##### For screensharing (Linux with X Display) 27 | 28 | The `ximagesrc` GStreamer plugin can be used to capture X Display and create raw RGB video. 29 | Refer to `ximagesrc` [RM](https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-ximagesrc.html) for configuration options. 30 | 31 | ``` 32 | /usr/bin/time gst-launch-1.0 ximagesrc startx=0 show-pointer=true use-damage=0 ! videoconvert \ 33 | ! x264enc bitrate=32000 tune=zerolatency speed-preset=veryfast byte-stream=true threads=1 key-int-max=15 \ 34 | intra-refresh=true ! video/x-h264, profile=baseline, framerate=30/1 ! mpegtsmux \ 35 | ! srtserversink uri=srt://0.0.0.0:8888/ latency=100 36 | ``` 37 | 38 | ##### For webcam images 39 | 40 | The `v4l2src` GStreamer plugin can be used to capture video from v4l2 devices, like webcams and TV cards. 41 | Refer to `v4l2src` [RM](https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-v4l2src.html) for further information. 42 | 43 | ``` 44 | /usr/bin/time gst-launch-1.0 v4l2src ! videoconvert ! x264enc bitrate=8000 tune=zerolatency speed-preset=superfast \ 45 | byte-stream=true threads=1 key-int-max=15 intra-refresh=true ! video/x-h264, profile=baseline ! mpegtsmux \ 46 | ! srtserversink uri=srt://0.0.0.0:8888/ latency=100 47 | ``` 48 | 49 | ##### Notes 50 | 51 | * The `decodebin` can also be used to configure settings automatically. Using explicit pipeline elements here make it possible to tune the settings when needed. 52 | * A use of `time` helps to determine when the thread is capped at 100%, while the the `thread=1` parameter makes the encoding use only one thread. Remove `threads=1` to allow multiple cores, or cjange the `speed-preset` to reduce CPU load. 53 | * The `timeout` setting can be tuned. A recommended timeout is 2x-2.5x of the expected roundtrip time. 54 | * The password functionality works as well, but only if a password is `>= 10` characters long; otherwise it's completely ignored. See [this bug](https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/694#note_106616) of GStreamer. 55 | 56 | ### Receiver client 57 | 58 | A client connection over SRT to the server with URI `srt://127.0.0.1:8888` (localhost) or a remote server is set up. URI syntax is `srt://:`. Then MPEG-TS demuxer and video decoder is used to get a decompressed video, that goes to a playback plugin `autovideosink`. Note that multiple clients can connect to the server started earlier. 59 | 60 | `gst-launch-1.0 srtclientsrc uri=srt://127.0.0.1:8888 ! tsdemux ! h264parse ! video/x-h264 ! avdec_h264 ! autovideosink sync=false` 61 | 62 | This works over both the internet and localhost. 63 | -------------------------------------------------------------------------------- /docs/images/SRT_History_Good_Signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/SRT_History_Good_Signal.png -------------------------------------------------------------------------------- /docs/images/SRT_Transmission_Bad_Signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/SRT_Transmission_Bad_Signal.png -------------------------------------------------------------------------------- /docs/images/block-aligned-5rx10c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/block-aligned-5rx10c.png -------------------------------------------------------------------------------- /docs/images/block-aligned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/block-aligned.png -------------------------------------------------------------------------------- /docs/images/non-block-aligned-5rx10c-deleted-packets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/non-block-aligned-5rx10c-deleted-packets.png -------------------------------------------------------------------------------- /docs/images/non-block-aligned-5rx10c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/non-block-aligned-5rx10c.png -------------------------------------------------------------------------------- /docs/images/non-block-aligned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/non-block-aligned.png -------------------------------------------------------------------------------- /docs/images/packet-filter-mechanism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/packet-filter-mechanism.png -------------------------------------------------------------------------------- /docs/images/rebuild-missing-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/rebuild-missing-sequence.png -------------------------------------------------------------------------------- /docs/images/srt-encryption-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/srt-encryption-1.png -------------------------------------------------------------------------------- /docs/images/srt-encryption-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/srt-encryption-2.png -------------------------------------------------------------------------------- /docs/images/staircase-pattern-5rx10c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BELABOX/srt/a1054cfe8bf225d49356576137274396c5742b9d/docs/images/staircase-pattern-5rx10c.png -------------------------------------------------------------------------------- /docs/srt-tunnel.md: -------------------------------------------------------------------------------- 1 | SRT Tunnel 2 | ========== 3 | 4 | Purpose 5 | ------- 6 | 7 | SRT Tunnel is a typical tunnelling application, that is, it simply passes the 8 | transmission from a given endpoint to another endpoint in both directions. 9 | 10 | Tunnels can be also "chained", that is, there can be more than one tunnel on 11 | the way between the real peers. 12 | 13 | This tunnel application can use both TCP and SRT as endpoint type and the 14 | typically predicted use case is to hand over the transmission for SRT for a 15 | longer distance, leaving TCP close to the caller and listener locations: 16 | 17 | ``` 18 | --> SRT> --> ... 19 | .... 20 | (long distance) 21 | .... 22 | --> TCP> --> 23 | ``` 24 | 25 | Usage 26 | ----- 27 | 28 | The `srt-tunnel` command line accepts two argument, beside the options: 29 | * Listener: the URI at which this tunnel should await connections 30 | * Caller: where this tunnel should connect when its Listener connected 31 | 32 | Options: 33 | 34 | * -ll, -loglevel: logging level, default:error 35 | * -lf, -logfa: logging Functional Area enabled 36 | * -c, -chunk: piece of data amount read at once, default=4096 bytes 37 | * -v, -verbose: display transmission details 38 | * -s, -skipflush: exit without waiting for data to complete 39 | 40 | -------------------------------------------------------------------------------- /docs/why-srt-was-created.md: -------------------------------------------------------------------------------- 1 | Some people have asked us why we're using the UDT library within our SRT protocol. Actually, some people claimed that SRT is just a slightly modified version of UDT and that UDT is known to be useless for live video transmission. Guess what, the latter is true. UDT has been designed for high throughput file transmission over public networks. However, SRT is far from being a slightly modified version of UDT. I'll get into the details, but will start with a little bit of history. 2 | 3 | Haivision has always been known for lowest latency video transmission across IP based networks, typically MPEG-TS unicast or multicast streams over the UDP protocol. This solution is perfect for protected networks and if packet loss became a problem, enabling forward error correction (FEC) fixed it. 4 | At some point we were getting questioned whether it would be possible to achieve the same latency between customer sites in different locations, between different cities, countries or even continents. Of course it's possible with satellite links or dedicated MPLS networks, but those are quite expensive solutions, so people wanted to use their public internet connectivity instead. While it's possible to go with FEC in some cases, that's not a reliable solution, as the amount of recoverable packet loss is limited, unless you accept a significant amount of bandwidth overhead. 5 | 6 | After evaluating the pros and cons of different third party solutions, we found that none satisfied all our requirements. Particularly the lack of insight into the underlying technology drove us to the decision to develop our own solution, which we then could deeply integrate into products. That way, it would become the "glue" that enables us to transmit streams between all our different products, locally or across far distances, while maintaining our low latency proposition. 7 | 8 | There were a few of possible choices to consider: 9 | - The TCP based approach. Problem for live streaming: Network congestion, too slow packet loss recovery. 10 | - The UDP based Approach. General problem: Packet loss, jitter, packet re-ordering, delay 11 | - Reliable UDP. Adds framing and selective retransmit. 12 | 13 | Having had a history with UDT for data transmission, I remembered its packet loss recovery abilities and just started playing with it. Though not designed for live streaming at all, it kind of worked when using really big buffers. I handed it over to one of our extremely talented networking guys in the embedded software team (thanks, Jean!) and asked him whether he'd be able to make this a low latency live streaming solution. I didn't hear anything back for quite a while and had almost lost my hope, when he contacted me to tell me he had to rewrite the whole packet retransmission functionality in order to be able to react to packet loss immediately when it happens and that he added an encryption protocol, which he had specified and implemented for other use cases before. Nice :-) 14 | 15 | We started testing sending low latency live streams back and forth between Germany and Montreal and it worked! However, we didn't get the latency down to a level we had hoped to achieve. The problem we faced turned out to be timing related (as always in media ...). 16 | 17 | What happened was this: 18 | ![Bad Signal](images/SRT_Transmission_Bad_Signal.png) 19 | 20 | The characteristics of the original stream on the source network got completely changed by the transmission over the public internet. The reasons are delay, jitter, packet loss and its recovery on the dirty network. The signal on the receiver side had completely different characteristics, which led to problems with decoding, as the audio and video decoders didn't get the packets at the expected times. This can be handled by buffering, but that's not what you want in low latency setups. 21 | 22 | The solution was to come up with a mechanism that recreates the signal characteristics on the receiver side. That way we were able to dramatically reduce the buffering. This functionality is part of the SRT protocol itself, so once the data comes out of the SRT protocol on the receiver side, the stream characteristics have been properly recovered. 23 | 24 | The result is a happy decoder: 25 | ![Good Signal](images/SRT_History_Good_Signal.png) 26 | 27 | We publicly showed SRT (Secure Reliable Transport) the first time at IBC 2013, where we were the only ones to show an HEVC encoded live stream, camera to glass, from a hotel suite outside the exhibition directly onto the show floor, using the network provided by the RAI. Everybody who has been at such a show before knows how bad these networks can get. And the network was bad. So bad that we expected the whole demo to fall apart, having pulled the first trial version of SRT directly from the labs. The excitement was huge, when we realized that the transmission still worked fine! 28 | 29 | Since then, we added SRT to all our products, enabling us to send high quality, low latency video from and to any endpoint, including our mobile applications. Of course there were improvements to be made and the protocol matured on the way. Until NAB 2017, where we announced that SRT is now Open Source. 30 | 31 | Marc 32 | -------------------------------------------------------------------------------- /examples/recvfile.cpp: -------------------------------------------------------------------------------- 1 | #ifndef _WIN32 2 | #include 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | if ((argc != 5) || (0 == atoi(argv[2]))) 19 | { 20 | cout << "usage: recvfile server_ip server_port remote_filename local_filename" << endl; 21 | return -1; 22 | } 23 | 24 | // use this function to initialize the UDT library 25 | srt_startup(); 26 | 27 | srt_setloglevel(srt_logging::LogLevel::debug); 28 | 29 | struct addrinfo hints, *peer; 30 | 31 | memset(&hints, 0, sizeof(struct addrinfo)); 32 | hints.ai_flags = AI_PASSIVE; 33 | hints.ai_family = AF_INET; 34 | hints.ai_socktype = SOCK_DGRAM; 35 | 36 | SRTSOCKET fhandle = srt_create_socket(); 37 | // SRT requires that third argument is always SOCK_DGRAM. The Stream API is set by an option, 38 | // although there's also lots of other options to be set, for which there's a convenience option, 39 | // SRTO_TRANSTYPE. 40 | SRT_TRANSTYPE tt = SRTT_FILE; 41 | srt_setsockopt(fhandle, 0, SRTO_TRANSTYPE, &tt, sizeof tt); 42 | 43 | if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer)) 44 | { 45 | cout << "incorrect server/peer address. " << argv[1] << ":" << argv[2] << endl; 46 | return -1; 47 | } 48 | 49 | // connect to the server, implicit bind 50 | if (SRT_ERROR == srt_connect(fhandle, peer->ai_addr, peer->ai_addrlen)) 51 | { 52 | cout << "connect: " << srt_getlasterror_str() << endl; 53 | return -1; 54 | } 55 | 56 | freeaddrinfo(peer); 57 | 58 | 59 | // send name information of the requested file 60 | int len = strlen(argv[3]); 61 | 62 | if (SRT_ERROR == srt_send(fhandle, (char*)&len, sizeof(int))) 63 | { 64 | cout << "send: " << srt_getlasterror_str() << endl; 65 | return -1; 66 | } 67 | 68 | if (SRT_ERROR == srt_send(fhandle, argv[3], len)) 69 | { 70 | cout << "send: " << srt_getlasterror_str() << endl; 71 | return -1; 72 | } 73 | 74 | // get size information 75 | int64_t size; 76 | 77 | if (SRT_ERROR == srt_recv(fhandle, (char*)&size, sizeof(int64_t))) 78 | { 79 | cout << "send: " << srt_getlasterror_str() << endl; 80 | return -1; 81 | } 82 | 83 | if (size < 0) 84 | { 85 | cout << "no such file " << argv[3] << " on the server\n"; 86 | return -1; 87 | } 88 | 89 | // receive the file 90 | //fstream ofs(argv[4], ios::out | ios::binary | ios::trunc); 91 | int64_t recvsize; 92 | int64_t offset = 0; 93 | 94 | SRT_TRACEBSTATS trace; 95 | srt_bstats(fhandle, &trace, true); 96 | 97 | if (SRT_ERROR == (recvsize = srt_recvfile(fhandle, argv[4], &offset, size, SRT_DEFAULT_RECVFILE_BLOCK))) 98 | { 99 | cout << "recvfile: " << srt_getlasterror_str() << endl; 100 | return -1; 101 | } 102 | 103 | srt_bstats(fhandle, &trace, true); 104 | 105 | cout << "speed = " << trace.mbpsRecvRate << "Mbits/sec" << endl; 106 | int losspercent = 100*trace.pktRcvLossTotal/trace.pktRecv; 107 | cout << "loss = " << trace.pktRcvLossTotal << "pkt (" << losspercent << "%)\n"; 108 | 109 | srt_close(fhandle); 110 | 111 | //ofs.close(); 112 | 113 | // use this function to release the UDT library 114 | srt_cleanup(); 115 | 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /examples/test-c-client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2017 Haivision Systems Inc. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; If not, see 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #ifdef _WIN32 23 | #define usleep(x) Sleep(x / 1000) 24 | #else 25 | #include 26 | #endif 27 | 28 | #include "srt.h" 29 | 30 | int main(int argc, char** argv) 31 | { 32 | int ss, st; 33 | struct sockaddr_in sa; 34 | int yes = 1; 35 | const char message [] = "This message should be sent to the other side"; 36 | 37 | if (argc != 3) { 38 | fprintf(stderr, "Usage: %s \n", argv[0]); 39 | return 1; 40 | } 41 | 42 | printf("srt startup\n"); 43 | srt_startup(); 44 | 45 | printf("srt socket\n"); 46 | ss = srt_create_socket(); 47 | if (ss == SRT_ERROR) 48 | { 49 | fprintf(stderr, "srt_socket: %s\n", srt_getlasterror_str()); 50 | return 1; 51 | } 52 | 53 | printf("srt remote address\n"); 54 | sa.sin_family = AF_INET; 55 | sa.sin_port = htons(atoi(argv[2])); 56 | if (inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1) 57 | { 58 | return 1; 59 | } 60 | 61 | printf("srt setsockflag\n"); 62 | srt_setsockflag(ss, SRTO_SENDER, &yes, sizeof yes); 63 | 64 | // Test deprecated 65 | //srt_setsockflag(ss, SRTO_STRICTENC, &yes, sizeof yes); 66 | 67 | printf("srt connect\n"); 68 | st = srt_connect(ss, (struct sockaddr*)&sa, sizeof sa); 69 | if (st == SRT_ERROR) 70 | { 71 | fprintf(stderr, "srt_connect: %s\n", srt_getlasterror_str()); 72 | return 1; 73 | } 74 | 75 | int i; 76 | for (i = 0; i < 100; i++) 77 | { 78 | printf("srt sendmsg2 #%d >> %s\n",i,message); 79 | st = srt_sendmsg2(ss, message, sizeof message, NULL); 80 | if (st == SRT_ERROR) 81 | { 82 | fprintf(stderr, "srt_sendmsg: %s\n", srt_getlasterror_str()); 83 | return 1; 84 | } 85 | 86 | usleep(1000); // 1 ms 87 | } 88 | 89 | 90 | printf("srt close\n"); 91 | st = srt_close(ss); 92 | if (st == SRT_ERROR) 93 | { 94 | fprintf(stderr, "srt_close: %s\n", srt_getlasterror_str()); 95 | return 1; 96 | } 97 | 98 | printf("srt cleanup\n"); 99 | srt_cleanup(); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /examples/test-c-server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2017 Haivision Systems Inc. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; If not, see 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | 23 | #include "srt.h" 24 | 25 | int main(int argc, char** argv) 26 | { 27 | int ss, st; 28 | struct sockaddr_in sa; 29 | int yes = 1; 30 | struct sockaddr_storage their_addr; 31 | 32 | if (argc != 3) { 33 | fprintf(stderr, "Usage: %s \n", argv[0]); 34 | return 1; 35 | } 36 | 37 | printf("srt startup\n"); 38 | srt_startup(); 39 | 40 | printf("srt socket\n"); 41 | ss = srt_create_socket(); 42 | if (ss == SRT_ERROR) 43 | { 44 | fprintf(stderr, "srt_socket: %s\n", srt_getlasterror_str()); 45 | return 1; 46 | } 47 | 48 | printf("srt bind address\n"); 49 | sa.sin_family = AF_INET; 50 | sa.sin_port = htons(atoi(argv[2])); 51 | if (inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1) 52 | { 53 | return 1; 54 | } 55 | 56 | printf("srt setsockflag\n"); 57 | srt_setsockflag(ss, SRTO_RCVSYN, &yes, sizeof yes); 58 | 59 | printf("srt bind\n"); 60 | st = srt_bind(ss, (struct sockaddr*)&sa, sizeof sa); 61 | if (st == SRT_ERROR) 62 | { 63 | fprintf(stderr, "srt_bind: %s\n", srt_getlasterror_str()); 64 | return 1; 65 | } 66 | 67 | printf("srt listen\n"); 68 | st = srt_listen(ss, 2); 69 | if (st == SRT_ERROR) 70 | { 71 | fprintf(stderr, "srt_listen: %s\n", srt_getlasterror_str()); 72 | return 1; 73 | } 74 | 75 | printf("srt accept\n"); 76 | int addr_size = sizeof their_addr; 77 | int their_fd = srt_accept(ss, (struct sockaddr *)&their_addr, &addr_size); 78 | 79 | int i; 80 | for (i = 0; i < 100; i++) 81 | { 82 | printf("srt recvmsg #%d... ",i); 83 | char msg[2048]; 84 | st = srt_recvmsg(their_fd, msg, sizeof msg); 85 | if (st == SRT_ERROR) 86 | { 87 | fprintf(stderr, "srt_recvmsg: %s\n", srt_getlasterror_str()); 88 | goto end; 89 | } 90 | 91 | printf("Got msg of len %d << %s\n", st, msg); 92 | } 93 | 94 | end: 95 | printf("srt close\n"); 96 | st = srt_close(ss); 97 | if (st == SRT_ERROR) 98 | { 99 | fprintf(stderr, "srt_close: %s\n", srt_getlasterror_str()); 100 | return 1; 101 | } 102 | 103 | printf("srt cleanup\n"); 104 | srt_cleanup(); 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /examples/testcapi-connect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include "srt.h" 15 | 16 | int main( int argc, char** argv ) 17 | { 18 | if (argc < 3) 19 | { 20 | fprintf(stderr, "Usage: %s \n", argv[0]); 21 | return 1; 22 | } 23 | 24 | int ss, st; 25 | struct sockaddr_in sa; 26 | int yes = 1; 27 | const char message [] = "This message should be sent to the other side"; 28 | 29 | srt_startup(); 30 | 31 | ss = srt_create_socket(); 32 | if ( ss == SRT_ERROR ) 33 | { 34 | fprintf(stderr, "srt_socket: %s\n", srt_getlasterror_str()); 35 | return 1; 36 | } 37 | 38 | sa.sin_port = htons(atoi(argv[2])); 39 | if ( inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1) 40 | { 41 | return 1; 42 | } 43 | 44 | // This is obligatory only in live mode, if you predict to connect 45 | // to a peer with SRT version 1.2.0 or older. Not required since 46 | // 1.3.0, and all older versions support only live mode. 47 | //srt_setsockflag(ss, SRTO_SENDER, &yes, sizeof yes); 48 | // 49 | // In order to make sure that the client supports non-live message 50 | // mode, let's require this. 51 | int minversion = SRT_VERSION_FEAT_HSv5; 52 | srt_setsockflag(ss, SRTO_MINVERSION, &minversion, sizeof minversion); 53 | 54 | // Require also non-live message mode. 55 | int file_mode = SRTT_FILE; 56 | srt_setsockflag(ss, SRTO_TRANSTYPE, &file_mode, sizeof file_mode); 57 | srt_setsockflag(ss, SRTO_MESSAGEAPI, &yes, sizeof yes); 58 | 59 | // Note that the other side will reject the connection if the 60 | // listener didn't set the same mode. 61 | 62 | st = srt_connect(ss, (struct sockaddr*)&sa, sizeof sa); 63 | if ( st == SRT_ERROR ) 64 | { 65 | fprintf(stderr, "srt_connect: %s\n", srt_getlasterror_str()); 66 | return 1; 67 | } 68 | 69 | st = srt_send(ss, message, sizeof message); 70 | if ( st == SRT_ERROR ) 71 | { 72 | fprintf(stderr, "srt_sendmsg: %s\n", srt_getlasterror_str()); 73 | return 1; 74 | } 75 | 76 | st = srt_close(ss); 77 | if ( st == SRT_ERROR ) 78 | { 79 | fprintf(stderr, "srt_close: %s\n", srt_getlasterror_str()); 80 | return 1; 81 | } 82 | 83 | srt_cleanup(); 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /haicrypt/cryspr-config.h: -------------------------------------------------------------------------------- 1 | #ifndef INC_SRT_CRYSPR_CONFIG_H 2 | #define INC_SRT_CRYSPR_CONFIG_H 3 | 4 | // Size of the single block for encryption. 5 | // This might need tweaking for particular implementation library. 6 | #define CRYSPR_AESBLKSZ 16 /* 128-bit */ 7 | 8 | #if defined(USE_OPENSSL) 9 | #include "cryspr-openssl.h" 10 | #define cryspr4SRT() crysprOpenSSL() 11 | #elif defined(USE_GNUTLS) 12 | #include "cryspr-gnutls.h" 13 | #define cryspr4SRT() crysprGnuTLS() 14 | #elif defined(USE_MBEDTLS) 15 | #include "cryspr-mbedtls.h" 16 | #define cryspr4SRT() crysprMbedtls() 17 | #else 18 | #error Cryspr implementation not selected. Please define USE_* + OPENSSL/GNUTLS/MBEDTLS. 19 | #endif 20 | 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /haicrypt/cryspr-gnutls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2019 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | 15 | 2019-06-27 (jdube) 16 | GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT) 17 | 18 | *****************************************************************************/ 19 | 20 | #ifndef CRYSPR_GNUTLS_H 21 | #define CRYSPR_GNUTLS_H 22 | 23 | #include 24 | #include //gnutls_rnd() 25 | 26 | #include //has AES cipher 27 | #include //has CTR cipher mode 28 | #include //has Password-based Key Derivation Function 2 29 | //#include //No need for sha1 since we have pbkdf2 30 | 31 | 32 | /* Define CRYSPR_HAS_AESCTR to 1 if this CRYSPR has AESCTR cipher mode 33 | if not set it 0 to use enable CTR cipher mode implementation using ECB cipher mode 34 | and provide the aes_ecb_cipher method. 35 | */ 36 | #define CRYSPR_HAS_AESCTR 1 37 | 38 | /* Define CRYSPR_HAS_AESKWRAP to 1 if this CRYSPR has AES Key Wrap 39 | if not set to 0 to enable default/fallback crysprFallback_AES_WrapKey/crysprFallback_AES_UnwrapKey methods 40 | and provide the aes_ecb_cipher method . 41 | */ 42 | #define CRYSPR_HAS_AESKWRAP 0 43 | 44 | /* Define CRYSPR_HAS_PBKDF2 to 1 if this CRYSPR has SHA1-HMAC Password-based Key Derivaion Function 2 45 | if not set to 0 to enable not-yet-implemented/fallback crysprFallback.km_pbkdf2 method 46 | and provide the sha1_msg_digest method. 47 | */ 48 | #define CRYSPR_HAS_PBKDF2 1 49 | 50 | /* 51 | #define CRYSPR_AESCTX to the CRYSPR specifix AES key context object. 52 | This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK 53 | It is set from hte keystring through CRYSPR_methods.aes_set_key and passed 54 | to CRYSPR_methods.aes_XXX. 55 | */ 56 | typedef struct aes_ctx CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */ 57 | 58 | struct tag_CRYSPR_methods *crysprGnuTLS(void); 59 | 60 | #endif /* CRYSPR_GNUTLS_H */ 61 | 62 | -------------------------------------------------------------------------------- /haicrypt/cryspr-mbedtls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2019 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | 15 | 2019-06-27 (jdube) 16 | GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT) 17 | 18 | *****************************************************************************/ 19 | 20 | #ifndef CRYSPR_GNUTLS_H 21 | #define CRYSPR_GNUTLS_H 22 | 23 | #include 24 | #include 25 | 26 | 27 | /* Define CRYSPR_HAS_AESCTR to 1 if this CRYSPR has AESCTR cipher mode 28 | if not set it 0 to use enable CTR cipher mode implementation using ECB cipher mode 29 | and provide the aes_ecb_cipher method. 30 | */ 31 | #define CRYSPR_HAS_AESCTR 1 32 | 33 | /* Define CRYSPR_HAS_AESKWRAP to 1 if this CRYSPR has AES Key Wrap 34 | if not set to 0 to enable default/fallback crysprFallback_AES_WrapKey/crysprFallback_AES_UnwrapKey methods 35 | and provide the aes_ecb_cipher method . 36 | */ 37 | #define CRYSPR_HAS_AESKWRAP 0 38 | 39 | /* Define CRYSPR_HAS_PBKDF2 to 1 if this CRYSPR has SHA1-HMAC Password-based Key Derivaion Function 2 40 | if not set to 0 to enable not-yet-implemented/fallback crysprFallback.km_pbkdf2 method 41 | and provide the sha1_msg_digest method. 42 | */ 43 | #define CRYSPR_HAS_PBKDF2 1 44 | 45 | // mbedtls uses in the enc/dec functions 16-byte blocks 46 | // for xcryption. This is not marked by any constant. See 47 | // e.g. , mbedtls_aes_crypt_ecb signature. 48 | #if CRYSPR_AESBLKSZ != 16 49 | #error mbedtls requires AES single block size 16 bytes, implicitly. 50 | #endif 51 | 52 | /* 53 | #define CRYSPR_AESCTX to the CRYSPR specifix AES key context object. 54 | This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK 55 | It is set from hte keystring through CRYSPR_methods.aes_set_key and passed 56 | to CRYSPR_methods.aes_XXX. 57 | */ 58 | typedef struct mbedtls_aes_context CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */ 59 | 60 | struct tag_CRYSPR_methods *crysprMbedtls(void); 61 | 62 | #endif /* CRYSPR_GNUTLS_H */ 63 | 64 | -------------------------------------------------------------------------------- /haicrypt/cryspr-openssl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2019 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | /***************************************************************************** 13 | written by 14 | Haivision Systems Inc. 15 | 16 | 2019-06-26 (jdube) 17 | OpenSSL Direct AES CRYSPR/4SRT (CRYypto Service PRovider for SRT). 18 | *****************************************************************************/ 19 | 20 | #ifndef CRYSPR_OPENSSL_H 21 | #define CRYSPR_OPENSSL_H 22 | 23 | #include /* PKCS5_xxx() */ 24 | #include /* AES_xxx() */ 25 | #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)) 26 | # include /* CRYPTO_xxx() */ 27 | #endif 28 | #include 29 | #include 30 | #include /* OPENSSL_VERSION_NUMBER */ 31 | 32 | /* Define CRYSPR_HAS_AESCTR to 1 if this CRYSPR has AESCTR cipher mode 33 | if not set it 0 to use enable CTR cipher mode implementation using ECB cipher mode 34 | and provide the aes_ecb_cipher method. 35 | */ 36 | #define CRYSPR_HAS_AESCTR 1 37 | 38 | /* Define CRYSPR_HAS_AESKWRAP to 1 if this CRYSPR has AES Key Wrap 39 | if not set to 0 to enable default/fallback crysprFallback_AES_WrapKey/crysprFallback_AES_UnwrapKey methods 40 | and provide the aes_ecb_cipher method . 41 | */ 42 | #if (OPENSSL_VERSION_NUMBER < 0x0090808fL) //0.9.8h 43 | #define CRYSPR_HAS_AESKWRAP 0 44 | #else 45 | #define CRYSPR_HAS_AESKWRAP 1 46 | #endif 47 | 48 | /* Define CRYSPR_HAS_PBKDF2 to 1 if this CRYSPR has SHA1-HMAC Password-based Key Derivaion Function 2 49 | if not set to 0 to enable not-yet-implemented/fallback crysprFallback.km_pbkdf2 method 50 | and provide the sha1_msg_digest method. 51 | */ 52 | #define CRYSPR_HAS_PBKDF2 1 /* Define to 1 if CRYSPR has Password-based Key Derivaion Function 2 */ 53 | 54 | /* 55 | #define CRYSPR_AESCTX to the CRYSPR specifix AES key context object. 56 | This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK 57 | It is set from hte keystring through CRYSPR_methods.aes_set_key and passed 58 | to CRYSPR_methods.aes_*. 59 | */ 60 | typedef AES_KEY CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */ 61 | 62 | struct tag_CRYSPR_methods *crysprOpenSSL(void); 63 | 64 | #endif /* CRYSPR_OPENSSL_H */ 65 | 66 | -------------------------------------------------------------------------------- /haicrypt/filelist-gnutls.maf: -------------------------------------------------------------------------------- 1 | # This file is currently reserved for future refactoring, when all headers 2 | # are going to be moved here. This is the list of headers considered to be 3 | # attached to the installation package. Once possible, please move the below 4 | # header files from ../include back to this directory. 5 | PUBLIC HEADERS 6 | haicrypt.h 7 | hcrypt_ctx.h 8 | hcrypt_msg.h 9 | 10 | PRIVATE HEADERS 11 | hcrypt.h 12 | cryspr.h 13 | cryspr-gnutls.h 14 | haicrypt_log.h 15 | 16 | SOURCES 17 | cryspr.c 18 | cryspr-gnutls.c 19 | hcrypt.c 20 | hcrypt_ctx_rx.c 21 | hcrypt_ctx_tx.c 22 | hcrypt_rx.c 23 | hcrypt_sa.c 24 | hcrypt_tx.c 25 | hcrypt_xpt_srt.c 26 | haicrypt_log.cpp 27 | -------------------------------------------------------------------------------- /haicrypt/filelist-mbedtls.maf: -------------------------------------------------------------------------------- 1 | # HaiCrypt library contents 2 | 3 | PUBLIC HEADERS 4 | haicrypt.h 5 | hcrypt_ctx.h 6 | hcrypt_msg.h 7 | 8 | PRIVATE HEADERS 9 | hcrypt.h 10 | cryspr.h 11 | cryspr-mbedtls.h 12 | haicrypt_log.h 13 | 14 | SOURCES 15 | cryspr.c 16 | cryspr-mbedtls.c 17 | hcrypt.c 18 | hcrypt_ctx_rx.c 19 | hcrypt_ctx_tx.c 20 | hcrypt_rx.c 21 | hcrypt_sa.c 22 | hcrypt_tx.c 23 | hcrypt_xpt_srt.c 24 | haicrypt_log.cpp 25 | -------------------------------------------------------------------------------- /haicrypt/filelist-openssl.maf: -------------------------------------------------------------------------------- 1 | # HaiCrypt library contents 2 | 3 | PUBLIC HEADERS 4 | haicrypt.h 5 | hcrypt_ctx.h 6 | hcrypt_msg.h 7 | 8 | PRIVATE HEADERS 9 | hcrypt.h 10 | cryspr.h 11 | cryspr-openssl.h 12 | haicrypt_log.h 13 | 14 | SOURCES 15 | cryspr.c 16 | cryspr-openssl.c 17 | hcrypt.c 18 | hcrypt_ctx_rx.c 19 | hcrypt_ctx_tx.c 20 | hcrypt_rx.c 21 | hcrypt_sa.c 22 | hcrypt_tx.c 23 | hcrypt_xpt_srt.c 24 | haicrypt_log.cpp 25 | -------------------------------------------------------------------------------- /haicrypt/haicrypt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | 15 | 2011-06-23 (jdube) 16 | HaiCrypt initial implementation. 17 | 2014-03-11 (jdube) 18 | Adaptation for SRT. 19 | *****************************************************************************/ 20 | 21 | #ifndef HAICRYPT_H 22 | #define HAICRYPT_H 23 | 24 | #include 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | typedef void *HaiCrypt_Cryspr; 31 | 32 | HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance (void); /* Return a default cryspr instance */ 33 | 34 | #define HAICRYPT_CIPHER_BLK_SZ 16 /* AES Block Size */ 35 | 36 | #define HAICRYPT_PWD_MAX_SZ 80 /* MAX password (for Password-based Key Derivation) */ 37 | #define HAICRYPT_KEY_MAX_SZ 32 /* MAX key */ 38 | #define HAICRYPT_SECRET_MAX_SZ (HAICRYPT_PWD_MAX_SZ > HAICRYPT_KEY_MAX_SZ ? HAICRYPT_PWD_MAX_SZ : HAICRYPT_KEY_MAX_SZ) 39 | 40 | 41 | #define HAICRYPT_SALT_SZ 16 42 | 43 | #define HAICRYPT_WRAPKEY_SIGN_SZ 8 /* RFC3394 AES KeyWrap signature size */ 44 | 45 | #define HAICRYPT_PBKDF2_SALT_LEN 8 /* PKCS#5 PBKDF2 Password based key derivation salt length */ 46 | #define HAICRYPT_PBKDF2_ITER_CNT 2048 /* PKCS#5 PBKDF2 Password based key derivation iteration count */ 47 | 48 | #define HAICRYPT_TS_PKT_SZ 188 /* Transport Stream packet size */ 49 | 50 | typedef struct { 51 | #define HAICRYPT_SECTYP_UNDEF 0 52 | #define HAICRYPT_SECTYP_PRESHARED 1 /* Preshared KEK */ 53 | #define HAICRYPT_SECTYP_PASSPHRASE 2 /* Password */ 54 | unsigned typ; 55 | size_t len; 56 | unsigned char str[HAICRYPT_SECRET_MAX_SZ]; 57 | }HaiCrypt_Secret; 58 | 59 | typedef struct { 60 | #define HAICRYPT_CFG_F_TX 0x01 /* !TX -> RX */ 61 | #define HAICRYPT_CFG_F_CRYPTO 0x02 /* Perform crypto Tx:Encrypt Rx:Decrypt */ 62 | #define HAICRYPT_CFG_F_FEC 0x04 /* Do Forward Error Correction */ 63 | unsigned flags; 64 | 65 | HaiCrypt_Secret secret; /* Security Association */ 66 | 67 | HaiCrypt_Cryspr cryspr; /* CRYSPR implementation */ 68 | #define HAICRYPT_DEF_KEY_LENGTH 16 /* default key length (bytes) */ 69 | size_t key_len; /* SEK length (bytes) */ 70 | #define HAICRYPT_DEF_DATA_MAX_LENGTH 1500 /* default packet data length (bytes) */ 71 | size_t data_max_len; /* Maximum data_len passed to HaiCrypt (bytes) */ 72 | 73 | #define HAICRYPT_XPT_STANDALONE 0 74 | #define HAICRYPT_XPT_SRT 1 75 | int xport; 76 | 77 | #define HAICRYPT_DEF_KM_TX_PERIOD 1000 /* Keying Material Default Tx Period (msec) */ 78 | unsigned int km_tx_period_ms; /* Keying Material Tx period (msec) */ 79 | #define HAICRYPT_DEF_KM_REFRESH_RATE 0x1000000 /* Keying Material Default Refresh Rate (pkts) */ 80 | unsigned int km_refresh_rate_pkt; /* Keying Material Refresh Rate (pkts) */ 81 | #define HAICRYPT_DEF_KM_PRE_ANNOUNCE 0x1000 /* Keying Material Default Pre/Post Announce (pkts) */ 82 | unsigned int km_pre_announce_pkt; /* Keying Material Pre/Post Announce (pkts) */ 83 | }HaiCrypt_Cfg; 84 | 85 | typedef enum HaiCrypt_CryptoDir { HAICRYPT_CRYPTO_DIR_RX, HAICRYPT_CRYPTO_DIR_TX } HaiCrypt_CryptoDir; 86 | 87 | //typedef void *HaiCrypt_Handle; 88 | // internally it will be correctly interpreted, 89 | // for the outsider it's just some kinda incomplete type 90 | // but still if you use any kinda pointer instead, you'll get complaints 91 | typedef struct hcrypt_Session_str* HaiCrypt_Handle; 92 | 93 | 94 | 95 | int HaiCrypt_SetLogLevel(int level, int logfa); 96 | 97 | int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc); 98 | int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handle *phhc); 99 | int HaiCrypt_Close(HaiCrypt_Handle hhc); 100 | int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_p); 101 | int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len, 102 | void *out_p[], size_t out_len_p[], int maxout); 103 | int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len, 104 | void *out_p[], size_t out_len_p[], int maxout); 105 | 106 | int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc); 107 | int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout); 108 | int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len); 109 | int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len); 110 | 111 | /* Status values */ 112 | 113 | #define HAICRYPT_ERROR -1 114 | #define HAICRYPT_ERROR_WRONG_SECRET -2 115 | #define HAICRYPT_OK 0 116 | 117 | 118 | #ifdef __cplusplus 119 | } 120 | #endif 121 | 122 | #endif /* HAICRYPT_H */ 123 | -------------------------------------------------------------------------------- /haicrypt/haicrypt_log.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #if ENABLE_HAICRYPT_LOGGING 12 | 13 | #include "hcrypt.h" 14 | #include "haicrypt.h" 15 | #include "../srtcore/srt.h" 16 | #include "../srtcore/logging.h" 17 | 18 | extern srt_logging::LogConfig srt_logger_config; 19 | 20 | // LOGFA symbol defined in srt.h 21 | srt_logging::Logger hclog(SRT_LOGFA_HAICRYPT, srt_logger_config, "SRT.hc"); 22 | 23 | extern "C" { 24 | 25 | int HaiCrypt_SetLogLevel(int level, int logfa) 26 | { 27 | srt_setloglevel(level); 28 | if (logfa != SRT_LOGFA_GENERAL) // General can't be turned on or off 29 | { 30 | srt_addlogfa(logfa); 31 | } 32 | return 0; 33 | } 34 | 35 | // HaiCrypt will be using its own FA, which will be turned off by default. 36 | 37 | // Templates made C way. 38 | // It's tempting to use the HAICRYPT_DEFINE_LOG_DISPATCHER macro here because it would provide the 39 | // exact signature that is needed here, the problem is though that this would expand the LOGLEVEL 40 | // parameter, which is also a macro, into the value that the macro designates, which would generate 41 | // the HaiCrypt_LogF_0 instead of HaiCrypt_LogF_LOG_DEBUG, for example. 42 | #define HAICRYPT_DEFINE_LOG_DISPATCHER(LOGLEVEL, dispatcher) \ 43 | int HaiCrypt_LogF_##LOGLEVEL ( const char* file, int line, const char* function, const char* format, ...) \ 44 | { \ 45 | va_list ap; \ 46 | va_start(ap, format); \ 47 | srt_logging::LogDispatcher& lg = hclog.dispatcher; \ 48 | if (!lg.CheckEnabled()) return -1; \ 49 | lg().setloc(file, line, function).vform(format, ap); \ 50 | va_end(ap); \ 51 | return 0; \ 52 | } 53 | 54 | 55 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_DEBUG, Debug); 56 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_NOTICE, Note); 57 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_INFO, Note); 58 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_WARNING, Warn); 59 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_ERR, Error); 60 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_CRIT, Fatal); 61 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_ALERT, Fatal); 62 | HAICRYPT_DEFINE_LOG_DISPATCHER(LOG_EMERG, Fatal); 63 | 64 | 65 | static void DumpCfgFlags(int flags, std::ostream& out) 66 | { 67 | static struct { int flg; const char* desc; } flgtable [] = { 68 | #define HCRYPTF(name) { HAICRYPT_CFG_F_##name, #name } 69 | HCRYPTF(TX), 70 | HCRYPTF(CRYPTO), 71 | HCRYPTF(FEC) 72 | #undef HCRYPTF 73 | }; 74 | size_t flgtable_size = sizeof(flgtable)/sizeof(flgtable[0]); 75 | size_t i; 76 | 77 | out << "{"; 78 | const char* sep = ""; 79 | const char* sep_bar = " | "; 80 | for (i = 0; i < flgtable_size; ++i) 81 | { 82 | if ( (flgtable[i].flg & flags) != 0 ) 83 | { 84 | out << sep << flgtable[i].desc; 85 | sep = sep_bar; 86 | } 87 | } 88 | out << "}"; 89 | } 90 | 91 | void HaiCrypt_DumpConfig(const HaiCrypt_Cfg* cfg) 92 | { 93 | std::ostringstream cfg_flags; 94 | 95 | DumpCfgFlags(cfg->flags, cfg_flags); 96 | 97 | LOGC(hclog.Debug, log << "CFG DUMP: flags=" << cfg_flags.str() 98 | << " xport=" << (cfg->xport == HAICRYPT_XPT_SRT ? "SRT" : "INVALID") 99 | << " cipher=" 100 | << (cfg->cipher == HaiCryptCipher_OpenSSL_EVP_CTR() ? "OSSL-EVP-CTR": 101 | cfg->cipher == HaiCryptCipher_OpenSSL_AES() ? "OSSL-AES": 102 | // This below is used as the only one when Nettle is used. When OpenSSL 103 | // is used, one of the above will trigger, and the one below will then never trigger. 104 | cfg->cipher == HaiCryptCipher_Get_Instance() ? "Nettle-AES": 105 | "UNKNOWN") 106 | << " key_len=" << cfg->key_len << " data_max_len=" << cfg->data_max_len); 107 | 108 | 109 | LOGC(hclog.Debug, log << "CFG DUMP: txperiod=" 110 | << cfg->km_tx_period_ms << "ms kmrefresh=" << cfg->km_refresh_rate_pkt 111 | << " kmpreannounce=" << cfg->km_pre_announce_pkt 112 | << " secret " 113 | << "{tp=" << (cfg->secret.typ == 1 ? "PSK" : cfg->secret.typ == 2 ? "PWD" : "???") 114 | << " len=" << cfg->secret.len << " pwd=" << cfg->secret.str << "}"); 115 | 116 | } 117 | 118 | } // extern "C" 119 | 120 | #endif // Block for the whole file 121 | -------------------------------------------------------------------------------- /haicrypt/haicrypt_log.h: -------------------------------------------------------------------------------- 1 | #ifndef INC_SRT_HAICRYPT_LOG_H 2 | #define INC_SRT_HAICRYPT_LOG_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define HAICRYPT_DECLARE_LOG_DISPATCHER(LOGLEVEL) \ 9 | int HaiCrypt_LogF_##LOGLEVEL ( const char* file, int line, const char* function, const char* format, ...) 10 | 11 | // Now declare all dispatcher functions 12 | 13 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_DEBUG); 14 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_NOTICE); 15 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_INFO); 16 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_WARNING); 17 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_ERR); 18 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_CRIT); 19 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_ALERT); 20 | HAICRYPT_DECLARE_LOG_DISPATCHER(LOG_EMERG); 21 | 22 | #define HCRYPT_LOG_INIT() 23 | #define HCRYPT_LOG_EXIT() 24 | #define HCRYPT_LOG(lvl, fmt, ...) HaiCrypt_LogF_##lvl (__FILE__, __LINE__, __FUNCTION__, fmt, __VA_ARGS__) 25 | 26 | #if ENABLE_HAICRYPT_LOGGING == 2 27 | #define HCRYPT_DEV 1 28 | #endif 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif // macroguard 35 | -------------------------------------------------------------------------------- /haicrypt/hcrypt_ctx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | /***************************************************************************** 13 | written by 14 | Haivision Systems Inc. 15 | 16 | 2011-06-23 (jdube) 17 | HaiCrypt initial implementation. 18 | 2014-03-11 (jdube) 19 | Adaptation for SRT. 20 | *****************************************************************************/ 21 | 22 | #ifndef HCRYPT_CTX_H 23 | #define HCRYPT_CTX_H 24 | 25 | #include 26 | #include 27 | #include "hcrypt.h" 28 | 29 | #if !defined(HAISRT_VERSION_INT) 30 | #include "haicrypt.h" 31 | #include "hcrypt_msg.h" 32 | #else 33 | // Included by haisrt.h or similar 34 | #include "haisrt/haicrypt.h" 35 | #include "haisrt/hcrypt_msg.h" 36 | #endif 37 | 38 | typedef struct { 39 | unsigned char *pfx; //Prefix described by transport msg info (in ctx) 40 | unsigned char *payload; 41 | size_t len; //Payload size 42 | }hcrypt_DataDesc; 43 | 44 | 45 | typedef struct tag_hcrypt_Ctx { 46 | struct tag_hcrypt_Ctx * alt; /* Alternative ctx (even/odd) */ 47 | 48 | #define HCRYPT_CTX_F_MSG 0x00FF /* Aligned wiht message header flags */ 49 | #define HCRYPT_CTX_F_eSEK HCRYPT_MSG_F_eSEK 50 | #define HCRYPT_CTX_F_oSEK HCRYPT_MSG_F_oSEK 51 | #define HCRYPT_CTX_F_xSEK HCRYPT_MSG_F_xSEK 52 | 53 | #define HCRYPT_CTX_F_ENCRYPT 0x0100 /* 0:decrypt 1:encrypt */ 54 | #define HCRYPT_CTX_F_ANNOUNCE 0x0200 /* Announce KM */ 55 | #define HCRYPT_CTX_F_TTSEND 0x0400 /* time to send */ 56 | unsigned flags; 57 | #define hcryptCtx_GetKeyFlags(ctx) ((ctx)->flags & HCRYPT_CTX_F_xSEK) 58 | #define hcryptCtx_GetKeyIndex(ctx) (((ctx)->flags & HCRYPT_CTX_F_xSEK)>>1) 59 | 60 | #define HCRYPT_CTX_S_INIT 1 61 | #define HCRYPT_CTX_S_SARDY 2 /* Security Association (KEK) ready */ 62 | #define HCRYPT_CTX_S_KEYED 3 /* Media Stream Encrypting Key (SEK) ready */ 63 | #define HCRYPT_CTX_S_ACTIVE 4 /* Announced and in use */ 64 | #define HCRYPT_CTX_S_DEPRECATED 5 /* Still announced but no longer used */ 65 | unsigned status; 66 | 67 | #define HCRYPT_CTX_MODE_CLRTXT 0 /* NULL cipher (for tests) */ 68 | #define HCRYPT_CTX_MODE_AESECB 1 /* Electronic Code Book mode */ 69 | #define HCRYPT_CTX_MODE_AESCTR 2 /* Counter mode */ 70 | #define HCRYPT_CTX_MODE_AESCBC 3 /* Cipher-block chaining mode */ 71 | unsigned mode; 72 | 73 | struct { 74 | size_t key_len; 75 | size_t pwd_len; 76 | char pwd[HAICRYPT_PWD_MAX_SZ]; 77 | } cfg; 78 | 79 | size_t salt_len; 80 | unsigned char salt[HAICRYPT_SALT_SZ]; 81 | 82 | size_t sek_len; 83 | unsigned char sek[HAICRYPT_KEY_MAX_SZ]; 84 | 85 | hcrypt_MsgInfo * msg_info; /* Transport message handler */ 86 | unsigned pkt_cnt; /* Key usage counter */ 87 | 88 | #define HCRYPT_CTX_MAX_KM_PFX_SZ 16 89 | size_t KMmsg_len; 90 | unsigned char KMmsg_cache[HCRYPT_CTX_MAX_KM_PFX_SZ + HCRYPT_MSG_KM_MAX_SZ]; 91 | 92 | #define HCRYPT_CTX_MAX_MS_PFX_SZ 16 93 | unsigned char MSpfx_cache[HCRYPT_CTX_MAX_MS_PFX_SZ]; 94 | } hcrypt_Ctx; 95 | 96 | 97 | #endif /* HCRYPT_CTX_H */ 98 | -------------------------------------------------------------------------------- /haicrypt/hcrypt_rx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | /***************************************************************************** 13 | written by 14 | Haivision Systems Inc. 15 | 16 | 2011-06-23 (jdube) 17 | HaiCrypt initial implementation. 18 | 2014-03-11 (jdube) 19 | Adaptation for SRT. 20 | *****************************************************************************/ 21 | 22 | #include /* NULL */ 23 | #include /* memcmp */ 24 | #include "hcrypt.h" 25 | 26 | int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc, 27 | unsigned char *in_pfx, unsigned char *data, size_t data_len) 28 | { 29 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 30 | hcrypt_Ctx *ctx; 31 | int nb = -1; 32 | 33 | if ((NULL == crypto) 34 | || (NULL == data)) { 35 | HCRYPT_LOG(LOG_ERR, "%s", "invalid parameters\n"); 36 | return(nb); 37 | } 38 | 39 | ctx = &crypto->ctx_pair[hcryptMsg_GetKeyIndex(crypto->msg_info, in_pfx)]; 40 | 41 | ASSERT(NULL != ctx); /* Header check should prevent this error */ 42 | ASSERT(NULL != crypto->cryspr); /* Header check should prevent this error */ 43 | 44 | crypto->ctx = ctx; /* Context of last received msg */ 45 | if (NULL == crypto->cryspr->ms_decrypt) { 46 | HCRYPT_LOG(LOG_ERR, "%s", "cryspr had no decryptor\n"); 47 | } else if (ctx->status >= HCRYPT_CTX_S_KEYED) { 48 | hcrypt_DataDesc indata; 49 | indata.pfx = in_pfx; 50 | indata.payload = data; 51 | indata.len = data_len; 52 | 53 | if (0 > (nb = crypto->cryspr->ms_decrypt(crypto->cryspr_cb, ctx, &indata, 1, NULL, NULL, NULL))) { 54 | HCRYPT_LOG(LOG_ERR, "%s", "ms_decrypt failed\n"); 55 | } else { 56 | nb = indata.len; 57 | } 58 | } else { /* No key received yet */ 59 | nb = 0; 60 | } 61 | return(nb); 62 | } 63 | 64 | int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc, 65 | unsigned char *in_msg, size_t in_len, 66 | void *out_p[], size_t out_len_p[], int maxout) 67 | { 68 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 69 | hcrypt_Ctx *ctx; 70 | int nbout = maxout; 71 | int msg_type; 72 | 73 | if ((NULL == crypto) 74 | || (NULL == in_msg)) { 75 | 76 | HCRYPT_LOG(LOG_ERR, "%s", "invalid parameters\n"); 77 | return(-1); 78 | } 79 | 80 | /* Validate HaiCrypt message */ 81 | if (0 > (msg_type = crypto->msg_info->parseMsg(in_msg))) { 82 | return(-1); 83 | } 84 | 85 | switch(msg_type) { 86 | case HCRYPT_MSG_PT_MS: /* MSmsg */ 87 | ctx = &crypto->ctx_pair[hcryptMsg_GetKeyIndex(crypto->msg_info, in_msg)]; 88 | 89 | if ((NULL == out_p) 90 | || (NULL == out_len_p)) { 91 | HCRYPT_LOG(LOG_ERR, "%s", "invalid parameters\n"); 92 | return(-1); 93 | } 94 | ASSERT(NULL != ctx); /* Header check should prevent this error */ 95 | ASSERT(NULL != crypto->cryspr); /* Header check should prevent this error */ 96 | 97 | crypto->ctx = ctx; /* Context of last received msg */ 98 | if (NULL == crypto->cryspr->ms_decrypt) { 99 | HCRYPT_LOG(LOG_ERR, "%s", "cryspr had no decryptor\n"); 100 | nbout = -1; 101 | } else if (ctx->status >= HCRYPT_CTX_S_KEYED) { 102 | hcrypt_DataDesc indata; 103 | indata.pfx = in_msg; 104 | indata.payload = &in_msg[crypto->msg_info->pfx_len]; 105 | indata.len = in_len - crypto->msg_info->pfx_len; 106 | 107 | if (crypto->cryspr->ms_decrypt(crypto->cryspr_cb, ctx, &indata, 1, out_p, out_len_p, &nbout)) { 108 | HCRYPT_LOG(LOG_ERR, "%s", "ms_decrypt failed\n"); 109 | nbout = -1; 110 | } 111 | } else { /* No key received yet */ 112 | nbout = 0; 113 | } 114 | break; 115 | 116 | case HCRYPT_MSG_PT_KM: /* KMmsg */ 117 | /* Even or Both SEKs check with even context */ 118 | ctx = &crypto->ctx_pair[hcryptMsg_GetKeyIndex(crypto->msg_info, in_msg)]; 119 | 120 | ASSERT(NULL != ctx); /* Header check should prevent this error */ 121 | 122 | if ((ctx->status < HCRYPT_CTX_S_KEYED) /* No key deciphered yet */ 123 | || (in_len != ctx->KMmsg_len) /* or not same size */ 124 | || (0 != memcmp(ctx->KMmsg_cache, in_msg, in_len))) { /* or different */ 125 | 126 | nbout = hcryptCtx_Rx_ParseKM(crypto, in_msg, in_len); 127 | //-2: unmatched shared secret 128 | //-1: other failures 129 | //0: success 130 | } else { 131 | nbout = 0; 132 | } 133 | if (NULL != out_p) out_p[0] = NULL; 134 | if (NULL != out_len_p) out_len_p[0] = 0; 135 | break; 136 | 137 | default: 138 | HCRYPT_LOG(LOG_WARNING, "%s", "unknown packet type\n"); 139 | nbout = 0; 140 | break; 141 | } 142 | 143 | return(nbout); 144 | } 145 | 146 | 147 | -------------------------------------------------------------------------------- /haicrypt/hcrypt_sa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | /***************************************************************************** 13 | written by 14 | Haivision Systems Inc. 15 | 16 | 2011-06-23 (jdube) 17 | HaiCrypt initial implementation. 18 | *****************************************************************************/ 19 | 20 | /* 21 | * For now: 22 | * Pre-shared or password derived KEK (Key Encrypting Key) 23 | * Future: 24 | * Certificate-based association 25 | */ 26 | #include /* memcpy */ 27 | #include "hcrypt.h" 28 | 29 | int hcryptCtx_SetSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_Secret *secret) 30 | { 31 | int iret; 32 | (void)crypto; 33 | 34 | switch(secret->typ) { 35 | case HAICRYPT_SECTYP_PRESHARED: 36 | ASSERT(secret->len <= HAICRYPT_KEY_MAX_SZ); 37 | ctx->cfg.pwd_len = 0; 38 | /* KEK: Key Encrypting Key */ 39 | if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, 40 | (HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false), 41 | secret->str, secret->len))) { 42 | HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", secret->len, iret); 43 | return(-1); 44 | } 45 | ctx->status = HCRYPT_CTX_S_SARDY; 46 | break; 47 | 48 | case HAICRYPT_SECTYP_PASSPHRASE: 49 | ASSERT(secret->len <= sizeof(ctx->cfg.pwd)); 50 | memcpy(ctx->cfg.pwd, secret->str, secret->len); 51 | ctx->cfg.pwd_len = secret->len; 52 | /* KEK will be derived from password with Salt */ 53 | ctx->status = HCRYPT_CTX_S_SARDY; 54 | break; 55 | 56 | default: 57 | HCRYPT_LOG(LOG_ERR, "Unknown secret type %d\n", 58 | secret->typ); 59 | return(-1); 60 | } 61 | return(0); 62 | } 63 | 64 | int hcryptCtx_GenSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx) 65 | { 66 | /* 67 | * KEK need same length as the key it protects (SEK) 68 | * KEK = PBKDF2(Pwd, LSB(64, Salt), Iter, Klen) 69 | */ 70 | unsigned char kek[HAICRYPT_KEY_MAX_SZ]; 71 | size_t kek_len = ctx->sek_len; 72 | size_t pbkdf_salt_len = (ctx->salt_len >= HAICRYPT_PBKDF2_SALT_LEN 73 | ? HAICRYPT_PBKDF2_SALT_LEN 74 | : ctx->salt_len); 75 | int iret = 0; 76 | (void)crypto; 77 | 78 | iret = crypto->cryspr->km_pbkdf2(crypto->cryspr_cb, ctx->cfg.pwd, ctx->cfg.pwd_len, 79 | &ctx->salt[ctx->salt_len - pbkdf_salt_len], pbkdf_salt_len, 80 | HAICRYPT_PBKDF2_ITER_CNT, kek_len, kek); 81 | 82 | if(iret) { 83 | HCRYPT_LOG(LOG_ERR, "km_pbkdf2() failed (rc=%d)\n", iret); 84 | return(-1); 85 | } 86 | HCRYPT_PRINTKEY(ctx->cfg.pwd, ctx->cfg.pwd_len, "pwd"); 87 | HCRYPT_PRINTKEY(kek, kek_len, "kek"); 88 | 89 | /* KEK: Key Encrypting Key */ 90 | if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, (HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false), kek, kek_len))) { 91 | HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", kek_len, iret); 92 | return(-1); 93 | } 94 | return(0); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /haicrypt/hcrypt_tx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | /***************************************************************************** 13 | written by 14 | Haivision Systems Inc. 15 | 16 | 2011-06-23 (jdube) 17 | HaiCrypt initial implementation. 18 | 2014-03-11 (jdube) 19 | Adaptation for SRT. 20 | *****************************************************************************/ 21 | 22 | #include 23 | #include /* NULL */ 24 | #include /* memcpy */ 25 | #ifdef _WIN32 26 | #include 27 | #include 28 | #include 29 | #else 30 | #include /* htonl */ 31 | #endif 32 | #include "hcrypt.h" 33 | 34 | int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_pp) 35 | { 36 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 37 | 38 | ASSERT(NULL != crypto); 39 | ASSERT(NULL != crypto->cryspr); 40 | 41 | int pad_factor = (HCRYPT_CTX_MODE_AESECB == crypto->ctx->mode ? 128/8 : 1); 42 | 43 | #ifndef _WIN32 44 | ASSERT(crypto->inbuf != NULL); 45 | #endif 46 | size_t in_len = crypto->msg_info->pfx_len + hcryptMsg_PaddedLen(data_len, pad_factor); 47 | *in_pp = crypto->inbuf; 48 | if (in_len > crypto->inbuf_siz) { 49 | *in_pp = NULL; 50 | return(-1); 51 | } 52 | return(crypto->msg_info->pfx_len); 53 | } 54 | 55 | int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout) 56 | { 57 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 58 | hcrypt_Ctx *ctx = crypto->ctx; 59 | int nbout = 0; 60 | 61 | if ((NULL == crypto) 62 | || (NULL == ctx) 63 | || (NULL == out_p) 64 | || (NULL == out_len_p)) { 65 | HCRYPT_LOG(LOG_ERR, "ManageKeys: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx); 66 | return(-1); 67 | } 68 | 69 | /* Manage Key Material (refresh, announce, decommission) */ 70 | hcryptCtx_Tx_ManageKM(crypto); 71 | 72 | ctx = crypto->ctx; 73 | if (NULL == ctx) { 74 | HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n"); 75 | return(-1); 76 | } 77 | ASSERT(ctx->status == HCRYPT_CTX_S_ACTIVE); 78 | 79 | nbout = hcryptCtx_Tx_InjectKM(crypto, out_p, out_len_p, maxout); 80 | return(nbout); 81 | } 82 | 83 | int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc) 84 | { 85 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 86 | hcrypt_Ctx *ctx = crypto->ctx; 87 | 88 | if ((NULL == crypto) 89 | || (NULL == ctx)){ 90 | HCRYPT_LOG(LOG_ERR, "GetKeyFlags: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx); 91 | return(-1); 92 | } 93 | return(hcryptCtx_GetKeyFlags(ctx)); 94 | } 95 | 96 | int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc, 97 | unsigned char *in_pfx, unsigned char *in_data, size_t in_len) 98 | { 99 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 100 | hcrypt_Ctx *ctx = crypto->ctx; 101 | int nbout = 0; 102 | 103 | if ((NULL == crypto) 104 | || (NULL == ctx)){ 105 | HCRYPT_LOG(LOG_ERR, "Tx_Data: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx); 106 | return(-1); 107 | } 108 | /* Get/Set packet index */ 109 | ctx->msg_info->indexMsg(in_pfx, ctx->MSpfx_cache); 110 | 111 | /* Encrypt */ 112 | { 113 | hcrypt_DataDesc indata; 114 | indata.pfx = in_pfx; 115 | indata.payload = in_data; 116 | indata.len = in_len; 117 | 118 | if (0 > (nbout = crypto->cryspr->ms_encrypt(crypto->cryspr_cb, ctx, &indata, 1, NULL, NULL, NULL))) { 119 | HCRYPT_LOG(LOG_ERR, "%s", "ms_encrypt failed\n"); 120 | return(nbout); 121 | } 122 | } 123 | ctx->pkt_cnt++; 124 | 125 | return(nbout); 126 | } 127 | 128 | int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc, 129 | unsigned char *in_msg, size_t in_len, 130 | void *out_p[], size_t out_len_p[], int maxout) 131 | { 132 | hcrypt_Session *crypto = (hcrypt_Session *)hhc; 133 | hcrypt_Ctx *ctx = crypto->ctx; 134 | int nb, nbout = 0; 135 | 136 | if ((NULL == crypto) 137 | || (NULL == ctx) 138 | || (NULL == out_p) 139 | || (NULL == out_len_p)) { 140 | HCRYPT_LOG(LOG_ERR, "Tx_Process: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx); 141 | return(-1); 142 | } 143 | 144 | /* Manage Key Material (refresh, announce, decommission) */ 145 | hcryptCtx_Tx_ManageKM(crypto); 146 | 147 | ctx = crypto->ctx; 148 | if (NULL == ctx) { 149 | HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n"); 150 | return(-1); 151 | } 152 | ASSERT(ctx->status == HCRYPT_CTX_S_ACTIVE); 153 | 154 | nbout += hcryptCtx_Tx_InjectKM(crypto, out_p, out_len_p, maxout); 155 | 156 | /* Get packet index */ 157 | ctx->msg_info->indexMsg(in_msg, ctx->MSpfx_cache); 158 | 159 | /* Encrypt */ 160 | nb = maxout - nbout; 161 | { 162 | hcrypt_DataDesc indata; 163 | indata.pfx = in_msg; 164 | indata.payload = &in_msg[ctx->msg_info->pfx_len]; 165 | indata.len = in_len - ctx->msg_info->pfx_len; 166 | 167 | if (crypto->cryspr->ms_encrypt(crypto->cryspr_cb, ctx, &indata, 1, &out_p[nbout], &out_len_p[nbout], &nb)) { 168 | HCRYPT_LOG(LOG_ERR, "%s", "ms_encrypt failed\n"); 169 | return(nbout); 170 | } 171 | } 172 | nbout += nb; 173 | ctx->pkt_cnt++; 174 | 175 | return(nbout); 176 | } 177 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /scripts/FindMbedTLS.cmake: -------------------------------------------------------------------------------- 1 | # original file from obs-studio: 2 | # https://github.com/obsproject/obs-studio 3 | # /cmake/Modules/FindMbedTLS.cmake 4 | # 5 | # Once done these will be defined: 6 | # 7 | # LIBMBEDTLS_FOUND 8 | # LIBMBEDTLS_INCLUDE_DIRS 9 | # LIBMBEDTLS_LIBRARIES 10 | # 11 | # For use in OBS: 12 | # 13 | # MBEDTLS_INCLUDE_DIR 14 | 15 | find_package(PkgConfig QUIET) 16 | if (PKG_CONFIG_FOUND) 17 | pkg_check_modules(_MBEDTLS QUIET mbedtls) 18 | endif() 19 | 20 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 21 | set(_lib_suffix 64) 22 | else() 23 | set(_lib_suffix 32) 24 | endif() 25 | 26 | # If we're on MacOS or Linux, please try to statically-link mbedtls. 27 | if(STATIC_MBEDTLS AND (APPLE OR UNIX)) 28 | set(_MBEDTLS_LIBRARIES libmbedtls.a) 29 | set(_MBEDCRYPTO_LIBRARIES libmbedcrypto.a) 30 | set(_MBEDX509_LIBRARIES libmbedx509.a) 31 | endif() 32 | 33 | find_path(MBEDTLS_INCLUDE_DIR 34 | NAMES mbedtls/ssl.h 35 | HINTS 36 | ${MBEDTLS_PREFIX} 37 | PATHS 38 | /usr/include /usr/local/include /opt/local/include /sw/include 39 | PATH_SUFFIXES 40 | include) 41 | 42 | find_library(MBEDTLS_LIB 43 | NAMES ${_MBEDTLS_LIBRARIES} mbedtls libmbedtls 44 | HINTS 45 | ${MBEDTLS_PREFIX} 46 | PATHS 47 | /usr/lib /usr/local/lib /opt/local/lib /sw/lib 48 | PATH_SUFFIXES 49 | lib${_lib_suffix} lib 50 | libs${_lib_suffix} libs 51 | bin${_lib_suffix} bin 52 | ../lib${_lib_suffix} ../lib 53 | ../libs${_lib_suffix} ../libs 54 | ../bin${_lib_suffix} ../bin) 55 | 56 | find_library(MBEDCRYPTO_LIB 57 | NAMES ${_MBEDCRYPTO_LIBRARIES} mbedcrypto libmbedcrypto 58 | HINTS 59 | ${MBEDTLS_PREFIX} 60 | PATHS 61 | /usr/lib /usr/local/lib /opt/local/lib /sw/lib 62 | PATH_SUFFIXES 63 | lib${_lib_suffix} lib 64 | libs${_lib_suffix} libs 65 | bin${_lib_suffix} bin 66 | ../lib${_lib_suffix} ../lib 67 | ../libs${_lib_suffix} ../libs 68 | ../bin${_lib_suffix} ../bin) 69 | 70 | find_library(MBEDX509_LIB 71 | NAMES ${_MBEDX509_LIBRARIES} mbedx509 libmbedx509 72 | HINTS 73 | ${MBEDTLS_PREFIX} 74 | PATHS 75 | /usr/lib /usr/local/lib /opt/local/lib /sw/lib 76 | PATH_SUFFIXES 77 | lib${_lib_suffix} lib 78 | libs${_lib_suffix} libs 79 | bin${_lib_suffix} bin 80 | ../lib${_lib_suffix} ../lib 81 | ../libs${_lib_suffix} ../libs 82 | ../bin${_lib_suffix} ../bin) 83 | 84 | # Sometimes mbedtls is split between three libs, and sometimes it isn't. 85 | # If it isn't, let's check if the symbols we need are all in MBEDTLS_LIB. 86 | if(MBEDTLS_LIB AND NOT MBEDCRYPTO_LIB AND NOT MBEDX509_LIB) 87 | set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIB}) 88 | set(CMAKE_REQUIRED_INCLUDES ${MBEDTLS_INCLUDE_DIR}) 89 | check_symbol_exists(mbedtls_x509_crt_init "mbedtls/x509_crt.h" MBEDTLS_INCLUDES_X509) 90 | check_symbol_exists(mbedtls_sha256_init "mbedtls/sha256.h" MBEDTLS_INCLUDES_CRYPTO) 91 | unset(CMAKE_REQUIRED_INCLUDES) 92 | unset(CMAKE_REQUIRED_LIBRARIES) 93 | endif() 94 | 95 | # If we find all three libraries, then go ahead. 96 | if(MBEDTLS_LIB AND MBEDCRYPTO_LIB AND MBEDX509_LIB) 97 | set(LIBMBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) 98 | set(LIBMBEDTLS_LIBRARIES ${MBEDTLS_LIB} ${MBEDCRYPTO_LIB} ${MBEDX509_LIB}) 99 | set(MBEDTLS_INCLUDE_DIRS ${LIBMBEDTLS_INCLUDE_DIRS}) 100 | set(MBEDTLS_LIBRARIES ${LIBMBEDTLS_LIBRARIES}) 101 | 102 | # Otherwise, if we find MBEDTLS_LIB, and it has both CRYPTO and x509 103 | # within the single lib (i.e. a windows build environment), then also 104 | # feel free to go ahead. 105 | elseif(MBEDTLS_LIB AND MBEDTLS_INCLUDES_CRYPTO AND MBEDTLS_INCLUDES_X509) 106 | set(LIBMBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) 107 | set(LIBMBEDTLS_LIBRARIES ${MBEDTLS_LIB}) 108 | set(MBEDTLS_INCLUDE_DIRS ${LIBMBEDTLS_INCLUDE_DIRS}) 109 | set(MBEDTLS_LIBRARIES ${LIBMBEDTLS_LIBRARIES}) 110 | endif() 111 | 112 | # Now we've accounted for the 3-vs-1 library case: 113 | include(FindPackageHandleStandardArgs) 114 | find_package_handle_standard_args(Libmbedtls DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) 115 | mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) 116 | -------------------------------------------------------------------------------- /scripts/build-windows.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\PowerShell.exe -Command "& '%~dpn0.ps1'" 3 | pause 4 | -------------------------------------------------------------------------------- /scripts/changelog/README.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | Script designed to create changelog out of `.csv` SRT git log. The output `changelog.md` is generated in the root folder. 4 | 5 | In order to generate git log file since the previous release (e.g., v1.4.0), use the following command: 6 | 7 | ``` 8 | git log --pretty=format:"%h|%s|%an|%ae" v1.4.0...HEAD^ > commits.csv 9 | ``` 10 | 11 | ## Requirements 12 | 13 | * python 3.6+ 14 | 15 | To install python libraries use: 16 | ``` 17 | pip install -r requirements.txt 18 | ``` 19 | -------------------------------------------------------------------------------- /scripts/changelog/changelog.py: -------------------------------------------------------------------------------- 1 | import enum 2 | 3 | import click 4 | import numpy as np 5 | import pandas as pd 6 | 7 | 8 | @enum.unique 9 | class Area(enum.Enum): 10 | core = 'core' 11 | tests = 'tests' 12 | build = 'build' 13 | apps = 'apps' 14 | docs = 'docs' 15 | 16 | 17 | def define_area(msg): 18 | areas = [e.value for e in Area] 19 | 20 | for area in areas: 21 | if msg.startswith(f'[{area}] '): 22 | return area 23 | 24 | return np.NaN 25 | 26 | 27 | def delete_prefix(msg): 28 | prefixes = [f'[{e.value}] ' for e in Area] 29 | 30 | for prefix in prefixes: 31 | if msg.startswith(prefix): 32 | return msg[len(prefix):] 33 | 34 | return msg[:] 35 | 36 | 37 | def write_into_changelog(df, f): 38 | f.write('\n') 39 | for _, row in df.iterrows(): 40 | f.write(f"\n{row['commit']} {row['message']}") 41 | f.write('\n') 42 | 43 | 44 | @click.command() 45 | @click.argument( 46 | 'git_log', 47 | type=click.Path(exists=True) 48 | ) 49 | def main(git_log): 50 | """ Script designed to create changelog out of .csv SRT git log """ 51 | 52 | df = pd.read_csv(git_log, sep = '|', names = ['commit', 'message', 'author', 'email']) 53 | df['area'] = df['message'].apply(define_area) 54 | df['message'] = df['message'].apply(delete_prefix) 55 | 56 | core = df[df['area']=='core'] 57 | tests = df[df['area']=='tests'] 58 | build = df[df['area']=='build'] 59 | apps = df[df['area']=='apps'] 60 | docs = df[df['area']=='docs'] 61 | other = df[df['area'].isna()] 62 | 63 | with open('changelog.md', 'w') as f: 64 | f.write('# Release Notes\n') 65 | 66 | f.write('\n## Changelog\n') 67 | f.write('\n
Click to expand/collapse') 68 | f.write('\n

') 69 | f.write('\n') 70 | 71 | if not core.empty: 72 | f.write('\n### Core Functionality') 73 | write_into_changelog(core, f) 74 | 75 | if not tests.empty: 76 | f.write('\n### Unit Tests') 77 | write_into_changelog(tests, f) 78 | 79 | if not build.empty: 80 | f.write('\n### Build Scripts (CMake, etc.)') 81 | write_into_changelog(build, f) 82 | 83 | if not apps.empty: 84 | f.write('\n### Sample Applications') 85 | write_into_changelog(apps, f) 86 | 87 | if not docs.empty: 88 | f.write('\n### Documentation') 89 | write_into_changelog(docs, f) 90 | 91 | if not other.empty: 92 | f.write('\n### Other') 93 | write_into_changelog(other, f) 94 | 95 | f.write('\n

') 96 | f.write('\n
') 97 | 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /scripts/changelog/requirements.txt: -------------------------------------------------------------------------------- 1 | click>=7.1.2 2 | numpy>=1.19.1 3 | pandas>=0.25.3 -------------------------------------------------------------------------------- /scripts/check-deps: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Now Check if Tcl is installed, run it if so. The backslash extends the comment and hides the line below against Tcl interpreter \ 3 | exec tclsh "$0" "$@" || echo "Please install 'tcl' package first - it's required to run any other scripts here." && exit 1 4 | 5 | # 6 | # SRT - Secure, Reliable, Transport 7 | # Copyright (c) 2018 Haivision Systems Inc. 8 | # 9 | # This Source Code Form is subject to the terms of the Mozilla Public 10 | # License, v. 2.0. If a copy of the MPL was not distributed with this 11 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 12 | # 13 | 14 | if { [catch {package require Tcl 8.5}] } { 15 | puts stderr "Tcl version at least 8.5 required, please upgrade" 16 | exit 1 17 | } 18 | 19 | set ok 1 20 | 21 | if { [catch {exec pkg-config --exists openssl}] } { 22 | set ok 0 23 | puts "Openssl: NOT INSTALLED, please install (libssl-dev\[el\], openssl-dev\[el\] etc.)" 24 | } else { 25 | puts "Openssl: found version [exec pkg-config --modversion openssl] -- ok" 26 | } 27 | 28 | 29 | set nothave [catch {set cmake [exec cmake --version]}] 30 | 31 | if { $nothave } { 32 | puts "CMake version >= 2.8 required - please install cmake" 33 | set ok 0 34 | } else { 35 | set cmakel1 [lindex [split $cmake \n] 0] 36 | set cv [lindex $cmakel1 end] 37 | if { [package vcompare $cv 2.8] == -1 } { 38 | puts "CMake version >= 2.8 required - please upgrade cmake" 39 | set ok 0 40 | } else { 41 | puts "Cmake version $cv -- ok." 42 | } 43 | } 44 | 45 | 46 | # May others also apply 47 | 48 | if { $ok } { 49 | puts "All dependencies satisfied, you should be good to go." 50 | exit 0 51 | } 52 | 53 | puts "Please fix the above findings before compiling" 54 | exit 1 55 | 56 | 57 | -------------------------------------------------------------------------------- /scripts/collect-gcov.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | shopt -s globstar 3 | gcov_data_dir="." 4 | for x in ./**/*.o; do 5 | echo "x: $x" 6 | gcov "$gcov_data_dir/$x" 7 | done 8 | -------------------------------------------------------------------------------- /scripts/gather-package.bat: -------------------------------------------------------------------------------- 1 | rem Create empty directories for package bundle 2 | @echo off 3 | 4 | IF "%PLATFORM%"=="x86" ( 5 | SET FOLDER_PLATFORM="32" 6 | ) ELSE IF "%PLATFORM%"=="x64" ( 7 | SET FOLDER_PLATFORM="64" 8 | ) ELSE ( 9 | echo "Platform %PLATFORM% is not supported" 10 | exit 1 11 | ) 12 | 13 | md %APPVEYOR_BUILD_FOLDER%\package 14 | md %APPVEYOR_BUILD_FOLDER%\package\include 15 | md %APPVEYOR_BUILD_FOLDER%\package\include\win 16 | md %APPVEYOR_BUILD_FOLDER%\package\bin 17 | md %APPVEYOR_BUILD_FOLDER%\package\lib 18 | IF "%GATHER_SSL_INTO_PACKAGE%"=="True" ( 19 | md %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM% 20 | ) 21 | 22 | rem Gather SRT includes, binaries and libs 23 | copy %APPVEYOR_BUILD_FOLDER%\version.h %APPVEYOR_BUILD_FOLDER%\package\include\ 24 | copy %APPVEYOR_BUILD_FOLDER%\srtcore\*.h %APPVEYOR_BUILD_FOLDER%\package\include\ 25 | copy %APPVEYOR_BUILD_FOLDER%\haicrypt\*.h %APPVEYOR_BUILD_FOLDER%\package\include\ 26 | copy %APPVEYOR_BUILD_FOLDER%\common\*.h %APPVEYOR_BUILD_FOLDER%\package\include\ 27 | copy %APPVEYOR_BUILD_FOLDER%\common\win\*.h %APPVEYOR_BUILD_FOLDER%\package\include\win\ 28 | copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.exe %APPVEYOR_BUILD_FOLDER%\package\bin\ 29 | copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.dll %APPVEYOR_BUILD_FOLDER%\package\bin\ 30 | copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.lib %APPVEYOR_BUILD_FOLDER%\package\lib\ 31 | copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.pdb %APPVEYOR_BUILD_FOLDER%\package\bin\ 32 | 33 | rem Gather 3rd party openssl elements 34 | IF "%GATHER_SSL_INTO_PACKAGE%"=="True" ( 35 | (robocopy c:\openssl-win%FOLDER_PLATFORM%\ %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM% /s /e /np) ^& IF %ERRORLEVEL% GTR 1 exit %ERRORLEVEL% 36 | ) 37 | exit 0 38 | -------------------------------------------------------------------------------- /scripts/generate-configure-options.tcl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/tclsh 2 | 3 | set cachefile [lindex $argv 0] 4 | 5 | if { $cachefile == "" } { 6 | puts stderr "Usage: [file tail $argv0] " 7 | exit 1 8 | } 9 | 10 | set struct { 11 | name 12 | type 13 | value 14 | description 15 | } 16 | 17 | set fd [open $cachefile r] 18 | 19 | set cached "" 20 | 21 | set dbase "" 22 | 23 | while {[gets $fd line] != -1 } { 24 | set line [string trim $line] 25 | 26 | # Hash comment 27 | if { [string index $line 0] == "#" } { 28 | continue 29 | } 30 | 31 | # empty line 32 | if { $line == "" } { 33 | set cached "" 34 | continue 35 | } 36 | 37 | if { [string range $line 0 1] == "//" } { 38 | set linepart [string range $line 2 end] 39 | # Variable description. Add to cache. 40 | if { $cached != "" && [string index $cached end] != " " && [string index $linepart 0] != " " } { 41 | append cached " " 42 | } 43 | append cached $linepart 44 | } 45 | 46 | # Possibly a variable 47 | if [string is alpha [string index $line 0]] { 48 | # Note: this skips variables starting grom underscore. 49 | 50 | if { [string range $line 0 5] == "CMAKE_" } { 51 | # Skip variables with CMAKE_ prefix, they are internal. 52 | continue 53 | } 54 | 55 | lassign [split $line =] vartype value 56 | lassign [split $vartype :] var type 57 | 58 | # Store the variable now 59 | set storage [list $var $type $value $cached] 60 | set cached "" 61 | lappend dbase $storage 62 | 63 | continue 64 | } 65 | 66 | #puts stderr "Ignored line: $line" 67 | 68 | # Ignored. 69 | } 70 | 71 | # Now look over the stored variables 72 | 73 | set lenlimit 80 74 | 75 | foreach stor $dbase { 76 | 77 | lassign $stor {*}$struct 78 | 79 | if { [string length $description] > $lenlimit } { 80 | set description [string range $description 0 $lenlimit-2]... 81 | } 82 | 83 | if { $type in {STATIC INTERNAL} } { 84 | continue 85 | } 86 | 87 | # Check special case of CXX to turn back to c++. 88 | set pos [string first CXX $name] 89 | if { $pos != -1 } { 90 | # Check around, actually after XX should be no letter. 91 | if { $pos+3 >= [string length $name] || ![string is alpha [string index $name $pos+3]] } { 92 | set name [string replace $name $pos $pos+2 C++] 93 | } 94 | } 95 | 96 | set optname [string tolower [string map {_ -} $name]] 97 | 98 | # Variables of type bool are just empty. 99 | # Variables of other types must have = added. 100 | # Lowercase cmake type will be used here. 101 | set optassign "" 102 | set def "" 103 | if { $type != "BOOL" } { 104 | set optassign "=<[string tolower $type]>" 105 | } else { 106 | # Supply default for boolean option 107 | set def " (default: $value)" 108 | } 109 | 110 | puts " $optname$optassign \"$description$def\"" 111 | } 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /scripts/googletest-download.cmake: -------------------------------------------------------------------------------- 1 | # code copied from https://crascit.com/2015/07/25/cmake-gtest/ 2 | cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) 3 | 4 | project(googletest-download NONE) 5 | 6 | include(ExternalProject) 7 | 8 | ExternalProject_Add( 9 | googletest 10 | SOURCE_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-src" 11 | BINARY_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-build" 12 | GIT_REPOSITORY 13 | https://github.com/google/googletest.git 14 | GIT_TAG release-1.8.1 15 | CONFIGURE_COMMAND "" 16 | BUILD_COMMAND "" 17 | INSTALL_COMMAND "" 18 | TEST_COMMAND "" 19 | ) 20 | -------------------------------------------------------------------------------- /scripts/googletest.cmake: -------------------------------------------------------------------------------- 1 | # the following code to fetch googletest 2 | # is inspired by and adapted after https://crascit.com/2015/07/25/cmake-gtest/ 3 | # download and unpack googletest at configure time 4 | 5 | macro(fetch_googletest _download_module_path _download_root) 6 | set(GOOGLETEST_DOWNLOAD_ROOT ${_download_root}) 7 | configure_file( 8 | ${_download_module_path}/googletest-download.cmake 9 | ${_download_root}/CMakeLists.txt 10 | @ONLY 11 | ) 12 | unset(GOOGLETEST_DOWNLOAD_ROOT) 13 | 14 | execute_process( 15 | COMMAND 16 | "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" . 17 | WORKING_DIRECTORY 18 | ${_download_root} 19 | ) 20 | execute_process( 21 | COMMAND 22 | "${CMAKE_COMMAND}" --build . 23 | WORKING_DIRECTORY 24 | ${_download_root} 25 | ) 26 | 27 | # adds the targers: gtest, gtest_main, gmock, gmock_main 28 | add_subdirectory( 29 | ${_download_root}/googletest-src 30 | ${_download_root}/googletest-build 31 | ) 32 | endmacro() 33 | -------------------------------------------------------------------------------- /scripts/maf.vim: -------------------------------------------------------------------------------- 1 | " 2 | " SRT - Secure, Reliable, Transport 3 | " Copyright (c) 2020 Haivision Systems Inc. 4 | " 5 | " This Source Code Form is subject to the terms of the Mozilla Public 6 | " License, v. 2.0. If a copy of the MPL was not distributed with this 7 | " file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | " 9 | " This file describes MAF ("manifest") file syntax used by 10 | " SRT project. 11 | " 12 | 13 | 14 | if exists("b:current_syntax") 15 | finish 16 | endif 17 | 18 | " conditionals 19 | syn match mafCondition contained " - [!A-Za-z].*"hs=s+2 20 | 21 | " section 22 | syn match mafSection "^[A-Z][0-9A-Za-z_].*$" contains=mafCondition 23 | syn match mafsection "^ .*$" contains=mafCondition 24 | 25 | " comments 26 | syn match mafComment "^\s*\zs#.*$" 27 | syn match mafComment "\s\zs#.*$" 28 | syn match mafComment contained "#.*$" 29 | 30 | 31 | " hilites 32 | 33 | hi def link mafComment Comment 34 | hi def link mafSection Statement 35 | hi def link mafCondition Number 36 | 37 | 38 | let b:current_syntax = "maf" 39 | -------------------------------------------------------------------------------- /scripts/mafread.tcl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/tclsh 2 | 3 | proc is-section line { 4 | return [regexp {^[A-Z ]+$} $line] 5 | } 6 | 7 | # First argument is Manifest file, others are sections. 8 | set sections [lassign $argv maffile] 9 | 10 | if { $sections == "" } { 11 | puts stderr "Usage: [file tail $argv0]
" 12 | exit 1 13 | } 14 | 15 | # NOTE: If the file doesn't exist, simply print nothing. 16 | # If there's no manifest file under this name, it means that 17 | # there are no files that satisfy given manifest and section. 18 | if { [catch {set fd [open $maffile r]}] } { 19 | exit 20 | } 21 | 22 | set extracted "" 23 | set insection 0 24 | 25 | while { [gets $fd line] >= 0 } { 26 | set oline [string trim $line] 27 | if { $oline == "" } { 28 | continue 29 | } 30 | 31 | if { [string index $oline 0] == "#" } { 32 | continue 33 | } 34 | 35 | if { !$insection } { 36 | # An opportunity to see if this is a section name 37 | if { ![is-section $line] } { 38 | continue 39 | } 40 | 41 | # If it is, then check if this is OUR section 42 | if { $oline in $sections } { 43 | set insection 1 44 | continue 45 | } 46 | } else { 47 | # We are inside the interesting section, so collect filenames 48 | # Check if this is a next section name - if it is, stop reading. 49 | if { [is-section $line] } { 50 | continue 51 | } 52 | 53 | # Otherwise read the current filename 54 | lappend extracted $oline 55 | } 56 | } 57 | 58 | puts $extracted 59 | -------------------------------------------------------------------------------- /scripts/set-version-metadata.ps1: -------------------------------------------------------------------------------- 1 | # Script for reading generated version values and updating metadata properties 2 | 3 | #read major / minor version values from version.h (generated by cmake via version.h.in) 4 | $majorVer=99 5 | $minorVer=99 6 | $patchVer=0 7 | $buildNum=0 8 | 9 | #define regular expressions to be used when checking for #define statements 10 | $versionSniffingRegex = "(\s*#define\s+(\S+)\s+)(\d+)" 11 | 12 | #read generated file, load values from this with regular expression 13 | Get-Content ".\version.h" | Where-Object { $_ -match $versionSniffingRegex } | ForEach-Object { 14 | switch ($Matches[2]) 15 | { 16 | "SRT_VERSION_MAJOR" { $majorVer = $Matches[3] } 17 | "SRT_VERSION_MINOR" { $minorVer = $Matches[3] } 18 | "SRT_VERSION_PATCH" { $patchVer = $Matches[3] } 19 | "SRT_VERSION_BUILD" { $buildNum = $Matches[3] } 20 | } 21 | } 22 | 23 | $FileDescriptionBranchCommitValue = "SRT Local Build" 24 | 25 | if($Env:APPVEYOR){ 26 | #make AppVeyor update with this new version number 27 | Update-AppveyorBuild -Version "$majorVer.$minorVer.$patchVer.$buildNum" 28 | $FileDescriptionBranchCommitValue = "$Env:APPVEYOR_REPO_NAME - $($Env:APPVEYOR_REPO_BRANCH) ($($Env:APPVEYOR_REPO_COMMIT.substring(0,8)))" 29 | } 30 | 31 | #find C++ resource files and update file description with branch / commit details 32 | $FileDescriptionStringRegex = '(\bVALUE\s+\"FileDescription\"\s*\,\s*\")([^\"]*\\\")*[^\"]*(\")' 33 | 34 | Get-ChildItem -Path "../srtcore/srt_shared.rc" | ForEach-Object { 35 | $fileName = $_ 36 | Write-Output "Processing metadata changes for file: $fileName" 37 | 38 | $FileLines = Get-Content -path $fileName 39 | 40 | for($i=0;$i -lt $FileLines.Count;$i++) 41 | { 42 | $FileLines[$i] = $FileLines[$i] -Replace $FileDescriptionStringRegex, "`${1}$FileDescriptionBranchCommitValue`${3}" 43 | } 44 | 45 | [System.IO.File]::WriteAllLines($fileName.FullName, $FileLines) 46 | } 47 | 48 | -------------------------------------------------------------------------------- /scripts/srt-ffplay: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # SRT - Secure, Reliable, Transport 5 | # Copyright (c) 2018 Haivision Systems Inc. 6 | # 7 | # This Source Code Form is subject to the terms of the Mozilla Public 8 | # License, v. 2.0. If a copy of the MPL was not distributed with this 9 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 | # 11 | 12 | FFPLAY=`type -p ffplay || echo none` 13 | if [[ $FFPLAY == "none" ]]; then 14 | echo >&2 "ERROR: ffplay not available to call. Please install ffplay first." 15 | exit 1 16 | fi 17 | 18 | DIRNAME=`dirname $0` 19 | if [[ ! -x $DIRNAME/srt-live-transmit ]]; then 20 | echo >&2 "ERROR: you need 'srt-live-transmit' tool from SRT package in the same directory as this script." 21 | exit 1 22 | fi 23 | 24 | SRCLOC=$1 25 | if [[ -z $SRCLOC ]]; then 26 | echo >&2 "Usage: `basename $0` " 27 | exit 1 28 | fi 29 | 30 | $DIRNAME/srt-live-transmit "$1" file://con/ | ffplay - 31 | 32 | -------------------------------------------------------------------------------- /scripts/srt.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@INSTALLDIR@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ 4 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 5 | 6 | Name: srt 7 | Description: SRT library set 8 | Version: @SRT_VERSION@ 9 | Libs: -L${libdir} -l@TARGET_srt@ @IFNEEDED_LINK_HAICRYPT@ @IFNEEDED_SRTBASE@ @IFNEEDED_SRT_LDFLAGS@ 10 | Libs.private: @SRT_LIBS_PRIVATE@ 11 | Cflags: -I${includedir} -I${includedir}/srt 12 | Requires.private: @SSL_REQUIRED_MODULES@ 13 | -------------------------------------------------------------------------------- /scripts/tcp-echo-client.tcl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/tclsh 2 | 3 | set read_running 0 4 | set write_running 0 5 | set read_eof 0 6 | set theend 0 7 | 8 | set nread 0 9 | set nwritten 0 10 | 11 | proc ReadBack {fd} { 12 | 13 | if { !$::write_running } { 14 | puts stderr "ERROR: connection closed unexpectedly!" 15 | set ::theend 1 16 | return 17 | } 18 | 19 | set r [read $fd 4096] 20 | if {$r == ""} { 21 | 22 | if {[eof $fd]} { 23 | puts stderr "EOF on socket" 24 | set ::read_running 0 25 | return 26 | } 27 | 28 | # --- puts stderr "SPURIOUS, not reading" 29 | return 30 | } 31 | 32 | # --- puts stderr "REPRINTING [string bytelength $r] bytes" 33 | puts -nonewline stdout $r 34 | incr ::nwritten [string bytelength $r] 35 | # --- puts stderr "DONE" 36 | 37 | set remain [expr {$::nread - $::nwritten}] 38 | if { $::read_eof } { 39 | puts stderr "Finishing... read=$::nread written=$::nwritten diff=[expr {$::nwritten - $::nread}] - [expr {100.0*$remain/$::nread}]%" 40 | } 41 | 42 | # Nothing more to read 43 | if {$remain == 0} { 44 | puts stderr "NOTHING MORE TO BE WRITTEN - exiting" 45 | set ::theend 1 46 | return 47 | } 48 | 49 | after idle "ReadBack $fd" 50 | } 51 | 52 | proc SendToSocket {fd} { 53 | global theend 54 | 55 | if { !$::write_running } { 56 | # --- puts stderr "SERVER DOWN, not reading" 57 | fileevent stdin readable {} 58 | return 59 | } 60 | 61 | if { $::read_eof } { 62 | # Don't read, already EOF. 63 | 64 | } 65 | # --- puts stderr "READING cin" 66 | set r [read stdin 4096] 67 | if {$r == ""} { 68 | if {[eof stdin]} { 69 | if {!$::read_eof} { 70 | puts stderr "EOF, setting server off" 71 | set ::read_eof 1 72 | } 73 | # Just enough when the next SendToSocket will 74 | # not be scheduled. 75 | return 76 | } 77 | # --- puts stderr "SPURIOUS, not reading" 78 | return 79 | } 80 | 81 | # --- puts stderr "SENDING [string bytelength $r] bytes" 82 | # Set blocking for a short moment of sending 83 | # in order to prevent losing data that must wait 84 | fconfigure $fd -blocking yes 85 | puts -nonewline $fd $r 86 | incr ::nread [string bytelength $r] 87 | fconfigure $fd -blocking no 88 | 89 | # --- if {[fblocked stdin]} { 90 | # --- # Nothing more to read 91 | # --- return 92 | # --- } 93 | after idle "SendToSocket $fd" 94 | } 95 | 96 | set fd [socket {*}$argv] 97 | fconfigure $fd -encoding binary -translation binary -blocking no -buffering none 98 | fileevent $fd readable "ReadBack $fd" 99 | 100 | fconfigure stdin -encoding binary -translation binary -blocking no 101 | fconfigure stdout -encoding binary -translation binary 102 | fileevent stdin readable "SendToSocket $fd" 103 | 104 | # --- puts stderr "READY, sending" 105 | set read_running 1 106 | set write_running 1 107 | 108 | vwait theend 109 | 110 | close $fd 111 | -------------------------------------------------------------------------------- /scripts/tcp-echo-server.tcl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/tclsh 2 | 3 | proc SpawnEchoServer {fd host port} { 4 | fconfigure $fd -encoding binary -translation binary -blocking no -buffering none 5 | fileevent $fd readable "EchoBack $fd" 6 | # --- puts stderr "Connected: [fconfigure $fd -peername]" 7 | } 8 | 9 | proc EchoBack {fd} { 10 | 11 | # --- puts stderr "READ-READY" 12 | 13 | while 1 { 14 | 15 | # --- puts stderr "READING 4096" 16 | set r [read $fd 4096] 17 | if {$r == ""} { 18 | if {[eof $fd]} { 19 | # --- puts stderr "EOF. Closing" 20 | close $fd 21 | return 22 | } 23 | 24 | # --- puts stderr "SPURIOUS, giving up read" 25 | return 26 | } 27 | 28 | # Set blocking for a short moment of sending 29 | # in order to prevent losing data that must wait 30 | 31 | # --- puts stderr "SENDING [string bytelength $r] bytes" 32 | fconfigure $fd -blocking yes 33 | puts -nonewline $fd $r 34 | fconfigure $fd -blocking no 35 | 36 | if {[fblocked $fd]} { 37 | # --- puts stderr "NO MORE DATA" 38 | # Nothing more to read 39 | return 40 | } 41 | 42 | # --- puts stderr "AGAIN" 43 | 44 | } 45 | 46 | } 47 | 48 | socket -server SpawnEchoServer $argv 49 | puts stderr "SERVER READY" 50 | 51 | vwait tk 52 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | # must be unique in a given SonarQube instance 2 | sonar.projectKey=srt 3 | sonar.organization=haivision 4 | 5 | # --- optional properties --- 6 | 7 | # This is the name and version displayed in the SonarCloud UI. 8 | #sonar.projectName=srt 9 | #sonar.projectVersion=1.0 10 | 11 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. 12 | #sonar.sources=. 13 | 14 | # Encoding of the source code. Default is default system encoding 15 | #sonar.sourceEncoding=UTF-8 16 | 17 | # ===================================================== 18 | # Meta-data for the project 19 | # ===================================================== 20 | 21 | sonar.links.homepage=https://github.com/Haivision/srt 22 | sonar.links.ci=https://travis-ci.org/Haivision/srt 23 | sonar.links.scm=https://github.com/Haivision/srt 24 | sonar.links.issue=https://github.com/Haivision/srt/issues 25 | 26 | 27 | # ===================================================== 28 | # Properties that will be shared amongst all modules 29 | # ===================================================== 30 | 31 | # SQ standard properties 32 | sonar.sources=. 33 | 34 | # Properties specific to the C/C++ analyzer: 35 | sonar.cfamily.build-wrapper-output=bw-output 36 | sonar.cfamily.gcov.reportsPath=. 37 | -------------------------------------------------------------------------------- /srt-ffplay: -------------------------------------------------------------------------------- 1 | scripts/srt-ffplay -------------------------------------------------------------------------------- /srtcore/README.md: -------------------------------------------------------------------------------- 1 | SRT Core 2 | ======== 3 | 4 | These files are contents of the SRT library. Beside files that are used exclusively 5 | and internally by the library, this directory also contains: 6 | 7 | - common files: usually header files, which can be used also by other projects, 8 | even if they don't link against SRT 9 | 10 | - public and protected header files - header files for the library, which will 11 | be picked up from here 12 | 13 | Which header files are public, protected and private, it's defined in the manifest 14 | file together with all source files that the SRT library comprises of: `filelist.maf`. 15 | 16 | 17 | Common files 18 | ============ 19 | 20 | This directory holds the files that may be used separately by both SRT library 21 | itself and the internal applications. 22 | 23 | Source files are added to SRT library, so apps don't have to use them. However 24 | these source files might be used by some internal applications that do not 25 | link against SRT library. 26 | 27 | Header files contained here might be required by internal applications no 28 | matter if they link against SRT or not. They are here because simultaneously 29 | they are used also by the SRT library. 30 | 31 | 32 | Utilities 33 | ========= 34 | 35 | 1. threadname.h 36 | 37 | This is a utility that is useful for debugging and it allows a thread to be given 38 | a name. This name is used in the logging messages, as well as you can see it also 39 | inside the debugger. 40 | 41 | This is currently supported only on Linux; some more portable and more reliable 42 | way is needed. 43 | 44 | 2. utilities.h 45 | 46 | A set of various reusable components, all defined as C++ classes or C++ inline 47 | functions. 48 | 49 | 3. `netinet_any.h` 50 | 51 | This defines a `sockaddr_any` type, which simplifies dealing with the BSD socket API 52 | using `sockaddr`, `sockaddr_in` and `sockaddr_in6` structures. 53 | 54 | 55 | Compat and portability 56 | ====================== 57 | 58 | 1. `srt_compat.h` 59 | 60 | This part contains some portability problem resolutions, including: 61 | - `strerror` in a version that is both portable and thread safe 62 | - `localtime` in a version that is both portable and thread safe 63 | 64 | 2. win directory 65 | 66 | This contains various header files that are used on Windows platform only. 67 | They provide various facilities available OOTB on POSIX systems. 68 | 69 | 3. `platform_sys.h` 70 | 71 | This is a file that is responsible to include whatever system include 72 | files must be included for whatever system API must be provided for 73 | the needs of SRT library. This is a part of public headers. 74 | 75 | 76 | -------------------------------------------------------------------------------- /srtcore/access_control.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2020 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | *****************************************************************************/ 15 | 16 | #ifndef INC_F_ACCESS_CONTROL_H 17 | #define INC_F_ACCESS_CONTROL_H 18 | 19 | // A list of rejection codes that are SRT specific. 20 | 21 | #define SRT_REJX_FALLBACK 1000 // A code used in case when the application wants to report some problem, but can't precisely specify it. 22 | #define SRT_REJX_KEY_NOTSUP 1001 // The key used in the StreamID keyed string is not supported by the service. 23 | #define SRT_REJX_FILEPATH 1002 // The resource type designates a file and the path is either wrong syntax or not found 24 | #define SRT_REJX_HOSTNOTFOUND 1003 // The `h` host specification was not recognized by the service 25 | 26 | // The list of http codes adopted for SRT. 27 | // An example C++ header for HTTP codes can be found at: 28 | // https://github.com/j-ulrich/http-status-codes-cpp 29 | 30 | // Some of the unused code can be revived in the future, if there 31 | // happens to be a good reason for it. 32 | 33 | #define SRT_REJX_BAD_REQUEST 1400 // General syntax error in the SocketID specification (also a fallback code for undefined cases) 34 | #define SRT_REJX_UNAUTHORIZED 1401 // Authentication failed, provided that the user was correctly identified and access to the required resource would be granted 35 | #define SRT_REJX_OVERLOAD 1402 // The server is too heavily loaded, or you have exceeded credits for accessing the service and the resource. 36 | #define SRT_REJX_FORBIDDEN 1403 // Access denied to the resource by any kind of reason. 37 | #define SRT_REJX_NOTFOUND 1404 // Resource not found at this time. 38 | #define SRT_REJX_BAD_MODE 1405 // The mode specified in `m` key in StreamID is not supported for this request. 39 | #define SRT_REJX_UNACCEPTABLE 1406 // The requested parameters specified in SocketID cannot be satisfied for the requested resource. Also when m=publish and the data format is not acceptable. 40 | // CODE NOT IN USE 407: unused: proxy functionality not predicted 41 | // CODE NOT IN USE 408: unused: no timeout predicted for listener callback 42 | #define SRT_REJX_CONFLICT 1409 // The resource being accessed is already locked for modification. This is in case of m=publish and the specified resource is currently read-only. 43 | // CODE NOT IN USE 410: unused: treated as a specific case of 404 44 | // CODE NOT IN USE 411: unused: no reason to include lenght in the protocol 45 | // CODE NOT IN USE 412: unused: preconditions not predicted in AC 46 | // CODE NOT IN USE 413: unused: AC size is already defined as 512 47 | // CODE NOT IN USE 414: unused: AC size is already defined as 512 48 | #define SRT_REJX_NOTSUP_MEDIA 1415 // The media type is not supported by the application. This is the `t` key that specifies the media type as stream, file and auth, possibly extended by the application. 49 | // CODE NOT IN USE 416: unused: no detailed specification defined 50 | // CODE NOT IN USE 417: unused: expectations not supported 51 | // CODE NOT IN USE 418: unused: sharks do not drink tea 52 | // CODE NOT IN USE 419: not defined in HTTP 53 | // CODE NOT IN USE 420: not defined in HTTP 54 | // CODE NOT IN USE 421: unused: misdirection not supported 55 | // CODE NOT IN USE 422: unused: aligned to general 400 56 | #define SRT_REJX_LOCKED 1423 // The resource being accessed is locked for any access. 57 | #define SRT_REJX_FAILED_DEPEND 1424 // The request failed because it specified a dependent session ID that has been disconnected. 58 | // CODE NOT IN USE 425: unused: replaying not supported 59 | // CODE NOT IN USE 426: unused: tempting, but it requires resend in connected 60 | // CODE NOT IN USE 427: not defined in HTTP 61 | // CODE NOT IN USE 428: unused: renders to 409 62 | // CODE NOT IN USE 429: unused: renders to 402 63 | // CODE NOT IN USE 451: unused: renders to 403 64 | #define SRT_REJX_ISE 1500 // Unexpected internal server error 65 | #define SRT_REJX_UNIMPLEMENTED 1501 // The request was recognized, but the current version doesn't support it. 66 | #define SRT_REJX_GW 1502 // The server acts as a gateway and the target endpoint rejected the connection. 67 | #define SRT_REJX_DOWN 1503 // The service has been temporarily taken over by a stub reporting this error. The real service can be down for maintenance or crashed. 68 | // CODE NOT IN USE 504: unused: timeout not supported 69 | #define SRT_REJX_VERSION 1505 // SRT version not supported. This might be either unsupported backward compatibility, or an upper value of a version. 70 | // CODE NOT IN USE 506: unused: negotiation and references not supported 71 | #define SRT_REJX_NOROOM 1507 // The data stream cannot be archived due to lacking storage space. This is in case when the request type was to send a file or the live stream to be archived. 72 | // CODE NOT IN USE 508: unused: no redirection supported 73 | // CODE NOT IN USE 509: not defined in HTTP 74 | // CODE NOT IN USE 510: unused: extensions not supported 75 | // CODE NOT IN USE 511: unused: intercepting proxies not supported 76 | 77 | 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /srtcore/cache.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 05/05/2009 39 | *****************************************************************************/ 40 | 41 | 42 | #include "platform_sys.h" 43 | 44 | #include 45 | #include "cache.h" 46 | #include "core.h" 47 | 48 | using namespace std; 49 | 50 | CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj) 51 | { 52 | std::copy(obj.m_piIP, obj.m_piIP + 4, m_piIP); 53 | m_iIPversion = obj.m_iIPversion; 54 | m_ullTimeStamp = obj.m_ullTimeStamp; 55 | m_iRTT = obj.m_iRTT; 56 | m_iBandwidth = obj.m_iBandwidth; 57 | m_iLossRate = obj.m_iLossRate; 58 | m_iReorderDistance = obj.m_iReorderDistance; 59 | m_dInterval = obj.m_dInterval; 60 | m_dCWnd = obj.m_dCWnd; 61 | 62 | return *this; 63 | } 64 | 65 | bool CInfoBlock::operator==(const CInfoBlock& obj) 66 | { 67 | if (m_iIPversion != obj.m_iIPversion) 68 | return false; 69 | 70 | else if (m_iIPversion == AF_INET) 71 | return (m_piIP[0] == obj.m_piIP[0]); 72 | 73 | for (int i = 0; i < 4; ++ i) 74 | { 75 | if (m_piIP[i] != obj.m_piIP[i]) 76 | return false; 77 | } 78 | 79 | return true; 80 | } 81 | 82 | CInfoBlock* CInfoBlock::clone() 83 | { 84 | CInfoBlock* obj = new CInfoBlock; 85 | 86 | std::copy(m_piIP, m_piIP + 4, obj->m_piIP); 87 | obj->m_iIPversion = m_iIPversion; 88 | obj->m_ullTimeStamp = m_ullTimeStamp; 89 | obj->m_iRTT = m_iRTT; 90 | obj->m_iBandwidth = m_iBandwidth; 91 | obj->m_iLossRate = m_iLossRate; 92 | obj->m_iReorderDistance = m_iReorderDistance; 93 | obj->m_dInterval = m_dInterval; 94 | obj->m_dCWnd = m_dCWnd; 95 | 96 | return obj; 97 | } 98 | 99 | int CInfoBlock::getKey() 100 | { 101 | if (m_iIPversion == AF_INET) 102 | return m_piIP[0]; 103 | 104 | return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3]; 105 | } 106 | 107 | void CInfoBlock::convert(const sockaddr_any& addr, uint32_t aw_ip[4]) 108 | { 109 | if (addr.family() == AF_INET) 110 | { 111 | aw_ip[0] = addr.sin.sin_addr.s_addr; 112 | aw_ip[1] = aw_ip[2] = aw_ip[3] = 0; 113 | } 114 | else 115 | { 116 | memcpy((aw_ip), addr.sin6.sin6_addr.s6_addr, sizeof addr.sin6.sin6_addr.s6_addr); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /srtcore/filelist.maf: -------------------------------------------------------------------------------- 1 | 2 | 3 | SOURCES 4 | api.cpp 5 | buffer.cpp 6 | cache.cpp 7 | channel.cpp 8 | common.cpp 9 | core.cpp 10 | crypto.cpp 11 | epoll.cpp 12 | fec.cpp 13 | handshake.cpp 14 | list.cpp 15 | logger_default.cpp 16 | logger_defs.cpp 17 | md5.cpp 18 | packet.cpp 19 | packetfilter.cpp 20 | queue.cpp 21 | congctl.cpp 22 | srt_c_api.cpp 23 | window.cpp 24 | srt_compat.c 25 | sync.cpp 26 | 27 | SOURCES - ENABLE_EXPERIMENTAL_BONDING 28 | group.cpp 29 | 30 | SOURCES - !ENABLE_STDCXX_SYNC 31 | sync_posix.cpp 32 | 33 | SOURCES - ENABLE_STDCXX_SYNC 34 | sync_cxx11.cpp 35 | 36 | SOURCES - EXTRA_WIN32_SHARED 37 | srt_shared.rc 38 | 39 | PUBLIC HEADERS 40 | srt.h 41 | logging_api.h 42 | access_control.h 43 | 44 | PROTECTED HEADERS 45 | platform_sys.h 46 | udt.h 47 | 48 | PRIVATE HEADERS 49 | api.h 50 | buffer.h 51 | cache.h 52 | channel.h 53 | common.h 54 | core.h 55 | crypto.h 56 | epoll.h 57 | handshake.h 58 | list.h 59 | logging.h 60 | md5.h 61 | netinet_any.h 62 | packet.h 63 | sync.h 64 | queue.h 65 | congctl.h 66 | srt_compat.h 67 | threadname.h 68 | utilities.h 69 | window.h 70 | 71 | PRIVATE HEADERS - ENABLE_EXPERIMENTAL_BONDING 72 | group.h 73 | -------------------------------------------------------------------------------- /srtcore/logger_default.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WARNING: Generated from ../scripts/generate-logging-defs.tcl 3 | 4 | DO NOT MODIFY. 5 | 6 | Copyright applies as per the generator script. 7 | */ 8 | 9 | 10 | #include "srt.h" 11 | #include "logging.h" 12 | #include "logger_defs.h" 13 | 14 | namespace srt_logging 15 | { 16 | AllFaOn::AllFaOn() 17 | { 18 | allfa.set(SRT_LOGFA_GENERAL, true); 19 | allfa.set(SRT_LOGFA_SOCKMGMT, true); 20 | allfa.set(SRT_LOGFA_CONN, true); 21 | allfa.set(SRT_LOGFA_XTIMER, true); 22 | allfa.set(SRT_LOGFA_TSBPD, true); 23 | allfa.set(SRT_LOGFA_RSRC, true); 24 | 25 | allfa.set(SRT_LOGFA_CONGEST, true); 26 | allfa.set(SRT_LOGFA_PFILTER, true); 27 | 28 | allfa.set(SRT_LOGFA_API_CTRL, true); 29 | 30 | allfa.set(SRT_LOGFA_QUE_CTRL, true); 31 | 32 | allfa.set(SRT_LOGFA_EPOLL_UPD, true); 33 | 34 | allfa.set(SRT_LOGFA_API_RECV, true); 35 | allfa.set(SRT_LOGFA_BUF_RECV, true); 36 | allfa.set(SRT_LOGFA_QUE_RECV, true); 37 | allfa.set(SRT_LOGFA_CHN_RECV, true); 38 | allfa.set(SRT_LOGFA_GRP_RECV, true); 39 | 40 | allfa.set(SRT_LOGFA_API_SEND, true); 41 | allfa.set(SRT_LOGFA_BUF_SEND, true); 42 | allfa.set(SRT_LOGFA_QUE_SEND, true); 43 | allfa.set(SRT_LOGFA_CHN_SEND, true); 44 | allfa.set(SRT_LOGFA_GRP_SEND, true); 45 | 46 | allfa.set(SRT_LOGFA_INTERNAL, true); 47 | 48 | allfa.set(SRT_LOGFA_QUE_MGMT, true); 49 | allfa.set(SRT_LOGFA_CHN_MGMT, true); 50 | allfa.set(SRT_LOGFA_GRP_MGMT, true); 51 | allfa.set(SRT_LOGFA_EPOLL_API, true); 52 | } 53 | } // namespace srt_logging 54 | -------------------------------------------------------------------------------- /srtcore/logger_defs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WARNING: Generated from ../scripts/generate-logging-defs.tcl 3 | 4 | DO NOT MODIFY. 5 | 6 | Copyright applies as per the generator script. 7 | */ 8 | 9 | 10 | #include "srt.h" 11 | #include "logging.h" 12 | #include "logger_defs.h" 13 | 14 | namespace srt_logging { AllFaOn logger_fa_all; } 15 | // We need it outside the namespace to preserve the global name. 16 | // It's a part of "hidden API" (used by applications) 17 | SRT_API srt_logging::LogConfig srt_logger_config(srt_logging::logger_fa_all.allfa); 18 | 19 | namespace srt_logging 20 | { 21 | Logger gglog(SRT_LOGFA_GENERAL, srt_logger_config, "SRT.gg"); 22 | Logger smlog(SRT_LOGFA_SOCKMGMT, srt_logger_config, "SRT.sm"); 23 | Logger cnlog(SRT_LOGFA_CONN, srt_logger_config, "SRT.cn"); 24 | Logger xtlog(SRT_LOGFA_XTIMER, srt_logger_config, "SRT.xt"); 25 | Logger tslog(SRT_LOGFA_TSBPD, srt_logger_config, "SRT.ts"); 26 | Logger rslog(SRT_LOGFA_RSRC, srt_logger_config, "SRT.rs"); 27 | 28 | Logger cclog(SRT_LOGFA_CONGEST, srt_logger_config, "SRT.cc"); 29 | Logger pflog(SRT_LOGFA_PFILTER, srt_logger_config, "SRT.pf"); 30 | 31 | Logger aclog(SRT_LOGFA_API_CTRL, srt_logger_config, "SRT.ac"); 32 | 33 | Logger qclog(SRT_LOGFA_QUE_CTRL, srt_logger_config, "SRT.qc"); 34 | 35 | Logger eilog(SRT_LOGFA_EPOLL_UPD, srt_logger_config, "SRT.ei"); 36 | 37 | Logger arlog(SRT_LOGFA_API_RECV, srt_logger_config, "SRT.ar"); 38 | Logger brlog(SRT_LOGFA_BUF_RECV, srt_logger_config, "SRT.br"); 39 | Logger qrlog(SRT_LOGFA_QUE_RECV, srt_logger_config, "SRT.qr"); 40 | Logger krlog(SRT_LOGFA_CHN_RECV, srt_logger_config, "SRT.kr"); 41 | Logger grlog(SRT_LOGFA_GRP_RECV, srt_logger_config, "SRT.gr"); 42 | 43 | Logger aslog(SRT_LOGFA_API_SEND, srt_logger_config, "SRT.as"); 44 | Logger bslog(SRT_LOGFA_BUF_SEND, srt_logger_config, "SRT.bs"); 45 | Logger qslog(SRT_LOGFA_QUE_SEND, srt_logger_config, "SRT.qs"); 46 | Logger kslog(SRT_LOGFA_CHN_SEND, srt_logger_config, "SRT.ks"); 47 | Logger gslog(SRT_LOGFA_GRP_SEND, srt_logger_config, "SRT.gs"); 48 | 49 | Logger inlog(SRT_LOGFA_INTERNAL, srt_logger_config, "SRT.in"); 50 | 51 | Logger qmlog(SRT_LOGFA_QUE_MGMT, srt_logger_config, "SRT.qm"); 52 | Logger kmlog(SRT_LOGFA_CHN_MGMT, srt_logger_config, "SRT.km"); 53 | Logger gmlog(SRT_LOGFA_GRP_MGMT, srt_logger_config, "SRT.gm"); 54 | Logger ealog(SRT_LOGFA_EPOLL_API, srt_logger_config, "SRT.ea"); 55 | } // namespace srt_logging 56 | -------------------------------------------------------------------------------- /srtcore/logger_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | WARNING: Generated from ../scripts/generate-logging-defs.tcl 3 | 4 | DO NOT MODIFY. 5 | 6 | Copyright applies as per the generator script. 7 | */ 8 | 9 | 10 | #ifndef INC_SRT_LOGGER_DEFS_H 11 | #define INC_SRT_LOGGER_DEFS_H 12 | 13 | #include "srt.h" 14 | #include "logging.h" 15 | 16 | namespace srt_logging 17 | { 18 | struct AllFaOn 19 | { 20 | LogConfig::fa_bitset_t allfa; 21 | AllFaOn(); 22 | }; 23 | 24 | extern Logger gglog; 25 | extern Logger smlog; 26 | extern Logger cnlog; 27 | extern Logger xtlog; 28 | extern Logger tslog; 29 | extern Logger rslog; 30 | 31 | extern Logger cclog; 32 | extern Logger pflog; 33 | 34 | extern Logger aclog; 35 | 36 | extern Logger qclog; 37 | 38 | extern Logger eilog; 39 | 40 | extern Logger arlog; 41 | extern Logger brlog; 42 | extern Logger qrlog; 43 | extern Logger krlog; 44 | extern Logger grlog; 45 | 46 | extern Logger aslog; 47 | extern Logger bslog; 48 | extern Logger qslog; 49 | extern Logger kslog; 50 | extern Logger gslog; 51 | 52 | extern Logger inlog; 53 | 54 | extern Logger qmlog; 55 | extern Logger kmlog; 56 | extern Logger gmlog; 57 | extern Logger ealog; 58 | 59 | } // namespace srt_logging 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /srtcore/logging_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | *****************************************************************************/ 15 | 16 | #ifndef INC_SRT_LOGGING_API_H 17 | #define INC_SRT_LOGGING_API_H 18 | 19 | // These are required for access functions: 20 | // - adding FA (requires set) 21 | // - setting a log stream (requires iostream) 22 | #ifdef __cplusplus 23 | #include 24 | #include 25 | #endif 26 | 27 | #ifdef _WIN32 28 | #include "win/syslog_defs.h" 29 | #else 30 | #include 31 | #endif 32 | 33 | // Syslog is included so that it provides log level names. 34 | // Haivision log standard requires the same names plus extra one: 35 | #ifndef LOG_DEBUG_TRACE 36 | #define LOG_DEBUG_TRACE 8 37 | #endif 38 | // It's unused anyway, just for the record. 39 | #define SRT_LOG_LEVEL_MIN LOG_CRIT 40 | #define SRT_LOG_LEVEL_MAX LOG_DEBUG 41 | 42 | // Flags 43 | #define SRT_LOGF_DISABLE_TIME 1 44 | #define SRT_LOGF_DISABLE_THREADNAME 2 45 | #define SRT_LOGF_DISABLE_SEVERITY 4 46 | #define SRT_LOGF_DISABLE_EOL 8 47 | 48 | // Handler type. 49 | typedef void SRT_LOG_HANDLER_FN(void* opaque, int level, const char* file, int line, const char* area, const char* message); 50 | 51 | #ifdef __cplusplus 52 | namespace srt_logging 53 | { 54 | 55 | 56 | struct LogFA 57 | { 58 | private: 59 | int value; 60 | public: 61 | operator int() const { return value; } 62 | 63 | LogFA(int v): value(v) 64 | { 65 | // Generally this was what it has to be used for. 66 | // Unfortunately it couldn't be agreed with the 67 | //logging_fa_all.insert(v); 68 | } 69 | }; 70 | 71 | const LogFA LOGFA_GENERAL = 0; 72 | 73 | 74 | 75 | namespace LogLevel 76 | { 77 | // There are 3 general levels: 78 | 79 | // A. fatal - this means the application WILL crash. 80 | // B. unexpected: 81 | // - error: this was unexpected for the library 82 | // - warning: this was expected by the library, but may be harmful for the application 83 | // C. expected: 84 | // - note: a significant, but rarely occurring event 85 | // - debug: may occur even very often and enabling it can harm performance 86 | 87 | enum type 88 | { 89 | fatal = LOG_CRIT, 90 | // Fatal vs. Error: with Error, you can still continue. 91 | error = LOG_ERR, 92 | // Error vs. Warning: Warning isn't considered a problem for the library. 93 | warning = LOG_WARNING, 94 | // Warning vs. Note: Note means something unusual, but completely correct behavior. 95 | note = LOG_NOTICE, 96 | // Note vs. Debug: Debug may occur even multiple times in a millisecond. 97 | // (Well, worth noting that Error and Warning potentially also can). 98 | debug = LOG_DEBUG 99 | }; 100 | } 101 | 102 | class Logger; 103 | 104 | } 105 | #endif 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /srtcore/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.2 2007/12/24 05:58:37 lilyco Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /srtcore/packetfilter_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2019 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #ifndef INC_SRT_PACKETFILTER_API_H 12 | #define INC_SRT_PACKETFILTER_API_H 13 | 14 | #include "platform_sys.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | class CPacket; 23 | 24 | enum SrtPktHeaderFields 25 | { 26 | SRT_PH_SEQNO = 0, //< sequence number 27 | SRT_PH_MSGNO = 1, //< message number 28 | SRT_PH_TIMESTAMP = 2, //< time stamp 29 | SRT_PH_ID = 3, //< socket ID 30 | 31 | // Must be the last value - this is size of all, not a field id 32 | SRT_PH_E_SIZE 33 | }; 34 | 35 | 36 | enum SRT_ARQLevel 37 | { 38 | SRT_ARQ_NEVER, //< Never send LOSSREPORT 39 | SRT_ARQ_ONREQ, //< Only record the loss, but report only those that are returned in receive() 40 | SRT_ARQ_ALWAYS, //< always send LOSSREPORT immediately after detecting a loss 41 | }; 42 | 43 | struct SrtConfig 44 | { 45 | std::string type; 46 | typedef std::map par_t; 47 | par_t parameters; 48 | }; 49 | 50 | struct SrtFilterConfig: SrtConfig 51 | { 52 | size_t extra_size; // needed for filter option check against payload size 53 | }; 54 | 55 | struct SrtFilterInitializer 56 | { 57 | SRTSOCKET socket_id; 58 | int32_t snd_isn; 59 | int32_t rcv_isn; 60 | size_t payload_size; 61 | }; 62 | 63 | struct SrtPacket 64 | { 65 | uint32_t hdr[SRT_PH_E_SIZE]; 66 | char buffer[SRT_LIVE_MAX_PLSIZE]; 67 | size_t length; 68 | 69 | SrtPacket(size_t size): length(size) 70 | { 71 | memset(hdr, 0, sizeof(hdr)); 72 | } 73 | 74 | uint32_t header(SrtPktHeaderFields field) { return hdr[field]; } 75 | char* data() { return buffer; } 76 | const char* data() const { return buffer; } 77 | size_t size() const { return length; } 78 | }; 79 | 80 | 81 | bool ParseFilterConfig(std::string s, SrtFilterConfig& out); 82 | 83 | 84 | class SrtPacketFilterBase 85 | { 86 | SrtFilterInitializer initParams; 87 | 88 | protected: 89 | 90 | SRTSOCKET socketID() const { return initParams.socket_id; } 91 | int32_t sndISN() const { return initParams.snd_isn; } 92 | int32_t rcvISN() const { return initParams.rcv_isn; } 93 | size_t payloadSize() const { return initParams.payload_size; } 94 | 95 | friend class PacketFilter; 96 | 97 | // Beside the size of the rows, special values: 98 | // 0: if you have 0 specified for rows, there are only columns 99 | // -1: Only during the handshake, use the value specified by peer. 100 | // -N: The N value still specifies the size, but in particular 101 | // dimension there is no filter control packet formed nor expected. 102 | 103 | public: 104 | 105 | typedef std::vector< std::pair > loss_seqs_t; 106 | 107 | protected: 108 | 109 | SrtPacketFilterBase(const SrtFilterInitializer& i): initParams(i) 110 | { 111 | } 112 | 113 | // Sender side 114 | 115 | /// This function creates and stores the filter control packet with 116 | /// a prediction to be immediately sent. This is called in the function 117 | /// that normally is prepared for extracting a data packet from the sender 118 | /// buffer and send it over the channel. The returned value informs the 119 | /// caller whether the control packet was available and therefore provided. 120 | /// @param [OUT] packet Target place where the packet should be stored 121 | /// @param [IN] seq Sequence number of the packet last requested for sending 122 | /// @return true if the control packet has been provided 123 | virtual bool packControlPacket(SrtPacket& packet, int32_t seq) = 0; 124 | 125 | /// This is called at the moment when the sender queue decided to pick up 126 | /// a new packet from the scheduled packets. This should be then used to 127 | /// continue filling the group, possibly followed by final calculating the 128 | /// control packet ready to send. The packet received by this function is 129 | /// potentially allowed to be modified. 130 | /// @param [INOUT] packet The packet about to send 131 | virtual void feedSource(CPacket& packet) = 0; 132 | 133 | 134 | // Receiver side 135 | 136 | // This function is called at the moment when a new data packet has 137 | // arrived (no matter if subsequent or recovered). The 'state' value 138 | // defines the configured level of loss state required to send the 139 | // loss report. 140 | virtual bool receive(const CPacket& pkt, loss_seqs_t& loss_seqs) = 0; 141 | 142 | // Backward configuration. 143 | // This should have some stable value after the configuration is parsed, 144 | // and it should be a stable value set ONCE, after the filter module is ready. 145 | virtual SRT_ARQLevel arqLevel() = 0; 146 | 147 | virtual ~SrtPacketFilterBase() 148 | { 149 | } 150 | }; 151 | 152 | 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /srtcore/packetfilter_builtin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2019 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | #ifndef INC_SRT_PACKETFILTER_BUILTIN_H 13 | #define INC_SRT_PACKETFILTER_BUILTIN_H 14 | 15 | // Integration header 16 | #include "fec.h" 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /srtcore/platform_sys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | #ifndef INC_SRT_PLATFORM_SYS_H 11 | #define INC_SRT_PLATFORM_SYS_H 12 | 13 | // INFORMATION 14 | // 15 | // This file collects all required platform-specific declarations 16 | // required to provide everything that the SRT library needs from system. 17 | // 18 | // There's also semi-modular system implemented using SRT_IMPORT_* macros. 19 | // To require a module to be imported, #define SRT_IMPORT_* where * is 20 | // the module name. Currently handled module macros: 21 | // 22 | // SRT_IMPORT_TIME (mach time on Mac, portability gettimeofday on WIN32) 23 | // SRT_IMPORT_EVENT (includes kevent on Mac) 24 | 25 | 26 | #ifdef _WIN32 27 | #define _CRT_SECURE_NO_WARNINGS 1 // silences windows complaints for sscanf 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #ifndef __MINGW__ 34 | #include 35 | #endif 36 | 37 | #ifdef SRT_IMPORT_TIME 38 | #include 39 | #endif 40 | 41 | #include 42 | #include 43 | #if defined(_MSC_VER) 44 | #pragma warning(disable:4251) 45 | #endif 46 | #else 47 | 48 | #if __APPLE__ 49 | // XXX Check if this condition doesn't require checking of 50 | // also other macros, like TARGET_OS_IOS etc. 51 | 52 | #include "TargetConditionals.h" 53 | #define __APPLE_USE_RFC_3542 /* IPV6_PKTINFO */ 54 | 55 | 56 | #ifdef SRT_IMPORT_TIME 57 | #include 58 | #endif 59 | 60 | #ifdef SRT_IMPORT_EVENT 61 | #include 62 | #include 63 | #include 64 | #include 65 | #endif 66 | 67 | #endif 68 | 69 | #ifdef BSD 70 | #ifdef SRT_IMPORT_EVENT 71 | #include 72 | #include 73 | #include 74 | #include 75 | #endif 76 | #endif 77 | 78 | #ifdef LINUX 79 | 80 | #ifdef SRT_IMPORT_EVENT 81 | #include 82 | #include 83 | #endif 84 | 85 | #endif 86 | 87 | #if defined(__ANDROID__) || defined(ANDROID) 88 | 89 | #ifdef SRT_IMPORT_EVENT 90 | #include 91 | #endif 92 | 93 | #endif 94 | 95 | #include 96 | #include 97 | #include 98 | #include 99 | #include 100 | #include 101 | #include 102 | #include 103 | #include 104 | 105 | #ifdef __cplusplus 106 | // Headers for errno, string and stdlib are 107 | // included indirectly correct C++ way. 108 | #else 109 | #include 110 | #include 111 | #include 112 | #endif 113 | 114 | #endif 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /srtcore/srt_compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | 12 | /***************************************************************************** 13 | written by 14 | Haivision Systems Inc. 15 | *****************************************************************************/ 16 | 17 | #ifndef INC_SRT_COMPAT_H 18 | #define INC_SRT_COMPAT_H 19 | 20 | #include 21 | #include 22 | 23 | #ifndef SRT_API 24 | #ifdef _WIN32 25 | #ifndef __MINGW__ 26 | #ifdef SRT_DYNAMIC 27 | #ifdef SRT_EXPORTS 28 | #define SRT_API __declspec(dllexport) 29 | #else 30 | #define SRT_API __declspec(dllimport) 31 | #endif 32 | #else 33 | #define SRT_API 34 | #endif 35 | #else 36 | #define SRT_API 37 | #endif 38 | #else 39 | #define SRT_API __attribute__ ((visibility("default"))) 40 | #endif 41 | #endif 42 | 43 | #ifdef _WIN32 44 | // https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx 45 | // printf() Format for ssize_t 46 | #if !defined(PRIzd) 47 | #define PRIzd "Id" 48 | #endif 49 | // printf() Format for size_t 50 | #if !defined(PRIzu) 51 | #define PRIzu "Iu" 52 | #endif 53 | #else 54 | // http://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html 55 | // printf() Format for ssize_t 56 | #if !defined(PRIzd) 57 | #define PRIzd "zd" 58 | #endif 59 | // printf() Format for size_t 60 | #if !defined(PRIzu) 61 | #define PRIzu "zu" 62 | #endif 63 | #endif 64 | 65 | 66 | #ifdef __cplusplus 67 | extern "C" { 68 | #endif 69 | 70 | /* Ensures that we store the error in the buffer and return the bufer. */ 71 | SRT_API const char * SysStrError(int errnum, char * buf, size_t buflen); 72 | 73 | #ifdef __cplusplus 74 | } // extern C 75 | 76 | 77 | // Extra C++ stuff. Included only in C++ mode. 78 | 79 | 80 | #include 81 | #include 82 | inline std::string SysStrError(int errnum) 83 | { 84 | char buf[1024]; 85 | return SysStrError(errnum, buf, 1024); 86 | } 87 | 88 | inline struct tm SysLocalTime(time_t tt) 89 | { 90 | struct tm tms; 91 | memset(&tms, 0, sizeof tms); 92 | #ifdef _WIN32 93 | errno_t rr = localtime_s(&tms, &tt); 94 | if (rr == 0) 95 | return tms; 96 | #else 97 | 98 | // Ignore the error, state that if something 99 | // happened, you simply have a pre-cleared tms. 100 | localtime_r(&tt, &tms); 101 | #endif 102 | 103 | return tms; 104 | } 105 | 106 | 107 | #endif // defined C++ 108 | 109 | #endif // INC_SRT_COMPAT_H 110 | -------------------------------------------------------------------------------- /srtcore/srt_shared.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "version.h" 4 | #include "winres.h" 5 | 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Version 9 | // 10 | 11 | VS_VERSION_INFO VERSIONINFO 12 | #ifdef SRT_VERSION_BUILD 13 | FILEVERSION SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH, SRT_VERSION_BUILD 14 | #else 15 | FILEVERSION SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH 16 | #endif 17 | FILEFLAGSMASK 0x3fL 18 | #ifdef _DEBUG 19 | FILEFLAGS 0x1L 20 | #else 21 | FILEFLAGS 0x0L 22 | #endif 23 | FILEOS 0x40004L 24 | FILETYPE 0x2L 25 | FILESUBTYPE 0x0L 26 | BEGIN 27 | BLOCK "StringFileInfo" 28 | BEGIN 29 | BLOCK "080904b0" 30 | BEGIN 31 | VALUE "CompanyName", "SRT Alliance" 32 | VALUE "FileDescription", "SRT Local Build" 33 | VALUE "InternalName", "srt.dll" 34 | VALUE "LegalCopyright", "" 35 | VALUE "OriginalFilename", "srt.dll" 36 | VALUE "ProductName", "SRT" 37 | VALUE "ProductVersion", SRT_VERSION_STRING 38 | END 39 | END 40 | BLOCK "VarFileInfo" 41 | BEGIN 42 | VALUE "Translation", 0x809, 1200 43 | END 44 | END 45 | 46 | -------------------------------------------------------------------------------- /srtcore/sync_cxx11.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2020 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include "sync.h" 14 | #include "srt_compat.h" 15 | #include "common.h" 16 | 17 | //////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // SyncCond (based on stl chrono C++11) 20 | // 21 | //////////////////////////////////////////////////////////////////////////////// 22 | 23 | srt::sync::Condition::Condition() {} 24 | 25 | srt::sync::Condition::~Condition() {} 26 | 27 | void srt::sync::Condition::init() {} 28 | 29 | void srt::sync::Condition::destroy() {} 30 | 31 | void srt::sync::Condition::wait(UniqueLock& lock) 32 | { 33 | m_cv.wait(lock); 34 | } 35 | 36 | bool srt::sync::Condition::wait_for(UniqueLock& lock, const steady_clock::duration& rel_time) 37 | { 38 | // Another possible implementation is wait_until(steady_clock::now() + timeout); 39 | return m_cv.wait_for(lock, rel_time) != cv_status::timeout; 40 | } 41 | 42 | bool srt::sync::Condition::wait_until(UniqueLock& lock, const steady_clock::time_point& timeout_time) 43 | { 44 | return m_cv.wait_until(lock, timeout_time) != cv_status::timeout; 45 | } 46 | 47 | void srt::sync::Condition::notify_one() 48 | { 49 | m_cv.notify_one(); 50 | } 51 | 52 | void srt::sync::Condition::notify_all() 53 | { 54 | m_cv.notify_all(); 55 | } 56 | 57 | //////////////////////////////////////////////////////////////////////////////// 58 | // 59 | // CThreadError class - thread local storage error wrapper 60 | // 61 | //////////////////////////////////////////////////////////////////////////////// 62 | 63 | // Threal local error will be used by CUDTUnited 64 | // with a static scope, therefore static thread_local 65 | static thread_local CUDTException s_thErr; 66 | 67 | void srt::sync::SetThreadLocalError(const CUDTException& e) 68 | { 69 | s_thErr = e; 70 | } 71 | 72 | CUDTException& srt::sync::GetThreadLocalError() 73 | { 74 | return s_thErr; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /srtcore/threadname.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | *****************************************************************************/ 15 | 16 | #ifndef INC_SRT_THREADNAME_H 17 | #define INC_SRT_THREADNAME_H 18 | 19 | #ifdef __linux__ 20 | 21 | #include 22 | #include 23 | 24 | class ThreadName 25 | { 26 | char old_name[128]; 27 | char new_name[128]; 28 | bool good; 29 | 30 | public: 31 | static const size_t BUFSIZE = 128; 32 | 33 | static bool get(char* namebuf) 34 | { 35 | return prctl(PR_GET_NAME, (unsigned long)namebuf, 0, 0) != -1; 36 | } 37 | 38 | static bool set(const char* name) 39 | { 40 | return prctl(PR_SET_NAME, (unsigned long)name, 0, 0) != -1; 41 | } 42 | 43 | 44 | ThreadName(const char* name) 45 | { 46 | if ( (good = get(old_name)) ) 47 | { 48 | snprintf(new_name, 127, "%s", name); 49 | new_name[127] = 0; 50 | prctl(PR_SET_NAME, (unsigned long)new_name, 0, 0); 51 | } 52 | } 53 | 54 | ~ThreadName() 55 | { 56 | if ( good ) 57 | prctl(PR_SET_NAME, (unsigned long)old_name, 0, 0); 58 | } 59 | }; 60 | 61 | #else 62 | 63 | #include "sync.h" 64 | 65 | // Fallback version, which simply reports the thread name as 66 | // T, and custom names used with `set` are ignored. 67 | // If you know how to implement this for other systems than 68 | // Linux, you can make another conditional. This one is now 69 | // the "ultimate fallback". 70 | 71 | class ThreadName 72 | { 73 | public: 74 | static const size_t BUFSIZE = 128; 75 | 76 | static bool get(char* output) 77 | { 78 | // The default implementation will simply try to get the thread ID 79 | std::ostringstream bs; 80 | bs << "T" << srt::sync::this_thread::get_id(); 81 | size_t s = bs.str().copy(output, BUFSIZE-1); 82 | output[s] = '\0'; 83 | return true; 84 | } 85 | static bool set(const char*) { return false; } 86 | 87 | ThreadName(const char*) 88 | { 89 | } 90 | 91 | ~ThreadName() // just to make it "non-trivially-destructible" for compatibility with normal version 92 | { 93 | } 94 | 95 | }; 96 | 97 | 98 | 99 | #endif 100 | #endif 101 | -------------------------------------------------------------------------------- /srtcore/version.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | /***************************************************************************** 12 | written by 13 | Haivision Systems Inc. 14 | *****************************************************************************/ 15 | 16 | #ifndef INC_SRT_VERSION_H 17 | #define INC_SRT_VERSION_H 18 | 19 | // To construct version value 20 | #define SRT_MAKE_VERSION(major, minor, patch) \ 21 | ((patch) + ((minor)*0x100) + ((major)*0x10000)) 22 | #define SRT_MAKE_VERSION_VALUE SRT_MAKE_VERSION 23 | 24 | #define SRT_VERSION_MAJOR @SRT_VERSION_MAJOR@ 25 | #define SRT_VERSION_MINOR @SRT_VERSION_MINOR@ 26 | #define SRT_VERSION_PATCH @SRT_VERSION_PATCH@ 27 | #cmakedefine SRT_VERSION_BUILD @APPVEYOR_BUILD_NUMBER_STRING@ 28 | 29 | #define SRT_VERSION_STRING "@SRT_VERSION@" 30 | #define SRT_VERSION_VALUE \ 31 | SRT_MAKE_VERSION_VALUE( \ 32 | SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH ) 33 | 34 | #endif // INC_SRT_VERSION_H 35 | -------------------------------------------------------------------------------- /test/filelist.maf: -------------------------------------------------------------------------------- 1 | 2 | SOURCES 3 | test_buffer.cpp 4 | test_connection_timeout.cpp 5 | test_many_connections.cpp 6 | test_cryspr.cpp 7 | test_enforced_encryption.cpp 8 | test_epoll.cpp 9 | test_fec_rebuilding.cpp 10 | test_file_transmission.cpp 11 | test_list.cpp 12 | test_listen_callback.cpp 13 | test_muxer.cpp 14 | test_seqno.cpp 15 | test_socket_options.cpp 16 | test_sync.cpp 17 | test_timer.cpp 18 | test_unitqueue.cpp 19 | test_utilities.cpp 20 | 21 | # Tests for bonding only - put here! 22 | 23 | SOURCES - ENABLE_EXPERIMENTAL_BONDING 24 | 25 | -------------------------------------------------------------------------------- /test/test_file_transmission.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2020 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | * Based on the proposal by Russell Greene (Issue #440) 10 | * 11 | */ 12 | 13 | #include 14 | 15 | #ifdef _WIN32 16 | #define INC_SRT_WIN_WINTIME // exclude gettimeofday from srt headers 17 | #endif 18 | 19 | #include "srt.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | //#pragma comment (lib, "ws2_32.lib") 27 | 28 | TEST(Transmission, FileUpload) 29 | { 30 | srt_startup(); 31 | 32 | // Generate the source file 33 | // We need a file that will contain more data 34 | // than can be contained in one sender buffer. 35 | 36 | SRTSOCKET sock_lsn = srt_create_socket(), sock_clr = srt_create_socket(); 37 | 38 | int tt = SRTT_FILE; 39 | srt_setsockflag(sock_lsn, SRTO_TRANSTYPE, &tt, sizeof tt); 40 | srt_setsockflag(sock_clr, SRTO_TRANSTYPE, &tt, sizeof tt); 41 | 42 | // Configure listener 43 | sockaddr_in sa_lsn = sockaddr_in(); 44 | sa_lsn.sin_family = AF_INET; 45 | sa_lsn.sin_addr.s_addr = INADDR_ANY; 46 | sa_lsn.sin_port = htons(5555); 47 | 48 | srt_bind(sock_lsn, (sockaddr*)&sa_lsn, sizeof sa_lsn); 49 | 50 | int optval = 0; 51 | int optlen = sizeof optval; 52 | ASSERT_EQ(srt_getsockflag(sock_lsn, SRTO_SNDBUF, &optval, &optlen), 0); 53 | size_t filesize = 7 * optval; 54 | 55 | { 56 | std::cout << "WILL CREATE source file with size=" << filesize << " (= 7 * " << optval << "[sndbuf])\n"; 57 | std::ofstream outfile("file.source", std::ios::out | std::ios::binary); 58 | ASSERT_EQ(!!outfile, true); 59 | 60 | srand(time(0)); 61 | 62 | for (size_t i = 0; i < filesize; ++i) 63 | { 64 | char outbyte = rand() % 255; 65 | outfile.write(&outbyte, 1); 66 | } 67 | } 68 | 69 | srt_listen(sock_lsn, 1); 70 | 71 | // Start listener-receiver thread 72 | 73 | bool thread_exit = false; 74 | 75 | auto client = std::thread([&] 76 | { 77 | sockaddr_in remote; 78 | int len = sizeof remote; 79 | const SRTSOCKET accepted_sock = srt_accept(sock_lsn, (sockaddr*)&remote, &len); 80 | ASSERT_GT(accepted_sock, 0); 81 | 82 | if (accepted_sock == SRT_INVALID_SOCK) 83 | { 84 | std::cerr << srt_getlasterror_str() << std::endl; 85 | EXPECT_NE(srt_close(sock_lsn), SRT_ERROR); 86 | return; 87 | } 88 | 89 | std::ofstream copyfile("file.target", std::ios::out | std::ios::trunc | std::ios::binary); 90 | 91 | std::vector buf(1456); 92 | 93 | for (;;) 94 | { 95 | int n = srt_recv(accepted_sock, buf.data(), 1456); 96 | ASSERT_NE(n, SRT_ERROR); 97 | if (n == 0) 98 | { 99 | break; 100 | } 101 | 102 | // Write to file any amount of data received 103 | copyfile.write(buf.data(), n); 104 | } 105 | 106 | EXPECT_NE(srt_close(accepted_sock), SRT_ERROR); 107 | 108 | thread_exit = true; 109 | }); 110 | 111 | sockaddr_in sa = sockaddr_in(); 112 | sa.sin_family = AF_INET; 113 | sa.sin_port = htons(5555); 114 | ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr), 1); 115 | 116 | srt_connect(sock_clr, (sockaddr*)&sa, sizeof(sa)); 117 | 118 | std::cout << "Connection initialized" << std::endl; 119 | 120 | std::ifstream ifile("file.source", std::ios::in | std::ios::binary); 121 | std::vector buf(1456); 122 | 123 | for (;;) 124 | { 125 | size_t n = ifile.read(buf.data(), 1456).gcount(); 126 | size_t shift = 0; 127 | while (n > 0) 128 | { 129 | int st = srt_send(sock_clr, buf.data()+shift, n); 130 | ASSERT_GT(st, 0); 131 | 132 | n -= st; 133 | shift += st; 134 | } 135 | 136 | if (ifile.eof()) 137 | { 138 | break; 139 | } 140 | 141 | ASSERT_EQ(ifile.good(), true); 142 | } 143 | 144 | // Finished sending, close the socket 145 | std::cout << "Finished sending, closing sockets:\n"; 146 | srt_close(sock_clr); 147 | srt_close(sock_lsn); 148 | 149 | std::cout << "Sockets closed, joining receiver thread\n"; 150 | client.join(); 151 | 152 | std::ifstream tarfile("file.target"); 153 | EXPECT_EQ(!!tarfile, true); 154 | 155 | tarfile.seekg(0, std::ios::end); 156 | size_t tar_size = tarfile.tellg(); 157 | EXPECT_EQ(tar_size, filesize); 158 | 159 | std::cout << "Comparing files\n"; 160 | // Compare files 161 | tarfile.seekg(0, std::ios::end); 162 | ifile.seekg(0, std::ios::beg); 163 | 164 | for (size_t i = 0; i < tar_size; ++i) 165 | { 166 | EXPECT_EQ(ifile.get(), tarfile.get()); 167 | } 168 | 169 | EXPECT_EQ(ifile.get(), EOF); 170 | EXPECT_EQ(tarfile.get(), EOF); 171 | 172 | remove("file.source"); 173 | remove("file.target"); 174 | 175 | (void)srt_cleanup(); 176 | } 177 | -------------------------------------------------------------------------------- /test/test_seqno.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "common.h" 3 | 4 | 5 | const int32_t CSeqNo::m_iSeqNoTH; 6 | const int32_t CSeqNo::m_iMaxSeqNo; 7 | 8 | 9 | TEST(CSeqNo, constants) 10 | { 11 | // Compare two seq#, considering the wraping. 12 | EXPECT_EQ(CSeqNo::m_iMaxSeqNo, 0x7FFFFFFF); 13 | EXPECT_EQ(CSeqNo::m_iSeqNoTH, 0x3FFFFFFF); 14 | } 15 | 16 | 17 | TEST(CSeqNo, seqcmp) 18 | { 19 | // Compare two seq#, considering the wraping. 20 | EXPECT_EQ(CSeqNo::seqcmp(0x7FFFFFFF, 0x7FFFFFFF), 0); 21 | 22 | // abs(seq1 - seq2) < 0x3FFFFFFF : seq1 - seq2 23 | EXPECT_EQ(CSeqNo::seqcmp(128, 1), 127); 24 | EXPECT_EQ(CSeqNo::seqcmp(1, 128), -127); 25 | 26 | // abs(seq1 - seq2) >= 0x3FFFFFFF : seq2 - seq1 27 | EXPECT_EQ(CSeqNo::seqcmp(0x7FFFFFFF, 1), 0x80000002); // -2147483646 28 | EXPECT_EQ(CSeqNo::seqcmp(1, 0x7FFFFFFF), 0x7FFFFFFE); // 2147483646 29 | } 30 | 31 | 32 | TEST(CSeqNo, seqoff) 33 | { 34 | // seqoff: offset from the 2nd to the 1st seq# 35 | EXPECT_EQ(CSeqNo::seqoff(0x7FFFFFFF, 0x7FFFFFFF), 0); 36 | 37 | // distance(seq2 - seq1) 38 | EXPECT_EQ(CSeqNo::seqoff(125, 1), -124); 39 | 40 | EXPECT_EQ(CSeqNo::seqoff(1, 0x7FFFFFFF), -2); 41 | EXPECT_EQ(CSeqNo::seqoff(0x7FFFFFFF, 1), 2); 42 | } 43 | 44 | 45 | TEST(CSeqNo, incseq) 46 | { 47 | // incseq: increase the seq# by 1 48 | EXPECT_EQ(CSeqNo::incseq(1), 2); 49 | EXPECT_EQ(CSeqNo::incseq(125), 126); 50 | EXPECT_EQ(CSeqNo::incseq(0x7FFFFFFF), 0); 51 | EXPECT_EQ(CSeqNo::incseq(0x3FFFFFFF), 0x40000000); 52 | } 53 | 54 | 55 | TEST(CSeqNo, decseq) 56 | { 57 | // decseq: decrease the seq# by 1 58 | EXPECT_EQ(CSeqNo::decseq(1), 0); 59 | EXPECT_EQ(CSeqNo::decseq(125), 124); 60 | EXPECT_EQ(CSeqNo::decseq(0), 0x7FFFFFFF); 61 | EXPECT_EQ(CSeqNo::decseq(0x40000000), 0x3FFFFFFF); 62 | } 63 | 64 | 65 | TEST(CSeqNo, incseqint) 66 | { 67 | // incseq: increase the seq# by 1 68 | EXPECT_EQ(CSeqNo::incseq(1, 1), 2); 69 | EXPECT_EQ(CSeqNo::incseq(125, 1), 126); 70 | EXPECT_EQ(CSeqNo::incseq(0x7FFFFFFF, 1), 0); 71 | EXPECT_EQ(CSeqNo::incseq(0x3FFFFFFF, 1), 0x40000000); 72 | 73 | EXPECT_EQ(CSeqNo::incseq(0x3FFFFFFF, 0x3FFFFFFF), 0x7FFFFFFE); 74 | EXPECT_EQ(CSeqNo::incseq(0x3FFFFFFF, 0x40000000), 0x7FFFFFFF); 75 | EXPECT_EQ(CSeqNo::incseq(0x3FFFFFFF, 0x40000001), 0x00000000); 76 | } 77 | 78 | 79 | TEST(CSeqNo, decseqint) 80 | { 81 | // decseq: decrease the seq# by 1 82 | EXPECT_EQ(CSeqNo::decseq(1, 1), 0); 83 | EXPECT_EQ(CSeqNo::decseq(125, 1), 124); 84 | EXPECT_EQ(CSeqNo::decseq(0, 1), 0x7FFFFFFF); 85 | EXPECT_EQ(CSeqNo::decseq(0x40000000, 1), 0x3FFFFFFF); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /test/test_socket_options.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2019 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | * Written by: 10 | * Haivision Systems Inc. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "srt.h" 18 | 19 | using namespace std; 20 | 21 | 22 | class TestSocketOptions 23 | : public ::testing::Test 24 | { 25 | protected: 26 | TestSocketOptions() 27 | { 28 | // initialization code here 29 | } 30 | 31 | ~TestSocketOptions() 32 | { 33 | // cleanup any pending stuff, but no exceptions allowed 34 | } 35 | 36 | protected: 37 | // SetUp() is run immediately before a test starts. 38 | void SetUp() 39 | { 40 | ASSERT_GE(srt_startup(), 0); 41 | const int yes = 1; 42 | 43 | m_caller_sock = srt_create_socket(); 44 | ASSERT_NE(m_caller_sock, SRT_INVALID_SOCK); 45 | ASSERT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_RCVSYN, &yes, sizeof yes), SRT_SUCCESS); // for async connect 46 | ASSERT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_SNDSYN, &yes, sizeof yes), SRT_SUCCESS); // for async connect 47 | 48 | m_listen_sock = srt_create_socket(); 49 | ASSERT_NE(m_listen_sock, SRT_INVALID_SOCK); 50 | ASSERT_EQ(srt_setsockopt(m_listen_sock, 0, SRTO_RCVSYN, &yes, sizeof yes), SRT_SUCCESS); // for async connect 51 | ASSERT_EQ(srt_setsockopt(m_listen_sock, 0, SRTO_SNDSYN, &yes, sizeof yes), SRT_SUCCESS); // for async connect 52 | } 53 | 54 | void TearDown() 55 | { 56 | // Code here will be called just after the test completes. 57 | // OK to throw exceptions from here if needed. 58 | ASSERT_NE(srt_close(m_caller_sock), SRT_ERROR); 59 | ASSERT_NE(srt_close(m_listen_sock), SRT_ERROR); 60 | srt_cleanup(); 61 | } 62 | 63 | protected: 64 | // put in any custom data members that you need 65 | 66 | SRTSOCKET m_caller_sock = SRT_INVALID_SOCK; 67 | SRTSOCKET m_listen_sock = SRT_INVALID_SOCK; 68 | 69 | int m_pollid = 0; 70 | }; 71 | 72 | 73 | /// A regression test for issue #735, fixed by PR #843. 74 | /// Checks propagation of listener's socket option SRTO_LOSSMAXTTL 75 | /// on SRT sockets being accepted. 76 | TEST_F(TestSocketOptions, LossMaxTTL) 77 | { 78 | const int loss_max_ttl = 5; 79 | ASSERT_EQ(srt_setsockopt(m_listen_sock, 0, SRTO_LOSSMAXTTL, &loss_max_ttl, sizeof loss_max_ttl), SRT_SUCCESS); 80 | 81 | // Specify address 82 | sockaddr_in sa; 83 | memset(&sa, 0, sizeof sa); 84 | sa.sin_family = AF_INET; 85 | sa.sin_port = htons(5200); 86 | ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr), 1); 87 | sockaddr* psa = (sockaddr*)&sa; 88 | ASSERT_NE(srt_bind(m_listen_sock, psa, sizeof sa), SRT_ERROR); 89 | 90 | srt_listen(m_listen_sock, 1); 91 | 92 | auto accept_async = [](SRTSOCKET listen_sock) { 93 | sockaddr_in client_address; 94 | int length = sizeof(sockaddr_in); 95 | const SRTSOCKET accepted_socket = srt_accept(listen_sock, (sockaddr*)&client_address, &length); 96 | return accepted_socket; 97 | }; 98 | auto accept_res = async(launch::async, accept_async, m_listen_sock); 99 | 100 | const int connect_res = srt_connect(m_caller_sock, psa, sizeof sa); 101 | EXPECT_EQ(connect_res, SRT_SUCCESS); 102 | 103 | const SRTSOCKET accepted_sock = accept_res.get(); 104 | ASSERT_NE(accepted_sock, SRT_INVALID_SOCK); 105 | 106 | int opt_val = 0; 107 | int opt_len = 0; 108 | ASSERT_EQ(srt_getsockopt(accepted_sock, 0, SRTO_LOSSMAXTTL, &opt_val, &opt_len), SRT_SUCCESS); 109 | EXPECT_EQ(opt_val, loss_max_ttl) << "Wrong SRTO_LOSSMAXTTL value on the accepted socket"; 110 | EXPECT_EQ(opt_len, sizeof opt_len) << "Wrong SRTO_LOSSMAXTTL value length on the accepted socket"; 111 | 112 | SRT_TRACEBSTATS stats; 113 | EXPECT_EQ(srt_bstats(accepted_sock, &stats, 0), SRT_SUCCESS); 114 | EXPECT_EQ(stats.pktReorderTolerance, loss_max_ttl); 115 | 116 | ASSERT_EQ(srt_getsockopt(m_listen_sock, 0, SRTO_LOSSMAXTTL, &opt_val, &opt_len), SRT_SUCCESS); 117 | EXPECT_EQ(opt_val, loss_max_ttl) << "Wrong SRTO_LOSSMAXTTL value on the listener socket"; 118 | EXPECT_EQ(opt_len, sizeof opt_len) << "Wrong SRTO_LOSSMAXTTL value length on the listener socket"; 119 | 120 | ASSERT_NE(srt_close(accepted_sock), SRT_ERROR); 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /test/test_timer.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include 3 | #include 4 | #include 5 | #include // std::accumulate 6 | #include "common.h" 7 | #include "sync.h" 8 | 9 | 10 | 11 | 12 | TEST(CTimer, DISABLED_SleeptoAccuracy) 13 | { 14 | using namespace std; 15 | using namespace srt::sync; 16 | 17 | const int num_samples = 1000; 18 | array sleeps_us; 19 | 20 | const uint64_t sleep_intervals_us[] = { 1, 5, 10, 50, 100, 250, 500, 1000, 5000, 10000 }; 21 | 22 | CTimer timer; 23 | 24 | for (uint64_t interval_us : sleep_intervals_us) 25 | { 26 | for (int i = 0; i < num_samples; i++) 27 | { 28 | steady_clock::time_point currtime = steady_clock::now(); 29 | timer.sleep_until(currtime + microseconds_from(interval_us)); 30 | 31 | steady_clock::time_point new_time = steady_clock::now(); 32 | sleeps_us[i] = count_microseconds(new_time - currtime); 33 | } 34 | 35 | cerr << "Target sleep duration: " << interval_us << " us\n"; 36 | cerr << "avg sleep duration: " << accumulate(sleeps_us.begin(), sleeps_us.end(), (uint64_t) 0) / num_samples << " us\n"; 37 | cerr << "min sleep duration: " << *min_element(sleeps_us.begin(), sleeps_us.end()) << " us\n"; 38 | cerr << "max sleep duration: " << *max_element(sleeps_us.begin(), sleeps_us.end()) << " us\n"; 39 | cerr << "\n"; 40 | } 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /test/test_unitqueue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "gtest/gtest.h" 4 | #include "queue.h" 5 | 6 | 7 | using namespace std; 8 | 9 | 10 | /// Create CUnitQueue with queue size of 4 units. 11 | /// The size of 4 is chosen on purpose, because 12 | /// CUnitQueue::getNextAvailUnit(..) has the following 13 | /// condition `if (m_iCount * 10 > m_iSize * 9)`. With m_iSize = 4 14 | /// it will be false up until m_iCount becomes 4. 15 | /// And there was an issue in getNextAvailUnit(..) in taking 16 | /// the very last element of the queue (it was skipped). 17 | TEST(CUnitQueue, Increase) 18 | { 19 | const int buffer_size_pkts = 4; 20 | CUnitQueue unit_queue; 21 | unit_queue.init(buffer_size_pkts, 1500, AF_INET); 22 | 23 | vector taken_units; 24 | for (int i = 0; i < 5 * buffer_size_pkts; ++i) 25 | { 26 | CUnit* unit = unit_queue.getNextAvailUnit(); 27 | ASSERT_NE(unit, nullptr); 28 | unit_queue.makeUnitGood(unit); 29 | taken_units.push_back(unit); 30 | } 31 | } 32 | 33 | /// Create CUnitQueue with queue size of 4 units. 34 | /// Then after requesting the 5th unit, free the previous 35 | /// four units. This makes the previous queue completely free. 36 | /// Requesting the 5th unit, there would be 3 units available in the 37 | /// beginning of the same queue. 38 | TEST(CUnitQueue, IncreaseAndFree) 39 | { 40 | const int buffer_size_pkts = 4; 41 | CUnitQueue unit_queue; 42 | unit_queue.init(buffer_size_pkts, 1500, AF_INET); 43 | 44 | CUnit* taken_unit = nullptr; 45 | for (int i = 0; i < 5 * buffer_size_pkts; ++i) 46 | { 47 | CUnit* unit = unit_queue.getNextAvailUnit(); 48 | ASSERT_NE(unit, nullptr); 49 | unit_queue.makeUnitGood(unit); 50 | 51 | if (taken_unit) 52 | unit_queue.makeUnitFree(taken_unit); 53 | 54 | taken_unit = unit; 55 | } 56 | } 57 | 58 | /// Create CUnitQueue with queue size of 4 units. 59 | /// Then after requesting the 5th unit, free the previous 60 | /// four units. This makes the previous queue completely free. 61 | /// Requesting the 9th unit, there would be 4 units available in the 62 | /// Thus the test checks if 63 | TEST(CUnitQueue, IncreaseAndFreeGrouped) 64 | { 65 | const int buffer_size_pkts = 4; 66 | CUnitQueue unit_queue; 67 | unit_queue.init(buffer_size_pkts, 1500, AF_INET); 68 | 69 | vector taken_units; 70 | for (int i = 0; i < 5 * buffer_size_pkts; ++i) 71 | { 72 | CUnit* unit = unit_queue.getNextAvailUnit(); 73 | ASSERT_NE(unit, nullptr); 74 | unit_queue.makeUnitGood(unit); 75 | 76 | if (taken_units.size() >= buffer_size_pkts) 77 | { 78 | for_each(taken_units.begin(), taken_units.end(), 79 | [&unit_queue](CUnit* u) { unit_queue.makeUnitFree(u); }); 80 | 81 | taken_units.clear(); 82 | } 83 | 84 | taken_units.push_back(unit); 85 | EXPECT_LE(unit_queue.capacity(), 2 * buffer_size_pkts) 86 | << "Buffer capacity should not exceed two queues of 4 units"; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /testing/README.md: -------------------------------------------------------------------------------- 1 | Testing 2 | ======= 3 | 4 | This directory contains applications used for testing and development only. 5 | 6 | They may contain experimental versions or not fully functioning features. 7 | 8 | Every application has its own individual Manifest file (`*.maf`), which defines 9 | of which source files particular application comprises. They may be contained 10 | either in the same directory, or in any other subproject. 11 | -------------------------------------------------------------------------------- /testing/srt-test-file.maf: -------------------------------------------------------------------------------- 1 | 2 | SOURCES 3 | srt-test-file.cpp 4 | testmedia.cpp 5 | ../apps/apputil.cpp 6 | ../apps/verbose.cpp 7 | ../apps/socketoptions.cpp 8 | ../apps/uriparser.cpp 9 | ../apps/logsupport.cpp 10 | ../apps/logsupport_appdefs.cpp 11 | 12 | -------------------------------------------------------------------------------- /testing/srt-test-live.maf: -------------------------------------------------------------------------------- 1 | 2 | 3 | SOURCES 4 | srt-test-live.cpp 5 | testmedia.cpp 6 | ../apps/apputil.cpp 7 | ../apps/verbose.cpp 8 | ../apps/socketoptions.cpp 9 | ../apps/uriparser.cpp 10 | ../apps/logsupport.cpp 11 | ../apps/logsupport_appdefs.cpp 12 | 13 | -------------------------------------------------------------------------------- /testing/srt-test-mpbond.maf: -------------------------------------------------------------------------------- 1 | 2 | SOURCES 3 | srt-test-mpbond.cpp 4 | testmedia.cpp 5 | ../apps/apputil.cpp 6 | ../apps/verbose.cpp 7 | ../apps/socketoptions.cpp 8 | ../apps/uriparser.cpp 9 | ../apps/logsupport.cpp 10 | ../apps/logsupport_appdefs.cpp 11 | 12 | -------------------------------------------------------------------------------- /testing/srt-test-multiplex.maf: -------------------------------------------------------------------------------- 1 | 2 | 3 | SOURCES 4 | srt-test-multiplex.cpp 5 | testmedia.cpp 6 | ../apps/apputil.cpp 7 | ../apps/verbose.cpp 8 | ../apps/socketoptions.cpp 9 | ../apps/uriparser.cpp 10 | ../apps/logsupport.cpp 11 | ../apps/logsupport_appdefs.cpp 12 | 13 | -------------------------------------------------------------------------------- /testing/srt-test-relay.maf: -------------------------------------------------------------------------------- 1 | 2 | 3 | SOURCES 4 | srt-test-relay.cpp 5 | testmedia.cpp 6 | ../apps/apputil.cpp 7 | ../apps/verbose.cpp 8 | ../apps/socketoptions.cpp 9 | ../apps/uriparser.cpp 10 | ../apps/logsupport.cpp 11 | ../apps/logsupport_appdefs.cpp 12 | 13 | -------------------------------------------------------------------------------- /testing/testmediabase.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #ifndef INC_SRT_COMMON_TRANMITBASE_HPP 12 | #define INC_SRT_COMMON_TRANMITBASE_HPP 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | typedef std::vector bytevector; 21 | extern volatile bool transmit_throw_on_interrupt; 22 | extern int transmit_bw_report; 23 | extern unsigned transmit_stats_report; 24 | extern size_t transmit_chunk_size; 25 | extern bool transmit_printformat_json; 26 | extern bool transmit_use_sourcetime; 27 | 28 | struct MediaPacket 29 | { 30 | bytevector payload; 31 | int64_t time = 0; 32 | 33 | MediaPacket(bytevector&& src): payload(std::move(src)) {} 34 | MediaPacket(bytevector&& src, int64_t stime): payload(std::move(src)), time(stime) {} 35 | 36 | MediaPacket(const bytevector& src): payload(src) {} 37 | MediaPacket(const bytevector& src, int64_t stime): payload(src), time(stime) {} 38 | MediaPacket() {} 39 | }; 40 | 41 | 42 | class Location 43 | { 44 | public: 45 | UriParser uri; 46 | Location() {} 47 | virtual bool IsOpen() = 0; 48 | virtual void Close() {} 49 | }; 50 | 51 | class Source: public virtual Location 52 | { 53 | public: 54 | virtual MediaPacket Read(size_t chunk) = 0; 55 | virtual bool End() = 0; 56 | static std::unique_ptr Create(const std::string& url); 57 | virtual ~Source() {} 58 | 59 | class ReadEOF: public std::runtime_error 60 | { 61 | public: 62 | ReadEOF(const std::string& fn): std::runtime_error( "EOF while reading file: " + fn ) 63 | { 64 | } 65 | }; 66 | }; 67 | 68 | class Target: public virtual Location 69 | { 70 | public: 71 | virtual void Write(const MediaPacket& portion) = 0; 72 | virtual bool Broken() = 0; 73 | virtual size_t Still() { return 0; } 74 | static std::unique_ptr Create(const std::string& url); 75 | virtual ~Target() {} 76 | }; 77 | 78 | 79 | class Relay: public virtual Source, public virtual Target, public virtual Location 80 | { 81 | public: 82 | static std::unique_ptr Create(const std::string& url); 83 | virtual ~Relay() {} 84 | }; 85 | 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /testing/uriparser-test.maf: -------------------------------------------------------------------------------- 1 | 2 | SOURCES 3 | ../apps/uriparser.cpp 4 | -------------------------------------------------------------------------------- /testing/utility-test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SRT - Secure, Reliable, Transport 3 | * Copyright (c) 2018 Haivision Systems Inc. 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | void ShowDistance(int32_t s1, int32_t s2) 22 | { 23 | using namespace std; 24 | 25 | cout << "s1=" << s1 << "s2=" << s2 << " DISTANCE:\n"; 26 | cout << "seqcmp -> " << CSeqNo::seqcmp(s1, s2) << endl; 27 | cout << "seqoff -> " << CSeqNo::seqoff(s2, s1) << endl; 28 | } 29 | 30 | int main() 31 | { 32 | using namespace std; 33 | 34 | cout << "PacketBoundary: " << hex << MSGNO_PACKET_BOUNDARY::mask << endl; 35 | 36 | cout << "PB_FIRST: " << hex << PacketBoundaryBits(PB_FIRST) << endl; 37 | cout << "PB_LAST: " << hex << PacketBoundaryBits(PB_LAST) << endl; 38 | cout << "PB_SOLO: " << hex << PacketBoundaryBits(PB_SOLO) << endl; 39 | 40 | cout << "inorder: " << hex << MSGNO_PACKET_INORDER::mask << " (1 << " << dec << MSGNO_PACKET_INORDER::offset << ")" << endl; 41 | cout << "msgno-seq mask: " << hex << MSGNO_SEQ::mask << endl; 42 | cout << "3 wrapped into enckeyspec: " << hex << setw(8) << setfill('0') << MSGNO_ENCKEYSPEC::wrap(3) << " - mask: " << MSGNO_ENCKEYSPEC::mask << endl; 43 | 44 | cout << "SrtVersion test: 2.3.8 == 0x020308 -- SrtVersion(2, 3, 8) == 0x" << hex << setw(8) << setfill('0') << SrtVersion(2, 3, 8) << endl; 45 | 46 | cout << "SEQNO_CONTROL::mask: " << hex << SEQNO_CONTROL::mask << " SEQNO 0x80050000 has control = " << SEQNO_CONTROL::unwrap(0x80050000) 47 | << " type = " << SEQNO_MSGTYPE::unwrap(0x80050000) << endl; 48 | 49 | cout << "Creating array of bytes: 10, 11, 20, 25 - FormatBinaryString: "; 50 | uint8_t array[4] = { 10, 11, 20, 25 }; 51 | cout << FormatBinaryString(array, 4) << endl; 52 | 53 | cout << "-------------------------------\n"; 54 | cout << "SEQUENCES:\n"; 55 | int32_t s1 = 100, s2 = 200; 56 | ShowDistance(s1, s2); 57 | 58 | cout << "GO BACK BY -150:\n"; 59 | s1 = CSeqNo::decseq(s1, 150); 60 | s2 = CSeqNo::decseq(s2, 150); 61 | ShowDistance(s1, s2); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /testing/utility-test.maf: -------------------------------------------------------------------------------- 1 | 2 | SOURCES 3 | utility-test.cpp 4 | --------------------------------------------------------------------------------