2009-05-08 20:19:54 -04:00
/*
* " $Id: pqistore.cc,v 1.5 2007-03-21 18:45:41 rmf24 Exp $ "
*
* 3 P / PQI network interface for RetroShare .
*
* Copyright 2004 - 2006 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 " .
*
*/
/* This is dependent on the sslroot at the moment.
* - > as we need to create / restore references to the Person .
* - > and store the signatures to do this .
*/
/*******************************************************************
* pqistore provides an store stream .
* This stores RsItem + Person Reference + Timestamp ,
*
* and allows Objects to be replayed or restored ,
* independently of the rest of the pqi system .
*
*/
# include "pqi/pqistore.h"
# include "serialiser/rsserial.h"
# include <iostream>
# include <fstream>
# include "util/rsdebug.h"
2012-04-13 20:30:23 -04:00
# include "util/rsstring.h"
2009-05-08 20:19:54 -04:00
2011-01-20 12:25:30 -05:00
//
// #define PQISTORE_DEBUG
//
2009-05-08 20:19:54 -04:00
const int pqistorezone = 9511 ;
2010-12-19 18:50:46 -05:00
pqistore : : pqistore ( RsSerialiser * rss , const std : : string & srcId , BinInterface * bio_in , int bio_flags_in )
2011-08-12 09:42:30 -04:00
: PQInterface ( " " ) , rsSerialiser ( rss ) , bio_flags ( bio_flags_in ) ,
nextPkt ( NULL ) , mSrcId ( srcId ) , bio ( bio_in )
2009-05-08 20:19:54 -04:00
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::pqistore() Initialisation! " ) ;
2009-05-08 20:19:54 -04:00
if ( ! bio_in )
2012-04-13 20:30:23 -04:00
{
pqioutput ( PQL_ALERT , pqistorezone , " pqistore::pqistore() NULL bio, FATAL ERROR! " ) ;
exit ( 1 ) ;
2009-05-08 20:19:54 -04:00
}
return ;
}
pqistore : : ~ pqistore ( )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::~pqistore() Destruction! " ) ;
2009-05-08 20:19:54 -04:00
if ( bio_flags & BIN_FLAGS_NO_CLOSE )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::~pqistore() Not Closing BinInterface!; " ) ;
2009-05-08 20:19:54 -04:00
}
else if ( bio )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::~pqistore() Deleting BinInterface! " ) ;
2009-05-08 20:19:54 -04:00
2012-04-13 20:30:23 -04:00
delete bio ;
2009-05-08 20:19:54 -04:00
}
if ( rsSerialiser )
delete rsSerialiser ;
if ( nextPkt )
{
delete nextPkt ;
}
return ;
}
// Get/Send Items.
int pqistore : : SendItem ( RsItem * si )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2009-05-08 20:19:54 -04:00
{
2012-04-13 20:30:23 -04:00
std : : string out = " pqistore::SendItem() \n " ;
2009-05-08 20:19:54 -04:00
si - > print ( out ) ;
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , out ) ;
2009-05-08 20:19:54 -04:00
}
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
// check if this is a writing bio.
if ( ! ( bio_flags & BIN_FLAGS_WRITEABLE ) )
{
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete si ;
return - 1 ;
}
// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ;
int ret = writePkt ( si ) ;
return ret ; /* 0 - failure, 1 - success*/
}
RsItem * pqistore : : GetItem ( )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::GetItem() " ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
// check if this is a reading bio.
if ( ! ( bio_flags & BIN_FLAGS_READABLE ) )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , " pqistore::GetItem() Error Not Readable " ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
return NULL ;
}
// load if we dont have a packet.
if ( ! nextPkt )
{
if ( ! readPkt ( & nextPkt ) )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , " pqistore::GetItem() Failed to ReadPkt " ) ;
2009-05-08 20:19:54 -04:00
return NULL ;
}
}
if ( ! nextPkt ) return NULL ;
RsItem * outPkt = nextPkt ;
nextPkt = NULL ;
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2009-05-08 20:19:54 -04:00
if ( outPkt ! = NULL )
2011-01-20 12:25:30 -05:00
{
2012-04-13 20:30:23 -04:00
std : : string out = " pqistore::GetItem() Returning: \n " ;
2011-01-20 12:25:30 -05:00
outPkt - > print ( out ) ;
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , out ) ;
2009-05-08 20:19:54 -04:00
}
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
return outPkt ;
}
2010-09-18 15:09:11 -04:00
2009-05-08 20:19:54 -04:00
// // PQInterface
int pqistore : : tick ( )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
std : : cerr < < " pqistore::tick() " < < std : : endl ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
return 0 ;
}
int pqistore : : status ( )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::status() " ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
return 0 ;
}
//
/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/
int pqistore : : writePkt ( RsItem * pqi )
{
// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ;
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::writePkt() " ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
uint32_t pktsize = rsSerialiser - > size ( pqi ) ;
void * ptr = malloc ( pktsize ) ;
if ( ! ( rsSerialiser - > serialise ( pqi , ptr , & pktsize ) ) )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
std : : string out = " pqistore::writePkt() Null Pkt generated! \n Caused By: \n " ;
2009-05-08 20:19:54 -04:00
pqi - > print ( out ) ;
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_ALERT , pqistorezone , out ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
free ( ptr ) ;
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete pqi ;
return 0 ;
}
/* extract the extra details */
uint32_t len = getRsItemSize ( ptr ) ;
if ( len ! = pktsize )
{
2012-04-13 20:30:23 -04:00
std : : string out ;
rs_sprintf ( out , " pqistore::writePkt() Length MisMatch: len: %u!= pktsize: %u \n Caused By: \n " , len , pktsize ) ;
pqi - > print_string ( out ) ;
pqioutput ( PQL_ALERT , pqistorezone , out ) ;
2009-05-08 20:19:54 -04:00
free ( ptr ) ;
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete pqi ;
return 0 ;
}
if ( ! ( bio - > cansend ( ) ) )
{
2012-04-13 20:30:23 -04:00
std : : string out ;
rs_sprintf ( out , " pqistore::writePkt() BIO cannot write! \n iscarding: \n " ) ;
pqi - > print_string ( out ) ;
pqioutput ( PQL_ALERT , pqistorezone , out ) ;
2009-05-08 20:19:54 -04:00
free ( ptr ) ;
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete pqi ;
return 0 ;
}
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
std : : string out = " Writing Pkt Body " ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
// write packet.
2012-02-17 05:03:38 -05:00
if ( len ! = ( uint32_t ) bio - > senddata ( ptr , len ) )
2009-05-08 20:19:54 -04:00
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
out + = " Problems with Send Data! " ;
pqioutput ( PQL_ALERT , pqistorezone , out ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
free ( ptr ) ;
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete pqi ;
return 0 ;
}
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
out + = " Success! " ;
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , out ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
free ( ptr ) ;
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete pqi ;
return 1 ;
}
/* Reads a single packet from the input stream
* gets the timestamp as well .
*/
int pqistore : : readPkt ( RsItem * * item_out )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::readPkt() " ) ;
2011-01-20 12:25:30 -05:00
# endif
2009-05-08 20:19:54 -04:00
if ( ( ! ( bio - > isactive ( ) ) ) | | ( ! ( bio - > moretoread ( ) ) ) )
{
return 0 ;
}
// enough space to read any packet.
int maxlen = getRsPktMaxSize ( ) ;
void * block = malloc ( maxlen ) ;
// initial read size: basic packet.
int blen = getRsPktBaseSize ( ) ;
int tmplen ;
/* we have the header */
// read the basic block (minimum packet size)
if ( blen ! = ( tmplen = bio - > readdata ( block , blen ) ) )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_WARNING , pqistorezone , " pqistore::readPkt() bad read(2) " ) ;
2009-05-08 20:19:54 -04:00
free ( block ) ;
return 0 ;
}
// workout how much more to read.
int extralen = getRsItemSize ( block ) - blen ;
2010-05-28 10:00:35 -04:00
if ( extralen + blen > maxlen )
std : : cerr < < " ***** ERROR: trying to read a packet of length " < < extralen + blen < < " , while the maximum length is " < < maxlen < < std : : endl ;
2009-05-08 20:19:54 -04:00
if ( extralen > 0 )
{
2010-04-23 08:57:59 -04:00
if ( extralen > blen + maxlen )
{
std : : cerr < < " pqistore: ERROR: Inconsistency in packet format (extralen= " < < extralen < < " , maxlen= " < < maxlen < < " ). Wasting the whole file. " < < std : : endl ;
free ( block ) ;
return 0 ;
}
2009-05-08 20:19:54 -04:00
void * extradata = ( void * ) ( ( ( char * ) block ) + blen ) ;
2010-04-23 08:57:59 -04:00
2009-05-08 20:19:54 -04:00
if ( extralen ! = ( tmplen = bio - > readdata ( extradata , extralen ) ) )
{
2012-04-13 20:30:23 -04:00
std : : string out ;
rs_sprintf ( out , " pqistore::readPkt() Error Completing Read (read %d/%d) " , tmplen , extralen ) ;
pqioutput ( PQL_ALERT , pqistorezone , out ) ;
2009-05-08 20:19:54 -04:00
free ( block ) ;
return 0 ;
}
}
// create packet, based on header.
2010-02-08 09:06:43 -05:00
//std::cerr << "Read Data Block -> Incoming Pkt(";
//std::cerr << blen + extralen << ")" << std::endl;
2009-05-08 20:19:54 -04:00
uint32_t readbytes = extralen + blen ;
RsItem * item = rsSerialiser - > deserialise ( block , & readbytes ) ;
free ( block ) ;
if ( item = = NULL )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_ALERT , pqistorezone , " pqistore::readPkt() Failed to create Item from store! " ) ;
2009-05-08 20:19:54 -04:00
return 0 ;
}
2009-05-12 17:55:50 -04:00
item - > PeerId ( mSrcId ) ;
2009-05-08 20:19:54 -04:00
* item_out = item ;
return 1 ;
}
/**** Hashing Functions ****/
std : : string pqistore : : gethash ( )
{
return bio - > gethash ( ) ;
}
2010-09-18 15:09:11 -04:00
pqiSSLstore : : pqiSSLstore ( RsSerialiser * rss , std : : string srcId , BinEncryptedFileInterface * bio_in , int bio_flagsin )
: pqistore ( rss , srcId , bio_in , bio_flagsin ) , enc_bio ( bio_in )
{
return ;
}
pqiSSLstore : : ~ pqiSSLstore ( )
{
2011-01-20 12:25:30 -05:00
// no need to delete member enc_bio, as it is deleted by the parent class.
2010-09-18 15:09:11 -04:00
return ;
}
bool pqiSSLstore : : encryptedSendItems ( const std : : list < RsItem * > & rsItemList )
{
std : : list < RsItem * > : : const_iterator it ;
uint32_t sizeItems = 0 , sizeItem = 0 ;
uint32_t offset = 0 ;
char * data = NULL ;
for ( it = rsItemList . begin ( ) ; it ! = rsItemList . end ( ) ; it + + )
sizeItems + = rsSerialiser - > size ( * it ) ;
data = new char [ sizeItems ] ;
for ( it = rsItemList . begin ( ) ; it ! = rsItemList . end ( ) ; it + + )
{
sizeItem = rsSerialiser - > size ( * it ) ;
2013-07-30 10:47:41 -04:00
if ( rsSerialiser - > serialise ( * it , ( data + offset ) , & sizeItem ) )
offset + = sizeItem ;
else
std : : cerr < < " (EE) pqiSSLstore::encryptedSendItems(): One item did not serialize. The item is probably unknown from the serializer. Dropping the item. " < < std : : endl ;
2010-09-18 15:09:11 -04:00
2011-01-01 15:37:10 -05:00
if ( ! ( bio_flags & BIN_FLAGS_NO_DELETE ) )
delete * it ;
2010-09-18 15:09:11 -04:00
}
2012-07-13 18:10:52 -04:00
bool result = true ;
2010-09-18 15:09:11 -04:00
if ( sizeItems = = offset )
enc_bio - > senddata ( data , sizeItems ) ;
else
2012-07-13 18:10:52 -04:00
result = false ;
2009-05-08 20:19:54 -04:00
2010-09-18 15:09:11 -04:00
if ( data ! = NULL )
delete [ ] data ;
2012-07-13 18:10:52 -04:00
return result ;
2010-09-18 15:09:11 -04:00
}
2009-05-08 20:19:54 -04:00
2010-09-18 15:09:11 -04:00
bool pqiSSLstore : : getEncryptedItems ( std : : list < RsItem * > & rsItemList )
{
RsItem * item ;
2013-06-23 17:53:14 -04:00
do
2010-09-18 15:09:11 -04:00
{
2013-06-23 17:53:14 -04:00
if ( NULL ! = ( item = GetItem ( ) ) )
rsItemList . push_back ( item ) ;
} while ( enc_bio - > isactive ( ) & & enc_bio - > moretoread ( ) ) ;
2010-09-18 15:09:11 -04:00
return true ;
}
RsItem * pqiSSLstore : : GetItem ( )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::GetItem() " ) ;
2011-01-20 12:25:30 -05:00
# endif
2010-09-18 15:09:11 -04:00
// check if this is a reading bio.
if ( ! ( bio_flags & BIN_FLAGS_READABLE ) )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , " pqistore::GetItem() Error Not Readable " ) ;
2010-09-18 15:09:11 -04:00
return NULL ;
}
// load if we dont have a packet.
if ( ! nextPkt )
{
if ( ! readPkt ( & nextPkt ) )
{
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , " pqistore::GetItem() Failed to ReadPkt " ) ;
2010-09-18 15:09:11 -04:00
return NULL ;
}
}
if ( ! nextPkt ) return NULL ;
RsItem * outPkt = nextPkt ;
nextPkt = NULL ;
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2010-09-18 15:09:11 -04:00
if ( outPkt ! = NULL )
2012-04-13 20:30:23 -04:00
{
std : : string out ;
rs_sprintf ( out , " pqistore::GetItem() Returning: \n " ) ;
outPkt - > print ( out ) ;
pqioutput ( PQL_DEBUG_BASIC , pqistorezone , out ) ;
2010-09-18 15:09:11 -04:00
}
2011-01-20 12:25:30 -05:00
# endif
2010-09-18 15:09:11 -04:00
return outPkt ;
}
int pqiSSLstore : : readPkt ( RsItem * * item_out )
{
2011-01-20 12:25:30 -05:00
# ifdef PQISTORE_DEBUG
2012-04-13 20:30:23 -04:00
pqioutput ( PQL_DEBUG_ALL , pqistorezone , " pqistore::readPkt() " ) ;
2011-01-20 12:25:30 -05:00
# endif
2010-09-18 15:09:11 -04:00
if ( ( ! ( enc_bio - > isactive ( ) ) ) | | ( ! ( enc_bio - > moretoread ( ) ) ) )
{
return 0 ;
}
// enough space to read any packet.
int maxlen = getRsPktMaxSize ( ) ;
void * block = malloc ( maxlen ) ;
// initial read size: basic packet.
int blen = getRsPktBaseSize ( ) ;
int tmplen ;
/* we have the header */
// read the basic block (minimum packet size)
if ( blen ! = ( tmplen = enc_bio - > readdata ( block , blen ) ) )
{
pqioutput ( PQL_WARNING , pqistorezone ,
" pqistore::readPkt() bad read(2) " ) ;
free ( block ) ;
return 0 ;
}
// workout how much more to read.
int extralen = getRsItemSize ( block ) - blen ;
if ( extralen + blen > maxlen )
std : : cerr < < " ***** ERROR: trying to read a packet of length " < < extralen + blen < < " , while the maximum length is " < < maxlen < < std : : endl ;
if ( extralen > 0 )
{
if ( extralen > blen + maxlen )
{
std : : cerr < < " pqistore: ERROR: Inconsistency in packet format (extralen= " < < extralen < < " , maxlen= " < < maxlen < < " ). Wasting the whole file. " < < std : : endl ;
free ( block ) ;
return 0 ;
}
void * extradata = ( void * ) ( ( ( char * ) block ) + blen ) ;
if ( extralen ! = ( tmplen = enc_bio - > readdata ( extradata , extralen ) ) )
{
2012-04-13 20:30:23 -04:00
std : : string out ;
rs_sprintf ( out , " pqistore::readPkt() Error Completing Read (read %d/%d) " , tmplen , extralen ) ;
pqioutput ( PQL_ALERT , pqistorezone , out ) ;
2010-09-18 15:09:11 -04:00
free ( block ) ;
return 0 ;
}
}
// create packet, based on header.
//std::cerr << "Read Data Block -> Incoming Pkt(";
//std::cerr << blen + extralen << ")" << std::endl;
uint32_t readbytes = extralen + blen ;
RsItem * item = rsSerialiser - > deserialise ( block , & readbytes ) ;
free ( block ) ;
if ( item = = NULL )
{
2011-09-14 07:05:17 -04:00
# ifdef PQISTORE_DEBUG
pqioutput ( PQL_ALERT , pqistorezone ,
2010-09-18 15:09:11 -04:00
" pqistore::readPkt() Failed to create Item from store! " ) ;
2011-09-14 07:05:17 -04:00
# endif
2010-09-18 15:09:11 -04:00
return 0 ;
}
item - > PeerId ( mSrcId ) ;
* item_out = item ;
return 1 ;
}