summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFabio Alessandrelli <fabio.alessandrelli@gmail.com>2019-04-21 04:57:53 +0200
committerFabio Alessandrelli <fabio.alessandrelli@gmail.com>2019-05-16 10:32:51 +0200
commit3e64a42b1492e38bf033041c0eb1212542728cbd (patch)
treed187f873ecfdace0d127c6bc340ed295edcaa2f1 /src
parentf2cf2e5340c1aa20516aea4863b8f7a46f317bb6 (diff)
downloadfork-godot-webrtc-native-3e64a42b1492e38bf033041c0eb1212542728cbd.tar.gz
fork-godot-webrtc-native-3e64a42b1492e38bf033041c0eb1212542728cbd.tar.bz2
fork-godot-webrtc-native-3e64a42b1492e38bf033041c0eb1212542728cbd.zip
Update to new DataChannel API.
New WebRTCLibDataChannel class act as PacketPeer. Old WebRTCPeer (now WebRTCPeerConnection) now allows you to set configuration (STUN/TURN) and creating multiple data channels. Fixed many bugs and implemented most of the missing API.
Diffstat (limited to 'src')
-rw-r--r--src/GodotCreateSessionDescriptionObserver.cpp10
-rw-r--r--src/GodotDataChannelObserver.cpp19
-rw-r--r--src/GodotPeerConnectionObserver.cpp24
-rw-r--r--src/GodotSetSessionDescriptionObserver.cpp8
-rw-r--r--src/WebRTCLibDataChannel.cpp177
-rw-r--r--src/WebRTCLibDataChannel.hpp76
-rw-r--r--src/WebRTCLibPeer.cpp202
-rw-r--r--src/WebRTCLibPeerConnection.cpp245
-rw-r--r--src/WebRTCLibPeerConnection.hpp (renamed from src/WebRTCLibPeer.hpp)57
-rw-r--r--src/init.cpp10
-rw-r--r--src/net/WebRTCDataChannelNative.cpp92
-rw-r--r--src/net/WebRTCDataChannelNative.hpp91
-rw-r--r--src/net/WebRTCPeerConnectionNative.cpp65
-rw-r--r--src/net/WebRTCPeerConnectionNative.hpp66
-rw-r--r--src/net/WebRTCPeerNative.cpp77
-rw-r--r--src/net/WebRTCPeerNative.hpp80
16 files changed, 858 insertions, 441 deletions
diff --git a/src/GodotCreateSessionDescriptionObserver.cpp b/src/GodotCreateSessionDescriptionObserver.cpp
index 77d1308..f9d110c 100644
--- a/src/GodotCreateSessionDescriptionObserver.cpp
+++ b/src/GodotCreateSessionDescriptionObserver.cpp
@@ -1,16 +1,16 @@
-#include "WebRTCLibPeer.hpp"
+#include "WebRTCLibPeerConnection.hpp"
using namespace godot_webrtc;
-WebRTCLibPeer::GodotCSDO::GodotCSDO(WebRTCLibPeer *parent) {
+WebRTCLibPeerConnection::GodotCSDO::GodotCSDO(WebRTCLibPeerConnection *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:
std::string sdp; // sdp = session description protocol
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){};
diff --git a/src/GodotDataChannelObserver.cpp b/src/GodotDataChannelObserver.cpp
deleted file mode 100644
index 7a6cf96..0000000
--- a/src/GodotDataChannelObserver.cpp
+++ /dev/null
@@ -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){};
diff --git a/src/GodotPeerConnectionObserver.cpp b/src/GodotPeerConnectionObserver.cpp
index 298cfcf..c3f8f39 100644
--- a/src/GodotPeerConnectionObserver.cpp
+++ b/src/GodotPeerConnectionObserver.cpp
@@ -1,33 +1,35 @@
-#include "WebRTCLibPeer.hpp"
+#include "WebRTCLibPeerConnection.hpp"
+#include "WebRTCLibDataChannel.hpp"
using namespace godot_webrtc;
-WebRTCLibPeer::GodotPCO::GodotPCO(WebRTCLibPeer *parent) {
+WebRTCLibPeerConnection::GodotPCO::GodotPCO(WebRTCLibPeerConnection *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:
godot::Dictionary candidateSDP;
@@ -38,7 +40,7 @@ void WebRTCLibPeer::GodotPCO::OnIceCandidate(const webrtc::IceCandidateInterface
candidate->ToString(&sdp);
godot::String candidateSdpName = sdp.c_str();
- parent->queue_signal("new_ice_candidate",
+ parent->queue_signal("ice_candidate_created",
3,
candidateSdpMidName,
candidateSdpMlineIndexName,
diff --git a/src/GodotSetSessionDescriptionObserver.cpp b/src/GodotSetSessionDescriptionObserver.cpp
index 52be2af..96d466c 100644
--- a/src/GodotSetSessionDescriptionObserver.cpp
+++ b/src/GodotSetSessionDescriptionObserver.cpp
@@ -1,11 +1,11 @@
-#include "WebRTCLibPeer.hpp"
+#include "WebRTCLibPeerConnection.hpp"
using namespace godot_webrtc;
-WebRTCLibPeer::GodotSSDO::GodotSSDO(WebRTCLibPeer *parent) {
+WebRTCLibPeerConnection::GodotSSDO::GodotSSDO(WebRTCLibPeerConnection *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){};
diff --git a/src/WebRTCLibDataChannel.cpp b/src/WebRTCLibDataChannel.cpp
new file mode 100644
index 0000000..ede89a9
--- /dev/null
+++ b/src/WebRTCLibDataChannel.cpp
@@ -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;
+}
diff --git a/src/WebRTCLibDataChannel.hpp b/src/WebRTCLibDataChannel.hpp
new file mode 100644
index 0000000..557d1da
--- /dev/null
+++ b/src/WebRTCLibDataChannel.hpp
@@ -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
diff --git a/src/WebRTCLibPeer.cpp b/src/WebRTCLibPeer.cpp
deleted file mode 100644
index c94cfcd..0000000
--- a/src/WebRTCLibPeer.cpp
+++ /dev/null
@@ -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;
-}
diff --git a/src/WebRTCLibPeerConnection.cpp b/src/WebRTCLibPeerConnection.cpp
new file mode 100644
index 0000000..a922f1b
--- /dev/null
+++ b/src/WebRTCLibPeerConnection.cpp
@@ -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();
+}
diff --git a/src/WebRTCLibPeer.hpp b/src/WebRTCLibPeerConnection.hpp
index 9707f4f..b46d606 100644
--- a/src/WebRTCLibPeer.hpp
+++ b/src/WebRTCLibPeerConnection.hpp
@@ -8,62 +8,47 @@
#include <functional> // std::function
#include <mutex> // mutex @TODO replace std::mutex with Godot mutex
-#include "net/WebRTCPeerNative.hpp"
+#include "net/WebRTCPeerConnectionNative.hpp"
namespace godot_webrtc {
-class WebRTCLibPeer : public WebRTCPeerNative {
- GODOT_CLASS(WebRTCLibPeer, WebRTCPeerNative);
+class WebRTCLibPeerConnection : public WebRTCPeerConnectionNative {
+ GODOT_CLASS(WebRTCLibPeerConnection, WebRTCPeerConnectionNative);
+
+private:
+ godot_error _create_pc(webrtc::PeerConnectionInterface::RTCConfiguration &config);
public:
static void _register_methods();
void _init();
- void set_write_mode(godot_int mode);
- godot_int get_write_mode() const;
- bool was_string_packet() const;
- godot_int get_connection_state() const;
+ ConnectionState 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 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();
- /* WebRTCPeer */
- 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;
-
- WebRTCLibPeer();
- ~WebRTCLibPeer();
+ WebRTCLibPeerConnection();
+ ~WebRTCLibPeerConnection();
/* 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::StringName p_name, Variant_ARG_LIST);
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 **/
class GodotPCO : public webrtc::PeerConnectionObserver {
public:
- WebRTCLibPeer *parent;
+ WebRTCLibPeerConnection *parent;
- GodotPCO(WebRTCLibPeer *parent);
+ GodotPCO(WebRTCLibPeerConnection *parent);
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;
@@ -77,9 +62,9 @@ public:
/** CreateSessionDescriptionObserver callback functions **/
class GodotCSDO : public webrtc::CreateSessionDescriptionObserver {
public:
- WebRTCLibPeer *parent;
+ WebRTCLibPeerConnection *parent;
- GodotCSDO(WebRTCLibPeer *parent);
+ GodotCSDO(WebRTCLibPeerConnection *parent);
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
void OnFailure(const std::string &error) override;
};
@@ -87,29 +72,23 @@ public:
/** SetSessionDescriptionObserver callback functions **/
class GodotSSDO : public webrtc::SetSessionDescriptionObserver {
public:
- WebRTCLibPeer *parent;
+ WebRTCLibPeerConnection *parent;
- GodotSSDO(WebRTCLibPeer *parent);
+ GodotSSDO(WebRTCLibPeerConnection *parent);
void OnSuccess() override;
void OnFailure(const std::string &error) override;
};
- GodotDCO dco;
GodotPCO pco;
rtc::scoped_refptr<GodotSSDO> ptr_ssdo;
rtc::scoped_refptr<GodotCSDO> ptr_csdo;
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;
rtc::Thread *signaling_thread;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory;
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection;
- rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel;
};
} // namespace godot_webrtc
diff --git a/src/init.cpp b/src/init.cpp
index 9b02bd9..75a89e9 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,5 +1,6 @@
-#include "WebRTCLibPeer.hpp"
-#include "net/WebRTCPeerNative.hpp"
+#include "WebRTCLibDataChannel.hpp"
+#include "WebRTCLibPeerConnection.hpp"
+#include "net/WebRTCPeerConnectionNative.hpp"
#include <gdnative_api_struct.gen.h>
/* Godot export stuff */
@@ -16,7 +17,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) {
- 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;
}
}
@@ -30,5 +31,6 @@ extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_opt
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
godot::Godot::nativescript_init(handle);
- godot::register_class<godot_webrtc::WebRTCLibPeer>();
+ godot::register_class<godot_webrtc::WebRTCLibPeerConnection>();
+ godot::register_class<godot_webrtc::WebRTCLibDataChannel>();
}
diff --git a/src/net/WebRTCDataChannelNative.cpp b/src/net/WebRTCDataChannelNative.cpp
new file mode 100644
index 0000000..8e1d3b1
--- /dev/null
+++ b/src/net/WebRTCDataChannelNative.cpp
@@ -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();
+}
diff --git a/src/net/WebRTCDataChannelNative.hpp b/src/net/WebRTCDataChannelNative.hpp
new file mode 100644
index 0000000..eaeb95d
--- /dev/null
+++ b/src/net/WebRTCDataChannelNative.hpp
@@ -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
diff --git a/src/net/WebRTCPeerConnectionNative.cpp b/src/net/WebRTCPeerConnectionNative.cpp
new file mode 100644
index 0000000..5f7d83e
--- /dev/null
+++ b/src/net/WebRTCPeerConnectionNative.cpp
@@ -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();
+}
diff --git a/src/net/WebRTCPeerConnectionNative.hpp b/src/net/WebRTCPeerConnectionNative.hpp
new file mode 100644
index 0000000..3b0ac79
--- /dev/null
+++ b/src/net/WebRTCPeerConnectionNative.hpp
@@ -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
diff --git a/src/net/WebRTCPeerNative.cpp b/src/net/WebRTCPeerNative.cpp
deleted file mode 100644
index a0872bc..0000000
--- a/src/net/WebRTCPeerNative.cpp
+++ /dev/null
@@ -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();
-}
diff --git a/src/net/WebRTCPeerNative.hpp b/src/net/WebRTCPeerNative.hpp
deleted file mode 100644
index d5f2c6f..0000000
--- a/src/net/WebRTCPeerNative.hpp
+++ /dev/null
@@ -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