summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/actions/webrtc-download/action.yml51
-rw-r--r--.github/workflows/build_release.yml188
-rw-r--r--.gitmodules11
-rw-r--r--README.md55
-rw-r--r--SConstruct434
-rw-r--r--builders.py236
-rw-r--r--deps/build/.gitignore (renamed from webrtc/.gitignore)0
m---------deps/libdatachannel0
m---------deps/openssl0
m---------godot-cpp0
m---------godot-cpp-3.x0
-rwxr-xr-xmisc/scripts/file_format.sh2
-rw-r--r--misc/webrtc.gdextension18
-rw-r--r--misc/webrtc.tres (renamed from misc/gdnlib.tres)24
-rw-r--r--src/WebRTCLibDataChannel.cpp232
-rw-r--r--src/WebRTCLibDataChannel.hpp98
-rw-r--r--src/WebRTCLibPeerConnection.cpp382
-rw-r--r--src/WebRTCLibPeerConnection.hpp111
-rw-r--r--src/init_gdextension.cpp72
-rw-r--r--src/init_gdnative.cpp (renamed from src/init.cpp)10
-rw-r--r--src/net/WebRTCDataChannelNative.cpp38
-rw-r--r--src/net/WebRTCDataChannelNative.hpp40
-rw-r--r--src/net/WebRTCPeerConnectionNative.cpp24
-rw-r--r--src/net/WebRTCPeerConnectionNative.hpp22
24 files changed, 1030 insertions, 1018 deletions
diff --git a/.github/actions/webrtc-download/action.yml b/.github/actions/webrtc-download/action.yml
deleted file mode 100644
index 75e268d..0000000
--- a/.github/actions/webrtc-download/action.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-name: 'Get WebRTC Library'
-description: 'Get pre-build statically linked WebRTC library from Faless/webrtc-builds'
-inputs:
- repo:
- description: 'Base repository'
- required: true
- default: "godotengine/webrtc-actions"
- release:
- description: 'Release tag'
- required: true
- default: '4472-33644-92ba70c'
- webrtc-base-name:
- description: 'The WebRTC version'
- required: true
- default: "webrtc-33644-92ba70c"
- out-dir:
- description: 'Directory where to extract the library'
- required: true
- default: "webrtc"
- platform:
- description: 'Platform to download'
- required: true
- archs:
- description: 'Space separated list of architecture to fetch'
- required: true
-runs:
- using: "composite"
- steps:
- - shell: bash
- env:
- RTC_BASE_URL: https://github.com/${{ inputs.repo }}/releases/download/${{ inputs.release }}/${{ inputs.webrtc-base-name }}
- run: |
- cd ${{ inputs.out-dir }}
-
- libplat=${{ inputs.platform }}
- if [ "${{ inputs.platform }}" = "windows" ]; then
- libplat=win
- elif [ "${{ inputs.platform }}" = "osx" ]; then
- libplat=mac
- fi
-
- for arch in ${{ inputs.archs }}
- do
- echo "Downloading ${{ env.RTC_BASE_URL }}-${{ inputs.platform }}-${arch}.tar.gz"
- curl -L ${{ env.RTC_BASE_URL }}-${libplat}-${arch}.tar.gz -o ${arch}.tar.gz
- tar -xzf ${arch}.tar.gz
- done
-
- mv lib ${{ inputs.platform }}
- ls -l
- ls -l *
diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml
index 2ab5787..d9cfd6e 100644
--- a/.github/workflows/build_release.yml
+++ b/.github/workflows/build_release.yml
@@ -33,77 +33,84 @@ jobs:
name: 🔧 Build
needs: static-checks
strategy:
+ fail-fast: false
matrix:
include:
# Android
- platform: android
- arch: 'x86'
- sconsflags: 'android_arch=x86'
+ arch: 'x86_32'
+ gdnative_flags: 'android_arch=x86'
+ sconsflags: ''
os: 'ubuntu-20.04'
- platform: android
- arch: 'x64'
- sconsflags: 'android_arch=x86_64'
+ arch: 'x86_64'
+ gdnative_flags: 'android_arch=x86_64'
+ sconsflags: ''
os: 'ubuntu-20.04'
- platform: android
- arch: 'arm'
- sconsflags: 'android_arch=armv7'
+ arch: 'arm32'
+ gdnative_flags: 'android_arch=armv7'
+ sconsflags: ''
os: 'ubuntu-20.04'
- platform: android
arch: 'arm64'
- sconsflags: 'android_arch=arm64v8'
+ gdnative_flags: 'android_arch=arm64v8'
+ sconsflags: ''
os: 'ubuntu-20.04'
# iOS
- platform: ios
- arch: 'x64'
- sconsflags: 'ios_arch=x86_64 ios_simulator=true'
- os: 'macos-latest'
- - platform: ios
- arch: 'arm'
- sconsflags: 'ios_arch=armv7'
+ arch: 'x86_64'
+ gdnative_flags: 'ios_arch=x86_64'
+ sconsflags: 'ios_simulator=true'
os: 'macos-latest'
- platform: ios
arch: 'arm64'
- sconsflags: 'ios_arch=arm64'
- os: 'macos-latest'
+ gdnative_flags: 'ios_arch=arm64'
+ sconsflags: ''
+ os: 'macos-11'
+
# Linux
- platform: linux
- arch: 'x86'
- sconsflags: 'bits=32'
+ arch: 'x86_32'
+ gdnative_flags: 'bits=32'
+ sconsflags: ''
os: 'ubuntu-20.04'
- platform: linux
- arch: 'x64'
- sconsflags: 'bits=64'
+ arch: 'x86_64'
+ gdnative_flags: 'bits=64'
+ sconsflags: ''
os: 'ubuntu-20.04'
# macOS
- platform: osx
- arch: 'x64'
- sconsflags: 'bits=64'
- os: 'macos-latest'
+ arch: 'x86_64'
+ gdnative_flags: 'macos_arch=x86_64 bits=64'
+ sconsflags: ''
+ os: 'macos-11'
- platform: osx
+ gdnative_flags: 'macos_arch=arm64 bits=64'
arch: 'arm64'
- sconsflags: 'bits=64 macos_arch=arm64 macos_sdk_path=/Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk/'
- os: 'macos-10.15'
+ sconsflags: ''
+ os: 'macos-11'
# Windows
- platform: windows
- arch: 'x86'
- sconsflags: 'bits=32'
- os: 'windows-latest'
+ arch: 'x86_32'
+ gdnative_flags: 'bits=32'
+ sconsflags: 'use_mingw=yes'
+ os: 'ubuntu-20.04'
msvc_arch: amd64_x86
- platform: windows
- arch: 'x64'
- sconsflags: 'bits=64'
- os: 'windows-latest'
+ arch: 'x86_64'
+ gdnative_flags: 'bits=64'
+ sconsflags: 'use_mingw=yes'
+ os: 'ubuntu-20.04'
msvc_arch: amd64
env:
- SCONSFLAGS: ${{ matrix.sconsflags }} platform=${{ matrix.platform }} --jobs=2
- NDK_VERSION: 22b
- ANDROID_NDK_ROOT: ${{github.workspace}}/android-ndk-r22b
- MSVC_VARS: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat'
+ SCONSFLAGS: ${{ matrix.sconsflags }} platform=${{ matrix.platform }} arch=${{ matrix.arch }} --jobs=2
defaults:
run:
@@ -114,31 +121,22 @@ jobs:
with:
submodules: recursive
- - name: Cache NDK
- id: cache-ndk
- if: ${{ matrix.platform == 'android' }}
- uses: actions/cache@v2
- with:
- path: ${{ env.ANDROID_NDK_ROOT }}
- key: ndk-${{ env.NDK_VERSION }}
-
- - name: Download NDK
- if: ${{ matrix.platform == 'android' && steps.cache-ndk.outputs.cache-hit != 'true' }}
- id: setup-ndk
- run: |
- cd ${{ github.workspace }}
- curl -L https://dl.google.com/android/repository/android-ndk-r${{ env.NDK_VERSION }}-linux-x86_64.zip -o ndk.zip
- unzip ndk.zip
- ls
-
- - name: Setup MSVC build environment for ${{ matrix.msvc_arch }}
+ - name: Install Windows build dependencies
if: ${{ matrix.platform == 'windows' }}
- run: "'${{ env.MSVC_VARS }}' ${{ matrix.msvc_arch }}"
+ run: |
+ sudo apt-get update
+ sudo apt-get install build-essential mingw-w64
+ sudo update-alternatives --set i686-w64-mingw32-gcc /usr/bin/i686-w64-mingw32-gcc-posix
+ sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix
+ sudo update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix
+ sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
+ dpkg -l | grep ii | grep mingw
+ update-alternatives --get-selections | grep mingw
- name: Install Linux build dependencies
if: ${{ matrix.platform == 'linux' }}
run: |
- sudo apt-get install build-essential gcc-multilib wget g++-multilib
+ sudo apt-get install build-essential gcc-multilib g++-multilib
- name: Set up Python 3.x
uses: actions/setup-python@v2
@@ -152,35 +150,25 @@ jobs:
python -m pip install scons
python --version
scons --version
+ cmake --version
- - name: Get WebRTC package for ${{ matrix.platform }} - ${{ matrix.arch }}
- uses: ./.github/actions/webrtc-download
- with:
- platform: ${{ matrix.platform }}
- archs: ${{ matrix.arch }}
-
- - name: Fix godot-cpp revision and file names for OSX arm64 build.
- if: ${{ matrix.platform == 'osx' && matrix.arch == 'arm64' }}
+ - name: Compile Extension - debug - ${{ matrix.platform }} - ${{ matrix.arch }}
run: |
- cd godot-cpp
- git checkout e08ecdc28c5409cb5366027227e996c342dcee93
- rm -rf src/gen/
- rm -rf include/gen/
- mkdir bin
- ln -s libgodot-cpp.osx.debug.64.a bin/libgodot-cpp.osx.debug.arm64.a
- ln -s libgodot-cpp.osx.release.64.a bin/libgodot-cpp.osx.release.arm64.a
-
- - name: Compilation ${{ matrix.platform }} - ${{ matrix.arch }} - godot-cpp
+ scons target=debug generate_bindings=yes
+
+ - name: Compile GDNative - debug - ${{ matrix.platform }} - ${{ matrix.arch }}
run: |
- scons -C godot-cpp target=debug generate_bindings=yes
- scons -C godot-cpp target=release
+ scons target=debug generate_bindings=yes ${{ matrix.gdnative_flags }} godot_version=3
- - name: Compilation ${{ matrix.platform }} - ${{ matrix.arch }} - webrtc-native
+ - name: Compile Extension - release - ${{ matrix.platform }} - ${{ matrix.arch }}
run: |
- scons target=debug
scons target=release
- - uses: actions/upload-artifact@v2
+ - name: Compile GDNative - release ${{ matrix.platform }} - ${{ matrix.arch }}
+ run: |
+ scons target=release ${{ matrix.gdnative_flags }} godot_version=3
+
+ - uses: actions/upload-artifact@v3
with:
name: ${{ github.job }}-${{ matrix.platform }}-${{ matrix.arch }}
path: bin/*
@@ -191,32 +179,54 @@ jobs:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: recursive
- - uses: actions/download-artifact@v2
+ - uses: actions/download-artifact@v3
with:
path: artifacts
+ - name: Bundle licenses.
+ run: |
+ cp LICENSE artifacts/LICENSE.webrtc-native
+ cp deps/libdatachannel/LICENSE artifacts/LICENSE.libdatachannel
+ cp deps/openssl/LICENSE.txt artifacts/LICENSE.openssl
+ cp deps/libdatachannel/deps/libjuice/LICENSE artifacts/LICENSE.libjuice
+ cp deps/libdatachannel/deps/usrsctp/LICENSE.md artifacts/LICENSE.usrsctp
+ cp deps/libdatachannel/deps/libsrtp/LICENSE artifacts/LICENSE.libsrtp
+ cp deps/libdatachannel/deps/json/LICENSE.MIT artifacts/LICENSE.json
+ cp deps/libdatachannel/deps/plog/LICENSE artifacts/LICENSE.plog
+
- name: Package artifacts for release
run: |
mkdir release
cd release
- for name in webrtc webrtc_debug
+
+ ls -R
+
+ for version in extension gdnative
do
- mkdir -p ${name}/lib/
- find ../artifacts -wholename "*/${name}/lib/*" | xargs cp -t ${name}/lib/
- find ../artifacts -wholename "*/${name}/${name}.tres" | head -n 1 | xargs cp -t ${name}/
+ for name in webrtc webrtc_debug
+ do
+ destdir="${version}/${name}"
+ mkdir -p ${destdir}/lib
+ find ../artifacts -wholename "*/${destdir}/lib/*" | xargs cp -t ${destdir}/lib/
+ find ../artifacts -wholename "*/${destdir}/${name}.tres" -or -wholename "*/${destdir}/${name}.gdextension" | head -n 1 | xargs cp -t ${destdir}/
+ find ../artifacts -wholename "*/LICENSE*" | xargs cp -t ${destdir}/
+ cd ${version}
+ zip -r ../godot-${version}-${name}.zip ${name}
+ cd ..
+ done
done
- zip -r godot-webrtc-native-release.zip webrtc
- zip -r godot-webrtc-native-debug.zip webrtc_debug
ls -R
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
- name: godot-webrtc-native-debug.zip
- path: release/godot-webrtc-native-debug.zip
+ name: godot-webrtc-extension
+ path: release/*-extension-*.zip
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
- name: godot-webrtc-native-release.zip
- path: release/godot-webrtc-native-release.zip
+ name: godot-webrtc-gdnative
+ path: release/*-gdnative-*.zip
diff --git a/.gitmodules b/.gitmodules
index 64fc4d4..1aa8d48 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,12 @@
+[submodule "godot-cpp-3.x"]
+ path = godot-cpp-3.x
+ url = https://github.com/godotengine/godot-cpp.git
[submodule "godot-cpp"]
path = godot-cpp
- url = https://github.com/GodotNativeTools/godot-cpp
+ url = https://github.com/godotengine/godot-cpp.git
+[submodule "libdatachannel"]
+ path = deps/libdatachannel
+ url = https://github.com/paullouisageneau/libdatachannel.git
+[submodule "openssl"]
+ path = deps/openssl
+ url = https://github.com/openssl/openssl.git
diff --git a/README.md b/README.md
index 556417b..b2e87f9 100644
--- a/README.md
+++ b/README.md
@@ -7,65 +7,44 @@
### Compiling
-Clone this repository with the following command to checkout both [godot-cpp](https://github.com/godotengine/godot-cpp) and [godot-headers](https://github.com/godotengine/godot-headers) dependencies.
+Clone this repository with the following command to checkout all the dependencies: [godot-cpp](https://github.com/godotengine/godot-cpp), [openssl](https://www.openssl.org/) and [libdatachannel](https://github.com/paullouisageneau/libdatachannel) (and sub-dependencies).
```
$ git clone --recurse-submodules https://github.com/godotengine/webrtc-native.git
```
-Note that if you wish to use a specific branch, add the -b option to the clone command:
-```
-$ git clone --recurse-submodules -b 3.2 https://github.com/godotengine/webrtc-native.git
-```
-
If you already checked out the branch use the following commands to update the dependencies:
```
$ git submodule update --init --recursive
```
-Right now our directory structure should look like this:
-```
-webrtc-native/
-├─bin/
-├─godot-cpp/
-| └─godot-headers/
-├─src/
-└─webrtc/
-```
+### Compiling the extension.
+
+To build the GDExtension version of the plugin (Godot 4.0) run the following command from the `webrtc-native` folder:
-### Compiling the cpp bindings library
-First, we need to compile our cpp bindings library:
```
-$ cd godot-cpp
-$ scons platform=<your platform> generate_bindings=yes
-$ cd ..
+$ scons platform=<your platform>
```
-> Replace `<your platform>` with either `windows`, `linux` or `osx`.
-
-> Include `use_llvm=yes` for using clang++
+This will build all the required dependencies into a single shared library.
-> Include `target=runtime` to build a runtime build (windows only at the moment)
+To build the GDNative version of the plugin (Godot 3.x) run the following command instead:
-> Include `target=release` or `target=debug` for release or debug build.
-
-> The resulting library will be created in `godot-cpp/bin/`, take note of its name as it will be different depending on platform.
-
-### Building WebRTC
+```
+$ scons platform=<your platform> godot_version=3
+```
-Building WebRTC is quite a complex task, involves huge downloads and long build times, and produces multiple output libraries that needs to bundled together.
+> Replace `<your platform>` with either `windows`, `linux`, `osx`, `android`, or `ios`.
-To make things easier, a set of [GitHub Actions](https://docs.github.com/en/actions) are used to generate the library for this plugin, [available in this repository](https://github.com/godotengine/webrtc-actions).
+> Include `target=release` or `target=debug` for release or debug build (default is `debug`).
-Alternatively, [**download the latest pre-compiled libraries**](https://github.com/godotengine/webrtc-actions/releases).
+The resulting library and associated `tres` or `gdextension` will be created in `bin/[extension|gdnative]/webrtc[_debug]` depending on the `target` and `godot_version`.
-Extract content of `include` into `webrtc/include` and content of `bin` into `webrtc/<your platform>`
+You simply need to copy that folder to the root folder of your project. Note that you will have to build the library for all the desired export platforms.
-### Compiling the plugin.
+### License
-```
-$ scons platform=<your platform> target=<your target>
-```
+The `webrtc-native` plugin is licensed under the MIT license (see [LICENSE](https://github.com/godotengine/webrtc-native/blob/master/LICENSE)), while `libdatachannel` and one of its dependencies (`libjuice`) are licensed under LGPLv2.1 or later, see [libdatachannel LICENSE](https://github.com/paullouisageneau/libdatachannel/blob/master/LICENSE) and [libjuice LICENSE](https://github.com/paullouisageneau/libjuice/blob/master/LICENSE).
-The generated library and associated `tres` will be placed in `bin/webrtc/` or `bin/webrtc_debug/` according to the desired target. You simply need to copy that folder to the root folder of your project.
+Make sure you understand and comply with the LGPLv2.1 license when redistributing this plugin.
diff --git a/SConstruct b/SConstruct
index 4fbe324..56bb711 100644
--- a/SConstruct
+++ b/SConstruct
@@ -2,17 +2,7 @@
import os, sys, platform, json, subprocess
-if sys.version_info < (3,):
-
- def decode_utf8(x):
- return x
-
-
-else:
- import codecs
-
- def decode_utf8(x):
- return codecs.utf_8_decode(x)[0]
+import builders
def add_sources(sources, dirpath, extension):
@@ -21,367 +11,123 @@ def add_sources(sources, dirpath, extension):
sources.append(dirpath + "/" + f)
-def gen_gdnative_lib(target, source, env):
- for t in target:
- with open(t.srcnode().path, "w") as w:
- w.write(
- decode_utf8(source[0].get_contents())
- .replace("{GDNATIVE_PATH}", os.path.splitext(t.name)[0])
- .replace("{TARGET}", env["target"])
- )
+def replace_flags(flags, replaces):
+ for k, v in replaces.items():
+ if k in flags:
+ flags[flags.index(k)] = v
env = Environment()
-
-target_arch = ARGUMENTS.get("b", ARGUMENTS.get("bits", "64"))
-target_platform = ARGUMENTS.get("p", ARGUMENTS.get("platform", "linux"))
-if target_platform == "windows":
- # This makes sure to keep the session environment variables on windows,
- # that way you can run scons in a vs 2017 prompt and it will find all the required tools
- if target_arch == "64":
- env = Environment(ENV=os.environ, TARGET_ARCH="amd64")
- else:
- env = Environment(ENV=os.environ, TARGET_ARCH="x86")
-
-env.Append(BUILDERS={"GDNativeLibBuilder": Builder(action=gen_gdnative_lib)})
-
-customs = ["custom.py"]
-opts = Variables(customs, ARGUMENTS)
-
-opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler", False))
-opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release")))
-
-opts.Add(EnumVariable("android_arch", "Target Android architecture", "armv7", ["armv7", "arm64v8", "x86", "x86_64"]))
-opts.Add(
- "android_api_level",
- "Target Android API level",
- "18" if ARGUMENTS.get("android_arch", "armv7") in ["armv7", "x86"] else "21",
-)
-opts.Add(
- "ANDROID_NDK_ROOT",
- "Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.",
- os.environ.get("ANDROID_NDK_ROOT", None),
-)
-
-opts.Add(EnumVariable("ios_arch", "Target iOS architecture", "arm64", ["armv7", "arm64", "x86_64"]))
-opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
-opts.Add(
- "IPHONEPATH",
- "Path to iPhone toolchain",
- "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
-)
-opts.Add("macos_sdk_path", "macOS SDK path", "")
-opts.Add(EnumVariable("macos_arch", "Target macOS architecture", "x86_64", ["x86_64", "arm64"]))
-
-# Update environment (parse options)
+opts = Variables(["customs.py"], ARGUMENTS)
+opts.Add(EnumVariable("godot_version", "The Godot target version", "4", ["3", "4"]))
opts.Update(env)
-target = env["target"]
-
-if target_platform == "android":
- target_arch = env["android_arch"]
-elif target_platform == "ios":
- target_arch = env["ios_arch"]
-
-host_platform = platform.system()
-# Local dependency paths, adapt them to your setup
-godot_headers = ARGUMENTS.get("headers", "godot-cpp/godot-headers")
-godot_cpp_headers = ARGUMENTS.get("godot_cpp_headers", "godot-cpp/include")
-godot_cpp_lib_dir = ARGUMENTS.get("godot_cpp_lib_dir", "godot-cpp/bin")
-result_path = os.path.join("bin", "webrtc" if env["target"] == "release" else "webrtc_debug", "lib")
-lib_prefix = ""
-
-# Convenience check to enforce the use_llvm overrides when CXX is clang(++)
-if "CXX" in env and "clang" in os.path.basename(env["CXX"]):
- env["use_llvm"] = True
-
-if target_platform == "linux":
- env["CXX"] = "g++"
-
- # LLVM
- if env["use_llvm"]:
- if "clang++" not in os.path.basename(env["CXX"]):
- env["CC"] = "clang"
- env["CXX"] = "clang++"
- env["LINK"] = "clang++"
-
- if env["target"] == "debug":
- env.Prepend(CCFLAGS=["-g3"])
- env.Append(LINKFLAGS=["-rdynamic"])
- else:
- env.Prepend(CCFLAGS=["-O3"])
-
- env.Append(CCFLAGS=["-fPIC", "-std=c++14"])
-
- if target_arch == "32":
- env.Append(CCFLAGS=["-m32"])
- env.Append(LINKFLAGS=["-m32"])
- elif target_arch == "64":
- env.Append(CCFLAGS=["-m64"])
- env.Append(LINKFLAGS=["-m64"])
- # i386 does not like static libstdc++
- env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
-
-elif target_platform == "windows":
- if host_platform == "Windows":
-
- lib_prefix = "lib"
- env.Append(LINKFLAGS=["/WX"])
- if target == "debug":
- env.Append(CCFLAGS=["/EHsc", "/D_DEBUG", "/MDd"])
- else:
- env.Append(CCFLAGS=["/O2", "/EHsc", "/DNDEBUG", "/MD"])
- else:
- if target_arch == "32":
- env["CXX"] = "i686-w64-mingw32-g++"
- elif target_arch == "64":
- env["CXX"] = "x86_64-w64-mingw32-g++"
-
- if env["target"] == "debug":
- env.Append(CCFLAGS=["-Og", "-g"])
- elif env["target"] == "release":
- env.Append(CCFLAGS=["-O3"])
-
- env.Append(CCFLAGS=["-std=c++14", "-Wwrite-strings"])
- env.Append(LINKFLAGS=["--static", "-Wl,--no-undefined", "-static-libgcc", "-static-libstdc++"])
-
-elif target_platform == "osx":
- if env["use_llvm"]:
- env["CXX"] = "clang++"
-
- # Only 64-bits is supported for OS X
- target_arch = "64"
- if env["macos_arch"] != "x86_64":
- target_arch = "arm64"
+if env["godot_version"] == "3":
+ env = SConscript("godot-cpp-3.x/SConstruct")
- env.Append(CCFLAGS=["-std=c++14", "-arch", env["macos_arch"]])
- env.Append(LINKFLAGS=["-arch", env["macos_arch"], "-framework", "Cocoa", "-Wl,-undefined,dynamic_lookup"])
+ # Patch base env
+ replace_flags(env["CCFLAGS"], {
+ "-mios-simulator-version-min=10.0": "-mios-simulator-version-min=11.0",
+ "-miphoneos-version-min=10.0": "-miphoneos-version-min=11.0",
+ "/std:c++14": "/std:c++17",
+ "-std=c++14": "-std=c++17",
+ })
- if env["macos_sdk_path"]:
- env.Append(CCFLAGS=["-isysroot", env["macos_sdk_path"]])
- env.Append(LINKFLAGS=["-isysroot", env["macos_sdk_path"]])
+ env = env.Clone()
if env["target"] == "debug":
- env.Append(CCFLAGS=["-Og", "-g"])
- elif env["target"] == "release":
- env.Append(CCFLAGS=["-O3"])
-
-elif target_platform == "ios":
- if env["ios_simulator"]:
- sdk_name = "iphonesimulator"
- env.Append(CCFLAGS=["-mios-simulator-version-min=10.0"])
- env["LIBSUFFIX"] = ".simulator" + env["LIBSUFFIX"]
- else:
- sdk_name = "iphoneos"
- env.Append(CCFLAGS=["-miphoneos-version-min=10.0"])
-
- try:
- sdk_path = decode_utf8(subprocess.check_output(["xcrun", "--sdk", sdk_name, "--show-sdk-path"]).strip())
- except (subprocess.CalledProcessError, OSError):
- raise ValueError("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
-
- compiler_path = env["IPHONEPATH"] + "/usr/bin/"
- env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
-
- env["CC"] = compiler_path + "clang"
- env["CXX"] = compiler_path + "clang++"
- env["AR"] = compiler_path + "ar"
- env["RANLIB"] = compiler_path + "ranlib"
-
- env.Append(CCFLAGS=["-std=c++14", "-arch", env["ios_arch"], "-isysroot", sdk_path])
- env.Append(
- LINKFLAGS=["-arch", env["ios_arch"], "-Wl,-undefined,dynamic_lookup", "-isysroot", sdk_path, "-F" + sdk_path]
- )
-
- if env["target"] == "debug":
- env.Append(CCFLAGS=["-Og", "-g"])
- elif env["target"] == "release":
- env.Append(CCFLAGS=["-O3"])
-
-
-elif target_platform == "android":
- # Verify NDK root
- if not "ANDROID_NDK_ROOT" in env:
- raise ValueError(
- "To build for Android, ANDROID_NDK_ROOT must be defined. Please set ANDROID_NDK_ROOT to the root folder of your Android NDK installation."
- )
-
- # Validate API level
- api_level = int(env["android_api_level"])
- if target_arch in ["arm64v8", "x86_64"] and api_level < 21:
- print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
- env["android_api_level"] = "21"
- api_level = 21
-
- # Setup toolchain
- toolchain = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/"
- if host_platform == "Windows":
- toolchain += "windows"
- import platform as pltfm
-
- if pltfm.machine().endswith("64"):
- toolchain += "-x86_64"
- elif host_platform == "Linux":
- toolchain += "linux-x86_64"
- elif host_platform == "Darwin":
- toolchain += "darwin-x86_64"
-
- # Get architecture info
- arch_info_table = {
- "armv7": {
- "march": "armv7-a",
- "target": "armv7a-linux-androideabi",
- "tool_path": "arm-linux-androideabi",
- "compiler_path": "armv7a-linux-androideabi",
- "ccflags": ["-mfpu=neon"],
- },
- "arm64v8": {
- "march": "armv8-a",
- "target": "aarch64-linux-android",
- "tool_path": "aarch64-linux-android",
- "compiler_path": "aarch64-linux-android",
- "ccflags": [],
- },
- "x86": {
- "march": "i686",
- "target": "i686-linux-android",
- "tool_path": "i686-linux-android",
- "compiler_path": "i686-linux-android",
- "ccflags": ["-mstackrealign"],
- },
- "x86_64": {
- "march": "x86-64",
- "target": "x86_64-linux-android",
- "tool_path": "x86_64-linux-android",
- "compiler_path": "x86_64-linux-android",
- "ccflags": [],
- },
- }
- arch_info = arch_info_table[target_arch]
-
- # Setup tools
- env["CC"] = toolchain + "/bin/clang"
- env["CXX"] = toolchain + "/bin/clang++"
-
- env.Append(
- CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"]
- )
- env.Append(CCFLAGS=arch_info["ccflags"])
- env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
-
- if env["target"] == "debug":
- env.Append(CCFLAGS=["-Og", "-g"])
- elif env["target"] == "release":
- env.Append(CCFLAGS=["-O3"])
-
+ env.Append(CPPDEFINES=["DEBUG_ENABLED"])
+
+ if env["platform"] == "windows" and env["use_mingw"]:
+ env.Append(LINKFLAGS=["-static-libgcc"])
+
+ # Normalize suffix
+ if env["platform"] in ["windows", "linux"]:
+ env["arch"] = "x86_32" if env["bits"] == "32" else "x86_64"
+ env["arch_suffix"] = env["arch"]
+ elif env["platform"] == "osx":
+ env["arch"] = env["macos_arch"]
+ env["arch_suffix"] = env["arch"]
+ elif env["platform"] == "ios":
+ env["arch"] = "arm32" if env["ios_arch"] == "armv7" else env["ios_arch"]
+ env["arch_suffix"] = env["ios_arch"] + (".simulator" if env["ios_simulator"] else "")
+ elif env["platform"] == "android":
+ env["arch"] = {
+ "armv7": "arm32",
+ "arm64v8": "arm64",
+ "x86": "x86_32",
+ "x86_64": "x86_64",
+ }[env["android_arch"]]
+ env["arch_suffix"] = env["arch"]
else:
- print("No valid target platform selected.")
- sys.exit(1)
-
-# Godot CPP bindings
-env.Append(CPPPATH=[godot_headers])
-env.Append(CPPPATH=[godot_cpp_headers, godot_cpp_headers + "/core", godot_cpp_headers + "/gen"])
-env.Append(LIBPATH=[godot_cpp_lib_dir])
-env.Append(
- LIBS=[
- "%sgodot-cpp.%s.%s.%s%s"
- % (lib_prefix, target_platform, target, target_arch, ".simulator" if env["ios_simulator"] else "")
- ]
-)
-
-# WebRTC stuff
-webrtc_dir = "webrtc"
-lib_name = "libwebrtc_full"
-lib_path = os.path.join(webrtc_dir, target_platform)
+ env = SConscript("godot-cpp/SConstruct")
+ replace_flags(env["CCFLAGS"], {
+ "-mios-simulator-version-min=10.0": "-mios-simulator-version-min=11.0",
+ "-miphoneos-version-min=10.0": "-miphoneos-version-min=11.0",
+ })
+ env = env.Clone()
-lib_path += {
- "32": "/x86",
- "64": "/x64",
- "armv7": "/arm",
- "arm64v8": "/arm64",
- "arm64": "/arm64",
- "x86": "/x86",
- "x86_64": "/x64",
-}[target_arch]
-
-if target == "debug":
- lib_path += "/Debug"
-else:
- lib_path += "/Release"
-
-env.Append(CPPPATH=[webrtc_dir + "/include", webrtc_dir + "/include/third_party/abseil-cpp"])
+opts.Update(env)
-if target_platform == "linux":
- env.Append(LIBS=[lib_name, "atomic"])
- env.Append(LIBPATH=[lib_path])
- # env.Append(CCFLAGS=["-std=c++11"])
- env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_LINUX"])
- env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
+target = env["target"]
+result_path = os.path.join("bin", "gdnative" if env["godot_version"] == "3" else "extension", "webrtc" if env["target"] == "release" else "webrtc_debug")
-elif target_platform == "windows":
- # Mostly VisualStudio
- if env["CC"] == "cl":
- env.Append(CCFLAGS=["/DWEBRTC_WIN", "/DWIN32_LEAN_AND_MEAN", "/DNOMINMAX", "/DRTC_UNUSED=", "/DNO_RETURN="])
- env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in ["secur32", "advapi32", "winmm", lib_name]])
- env.Append(LIBPATH=[lib_path])
- # Mostly "gcc"
- else:
- env.Append(
- CCFLAGS=[
- "-DWINVER=0x0603",
- "-D_WIN32_WINNT=0x0603",
- "-DWEBRTC_WIN",
- "-DWIN32_LEAN_AND_MEAN",
- "-DNOMINMAX",
- "-DRTC_UNUSED=",
- "-DNO_RETURN=",
- ]
- )
- env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in ["secur32", "advapi32", "winmm", lib_name]])
- env.Append(LIBPATH=[lib_path])
+# Dependencies
+deps_source_dir = "deps"
+env.Append(BUILDERS={
+ "BuildOpenSSL": env.Builder(action=builders.ssl_action, emitter=builders.ssl_emitter),
+ "BuildLibDataChannel": env.Builder(action=builders.rtc_action, emitter=builders.rtc_emitter),
+})
-elif target_platform == "osx":
- env.Append(LIBS=[lib_name])
- env.Append(LIBPATH=[lib_path])
- env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_MAC"])
- env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
+# SSL
+ssl = env.BuildOpenSSL(env.Dir(builders.get_ssl_build_dir(env)), env.Dir(builders.get_ssl_source_dir(env)))
-elif target_platform == "ios":
- env.Append(LIBS=[lib_name])
- env.Append(LIBPATH=[lib_path])
- env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_MAC", "-DWEBRTC_IOS"])
- env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
+env.Prepend(CPPPATH=[builders.get_ssl_include_dir(env)])
+env.Prepend(LIBPATH=[builders.get_ssl_build_dir(env)])
+env.Append(LIBS=[ssl])
-elif target_platform == "android":
- env.Append(LIBS=["log"])
- env.Append(LIBS=[lib_name])
- env.Append(LIBPATH=[lib_path])
- env.Append(CCFLAGS=["-DWEBRTC_POSIX", "-DWEBRTC_LINUX", "-DWEBRTC_ANDROID"])
- env.Append(CCFLAGS=["-DRTC_UNUSED=''", "-DNO_RETURN=''"])
+# RTC
+rtc = env.BuildLibDataChannel(env.Dir(builders.get_rtc_build_dir(env)), [env.Dir(builders.get_rtc_source_dir(env))] + ssl)
- if target_arch == "arm64v8":
- env.Append(CCFLAGS=["-DWEBRTC_ARCH_ARM64", "-DWEBRTC_HAS_NEON"])
- elif target_arch == "armv7":
- env.Append(CCFLAGS=["-DWEBRTC_ARCH_ARM", "-DWEBRTC_ARCH_ARM_V7", "-DWEBRTC_HAS_NEON"])
+env.Append(LIBPATH=[builders.get_rtc_build_dir(env)])
+env.Append(CPPPATH=[builders.get_rtc_include_dir(env)])
+env.Prepend(LIBS=[rtc])
# Our includes and sources
env.Append(CPPPATH=["src/"])
sources = []
-add_sources(sources, "src/", "cpp")
-add_sources(sources, "src/net/", "cpp")
+sources.append(
+ [
+ "src/WebRTCLibDataChannel.cpp",
+ "src/WebRTCLibPeerConnection.cpp",
+ ]
+)
+if env["godot_version"] == "4":
+ sources.append("src/init_gdextension.cpp")
+else:
+ env.Append(CPPDEFINES=["GDNATIVE_WEBRTC"])
+ sources.append("src/init_gdnative.cpp")
+ add_sources(sources, "src/net/", "cpp")
-# Suffix
-suffix = ".%s.%s" % (target, target_arch)
-env["SHOBJSUFFIX"] = suffix + env["SHOBJSUFFIX"]
+env.Depends(sources, [ssl, rtc])
# Make the shared library
-result_name = "webrtc_native.%s.%s.%s" % (target_platform, target, target_arch) + env["SHLIBSUFFIX"]
+result_name = "webrtc_native.{}.{}.{}{}".format(env["platform"], env["target"], env["arch_suffix"], env["SHLIBSUFFIX"])
+env.Depends(sources, ssl)
+
+if env["platform"] == "windows" and env["use_mingw"]:
+ env.Append(LIBS=["iphlpapi", "ws2_32", "bcrypt"])
-library = env.SharedLibrary(target=os.path.join(result_path, result_name), source=sources)
+library = env.SharedLibrary(target=os.path.join(result_path, "lib", result_name), source=sources)
Default(library)
# GDNativeLibrary
gdnlib = "webrtc"
if target != "release":
gdnlib += "_debug"
-Default(env.GDNativeLibBuilder([os.path.join("bin", gdnlib, gdnlib + ".tres")], ["misc/gdnlib.tres"]))
+ext = ".tres" if env["godot_version"] == "3" else ".gdextension"
+extfile = env.Substfile(os.path.join(result_path, gdnlib + ext), "misc/webrtc" + ext, SUBST_DICT={
+ "{GDNATIVE_PATH}": gdnlib,
+ "{TARGET}": env["target"],
+})
+Default(extfile)
diff --git a/builders.py b/builders.py
new file mode 100644
index 0000000..32dd1f3
--- /dev/null
+++ b/builders.py
@@ -0,0 +1,236 @@
+import os
+from SCons.Script import Environment
+
+
+def get_android_api(env):
+ return env["android_api_level"] if int(env["android_api_level"]) > 28 else "28"
+
+
+def get_deps_dir(env):
+ return env.Dir("#deps").abspath
+
+
+def get_deps_build_dir(env):
+ return get_deps_dir(env) + "/build/{}.{}.{}.dir".format(env["platform"], env["target"], env["arch_suffix"])
+
+
+def get_rtc_source_dir(env):
+ return get_deps_dir(env) + "/libdatachannel"
+
+
+def get_rtc_build_dir(env):
+ return get_deps_build_dir(env) + "/libdatachannel"
+
+
+def get_rtc_include_dir(env):
+ return get_rtc_source_dir(env) + "/include"
+
+
+def get_ssl_source_dir(env):
+ return get_deps_dir(env) + "/openssl"
+
+
+def get_ssl_build_dir(env):
+ return get_deps_build_dir(env) + "/openssl"
+
+
+def get_ssl_install_dir(env):
+ return get_ssl_build_dir(env) + "/dest"
+
+
+def get_ssl_include_dir(env):
+ return get_ssl_install_dir(env) + "/include"
+
+
+def ssl_emitter(target, source, env):
+ build_dir = get_ssl_build_dir(env)
+ libs = ["libssl.a", "libcrypto.a"]
+ install_dir = get_ssl_install_dir(env)
+ ssl_include = os.path.join(source[0].abspath, "include")
+ return [env.File(build_dir + "/" + l) for l in libs], source
+
+
+def ssl_action(target, source, env):
+ build_dir = get_ssl_build_dir(env)
+ source_dir = source[0].abspath
+
+ ssl_env = Environment()
+ install_dir = get_ssl_install_dir(env)
+ args = [
+ "no-ssl3",
+ "no-weak-ssl-ciphers",
+ "no-legacy",
+ "--prefix=%s" % install_dir,
+ "--openssldir=%s" % install_dir,
+ ]
+ if env["platform"] != "windows":
+ args.append("no-shared") # Windows "app" doesn't like static-only builds.
+ if env["platform"] == "linux":
+ if env["arch"] == "x86_32":
+ args.extend(["linux-x86"])
+ else:
+ args.extend(["linux-x86_64"])
+
+ elif env["platform"] == "android":
+ args.extend([
+ {
+ "arm64": "android-arm64",
+ "arm32": "android-arm",
+ "x86_32": "android-x86",
+ "x86_64": "android-x86_64",
+ }[env["arch"]],
+ "-D__ANDROID_API__=%s" % get_android_api(env),
+ ])
+ # Setup toolchain path.
+ ssl_env.PrependENVPath("PATH", os.path.dirname(env["CC"]))
+ ssl_env["ENV"]["ANDROID_NDK_ROOT"] = os.environ.get("ANDROID_NDK_ROOT", "")
+
+ elif env["platform"] == "osx":
+ if env["arch"] == "x86_64":
+ args.extend(["darwin64-x86_64"])
+ elif env["arch"] == "arm64":
+ args.extend(["darwin64-arm64"])
+ else:
+ raise ValueError("macOS architecture not supported: %s" % env["arch"])
+
+ elif env["platform"] == "ios":
+ if env["ios_simulator"]:
+ args.extend(["iossimulator-xcrun"])
+ elif env["arch"] == "arm32":
+ args.extend(["ios-xcrun"])
+ elif env["arch"] == "arm64":
+ args.extend(["ios64-xcrun"])
+ else:
+ raise ValueError("iOS architecture not supported: %s" % env["arch"])
+
+ elif env["platform"] == "windows":
+ if env["arch"] == "x86_32":
+ if env["use_mingw"]:
+ args.extend([
+ "mingw",
+ "--cross-compile-prefix=i686-w64-mingw32-",
+ ])
+ else:
+ args.extend(["VC-WIN32"])
+ else:
+ if env["use_mingw"]:
+ args.extend([
+ "mingw64",
+ "--cross-compile-prefix=x86_64-w64-mingw32-",
+ ])
+ else:
+ args.extend(["VC-WIN64A"])
+
+ jobs = env.GetOption("num_jobs")
+ ssl_env.Execute([
+ "mkdir -p " + build_dir, # TODO python?
+ ("cd %s && %s/Configure " % (build_dir, source_dir)) + " ".join(args),
+ "make -C %s -j%s" % (build_dir, jobs),
+ "make -C %s install_sw install_ssldirs -j%s" % (build_dir, jobs),
+ ]
+ )
+ return None
+
+
+def rtc_emitter(target, source, env):
+ build_dir = get_rtc_build_dir(env)
+ libs = ["libdatachannel-static.a", "libjuice-static.a", "libsrtp2.a", "libusrsctp.a"]
+ lib_paths = [
+ build_dir,
+ os.path.join(build_dir, "deps/libjuice"),
+ os.path.join(build_dir, "deps/libsrtp"),
+ os.path.join(build_dir, "deps/usrsctp/usrsctplib"),
+ ]
+ return [env.File(lib_paths[i] + "/" + libs[i]) for i in range(len(libs))], source
+
+
+def rtc_action(target, source, env):
+ build_dir = get_rtc_build_dir(env)
+ source_dir = source[0].abspath
+ args = [
+ "-B",
+ build_dir,
+ "-DUSE_NICE=0",
+ "-DNO_WEBSOCKET=1",
+ #"-DNO_MEDIA=1", # Windows builds fail without it.
+ "-DNO_EXAMPLES=1",
+ "-DNO_WEBSOCKET=1",
+ "-DNO_TESTS=1",
+ "-DOPENSSL_USE_STATIC_LIBS=1",
+ "-DOPENSSL_INCLUDE_DIR=%s" % get_ssl_include_dir(env),
+ "-DOPENSSL_SSL_LIBRARY=%s/libssl.a" % get_ssl_build_dir(env),
+ "-DOPENSSL_CRYPTO_LIBRARY=%s/libcrypto.a" % get_ssl_build_dir(env),
+ ]
+ if env["platform"] == "android":
+ abi = {
+ "arm64": "arm64-v8a",
+ "arm32": "armeabi-v7a",
+ "x86_32": "x86",
+ "x86_64": "x86_64",
+ }[env["arch"]]
+ args.extend([
+ "-DCMAKE_SYSTEM_NAME=Android",
+ "-DCMAKE_SYSTEM_VERSION=%s" % get_android_api(env),
+ "-DCMAKE_ANDROID_ARCH_ABI=%s" % abi,
+ "-DANDROID_ABI=%s" % abi,
+ "-DCMAKE_TOOLCHAIN_FILE=%s/build/cmake/android.toolchain.cmake" % os.environ.get("ANDROID_NDK_ROOT", ""),
+ "-DCMAKE_ANDROID_STL_TYPE=c++_static",
+ ])
+ elif env["platform"] == "linux":
+ if env["arch"] == "x86_32":
+ args.extend([
+ "-DCMAKE_C_FLAGS=-m32",
+ "-DCMAKE_CXX_FLAGS=-m32"
+ ])
+ else:
+ args.extend([
+ "-DCMAKE_C_FLAGS=-m64",
+ "-DCMAKE_CXX_FLAGS=-m64"
+ ])
+ elif env["platform"] == "osx":
+ if env["macos_deployment_target"] != "default":
+ args.extend(["-DCMAKE_OSX_DEPLOYMENT_TARGET=%s" % env["macos_deployment_target"]])
+ if env["arch"] == "x86_64":
+ args.extend(["-DCMAKE_OSX_ARCHITECTURES=x86_64"])
+ elif env["arch"] == "arm64":
+ args.extend(["-DCMAKE_OSX_ARCHITECTURES=arm64"])
+ else:
+ raise ValueError("OSX architecture not supported: %s" % env["arch"])
+ elif env["platform"] == "ios":
+ if env["arch"] == "universal":
+ raise ValueError("iOS architecture not supported: %s" % env["arch"])
+ args.extend([
+ "-DCMAKE_SYSTEM_NAME=iOS",
+ "-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
+ "-DCMAKE_OSX_ARCHITECTURES=%s" % env["arch"],
+ ])
+ if env["ios_simulator"]:
+ args.extend(["-DCMAKE_OSX_SYSROOT=iphonesimulator"])
+ elif env["platform"] == "windows":
+ args.extend(["-DOPENSSL_ROOT_DIR=%s" % get_ssl_build_dir(env)])
+ if env["arch"] == "x86_32":
+ if env["use_mingw"]:
+ args.extend([
+ "-G 'Unix Makefiles'",
+ "-DCMAKE_C_COMPILER=i686-w64-mingw32-gcc",
+ "-DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++",
+ "-DCMAKE_SYSTEM_NAME=Windows",
+ ])
+ else:
+ if env["use_mingw"]:
+ args.extend([
+ "-G 'Unix Makefiles'",
+ "-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc",
+ "-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++",
+ "-DCMAKE_SYSTEM_NAME=Windows"
+ ])
+
+ args.append(source_dir)
+ jobs = env.GetOption("num_jobs")
+ rtc_env = Environment()
+ rtc_env.Execute([
+ "cmake " + " ".join(args),
+ "cmake --build %s -t datachannel-static -j%s" % (build_dir, jobs),
+ ]
+ )
+ return None
diff --git a/webrtc/.gitignore b/deps/build/.gitignore
index d6b7ef3..d6b7ef3 100644
--- a/webrtc/.gitignore
+++ b/deps/build/.gitignore
diff --git a/deps/libdatachannel b/deps/libdatachannel
new file mode 160000
+Subproject 59cc9f214c7435c394e531b0c67ff1b86279f2b
diff --git a/deps/openssl b/deps/openssl
new file mode 160000
+Subproject 4d346a188c27bdf78aa76590c641e1217732ca4
diff --git a/godot-cpp b/godot-cpp
-Subproject 77d41fa179e40560f1e264ed483638bf5171377
+Subproject 40f5bfda226b71b629742c8314f2f175da7b523
diff --git a/godot-cpp-3.x b/godot-cpp-3.x
new file mode 160000
+Subproject ac572d5f847572ee90e32e014854894dda8b4ce
diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh
index e6e1fe2..3bb4d8d 100755
--- a/misc/scripts/file_format.sh
+++ b/misc/scripts/file_format.sh
@@ -20,6 +20,8 @@ while IFS= read -rd '' f; do
continue
elif [[ "$f" == "godot-cpp"* ]]; then
continue
+ elif [[ "$f" == "misc/patches"* ]]; then
+ continue
fi
# Ensure that files are UTF-8 formatted.
recode UTF-8 "$f" 2> /dev/null
diff --git a/misc/webrtc.gdextension b/misc/webrtc.gdextension
new file mode 100644
index 0000000..a00d370
--- /dev/null
+++ b/misc/webrtc.gdextension
@@ -0,0 +1,18 @@
+[configuration]
+
+entry_symbol = "webrtc_extension_init"
+
+[libraries]
+
+linux.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.x86_64.so"
+linux.x86_32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.x86_32.so"
+osx.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.x86_64.dylib"
+osx.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.arm64.dylib"
+windows.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.windows.{TARGET}.x86_64.dll"
+windows.x86_32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.windows.{TARGET}.x86_32.dll"
+android.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.arm64.so"
+android.arm32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.arm32.so"
+android.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86_64.so"
+android.x86_32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86_32.so"
+ios.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.arm64.dylib"
+ios.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.x86_64.simulator.dylib"
diff --git a/misc/gdnlib.tres b/misc/webrtc.tres
index eb291a9..9519d9f 100644
--- a/misc/gdnlib.tres
+++ b/misc/webrtc.tres
@@ -3,21 +3,21 @@
[resource]
singleton = true
reloadable = false
-entry/OSX.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.64.dylib"
+entry/OSX.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.x86_64.dylib"
entry/OSX.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.osx.{TARGET}.arm64.dylib"
-entry/Windows.64 = "res://{GDNATIVE_PATH}/lib/webrtc_native.windows.{TARGET}.64.dll"
-entry/Windows.32 = "res://{GDNATIVE_PATH}/lib/webrtc_native.windows.{TARGET}.32.dll"
-entry/X11.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.64.so"
-entry/X11.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.32.so"
-entry/Server.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.64.so"
-entry/Server.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.32.so"
-entry/Android.armeabi-v7a = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.armv7.so"
-entry/Android.arm64-v8a = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.arm64v8.so"
+entry/Windows.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.windows.{TARGET}.x86_64.dll"
+entry/Windows.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.windows.{TARGET}.x86_32.dll"
+entry/X11.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.x86_64.so"
+entry/X11.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.x86_32.so"
+entry/Server.64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.x86_64.so"
+entry/Server.32 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.linux.{TARGET}.x86_32.so"
+entry/Android.armeabi-v7a = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.arm32.so"
+entry/Android.arm64-v8a = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.arm64.so"
entry/Android.x64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86_64.so"
-entry/Android.x86 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86.so"
-entry/iOS.armv7 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.armv7.dylib"
+entry/Android.x86 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.android.{TARGET}.x86_32.so"
+entry/iOS.armv7 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.armv32.dylib"
entry/iOS.arm64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.arm64.dylib"
-entry/iOS.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.x86_64.dylib"
+entry/iOS.x86_64 = "res://{GDNATIVE_PATH}/lib/libwebrtc_native.ios.{TARGET}.x86_64.simulator.dylib"
dependency/Windows.64 = [ ]
dependency/Windows.32 = [ ]
dependency/X11.64 = [ ]
diff --git a/src/WebRTCLibDataChannel.cpp b/src/WebRTCLibDataChannel.cpp
index bab9c79..5c4ad5d 100644
--- a/src/WebRTCLibDataChannel.cpp
+++ b/src/WebRTCLibDataChannel.cpp
@@ -30,138 +30,155 @@
#include "WebRTCLibDataChannel.hpp"
+#ifdef GDNATIVE_WEBRTC
#include "GDNativeLibrary.hpp"
#include "NativeScript.hpp"
+#define ERR_UNAVAILABLE GODOT_ERR_UNAVAILABLE
+#define FAILED GODOT_FAILED
+#define ERR_INVALID_PARAMETER GODOT_ERR_INVALID_PARAMETER
+#define OK GODOT_OK
+#endif
-using namespace godot_webrtc;
-
-// Channel observer
-WebRTCLibDataChannel::ChannelObserver::ChannelObserver(WebRTCLibDataChannel *parent) {
- this->parent = parent;
-}
-
-void WebRTCLibDataChannel::ChannelObserver::OnMessage(const webrtc::DataBuffer &buffer) {
- parent->queue_packet(buffer.data.data<uint8_t>(), buffer.data.size());
-}
-
-void WebRTCLibDataChannel::ChannelObserver::OnStateChange() {
-}
+#include <stdio.h>
+#include <string.h>
+#include <cstring>
-void WebRTCLibDataChannel::ChannelObserver::OnBufferedAmountChange(uint64_t previous_amount) {
-}
+using namespace godot;
+using namespace godot_webrtc;
// DataChannel
-WebRTCLibDataChannel *WebRTCLibDataChannel::new_data_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel) {
+WebRTCLibDataChannel *WebRTCLibDataChannel::new_data_channel(std::shared_ptr<rtc::DataChannel> p_channel, bool p_negotiated) {
// Invalid channel result in NULL return
- ERR_FAIL_COND_V(p_channel.get() == nullptr, NULL);
+ ERR_FAIL_COND_V(!p_channel, nullptr);
+#ifdef GDNATIVE_WEBRTC
// Instance a WebRTCDataChannelGDNative object
- godot::WebRTCDataChannelGDNative *out = godot::WebRTCDataChannelGDNative::_new();
- // Set our implementation as it's script
- godot::NativeScript *script = godot::NativeScript::_new();
- script->set_library(godot::detail::get_wrapper<godot::GDNativeLibrary>((godot_object *)godot::gdnlib));
+ WebRTCDataChannelGDNative *native = WebRTCDataChannelGDNative::_new();
+ // Set our implementation as its script
+ NativeScript *script = NativeScript::_new();
+ script->set_library(detail::get_wrapper<GDNativeLibrary>((godot_object *)gdnlib));
script->set_class_name("WebRTCLibDataChannel");
- out->set_script(script);
-
- // Bind the data channel to the ScriptInstance userdata (our script)
- WebRTCLibDataChannel *tmp = out->cast_to<WebRTCLibDataChannel>(out);
- tmp->bind_channel(p_channel);
-
- return tmp;
+ native->set_script(script);
+ WebRTCLibDataChannel *out = native->cast_to<WebRTCLibDataChannel>(native);
+#else
+ WebRTCLibDataChannel *out = memnew(WebRTCLibDataChannel);
+#endif
+ // Bind the library data channel to our object.
+ out->bind_channel(p_channel, p_negotiated);
+ return out;
}
-void WebRTCLibDataChannel::bind_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel) {
- ERR_FAIL_COND(p_channel.get() == nullptr);
+void WebRTCLibDataChannel::bind_channel(std::shared_ptr<rtc::DataChannel> p_channel, bool p_negotiated) {
+ ERR_FAIL_COND(!p_channel);
channel = p_channel;
- label = p_channel->label();
- protocol = p_channel->protocol();
- channel->RegisterObserver(&observer);
-}
-
-void WebRTCLibDataChannel::queue_packet(const uint8_t *data, uint32_t size) {
+ negotiated = p_negotiated;
+
+ // Binding this should be fine as long as we call close when going out of scope.
+ p_channel->onMessage([this](auto message) {
+ if (std::holds_alternative<rtc::string>(message)) {
+ rtc::string str = std::get<rtc::string>(message);
+ queue_packet(reinterpret_cast<const uint8_t *>(str.c_str()), str.size(), true);
+ } else if (std::holds_alternative<rtc::binary>(message)) {
+ rtc::binary bin = std::get<rtc::binary>(message);
+ queue_packet(reinterpret_cast<const uint8_t *>(&bin[0]), bin.size(), false);
+ } else {
+ ERR_PRINT("Message parsing bug. Unknown message type.");
+ }
+ });
+ p_channel->onOpen([this]() {
+ channel_state = STATE_OPEN;
+ });
+ p_channel->onClosed([this]() {
+ channel_state = STATE_CLOSED;
+ });
+ p_channel->onError([](auto error) {
+ ERR_PRINT("Channel Error: " + String(std::string(error).c_str()));
+ });
+}
+
+void WebRTCLibDataChannel::queue_packet(const uint8_t *data, uint32_t size, bool p_is_string) {
mutex->lock();
- godot::PoolByteArray packet;
+ std::vector<uint8_t> packet;
packet.resize(size);
- {
- godot::PoolByteArray::Write w = packet.write();
- memcpy(w.ptr(), data, size);
- }
- packet_queue.push(packet);
+ memcpy(&packet[0], data, size);
+ packet_queue.push(QueuedPacket(packet, p_is_string));
mutex->unlock();
}
-void WebRTCLibDataChannel::set_write_mode(godot_int mode) {
+void WebRTCLibDataChannel::_set_write_mode(int64_t p_mode) {
+ ERR_FAIL_COND(p_mode != WRITE_MODE_TEXT && p_mode != WRITE_MODE_BINARY);
+ write_mode = (WriteMode)p_mode;
}
-godot_int WebRTCLibDataChannel::get_write_mode() const {
- return 0;
+int64_t WebRTCLibDataChannel::_get_write_mode() const {
+ return write_mode;
}
-bool WebRTCLibDataChannel::was_string_packet() const {
- return false;
+bool WebRTCLibDataChannel::_was_string_packet() const {
+ return current_packet.second;
}
-WebRTCLibDataChannel::ChannelState WebRTCLibDataChannel::get_ready_state() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, STATE_CLOSED);
- return (ChannelState)channel->state();
+int64_t WebRTCLibDataChannel::_get_ready_state() const {
+ ERR_FAIL_COND_V(!channel, STATE_CLOSED);
+ return channel_state;
}
-const char *WebRTCLibDataChannel::get_label() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, "");
- return label.c_str();
+String WebRTCLibDataChannel::_get_label() const {
+ ERR_FAIL_COND_V(!channel, "");
+ return channel->label().c_str();
}
-bool WebRTCLibDataChannel::is_ordered() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, false);
- return channel->ordered();
+bool WebRTCLibDataChannel::_is_ordered() const {
+ ERR_FAIL_COND_V(!channel, false);
+ return channel->reliability().unordered == false;
}
-int WebRTCLibDataChannel::get_id() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, -1);
- return channel->id();
+int64_t WebRTCLibDataChannel::_get_id() const {
+ ERR_FAIL_COND_V(!channel, -1);
+ return channel->id().value_or(-1);
}
-int WebRTCLibDataChannel::get_max_packet_life_time() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, 0);
- return channel->maxRetransmitTime();
+int64_t WebRTCLibDataChannel::_get_max_packet_life_time() const {
+ ERR_FAIL_COND_V(!channel, 0);
+ return channel->reliability().type == rtc::Reliability::Type::Timed ? std::get<std::chrono::milliseconds>(channel->reliability().rexmit).count() : -1;
}
-int WebRTCLibDataChannel::get_max_retransmits() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, 0);
- return channel->maxRetransmits();
+int64_t WebRTCLibDataChannel::_get_max_retransmits() const {
+ ERR_FAIL_COND_V(!channel, 0);
+ return channel->reliability().type == rtc::Reliability::Type::Rexmit ? std::get<int>(channel->reliability().rexmit) : -1;
}
-const char *WebRTCLibDataChannel::get_protocol() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, "");
- return protocol.c_str();
+String WebRTCLibDataChannel::_get_protocol() const {
+ ERR_FAIL_COND_V(!channel, "");
+ return channel->protocol().c_str();
}
-bool WebRTCLibDataChannel::is_negotiated() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, false);
- return channel->negotiated();
+bool WebRTCLibDataChannel::_is_negotiated() const {
+ ERR_FAIL_COND_V(!channel, false);
+ return negotiated;
}
-int WebRTCLibDataChannel::get_buffered_amount() const {
- ERR_FAIL_COND_V(channel.get() == nullptr, 0);
- return channel->buffered_amount();
+int64_t WebRTCLibDataChannel::_get_buffered_amount() const {
+ ERR_FAIL_COND_V(!channel, 0);
+ return channel->bufferedAmount();
}
-godot_error WebRTCLibDataChannel::poll() {
- return GODOT_OK;
+int64_t WebRTCLibDataChannel::_poll() {
+ return OK;
}
-void WebRTCLibDataChannel::close() {
- if (channel.get() != nullptr) {
- channel->Close();
- channel->UnregisterObserver();
+void WebRTCLibDataChannel::_close() try {
+ if (channel) {
+ channel->close();
}
+} catch (...) {
}
-godot_error WebRTCLibDataChannel::get_packet(const uint8_t **r_buffer, int *r_len) {
- ERR_FAIL_COND_V(packet_queue.empty(), GODOT_ERR_UNAVAILABLE);
+int64_t WebRTCLibDataChannel::_get_packet(const uint8_t **r_buffer, int32_t *r_len) {
+ ERR_FAIL_COND_V(packet_queue.empty(), ERR_UNAVAILABLE);
mutex->lock();
@@ -169,47 +186,46 @@ godot_error WebRTCLibDataChannel::get_packet(const uint8_t **r_buffer, int *r_le
current_packet = packet_queue.front();
packet_queue.pop();
// Set out buffer and size (buffer will be gone at next get_packet or close)
- *r_buffer = current_packet.read().ptr();
- *r_len = current_packet.size();
+ *r_buffer = &current_packet.first[0];
+ *r_len = current_packet.first.size();
mutex->unlock();
- return GODOT_OK;
+ return 0;
}
-godot_error WebRTCLibDataChannel::put_packet(const uint8_t *p_buffer, int p_len) {
- ERR_FAIL_COND_V(channel.get() == nullptr, GODOT_ERR_UNAVAILABLE);
-
- webrtc::DataBuffer webrtc_buffer(rtc::CopyOnWriteBuffer(p_buffer, p_len), true);
- ERR_FAIL_COND_V(!channel->Send(webrtc_buffer), GODOT_FAILED);
-
- return GODOT_OK;
+int64_t WebRTCLibDataChannel::_put_packet(const uint8_t *p_buffer, int64_t p_len) try {
+ ERR_FAIL_COND_V(!channel, FAILED);
+ ERR_FAIL_COND_V(channel->isClosed(), FAILED);
+ if (write_mode == WRITE_MODE_TEXT) {
+ std::string str(p_len, '\x00');
+ std::strncpy(str.data(), (const char *)p_buffer, p_len);
+ channel->send(str);
+ } else if (write_mode == WRITE_MODE_BINARY) {
+ channel->send(reinterpret_cast<const std::byte *>(p_buffer), p_len);
+ } else {
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
+ }
+ return OK;
+} catch (const std::exception &e) {
+ ERR_PRINT(e.what());
+ ERR_FAIL_V(FAILED);
}
-godot_int WebRTCLibDataChannel::get_available_packet_count() const {
+int64_t WebRTCLibDataChannel::_get_available_packet_count() const {
return packet_queue.size();
}
-godot_int WebRTCLibDataChannel::get_max_packet_size() const {
- return 1200;
-}
-
-void WebRTCLibDataChannel::_register_methods() {
+int64_t WebRTCLibDataChannel::_get_max_packet_size() const {
+ return 16384; // See RFC-8831 section 6.6: https://datatracker.ietf.org/doc/rfc8831/
}
-void WebRTCLibDataChannel::_init() {
- register_interface(&interface);
-}
-
-WebRTCLibDataChannel::WebRTCLibDataChannel() :
- observer(this) {
+WebRTCLibDataChannel::WebRTCLibDataChannel() {
mutex = new std::mutex;
}
WebRTCLibDataChannel::~WebRTCLibDataChannel() {
- close();
- if (_owner) {
- register_interface(NULL);
- }
+ _close();
+ channel = nullptr;
delete mutex;
}
diff --git a/src/WebRTCLibDataChannel.hpp b/src/WebRTCLibDataChannel.hpp
index 63c7fdd..b79eeaa 100644
--- a/src/WebRTCLibDataChannel.hpp
+++ b/src/WebRTCLibDataChannel.hpp
@@ -31,72 +31,72 @@
#ifndef WEBRTC_DATA_CHANNEL_H
#define WEBRTC_DATA_CHANNEL_H
+#ifdef GDNATIVE_WEBRTC
#include <Godot.hpp> // Godot.hpp must go first, or windows builds breaks
-#include "api/peer_connection_interface.h" // interface for all things needed from WebRTC
-#include "media/base/media_engine.h" // needed for CreateModularPeerConnectionFactory
-
-#include "PoolArrays.hpp"
#include "net/WebRTCDataChannelNative.hpp"
+#define WebRTCDataChannelExtension WebRTCDataChannelNative
+#if !defined(GDCLASS)
+#define GDCLASS(arg1, arg2) GODOT_CLASS(arg1, arg2)
+#endif
+#else
+#include <godot_cpp/classes/web_rtc_data_channel_extension.hpp>
+#endif
+
#include <mutex>
+#include <queue>
+#include <utility>
+
+#include "rtc/rtc.hpp"
namespace godot_webrtc {
-class WebRTCLibDataChannel : public WebRTCDataChannelNative {
- GODOT_CLASS(WebRTCLibDataChannel, WebRTCDataChannelNative);
+class WebRTCLibDataChannel : public godot::WebRTCDataChannelExtension {
+ GDCLASS(WebRTCLibDataChannel, WebRTCDataChannelExtension);
private:
- class ChannelObserver : public webrtc::DataChannelObserver {
- public:
- WebRTCLibDataChannel *parent;
+ using QueuedPacket = std::pair<std::vector<uint8_t>, bool>;
+ std::mutex *mutex;
+ std::queue<QueuedPacket> packet_queue;
+ QueuedPacket current_packet;
+ std::shared_ptr<rtc::DataChannel> channel = nullptr;
- ChannelObserver(WebRTCLibDataChannel *parent);
- void OnMessage(const webrtc::DataBuffer &buffer) override;
- void OnStateChange() override; // UNUSED
- void OnBufferedAmountChange(uint64_t previous_amount) override; // UNUSED
- };
+ WriteMode write_mode = WRITE_MODE_TEXT;
+ ChannelState channel_state = STATE_CONNECTING;
+ bool negotiated = false;
- ChannelObserver observer;
- rtc::scoped_refptr<webrtc::DataChannelInterface> channel;
+ void queue_packet(const uint8_t *data, uint32_t size, bool p_is_string);
+ void bind_channel(std::shared_ptr<rtc::DataChannel> p_channel, bool p_negotiated);
- std::mutex *mutex;
- std::queue<godot::PoolByteArray> packet_queue;
- godot::PoolByteArray current_packet;
- std::string label;
- std::string protocol;
+protected:
+ static void _bind_methods() {}
public:
- static WebRTCLibDataChannel *new_data_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel);
- static void _register_methods();
+ static WebRTCLibDataChannel *new_data_channel(std::shared_ptr<rtc::DataChannel> p_channel, bool p_negotiated);
- void _init();
-
- void bind_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel);
- void queue_packet(const uint8_t *data, uint32_t size);
+ /* PacketPeer */
+ virtual int64_t _get_packet(const uint8_t **r_buffer, int32_t *r_len) override;
+ virtual int64_t _put_packet(const uint8_t *p_buffer, int64_t p_len) override;
+ virtual int64_t _get_available_packet_count() const override;
+ virtual int64_t _get_max_packet_size() const override;
/* WebRTCDataChannel */
- void set_write_mode(godot_int mode);
- godot_int get_write_mode() const;
- bool was_string_packet() const;
-
- ChannelState get_ready_state() const;
- const char *get_label() const;
- bool is_ordered() const;
- int get_id() const;
- int get_max_packet_life_time() const;
- int get_max_retransmits() const;
- const char *get_protocol() const;
- bool is_negotiated() const;
- int get_buffered_amount() const;
-
- godot_error poll();
- void close();
-
- /* PacketPeer */
- virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len);
- virtual godot_error put_packet(const uint8_t *p_buffer, int p_len);
- virtual godot_int get_available_packet_count() const;
- virtual godot_int get_max_packet_size() const;
+ int64_t _poll() override;
+ void _close() override;
+
+ void _set_write_mode(int64_t p_mode) override;
+ int64_t _get_write_mode() const override;
+ bool _was_string_packet() const override;
+
+ int64_t _get_ready_state() const override;
+ godot::String _get_label() const override;
+ bool _is_ordered() const override;
+ int64_t _get_id() const override;
+ int64_t _get_max_packet_life_time() const override;
+ int64_t _get_max_retransmits() const override;
+ godot::String _get_protocol() const override;
+ bool _is_negotiated() const override;
+ int64_t _get_buffered_amount() const override;
WebRTCLibDataChannel();
~WebRTCLibDataChannel();
diff --git a/src/WebRTCLibPeerConnection.cpp b/src/WebRTCLibPeerConnection.cpp
index d090654..cda018a 100644
--- a/src/WebRTCLibPeerConnection.cpp
+++ b/src/WebRTCLibPeerConnection.cpp
@@ -29,214 +29,201 @@
/*************************************************************************/
#include "WebRTCLibPeerConnection.hpp"
-#include "WebRTCDataChannel.hpp"
-#include "WebRTCDataChannelGDNative.hpp"
#include "WebRTCLibDataChannel.hpp"
+using namespace godot;
using namespace godot_webrtc;
-std::unique_ptr<rtc::Thread> WebRTCLibPeerConnection::signaling_thread = nullptr;
-
-// PeerConnectionObserver
-void WebRTCLibPeerConnection::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
- godot::Dictionary candidateSDP;
- godot::String candidateSdpMidName = candidate->sdp_mid().c_str();
- int candidateSdpMlineIndexName = candidate->sdp_mline_index();
- std::string sdp;
- candidate->ToString(&sdp);
- godot::String candidateSdpName = sdp.c_str();
- parent->queue_signal("ice_candidate_created", 3, candidateSdpMidName, candidateSdpMlineIndexName, candidateSdpName);
-}
+#ifdef GDNATIVE_WEBRTC
+struct CastableError {
+ godot::Error err_enum;
+ int64_t err_int;
-// SetSessionDescriptionObserver
-void WebRTCLibPeerConnection::GodotSSDO::OnSuccess() {
- if (make_offer) {
- make_offer = false;
- parent->peer_connection->CreateAnswer(parent->ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
+ operator int64_t() { return err_int; }
+ operator godot::Error() { return err_enum; }
+ CastableError(godot::Error p_enum, int64_t p_int) {
+ err_enum = p_enum;
+ err_int = p_int;
}
-}
-
-// CreateSessionDescriptionObserver
-void WebRTCLibPeerConnection::GodotCSDO::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
- // serialize this offer and send it to the remote peer:
- std::string sdp;
- desc->ToString(&sdp);
- parent->queue_signal("session_description_created", 2, desc->type().c_str(), sdp.c_str());
-}
+};
+#define MKERR(m_err) CastableError(godot::Error::m_err, GODOT_##m_err)
+#define OK MKERR(OK)
+#define FAILED MKERR(FAILED)
+#define ERR_UNCONFIGURED MKERR(ERR_UNCONFIGURED)
+#define ERR_UNAVAILABLE MKERR(ERR_UNAVAILABLE)
+#define ERR_INVALID_PARAMETER MKERR(ERR_INVALID_PARAMETER)
+#define ERR_BUG MKERR(ERR_BUG)
+#endif
void WebRTCLibPeerConnection::initialize_signaling() {
- if (signaling_thread.get() == nullptr) {
- signaling_thread = rtc::Thread::Create();
- }
- signaling_thread->Start();
+#ifdef DEBUG_ENABLED
+ rtc::InitLogger(rtc::LogLevel::Debug);
+#endif
}
void WebRTCLibPeerConnection::deinitialize_signaling() {
- if (signaling_thread.get() != nullptr) {
- signaling_thread->Stop();
- }
}
-godot_error _parse_ice_server(webrtc::PeerConnectionInterface::RTCConfiguration &r_config, godot::Dictionary p_server) {
- godot::Variant v;
- webrtc::PeerConnectionInterface::IceServer ice_server;
- godot::String url;
-
- ERR_FAIL_COND_V(!p_server.has("urls"), GODOT_ERR_INVALID_PARAMETER);
+Error WebRTCLibPeerConnection::_parse_ice_server(rtc::Configuration &r_config, Dictionary p_server) {
+ ERR_FAIL_COND_V(!p_server.has("urls"), ERR_INVALID_PARAMETER);
// Parse mandatory URL
- v = p_server["urls"];
- if (v.get_type() == godot::Variant::STRING) {
- url = v;
- ice_server.urls.push_back(url.utf8().get_data());
- } else if (v.get_type() == godot::Variant::ARRAY) {
- godot::Array names = v;
- for (int j = 0; j < names.size(); j++) {
- v = names[j];
- ERR_FAIL_COND_V(v.get_type() != godot::Variant::STRING, GODOT_ERR_INVALID_PARAMETER);
- url = v;
- ice_server.urls.push_back(url.utf8().get_data());
- }
+ Array urls;
+ Variant urls_var = p_server["urls"];
+ if (urls_var.get_type() == Variant::STRING) {
+ urls.push_back(urls_var);
+ } else if (urls_var.get_type() == Variant::ARRAY) {
+ urls = urls_var;
} else {
- ERR_FAIL_V(GODOT_ERR_INVALID_PARAMETER);
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
// Parse credentials (only meaningful for TURN, only support password)
- if (p_server.has("username") && (v = p_server["username"]) && v.get_type() == godot::Variant::STRING) {
- ice_server.username = (v.operator godot::String()).utf8().get_data();
+ String username;
+ String credential;
+ if (p_server.has("username") && p_server["username"].get_type() == Variant::STRING) {
+ username = p_server["username"];
}
- if (p_server.has("credential") && (v = p_server["credential"]) && v.get_type() == godot::Variant::STRING) {
- ice_server.password = (v.operator godot::String()).utf8().get_data();
+ if (p_server.has("credential") && p_server["credential"].get_type() == Variant::STRING) {
+ credential = p_server["credential"];
}
-
- r_config.servers.push_back(ice_server);
- return GODOT_OK;
+ for (int i = 0; i < urls.size(); i++) {
+ rtc::IceServer srv(urls[i].operator String().utf8().get_data());
+ srv.username = username.utf8().get_data();
+ srv.password = credential.utf8().get_data();
+ r_config.iceServers.push_back(srv);
+ }
+ return OK;
}
-godot_error _parse_channel_config(webrtc::DataChannelInit &r_config, godot::Dictionary p_dict) {
- godot::Variant v;
-#define _SET_N(PROP, PNAME, TYPE) \
- if (p_dict.has(#PROP)) { \
- v = p_dict[#PROP]; \
- if (v.get_type() == godot::Variant::TYPE) \
- r_config.PNAME = v; \
+Error WebRTCLibPeerConnection::_parse_channel_config(rtc::DataChannelInit &r_config, const Dictionary &p_dict) {
+ Variant nil;
+ Variant v;
+ if (p_dict.has("negotiated")) {
+ r_config.negotiated = p_dict["negotiated"].operator bool();
}
-#define _SET(PROP, TYPE) _SET_N(PROP, PROP, TYPE)
- _SET(negotiated, BOOL);
- _SET(id, INT);
- _SET_N(maxPacketLifeTime, maxRetransmitTime, INT);
- _SET(maxRetransmits, INT);
- _SET(ordered, BOOL);
-#undef _SET
- if (p_dict.has("protocol") && (v = p_dict["protocol"]) && v.get_type() == godot::Variant::STRING) {
- r_config.protocol = v.operator godot::String().utf8().get_data();
+ if (p_dict.has("id")) {
+ r_config.id = uint16_t(p_dict["id"].operator int32_t());
}
-
- // ID makes sense only when negotiated is true (and must be set in that case)
- ERR_FAIL_COND_V(r_config.negotiated ? r_config.id == -1 : r_config.id != -1, GODOT_ERR_INVALID_PARAMETER);
- // Only one of maxRetransmits and maxRetransmitTime can be set on a channel.
- ERR_FAIL_COND_V(r_config.maxRetransmits && r_config.maxRetransmitTime, GODOT_ERR_INVALID_PARAMETER);
- return GODOT_OK;
+ // If negotiated it must have an ID, and ID only makes sense when negotiated.
+ ERR_FAIL_COND_V(r_config.negotiated != r_config.id.has_value(), ERR_INVALID_PARAMETER);
+ // Channels cannot be both time-constrained and retry-constrained.
+ ERR_FAIL_COND_V(p_dict.has("maxPacketLifeTime") && p_dict.has("maxRetransmits"), ERR_INVALID_PARAMETER);
+ if (p_dict.has("maxPacketLifeTime")) {
+ r_config.reliability.type = rtc::Reliability::Type::Timed;
+ r_config.reliability.rexmit = std::chrono::milliseconds(p_dict["maxPacketLifeTime"].operator int32_t());
+ } else if (p_dict.has("maxRetransmits")) {
+ r_config.reliability.type = rtc::Reliability::Type::Rexmit;
+ r_config.reliability.rexmit = p_dict["maxRetransmits"].operator int32_t();
+ }
+ if (p_dict.has("ordered") && p_dict["ordered"].operator bool() == false) {
+ r_config.reliability.unordered = true;
+ }
+ if (p_dict.has("protocol")) {
+ r_config.protocol = p_dict["protocol"].operator String().utf8().get_data();
+ }
+ return OK;
}
-WebRTCLibPeerConnection::ConnectionState WebRTCLibPeerConnection::get_connection_state() const {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, STATE_CLOSED);
+int64_t WebRTCLibPeerConnection::_get_connection_state() const {
+ ERR_FAIL_COND_V(peer_connection == nullptr, STATE_CLOSED);
- webrtc::PeerConnectionInterface::IceConnectionState state = peer_connection->ice_connection_state();
+ rtc::PeerConnection::State state = peer_connection->state();
switch (state) {
- case webrtc::PeerConnectionInterface::kIceConnectionNew:
+ case rtc::PeerConnection::State::New:
return STATE_NEW;
- case webrtc::PeerConnectionInterface::kIceConnectionChecking:
+ case rtc::PeerConnection::State::Connecting:
return STATE_CONNECTING;
- case webrtc::PeerConnectionInterface::kIceConnectionConnected:
+ case rtc::PeerConnection::State::Connected:
return STATE_CONNECTED;
- case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
- return STATE_CONNECTED;
- case webrtc::PeerConnectionInterface::kIceConnectionFailed:
- return STATE_FAILED;
- case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
+ case rtc::PeerConnection::State::Disconnected:
return STATE_DISCONNECTED;
- case webrtc::PeerConnectionInterface::kIceConnectionClosed:
- return STATE_CLOSED;
+ case rtc::PeerConnection::State::Failed:
+ return STATE_FAILED;
default:
return STATE_CLOSED;
}
}
-godot_error WebRTCLibPeerConnection::initialize(const godot_dictionary *p_config) {
- webrtc::PeerConnectionInterface::RTCConfiguration config;
- godot::Dictionary d = *(godot::Dictionary *)p_config;
- godot::Variant v;
- if (d.has("iceServers") && (v = d["iceServers"]) && v.get_type() == godot::Variant::ARRAY) {
- godot::Array servers = v;
+int64_t WebRTCLibPeerConnection::_initialize(const Dictionary &p_config) {
+ rtc::Configuration config = {};
+ if (p_config.has("iceServers") && p_config["iceServers"].get_type() == Variant::ARRAY) {
+ Array servers = p_config["iceServers"];
for (int i = 0; i < servers.size(); i++) {
- v = servers[i];
- ERR_FAIL_COND_V(v.get_type() != godot::Variant::DICTIONARY, GODOT_ERR_INVALID_PARAMETER);
- godot_error err;
- godot::Dictionary server = v;
- err = _parse_ice_server(config, server);
- ERR_FAIL_COND_V(err != GODOT_OK, err);
+ ERR_FAIL_COND_V(servers[i].get_type() != Variant::DICTIONARY, ERR_INVALID_PARAMETER);
+ Dictionary server = servers[i];
+ Error err = _parse_ice_server(config, server);
+ ERR_FAIL_COND_V(err != OK, FAILED);
}
}
- return _create_pc(config);
+ return (int64_t)_create_pc(config);
}
-godot_object *WebRTCLibPeerConnection::create_data_channel(const char *p_channel, const godot_dictionary *p_channel_config) {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, NULL);
+Object *WebRTCLibPeerConnection::_create_data_channel(const String &p_channel, const Dictionary &p_channel_config) try {
+ ERR_FAIL_COND_V(!peer_connection, nullptr);
// Read config from dictionary
- webrtc::DataChannelInit config;
- godot::Dictionary d = *(godot::Dictionary *)p_channel_config;
- godot_error err = _parse_channel_config(config, d);
- ERR_FAIL_COND_V(err != GODOT_OK, NULL);
-
- WebRTCLibDataChannel *wrapper = WebRTCLibDataChannel::new_data_channel(peer_connection->CreateDataChannel(p_channel, &config));
- ERR_FAIL_COND_V(wrapper == NULL, NULL);
- return wrapper->_owner;
+ rtc::DataChannelInit config;
+
+ Error err = _parse_channel_config(config, p_channel_config);
+ ERR_FAIL_COND_V(err != OK, nullptr);
+
+ std::shared_ptr<rtc::DataChannel> ch = peer_connection->createDataChannel(p_channel.utf8().get_data(), config);
+ ERR_FAIL_COND_V(ch == nullptr, nullptr);
+
+ WebRTCLibDataChannel *wrapper = WebRTCLibDataChannel::new_data_channel(ch, ch->id().has_value());
+ ERR_FAIL_COND_V(wrapper == nullptr, nullptr);
+ return wrapper;
+} catch (const std::exception &e) {
+ ERR_PRINT(e.what());
+ ERR_FAIL_V(nullptr);
}
-godot_error WebRTCLibPeerConnection::create_offer() {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
- peer_connection->CreateOffer(ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
- return GODOT_OK;
+int64_t WebRTCLibPeerConnection::_create_offer() try {
+ ERR_FAIL_COND_V(!peer_connection, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(_get_connection_state() != STATE_NEW, FAILED);
+ peer_connection->setLocalDescription(rtc::Description::Type::Offer);
+ return OK;
+} catch (const std::exception &e) {
+ ERR_PRINT(e.what());
+ ERR_FAIL_V(FAILED);
}
-#define _MAKE_DESC(TYPE, SDP) webrtc::CreateSessionDescription((godot::String(TYPE) == godot::String("offer") ? webrtc::SdpType::kOffer : webrtc::SdpType::kAnswer), SDP)
-godot_error WebRTCLibPeerConnection::set_remote_description(const char *type, const char *sdp) {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
- std::unique_ptr<webrtc::SessionDescriptionInterface> desc = _MAKE_DESC(type, sdp);
- if (desc->GetType() == webrtc::SdpType::kOffer) {
- ptr_ssdo->make_offer = true;
+int64_t WebRTCLibPeerConnection::_set_remote_description(const String &p_type, const String &p_sdp) try {
+ ERR_FAIL_COND_V(!peer_connection, ERR_UNCONFIGURED);
+ std::string sdp(p_sdp.utf8().get_data());
+ std::string type(p_type.utf8().get_data());
+ rtc::Description desc(sdp, type);
+ peer_connection->setRemoteDescription(desc);
+ // Automatically create the answer.
+ if (p_type == String("offer")) {
+ peer_connection->setLocalDescription(rtc::Description::Type::Answer);
}
- peer_connection->SetRemoteDescription(ptr_ssdo, desc.release());
- return GODOT_OK;
+ return OK;
+} catch (const std::exception &e) {
+ ERR_PRINT(e.what());
+ ERR_FAIL_V(FAILED);
}
-godot_error WebRTCLibPeerConnection::set_local_description(const char *type, const char *sdp) {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
- std::unique_ptr<webrtc::SessionDescriptionInterface> desc = _MAKE_DESC(type, sdp);
- peer_connection->SetLocalDescription(ptr_ssdo, desc.release());
- return GODOT_OK;
+int64_t WebRTCLibPeerConnection::_set_local_description(const String &p_type, const String &p_sdp) {
+ ERR_FAIL_COND_V(!peer_connection, ERR_UNCONFIGURED);
+ // XXX Library quirk. It doesn't seem possible to create offers/answers without setting the local description.
+ // Ignore this call for now to avoid crash (it's already set automatically!).
+ //peer_connection->setLocalDescription(p_type == String("offer") ? rtc::Description::Type::Offer : rtc::Description::Type::Answer);
+ return OK;
}
-#undef _MAKE_DESC
-
-godot_error WebRTCLibPeerConnection::add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
-
- webrtc::SdpParseError *error = nullptr;
- webrtc::IceCandidateInterface *candidate = webrtc::CreateIceCandidate(
- sdpMidName,
- sdpMlineIndexName,
- sdpName,
- error);
-
- ERR_FAIL_COND_V(error || !candidate, GODOT_ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!peer_connection->AddIceCandidate(candidate), GODOT_FAILED);
- return GODOT_OK;
+int64_t WebRTCLibPeerConnection::_add_ice_candidate(const String &sdpMidName, int64_t sdpMlineIndexName, const String &sdpName) try {
+ ERR_FAIL_COND_V(!peer_connection, ERR_UNCONFIGURED);
+ rtc::Candidate candidate(sdpName.utf8().get_data(), sdpMidName.utf8().get_data());
+ peer_connection->addRemoteCandidate(candidate);
+ return OK;
+} catch (const std::exception &e) {
+ ERR_PRINT(e.what());
+ ERR_FAIL_V(FAILED);
}
-godot_error WebRTCLibPeerConnection::poll() {
- ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
+int64_t WebRTCLibPeerConnection::_poll() {
+ ERR_FAIL_COND_V(!peer_connection, ERR_UNCONFIGURED);
while (!signal_queue.empty()) {
mutex_signal_queue->lock();
@@ -245,68 +232,83 @@ godot_error WebRTCLibPeerConnection::poll() {
mutex_signal_queue->unlock();
signal.emit(this);
}
- return GODOT_OK;
+ return OK;
}
-void WebRTCLibPeerConnection::close() {
- if (peer_connection.get() != nullptr) {
- peer_connection->Close();
+void WebRTCLibPeerConnection::_close() {
+ if (peer_connection != nullptr) {
+ try {
+ peer_connection->close();
+ } catch (...) {
+ }
}
- peer_connection = nullptr;
+
while (!signal_queue.empty()) {
signal_queue.pop();
}
}
-void WebRTCLibPeerConnection::_register_methods() {
-}
-
void WebRTCLibPeerConnection::_init() {
+#ifdef GDNATIVE_WEBRTC
register_interface(&interface);
-
- // initialize variables:
+#endif
mutex_signal_queue = new std::mutex;
- // create a PeerConnectionFactoryInterface:
- webrtc::PeerConnectionFactoryDependencies deps;
-
- ERR_FAIL_COND(signaling_thread.get() == nullptr);
- deps.signaling_thread = signaling_thread.get();
- pc_factory = webrtc::CreateModularPeerConnectionFactory(std::move(deps));
-
- // Create peer connection with default configuration.
- webrtc::PeerConnectionInterface::RTCConfiguration config;
- _create_pc(config);
+ _initialize(Dictionary());
}
-godot_error WebRTCLibPeerConnection::_create_pc(webrtc::PeerConnectionInterface::RTCConfiguration &config) {
- ERR_FAIL_COND_V(pc_factory.get() == nullptr, GODOT_ERR_BUG);
- peer_connection = nullptr;
- peer_connection = pc_factory->CreatePeerConnection(config, nullptr, nullptr, &pco);
- if (peer_connection.get() == nullptr) { // PeerConnection couldn't be created. Fail the method call.
- ERR_PRINT("PeerConnection could not be created");
- return GODOT_FAILED;
- }
- return GODOT_OK;
+Error WebRTCLibPeerConnection::_create_pc(rtc::Configuration &r_config) try {
+ // Prevents libdatachannel from automatically creating offers.
+ r_config.disableAutoNegotiation = true;
+
+ peer_connection = std::make_shared<rtc::PeerConnection>(r_config);
+ ERR_FAIL_COND_V(!peer_connection, FAILED);
+
+ // Binding this should be fine as long as we call close when going out of scope.
+ peer_connection->onLocalDescription([this](rtc::Description description) {
+ String type = description.type() == rtc::Description::Type::Offer ? "offer" : "answer";
+ queue_signal("session_description_created", 2, type, String(std::string(description).c_str()));
+ });
+ peer_connection->onLocalCandidate([this](rtc::Candidate candidate) {
+ queue_signal("ice_candidate_created", 3, String(candidate.mid().c_str()), 0, String(candidate.candidate().c_str()));
+ });
+ peer_connection->onDataChannel([this](std::shared_ptr<rtc::DataChannel> channel) {
+ queue_signal("data_channel_received", 1, WebRTCLibDataChannel::new_data_channel(channel, false));
+ });
+ /*
+ peer_connection->onStateChange([](rtc::PeerConnection::State state) {
+ std::cout << "[State: " << state << "]" << std::endl;
+ });
+
+ peer_connection->onGatheringStateChange([](rtc::PeerConnection::GatheringState state) {
+ std::cout << "[Gathering State: " << state << "]" << std::endl;
+ });
+ */
+ return OK;
+} catch (const std::exception &e) {
+ ERR_PRINT(e.what());
+ ERR_FAIL_V(FAILED);
}
-WebRTCLibPeerConnection::WebRTCLibPeerConnection() :
- pco(this),
- ptr_csdo(new rtc::RefCountedObject<GodotCSDO>(this)),
- ptr_ssdo(new rtc::RefCountedObject<GodotSSDO>(this)) {
+WebRTCLibPeerConnection::WebRTCLibPeerConnection() {
+#ifndef GDNATIVE_WEBRTC
+ _init();
+#endif
}
WebRTCLibPeerConnection::~WebRTCLibPeerConnection() {
+#ifdef GDNATIVE_WEBRTC
if (_owner) {
- register_interface(NULL);
+ register_interface(nullptr);
}
- close();
+#endif
+ _close();
delete mutex_signal_queue;
}
-void WebRTCLibPeerConnection::queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1, const godot::Variant &p_arg2, const godot::Variant &p_arg3) {
+void WebRTCLibPeerConnection::queue_signal(String p_name, int p_argc, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3) {
mutex_signal_queue->lock();
- const godot::Variant argv[3] = { p_arg1, p_arg2, p_arg3 };
+ const Variant argv[3] = { p_arg1, p_arg2, p_arg3 };
signal_queue.push(Signal(p_name, p_argc, argv));
mutex_signal_queue->unlock();
}
diff --git a/src/WebRTCLibPeerConnection.hpp b/src/WebRTCLibPeerConnection.hpp
index a265bc1..1a759b2 100644
--- a/src/WebRTCLibPeerConnection.hpp
+++ b/src/WebRTCLibPeerConnection.hpp
@@ -31,99 +31,61 @@
#ifndef WEBRTC_PEER_H
#define WEBRTC_PEER_H
+#ifdef GDNATIVE_WEBRTC
#include <Godot.hpp> // Godot.hpp must go first, or windows builds breaks
-#include "api/peer_connection_interface.h" // interface for all things needed from WebRTC
-#include "media/base/media_engine.h" // needed for CreateModularPeerConnectionFactory
-#include <mutex>
-
#include "net/WebRTCPeerConnectionNative.hpp"
+#define WebRTCPeerConnectionExtension WebRTCPeerConnectionNative
+#if !defined(GDCLASS)
+#define GDCLASS(arg1, arg2) GODOT_CLASS(arg1, arg2)
+#endif
+#else
+#include <godot_cpp/classes/web_rtc_peer_connection_extension.hpp>
+#endif
+
+#include "rtc/rtc.hpp"
+
+#include <mutex>
+#include <queue>
namespace godot_webrtc {
-class WebRTCLibPeerConnection : public WebRTCPeerConnectionNative {
- GODOT_CLASS(WebRTCLibPeerConnection, WebRTCPeerConnectionNative);
+class WebRTCLibPeerConnection : public godot::WebRTCPeerConnectionExtension {
+ GDCLASS(WebRTCLibPeerConnection, WebRTCPeerConnectionExtension);
private:
- godot_error _create_pc(webrtc::PeerConnectionInterface::RTCConfiguration &config);
+ std::shared_ptr<rtc::PeerConnection> peer_connection = nullptr;
+ godot::Array candidates;
+
+ godot::Error _create_pc(rtc::Configuration &r_config);
+ godot::Error _parse_ice_server(rtc::Configuration &r_config, godot::Dictionary p_server);
+ godot::Error _parse_channel_config(rtc::DataChannelInit &r_config, const godot::Dictionary &p_dict);
- static std::unique_ptr<rtc::Thread> signaling_thread;
+protected:
+ static void _bind_methods() {}
public:
- static void _register_methods();
+ static void _register_methods() {}
static void initialize_signaling();
static void deinitialize_signaling();
void _init();
- ConnectionState get_connection_state() const;
+ int64_t _get_connection_state() const override;
- godot_error initialize(const godot_dictionary *p_config);
- godot_object *create_data_channel(const char *p_channel, const godot_dictionary *p_channel_config);
- godot_error create_offer();
- godot_error set_remote_description(const char *type, const char *sdp);
- godot_error set_local_description(const char *type, const char *sdp);
- godot_error add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName);
- godot_error poll();
- void close();
+ int64_t _initialize(const godot::Dictionary &p_config) override;
+ godot::Object *_create_data_channel(const godot::String &p_channel, const godot::Dictionary &p_channel_config) override;
+ int64_t _create_offer() override;
+ int64_t _set_remote_description(const godot::String &type, const godot::String &sdp) override;
+ int64_t _set_local_description(const godot::String &type, const godot::String &sdp) override;
+ int64_t _add_ice_candidate(const godot::String &sdpMidName, int64_t sdpMlineIndexName, const godot::String &sdpName) override;
+ int64_t _poll() override;
+ void _close() override;
WebRTCLibPeerConnection();
~WebRTCLibPeerConnection();
- /* helper functions */
private:
- void queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1 = godot::Variant(), const godot::Variant &p_arg2 = godot::Variant(), const godot::Variant &p_arg3 = godot::Variant());
- void queue_packet(uint8_t *, int);
-
- /** PeerConnectionObserver callback functions **/
- class GodotPCO : public webrtc::PeerConnectionObserver {
- public:
- WebRTCLibPeerConnection *parent;
-
- GodotPCO(WebRTCLibPeerConnection *p_parent) {
- parent = p_parent;
- }
- void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override;
-
- void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override {}
- void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {}
- void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override {}
- void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override {}
- void OnRenegotiationNeeded() override {}
- void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override {}
- void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override {}
- };
-
- /** CreateSessionDescriptionObserver callback functions **/
- class GodotCSDO : public webrtc::CreateSessionDescriptionObserver {
- public:
- WebRTCLibPeerConnection *parent = nullptr;
-
- GodotCSDO(WebRTCLibPeerConnection *p_parent) {
- parent = p_parent;
- }
- void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
- void OnFailure(webrtc::RTCError error) override {
- ERR_PRINT(godot::String(error.message()));
- }
- };
-
- /** SetSessionDescriptionObserver callback functions **/
- class GodotSSDO : public webrtc::SetSessionDescriptionObserver {
- public:
- WebRTCLibPeerConnection *parent = nullptr;
- bool make_offer = false;
-
- GodotSSDO(WebRTCLibPeerConnection *p_parent) {
- parent = p_parent;
- }
- void OnSuccess() override;
- void OnFailure(webrtc::RTCError error) override {
- make_offer = false;
- ERR_PRINT(godot::String(error.message()));
- }
- };
-
class Signal {
godot::String method;
godot::Variant argv[3];
@@ -151,15 +113,10 @@ private:
}
};
- GodotPCO pco;
- rtc::scoped_refptr<GodotSSDO> ptr_ssdo;
- rtc::scoped_refptr<GodotCSDO> ptr_csdo;
-
std::mutex *mutex_signal_queue = nullptr;
std::queue<Signal> signal_queue;
- rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory;
- rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
+ void queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1 = godot::Variant(), const godot::Variant &p_arg2 = godot::Variant(), const godot::Variant &p_arg3 = godot::Variant());
};
} // namespace godot_webrtc
diff --git a/src/init_gdextension.cpp b/src/init_gdextension.cpp
new file mode 100644
index 0000000..c923881
--- /dev/null
+++ b/src/init_gdextension.cpp
@@ -0,0 +1,72 @@
+/*************************************************************************/
+/* init_gdextension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include <godot/gdnative_interface.h>
+
+#include <godot_cpp/core/class_db.hpp>
+#include <godot_cpp/core/defs.hpp>
+#include <godot_cpp/godot.hpp>
+
+#include "WebRTCLibDataChannel.hpp"
+#include "WebRTCLibPeerConnection.hpp"
+
+using namespace godot;
+using namespace godot_webrtc;
+
+void register_webrtc_extension_types(ModuleInitializationLevel p_level) {
+ if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
+ return;
+ }
+
+ WebRTCLibPeerConnection::initialize_signaling();
+ godot::ClassDB::register_class<WebRTCLibDataChannel>();
+ godot::ClassDB::register_class<WebRTCLibPeerConnection>();
+ WebRTCPeerConnection::set_default_extension("WebRTCLibPeerConnection");
+}
+
+void unregister_webrtc_extension_types(ModuleInitializationLevel p_level) {
+ if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
+ return;
+ }
+
+ WebRTCLibPeerConnection::deinitialize_signaling();
+}
+
+extern "C" {
+GDNativeBool GDN_EXPORT webrtc_extension_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
+ GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
+
+ init_obj.register_initializer(register_webrtc_extension_types);
+ init_obj.register_terminator(unregister_webrtc_extension_types);
+ init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
+
+ return init_obj.init();
+}
+}
diff --git a/src/init.cpp b/src/init_gdnative.cpp
index a6066c3..77669af 100644
--- a/src/init.cpp
+++ b/src/init_gdnative.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* init.cpp */
+/* init_gdnative.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -78,7 +78,7 @@ godot_net_webrtc_library library = {
};
extern "C" void GDN_EXPORT godot_gdnative_singleton() {
- if (WebRTCPeerConnectionNative::_net_api) {
+ if (godot::WebRTCPeerConnectionNative::_net_api) {
ERR_FAIL_COND(!godot::gdnlib);
_singleton_lib = godot::gdnlib;
ERR_FAIL_COND(!godot::api);
@@ -92,7 +92,7 @@ extern "C" void GDN_EXPORT godot_gdnative_singleton() {
_set_library_mb = godot::api->godot_method_bind_get_method("NativeScript", "set_library");
ERR_FAIL_COND(!_set_library_mb);
// If registration is successful _singleton will be set to true
- _singleton = WebRTCPeerConnectionNative::_net_api->godot_net_set_webrtc_library(&library) == GODOT_OK;
+ _singleton = godot::WebRTCPeerConnectionNative::_net_api->godot_net_set_webrtc_library(&library) == GODOT_OK;
if (!_singleton)
ERR_PRINT("Failed initializing webrtc singleton library");
}
@@ -111,7 +111,7 @@ extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
break;
if (net_api->next->version.major == 3 && net_api->next->version.minor == 2) {
- WebRTCPeerConnectionNative::_net_api = (const godot_gdnative_ext_net_3_2_api_struct *)net_api->next;
+ godot::WebRTCPeerConnectionNative::_net_api = (const godot_gdnative_ext_net_3_2_api_struct *)net_api->next;
}
}
@@ -121,7 +121,7 @@ extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
if (_singleton) { // If we are the active singleton, unregister
- WebRTCPeerConnectionNative::_net_api->godot_net_set_webrtc_library(NULL);
+ godot::WebRTCPeerConnectionNative::_net_api->godot_net_set_webrtc_library(NULL);
}
godot_webrtc::WebRTCLibPeerConnection::deinitialize_signaling();
godot::Godot::gdnative_terminate(o);
diff --git a/src/net/WebRTCDataChannelNative.cpp b/src/net/WebRTCDataChannelNative.cpp
index 4e6b114..4639021 100644
--- a/src/net/WebRTCDataChannelNative.cpp
+++ b/src/net/WebRTCDataChannelNative.cpp
@@ -31,6 +31,8 @@
#include "WebRTCDataChannelNative.hpp"
#include "net/WebRTCPeerConnectionNative.hpp"
+using namespace godot;
+
void WebRTCDataChannelNative::register_interface(const godot_net_webrtc_data_channel *p_interface) {
ERR_FAIL_COND(!WebRTCPeerConnectionNative::_net_api);
WebRTCPeerConnectionNative::_net_api->godot_net_bind_webrtc_data_channel(_owner, p_interface);
@@ -54,73 +56,73 @@ WebRTCDataChannelNative::~WebRTCDataChannelNative() {
* and you could use void *user for any kind of state struct pointer you have.
*/
godot_error get_packet_wdc(void *user, const uint8_t **r_buffer, int *r_len) {
- return ((WebRTCDataChannelNative *)user)->get_packet(r_buffer, r_len);
+ return (godot_error)(((WebRTCDataChannelNative *)user)->_get_packet(r_buffer, r_len));
}
godot_error put_packet_wdc(void *user, const uint8_t *p_buffer, int p_len) {
- return ((WebRTCDataChannelNative *)user)->put_packet(p_buffer, p_len);
+ return (godot_error)(((WebRTCDataChannelNative *)user)->_put_packet(p_buffer, p_len));
}
godot_int get_available_packet_count_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_available_packet_count();
+ return ((WebRTCDataChannelNative *)user)->_get_available_packet_count();
}
godot_int get_max_packet_size_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_max_packet_size();
+ return ((WebRTCDataChannelNative *)user)->_get_max_packet_size();
}
void set_write_mode_wdc(void *user, godot_int write_mode) {
- ((WebRTCDataChannelNative *)user)->set_write_mode(write_mode);
+ ((WebRTCDataChannelNative *)user)->_set_write_mode(write_mode);
}
godot_int get_write_mode_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_write_mode();
+ return ((WebRTCDataChannelNative *)user)->_get_write_mode();
}
bool was_string_packet_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->was_string_packet();
+ return ((WebRTCDataChannelNative *)user)->_was_string_packet();
}
godot_int get_ready_state_wdc(const void *user) {
- return (godot_int)(((WebRTCDataChannelNative *)user)->get_ready_state());
+ return (godot_int)(((WebRTCDataChannelNative *)user)->_get_ready_state());
}
const char *get_label_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_label();
+ return ((WebRTCDataChannelNative *)user)->_get_label().utf8().get_data();
}
bool is_ordered_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->is_ordered();
+ return ((WebRTCDataChannelNative *)user)->_is_ordered();
}
int get_id_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_id();
+ return ((WebRTCDataChannelNative *)user)->_get_id();
}
int get_max_packet_life_time_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_max_packet_life_time();
+ return ((WebRTCDataChannelNative *)user)->_get_max_packet_life_time();
}
int get_max_retransmits_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_max_retransmits();
+ return ((WebRTCDataChannelNative *)user)->_get_max_retransmits();
}
const char *get_protocol_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_protocol();
+ return ((WebRTCDataChannelNative *)user)->_get_protocol().utf8().get_data();
}
bool is_negotiated_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->is_negotiated();
+ return ((WebRTCDataChannelNative *)user)->_is_negotiated();
}
int get_buffered_amount_wdc(const void *user) {
- return ((WebRTCDataChannelNative *)user)->get_buffered_amount();
+ return ((WebRTCDataChannelNative *)user)->_get_buffered_amount();
}
godot_error poll_wdc(void *user) {
- return ((WebRTCDataChannelNative *)user)->poll();
+ return (godot_error)(((WebRTCDataChannelNative *)user)->_poll());
}
void close_wdc(void *user) {
- ((WebRTCDataChannelNative *)user)->close();
+ ((WebRTCDataChannelNative *)user)->_close();
}
diff --git a/src/net/WebRTCDataChannelNative.hpp b/src/net/WebRTCDataChannelNative.hpp
index 20ef38e..a8ab697 100644
--- a/src/net/WebRTCDataChannelNative.hpp
+++ b/src/net/WebRTCDataChannelNative.hpp
@@ -69,6 +69,8 @@ typedef struct {
}
#endif
+namespace godot {
+
class WebRTCDataChannelNative : public godot::WebRTCDataChannelGDNative {
GODOT_CLASS(WebRTCDataChannelNative, godot::WebRTCDataChannelGDNative);
@@ -110,30 +112,32 @@ public:
void _init();
void register_interface(const godot_net_webrtc_data_channel *interface);
- virtual void set_write_mode(godot_int mode) = 0;
- virtual godot_int get_write_mode() const = 0;
- virtual bool was_string_packet() const = 0;
+ virtual void _set_write_mode(int64_t mode) = 0;
+ virtual int64_t _get_write_mode() const = 0;
+ virtual bool _was_string_packet() const = 0;
- virtual ChannelState get_ready_state() const = 0;
- virtual const char *get_label() const = 0;
- virtual bool is_ordered() const = 0;
- virtual int get_id() const = 0;
- virtual int get_max_packet_life_time() const = 0;
- virtual int get_max_retransmits() const = 0;
- virtual const char *get_protocol() const = 0;
- virtual bool is_negotiated() const = 0;
- virtual int get_buffered_amount() const = 0;
+ virtual int64_t _get_ready_state() const = 0;
+ virtual godot::String _get_label() const = 0;
+ virtual bool _is_ordered() const = 0;
+ virtual int64_t _get_id() const = 0;
+ virtual int64_t _get_max_packet_life_time() const = 0;
+ virtual int64_t _get_max_retransmits() const = 0;
+ virtual godot::String _get_protocol() const = 0;
+ virtual bool _is_negotiated() const = 0;
+ virtual int64_t _get_buffered_amount() const = 0;
- virtual godot_error poll() = 0;
- virtual void close() = 0;
+ virtual int64_t _poll() = 0;
+ virtual void _close() = 0;
/* PacketPeer */
- virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len) = 0;
- virtual godot_error put_packet(const uint8_t *p_buffer, int p_len) = 0;
- virtual godot_int get_available_packet_count() const = 0;
- virtual godot_int get_max_packet_size() const = 0;
+ virtual int64_t _get_packet(const uint8_t **r_buffer, int32_t *r_len) = 0;
+ virtual int64_t _put_packet(const uint8_t *p_buffer, int64_t p_len) = 0;
+ virtual int64_t _get_available_packet_count() const = 0;
+ virtual int64_t _get_max_packet_size() const = 0;
~WebRTCDataChannelNative();
};
+}; // namespace godot
+
#endif // WEBRTC_DATA_CHANNEL_NATIVE
diff --git a/src/net/WebRTCPeerConnectionNative.cpp b/src/net/WebRTCPeerConnectionNative.cpp
index c8c7587..508004f 100644
--- a/src/net/WebRTCPeerConnectionNative.cpp
+++ b/src/net/WebRTCPeerConnectionNative.cpp
@@ -30,6 +30,8 @@
#include "WebRTCPeerConnectionNative.hpp"
+using namespace godot;
+
const godot_gdnative_ext_net_3_2_api_struct *WebRTCPeerConnectionNative::_net_api = NULL;
void WebRTCPeerConnectionNative::register_interface(const godot_net_webrtc_peer_connection *p_interface) {
@@ -55,19 +57,23 @@ WebRTCPeerConnectionNative::~WebRTCPeerConnectionNative() {
* and you could use void *user for any kind of state struct pointer you have.
*/
godot_int get_connection_state_wp(const void *user) {
- return (godot_int)((WebRTCPeerConnectionNative *)user)->get_connection_state();
+ return (godot_int)((WebRTCPeerConnectionNative *)user)->_get_connection_state();
}
godot_error initialize_wp(void *user, const godot_dictionary *p_config) {
- return ((WebRTCPeerConnectionNative *)user)->initialize(p_config);
+ return (godot_error)(((WebRTCPeerConnectionNative *)user)->_initialize(*(Dictionary *)p_config));
}
godot_object *create_data_channel_wp(void *user, const char *p_channel, const godot_dictionary *p_channel_config) {
- return ((WebRTCPeerConnectionNative *)user)->create_data_channel(p_channel, p_channel_config);
+ Object *ptr = ((WebRTCPeerConnectionNative *)user)->_create_data_channel(p_channel, *(Dictionary *)p_channel_config);
+ if (ptr) {
+ return ptr->_owner;
+ }
+ return nullptr;
}
godot_error create_offer_wp(void *user) {
- return ((WebRTCPeerConnectionNative *)user)->create_offer();
+ return (godot_error)(((WebRTCPeerConnectionNative *)user)->_create_offer());
}
godot_error create_answer_wp(void *user) {
@@ -75,21 +81,21 @@ godot_error create_answer_wp(void *user) {
}
godot_error set_remote_description_wp(void *user, const char *type, const char *sdp) {
- return ((WebRTCPeerConnectionNative *)user)->set_remote_description(type, sdp);
+ return (godot_error)(((WebRTCPeerConnectionNative *)user)->_set_remote_description(type, sdp));
}
godot_error set_local_description_wp(void *user, const char *type, const char *sdp) {
- return ((WebRTCPeerConnectionNative *)user)->set_local_description(type, sdp);
+ return (godot_error)(((WebRTCPeerConnectionNative *)user)->_set_local_description(type, sdp));
}
godot_error add_ice_candidate_wp(void *user, const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
- return ((WebRTCPeerConnectionNative *)user)->add_ice_candidate(sdpMidName, sdpMlineIndexName, sdpName);
+ return (godot_error)(((WebRTCPeerConnectionNative *)user)->_add_ice_candidate(sdpMidName, sdpMlineIndexName, sdpName));
}
godot_error poll_wp(void *user) {
- return ((WebRTCPeerConnectionNative *)user)->poll();
+ return (godot_error)((WebRTCPeerConnectionNative *)user)->_poll();
}
void close_wp(void *user) {
- ((WebRTCPeerConnectionNative *)user)->close();
+ ((WebRTCPeerConnectionNative *)user)->_close();
}
diff --git a/src/net/WebRTCPeerConnectionNative.hpp b/src/net/WebRTCPeerConnectionNative.hpp
index fb75a46..1613b53 100644
--- a/src/net/WebRTCPeerConnectionNative.hpp
+++ b/src/net/WebRTCPeerConnectionNative.hpp
@@ -50,6 +50,8 @@ godot_error add_ice_candidate_wp(void *, const char *, int, const char *);
godot_error poll_wp(void *);
void close_wp(void *);
+namespace godot {
+
class WebRTCPeerConnectionNative : public godot::WebRTCPeerConnectionGDNative {
GODOT_CLASS(WebRTCPeerConnectionNative, godot::WebRTCPeerConnectionGDNative);
@@ -79,18 +81,20 @@ public:
void _init();
void register_interface(const godot_net_webrtc_peer_connection *interface);
- virtual ConnectionState get_connection_state() const = 0;
+ virtual int64_t _get_connection_state() const = 0;
- virtual godot_error initialize(const godot_dictionary *p_config) = 0;
- virtual godot_object *create_data_channel(const char *p_channel, const godot_dictionary *p_channel_config) = 0;
- virtual godot_error create_offer() = 0;
- virtual godot_error set_remote_description(const char *type, const char *sdp) = 0;
- virtual godot_error set_local_description(const char *type, const char *sdp) = 0;
- virtual godot_error add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) = 0;
- virtual godot_error poll() = 0;
- virtual void close() = 0;
+ virtual int64_t _initialize(const godot::Dictionary &p_config) = 0;
+ virtual godot::Object *_create_data_channel(const godot::String &p_channel, const godot::Dictionary &p_channel_config) = 0;
+ virtual int64_t _create_offer() = 0;
+ virtual int64_t _set_remote_description(const godot::String &type, const godot::String &sdp) = 0;
+ virtual int64_t _set_local_description(const godot::String &type, const godot::String &sdp) = 0;
+ virtual int64_t _add_ice_candidate(const godot::String &sdpMidName, int64_t sdpMlineIndexName, const godot::String &sdpName) = 0;
+ virtual int64_t _poll() = 0;
+ virtual void _close() = 0;
~WebRTCPeerConnectionNative();
};
+}; // namespace godot
+
#endif // WEBRTC_PEER_NATIVE