mirror of
https://github.com/godotengine/webrtc-native.git
synced 2026-01-01 05:48:15 +03:00
211 lines
6.8 KiB
C++
211 lines
6.8 KiB
C++
/*************************************************************************/
|
|
/* WebRTCLibDataChannel.cpp */
|
|
/*************************************************************************/
|
|
/* This file is part of: */
|
|
/* GODOT ENGINE */
|
|
/* https://godotengine.org */
|
|
/*************************************************************************/
|
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
/* */
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
/* a copy of this software and associated documentation files (the */
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
/* the following conditions: */
|
|
/* */
|
|
/* The above copyright notice and this permission notice shall be */
|
|
/* included in all copies or substantial portions of the Software. */
|
|
/* */
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/*************************************************************************/
|
|
|
|
#include "WebRTCLibDataChannel.hpp"
|
|
|
|
#include "GDNativeLibrary.hpp"
|
|
#include "NativeScript.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::detail::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 = out->cast_to<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;
|
|
}
|