mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-18 20:34:26 -05:00
Implemented turtle tunneling. Not debugged yet 8-).
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1127 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
2f7fb3690f
commit
e2ea2ec75b
@ -34,6 +34,9 @@
|
||||
#include "pqi/p3connmgr.h"
|
||||
#include "pqi/pqinotify.h"
|
||||
|
||||
#include "serialiser/rstlvbase.h"
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
|
||||
#include "p3turtle.h"
|
||||
|
||||
#include <iostream>
|
||||
@ -50,8 +53,6 @@
|
||||
|
||||
/* TURTLE FLAGS */
|
||||
|
||||
#define P3TURTLE_DEBUG 1
|
||||
|
||||
p3turtle::p3turtle(p3ConnectMgr *cm) :p3Service(RS_SERVICE_TYPE_TURTLE), mConnMgr(cm)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
@ -63,7 +64,6 @@ p3turtle::p3turtle(p3ConnectMgr *cm) :p3Service(RS_SERVICE_TYPE_TURTLE), mConnMg
|
||||
int p3turtle::tick()
|
||||
{
|
||||
handleIncoming(); // handle incoming packets
|
||||
// handleOutgoing(); // handle outgoing packets
|
||||
|
||||
// Clean every 10 sec.
|
||||
time_t now = time(NULL) ;
|
||||
@ -81,61 +81,47 @@ void p3turtle::autoWash()
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Calling autowash." << std::endl ;
|
||||
#endif
|
||||
|
||||
// look for tunnels and stored temportary info that have not been used for a while.
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Helper functions ------------------------------ //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
uint32_t p3turtle::generateRandomRequestId()
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
return rand() ;
|
||||
}
|
||||
|
||||
TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match)
|
||||
uint32_t p3turtle::generatePersonalFilePrint(const TurtleFileHash& hash)
|
||||
{
|
||||
// generate a new search id.
|
||||
|
||||
TurtleRequestId id = generateRandomRequestId() ;
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
// Form a request packet that simulates a request from us.
|
||||
//
|
||||
RsTurtleSearchRequestItem *item = new RsTurtleSearchRequestItem ;
|
||||
// whatever cooking from the file hash and OwnId that cannot be recovered.
|
||||
// The only important thing is that the saem hash produces the same tunnel
|
||||
// id.
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "performing search. OwnId = " << mConnMgr->getOwnId() << std::endl ;
|
||||
#endif
|
||||
while(mConnMgr->getOwnId() == "")
|
||||
std::string buff(hash + mConnMgr->getOwnId()) ;
|
||||
uint32_t res = 0 ;
|
||||
uint32_t decal = 0 ;
|
||||
|
||||
for(uint i=0;i<buff.length();++i)
|
||||
{
|
||||
std::cerr << "... waitting for connect manager to form own id." << std::endl ;
|
||||
#ifdef WIN32
|
||||
Sleep(1000) ;
|
||||
#else
|
||||
sleep(1) ;
|
||||
#endif
|
||||
res += 7*buff[i] + decal ;
|
||||
decal = decal*44497+15641+(res%86243) ;
|
||||
}
|
||||
|
||||
item->PeerId(mConnMgr->getOwnId()) ;
|
||||
item->match_string = string_to_match ;
|
||||
item->request_id = id ;
|
||||
item->depth = 0 ;
|
||||
|
||||
// send it
|
||||
|
||||
handleSearchRequest(item) ;
|
||||
|
||||
delete item ;
|
||||
|
||||
return id ;
|
||||
return res ;
|
||||
}
|
||||
|
||||
void p3turtle::turtleDownload(const std::string& file_hash)
|
||||
{
|
||||
pqiNotify *notify = getPqiNotify();
|
||||
|
||||
if (notify)
|
||||
notify->AddSysMessage(0, RS_SYS_WARNING, std::string("Unimplemented"),std::string("turtle download is not yet implemented. Sorry"));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Global routing. -------------------------------- //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
int p3turtle::handleIncoming()
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
@ -160,6 +146,12 @@ int p3turtle::handleIncoming()
|
||||
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult(dynamic_cast<RsTurtleSearchResultItem *>(item)) ;
|
||||
break ;
|
||||
|
||||
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest(dynamic_cast<RsTurtleOpenTunnelItem *>(item)) ;
|
||||
break ;
|
||||
|
||||
case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult(dynamic_cast<RsTurtleTunnelOkItem *>(item)) ;
|
||||
break ;
|
||||
|
||||
// Here will also come handling of file transfer requests, tunnel digging/closing, etc.
|
||||
default:
|
||||
std::cerr << "p3turtle::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ;
|
||||
@ -170,6 +162,10 @@ int p3turtle::handleIncoming()
|
||||
return nhandled;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Search handling. ------------------------------- //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
@ -183,7 +179,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
||||
// If the item contains an already handled search request, give up. This
|
||||
// happens when the same search request gets relayed by different peers
|
||||
//
|
||||
if(requests_origins.find(item->request_id) != requests_origins.end())
|
||||
if(_search_requests_origins.find(item->request_id) != _search_requests_origins.end())
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " This is a bouncing request. Ignoring and deleting it." << std::endl ;
|
||||
@ -194,7 +190,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
||||
// This is a new request. Let's add it to the request map, and forward it to
|
||||
// open peers.
|
||||
|
||||
requests_origins[item->request_id] = item->PeerId() ;
|
||||
_search_requests_origins[item->request_id] = item->PeerId() ;
|
||||
|
||||
// If it's not for us, perform a local search. If something found, forward the search result back.
|
||||
|
||||
@ -287,12 +283,12 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
// Find who actually sent the corresponding request.
|
||||
//
|
||||
std::map<TurtleRequestId,TurtlePeerId>::const_iterator it = requests_origins.find(item->request_id) ;
|
||||
std::map<TurtleRequestId,TurtlePeerId>::const_iterator it = _search_requests_origins.find(item->request_id) ;
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Received search result:" << std::endl ;
|
||||
item->print(std::cerr,0) ;
|
||||
#endif
|
||||
if(it == requests_origins.end())
|
||||
if(it == _search_requests_origins.end())
|
||||
{
|
||||
// This is an error: how could we receive a search result corresponding to a search item we
|
||||
// have forwarded but that it not in the list ??
|
||||
@ -323,6 +319,10 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// ------------------------------------- IO --------------------------------------- //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
std::ostream& RsTurtleSearchRequestItem::print(std::ostream& o, uint16_t)
|
||||
{
|
||||
o << "Search request:" << std::endl ;
|
||||
@ -349,17 +349,225 @@ std::ostream& RsTurtleSearchResultItem::print(std::ostream& o, uint16_t)
|
||||
return o ;
|
||||
}
|
||||
|
||||
void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item)
|
||||
std::ostream& RsTurtleOpenTunnelItem::print(std::ostream& o, uint16_t)
|
||||
{
|
||||
o << "Open Tunnel:" << std::endl ;
|
||||
|
||||
o << " Peer id : " << PeerId() << std::endl ;
|
||||
o << " Partial tId: " << (void *)partial_tunnel_id << std::endl ;
|
||||
o << " Req. Id : " << (void *)request_id << std::endl ;
|
||||
o << " Depth : " << depth << std::endl ;
|
||||
o << " Hash : " << file_hash << std::endl ;
|
||||
|
||||
return o ;
|
||||
}
|
||||
|
||||
std::ostream& RsTurtleTunnelOkItem::print(std::ostream& o, uint16_t)
|
||||
{
|
||||
o << "Tunnel Ok:" << std::endl ;
|
||||
|
||||
o << " Peer id : " << PeerId() << std::endl ;
|
||||
o << " tunnel id : " << (void*)tunnel_id << std::endl ;
|
||||
o << " Req. Id : " << (void *)request_id << std::endl ;
|
||||
|
||||
return o ;
|
||||
}
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Search handling. ------------------------------- //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
|
||||
void p3turtle::diggTunnel(const TurtleFileHash& hash)
|
||||
{
|
||||
// just cout for now, but it should be notified to the gui
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Returning result for search request " << item->request_id << " upwards." << std::endl ;
|
||||
std::cerr << "performing tunnel request. OwnId = " << mConnMgr->getOwnId() << std::endl ;
|
||||
#endif
|
||||
while(mConnMgr->getOwnId() == "")
|
||||
{
|
||||
std::cerr << "... waitting for connect manager to form own id." << std::endl ;
|
||||
#ifdef WIN32
|
||||
Sleep(1000) ;
|
||||
#else
|
||||
sleep(1) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
TurtleRequestId id = generateRandomRequestId() ;
|
||||
|
||||
// Form a tunnel request packet that simulates a request from us.
|
||||
//
|
||||
RsTurtleOpenTunnelItem *item = new RsTurtleOpenTunnelItem ;
|
||||
|
||||
item->PeerId(mConnMgr->getOwnId()) ;
|
||||
item->file_hash = hash ;
|
||||
item->request_id = id ;
|
||||
item->partial_tunnel_id = generatePersonalFilePrint(hash) ;
|
||||
item->depth = 0 ;
|
||||
|
||||
// send it
|
||||
|
||||
handleTunnelRequest(item) ;
|
||||
|
||||
delete item ;
|
||||
}
|
||||
|
||||
void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Received tunnel request from peer " << item->PeerId() << ": " << std::endl ;
|
||||
item->print(std::cerr,0) ;
|
||||
#endif
|
||||
// If the item contains an already handled tunnel request, give up. This
|
||||
// happens when the same tunnel request gets relayed by different peers
|
||||
//
|
||||
if(_tunnel_requests_origins.find(item->request_id) != _tunnel_requests_origins.end())
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " This is a bouncing request. Ignoring and deleting item." << std::endl ;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
|
||||
// This is a new request. Let's add it to the request map, and forward it to
|
||||
// open peers.
|
||||
|
||||
_tunnel_requests_origins[item->request_id] = item->PeerId() ;
|
||||
|
||||
// If it's not for us, perform a local search. If something found, forward the search result back.
|
||||
|
||||
if(item->PeerId() != mConnMgr->getOwnId())
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Request not from us. Performing local search" << std::endl ;
|
||||
#endif
|
||||
if((_sharing_strategy != SHARE_FRIENDS_ONLY || item->depth < 2) && performLocalHashSearch(item->file_hash))
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Local hash found. Sending tunnel ok to origin (" << item->PeerId() << ")." << std::endl ;
|
||||
#endif
|
||||
// Send back tunnel ok to the same guy
|
||||
//
|
||||
RsTurtleTunnelOkItem *res_item = new RsTurtleTunnelOkItem ;
|
||||
|
||||
res_item->request_id = item->request_id ;
|
||||
res_item->tunnel_id = item->partial_tunnel_id ^ generatePersonalFilePrint(item->file_hash) ;
|
||||
res_item->PeerId(item->PeerId()) ;
|
||||
|
||||
sendItem(res_item) ;
|
||||
|
||||
// Note in the tunnels list that we have an ending tunnel here.
|
||||
TurtleTunnel tt ;
|
||||
tt.local_src = item->PeerId() ;
|
||||
tt.local_dst = mConnMgr->getOwnId() ; // this means us
|
||||
tt.time_stamp = time(NULL) ;
|
||||
|
||||
_local_tunnels[res_item->tunnel_id] = tt ;
|
||||
|
||||
// We return straight, because when something is found, there's no need to digg a tunnel further.
|
||||
return ;
|
||||
}
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
else
|
||||
std::cerr << " No hash found locally, or local file not allowed for distant peers. Forwarding. " << std::endl ;
|
||||
#endif
|
||||
}
|
||||
|
||||
// If search depth not too large, also forward this search request to all other peers.
|
||||
//
|
||||
if(item->depth < TURTLE_MAX_SEARCH_DEPTH)
|
||||
{
|
||||
std::list<std::string> onlineIds ;
|
||||
mConnMgr->getOnlineList(onlineIds);
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Forwarding tunnel request: Looking for online peers" << std::endl ;
|
||||
#endif
|
||||
|
||||
rsicontrol->getNotify().notifyTurtleSearchResult(item->request_id,item->result) ;
|
||||
for(std::list<std::string>::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it)
|
||||
if(*it != item->PeerId())
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Forwarding request to peer = " << *it << std::endl ;
|
||||
#endif
|
||||
// Copy current item and modify it.
|
||||
RsTurtleOpenTunnelItem *fwd_item = new RsTurtleOpenTunnelItem(*item) ;
|
||||
|
||||
++(fwd_item->depth) ; // increase tunnel depth
|
||||
fwd_item->PeerId(*it) ;
|
||||
|
||||
sendItem(fwd_item) ;
|
||||
}
|
||||
}
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
else
|
||||
std::cout << " Dropping this item, as tunnel depth is " << item->depth << std::endl ;
|
||||
#endif
|
||||
}
|
||||
|
||||
void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
// Find who actually sent the corresponding turtle tunnel request.
|
||||
//
|
||||
std::map<TurtleTunnelRequestId,TurtlePeerId>::const_iterator it = _tunnel_requests_origins.find(item->request_id) ;
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Received tunnel result:" << std::endl ;
|
||||
item->print(std::cerr,0) ;
|
||||
#endif
|
||||
if(it == _tunnel_requests_origins.end())
|
||||
{
|
||||
// This is an error: how could we receive a tunnel result corresponding to a tunnel item we
|
||||
// have forwarded but that it not in the list ??
|
||||
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": tunnel result has no peer direction!" << std::endl ;
|
||||
delete item ;
|
||||
return ;
|
||||
}
|
||||
|
||||
// store tunnel info.
|
||||
if(_local_tunnels.find(item->tunnel_id) != _local_tunnels.end())
|
||||
std::cerr << "Tunnel already there. This is an error !!" << std::endl ;
|
||||
|
||||
TurtleTunnel& tunnel(_local_tunnels[item->tunnel_id]) ;
|
||||
|
||||
tunnel.local_src = it->second ;
|
||||
tunnel.local_dst = item->PeerId() ;
|
||||
tunnel.time_stamp = time(NULL) ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " storing tunnel info. src=" << tunnel.local_src << ", dst=" << tunnel.local_dst << ", id=" << item->tunnel_id << std::endl ;
|
||||
#endif
|
||||
|
||||
// Is this result's target actually ours ?
|
||||
|
||||
if(it->second == mConnMgr->getOwnId())
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Tunnel starting point. Storing id=" << item->tunnel_id << " for hash (unknown) and tunnel request id " << it->second << std::endl;
|
||||
#endif
|
||||
// Tunnel is ending here. Add it to the list of tunnels for the given hash.
|
||||
|
||||
// a connexion between the file hash and the tunnel id is missing at this point.
|
||||
//_file_hashes_tunnels.insert(item->tunnel_id) ;
|
||||
}
|
||||
else
|
||||
{ // Nope, forward it back.
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Forwarding result back to " << it->second << std::endl;
|
||||
#endif
|
||||
RsTurtleTunnelOkItem *fwd_item = new RsTurtleTunnelOkItem(*item) ; // copy the item
|
||||
fwd_item->PeerId(it->second) ;
|
||||
|
||||
sendItem(fwd_item) ;
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// ------------------------------ Tunnel maintenance. ------------------------------ //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
|
||||
/************* from pqiMonitor *******************/
|
||||
void p3turtle::statusChange(const std::list<pqipeer> &plist)
|
||||
{
|
||||
@ -383,10 +591,120 @@ void p3turtle::statusChange(const std::list<pqipeer> &plist)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// ------------------------------ IO with libretroshare ----------------------------//
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
void p3turtle::performLocalSearch(const std::string& s,std::list<TurtleFileInfo>& result)
|
||||
{
|
||||
/* call to core */
|
||||
std::list<FileDetail> initialResults;
|
||||
std::list<std::string> words ;
|
||||
|
||||
#include "serialiser/rstlvbase.h"
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
// to do: split search string into words.
|
||||
words.push_back(s) ;
|
||||
|
||||
// now, search!
|
||||
rsFiles->SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL);
|
||||
|
||||
result.clear() ;
|
||||
|
||||
for(std::list<FileDetail>::const_iterator it(initialResults.begin());it!=initialResults.end();++it)
|
||||
{
|
||||
TurtleFileInfo i ;
|
||||
i.hash = it->hash ;
|
||||
i.size = it->size ;
|
||||
i.name = it->name ;
|
||||
|
||||
result.push_back(i) ;
|
||||
}
|
||||
}
|
||||
|
||||
TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match)
|
||||
{
|
||||
// generate a new search id.
|
||||
|
||||
TurtleRequestId id = generateRandomRequestId() ;
|
||||
|
||||
// Form a request packet that simulates a request from us.
|
||||
//
|
||||
RsTurtleSearchRequestItem *item = new RsTurtleSearchRequestItem ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "performing search. OwnId = " << mConnMgr->getOwnId() << std::endl ;
|
||||
#endif
|
||||
while(mConnMgr->getOwnId() == "")
|
||||
{
|
||||
std::cerr << "... waitting for connect manager to form own id." << std::endl ;
|
||||
#ifdef WIN32
|
||||
Sleep(1000) ;
|
||||
#else
|
||||
sleep(1) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
item->PeerId(mConnMgr->getOwnId()) ;
|
||||
item->match_string = string_to_match ;
|
||||
item->request_id = id ;
|
||||
item->depth = 0 ;
|
||||
|
||||
// send it
|
||||
|
||||
handleSearchRequest(item) ;
|
||||
|
||||
delete item ;
|
||||
|
||||
return id ;
|
||||
}
|
||||
|
||||
|
||||
void p3turtle::turtleDownload(const std::string& file_hash)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
if(_file_hashes_tunnels.find(file_hash) != _file_hashes_tunnels.end()) // download already asked.
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "p3turtle: File hash " << file_hash << " already in pool. Returning." << std::endl ;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
|
||||
// No tunnels at start, but this triggers digging new tunnels.
|
||||
//
|
||||
_file_hashes_tunnels[file_hash] = std::list<TurtleTunnelId>() ;
|
||||
|
||||
// also should send associated request to the file transfer module.
|
||||
|
||||
// todo!
|
||||
}
|
||||
|
||||
void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item)
|
||||
{
|
||||
// just cout for now, but it should be notified to the gui
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Returning result for search request " << item->request_id << " upwards." << std::endl ;
|
||||
#endif
|
||||
|
||||
rsicontrol->getNotify().notifyTurtleSearchResult(item->request_id,item->result) ;
|
||||
}
|
||||
|
||||
bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash)
|
||||
{
|
||||
FileInfo info ;
|
||||
|
||||
return rsFiles->FileDetails(hash, RS_FILE_HINTS_LOCAL, info);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Serialization. --------------------------------- //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
|
||||
//
|
||||
// ---------------------------------- Packet sizes -----------------------------------//
|
||||
//
|
||||
uint32_t RsTurtleSearchRequestItem::serial_size()
|
||||
{
|
||||
uint32_t s = 0 ;
|
||||
@ -418,6 +736,32 @@ uint32_t RsTurtleSearchResultItem::serial_size()
|
||||
return s ;
|
||||
}
|
||||
|
||||
uint32_t RsTurtleOpenTunnelItem::serial_size()
|
||||
{
|
||||
uint32_t s = 0 ;
|
||||
|
||||
s += 8 ; // header
|
||||
s += GetTlvStringSize(file_hash) ; // file hash
|
||||
s += 4 ; // tunnel request id
|
||||
s += 4 ; // partial tunnel id
|
||||
s += 2 ; // depth
|
||||
|
||||
return s ;
|
||||
}
|
||||
|
||||
uint32_t RsTurtleTunnelOkItem::serial_size()
|
||||
{
|
||||
uint32_t s = 0 ;
|
||||
|
||||
s += 8 ; // header
|
||||
s += 4 ; // tunnel id
|
||||
s += 4 ; // tunnel request id
|
||||
|
||||
return s ;
|
||||
}
|
||||
//
|
||||
// ---------------------------------- Serialization ----------------------------------//
|
||||
//
|
||||
RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size)
|
||||
{
|
||||
// look what we have...
|
||||
@ -549,7 +893,6 @@ bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize)
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize)
|
||||
: RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT)
|
||||
{
|
||||
@ -589,29 +932,122 @@ RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize)
|
||||
throw std::runtime_error("Unknown error while deserializing.") ;
|
||||
}
|
||||
|
||||
void p3turtle::performLocalSearch(const std::string& s,std::list<TurtleFileInfo>& result)
|
||||
bool RsTurtleOpenTunnelItem::serialize(void *data,uint32_t& pktsize)
|
||||
{
|
||||
/* call to core */
|
||||
std::list<FileDetail> initialResults;
|
||||
std::list<std::string> words ;
|
||||
uint32_t tlvsize = serial_size();
|
||||
uint32_t offset = 0;
|
||||
|
||||
// to do: split search string into words.
|
||||
words.push_back(s) ;
|
||||
|
||||
// now, search!
|
||||
rsFiles->SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL);
|
||||
if (pktsize < tlvsize)
|
||||
return false; /* not enough space */
|
||||
|
||||
result.clear() ;
|
||||
pktsize = tlvsize;
|
||||
|
||||
for(std::list<FileDetail>::const_iterator it(initialResults.begin());it!=initialResults.end();++it)
|
||||
bool ok = true;
|
||||
|
||||
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
|
||||
|
||||
/* skip the header */
|
||||
offset += 8;
|
||||
|
||||
/* add mandatory parts first */
|
||||
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_HASH_SHA1, file_hash); // file hash
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, request_id);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, partial_tunnel_id);
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, depth);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
TurtleFileInfo i ;
|
||||
i.hash = it->hash ;
|
||||
i.size = it->size ;
|
||||
i.name = it->name ;
|
||||
|
||||
result.push_back(i) ;
|
||||
ok = false;
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsTurtleOpenTunnelItem::serialiseTransfer() Size Error! " << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
RsTurtleOpenTunnelItem::RsTurtleOpenTunnelItem(void *data,uint32_t pktsize)
|
||||
: RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " type = open tunnel" << std::endl ;
|
||||
#endif
|
||||
uint32_t offset = 8; // skip the header
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
|
||||
/* add mandatory parts first */
|
||||
|
||||
bool ok = true ;
|
||||
ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_HASH_SHA1, file_hash); // file hash
|
||||
ok &= getRawUInt32(data, pktsize, &offset, &request_id);
|
||||
ok &= getRawUInt32(data, pktsize, &offset, &partial_tunnel_id) ;
|
||||
ok &= getRawUInt16(data, pktsize, &offset, &depth);
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " reuqest_id=" << (void*)request_id << ", partial_id=" << (void*)partial_tunnel_id << ", depth=" << depth << ", hash=" << file_hash << std::endl ;
|
||||
#endif
|
||||
|
||||
if (offset != rssize)
|
||||
throw std::runtime_error("RsTurtleOpenTunnelItem::() error while deserializing.") ;
|
||||
if (!ok)
|
||||
throw std::runtime_error("RsTurtleOpenTunnelItem::() unknown error while deserializing.") ;
|
||||
}
|
||||
|
||||
bool RsTurtleTunnelOkItem::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, request_id);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
ok = false;
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsTurtleTunnelOkItem::serialiseTransfer() Size Error! " << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
RsTurtleTunnelOkItem::RsTurtleTunnelOkItem(void *data,uint32_t pktsize)
|
||||
: RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_OK)
|
||||
{
|
||||
#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 ;
|
||||
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
|
||||
ok &= getRawUInt32(data, pktsize, &offset, &request_id);
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " reuqest_id=" << (void*)request_id << ", tunnel_id=" << (void*)tunnel_id << std::endl ;
|
||||
#endif
|
||||
|
||||
if (offset != rssize)
|
||||
throw std::runtime_error("RsTurtleTunnelOkItem::() error while deserializing.") ;
|
||||
if (!ok)
|
||||
throw std::runtime_error("RsTurtleTunnelOkItem::() unknown error while deserializing.") ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
//====================================== General setup of the router ===================================//
|
||||
//
|
||||
// This class implements the turtle hopping router. It basically serves as
|
||||
// - a cache of turtle tunnels which are the communicating ways between distant peers.
|
||||
// - turtle tunnels are either end-point tunnels, or transitory points, in which case items are just
|
||||
@ -39,6 +41,108 @@
|
||||
// - name // name of the file found
|
||||
// - search request id. //
|
||||
//
|
||||
// - when downloading:
|
||||
// - for a given hash, a set of starting tunnels is maintained. Transitory
|
||||
// tunnels are also maintained for other hashes as requested by distant
|
||||
// peers.
|
||||
//
|
||||
//============================================= Operations =============================================//
|
||||
//
|
||||
// A download session works as follows:
|
||||
// Initiation:
|
||||
// 1 - the user searches for files (turtle search), and selects one and clicks download.
|
||||
// 2 - In parallel:
|
||||
// - the ft module gets a request, and searches for peers to provide this using its search modules.
|
||||
// - the turtle router is informed that a turtle download will happen with the given hash, so
|
||||
// it initiates tunnels for this hash.
|
||||
// In a loop:
|
||||
// 3 - the ft module asks the hash to the turtle searchModule, and sends file requests to the pqi
|
||||
// interface of this module.
|
||||
// 4 - the turtle pqi interface forwards these requests to the turtle router, which sends them to
|
||||
// the correct peers, selecting randomly among all the possible tunnels for this hash.
|
||||
// 5 - when a file data packet gets back, the turtle router forwards it back to the file transfer module.
|
||||
//
|
||||
//================================ connexion to the file transfer module ===============================//
|
||||
//
|
||||
// The turtle router should provide the ft module with the necessary interface for asking files, and
|
||||
// retreiving data:
|
||||
// - a search module that responds with a given fake peer id for hash request for which it has tunnels.
|
||||
// - a pqi interface to ask for file data
|
||||
// - p3turtle sends back file data packets to the file transfer module
|
||||
//
|
||||
//========================================== Tunnel usage rules ========================================//
|
||||
//
|
||||
// Tunnels should be used according to their capacity. This is an unresolved problem as for now.
|
||||
//
|
||||
//======================================= Tunnel maintenance rules =====================================//
|
||||
//
|
||||
// P3turtle should derive from pqihandler, just as p3disc, so that newly connected peers should trigger
|
||||
// asking for new tunnels, and disconnecting peers should produce a close tunnel packet.
|
||||
//
|
||||
// - when a peer A connects:
|
||||
// - initiate new tunnels for all active file hashes (go through the list of hashes) by
|
||||
// asking to A, for the same hash and the same source. Only report tunnels for which the destination
|
||||
// endpoint is different, which should not happen in fact, because of bouncing gards.
|
||||
//
|
||||
// - when a peer A disconnects.
|
||||
// - close tunnels whose destination is beyond A by sending a close request backward.
|
||||
// - close tunnels whose source is beyond A by sending a forward close request.
|
||||
//
|
||||
// - when receive open tunnel from A
|
||||
// - check whether it's a bouncing request. If yes, give up.
|
||||
// - check hash against local files.
|
||||
// if > 0
|
||||
// return tunnel ok item. No need to go forward, as sub tunnels are not useful.
|
||||
// else
|
||||
// forward request to peers, notting source and hashes.
|
||||
//
|
||||
// - when receive tunnel ok from A
|
||||
// - no need to check whether we already have this tunnel, as bouncing gards prevent this.
|
||||
// - leave a trace for the tunnel, and send (forward) backward.
|
||||
//
|
||||
// - when receive close tunnel from A
|
||||
// - if I am the endpoint
|
||||
// - locally close the tunnel.
|
||||
// - respond with tunnel closed.
|
||||
// - otherwise, block the tunnel, and forward close tunnel to tunnel destination.
|
||||
//
|
||||
// - when receive tunnel closed from A
|
||||
// - locally close the tunnel
|
||||
// - forward back
|
||||
//
|
||||
// Ids management:
|
||||
// - tunnel ids should be identical for requests between 2 same peers for the same file hash.
|
||||
// - tunnel requests ids do not need to be identical.
|
||||
// So:
|
||||
// - when issuing an open tunnel order,
|
||||
// - a random request id is generated and used for packet routing
|
||||
// - a partial tunnel id is build, which is unique to the pair (source,file hash)
|
||||
// - when tunnel_ok is sent back, the tunnel id is completed so that it is unique to the
|
||||
// triplet (source, destination, file hash).
|
||||
//
|
||||
// For these needs, tunnels are represented by:
|
||||
// - their file hash. Each tunnel is only designed for transferring a single and same file.
|
||||
// - their local endpoints id. These are the ids of the peers in direction to the source and destination.
|
||||
// - the tunnel id, which is unique to the triple hash+global source+global destination.
|
||||
// - there is a difference between source and destination in tunnels. The source is the file asker, the
|
||||
// destination is the file provider. This helps sorting tunnels.
|
||||
// - a timestamp, used for cleaning unused tunnels.
|
||||
//
|
||||
// The turtle router has:
|
||||
// - a list of search requests and where to bounce them back.
|
||||
// - a list of tunnel digging requests and where to bounce them, back.
|
||||
// - a list of active file hashes, for which is should constantly maintain tunnels.
|
||||
// - a list of active tunnels, some being transitory, some being endpoints.
|
||||
//
|
||||
// Turtle router entries:
|
||||
// - a function for performing turtle search
|
||||
// - a function for downloading files.
|
||||
//
|
||||
// Questions:
|
||||
// - should tunnels be re-used ? nope. The only useful case would be when two peers are exchanging files, which happens quite rarely.
|
||||
// - at a given moment, there is at most 1 tunnel for a given triplet (hash, source, destination).
|
||||
|
||||
|
||||
#ifndef MRK_PQI_TURTLE_H
|
||||
#define MRK_PQI_TURTLE_H
|
||||
|
||||
@ -67,6 +171,10 @@ static const int TURTLE_MAX_SEARCH_DEPTH = 6 ;
|
||||
typedef std::string TurtlePeerId ;
|
||||
typedef std::string TurtleFileHash ;
|
||||
typedef std::string TurtleFileName ;
|
||||
typedef TurtleRequestId TurtleSearchRequestId ;
|
||||
|
||||
typedef uint32_t TurtleTunnelRequestId ;
|
||||
typedef uint32_t TurtleTunnelId ;
|
||||
|
||||
class RsTurtleItem: public RsItem
|
||||
{
|
||||
@ -88,7 +196,7 @@ class RsTurtleSearchResultItem: public RsTurtleItem
|
||||
uint16_t depth ;
|
||||
uint8_t peer_id[16]; // peer id. This will eventually be obfuscated in some way.
|
||||
|
||||
TurtleRequestId request_id ; // randomly generated request id.
|
||||
TurtleSearchRequestId request_id ; // randomly generated request id.
|
||||
|
||||
std::list<TurtleFileInfo> result ;
|
||||
virtual std::ostream& print(std::ostream& o, uint16_t) ;
|
||||
@ -115,6 +223,69 @@ class RsTurtleSearchRequestItem: public RsTurtleItem
|
||||
virtual uint32_t serial_size() ;
|
||||
};
|
||||
|
||||
class RsTurtleOpenTunnelItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleOpenTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL) {}
|
||||
RsTurtleOpenTunnelItem(void *data,uint32_t size) ; // deserialization
|
||||
|
||||
TurtleFileHash file_hash ; // hash to match
|
||||
uint32_t request_id ; // randomly generated request id.
|
||||
uint32_t partial_tunnel_id ; // uncomplete tunnel id. Will be completed at destination.
|
||||
uint16_t depth ; // Used for limiting search depth.
|
||||
|
||||
virtual std::ostream& print(std::ostream& o, uint16_t) ;
|
||||
|
||||
protected:
|
||||
virtual bool serialize(void *data,uint32_t& size) ;
|
||||
virtual uint32_t serial_size() ;
|
||||
};
|
||||
|
||||
class RsTurtleTunnelOkItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleTunnelOkItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_OK) {}
|
||||
RsTurtleTunnelOkItem(void *data,uint32_t size) ; // deserialization
|
||||
|
||||
uint32_t tunnel_id ; // id of the tunnel. Should be identical for a tunnel between two same peers for the same hash.
|
||||
uint32_t request_id ; // randomly generated request id corresponding to the intial request.
|
||||
|
||||
virtual std::ostream& print(std::ostream& o, uint16_t) ;
|
||||
|
||||
protected:
|
||||
virtual bool serialize(void *data,uint32_t& size) ;
|
||||
virtual uint32_t serial_size() ;
|
||||
};
|
||||
|
||||
class RsTurtleCloseTunnelItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleCloseTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_CLOSE_TUNNEL) {}
|
||||
RsTurtleCloseTunnelItem(void *data,uint32_t size) ; // deserialization
|
||||
|
||||
uint32_t tunnel_id ; // id of the tunnel to close.
|
||||
|
||||
virtual std::ostream& print(std::ostream& o, uint16_t) ;
|
||||
protected:
|
||||
virtual bool serialize(void *data,uint32_t& size) ;
|
||||
virtual uint32_t serial_size() ;
|
||||
};
|
||||
|
||||
class RsTurtleTunnelClosedItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleTunnelClosedItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_CLOSED) {}
|
||||
RsTurtleTunnelClosedItem(void *data,uint32_t size) ; // deserialization
|
||||
|
||||
uint32_t tunnel_id ; // id of the tunnel to close.
|
||||
|
||||
virtual std::ostream& print(std::ostream& o, uint16_t) ;
|
||||
protected:
|
||||
virtual bool serialize(void *data,uint32_t& size) ;
|
||||
virtual uint32_t serial_size() ;
|
||||
};
|
||||
|
||||
|
||||
// Class responsible for serializing/deserializing all turtle items.
|
||||
//
|
||||
class RsTurtleSerialiser: public RsSerialType
|
||||
@ -136,9 +307,9 @@ class RsTurtleSerialiser: public RsSerialType
|
||||
class TurtleTunnel
|
||||
{
|
||||
public:
|
||||
TurtlePeerId in ; // where packets come from
|
||||
TurtlePeerId out ; // where packets should go
|
||||
uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels.
|
||||
TurtlePeerId local_src ; // where packets come from. Direction to the source.
|
||||
TurtlePeerId local_dst ; // where packets should go. Direction to the destination.
|
||||
uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels.
|
||||
};
|
||||
|
||||
class p3turtle: public p3Service, public pqiMonitor, public RsTurtle
|
||||
@ -150,11 +321,16 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle
|
||||
// the request id, which will be further used by the gui to store results
|
||||
// as they come back.
|
||||
//
|
||||
virtual TurtleRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
|
||||
// Launches a complete download file operation: diggs one or more
|
||||
// Initiates tunnel handling for the given file hash.
|
||||
// tunnels. Launches an exception if an error occurs during the
|
||||
// initialization process.
|
||||
// initialization process. The turtle router itself does not initiate downloads,
|
||||
// it only maintains tunnels for the given hash. The download should be
|
||||
// driven by the file transfer module. Maybe this function can do the whole thing:
|
||||
// - initiate tunnel handling
|
||||
// - send the file request to the file transfer module
|
||||
// - populate the file transfer module with the adequate pqi interface and search module.
|
||||
//
|
||||
virtual void turtleDownload(const std::string& file_hash) ;
|
||||
|
||||
@ -166,34 +342,58 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle
|
||||
|
||||
/************* from pqiMonitor *******************/
|
||||
|
||||
// Handles incoming and outgoing packets, sort search requests and
|
||||
// forward info upward.
|
||||
// This function does many things:
|
||||
// - It handles incoming and outgoing packets
|
||||
// - it sorts search requests and forwards search results upward.
|
||||
// - it cleans unused (tunnel+search) requests.
|
||||
// - it maintains the pool of tunnels, for each request file hash.
|
||||
//
|
||||
virtual int tick();
|
||||
|
||||
private:
|
||||
uint32_t generateRandomRequestId() ;
|
||||
void autoWash() ;
|
||||
//--------------------------- Admin/Helper functions -------------------------//
|
||||
|
||||
uint32_t generatePersonalFilePrint(const TurtleFileHash&) ; /// Generates a cyphered combination of ownId() and file hash
|
||||
uint32_t generateRandomRequestId() ; /// Generates a random uint32_t number.
|
||||
|
||||
/* Network Input */
|
||||
int handleIncoming();
|
||||
// int handleOutgoing();
|
||||
void autoWash() ; /// Auto cleaning of unused tunnels, search requests and tunnel requests.
|
||||
|
||||
// Performs a search calling local cache and search structure.
|
||||
void performLocalSearch(const std::string& s,std::list<TurtleFileInfo>& result) ;
|
||||
//------------------------------ Tunnel handling -----------------------------//
|
||||
|
||||
void handleSearchRequest(RsTurtleSearchRequestItem *item);
|
||||
void diggTunnel(const TurtleFileHash& hash) ; /// initiates tunnels from here to any peers having the given file hash
|
||||
|
||||
//----------------------------- Routing functions ----------------------------//
|
||||
|
||||
int handleIncoming(); /// Main routing function
|
||||
|
||||
void handleSearchRequest(RsTurtleSearchRequestItem *item); /// specific routing functions for handling particular packets.
|
||||
void handleSearchResult(RsTurtleSearchResultItem *item);
|
||||
void handleTunnelRequest(RsTurtleOpenTunnelItem *item);
|
||||
void handleTunnelResult(RsTurtleTunnelOkItem *item);
|
||||
|
||||
// returns a search result upwards (possibly to the gui)
|
||||
//------ Functions connecting the turtle router to other components.----------//
|
||||
|
||||
// Performs a search calling local cache and search structure.
|
||||
void performLocalSearch(const std::string& match_string,std::list<TurtleFileInfo>& result) ;
|
||||
|
||||
// Returns a search result upwards (possibly to the gui)
|
||||
void returnSearchResult(RsTurtleSearchResultItem *item) ;
|
||||
|
||||
// Returns true if the file with given hash is hosted locally.
|
||||
bool performLocalHashSearch(const TurtleFileHash& hash) ;
|
||||
|
||||
//--------------------------- Local variables --------------------------------//
|
||||
|
||||
/* data */
|
||||
p3ConnectMgr *mConnMgr;
|
||||
|
||||
RsMutex mTurtleMtx;
|
||||
|
||||
std::map<TurtleRequestId,TurtlePeerId> requests_origins ; // keeps trace of who emmitted a given request
|
||||
std::map<TurtleFileHash,TurtleTunnel> file_tunnels ; // stores adequate tunnels for each file hash.
|
||||
std::map<TurtleSearchRequestId,TurtlePeerId> _search_requests_origins ; /// keeps trace of who emmitted a given search request
|
||||
std::map<TurtleTunnelRequestId,TurtlePeerId> _tunnel_requests_origins ; /// keeps trace of who emmitted a tunnel request
|
||||
|
||||
std::map<TurtleFileHash,std::list<TurtleTunnelId> > _file_hashes_tunnels ; /// stores adequate tunnels for each file hash locally asked
|
||||
std::map<TurtleTunnelId,TurtleTunnel > _local_tunnels ; /// local tunnels, stored by ids (Either transiting or ending).
|
||||
|
||||
time_t _last_clean_time ;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user