mirror of
https://github.com/godotengine/webrtc-native.git
synced 2026-01-03 14:09:58 +03:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
423454086e | ||
|
|
599ed98f6c | ||
|
|
f5ebac4519 | ||
|
|
3e64a42b14 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ bin/*
|
|||||||
*.lib
|
*.lib
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
*.obj
|
*.obj
|
||||||
|
*.swp
|
||||||
|
|||||||
13
SConstruct
13
SConstruct
@@ -9,6 +9,13 @@ def add_sources(sources, dirpath, extension):
|
|||||||
sources.append(dirpath + '/' + f)
|
sources.append(dirpath + '/' + f)
|
||||||
|
|
||||||
|
|
||||||
|
def get_arch_dir(name):
|
||||||
|
if name == '32':
|
||||||
|
return 'x86'
|
||||||
|
elif name == '64':
|
||||||
|
return 'x64'
|
||||||
|
return name
|
||||||
|
|
||||||
env = Environment()
|
env = Environment()
|
||||||
customs = ['custom.py']
|
customs = ['custom.py']
|
||||||
opts = Variables(customs, ARGUMENTS)
|
opts = Variables(customs, ARGUMENTS)
|
||||||
@@ -107,7 +114,7 @@ else:
|
|||||||
# Godot CPP bindings
|
# Godot CPP bindings
|
||||||
env.Append(CPPPATH=[godot_headers])
|
env.Append(CPPPATH=[godot_headers])
|
||||||
env.Append(CPPPATH=[godot_cpp_headers, godot_cpp_headers + '/core', godot_cpp_headers + '/gen'])
|
env.Append(CPPPATH=[godot_cpp_headers, godot_cpp_headers + '/core', godot_cpp_headers + '/gen'])
|
||||||
env.Append(LIBPATH=[godot_cpp_lib_dir + '/' + target])
|
env.Append(LIBPATH=[godot_cpp_lib_dir + '/' + target + '/' + get_arch_dir(target_arch)])
|
||||||
env.Append(LIBS=['godot-cpp'])
|
env.Append(LIBS=['godot-cpp'])
|
||||||
|
|
||||||
# WebRTC stuff
|
# WebRTC stuff
|
||||||
@@ -156,6 +163,10 @@ sources = []
|
|||||||
add_sources(sources, 'src/', 'cpp')
|
add_sources(sources, 'src/', 'cpp')
|
||||||
add_sources(sources, 'src/net/', 'cpp')
|
add_sources(sources, 'src/net/', 'cpp')
|
||||||
|
|
||||||
|
# Suffix
|
||||||
|
suffix = '.%s.%s' % (target, target_arch)
|
||||||
|
env["SHOBJSUFFIX"] = suffix + env["SHOBJSUFFIX"]
|
||||||
|
|
||||||
# Make the shared library
|
# Make the shared library
|
||||||
library = env.SharedLibrary(target=os.path.join(result_path, result_name), source=sources)
|
library = env.SharedLibrary(target=os.path.join(result_path, result_name), source=sources)
|
||||||
Default(library)
|
Default(library)
|
||||||
|
|||||||
2
lib/godot-cpp/release/x64/.gitignore
vendored
Normal file
2
lib/godot-cpp/release/x64/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
2
lib/godot-cpp/release/x86/.gitignore
vendored
Normal file
2
lib/godot-cpp/release/x86/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
using namespace godot_webrtc;
|
||||||
|
|
||||||
WebRTCLibPeer::GodotCSDO::GodotCSDO(WebRTCLibPeer *parent) {
|
WebRTCLibPeerConnection::GodotCSDO::GodotCSDO(WebRTCLibPeerConnection *parent) {
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotCSDO::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
|
void WebRTCLibPeerConnection::GodotCSDO::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
|
||||||
// serialize this offer and send it to the remote peer:
|
// serialize this offer and send it to the remote peer:
|
||||||
std::string sdp; // sdp = session description protocol
|
std::string sdp; // sdp = session description protocol
|
||||||
desc->ToString(&sdp);
|
desc->ToString(&sdp);
|
||||||
parent->queue_signal("offer_created", 2, desc->type().c_str(), sdp.c_str());
|
parent->queue_signal("session_description_created", 2, desc->type().c_str(), sdp.c_str());
|
||||||
};
|
};
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotCSDO::OnFailure(const std::string &error){};
|
void WebRTCLibPeerConnection::GodotCSDO::OnFailure(const std::string &error){};
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
WebRTCLibPeer::GodotDCO::GodotDCO(WebRTCLibPeer *parent) {
|
|
||||||
this->parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotDCO::OnMessage(const webrtc::DataBuffer &buffer) {
|
|
||||||
const uint8_t *data = buffer.data.data<uint8_t>();
|
|
||||||
uint8_t *memory_controlled_buffer = new uint8_t[buffer.data.size()];
|
|
||||||
|
|
||||||
std::copy(data, data + buffer.data.size(), memory_controlled_buffer);
|
|
||||||
parent->queue_packet(memory_controlled_buffer, buffer.data.size());
|
|
||||||
};
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotDCO::OnStateChange(){};
|
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotDCO::OnBufferedAmountChange(uint64_t previous_amount){};
|
|
||||||
@@ -1,33 +1,35 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
using namespace godot_webrtc;
|
||||||
|
|
||||||
WebRTCLibPeer::GodotPCO::GodotPCO(WebRTCLibPeer *parent) {
|
WebRTCLibPeerConnection::GodotPCO::GodotPCO(WebRTCLibPeerConnection *parent) {
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) {
|
void WebRTCLibPeerConnection::GodotPCO::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
void WebRTCLibPeerConnection::GodotPCO::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
void WebRTCLibPeerConnection::GodotPCO::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
void WebRTCLibPeerConnection::GodotPCO::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
||||||
|
parent->queue_signal("data_channel_received", 1, WebRTCLibDataChannel::new_data_channel(data_channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnRenegotiationNeeded() {
|
void WebRTCLibPeerConnection::GodotPCO::OnRenegotiationNeeded() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
void WebRTCLibPeerConnection::GodotPCO::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) {
|
void WebRTCLibPeerConnection::GodotPCO::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
|
void WebRTCLibPeerConnection::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
|
||||||
// Serialize the candidate and send it to the remote peer:
|
// Serialize the candidate and send it to the remote peer:
|
||||||
|
|
||||||
godot::Dictionary candidateSDP;
|
godot::Dictionary candidateSDP;
|
||||||
@@ -38,7 +40,7 @@ void WebRTCLibPeer::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface
|
|||||||
candidate->ToString(&sdp);
|
candidate->ToString(&sdp);
|
||||||
godot::String candidateSdpName = sdp.c_str();
|
godot::String candidateSdpName = sdp.c_str();
|
||||||
|
|
||||||
parent->queue_signal("new_ice_candidate",
|
parent->queue_signal("ice_candidate_created",
|
||||||
3,
|
3,
|
||||||
candidateSdpMidName,
|
candidateSdpMidName,
|
||||||
candidateSdpMlineIndexName,
|
candidateSdpMlineIndexName,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
using namespace godot_webrtc;
|
||||||
|
|
||||||
WebRTCLibPeer::GodotSSDO::GodotSSDO(WebRTCLibPeer *parent) {
|
WebRTCLibPeerConnection::GodotSSDO::GodotSSDO(WebRTCLibPeerConnection *parent) {
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotSSDO::OnSuccess(){};
|
void WebRTCLibPeerConnection::GodotSSDO::OnSuccess(){};
|
||||||
|
|
||||||
void WebRTCLibPeer::GodotSSDO::OnFailure(const std::string &error){};
|
void WebRTCLibPeerConnection::GodotSSDO::OnFailure(const std::string &error){};
|
||||||
|
|||||||
177
src/WebRTCLibDataChannel.cpp
Normal file
177
src/WebRTCLibDataChannel.cpp
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
|
|
||||||
|
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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::ChannelObserver::OnBufferedAmountChange(uint64_t previous_amount) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataChannel
|
||||||
|
WebRTCLibDataChannel *WebRTCLibDataChannel::new_data_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel) {
|
||||||
|
// Invalid channel result in NULL return
|
||||||
|
ERR_FAIL_COND_V(p_channel.get() == nullptr, NULL);
|
||||||
|
|
||||||
|
// 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::get_wrapper<godot::GDNativeLibrary>((godot_object *)godot::gdnlib));
|
||||||
|
script->set_class_name("WebRTCLibDataChannel");
|
||||||
|
out->set_script(script);
|
||||||
|
|
||||||
|
// Bind the data channel to the ScriptInstance userdata (our script)
|
||||||
|
WebRTCLibDataChannel *tmp = godot::as<WebRTCLibDataChannel>(out);
|
||||||
|
tmp->bind_channel(p_channel);
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::bind_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel) {
|
||||||
|
ERR_FAIL_COND(p_channel.get() == nullptr);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
mutex->lock();
|
||||||
|
|
||||||
|
godot::PoolByteArray packet;
|
||||||
|
packet.resize(size);
|
||||||
|
{
|
||||||
|
godot::PoolByteArray::Write w = packet.write();
|
||||||
|
memcpy(w.ptr(), data, size);
|
||||||
|
}
|
||||||
|
packet_queue.push(packet);
|
||||||
|
|
||||||
|
mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::set_write_mode(godot_int mode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int WebRTCLibDataChannel::get_write_mode() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebRTCLibDataChannel::was_string_packet() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibDataChannel::ChannelState WebRTCLibDataChannel::get_ready_state() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, STATE_CLOSED);
|
||||||
|
return (ChannelState)channel->state();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *WebRTCLibDataChannel::get_label() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, "");
|
||||||
|
return label.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebRTCLibDataChannel::is_ordered() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, false);
|
||||||
|
return channel->ordered();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_id() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, -1);
|
||||||
|
return channel->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_max_packet_life_time() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, 0);
|
||||||
|
return channel->maxRetransmitTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRTCLibDataChannel::get_max_retransmits() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, 0);
|
||||||
|
return channel->maxRetransmits();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *WebRTCLibDataChannel::get_protocol() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, "");
|
||||||
|
return protocol.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebRTCLibDataChannel::is_negotiated() const {
|
||||||
|
ERR_FAIL_COND_V(channel.get() == nullptr, false);
|
||||||
|
return channel->negotiated();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibDataChannel::poll() {
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::close() {
|
||||||
|
if(channel.get() != nullptr) {
|
||||||
|
channel->Close();
|
||||||
|
channel->UnregisterObserver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibDataChannel::get_packet(const uint8_t **r_buffer, int *r_len) {
|
||||||
|
ERR_FAIL_COND_V(packet_queue.empty(), GODOT_ERR_UNAVAILABLE);
|
||||||
|
|
||||||
|
mutex->lock();
|
||||||
|
|
||||||
|
// Update current packet and pop queue
|
||||||
|
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();
|
||||||
|
|
||||||
|
mutex->unlock();
|
||||||
|
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int WebRTCLibDataChannel::get_available_packet_count() const {
|
||||||
|
return packet_queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int WebRTCLibDataChannel::get_max_packet_size() const {
|
||||||
|
return 1200;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::_register_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibDataChannel::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibDataChannel::WebRTCLibDataChannel() : observer(this) {
|
||||||
|
mutex = new std::mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibDataChannel::~WebRTCLibDataChannel() {
|
||||||
|
close();
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
delete mutex;
|
||||||
|
}
|
||||||
76
src/WebRTCLibDataChannel.hpp
Normal file
76
src/WebRTCLibDataChannel.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#ifndef WEBRTC_DATA_CHANNEL_H
|
||||||
|
#define WEBRTC_DATA_CHANNEL_H
|
||||||
|
|
||||||
|
#include <Godot.hpp> // Godot.hpp must go first, or windows builds breaks
|
||||||
|
|
||||||
|
#include "api/peerconnectioninterface.h" // interface for all things needed from WebRTC
|
||||||
|
#include "media/base/mediaengine.h" // needed for CreateModularPeerConnectionFactory
|
||||||
|
|
||||||
|
#include "net/WebRTCDataChannelNative.hpp"
|
||||||
|
#include "PoolArrays.hpp"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace godot_webrtc {
|
||||||
|
|
||||||
|
class WebRTCLibDataChannel : public WebRTCDataChannelNative {
|
||||||
|
GODOT_CLASS(WebRTCLibDataChannel, WebRTCDataChannelNative);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ChannelObserver : public webrtc::DataChannelObserver {
|
||||||
|
public:
|
||||||
|
WebRTCLibDataChannel *parent;
|
||||||
|
|
||||||
|
ChannelObserver(WebRTCLibDataChannel *parent);
|
||||||
|
void OnMessage(const webrtc::DataBuffer &buffer) override;
|
||||||
|
void OnStateChange() override; // UNUSED
|
||||||
|
void OnBufferedAmountChange(uint64_t previous_amount) override; // UNUSED
|
||||||
|
};
|
||||||
|
|
||||||
|
ChannelObserver observer;
|
||||||
|
rtc::scoped_refptr<webrtc::DataChannelInterface> channel;
|
||||||
|
|
||||||
|
std::mutex *mutex;
|
||||||
|
std::queue<godot::PoolByteArray> packet_queue;
|
||||||
|
godot::PoolByteArray current_packet;
|
||||||
|
std::string label;
|
||||||
|
std::string protocol;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static WebRTCLibDataChannel *new_data_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel);
|
||||||
|
static void _register_methods();
|
||||||
|
|
||||||
|
void _init();
|
||||||
|
|
||||||
|
void bind_channel(rtc::scoped_refptr<webrtc::DataChannelInterface> p_channel);
|
||||||
|
void queue_packet(const uint8_t *data, uint32_t size);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
WebRTCLibDataChannel();
|
||||||
|
~WebRTCLibDataChannel();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace godot_webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_DATA_CHANNEL_H
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
|
||||||
|
|
||||||
using namespace godot_webrtc;
|
|
||||||
|
|
||||||
void WebRTCLibPeer::set_write_mode(godot_int mode) {
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_write_mode() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebRTCLibPeer::was_string_packet() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_connection_state() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::create_offer() {
|
|
||||||
peer_connection->CreateOffer(
|
|
||||||
ptr_csdo, // CreateSessionDescriptionObserver* observer,
|
|
||||||
nullptr // webrtc::PeerConnectionInterface::RTCOfferAnswerOptions() // const MediaConstraintsInterface* constraints
|
|
||||||
);
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::set_remote_description(const char *type, const char *sdp) {
|
|
||||||
godot_error err = set_description(type, sdp, false); //false meaning !isLocal because it is remote
|
|
||||||
peer_connection->CreateAnswer(ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::set_local_description(const char *type, const char *sdp) {
|
|
||||||
return set_description(type, sdp, true); // isLocal == true
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
|
|
||||||
webrtc::SdpParseError *error = nullptr;
|
|
||||||
webrtc::IceCandidateInterface *candidate = webrtc::CreateIceCandidate(
|
|
||||||
sdpMidName,
|
|
||||||
sdpMlineIndexName,
|
|
||||||
sdpName,
|
|
||||||
error);
|
|
||||||
|
|
||||||
// @TODO do something if there's an error (if error, or if !candidate)
|
|
||||||
if (error || !candidate)
|
|
||||||
std::cout << "ERROR with creating ICE candidate (" << error << ")\n";
|
|
||||||
|
|
||||||
if (!peer_connection->AddIceCandidate(candidate))
|
|
||||||
ERR_PRINT("Error with adding ICE candidate");
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::poll() {
|
|
||||||
std::function<void()> signal;
|
|
||||||
while (!signal_queue.empty()) {
|
|
||||||
mutex_signal_queue->lock();
|
|
||||||
signal = signal_queue.front();
|
|
||||||
signal_queue.pop();
|
|
||||||
mutex_signal_queue->unlock();
|
|
||||||
|
|
||||||
signal();
|
|
||||||
}
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::get_packet(const uint8_t **r_buffer, int *r_len) {
|
|
||||||
if (packet_queue_size == 0)
|
|
||||||
return GODOT_ERR_UNAVAILABLE;
|
|
||||||
mutex_packet_queue->lock();
|
|
||||||
uint8_t *current_packet = packet_queue.front();
|
|
||||||
*r_buffer = current_packet;
|
|
||||||
*r_len = packet_sizes_queue.front();
|
|
||||||
|
|
||||||
packet_queue.pop();
|
|
||||||
packet_sizes_queue.pop();
|
|
||||||
mutex_packet_queue->unlock();
|
|
||||||
|
|
||||||
--packet_queue_size;
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::put_packet(const uint8_t *p_buffer, int p_len) {
|
|
||||||
webrtc::DataBuffer webrtc_buffer(rtc::CopyOnWriteBuffer(p_buffer, p_len), true);
|
|
||||||
data_channel->Send(webrtc_buffer);
|
|
||||||
return GODOT_OK; // @TODO properly return any Error we may get.
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_available_packet_count() const {
|
|
||||||
return packet_queue_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int WebRTCLibPeer::get_max_packet_size() const {
|
|
||||||
return 1200;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::_register_methods() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::_init() {
|
|
||||||
register_interface(&interface);
|
|
||||||
|
|
||||||
// initialize variables:
|
|
||||||
mutex_signal_queue = new std::mutex;
|
|
||||||
mutex_packet_queue = new std::mutex;
|
|
||||||
packet_queue_size = 0;
|
|
||||||
|
|
||||||
// create a PeerConnectionFactoryInterface:
|
|
||||||
signaling_thread = new rtc::Thread;
|
|
||||||
signaling_thread->Start();
|
|
||||||
pc_factory = webrtc::CreateModularPeerConnectionFactory(
|
|
||||||
nullptr, // rtc::Thread* network_thread,
|
|
||||||
nullptr, // rtc::Thread* worker_thread,
|
|
||||||
signaling_thread,
|
|
||||||
nullptr, // std::unique_ptr<cricket::MediaEngineInterface> media_engine,
|
|
||||||
nullptr, // std::unique_ptr<CallFactoryInterface> call_factory,
|
|
||||||
nullptr // std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory
|
|
||||||
);
|
|
||||||
if (pc_factory.get() == nullptr) { // PeerConnectionFactory couldn't be created. Fail the method call.
|
|
||||||
ERR_PRINT("PeerConnectionFactory could not be created");
|
|
||||||
// return GODOT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create PeerConnection configuration and add the ice servers:
|
|
||||||
webrtc::PeerConnectionInterface::RTCConfiguration configuration;
|
|
||||||
//webrtc::PeerConnectionInterface::IceServer ice_server;
|
|
||||||
|
|
||||||
//ice_server.uri = "stun:stun.l.google.com:19302"; // @FIXME allow user to input ice servers
|
|
||||||
//configuration.servers.push_back(ice_server);
|
|
||||||
|
|
||||||
// create a PeerConnection object:
|
|
||||||
peer_connection = pc_factory->CreatePeerConnection(configuration, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a DataChannel
|
|
||||||
webrtc::DataChannelInit data_channel_config;
|
|
||||||
data_channel_config.negotiated = true; // True if the channel has been externally negotiated
|
|
||||||
data_channel_config.id = 0;
|
|
||||||
|
|
||||||
data_channel = peer_connection->CreateDataChannel("channel", &data_channel_config);
|
|
||||||
// @TODO (NONESSENTIAL) create data_channel check. fail function call if data_channel isn't created
|
|
||||||
data_channel->RegisterObserver(&dco);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRTCLibPeer::WebRTCLibPeer() :
|
|
||||||
dco(this),
|
|
||||||
pco(this),
|
|
||||||
ptr_csdo(new rtc::RefCountedObject<GodotCSDO>(this)),
|
|
||||||
ptr_ssdo(new rtc::RefCountedObject<GodotSSDO>(this)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRTCLibPeer::~WebRTCLibPeer() {
|
|
||||||
if (_owner) {
|
|
||||||
register_interface(NULL);
|
|
||||||
}
|
|
||||||
delete mutex_signal_queue;
|
|
||||||
delete mutex_packet_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::queue_signal(godot::String p_name, int p_argc, const godot::Variant &p_arg1, const godot::Variant &p_arg2, const godot::Variant &p_arg3) {
|
|
||||||
mutex_signal_queue->lock();
|
|
||||||
signal_queue.push(
|
|
||||||
[this, p_name, p_argc, p_arg1, p_arg2, p_arg3] {
|
|
||||||
if (p_argc == 2)
|
|
||||||
emit_signal(p_name, p_arg1, p_arg2);
|
|
||||||
else
|
|
||||||
emit_signal(p_name, p_arg1, p_arg2, p_arg3);
|
|
||||||
});
|
|
||||||
mutex_signal_queue->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCLibPeer::queue_packet(uint8_t *buffer, int buffer_size) {
|
|
||||||
mutex_packet_queue->lock();
|
|
||||||
packet_queue.push(buffer);
|
|
||||||
packet_sizes_queue.push(buffer_size);
|
|
||||||
++packet_queue_size;
|
|
||||||
mutex_packet_queue->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error WebRTCLibPeer::set_description(const char *type, const char *sdp, bool isLocal) {
|
|
||||||
// webrtc::SdpType type = (isOffer) ? webrtc::SdpType::kOffer : webrtc::SdpType::kAnswer;
|
|
||||||
godot::String string_sdp = sdp;
|
|
||||||
|
|
||||||
webrtc::SdpType sdptype = (godot::String(type) == godot::String("offer")) ? webrtc::SdpType::kOffer : webrtc::SdpType::kAnswer;
|
|
||||||
std::unique_ptr<webrtc::SessionDescriptionInterface> desc =
|
|
||||||
webrtc::CreateSessionDescription(sdptype, sdp);
|
|
||||||
|
|
||||||
if (isLocal) {
|
|
||||||
peer_connection->SetLocalDescription(
|
|
||||||
ptr_ssdo, // @TODO (NONESSENTIAL, OPTIONAL) replace this with DummySetSessionDescriptionObserver::Create()
|
|
||||||
desc.release());
|
|
||||||
} else {
|
|
||||||
peer_connection->SetRemoteDescription(
|
|
||||||
ptr_ssdo, // @TODO (NONESSENTIAL, OPTIONAL) replace this with DummySetSessionDescriptionObserver::Create()
|
|
||||||
desc.release());
|
|
||||||
}
|
|
||||||
return GODOT_OK;
|
|
||||||
}
|
|
||||||
245
src/WebRTCLibPeerConnection.cpp
Normal file
245
src/WebRTCLibPeerConnection.cpp
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
#include "WebRTCDataChannel.hpp"
|
||||||
|
#include "WebRTCDataChannelGDNative.hpp"
|
||||||
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
|
|
||||||
|
using namespace godot_webrtc;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_V(GODOT_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();
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
r_config.servers.push_back(ice_server);
|
||||||
|
return GODOT_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; }
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 != -1 && r_config.maxRetransmitTime != -1, GODOT_ERR_INVALID_PARAMETER);
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection::ConnectionState WebRTCLibPeerConnection::get_connection_state() const {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, STATE_CLOSED);
|
||||||
|
|
||||||
|
webrtc::PeerConnectionInterface::IceConnectionState state = peer_connection->ice_connection_state();
|
||||||
|
switch(state) {
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionNew:
|
||||||
|
return STATE_NEW;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionChecking:
|
||||||
|
return STATE_CONNECTING;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionConnected:
|
||||||
|
return STATE_CONNECTED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
|
||||||
|
return STATE_CONNECTED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionFailed:
|
||||||
|
return STATE_FAILED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
|
||||||
|
return STATE_DISCONNECTED;
|
||||||
|
case webrtc::PeerConnectionInterface::kIceConnectionClosed:
|
||||||
|
return STATE_CLOSED;
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _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);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::create_offer() {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
peer_connection->CreateOffer(ptr_csdo, nullptr);
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
|
peer_connection->SetRemoteDescription(ptr_ssdo, desc.release());
|
||||||
|
peer_connection->CreateAnswer(ptr_csdo, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error WebRTCLibPeerConnection::poll() {
|
||||||
|
ERR_FAIL_COND_V(peer_connection.get() == nullptr, GODOT_ERR_UNCONFIGURED);
|
||||||
|
|
||||||
|
std::function<void()> signal;
|
||||||
|
while (!signal_queue.empty()) {
|
||||||
|
mutex_signal_queue->lock();
|
||||||
|
signal = signal_queue.front();
|
||||||
|
signal_queue.pop();
|
||||||
|
mutex_signal_queue->unlock();
|
||||||
|
|
||||||
|
signal();
|
||||||
|
}
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::close() {
|
||||||
|
peer_connection->Close();
|
||||||
|
while(!signal_queue.empty()) {
|
||||||
|
signal_queue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::_register_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCLibPeerConnection::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
|
||||||
|
// initialize variables:
|
||||||
|
mutex_signal_queue = new std::mutex;
|
||||||
|
|
||||||
|
// create a PeerConnectionFactoryInterface:
|
||||||
|
signaling_thread = new rtc::Thread;
|
||||||
|
signaling_thread->Start();
|
||||||
|
pc_factory = webrtc::CreateModularPeerConnectionFactory(
|
||||||
|
nullptr, // rtc::Thread* network_thread,
|
||||||
|
nullptr, // rtc::Thread* worker_thread,
|
||||||
|
signaling_thread,
|
||||||
|
nullptr, // std::unique_ptr<cricket::MediaEngineInterface> media_engine,
|
||||||
|
nullptr, // std::unique_ptr<CallFactoryInterface> call_factory,
|
||||||
|
nullptr // std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create peer connection with default configuration.
|
||||||
|
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||||
|
_create_pc(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection::WebRTCLibPeerConnection() :
|
||||||
|
pco(this),
|
||||||
|
ptr_csdo(new rtc::RefCountedObject<GodotCSDO>(this)),
|
||||||
|
ptr_ssdo(new rtc::RefCountedObject<GodotSSDO>(this)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCLibPeerConnection::~WebRTCLibPeerConnection() {
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
mutex_signal_queue->lock();
|
||||||
|
signal_queue.push(
|
||||||
|
[this, p_name, p_argc, p_arg1, p_arg2, p_arg3] {
|
||||||
|
if (p_argc == 1) {
|
||||||
|
emit_signal(p_name, p_arg1);
|
||||||
|
} else if (p_argc == 2) {
|
||||||
|
emit_signal(p_name, p_arg1, p_arg2);
|
||||||
|
} else {
|
||||||
|
emit_signal(p_name, p_arg1, p_arg2, p_arg3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mutex_signal_queue->unlock();
|
||||||
|
}
|
||||||
@@ -8,62 +8,47 @@
|
|||||||
#include <functional> // std::function
|
#include <functional> // std::function
|
||||||
#include <mutex> // mutex @TODO replace std::mutex with Godot mutex
|
#include <mutex> // mutex @TODO replace std::mutex with Godot mutex
|
||||||
|
|
||||||
#include "net/WebRTCPeerNative.hpp"
|
#include "net/WebRTCPeerConnectionNative.hpp"
|
||||||
|
|
||||||
namespace godot_webrtc {
|
namespace godot_webrtc {
|
||||||
|
|
||||||
class WebRTCLibPeer : public WebRTCPeerNative {
|
class WebRTCLibPeerConnection : public WebRTCPeerConnectionNative {
|
||||||
GODOT_CLASS(WebRTCLibPeer, WebRTCPeerNative);
|
GODOT_CLASS(WebRTCLibPeerConnection, WebRTCPeerConnectionNative);
|
||||||
|
|
||||||
|
private:
|
||||||
|
godot_error _create_pc(webrtc::PeerConnectionInterface::RTCConfiguration &config);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void _register_methods();
|
static void _register_methods();
|
||||||
|
|
||||||
void _init();
|
void _init();
|
||||||
|
|
||||||
void set_write_mode(godot_int mode);
|
ConnectionState get_connection_state() const;
|
||||||
godot_int get_write_mode() const;
|
|
||||||
bool was_string_packet() const;
|
|
||||||
godot_int get_connection_state() const;
|
|
||||||
|
|
||||||
|
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 create_offer();
|
||||||
godot_error set_remote_description(const char *type, const char *sdp);
|
godot_error set_remote_description(const char *type, const char *sdp);
|
||||||
godot_error set_local_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 add_ice_candidate(const char *sdpMidName, int sdpMlineIndexName, const char *sdpName);
|
||||||
godot_error poll();
|
godot_error poll();
|
||||||
|
void close();
|
||||||
|
|
||||||
/* WebRTCPeer */
|
WebRTCLibPeerConnection();
|
||||||
virtual godot_error get_packet(const uint8_t **r_buffer, int *r_len);
|
~WebRTCLibPeerConnection();
|
||||||
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;
|
|
||||||
|
|
||||||
WebRTCLibPeer();
|
|
||||||
~WebRTCLibPeer();
|
|
||||||
|
|
||||||
/* helper functions */
|
/* helper functions */
|
||||||
|
|
||||||
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_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_signal(godot::StringName p_name, Variant_ARG_LIST);
|
// void queue_signal(godot::StringName p_name, Variant_ARG_LIST);
|
||||||
void queue_packet(uint8_t *, int);
|
void queue_packet(uint8_t *, int);
|
||||||
godot_error set_description(const char *type, const char *sdp, bool isLocal);
|
|
||||||
|
|
||||||
/** DataChannelObserver callback functions **/
|
|
||||||
class GodotDCO : public webrtc::DataChannelObserver {
|
|
||||||
public:
|
|
||||||
WebRTCLibPeer *parent;
|
|
||||||
|
|
||||||
GodotDCO(WebRTCLibPeer *parent);
|
|
||||||
void OnMessage(const webrtc::DataBuffer &buffer) override;
|
|
||||||
void OnStateChange() override; // UNUSED
|
|
||||||
void OnBufferedAmountChange(uint64_t previous_amount) override; // UNUSED
|
|
||||||
};
|
|
||||||
|
|
||||||
/** PeerConnectionObserver callback functions **/
|
/** PeerConnectionObserver callback functions **/
|
||||||
class GodotPCO : public webrtc::PeerConnectionObserver {
|
class GodotPCO : public webrtc::PeerConnectionObserver {
|
||||||
public:
|
public:
|
||||||
WebRTCLibPeer *parent;
|
WebRTCLibPeerConnection *parent;
|
||||||
|
|
||||||
GodotPCO(WebRTCLibPeer *parent);
|
GodotPCO(WebRTCLibPeerConnection *parent);
|
||||||
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override;
|
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override;
|
||||||
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
||||||
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
||||||
@@ -77,9 +62,9 @@ public:
|
|||||||
/** CreateSessionDescriptionObserver callback functions **/
|
/** CreateSessionDescriptionObserver callback functions **/
|
||||||
class GodotCSDO : public webrtc::CreateSessionDescriptionObserver {
|
class GodotCSDO : public webrtc::CreateSessionDescriptionObserver {
|
||||||
public:
|
public:
|
||||||
WebRTCLibPeer *parent;
|
WebRTCLibPeerConnection *parent;
|
||||||
|
|
||||||
GodotCSDO(WebRTCLibPeer *parent);
|
GodotCSDO(WebRTCLibPeerConnection *parent);
|
||||||
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
|
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
|
||||||
void OnFailure(const std::string &error) override;
|
void OnFailure(const std::string &error) override;
|
||||||
};
|
};
|
||||||
@@ -87,29 +72,23 @@ public:
|
|||||||
/** SetSessionDescriptionObserver callback functions **/
|
/** SetSessionDescriptionObserver callback functions **/
|
||||||
class GodotSSDO : public webrtc::SetSessionDescriptionObserver {
|
class GodotSSDO : public webrtc::SetSessionDescriptionObserver {
|
||||||
public:
|
public:
|
||||||
WebRTCLibPeer *parent;
|
WebRTCLibPeerConnection *parent;
|
||||||
|
|
||||||
GodotSSDO(WebRTCLibPeer *parent);
|
GodotSSDO(WebRTCLibPeerConnection *parent);
|
||||||
void OnSuccess() override;
|
void OnSuccess() override;
|
||||||
void OnFailure(const std::string &error) override;
|
void OnFailure(const std::string &error) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
GodotDCO dco;
|
|
||||||
GodotPCO pco;
|
GodotPCO pco;
|
||||||
rtc::scoped_refptr<GodotSSDO> ptr_ssdo;
|
rtc::scoped_refptr<GodotSSDO> ptr_ssdo;
|
||||||
rtc::scoped_refptr<GodotCSDO> ptr_csdo;
|
rtc::scoped_refptr<GodotCSDO> ptr_csdo;
|
||||||
|
|
||||||
std::mutex *mutex_signal_queue;
|
std::mutex *mutex_signal_queue;
|
||||||
std::mutex *mutex_packet_queue;
|
|
||||||
int packet_queue_size;
|
|
||||||
std::queue<uint8_t *> packet_queue;
|
|
||||||
std::queue<int> packet_sizes_queue;
|
|
||||||
std::queue<std::function<void()> > signal_queue;
|
std::queue<std::function<void()> > signal_queue;
|
||||||
|
|
||||||
rtc::Thread *signaling_thread;
|
rtc::Thread *signaling_thread;
|
||||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory;
|
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory;
|
||||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
|
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
|
||||||
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace godot_webrtc
|
} // namespace godot_webrtc
|
||||||
78
src/init.cpp
78
src/init.cpp
@@ -1,6 +1,72 @@
|
|||||||
#include "WebRTCLibPeer.hpp"
|
#include "WebRTCLibDataChannel.hpp"
|
||||||
#include "net/WebRTCPeerNative.hpp"
|
#include "WebRTCLibPeerConnection.hpp"
|
||||||
|
#include "net/WebRTCPeerConnectionNative.hpp"
|
||||||
#include <gdnative_api_struct.gen.h>
|
#include <gdnative_api_struct.gen.h>
|
||||||
|
#include <net/godot_net.h>
|
||||||
|
|
||||||
|
/* Singleton */
|
||||||
|
static bool _singleton = false;
|
||||||
|
static const godot_object *_singleton_lib = NULL;
|
||||||
|
static const godot_gdnative_core_api_struct *_singleton_api = NULL;
|
||||||
|
static godot_class_constructor _create_ns_cb = NULL;
|
||||||
|
static godot_method_bind *_set_script_mb = NULL;
|
||||||
|
static godot_method_bind *_set_class_name_mb = NULL;
|
||||||
|
static godot_method_bind *_set_library_mb = NULL;
|
||||||
|
|
||||||
|
void unregistered() {
|
||||||
|
_singleton = false; // We are no longer the active singleton
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error create_peer_connection_wp(godot_object *out) {
|
||||||
|
ERR_FAIL_COND_V(!_singleton, GODOT_FAILED);
|
||||||
|
// Create Script
|
||||||
|
godot_object *script = _create_ns_cb();
|
||||||
|
ERR_FAIL_COND_V(!script, GODOT_FAILED);
|
||||||
|
|
||||||
|
const void *args[] = { (void *)_singleton_lib };
|
||||||
|
_singleton_api->godot_method_bind_ptrcall(_set_library_mb, script, args, nullptr);
|
||||||
|
|
||||||
|
godot_string s;
|
||||||
|
_singleton_api->godot_string_new(&s);
|
||||||
|
_singleton_api->godot_string_parse_utf8(&s, "WebRTCLibPeerConnection");
|
||||||
|
const void *args2[] = { (void *)&s };
|
||||||
|
_singleton_api->godot_method_bind_ptrcall(_set_class_name_mb, script, args2, nullptr);
|
||||||
|
_singleton_api->godot_string_destroy(&s);
|
||||||
|
|
||||||
|
// Bind script to Object
|
||||||
|
const void *args3[] = { (void *)script };
|
||||||
|
_singleton_api->godot_method_bind_ptrcall(_set_script_mb, out, args3, nullptr);
|
||||||
|
|
||||||
|
return GODOT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_net_webrtc_library library = {
|
||||||
|
{3, 2},
|
||||||
|
&unregistered,
|
||||||
|
&create_peer_connection_wp,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" void GDN_EXPORT godot_gdnative_singleton() {
|
||||||
|
if (WebRTCPeerConnectionNative::_net_api) {
|
||||||
|
ERR_FAIL_COND(!godot::gdnlib);
|
||||||
|
_singleton_lib = godot::gdnlib;
|
||||||
|
ERR_FAIL_COND(!godot::api);
|
||||||
|
_singleton_api = godot::api;
|
||||||
|
_create_ns_cb = godot::api->godot_get_class_constructor("NativeScript");
|
||||||
|
ERR_FAIL_COND(!_create_ns_cb);
|
||||||
|
_set_script_mb = godot::api->godot_method_bind_get_method("Object", "set_script");
|
||||||
|
ERR_FAIL_COND(!_set_script_mb);
|
||||||
|
_set_class_name_mb = godot::api->godot_method_bind_get_method("NativeScript", "set_class_name");
|
||||||
|
ERR_FAIL_COND(!_set_class_name_mb);
|
||||||
|
_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;
|
||||||
|
if (!_singleton)
|
||||||
|
ERR_PRINT("Failed initializing webrtc singleton library");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Godot export stuff */
|
/* Godot export stuff */
|
||||||
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
||||||
@@ -16,7 +82,7 @@ extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (net_api->next->version.major == 3 && net_api->next->version.minor == 2) {
|
if (net_api->next->version.major == 3 && net_api->next->version.minor == 2) {
|
||||||
WebRTCPeerNative::_net_api = (const godot_gdnative_ext_net_3_2_api_struct *)net_api->next;
|
WebRTCPeerConnectionNative::_net_api = (const godot_gdnative_ext_net_3_2_api_struct *)net_api->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,11 +90,15 @@ 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) {
|
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::Godot::gdnative_terminate(o);
|
godot::Godot::gdnative_terminate(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
|
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
|
||||||
godot::Godot::nativescript_init(handle);
|
godot::Godot::nativescript_init(handle);
|
||||||
|
|
||||||
godot::register_class<godot_webrtc::WebRTCLibPeer>();
|
godot::register_class<godot_webrtc::WebRTCLibPeerConnection>();
|
||||||
|
godot::register_class<godot_webrtc::WebRTCLibDataChannel>();
|
||||||
}
|
}
|
||||||
|
|||||||
92
src/net/WebRTCDataChannelNative.cpp
Normal file
92
src/net/WebRTCDataChannelNative.cpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#include "WebRTCDataChannelNative.hpp"
|
||||||
|
#include "net/WebRTCPeerConnectionNative.hpp"
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCDataChannelNative::_register_methods() {}
|
||||||
|
|
||||||
|
void WebRTCDataChannelNative::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCDataChannelNative::~WebRTCDataChannelNative() {
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The C interface that implements WebRTCDataChannel.
|
||||||
|
* In this case it forwards calls to our C++ class, but could be plain C,
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error put_packet_wdc(void *user, const uint8_t *p_buffer, int p_len) {
|
||||||
|
return ((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();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_max_packet_size_wdc(const void *user) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_write_mode_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_write_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool was_string_packet_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->was_string_packet();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int get_ready_state_wdc(const void *user) {
|
||||||
|
return (godot_int)(((WebRTCDataChannelNative *)user)->get_ready_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_label_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_label();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ordered_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->is_ordered();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_id_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_max_packet_life_time_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_max_packet_life_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_max_retransmits_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_max_retransmits();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_protocol_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->get_protocol();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_negotiated_wdc(const void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->is_negotiated();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error poll_wdc(void *user) {
|
||||||
|
return ((WebRTCDataChannelNative *)user)->poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_wdc(void *user) {
|
||||||
|
((WebRTCDataChannelNative *)user)->close();
|
||||||
|
}
|
||||||
91
src/net/WebRTCDataChannelNative.hpp
Normal file
91
src/net/WebRTCDataChannelNative.hpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#ifndef WEBRTC_DATA_CHANNEL_NATIVE
|
||||||
|
#define WEBRTC_DATA_CHANNEL_NATIVE
|
||||||
|
|
||||||
|
#include <Godot.hpp>
|
||||||
|
#include <Reference.hpp>
|
||||||
|
#include <WebRTCDataChannelGDNative.hpp>
|
||||||
|
|
||||||
|
#include <net/godot_net.h>
|
||||||
|
|
||||||
|
/* Forward declare interface functions */
|
||||||
|
godot_error get_packet_wdc(void *, const uint8_t **, int *);
|
||||||
|
godot_error put_packet_wdc(void *, const uint8_t *, int);
|
||||||
|
godot_int get_available_packet_count_wdc(const void *);
|
||||||
|
godot_int get_max_packet_size_wdc(const void *);
|
||||||
|
|
||||||
|
void set_write_mode_wdc(void *, godot_int);
|
||||||
|
godot_int get_write_mode_wdc(const void *);
|
||||||
|
bool was_string_packet_wdc(const void *);
|
||||||
|
godot_int get_ready_state_wdc(const void *);
|
||||||
|
const char *get_label_wdc(const void *);
|
||||||
|
bool is_ordered_wdc(const void *);
|
||||||
|
int get_id_wdc(const void *);
|
||||||
|
int get_max_packet_life_time_wdc(const void *);
|
||||||
|
int get_max_retransmits_wdc(const void *);
|
||||||
|
const char *get_protocol_wdc(const void *);
|
||||||
|
bool is_negotiated_wdc(const void *);
|
||||||
|
godot_error poll_wdc(void *);
|
||||||
|
void close_wdc(void *);
|
||||||
|
|
||||||
|
class WebRTCDataChannelNative : public godot::WebRTCDataChannelGDNative {
|
||||||
|
GODOT_CLASS(WebRTCDataChannelNative, godot::WebRTCDataChannelGDNative);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
godot_net_webrtc_data_channel interface = {
|
||||||
|
{ 3, 1 },
|
||||||
|
this,
|
||||||
|
|
||||||
|
&get_packet_wdc,
|
||||||
|
&put_packet_wdc,
|
||||||
|
&get_available_packet_count_wdc,
|
||||||
|
&get_max_packet_size_wdc,
|
||||||
|
|
||||||
|
&set_write_mode_wdc,
|
||||||
|
&get_write_mode_wdc,
|
||||||
|
&was_string_packet_wdc,
|
||||||
|
&get_ready_state_wdc,
|
||||||
|
&get_label_wdc,
|
||||||
|
&is_ordered_wdc,
|
||||||
|
&get_id_wdc,
|
||||||
|
&get_max_packet_life_time_wdc,
|
||||||
|
&get_max_retransmits_wdc,
|
||||||
|
&get_protocol_wdc,
|
||||||
|
&is_negotiated_wdc,
|
||||||
|
|
||||||
|
&poll_wdc,
|
||||||
|
&close_wdc,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void _register_methods();
|
||||||
|
|
||||||
|
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 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 godot_error 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;
|
||||||
|
|
||||||
|
~WebRTCDataChannelNative();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBRTC_DATA_CHANNEL_NATIVE
|
||||||
65
src/net/WebRTCPeerConnectionNative.cpp
Normal file
65
src/net/WebRTCPeerConnectionNative.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include "WebRTCPeerConnectionNative.hpp"
|
||||||
|
|
||||||
|
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) {
|
||||||
|
ERR_FAIL_COND(!_net_api);
|
||||||
|
_net_api->godot_net_bind_webrtc_peer_connection(_owner, p_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRTCPeerConnectionNative::_register_methods() {}
|
||||||
|
|
||||||
|
void WebRTCPeerConnectionNative::_init() {
|
||||||
|
register_interface(&interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRTCPeerConnectionNative::~WebRTCPeerConnectionNative() {
|
||||||
|
if (_owner) {
|
||||||
|
register_interface(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The C interface that implements WebRTCPeerConnection.
|
||||||
|
* In this case it forwards calls to our C++ class, but could be plain C,
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error initialize_wp(void *user, const godot_dictionary *p_config) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->initialize(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error create_offer_wp(void *user) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->create_offer();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error create_answer_wp(void *user) {
|
||||||
|
return GODOT_ERR_UNAVAILABLE; // Not implemented, not used yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error set_remote_description_wp(void *user, const char *type, const char *sdp) {
|
||||||
|
return ((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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_error poll_wp(void *user) {
|
||||||
|
return ((WebRTCPeerConnectionNative *)user)->poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_wp(void *user) {
|
||||||
|
((WebRTCPeerConnectionNative *)user)->close();
|
||||||
|
}
|
||||||
66
src/net/WebRTCPeerConnectionNative.hpp
Normal file
66
src/net/WebRTCPeerConnectionNative.hpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#ifndef WEBRTC_PEER_NATIVE
|
||||||
|
#define WEBRTC_PEER_NATIVE
|
||||||
|
|
||||||
|
#include <Godot.hpp>
|
||||||
|
#include <Reference.hpp>
|
||||||
|
#include <WebRTCPeerConnectionGDNative.hpp>
|
||||||
|
|
||||||
|
#include <net/godot_net.h>
|
||||||
|
|
||||||
|
/* Forward declare interface functions */
|
||||||
|
godot_int get_connection_state_wp(const void *);
|
||||||
|
|
||||||
|
godot_error initialize_wp(void *, const godot_dictionary *);
|
||||||
|
godot_object *create_data_channel_wp(void *, const char *, const godot_dictionary *);
|
||||||
|
godot_error create_offer_wp(void *);
|
||||||
|
godot_error create_answer_wp(void *);
|
||||||
|
godot_error set_remote_description_wp(void *, const char *, const char *);
|
||||||
|
godot_error set_local_description_wp(void *, const char *, const char *);
|
||||||
|
godot_error add_ice_candidate_wp(void *, const char *, int, const char *);
|
||||||
|
godot_error poll_wp(void *);
|
||||||
|
void close_wp(void *);
|
||||||
|
|
||||||
|
class WebRTCPeerConnectionNative : public godot::WebRTCPeerConnectionGDNative {
|
||||||
|
GODOT_CLASS(WebRTCPeerConnectionNative, godot::WebRTCPeerConnectionGDNative);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
godot_net_webrtc_peer_connection interface = {
|
||||||
|
{ 3, 1 },
|
||||||
|
this,
|
||||||
|
|
||||||
|
&get_connection_state_wp,
|
||||||
|
|
||||||
|
&initialize_wp,
|
||||||
|
&create_data_channel_wp,
|
||||||
|
&create_offer_wp,
|
||||||
|
&create_answer_wp,
|
||||||
|
&set_remote_description_wp,
|
||||||
|
&set_local_description_wp,
|
||||||
|
&add_ice_candidate_wp,
|
||||||
|
&poll_wp,
|
||||||
|
&close_wp,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void _register_methods();
|
||||||
|
static const godot_gdnative_ext_net_3_2_api_struct *_net_api;
|
||||||
|
|
||||||
|
void _init();
|
||||||
|
void register_interface(const godot_net_webrtc_peer_connection *interface);
|
||||||
|
|
||||||
|
virtual ConnectionState 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;
|
||||||
|
|
||||||
|
~WebRTCPeerConnectionNative();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBRTC_PEER_NATIVE
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#include "WebRTCPeerNative.hpp"
|
|
||||||
|
|
||||||
const godot_gdnative_ext_net_3_2_api_struct *WebRTCPeerNative::_net_api = NULL;
|
|
||||||
|
|
||||||
void WebRTCPeerNative::register_interface(const godot_net_webrtc_peer *p_interface) {
|
|
||||||
ERR_FAIL_COND(!_net_api);
|
|
||||||
_net_api->godot_net_bind_webrtc_peer(_owner, p_interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebRTCPeerNative::_register_methods() {}
|
|
||||||
|
|
||||||
void WebRTCPeerNative::_init() {
|
|
||||||
register_interface(&interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRTCPeerNative::~WebRTCPeerNative() {
|
|
||||||
if (_owner) {
|
|
||||||
register_interface(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The C interface that implements WebRTCPeer.
|
|
||||||
* In this case it forwards calls to our C++ class, but could be plain C,
|
|
||||||
* and you could use void *user for any kind of state struct pointer you have.
|
|
||||||
*/
|
|
||||||
godot_error get_packet_wp(void *user, const uint8_t **r_buffer, int *r_len) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_packet(r_buffer, r_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error put_packet_wp(void *user, const uint8_t *p_buffer, int p_len) {
|
|
||||||
return ((WebRTCPeerNative *)user)->put_packet(p_buffer, p_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_available_packet_count_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_available_packet_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_max_packet_size_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_max_packet_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_write_mode_wp(void *user, godot_int write_mode) {
|
|
||||||
((WebRTCPeerNative *)user)->set_write_mode(write_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_write_mode_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_write_mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool was_string_packet_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->was_string_packet();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_int get_connection_state_wp(const void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->get_connection_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error create_offer_wp(void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->create_offer();
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error set_remote_description_wp(void *user, const char *type, const char *sdp) {
|
|
||||||
return ((WebRTCPeerNative *)user)->set_remote_description(type, sdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error set_local_description_wp(void *user, const char *type, const char *sdp) {
|
|
||||||
return ((WebRTCPeerNative *)user)->set_local_description(type, sdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error add_ice_candidate_wp(void *user, const char *sdpMidName, int sdpMlineIndexName, const char *sdpName) {
|
|
||||||
return ((WebRTCPeerNative *)user)->add_ice_candidate(sdpMidName, sdpMlineIndexName, sdpName);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_error poll_wp(void *user) {
|
|
||||||
return ((WebRTCPeerNative *)user)->poll();
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#ifndef WEBRTC_PEER_NATIVE
|
|
||||||
#define WEBRTC_PEER_NATIVE
|
|
||||||
|
|
||||||
#include <Godot.hpp>
|
|
||||||
#include <Reference.hpp>
|
|
||||||
#include <WebRTCPeerGDNative.hpp>
|
|
||||||
|
|
||||||
#include <net/godot_net.h>
|
|
||||||
|
|
||||||
/* Forward declare interface functions */
|
|
||||||
godot_error get_packet_wp(void *, const uint8_t **, int *);
|
|
||||||
godot_error put_packet_wp(void *, const uint8_t *, int);
|
|
||||||
godot_int get_available_packet_count_wp(const void *);
|
|
||||||
godot_int get_max_packet_size_wp(const void *);
|
|
||||||
|
|
||||||
void set_write_mode_wp(void *, godot_int);
|
|
||||||
godot_int get_write_mode_wp(const void *);
|
|
||||||
bool was_string_packet_wp(const void *);
|
|
||||||
godot_int get_connection_state_wp(const void *);
|
|
||||||
|
|
||||||
godot_error create_offer_wp(void *);
|
|
||||||
godot_error set_remote_description_wp(void *, const char *, const char *);
|
|
||||||
godot_error set_local_description_wp(void *, const char *, const char *);
|
|
||||||
godot_error add_ice_candidate_wp(void *, const char *, int, const char *);
|
|
||||||
godot_error poll_wp(void *);
|
|
||||||
|
|
||||||
class WebRTCPeerNative : public godot::WebRTCPeerGDNative {
|
|
||||||
GODOT_CLASS(WebRTCPeerNative, godot::WebRTCPeerGDNative);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
godot_net_webrtc_peer interface = {
|
|
||||||
{ 3, 1 },
|
|
||||||
this,
|
|
||||||
|
|
||||||
&get_packet_wp,
|
|
||||||
&put_packet_wp,
|
|
||||||
&get_available_packet_count_wp,
|
|
||||||
&get_max_packet_size_wp,
|
|
||||||
|
|
||||||
&set_write_mode_wp,
|
|
||||||
&get_write_mode_wp,
|
|
||||||
&was_string_packet_wp,
|
|
||||||
&get_connection_state_wp,
|
|
||||||
|
|
||||||
&create_offer_wp,
|
|
||||||
&set_remote_description_wp,
|
|
||||||
&set_local_description_wp,
|
|
||||||
&add_ice_candidate_wp,
|
|
||||||
&poll_wp,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void _register_methods();
|
|
||||||
static const godot_gdnative_ext_net_3_2_api_struct *_net_api;
|
|
||||||
|
|
||||||
void _init();
|
|
||||||
void register_interface(const godot_net_webrtc_peer *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 godot_int get_connection_state() const = 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;
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
~WebRTCPeerNative();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WEBRTC_PEER_NATIVE
|
|
||||||
Reference in New Issue
Block a user