mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-03 22:55:04 -04:00
fixed merge with upstream/master
This commit is contained in:
commit
2bab688dec
99 changed files with 4868 additions and 904 deletions
|
@ -31,6 +31,7 @@
|
|||
#endif
|
||||
|
||||
#include "rsserver/p3face.h"
|
||||
#include "crypto/rscrypto.h"
|
||||
|
||||
#include "pqi/authssl.h"
|
||||
#include "pqi/p3linkmgr.h"
|
||||
|
@ -60,11 +61,14 @@ static std::map<TurtleTunnelRequestId, std::vector<time_t> > TS_request_bounces
|
|||
void TS_dumpState() ;
|
||||
#endif
|
||||
|
||||
#define TURTLE_DEBUG() std::cerr << time(NULL) << " : TURTLE : " << __FUNCTION__ << " : "
|
||||
#define TURTLE_ERROR() std::cerr << "(EE) TURTLE ERROR : "
|
||||
|
||||
// These number may be quite important. I setup them with sensible values, but
|
||||
// an in-depth test would be better to get an idea of what the ideal values
|
||||
// could ever be.
|
||||
//
|
||||
// update of 14-03-11:
|
||||
// update of 14-03-11:
|
||||
// - I raised the cache time for tunnel requests. This avoids inconsistencies such as:
|
||||
// * tunnel requests bouncing back while the original request is not in the cache anymore
|
||||
// * special case of this for own file transfer: an outgoing tunnel is built with no end.
|
||||
|
@ -76,17 +80,18 @@ void TS_dumpState() ;
|
|||
// - The total number of TR per second emmited from self will be MAX_TUNNEL_REQS_PER_SECOND / TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 0.5
|
||||
// - I updated forward probabilities to higher values, and min them to 1/nb_connected_friends to prevent blocking tunnels.
|
||||
//
|
||||
static const time_t TUNNEL_REQUESTS_LIFE_TIME = 240 ; /// life time for tunnel requests in the cache.
|
||||
static const time_t SEARCH_REQUESTS_LIFE_TIME = 240 ; /// life time for search requests in the cache
|
||||
static const time_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns.
|
||||
static const time_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel.
|
||||
static const time_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec.
|
||||
static const time_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds
|
||||
static const time_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs
|
||||
static const time_t TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 2 ; /// Tunnel management calls every 2 secs.
|
||||
static const uint32_t MAX_TUNNEL_REQS_PER_SECOND = 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before
|
||||
static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS =5000 ; /// maximum number of search results forwarded back to the source.
|
||||
static const time_t TUNNEL_REQUESTS_LIFE_TIME = 240 ; /// life time for tunnel requests in the cache.
|
||||
static const time_t SEARCH_REQUESTS_LIFE_TIME = 240 ; /// life time for search requests in the cache
|
||||
static const time_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns.
|
||||
static const time_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel.
|
||||
static const time_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec.
|
||||
static const time_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds
|
||||
static const time_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs
|
||||
static const time_t TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 2 ; /// Tunnel management calls every 2 secs.
|
||||
static const uint32_t MAX_TUNNEL_REQS_PER_SECOND = 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before
|
||||
static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_FILES =5000 ; /// maximum number of search results forwarded back to the source.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT= 100 ; /// default maximum number of search results forwarded back source.
|
||||
|
||||
static const float depth_peer_probability[7] = { 1.0f,0.99f,0.9f,0.7f,0.6f,0.5,0.4f } ;
|
||||
|
||||
|
@ -148,13 +153,15 @@ void p3turtle::getItemNames(std::map<uint8_t,std::string>& names) const
|
|||
{
|
||||
names.clear();
|
||||
|
||||
names[RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST ] = "Search request";
|
||||
names[RS_TURTLE_SUBTYPE_SEARCH_RESULT ] = "Search result";
|
||||
names[RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST ] = "Filename substring search request";
|
||||
names[RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST ] = "Generic search request";
|
||||
names[RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT ] = "File search result";
|
||||
names[RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT ] = "Generic search result";
|
||||
names[RS_TURTLE_SUBTYPE_OPEN_TUNNEL ] = "Tunnel request";
|
||||
names[RS_TURTLE_SUBTYPE_TUNNEL_OK ] = "Tunnel response";
|
||||
names[RS_TURTLE_SUBTYPE_FILE_REQUEST ] = "Data request";
|
||||
names[RS_TURTLE_SUBTYPE_FILE_DATA ] = "Data chunk";
|
||||
names[RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST ] = "RegExp search";
|
||||
names[RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST ] = "Filename RegExp search request";
|
||||
names[RS_TURTLE_SUBTYPE_GENERIC_DATA ] = "Generic data";
|
||||
names[RS_TURTLE_SUBTYPE_FILE_MAP ] = "Chunk map";
|
||||
names[RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST ] = "Chunk map request";
|
||||
|
@ -162,7 +169,7 @@ void p3turtle::getItemNames(std::map<uint8_t,std::string>& names) const
|
|||
names[RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST ] = "Chunk CRC request";
|
||||
}
|
||||
|
||||
void p3turtle::setEnabled(bool b)
|
||||
void p3turtle::setEnabled(bool b)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
_turtle_routing_enabled = b;
|
||||
|
@ -181,7 +188,7 @@ bool p3turtle::enabled() const
|
|||
}
|
||||
|
||||
|
||||
void p3turtle::setSessionEnabled(bool b)
|
||||
void p3turtle::setSessionEnabled(bool b)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
_turtle_routing_session_enabled = b;
|
||||
|
@ -239,7 +246,7 @@ int p3turtle::tick()
|
|||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
_last_tunnel_management_time = now ;
|
||||
|
||||
// Update traffic statistics. The constants are important: they allow a smooth variation of the
|
||||
// Update traffic statistics. The constants are important: they allow a smooth variation of the
|
||||
// traffic speed, which is used to moderate tunnel requests statistics.
|
||||
//
|
||||
_traffic_info = _traffic_info*0.9 + _traffic_info_buffer* (0.1 / (float)TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS) ;
|
||||
|
@ -367,8 +374,8 @@ void p3turtle::manageTunnels()
|
|||
// - the hash hasn't been tunneled for more than REGULAR_TUNNEL_DIGGING_TIME seconds, even if downloading.
|
||||
//
|
||||
// Candidate hashes are sorted, by olderness. The older gets tunneled first. At most MAX_TUNNEL_REQS_PER_SECOND are
|
||||
// treated at once, as this method is called every second.
|
||||
// Note: Because REGULAR_TUNNEL_DIGGING_TIME is larger than EMPTY_TUNNELS_DIGGING_TIME, files being downloaded get
|
||||
// treated at once, as this method is called every second.
|
||||
// Note: Because REGULAR_TUNNEL_DIGGING_TIME is larger than EMPTY_TUNNELS_DIGGING_TIME, files being downloaded get
|
||||
// re-tunneled in priority. As this happens less, they don't obliterate tunneling for files that have no tunnels yet.
|
||||
|
||||
std::vector<std::pair<TurtleFileHash,time_t> > hashes_to_digg ;
|
||||
|
@ -549,7 +556,7 @@ void p3turtle::autoWash()
|
|||
|
||||
// Now remove all the virtual peers ids at the client services. Off mutex!
|
||||
//
|
||||
|
||||
|
||||
for(uint32_t i=0;i<services_vpids_to_remove.size();++i)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
|
@ -611,7 +618,7 @@ void p3turtle::locked_closeTunnel(TurtleTunnelId tid,std::vector<std::pair<RsTur
|
|||
// Let's be cautious. Normally we should never be here without consistent information,
|
||||
// but still, this happens, rarely.
|
||||
//
|
||||
if(_virtual_peers.find(vpid) != _virtual_peers.end())
|
||||
if(_virtual_peers.find(vpid) != _virtual_peers.end())
|
||||
_virtual_peers.erase(_virtual_peers.find(vpid)) ;
|
||||
|
||||
std::map<TurtleFileHash,TurtleHashInfo>::iterator it(_incoming_file_hashes.find(hash)) ;
|
||||
|
@ -656,7 +663,7 @@ void p3turtle::locked_closeTunnel(TurtleTunnelId tid,std::vector<std::pair<RsTur
|
|||
|
||||
// Also remove the associated virtual peer
|
||||
//
|
||||
if(_virtual_peers.find(vpid) != _virtual_peers.end())
|
||||
if(_virtual_peers.find(vpid) != _virtual_peers.end())
|
||||
_virtual_peers.erase(_virtual_peers.find(vpid)) ;
|
||||
}
|
||||
}
|
||||
|
@ -721,7 +728,7 @@ bool p3turtle::loadList(std::list<RsItem*>& load)
|
|||
RsConfigKeyValueSet *vitem = dynamic_cast<RsConfigKeyValueSet*>(*it) ;
|
||||
|
||||
if(vitem != NULL)
|
||||
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
|
||||
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
|
||||
{
|
||||
if(kit->key == "TURTLE_CONFIG_MAX_TR_RATE")
|
||||
{
|
||||
|
@ -821,7 +828,7 @@ int p3turtle::handleIncoming()
|
|||
RsTurtleGenericTunnelItem *gti = dynamic_cast<RsTurtleGenericTunnelItem *>(item) ;
|
||||
|
||||
if(gti != NULL)
|
||||
routeGenericTunnelItem(gti) ; /// Generic packets, that travel through established tunnels.
|
||||
routeGenericTunnelItem(gti) ; /// Generic packets, that travel through established tunnels.
|
||||
else /// These packets should be destroyed by the client.
|
||||
{
|
||||
/// Special packets that require specific treatment, because tunnels do not exist for these packets.
|
||||
|
@ -830,10 +837,12 @@ int p3turtle::handleIncoming()
|
|||
switch(item->PacketSubType())
|
||||
{
|
||||
case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST:
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST:
|
||||
case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST: handleSearchRequest(dynamic_cast<RsTurtleSearchRequestItem *>(item)) ;
|
||||
break ;
|
||||
|
||||
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult(dynamic_cast<RsTurtleSearchResultItem *>(item)) ;
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT :
|
||||
case RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT : handleSearchResult(dynamic_cast<RsTurtleSearchResultItem *>(item)) ;
|
||||
break ;
|
||||
|
||||
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest(dynamic_cast<RsTurtleOpenTunnelItem *>(item)) ;
|
||||
|
@ -859,8 +868,6 @@ int p3turtle::handleIncoming()
|
|||
//
|
||||
void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
// take a look at the item and test against inconsistent values
|
||||
// - If the item destimation is
|
||||
|
||||
|
@ -868,7 +875,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
|||
std::cerr << "Received search request from peer " << item->PeerId() << ": " << std::endl ;
|
||||
item->print(std::cerr,0) ;
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t item_size = RsTurtleSerialiser().size(item);
|
||||
|
||||
if(item_size > TURTLE_MAX_SEARCH_REQ_ACCEPTED_SERIAL_SIZE)
|
||||
|
@ -879,27 +886,57 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
|||
std::cerr << " Caught a turtle search item with arbitrary large size from " << item->PeerId() << " of size " << item_size << " and depth " << item->depth << ". This is not allowed => dropping." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(_search_requests_origins.size() > MAX_ALLOWED_SR_IN_CACHE)
|
||||
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
if(_search_requests_origins.size() > MAX_ALLOWED_SR_IN_CACHE)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Dropping, because the search request cache is full." << std::endl ;
|
||||
std::cerr << " Dropping, because the search request cache is full." << std::endl ;
|
||||
#endif
|
||||
std::cerr << " More than " << MAX_ALLOWED_SR_IN_CACHE << " search request in cache. A peer is probably trying to flood your network See the depth charts to find him." << std::endl;
|
||||
return ;
|
||||
std::cerr << " More than " << MAX_ALLOWED_SR_IN_CACHE << " search request in cache. A peer is probably trying to flood your network See the depth charts to find him." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// If the item contains an already handled search request, give up. This
|
||||
// happens when the same search request gets relayed by different peers
|
||||
//
|
||||
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 ;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
// If the item contains an already handled search request, give up. This
|
||||
// happens when the same search request gets relayed by different peers
|
||||
//
|
||||
if(_search_requests_origins.find(item->request_id) != _search_requests_origins.end())
|
||||
// Perform local search off-mutex,because this might call some services that are above turtle in the mutex chain.
|
||||
|
||||
uint32_t search_result_count = 0;
|
||||
uint32_t max_allowed_hits = TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT;
|
||||
|
||||
if(item->PeerId() != _own_id) // is the request not coming from us?
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " This is a bouncing request. Ignoring and deleting it." << std::endl ;
|
||||
std::cerr << " Request not from us. Performing local search" << std::endl ;
|
||||
#endif
|
||||
return ;
|
||||
std::list<RsTurtleSearchResultItem*> search_results ;
|
||||
|
||||
performLocalSearch(item,search_result_count,search_results,max_allowed_hits) ;
|
||||
|
||||
for(auto it(search_results.begin());it!=search_results.end();++it)
|
||||
{
|
||||
(*it)->request_id = item->request_id ;
|
||||
(*it)->depth = 0 ;
|
||||
(*it)->PeerId(item->PeerId()) ;
|
||||
|
||||
sendItem(*it) ;
|
||||
}
|
||||
}
|
||||
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
// This is a new request. Let's add it to the request map, and forward it to
|
||||
// open peers.
|
||||
|
||||
|
@ -907,67 +944,17 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
|||
req.origin = item->PeerId() ;
|
||||
req.time_stamp = time(NULL) ;
|
||||
req.depth = item->depth ;
|
||||
req.result_count = 0;
|
||||
req.result_count = search_result_count;
|
||||
req.keywords = item->GetKeywords() ;
|
||||
|
||||
// If it's not for us, perform a local search. If something found, forward the search result back.
|
||||
|
||||
if(item->PeerId() != _own_id)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Request not from us. Performing local search" << std::endl ;
|
||||
#endif
|
||||
|
||||
std::list<TurtleFileInfo> result ;
|
||||
|
||||
item->performLocalSearch(result) ;
|
||||
|
||||
RsTurtleSearchResultItem *res_item = NULL ;
|
||||
uint32_t item_size = 0 ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
if(!result.empty())
|
||||
std::cerr << " " << result.size() << " matches found. Sending back to origin (" << item->PeerId() << ")." << std::endl ;
|
||||
#endif
|
||||
while(!result.empty() && req.result_count < TURTLE_SEARCH_RESULT_MAX_HITS)
|
||||
{
|
||||
// Let's chop search results items into several chunks of finite size to avoid exceeding streamer's capacity.
|
||||
//
|
||||
static const uint32_t RSTURTLE_MAX_SEARCH_RESPONSE_SIZE = 10000 ;
|
||||
|
||||
if(res_item == NULL)
|
||||
{
|
||||
res_item = new RsTurtleSearchResultItem ;
|
||||
item_size = 0 ;
|
||||
|
||||
res_item->depth = 0 ;
|
||||
res_item->request_id = item->request_id ;
|
||||
res_item->PeerId(item->PeerId()) ; // send back to the same guy
|
||||
}
|
||||
res_item->result.push_back(result.front()) ;
|
||||
|
||||
++req.result_count ; // increase hit number for this particular search request.
|
||||
|
||||
item_size += 8 /* size */ + result.front().hash.serial_size() + result.front().name.size() ;
|
||||
result.pop_front() ;
|
||||
|
||||
if(item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE || result.empty() || req.result_count >= TURTLE_SEARCH_RESULT_MAX_HITS)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Sending back chunk of size " << item_size << ", for " << res_item->result.size() << " elements." << std::endl ;
|
||||
#endif
|
||||
sendItem(res_item) ;
|
||||
res_item = NULL ;
|
||||
}
|
||||
}
|
||||
}
|
||||
req.service_id = item->serviceId() ;
|
||||
req.max_allowed_hits = max_allowed_hits;
|
||||
|
||||
// if enough has been sent back already, do not sarch further
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " result count = " << req.result_count << std::endl;
|
||||
#endif
|
||||
if(req.result_count >= TURTLE_SEARCH_RESULT_MAX_HITS)
|
||||
if(req.result_count >= max_allowed_hits)
|
||||
return ;
|
||||
|
||||
// If search depth not too large, also forward this search request to all other peers.
|
||||
|
@ -1004,14 +991,14 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
|||
// Copy current item and modify it.
|
||||
RsTurtleSearchRequestItem *fwd_item = item->clone() ;
|
||||
|
||||
// increase search depth, except in some rare cases, to prevent correlation between
|
||||
// increase search depth, except in some rare cases, to prevent correlation between
|
||||
// TR sniffing and friend names. The strategy is to not increase depth if the depth
|
||||
// is 1:
|
||||
// If B receives a TR of depth 1 from A, B cannot deduice that A is downloading the
|
||||
// file, since A might have shifted the depth.
|
||||
//
|
||||
if(!random_dshift)
|
||||
++(fwd_item->depth) ;
|
||||
++(fwd_item->depth) ;
|
||||
|
||||
fwd_item->PeerId(*it) ;
|
||||
|
||||
|
@ -1025,67 +1012,194 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
|||
#endif
|
||||
}
|
||||
|
||||
// This function should be removed in the future, when file search will also use generic search items.
|
||||
|
||||
void p3turtle::performLocalSearch(RsTurtleSearchRequestItem *item,uint32_t& req_result_count,std::list<RsTurtleSearchResultItem*>& search_results,uint32_t& max_allowed_hits)
|
||||
{
|
||||
RsTurtleFileSearchRequestItem *ftsearch = dynamic_cast<RsTurtleFileSearchRequestItem*>(item) ;
|
||||
|
||||
if(ftsearch != NULL)
|
||||
{
|
||||
performLocalSearch_files(ftsearch,req_result_count,search_results,max_allowed_hits) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
RsTurtleGenericSearchRequestItem *gnsearch = dynamic_cast<RsTurtleGenericSearchRequestItem*>(item) ;
|
||||
|
||||
if(gnsearch != NULL)
|
||||
{
|
||||
performLocalSearch_generic(gnsearch,req_result_count,search_results,max_allowed_hits) ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
void p3turtle::performLocalSearch_generic(RsTurtleGenericSearchRequestItem *item, uint32_t& req_result_count, std::list<RsTurtleSearchResultItem*>& result,uint32_t& max_allowed_hits)
|
||||
{
|
||||
unsigned char *search_result_data = NULL ;
|
||||
uint32_t search_result_data_len = 0 ;
|
||||
|
||||
RsTurtleClientService *client = NULL ;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
auto it = _registered_services.find(item->service_id) ;
|
||||
|
||||
if(it == _registered_services.end())
|
||||
return ;
|
||||
|
||||
client = it->second ;
|
||||
}
|
||||
|
||||
if(client->receiveSearchRequest(item->search_data,item->search_data_len,search_result_data,search_result_data_len,max_allowed_hits))
|
||||
{
|
||||
RsTurtleGenericSearchResultItem *result_item = new RsTurtleGenericSearchResultItem ;
|
||||
|
||||
result_item->result_data = search_result_data ;
|
||||
result_item->result_data_len = search_result_data_len ;
|
||||
|
||||
result.push_back(result_item) ;
|
||||
}
|
||||
}
|
||||
|
||||
void p3turtle::performLocalSearch_files(RsTurtleFileSearchRequestItem *item,uint32_t& req_result_count,std::list<RsTurtleSearchResultItem*>& result,uint32_t& max_allowed_hits)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Performing rsFiles->search()" << std::endl ;
|
||||
#endif
|
||||
// now, search!
|
||||
std::list<TurtleFileInfo> initialResults ;
|
||||
item->search(initialResults) ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << initialResults.size() << " matches found." << std::endl ;
|
||||
#endif
|
||||
result.clear() ;
|
||||
RsTurtleFTSearchResultItem *res_item = NULL ;
|
||||
uint32_t item_size = 0 ;
|
||||
|
||||
static const uint32_t RSTURTLE_MAX_SEARCH_RESPONSE_SIZE = 10000 ;
|
||||
max_allowed_hits = TURTLE_SEARCH_RESULT_MAX_HITS_FILES;
|
||||
|
||||
for(auto it(initialResults.begin());it!=initialResults.end();++it)
|
||||
{
|
||||
if(res_item == NULL)
|
||||
{
|
||||
res_item = new RsTurtleFTSearchResultItem ;
|
||||
item_size = 0 ;
|
||||
|
||||
result.push_back(res_item) ;
|
||||
}
|
||||
res_item->result.push_back(*it);
|
||||
|
||||
// Let's chop search results items into several chunks of finite size to avoid exceeding streamer's capacity.
|
||||
//
|
||||
++req_result_count ; // increase hit number for this particular search request.
|
||||
|
||||
item_size += 8 /* size */ + it->hash.serial_size() + it->name.size() ;
|
||||
|
||||
if(item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE || req_result_count >= max_allowed_hits)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Sending back chunk of size " << item_size << ", for " << res_item->result.size() << " elements." << std::endl ;
|
||||
#endif
|
||||
res_item = NULL ; // forces creation of a new item.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
// Find who actually sent the corresponding request.
|
||||
//
|
||||
std::map<TurtleRequestId,TurtleSearchRequestInfo>::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 == _search_requests_origins.end())
|
||||
std::list<std::pair<RsTurtleSearchResultItem*,RsTurtleClientService*> > results_to_notify_off_mutex ;
|
||||
|
||||
{
|
||||
// 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 ??
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
// Find who actually sent the corresponding request.
|
||||
//
|
||||
std::map<TurtleRequestId,TurtleSearchRequestInfo>::iterator it = _search_requests_origins.find(item->request_id) ;
|
||||
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": search result has no peer direction!" << std::endl ;
|
||||
return ;
|
||||
}
|
||||
|
||||
// Is this result's target actually ours ?
|
||||
|
||||
if(it->second.origin == _own_id)
|
||||
{
|
||||
it->second.result_count += item->result.size() ;
|
||||
returnSearchResult(item) ; // Yes, so send upward.
|
||||
}
|
||||
else
|
||||
{ // Nope, so forward it back.
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Forwarding result back to " << it->second.origin << std::endl;
|
||||
std::cerr << "Received search result:" << std::endl ;
|
||||
item->print(std::cerr,0) ;
|
||||
#endif
|
||||
// We update the total count forwarded back, and chop it to TURTLE_SEARCH_RESULT_MAX_HITS.
|
||||
|
||||
uint32_t n = item->result.size(); // not so good!
|
||||
|
||||
if(it->second.result_count >= TURTLE_SEARCH_RESULT_MAX_HITS)
|
||||
if(it == _search_requests_origins.end())
|
||||
{
|
||||
std::cerr << "(WW) exceeded turtle search result to forward. Req=" << std::hex << item->request_id << std::dec << ": dropping item with " << n << " elements." << std::endl;
|
||||
// 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 ??
|
||||
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": search result for request " << std::hex << item->request_id << std::dec << " has no peer direction!" << std::endl ;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(it->second.result_count + n > TURTLE_SEARCH_RESULT_MAX_HITS)
|
||||
{
|
||||
for(uint32_t i=it->second.result_count + n; i>TURTLE_SEARCH_RESULT_MAX_HITS;--i)
|
||||
item->result.pop_back() ;
|
||||
// Is this result's target actually ours ?
|
||||
|
||||
it->second.result_count = TURTLE_SEARCH_RESULT_MAX_HITS ;
|
||||
if(it->second.origin == _own_id)
|
||||
{
|
||||
it->second.result_count += item->count() ;
|
||||
|
||||
auto it2 = _registered_services.find(it->second.service_id) ;
|
||||
|
||||
if(it2 != _registered_services.end())
|
||||
results_to_notify_off_mutex.push_back(std::make_pair(item,it2->second)) ;
|
||||
else
|
||||
std::cerr << "(EE) cannot find client service for ID " << std::hex << it->second.service_id << std::dec << ": search result item will be dropped." << std::endl;
|
||||
}
|
||||
else
|
||||
it->second.result_count += n ;
|
||||
{ // Nope, so forward it back.
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Forwarding result back to " << it->second.origin << std::endl;
|
||||
#endif
|
||||
// We update the total count forwarded back, and chop it to TURTLE_SEARCH_RESULT_MAX_HITS.
|
||||
|
||||
RsTurtleSearchResultItem *fwd_item = new RsTurtleSearchResultItem(*item) ; // copy the item
|
||||
uint32_t n = item->count(); // not so good!
|
||||
|
||||
// Normally here, we should setup the forward adress, so that the owner's
|
||||
// of the files found can be further reached by a tunnel.
|
||||
if(it->second.result_count >= it->second.max_allowed_hits)
|
||||
{
|
||||
std::cerr << "(WW) exceeded turtle search result to forward. Req=" << std::hex << item->request_id << std::dec << ": dropping item with " << n << " elements." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
fwd_item->PeerId(it->second.origin) ;
|
||||
fwd_item->depth = 0 ; // obfuscate the depth for non immediate friends. Result will always be 0. This effectively removes the information.
|
||||
if(it->second.result_count + n > it->second.max_allowed_hits)
|
||||
{
|
||||
for(uint32_t i=it->second.result_count + n; i>it->second.max_allowed_hits;--i)
|
||||
item->pop() ;
|
||||
|
||||
sendItem(fwd_item) ;
|
||||
it->second.result_count = it->second.max_allowed_hits ;
|
||||
}
|
||||
else
|
||||
it->second.result_count += n ;
|
||||
|
||||
RsTurtleSearchResultItem *fwd_item = item->duplicate();
|
||||
|
||||
// Normally here, we should setup the forward adress, so that the owner's
|
||||
// of the files found can be further reached by a tunnel.
|
||||
|
||||
fwd_item->PeerId(it->second.origin) ;
|
||||
fwd_item->depth = 0 ; // obfuscate the depth for non immediate friends. Result will always be 0. This effectively removes the information.
|
||||
|
||||
sendItem(fwd_item) ;
|
||||
}
|
||||
}
|
||||
|
||||
// now we notify clients off-mutex.
|
||||
|
||||
for(auto it(results_to_notify_off_mutex.begin());it!=results_to_notify_off_mutex.end();++it)
|
||||
{
|
||||
// Hack to use the old search result handling in ftServer. Normally ftServer should use the new method with serialized result.
|
||||
|
||||
#warning make sure memory is correctly deleted here
|
||||
RsTurtleFTSearchResultItem *ftsr = dynamic_cast<RsTurtleFTSearchResultItem*>(it->first) ;
|
||||
|
||||
if(ftsr!=NULL)
|
||||
{
|
||||
RsServer::notify()->notifyTurtleSearchResult(ftsr->request_id,ftsr->result) ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
RsTurtleGenericSearchResultItem *gnsr = dynamic_cast<RsTurtleGenericSearchResultItem*>(it->first) ;
|
||||
|
||||
if(gnsr!=NULL)
|
||||
(*it).second->receiveSearchResult(gnsr->request_id,gnsr->result_data,gnsr->result_data_len) ;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -1147,8 +1261,8 @@ void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item)
|
|||
|
||||
// Let's figure out whether this packet is for us or not.
|
||||
|
||||
if(item->PeerId() == tunnel.local_dst && tunnel.local_src != _own_id) //direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT &&
|
||||
{
|
||||
if(item->PeerId() == tunnel.local_dst && tunnel.local_src != _own_id) //direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT &&
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Forwarding generic item to peer " << tunnel.local_src << std::endl ;
|
||||
#endif
|
||||
|
@ -1186,7 +1300,7 @@ void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item)
|
|||
// The packet was not forwarded, so it is for us. Let's treat it.
|
||||
// This is done off-mutex, to avoid various deadlocks
|
||||
//
|
||||
|
||||
|
||||
handleRecvGenericTunnelItem(item) ;
|
||||
|
||||
delete item ;
|
||||
|
@ -1309,13 +1423,13 @@ void p3turtle::sendTurtleData(const RsPeerId& virtual_peer_id,RsTurtleGenericTun
|
|||
|
||||
if(tunnel.local_src == _own_id)
|
||||
{
|
||||
item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ;
|
||||
item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ;
|
||||
item->PeerId(tunnel.local_dst) ;
|
||||
_traffic_info_buffer.data_dn_Bps += ss ;
|
||||
}
|
||||
else if(tunnel.local_dst == _own_id)
|
||||
{
|
||||
item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ;
|
||||
item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ;
|
||||
item->PeerId(tunnel.local_src) ;
|
||||
_traffic_info_buffer.data_up_Bps += ss ;
|
||||
}
|
||||
|
@ -1453,7 +1567,7 @@ void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item)
|
|||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<TurtleTunnelRequestId,TurtleTunnelRequestInfo>::iterator it = _tunnel_requests_origins.find(item->request_id) ;
|
||||
|
||||
|
||||
if(it != _tunnel_requests_origins.end())
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
|
@ -1556,7 +1670,7 @@ void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item)
|
|||
// - the tunnel id will now be unique for a given route
|
||||
// - allows a better balance of bandwidth for a given transfer
|
||||
// - avoid the waste of items that get lost when re-routing a tunnel
|
||||
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Perturbating partial tunnel id. Original=" << std::hex << item->partial_tunnel_id ;
|
||||
#endif
|
||||
|
@ -1587,7 +1701,7 @@ void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item)
|
|||
forward_probability = 1.0f / nb_online_ids ;
|
||||
|
||||
// Setting forward_probability to 1/nb_online_ids forces at most one TR up per TR dn. But if we are overflooded by
|
||||
// TR dn, we still need to control them to avoid flooding the pqiHandler outqueue. So we additionally moderate the
|
||||
// TR dn, we still need to control them to avoid flooding the pqiHandler outqueue. So we additionally moderate the
|
||||
// forward probability so as to reduct the output rate accordingly.
|
||||
//
|
||||
if(_traffic_info.tr_dn_Bps / (float)TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate)
|
||||
|
@ -1613,7 +1727,7 @@ void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item)
|
|||
// Copy current item and modify it.
|
||||
RsTurtleOpenTunnelItem *fwd_item = new RsTurtleOpenTunnelItem(*item) ;
|
||||
|
||||
// increase search depth, except in some rare cases, to prevent correlation between
|
||||
// increase search depth, except in some rare cases, to prevent correlation between
|
||||
// TR sniffing and friend names. The strategy is to not increase depth if the depth
|
||||
// is 1:
|
||||
// If B receives a TR of depth 1 from A, B cannot deduice that A is downloading the
|
||||
|
@ -1770,7 +1884,9 @@ void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item)
|
|||
// ------------------------------ IO with libretroshare ----------------------------//
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
void RsTurtleStringSearchRequestItem::performLocalSearch(std::list<TurtleFileInfo>& result) const
|
||||
|
||||
|
||||
void RsTurtleStringSearchRequestItem::search(std::list<TurtleFileInfo>& result) const
|
||||
{
|
||||
/* call to core */
|
||||
std::list<DirDetails> initialResults;
|
||||
|
@ -1793,7 +1909,7 @@ void RsTurtleStringSearchRequestItem::performLocalSearch(std::list<TurtleFileInf
|
|||
for(std::list<DirDetails>::const_iterator it(initialResults.begin());it!=initialResults.end();++it)
|
||||
{
|
||||
// retain only file type
|
||||
if (it->type == DIR_TYPE_DIR)
|
||||
if (it->type == DIR_TYPE_DIR)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Skipping directory " << it->name << std::endl ;
|
||||
|
@ -1809,7 +1925,7 @@ void RsTurtleStringSearchRequestItem::performLocalSearch(std::list<TurtleFileInf
|
|||
result.push_back(i) ;
|
||||
}
|
||||
}
|
||||
void RsTurtleRegExpSearchRequestItem::performLocalSearch(std::list<TurtleFileInfo>& result) const
|
||||
void RsTurtleRegExpSearchRequestItem::search(std::list<TurtleFileInfo>& result) const
|
||||
{
|
||||
/* call to core */
|
||||
std::list<DirDetails> initialResults;
|
||||
|
@ -1832,7 +1948,7 @@ void RsTurtleRegExpSearchRequestItem::performLocalSearch(std::list<TurtleFileInf
|
|||
for(std::list<DirDetails>::const_iterator it(initialResults.begin());it!=initialResults.end();++it)
|
||||
{
|
||||
// retain only file type
|
||||
if (it->type == DIR_TYPE_DIR)
|
||||
if (it->type == DIR_TYPE_DIR)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Skipping directory " << it->name << std::endl ;
|
||||
|
@ -1904,6 +2020,34 @@ TurtleRequestId p3turtle::turtleSearch(const RsRegularExpression::LinearizedExpr
|
|||
return id ;
|
||||
}
|
||||
|
||||
TurtleRequestId p3turtle::turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service)
|
||||
{
|
||||
// generate a new search id.
|
||||
|
||||
TurtleRequestId id = generateRandomRequestId() ;
|
||||
|
||||
// Form a request packet that simulates a request from us.
|
||||
//
|
||||
RsTurtleGenericSearchRequestItem item ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "performing search. OwnId = " << _own_id << std::endl ;
|
||||
#endif
|
||||
|
||||
item.PeerId(_own_id) ;
|
||||
item.service_id = client_service->serviceId();
|
||||
item.search_data = search_bin_data ;
|
||||
item.search_data_len = search_bin_data_len ;
|
||||
item.request_id = id ;
|
||||
item.depth = 0 ;
|
||||
|
||||
// send it
|
||||
|
||||
handleSearchRequest(&item) ;
|
||||
|
||||
return id ;
|
||||
}
|
||||
|
||||
void p3turtle::monitorTunnels(const RsFileHash& hash,RsTurtleClientService *client_service,bool allow_multi_tunnels)
|
||||
{
|
||||
{
|
||||
|
@ -1944,29 +2088,49 @@ void p3turtle::monitorTunnels(const RsFileHash& hash,RsTurtleClientService *clie
|
|||
IndicateConfigChanged() ; // initiates saving of handled hashes.
|
||||
}
|
||||
|
||||
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 " << HEX_PRINT(item->request_id) << " upwards." << std::endl ;
|
||||
#endif
|
||||
|
||||
RsServer::notify()->notifyTurtleSearchResult(item->request_id,item->result) ;
|
||||
}
|
||||
|
||||
// RsTurtleGxsSearchResultGroupSummaryItem *gxs_sr_gs = dynamic_cast<RsTurtleGxsSearchResultGroupSummaryItem*>(item) ;
|
||||
//
|
||||
// if(gxs_sr_gs != NULL)
|
||||
// {
|
||||
// RsServer::notify()->notifyTurtleSearchResult(gxs_sr_gs->request_id,gxs_sr_gs->result) ;
|
||||
// return ;
|
||||
// }
|
||||
// RsTurtleGxsSearchResultGroupDataItem *gxs_sr_gd = dynamic_cast<RsTurtleGxsSearchResultGroupDataItem*>(item) ;
|
||||
//
|
||||
// if(gxs_sr_gd != NULL)
|
||||
// {
|
||||
//#warning MISSING CODE HERE TO HANDLE ENCRYPTED INCOMING GROUP DATA.
|
||||
// //RsServer::notify()->notifyTurtleSearchResult(gxs_sr_gd->request_id,gxs_sr_gd->encrypted_nxs_group) ;
|
||||
// return ;
|
||||
// }
|
||||
|
||||
/// Warning: this function should never be called while the turtle mutex is locked.
|
||||
/// Otherwize this is a possible source of cross-lock with the File mutex.
|
||||
//
|
||||
bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId& peer_id,RsTurtleClientService *& service)
|
||||
{
|
||||
if(_registered_services.empty())
|
||||
std::cerr << "Turtle router has no services registered. Tunnel requests cannot be handled." << std::endl;
|
||||
std::map<uint16_t,RsTurtleClientService*> client_map ;
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
for(std::list<RsTurtleClientService*>::const_iterator it(_registered_services.begin());it!=_registered_services.end();++it)
|
||||
if( (*it)->handleTunnelRequest(hash,peer_id))
|
||||
if(_registered_services.empty())
|
||||
{
|
||||
std::cerr << "Turtle router has no services registered. Tunnel requests cannot be handled." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
client_map = _registered_services ;
|
||||
}
|
||||
|
||||
for(auto it(client_map.begin());it!=client_map.end();++it)
|
||||
if( (*it).second->handleTunnelRequest(hash,peer_id))
|
||||
{
|
||||
service = *it ;
|
||||
service = it->second ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -1976,14 +2140,9 @@ bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId&
|
|||
|
||||
void p3turtle::registerTunnelService(RsTurtleClientService *service)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
for(std::list<RsTurtleClientService*>::const_iterator it(_registered_services.begin());it!=_registered_services.end();++it)
|
||||
if(service == *it)
|
||||
throw std::runtime_error("p3turtle::registerTunnelService(): Cannot register the same service twice. Please fix the code!") ;
|
||||
#endif
|
||||
std::cerr << "p3turtle: registered new tunnel service " << (void*)service << std::endl;
|
||||
std::cerr << "p3turtle: registered new tunnel service with ID=" << std::hex << service->serviceId() << std::dec << " and pointer " << (void*)service << std::endl;
|
||||
|
||||
_registered_services.push_back(service) ;
|
||||
_registered_services[service->serviceId()] = service ;
|
||||
_serialiser->registerClientService(service) ;
|
||||
}
|
||||
|
||||
|
@ -2065,7 +2224,7 @@ std::string p3turtle::getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_i
|
|||
std::map<TurtleVirtualPeerId,TurtleTunnelId>::const_iterator it(_virtual_peers.find(virtual_peer_id)) ;
|
||||
if(it != _virtual_peers.end())
|
||||
{
|
||||
std::map<TurtleTunnelId,TurtleTunnel>::iterator it2( _local_tunnels.find(it->second) ) ;
|
||||
std::map<TurtleTunnelId,TurtleTunnel>::iterator it2( _local_tunnels.find(it->second) ) ;
|
||||
if(it2 != _local_tunnels.end())
|
||||
{
|
||||
if(it2->second.local_src == _own_id)
|
||||
|
@ -2077,6 +2236,28 @@ std::string p3turtle::getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_i
|
|||
return name;
|
||||
}
|
||||
|
||||
bool p3turtle::encryptData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item)
|
||||
{
|
||||
unsigned char *encrypted_data = NULL ;
|
||||
uint32_t encrypted_data_len = 0 ;
|
||||
|
||||
if(!librs::crypto::encryptAuthenticateData(clear_data,clear_data_size,encryption_master_key,encrypted_data,encrypted_data_len))
|
||||
{
|
||||
delete encrypted_item ;
|
||||
return false ;
|
||||
}
|
||||
encrypted_item = new RsTurtleGenericDataItem ;
|
||||
|
||||
encrypted_item->data_bytes = encrypted_data ;
|
||||
encrypted_item->data_size = encrypted_data_len ;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3turtle::decryptItem(const RsTurtleGenericDataItem* encrypted_item, uint8_t *encryption_master_key, unsigned char *& decrypted_data, uint32_t& decrypted_data_size)
|
||||
{
|
||||
return librs::crypto::decryptAuthenticateData((unsigned char*)encrypted_item->data_bytes,encrypted_item->data_size,encryption_master_key,decrypted_data,decrypted_data_size);
|
||||
}
|
||||
|
||||
void p3turtle::getInfo( std::vector<std::vector<std::string> >& hashes_info,
|
||||
std::vector<std::vector<std::string> >& tunnels_info,
|
||||
std::vector<TurtleSearchRequestDisplayInfo >& search_reqs_info,
|
||||
|
@ -2111,12 +2292,12 @@ void p3turtle::getInfo( std::vector<std::vector<std::string> >& hashes_info,
|
|||
tunnel.push_back(printNumber(it->first,true)) ;
|
||||
|
||||
std::string name;
|
||||
if(mLinkMgr->getPeerName(it->second.local_src,name))
|
||||
if(mLinkMgr->getPeerName(it->second.local_src,name))
|
||||
tunnel.push_back(name) ;
|
||||
else
|
||||
tunnel.push_back(it->second.local_src.toStdString()) ;
|
||||
|
||||
if(mLinkMgr->getPeerName(it->second.local_dst,name))
|
||||
if(mLinkMgr->getPeerName(it->second.local_dst,name))
|
||||
tunnel.push_back(name) ;
|
||||
else
|
||||
tunnel.push_back(it->second.local_dst.toStdString());
|
||||
|
|
|
@ -166,10 +166,12 @@ class TurtleSearchRequestInfo
|
|||
{
|
||||
public:
|
||||
TurtlePeerId origin ; // where the request came from.
|
||||
uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels.
|
||||
int depth ; // depth of the request. Used to optimize tunnel length.
|
||||
uint32_t result_count; // responses to this request. Useful to avoid spamming tunnel responses.
|
||||
std::string keywords;
|
||||
uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels.
|
||||
int depth ; // depth of the request. Used to optimize tunnel length.
|
||||
uint32_t result_count; // responses to this request. Useful to avoid spamming tunnel responses.
|
||||
std::string keywords;
|
||||
uint16_t service_id; // ID of the client service who issues the request. This is null if the request does not have a local origin.
|
||||
uint32_t max_allowed_hits;// Max number of hits allowed for this search. This actually depends on the type of search (files, GXS groups, GXS group data, etc)
|
||||
};
|
||||
class TurtleTunnelRequestInfo
|
||||
{
|
||||
|
@ -241,11 +243,16 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
|
|||
// the request id, which will be further used by the gui to store results
|
||||
// as they come back.
|
||||
//
|
||||
// Eventually, search requests should be handled by client services. We will therefore
|
||||
// remove the specific file search packets from the turtle router.
|
||||
//
|
||||
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ;
|
||||
// The first two methods are old style search requests for FT, while the 3rd one is using a generic search data type, that is only to
|
||||
// be deserialized by the service. The memory ownership is kept by the calling function. Similarly, the search response will be a
|
||||
// generic data type that is to be deserialized by the client service.
|
||||
//
|
||||
// Eventually, search requests will use the generic system
|
||||
// even for FT. We need to keep the old method for a while for backward compatibility.
|
||||
//
|
||||
virtual TurtleRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ;
|
||||
virtual TurtleRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
virtual TurtleRequestId turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) ;
|
||||
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the initialization process. The
|
||||
|
@ -329,6 +336,12 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
|
|||
/// Send a data request into the correct tunnel for the given file hash
|
||||
void sendTurtleData(const RsPeerId& virtual_peer_id, RsTurtleGenericTunnelItem *item) ;
|
||||
|
||||
/// Encrypts/decrypts an item, using a autenticated construction + chacha20, based on the given 32 bytes master key.
|
||||
/// Input values are not touched (memory is not released). Memory ownership of outputs is left to the client.
|
||||
///
|
||||
static bool encryptData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item);
|
||||
static bool decryptItem(const RsTurtleGenericDataItem *item, uint8_t* encryption_master_key, unsigned char *& decrypted_data,uint32_t& decrypted_data_size);
|
||||
|
||||
private:
|
||||
//--------------------------- Admin/Helper functions -------------------------//
|
||||
|
||||
|
@ -382,10 +395,9 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
|
|||
//------ 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) ;
|
||||
void performLocalSearch (RsTurtleSearchRequestItem *item, uint32_t& req_result_count,std::list<RsTurtleSearchResultItem*>& result,uint32_t& max_allowed_hits) ;
|
||||
void performLocalSearch_files (RsTurtleFileSearchRequestItem *item, uint32_t& req_result_count, std::list<RsTurtleSearchResultItem*>& result, uint32_t &max_allowed_hits) ;
|
||||
void performLocalSearch_generic(RsTurtleGenericSearchRequestItem *item, uint32_t& req_result_count, std::list<RsTurtleSearchResultItem*>& result, uint32_t &max_allowed_hits) ;
|
||||
|
||||
/// Returns true if the file with given hash is hosted locally, and accessible in anonymous mode the supplied peer.
|
||||
virtual bool performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId& client_peer_id,RsTurtleClientService *& service);
|
||||
|
@ -407,7 +419,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
|
|||
std::map<TurtleTunnelRequestId,TurtleTunnelRequestInfo> _tunnel_requests_origins ;
|
||||
|
||||
/// stores adequate tunnels for each file hash locally managed
|
||||
std::map<TurtleFileHash,TurtleHashInfo> _incoming_file_hashes ;
|
||||
std::map<TurtleFileHash,TurtleHashInfo> _incoming_file_hashes ;
|
||||
|
||||
/// stores file info for each file we provide.
|
||||
std::map<TurtleTunnelId,RsTurtleClientService *> _outgoing_tunnel_client_services ;
|
||||
|
@ -422,7 +434,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
|
|||
std::set<TurtleFileHash> _hashes_to_remove ;
|
||||
|
||||
/// List of client services that have regitered.
|
||||
std::list<RsTurtleClientService*> _registered_services ;
|
||||
std::map<uint16_t,RsTurtleClientService*> _registered_services ;
|
||||
|
||||
time_t _last_clean_time ;
|
||||
time_t _last_tunnel_management_time ;
|
||||
|
|
|
@ -49,10 +49,12 @@ RsItem *RsTurtleSerialiser::create_item(uint16_t service,uint8_t item_subtype) c
|
|||
{
|
||||
case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST : return new RsTurtleStringSearchRequestItem();
|
||||
case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST : return new RsTurtleRegExpSearchRequestItem();
|
||||
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : return new RsTurtleSearchResultItem();
|
||||
case RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT : return new RsTurtleFTSearchResultItem();
|
||||
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem();
|
||||
case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_DATA : return new RsTurtleGenericDataItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST : return new RsTurtleGenericSearchRequestItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT : return new RsTurtleGenericSearchResultItem();
|
||||
|
||||
default:
|
||||
break ;
|
||||
|
@ -69,20 +71,44 @@ RsItem *RsTurtleSerialiser::create_item(uint16_t service,uint8_t item_subtype) c
|
|||
return NULL ;
|
||||
}
|
||||
|
||||
std::string RsTurtleGenericSearchRequestItem::GetKeywords()
|
||||
{
|
||||
return std::string("Generic search : " + RsUtil::BinToHex(search_data,search_data_len,10));
|
||||
}
|
||||
|
||||
void RsTurtleStringSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_VALUE,match_string,"match_string") ;
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,request_id,"request_id") ;
|
||||
RsTypeSerializer::serial_process<uint16_t>(j,ctx,depth ,"depth") ;
|
||||
}
|
||||
|
||||
void RsTurtleRegExpSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,request_id,"request_id") ;
|
||||
RsTypeSerializer::serial_process<uint16_t>(j,ctx,depth,"depth") ;
|
||||
RsTypeSerializer::serial_process(j,ctx,expr,"expr") ;
|
||||
}
|
||||
void RsTurtleGenericSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,request_id,"request_id") ;
|
||||
RsTypeSerializer::serial_process<uint16_t>(j,ctx,depth,"depth") ;
|
||||
RsTypeSerializer::serial_process<uint16_t>(j,ctx,service_id,"service_id") ;
|
||||
RsTypeSerializer::serial_process<uint8_t >(j,ctx,request_type,"request_type") ;
|
||||
|
||||
RsTypeSerializer::TlvMemBlock_proxy prox(search_data,search_data_len) ;
|
||||
RsTypeSerializer::serial_process(j,ctx,prox,"search_data") ;
|
||||
}
|
||||
RsTurtleSearchRequestItem *RsTurtleGenericSearchRequestItem::clone() const
|
||||
{
|
||||
RsTurtleGenericSearchRequestItem *sr = new RsTurtleGenericSearchRequestItem ;
|
||||
|
||||
memcpy(sr,this,sizeof(RsTurtleGenericSearchRequestItem)) ;
|
||||
|
||||
sr->search_data = (unsigned char*)rs_malloc(search_data_len) ;
|
||||
memcpy(sr->search_data,search_data,search_data_len) ;
|
||||
|
||||
return sr ;
|
||||
}
|
||||
template<> uint32_t RsTypeSerializer::serial_size(const RsRegularExpression::LinearizedExpression& r)
|
||||
{
|
||||
uint32_t s = 0 ;
|
||||
|
@ -164,12 +190,31 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsRegul
|
|||
RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression)
|
||||
RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression)
|
||||
|
||||
void RsTurtleSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
void RsTurtleFTSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,request_id,"request_id") ;
|
||||
RsTypeSerializer::serial_process<uint16_t>(j,ctx,depth ,"depth") ;
|
||||
RsTypeSerializer::serial_process (j,ctx,result ,"result") ;
|
||||
}
|
||||
void RsTurtleGenericSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,request_id,"request_id") ;
|
||||
RsTypeSerializer::serial_process<uint16_t>(j,ctx,depth ,"depth") ;
|
||||
|
||||
RsTypeSerializer::TlvMemBlock_proxy prox(result_data,result_data_len) ;
|
||||
RsTypeSerializer::serial_process(j,ctx,prox,"search_data") ;
|
||||
}
|
||||
RsTurtleSearchResultItem *RsTurtleGenericSearchResultItem::duplicate() const
|
||||
{
|
||||
RsTurtleGenericSearchResultItem *sr = new RsTurtleGenericSearchResultItem ;
|
||||
|
||||
sr->result_data = (unsigned char*)rs_malloc(result_data_len) ;
|
||||
memcpy(sr->result_data,result_data,result_data_len) ;
|
||||
sr->result_data_len = result_data_len ;
|
||||
sr->request_id = request_id ;
|
||||
sr->depth = depth ;
|
||||
return sr ;
|
||||
}
|
||||
|
||||
template<> uint32_t RsTypeSerializer::serial_size(const TurtleFileInfo& i)
|
||||
{
|
||||
|
|
|
@ -37,20 +37,24 @@
|
|||
#include "serialiser/rsserializer.h"
|
||||
|
||||
const uint8_t RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST = 0x01 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_SEARCH_RESULT = 0x02 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT = 0x02 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_OPEN_TUNNEL = 0x03 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_TUNNEL_OK = 0x04 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_FILE_REQUEST = 0x07 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_FILE_DATA = 0x08 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST = 0x09 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_GENERIC_DATA = 0x0a ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST = 0x0b ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT = 0x0c ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP = 0x10 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST = 0x11 ;
|
||||
// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC = 0x12 ; // unused
|
||||
// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST = 0x13 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC = 0x14 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST = 0x15 ;
|
||||
|
||||
// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC = 0x12 ; // unused
|
||||
// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST = 0x13 ;
|
||||
|
||||
class TurtleSearchRequestInfo ;
|
||||
|
||||
/***********************************************************************************/
|
||||
/* Basic Turtle Item Class */
|
||||
|
@ -67,49 +71,66 @@ class RsTurtleItem: public RsItem
|
|||
/* Specific packets */
|
||||
/***********************************************************************************/
|
||||
|
||||
class RsTurtleSearchResultItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleSearchResultItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT), request_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT) ;}
|
||||
// Class hierarchy is
|
||||
//
|
||||
// RsTurtleItem
|
||||
// |
|
||||
// +---- RsTurtleSearchRequestItem
|
||||
// | |
|
||||
// | +---- RsTurtleFileSearchRequestItem
|
||||
// | | |
|
||||
// | | +---- RsTurtleStringSearchRequestItem
|
||||
// | | |
|
||||
// | | +---- RsTurtleReqExpSearchRequestItem
|
||||
// | |
|
||||
// | +---- RsTurtleGenericSearchRequestItem
|
||||
// |
|
||||
// +---- RsTurtleSearchResultItem
|
||||
// |
|
||||
// +---- RsTurtleFTSearchResultItem
|
||||
// |
|
||||
// +---- RsTurtleGenericSearchResultItem
|
||||
//
|
||||
|
||||
TurtleSearchRequestId request_id ; // Randomly generated request id.
|
||||
|
||||
uint16_t depth ; // The depth of a search result is obfuscated in this way:
|
||||
// If the actual depth is 1, this field will be 1.
|
||||
// If the actual depth is > 1, this field is a larger arbitrary integer.
|
||||
std::list<TurtleFileInfo> result ;
|
||||
|
||||
void clear() { result.clear() ; }
|
||||
protected:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
|
||||
};
|
||||
class RsTurtleSearchResultItem ;
|
||||
|
||||
class RsTurtleSearchRequestItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleSearchRequestItem(uint32_t subtype) : RsTurtleItem(subtype), request_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST) ;}
|
||||
virtual ~RsTurtleSearchRequestItem() {}
|
||||
|
||||
virtual RsTurtleSearchRequestItem *clone() const = 0 ; // used for cloning in routing methods
|
||||
|
||||
virtual void performLocalSearch(std::list<TurtleFileInfo>&) const = 0 ; // abstracts the search method
|
||||
|
||||
virtual std::string GetKeywords() = 0;
|
||||
|
||||
virtual uint16_t serviceId() const= 0 ;
|
||||
|
||||
uint32_t request_id ; // randomly generated request id.
|
||||
uint16_t depth ; // Used for limiting search depth.
|
||||
};
|
||||
|
||||
class RsTurtleStringSearchRequestItem: public RsTurtleSearchRequestItem
|
||||
class RsTurtleFileSearchRequestItem: public RsTurtleSearchRequestItem
|
||||
{
|
||||
public:
|
||||
RsTurtleStringSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {}
|
||||
|
||||
RsTurtleFileSearchRequestItem(uint32_t subtype) : RsTurtleSearchRequestItem(subtype) {}
|
||||
virtual ~RsTurtleFileSearchRequestItem() {}
|
||||
|
||||
virtual uint16_t serviceId() const { return RS_SERVICE_TYPE_FILE_TRANSFER ; }
|
||||
virtual void search(std::list<TurtleFileInfo> &) const =0;
|
||||
};
|
||||
|
||||
class RsTurtleStringSearchRequestItem: public RsTurtleFileSearchRequestItem
|
||||
{
|
||||
public:
|
||||
RsTurtleStringSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {}
|
||||
virtual ~RsTurtleStringSearchRequestItem() {}
|
||||
|
||||
virtual void search(std::list<TurtleFileInfo> &) const ;
|
||||
|
||||
std::string match_string ; // string to match
|
||||
|
||||
std::string GetKeywords() { return match_string; }
|
||||
|
||||
|
||||
virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleStringSearchRequestItem(*this) ; }
|
||||
virtual void performLocalSearch(std::list<TurtleFileInfo>&) const ;
|
||||
|
||||
void clear() { match_string.clear() ; }
|
||||
|
||||
|
@ -117,10 +138,11 @@ class RsTurtleStringSearchRequestItem: public RsTurtleSearchRequestItem
|
|||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
};
|
||||
|
||||
class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem
|
||||
class RsTurtleRegExpSearchRequestItem: public RsTurtleFileSearchRequestItem
|
||||
{
|
||||
public:
|
||||
RsTurtleRegExpSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {}
|
||||
RsTurtleRegExpSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {}
|
||||
virtual ~RsTurtleRegExpSearchRequestItem() {}
|
||||
|
||||
RsRegularExpression::LinearizedExpression expr ; // Reg Exp in linearised mode
|
||||
|
||||
|
@ -131,15 +153,91 @@ class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem
|
|||
delete ex;
|
||||
return exs;
|
||||
}
|
||||
|
||||
virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; }
|
||||
virtual void performLocalSearch(std::list<TurtleFileInfo>&) const ;
|
||||
|
||||
virtual void search(std::list<TurtleFileInfo> &) const ;
|
||||
|
||||
virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; }
|
||||
void clear() { expr = RsRegularExpression::LinearizedExpression(); }
|
||||
protected:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
};
|
||||
|
||||
class RsTurtleGenericSearchRequestItem: public RsTurtleSearchRequestItem
|
||||
{
|
||||
public:
|
||||
RsTurtleGenericSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST) {}
|
||||
virtual ~RsTurtleGenericSearchRequestItem() { clear(); }
|
||||
|
||||
uint16_t service_id ; // service to search
|
||||
uint32_t search_data_len ;
|
||||
uint8_t request_type ; // type of request. This is used to limit the number of responses.
|
||||
unsigned char *search_data ;
|
||||
|
||||
std::string GetKeywords() ;
|
||||
virtual uint16_t serviceId() const { return service_id ; }
|
||||
|
||||
virtual RsTurtleSearchRequestItem *clone() const ;
|
||||
virtual uint32_t requestType() const { return request_type; }
|
||||
|
||||
void clear() { free(search_data); search_data=NULL; search_data_len=0; }
|
||||
|
||||
protected:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
|
||||
private:
|
||||
RsTurtleGenericSearchRequestItem(const RsTurtleGenericSearchRequestItem&): RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST) {} // make the object non copi-able.
|
||||
RsTurtleGenericSearchRequestItem& operator=(const RsTurtleGenericSearchRequestItem&) { return *this;}
|
||||
};
|
||||
class RsTurtleSearchResultItem: public RsTurtleItem
|
||||
{
|
||||
public:
|
||||
RsTurtleSearchResultItem(uint8_t subtype) : RsTurtleItem(subtype), request_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT) ;}
|
||||
|
||||
TurtleSearchRequestId request_id ; // Randomly generated request id.
|
||||
uint16_t depth ; // The depth of a search result is obfuscated in this way:
|
||||
// If the actual depth is 1, this field will be 1.
|
||||
// If the actual depth is > 1, this field is a larger arbitrary integer.
|
||||
|
||||
virtual uint32_t count() const =0;
|
||||
virtual void pop() =0;
|
||||
|
||||
virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)=0;
|
||||
virtual RsTurtleSearchResultItem *duplicate() const =0;
|
||||
};
|
||||
|
||||
class RsTurtleFTSearchResultItem: public RsTurtleSearchResultItem
|
||||
{
|
||||
public:
|
||||
RsTurtleFTSearchResultItem() : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT){}
|
||||
|
||||
std::list<TurtleFileInfo> result ;
|
||||
|
||||
void clear() { result.clear() ; }
|
||||
uint32_t count() const { return result.size() ; }
|
||||
virtual void pop() { result.pop_back() ;}
|
||||
virtual RsTurtleSearchResultItem *duplicate() const { return new RsTurtleFTSearchResultItem(*this) ; }
|
||||
protected:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
};
|
||||
|
||||
class RsTurtleGenericSearchResultItem: public RsTurtleSearchResultItem
|
||||
{
|
||||
public:
|
||||
RsTurtleGenericSearchResultItem() : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT){}
|
||||
virtual ~RsTurtleGenericSearchResultItem() {}
|
||||
|
||||
uint32_t count() const { return result_data_len/50 ; } // This is a blind size estimate. We should probably use the actual size to limit search results.
|
||||
virtual void pop() {}
|
||||
|
||||
unsigned char *result_data ;
|
||||
uint32_t result_data_len ;
|
||||
|
||||
virtual RsTurtleSearchResultItem *duplicate() const ;
|
||||
void clear() { free(result_data); result_data=NULL; result_data_len=0; }
|
||||
protected:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
};
|
||||
|
||||
/***********************************************************************************/
|
||||
/* Turtle Tunnel Item classes */
|
||||
/***********************************************************************************/
|
||||
|
@ -149,10 +247,10 @@ class RsTurtleOpenTunnelItem: public RsTurtleItem
|
|||
public:
|
||||
RsTurtleOpenTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL), request_id(0), partial_tunnel_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL) ;}
|
||||
|
||||
TurtleFileHash file_hash ; // hash to match
|
||||
uint32_t request_id ; // randomly generated request id.
|
||||
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.
|
||||
uint16_t depth ; // Used for limiting search depth.
|
||||
|
||||
void clear() { file_hash.clear() ;}
|
||||
protected:
|
||||
|
@ -188,24 +286,24 @@ class RsTurtleGenericTunnelItem: public RsTurtleItem
|
|||
|
||||
/// Does this packet stamps tunnels when it passes through ?
|
||||
/// This is used for keeping trace weither tunnels are active or not.
|
||||
|
||||
|
||||
virtual bool shouldStampTunnel() const = 0 ;
|
||||
|
||||
/// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to
|
||||
/// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to
|
||||
/// indicate which tunnel they are travelling through.
|
||||
|
||||
|
||||
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
|
||||
|
||||
/// Indicate weither the packet is a client packet (goign back to the
|
||||
/// client) or a server packet (going to the server. Typically file
|
||||
/// requests are server packets, whereas file data are client packets.
|
||||
|
||||
|
||||
virtual Direction travelingDirection() const { return direction ; }
|
||||
virtual void setTravelingDirection(Direction d) { direction = d; }
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -39,51 +39,125 @@ class p3turtle ;
|
|||
class RsTurtleClientService
|
||||
{
|
||||
public:
|
||||
// Handling of tunnel request for the given hash. Most of the time, it's a search in a predefined list.
|
||||
// The output info_string is used by the turtle router to display info about tunnels it manages. It is
|
||||
// not passed to the tunnel.
|
||||
/*!
|
||||
* \brief serviceId
|
||||
* Returns the ID of the client service. This is used to pass the ID to search requests, from the client services
|
||||
* \return
|
||||
* The service ID.
|
||||
*/
|
||||
|
||||
virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) { return false ; }
|
||||
virtual uint16_t serviceId() const
|
||||
{
|
||||
std::cerr << "!!!!!! Received request for service ID in turtle router client, but the client service is not handling it !!!!!!!" << std::endl ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief handleTunnelRequest
|
||||
Handling of tunnel request for the given hash. To be derived by the service in order to tell the turtle router
|
||||
whether the service handles this hash or not. Most of the time, it's a search in a predefined list.
|
||||
|
||||
* \return true if the service
|
||||
*/
|
||||
virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) { return false ; }
|
||||
|
||||
// This method is called by the turtle router to send data that comes out of a turtle tunnel.
|
||||
// The turtle router stays responsible for the memory management of data. Most of the time the
|
||||
// data chunk is a serialized item to be de-serialized by the client service.
|
||||
//
|
||||
// Parameters:
|
||||
// virtual_peer_id : name of the tunnel that sent the data
|
||||
// data : memory chunk for the data
|
||||
// size : size of data
|
||||
// item->direction : direction of travel:
|
||||
// RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a client
|
||||
// RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a server
|
||||
//
|
||||
// Most of the time this parameter is not used by services, except when some info (such as chunk maps, chat items, etc) go
|
||||
// both ways, and their nature cannot suffice to determine where they should be handled.
|
||||
//
|
||||
// By default (if not overloaded), the method will just free the data, as any subclass should do as well.
|
||||
// Note: p3turtle stays owner of the item, so the client should not delete it!
|
||||
//
|
||||
virtual void receiveTurtleData(RsTurtleGenericTunnelItem */*item*/,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/)
|
||||
/*!
|
||||
* \brief receiveTurtleData
|
||||
* This method is called by the turtle router to send data that comes out of a turtle tunnel, and should
|
||||
* be overloaded by the client service.
|
||||
* The turtle router stays responsible for the memory management of data. Most of the time the
|
||||
* data chunk is a serialized item to be de-serialized by the client service.
|
||||
*
|
||||
* Parameters:
|
||||
* virtual_peer_id : name of the tunnel that sent the data
|
||||
* data : memory chunk for the data
|
||||
* size : size of data
|
||||
* item->direction : direction of travel:
|
||||
* RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a client
|
||||
* RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a server
|
||||
*
|
||||
* Most of the time this parameter is not used by services, except when some info (such as chunk maps, chat items, etc) go
|
||||
* both ways, and their nature cannot suffice to determine where they should be handled.
|
||||
*
|
||||
* By default (if not overloaded), the method will just free the data, as any subclass should do as well.
|
||||
* Note: p3turtle stays owner of the item, so the client should not delete it!
|
||||
*/
|
||||
virtual void receiveTurtleData(const RsTurtleGenericTunnelItem * /* item */,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/)
|
||||
{
|
||||
std::cerr << "!!!!!! Received Data from turtle router, but the client service is not handling it !!!!!!!!!!" << std::endl ;
|
||||
}
|
||||
|
||||
// Method for creating specific items of the client service. The
|
||||
// method has a default behavior of not doing anything, since most client
|
||||
// services might only use the generic item already provided by the turtle
|
||||
// router: RsTurtleGenericDataItem
|
||||
/*!
|
||||
* \brief receiveSearchRequest
|
||||
* This method is called by the turtle router to notify the client of a search request in the form generic data. The returned
|
||||
* result contains the serialised generic result returned by the client.
|
||||
*
|
||||
* The turtle router keeps the memory ownership over search_request_data
|
||||
*
|
||||
* \param search_request_data generic serialized search data
|
||||
* \param search_request_data_len length of the serialized search data
|
||||
* \param search_result_data generic serialized search result data
|
||||
* \param search_result_data_len length of the serialized search result data
|
||||
* \param max_allowed_hits max number of hits allowed to be sent back and forwarded
|
||||
*
|
||||
* \return true if the search is successful.
|
||||
*/
|
||||
virtual bool receiveSearchRequest(unsigned char */*search_request_data*/,
|
||||
uint32_t /*search_request_data_len*/,
|
||||
unsigned char *& /*search_result_data*/,
|
||||
uint32_t& /*search_result_data_len*/,
|
||||
uint32_t& /* max_allows_hits */)
|
||||
{
|
||||
std::cerr << "!!!!!! Received search result from turtle router, but the client service who requested it is not handling it !!!!!!!!!!" << std::endl ;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief receiveSearchResult
|
||||
* This method is called by the turtle router to notify the client of a search result. The result is serialized for the current class to read.
|
||||
*
|
||||
* \param search_result_data result data. Memory ownership is owned by the turtle router. So do not delete!
|
||||
* \param search_result_data length of result data
|
||||
*/
|
||||
virtual void receiveSearchResult(TurtleSearchRequestId /* request_id */,unsigned char * /*search_result_data*/,uint32_t /*search_result_data_len*/)
|
||||
{
|
||||
std::cerr << "!!!!!! Received search result from turtle router, but the client service who requested it is not handling it !!!!!!!!!!" << std::endl ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief serializer
|
||||
* Method for creating specific items of the client service. The
|
||||
* method has a default behavior of not doing anything, since most client
|
||||
* services might only use the generic item already provided by the turtle
|
||||
* router: RsTurtleGenericDataItem
|
||||
*
|
||||
* \return the client's serializer is returned
|
||||
*/
|
||||
virtual RsServiceSerializer *serializer() { return NULL ; }
|
||||
|
||||
// These methods are called by the turtle router to add/remove virtual peers when tunnels are created/deleted
|
||||
//
|
||||
/*!
|
||||
* \brief addVirtualPeer
|
||||
* These methods are called by the turtle router to notify the client in order to add/remove virtual peers when tunnels are created/deleted
|
||||
* These methods must be overloaded, because a service which does not care about tunel being openned or closed is not supposed to need tunnels.
|
||||
*
|
||||
* \param hash hash that the tunnel responds to
|
||||
* \param virtual_peer_id virtual peer id provided by turtle to allow the client to send data into this tunnel. This peer is related to the tunnel itself
|
||||
* rather than to its destination. As such, multiple peer ids may actually send data to the same computer because multiple tunnels
|
||||
* arrive at the same location.
|
||||
* \param dir dir indicates which side the cient will be talking to: CLIENT means that the client is the server. SERVER means that the client acts
|
||||
* as a client (and therefore actually requested the tunnel).
|
||||
*/
|
||||
virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) = 0 ;
|
||||
virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) = 0 ;
|
||||
|
||||
// This function is mandatory. It should do two things:
|
||||
// 1 - keep a pointer to the turtle router, so as to be able to send data (e.g. copy pt into a local variable)
|
||||
// 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it.
|
||||
//
|
||||
/*!
|
||||
* \brief connectToTurtleRouter
|
||||
* This function must be overloaded by the client. It should do two things:
|
||||
* 1 - keep a pointer to the turtle router, so as to be able to send data (e.g. store pt into a local variable)
|
||||
* 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it.
|
||||
*
|
||||
* \param pt A pointer to the turtle router.
|
||||
*/
|
||||
virtual void connectToTurtleRouter(p3turtle *pt) = 0 ;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue