2019-05-11 07:53:49 +08:00
/*************************************************************************/
2021-07-12 22:26:37 +08:00
/* webrtc_multiplayer_peer.cpp */
2019-05-11 07:53:49 +08:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
2021-01-02 03:13:46 +08:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2019-05-11 07:53:49 +08:00
/* */
/* 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. */
/*************************************************************************/
2021-07-12 22:26:37 +08:00
# include "webrtc_multiplayer_peer.h"
2019-05-11 07:53:49 +08:00
# include "core/io/marshalls.h"
# include "core/os/os.h"
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : _bind_methods ( ) {
2021-07-27 18:06:48 +08:00
ClassDB : : bind_method ( D_METHOD ( " initialize " , " peer_id " , " server_compatibility " , " channels_config " ) , & WebRTCMultiplayerPeer : : initialize , DEFVAL ( false ) , DEFVAL ( Array ( ) ) ) ;
2021-07-12 22:26:37 +08:00
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " get_peer " , " peer_id " ) , & WebRTCMultiplayerPeer : : get_peer ) ;
ClassDB : : bind_method ( D_METHOD ( " get_peers " ) , & WebRTCMultiplayerPeer : : get_peers ) ;
ClassDB : : bind_method ( D_METHOD ( " close " ) , & WebRTCMultiplayerPeer : : close ) ;
2019-05-11 07:53:49 +08:00
}
2021-07-27 18:06:48 +08:00
void WebRTCMultiplayerPeer : : set_transfer_channel ( int p_channel ) {
transfer_channel = p_channel ;
}
int WebRTCMultiplayerPeer : : get_transfer_channel ( ) const {
return transfer_channel ;
}
2021-09-04 01:40:47 +08:00
void WebRTCMultiplayerPeer : : set_transfer_mode ( Multiplayer : : TransferMode p_mode ) {
2019-05-11 07:53:49 +08:00
transfer_mode = p_mode ;
}
2021-09-04 01:40:47 +08:00
Multiplayer : : TransferMode WebRTCMultiplayerPeer : : get_transfer_mode ( ) const {
2019-05-11 07:53:49 +08:00
return transfer_mode ;
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : set_target_peer ( int p_peer_id ) {
2019-05-11 07:53:49 +08:00
target_peer = p_peer_id ;
}
2021-07-12 22:11:05 +08:00
/* Returns the ID of the MultiplayerPeer who sent the most recent packet: */
2021-07-12 22:26:37 +08:00
int WebRTCMultiplayerPeer : : get_packet_peer ( ) const {
2019-05-11 07:53:49 +08:00
return next_packet_peer ;
}
2021-07-12 22:26:37 +08:00
bool WebRTCMultiplayerPeer : : is_server ( ) const {
2019-05-11 07:53:49 +08:00
return unique_id = = TARGET_PEER_SERVER ;
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : poll ( ) {
2020-05-14 22:41:43 +08:00
if ( peer_map . size ( ) = = 0 ) {
2019-05-11 07:53:49 +08:00
return ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
List < int > remove ;
List < int > add ;
2020-03-17 14:33:00 +08:00
for ( Map < int , Ref < ConnectedPeer > > : : Element * E = peer_map . front ( ) ; E ; E = E - > next ( ) ) {
2019-05-11 07:53:49 +08:00
Ref < ConnectedPeer > peer = E - > get ( ) ;
peer - > connection - > poll ( ) ;
// Check peer state
switch ( peer - > connection - > get_connection_state ( ) ) {
case WebRTCPeerConnection : : STATE_NEW :
case WebRTCPeerConnection : : STATE_CONNECTING :
// Go to next peer, not ready yet.
continue ;
case WebRTCPeerConnection : : STATE_CONNECTED :
// Good to go, go ahead and check channel state.
break ;
default :
// Peer is closed or in error state. Got to next peer.
remove . push_back ( E - > key ( ) ) ;
continue ;
}
// Check channels state
int ready = 0 ;
2020-03-17 14:33:00 +08:00
for ( List < Ref < WebRTCDataChannel > > : : Element * C = peer - > channels . front ( ) ; C & & C - > get ( ) . is_valid ( ) ; C = C - > next ( ) ) {
2019-05-11 07:53:49 +08:00
Ref < WebRTCDataChannel > ch = C - > get ( ) ;
switch ( ch - > get_ready_state ( ) ) {
case WebRTCDataChannel : : STATE_CONNECTING :
continue ;
case WebRTCDataChannel : : STATE_OPEN :
ready + + ;
continue ;
default :
// Channel was closed or in error state, remove peer id.
remove . push_back ( E - > key ( ) ) ;
}
// We got a closed channel break out, the peer will be removed.
break ;
}
// This peer has newly connected, and all channels are now open.
if ( ready = = peer - > channels . size ( ) & & ! peer - > connected ) {
peer - > connected = true ;
add . push_back ( E - > key ( ) ) ;
}
}
// Remove disconnected peers
2021-07-16 11:45:57 +08:00
for ( int & E : remove ) {
remove_peer ( E ) ;
if ( next_packet_peer = = E ) {
2019-05-11 07:53:49 +08:00
next_packet_peer = 0 ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
}
// Signal newly connected peers
2021-07-16 11:45:57 +08:00
for ( int & E : add ) {
2019-05-11 07:53:49 +08:00
// Already connected to server: simply notify new peer.
// NOTE: Mesh is always connected.
2020-05-14 22:41:43 +08:00
if ( connection_status = = CONNECTION_CONNECTED ) {
2021-07-16 11:45:57 +08:00
emit_signal ( SNAME ( " peer_connected " ) , E ) ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
// Server emulation mode suppresses peer_conencted until server connects.
2021-07-16 11:45:57 +08:00
if ( server_compat & & E = = TARGET_PEER_SERVER ) {
2019-05-11 07:53:49 +08:00
// Server connected.
connection_status = CONNECTION_CONNECTED ;
2021-07-18 05:22:52 +08:00
emit_signal ( SNAME ( " peer_connected " ) , TARGET_PEER_SERVER ) ;
emit_signal ( SNAME ( " connection_succeeded " ) ) ;
2019-05-11 07:53:49 +08:00
// Notify of all previously connected peers
2020-03-17 14:33:00 +08:00
for ( Map < int , Ref < ConnectedPeer > > : : Element * F = peer_map . front ( ) ; F ; F = F - > next ( ) ) {
2020-05-14 22:41:43 +08:00
if ( F - > key ( ) ! = 1 & & F - > get ( ) - > connected ) {
2021-07-18 05:22:52 +08:00
emit_signal ( SNAME ( " peer_connected " ) , F - > key ( ) ) ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
}
break ; // Because we already notified of all newly added peers.
}
}
// Fetch next packet
2020-05-14 22:41:43 +08:00
if ( next_packet_peer = = 0 ) {
2019-05-11 07:53:49 +08:00
_find_next_peer ( ) ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : _find_next_peer ( ) {
2020-03-17 14:33:00 +08:00
Map < int , Ref < ConnectedPeer > > : : Element * E = peer_map . find ( next_packet_peer ) ;
2020-05-14 22:41:43 +08:00
if ( E ) {
2020-05-10 18:56:01 +08:00
E = E - > next ( ) ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
// After last.
while ( E ) {
2021-07-26 23:50:35 +08:00
for ( const Ref < WebRTCDataChannel > & F : E - > get ( ) - > channels ) {
2021-07-16 11:45:57 +08:00
if ( F - > get_available_packet_count ( ) ) {
2019-05-11 07:53:49 +08:00
next_packet_peer = E - > key ( ) ;
return ;
}
}
E = E - > next ( ) ;
}
E = peer_map . front ( ) ;
// Before last
while ( E ) {
2021-07-26 23:50:35 +08:00
for ( const Ref < WebRTCDataChannel > & F : E - > get ( ) - > channels ) {
2021-07-16 11:45:57 +08:00
if ( F - > get_available_packet_count ( ) ) {
2019-05-11 07:53:49 +08:00
next_packet_peer = E - > key ( ) ;
return ;
}
}
2020-05-14 22:41:43 +08:00
if ( E - > key ( ) = = ( int ) next_packet_peer ) {
2019-05-11 07:53:49 +08:00
break ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
E = E - > next ( ) ;
}
// No packet found
next_packet_peer = 0 ;
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : set_refuse_new_connections ( bool p_enable ) {
2019-05-11 07:53:49 +08:00
refuse_connections = p_enable ;
}
2021-07-12 22:26:37 +08:00
bool WebRTCMultiplayerPeer : : is_refusing_new_connections ( ) const {
2019-05-11 07:53:49 +08:00
return refuse_connections ;
}
2021-07-12 22:26:37 +08:00
MultiplayerPeer : : ConnectionStatus WebRTCMultiplayerPeer : : get_connection_status ( ) const {
2019-05-11 07:53:49 +08:00
return connection_status ;
}
2021-07-27 18:06:48 +08:00
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 + + ) {
2021-09-04 01:40:47 +08:00
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.Multiplayer::TransferMode' " ) ;
2021-07-27 18:06:48 +08:00
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 ) {
2021-09-04 01:40:47 +08:00
case Multiplayer : : TRANSFER_MODE_ORDERED :
2021-07-27 18:06:48 +08:00
cfg [ " maxPacketLifetime " ] = 1 ;
break ;
2021-09-04 01:40:47 +08:00
case Multiplayer : : TRANSFER_MODE_UNRELIABLE :
2021-07-27 18:06:48 +08:00
cfg [ " maxPacketLifetime " ] = 1 ;
cfg [ " ordered " ] = false ;
break ;
2021-09-04 01:40:47 +08:00
case Multiplayer : : TRANSFER_MODE_RELIABLE :
2021-07-27 18:06:48 +08:00
break ;
default :
2021-09-04 01:40:47 +08:00
ERR_FAIL_V_MSG ( ERR_INVALID_PARAMETER , vformat ( " The 'channels_config' array must contain only enum values from 'MultiplayerPeer.Multiplayer::TransferMode'. Got: %d " , mode ) ) ;
2021-07-27 18:06:48 +08:00
}
channels_config . push_back ( cfg ) ;
}
2019-05-11 07:53:49 +08:00
unique_id = p_self_id ;
server_compat = p_server_compat ;
// Mesh and server are always connected
2020-05-14 22:41:43 +08:00
if ( ! server_compat | | p_self_id = = 1 ) {
2019-05-11 07:53:49 +08:00
connection_status = CONNECTION_CONNECTED ;
2020-05-14 22:41:43 +08:00
} else {
2019-05-11 07:53:49 +08:00
connection_status = CONNECTION_CONNECTING ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
return OK ;
}
2021-07-12 22:26:37 +08:00
int WebRTCMultiplayerPeer : : get_unique_id ( ) const {
2019-05-11 07:53:49 +08:00
ERR_FAIL_COND_V ( connection_status = = CONNECTION_DISCONNECTED , 1 ) ;
return unique_id ;
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : _peer_to_dict ( Ref < ConnectedPeer > p_connected_peer , Dictionary & r_dict ) {
2019-05-11 07:53:49 +08:00
Array channels ;
2021-07-26 23:50:35 +08:00
for ( Ref < WebRTCDataChannel > & F : p_connected_peer - > channels ) {
2021-07-16 11:45:57 +08:00
channels . push_back ( F ) ;
2019-05-11 07:53:49 +08:00
}
r_dict [ " connection " ] = p_connected_peer - > connection ;
r_dict [ " connected " ] = p_connected_peer - > connected ;
r_dict [ " channels " ] = channels ;
}
2021-07-12 22:26:37 +08:00
bool WebRTCMultiplayerPeer : : has_peer ( int p_peer_id ) {
2019-05-11 07:53:49 +08:00
return peer_map . has ( p_peer_id ) ;
}
2021-07-12 22:26:37 +08:00
Dictionary WebRTCMultiplayerPeer : : get_peer ( int p_peer_id ) {
2019-05-11 07:53:49 +08:00
ERR_FAIL_COND_V ( ! peer_map . has ( p_peer_id ) , Dictionary ( ) ) ;
Dictionary out ;
_peer_to_dict ( peer_map [ p_peer_id ] , out ) ;
return out ;
}
2021-07-12 22:26:37 +08:00
Dictionary WebRTCMultiplayerPeer : : get_peers ( ) {
2019-05-11 07:53:49 +08:00
Dictionary out ;
2020-03-17 14:33:00 +08:00
for ( Map < int , Ref < ConnectedPeer > > : : Element * E = peer_map . front ( ) ; E ; E = E - > next ( ) ) {
2019-05-11 07:53:49 +08:00
Dictionary d ;
_peer_to_dict ( E - > get ( ) , d ) ;
out [ E - > key ( ) ] = d ;
}
return out ;
}
2021-07-12 22:26:37 +08:00
Error WebRTCMultiplayerPeer : : add_peer ( Ref < WebRTCPeerConnection > p_peer , int p_peer_id , int p_unreliable_lifetime ) {
2019-05-11 07:53:49 +08:00
ERR_FAIL_COND_V ( p_peer_id < 0 | | p_peer_id > ~ ( 1 < < 31 ) , ERR_INVALID_PARAMETER ) ;
ERR_FAIL_COND_V ( p_unreliable_lifetime < 0 , ERR_INVALID_PARAMETER ) ;
ERR_FAIL_COND_V ( refuse_connections , ERR_UNAUTHORIZED ) ;
// Peer must be valid, and in new state (to create data channels)
ERR_FAIL_COND_V ( ! p_peer . is_valid ( ) , ERR_INVALID_PARAMETER ) ;
ERR_FAIL_COND_V ( p_peer - > get_connection_state ( ) ! = WebRTCPeerConnection : : STATE_NEW , ERR_INVALID_PARAMETER ) ;
Ref < ConnectedPeer > peer = memnew ( ConnectedPeer ) ;
peer - > connection = p_peer ;
// Initialize data channels
Dictionary cfg ;
cfg [ " negotiated " ] = true ;
cfg [ " ordered " ] = true ;
cfg [ " id " ] = 1 ;
peer - > channels [ CH_RELIABLE ] = p_peer - > create_data_channel ( " reliable " , cfg ) ;
2021-07-27 18:06:48 +08:00
ERR_FAIL_COND_V ( peer - > channels [ CH_RELIABLE ] . is_null ( ) , FAILED ) ;
2019-05-11 07:53:49 +08:00
cfg [ " id " ] = 2 ;
cfg [ " maxPacketLifetime " ] = p_unreliable_lifetime ;
peer - > channels [ CH_ORDERED ] = p_peer - > create_data_channel ( " ordered " , cfg ) ;
2021-07-27 18:06:48 +08:00
ERR_FAIL_COND_V ( peer - > channels [ CH_ORDERED ] . is_null ( ) , FAILED ) ;
2019-05-11 07:53:49 +08:00
cfg [ " id " ] = 3 ;
cfg [ " ordered " ] = false ;
peer - > channels [ CH_UNRELIABLE ] = p_peer - > create_data_channel ( " unreliable " , cfg ) ;
2021-07-27 18:06:48 +08:00
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 ) ;
}
2019-05-11 07:53:49 +08:00
peer_map [ p_peer_id ] = peer ; // add the new peer connection to the peer_map
return OK ;
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : remove_peer ( int p_peer_id ) {
2019-05-11 07:53:49 +08:00
ERR_FAIL_COND ( ! peer_map . has ( p_peer_id ) ) ;
Ref < ConnectedPeer > peer = peer_map [ p_peer_id ] ;
peer_map . erase ( p_peer_id ) ;
if ( peer - > connected ) {
peer - > connected = false ;
2021-07-18 05:22:52 +08:00
emit_signal ( SNAME ( " peer_disconnected " ) , p_peer_id ) ;
2019-05-11 07:53:49 +08:00
if ( server_compat & & p_peer_id = = TARGET_PEER_SERVER ) {
2021-07-18 05:22:52 +08:00
emit_signal ( SNAME ( " server_disconnected " ) ) ;
2019-05-11 07:53:49 +08:00
connection_status = CONNECTION_DISCONNECTED ;
}
}
}
2021-07-12 22:26:37 +08:00
Error WebRTCMultiplayerPeer : : get_packet ( const uint8_t * * r_buffer , int & r_buffer_size ) {
2019-05-11 07:53:49 +08:00
// Peer not available
if ( next_packet_peer = = 0 | | ! peer_map . has ( next_packet_peer ) ) {
_find_next_peer ( ) ;
ERR_FAIL_V ( ERR_UNAVAILABLE ) ;
}
2021-07-26 23:50:35 +08:00
for ( Ref < WebRTCDataChannel > & E : peer_map [ next_packet_peer ] - > channels ) {
2021-07-16 11:45:57 +08:00
if ( E - > get_available_packet_count ( ) ) {
Error err = E - > get_packet ( r_buffer , r_buffer_size ) ;
2019-05-11 07:53:49 +08:00
_find_next_peer ( ) ;
return err ;
}
}
// Channels for that peer were empty. Bug?
_find_next_peer ( ) ;
ERR_FAIL_V ( ERR_BUG ) ;
}
2021-07-12 22:26:37 +08:00
Error WebRTCMultiplayerPeer : : put_packet ( const uint8_t * p_buffer , int p_buffer_size ) {
2019-05-11 07:53:49 +08:00
ERR_FAIL_COND_V ( connection_status = = CONNECTION_DISCONNECTED , ERR_UNCONFIGURED ) ;
2021-07-27 18:06:48 +08:00
int ch = transfer_channel ;
if ( ch = = 0 ) {
switch ( transfer_mode ) {
2021-09-04 01:40:47 +08:00
case Multiplayer : : TRANSFER_MODE_RELIABLE :
2021-07-27 18:06:48 +08:00
ch = CH_RELIABLE ;
break ;
2021-09-04 01:40:47 +08:00
case Multiplayer : : TRANSFER_MODE_ORDERED :
2021-07-27 18:06:48 +08:00
ch = CH_ORDERED ;
break ;
2021-09-04 01:40:47 +08:00
case Multiplayer : : TRANSFER_MODE_UNRELIABLE :
2021-07-27 18:06:48 +08:00
ch = CH_UNRELIABLE ;
break ;
}
} else {
ch + = CH_RESERVED_MAX - 1 ;
2019-05-11 07:53:49 +08:00
}
2020-04-02 07:20:12 +08:00
Map < int , Ref < ConnectedPeer > > : : Element * E = nullptr ;
2019-05-11 07:53:49 +08:00
if ( target_peer > 0 ) {
E = peer_map . find ( target_peer ) ;
2019-08-11 16:49:53 +08:00
ERR_FAIL_COND_V_MSG ( ! E , ERR_INVALID_PARAMETER , " Invalid target peer: " + itos ( target_peer ) + " . " ) ;
2021-07-27 18:06:48 +08:00
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 ) ;
2019-05-11 07:53:49 +08:00
return E - > value ( ) - > channels [ ch ] - > put_packet ( p_buffer , p_buffer_size ) ;
} else {
int exclude = - target_peer ;
2020-03-17 14:33:00 +08:00
for ( Map < int , Ref < ConnectedPeer > > : : Element * F = peer_map . front ( ) ; F ; F = F - > next ( ) ) {
2019-05-11 07:53:49 +08:00
// Exclude packet. If target_peer == 0 then don't exclude any packets
2020-05-14 22:41:43 +08:00
if ( target_peer ! = 0 & & F - > key ( ) = = exclude ) {
2019-05-11 07:53:49 +08:00
continue ;
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
2021-07-27 18:06:48 +08:00
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 ( ) ) ;
2019-05-11 07:53:49 +08:00
F - > value ( ) - > channels [ ch ] - > put_packet ( p_buffer , p_buffer_size ) ;
}
}
return OK ;
}
2021-07-12 22:26:37 +08:00
int WebRTCMultiplayerPeer : : get_available_packet_count ( ) const {
2020-05-14 22:41:43 +08:00
if ( next_packet_peer = = 0 ) {
2019-05-11 07:53:49 +08:00
return 0 ; // To be sure next call to get_packet works if size > 0 .
2020-05-14 22:41:43 +08:00
}
2019-05-11 07:53:49 +08:00
int size = 0 ;
2020-03-17 14:33:00 +08:00
for ( Map < int , Ref < ConnectedPeer > > : : Element * E = peer_map . front ( ) ; E ; E = E - > next ( ) ) {
2021-07-26 23:50:35 +08:00
for ( const Ref < WebRTCDataChannel > & F : E - > get ( ) - > channels ) {
2021-07-16 11:45:57 +08:00
size + = F - > get_available_packet_count ( ) ;
2019-05-11 07:53:49 +08:00
}
}
return size ;
}
2021-07-12 22:26:37 +08:00
int WebRTCMultiplayerPeer : : get_max_packet_size ( ) const {
2019-05-11 07:53:49 +08:00
return 1200 ;
}
2021-07-12 22:26:37 +08:00
void WebRTCMultiplayerPeer : : close ( ) {
2019-05-11 07:53:49 +08:00
peer_map . clear ( ) ;
2021-07-27 18:06:48 +08:00
channels_config . clear ( ) ;
2019-05-11 07:53:49 +08:00
unique_id = 0 ;
next_packet_peer = 0 ;
target_peer = 0 ;
connection_status = CONNECTION_DISCONNECTED ;
}
2021-07-12 22:26:37 +08:00
WebRTCMultiplayerPeer : : ~ WebRTCMultiplayerPeer ( ) {
2019-05-11 07:53:49 +08:00
close ( ) ;
}