2017-12-21 03:13:23 +01:00
/*************************************************************************/
2019-02-12 22:28:47 +01:00
/* websocket_multiplayer_peer.cpp */
2017-12-21 03:13:23 +01:00
/*************************************************************************/
/* This file is part of: */
2017-12-21 03:47:16 +01:00
/* GODOT ENGINE */
/* https://godotengine.org */
2017-12-21 03:13:23 +01:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2017-12-21 03:13:23 +01: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. */
/*************************************************************************/
2019-01-01 12:46:36 +01:00
2019-02-12 22:28:47 +01:00
# include "websocket_multiplayer_peer.h"
2017-12-21 03:13:23 +01:00
# include "core/os/os.h"
WebSocketMultiplayerPeer : : WebSocketMultiplayerPeer ( ) {
}
WebSocketMultiplayerPeer : : ~ WebSocketMultiplayerPeer ( ) {
_clear ( ) ;
}
void WebSocketMultiplayerPeer : : _clear ( ) {
_peer_map . clear ( ) ;
2020-05-14 16:41:43 +02:00
if ( _current_packet . data ! = nullptr ) {
2017-12-21 03:13:23 +01:00
memfree ( _current_packet . data ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
2021-07-16 05:45:57 +02:00
for ( Packet & E : _incoming_packets ) {
memfree ( E . data ) ;
E . data = nullptr ;
2017-12-21 03:13:23 +01:00
}
_incoming_packets . clear ( ) ;
}
void WebSocketMultiplayerPeer : : _bind_methods ( ) {
2019-06-15 17:13:26 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_buffers " , " input_buffer_size_kb " , " input_max_packets " , " output_buffer_size_kb " , " output_max_packets " ) , & WebSocketMultiplayerPeer : : set_buffers ) ;
2017-12-21 03:13:23 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_peer " , " peer_id " ) , & WebSocketMultiplayerPeer : : get_peer ) ;
ADD_SIGNAL ( MethodInfo ( " peer_packet " , PropertyInfo ( Variant : : INT , " peer_source " ) ) ) ;
}
//
// PacketPeer
//
int WebSocketMultiplayerPeer : : get_available_packet_count ( ) const {
2020-01-21 20:46:32 +01:00
ERR_FAIL_COND_V_MSG ( ! _is_multiplayer , 0 , " Please use get_peer(ID).get_available_packet_count to get available packet count from peers when not using the MultiplayerAPI. " ) ;
2017-12-21 03:13:23 +01:00
return _incoming_packets . size ( ) ;
}
Error WebSocketMultiplayerPeer : : get_packet ( const uint8_t * * r_buffer , int & r_buffer_size ) {
2019-08-11 10:49:53 +02:00
ERR_FAIL_COND_V_MSG ( ! _is_multiplayer , ERR_UNCONFIGURED , " Please use get_peer(ID).get_packet/var to communicate with peers when not using the MultiplayerAPI. " ) ;
2017-12-21 03:13:23 +01:00
2019-01-27 14:59:25 +01:00
r_buffer_size = 0 ;
2020-04-02 01:20:12 +02:00
if ( _current_packet . data ! = nullptr ) {
2017-12-21 03:13:23 +01:00
memfree ( _current_packet . data ) ;
2020-04-02 01:20:12 +02:00
_current_packet . data = nullptr ;
2017-12-21 03:13:23 +01:00
}
2021-04-30 15:36:14 +02:00
ERR_FAIL_COND_V ( _incoming_packets . size ( ) = = 0 , ERR_UNAVAILABLE ) ;
2017-12-21 03:13:23 +01:00
_current_packet = _incoming_packets . front ( ) - > get ( ) ;
_incoming_packets . pop_front ( ) ;
* r_buffer = _current_packet . data ;
r_buffer_size = _current_packet . size ;
return OK ;
}
Error WebSocketMultiplayerPeer : : put_packet ( const uint8_t * p_buffer , int p_buffer_size ) {
2019-08-11 10:49:53 +02:00
ERR_FAIL_COND_V_MSG ( ! _is_multiplayer , ERR_UNCONFIGURED , " Please use get_peer(ID).put_packet/var to communicate with peers when not using the MultiplayerAPI. " ) ;
2017-12-21 03:13:23 +01:00
2020-02-17 22:06:54 +01:00
Vector < uint8_t > buffer = _make_pkt ( SYS_NONE , get_unique_id ( ) , _target_peer , p_buffer , p_buffer_size ) ;
2017-12-21 03:13:23 +01:00
if ( is_server ( ) ) {
2020-02-17 22:06:54 +01:00
return _server_relay ( 1 , _target_peer , & ( buffer . ptr ( ) [ 0 ] ) , buffer . size ( ) ) ;
2017-12-21 03:13:23 +01:00
} else {
2020-02-17 22:06:54 +01:00
return get_peer ( 1 ) - > put_packet ( & ( buffer . ptr ( ) [ 0 ] ) , buffer . size ( ) ) ;
2017-12-21 03:13:23 +01:00
}
}
//
2021-07-12 16:11:05 +02:00
// MultiplayerPeer
2017-12-21 03:13:23 +01:00
//
void WebSocketMultiplayerPeer : : set_target_peer ( int p_target_peer ) {
_target_peer = p_target_peer ;
}
int WebSocketMultiplayerPeer : : get_packet_peer ( ) const {
2019-08-11 10:49:53 +02:00
ERR_FAIL_COND_V_MSG ( ! _is_multiplayer , 1 , " This function is not available when not using the MultiplayerAPI. " ) ;
2017-12-21 03:13:23 +01:00
ERR_FAIL_COND_V ( _incoming_packets . size ( ) = = 0 , 1 ) ;
return _incoming_packets . front ( ) - > get ( ) . source ;
}
int WebSocketMultiplayerPeer : : get_unique_id ( ) const {
return _peer_id ;
}
void WebSocketMultiplayerPeer : : _send_sys ( Ref < WebSocketPeer > p_peer , uint8_t p_type , int32_t p_peer_id ) {
ERR_FAIL_COND ( ! p_peer . is_valid ( ) ) ;
ERR_FAIL_COND ( ! p_peer - > is_connected_to_host ( ) ) ;
2020-02-17 22:06:54 +01:00
Vector < uint8_t > message = _make_pkt ( p_type , 1 , 0 , ( uint8_t * ) & p_peer_id , 4 ) ;
p_peer - > put_packet ( & ( message . ptr ( ) [ 0 ] ) , message . size ( ) ) ;
2017-12-21 03:13:23 +01:00
}
2020-02-17 22:06:54 +01:00
Vector < uint8_t > WebSocketMultiplayerPeer : : _make_pkt ( uint8_t p_type , int32_t p_from , int32_t p_to , const uint8_t * p_data , uint32_t p_data_size ) {
Vector < uint8_t > out ;
2017-12-21 03:13:23 +01:00
out . resize ( PROTO_SIZE + p_data_size ) ;
2020-02-17 22:06:54 +01:00
uint8_t * w = out . ptrw ( ) ;
2021-04-27 16:19:21 +02:00
memcpy ( & w [ 0 ] , & p_type , 1 ) ;
memcpy ( & w [ 1 ] , & p_from , 4 ) ;
memcpy ( & w [ 5 ] , & p_to , 4 ) ;
memcpy ( & w [ PROTO_SIZE ] , p_data , p_data_size ) ;
2017-12-21 03:13:23 +01:00
return out ;
}
void WebSocketMultiplayerPeer : : _send_add ( int32_t p_peer_id ) {
// First of all, confirm the ID!
_send_sys ( get_peer ( p_peer_id ) , SYS_ID , p_peer_id ) ;
// Then send the server peer (which will trigger connection_succeded in client)
_send_sys ( get_peer ( p_peer_id ) , SYS_ADD , 1 ) ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < int , Ref < WebSocketPeer > > & E : _peer_map ) {
int32_t id = E . key ;
2020-05-14 16:41:43 +02:00
if ( p_peer_id = = id ) {
2021-03-12 14:35:16 +01:00
continue ; // Skip the newly added peer (already confirmed)
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
// Send new peer to others
_send_sys ( get_peer ( id ) , SYS_ADD , p_peer_id ) ;
// Send others to new peer
_send_sys ( get_peer ( p_peer_id ) , SYS_ADD , id ) ;
}
}
void WebSocketMultiplayerPeer : : _send_del ( int32_t p_peer_id ) {
2021-08-09 22:13:42 +02:00
for ( const KeyValue < int , Ref < WebSocketPeer > > & E : _peer_map ) {
int32_t id = E . key ;
2020-05-14 16:41:43 +02:00
if ( p_peer_id ! = id ) {
2017-12-21 03:13:23 +01:00
_send_sys ( get_peer ( id ) , SYS_DEL , p_peer_id ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
}
}
void WebSocketMultiplayerPeer : : _store_pkt ( int32_t p_source , int32_t p_dest , const uint8_t * p_data , uint32_t p_data_size ) {
Packet packet ;
packet . data = ( uint8_t * ) memalloc ( p_data_size ) ;
packet . size = p_data_size ;
packet . source = p_source ;
packet . destination = p_dest ;
2021-04-27 16:19:21 +02:00
memcpy ( packet . data , & p_data [ PROTO_SIZE ] , p_data_size ) ;
2017-12-21 03:13:23 +01:00
_incoming_packets . push_back ( packet ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " peer_packet " ) , p_source ) ;
2017-12-21 03:13:23 +01:00
}
Error WebSocketMultiplayerPeer : : _server_relay ( int32_t p_from , int32_t p_to , const uint8_t * p_buffer , uint32_t p_buffer_size ) {
if ( p_to = = 1 ) {
return OK ; // Will not send to self
} else if ( p_to = = 0 ) {
2021-08-09 22:13:42 +02:00
for ( KeyValue < int , Ref < WebSocketPeer > > & E : _peer_map ) {
if ( E . key ! = p_from ) {
E . value - > put_packet ( p_buffer , p_buffer_size ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
}
return OK ; // Sent to all but sender
} else if ( p_to < 0 ) {
2021-08-09 22:13:42 +02:00
for ( KeyValue < int , Ref < WebSocketPeer > > & E : _peer_map ) {
if ( E . key ! = p_from & & E . key ! = - p_to ) {
E . value - > put_packet ( p_buffer , p_buffer_size ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
}
return OK ; // Sent to all but sender and excluded
} else {
ERR_FAIL_COND_V ( p_to = = p_from , FAILED ) ;
2019-08-19 17:21:24 +02:00
Ref < WebSocketPeer > peer_to = get_peer ( p_to ) ;
ERR_FAIL_COND_V ( peer_to . is_null ( ) , FAILED ) ;
return peer_to - > put_packet ( p_buffer , p_buffer_size ) ; // Sending to specific peer
2017-12-21 03:13:23 +01:00
}
}
void WebSocketMultiplayerPeer : : _process_multiplayer ( Ref < WebSocketPeer > p_peer , uint32_t p_peer_id ) {
ERR_FAIL_COND ( ! p_peer . is_valid ( ) ) ;
const uint8_t * in_buffer ;
int size = 0 ;
int data_size = 0 ;
Error err = p_peer - > get_packet ( & in_buffer , size ) ;
ERR_FAIL_COND ( err ! = OK ) ;
ERR_FAIL_COND ( size < PROTO_SIZE ) ;
data_size = size - PROTO_SIZE ;
uint8_t type = 0 ;
2019-02-21 20:57:39 +01:00
uint32_t from = 0 ;
2017-12-21 03:13:23 +01:00
int32_t to = 0 ;
2021-04-27 16:19:21 +02:00
memcpy ( & type , in_buffer , 1 ) ;
memcpy ( & from , & in_buffer [ 1 ] , 4 ) ;
memcpy ( & to , & in_buffer [ 5 ] , 4 ) ;
2017-12-21 03:13:23 +01:00
if ( is_server ( ) ) { // Server can resend
ERR_FAIL_COND ( type ! = SYS_NONE ) ; // Only server sends sys messages
ERR_FAIL_COND ( from ! = p_peer_id ) ; // Someone is cheating
if ( to = = 1 ) { // This is for the server
_store_pkt ( from , to , in_buffer , data_size ) ;
} else if ( to = = 0 ) {
// Broadcast, for us too
_store_pkt ( from , to , in_buffer , data_size ) ;
} else if ( to < 0 ) {
// All but one, for us if not excluded
2020-05-14 16:41:43 +02:00
if ( _peer_id ! = - ( int32_t ) p_peer_id ) {
2017-12-21 03:13:23 +01:00
_store_pkt ( from , to , in_buffer , data_size ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
}
2019-08-19 18:15:50 +02:00
// Relay if needed (i.e. "to" includes a peer that is not the server)
_server_relay ( from , to , in_buffer , size ) ;
2017-12-21 03:13:23 +01:00
} else {
if ( type = = SYS_NONE ) { // Payload message
_store_pkt ( from , to , in_buffer , data_size ) ;
return ;
}
// System message
ERR_FAIL_COND ( data_size < 4 ) ;
int id = 0 ;
2021-04-27 16:19:21 +02:00
memcpy ( & id , & in_buffer [ PROTO_SIZE ] , 4 ) ;
2017-12-21 03:13:23 +01:00
switch ( type ) {
case SYS_ADD : // Add peer
_peer_map [ id ] = Ref < WebSocketPeer > ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " peer_connected " ) , id ) ;
2020-05-14 16:41:43 +02:00
if ( id = = 1 ) { // We just connected to the server
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " connection_succeeded " ) ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-21 03:13:23 +01:00
break ;
case SYS_DEL : // Remove peer
_peer_map . erase ( id ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " peer_disconnected " ) , id ) ;
2017-12-21 03:13:23 +01:00
break ;
2021-03-12 14:35:16 +01:00
case SYS_ID : // Hello, server assigned ID
2017-12-21 03:13:23 +01:00
_peer_id = id ;
break ;
default :
2019-08-11 10:49:53 +02:00
ERR_FAIL_MSG ( " Invalid multiplayer message. " ) ;
2017-12-21 03:13:23 +01:00
break ;
}
}
}