added service part and item queues to GXS tunnel service

This commit is contained in:
csoler 2015-11-24 21:57:59 -05:00
parent 19f1a82bd8
commit b552408aab
4 changed files with 307 additions and 172 deletions

View File

@ -32,6 +32,7 @@
#include "util/rsaes.h"
#include "util/rsprint.h"
#include "util/rsmemory.h"
#include <retroshare/rsidentity.h>
#include <retroshare/rsiface.h>
@ -57,9 +58,20 @@ static const uint32_t RS_GXS_TUNNEL_STATUS_CAN_TALK = 0x01 ;
static const uint32_t RS_GXS_TUNNEL_STATUS_TUNNEL_DN = 0x02 ;
static const uint32_t RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED = 0x03 ;
static const uint32_t RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND = 10 ; // re-send every 10 secs.
static const uint32_t GXS_TUNNEL_ENCRYPTION_HMAC_SIZE = SHA_DIGEST_LENGTH ;
static const uint32_t GXS_TUNNEL_ENCRYPTION_IV_SIZE = 8 ;
p3GxsTunnelService::p3GxsTunnelService(RsGixs *pids)
: mGixs(pids), mGxsTunnelMtx("GXS tunnel")
{
mTurtle = NULL ;
// any value is fine here, even 0, since items in different RS sessions will use different AES keys.
global_item_counter = 0;//RSRandom::random_u64() ;
}
void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr)
{
mTurtle = tr ;
@ -68,12 +80,47 @@ void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr)
void p3GxsTunnelService::flush()
{
// Flush pending DH items. This is a higher priority, so we deal with them first.
std::cerr << "p3GxsTunnelService::flush() flushing pending items." << std::endl;
{
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
while(!pendingDHItems.empty())
if(locked_sendClearTunnelData(pendingDHItems.front()) )
pendingDHItems.pop_front() ;
}
// Flush items that could not be sent, probably because of a Mutex protected zone.
//
while(!pendingGxsTunnelItems.empty())
{
sendTurtleData(pendingGxsTunnelItems.front() ) ;
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
while(!pendingGxsTunnelItems.empty())
if(locked_sendEncryptedTunnelData(pendingGxsTunnelItems.front()))
pendingGxsTunnelItems.pop_front() ;
else
std::cerr << "Cannot send encrypted data item to tunnel " << pendingGxsTunnelItems.front()->PeerId() << std::endl;
}
// Look at pending data item, and re-send them if necessary.
{
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
time_t now = time(NULL) ;
for(std::map<uint64_t, GxsTunnelData>::iterator it = pendingGxsTunnelDataItems.begin();it != pendingGxsTunnelDataItems.end();++it)
if(now > RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND + it->second.last_sending_attempt)
{
if(locked_sendEncryptedTunnelData(it->second.data_item))
{
std::cerr << " sending data item #" << std::hex << it->first << std::dec << std::endl;
it->second.last_sending_attempt = now ;
}
else
std::cerr << " Cannot send item " << std::hex << it->first << std::dec << std::endl;
}
}
// TODO: also sweep GXS id map and disable any ID with no virtual peer id in the list.
@ -121,80 +168,108 @@ void p3GxsTunnelService::flush()
}
}
bool p3GxsTunnelService::handleIncomingItem(RsGxsTunnelItem *item)
// In this function the PeerId is the GXS tunnel ID.
void p3GxsTunnelService::handleIncomingItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelItem *item)
{
if(item == NULL)
return false ;
return ;
// We have 3 things to do:
//
// 1 - if it's a data item, send an ACK
// 2 - if it's an ack item, mark the item as properly received, and remove it from the queue
// 3 - if it's a status item, act accordingly.
switch(item->PacketSubType())
{
case RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY: handleRecvDHPublicKey(dynamic_cast<RsGxsTunnelDHPublicKeyItem*>(item)) ; break ;
return true ;
#warning need to implement tunnel data handling here
case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA:
return true ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA: handleRecvTunnelDataItem(tunnel_id,dynamic_cast<RsGxsTunnelDataItem*>(item)) ;
break ;
#warning need to implement tunnel data ACK handling here
case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK:
return true ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK: handleRecvTunnelDataAckItem(tunnel_id,dynamic_cast<RsGxsTunnelDataAckItem*>(item)) ;
break ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: handleRecvStatusItem(dynamic_cast<RsGxsTunnelStatusItem*>(item)) ;
return true ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: handleRecvStatusItem(tunnel_id,dynamic_cast<RsGxsTunnelStatusItem*>(item)) ;
break ;
default:
return false ;
std::cerr << "(EE) impossible situation. DH items should be handled at the service level" << std::endl;
}
return false ;
delete item ;
}
//#warning is this function still used??
//bool p3GxsTunnelService::handleOutgoingItem(RsGxsTunnelItem *item)
//{
// {
// RS_STACK_MUTEX(mGxsTunnelMtx) ;
//
// std::map<RsGxsId,GxsTunnelPeerInfo>::const_iterator it=_gxs_tunnel_contacts.find(RsGxsId(item->PeerId()));
//
// if(it == _gxs_tunnel_contacts.end())
// return false ;
// }
//
//#ifdef CHAT_DEBUG
// std::cerr << "p3GxsTunnelService::handleOutgoingItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
//#endif
// sendTurtleData(item) ;
// return true;
//}
void p3GxsTunnelService::handleRecvStatusItem(RsGxsTunnelStatusItem *cs)
void p3GxsTunnelService::handleRecvTunnelDataAckItem(const RsGxsTunnelId& id,RsGxsTunnelDataAckItem *item)
{
if(cs->flags & RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION)
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
std::cerr << "p3GxsTunnelService::handling RecvTunnelDataAckItem()" << std::endl;
std::cerr << " item counter = " << std::hex << item->unique_item_counter << std::dec << std::endl;
// remove it from the queue.
std::map<uint64_t,GxsTunnelData>::iterator it = pendingGxsTunnelDataItems.find(item->unique_item_counter) ;
if(it == pendingGxsTunnelDataItems.end())
{
RsGxsTunnelId tunnel_id ;
TurtleVirtualPeerId vpid = cs->PeerId() ;
std::cerr << " (EE) item number " << std::hex << item->unique_item_counter << " is unknown. This is unexpected." << std::endl;
return ;
}
delete it->second.data_item ;
pendingGxsTunnelDataItems.erase(it) ;
}
void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelDataItem *item)
{
// imediately send an ACK for this item
RsGxsTunnelDataAckItem *ackitem = new RsGxsTunnelDataAckItem ;
ackitem->unique_item_counter = item->unique_item_counter ;
ackitem->PeerId(item->PeerId());
{
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
pendingGxsTunnelItems.push_back(ackitem) ; // we use the queue that does not need an ACK, in order to avoid an infinite loop ;-)
}
std::map<RsPeerId,GxsTunnelDHInfo>::iterator it = _gxs_tunnel_virtual_peer_ids.find(vpid) ;
// notify the client for the received data
if(it == _gxs_tunnel_virtual_peer_ids.end())
std::cerr << "p3GxsTunnelService::handleRecvTunnelDataItem()" << std::endl;
std::cerr << " data size = " << item->data_size << std::endl;
std::cerr << " service id = " << std::hex << item->service_id << std::dec << std::endl;
std::cerr << " counter id = " << std::hex << item->unique_item_counter << std::dec << std::endl;
RsGxsTunnelClientService *service = NULL ;
{
std::cerr << " (EE) Cannot find hash in gxs_tunnel peer list!!" << std::endl;
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
std::map<uint32_t,RsGxsTunnelClientService *>::const_iterator it = mRegisteredServices.find(item->service_id) ;
if(it == mRegisteredServices.end())
{
std::cerr << " (EE) no registered service with ID " << std::hex << item->service_id << std::dec << ". Rejecting item." << std::endl;
return ;
}
tunnel_id = it->second.tunnel_id ;
service = it->second ;
}
service->receiveData(tunnel_id,item->data,item->data_size) ;
item->data = NULL ; // avoids deletion, since the client has the memory now
item->data_size = 0 ;
}
void p3GxsTunnelService::handleRecvStatusItem(const RsGxsTunnelId& tunnel_id, RsGxsTunnelStatusItem *cs)
{
if(cs->flags & RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION)
markGxsTunnelAsClosed(tunnel_id);
}
// nothing more to do, because the decryption routing will update the last_contact time when decrypting.
if(cs->flags & RS_GXS_TUNNEL_FLAG_KEEP_ALIVE)
std::cerr << "GxsTunnelService::handleRecvGxsTunnelStatusItem(): received keep alive packet for inactive tunnel! peerId=" << cs->PeerId() << std::endl;
std::cerr << "GxsTunnelService::handleRecvGxsTunnelStatusItem(): received keep alive packet for inactive tunnel! peerId=" << cs->PeerId() << " tunnel=" << tunnel_id << std::endl;
}
bool p3GxsTunnelService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/)
@ -408,7 +483,6 @@ void p3GxsTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
// Now try deserialise the decrypted data to make an RsItem out of it.
//
#warning needs proper passing of item to client
RsItem *citem = RsGxsTunnelSerialiser().deserialise(&((uint8_t*)item->data_bytes)[8],&item->data_size-8) ;
if(citem == NULL)
@ -419,11 +493,12 @@ void p3GxsTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
// DH key items are sent even before we know who we speak to, so the virtual peer id is used in this
// case only.
RsGxsTunnelDHPublicKeyItem *dhitem = dynamic_cast<RsGxsTunnelDHPublicKeyItem*>(citem) ;
if(dynamic_cast<RsGxsTunnelDHPublicKeyItem*>(citem) != NULL)
if(dhitem != NULL)
{
citem->PeerId(virtual_peer_id) ;
handleIncomingItem(dynamic_cast<RsGxsTunnelItem*>(citem)) ;
dhitem->PeerId(virtual_peer_id) ;
handleRecvDHPublicKey(dhitem) ;
}
else
std::cerr << "(EE) Deserialiased item has unexpected type." << std::endl;
@ -444,6 +519,7 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
#endif
RsGxsTunnelItem *citem = NULL;
RsGxsTunnelId tunnel_id;
{
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
@ -462,7 +538,7 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
return true ;
}
RsGxsTunnelId tunnel_id = it->second.tunnel_id ;
tunnel_id = it->second.tunnel_id ;
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ;
if(it2 == _gxs_tunnel_contacts.end())
@ -534,7 +610,7 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "(II) Setting peer id to " << citem->PeerId() << std::endl;
#endif
handleIncomingItem(citem) ; // Treats the item, and deletes it
handleIncomingItem(tunnel_id,citem) ; // Treats the item, and deletes it
return true ;
}
@ -792,7 +868,7 @@ bool p3GxsTunnelService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_
dhitem->print(std::cerr, 2) ;
std::cerr << std::endl;
#endif
pendingGxsTunnelItems.push_back(dhitem) ; // sent off-mutex to avoid deadlocking.
pendingDHItems.push_back(dhitem) ; // sent off-mutex to avoid deadlocking.
return true ;
}
@ -841,14 +917,12 @@ bool p3GxsTunnelService::locked_initDHSessionKey(DH *& dh)
// Encrypts and sends the item.
void p3GxsTunnelService::sendTurtleData(RsGxsTunnelItem *item)
bool p3GxsTunnelService::locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item)
{
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "GxsTunnelService::sendTurtleData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl;
std::cerr << "GxsTunnelService::sendClearTunnelData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl;
#endif
if(dynamic_cast<RsGxsTunnelDHPublicKeyItem*>(item) != NULL)
{
// make a TurtleGenericData item out of it, and send it in clear.
//
RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ;
@ -865,53 +939,46 @@ void p3GxsTunnelService::sendTurtleData(RsGxsTunnelItem *item)
{
std::cerr << "(EE) Could not serialise item!!!" << std::endl;
delete gitem ;
delete item ;
return ;
return false;
}
#ifdef DEBUG_GXS_TUNNEL
std::cerr << " GxsTunnelService::sendTurtleData(): Sending clear data to virtual peer: " << item->PeerId() << std::endl;
std::cerr << " GxsTunnelService::sendClearTunnelData(): Sending clear data to virtual peer: " << item->PeerId() << std::endl;
std::cerr << " gitem->data_size = " << gitem->data_size << std::endl;
std::cerr << " data = " << RsUtil::BinToHex((char*)gitem->data_bytes,gitem->data_size) ;
std::cerr << std::endl;
#endif
mTurtle->sendTurtleData(item->PeerId(),gitem) ;
}
else
{
return true ;
}
// Sends this item using secured/authenticated method, thx to the establshed cryptographic channel.
bool p3GxsTunnelService::locked_sendEncryptedTunnelData(RsGxsTunnelItem *item)
{
uint32_t rssize = item->serial_size();
uint8_t *buff = (uint8_t*)malloc(rssize) ;
RsTemporaryMemory buff(rssize) ;
if(!item->serialise(buff,rssize))
{
std::cerr << "(EE) GxsTunnelService::sendTurtleData(): Could not serialise item!" << std::endl;
free(buff) ;
delete item ;
return ;
std::cerr << "(EE) GxsTunnelService::sendEncryptedTunnelData(): Could not serialise item!" << std::endl;
return false;
}
sendEncryptedTurtleData(buff,rssize,item->PeerId()) ;
free(buff) ;
}
delete item ;
}
void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rssize,const TurtleVirtualPeerId& vpid)
{
uint8_t aes_key[GXS_TUNNEL_AES_KEY_SIZE] ;
uint64_t IV = 0;
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "Sending encrypted data to tunnel wuth vpid " << vpid << std::endl;
std::cerr << "Sending encrypted data to tunnel wuth vpid " << item->PeerId() << std::endl;
#endif
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
TurtleVirtualPeerId vpid = item->PeerId() ;
std::map<TurtleVirtualPeerId,GxsTunnelDHInfo>::const_iterator it2 = _gxs_tunnel_virtual_peer_ids.find(vpid) ;
if(it2 == _gxs_tunnel_virtual_peer_ids.end())
{
std::cerr << "(EE) no virtual peer " << vpid << ". Something's wrong!" << std::endl;
return ;
return false;
}
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it = _gxs_tunnel_contacts.find(it2->second.tunnel_id) ;
@ -919,12 +986,12 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
if(it == _gxs_tunnel_contacts.end())
{
std::cerr << "(EE) Cannot find contact key info for virtual peer id " << vpid << ". Cannot send message!" << std::endl;
return ;
return false;
}
if(it->second.status != RS_GXS_TUNNEL_STATUS_CAN_TALK)
{
std::cerr << "(EE) Cannot talk to vpid " << vpid << ". Tunnel status is: " << it->second.status << std::endl;
return ;
return false;
}
memcpy(aes_key,it->second.aes_key,GXS_TUNNEL_AES_KEY_SIZE) ;
@ -933,19 +1000,19 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
while(IV == 0) IV = RSRandom::random_u64() ; // make a random 8 bytes IV, that is not 0
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "GxsTunnelService::sendTurtleData(): tunnel found. Encrypting data." << std::endl;
std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): tunnel found. Encrypting data." << std::endl;
#endif
// Now encrypt this data using AES.
//
uint8_t *encrypted_data = new uint8_t[RsAES::get_buffer_size(rssize)];
uint32_t encrypted_size = RsAES::get_buffer_size(rssize);
RsTemporaryMemory encrypted_data(encrypted_size) ;
if(!RsAES::aes_crypt_8_16(buff,rssize,aes_key,(uint8_t*)&IV,encrypted_data,encrypted_size))
{
std::cerr << "(EE) packet encryption failed." << std::endl;
delete[] encrypted_data ;
return ;
return false;
}
// make a TurtleGenericData item out of it:
@ -962,21 +1029,21 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
memcpy(& (((uint8_t*)gitem->data_bytes)[GXS_TUNNEL_ENCRYPTION_HMAC_SIZE+GXS_TUNNEL_ENCRYPTION_IV_SIZE]),encrypted_data,encrypted_size) ;
delete[] encrypted_data ;
#ifdef DEBUG_GXS_TUNNEL
std::cerr << " Using IV: " << std::hex << IV << std::dec << std::endl;
std::cerr << " Using Key: " << RsUtil::BinToHex((char*)aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; std::cerr << std::endl;
std::cerr << " hmac: " << RsUtil::BinToHex((char*)gitem->data_bytes,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) ;
#endif
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "GxsTunnelService::sendTurtleData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl;
std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl;
std::cerr << " gitem->data_size = " << gitem->data_size << std::endl;
std::cerr << " serialised data = " << RsUtil::BinToHex((char*)gitem->data_bytes,gitem->data_size) ;
std::cerr << std::endl;
#endif
mTurtle->sendTurtleData(virtual_peer_id,gitem) ;
return true ;
}
bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, RsGxsTunnelId &tunnel_id, uint32_t& error_code)
@ -1009,6 +1076,55 @@ bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id, const Rs
return true ;
}
bool p3GxsTunnelService::sendData(const RsGxsTunnelId &tunnel_id, uint32_t service_id, const uint8_t *data, uint32_t size)
{
// make sure that the tunnel ID is registered.
std::cerr << "p3GxsTunnelService::sendData()" << std::endl;
std::cerr << " tunnel id : " << tunnel_id << std::endl;
std::cerr << " data size : " << size << std::endl;
std::cerr << " service id: " << std::hex << service_id << std::dec << std::endl;
RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ;
if(it == _gxs_tunnel_contacts.end())
{
std::cerr << " (EE) no tunnel known with this ID. Sorry!" << std::endl;
return false ;
}
// make sure the service is registered.
if(mRegisteredServices.find(service_id) == mRegisteredServices.end())
{
std::cerr << " (EE) no service registered with this ID. Please call rsGxsTunnel->registerClientService() at some point." << std::endl;
return false ;
}
std::cerr << " verifications fine! Storing in out queue with:" << std::endl;
RsGxsTunnelDataItem *item = new RsGxsTunnelDataItem ;
item->unique_item_counter = global_item_counter++; // this allows to make the item unique
item->flags = 0; // not used yet.
item->service_id = service_id;
item->data_size = size; // encrypted data size
item->data = (uint8_t*)malloc(size); // encrypted data
memcpy(item->data,data,size) ;
GxsTunnelData& tdata( pendingGxsTunnelDataItems[item->unique_item_counter] ) ;
tdata.data_item = item ;
tdata.last_sending_attempt = 0 ; // never sent until now
std::cerr << " counter id : " << std::hex << item->unique_item_counter << std::dec << std::endl;
return true ;
}
void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,RsGxsTunnelId& tunnel_id)
{
// compute a random hash for that pair, and init the DH session for it so that we can recognise it when we get the virtual peer for it.
@ -1158,7 +1274,7 @@ bool p3GxsTunnelService::closeExistingTunnel(const RsGxsTunnelId& tunnel_id)
cs->flags = RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION;
cs->PeerId(vpid) ;
sendTurtleData(cs) ; // that needs to be done off-mutex and before we close the tunnel.
locked_sendEncryptedTunnelData(cs) ; // that needs to be done off-mutex and before we close the tunnel also ignoring failure.
#ifdef DEBUG_GXS_TUNNEL
std::cerr << " This is client side. Stopping tunnel manageement for tunnel_id " << tunnel_id << std::endl;

View File

@ -116,24 +116,23 @@ static const uint32_t GXS_TUNNEL_AES_KEY_SIZE = 16 ;
class p3GxsTunnelService: public RsGxsTunnelService, public RsTurtleClientService
{
public:
p3GxsTunnelService(RsGixs *pids)
: mGixs(pids), mGxsTunnelMtx("GXS tunnel")
{
mTurtle = NULL ;
}
p3GxsTunnelService(RsGixs *pids) ;
virtual void connectToTurtleRouter(p3turtle *) ;
// Creates the invite if the public key of the distant peer is available.
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
//
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t& error_code) ;
virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id) ;
virtual bool getTunnelStatus(const RsGxsTunnelId& tunnel_id,uint32_t &status);
virtual bool sendData(const RsGxsTunnelId& tunnel_id,uint32_t service_id,const uint8_t *data,uint32_t size) ;
virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) ;
private:
void flush() ;
virtual bool handleIncomingItem(RsGxsTunnelItem *) ;
virtual void handleIncomingItem(const RsGxsTunnelId &tunnel_id, RsGxsTunnelItem *) ;
class GxsTunnelPeerInfo
{
@ -170,6 +169,12 @@ private:
TurtleFileHash hash ;
};
struct GxsTunnelData
{
RsGxsTunnelDataItem *data_item ;
time_t last_sending_attempt ;
};
// This maps contains the current peers to talk to with distant chat.
//
std::map<RsGxsTunnelId,GxsTunnelPeerInfo> _gxs_tunnel_contacts ; // current peers we can talk to
@ -178,7 +183,9 @@ private:
// List of items to be sent asap. Used to store items that we cannot pass directly to
// sendTurtleData(), because of Mutex protection.
std::list<RsGxsTunnelItem*> pendingGxsTunnelItems ;
std::map<uint64_t,GxsTunnelData> pendingGxsTunnelDataItems ; // items that need provable transport and encryption
std::list<RsGxsTunnelItem*> pendingGxsTunnelItems ; // items that do not need provable transport, yet need encryption
std::list<RsGxsTunnelDHPublicKeyItem*> pendingDHItems ;
// Overloaded from RsTurtleClientService
@ -209,12 +216,15 @@ private:
// item handling
void handleRecvStatusItem(RsGxsTunnelStatusItem *item) ;
void handleRecvStatusItem(const RsGxsTunnelId& id,RsGxsTunnelStatusItem *item) ;
void handleRecvTunnelDataItem(const RsGxsTunnelId& id,RsGxsTunnelDataItem *item) ;
void handleRecvTunnelDataAckItem(const RsGxsTunnelId &id, RsGxsTunnelDataAckItem *item);
// Comunication with Turtle service
void sendTurtleData(RsGxsTunnelItem *) ;
void sendEncryptedTurtleData(const uint8_t *buff, uint32_t rssize, const TurtleVirtualPeerId &vpid) ;
bool locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) ;
bool locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item); // this limits the usage to DH items. Others should be encrypted!
bool handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) ;
static TurtleFileHash hashFromVirtualPeerId(const DistantChatPeerId& peerId) ; // converts IDs so that we can talk to RsPeerId from outside
@ -224,4 +234,9 @@ private:
p3turtle *mTurtle ;
RsGixs *mGixs ;
RsMutex mGxsTunnelMtx ;
uint64_t global_item_counter ;
std::map<uint32_t,RsGxsTunnelClientService*> mRegisteredServices ;
};

View File

@ -61,33 +61,32 @@ class RsGxsTunnelItem: public RsItem
virtual uint32_t serial_size() = 0 ; // deserialise is handled using a constructor
};
// /*!
// * For sending distant communication data. The item is not encrypted after being serialised, but the data it.
// * The MAC is computed over encrypted data using the PFS key. All other items (except DH keys) are serialised, encrypted, and
// * sent as data in a RsGxsTunnelDataItem.
// *
// * @see p3GxsTunnelService
// */
// class RsGxsTunnelDataItem: public RsGxsTunnelItem
// {
// public:
// RsGxsTunnelDataItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA) {}
// RsGxsTunnelDataItem(uint8_t subtype) :RsGxsTunnelItem(subtype) {}
//
// virtual ~RsGxsTunnelDataItem() {}
// virtual void clear() {}
// virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
//
// virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
// virtual uint32_t serial_size() ; // deserialise is handled using a constructor
//
// uint32_t sendTime;
// uint32_t flags; // mainly NEEDS_HACK?
// unsigned char *data ; // encrypted data
// uint32_t data_size ; // encrypted data size
// unsigned char IV[IV_LENGTH] ; // IV for the encrypted data
// unsigned char encrypted_data_mac[SHA_DIGEST_LENGTH] ; // mac of the encrypted data, in order to avoid
// };
/*!
* For sending distant communication data. The item is not encrypted after being serialised, but the data it.
* The MAC is computed over encrypted data using the PFS key. All other items (except DH keys) are serialised, encrypted, and
* sent as data in a RsGxsTunnelDataItem.
*
* @see p3GxsTunnelService
*/
class RsGxsTunnelDataItem: public RsGxsTunnelItem
{
public:
RsGxsTunnelDataItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA) {}
RsGxsTunnelDataItem(uint8_t subtype) :RsGxsTunnelItem(subtype) {}
virtual ~RsGxsTunnelDataItem() {}
virtual void clear() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
uint64_t unique_item_counter; // this allows to make the item unique
uint32_t flags; // mainly NEEDS_HACK?
uint32_t service_id ;
uint32_t data_size ; // encrypted data size
unsigned char *data ; // encrypted data
};
// Used to send status of connection. This can be closing orders, flushing orders, etc.
// These items are always sent encrypted.
@ -121,7 +120,7 @@ class RsGxsTunnelDataAckItem: public RsGxsTunnelItem
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
Sha1CheckSum data_hash ;
uint64_t unique_item_counter ; // unique identifier for that item
};

View File

@ -49,7 +49,7 @@ public:
// Data obtained from the corresponding GXS id. The memory ownership is transferred to the client, which
// is responsible to free it using free() once used.
virtual void receiveData(const RsGxsTunnelId& id,const RsGxsId& from_id,unsigned char *data,uint32_t data_size) =0;
virtual void receiveData(const RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) =0;
};
class GxsTunnelInfo
@ -84,6 +84,11 @@ public:
// Communication to other services. //
//===================================================//
// Register a new client service. The service ID needs to be unique, and it's the coder's resonsibility to use an ID that is not used elsewhere
// for the same purpose.
virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) =0;
// Asks for a tunnel. The service will request it to turtle router, and exchange a AES key using DH.
// When the tunnel is secured, the client---here supplied as argument---will be notified. He can
// then send data into the tunnel. The same tunnel may be used by different clients.
@ -91,9 +96,9 @@ public:
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t& error_code) =0 ;
// Data is sent through the established tunnel, possibly multiple times, until reception is acknowledged. If the tunnel does not exist, the item is rejected and
// an error is issued. In any case, the memory ownership of the data is transferred to the tunnel service, so the client should not use it afterwards.
// an error is issued. In any case, the memory ownership of the data is *not* transferred to the tunnel service, so the client should delete it afterwards, if needed.
virtual bool sendData(RsGxsTunnelId tunnel_id, uint32_t client_service_id, const uint8_t *data, uint32_t data_size) =0;
virtual bool sendData(const RsGxsTunnelId tunnel_id, uint32_t client_service_id, const uint8_t *data, uint32_t data_size) =0;
// Removes any established tunnel to this GXS id. This makes the tunnel refuse further data, but the tunnel will be however kept alive
// until all pending data is flushed. All clients attached to the tunnel will be notified that the tunnel gets closed.