2016-10-10 17:50:51 +00:00
/*************************************************************************/
2021-07-12 14:18:43 +00:00
/* enet_multiplayer_peer.cpp */
2016-10-10 17:50:51 +00:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2016-10-10 17:50:51 +00:00
/*************************************************************************/
2021-01-01 19:13:46 +00:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2016-10-10 17:50:51 +00: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. */
/*************************************************************************/
2018-01-04 23:50:27 +00:00
2021-07-12 14:18:43 +00:00
# include "enet_multiplayer_peer.h"
2018-09-11 16:13:45 +00:00
# include "core/io/ip.h"
# include "core/io/marshalls.h"
# include "core/os/os.h"
2016-08-14 16:29:25 +00:00
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : set_transfer_mode ( TransferMode p_mode ) {
2017-03-05 15:44:50 +00:00
transfer_mode = p_mode ;
2016-08-14 16:29:25 +00:00
}
2020-05-14 12:29:06 +00:00
2021-07-12 14:18:43 +00:00
MultiplayerPeer : : TransferMode ENetMultiplayerPeer : : get_transfer_mode ( ) const {
2018-01-11 22:35:12 +00:00
return transfer_mode ;
}
2016-08-14 16:29:25 +00:00
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : set_target_peer ( int p_peer ) {
2017-03-05 15:44:50 +00:00
target_peer = p_peer ;
2016-08-14 16:29:25 +00:00
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_packet_peer ( ) const {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , 1 , " The multiplayer instance isn't currently active. " ) ;
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND_V ( incoming_packets . size ( ) = = 0 , 1 ) ;
2016-08-14 16:29:25 +00:00
return incoming_packets . front ( ) - > get ( ) . from ;
}
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : create_server ( int p_port , int p_max_clients , int p_max_channels , int p_in_bandwidth , int p_out_bandwidth ) {
ERR_FAIL_COND_V_MSG ( _is_active ( ) , ERR_ALREADY_IN_USE , " The multiplayer instance is already active. " ) ;
Ref < ENetConnection > host ;
host . instantiate ( ) ;
Error err = host - > create_host_bound ( bind_ip , p_port , p_max_clients , 0 , p_max_channels > 0 ? p_max_channels + SYSCH_MAX : 0 , p_out_bandwidth ) ;
if ( err ! = OK ) {
return err ;
2020-01-13 15:51:17 +00:00
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
active_mode = MODE_SERVER ;
2017-03-05 15:44:50 +00:00
refuse_connections = false ;
unique_id = 1 ;
connection_status = CONNECTION_CONNECTED ;
2021-07-15 23:48:44 +00:00
hosts [ 0 ] = host ;
2016-08-14 16:29:25 +00:00
return OK ;
}
2018-05-06 22:28:59 +00:00
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : create_client ( const String & p_address , int p_port , int p_channel_count , int p_in_bandwidth , int p_out_bandwidth , int p_local_port ) {
ERR_FAIL_COND_V_MSG ( _is_active ( ) , ERR_ALREADY_IN_USE , " The multiplayer instance is already active. " ) ;
Ref < ENetConnection > host ;
host . instantiate ( ) ;
Error err ;
if ( p_local_port ) {
err = host - > create_host_bound ( bind_ip , p_local_port , 1 , 0 , p_in_bandwidth , p_out_bandwidth ) ;
2021-03-29 16:14:50 +00:00
} else {
2021-07-15 23:48:44 +00:00
err = host - > create_host ( 1 , 0 , p_in_bandwidth , p_out_bandwidth ) ;
2021-03-29 16:14:50 +00:00
}
2021-07-15 23:48:44 +00:00
if ( err ! = OK ) {
return err ;
2021-03-29 16:14:50 +00:00
}
2016-08-14 17:06:51 +00:00
2021-07-15 22:43:49 +00:00
unique_id = generate_unique_id ( ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
Ref < ENetPacketPeer > peer = host - > connect_to_host ( p_address , p_port , p_channel_count > 0 ? p_channel_count + SYSCH_MAX : 0 , unique_id ) ;
if ( peer . is_null ( ) ) {
host - > destroy ( ) ;
ERR_FAIL_V_MSG ( ERR_CANT_CREATE , " Couldn't connect to the ENet multiplayer server. " ) ;
2016-08-14 17:06:51 +00:00
}
2021-07-15 23:48:44 +00:00
// Need to wait for CONNECT event.
2017-03-05 15:44:50 +00:00
connection_status = CONNECTION_CONNECTING ;
2021-07-15 23:48:44 +00:00
active_mode = MODE_CLIENT ;
2017-03-05 15:44:50 +00:00
refuse_connections = false ;
2021-07-15 23:48:44 +00:00
peers [ 1 ] = peer ;
hosts [ 0 ] = host ;
2016-08-14 16:29:25 +00:00
return OK ;
}
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : create_mesh ( int p_id ) {
ERR_FAIL_COND_V_MSG ( p_id < = 0 , ERR_INVALID_PARAMETER , " The unique ID must be greater then 0 " ) ;
ERR_FAIL_COND_V_MSG ( _is_active ( ) , ERR_ALREADY_IN_USE , " The multiplayer instance is already active. " ) ;
active_mode = MODE_MESH ;
refuse_connections = false ;
unique_id = p_id ;
connection_status = CONNECTION_CONNECTED ;
return OK ;
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : add_mesh_peer ( int p_id , Ref < ENetConnection > p_host ) {
ERR_FAIL_COND_V ( p_host . is_null ( ) , ERR_INVALID_PARAMETER ) ;
ERR_FAIL_COND_V_MSG ( active_mode ! = MODE_MESH , ERR_UNCONFIGURED , " The multiplayer instance is not configured as a mesh. Call 'create_mesh' first. " ) ;
List < Ref < ENetPacketPeer > > host_peers ;
p_host - > get_peers ( host_peers ) ;
ERR_FAIL_COND_V_MSG ( host_peers . size ( ) ! = 1 | | host_peers [ 0 ] - > get_state ( ) ! = ENetPacketPeer : : STATE_CONNECTED , ERR_INVALID_PARAMETER , " The provided host must have excatly one peer in the connected state. " ) ;
hosts [ p_id ] = p_host ;
peers [ p_id ] = host_peers [ 0 ] ;
emit_signal ( SNAME ( " peer_connected " ) , p_id ) ;
return OK ;
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
bool ENetMultiplayerPeer : : _poll_server ( ) {
for ( const KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( ! ( E . value - > is_active ( ) ) ) {
emit_signal ( SNAME ( " peer_disconnected " ) , E . value - > get_meta ( SNAME ( " _net_id " ) ) ) ;
peers . erase ( E . key ) ;
2020-05-14 14:41:43 +00:00
}
2021-07-15 23:48:44 +00:00
}
ENetConnection : : Event event ;
ENetConnection : : EventType ret = hosts [ 0 ] - > service ( 0 , event ) ;
if ( ret = = ENetConnection : : EVENT_ERROR ) {
return true ;
}
switch ( ret ) {
case ENetConnection : : EVENT_CONNECT : {
if ( refuse_connections ) {
event . peer - > reset ( ) ;
return false ;
}
// Client joined with invalid ID, probably trying to exploit us.
if ( event . data < 2 | | peers . has ( ( int ) event . data ) ) {
event . peer - > reset ( ) ;
return false ;
}
int id = event . data ;
event . peer - > set_meta ( SNAME ( " _net_id " ) , id ) ;
peers [ id ] = event . peer ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
emit_signal ( SNAME ( " peer_connected " ) , id ) ;
if ( server_relay ) {
_notify_peers ( id , true ) ;
}
return false ;
}
case ENetConnection : : EVENT_DISCONNECT : {
int id = event . peer - > get_meta ( SNAME ( " _net_id " ) ) ;
if ( ! peers . has ( id ) ) {
// Never fully connected.
return false ;
}
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
emit_signal ( SNAME ( " peer_disconnected " ) , id ) ;
peers . erase ( id ) ;
if ( ! server_relay ) {
_notify_peers ( id , false ) ;
}
return false ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
case ENetConnection : : EVENT_RECEIVE : {
if ( event . channel_id = = SYSCH_CONFIG ) {
_destroy_unused ( event . packet ) ;
ERR_FAIL_V_MSG ( false , " Only server can send config messages " ) ;
} else {
if ( event . packet - > dataLength < 8 ) {
_destroy_unused ( event . packet ) ;
ERR_FAIL_V_MSG ( false , " Invalid packet size " ) ;
}
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
uint32_t source = decode_uint32 ( & event . packet - > data [ 0 ] ) ;
int target = decode_uint32 ( & event . packet - > data [ 4 ] ) ;
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
uint32_t id = event . peer - > get_meta ( SNAME ( " _net_id " ) ) ;
// Someone is cheating and trying to fake the source!
if ( source ! = id ) {
_destroy_unused ( event . packet ) ;
ERR_FAIL_V_MSG ( false , " Someone is cheating and trying to fake the source! " ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
Packet packet ;
packet . packet = event . packet ;
packet . channel = event . channel_id ;
packet . from = id ;
2019-02-20 15:28:53 +00:00
2021-07-15 23:48:44 +00:00
// Even if relaying is disabled, these targets are valid as incoming packets.
if ( target = = 1 | | target = = 0 | | target < - 1 ) {
packet . packet - > referenceCount + + ;
incoming_packets . push_back ( packet ) ;
}
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
if ( server_relay & & target ! = 1 ) {
packet . packet - > referenceCount + + ;
_relay ( source , target , event . channel_id , event . packet ) ;
packet . packet - > referenceCount - - ;
_destroy_unused ( event . packet ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
// Destroy packet later
}
return false ;
}
default :
return true ;
}
}
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
bool ENetMultiplayerPeer : : _poll_client ( ) {
if ( peers . has ( 1 ) & & ! peers [ 1 ] - > is_active ( ) ) {
if ( connection_status = = CONNECTION_CONNECTED ) {
// Client just disconnected from server.
emit_signal ( SNAME ( " server_disconnected " ) ) ;
} else {
emit_signal ( SNAME ( " connection_failed " ) ) ;
}
close_connection ( ) ;
return true ;
}
ENetConnection : : Event event ;
ENetConnection : : EventType ret = hosts [ 0 ] - > service ( 0 , event ) ;
if ( ret = = ENetConnection : : EVENT_ERROR ) {
return true ;
}
switch ( ret ) {
case ENetConnection : : EVENT_CONNECT : {
emit_signal ( SNAME ( " peer_connected " ) , 1 ) ;
connection_status = CONNECTION_CONNECTED ;
emit_signal ( SNAME ( " connection_succeeded " ) ) ;
return false ;
}
case ENetConnection : : EVENT_DISCONNECT : {
if ( connection_status = = CONNECTION_CONNECTED ) {
// Client just disconnected from server.
emit_signal ( SNAME ( " server_disconnected " ) ) ;
} else {
emit_signal ( SNAME ( " connection_failed " ) ) ;
}
close_connection ( ) ;
return true ;
}
case ENetConnection : : EVENT_RECEIVE : {
if ( event . channel_id = = SYSCH_CONFIG ) {
// Config message
if ( event . packet - > dataLength ! = 8 ) {
_destroy_unused ( event . packet ) ;
ERR_FAIL_V ( false ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
int msg = decode_uint32 ( & event . packet - > data [ 0 ] ) ;
int id = decode_uint32 ( & event . packet - > data [ 4 ] ) ;
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
switch ( msg ) {
case SYSMSG_ADD_PEER : {
peers [ id ] = Ref < ENetPacketPeer > ( ) ;
emit_signal ( SNAME ( " peer_connected " ) , id ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
} break ;
case SYSMSG_REMOVE_PEER : {
peers . erase ( id ) ;
emit_signal ( SNAME ( " peer_disconnected " ) , id ) ;
} break ;
2019-11-26 16:21:19 +00:00
}
2021-07-15 23:48:44 +00:00
_destroy_unused ( event . packet ) ;
} else {
if ( event . packet - > dataLength < 8 ) {
_destroy_unused ( event . packet ) ;
ERR_FAIL_V_MSG ( false , " Invalid packet size " ) ;
2016-08-19 19:48:08 +00:00
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
uint32_t source = decode_uint32 ( & event . packet - > data [ 0 ] ) ;
Packet packet ;
packet . packet = event . packet ;
packet . from = source ;
packet . channel = event . channel_id ;
packet . packet - > referenceCount + + ;
incoming_packets . push_back ( packet ) ;
// Destroy packet later
}
return false ;
}
default :
return true ;
}
}
bool ENetMultiplayerPeer : : _poll_mesh ( ) {
for ( const KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( ! ( E . value - > is_active ( ) ) ) {
emit_signal ( SNAME ( " peer_disconnected " ) , E . key ) ;
peers . erase ( E . key ) ;
if ( hosts . has ( E . key ) ) {
hosts . erase ( E . key ) ;
}
}
}
bool should_stop = true ;
for ( KeyValue < int , Ref < ENetConnection > > & E : hosts ) {
ENetConnection : : Event event ;
ENetConnection : : EventType ret = E . value - > service ( 0 , event ) ;
if ( ret = = ENetConnection : : EVENT_ERROR ) {
if ( peers . has ( E . key ) ) {
emit_signal ( SNAME ( " peer_disconnected " ) , E . key ) ;
peers . erase ( E . key ) ;
}
hosts . erase ( E . key ) ;
continue ;
}
switch ( ret ) {
case ENetConnection : : EVENT_CONNECT :
should_stop = false ;
event . peer - > reset ( ) ;
break ;
case ENetConnection : : EVENT_DISCONNECT :
should_stop = false ;
if ( peers . has ( E . key ) ) {
emit_signal ( SNAME ( " peer_disconnected " ) , E . key ) ;
peers . erase ( E . key ) ;
}
hosts . erase ( E . key ) ;
break ;
case ENetConnection : : EVENT_RECEIVE : {
should_stop = false ;
if ( event . packet - > dataLength < 8 ) {
_destroy_unused ( event . packet ) ;
ERR_CONTINUE_MSG ( true , " Invalid packet size " ) ;
2016-08-19 19:48:08 +00:00
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
Packet packet ;
packet . packet = event . packet ;
packet . from = E . key ;
packet . channel = event . channel_id ;
packet . packet - > referenceCount + + ;
incoming_packets . push_back ( packet ) ;
2017-03-05 15:44:50 +00:00
} break ;
2021-07-15 23:48:44 +00:00
default :
break ; // Nothing to do
2016-08-14 16:29:25 +00:00
}
}
2021-07-15 23:48:44 +00:00
return should_stop ;
2016-08-14 16:29:25 +00:00
}
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : poll ( ) {
ERR_FAIL_COND_MSG ( ! _is_active ( ) , " The multiplayer instance isn't currently active. " ) ;
2016-08-14 21:49:50 +00:00
2021-07-15 23:48:44 +00:00
_pop_current_packet ( ) ;
while ( true ) {
switch ( active_mode ) {
case MODE_CLIENT :
if ( _poll_client ( ) ) {
return ;
}
break ;
case MODE_SERVER :
if ( _poll_server ( ) ) {
return ;
}
break ;
case MODE_MESH :
if ( _poll_mesh ( ) ) {
return ;
}
break ;
default :
return ;
}
}
}
bool ENetMultiplayerPeer : : is_server ( ) const {
return active_mode = = MODE_SERVER ;
2016-08-14 21:49:50 +00:00
}
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : close_connection ( uint32_t wait_usec ) {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_MSG ( ! _is_active ( ) , " The multiplayer instance isn't currently active. " ) ;
2016-08-14 16:29:25 +00:00
_pop_current_packet ( ) ;
2017-03-05 15:44:50 +00:00
bool peers_disconnected = false ;
2021-07-15 23:48:44 +00:00
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . value . is_valid ( ) & & E . value - > get_state ( ) = = ENetPacketPeer : : STATE_CONNECTED ) {
E . value - > peer_disconnect_now ( unique_id ) ;
2017-03-05 15:44:50 +00:00
peers_disconnected = true ;
2016-08-19 19:48:08 +00:00
}
}
if ( peers_disconnected ) {
2021-07-15 23:48:44 +00:00
for ( KeyValue < int , Ref < ENetConnection > > & E : hosts ) {
E . value - > flush ( ) ;
}
2018-05-06 22:28:59 +00:00
if ( wait_usec > 0 ) {
OS : : get_singleton ( ) - > delay_usec ( wait_usec ) ; // Wait for disconnection packets to send
}
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
active_mode = MODE_NONE ;
2016-08-14 16:29:25 +00:00
incoming_packets . clear ( ) ;
2021-07-15 23:48:44 +00:00
peers . clear ( ) ;
hosts . clear ( ) ;
unique_id = 0 ;
2017-03-05 15:44:50 +00:00
connection_status = CONNECTION_DISCONNECTED ;
2016-08-14 16:29:25 +00:00
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_available_packet_count ( ) const {
2016-08-14 16:29:25 +00:00
return incoming_packets . size ( ) ;
}
2018-05-06 22:28:59 +00:00
2021-07-12 14:18:43 +00:00
Error ENetMultiplayerPeer : : get_packet ( const uint8_t * * r_buffer , int & r_buffer_size ) {
2020-02-02 22:34:47 +00:00
ERR_FAIL_COND_V_MSG ( incoming_packets . size ( ) = = 0 , ERR_UNAVAILABLE , " No incoming packets available. " ) ;
2016-08-14 16:29:25 +00:00
_pop_current_packet ( ) ;
current_packet = incoming_packets . front ( ) - > get ( ) ;
incoming_packets . pop_front ( ) ;
2019-01-15 07:32:17 +00:00
* r_buffer = ( const uint8_t * ) ( & current_packet . packet - > data [ 8 ] ) ;
r_buffer_size = current_packet . packet - > dataLength - 8 ;
2016-08-14 16:29:25 +00:00
return OK ;
}
2018-05-06 22:28:59 +00:00
2021-07-12 14:18:43 +00:00
Error ENetMultiplayerPeer : : put_packet ( const uint8_t * p_buffer , int p_buffer_size ) {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , ERR_UNCONFIGURED , " The multiplayer instance isn't currently active. " ) ;
2020-02-02 22:34:47 +00:00
ERR_FAIL_COND_V_MSG ( connection_status ! = CONNECTION_CONNECTED , ERR_UNCONFIGURED , " The multiplayer instance isn't currently connected to any server or client. " ) ;
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( target_peer ! = 0 & & ! peers . has ( ABS ( target_peer ) ) , ERR_INVALID_PARAMETER , vformat ( " Invalid target peer: %d " , target_peer ) ) ;
ERR_FAIL_COND_V ( active_mode = = MODE_CLIENT & & ! peers . has ( 1 ) , ERR_BUG ) ;
2016-08-14 16:29:25 +00:00
2017-03-05 15:44:50 +00:00
int packet_flags = 0 ;
int channel = SYSCH_RELIABLE ;
2016-08-19 19:48:08 +00:00
2017-03-05 15:44:50 +00:00
switch ( transfer_mode ) {
2016-08-14 16:29:25 +00:00
case TRANSFER_MODE_UNRELIABLE : {
2021-07-15 23:48:44 +00:00
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED ;
2017-03-05 15:44:50 +00:00
channel = SYSCH_UNRELIABLE ;
2016-08-14 16:29:25 +00:00
} break ;
2016-08-20 01:54:02 +00:00
case TRANSFER_MODE_UNRELIABLE_ORDERED : {
2017-03-05 15:44:50 +00:00
packet_flags = 0 ;
channel = SYSCH_UNRELIABLE ;
2016-08-14 16:29:25 +00:00
} break ;
2016-08-20 01:54:02 +00:00
case TRANSFER_MODE_RELIABLE : {
2017-03-05 15:44:50 +00:00
packet_flags = ENET_PACKET_FLAG_RELIABLE ;
channel = SYSCH_RELIABLE ;
2016-08-14 16:29:25 +00:00
} break ;
}
2020-04-01 23:20:12 +00:00
ENetPacket * packet = enet_packet_create ( nullptr , p_buffer_size + 8 , packet_flags ) ;
2018-04-08 20:45:14 +00:00
encode_uint32 ( unique_id , & packet - > data [ 0 ] ) ; // Source ID
encode_uint32 ( target_peer , & packet - > data [ 4 ] ) ; // Dest ID
2021-04-27 14:19:21 +00:00
memcpy ( & packet - > data [ 8 ] , p_buffer , p_buffer_size ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
if ( is_server ( ) ) {
2017-03-05 15:44:50 +00:00
if ( target_peer = = 0 ) {
2021-07-15 23:48:44 +00:00
hosts [ 0 ] - > broadcast ( channel , packet ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
} else if ( target_peer < 0 ) {
// Send to all but one and make copies for sending.
2017-03-05 15:44:50 +00:00
int exclude = - target_peer ;
2021-07-15 23:48:44 +00:00
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = exclude ) {
2016-08-19 19:48:08 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2021-07-15 23:48:44 +00:00
E . value - > send ( channel , packet ) ;
}
_destroy_unused ( packet ) ;
} else {
peers [ target_peer ] - > send ( channel , packet ) ;
}
ERR_FAIL_COND_V ( ! hosts . has ( 0 ) , ERR_BUG ) ;
hosts [ 0 ] - > flush ( ) ;
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
} else if ( active_mode = = MODE_CLIENT ) {
peers [ 1 ] - > send ( channel , packet ) ; // Send to server for broadcast.
ERR_FAIL_COND_V ( ! hosts . has ( 0 ) , ERR_BUG ) ;
hosts [ 0 ] - > flush ( ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
} else {
if ( target_peer < = 0 ) {
int exclude = ABS ( target_peer ) ;
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = exclude ) {
continue ;
}
E . value - > send ( channel , packet ) ;
ERR_CONTINUE ( ! hosts . has ( E . key ) ) ;
hosts [ E . key ] - > flush ( ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
_destroy_unused ( packet ) ;
2016-08-19 19:48:08 +00:00
} else {
2021-07-15 23:48:44 +00:00
peers [ target_peer ] - > send ( channel , packet ) ;
ERR_FAIL_COND_V ( ! hosts . has ( target_peer ) , ERR_BUG ) ;
hosts [ target_peer ] - > flush ( ) ;
2016-08-19 19:48:08 +00:00
}
2016-08-14 16:29:25 +00:00
}
return OK ;
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_max_packet_size ( ) const {
2018-04-08 20:45:14 +00:00
return 1 < < 24 ; // Anything is good
2016-08-14 16:29:25 +00:00
}
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : _pop_current_packet ( ) {
2016-08-14 16:29:25 +00:00
if ( current_packet . packet ) {
2021-07-15 23:48:44 +00:00
current_packet . packet - > referenceCount - - ;
_destroy_unused ( current_packet . packet ) ;
2020-04-01 23:20:12 +00:00
current_packet . packet = nullptr ;
2017-03-05 15:44:50 +00:00
current_packet . from = 0 ;
2018-05-12 17:42:00 +00:00
current_packet . channel = - 1 ;
2016-08-14 16:29:25 +00:00
}
}
2021-07-12 14:18:43 +00:00
MultiplayerPeer : : ConnectionStatus ENetMultiplayerPeer : : get_connection_status ( ) const {
2016-08-14 17:06:51 +00:00
return connection_status ;
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_unique_id ( ) const {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , 0 , " The multiplayer instance isn't currently active. " ) ;
2016-08-19 19:48:08 +00:00
return unique_id ;
}
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : set_refuse_new_connections ( bool p_enable ) {
2017-03-05 15:44:50 +00:00
refuse_connections = p_enable ;
2020-07-13 17:14:27 +00:00
# ifdef GODOT_ENET
2021-07-15 23:48:44 +00:00
if ( _is_active ( ) ) {
for ( KeyValue < int , Ref < ENetConnection > > & E : hosts ) {
E . value - > refuse_new_connections ( p_enable ) ;
}
2020-07-23 08:38:48 +00:00
}
2020-07-13 17:14:27 +00:00
# endif
2016-08-19 19:48:08 +00:00
}
2021-07-12 14:18:43 +00:00
bool ENetMultiplayerPeer : : is_refusing_new_connections ( ) const {
2016-08-19 19:48:08 +00:00
return refuse_connections ;
}
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : set_server_relay_enabled ( bool p_enabled ) {
ERR_FAIL_COND_MSG ( _is_active ( ) , " Server relaying can't be toggled while the multiplayer instance is active. " ) ;
server_relay = p_enabled ;
2016-08-22 04:14:08 +00:00
}
2021-07-15 23:48:44 +00:00
bool ENetMultiplayerPeer : : is_server_relay_enabled ( ) const {
return server_relay ;
2016-08-22 04:14:08 +00:00
}
2021-07-15 23:48:44 +00:00
Ref < ENetConnection > ENetMultiplayerPeer : : get_host ( ) const {
ERR_FAIL_COND_V ( ! _is_active ( ) , nullptr ) ;
ERR_FAIL_COND_V ( active_mode = = MODE_MESH , nullptr ) ;
return hosts [ 0 ] ;
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
Ref < ENetPacketPeer > ENetMultiplayerPeer : : get_peer ( int p_id ) const {
ERR_FAIL_COND_V ( ! _is_active ( ) , nullptr ) ;
ERR_FAIL_COND_V ( ! peers . has ( p_id ) , nullptr ) ;
ERR_FAIL_COND_V ( active_mode = = MODE_CLIENT & & p_id ! = 1 , nullptr ) ;
return peers [ p_id ] ;
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : _destroy_unused ( ENetPacket * p_packet ) {
if ( p_packet - > referenceCount = = 0 ) {
enet_packet_destroy ( p_packet ) ;
2016-08-22 04:14:08 +00:00
}
2021-07-15 23:48:44 +00:00
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : _relay ( int p_from , int p_to , enet_uint8 p_channel , ENetPacket * p_packet ) {
if ( p_to = = 0 ) {
// Re-send to everyone but sender :|
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = p_from ) {
continue ;
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
E . value - > send ( p_channel , p_packet ) ;
2019-04-09 15:08:36 +00:00
}
2021-07-15 23:48:44 +00:00
} else if ( p_to < 0 ) {
// Re-send to everyone but excluded and sender.
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = p_from | | E . key = = - p_to ) { // Do not resend to self, also do not send to excluded
continue ;
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
E . value - > send ( p_channel , p_packet ) ;
2019-04-09 15:08:36 +00:00
}
2016-08-22 04:14:08 +00:00
} else {
2021-07-15 23:48:44 +00:00
// To someone else, specifically
ERR_FAIL_COND ( ! peers . has ( p_to ) ) ;
ENetPacket * packet = enet_packet_create ( p_packet - > data , p_packet - > dataLength , p_packet - > flags ) ;
peers [ p_to ] - > send ( p_channel , packet ) ;
2016-08-22 04:14:08 +00:00
}
}
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : _notify_peers ( int p_id , bool p_connected ) {
if ( p_connected ) {
ERR_FAIL_COND ( ! peers . has ( p_id ) ) ;
// Someone connected, notify all the peers available.
Ref < ENetPacketPeer > peer = peers [ p_id ] ;
ENetPacket * packet = enet_packet_create ( nullptr , 8 , ENET_PACKET_FLAG_RELIABLE ) ;
encode_uint32 ( SYSMSG_ADD_PEER , & packet - > data [ 0 ] ) ;
encode_uint32 ( p_id , & packet - > data [ 4 ] ) ;
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = p_id ) {
continue ;
}
// Send new peer to existing peer.
E . value - > send ( SYSCH_CONFIG , packet ) ;
// Send existing peer to new peer.
// This packet will be automatically destroyed by ENet after send.
ENetPacket * packet2 = enet_packet_create ( nullptr , 8 , ENET_PACKET_FLAG_RELIABLE ) ;
encode_uint32 ( SYSMSG_ADD_PEER , & packet2 - > data [ 0 ] ) ;
encode_uint32 ( E . key , & packet2 - > data [ 4 ] ) ;
peer - > send ( SYSCH_CONFIG , packet2 ) ;
}
_destroy_unused ( packet ) ;
} else {
// Server just received a client disconnect and is in relay mode, notify everyone else.
ENetPacket * packet = enet_packet_create ( nullptr , 8 , ENET_PACKET_FLAG_RELIABLE ) ;
encode_uint32 ( SYSMSG_REMOVE_PEER , & packet - > data [ 0 ] ) ;
encode_uint32 ( p_id , & packet - > data [ 4 ] ) ;
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = p_id ) {
continue ;
}
E . value - > send ( SYSCH_CONFIG , packet ) ;
}
_destroy_unused ( packet ) ;
2016-08-22 04:14:08 +00:00
}
}
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : _bind_methods ( ) {
2021-07-15 23:48:44 +00:00
ClassDB : : bind_method ( D_METHOD ( " create_server " , " port " , " max_clients " , " max_channels " , " in_bandwidth " , " out_bandwidth " ) , & ENetMultiplayerPeer : : create_server , DEFVAL ( 32 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " create_client " , " address " , " port " , " channel_count " , " in_bandwidth " , " out_bandwidth " , " local_port " ) , & ENetMultiplayerPeer : : create_client , DEFVAL ( 0 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " create_mesh " , " unique_id " ) , & ENetMultiplayerPeer : : create_mesh ) ;
ClassDB : : bind_method ( D_METHOD ( " add_mesh_peer " , " peer_id " , " host " ) , & ENetMultiplayerPeer : : add_mesh_peer ) ;
2021-07-12 14:18:43 +00:00
ClassDB : : bind_method ( D_METHOD ( " close_connection " , " wait_usec " ) , & ENetMultiplayerPeer : : close_connection , DEFVAL ( 100 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " set_bind_ip " , " ip " ) , & ENetMultiplayerPeer : : set_bind_ip ) ;
2021-07-15 23:48:44 +00:00
2021-07-12 14:18:43 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_server_relay_enabled " , " enabled " ) , & ENetMultiplayerPeer : : set_server_relay_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_server_relay_enabled " ) , & ENetMultiplayerPeer : : is_server_relay_enabled ) ;
2021-07-15 23:48:44 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_host " ) , & ENetMultiplayerPeer : : get_host ) ;
ClassDB : : bind_method ( D_METHOD ( " get_peer " , " id " ) , & ENetMultiplayerPeer : : get_peer ) ;
2018-05-12 17:42:00 +00:00
2019-11-26 16:21:19 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " server_relay " ) , " set_server_relay_enabled " , " is_server_relay_enabled " ) ;
2021-07-15 23:48:44 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " host " , PROPERTY_HINT_RESOURCE_TYPE , " ENetConnection " , PROPERTY_USAGE_NONE ) , " " , " get_host " ) ;
2016-08-14 17:06:51 +00:00
}
2021-07-12 14:18:43 +00:00
ENetMultiplayerPeer : : ENetMultiplayerPeer ( ) {
2021-05-06 00:48:18 +00:00
bind_ip = IPAddress ( " * " ) ;
2016-08-14 16:29:25 +00:00
}
2016-08-14 17:06:51 +00:00
2021-07-12 14:18:43 +00:00
ENetMultiplayerPeer : : ~ ENetMultiplayerPeer ( ) {
2021-07-15 23:48:44 +00:00
if ( _is_active ( ) ) {
2019-06-01 13:42:22 +00:00
close_connection ( ) ;
}
2016-08-14 16:29:25 +00:00
}
2016-08-27 11:41:34 +00:00
2018-05-06 22:28:59 +00:00
// Sets IP for ENet to bind when using create_server or create_client
2016-08-27 11:41:34 +00:00
// if no IP is set, then ENet bind to ENET_HOST_ANY
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : set_bind_ip ( const IPAddress & p_ip ) {
2020-02-02 22:34:47 +00:00
ERR_FAIL_COND_MSG ( ! p_ip . is_valid ( ) & & ! p_ip . is_wildcard ( ) , vformat ( " Invalid bind IP address: %s " , String ( p_ip ) ) ) ;
2017-01-22 05:00:59 +00:00
bind_ip = p_ip ;
2016-08-27 11:41:34 +00:00
}