From c0fcf243baecca659b1c514a29ecfb5db12903ef Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Tue, 6 Dec 2022 17:54:20 +0000 Subject: [PATCH 01/29] SRT SWIG * -add swig bindings and wrapper for c# --- .appveyor.yml | 22 ++-- .gitignore | 8 ++ CMakeLists.txt | 30 +++++ scripts/Dockerfile.linux | 38 +++++++ scripts/build-lin-docker.bat | 3 + scripts/build-lin-docker.ps1 | 55 +++++++++ scripts/build-linux.sh | 14 +++ scripts/build-windows.ps1 | 50 +++++--- scripts/create-win64-nuget.bat | 29 +++++ scripts/gather-package.bat | 11 +- scripts/get-windows-build-packages.bat | 2 + scripts/get-windows-build-packages.ps1 | 6 + scripts/nuget/SrtSharp/SrtSharp.nuspec | 29 +++++ scripts/nuget/SrtSharp/build/SrtSharp.props | 23 ++++ scripts/nuget/SrtSharp/build/SrtSharp.targets | 24 ++++ scripts/set-version-metadata.ps1 | 2 +- srtcore/srt.h | 5 + srtcore/srt.i | 107 ++++++++++++++++++ srtcore/swig_bindings/csharp/srtsharp.csproj | 9 ++ 19 files changed, 439 insertions(+), 28 deletions(-) create mode 100644 scripts/Dockerfile.linux create mode 100644 scripts/build-lin-docker.bat create mode 100755 scripts/build-lin-docker.ps1 create mode 100755 scripts/build-linux.sh create mode 100644 scripts/create-win64-nuget.bat create mode 100644 scripts/get-windows-build-packages.bat create mode 100644 scripts/get-windows-build-packages.ps1 create mode 100644 scripts/nuget/SrtSharp/SrtSharp.nuspec create mode 100644 scripts/nuget/SrtSharp/build/SrtSharp.props create mode 100644 scripts/nuget/SrtSharp/build/SrtSharp.targets create mode 100644 srtcore/srt.i create mode 100644 srtcore/swig_bindings/csharp/srtsharp.csproj diff --git a/.appveyor.yml b/.appveyor.yml index 96b785d93..d542ff506 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -3,29 +3,29 @@ configuration: - Debug image: + - Ubuntu - Visual Studio 2019 - Visual Studio 2015 - - Visual Studio 2013 platform: - x64 - x86 build_script: - - ps: $VSIMG = $Env:APPVEYOR_BUILD_WORKER_IMAGE; $CNFG = $Env:CONFIGURATION + - ps: $VSIMG = $Env:APPVEYOR_BUILD_WORKER_IMAGE; $CNFG = $Env:CONFIGURATION # use a few differing arguments depending on VS version to exercise different options during builds - - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON } - - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON } + - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON -ENABLE_SWIG ON} + - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -ENABLE_SWIG ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } - - ps: if ($VSIMG -match '2013' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -CXX11 OFF -BUILD_APPS ON } - - ps: if ($VSIMG -match '2013' -and $CNFG -eq "Debug") { Exit-AppveyorBuild } # just skip 2013 debug build for speed + - sh: ./scripts/build-lin-docker.ps1 test_script: - ps: if ( $Env:RUN_UNIT_TESTS ) { cd ./_build; ctest -E "TestIPv6.v6_calls_v4" --extra-verbose -C $Env:CONFIGURATION; cd ../ } - + after_build: -- cmd: >- - scripts/gather-package.bat - 7z a SRT-%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%-Win%PLATFORM%-%VS_VERSION%-%APPVEYOR_BUILD_VERSION%.zip %APPVEYOR_BUILD_FOLDER%\package\* - appveyor PushArtifact SRT-%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%-Win%PLATFORM%-%VS_VERSION%-%APPVEYOR_BUILD_VERSION%.zip + - cmd: cd %APPVEYOR_BUILD_FOLDER% + - cmd: scripts/gather-package.bat + - cmd: scripts/create-win64-nuget.bat + - cmd: 7z a SRT-%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%-Win%PLATFORM%-%VS_VERSION%-%APPVEYOR_BUILD_VERSION%.zip %APPVEYOR_BUILD_FOLDER%\package\* + - cmd: appveyor PushArtifact SRT-%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%-Win%PLATFORM%-%VS_VERSION%-%APPVEYOR_BUILD_VERSION%.zip diff --git a/.gitignore b/.gitignore index 699d0e1b4..3bdec2300 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,11 @@ vcpkg/ # LSP compile_commands.json + +# Nuget packages +packages/ +package/ +*.nupkg + +# Swig bindings +/srtcore/swig_bindings diff --git a/CMakeLists.txt b/CMakeLists.txt index 58a31d1f2..e3fa651f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,6 +160,8 @@ option(USE_BUSY_WAITING "Enable more accurate sending times at a cost of potenti option(USE_GNUSTL "Get c++ library/headers from the gnustl.pc" OFF) option(ENABLE_SOCK_CLOEXEC "Enable setting SOCK_CLOEXEC on a socket" ON) option(ENABLE_SHOW_PROJECT_CONFIG "Enable show Project Configuration" OFF) +option(ENABLE_SWIG "Enable SWIG, used to generate alternative language bindings" OFF) +option(ENABLE_SWIG_CSHARP "Enable SWIG binding generation for CSharp language (only effective if ENABLE_SWIG is ON)" ON) option(ENABLE_CLANG_TSA "Enable Clang Thread Safety Analysis" OFF) @@ -1340,6 +1342,34 @@ endif() srt_add_example(testcapi-connect.c) endif() +#SWIG support - adding bindings for other languages into a new library that statically include the main SRT lib +cmake_policy(SET CMP0078 NEW) +cmake_policy(SET CMP0086 NEW) + +#older cmakes do not understand this policy, so filter (VS2015 AppVeyor cmake is too old) +if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.21) + cmake_policy(SET CMP0122 NEW) +endif() + + +#experimental SWIG support for csharp - only enabled for Windows currently +if(ENABLE_SWIG) + if(MICROSOFT) + #if nuget has been used to install swig in the project packages, bind to that + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/packages/swig/swigwin-4.1.1/swig.exe") + set(SWIG_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/packages/swig/swigwin-4.1.1/swig.exe") + endif() + endif() + + FIND_PACKAGE(SWIG REQUIRED) + INCLUDE(${SWIG_USE_FILE}) + + if(ENABLE_SWIG_CSHARP) + swig_add_library(srt_swig_csharp LANGUAGE csharp SOURCES srtcore/srt.i OUTPUT_DIR ${CMAKE_BINARY_DIR}/swig_bindings/csharp) + swig_link_libraries(srt_swig_csharp ${srt_link_library} ${DEPENDS_srt}) + set_property(TARGET srt_swig_csharp PROPERTY SWIG_COMPILE_OPTIONS -namespace SrtSharp) + endif() +endif() if (ENABLE_UNITTESTS AND ENABLE_CXX11) diff --git a/scripts/Dockerfile.linux b/scripts/Dockerfile.linux new file mode 100644 index 000000000..eedaa5919 --- /dev/null +++ b/scripts/Dockerfile.linux @@ -0,0 +1,38 @@ +FROM ubuntu:20.04 + +LABEL maintainer="Lewis Kirkaldie " + +ENV TZ=Europe/Berlin +ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 +ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +#base dev packages and OS tools, including mono and boost other library dependencies +RUN apt-get update && apt-get upgrade -y && apt-get install -y \ + build-essential git nano gnupg apt-utils unzip sudo bzip2 \ + apt-transport-https curl wget ca-certificates cpio \ + libssl-dev software-properties-common \ + p7zip-full p7zip-rar swig && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +#add powershell core & dotnet 6.0 +RUN cd /tmp && \ + curl -o packages-microsoft-prod.deb https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -sS && \ + dpkg -i packages-microsoft-prod.deb && \ + rm packages-microsoft-prod.deb && \ + apt-get update && \ + apt-get install -y powershell && \ + apt-get install -y dotnet-sdk-6.0 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +#add cmake 3.24.1 +RUN mkdir -p /usr/src/cmake \ +&& curl -L https://github.com/Kitware/CMake/releases/download/v3.24.1/cmake-3.24.1-linux-x86_64.tar.gz -o /usr/src/cmake/cmake.tar.gz -sS \ +&& tar -C /usr/src/cmake -xzf /usr/src/cmake/cmake.tar.gz \ +&& ln -s /usr/src/cmake/cmake-3.24.1-linux-x86_64/bin/cmake /usr/bin/cmake \ +&& rm /usr/src/cmake/cmake.tar.gz diff --git a/scripts/build-lin-docker.bat b/scripts/build-lin-docker.bat new file mode 100644 index 000000000..78a926cb5 --- /dev/null +++ b/scripts/build-lin-docker.bat @@ -0,0 +1,3 @@ +@ECHO OFF +%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\PowerShell.exe -Command "& '%~dpn0.ps1'" +pause diff --git a/scripts/build-lin-docker.ps1 b/scripts/build-lin-docker.ps1 new file mode 100755 index 000000000..60dd0d6c7 --- /dev/null +++ b/scripts/build-lin-docker.ps1 @@ -0,0 +1,55 @@ +#! /usr/bin/pwsh + +################################################################################ +# Linux SRT Build Script +#============================ +# Usable on a Linux machine (or container), or called by CI systems like AppVeyor +# +# By default produces a 64-bit Release binary using C++11 threads, without +# encryption or unit tests enabled, but including test apps. +################################################################################ + +param ( + [Parameter()][String]$CONFIGURATION = "Release", + [Parameter()][String]$DEVENV_PLATFORM = "x64", + [Parameter()][String]$ENABLE_ENCRYPTION = "OFF", + [Parameter()][String]$STATIC_LINK_SSL = "OFF", + [Parameter()][String]$CXX11 = "ON", + [Parameter()][String]$BUILD_APPS = "ON", + [Parameter()][String]$UNIT_TESTS = "OFF", + [Parameter()][String]$BUILD_DIR = "_build-linux", + [Parameter()][String]$ENABLE_SWIG = "OFF", + [Parameter()][String]$ENABLE_SWIG_CSHARP = "ON" +) + +$projectRoot = Join-Path $PSScriptRoot "/.." -Resolve + +# generate command to make sure an up-to-date docker container (for compiling within) is built +$execVar = "docker build -t srtbuildcontainer:latest -f $($projectRoot)/scripts/Dockerfile.linux ." +Write-Output $execVar +Invoke-Expression "& $execVar" + +# clear any previous build and create & enter the build directory +$buildDir = Join-Path "$projectRoot" "$BUILD_DIR" +Write-Output "Creating (or cleaning if already existing) the folder $buildDir for project files and outputs" +Remove-Item -Path $buildDir -Recurse -Force -ErrorAction SilentlyContinue | Out-Null +New-Item -ItemType Directory -Path $buildDir -ErrorAction SilentlyContinue | Out-Null + +# build the cmake command flags from arguments +$cmakeFlags = "-DCMAKE_BUILD_TYPE=$CONFIGURATION " + + "-DENABLE_STDCXX_SYNC=$CXX11 " + + "-DENABLE_APPS=$BUILD_APPS " + + "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + + "-DENABLE_UNITTESTS=$UNIT_TESTS " + + "-DENABLE_SWIG=$ENABLE_SWIG " + + "-DENABLE_SWIG_CSHARP=$ENABLE_SWIG_CSHARP" + +# generate command for docker run of cmake generation step +$execVar = "docker run --rm -v $($projectRoot):/srt -w /srt/$BUILD_DIR srtbuildcontainer:latest cmake -S ../ $cmakeFlags" +Write-Output $execVar +Invoke-Expression "& $execVar" + +# generate command for docker run of cmake build +$execVar = "docker run --rm -v $($projectRoot):/srt -w /srt/$BUILD_DIR srtbuildcontainer:latest cmake --build ./" +Write-Output $execVar +Invoke-Expression "& $execVar" diff --git a/scripts/build-linux.sh b/scripts/build-linux.sh new file mode 100755 index 000000000..af483e05c --- /dev/null +++ b/scripts/build-linux.sh @@ -0,0 +1,14 @@ +#! /usr/bin/bash + +set -e +set -o pipefail + +if [ -d Release.linux ]; then + rm -rf ./Release.linux +fi + +printf "\nBuilding Release\n" +mkdir Release.linux +cd Release.linux +cmake -S ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_UNITTESTS=ON -DENABLE_EXPERIMENTAL_BONDING=ON -DENABLE_SWIG=ON +cmake --build ./ \ No newline at end of file diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index cd25da12c..1d25c9824 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -20,7 +20,9 @@ param ( [Parameter()][String]$UNIT_TESTS = "OFF", [Parameter()][String]$BUILD_DIR = "_build", [Parameter()][String]$VCPKG_OPENSSL = "OFF", - [Parameter()][String]$BONDING = "OFF" + [Parameter()][String]$BONDING = "OFF", + [Parameter()][String]$ENABLE_SWIG = "ON", + [Parameter()][String]$ENABLE_SWIG_CSHARP = "ON" ) # cmake can be optionally installed (useful when running interactively on a developer station). @@ -38,7 +40,6 @@ if ( $Env:APPVEYOR ) { if ( $Env:PLATFORM -eq 'x86' ) { $DEVENV_PLATFORM = 'Win32' } else { $DEVENV_PLATFORM = 'x64' } if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2019' ) { $VS_VERSION='2019' } if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2015' ) { $VS_VERSION='2015' } - if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2013' ) { $VS_VERSION='2013' } #if not statically linking OpenSSL, set flag to gather the specific openssl package from the build server into package if ( $STATIC_LINK_SSL -eq 'OFF' ) { $Env:GATHER_SSL_INTO_PACKAGE = $true } @@ -48,13 +49,11 @@ if ( $Env:APPVEYOR ) { $CONFIGURATION = $Env:CONFIGURATION - #appveyor has many openssl installations - place the latest one in the default location unless VS2013 - if( $VS_VERSION -ne '2013' ) { - Remove-Item -Path "C:\OpenSSL-Win32" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null - Remove-Item -Path "C:\OpenSSL-Win64" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null - Copy-Item -Path "C:\OpenSSL-v111-Win32" "C:\OpenSSL-Win32" -Recurse | Out-Null - Copy-Item -Path "C:\OpenSSL-v111-Win64" "C:\OpenSSL-Win64" -Recurse | Out-Null - } + #appveyor has many openssl installations - place the latest v111 edition in the default location + Remove-Item -Path "C:\OpenSSL-Win32" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null + Remove-Item -Path "C:\OpenSSL-Win64" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null + Copy-Item -Path "C:\OpenSSL-v111-Win32" "C:\OpenSSL-Win32" -Recurse | Out-Null + Copy-Item -Path "C:\OpenSSL-v111-Win64" "C:\OpenSSL-Win64" -Recurse | Out-Null } # persist VS_VERSION so it can be used in an artifact name later @@ -64,8 +63,6 @@ $Env:VS_VERSION = $VS_VERSION if ( $VS_VERSION -eq '2019' ) { $CMAKE_GENERATOR = 'Visual Studio 16 2019'; $MSBUILDVER = "16.0"; } if ( $VS_VERSION -eq '2015' -and $DEVENV_PLATFORM -eq 'Win32' ) { $CMAKE_GENERATOR = 'Visual Studio 14 2015'; $MSBUILDVER = "14.0"; } if ( $VS_VERSION -eq '2015' -and $DEVENV_PLATFORM -eq 'x64' ) { $CMAKE_GENERATOR = 'Visual Studio 14 2015 Win64'; $MSBUILDVER = "14.0"; } -if ( $VS_VERSION -eq '2013' -and $DEVENV_PLATFORM -eq 'Win32' ) { $CMAKE_GENERATOR = 'Visual Studio 12 2013'; $MSBUILDVER = "12.0"; } -if ( $VS_VERSION -eq '2013' -and $DEVENV_PLATFORM -eq 'x64' ) { $CMAKE_GENERATOR = 'Visual Studio 12 2013 Win64'; $MSBUILDVER = "12.0"; } # clear any previous build and create & enter the build directory $buildDir = Join-Path "$projectRoot" "$BUILD_DIR" @@ -132,13 +129,29 @@ if ( $VCPKG_OPENSSL -eq "ON" ) { } } +# check to see if SWIG is marked to be used - if so, download swig into packages folder so cmake can find it +if ( $ENABLE_SWIG -eq "ON" ) { + if ( Test-Path "$projectRoot/packages/swig/swigwin-4.1.1" ) { + Write-Output "Found pre-existing copy of Swigwin 4.1.1 - using this binary" + } + else { + Write-Output "Swigwin 4.1.1 not found - downloading and unpacking..." + Remove-Item -LiteralPath $projectRoot/packages/swig/ -Force -Recurse -ErrorAction Ignore + Invoke-WebRequest 'https://deac-fra.dl.sourceforge.net/project/swig/swigwin/swigwin-4.1.1/swigwin-4.1.1.zip' -OutFile swig.zip + Expand-Archive swig.zip -DestinationPath $projectRoot/packages/swig + Remove-Item swig.zip + } +} + # build the cmake command flags from arguments $cmakeFlags = "-DCMAKE_BUILD_TYPE=$CONFIGURATION " + "-DENABLE_STDCXX_SYNC=$CXX11 " + "-DENABLE_APPS=$BUILD_APPS " + - "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + - "-DENABLE_BONDING=$BONDING " + - "-DENABLE_UNITTESTS=$UNIT_TESTS" + "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + + "-DENABLE_BONDING=$BONDING " + + "-DENABLE_UNITTESTS=$UNIT_TESTS " + + "-DENABLE_SWIG=$ENABLE_SWIG " + + "-DENABLE_SWIG_CSHARP=$ENABLE_SWIG_CSHARP" # if VCPKG is flagged to provide OpenSSL, checkout VCPKG and install package if ( $VCPKG_OPENSSL -eq 'ON' ) { @@ -229,6 +242,15 @@ if ( $null -eq $msBuildPath ) { & $msBuildPath SRT.sln -m /p:Configuration=$CONFIGURATION /p:Platform=$DEVENV_PLATFORM +# if CSharp SWIG is on, now trigger compilation of these elements (cmake for dotnet is very new, and not available in older versions) +if($ENABLE_SWIG_CSHARP){ + Push-Location "$buildDir/swig_bindings/csharp" + Copy-Item "$projectRoot/srtcore/swig_bindings/csharp/*.csproj" . + & dotnet build -c $CONFIGURATION + Copy-Item "bin/$CONFIGURATION/netstandard2.0/*.dll" "$buildDir/$CONFIGURATION" + Pop-Location +} + # return to the directory previously occupied before running the script Pop-Location diff --git a/scripts/create-win64-nuget.bat b/scripts/create-win64-nuget.bat new file mode 100644 index 000000000..de295bc1a --- /dev/null +++ b/scripts/create-win64-nuget.bat @@ -0,0 +1,29 @@ +rem Bundle CI NuGet package for VS2015 Win64 Release only build (true package should contain multi-arch composite output) +@echo off + +rem If running in AppVeyor, only create a NuGet package on VS2015 x64 Release +IF DEFINED APPVEYOR_BUILD_VERSION ( + IF "%PLATFORM%"=="x64" ( + IF "%VS_VERSION%"=="2015" ( + IF "%CONFIGURATION%"=="Release" ( + echo "Building NuPkg for this build (VS2015, x64 Release)" + nuget pack .\scripts\nuget\SrtSharp\SrtSharp.nuspec -version %APPVEYOR_BUILD_VERSION%-2015-beta + appveyor PushArtifact SrtSharp.%APPVEYOR_BUILD_VERSION%-2015-beta.nupkg + exit 0 + ) + ) + IF "%VS_VERSION%"=="2019" ( + IF "%CONFIGURATION%"=="Release" ( + echo "Building NuPkg for this build (VS2019, x64 Release)" + nuget pack .\scripts\nuget\SrtSharp\SrtSharp.nuspec -version %APPVEYOR_BUILD_VERSION%-beta + appveyor PushArtifact SrtSharp.%APPVEYOR_BUILD_VERSION%-beta.nupkg + exit 0 + ) + ) + ) + echo "Skipping NuPkg build (not VS2015/2019, x64 Release)" + exit 0 +) ELSE ( + rem probably running on a local workstation, so use the first given argument parameter as the version number and don't push or exit + nuget pack .\scripts\nuget\SrtSharp\SrtSharp.nuspec -version %1 +) \ No newline at end of file diff --git a/scripts/gather-package.bat b/scripts/gather-package.bat index a0221cc05..defce9d0d 100644 --- a/scripts/gather-package.bat +++ b/scripts/gather-package.bat @@ -18,9 +18,10 @@ md %APPVEYOR_BUILD_FOLDER%\package\lib IF "%GATHER_SSL_INTO_PACKAGE%"=="True" ( md %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM% ) +md %APPVEYOR_BUILD_FOLDER%\package\swig_bindings rem Gather SRT includes, binaries and libs -copy %APPVEYOR_BUILD_FOLDER%\version.h %APPVEYOR_BUILD_FOLDER%\package\include\ +copy %APPVEYOR_BUILD_FOLDER%\_build\version.h %APPVEYOR_BUILD_FOLDER%\package\include\ copy %APPVEYOR_BUILD_FOLDER%\srtcore\*.h %APPVEYOR_BUILD_FOLDER%\package\include\ copy %APPVEYOR_BUILD_FOLDER%\haicrypt\*.h %APPVEYOR_BUILD_FOLDER%\package\include\ copy %APPVEYOR_BUILD_FOLDER%\common\*.h %APPVEYOR_BUILD_FOLDER%\package\include\ @@ -28,10 +29,16 @@ copy %APPVEYOR_BUILD_FOLDER%\common\win\*.h %APPVEYOR_BUILD_FOLDER%\package\incl copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.exe %APPVEYOR_BUILD_FOLDER%\package\bin\ copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.dll %APPVEYOR_BUILD_FOLDER%\package\bin\ copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.lib %APPVEYOR_BUILD_FOLDER%\package\lib\ -copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.pdb %APPVEYOR_BUILD_FOLDER%\package\bin\ rem Gather 3rd party openssl elements IF "%GATHER_SSL_INTO_PACKAGE%"=="True" ( (robocopy c:\openssl-win%FOLDER_PLATFORM%\ %APPVEYOR_BUILD_FOLDER%\package\openssl-win%FOLDER_PLATFORM% /s /e /np) ^& IF %ERRORLEVEL% GTR 1 exit %ERRORLEVEL% ) +IF "%CONFIGURATION%"=="Debug" ( + copy %APPVEYOR_BUILD_FOLDER%\_build\%CONFIGURATION%\*.pdb %APPVEYOR_BUILD_FOLDER%\package\bin\ +) + +rem gather any generated bindings for languages +(robocopy %APPVEYOR_BUILD_FOLDER%\srtcore\swig_bindings\ %APPVEYOR_BUILD_FOLDER%\package\swig_bindings /s /e /np) ^& IF %ERRORLEVEL% GTR 1 exit %ERRORLEVEL% + exit 0 diff --git a/scripts/get-windows-build-packages.bat b/scripts/get-windows-build-packages.bat new file mode 100644 index 000000000..8685119a9 --- /dev/null +++ b/scripts/get-windows-build-packages.bat @@ -0,0 +1,2 @@ +@ECHO OFF +PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" \ No newline at end of file diff --git a/scripts/get-windows-build-packages.ps1 b/scripts/get-windows-build-packages.ps1 new file mode 100644 index 000000000..94717794a --- /dev/null +++ b/scripts/get-windows-build-packages.ps1 @@ -0,0 +1,6 @@ +#Script to grab external libraries for building these samples + +# prep shared variables +$DEVENV_PLATFORM = 'x64' # alternative is x86 +$FOLDER_PLATFORM = 'win64' # alternative is win32 +nuget install swigwintools -version 4.0.0 \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec new file mode 100644 index 000000000..b0fe1438c --- /dev/null +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -0,0 +1,29 @@ + + + + SrtSharp + SRT Library wrapped for C# + $version$-beta + Cinegy GmbH + Cinegy GmbH + MPL-2.0 + false + Secure, Reliable Transport Library with C# bindings, published by Cinegy GmbH + 2019 SRT Haivision Systems Inc (packaged by Cinegy GmbH). All rights reserved. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/build/SrtSharp.props b/scripts/nuget/SrtSharp/build/SrtSharp.props new file mode 100644 index 000000000..60c909ff5 --- /dev/null +++ b/scripts/nuget/SrtSharp/build/SrtSharp.props @@ -0,0 +1,23 @@ + + + + + $(MSBuildThisFileDirectory)\..\sources\;%(AdditionalIncludeDirectories) + + + $(MSBuildThisFileDirectory)\..\runtimes\win-$(PlatformTarget)\native\release;%(AdditionalLibraryDirectories) + cinecoder.lib;%(AdditionalDependencies) + + + $(MSBuildThisFileDirectory)\..\sources\interfaces;$(MSBuildThisFileDirectory)\..\sources\interfaces\Systems;%(AdditionalIncludeDirectories) + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/build/SrtSharp.targets b/scripts/nuget/SrtSharp/build/SrtSharp.targets new file mode 100644 index 000000000..974c15a19 --- /dev/null +++ b/scripts/nuget/SrtSharp/build/SrtSharp.targets @@ -0,0 +1,24 @@ + + + + True + False + + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/set-version-metadata.ps1 b/scripts/set-version-metadata.ps1 index 050838e5e..d1d5003a4 100644 --- a/scripts/set-version-metadata.ps1 +++ b/scripts/set-version-metadata.ps1 @@ -40,7 +40,7 @@ if($Env:TEAMCITY_VERSION){ #find C++ resource files and update file description with branch / commit details $FileDescriptionStringRegex = '(\bVALUE\s+\"FileDescription\"\s*\,\s*\")([^\"]*\\\")*[^\"]*(\")' -Get-ChildItem -Path "../srtcore/srt_shared.rc" | ForEach-Object { +Get-ChildItem -Path "$PSScriptRoot/../srtcore/srt_shared.rc" | ForEach-Object { $fileName = $_ Write-Output "Processing metadata changes for file: $fileName" diff --git a/srtcore/srt.h b/srtcore/srt.h index 9dd2149e8..ab6a6f6cb 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -60,6 +60,11 @@ written by #define SRT_API __attribute__ ((visibility("default"))) #endif +#ifdef SWIG + // Remove SRT_API definition when using SWIG + #undef SRT_API + #define SRT_API +#endif // For feature tests if you need. // You can use these constants with SRTO_MINVERSION option. diff --git a/srtcore/srt.i b/srtcore/srt.i new file mode 100644 index 000000000..b795890a7 --- /dev/null +++ b/srtcore/srt.i @@ -0,0 +1,107 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Lewis Kirkaldie - Cinegy GmbH + *****************************************************************************/ + +/* +Automatic generatation of bindings via SWIG (http://www.swig.org) +Install swig via the following (or use instructions from the link above): + sudo apt install swig / nuget install swigwintools +Generate the bindings using: + mkdir srtcore/bindings/csharp -p + swig -v -csharp -namespace SrtSharp -outdir ./srtcore/bindings/csharp/ ./srtcore/srt.i +You can now reference the SrtSharp lib in your .Net Core projects. Ensure the srtlib.so (or srt.dll / srt_swig_csharp.dll) is in the binary path of your .NetCore project. +*/ + +%module srt +%{ + #include "srt.h" +%} + +%include + +//push anything with an argument name 'buf' back to being an array (e.g. csharp defaults this type to string, which is not ideal here) +%apply unsigned char INOUT[] { char* buf} + +/// +/// C# related configration section, customizing binding for this language +/// + +// add top-level code to module file, which allows C# bindings of specific objects to be injected for easier use in C# + +%pragma(csharp) moduleimports=%{ +using System; +using System.Net; +using System.Runtime.InteropServices; + +// sockaddr_in layout in C# - for easier creation of socket object from C# code +[StructLayout(LayoutKind.Sequential)] +public struct sockaddr_in +{ + public short sin_family; + public ushort sin_port; + public uint sin_addr; + public long sin_zero; +}; + +public static class SocketHelper{ + public static SWIGTYPE_p_sockaddr CreateSocketAddress(string address, int port){ + var destination = IPAddress.Parse(address); + + var sin = new sockaddr_in() + { + sin_family = srt.AF_INET, + sin_port = (ushort)IPAddress.HostToNetworkOrder((short)port), +#pragma warning disable 618 + sin_addr = (uint)destination.Address, +#pragma warning restore 618 + sin_zero = 0 + }; + + var hnd = GCHandle.Alloc(sin, GCHandleType.Pinned); + + var socketAddress = new SWIGTYPE_p_sockaddr(hnd.AddrOfPinnedObject(), false); + + hnd.Free(); + + return socketAddress; + } +} +%} + +/// Rebind objects from the default mappings for types and objects that are optimized for C# + +//enums in C# are int by default, this override pushes this enum to the require uint format +%typemap(csbase) SRT_EPOLL_OPT "uint" + +//the SRT_ERRNO enum references itself another enum - we must import this other enum into the class file for resolution +%typemap(csimports) SRT_ERRNO %{ + + using static CodeMajor; + using static CodeMinor; + +%} + +SWIG_CSBODY_PROXY(public, public, SWIGTYPE) +SWIG_CSBODY_TYPEWRAPPER(public, public, public, SWIGTYPE) + +%typemap(ctype) SWIGTYPE "const struct sockaddr*" +%typemap(imtype, out="global::System.IntPtr") SWIGTYPE "global::System.Runtime.InteropServices.HandleRef" +%typemap(cstype) const struct sockaddr* "SWIGTYPE_p_sockaddr" + +// General interface definition of wrapper - due to above typemaps and code, we can now just reference the main srt.h file + +const short AF_INET = 2; + + +%include "srt.h"; \ No newline at end of file diff --git a/srtcore/swig_bindings/csharp/srtsharp.csproj b/srtcore/swig_bindings/csharp/srtsharp.csproj new file mode 100644 index 000000000..7ea99cbfe --- /dev/null +++ b/srtcore/swig_bindings/csharp/srtsharp.csproj @@ -0,0 +1,9 @@ + + + + netstandard2.0 + AnyCPU + true + + + From cee3a354e461e1e2854c2dd833a9ba1502d402fe Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Tue, 6 Dec 2022 17:54:50 +0000 Subject: [PATCH 02/29] Srt1.5.1 swig (#8) * -add swig bindings and wrapper for c# From e73b1199f59dc2a32b3ff7ae94bb551f0025f0c9 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Tue, 6 Dec 2022 18:09:38 +0000 Subject: [PATCH 03/29] -docker lin build now uses ubuntu 22.04 base -improve some comments in CMakeLists -default win swig back to OFF --- .appveyor.yml | 2 +- CMakeLists.txt | 3 ++- scripts/Dockerfile.linux | 4 ++-- scripts/build-windows.ps1 | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index d542ff506..697d398c4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -18,7 +18,7 @@ build_script: - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -ENABLE_SWIG ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } - - sh: ./scripts/build-lin-docker.ps1 + - sh: ./scripts/build-lin-docker.ps1 -ENABLE_SWIG ON test_script: - ps: if ( $Env:RUN_UNIT_TESTS ) { cd ./_build; ctest -E "TestIPv6.v6_calls_v4" --extra-verbose -C $Env:CONFIGURATION; cd ../ } diff --git a/CMakeLists.txt b/CMakeLists.txt index e3fa651f0..ad850bac4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1352,8 +1352,9 @@ if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.21) endif() -#experimental SWIG support for csharp - only enabled for Windows currently +#experimental SWIG support for csharp if(ENABLE_SWIG) + #on windows, there is no swig just in the path - nuget / scripted downloads must be pointed at (linux it just works) if(MICROSOFT) #if nuget has been used to install swig in the project packages, bind to that if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/packages/swig/swigwin-4.1.1/swig.exe") diff --git a/scripts/Dockerfile.linux b/scripts/Dockerfile.linux index eedaa5919..4fb9a00d7 100644 --- a/scripts/Dockerfile.linux +++ b/scripts/Dockerfile.linux @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 LABEL maintainer="Lewis Kirkaldie " @@ -21,7 +21,7 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \ #add powershell core & dotnet 6.0 RUN cd /tmp && \ - curl -o packages-microsoft-prod.deb https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -sS && \ + curl -o packages-microsoft-prod.deb https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -sS && \ dpkg -i packages-microsoft-prod.deb && \ rm packages-microsoft-prod.deb && \ apt-get update && \ diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index 1d25c9824..d3ad718fa 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -21,7 +21,7 @@ param ( [Parameter()][String]$BUILD_DIR = "_build", [Parameter()][String]$VCPKG_OPENSSL = "OFF", [Parameter()][String]$BONDING = "OFF", - [Parameter()][String]$ENABLE_SWIG = "ON", + [Parameter()][String]$ENABLE_SWIG = "OFF", [Parameter()][String]$ENABLE_SWIG_CSHARP = "ON" ) From 2ea30af3d553201f1ec231f0fcc7853856770f7e Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Thu, 8 Dec 2022 15:42:53 +0000 Subject: [PATCH 04/29] SWIG Linux improvements, C# type mapping fixes --- CMakeLists.txt | 5 ++++- scripts/Dockerfile.linux | 21 +++++++++---------- scripts/build-lin-docker.ps1 | 23 +++++++++++++-------- scripts/build-windows.ps1 | 9 ++++++++- scripts/create-nuget.ps1 | 28 ++++++++++++++++++++++++++ scripts/nuget/SrtSharp/SrtSharp.nuspec | 11 +++++----- srtcore/srt.i | 25 +++++++++++++++++++++-- 7 files changed, 93 insertions(+), 29 deletions(-) mode change 100755 => 100644 scripts/build-lin-docker.ps1 create mode 100644 scripts/create-nuget.ps1 diff --git a/CMakeLists.txt b/CMakeLists.txt index ad850bac4..513d952a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1351,7 +1351,6 @@ if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.21) cmake_policy(SET CMP0122 NEW) endif() - #experimental SWIG support for csharp if(ENABLE_SWIG) #on windows, there is no swig just in the path - nuget / scripted downloads must be pointed at (linux it just works) @@ -1364,6 +1363,10 @@ if(ENABLE_SWIG) FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) + + if(UNIX AND NOT APPLE) + list(APPEND CMAKE_SWIG_FLAGS "-DSWIGWORDSIZE64") + endif() if(ENABLE_SWIG_CSHARP) swig_add_library(srt_swig_csharp LANGUAGE csharp SOURCES srtcore/srt.i OUTPUT_DIR ${CMAKE_BINARY_DIR}/swig_bindings/csharp) diff --git a/scripts/Dockerfile.linux b/scripts/Dockerfile.linux index 4fb9a00d7..15c39eb30 100644 --- a/scripts/Dockerfile.linux +++ b/scripts/Dockerfile.linux @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM debian:bullseye LABEL maintainer="Lewis Kirkaldie " @@ -15,20 +15,17 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \ build-essential git nano gnupg apt-utils unzip sudo bzip2 \ apt-transport-https curl wget ca-certificates cpio \ libssl-dev software-properties-common \ - p7zip-full p7zip-rar swig && \ + p7zip-full swig && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -#add powershell core & dotnet 6.0 -RUN cd /tmp && \ - curl -o packages-microsoft-prod.deb https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -sS && \ - dpkg -i packages-microsoft-prod.deb && \ - rm packages-microsoft-prod.deb && \ - apt-get update && \ - apt-get install -y powershell && \ - apt-get install -y dotnet-sdk-6.0 && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* +# add powershell core & dotnet 6.0 +# RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ +# sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' && \ +# apt update && sudo apt install -y powershell && \ +# apt-get install -y dotnet-sdk-6.0 && \ +# apt-get clean && \ +# rm -rf /var/lib/apt/lists/* #add cmake 3.24.1 RUN mkdir -p /usr/src/cmake \ diff --git a/scripts/build-lin-docker.ps1 b/scripts/build-lin-docker.ps1 old mode 100755 new mode 100644 index 60dd0d6c7..3cacc7e36 --- a/scripts/build-lin-docker.ps1 +++ b/scripts/build-lin-docker.ps1 @@ -9,8 +9,9 @@ # encryption or unit tests enabled, but including test apps. ################################################################################ -param ( +param ( [Parameter()][String]$CONFIGURATION = "Release", + [Parameter()][String]$BUILDCONTAINER = "srtselfbuildcontainer", [Parameter()][String]$DEVENV_PLATFORM = "x64", [Parameter()][String]$ENABLE_ENCRYPTION = "OFF", [Parameter()][String]$STATIC_LINK_SSL = "OFF", @@ -18,16 +19,21 @@ param ( [Parameter()][String]$BUILD_APPS = "ON", [Parameter()][String]$UNIT_TESTS = "OFF", [Parameter()][String]$BUILD_DIR = "_build-linux", - [Parameter()][String]$ENABLE_SWIG = "OFF", + [Parameter()][String]$BONDING = "ON", + [Parameter()][String]$ENABLE_SWIG = "ON", [Parameter()][String]$ENABLE_SWIG_CSHARP = "ON" ) $projectRoot = Join-Path $PSScriptRoot "/.." -Resolve -# generate command to make sure an up-to-date docker container (for compiling within) is built -$execVar = "docker build -t srtbuildcontainer:latest -f $($projectRoot)/scripts/Dockerfile.linux ." -Write-Output $execVar -Invoke-Expression "& $execVar" +if($BUILDCONTAINER -eq "srtselfbuildcontainer") { + # the default build container name was passed - so rebuild this self-contained build environment first + # on a CI system, there may be a known-suitable build container already existing, so this can speed up builds + # but if this is on default, we can just self-serve + $execVar = "docker build -t $BUILDCONTAINER -f $($projectRoot)/scripts/Dockerfile.linux ." + Write-Output $execVar + Invoke-Expression "& $execVar" +} # clear any previous build and create & enter the build directory $buildDir = Join-Path "$projectRoot" "$BUILD_DIR" @@ -41,15 +47,16 @@ $cmakeFlags = "-DCMAKE_BUILD_TYPE=$CONFIGURATION " + "-DENABLE_APPS=$BUILD_APPS " + "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + "-DENABLE_UNITTESTS=$UNIT_TESTS " + + "-DENABLE_BONDING=$BONDING " + "-DENABLE_SWIG=$ENABLE_SWIG " + "-DENABLE_SWIG_CSHARP=$ENABLE_SWIG_CSHARP" # generate command for docker run of cmake generation step -$execVar = "docker run --rm -v $($projectRoot):/srt -w /srt/$BUILD_DIR srtbuildcontainer:latest cmake -S ../ $cmakeFlags" +$execVar = "docker run --rm -v $($projectRoot):/srt -w /srt/$BUILD_DIR $BUILDCONTAINER cmake -S ../ $cmakeFlags" Write-Output $execVar Invoke-Expression "& $execVar" # generate command for docker run of cmake build -$execVar = "docker run --rm -v $($projectRoot):/srt -w /srt/$BUILD_DIR srtbuildcontainer:latest cmake --build ./" +$execVar = "docker run --rm -v $($projectRoot):/srt -w /srt/$BUILD_DIR $BUILDCONTAINER cmake --build ./" Write-Output $execVar Invoke-Expression "& $execVar" diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index d3ad718fa..d2536ec85 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -56,6 +56,13 @@ if ( $Env:APPVEYOR ) { Copy-Item -Path "C:\OpenSSL-v111-Win64" "C:\OpenSSL-Win64" -Recurse | Out-Null } +# if running within TeamCity, force SWIG and BONDING to ON (to avoid changing default behaviour on pre-existing CI systems) +# this should be removable ones master branch is merged to always have these params available (so CI can set them reliably itself) +if($Env:TEAMCITY_VERSION){ + $ENABLE_SWIG = "ON" + $BONDING = "ON" +} + # persist VS_VERSION so it can be used in an artifact name later $Env:VS_VERSION = $VS_VERSION @@ -243,7 +250,7 @@ if ( $null -eq $msBuildPath ) { & $msBuildPath SRT.sln -m /p:Configuration=$CONFIGURATION /p:Platform=$DEVENV_PLATFORM # if CSharp SWIG is on, now trigger compilation of these elements (cmake for dotnet is very new, and not available in older versions) -if($ENABLE_SWIG_CSHARP){ +if(($ENABLE_SWIG -eq "ON") -and ($ENABLE_SWIG_CSHARP -eq "ON")){ Push-Location "$buildDir/swig_bindings/csharp" Copy-Item "$projectRoot/srtcore/swig_bindings/csharp/*.csproj" . & dotnet build -c $CONFIGURATION diff --git a/scripts/create-nuget.ps1 b/scripts/create-nuget.ps1 new file mode 100644 index 000000000..f27e2d256 --- /dev/null +++ b/scripts/create-nuget.ps1 @@ -0,0 +1,28 @@ +################################################################################ +# Windows SRT NuGet Package Creation Script +#============================ +# Usable on a Windows PC with Powershell and nuget available, +# or called by CI systems like AppVeyor +# +################################################################################ + +param ( + [Parameter()][String]$PACKAGEFOLDER = "package", + [Parameter()][String]$VERSION = "1.5.1.0" +) + +# make all errors trigger a script stop, rather than just carry on +$ErrorActionPreference = "Stop" + +$packageDir = Join-Path $PSScriptRoot "../" $PACKAGEFOLDER -Resolve + +Get-ChildItem $packageDir -Filter *.zip | Foreach-Object { + Expand-Archive -Force -Path $_.FullName -DestinationPath $(Join-Path $packageDir "extracted") +} + +nuget pack .\nuget\SrtSharp\SrtSharp.nuspec -version $VERSION + +# if antyhing returned non-zero, throw to cause failure in CI +if( $LASTEXITCODE -ne 0 ) { + throw +} diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec index b0fe1438c..f21478dcb 100644 --- a/scripts/nuget/SrtSharp/SrtSharp.nuspec +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -16,13 +16,14 @@ - + + - + + + - - - + diff --git a/srtcore/srt.i b/srtcore/srt.i index b795890a7..ab3f039ee 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -16,7 +16,7 @@ written by /* Automatic generatation of bindings via SWIG (http://www.swig.org) Install swig via the following (or use instructions from the link above): - sudo apt install swig / nuget install swigwintools + sudo apt install swig / nuget install swigwintools / download latest from swig.org Generate the bindings using: mkdir srtcore/bindings/csharp -p swig -v -csharp -namespace SrtSharp -outdir ./srtcore/bindings/csharp/ ./srtcore/srt.i @@ -29,12 +29,33 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %} %include +%include "stdint.i" +%include "typemaps.i" + +#if defined(SWIGCSHARP) //push anything with an argument name 'buf' back to being an array (e.g. csharp defaults this type to string, which is not ideal here) %apply unsigned char INOUT[] { char* buf} +#if defined(SWIGWORDSIZE64) +%define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE) +%clear NEW_TYPE; +%clear NEW_TYPE *; +%clear NEW_TYPE &; +%clear const NEW_TYPE &; +%apply TYPE { NEW_TYPE }; +%apply TYPE * { NEW_TYPE * }; +%apply TYPE & { NEW_TYPE & }; +%apply const TYPE & { const NEW_TYPE & }; +%enddef // PRIMITIVE_TYPEMAP +PRIMITIVE_TYPEMAP(long int, long long); +PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long); +#undef PRIMITIVE_TYPEMAP +#endif // defined(SWIGWORDSIZE64) +#endif // defined(SWIGCSHARP) + /// -/// C# related configration section, customizing binding for this language +/// C# related configuration section, customizing binding for this language /// // add top-level code to module file, which allows C# bindings of specific objects to be injected for easier use in C# From 31918626ca6d468a0cd7e1dc31e008493493daff Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 25 Feb 2023 19:58:37 +0200 Subject: [PATCH 05/29] Scripts update SWIG definition updates --- scripts/build-windows.ps1 | 26 +- scripts/nuget/SrtSharp/SrtSharp.nuspec | 5 +- scripts/nuget/SrtSharp/build/SrtSharp.targets | 9 - srtcore/srt.i | 544 ++++++++++++++++-- 4 files changed, 500 insertions(+), 84 deletions(-) diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index d2536ec85..4fd95868b 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -4,13 +4,13 @@ # Usable on a Windows PC with Powershell and Visual studio, # or called by CI systems like AppVeyor # -# By default produces a VS2019 64-bit Release binary using C++11 threads, without +# By default produces a VS2022 64-bit Release binary using C++11 threads, without # encryption or unit tests enabled, but including test apps. # Before enabling any encryption options, install OpenSSL or set VCKPG flag to build ################################################################################ param ( - [Parameter()][String]$VS_VERSION = "2019", + [Parameter()][String]$VS_VERSION = "2022", [Parameter()][String]$CONFIGURATION = "Release", [Parameter()][String]$DEVENV_PLATFORM = "x64", [Parameter()][String]$ENABLE_ENCRYPTION = "OFF", @@ -21,7 +21,7 @@ param ( [Parameter()][String]$BUILD_DIR = "_build", [Parameter()][String]$VCPKG_OPENSSL = "OFF", [Parameter()][String]$BONDING = "OFF", - [Parameter()][String]$ENABLE_SWIG = "OFF", + [Parameter()][String]$ENABLE_SWIG = "ON", [Parameter()][String]$ENABLE_SWIG_CSHARP = "ON" ) @@ -38,6 +38,7 @@ $projectRoot = Join-Path $PSScriptRoot "/.." -Resolve # if running within AppVeyor, use environment variables to set params instead of passed-in values if ( $Env:APPVEYOR ) { if ( $Env:PLATFORM -eq 'x86' ) { $DEVENV_PLATFORM = 'Win32' } else { $DEVENV_PLATFORM = 'x64' } + if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2022' ) { $VS_VERSION='2022' } if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2019' ) { $VS_VERSION='2019' } if ( $Env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2015' ) { $VS_VERSION='2015' } @@ -67,6 +68,7 @@ if($Env:TEAMCITY_VERSION){ $Env:VS_VERSION = $VS_VERSION # select the appropriate cmake generator string given the environment +if ( $VS_VERSION -eq '2022' ) { $CMAKE_GENERATOR = 'Visual Studio 17 2022'; $MSBUILDVER = "17.0"; } if ( $VS_VERSION -eq '2019' ) { $CMAKE_GENERATOR = 'Visual Studio 16 2019'; $MSBUILDVER = "16.0"; } if ( $VS_VERSION -eq '2015' -and $DEVENV_PLATFORM -eq 'Win32' ) { $CMAKE_GENERATOR = 'Visual Studio 14 2015'; $MSBUILDVER = "14.0"; } if ( $VS_VERSION -eq '2015' -and $DEVENV_PLATFORM -eq 'x64' ) { $CMAKE_GENERATOR = 'Visual Studio 14 2015 Win64'; $MSBUILDVER = "14.0"; } @@ -152,13 +154,13 @@ if ( $ENABLE_SWIG -eq "ON" ) { # build the cmake command flags from arguments $cmakeFlags = "-DCMAKE_BUILD_TYPE=$CONFIGURATION " + - "-DENABLE_STDCXX_SYNC=$CXX11 " + - "-DENABLE_APPS=$BUILD_APPS " + - "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + - "-DENABLE_BONDING=$BONDING " + - "-DENABLE_UNITTESTS=$UNIT_TESTS " + - "-DENABLE_SWIG=$ENABLE_SWIG " + - "-DENABLE_SWIG_CSHARP=$ENABLE_SWIG_CSHARP" + "-DENABLE_STDCXX_SYNC=$CXX11 " + + "-DENABLE_APPS=$BUILD_APPS " + + "-DENABLE_ENCRYPTION=$ENABLE_ENCRYPTION " + + "-DENABLE_BONDING=$BONDING " + + "-DENABLE_UNITTESTS=$UNIT_TESTS " + + "-DENABLE_SWIG=$ENABLE_SWIG " + + "-DENABLE_SWIG_CSHARP=$ENABLE_SWIG_CSHARP" # if VCPKG is flagged to provide OpenSSL, checkout VCPKG and install package if ( $VCPKG_OPENSSL -eq 'ON' ) { @@ -201,8 +203,8 @@ else { $cmakeFlags += " -DOPENSSL_USE_STATIC_LIBS=$STATIC_LINK_SSL " } -# cmake uses a flag for architecture from vs2019, so add that as a suffix -if ( $VS_VERSION -eq '2019' ) { +# cmake uses a flag for architecture from vs2022, so add that as a suffix +if ( $VS_VERSION -eq '2019' -or $VS_VERSION -eq '2022') { $cmakeFlags += " -A `"$DEVENV_PLATFORM`"" } diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec index f21478dcb..98ea332cf 100644 --- a/scripts/nuget/SrtSharp/SrtSharp.nuspec +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -18,13 +18,10 @@ - + - - - \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/build/SrtSharp.targets b/scripts/nuget/SrtSharp/build/SrtSharp.targets index 974c15a19..9ec270d9d 100644 --- a/scripts/nuget/SrtSharp/build/SrtSharp.targets +++ b/scripts/nuget/SrtSharp/build/SrtSharp.targets @@ -4,15 +4,6 @@ True False - - diff --git a/srtcore/srt.i b/srtcore/srt.i index ab3f039ee..11b486c93 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -29,13 +29,220 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %} %include -%include "stdint.i" -%include "typemaps.i" - +%include +%include #if defined(SWIGCSHARP) -//push anything with an argument name 'buf' back to being an array (e.g. csharp defaults this type to string, which is not ideal here) -%apply unsigned char INOUT[] { char* buf} +// Push anything with an argument name 'buf' back to being an array (e.g. csharp defaults this type to string, which is not ideal here) +%apply unsigned char INOUT[] { + char* buf, + const char* buf + } + +%apply int INOUT[] { const SRTSOCKET listeners[]} +%apply int INOUT[] { const int* fara} + +// Marshal Pointers to IntPtr +%apply void *VOID_INT_PTR { + void *, + SRT_LOG_HANDLER_FN *, // Delegate + srt_listen_callback_fn*, // Delegate + srt_connect_callback_fn*, // Delegate + int *, + byte *, + size_t *, + int64_t *, + SRT_SOCKOPT_CONFIG* + } + +// REF int mapping +%typemap(cstype) int * "ref int" +%typemap(csin, + pre=" var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", + post=" pin_$csinput.Free();" + ) int * + "pin_$csinput.AddrOfPinnedObject()" + +// REF size_t mapping +%typemap(cstype) size_t * "ref ulong" +%typemap(csin, + pre=" var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", + post=" pin_$csinput.Free();" + ) size_t * + "pin_$csinput.AddrOfPinnedObject()" + +// ---- OVERRIDE SIGNATURE (struct sockaddr* addr, int* addrlen) +%typemap(in) (struct sockaddr*, int*) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = args->Arg2; +} +%typemap(cstype) (struct sockaddr*, int*) "out IPEndPoint" +%typemap(imtype) (struct sockaddr*, int*) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var sock_$csinput = new SocketAddress(AddressFamily.InterNetwork); + var content_$csinput = sock_$csinput.GetInternalBuffer(); + int content_len_$csinput = sock_$csinput.Size; + var pin_content_$csinput = GCHandle.Alloc(content_$csinput, GCHandleType.Pinned); + var pin_content_len_$csinput = GCHandle.Alloc(content_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_content_$csinput.AddrOfPinnedObject(), + Arg2 = pin_content_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + sock_$csinput.SetInternalSize(content_len_$csinput); + $csinput = sock_$csinput.ToIPEndPoint(); + pin_content_$csinput.Free(); + pin_content_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (struct sockaddr*, int*) + "input_$csinput" + +// Apply mappings for different functions with the same signature (struct sockaddr*, int*) +%apply (struct sockaddr*, int*) +{ + (struct sockaddr* addr, int* addrlen), + (struct sockaddr* name, int* namelen) +} + +// ---- OVERRIDE SIGNATURE (const struct sockaddr addr, int addrlen) +%typemap(in) (const struct sockaddr*, int) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = *args->Arg2; +} +%typemap(cstype) (const struct sockaddr*, int) "IPEndPoint" +%typemap(imtype) (const struct sockaddr*, int) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var sock_$csinput = $csinput.Serialize(); + var content_$csinput = sock_$csinput.GetInternalBuffer(); + int content_len_$csinput = sock_$csinput.Size; + var pin_content_$csinput = GCHandle.Alloc(content_$csinput, GCHandleType.Pinned); + var pin_content_len_$csinput = GCHandle.Alloc(content_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_content_$csinput.AddrOfPinnedObject(), + Arg2 = pin_content_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_content_$csinput.Free(); + pin_content_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (const struct sockaddr*, int) + "input_$csinput" + +// Apply mappings for different functions with the same signature (const struct sockaddr*, int) +%apply (const struct sockaddr*, int) +{ + (const struct sockaddr* name, int namelen), + (const struct sockaddr* local_name, int local_namelen), + (const struct sockaddr* remote_name, int remote_namelen), + (const struct sockaddr* target, int len), + (const struct sockaddr* adr, int namelen) +} + +// ---- OVERRIDE SIGNATURE (const struct sockaddr* /*nullable*/) +%typemap(cstype) (const struct sockaddr*) "IPEndPoint" +%typemap(imtype) (const struct sockaddr*) "global::System.IntPtr" +%typemap(csin, + pre=" + var input_$csinput = IntPtr.Zero; + GCHandle? pin_content_$csinput = null; + if($csinput != null) + { + var sock_$csinput = $csinput.Serialize(); + var content_$csinput = sock_$csinput.GetInternalBuffer(); + pin_content_$csinput = GCHandle.Alloc(content_$csinput, GCHandleType.Pinned); + input_$csinput = pin_content_$csinput.Value.AddrOfPinnedObject(); + }", + post=" + pin_content_$csinput?.Free();" + ) (const struct sockaddr*) + "input_$csinput" + +// REF int64_t mapping +%typemap(cstype) (int64_t *) "ref long" +%typemap(csin, + pre=" var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", + post=" pin_$csinput.Free();" + ) int64_t * + "pin_$csinput.AddrOfPinnedObject()" + +%typemap(cstype) (SRT_LOG_HANDLER_FN *) "SrtLogHandlerDelegate" +%typemap(csin, + pre=" GCKeeper.Keep(nameof(SrtLogHandlerDelegate), $csinput);var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);") SRT_LOG_HANDLER_FN* + "delegatePtr_$csinput" + +%typemap(cstype) (srt_listen_callback_fn *) "SrtListenCallbackDelegate" +%typemap(csin, + pre=" GCKeeper.Keep(nameof(SrtListenCallbackDelegate), $csinput);var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" + ) srt_listen_callback_fn* + "delegatePtr_$csinput" + +%typemap(cstype) (srt_connect_callback_fn *) "SrtConnectCallbackDelegate" +%typemap(csin, + pre=" GCKeeper.Keep(nameof(SrtConnectCallbackDelegate), $csinput);var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" + ) srt_connect_callback_fn* + "delegatePtr_$csinput" + +%typemap(cstype) (const int* events) "SRT_EPOLL_OPT?" +%typemap(csin, + pre=" + GCHandle? pin_$csinput = null; + IntPtr pinAddr_$csinput = IntPtr.Zero; + if($csinput.HasValue) + { + uint opt_$csinput = (uint)$csinput.Value; + pin_$csinput = GCHandle.Alloc(opt_$csinput, GCHandleType.Pinned); + pinAddr_$csinput = pin_$csinput.Value.AddrOfPinnedObject(); + } + ", + post=" + pin_$csinput?.Free(); + " + ) const int* events + "pinAddr_$csinput" + +/* ------------------------ NOT READY YET +// ---- OVERRIDE SIGNATURE (SRT_SOCKOPT opt, void* string_val, int* string_len) +%typemap(in) (SRT_SOCKOPT opt, void* string_val, int* string_len) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = (SRT_SOCKOPT)(*args->Arg1); + $2 = args->Arg2; + $3 = args->Arg3; +} +%typemap(cstype) (SRT_SOCKOPT opt, void* string_val, int* string_len) "SRT_SOCKOPT" +%typemap(imtype) (SRT_SOCKOPT opt, void* string_val, int* string_len) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var sock_$csinput = $csinput.Serialize(); + var content_$csinput = sock_$csinput.GetInternalBuffer(); + int content_len_$csinput = sock_$csinput.Size; + var pin_content_$csinput = GCHandle.Alloc(content_$csinput, GCHandleType.Pinned); + var pin_content_len_$csinput = GCHandle.Alloc(content_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_content_$csinput.AddrOfPinnedObject(), + Arg2 = pin_content_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_content_$csinput.Free(); + pin_content_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (SRT_SOCKOPT opt, void* string_val, int* string_len) + "input_$csinput" + +%typemap(cstype) int srt_getsockflag_string() "string" +------------------------ NOT READY YET */ #if defined(SWIGWORDSIZE64) %define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE) @@ -54,75 +261,294 @@ PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long); #endif // defined(SWIGWORDSIZE64) #endif // defined(SWIGCSHARP) -/// -/// C# related configuration section, customizing binding for this language -/// +// +// C# related configuration section, customizing binding for this language +// +// Rebind objects from the default mappings for types and objects that are optimized for C# +//enums in C# are int by default, this override pushes this enum to the require uint format +%typemap(csbase) SRT_EPOLL_OPT "uint" +%typemap(csattributes) SRT_EPOLL_OPT "[System.Flags]" + +//the SRT_ERRNO enum references itself another enum - we must import this other enum into the class file for resolution +%typemap(csimports) SRT_ERRNO %{ + using static CodeMajor; + using static CodeMinor; +%} + +%typemap(csimports) SRT_STRING_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%typemap(csimports) SRT_BOOL_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%typemap(csimports) SRT_INT_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%typemap(csimports) SRT_LONG_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%rename(SRT_TRACEBSTATS) CBytePerfMon; + +// Ignore deprecated methods +%ignore srt_rejectreason_msg; + +// General interface definition of wrapper - due to above typemaps and code, we can now just reference the main srt.h file +%include "srt.h"; + +// C additional definitions +%inline{ + +typedef struct +{ + byte *Arg1; + byte *Arg2; + byte *Arg3; + byte *Arg4; + byte *Arg5; + byte *Arg6; +} TransitiveArguments; + +typedef enum +{ + SRTO_STRING_BINDTODEVICE = SRTO_BINDTODEVICE, + SRTO_STRING_CONGESTION = SRTO_CONGESTION, + SRTO_STRING_PACKETFILTER = SRTO_PACKETFILTER, + SRTO_STRING_PASSPHRASE = SRTO_PASSPHRASE, + SRTO_STRING_STREAMID = SRTO_STREAMID, +}SRT_STRING_SOCKOPT; + +typedef enum +{ + SRTO_LONG_INPUTBW = SRTO_INPUTBW, + SRTO_LONG_MAXBW = SRTO_MAXBW, + SRTO_LONG_MININPUTBW = SRTO_MININPUTBW, +}SRT_LONG_SOCKOPT; + +typedef enum +{ + SRTO_BOOL_DRIFTTRACER = SRTO_DRIFTTRACER, + SRTO_BOOL_ENFORCEDENCRYPTION = SRTO_ENFORCEDENCRYPTION, + SRTO_BOOL_MESSAGEAPI = SRTO_MESSAGEAPI, + SRTO_BOOL_NAKREPORT = SRTO_NAKREPORT, + SRTO_BOOL_RCVSYN = SRTO_RCVSYN, + SRTO_BOOL_RENDEZVOUS = SRTO_RENDEZVOUS, + SRTO_BOOL_REUSEADDR = SRTO_REUSEADDR, + SRTO_BOOL_SENDER = SRTO_SENDER, + SRTO_BOOL_SNDSYN = SRTO_SNDSYN, + SRTO_BOOL_TLPKTDROP = SRTO_TLPKTDROP, + SRTO_BOOL_TSBPDMODE = SRTO_TSBPDMODE +}SRT_BOOL_SOCKOPT; + +typedef enum +{ + SRTO_INT_CONNTIMEO = SRTO_CONNTIMEO, + SRTO_INT_CRYPTOMODE = SRTO_CRYPTOMODE, + SRTO_INT_EVENT = SRTO_EVENT, + SRTO_INT_FC = SRTO_FC, + SRTO_INT_GROUPCONNECT = SRTO_GROUPCONNECT, + SRTO_INT_GROUPMINSTABLETIMEO = SRTO_GROUPMINSTABLETIMEO, + SRTO_INT_GROUPTYPE = SRTO_GROUPTYPE, + SRTO_INT_IPTOS = SRTO_IPTOS, + SRTO_INT_IPTTL = SRTO_IPTTL, + SRTO_INT_IPV6ONLY = SRTO_IPV6ONLY, + SRTO_INT_ISN = SRTO_ISN, + SRTO_INT_KMPREANNOUNCE = SRTO_KMPREANNOUNCE, + SRTO_INT_KMREFRESHRATE = SRTO_KMREFRESHRATE, + SRTO_INT_KMSTATE = SRTO_KMSTATE, + SRTO_INT_LATENCY = SRTO_LATENCY, + SRTO_INT_LOSSMAXTTL = SRTO_LOSSMAXTTL, + SRTO_INT_MINVERSION = SRTO_MINVERSION, + SRTO_INT_MSS = SRTO_MSS, + SRTO_INT_OHEADBW = SRTO_OHEADBW, + SRTO_INT_PAYLOADSIZE = SRTO_PAYLOADSIZE, + SRTO_INT_PBKEYLEN = SRTO_PBKEYLEN, + SRTO_INT_PEERIDLETIMEO = SRTO_PEERIDLETIMEO, + SRTO_INT_PEERLATENCY = SRTO_PEERLATENCY, + SRTO_INT_PEERVERSION = SRTO_PEERVERSION, + SRTO_INT_RCVBUF = SRTO_RCVBUF, + SRTO_INT_RCVDATA = SRTO_RCVDATA, + SRTO_INT_RCVKMSTATE = SRTO_RCVKMSTATE, + SRTO_INT_RCVLATENCY = SRTO_RCVLATENCY, + SRTO_INT_RCVTIMEO = SRTO_RCVTIMEO, + SRTO_INT_RETRANSMITALGO = SRTO_RETRANSMITALGO, + SRTO_INT_SNDBUF = SRTO_SNDBUF, + SRTO_INT_SNDDATA = SRTO_SNDDATA, + SRTO_INT_SNDDROPDELAY = SRTO_SNDDROPDELAY, + SRTO_INT_SNDKMSTATE = SRTO_SNDKMSTATE, + SRTO_INT_SNDTIMEO = SRTO_SNDTIMEO, + SRTO_INT_STATE = SRTO_STATE, + SRTO_INT_TRANSTYPE = SRTO_TRANSTYPE, + SRTO_INT_UDP_RCVBUF = SRTO_UDP_RCVBUF, + SRTO_INT_UDP_SNDBUF = SRTO_UDP_SNDBUF, + SRTO_INT_VERSION = SRTO_VERSION, +}SRT_INT_SOCKOPT; + +int srt_getsockflag_string(SRTSOCKET u, SRT_STRING_SOCKOPT opt, void* string_val, int* string_len) +{ + return srt_getsockflag(u, opt, string_val, string_len); +} + +int srt_getsockflag_bool(SRTSOCKET u, SRT_BOOL_SOCKOPT opt, void* string_val, int* string_len) +{ + return srt_getsockflag(u, opt, string_val, string_len); +} -// add top-level code to module file, which allows C# bindings of specific objects to be injected for easier use in C# +int srt_getsockflag_int(SRTSOCKET u, SRT_INT_SOCKOPT opt, void* string_val, int* string_len) +{ + return srt_getsockflag(u, opt, string_val, string_len); +} + +int srt_getsockflag_long(SRTSOCKET u, SRT_LONG_SOCKOPT opt, void* string_val, int* string_len) +{ + return srt_getsockflag(u, opt, string_val, string_len); +} +} + +// add top-level code to module file +// which allows C# bindings of specific objects to be injected for easier use in C# %pragma(csharp) moduleimports=%{ + using System; using System.Net; +using System.Net.Sockets; using System.Runtime.InteropServices; +using System.Reflection; +using System.Collections.Concurrent; +using static SrtSharp.SRT_SOCKOPT; -// sockaddr_in layout in C# - for easier creation of socket object from C# code -[StructLayout(LayoutKind.Sequential)] -public struct sockaddr_in -{ - public short sin_family; - public ushort sin_port; - public uint sin_addr; - public long sin_zero; -}; - -public static class SocketHelper{ - public static SWIGTYPE_p_sockaddr CreateSocketAddress(string address, int port){ - var destination = IPAddress.Parse(address); - - var sin = new sockaddr_in() - { - sin_family = srt.AF_INET, - sin_port = (ushort)IPAddress.HostToNetworkOrder((short)port), -#pragma warning disable 618 - sin_addr = (uint)destination.Address, -#pragma warning restore 618 - sin_zero = 0 - }; - - var hnd = GCHandle.Alloc(sin, GCHandleType.Pinned); - - var socketAddress = new SWIGTYPE_p_sockaddr(hnd.AddrOfPinnedObject(), false); - - hnd.Free(); - - return socketAddress; - } -} -%} +/// +/// Delegate which is used for logger callbacks +/// +/// Custom parameter +/// Log level +/// File name +/// Line number +/// Log area name +/// Message +public delegate void SrtLogHandlerDelegate(IntPtr opaque, int level, string file, int line, string area, string message); -/// Rebind objects from the default mappings for types and objects that are optimized for C# +/// +/// Callback hook delegate, which will be executed on a socket that is automatically created to handle the incoming connection on the listening socket (and is about to be returned by srt_accept), but before the connection has been accepted. +/// +/// The pointer passed as hook_opaque when registering +/// The freshly created socket to handle the incoming connection +/// The handshake version (usually 5, pre-1.3 versions of SRT use 4) +/// The address of the incoming connection +/// The value set to SRTO_STREAMID option set on the peer side +public delegate void SrtListenCallbackDelegate( + IntPtr opaque, + int ns, + int hsVersion, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SockAddrMarshaler))]IPEndPoint peerAddress, + string streamId); -//enums in C# are int by default, this override pushes this enum to the require uint format -%typemap(csbase) SRT_EPOLL_OPT "uint" +/// +/// Callback hook delegate, which will be executed on a given u socket or all member sockets of a u group, just after a pending connection in the background has been resolved and the connection has failed. Note that this function is not guaranteed to be called if the u socket is set to blocking mode (SRTO_RCVSYN option set to true). It is guaranteed to be called when a socket is in non-blocking mode, or when you use a group. +/// +/// The pointer passed as hook_opaque when registering +/// The socket for which the connection process was resolved +/// The error code, same as for srt_connect for blocking mode +/// The target address passed to srt_connect call +/// The token value, if it was used for group connection, otherwise -1 +public delegate void SrtConnectCallbackDelegate( + IntPtr opaque, + int ns, + int errorCode, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SockAddrMarshaler))]IPEndPoint peerAddress, + int token); -//the SRT_ERRNO enum references itself another enum - we must import this other enum into the class file for resolution -%typemap(csimports) SRT_ERRNO %{ +internal static class MarshalExtensions +{ + private static readonly FieldInfo SocketAddressBufferField = typeof(SocketAddress).GetField("Buffer", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly FieldInfo SocketAddressInternalSizeField = typeof(SocketAddress).GetField("InternalSize", BindingFlags.Instance | BindingFlags.NonPublic); - using static CodeMajor; - using static CodeMinor; + internal static byte[] GetInternalBuffer(this SocketAddress socketAddress) + { + return (byte[])SocketAddressBufferField.GetValue(socketAddress); + } + + internal static void SetInternalSize(this SocketAddress socketAddress, int size) + { + SocketAddressInternalSizeField.SetValue(socketAddress, size); + } + + internal static IPEndPoint ToIPEndPoint(this SocketAddress socketAddress) + { + IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); + return (IPEndPoint)endPoint.Create(socketAddress); + } +} -%} +internal class SockAddrMarshaler : ICustomMarshaler +{ + public void CleanUpManagedData(object managedObj) + { + //Nothing GC will clean up managed object + } -SWIG_CSBODY_PROXY(public, public, SWIGTYPE) -SWIG_CSBODY_TYPEWRAPPER(public, public, public, SWIGTYPE) + public void CleanUpNativeData(IntPtr pNativeData) + { + //Nothing + } -%typemap(ctype) SWIGTYPE "const struct sockaddr*" -%typemap(imtype, out="global::System.IntPtr") SWIGTYPE "global::System.Runtime.InteropServices.HandleRef" -%typemap(cstype) const struct sockaddr* "SWIGTYPE_p_sockaddr" + public int GetNativeDataSize() + { + return -1; + } -// General interface definition of wrapper - due to above typemaps and code, we can now just reference the main srt.h file + public IntPtr MarshalManagedToNative(object managedObj) + { + // We do not support C# to C conversation + throw new NotSupportedException(); + } + + const int DATA_OFFSET = 2; -const short AF_INET = 2; + public object MarshalNativeToManaged(IntPtr pNativeData) + { + var family = Marshal.ReadInt16(pNativeData); + var dataPointer = pNativeData + DATA_OFFSET; + var socketAddress = new SocketAddress((AddressFamily) family, 16) + { + // Swap port bytes + [DATA_OFFSET + 0] = Marshal.ReadByte(dataPointer + 1), + [DATA_OFFSET + 1] = Marshal.ReadByte(dataPointer), + // Copy address bytes + [DATA_OFFSET + 2] = Marshal.ReadByte(dataPointer + 2), + [DATA_OFFSET + 3] = Marshal.ReadByte(dataPointer + 3), + [DATA_OFFSET + 4] = Marshal.ReadByte(dataPointer + 4), + [DATA_OFFSET + 5] = Marshal.ReadByte(dataPointer + 5), + [DATA_OFFSET + 6] = Marshal.ReadByte(dataPointer + 6), + [DATA_OFFSET + 7] = Marshal.ReadByte(dataPointer + 7), + [DATA_OFFSET + 8] = Marshal.ReadByte(dataPointer + 8), + [DATA_OFFSET + 9] = Marshal.ReadByte(dataPointer + 9), + [DATA_OFFSET + 10] = Marshal.ReadByte(dataPointer + 10), + [DATA_OFFSET + 11] = Marshal.ReadByte(dataPointer + 11), + [DATA_OFFSET + 12] = Marshal.ReadByte(dataPointer + 12), + [DATA_OFFSET + 13] = Marshal.ReadByte(dataPointer + 13), + }; + + var endPoint = new IPEndPoint(IPAddress.Any, 0); + return (IPEndPoint)endPoint.Create(socketAddress); + } +} +static class GCKeeper +{ + private static readonly ConcurrentDictionary _registry = new ConcurrentDictionary(); + public static void Keep(string name, object value) + { + _registry.AddOrUpdate(name, value, (key, existen) => value); + } + public static void Forget(string name) + { + _registry.TryRemove(name, out _); + } +} -%include "srt.h"; \ No newline at end of file +%} \ No newline at end of file From 7971f28bf4545f3bc92b7f0688452d0c5fbed186 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Sun, 26 Feb 2023 11:21:27 +0000 Subject: [PATCH 06/29] -swig off by default (breaks older CI builds) -set execution bit on build_lin script (CI problem) --- googletest/googletest-src | 1 + scripts/build-lin-docker.ps1 | 0 scripts/build-windows.ps1 | 4 ++-- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 160000 googletest/googletest-src mode change 100644 => 100755 scripts/build-lin-docker.ps1 diff --git a/googletest/googletest-src b/googletest/googletest-src new file mode 160000 index 000000000..703bd9caa --- /dev/null +++ b/googletest/googletest-src @@ -0,0 +1 @@ +Subproject commit 703bd9caab50b139428cea1aaff9974ebee5742e diff --git a/scripts/build-lin-docker.ps1 b/scripts/build-lin-docker.ps1 old mode 100644 new mode 100755 diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index 4fd95868b..13dd33a11 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -21,7 +21,7 @@ param ( [Parameter()][String]$BUILD_DIR = "_build", [Parameter()][String]$VCPKG_OPENSSL = "OFF", [Parameter()][String]$BONDING = "OFF", - [Parameter()][String]$ENABLE_SWIG = "ON", + [Parameter()][String]$ENABLE_SWIG = "OFF", [Parameter()][String]$ENABLE_SWIG_CSHARP = "ON" ) @@ -203,7 +203,7 @@ else { $cmakeFlags += " -DOPENSSL_USE_STATIC_LIBS=$STATIC_LINK_SSL " } -# cmake uses a flag for architecture from vs2022, so add that as a suffix +# cmake uses a flag for architecture from vs2019 onwards, so add that as a suffix if ( $VS_VERSION -eq '2019' -or $VS_VERSION -eq '2022') { $cmakeFlags += " -A `"$DEVENV_PLATFORM`"" } From 496172889c7de0e18c433c656c33e28f532b71f3 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Sun, 26 Feb 2023 11:33:15 +0000 Subject: [PATCH 07/29] -explicit call to run linux build in pwsh (CI fix) --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 697d398c4..1dc7787d9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -18,7 +18,7 @@ build_script: - ps: if ($VSIMG -match '2019' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -ENABLE_SWIG ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Release") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS ON -UNIT_TESTS ON -BONDING ON} - ps: if ($VSIMG -match '2015' -and $CNFG -eq "Debug") { .\scripts\build-windows.ps1 -STATIC_LINK_SSL ON -BUILD_APPS OFF } - - sh: ./scripts/build-lin-docker.ps1 -ENABLE_SWIG ON + - sh: pwsh ./scripts/build-lin-docker.ps1 -ENABLE_SWIG ON test_script: - ps: if ( $Env:RUN_UNIT_TESTS ) { cd ./_build; ctest -E "TestIPv6.v6_calls_v4" --extra-verbose -C $Env:CONFIGURATION; cd ../ } From ae46ba86bd8ffaff7b6178a9680427f3fbcb639e Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Tue, 28 Feb 2023 10:35:32 +0000 Subject: [PATCH 08/29] -compile up-to-date swig within linux container -typedef byte (needed to compile on linux) -download swig from cinegy s3 link (fix flakey CI) --- .DS_Store | Bin 0 -> 6148 bytes scripts/Dockerfile.linux | 6 +++++- scripts/build-windows.ps1 | 5 ++++- srtcore/srt.i | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Sat, 18 Mar 2023 11:22:24 +0200 Subject: [PATCH 09/29] WIP --- srtcore/srt.i | 357 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 335 insertions(+), 22 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 52dadb83b..315f8207b 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -11,6 +11,7 @@ /***************************************************************************** written by Lewis Kirkaldie - Cinegy GmbH + Volodymyr Shkolka - Cinegy GmbH *****************************************************************************/ /* @@ -42,7 +43,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %apply int INOUT[] { const SRTSOCKET listeners[]} %apply int INOUT[] { const int* fara} -// Marshal Pointers to IntPtr +// ---- Marshal Pointers to IntPtr %apply void *VOID_INT_PTR { void *, SRT_LOG_HANDLER_FN *, // Delegate @@ -55,27 +56,27 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s SRT_SOCKOPT_CONFIG* } -// REF int mapping +// ---- REF int mapping %typemap(cstype) int * "ref int" %typemap(csin, - pre=" var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", - post=" pin_$csinput.Free();" + pre="var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", + post="pin_$csinput.Free();" ) int * "pin_$csinput.AddrOfPinnedObject()" -// REF size_t mapping +// ---- REF size_t mapping %typemap(cstype) size_t * "ref ulong" %typemap(csin, - pre=" var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", - post=" pin_$csinput.Free();" + pre="var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", + post="pin_$csinput.Free();" ) size_t * "pin_$csinput.AddrOfPinnedObject()" // ---- OVERRIDE SIGNATURE (struct sockaddr* addr, int* addrlen) %typemap(in) (struct sockaddr*, int*) { TransitiveArguments * args = (TransitiveArguments *)$input; - $1 = args->Arg1; - $2 = args->Arg2; + $1 = (struct sockaddr *)args->Arg1; + $2 = (int *)args->Arg2; } %typemap(cstype) (struct sockaddr*, int*) "out IPEndPoint" %typemap(imtype) (struct sockaddr*, int*) "global::System.Runtime.InteropServices.HandleRef" @@ -112,7 +113,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s // ---- OVERRIDE SIGNATURE (const struct sockaddr addr, int addrlen) %typemap(in) (const struct sockaddr*, int) { TransitiveArguments * args = (TransitiveArguments *)$input; - $1 = args->Arg1; + $1 = (struct sockaddr *)args->Arg1; $2 = *args->Arg2; } %typemap(cstype) (const struct sockaddr*, int) "IPEndPoint" @@ -162,33 +163,41 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s pin_content_$csinput = GCHandle.Alloc(content_$csinput, GCHandleType.Pinned); input_$csinput = pin_content_$csinput.Value.AddrOfPinnedObject(); }", - post=" - pin_content_$csinput?.Free();" + post="pin_content_$csinput?.Free();" ) (const struct sockaddr*) "input_$csinput" -// REF int64_t mapping +// ---- REF int64_t mapping %typemap(cstype) (int64_t *) "ref long" %typemap(csin, - pre=" var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", - post=" pin_$csinput.Free();" + pre="var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", + post="pin_$csinput.Free();" ) int64_t * "pin_$csinput.AddrOfPinnedObject()" +// ---- SRT_LOG_HANDLER_FN to Delegate mapping %typemap(cstype) (SRT_LOG_HANDLER_FN *) "SrtLogHandlerDelegate" %typemap(csin, - pre=" GCKeeper.Keep(nameof(SrtLogHandlerDelegate), $csinput);var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);") SRT_LOG_HANDLER_FN* + pre=" + GCKeeper.Keep(nameof(SrtLogHandlerDelegate), $csinput); + var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" + ) SRT_LOG_HANDLER_FN* "delegatePtr_$csinput" +// ---- srt_listen_callback_fn to Delegate mapping %typemap(cstype) (srt_listen_callback_fn *) "SrtListenCallbackDelegate" %typemap(csin, - pre=" GCKeeper.Keep(nameof(SrtListenCallbackDelegate), $csinput);var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" + pre=" + GCKeeper.Keep(nameof(SrtListenCallbackDelegate), $csinput); + var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" ) srt_listen_callback_fn* "delegatePtr_$csinput" %typemap(cstype) (srt_connect_callback_fn *) "SrtConnectCallbackDelegate" %typemap(csin, - pre=" GCKeeper.Keep(nameof(SrtConnectCallbackDelegate), $csinput);var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" + pre=" + GCKeeper.Keep(nameof(SrtConnectCallbackDelegate), $csinput); + var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" ) srt_connect_callback_fn* "delegatePtr_$csinput" @@ -204,9 +213,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s pinAddr_$csinput = pin_$csinput.Value.AddrOfPinnedObject(); } ", - post=" - pin_$csinput?.Free(); - " + post="pin_$csinput?.Free();" ) const int* events "pinAddr_$csinput" @@ -244,6 +251,89 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) int srt_getsockflag_string() "string" ------------------------ NOT READY YET */ +// --- Map srt_setlogflags member to artificial LogFlag structure +// --- structure itself defined in csharp module imports below +// Type mappings for IM wrapper INT -> managed struct +%inline{ typedef int LogFlag; } + +// Force C# to use LogFlag structure instead original INT +%typemap(cstype) LogFlag "LogFlag" + +// Redefine C# method representation +%ignore srt_setlogflags(int flags); +void srt_setlogflags(LogFlag flags) { srt_setlogflags(flags); } + +// Forward constants from C side to C# srt module +const LogFlag SRT_LOGF_DISABLE_TIME = SRT_LOGF_DISABLE_TIME; +const LogFlag SRT_LOGF_DISABLE_THREADNAME = SRT_LOGF_DISABLE_THREADNAME; +const LogFlag SRT_LOGF_DISABLE_SEVERITY = SRT_LOGF_DISABLE_SEVERITY; +const LogFlag SRT_LOGF_DISABLE_EOL = SRT_LOGF_DISABLE_EOL; + +// --- Map srt_setloglevel member to artificial LogLevel structure +// --- structure itself defined in csharp module imports below +// Type mappings for IM wrapper INT -> managed struct +%inline{ typedef int LogLevel; } + +// Force C# to use LogLevel structure instead original INT +%typemap(cstype) LogLevel "LogLevel" + +// Redefine C# method representation +%ignore srt_setloglevel(int ll); +void srt_setloglevel(LogLevel logLevel) { srt_setloglevel(logLevel); } + +// Forward constants from C side to C# srt module +const LogLevel LOG_DEBUG = LOG_DEBUG; +const LogLevel LOG_NOTICE = LOG_NOTICE; +const LogLevel LOG_WARNING = LOG_WARNING; +const LogLevel LOG_ERR = LOG_ERR; +const LogLevel LOG_CRIT = LOG_CRIT; + +// --- Map srt_addlogfa/srt_dellogfa/srt_resetlogfa members to artificial LogFunctionalArea structure +// --- structure itself defined in csharp module imports below +// Type mappings for IM wrapper INT -> managed struct +%inline{ typedef int LogFunctionalArea; } + +// Force C# to use LogFunctionalArea structure instead original INT +%typemap(cstype) LogFunctionalArea "LogFunctionalArea" + +// Redefine C# method representation +%ignore srt_addlogfa(int fa); +void srt_addlogfa(LogFunctionalArea functionalArea) { srt_addlogfa(functionalArea); } + +%ignore srt_dellogfa(int fa); +void srt_dellogfa(LogFunctionalArea functionalArea) { srt_dellogfa(functionalArea); } + +// OVERRIDE SIGNATURE (const int* fara, size_t fara_size) +%typemap(in) (const int* fara, size_t fara_size) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = (int const *)args->Arg1; + $2 = (size_t)*args->Arg2; +} + +%typemap(cstype) (const int* fara, size_t fara_size) "params LogFunctionalArea[]" +%typemap(imtype) (const int* fara, size_t fara_size) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var array_$csinput = $csinput.Select(x => (int)x).ToArray(); + int array_len_$csinput = array_$csinput.Length; + + var pin_array_$csinput = GCHandle.Alloc(array_$csinput, GCHandleType.Pinned); + var pin_array_len_$csinput = GCHandle.Alloc(array_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_array_$csinput.AddrOfPinnedObject(), + Arg2 = pin_array_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_array_$csinput.Free(); + pin_array_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (const int* fara, size_t fara_size) + "input_$csinput" + + #if defined(SWIGWORDSIZE64) %define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE) %clear NEW_TYPE; @@ -299,13 +389,14 @@ PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long); // General interface definition of wrapper - due to above typemaps and code, we can now just reference the main srt.h file %include "srt.h"; -// C additional definitions +// --- C additional definitions %inline{ #ifndef _WIN32 typedef unsigned char byte; #endif +// Structure used for arguments transit typedef struct { byte *Arg1; @@ -418,6 +509,7 @@ int srt_getsockflag_long(SRTSOCKET u, SRT_LONG_SOCKOPT opt, void* string_val, in %pragma(csharp) moduleimports=%{ using System; +using System.Linq; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; @@ -555,4 +647,225 @@ static class GCKeeper } } +/// +/// Artificial structure that represents arguments for srt_setlogflags(LogFlag) +/// +public readonly struct LogFlag +{ + /// + /// Do not provide the time in the header + /// + public static readonly LogFlag DisableTime = srt.SRT_LOGF_DISABLE_TIME; + + /// + /// Do not provide the thread name in the header + /// + public static readonly LogFlag DisableThreadName = srt.SRT_LOGF_DISABLE_THREADNAME; + + /// + /// Do not provide severity information in the header + /// + public static readonly LogFlag DisableSeverity = srt.SRT_LOGF_DISABLE_SEVERITY; + + /// + /// Do not add the end-of-line character to the log line + /// + public static readonly LogFlag DisableEOL = srt.SRT_LOGF_DISABLE_EOL; + + private readonly int _value; + LogFlag(int value) => _value = value; + public override string ToString() => $"{_value}"; + public static implicit operator LogFlag(int b) => new LogFlag(b); + public static implicit operator int(LogFlag d) => d._value; +} + +/// +/// Artificial structure that represents arguments for srt_setloglevel(LogLevel) +/// +public readonly struct LogLevel +{ + /// + /// Highly detailed and very frequent messages + /// + public static readonly LogLevel Debug = srt.LOG_DEBUG; + + /// + /// Occasionally displayed information + /// + public static readonly LogLevel Notice = srt.LOG_NOTICE; + + /// + /// Unusual behavior + /// + public static readonly LogLevel Warning = srt.LOG_WARNING; + + /// + /// Abnormal behavior + /// + public static readonly LogLevel Error = srt.LOG_ERR; + + /// + /// Error that makes the current socket unusable + /// + public static readonly LogLevel Critical = srt.LOG_CRIT; + + private readonly int _value; + LogLevel(int value) => _value = value; + public override string ToString() => $"{_value}"; + public static implicit operator LogLevel(int b) => new LogLevel(b); + public static implicit operator int(LogLevel d) => d._value; +} + +/// +/// Artificial structure that represents arguments for srt_addlogfa/srt_dellogfa/srt_resetlogfa +/// +public readonly struct LogFunctionalArea +{ + /// + /// gglog: General uncategorized log; for serious issues only + /// + public static readonly LogFunctionalArea General = srt.SRT_LOGFA_GENERAL; + + /// + /// smlog: Socket create/open/close/configure activities + /// + public static readonly LogFunctionalArea SocketManagement = srt.SRT_LOGFA_SOCKMGMT; + + /// + /// cnlog: Connection establishment and handshake + /// + public static readonly LogFunctionalArea Connection = srt.SRT_LOGFA_CONN; + + /// + /// xtlog: The checkTimer and around activities + /// + public static readonly LogFunctionalArea XTimer = srt.SRT_LOGFA_XTIMER; + + /// + /// tslog: The TsBPD thread + /// + public static readonly LogFunctionalArea TsBPD = srt.SRT_LOGFA_TSBPD; + + /// + /// rslog: System resource allocation and management + /// + public static readonly LogFunctionalArea ResourceManagement = srt.SRT_LOGFA_RSRC; + + /// + /// cclog: Congestion control module + /// + public static readonly LogFunctionalArea Congestion = srt.SRT_LOGFA_CONGEST; + + /// + /// pflog: Packet filter module + /// + public static readonly LogFunctionalArea PacketFilter = srt.SRT_LOGFA_PFILTER; + + /// + /// aclog: API part for socket and library management + /// + public static readonly LogFunctionalArea SocketApi = srt.SRT_LOGFA_API_CTRL; + + /// + /// qclog: Queue control activities + /// + public static readonly LogFunctionalArea QueueControl = srt.SRT_LOGFA_QUE_CTRL; + + /// + /// eilog: EPoll; internal update activities + /// + public static readonly LogFunctionalArea EPollActivities = srt.SRT_LOGFA_EPOLL_UPD; + + /// + /// arlog: API part for receiving + /// + public static readonly LogFunctionalArea ReceivingApi = srt.SRT_LOGFA_API_RECV; + + /// + /// brlog: Buffer; receiving side + /// + public static readonly LogFunctionalArea ReceivingBuffer = srt.SRT_LOGFA_BUF_RECV; + + /// + /// qrlog: Queue; receiving side + /// + public static readonly LogFunctionalArea ReceivingQueue = srt.SRT_LOGFA_QUE_RECV; + + /// + /// krlog: CChannel; receiving side + /// + public static readonly LogFunctionalArea ReceivingChannel = srt.SRT_LOGFA_CHN_RECV; + + /// + /// grlog: Group; receiving side + /// + public static readonly LogFunctionalArea ReceivingGroup = srt.SRT_LOGFA_GRP_RECV; + + /// + /// aslog: API part for sending + /// + public static readonly LogFunctionalArea SendingApi = srt.SRT_LOGFA_API_SEND; + + /// + /// bslog: Buffer; sending side + /// + public static readonly LogFunctionalArea SendingBuffer = srt.SRT_LOGFA_BUF_SEND; + + /// + /// qslog: Queue; sending side + /// + public static readonly LogFunctionalArea SendingQueue = srt.SRT_LOGFA_QUE_SEND; + + /// + /// kslog: CChannel; sending side + /// + public static readonly LogFunctionalArea SendingChannel = srt.SRT_LOGFA_CHN_SEND; + + /// + /// gslog: Group; sending side + /// + public static readonly LogFunctionalArea SendingGroup = srt.SRT_LOGFA_GRP_SEND; + + /// + /// inlog: Internal activities not connected directly to a socket + /// + public static readonly LogFunctionalArea Internal = srt.SRT_LOGFA_INTERNAL; + + /// + /// qmlog: Queue; management part + /// + public static readonly LogFunctionalArea ManagementQueue = srt.SRT_LOGFA_QUE_MGMT; + + /// + /// kmlog: CChannel; management part + /// + public static readonly LogFunctionalArea ManagementChannel = srt.SRT_LOGFA_CHN_MGMT; + + /// + /// gmlog: Group; management part + /// + public static readonly LogFunctionalArea ManagementGroup = srt.SRT_LOGFA_GRP_MGMT; + + /// + /// ealog: EPoll; API part + /// + public static readonly LogFunctionalArea EPollApi = srt.SRT_LOGFA_EPOLL_API; + + /// + /// hclog: Haicrypt module area + /// + public static readonly LogFunctionalArea HaiCrypt = srt.SRT_LOGFA_HAICRYPT; + + /// + /// aplog: Applications + /// + public static readonly LogFunctionalArea Applications = srt.SRT_LOGFA_APPLOG; + + private readonly int _value; + LogFunctionalArea(int value) => _value = value; + public override string ToString() => $"{_value}"; + public static implicit operator LogFunctionalArea(int b) => new LogFunctionalArea(b); + public static implicit operator int(LogFunctionalArea d) => d._value; +} + %} \ No newline at end of file From 741c3ca0a94eab295a4947f32e6aa30f237a4647 Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 18 Mar 2023 14:29:32 +0200 Subject: [PATCH 10/29] Added options handling --- srtcore/srt.i | 564 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 401 insertions(+), 163 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 315f8207b..eef4bbb23 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -60,7 +60,9 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) int * "ref int" %typemap(csin, pre="var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", - post="pin_$csinput.Free();" + post=" + $csinput = (int)pin_$csinput.Target; + pin_$csinput.Free();" ) int * "pin_$csinput.AddrOfPinnedObject()" @@ -68,7 +70,9 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) size_t * "ref ulong" %typemap(csin, pre="var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", - post="pin_$csinput.Free();" + post=" + $csinput = (ulong)pin_$csinput.Target; + pin_$csinput.Free();" ) size_t * "pin_$csinput.AddrOfPinnedObject()" @@ -171,7 +175,9 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) (int64_t *) "ref long" %typemap(csin, pre="var pin_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned);", - post="pin_$csinput.Free();" + post=" + $csinput = (long)pin_$csinput.Target; + pin_$csinput.Free();" ) int64_t * "pin_$csinput.AddrOfPinnedObject()" @@ -201,6 +207,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s ) srt_connect_callback_fn* "delegatePtr_$csinput" +// ---- Nullable SRT_EPOLL_OPT handling %typemap(cstype) (const int* events) "SRT_EPOLL_OPT?" %typemap(csin, pre=" @@ -217,40 +224,6 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s ) const int* events "pinAddr_$csinput" -/* ------------------------ NOT READY YET -// ---- OVERRIDE SIGNATURE (SRT_SOCKOPT opt, void* string_val, int* string_len) -%typemap(in) (SRT_SOCKOPT opt, void* string_val, int* string_len) { - TransitiveArguments * args = (TransitiveArguments *)$input; - $1 = (SRT_SOCKOPT)(*args->Arg1); - $2 = args->Arg2; - $3 = args->Arg3; -} -%typemap(cstype) (SRT_SOCKOPT opt, void* string_val, int* string_len) "SRT_SOCKOPT" -%typemap(imtype) (SRT_SOCKOPT opt, void* string_val, int* string_len) "global::System.Runtime.InteropServices.HandleRef" -%typemap(csin, - pre=" - var sock_$csinput = $csinput.Serialize(); - var content_$csinput = sock_$csinput.GetInternalBuffer(); - int content_len_$csinput = sock_$csinput.Size; - var pin_content_$csinput = GCHandle.Alloc(content_$csinput, GCHandleType.Pinned); - var pin_content_len_$csinput = GCHandle.Alloc(content_len_$csinput, GCHandleType.Pinned); - - var transitive_$csinput = new TransitiveArguments - { - Arg1 = pin_content_$csinput.AddrOfPinnedObject(), - Arg2 = pin_content_len_$csinput.AddrOfPinnedObject() - }; - var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", - post=" - pin_content_$csinput.Free(); - pin_content_len_$csinput.Free(); - transitive_$csinput.Dispose();" - ) (SRT_SOCKOPT opt, void* string_val, int* string_len) - "input_$csinput" - -%typemap(cstype) int srt_getsockflag_string() "string" ------------------------- NOT READY YET */ - // --- Map srt_setlogflags member to artificial LogFlag structure // --- structure itself defined in csharp module imports below // Type mappings for IM wrapper INT -> managed struct @@ -261,7 +234,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s // Redefine C# method representation %ignore srt_setlogflags(int flags); -void srt_setlogflags(LogFlag flags) { srt_setlogflags(flags); } +void srt_setlogflags(LogFlag flags); // Forward constants from C side to C# srt module const LogFlag SRT_LOGF_DISABLE_TIME = SRT_LOGF_DISABLE_TIME; @@ -279,7 +252,7 @@ const LogFlag SRT_LOGF_DISABLE_EOL = SRT_LOGF_DISABLE_EOL; // Redefine C# method representation %ignore srt_setloglevel(int ll); -void srt_setloglevel(LogLevel logLevel) { srt_setloglevel(logLevel); } +void srt_setloglevel(LogLevel logLevel); // Forward constants from C side to C# srt module const LogLevel LOG_DEBUG = LOG_DEBUG; @@ -298,10 +271,10 @@ const LogLevel LOG_CRIT = LOG_CRIT; // Redefine C# method representation %ignore srt_addlogfa(int fa); -void srt_addlogfa(LogFunctionalArea functionalArea) { srt_addlogfa(functionalArea); } +void srt_addlogfa(LogFunctionalArea functionalArea); %ignore srt_dellogfa(int fa); -void srt_dellogfa(LogFunctionalArea functionalArea) { srt_dellogfa(functionalArea); } +void srt_dellogfa(LogFunctionalArea functionalArea); // OVERRIDE SIGNATURE (const int* fara, size_t fara_size) %typemap(in) (const int* fara, size_t fara_size) { @@ -333,6 +306,378 @@ void srt_dellogfa(LogFunctionalArea functionalArea) { srt_dellogfa(functionalAre ) (const int* fara, size_t fara_size) "input_$csinput" +// ---- ADD ADDITIONAL method for string flags manipulation +// -- srt_getsockflag_string method +%typemap(in) (void* stringOptVal, int* stringOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int*)args->Arg2; +} +%typemap(cstype) (void* stringOptVal, int* stringOptLen) "out string" +%typemap(imtype) (void* stringOptVal, int* stringOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var value_len_$csinput = 512; + var value_$csinput = new byte[value_len_$csinput]; + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + $csinput = Encoding.UTF8.GetString(value_$csinput.AsSpan(0, (int)pin_value_len_$csinput.Target)); + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* stringOptVal, int* stringOptLen) + "input_$csinput" + +// -- srt_setsockflag_string method +%typemap(in) (void* stringOptVal, int stringOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = *(int*)args->Arg2; +} +%typemap(cstype) (void* stringOptVal, int stringOptLen) "string" +%typemap(imtype) (void* stringOptVal, int stringOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var value_$csinput = Encoding.UTF8.GetBytes($csinput); + var value_len_$csinput = value_$csinput.Length; + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* stringOptVal, int stringOptLen) + "input_$csinput" + +%typemap(csimports) SRT_STRING_SOCKOPT %{ + using static SRT_SOCKOPT; +%} +%inline { + typedef enum + { + SRTO_STRING_BINDTODEVICE = SRTO_BINDTODEVICE, + SRTO_STRING_CONGESTION = SRTO_CONGESTION, + SRTO_STRING_PACKETFILTER = SRTO_PACKETFILTER, + SRTO_STRING_PASSPHRASE = SRTO_PASSPHRASE, + SRTO_STRING_STREAMID = SRTO_STREAMID, + }SRT_STRING_SOCKOPT; + + int srt_getsockflag_string(SRTSOCKET u, SRT_STRING_SOCKOPT opt, void* stringOptVal, int* stringOptLen) + { + return srt_getsockflag(u, (SRT_SOCKOPT)opt, stringOptVal, stringOptLen); + } + + int srt_setsockflag_string(SRTSOCKET u, SRT_STRING_SOCKOPT opt, void* stringOptVal, int stringOptLen) + { + return srt_setsockflag(u, (SRT_SOCKOPT)opt, stringOptVal, stringOptLen); + } +} + +// ---- ADD ADDITIONAL method for bool flags manipulation +// -- srt_getsockflag_bool method +%typemap(in) (void* boolOptVal, int* boolOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int*)args->Arg2; +} +%typemap(cstype) (void* boolOptVal, int* boolOptLen) "out bool" +%typemap(imtype) (void* boolOptVal, int* boolOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + byte value_$csinput = default(byte); + var value_len_$csinput = Marshal.SizeOf(value_$csinput.GetType()); + + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + $csinput = ((byte)pin_value_$csinput.Target) == 1 ? true : false; + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* boolOptVal, int* boolOptLen) + "input_$csinput" + +// -- srt_setsockflag_bool method +%typemap(in) (void* boolOptVal, int boolOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = *(int*)args->Arg2; +} +%typemap(cstype) (void* boolOptVal, int boolOptLen) "bool" +%typemap(imtype) (void* boolOptVal, int boolOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var value_$csinput = $csinput ? (byte)1 : (byte)0; + var value_len_$csinput = Marshal.SizeOf(value_$csinput.GetType()); + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* boolOptVal, int boolOptLen) + "input_$csinput" + +%typemap(csimports) SRT_BOOL_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%inline { + typedef enum + { + SRTO_BOOL_DRIFTTRACER = SRTO_DRIFTTRACER, + SRTO_BOOL_ENFORCEDENCRYPTION = SRTO_ENFORCEDENCRYPTION, + SRTO_BOOL_MESSAGEAPI = SRTO_MESSAGEAPI, + SRTO_BOOL_NAKREPORT = SRTO_NAKREPORT, + SRTO_BOOL_RCVSYN = SRTO_RCVSYN, + SRTO_BOOL_RENDEZVOUS = SRTO_RENDEZVOUS, + SRTO_BOOL_REUSEADDR = SRTO_REUSEADDR, + SRTO_BOOL_SENDER = SRTO_SENDER, + SRTO_BOOL_SNDSYN = SRTO_SNDSYN, + SRTO_BOOL_TLPKTDROP = SRTO_TLPKTDROP, + SRTO_BOOL_TSBPDMODE = SRTO_TSBPDMODE + }SRT_BOOL_SOCKOPT; + + int srt_getsockflag_bool(SRTSOCKET u, SRT_BOOL_SOCKOPT opt, void* boolOptVal, int* boolOptLen) + { + return srt_getsockflag(u, (SRT_SOCKOPT)opt, boolOptVal, boolOptLen); + } + + int srt_setsockflag_bool(SRTSOCKET u, SRT_BOOL_SOCKOPT opt, void* boolOptVal, int boolOptLen) + { + return srt_setsockflag(u, (SRT_SOCKOPT)opt, boolOptVal, boolOptLen); + } +} + +// ---- ADD ADDITIONAL method for long flags manipulation +// -- srt_getsockflag_long method +%typemap(in) (void* longOptVal, int* longOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int*)args->Arg2; +} +%typemap(cstype) (void* longOptVal, int* longOptLen) "out long" +%typemap(imtype) (void* longOptVal, int* longOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + long value_$csinput = default(long); + var value_len_$csinput = Marshal.SizeOf(value_$csinput.GetType()); + + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + $csinput = (long)pin_value_$csinput.Target; + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* longOptVal, int* longOptLen) + "input_$csinput" + +// -- srt_setsockflag_long method +%typemap(in) (void* longOptVal, int longOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = *(int*)args->Arg2; +} +%typemap(cstype) (void* longOptVal, int longOptLen) "long" +%typemap(imtype) (void* longOptVal, int longOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var value_$csinput = $csinput; + var value_len_$csinput = Marshal.SizeOf(value_$csinput.GetType()); + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* longOptVal, int longOptLen) + "input_$csinput" + +%typemap(csimports) SRT_LONG_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%inline { + typedef enum + { + SRTO_LONG_INPUTBW = SRTO_INPUTBW, + SRTO_LONG_MAXBW = SRTO_MAXBW, + SRTO_LONG_MININPUTBW = SRTO_MININPUTBW, + }SRT_LONG_SOCKOPT; + + int srt_getsockflag_long(SRTSOCKET u, SRT_LONG_SOCKOPT opt, void* longOptVal, int* longOptLen) + { + return srt_getsockflag(u, (SRT_SOCKOPT)opt, longOptVal, longOptLen); + } + + int srt_setsockflag_long(SRTSOCKET u, SRT_LONG_SOCKOPT opt, void* longOptVal, int longOptLen) + { + return srt_setsockflag(u, (SRT_SOCKOPT)opt, longOptVal, longOptLen); + } +} + +// ---- ADD ADDITIONAL method for int flags manipulation +// -- srt_getsockflag_int method +%typemap(in) (void* intOptVal, int* intOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int*)args->Arg2; +} +%typemap(cstype) (void* intOptVal, int* intOptLen) "out int" +%typemap(imtype) (void* intOptVal, int* intOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + int value_$csinput = default(int); + var value_len_$csinput = Marshal.SizeOf(value_$csinput.GetType()); + + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + $csinput = (int)pin_value_$csinput.Target; + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* intOptVal, int* intOptLen) + "input_$csinput" + +// -- srt_setsockflag_int method +%typemap(in) (void* intOptVal, int intOptLen) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = *(int*)args->Arg2; +} +%typemap(cstype) (void* intOptVal, int intOptLen) "int" +%typemap(imtype) (void* intOptVal, int intOptLen) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + var value_$csinput = $csinput; + var value_len_$csinput = Marshal.SizeOf(value_$csinput.GetType()); + var pin_value_$csinput = GCHandle.Alloc(value_$csinput, GCHandleType.Pinned); + var pin_value_len_$csinput = GCHandle.Alloc(value_len_$csinput, GCHandleType.Pinned); + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_value_$csinput.AddrOfPinnedObject(), + Arg2 = pin_value_len_$csinput.AddrOfPinnedObject() + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_value_$csinput.Free(); + pin_value_len_$csinput.Free(); + transitive_$csinput.Dispose();" + ) (void* intOptVal, int intOptLen) + "input_$csinput" + +%typemap(csimports) SRT_INT_SOCKOPT %{ + using static SRT_SOCKOPT; +%} + +%inline { + typedef enum + { + SRTO_INT_CONNTIMEO = SRTO_CONNTIMEO, + SRTO_INT_CRYPTOMODE = SRTO_CRYPTOMODE, + SRTO_INT_EVENT = SRTO_EVENT, + SRTO_INT_FC = SRTO_FC, + SRTO_INT_GROUPCONNECT = SRTO_GROUPCONNECT, + SRTO_INT_GROUPMINSTABLETIMEO = SRTO_GROUPMINSTABLETIMEO, + SRTO_INT_GROUPTYPE = SRTO_GROUPTYPE, + SRTO_INT_IPTOS = SRTO_IPTOS, + SRTO_INT_IPTTL = SRTO_IPTTL, + SRTO_INT_IPV6ONLY = SRTO_IPV6ONLY, + SRTO_INT_ISN = SRTO_ISN, + SRTO_INT_KMPREANNOUNCE = SRTO_KMPREANNOUNCE, + SRTO_INT_KMREFRESHRATE = SRTO_KMREFRESHRATE, + SRTO_INT_KMSTATE = SRTO_KMSTATE, + SRTO_INT_LATENCY = SRTO_LATENCY, + SRTO_INT_LOSSMAXTTL = SRTO_LOSSMAXTTL, + SRTO_INT_MINVERSION = SRTO_MINVERSION, + SRTO_INT_MSS = SRTO_MSS, + SRTO_INT_OHEADBW = SRTO_OHEADBW, + SRTO_INT_PAYLOADSIZE = SRTO_PAYLOADSIZE, + SRTO_INT_PBKEYLEN = SRTO_PBKEYLEN, + SRTO_INT_PEERIDLETIMEO = SRTO_PEERIDLETIMEO, + SRTO_INT_PEERLATENCY = SRTO_PEERLATENCY, + SRTO_INT_PEERVERSION = SRTO_PEERVERSION, + SRTO_INT_RCVBUF = SRTO_RCVBUF, + SRTO_INT_RCVDATA = SRTO_RCVDATA, + SRTO_INT_RCVKMSTATE = SRTO_RCVKMSTATE, + SRTO_INT_RCVLATENCY = SRTO_RCVLATENCY, + SRTO_INT_RCVTIMEO = SRTO_RCVTIMEO, + SRTO_INT_RETRANSMITALGO = SRTO_RETRANSMITALGO, + SRTO_INT_SNDBUF = SRTO_SNDBUF, + SRTO_INT_SNDDATA = SRTO_SNDDATA, + SRTO_INT_SNDDROPDELAY = SRTO_SNDDROPDELAY, + SRTO_INT_SNDKMSTATE = SRTO_SNDKMSTATE, + SRTO_INT_SNDTIMEO = SRTO_SNDTIMEO, + SRTO_INT_STATE = SRTO_STATE, + SRTO_INT_TRANSTYPE = SRTO_TRANSTYPE, + SRTO_INT_UDP_RCVBUF = SRTO_UDP_RCVBUF, + SRTO_INT_UDP_SNDBUF = SRTO_UDP_SNDBUF, + SRTO_INT_VERSION = SRTO_VERSION, + }SRT_INT_SOCKOPT; + + int srt_getsockflag_int(SRTSOCKET u, SRT_INT_SOCKOPT opt, void* intOptVal, int* intOptLen) + { + return srt_getsockflag(u, (SRT_SOCKOPT)opt, intOptVal, intOptLen); + } + + int srt_setsockflag_int(SRTSOCKET u, SRT_INT_SOCKOPT opt, void* intOptVal, int intOptLen) + { + return srt_setsockflag(u, (SRT_SOCKOPT)opt, intOptVal, intOptLen); + } +} #if defined(SWIGWORDSIZE64) %define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE) @@ -365,143 +710,35 @@ PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long); using static CodeMinor; %} -%typemap(csimports) SRT_STRING_SOCKOPT %{ - using static SRT_SOCKOPT; -%} - -%typemap(csimports) SRT_BOOL_SOCKOPT %{ - using static SRT_SOCKOPT; -%} - %typemap(csimports) SRT_INT_SOCKOPT %{ using static SRT_SOCKOPT; %} -%typemap(csimports) SRT_LONG_SOCKOPT %{ - using static SRT_SOCKOPT; -%} - %rename(SRT_TRACEBSTATS) CBytePerfMon; // Ignore deprecated methods %ignore srt_rejectreason_msg; +%ignore srt_setsockopt; // General interface definition of wrapper - due to above typemaps and code, we can now just reference the main srt.h file %include "srt.h"; // --- C additional definitions %inline{ + #ifndef _WIN32 + typedef unsigned char byte; + #endif -#ifndef _WIN32 - typedef unsigned char byte; -#endif - -// Structure used for arguments transit -typedef struct -{ - byte *Arg1; - byte *Arg2; - byte *Arg3; - byte *Arg4; - byte *Arg5; - byte *Arg6; -} TransitiveArguments; - -typedef enum -{ - SRTO_STRING_BINDTODEVICE = SRTO_BINDTODEVICE, - SRTO_STRING_CONGESTION = SRTO_CONGESTION, - SRTO_STRING_PACKETFILTER = SRTO_PACKETFILTER, - SRTO_STRING_PASSPHRASE = SRTO_PASSPHRASE, - SRTO_STRING_STREAMID = SRTO_STREAMID, -}SRT_STRING_SOCKOPT; - -typedef enum -{ - SRTO_LONG_INPUTBW = SRTO_INPUTBW, - SRTO_LONG_MAXBW = SRTO_MAXBW, - SRTO_LONG_MININPUTBW = SRTO_MININPUTBW, -}SRT_LONG_SOCKOPT; - -typedef enum -{ - SRTO_BOOL_DRIFTTRACER = SRTO_DRIFTTRACER, - SRTO_BOOL_ENFORCEDENCRYPTION = SRTO_ENFORCEDENCRYPTION, - SRTO_BOOL_MESSAGEAPI = SRTO_MESSAGEAPI, - SRTO_BOOL_NAKREPORT = SRTO_NAKREPORT, - SRTO_BOOL_RCVSYN = SRTO_RCVSYN, - SRTO_BOOL_RENDEZVOUS = SRTO_RENDEZVOUS, - SRTO_BOOL_REUSEADDR = SRTO_REUSEADDR, - SRTO_BOOL_SENDER = SRTO_SENDER, - SRTO_BOOL_SNDSYN = SRTO_SNDSYN, - SRTO_BOOL_TLPKTDROP = SRTO_TLPKTDROP, - SRTO_BOOL_TSBPDMODE = SRTO_TSBPDMODE -}SRT_BOOL_SOCKOPT; - -typedef enum -{ - SRTO_INT_CONNTIMEO = SRTO_CONNTIMEO, - SRTO_INT_CRYPTOMODE = SRTO_CRYPTOMODE, - SRTO_INT_EVENT = SRTO_EVENT, - SRTO_INT_FC = SRTO_FC, - SRTO_INT_GROUPCONNECT = SRTO_GROUPCONNECT, - SRTO_INT_GROUPMINSTABLETIMEO = SRTO_GROUPMINSTABLETIMEO, - SRTO_INT_GROUPTYPE = SRTO_GROUPTYPE, - SRTO_INT_IPTOS = SRTO_IPTOS, - SRTO_INT_IPTTL = SRTO_IPTTL, - SRTO_INT_IPV6ONLY = SRTO_IPV6ONLY, - SRTO_INT_ISN = SRTO_ISN, - SRTO_INT_KMPREANNOUNCE = SRTO_KMPREANNOUNCE, - SRTO_INT_KMREFRESHRATE = SRTO_KMREFRESHRATE, - SRTO_INT_KMSTATE = SRTO_KMSTATE, - SRTO_INT_LATENCY = SRTO_LATENCY, - SRTO_INT_LOSSMAXTTL = SRTO_LOSSMAXTTL, - SRTO_INT_MINVERSION = SRTO_MINVERSION, - SRTO_INT_MSS = SRTO_MSS, - SRTO_INT_OHEADBW = SRTO_OHEADBW, - SRTO_INT_PAYLOADSIZE = SRTO_PAYLOADSIZE, - SRTO_INT_PBKEYLEN = SRTO_PBKEYLEN, - SRTO_INT_PEERIDLETIMEO = SRTO_PEERIDLETIMEO, - SRTO_INT_PEERLATENCY = SRTO_PEERLATENCY, - SRTO_INT_PEERVERSION = SRTO_PEERVERSION, - SRTO_INT_RCVBUF = SRTO_RCVBUF, - SRTO_INT_RCVDATA = SRTO_RCVDATA, - SRTO_INT_RCVKMSTATE = SRTO_RCVKMSTATE, - SRTO_INT_RCVLATENCY = SRTO_RCVLATENCY, - SRTO_INT_RCVTIMEO = SRTO_RCVTIMEO, - SRTO_INT_RETRANSMITALGO = SRTO_RETRANSMITALGO, - SRTO_INT_SNDBUF = SRTO_SNDBUF, - SRTO_INT_SNDDATA = SRTO_SNDDATA, - SRTO_INT_SNDDROPDELAY = SRTO_SNDDROPDELAY, - SRTO_INT_SNDKMSTATE = SRTO_SNDKMSTATE, - SRTO_INT_SNDTIMEO = SRTO_SNDTIMEO, - SRTO_INT_STATE = SRTO_STATE, - SRTO_INT_TRANSTYPE = SRTO_TRANSTYPE, - SRTO_INT_UDP_RCVBUF = SRTO_UDP_RCVBUF, - SRTO_INT_UDP_SNDBUF = SRTO_UDP_SNDBUF, - SRTO_INT_VERSION = SRTO_VERSION, -}SRT_INT_SOCKOPT; - -int srt_getsockflag_string(SRTSOCKET u, SRT_STRING_SOCKOPT opt, void* string_val, int* string_len) -{ - return srt_getsockflag(u, opt, string_val, string_len); -} - -int srt_getsockflag_bool(SRTSOCKET u, SRT_BOOL_SOCKOPT opt, void* string_val, int* string_len) -{ - return srt_getsockflag(u, opt, string_val, string_len); -} - -int srt_getsockflag_int(SRTSOCKET u, SRT_INT_SOCKOPT opt, void* string_val, int* string_len) -{ - return srt_getsockflag(u, opt, string_val, string_len); -} - -int srt_getsockflag_long(SRTSOCKET u, SRT_LONG_SOCKOPT opt, void* string_val, int* string_len) -{ - return srt_getsockflag(u, opt, string_val, string_len); -} - + // Structure used for arguments transit + typedef struct + { + byte *Arg1; + byte *Arg2; + byte *Arg3; + byte *Arg4; + byte *Arg5; + byte *Arg6; + } TransitiveArguments; } // add top-level code to module file @@ -510,6 +747,7 @@ int srt_getsockflag_long(SRTSOCKET u, SRT_LONG_SOCKOPT opt, void* string_val, in using System; using System.Linq; +using System.Text; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; From 40357d3114b7512eac0f73ff47aa1511952212a6 Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 18 Mar 2023 14:40:21 +0200 Subject: [PATCH 11/29] Marshaler fix --- srtcore/srt.i | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/srtcore/srt.i b/srtcore/srt.i index eef4bbb23..a88b05537 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -820,6 +820,23 @@ internal static class MarshalExtensions internal class SockAddrMarshaler : ICustomMarshaler { + private SockAddrMarshaler(string cookies) + { + Cookies = cookies; + } + + /// + /// Required method by NET marshaling implementation + /// + /// + /// + public static ICustomMarshaler GetInstance(string cookies) + { + return new SockAddrMarshaler(cookies); + } + + public string Cookies { get; } + public void CleanUpManagedData(object managedObj) { //Nothing GC will clean up managed object From 0972dd3ad1a94b2c47ebeb8e4de827700f989c84 Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 18 Mar 2023 20:03:57 +0200 Subject: [PATCH 12/29] Fixed delegates, a lot of modifications --- srtcore/srt.i | 104 +++++++++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index a88b05537..e2bd08de3 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -224,6 +224,20 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s ) const int* events "pinAddr_$csinput" +// --- Map all SRTSOCKET to artificial SRTSOCKET structure +%typemap(cstype) SRTSOCKET "SRTSOCKET" + +// --- Map srt_getlasterror return type to SRT_ERRNO +%typemap(csbase) SRT_ERRNO "int" +%typemap(cstype) int srt_getlasterror "SRT_ERRNO" +%typemap(csout) int srt_getlasterror { return (SRT_ERRNO)$imcall; } + +// --- Map srt_create_socket return type to SRTSOCKET +%typemap(cstype) int srt_create_socket "SRTSOCKET" + +// --- Map srt_accept return type to SRTSOCKET +%typemap(cstype) int srt_accept "SRTSOCKET" + // --- Map srt_setlogflags member to artificial LogFlag structure // --- structure itself defined in csharp module imports below // Type mappings for IM wrapper INT -> managed struct @@ -778,7 +792,7 @@ public delegate void SrtListenCallbackDelegate( IntPtr opaque, int ns, int hsVersion, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SockAddrMarshaler))]IPEndPoint peerAddress, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SockAddrMarshaler))] IPEndPoint peerAddress, string streamId); /// @@ -791,12 +805,12 @@ public delegate void SrtListenCallbackDelegate( /// The token value, if it was used for group connection, otherwise -1 public delegate void SrtConnectCallbackDelegate( IntPtr opaque, - int ns, - int errorCode, + int ns, + SRT_ERRNO errorCode, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SockAddrMarshaler))]IPEndPoint peerAddress, int token); -internal static class MarshalExtensions +public static class MarshalExtensions { private static readonly FieldInfo SocketAddressBufferField = typeof(SocketAddress).GetField("Buffer", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo SocketAddressInternalSizeField = typeof(SocketAddress).GetField("InternalSize", BindingFlags.Instance | BindingFlags.NonPublic); @@ -816,52 +830,34 @@ internal static class MarshalExtensions IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); return (IPEndPoint)endPoint.Create(socketAddress); } -} -internal class SockAddrMarshaler : ICustomMarshaler -{ - private SockAddrMarshaler(string cookies) + public static void Validate(this int responseCode, string message) { - Cookies = cookies; + if(responseCode != srt.SRT_ERROR) return; + throw new InvalidOperationException($"{message} failed: {srt.srt_getlasterror_str()}"); } - - /// - /// Required method by NET marshaling implementation - /// - /// - /// - public static ICustomMarshaler GetInstance(string cookies) + + public static SRTSOCKET Validate(this SRTSOCKET socket) { - return new SockAddrMarshaler(cookies); + if(socket.IsValid) return socket; + throw new InvalidOperationException($"Socket was not created: {srt.srt_getlasterror_str()}"); } +} +internal class SockAddrMarshaler : ICustomMarshaler +{ + private SockAddrMarshaler(string cookies) => Cookies = cookies; public string Cookies { get; } - public void CleanUpManagedData(object managedObj) - { - //Nothing GC will clean up managed object - } - - public void CleanUpNativeData(IntPtr pNativeData) - { - //Nothing - } - - public int GetNativeDataSize() - { - return -1; - } - - public IntPtr MarshalManagedToNative(object managedObj) - { - // We do not support C# to C conversation - throw new NotSupportedException(); - } - - const int DATA_OFFSET = 2; + public static ICustomMarshaler GetInstance(string cookies) => new SockAddrMarshaler(cookies); + public void CleanUpManagedData(object managedObj) { /* Nothing GC will clean up managed object */ } + public void CleanUpNativeData(IntPtr pNativeData) { /* Nothing */ } + public int GetNativeDataSize() => -1; + public IntPtr MarshalManagedToNative(object managedObj) => throw new NotSupportedException(); public object MarshalNativeToManaged(IntPtr pNativeData) { + const int DATA_OFFSET = 2; var family = Marshal.ReadInt16(pNativeData); var dataPointer = pNativeData + DATA_OFFSET; var socketAddress = new SocketAddress((AddressFamily) family, 16) @@ -892,7 +888,7 @@ internal class SockAddrMarshaler : ICustomMarshaler static class GCKeeper { private static readonly ConcurrentDictionary _registry = new ConcurrentDictionary(); - public static void Keep(string name, object value) + public static void Keep(string name, object value) { _registry.AddOrUpdate(name, value, (key, existen) => value); } @@ -902,6 +898,34 @@ static class GCKeeper } } +/// +/// Artificial structure that represents SRTSOCKET +/// +public readonly struct SRTSOCKET : IDisposable +{ + /// + /// Not initialized socket structure + /// + public static readonly SRTSOCKET NotInitialized = 0; + + /// + /// Check socket is created + /// + public bool IsCreated { get { return _value > 0; } } + + /// + /// Check socket is valid + /// + public bool IsValid { get { return _value != -1; } } + + private readonly int _value; + SRTSOCKET(int value) => _value = value; + public void Dispose() { if(IsCreated) srt.srt_close(_value); } + public override string ToString() => $"{_value}"; + public static implicit operator SRTSOCKET(int b) => new SRTSOCKET(b); + public static implicit operator int(SRTSOCKET d) => d._value; +} + /// /// Artificial structure that represents arguments for srt_setlogflags(LogFlag) /// From 5a761af3c8c243f98e64fbc120c81a5810dd9218 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Thu, 23 Mar 2023 10:52:54 +0000 Subject: [PATCH 13/29] -SWIG on in teamcity if VS2019+ --- scripts/build-windows.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index 3ba9266b2..845a0c415 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -57,9 +57,9 @@ if ( $Env:APPVEYOR ) { Copy-Item -Path "C:\OpenSSL-v111-Win64" "C:\OpenSSL-Win64" -Recurse | Out-Null } -# if running within TeamCity, force SWIG and BONDING to ON (to avoid changing default behaviour on pre-existing CI systems) +# if running within TeamCity and VS2019 / 2022 compilation, force SWIG and BONDING to ON (to avoid changing default behaviour on pre-existing CI systems) # this should be removable ones master branch is merged to always have these params available (so CI can set them reliably itself) -if($Env:TEAMCITY_VERSION){ +if($Env:TEAMCITY_VERSION -and ($VS_VERSION -eq "2022" -or $VS_VERSION -eq "2019")){ $ENABLE_SWIG = "ON" $BONDING = "ON" } From 02c9634d890511e60edba2ef56cf5e0ddb902f11 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Thu, 23 Mar 2023 11:18:18 +0000 Subject: [PATCH 14/29] -update cmake to 3.25.3 (VS2022 support) --- scripts/build-windows.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index 845a0c415..3c65f32eb 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -28,7 +28,7 @@ param ( # cmake can be optionally installed (useful when running interactively on a developer station). # The URL for automatic download is defined later in the script, but it should be possible to just vary the # specific version set below and the URL should be stable enough to still work - you have been warned. -$cmakeVersion = "3.23.2" +$cmakeVersion = "3.25.3" # make all errors trigger a script stop, rather than just carry on $ErrorActionPreference = "Stop" @@ -57,9 +57,9 @@ if ( $Env:APPVEYOR ) { Copy-Item -Path "C:\OpenSSL-v111-Win64" "C:\OpenSSL-Win64" -Recurse | Out-Null } -# if running within TeamCity and VS2019 / 2022 compilation, force SWIG and BONDING to ON (to avoid changing default behaviour on pre-existing CI systems) +# if running within TeamCity and VS2022 compilation, force SWIG and BONDING to ON (to avoid changing default behaviour on pre-existing CI systems) # this should be removable ones master branch is merged to always have these params available (so CI can set them reliably itself) -if($Env:TEAMCITY_VERSION -and ($VS_VERSION -eq "2022" -or $VS_VERSION -eq "2019")){ +if($Env:TEAMCITY_VERSION -and ($VS_VERSION -eq "2022")){ $ENABLE_SWIG = "ON" $BONDING = "ON" } From e0e20d72a391451b555a2b042e23e196071c866b Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Thu, 23 Mar 2023 13:11:26 +0000 Subject: [PATCH 15/29] -remove use of span (fails with netstandard2.0) --- srtcore/srt.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index e2bd08de3..08ce5122e 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -343,7 +343,7 @@ void srt_dellogfa(LogFunctionalArea functionalArea); }; var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", post=" - $csinput = Encoding.UTF8.GetString(value_$csinput.AsSpan(0, (int)pin_value_len_$csinput.Target)); + $csinput = Encoding.UTF8.GetString(value_$csinput,0, (int)pin_value_len_$csinput.Target); pin_value_$csinput.Free(); pin_value_len_$csinput.Free(); transitive_$csinput.Dispose();" From 57c0df6c903a36f53facda2beb30a2d2362b98d9 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Tue, 28 Mar 2023 15:09:05 +0100 Subject: [PATCH 16/29] -fix cmake download -add socketID into delegate dictionary name on listen/connect --- scripts/create-nuget.ps1 | 2 +- srtcore/srt.i | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/create-nuget.ps1 b/scripts/create-nuget.ps1 index f27e2d256..dae4f67ef 100644 --- a/scripts/create-nuget.ps1 +++ b/scripts/create-nuget.ps1 @@ -20,7 +20,7 @@ Get-ChildItem $packageDir -Filter *.zip | Foreach-Object { Expand-Archive -Force -Path $_.FullName -DestinationPath $(Join-Path $packageDir "extracted") } -nuget pack .\nuget\SrtSharp\SrtSharp.nuspec -version $VERSION +nuget pack .\nuget\SrtSharp\SrtSharp.nuspec -version $VERSION-alpha # if antyhing returned non-zero, throw to cause failure in CI if( $LASTEXITCODE -ne 0 ) { diff --git a/srtcore/srt.i b/srtcore/srt.i index 08ce5122e..82794ee69 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -194,7 +194,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) (srt_listen_callback_fn *) "SrtListenCallbackDelegate" %typemap(csin, pre=" - GCKeeper.Keep(nameof(SrtListenCallbackDelegate), $csinput); + GCKeeper.Keep($"{nameof(SrtListenCallbackDelegate)}-{clr}", hook_fn); var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" ) srt_listen_callback_fn* "delegatePtr_$csinput" @@ -202,7 +202,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) (srt_connect_callback_fn *) "SrtConnectCallbackDelegate" %typemap(csin, pre=" - GCKeeper.Keep(nameof(SrtConnectCallbackDelegate), $csinput); + GCKeeper.Keep($"{nameof(SrtConnectCallbackDelegate)}-{clr}", hook_fn); var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" ) srt_connect_callback_fn* "delegatePtr_$csinput" From 464dec32d81969426b1eadcc67ab405a1d2535b1 Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 8 Apr 2023 10:36:44 +0300 Subject: [PATCH 17/29] Fixed callback delegates associated with socket GC lifetime --- srtcore/srt.i | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 82794ee69..8d0f206b7 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -194,7 +194,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) (srt_listen_callback_fn *) "SrtListenCallbackDelegate" %typemap(csin, pre=" - GCKeeper.Keep($"{nameof(SrtListenCallbackDelegate)}-{clr}", hook_fn); + GCKeeper.Keep($\"{nameof(SrtListenCallbackDelegate)}-{lsn}\", hook_fn); var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" ) srt_listen_callback_fn* "delegatePtr_$csinput" @@ -202,7 +202,7 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s %typemap(cstype) (srt_connect_callback_fn *) "SrtConnectCallbackDelegate" %typemap(csin, pre=" - GCKeeper.Keep($"{nameof(SrtConnectCallbackDelegate)}-{clr}", hook_fn); + GCKeeper.Keep($\"{nameof(SrtConnectCallbackDelegate)}-{clr}\", hook_fn); var delegatePtr_$csinput = Marshal.GetFunctionPointerForDelegate($csinput);" ) srt_connect_callback_fn* "delegatePtr_$csinput" @@ -920,7 +920,15 @@ public readonly struct SRTSOCKET : IDisposable private readonly int _value; SRTSOCKET(int value) => _value = value; - public void Dispose() { if(IsCreated) srt.srt_close(_value); } + public void Dispose() + { + if(IsCreated!) return; + + srt.srt_close(_value); + // Remove any kept delegate pointers associated with an socket + GCKeeper.Forget($"{nameof(SrtConnectCallbackDelegate)}-{_value}"); + GCKeeper.Forget($"{nameof(SrtListenCallbackDelegate)}-{_value}"); + } public override string ToString() => $"{_value}"; public static implicit operator SRTSOCKET(int b) => new SRTSOCKET(b); public static implicit operator int(SRTSOCKET d) => d._value; From 3103108479eb339680575bff99a34a426289b3fc Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 29 Apr 2023 14:31:56 +0300 Subject: [PATCH 18/29] Added EPOLL mappings --- srtcore/srt.i | 251 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 248 insertions(+), 3 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 8d0f206b7..42f3462c4 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -224,20 +224,177 @@ You can now reference the SrtSharp lib in your .Net Core projects. Ensure the s ) const int* events "pinAddr_$csinput" -// --- Map all SRTSOCKET to artificial SRTSOCKET structure -%typemap(cstype) SRTSOCKET "SRTSOCKET" - // --- Map srt_getlasterror return type to SRT_ERRNO %typemap(csbase) SRT_ERRNO "int" %typemap(cstype) int srt_getlasterror "SRT_ERRNO" %typemap(csout) int srt_getlasterror { return (SRT_ERRNO)$imcall; } +// ------------------------------------------------------------ +// ------------------------- SRTSOCKET ------------------------ +// ------------------------------------------------------------ + +// --- Map all SRTSOCKET to artificial SRTSOCKET structure +%typemap(cstype) SRTSOCKET "SRTSOCKET" + // --- Map srt_create_socket return type to SRTSOCKET %typemap(cstype) int srt_create_socket "SRTSOCKET" // --- Map srt_accept return type to SRTSOCKET %typemap(cstype) int srt_accept "SRTSOCKET" +// ------------------------------------------------------------ +// ------------------------- SYSSOCKET ------------------------ +// ------------------------------------------------------------ + +// --- Map all SYSSOCKET to artificial SYSSOCKET structure +%typemap(cstype) SYSSOCKET "SYSSOCKET" + +// ------------------------------------------------------------ +// ------------------------- EPOLL ---------------------------- +// ------------------------------------------------------------ +// --- Map all int eid to artificial EPOLL structure +%typemap(cstype) int eid "EPOLL" + +// --- Map srt_epoll_create return type to EPOLL +%typemap(cstype) int srt_epoll_create "EPOLL" + +// srt_epoll_wait method parameters transformations +%typemap(in) (SRTSOCKET* , int*) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int*)args->Arg2; +} +%typemap(cstype) (SRTSOCKET* , int*) "SRTSOCKET[]" +%typemap(imtype) (SRTSOCKET* , int*) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + GCHandle? pin_array_$csinput = null; + GCHandle? pin_array_len_$csinput = null; + if($csinput != null) + { + Array.Clear($csinput, 0, $csinput.Length); + var array_len_$csinput = $csinput.Length; + pin_array_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned); + pin_array_len_$csinput = GCHandle.Alloc(array_len_$csinput, GCHandleType.Pinned); + } + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_array_$csinput?.AddrOfPinnedObject() ?? IntPtr.Zero, + Arg2 = pin_array_len_$csinput?.AddrOfPinnedObject() ?? IntPtr.Zero + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_array_$csinput?.Free(); + pin_array_len_$csinput?.Free(); + transitive_$csinput.Dispose();" + ) (SRTSOCKET* , int*) + "input_$csinput" + +// Apply mappings for different functions with the same signature (SRTSOCKET* , int*) +%apply (SRTSOCKET* , int*) +{ + (SRTSOCKET* readfds, int* rnum), + (SRTSOCKET* writefds, int* wnum) +} + +%typemap(in) (SYSSOCKET* , int*) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int*)args->Arg2; +} +%typemap(cstype) (SYSSOCKET* , int*) "SYSSOCKET[]" +%typemap(imtype) (SYSSOCKET* , int*) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + GCHandle? pin_array_$csinput = null; + GCHandle? pin_array_len_$csinput = null; + if($csinput != null) + { + Array.Clear($csinput, 0, $csinput.Length); + var array_len_$csinput = $csinput.Length; + pin_array_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned); + pin_array_len_$csinput = GCHandle.Alloc(array_len_$csinput, GCHandleType.Pinned); + } + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_array_$csinput?.AddrOfPinnedObject() ?? IntPtr.Zero, + Arg2 = pin_array_len_$csinput?.AddrOfPinnedObject() ?? IntPtr.Zero + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_array_$csinput?.Free(); + pin_array_len_$csinput?.Free(); + transitive_$csinput.Dispose();" + ) (SYSSOCKET* , int*) + "input_$csinput" + +// Apply mappings for different functions with the same signature (SYSSOCKET* , int*) +%apply (SYSSOCKET* , int*) +{ + (SYSSOCKET* lrfds, int* lrnum), + (SYSSOCKET* lwfds, int* lwnum) +} + +// srt_epoll_uwait method parameters transformations +/* +%inline +{ + int srt_getepoll_event_size() + { + return sizeof(SRT_EPOLL_EVENT); + } +} +*/ + +//%ignore srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +%ignore SRT_EPOLL_EVENT_STR; +//int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT1* fdsSet, int fdsSize, int64_t msTimeOut); + +%typemap(in) (SRT_EPOLL_EVENT* , int) { + TransitiveArguments * args = (TransitiveArguments *)$input; + $1 = args->Arg1; + $2 = (int)args->Arg2; +} +%typemap(cstype) (SRT_EPOLL_EVENT* , int) "SRT_EPOLL_EVENT[]" +%typemap(imtype) (SRT_EPOLL_EVENT* , int) "global::System.Runtime.InteropServices.HandleRef" +%typemap(csin, + pre=" + GCHandle? pin_array_$csinput = null; + int array_len_$csinput = 0; + if($csinput != null) + { + array_len_$csinput = $csinput.Length; + pin_array_$csinput = GCHandle.Alloc($csinput, GCHandleType.Pinned); + } + + var transitive_$csinput = new TransitiveArguments + { + Arg1 = pin_array_$csinput?.AddrOfPinnedObject() ?? IntPtr.Zero, + Arg2 = new IntPtr(array_len_$csinput) + }; + var input_$csinput = TransitiveArguments.getCPtr(transitive_$csinput);", + post=" + pin_array_$csinput?.Free(); + transitive_$csinput.Dispose();" + ) (SRT_EPOLL_EVENT* , int) + "input_$csinput" + +// Apply mappings for different functions with the same signature (SRT_EPOLL_EVENT* , int) +%apply (SRT_EPOLL_EVENT* , int) +{ + (SRT_EPOLL_EVENT* fdsSet, int fdsSize) +} + +// Rework srt_epoll_set flags type +%inline{ typedef enum SRT_EPOLL_FLAGS SRT_EPOLL_FLAGS_TRANSIENT; } +%ignore srt_epoll_set(int eid, int32_t flags); +int32_t srt_epoll_set(int eid, SRT_EPOLL_FLAGS_TRANSIENT flags); + +// ------------------------------------------------------------ +// ------------------------- LOGGING -------------------------- +// ------------------------------------------------------------ // --- Map srt_setlogflags member to artificial LogFlag structure // --- structure itself defined in csharp module imports below // Type mappings for IM wrapper INT -> managed struct @@ -320,6 +477,9 @@ void srt_dellogfa(LogFunctionalArea functionalArea); ) (const int* fara, size_t fara_size) "input_$csinput" +// ------------------------------------------------------------ +// ------------------------- FLAGS ---------------------------- +// ------------------------------------------------------------ // ---- ADD ADDITIONAL method for string flags manipulation // -- srt_getsockflag_string method %typemap(in) (void* stringOptVal, int* stringOptLen) { @@ -917,6 +1077,11 @@ public readonly struct SRTSOCKET : IDisposable /// Check socket is valid /// public bool IsValid { get { return _value != -1; } } + + /// + /// Get socket status + /// + public SRT_SOCKSTATUS Status { get { return srt.srt_getsockstate(_value); } } private readonly int _value; SRTSOCKET(int value) => _value = value; @@ -934,6 +1099,70 @@ public readonly struct SRTSOCKET : IDisposable public static implicit operator int(SRTSOCKET d) => d._value; } +/// +/// Artificial structure that represents SYSSOCKET +/// +public readonly struct SYSSOCKET : IDisposable +{ + /// + /// Not initialized socket structure + /// + public static readonly SYSSOCKET NotInitialized = 0; + + /// + /// Check socket is created + /// + public bool IsCreated { get { return _value > 0; } } + + /// + /// Check socket is valid + /// + public bool IsValid { get { return _value != -1; } } + + private readonly int _value; + SYSSOCKET(int value) => _value = value; + public void Dispose() + { + if(IsCreated!) return; + } + public override string ToString() => $"{_value}"; + public static implicit operator SYSSOCKET(int b) => new SYSSOCKET(b); + public static implicit operator int(SYSSOCKET d) => d._value; +} + +/// +/// Artificial structure that represents EPOLL +/// +public readonly struct EPOLL : IDisposable +{ + /// + /// Not initialized epoll structure + /// + public static readonly EPOLL NotInitialized = 0; + + /// + /// Check epoll is created + /// + public bool IsCreated { get { return _value > 0; } } + + /// + /// Check epoll is valid + /// + public bool IsValid { get { return _value != -1; } } + + private readonly int _value; + EPOLL(int value) => _value = value; + public void Dispose() + { + if(IsCreated!) return; + + srt.srt_epoll_release(_value); + } + public override string ToString() => $"{_value}"; + public static implicit operator EPOLL(int b) => new EPOLL(b); + public static implicit operator int(EPOLL d) => d._value; +} + /// /// Artificial structure that represents arguments for srt_setlogflags(LogFlag) /// @@ -1155,4 +1384,20 @@ public readonly struct LogFunctionalArea public static implicit operator int(LogFunctionalArea d) => d._value; } +/// +/// SRT_EPOLL_EVENT structure definition +/// +[StructLayout(LayoutKind.Sequential)] +public struct SRT_EPOLL_EVENT +{ + /// + /// The user socket (SRT socket) + /// + public SRTSOCKET Socket; + + /// + /// Event flags that report readiness of this socket + /// + public SRT_EPOLL_OPT Events; +} %} \ No newline at end of file From efa8fa25c1b16983a3834685caca7995cfc5f5d3 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Thu, 4 May 2023 15:00:37 +0100 Subject: [PATCH 19/29] -clear null-forgiveness flag (not C# 8) --- srtcore/srt.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 42f3462c4..230cd2d07 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -1087,7 +1087,7 @@ public readonly struct SRTSOCKET : IDisposable SRTSOCKET(int value) => _value = value; public void Dispose() { - if(IsCreated!) return; + if(IsCreated) return; srt.srt_close(_value); // Remove any kept delegate pointers associated with an socket @@ -1123,7 +1123,7 @@ public readonly struct SYSSOCKET : IDisposable SYSSOCKET(int value) => _value = value; public void Dispose() { - if(IsCreated!) return; + if(IsCreated) return; } public override string ToString() => $"{_value}"; public static implicit operator SYSSOCKET(int b) => new SYSSOCKET(b); @@ -1154,7 +1154,7 @@ public readonly struct EPOLL : IDisposable EPOLL(int value) => _value = value; public void Dispose() { - if(IsCreated!) return; + if(IsCreated) return; srt.srt_epoll_release(_value); } From 571c07c2bb33991b0fa011e899d38f8957c24ed8 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Fri, 5 May 2023 17:19:36 +0100 Subject: [PATCH 20/29] -change ordering of SWIG cmake policies inclusion --- CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 513d952a2..cbb00d209 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1342,17 +1342,19 @@ endif() srt_add_example(testcapi-connect.c) endif() + #SWIG support - adding bindings for other languages into a new library that statically include the main SRT lib -cmake_policy(SET CMP0078 NEW) -cmake_policy(SET CMP0086 NEW) +if(ENABLE_SWIG) -#older cmakes do not understand this policy, so filter (VS2015 AppVeyor cmake is too old) -if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.21) - cmake_policy(SET CMP0122 NEW) -endif() + #older cmakes do not understand SWIG in a trusted manner (e.g. VS2015 AppVeyor cmake is too old, and Travis Xenial) + if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.21) + cmake_policy(SET CMP0078 NEW) + cmake_policy(SET CMP0086 NEW) + cmake_policy(SET CMP0122 NEW) + else + message(FATAL_ERROR "ENABLE_SWIG is set, but cmake version is not at least 3.21 and SWIG support may be broken on earlier editions") + endif() -#experimental SWIG support for csharp -if(ENABLE_SWIG) #on windows, there is no swig just in the path - nuget / scripted downloads must be pointed at (linux it just works) if(MICROSOFT) #if nuget has been used to install swig in the project packages, bind to that From 75839582c14abecdfc0216119ed47ee0061ac079 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Fri, 5 May 2023 17:26:23 +0100 Subject: [PATCH 21/29] -added missed () from cmake else --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbb00d209..0d9ef21ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1351,7 +1351,7 @@ if(ENABLE_SWIG) cmake_policy(SET CMP0078 NEW) cmake_policy(SET CMP0086 NEW) cmake_policy(SET CMP0122 NEW) - else + else() message(FATAL_ERROR "ENABLE_SWIG is set, but cmake version is not at least 3.21 and SWIG support may be broken on earlier editions") endif() From 0afb40b090852ad16fe16cf1d408c4e297728b09 Mon Sep 17 00:00:00 2001 From: Lewis Kirkaldie Date: Mon, 8 May 2023 12:14:06 +0100 Subject: [PATCH 22/29] -skip enum define due to conditionals --- srtcore/srt.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 230cd2d07..fc5e03d25 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -801,7 +801,7 @@ void srt_dellogfa(LogFunctionalArea functionalArea); typedef enum { SRTO_INT_CONNTIMEO = SRTO_CONNTIMEO, - SRTO_INT_CRYPTOMODE = SRTO_CRYPTOMODE, + //SRTO_INT_CRYPTOMODE = SRTO_CRYPTOMODE, //TODO: Remove when AEAD option is no longer conditional SRTO_INT_EVENT = SRTO_EVENT, SRTO_INT_FC = SRTO_FC, SRTO_INT_GROUPCONNECT = SRTO_GROUPCONNECT, From 661cc376da8e03124c91c7d009afb395b0a678e4 Mon Sep 17 00:00:00 2001 From: Shkolka Volodymyr Date: Sat, 17 Jun 2023 12:25:58 +0300 Subject: [PATCH 23/29] Fixed ps1 file permission --- scripts/build-lin-docker.ps1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/build-lin-docker.ps1 diff --git a/scripts/build-lin-docker.ps1 b/scripts/build-lin-docker.ps1 old mode 100644 new mode 100755 From 44a548d70818b605ea4d57a6a3eac67ab53904c7 Mon Sep 17 00:00:00 2001 From: Volodymyr Shkolka Date: Sun, 7 Jan 2024 10:20:57 +0200 Subject: [PATCH 24/29] Nuget package configuration update --- scripts/create-nuget.ps1 | 15 ++++++------ scripts/nuget/SrtSharp/SrtSharp.nuspec | 8 +------ scripts/nuget/SrtSharp/build/SrtSharp.props | 23 ------------------- scripts/nuget/SrtSharp/build/SrtSharp.targets | 15 ------------ 4 files changed, 8 insertions(+), 53 deletions(-) delete mode 100644 scripts/nuget/SrtSharp/build/SrtSharp.props delete mode 100644 scripts/nuget/SrtSharp/build/SrtSharp.targets diff --git a/scripts/create-nuget.ps1 b/scripts/create-nuget.ps1 index dae4f67ef..39cea0242 100644 --- a/scripts/create-nuget.ps1 +++ b/scripts/create-nuget.ps1 @@ -7,20 +7,19 @@ ################################################################################ param ( - [Parameter()][String]$PACKAGEFOLDER = "package", - [Parameter()][String]$VERSION = "1.5.1.0" + [Parameter()][String]$VERSION = "1.5.1.10199", + [Parameter()][String]$BUILD_DIR = "_nuget" ) # make all errors trigger a script stop, rather than just carry on $ErrorActionPreference = "Stop" -$packageDir = Join-Path $PSScriptRoot "../" $PACKAGEFOLDER -Resolve +$projectRoot = Join-Path $PSScriptRoot "/.." -Resolve +$sourceDir = Join-Path "$projectRoot" "package" +$targetDir = Join-Path "$projectRoot" "$BUILD_DIR" +$nuspecPath = Join-Path "$projectRoot" "scripts/nuget/SrtSharp/SrtSharp.nuspec" -Get-ChildItem $packageDir -Filter *.zip | Foreach-Object { - Expand-Archive -Force -Path $_.FullName -DestinationPath $(Join-Path $packageDir "extracted") -} - -nuget pack .\nuget\SrtSharp\SrtSharp.nuspec -version $VERSION-alpha +nuget pack $nuspecPath -version $VERSION-alpha -OutputDirectory $targetDir # if antyhing returned non-zero, throw to cause failure in CI if( $LASTEXITCODE -ne 0 ) { diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec index 98ea332cf..40c061afe 100644 --- a/scripts/nuget/SrtSharp/SrtSharp.nuspec +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -16,12 +16,6 @@ - - - - - - - + \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/build/SrtSharp.props b/scripts/nuget/SrtSharp/build/SrtSharp.props deleted file mode 100644 index 60c909ff5..000000000 --- a/scripts/nuget/SrtSharp/build/SrtSharp.props +++ /dev/null @@ -1,23 +0,0 @@ - - - - - $(MSBuildThisFileDirectory)\..\sources\;%(AdditionalIncludeDirectories) - - - $(MSBuildThisFileDirectory)\..\runtimes\win-$(PlatformTarget)\native\release;%(AdditionalLibraryDirectories) - cinecoder.lib;%(AdditionalDependencies) - - - $(MSBuildThisFileDirectory)\..\sources\interfaces;$(MSBuildThisFileDirectory)\..\sources\interfaces\Systems;%(AdditionalIncludeDirectories) - - - - - - - - - - - \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/build/SrtSharp.targets b/scripts/nuget/SrtSharp/build/SrtSharp.targets deleted file mode 100644 index 9ec270d9d..000000000 --- a/scripts/nuget/SrtSharp/build/SrtSharp.targets +++ /dev/null @@ -1,15 +0,0 @@ - - - - True - False - - - - - - - - - - \ No newline at end of file From cd30b7464377a846470fe4cbd09240c781617594 Mon Sep 17 00:00:00 2001 From: Volodymyr Shkolka Date: Sun, 7 Jan 2024 10:59:31 +0200 Subject: [PATCH 25/29] Added readme file --- scripts/nuget/SrtSharp/SrtSharp.nuspec | 1 + scripts/nuget/SrtSharp/readme.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 scripts/nuget/SrtSharp/readme.md diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec index 40c061afe..fa51ee71e 100644 --- a/scripts/nuget/SrtSharp/SrtSharp.nuspec +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -17,5 +17,6 @@ + \ No newline at end of file diff --git a/scripts/nuget/SrtSharp/readme.md b/scripts/nuget/SrtSharp/readme.md new file mode 100644 index 000000000..70ee46061 --- /dev/null +++ b/scripts/nuget/SrtSharp/readme.md @@ -0,0 +1,19 @@ +# SrtSharp + +## Overview +SrtSharp is a .NET wrapper for the official [Haivision SRT](https://github.com/Haivision/srt) developed by [Cinegy](https://www.cinegy.com/). This package utilizes [SWIG](https://www.swig.org/) for interfacing with the SRT library, along with custom adaptations to fit .NET standards. + +## Features +- **.NET Standard 2.0 Library**: Ensures compatibility with a wide range of .NET applications. +- **Cross-Platform Compatibility**: Supports both x64 Linux and Windows runtimes. +- **Efficient SRT Handling**: Leverages Haivision's SRT for low-latency video streaming. + +## Installation +You can install SrtSharp via NuGet Package Manager or the dotnet CLI: + +```shell +dotnet add package SrtSharp +``` + +## Examples +For practical examples of how to use SrtSharp, please refer to the [Cinegy.SRT GitHub repository](https://github.com/Cinegy/Cinegy.SRT). From f29b2ebd7634e2517285ca7181b89dfd1f1db47d Mon Sep 17 00:00:00 2001 From: Volodymyr Shkolka Date: Sun, 7 Jan 2024 11:13:14 +0200 Subject: [PATCH 26/29] Added proper readme file --- scripts/nuget/SrtSharp/SrtSharp.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec index fa51ee71e..0766a5b39 100644 --- a/scripts/nuget/SrtSharp/SrtSharp.nuspec +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -10,6 +10,7 @@ false Secure, Reliable Transport Library with C# bindings, published by Cinegy GmbH 2019 SRT Haivision Systems Inc (packaged by Cinegy GmbH). All rights reserved. + readme.md From 97bd1700add4d7b77357905c883c51faecb79213 Mon Sep 17 00:00:00 2001 From: Volodymyr Shkolka Date: Sun, 7 Jan 2024 11:16:52 +0200 Subject: [PATCH 27/29] Fixed Nuget readme metadata --- scripts/nuget/SrtSharp/SrtSharp.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nuget/SrtSharp/SrtSharp.nuspec b/scripts/nuget/SrtSharp/SrtSharp.nuspec index 0766a5b39..458c64551 100644 --- a/scripts/nuget/SrtSharp/SrtSharp.nuspec +++ b/scripts/nuget/SrtSharp/SrtSharp.nuspec @@ -10,7 +10,7 @@ false Secure, Reliable Transport Library with C# bindings, published by Cinegy GmbH 2019 SRT Haivision Systems Inc (packaged by Cinegy GmbH). All rights reserved. - readme.md + readme.md From e9fbd51edfebc7e44b01c9cce66df701df716456 Mon Sep 17 00:00:00 2001 From: Volodymyr Shkolka Date: Sat, 13 Jan 2024 11:16:01 +0200 Subject: [PATCH 28/29] Fixed .NET 8 SocketAddress internal fields access issue --- srtcore/srt.i | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index fc5e03d25..94d5d55e7 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -972,16 +972,37 @@ public delegate void SrtConnectCallbackDelegate( public static class MarshalExtensions { - private static readonly FieldInfo SocketAddressBufferField = typeof(SocketAddress).GetField("Buffer", BindingFlags.Instance | BindingFlags.NonPublic); - private static readonly FieldInfo SocketAddressInternalSizeField = typeof(SocketAddress).GetField("InternalSize", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly FieldInfo SocketAddressBufferField; + private static readonly FieldInfo SocketAddressInternalSizeField; + + static MarshalExtensions() + { + // Internal fields of SocketAddress class are used to access the internal buffer and size + // But starting from NET 8 internal fields were renamed, so we need to find them in a different way + var socketAddressFields = typeof(SocketAddress).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); + SocketAddressBufferField = socketAddressFields.FirstOrDefault(f => f.FieldType == typeof(byte[])); + SocketAddressInternalSizeField = socketAddressFields.FirstOrDefault(f => f.FieldType == typeof(int)); + } internal static byte[] GetInternalBuffer(this SocketAddress socketAddress) { + if (SocketAddressBufferField == null) + { + var message = $"Unable to find the internal buffer field in the {nameof(SocketAddress)} class."; + throw new PlatformNotSupportedException(message); + } + return (byte[])SocketAddressBufferField.GetValue(socketAddress); } internal static void SetInternalSize(this SocketAddress socketAddress, int size) { + if (SocketAddressInternalSizeField == null) + { + var message = $"Unable to find the internal buffer size field in the {nameof(SocketAddress)} class."; + throw new PlatformNotSupportedException(message); + } + SocketAddressInternalSizeField.SetValue(socketAddress, size); } From 33a150ce42cbc119be53c579a7c1a9a686060a15 Mon Sep 17 00:00:00 2001 From: Volodymyr Shkolka Date: Sat, 1 Jun 2024 12:12:45 +0300 Subject: [PATCH 29/29] Fixed Dispose call on sockets --- srtcore/srt.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srtcore/srt.i b/srtcore/srt.i index 94d5d55e7..495f51ef5 100644 --- a/srtcore/srt.i +++ b/srtcore/srt.i @@ -1108,7 +1108,7 @@ public readonly struct SRTSOCKET : IDisposable SRTSOCKET(int value) => _value = value; public void Dispose() { - if(IsCreated) return; + if(!IsCreated) return; srt.srt_close(_value); // Remove any kept delegate pointers associated with an socket @@ -1144,7 +1144,7 @@ public readonly struct SYSSOCKET : IDisposable SYSSOCKET(int value) => _value = value; public void Dispose() { - if(IsCreated) return; + if(!IsCreated) return; } public override string ToString() => $"{_value}"; public static implicit operator SYSSOCKET(int b) => new SYSSOCKET(b); @@ -1175,7 +1175,7 @@ public readonly struct EPOLL : IDisposable EPOLL(int value) => _value = value; public void Dispose() { - if(IsCreated) return; + if(!IsCreated) return; srt.srt_epoll_release(_value); }