summaryrefslogtreecommitdiff
path: root/modules/webrtc
diff options
context:
space:
mode:
authorFabio Alessandrelli <fabio.alessandrelli@gmail.com>2021-07-27 12:06:48 +0200
committerFabio Alessandrelli <fabio.alessandrelli@gmail.com>2021-07-30 17:29:50 +0200
commit2cf39b97ae326a28015b67221b928e4861380d29 (patch)
tree12d05483c198a7387768a6739fedbf143bd1ae0d /modules/webrtc
parentc27ef1565ff44eaacc081081b6b21b23665fbe10 (diff)
[Net] Implement RPC channels in MultiplayerAPI.
Diffstat (limited to 'modules/webrtc')
-rw-r--r--modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml2
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp97
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.h24
3 files changed, 82 insertions, 41 deletions
diff --git a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
index 0c4a0d4ea0..c53af22ae1 100644
--- a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
+++ b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
@@ -51,10 +51,12 @@
<return type="int" enum="Error" />
<argument index="0" name="peer_id" type="int" />
<argument index="1" name="server_compatibility" type="bool" default="false" />
+ <argument index="2" name="channels_config" type="Array" default="[]" />
<description>
Initialize the multiplayer peer with the given [code]peer_id[/code] (must be between 1 and 2147483647).
If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant MultiplayerPeer.CONNECTION_CONNECTED] and [signal MultiplayerPeer.connection_succeeded] will not be emitted.
If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal MultiplayerPeer.peer_connected] signals until a peer with id [constant MultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal MultiplayerPeer.connection_succeeded]. After that the signal [signal MultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal MultiplayerPeer.server_disconnected] will be emitted and state will become [constant MultiplayerPeer.CONNECTION_CONNECTED].
+ You can optionally specify a [code]channels_config[/code] array of [enum MultiplayerPeer.TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel).
</description>
</method>
<method name="remove_peer">
diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 9b08a26aed..95c8c13449 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -34,7 +34,7 @@
#include "core/os/os.h"
void WebRTCMultiplayerPeer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("initialize", "peer_id", "server_compatibility"), &WebRTCMultiplayerPeer::initialize, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("initialize", "peer_id", "server_compatibility", "channels_config"), &WebRTCMultiplayerPeer::initialize, DEFVAL(false), DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("add_peer", "peer", "peer_id", "unreliable_lifetime"), &WebRTCMultiplayerPeer::add_peer, DEFVAL(1));
ClassDB::bind_method(D_METHOD("remove_peer", "peer_id"), &WebRTCMultiplayerPeer::remove_peer);
ClassDB::bind_method(D_METHOD("has_peer", "peer_id"), &WebRTCMultiplayerPeer::has_peer);
@@ -43,6 +43,14 @@ void WebRTCMultiplayerPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("close"), &WebRTCMultiplayerPeer::close);
}
+void WebRTCMultiplayerPeer::set_transfer_channel(int p_channel) {
+ transfer_channel = p_channel;
+}
+
+int WebRTCMultiplayerPeer::get_transfer_channel() const {
+ return transfer_channel;
+}
+
void WebRTCMultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
transfer_mode = p_mode;
}
@@ -192,8 +200,34 @@ MultiplayerPeer::ConnectionStatus WebRTCMultiplayerPeer::get_connection_status()
return connection_status;
}
-Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat) {
- ERR_FAIL_COND_V(p_self_id < 0 || p_self_id > ~(1 << 31), ERR_INVALID_PARAMETER);
+Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat, Array p_channels_config) {
+ ERR_FAIL_COND_V(p_self_id < 1 || p_self_id > ~(1 << 31), ERR_INVALID_PARAMETER);
+ channels_config.clear();
+ for (int i = 0; i < p_channels_config.size(); i++) {
+ ERR_FAIL_COND_V_MSG(p_channels_config[i].get_type() != Variant::INT, ERR_INVALID_PARAMETER, "The 'channels_config' array must contain only enum values from 'MultiplayerPeer.TransferMode'");
+ int mode = p_channels_config[i].operator int();
+ // Initialize data channel configurations.
+ Dictionary cfg;
+ cfg["id"] = CH_RESERVED_MAX + i + 1;
+ cfg["negotiated"] = true;
+ cfg["ordered"] = true;
+
+ switch (mode) {
+ case TRANSFER_MODE_UNRELIABLE_ORDERED:
+ cfg["maxPacketLifetime"] = 1;
+ break;
+ case TRANSFER_MODE_UNRELIABLE:
+ cfg["maxPacketLifetime"] = 1;
+ cfg["ordered"] = false;
+ break;
+ case TRANSFER_MODE_RELIABLE:
+ break;
+ default:
+ ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("The 'channels_config' array must contain only enum values from 'MultiplayerPeer.TransferMode'. Got: %d", mode));
+ }
+ channels_config.push_back(cfg);
+ }
+
unique_id = p_self_id;
server_compat = p_server_compat;
@@ -260,17 +294,23 @@ Error WebRTCMultiplayerPeer::add_peer(Ref<WebRTCPeerConnection> p_peer, int p_pe
cfg["id"] = 1;
peer->channels[CH_RELIABLE] = p_peer->create_data_channel("reliable", cfg);
- ERR_FAIL_COND_V(!peer->channels[CH_RELIABLE].is_valid(), FAILED);
+ ERR_FAIL_COND_V(peer->channels[CH_RELIABLE].is_null(), FAILED);
cfg["id"] = 2;
cfg["maxPacketLifetime"] = p_unreliable_lifetime;
peer->channels[CH_ORDERED] = p_peer->create_data_channel("ordered", cfg);
- ERR_FAIL_COND_V(!peer->channels[CH_ORDERED].is_valid(), FAILED);
+ ERR_FAIL_COND_V(peer->channels[CH_ORDERED].is_null(), FAILED);
cfg["id"] = 3;
cfg["ordered"] = false;
peer->channels[CH_UNRELIABLE] = p_peer->create_data_channel("unreliable", cfg);
- ERR_FAIL_COND_V(!peer->channels[CH_UNRELIABLE].is_valid(), FAILED);
+ ERR_FAIL_COND_V(peer->channels[CH_UNRELIABLE].is_null(), FAILED);
+
+ for (const Dictionary &dict : channels_config) {
+ Ref<WebRTCDataChannel> ch = p_peer->create_data_channel(String::num_int64(dict["id"]), dict);
+ ERR_FAIL_COND_V(ch.is_null(), FAILED);
+ peer->channels.push_back(ch);
+ }
peer_map[p_peer_id] = peer; // add the new peer connection to the peer_map
@@ -312,17 +352,21 @@ Error WebRTCMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_
Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
ERR_FAIL_COND_V(connection_status == CONNECTION_DISCONNECTED, ERR_UNCONFIGURED);
- int ch = CH_RELIABLE;
- switch (transfer_mode) {
- case TRANSFER_MODE_RELIABLE:
- ch = CH_RELIABLE;
- break;
- case TRANSFER_MODE_UNRELIABLE_ORDERED:
- ch = CH_ORDERED;
- break;
- case TRANSFER_MODE_UNRELIABLE:
- ch = CH_UNRELIABLE;
- break;
+ int ch = transfer_channel;
+ if (ch == 0) {
+ switch (transfer_mode) {
+ case TRANSFER_MODE_RELIABLE:
+ ch = CH_RELIABLE;
+ break;
+ case TRANSFER_MODE_UNRELIABLE_ORDERED:
+ ch = CH_ORDERED;
+ break;
+ case TRANSFER_MODE_UNRELIABLE:
+ ch = CH_UNRELIABLE;
+ break;
+ }
+ } else {
+ ch += CH_RESERVED_MAX - 1;
}
Map<int, Ref<ConnectedPeer>>::Element *E = nullptr;
@@ -331,8 +375,8 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
E = peer_map.find(target_peer);
ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, "Invalid target peer: " + itos(target_peer) + ".");
- ERR_FAIL_COND_V(E->value()->channels.size() <= ch, ERR_BUG);
- ERR_FAIL_COND_V(!E->value()->channels[ch].is_valid(), ERR_BUG);
+ ERR_FAIL_COND_V_MSG(E->value()->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
+ ERR_FAIL_COND_V(E->value()->channels[ch].is_null(), ERR_BUG);
return E->value()->channels[ch]->put_packet(p_buffer, p_buffer_size);
} else {
@@ -344,7 +388,8 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
continue;
}
- ERR_CONTINUE(F->value()->channels.size() <= ch || !F->value()->channels[ch].is_valid());
+ ERR_CONTINUE_MSG(F->value()->channels.size() <= ch, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
+ ERR_CONTINUE(F->value()->channels[ch].is_null());
F->value()->channels[ch]->put_packet(p_buffer, p_buffer_size);
}
}
@@ -370,23 +415,13 @@ int WebRTCMultiplayerPeer::get_max_packet_size() const {
void WebRTCMultiplayerPeer::close() {
peer_map.clear();
+ channels_config.clear();
unique_id = 0;
next_packet_peer = 0;
target_peer = 0;
connection_status = CONNECTION_DISCONNECTED;
}
-WebRTCMultiplayerPeer::WebRTCMultiplayerPeer() {
- unique_id = 0;
- next_packet_peer = 0;
- target_peer = 0;
- client_count = 0;
- transfer_mode = TRANSFER_MODE_RELIABLE;
- refuse_connections = false;
- connection_status = CONNECTION_DISCONNECTED;
- server_compat = false;
-}
-
WebRTCMultiplayerPeer::~WebRTCMultiplayerPeer() {
close();
}
diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h
index 1d9387b6dc..ef4fe1678c 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.h
+++ b/modules/webrtc/webrtc_multiplayer_peer.h
@@ -62,25 +62,27 @@ private:
}
};
- uint32_t unique_id;
- int target_peer;
- int client_count;
- bool refuse_connections;
- ConnectionStatus connection_status;
- TransferMode transfer_mode;
- int next_packet_peer;
- bool server_compat;
+ uint32_t unique_id = 0;
+ int target_peer = 0;
+ int client_count = 0;
+ bool refuse_connections = false;
+ ConnectionStatus connection_status = CONNECTION_DISCONNECTED;
+ int transfer_channel = 0;
+ TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
+ int next_packet_peer = 0;
+ bool server_compat = false;
Map<int, Ref<ConnectedPeer>> peer_map;
+ List<Dictionary> channels_config;
void _peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict);
void _find_next_peer();
public:
- WebRTCMultiplayerPeer();
+ WebRTCMultiplayerPeer() {}
~WebRTCMultiplayerPeer();
- Error initialize(int p_self_id, bool p_server_compat = false);
+ Error initialize(int p_self_id, bool p_server_compat = false, Array p_channels_config = Array());
Error add_peer(Ref<WebRTCPeerConnection> p_peer, int p_peer_id, int p_unreliable_lifetime = 1);
void remove_peer(int p_peer_id);
bool has_peer(int p_peer_id);
@@ -95,6 +97,8 @@ public:
int get_max_packet_size() const override;
// MultiplayerPeer
+ void set_transfer_channel(int p_channel) override;
+ int get_transfer_channel() const override;
void set_transfer_mode(TransferMode p_mode) override;
TransferMode get_transfer_mode() const override;
void set_target_peer(int p_peer_id) override;