2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* packet_peer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +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. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "packet_peer.h"
2018-09-11 18:13:45 +02:00
# include "core/io/marshalls.h"
# include "core/project_settings.h"
2014-02-10 02:10:30 +01:00
/* helpers / binders */
2018-12-08 21:07:33 +01:00
PacketPeer : : PacketPeer ( ) :
last_get_error ( OK ) ,
2020-01-18 19:52:59 +01:00
allow_object_decoding ( false ) ,
encode_buffer_max_size ( 8 * 1024 * 1024 ) {
2014-02-10 02:10:30 +01:00
}
2017-08-14 16:58:10 +02:00
void PacketPeer : : set_allow_object_decoding ( bool p_enable ) {
allow_object_decoding = p_enable ;
}
bool PacketPeer : : is_object_decoding_allowed ( ) const {
return allow_object_decoding ;
}
2020-01-18 19:52:59 +01:00
void PacketPeer : : set_encode_buffer_max_size ( int p_max_size ) {
ERR_FAIL_COND_MSG ( p_max_size < 1024 , " Max encode buffer must be at least 1024 bytes " ) ;
ERR_FAIL_COND_MSG ( p_max_size > 256 * 1024 * 1024 , " Max encode buffer cannot exceed 256 MiB " ) ;
encode_buffer_max_size = next_power_of_2 ( p_max_size ) ;
encode_buffer . resize ( 0 ) ;
}
int PacketPeer : : get_encode_buffer_max_size ( ) const {
return encode_buffer_max_size ;
}
2017-12-15 16:05:42 +01:00
Error PacketPeer : : get_packet_buffer ( PoolVector < uint8_t > & r_buffer ) {
2014-02-10 02:10:30 +01:00
const uint8_t * buffer ;
int buffer_size ;
2017-03-05 16:44:50 +01:00
Error err = get_packet ( & buffer , buffer_size ) ;
2014-02-10 02:10:30 +01:00
if ( err )
return err ;
r_buffer . resize ( buffer_size ) ;
2017-03-05 16:44:50 +01:00
if ( buffer_size = = 0 )
2014-02-10 02:10:30 +01:00
return OK ;
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Write w = r_buffer . write ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < buffer_size ; i + + )
w [ i ] = buffer [ i ] ;
2014-02-10 02:10:30 +01:00
return OK ;
}
2017-01-07 22:25:37 +01:00
Error PacketPeer : : put_packet_buffer ( const PoolVector < uint8_t > & p_buffer ) {
2014-02-10 02:10:30 +01:00
int len = p_buffer . size ( ) ;
2017-03-05 16:44:50 +01:00
if ( len = = 0 )
2014-02-10 02:10:30 +01:00
return OK ;
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > : : Read r = p_buffer . read ( ) ;
2017-03-05 16:44:50 +01:00
return put_packet ( & r [ 0 ] , len ) ;
2014-02-10 02:10:30 +01:00
}
2019-03-26 16:52:42 +01:00
Error PacketPeer : : get_var ( Variant & r_variant , bool p_allow_objects ) {
2014-02-10 02:10:30 +01:00
const uint8_t * buffer ;
int buffer_size ;
2017-03-05 16:44:50 +01:00
Error err = get_packet ( & buffer , buffer_size ) ;
2014-02-10 02:10:30 +01:00
if ( err )
return err ;
2019-03-26 16:52:42 +01:00
return decode_variant ( r_variant , buffer , buffer_size , NULL , p_allow_objects | | allow_object_decoding ) ;
2014-02-10 02:10:30 +01:00
}
2019-03-26 16:52:42 +01:00
Error PacketPeer : : put_var ( const Variant & p_packet , bool p_full_objects ) {
2014-02-10 02:10:30 +01:00
int len ;
2019-03-26 16:52:42 +01:00
Error err = encode_variant ( p_packet , NULL , len , p_full_objects | | allow_object_decoding ) ; // compute len first
2014-02-10 02:10:30 +01:00
if ( err )
return err ;
2017-03-05 16:44:50 +01:00
if ( len = = 0 )
2014-02-10 02:10:30 +01:00
return OK ;
2020-01-18 19:52:59 +01:00
ERR_FAIL_COND_V_MSG ( len > encode_buffer_max_size , ERR_OUT_OF_MEMORY , " Failed to encode variant, encode size is bigger then encode_buffer_max_size. Consider raising it via 'set_encode_buffer_max_size'. " ) ;
if ( unlikely ( encode_buffer . size ( ) < len ) ) {
encode_buffer . resize ( 0 ) ; // Avoid realloc
encode_buffer . resize ( next_power_of_2 ( len ) ) ;
}
PoolVector < uint8_t > : : Write w = encode_buffer . write ( ) ;
err = encode_variant ( p_packet , w . ptr ( ) , len , p_full_objects | | allow_object_decoding ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( err ! = OK , err , " Error when trying to encode Variant. " ) ;
2014-02-10 02:10:30 +01:00
2020-01-18 19:52:59 +01:00
return put_packet ( w . ptr ( ) , len ) ;
2014-02-10 02:10:30 +01:00
}
2019-03-26 16:52:42 +01:00
Variant PacketPeer : : _bnd_get_var ( bool p_allow_objects ) {
2014-02-10 02:10:30 +01:00
Variant var ;
2019-07-23 09:14:31 +02:00
Error err = get_var ( var , p_allow_objects ) ;
2014-02-10 02:10:30 +01:00
2019-07-23 09:14:31 +02:00
ERR_FAIL_COND_V ( err ! = OK , Variant ( ) ) ;
2014-02-10 02:10:30 +01:00
return var ;
2019-07-23 09:14:31 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Error PacketPeer : : _put_packet ( const PoolVector < uint8_t > & p_buffer ) {
2015-06-06 14:44:38 +02:00
return put_packet_buffer ( p_buffer ) ;
}
2017-12-15 16:05:42 +01:00
PoolVector < uint8_t > PacketPeer : : _get_packet ( ) {
2015-06-06 14:44:38 +02:00
2017-01-07 22:25:37 +01:00
PoolVector < uint8_t > raw ;
2017-03-05 16:44:50 +01:00
last_get_error = get_packet_buffer ( raw ) ;
2015-06-06 14:44:38 +02:00
return raw ;
}
Error PacketPeer : : _get_packet_error ( ) const {
return last_get_error ;
}
2014-02-10 02:10:30 +01:00
void PacketPeer : : _bind_methods ( ) {
2019-03-26 16:52:42 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_var " , " allow_objects " ) , & PacketPeer : : _bnd_get_var , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " put_var " , " var " , " full_objects " ) , & PacketPeer : : put_var , DEFVAL ( false ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_packet " ) , & PacketPeer : : _get_packet ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " put_packet " , " buffer " ) , & PacketPeer : : _put_packet ) ;
ClassDB : : bind_method ( D_METHOD ( " get_packet_error " ) , & PacketPeer : : _get_packet_error ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_available_packet_count " ) , & PacketPeer : : get_available_packet_count ) ;
2017-08-14 16:58:10 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_allow_object_decoding " , " enable " ) , & PacketPeer : : set_allow_object_decoding ) ;
ClassDB : : bind_method ( D_METHOD ( " is_object_decoding_allowed " ) , & PacketPeer : : is_object_decoding_allowed ) ;
2020-01-18 19:52:59 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_encode_buffer_max_size " ) , & PacketPeer : : get_encode_buffer_max_size ) ;
ClassDB : : bind_method ( D_METHOD ( " set_encode_buffer_max_size " , " max_size " ) , & PacketPeer : : set_encode_buffer_max_size ) ;
2018-01-11 23:35:12 +01:00
2020-01-18 19:52:59 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " encode_buffer_max_size " ) , " set_encode_buffer_max_size " , " get_encode_buffer_max_size " ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_object_decoding " ) , " set_allow_object_decoding " , " is_object_decoding_allowed " ) ;
2014-02-10 02:10:30 +01:00
} ;
/***************/
void PacketPeerStream : : _set_stream_peer ( REF p_peer ) {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( p_peer . is_null ( ) , " It's not a reference to a valid Resource object. " ) ;
2014-02-10 02:10:30 +01:00
set_stream_peer ( p_peer ) ;
}
void PacketPeerStream : : _bind_methods ( ) {
2018-01-12 14:25:05 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_stream_peer " , " peer " ) , & PacketPeerStream : : set_stream_peer ) ;
2018-01-11 23:35:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_stream_peer " ) , & PacketPeerStream : : get_stream_peer ) ;
2017-08-09 01:55:22 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_input_buffer_max_size " , " max_size_bytes " ) , & PacketPeerStream : : set_input_buffer_max_size ) ;
ClassDB : : bind_method ( D_METHOD ( " set_output_buffer_max_size " , " max_size_bytes " ) , & PacketPeerStream : : set_output_buffer_max_size ) ;
2017-08-18 15:59:31 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_input_buffer_max_size " ) , & PacketPeerStream : : get_input_buffer_max_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_output_buffer_max_size " ) , & PacketPeerStream : : get_output_buffer_max_size ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " input_buffer_max_size " ) , " set_input_buffer_max_size " , " get_input_buffer_max_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " output_buffer_max_size " ) , " set_output_buffer_max_size " , " get_output_buffer_max_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " stream_peer " , PROPERTY_HINT_RESOURCE_TYPE , " StreamPeer " , 0 ) , " set_stream_peer " , " get_stream_peer " ) ;
2014-02-10 02:10:30 +01:00
}
Error PacketPeerStream : : _poll_buffer ( ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( peer . is_null ( ) , ERR_UNCONFIGURED ) ;
2014-02-10 02:10:30 +01:00
int read = 0 ;
2018-01-03 21:08:44 +01:00
ERR_FAIL_COND_V ( input_buffer . size ( ) < ring_buffer . space_left ( ) , ERR_UNAVAILABLE ) ;
2018-07-25 03:11:03 +02:00
Error err = peer - > get_partial_data ( input_buffer . ptrw ( ) , ring_buffer . space_left ( ) , read ) ;
2014-02-10 02:10:30 +01:00
if ( err )
return err ;
2017-03-05 16:44:50 +01:00
if ( read = = 0 )
2014-02-10 02:10:30 +01:00
return OK ;
2017-08-09 01:55:22 +02:00
int w = ring_buffer . write ( & input_buffer [ 0 ] , read ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( w ! = read , ERR_BUG ) ;
2014-02-10 02:10:30 +01:00
return OK ;
}
int PacketPeerStream : : get_available_packet_count ( ) const {
_poll_buffer ( ) ;
uint32_t remaining = ring_buffer . data_left ( ) ;
2017-03-05 16:44:50 +01:00
int ofs = 0 ;
int count = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( remaining > = 4 ) {
2014-02-10 02:10:30 +01:00
uint8_t lbuf [ 4 ] ;
2017-03-05 16:44:50 +01:00
ring_buffer . copy ( lbuf , ofs , 4 ) ;
2014-02-10 02:10:30 +01:00
uint32_t len = decode_uint32 ( lbuf ) ;
2017-03-05 16:44:50 +01:00
remaining - = 4 ;
ofs + = 4 ;
if ( len > remaining )
2014-02-10 02:10:30 +01:00
break ;
2017-03-05 16:44:50 +01:00
remaining - = len ;
ofs + = len ;
2014-02-10 02:10:30 +01:00
count + + ;
}
return count ;
}
2017-12-15 16:05:42 +01:00
Error PacketPeerStream : : get_packet ( const uint8_t * * r_buffer , int & r_buffer_size ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( peer . is_null ( ) , ERR_UNCONFIGURED ) ;
2014-02-10 02:10:30 +01:00
_poll_buffer ( ) ;
int remaining = ring_buffer . data_left ( ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( remaining < 4 , ERR_UNAVAILABLE ) ;
2014-02-10 02:10:30 +01:00
uint8_t lbuf [ 4 ] ;
2017-03-05 16:44:50 +01:00
ring_buffer . copy ( lbuf , 0 , 4 ) ;
remaining - = 4 ;
2016-03-09 00:00:52 +01:00
uint32_t len = decode_uint32 ( lbuf ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( remaining < ( int ) len , ERR_UNAVAILABLE ) ;
2014-02-10 02:10:30 +01:00
2019-02-21 20:57:39 +01:00
ERR_FAIL_COND_V ( input_buffer . size ( ) < ( int ) len , ERR_UNAVAILABLE ) ;
2017-03-05 16:44:50 +01:00
ring_buffer . read ( lbuf , 4 ) ; //get rid of first 4 bytes
2018-07-25 03:11:03 +02:00
ring_buffer . read ( input_buffer . ptrw ( ) , len ) ; // read packet
2014-02-10 02:10:30 +01:00
2017-08-09 01:55:22 +02:00
* r_buffer = & input_buffer [ 0 ] ;
2017-03-05 16:44:50 +01:00
r_buffer_size = len ;
2014-02-10 02:10:30 +01:00
return OK ;
}
2017-03-05 16:44:50 +01:00
Error PacketPeerStream : : put_packet ( const uint8_t * p_buffer , int p_buffer_size ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( peer . is_null ( ) , ERR_UNCONFIGURED ) ;
2014-02-10 02:10:30 +01:00
Error err = _poll_buffer ( ) ; //won't hurt to poll here too
if ( err )
return err ;
2017-03-05 16:44:50 +01:00
if ( p_buffer_size = = 0 )
2014-02-10 02:10:30 +01:00
return OK ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( p_buffer_size < 0 , ERR_INVALID_PARAMETER ) ;
2017-08-09 01:55:22 +02:00
ERR_FAIL_COND_V ( p_buffer_size + 4 > output_buffer . size ( ) , ERR_INVALID_PARAMETER ) ;
2014-02-10 02:10:30 +01:00
2018-07-25 03:11:03 +02:00
encode_uint32 ( p_buffer_size , output_buffer . ptrw ( ) ) ;
uint8_t * dst = & output_buffer . write [ 4 ] ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_buffer_size ; i + + )
dst [ i ] = p_buffer [ i ] ;
2014-02-10 02:10:30 +01:00
2017-08-09 01:55:22 +02:00
return peer - > put_data ( & output_buffer [ 0 ] , p_buffer_size + 4 ) ;
2014-02-10 02:10:30 +01:00
}
int PacketPeerStream : : get_max_packet_size ( ) const {
2017-08-09 01:55:22 +02:00
return output_buffer . size ( ) ;
2014-02-10 02:10:30 +01:00
}
void PacketPeerStream : : set_stream_peer ( const Ref < StreamPeer > & p_peer ) {
2016-01-24 20:59:39 +01:00
//ERR_FAIL_COND(p_peer.is_null());
2014-02-10 02:10:30 +01:00
if ( p_peer . ptr ( ) ! = peer . ptr ( ) ) {
ring_buffer . advance_read ( ring_buffer . data_left ( ) ) ; // reset the ring buffer
} ;
2017-03-05 16:44:50 +01:00
peer = p_peer ;
2014-02-10 02:10:30 +01:00
}
2018-01-11 23:35:12 +01:00
Ref < StreamPeer > PacketPeerStream : : get_stream_peer ( ) const {
return peer ;
}
2014-02-10 02:10:30 +01:00
void PacketPeerStream : : set_input_buffer_max_size ( int p_max_size ) {
2019-11-20 16:22:16 +01:00
ERR_FAIL_COND_MSG ( p_max_size < 0 , " Max size of input buffer size cannot be smaller than 0. " ) ;
2014-02-10 02:10:30 +01:00
//warning may lose packets
2019-08-15 04:57:49 +02:00
ERR_FAIL_COND_MSG ( ring_buffer . data_left ( ) , " Buffer in use, resizing would cause loss of data. " ) ;
2019-12-22 15:23:35 +01:00
ring_buffer . resize ( nearest_shift ( next_power_of_2 ( p_max_size + 4 ) ) - 1 ) ;
2017-08-17 23:35:55 +02:00
input_buffer . resize ( next_power_of_2 ( p_max_size + 4 ) ) ;
2017-08-09 01:55:22 +02:00
}
2017-08-18 15:59:31 +02:00
int PacketPeerStream : : get_input_buffer_max_size ( ) const {
return input_buffer . size ( ) - 4 ;
}
2017-08-09 01:55:22 +02:00
void PacketPeerStream : : set_output_buffer_max_size ( int p_max_size ) {
2017-08-17 23:35:55 +02:00
output_buffer . resize ( next_power_of_2 ( p_max_size + 4 ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-18 15:59:31 +02:00
int PacketPeerStream : : get_output_buffer_max_size ( ) const {
return output_buffer . size ( ) - 4 ;
}
2014-02-10 02:10:30 +01:00
PacketPeerStream : : PacketPeerStream ( ) {
2017-07-18 02:05:38 +02:00
int rbsize = GLOBAL_GET ( " network/limits/packet_peer_stream/max_buffer_po2 " ) ;
2014-02-10 02:10:30 +01:00
ring_buffer . resize ( rbsize ) ;
2017-08-09 01:55:22 +02:00
input_buffer . resize ( 1 < < rbsize ) ;
output_buffer . resize ( 1 < < rbsize ) ;
2014-02-10 02:10:30 +01:00
}