added serialisation/deserialisation and handling of generic tunnel data items

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-GenericTunneling@6295 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2013-04-06 13:58:27 +00:00
parent 6760b35ae6
commit 5e62f6c0c5
4 changed files with 169 additions and 53 deletions

View File

@ -776,6 +776,9 @@ int p3turtle::handleIncoming()
case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult(dynamic_cast<RsTurtleTunnelOkItem *>(item)) ;
break ;
case RS_TURTLE_SUBTYPE_GENERIC_DATA : handleRecvGenericDataItem(dynamic_cast<RsTurtleGenericDataItem *>(item)) ;
break ;
default:
std::cerr << "p3turtle::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ;
}
@ -1076,48 +1079,66 @@ void p3turtle::handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item)
std::string vpid ;
RsTurtleClientService *service ;
// Now lock the router
{
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
std::map<TurtleTunnelId,TurtleTunnel>::iterator it2(_local_tunnels.find(item->tunnelId())) ;
if(it2 == _local_tunnels.end())
{
#ifdef P3TURTLE_DEBUG
std::cerr << "p3turtle: got file CRC32 map with unknown tunnel id " << (void*)item->tunnelId() << std::endl ;
#endif
return ;
}
TurtleTunnel& tunnel(it2->second) ;
#ifdef P3TURTLE_DEBUG
assert(!tunnel.hash.empty()) ;
std::cerr << " This is an endpoint for this file map." << std::endl ;
std::cerr << " Forwarding data to the multiplexer." << std::endl ;
std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ;
#endif
// We should check that there is no backward call to the turtle router!
//
vpid = tunnel.vpid ;
hash = tunnel.hash ;
std::map<TurtleFileHash,TurtleHashInfo>::const_iterator it = _incoming_file_hashes.find(hash) ;
if(it == _incoming_file_hashes.end())
{
std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << " has no attached service! Dropping the item. This is a serious consistency error." << std::endl;
return ;
}
service = it->second.service ;
}
if(!getTunnelServiceInfo(item->tunnelId(),vpid,hash,service))
return ;
service->receiveTurtleData(item,hash,vpid,item->travelingDirection()) ;
}
void p3turtle::handleRecvGenericDataItem(RsTurtleGenericDataItem *item)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "p3Turtle: received Generic Data item:" << std::endl ;
item->print(std::cerr,1) ;
#endif
std::string virtual_peer_id ;
std::string hash ;
RsTurtleClientService *service ;
if(!getTunnelServiceInfo(item->tunnelId(),virtual_peer_id,hash,service))
return ;
service->receiveTurtleData(item->data_bytes,item->data_size,hash,virtual_peer_id,item->travelingDirection()) ;
}
bool p3turtle::getTunnelServiceInfo(TurtleTunnelId tunnel_id,std::string& vpid,std::string& hash,RsTurtleClientService *& service)
{
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
std::map<TurtleTunnelId,TurtleTunnel>::iterator it2(_local_tunnels.find(tunnel_id)) ;
if(it2 == _local_tunnels.end())
{
#ifdef P3TURTLE_DEBUG
std::cerr << "p3turtle: got file CRC32 map with unknown tunnel id " << (void*)item->tunnelId() << std::endl ;
#endif
return false;
}
TurtleTunnel& tunnel(it2->second) ;
#ifdef P3TURTLE_DEBUG
assert(!tunnel.hash.empty()) ;
std::cerr << " This is an endpoint for this file map." << std::endl ;
std::cerr << " Forwarding data to the multiplexer." << std::endl ;
std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ;
#endif
// We should check that there is no backward call to the turtle router!
//
vpid = tunnel.vpid ;
hash = tunnel.hash ;
std::map<TurtleFileHash,TurtleHashInfo>::const_iterator it = _incoming_file_hashes.find(hash) ;
if(it == _incoming_file_hashes.end())
{
std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << " has no attached service! Dropping the item. This is a serious consistency error." << std::endl;
return false;
}
service = it->second.service ;
}
// Send a data request into the correct tunnel for the given file hash
//
void p3turtle::sendTurtleData(const std::string& virtual_peer_id,RsTurtleGenericTunnelItem *item)

View File

@ -352,6 +352,8 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
/// specific routing functions for handling particular packets.
void handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item);
void handleRecvGenericDataItem(RsTurtleGenericDataItem *item);
bool getTunnelServiceInfo(TurtleTunnelId, std::string& virtual_peer_id, std::string& hash, RsTurtleClientService*&) ;
// following functions should go to ftServer
void handleSearchRequest(RsTurtleSearchRequestItem *item);

View File

@ -91,6 +91,17 @@ uint32_t RsTurtleTunnelOkItem::serial_size()
return s ;
}
uint32_t RsTurtleGenericDataItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // data size
s += data_size ; // data
return s ;
}
//
// ---------------------------------- Serialization ----------------------------------//
//
@ -122,18 +133,8 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size)
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : return new RsTurtleSearchResultItem(data,*size) ;
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem(data,*size) ;
case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem(data,*size) ;
case RS_TURTLE_SUBTYPE_GENERIC_DATA : return new RsTurtleGenericDataItem(data,*size) ;
// We need to call some client serialiser from there.
//
// case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(data,*size) ;
// case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,*size) ;
default:
break ;
}
@ -520,6 +521,84 @@ RsTurtleTunnelOkItem::RsTurtleTunnelOkItem(void *data,uint32_t pktsize)
#endif
}
RsTurtleGenericDataItem::RsTurtleGenericDataItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_DATA) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = tunnel ok" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
/* add mandatory parts first */
bool ok = true ;
uint32_t data_size = 0;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt32(data, pktsize, &offset, &data_size);
#ifdef P3TURTLE_DEBUG
std::cerr << " request_id=" << (void*)request_id << ", tunnel_id=" << (void*)tunnel_id << std::endl ;
#endif
data_bytes = malloc(data_size) ;
if(data_bytes != NULL)
{
memcpy(data_bytes,data+offset,data_size) ;
offset += data_size ;
}
else
{
std::cerr << "(EE) RsTurtleGenericDataItem: Error. Cannot allocate data for a size of " << data_size << " bytes." <<std::endl;
offset = 0 ; // generate an error
}
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
UNREFERENCED_LOCAL_VARIABLE(rssize);
#else
if (offset != rssize)
throw std::runtime_error("RsTurtleTunnelOkItem::() error while deserializing.") ;
if (!ok)
throw std::runtime_error("RsTurtleTunnelOkItem::() unknown error while deserializing.") ;
#endif
}
bool RsTurtleGenericDataItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, data_size);
memcpy(data+offset,data_bytes,data_size) ;
offset += data_size ;
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsTurtleTunnelOkItem::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
// -----------------------------------------------------------------------------------//
// ------------------------------------- IO --------------------------------------- //
// -----------------------------------------------------------------------------------//
@ -587,3 +666,13 @@ std::ostream& RsTurtleTunnelOkItem::print(std::ostream& o, uint16_t)
return o ;
}
std::ostream& RsTurtleGenericDataItem::print(std::ostream& o, uint16_t)
{
o << "Generic Data item:" << std::endl ;
o << " Peer id : " << PeerId() << std::endl ;
o << " data size : " << data_size << std::endl ;
o << " data bytes: " << std::hex << (void*)data_bytes << std::dec << std::endl ;
return o ;
}

View File

@ -181,15 +181,17 @@ class RsTurtleGenericTunnelItem: public RsTurtleItem
virtual Direction travelingDirection() const { return direction ; }
virtual void setTravelingDirection(Direction d) { direction = d; }
Direction direction ;
uint32_t tunnel_id ; // id of the tunnel to travel through
Direction direction ; // This does not need to be serialised. It's only used by the client services, optionnally,
// and is set by the turtle router according to which direction the item travels.
uint32_t tunnel_id ; // Id of the tunnel to travel through
};
/***********************************************************************************/
/* Specific Turtle Transfer items */
/***********************************************************************************/
// This item can be used by any service to pass-on data into a tunnel.
// This item can be used by any service to pass-on arbitrary data into a tunnel.
//
class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem
{
@ -197,10 +199,12 @@ class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem
RsTurtleGenericDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);}
RsTurtleGenericDataItem(void *data,uint32_t size) ; // deserialization
virtual ~RsTurtleGenericDataItem() { if(data_bytes != NULL) free(data_bytes) ; }
virtual bool shouldStampTunnel() const { return true ; }
uint32_t data_size ;
void *data ;
void *data_bytes ;
virtual std::ostream& print(std::ostream& o, uint16_t) ;
protected: