2007-11-15 23:45:00 -05:00
/*
* libretroshare / src / serialiser : rsserial . cc
*
* RetroShare Serialiser .
*
* Copyright 2007 - 2008 by Robert Fernie .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare@lunamutt.com " .
*
*/
# include "serialiser/rsbaseserial.h"
# include "serialiser/rsserial.h"
2011-02-20 16:36:21 -05:00
# include "util/rsthreads.h"
2012-04-18 17:20:37 -04:00
# include "util/rsstring.h"
2015-03-25 18:21:01 -04:00
# include "util/rsprint.h"
2007-11-15 23:45:00 -05:00
2011-02-20 16:36:21 -05:00
# include <math.h>
2007-11-15 23:45:00 -05:00
# include <map>
2011-02-20 16:36:21 -05:00
# include <vector>
2008-03-31 10:06:59 -04:00
# include <iostream>
2007-11-15 23:45:00 -05:00
2008-03-31 10:06:59 -04:00
/***
2011-07-29 11:17:39 -04:00
* # define RSSERIAL_DEBUG 1
* # define RSSERIAL_ERROR_DEBUG 1
2008-03-31 10:06:59 -04:00
* * */
2007-11-21 23:04:13 -05:00
2011-07-29 11:17:39 -04:00
// As these represent SERIOUS ERRORs, this debug should be left one.
# define RSSERIAL_ERROR_DEBUG 1
# if defined(RSSERIAL_DEBUG) || defined(RSSERIAL_ERROR_DEBUG)
2007-12-11 19:54:42 -05:00
# include <sstream>
2007-11-21 23:04:13 -05:00
# endif
2007-11-15 23:45:00 -05:00
RsItem : : RsItem ( uint32_t t )
: type ( t )
{
2011-09-04 16:01:30 -04:00
_priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities
2007-11-15 23:45:00 -05:00
}
2015-03-14 10:33:23 -04:00
2011-02-20 16:36:21 -05:00
# ifdef DO_STATISTICS
class Counter
{
public :
Counter ( int i ) : _i ( i ) { }
Counter ( ) : _i ( 0 ) { }
int v ( ) const { return _i ; }
int & v ( ) { return _i ; }
private :
int _i ;
} ;
static RsMutex smtx ;
static std : : map < int , Counter > size_hits ;
static int nb_rsitem_creations = 0 ;
static int total_rsitem_mallocs = 0 ;
static int total_rsitem_frees = 0 ;
static int total_rsitem_freed = 0 ;
static time_t last_time = 0 ;
void * RsItem : : operator new ( size_t s )
{
// std::cerr << "New RsItem: s=" << s << std::endl;
RsStackMutex m ( smtx ) ;
+ + size_hits [ s ] . v ( ) ;
time_t now = time ( NULL ) ;
+ + nb_rsitem_creations ;
total_rsitem_mallocs + = s ;
if ( last_time + 20 < now )
{
std : : cerr < < " Memory statistics: " < < std : : endl ;
std : : cerr < < " Total RsItem memory: " < < total_rsitem_mallocs < < std : : endl ;
std : : cerr < < " Total RsItem creations: " < < nb_rsitem_creations < < std : : endl ;
std : : cerr < < " Total RsItem freed memory: " < < total_rsitem_freed < < std : : endl ;
std : : cerr < < " Total RsItem deletions: " < < total_rsitem_frees < < std : : endl ;
std : : cerr < < " Now printing histogram: " < < std : : endl ;
for ( std : : map < int , Counter > : : const_iterator it ( size_hits . begin ( ) ) ; it ! = size_hits . end ( ) ; + + it )
std : : cerr < < it - > first < < " " < < it - > second . v ( ) < < std : : endl ;
last_time = now ;
}
RsItem * a = static_cast < RsItem * > ( : : operator new ( s ) ) ;
return a ;
}
void RsItem : : operator delete ( void * p , size_t s )
{
// std::cerr << "Delete RsItem: s=" << s << std::endl;
RsStackMutex m ( smtx ) ;
total_rsitem_freed + = s ;
+ + total_rsitem_frees ;
: : operator delete ( p ) ;
}
# endif
2007-11-15 23:45:00 -05:00
RsItem : : RsItem ( uint8_t ver , uint8_t cls , uint8_t t , uint8_t subtype )
{
2011-09-04 16:01:30 -04:00
_priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities
2007-11-15 23:45:00 -05:00
type = ( ver < < 24 ) + ( cls < < 16 ) + ( t < < 8 ) + subtype ;
}
RsItem : : ~ RsItem ( )
{
}
2012-04-13 20:30:23 -04:00
void RsItem : : print_string ( std : : string & out , uint16_t indent )
{
std : : ostringstream stream ;
print ( stream , indent ) ;
out + = stream . str ( ) ;
}
2013-11-02 10:35:33 -04:00
uint32_t RsItem : : PacketId ( ) const
2007-11-15 23:45:00 -05:00
{
return type ;
}
uint8_t RsItem : : PacketVersion ( )
{
return ( type > > 24 ) ;
}
uint8_t RsItem : : PacketClass ( )
{
return ( type > > 16 ) & 0xFF ;
}
uint8_t RsItem : : PacketType ( )
{
return ( type > > 8 ) & 0xFF ;
}
2014-04-18 17:58:14 -04:00
uint8_t RsItem : : PacketSubType ( ) const
2007-11-15 23:45:00 -05:00
{
return ( type & 0xFF ) ;
}
2007-12-11 19:54:42 -05:00
/* For Service Packets */
RsItem : : RsItem ( uint8_t ver , uint16_t service , uint8_t subtype )
{
2011-09-04 16:01:30 -04:00
_priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities
2007-12-11 19:54:42 -05:00
type = ( ver < < 24 ) + ( service < < 8 ) + subtype ;
return ;
}
2014-04-18 17:58:14 -04:00
uint16_t RsItem : : PacketService ( ) const
2007-12-11 19:54:42 -05:00
{
return ( type > > 8 ) & 0xFFFF ;
}
2014-12-02 08:22:48 -05:00
void RsItem : : setPacketService ( uint16_t service )
{
type & = 0xFF0000FF ;
type | = ( uint32_t ) ( service < < 8 ) ;
}
2007-12-11 19:54:42 -05:00
2007-11-15 23:45:00 -05:00
RsSerialType : : RsSerialType ( uint32_t t )
: type ( t & 0xFFFFFF00 )
{
return ;
}
RsSerialType : : RsSerialType ( uint8_t ver , uint8_t cls , uint8_t t )
{
type = ( ver < < 24 ) + ( cls < < 16 ) + ( t < < 8 ) ;
return ;
}
2007-12-11 19:54:42 -05:00
RsSerialType : : RsSerialType ( uint8_t ver , uint16_t service )
{
type = ( ver < < 24 ) + ( service < < 8 ) ;
return ;
}
2007-11-15 23:45:00 -05:00
RsSerialType : : ~ RsSerialType ( )
{
return ;
}
uint32_t RsSerialType : : size ( RsItem * )
{
# ifdef RSSERIAL_DEBUG
std : : cerr < < " RsSerialType::size() " < < std : : endl ;
# endif
/* base size: type + length */
return 8 ;
}
2011-08-12 09:42:30 -04:00
bool RsSerialType : : serialise ( RsItem */ * item */ , void */ * data */ , uint32_t */ * size */ )
2007-11-15 23:45:00 -05:00
{
# ifdef RSSERIAL_DEBUG
std : : cerr < < " RsSerialType::serialise() " < < std : : endl ;
# endif
return false ;
}
2011-08-12 09:42:30 -04:00
RsItem * RsSerialType : : deserialise ( void */ * data */ , uint32_t */ * size */ )
2007-11-15 23:45:00 -05:00
{
# ifdef RSSERIAL_DEBUG
std : : cerr < < " RsSerialType::deserialise() " < < std : : endl ;
# endif
return NULL ;
}
2013-11-02 10:35:33 -04:00
uint32_t RsSerialType : : PacketId ( ) const
2007-11-15 23:45:00 -05:00
{
return type ;
}
RsSerialiser : : RsSerialiser ( )
{
return ;
}
RsSerialiser : : ~ RsSerialiser ( )
{
/* clean up the map */
std : : map < uint32_t , RsSerialType * > : : iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = serialisers . begin ( ) ; it ! = serialisers . end ( ) ; + + it )
2007-11-15 23:45:00 -05:00
{
delete ( it - > second ) ;
}
serialisers . clear ( ) ;
return ;
}
bool RsSerialiser : : addSerialType ( RsSerialType * serialiser )
{
2007-11-21 23:04:13 -05:00
uint32_t type = ( serialiser - > PacketId ( ) & 0xFFFFFF00 ) ;
2007-11-15 23:45:00 -05:00
std : : map < uint32_t , RsSerialType * > : : iterator it ;
if ( serialisers . end ( ) ! = ( it = serialisers . find ( type ) ) )
{
# ifdef RSSERIAL_DEBUG
std : : cerr < < " RsSerialiser::addSerialType() Error Serialiser already exists! " ;
std : : cerr < < std : : endl ;
# endif
return false ;
}
serialisers [ type ] = serialiser ;
return true ;
}
uint32_t RsSerialiser : : size ( RsItem * item )
{
/* find the type */
2007-11-21 23:04:13 -05:00
uint32_t type = ( item - > PacketId ( ) & 0xFFFFFF00 ) ;
2007-11-15 23:45:00 -05:00
std : : map < uint32_t , RsSerialType * > : : iterator it ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
2007-12-11 19:54:42 -05:00
/* remove 8 more bits -> try again */
type & = 0xFFFF0000 ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
/* one more try */
type & = 0xFF000000 ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
std : : cerr < < " RsSerialiser::size() ERROR serialiser missing! " ;
2008-02-04 12:55:13 -05:00
2012-04-18 17:20:37 -04:00
std : : string out ;
rs_sprintf ( out , " %x " , item - > PacketId ( ) ) ;
2008-02-04 12:55:13 -05:00
std : : cerr < < " RsSerialiser::size() PacketId: " ;
2012-04-18 17:20:37 -04:00
std : : cerr < < out ;
2007-12-11 19:54:42 -05:00
std : : cerr < < std : : endl ;
2007-11-15 23:45:00 -05:00
# endif
2007-12-11 19:54:42 -05:00
return 0 ;
}
}
2007-11-15 23:45:00 -05:00
}
2007-11-21 23:04:13 -05:00
# ifdef RSSERIAL_DEBUG
2012-04-18 17:20:37 -04:00
std : : string out ;
rs_sprintf ( out , " RsSerialiser::size() Item->PacketId(): %x matched to Serialiser Type: %lu " , item - > PacketId ( ) , type ) ;
std : : cerr < < out < < std : : endl ;
2007-11-21 23:04:13 -05:00
# endif
2007-11-15 23:45:00 -05:00
return ( it - > second ) - > size ( item ) ;
}
bool RsSerialiser : : serialise ( RsItem * item , void * data , uint32_t * size )
{
/* find the type */
uint32_t type = ( item - > PacketId ( ) & 0xFFFFFF00 ) ;
std : : map < uint32_t , RsSerialType * > : : iterator it ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
2007-12-11 19:54:42 -05:00
/* remove 8 more bits -> try again */
type & = 0xFFFF0000 ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
/* one more try */
type & = 0xFF000000 ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
std : : cerr < < " RsSerialiser::serialise() ERROR serialiser missing! " ;
2012-04-18 17:20:37 -04:00
std : : string out ;
rs_sprintf ( out , " %x " , item - > PacketId ( ) ) ;
2008-02-04 12:55:13 -05:00
std : : cerr < < " RsSerialiser::serialise() PacketId: " ;
2012-04-18 17:20:37 -04:00
std : : cerr < < out ;
2007-12-11 19:54:42 -05:00
std : : cerr < < std : : endl ;
2007-11-15 23:45:00 -05:00
# endif
2007-12-11 19:54:42 -05:00
return false ;
}
}
2007-11-15 23:45:00 -05:00
}
2007-11-21 23:04:13 -05:00
# ifdef RSSERIAL_DEBUG
2012-04-18 17:20:37 -04:00
std : : string out ;
rs_sprintf ( out , " RsSerialiser::serialise() Item->PacketId(): %x matched to Serialiser Type: %lu " , item - > PacketId ( ) , type ) ;
std : : cerr < < out < < std : : endl ;
2007-11-21 23:04:13 -05:00
# endif
2007-11-15 23:45:00 -05:00
return ( it - > second ) - > serialise ( item , data , size ) ;
}
RsItem * RsSerialiser : : deserialise ( void * data , uint32_t * size )
{
/* find the type */
if ( * size < 8 )
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
std : : cerr < < " RsSerialiser::deserialise() ERROR Not Enough Data(1) " ;
2007-11-15 23:45:00 -05:00
std : : cerr < < std : : endl ;
# endif
return NULL ;
}
uint32_t type = ( getRsItemId ( data ) & 0xFFFFFF00 ) ;
uint32_t pkt_size = getRsItemSize ( data ) ;
2011-07-29 11:17:39 -04:00
//std::cerr << "RsSerialiser::deserialise() RsItem Type: " << std::hex << getRsItemId(data) << " Size: " << pkt_size;
//std::cerr << std::endl;
2014-04-05 00:48:52 -04:00
if ( pkt_size ! = * size )
2007-11-15 23:45:00 -05:00
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
2014-04-05 00:48:52 -04:00
std : : cerr < < " RsSerialiser::deserialise() ERROR Size mismatch(2) " ;
2007-11-15 23:45:00 -05:00
std : : cerr < < std : : endl ;
# endif
return NULL ;
}
2015-12-27 10:03:07 -05:00
if ( pkt_size > getRsPktMaxSize ( ) )
{
std : : cerr < < " (EE) trying to deserialise a packet with absurdely large size " < < pkt_size < < " . This means there's a bug upward or packet corruption. Packet content: " < < RsUtil : : BinToHex ( ( unsigned char * ) data , std : : min ( 300u , pkt_size ) ) ;
return NULL ;
}
2007-11-15 23:45:00 -05:00
/* store the packet size to return the amount we should use up */
* size = pkt_size ;
std : : map < uint32_t , RsSerialType * > : : iterator it ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
2007-12-11 19:54:42 -05:00
/* remove 8 more bits -> try again */
type & = 0xFFFF0000 ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
/* one more try */
type & = 0xFF000000 ;
if ( serialisers . end ( ) = = ( it = serialisers . find ( type ) ) )
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
std : : cerr < < " RsSerialiser::deserialise() ERROR deserialiser missing! " ;
2012-04-18 17:20:37 -04:00
std : : string out ;
rs_sprintf ( out , " %x " , getRsItemId ( data ) ) ;
2008-02-04 12:55:13 -05:00
std : : cerr < < " RsSerialiser::deserialise() PacketId: " ;
2012-04-18 17:20:37 -04:00
std : : cerr < < out < < std : : endl ;
2007-11-15 23:45:00 -05:00
# endif
2007-12-11 19:54:42 -05:00
return NULL ;
}
}
2007-11-15 23:45:00 -05:00
}
RsItem * item = ( it - > second ) - > deserialise ( data , & pkt_size ) ;
if ( ! item )
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
std : : cerr < < " RsSerialiser::deserialise() ERROR Failed! " ;
std : : cerr < < std : : endl ;
std : : cerr < < " RsSerialiser::deserialise() pkt_size: " < < pkt_size < < " vs *size: " < < * size ;
2015-03-25 18:21:01 -04:00
std : : cerr < < std : : endl ;
2015-09-24 18:03:19 -04:00
//RsItem *item2 = (it->second)->deserialise(data, &pkt_size);
2011-07-29 11:17:39 -04:00
uint32_t failedtype = getRsItemId ( data ) ;
std : : cerr < < " RsSerialiser::deserialise() FAILED PACKET Size: " ;
std : : cerr < < getRsItemSize ( data ) < < " ID: " ;
std : : cerr < < std : : hex < < failedtype < < std : : dec ;
std : : cerr < < " RsSerialiser::deserialise() FAILED PACKET: " ;
std : : cerr < < " Version: " < < std : : hex < < ( uint32_t ) getRsItemVersion ( failedtype ) < < std : : dec ;
std : : cerr < < " Class: " < < std : : hex < < ( uint32_t ) getRsItemClass ( failedtype ) < < std : : dec ;
std : : cerr < < " Type: " < < std : : hex < < ( uint32_t ) getRsItemType ( failedtype ) < < std : : dec ;
std : : cerr < < " SubType: " < < std : : hex < < ( uint32_t ) getRsItemSubType ( failedtype ) < < std : : dec ;
2015-04-03 17:57:24 -04:00
std : : cerr < < " Data: " < < RsUtil : : BinToHex ( ( char * ) data , pkt_size ) . substr ( 0 , 300 ) < < std : : endl ;
2015-03-25 18:21:01 -04:00
std : : cerr < < std : : endl ;
2007-12-11 19:54:42 -05:00
# endif
2007-11-15 23:45:00 -05:00
return NULL ;
}
if ( pkt_size ! = * size )
{
2011-07-29 11:17:39 -04:00
# ifdef RSSERIAL_ERROR_DEBUG
std : : cerr < < " RsSerialiser::deserialise() ERROR: size mismatch! " ;
std : : cerr < < std : : endl ;
std : : cerr < < " RsSerialiser::deserialise() pkt_size: " < < pkt_size < < " vs *size: " < < * size ;
std : : cerr < < std : : endl ;
uint32_t failedtype = getRsItemId ( data ) ;
std : : cerr < < " RsSerialiser::deserialise() FAILED PACKET Size: " ;
std : : cerr < < getRsItemSize ( data ) < < " ID: " ;
std : : cerr < < std : : hex < < failedtype < < std : : dec ;
std : : cerr < < " RsSerialiser::deserialise() FAILED PACKET: " ;
std : : cerr < < " Version: " < < std : : hex < < ( uint32_t ) getRsItemVersion ( failedtype ) < < std : : dec ;
std : : cerr < < " Class: " < < std : : hex < < ( uint32_t ) getRsItemClass ( failedtype ) < < std : : dec ;
std : : cerr < < " Type: " < < std : : hex < < ( uint32_t ) getRsItemType ( failedtype ) < < std : : dec ;
2015-03-25 18:21:01 -04:00
std : : cerr < < " SubType: " < < std : : hex < < ( uint32_t ) getRsItemSubType ( failedtype ) < < std : : dec ;
2015-04-03 17:57:24 -04:00
std : : cerr < < " Data: " < < RsUtil : : BinToHex ( ( char * ) data , pkt_size ) . substr ( 0 , 300 ) < < std : : endl ;
2007-11-15 23:45:00 -05:00
std : : cerr < < std : : endl ;
# endif
}
return item ;
}
bool setRsItemHeader ( void * data , uint32_t size , uint32_t type , uint32_t pktsize )
{
if ( size < 8 )
return false ;
uint32_t offset = 0 ;
bool ok = true ;
ok & = setRawUInt32 ( data , 8 , & offset , type ) ;
ok & = setRawUInt32 ( data , 8 , & offset , pktsize ) ;
return ok ;
}
uint32_t getRsItemId ( void * data )
{
2009-02-22 12:36:39 -05:00
uint32_t type = 0 ;
2007-11-15 23:45:00 -05:00
uint32_t offset = 0 ;
getRawUInt32 ( data , 4 , & offset , & type ) ;
return type ;
}
uint32_t getRsItemSize ( void * data )
{
2009-02-22 12:36:39 -05:00
uint32_t size = 0 ;
2007-11-15 23:45:00 -05:00
uint32_t offset = 4 ;
getRawUInt32 ( data , 8 , & offset , & size ) ;
return size ;
}
uint8_t getRsItemVersion ( uint32_t type )
{
return ( type > > 24 ) ;
}
uint8_t getRsItemClass ( uint32_t type )
{
return ( type > > 16 ) & 0xFF ;
}
uint8_t getRsItemType ( uint32_t type )
{
return ( type > > 8 ) & 0xFF ;
}
uint8_t getRsItemSubType ( uint32_t type )
{
return ( type & 0xFF ) ;
}
2007-12-11 19:54:42 -05:00
uint16_t getRsItemService ( uint32_t type )
{
return ( type > > 8 ) & 0xFFFF ;
}
std : : ostream & printRsItemBase ( std : : ostream & out , std : : string clsName , uint16_t indent )
{
printIndent ( out , indent ) ;
out < < " RsItem: " < < clsName < < " #################################### " ;
out < < std : : endl ;
return out ;
}
std : : ostream & printRsItemEnd ( std : : ostream & out , std : : string clsName , uint16_t indent )
{
printIndent ( out , indent ) ;
out < < " ###################### " < < clsName < < " ##################### " ;
out < < std : : endl ;
return out ;
}
std : : ostream & RsRawItem : : print ( std : : ostream & out , uint16_t indent )
{
printRsItemBase ( out , " RsRawItem " , indent ) ;
printIndent ( out , indent ) ;
out < < " Size: " < < len < < std : : endl ;
printRsItemEnd ( out , " RsRawItem " , indent ) ;
return out ;
}
uint32_t getRsPktMaxSize ( )
{
2008-03-31 10:06:59 -04:00
//return 65535; /* 2^16 (old artifical low size) */
//return 1048575; /* 2^20 -1 (Too Big! - must remove fixed static buffers first) */
/* Remember that every pqistreamer allocates an input buffer of this size!
* So don ' t make it too big !
*/
return 262143 ; /* 2^18 -1 */
2007-12-11 19:54:42 -05:00
}
2007-11-15 23:45:00 -05:00
2007-12-11 19:54:42 -05:00
uint32_t getRsPktBaseSize ( )
{
return 8 ; /* 4 + 4 */
}
2007-11-15 23:45:00 -05:00