mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
turtle tunnel management
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1289 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
2bd3899c05
commit
48218e98cb
@ -119,7 +119,32 @@ void ftController::addFileSource(const std::string& hash,const std::string& peer
|
||||
std::cerr << "... not added: hash not found." << std::endl ;
|
||||
#endif
|
||||
}
|
||||
void ftController::removeFileSource(const std::string& hash,const std::string& peer_id)
|
||||
{
|
||||
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
|
||||
|
||||
std::map<std::string, ftFileControl>::iterator it;
|
||||
std::map<std::string, ftFileControl> currentDownloads = *(&mDownloads);
|
||||
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ;
|
||||
#endif
|
||||
for(it = currentDownloads.begin(); it != currentDownloads.end(); it++)
|
||||
if(it->first == hash)
|
||||
{
|
||||
it->second.mTransfer->removeFileSource(peer_id);
|
||||
|
||||
// setPeerState(it->second.mTransfer, peer_id, rate, mConnMgr->isOnline(peer_id));
|
||||
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "... added." << std::endl ;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "... not added: hash not found." << std::endl ;
|
||||
#endif
|
||||
}
|
||||
void ftController::run()
|
||||
{
|
||||
|
||||
|
@ -162,6 +162,7 @@ virtual bool CancelCacheFile(RsPeerId id, std::string path, std::string hash, ui
|
||||
public:
|
||||
virtual void statusChange(const std::list<pqipeer> &plist);
|
||||
void addFileSource(const std::string& hash,const std::string& peer_id) ;
|
||||
void removeFileSource(const std::string& hash,const std::string& peer_id) ;
|
||||
|
||||
|
||||
/* p3Config Interface */
|
||||
|
@ -151,6 +151,27 @@ bool ftTransferModule::addFileSource(std::string peerId)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftTransferModule::removeFileSource(std::string peerId)
|
||||
{
|
||||
RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/
|
||||
std::map<std::string,peerInfo>::iterator mit;
|
||||
mit = mFileSources.find(peerId);
|
||||
|
||||
if (mit != mFileSources.end())
|
||||
{
|
||||
/* add in new source */
|
||||
mFileSources.erase(mit) ;
|
||||
#ifdef FT_DEBUG
|
||||
std::cerr << "ftTransferModule::addFileSource(): removing peer: " << peerId << " from sourceList" << std::cerr << std::endl;
|
||||
#endif
|
||||
}
|
||||
#ifdef FT_DEBUG
|
||||
else
|
||||
std::cerr << "ftTransferModule::addFileSource(): Should remove peer: " << peerId << ", but it's not in the source list. " << std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftTransferModule::setPeerState(std::string peerId,uint32_t state,uint32_t maxRate)
|
||||
{
|
||||
|
@ -131,6 +131,7 @@ public:
|
||||
//interface to download controller
|
||||
bool setFileSources(std::list<std::string> peerIds);
|
||||
bool addFileSource(std::string peerId);
|
||||
bool removeFileSource(std::string peerId);
|
||||
bool setPeerState(std::string peerId,uint32_t state,uint32_t maxRate); //state = ONLINE/OFFLINE
|
||||
bool getFileSources(std::list<std::string> &peerIds);
|
||||
bool getPeerState(std::string peerId,uint32_t &state,uint32_t &tfRate);
|
||||
|
@ -69,6 +69,9 @@ const uint32_t CONFIG_TYPE_FT_SHARED = 0x0007;
|
||||
const uint32_t CONFIG_TYPE_FT_EXTRA_LIST= 0x0008;
|
||||
const uint32_t CONFIG_TYPE_FT_CONTROL = 0x0009;
|
||||
|
||||
/* turtle router */
|
||||
const uint32_t CONFIG_TYPE_TURTLE = 0x0020;
|
||||
|
||||
/* wish these ids where higher...
|
||||
* may move when switch to v0.5
|
||||
*/
|
||||
|
@ -67,11 +67,18 @@ class RsTurtle
|
||||
//
|
||||
virtual TurtleRequestId turtleSearch(const std::string& match_string) = 0 ;
|
||||
|
||||
// Launches a complete download file operation: diggs one or more
|
||||
// tunnels. Launches an exception if an error occurs during the
|
||||
// initialization process.
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the 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 by calling ftServer::FileRequest().
|
||||
//
|
||||
virtual void turtleDownload(const std::string& name,const std::string& file_hash,uint64_t size) = 0 ;
|
||||
virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) = 0 ;
|
||||
|
||||
// Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should
|
||||
// be called after calling ftServer::fileCancel().
|
||||
//
|
||||
virtual void stopMonitoringFileTunnels(const std::string& file_hash) = 0 ;
|
||||
|
||||
// Sets the file sharing strategy. It concerns all local files. It would
|
||||
// be better to handle this for each file, of course.
|
||||
|
@ -813,6 +813,7 @@ int RsServer::StartupRetroShare()
|
||||
mConfigMgr->addConfiguration("ranklink.cfg", mRanking);
|
||||
mConfigMgr->addConfiguration("forums.cfg", mForums);
|
||||
mConfigMgr->addConfiguration("channels.cfg", mChannels);
|
||||
mConfigMgr->addConfiguration("turtle.cfg", tr);
|
||||
|
||||
#ifndef RS_RELEASE
|
||||
#else
|
||||
|
@ -53,17 +53,20 @@
|
||||
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsprint.h"
|
||||
|
||||
// Operating System specific includes.
|
||||
#include "pqi/pqinetwork.h"
|
||||
|
||||
static const unsigned int TUNNEL_REQUESTS_LIFE_TIME = 120 ; // life time for requests in the cache.
|
||||
static const unsigned int SEARCH_REQUESTS_LIFE_TIME = 120 ;
|
||||
|
||||
/* TURTLE FLAGS */
|
||||
// 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.
|
||||
//
|
||||
static const time_t TUNNEL_REQUESTS_LIFE_TIME = 120 ; /// life time for tunnel requests in the cache.
|
||||
static const time_t SEARCH_REQUESTS_LIFE_TIME = 120 ; /// 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 = 600 ; /// maximum life time of an unused tunnel.
|
||||
static const time_t MAXIMUM_HASH_IDLE_TIME = 300 ; /// maximum life time of an unused file hash.
|
||||
|
||||
p3turtle::p3turtle(p3ConnectMgr *cm,ftServer *fs)
|
||||
:p3Service(RS_SERVICE_TYPE_TURTLE), mConnMgr(cm)
|
||||
:p3Service(RS_SERVICE_TYPE_TURTLE), mConnMgr(cm), p3Config(CONFIG_TYPE_TURTLE)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
@ -79,19 +82,28 @@ p3turtle::p3turtle(p3ConnectMgr *cm,ftServer *fs)
|
||||
|
||||
int p3turtle::tick()
|
||||
{
|
||||
// Handle tunnel trafic
|
||||
//
|
||||
handleIncoming(); // handle incoming packets
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
// Manage tunnels every 10 sec.
|
||||
// Tunnel management:
|
||||
// - we digg new tunnels at least every 5 min (300 sec).
|
||||
// - we digg new tunnels each time a new peer connects
|
||||
// - we digg new tunnels each time a new hash is asked for
|
||||
//
|
||||
if(now > 10+_last_tunnel_management_time)
|
||||
if(now > REGULAR_TUNNEL_DIGGING_TIME+_last_tunnel_management_time || _force_digg_new_tunnels)
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Calling tunnel management." << std::endl ;
|
||||
#endif
|
||||
manageTunnels() ;
|
||||
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
_last_tunnel_management_time = now ;
|
||||
_force_digg_new_tunnels = false ;
|
||||
}
|
||||
|
||||
// Clean every 10 sec.
|
||||
@ -101,12 +113,12 @@ int p3turtle::tick()
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Calling autowash." << std::endl ;
|
||||
#endif
|
||||
autoWash() ; // clean old/unused tunnels and search requests.
|
||||
autoWash() ; // clean old/unused tunnels and file hashes, as well as search and tunnel requests.
|
||||
_last_clean_time = now ;
|
||||
}
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
// Dump state every 20 sec.
|
||||
// Dump state for debugging, every 20 sec.
|
||||
//
|
||||
static time_t last_dump = time(NULL) ;
|
||||
|
||||
@ -132,38 +144,27 @@ void p3turtle::statusChange(const std::list<pqipeer> &plist) // derived from pqi
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
// Do we shutdown tunnels whne peers are down, or automatically find a new tunnel ?
|
||||
// I'll see that later...
|
||||
// We actually do not shut down tunnels when peers get down: Tunnels that
|
||||
// are not working properly get automatically removed after some time.
|
||||
|
||||
// save the list of active peers. This is useful for notifying the ftContoller
|
||||
_online_peers = plist ;
|
||||
|
||||
std::cerr << "p3turtle: status change triggered. Saving list of " << plist.size() << " peers." << std::endl ;
|
||||
#ifdef TO_DO
|
||||
/* get a list of all online peers */
|
||||
std::list<std::string> onlineIds;
|
||||
mConnMgr->getOnlineList(onlineIds);
|
||||
|
||||
std::list<pqipeer>::const_iterator pit;
|
||||
/* if any have switched to 'connected' then we notify */
|
||||
for(pit = plist.begin(); pit != plist.end(); pit++)
|
||||
{
|
||||
if ((pit->state & RS_PEER_S_FRIEND) &&
|
||||
(pit->actions & RS_PEER_CONNECTED))
|
||||
{
|
||||
/* send our details to them */
|
||||
sendOwnDetails(pit->id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* if any have switched to 'connected' then we force digging new tunnels */
|
||||
|
||||
for(std::list<pqipeer>::const_iterator pit = plist.begin(); pit != plist.end(); pit++)
|
||||
if ((pit->state & RS_PEER_S_FRIEND) && (pit->actions & RS_PEER_CONNECTED))
|
||||
_force_digg_new_tunnels = true ;
|
||||
}
|
||||
|
||||
// adds a virtual peer to the list that is communicated ot ftController.
|
||||
//
|
||||
void p3turtle::addDistantPeer(const TurtleFileHash& hash,TurtleTunnelId tid)
|
||||
void p3turtle::addDistantPeer(const TurtleFileHash&,TurtleTunnelId tid)
|
||||
{
|
||||
char buff[400] ;
|
||||
sprintf(buff,"%s_%8x",hash.c_str(),tid) ;
|
||||
sprintf(buff,"Turtle tunnel %8x",tid) ;
|
||||
|
||||
{
|
||||
_virtual_peers[TurtleVirtualPeerId(buff)] = tid ;
|
||||
@ -198,21 +199,20 @@ void p3turtle::getVirtualPeersList(std::list<pqipeer>& list)
|
||||
//
|
||||
void p3turtle::manageTunnels()
|
||||
{
|
||||
// Digg new tunnels for waiting file hashes
|
||||
// Digg new tunnels for all file hashes
|
||||
|
||||
std::vector<std::string> hashes_to_digg ;
|
||||
std::vector<TurtleFileHash> hashes_to_digg ;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
for(std::map<TurtleFileHash,TurtleFileHashInfo>::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it)
|
||||
if(it->second.tunnels.empty())
|
||||
{
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "Tunnel management: No tunnels for hash " << it->first << ", digging new ones." << std::endl ;
|
||||
std::cerr << "Tunnel management: digging new tunnels for hash " << it->first << "." << std::endl ;
|
||||
#endif
|
||||
hashes_to_digg.push_back(it->first) ;
|
||||
}
|
||||
hashes_to_digg.push_back(it->first) ;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint i=0;i<hashes_to_digg.size();++i)
|
||||
@ -221,8 +221,6 @@ void p3turtle::manageTunnels()
|
||||
|
||||
void p3turtle::autoWash()
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " In autowash." << std::endl ;
|
||||
#endif
|
||||
@ -231,25 +229,157 @@ void p3turtle::autoWash()
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
for(std::map<TurtleSearchRequestId,TurtleRequestInfo>::iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it)
|
||||
if(now > (time_t)(it->second.time_stamp + SEARCH_REQUESTS_LIFE_TIME))
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " removed search request " << (void *)it->first << ", timeout." << std::endl ;
|
||||
#endif
|
||||
_search_requests_origins.erase(it) ;
|
||||
}
|
||||
// Search requests
|
||||
//
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
for(std::map<TurtleTunnelRequestId,TurtleRequestInfo>::iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it)
|
||||
if(now > (time_t)(it->second.time_stamp + TUNNEL_REQUESTS_LIFE_TIME))
|
||||
{
|
||||
for(std::map<TurtleSearchRequestId,TurtleRequestInfo>::iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it)
|
||||
if(now > (time_t)(it->second.time_stamp + SEARCH_REQUESTS_LIFE_TIME))
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " removed tunnel request " << (void *)it->first << ", timeout." << std::endl ;
|
||||
std::cerr << " removed search request " << (void *)it->first << ", timeout." << std::endl ;
|
||||
#endif
|
||||
_tunnel_requests_origins.erase(it) ;
|
||||
}
|
||||
_search_requests_origins.erase(it) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Tunnel requests
|
||||
//
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
for(std::map<TurtleTunnelRequestId,TurtleRequestInfo>::iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it)
|
||||
if(now > (time_t)(it->second.time_stamp + TUNNEL_REQUESTS_LIFE_TIME))
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " removed tunnel request " << (void *)it->first << ", timeout." << std::endl ;
|
||||
#endif
|
||||
_tunnel_requests_origins.erase(it) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Tunnels.
|
||||
std::vector<TurtleTunnelId> tunnels_to_close ;
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
for(std::map<TurtleTunnelId,TurtleTunnel>::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it)
|
||||
if(now > (time_t)(it->second.time_stamp + MAXIMUM_TUNNEL_IDLE_TIME))
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " removing tunnel " << (void *)it->first << ": timeout." << std::endl ;
|
||||
#endif
|
||||
tunnels_to_close.push_back(it->first) ;
|
||||
}
|
||||
}
|
||||
for(uint i=0;i<tunnels_to_close.size();++i)
|
||||
closeTunnel(tunnels_to_close[i]) ;
|
||||
|
||||
// File hashes can only be removed by calling the 'stopMonitoringFileTunnels()' command.
|
||||
}
|
||||
|
||||
void p3turtle::closeTunnel(TurtleTunnelId tid)
|
||||
{
|
||||
// This is closing a given tunnel, removing it from file sources, and from the list of tunnels of its
|
||||
// corresponding file hash. In the original turtle4privacy paradigm, they also send back and forward
|
||||
// tunnel closing commands. I'm not sure this is necessary, because if a tunnel is closed somewhere, it's
|
||||
// source is not going to be used and the tunnel will eventually disappear.
|
||||
//
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<TurtleTunnelId,TurtleTunnel>::iterator it(_local_tunnels.find(tid)) ;
|
||||
|
||||
if(it == _local_tunnels.end())
|
||||
{
|
||||
std::cerr << "p3turtle: was asked to close tunnel 0x" << (void*)tid << ", which actually doesn't exist." << std::endl ;
|
||||
return ;
|
||||
}
|
||||
std::cerr << "p3turtle: Closing tunnel 0x" << (void*)tid << std::endl ;
|
||||
|
||||
if(it->second.local_src == mConnMgr->getOwnId()) // this is a starting tunnel. We thus remove
|
||||
// - the virtual peer from the vpid list
|
||||
// - the tunnel id from the file hash
|
||||
// - the virtual peer from the file sources in the file transfer controller.
|
||||
{
|
||||
TurtleTunnelId tid = it->first ;
|
||||
TurtleVirtualPeerId vpid = it->second.vpid ;
|
||||
TurtleFileHash hash = it->second.hash ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Tunnel is a starting point. Also removing " ;
|
||||
std::cerr << " Virtual Peer Id " << vpid << std::endl ;
|
||||
std::cerr << " Associated file source." << std::endl ;
|
||||
#endif
|
||||
_ft_controller->removeFileSource(hash,vpid) ;
|
||||
_virtual_peers.erase(_virtual_peers.find(vpid)) ;
|
||||
|
||||
std::vector<TurtleTunnelId>& tunnels(_incoming_file_hashes[hash].tunnels) ;
|
||||
|
||||
for(uint i=0;i<tunnels.size();++i)
|
||||
if(tunnels[i] == tid)
|
||||
{
|
||||
tunnels[i] = tunnels.back() ;
|
||||
tunnels.pop_back() ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
else if(it->second.local_dst == mConnMgr->getOwnId()) // This is a ending tunnel. We also remove the virtual peer id
|
||||
{
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << " Tunnel is a ending point. Also removing associated outgoing hash." ;
|
||||
#endif
|
||||
_outgoing_file_hashes.erase(_outgoing_file_hashes.find(it->second.hash)) ;
|
||||
}
|
||||
|
||||
_local_tunnels.erase(it) ;
|
||||
}
|
||||
|
||||
void p3turtle::stopMonitoringFileTunnels(const std::string& hash)
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<TurtleFileHash,TurtleFileHashInfo>::iterator it(_incoming_file_hashes.find(hash)) ;
|
||||
|
||||
if(it == _incoming_file_hashes.end())
|
||||
{
|
||||
std::cerr << "p3turtle: asked to stop monitoring file hash " << hash << ", but this hash is actually not handled by the turtle router." << std::endl ;
|
||||
return ;
|
||||
}
|
||||
|
||||
// copy the list of tunnels to remove.
|
||||
std::vector<TurtleTunnelId> tunnels_to_remove = it->second.tunnels ;
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "p3turtle: stopping monitoring for file hash " << hash << ", and closing " << tunnels_to_remove.size() << " tunnels." << std::endl ;
|
||||
#endif
|
||||
|
||||
for(uint i=0;i<tunnels_to_remove.size();++i)
|
||||
closeTunnel(tunnels_to_remove[i]) ;
|
||||
|
||||
_incoming_file_hashes.erase(it) ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Config functions ------------------------------ //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
//
|
||||
RsSerialiser *p3turtle::setupSerialiser()
|
||||
{
|
||||
RsSerialiser *rss = new RsSerialiser();
|
||||
|
||||
return rss ;
|
||||
}
|
||||
std::list<RsItem*> p3turtle::saveList(bool& cleanup)
|
||||
{
|
||||
cleanup = true ;
|
||||
return std::list<RsItem*>() ;
|
||||
}
|
||||
bool p3turtle::loadList(std::list<RsItem*> load)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
// -------------------------------- Helper functions ------------------------------ //
|
||||
// -----------------------------------------------------------------------------------//
|
||||
@ -481,6 +611,7 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
||||
// 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 = 2 + (rand() % 256) ; // obfuscate the depth for non immediate friends.
|
||||
|
||||
sendItem(fwd_item) ;
|
||||
}
|
||||
@ -638,6 +769,8 @@ void p3turtle::sendDataRequest(const std::string& peerId, const std::string& has
|
||||
TurtleTunnelId tunnel_id = it->second ;
|
||||
TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ;
|
||||
|
||||
tunnel.time_stamp = time(NULL) ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
assert(hash == tunnel.hash) ;
|
||||
#endif
|
||||
@ -669,11 +802,12 @@ void p3turtle::sendFileData(const std::string& peerId, const std::string& hash,
|
||||
TurtleTunnelId tunnel_id = it->second ;
|
||||
TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ;
|
||||
|
||||
tunnel.time_stamp = time(NULL) ;
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
assert(hash == tunnel.hash) ;
|
||||
#endif
|
||||
RsTurtleFileDataItem *item = new RsTurtleFileDataItem ;
|
||||
item->tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever.
|
||||
item->tunnel_id = tunnel_id ;
|
||||
item->chunk_offset = offset ;
|
||||
item->chunk_size = chunksize ;
|
||||
item->chunk_data = malloc(chunksize) ;
|
||||
@ -747,17 +881,12 @@ std::string p3turtle::getTurtlePeerId(TurtleTunnelId tid) const
|
||||
|
||||
std::map<TurtleTunnelId,TurtleTunnel>::const_iterator it( _local_tunnels.find(tid) ) ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
assert(it!=_local_tunnels.end()) ;
|
||||
assert(it->second.vpid != "") ;
|
||||
#endif
|
||||
|
||||
return it->second.vpid ;
|
||||
|
||||
// static std::string s="Turtle peer" ;
|
||||
// unsigned char buf[100] ;
|
||||
//
|
||||
// sprintf(buff,"% 8d",id) ;
|
||||
//
|
||||
// return s+" "+buff;
|
||||
}
|
||||
|
||||
bool p3turtle::isOnline(const std::string& peer_id) const
|
||||
@ -953,7 +1082,7 @@ void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item)
|
||||
|
||||
// store tunnel info.
|
||||
if(_local_tunnels.find(item->tunnel_id) != _local_tunnels.end())
|
||||
std::cerr << "Tunnel already there. This is an error !!" << std::endl ;
|
||||
std::cerr << "Tunnel id " << item->tunnel_id << " is already there. Giving up !!" << std::endl ;
|
||||
|
||||
TurtleTunnel& tunnel(_local_tunnels[item->tunnel_id]) ;
|
||||
|
||||
@ -1086,8 +1215,7 @@ TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match)
|
||||
return id ;
|
||||
}
|
||||
|
||||
|
||||
void p3turtle::turtleDownload(const std::string& name,const std::string& file_hash,uint64_t size)
|
||||
void p3turtle::monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size)
|
||||
{
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
@ -1106,18 +1234,24 @@ void p3turtle::turtleDownload(const std::string& name,const std::string& file_ha
|
||||
// No tunnels at start, but this triggers digging new tunnels.
|
||||
//
|
||||
_incoming_file_hashes[file_hash].tunnels.clear();
|
||||
_force_digg_new_tunnels = true ;
|
||||
|
||||
// also should send associated request to the file transfer module.
|
||||
_incoming_file_hashes[file_hash].size = size ;
|
||||
_incoming_file_hashes[file_hash].name = name ;
|
||||
_incoming_file_hashes[file_hash].time_stamp = time(NULL) ;
|
||||
}
|
||||
|
||||
#ifdef TO_REMOVE
|
||||
std::list<std::string> srcIds ;
|
||||
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
std::cerr << "p3turtle: Calling ft server to handle the dl" << std::endl ;
|
||||
#endif
|
||||
_ft_server->FileRequest(name,file_hash, size, "", 0, srcIds) ;
|
||||
#endif
|
||||
|
||||
IndicateConfigChanged() ; // initiates saving of handled hashes.
|
||||
}
|
||||
|
||||
void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item)
|
||||
@ -1151,26 +1285,33 @@ void p3turtle::dumpState()
|
||||
std::cerr << " hash=0x" << it->first << ", name=" << it->second.name << ", size=" << it->second.size << ", tunnel ids =" ;
|
||||
for(std::vector<TurtleTunnelId>::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2)
|
||||
std::cerr << " " << (void*)*it2 ;
|
||||
std::cerr << ", last_req=" << (void*)it->second.last_request << std::endl ;
|
||||
std::cerr << ", last_req=" << (void*)it->second.last_request << ", time_stamp = " << it->second.time_stamp << std::endl ;
|
||||
}
|
||||
std::cerr << " Active outgoing file hashes: " << _outgoing_file_hashes.size() << std::endl ;
|
||||
for(std::map<TurtleFileHash,FileInfo>::const_iterator it(_outgoing_file_hashes.begin());it!=_outgoing_file_hashes.end();++it)
|
||||
std::cerr << " hash=0x" << it->first << ", name=" << it->second.fname << ", size=" << it->second.size ;
|
||||
std::cerr << " hash=0x" << it->first << ", name=" << it->second.fname << ", size=" << it->second.size << std::endl ;
|
||||
|
||||
std::cerr << " Local tunnels:" << std::endl ;
|
||||
for(std::map<TurtleTunnelId,TurtleTunnel>::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it)
|
||||
std::cerr << " " << (void*)it->first << ": from="
|
||||
<< it->second.local_src << ", to=" << it->second.local_dst
|
||||
<< ", hash=0x" << it->second.hash << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp << " secs ago)"
|
||||
<< ", peer id =" << it->second.vpid << std::endl ;
|
||||
<< ", peer id =" << it->second.vpid << ", time_stamp=" << it->second.time_stamp << std::endl ;
|
||||
|
||||
std::cerr << " buffered request origins: " << std::endl ;
|
||||
std::cerr << " Search requests: " << _search_requests_origins.size() << std::endl ;
|
||||
|
||||
for(std::map<TurtleSearchRequestId,TurtleRequestInfo>::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it)
|
||||
std::cerr << " " << (void*)it->first << ": from=" << it->second.origin << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp << " secs ago)" << std::endl ;
|
||||
std::cerr << " " << (void*)it->first << ": from=" << it->second.origin
|
||||
<< ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp
|
||||
<< " secs ago)" << std::endl ;
|
||||
|
||||
std::cerr << " Tunnel requests: " << _tunnel_requests_origins.size() << std::endl ;
|
||||
for(std::map<TurtleTunnelRequestId,TurtleRequestInfo>::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it)
|
||||
std::cerr << " " << (void*)it->first << ": from=" << it->second.origin << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp << " secs ago)" << std::endl ;
|
||||
std::cerr << " " << (void*)it->first << ": from=" << it->second.origin
|
||||
<< ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp
|
||||
<< " secs ago)" << std::endl ;
|
||||
|
||||
std::cerr << " Virtual peers:" << std::endl ;
|
||||
for(std::map<TurtleVirtualPeerId,TurtleTunnelId>::const_iterator it(_virtual_peers.begin());it!=_virtual_peers.end();++it)
|
||||
std::cerr << " id=" << it->first << ", tunnel=" << (void*)(it->second) << std::endl ;
|
||||
|
@ -161,6 +161,7 @@ class ftServer ;
|
||||
class p3AuthMgr;
|
||||
class p3ConnectMgr;
|
||||
class ftDataMultiplex;
|
||||
class RsSerialiser;
|
||||
static const int TURTLE_MAX_SEARCH_DEPTH = 6 ;
|
||||
|
||||
// This class is used to keep trace of requests (searches and tunnels).
|
||||
@ -191,10 +192,22 @@ class TurtleFileHashInfo
|
||||
TurtleRequestId last_request ; // last request for the tunnels of this hash
|
||||
|
||||
TurtleFileName name ;
|
||||
time_t time_stamp ;
|
||||
uint64_t size ;
|
||||
};
|
||||
|
||||
class p3turtle: public p3Service, public pqiMonitor, public RsTurtle, public ftSearch
|
||||
// Subclassing:
|
||||
//
|
||||
// Class | Brings what | Usage
|
||||
// -----------+------------------+------------------------------------------------------
|
||||
// p3Service | sendItem() | handle packet sending/receiving to/from friend peers.
|
||||
// pqiMonitor | configChanged() | handle who's connecting/disconnecting to dig new tunnels
|
||||
// RsTurtle | start/stop file()| brings interface for turtle service
|
||||
// ftSearch | search() | used to allow searching for monitored files.
|
||||
// p3Config | ConfigChanged() | used to load/save .cfg file for turtle variales.
|
||||
// -----------+------------------+------------------------------------------------------
|
||||
//
|
||||
class p3turtle: public p3Service, public pqiMonitor, public RsTurtle, public ftSearch, public p3Config
|
||||
{
|
||||
public:
|
||||
p3turtle(p3ConnectMgr *cm,ftServer *m);
|
||||
@ -205,16 +218,24 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle, public ftS
|
||||
//
|
||||
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
|
||||
// Initiates tunnel handling for the given file hash.
|
||||
// tunnels. Launches an exception if an error occurs during the
|
||||
// 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:
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the 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& name,const std::string& file_hash,uint64_t size) ;
|
||||
// This function should be called in addition to ftServer::FileRequest() so that the turtle router
|
||||
// automatically provide tunnels for the file to download.
|
||||
//
|
||||
virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) ;
|
||||
|
||||
// This should be called when canceling a file download, so that the turtle router stops
|
||||
// handling tunnels for this file.
|
||||
//
|
||||
virtual void stopMonitoringFileTunnels(const std::string& file_hash) ;
|
||||
|
||||
/************* from pqiMonitor *******************/
|
||||
// Informs the turtle router that some peers are (dis)connected. This should initiate digging new tunnels,
|
||||
@ -237,6 +258,11 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle, public ftS
|
||||
//
|
||||
virtual bool search(std::string hash, uint64_t size, uint32_t hintflags, FileInfo &info) const ;
|
||||
|
||||
/************* from p3Config *******************/
|
||||
virtual RsSerialiser *setupSerialiser() ;
|
||||
virtual std::list<RsItem*> saveList(bool& cleanup) ;
|
||||
virtual bool loadList(std::list<RsItem*> load) ;
|
||||
|
||||
/************* Communication with ftserver *******************/
|
||||
// Does the turtle router manages tunnels to this peer ? (this is not a
|
||||
// real id, but a fake one, that the turtle router is capable of connecting with a tunnel id).
|
||||
@ -271,8 +297,9 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle, public ftS
|
||||
|
||||
//----------------------------- Routing functions ----------------------------//
|
||||
|
||||
void manageTunnels() ; /// Handle tunnel digging for current file hashes
|
||||
int handleIncoming(); /// Main routing function
|
||||
void manageTunnels() ; /// Handle tunnel digging for current file hashes
|
||||
void closeTunnel(TurtleTunnelId tid) ; /// closes a given tunnel
|
||||
int handleIncoming(); /// Main routing function
|
||||
|
||||
void handleSearchRequest(RsTurtleSearchRequestItem *item); /// specific routing functions for handling particular packets.
|
||||
void handleSearchResult(RsTurtleSearchResultItem *item);
|
||||
@ -303,18 +330,16 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle, public ftS
|
||||
|
||||
std::map<TurtleSearchRequestId,TurtleRequestInfo> _search_requests_origins ; /// keeps trace of who emmitted a given search request
|
||||
std::map<TurtleTunnelRequestId,TurtleRequestInfo> _tunnel_requests_origins ; /// keeps trace of who emmitted a tunnel request
|
||||
|
||||
std::map<TurtleFileHash,TurtleFileHashInfo> _incoming_file_hashes ; /// stores adequate tunnels for each file hash locally managed
|
||||
std::map<TurtleFileHash,FileInfo> _outgoing_file_hashes ; /// stores file info for each file we provide.
|
||||
|
||||
std::map<TurtleTunnelId,TurtleTunnel > _local_tunnels ; /// local tunnels, stored by ids (Either transiting or ending).
|
||||
|
||||
std::map<TurtleVirtualPeerId,TurtleTunnelId> _virtual_peers ; /// Peers corresponding to each tunnel.
|
||||
|
||||
time_t _last_clean_time ;
|
||||
time_t _last_tunnel_management_time ;
|
||||
|
||||
std::list<pqipeer> _online_peers;
|
||||
bool _force_digg_new_tunnels ; /// used to force digging new tunnels
|
||||
#ifdef P3TURTLE_DEBUG
|
||||
void dumpState() ;
|
||||
#endif
|
||||
|
@ -33,11 +33,12 @@ class RsTurtleSearchResultItem: public RsTurtleItem
|
||||
RsTurtleSearchResultItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT) {}
|
||||
RsTurtleSearchResultItem(void *data,uint32_t size) ; // deserialization
|
||||
|
||||
uint16_t depth ;
|
||||
uint8_t peer_id[16]; // peer id. This will eventually be obfuscated in some way.
|
||||
|
||||
TurtleSearchRequestId request_id ; // randomly generated request id.
|
||||
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 ;
|
||||
|
||||
virtual std::ostream& print(std::ostream& o, uint16_t) ;
|
||||
|
@ -611,9 +611,9 @@ void TransfersDialog::insertTransfers()
|
||||
int dlPeers = 0;
|
||||
for (pit = info.peers.begin(); pit != info.peers.end(); pit++) {
|
||||
symbol = "";
|
||||
name = QString::fromStdString(rsPeers->getPeerName(pit->peerId));
|
||||
name = getPeerName(pit->peerId);
|
||||
//unique combination: fileName + peerName, variant: hash + peerName (too long)
|
||||
coreId = QString::fromStdString(info.fname + rsPeers->getPeerName(pit->peerId));
|
||||
coreId = QString::fromStdString(info.fname) + getPeerName(pit->peerId);
|
||||
fileSize = info.size;
|
||||
progress = (info.transfered * 100.0) / info.size;
|
||||
dlspeed = pit->tfRate * 1024.0;
|
||||
@ -645,7 +645,7 @@ void TransfersDialog::insertTransfers()
|
||||
continue;
|
||||
|
||||
/* if peers found in selectedIds, select again */
|
||||
if (selectedIds.end() != std::find(selectedIds.begin(), selectedIds.end(), info.fname + rsPeers->getPeerName(pit->peerId))) {
|
||||
if (selectedIds.end() != std::find(selectedIds.begin(), selectedIds.end(), info.fname + getPeerName(pit->peerId).toStdString())) {
|
||||
QStandardItem *dlItem = DLListModel->item(addedRow);
|
||||
QModelIndex childIndex = DLListModel->indexFromItem(dlItem).child(dlPeers, 0);
|
||||
selection->select(childIndex, QItemSelectionModel::Rows | QItemSelectionModel::SelectCurrent);
|
||||
@ -669,7 +669,7 @@ void TransfersDialog::insertTransfers()
|
||||
symbol = "";
|
||||
coreId = QString::fromStdString(info.hash);
|
||||
name = QString::fromStdString(info.fname);
|
||||
sources = QString::fromStdString(rsPeers->getPeerName(pit->peerId));
|
||||
sources = getPeerName(pit->peerId);
|
||||
|
||||
switch(pit->status)
|
||||
{
|
||||
@ -749,6 +749,19 @@ void TransfersDialog::insertTransfers()
|
||||
}
|
||||
}
|
||||
|
||||
QString TransfersDialog::getPeerName(const std::string& id) const
|
||||
{
|
||||
QString res = QString::fromStdString(rsPeers->getPeerName(id)) ;
|
||||
|
||||
// This is because turtle tunnels have no name (I didn't want to bother with
|
||||
// connect mgr). In such a case their id can suitably hold for a name.
|
||||
//
|
||||
if(res == "")
|
||||
return QString::fromStdString(id) ;
|
||||
else
|
||||
return res ;
|
||||
}
|
||||
|
||||
void TransfersDialog::cancel()
|
||||
{
|
||||
QString queryWrn2;
|
||||
@ -764,11 +777,13 @@ void TransfersDialog::cancel()
|
||||
if(selection->isRowSelected(i, QModelIndex()))
|
||||
{
|
||||
std::string id = getID(i, DLListModel).toStdString();
|
||||
#ifdef UNUSED
|
||||
QString qname = getFileName(i, DLListModel);
|
||||
/* XXX -> Should not have to 'trim' filename ... something wrong here..
|
||||
* but otherwise, not exact filename .... BUG
|
||||
*/
|
||||
std::string name = (qname.trimmed()).toStdString();
|
||||
#endif
|
||||
rsFiles->FileCancel(id); /* hash */
|
||||
|
||||
}
|
||||
|
@ -74,6 +74,8 @@ class TransfersDialog : public MainPage
|
||||
void playFiles(QStringList files);
|
||||
|
||||
private:
|
||||
QString getPeerName(const std::string& peer_id) const ;
|
||||
|
||||
QStandardItemModel *DLListModel;
|
||||
QStandardItemModel *ULListModel;
|
||||
QItemSelectionModel *selection;
|
||||
|
@ -259,12 +259,14 @@ void TurtleSearchDialog::download()
|
||||
"", 0, srcIds);
|
||||
#endif
|
||||
|
||||
std::list<std::string> srcIds;
|
||||
std::cout << "Issuing file request from search dialog: -"
|
||||
<< (item->text(SR_NAME_COL)).toStdString() << "-"
|
||||
<< (item->text(SR_HASH_COL)).toStdString() << "-"
|
||||
<< (item->text(SR_REALSIZE_COL)).toInt() << std::endl ;
|
||||
|
||||
rsTurtle->turtleDownload(item->text(SR_NAME_COL).toStdString(),item->text(SR_HASH_COL).toStdString(),item->text(SR_REALSIZE_COL).toInt()) ;
|
||||
rsTurtle->monitorFileTunnels(item->text(SR_NAME_COL).toStdString(),item->text(SR_HASH_COL).toStdString(),item->text(SR_REALSIZE_COL).toInt()) ;
|
||||
rsFiles->FileRequest(item->text(SR_NAME_COL).toStdString(),item->text(SR_HASH_COL).toStdString(),item->text(SR_REALSIZE_COL).toInt(),"",0,srcIds) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,11 +67,18 @@ class RsTurtle
|
||||
//
|
||||
virtual TurtleRequestId turtleSearch(const std::string& match_string) = 0 ;
|
||||
|
||||
// Launches a complete download file operation: diggs one or more
|
||||
// tunnels. Launches an exception if an error occurs during the
|
||||
// initialization process.
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the 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 by calling ftServer::FileRequest().
|
||||
//
|
||||
virtual void turtleDownload(const std::string& name,const std::string& file_hash,uint64_t size) = 0 ;
|
||||
virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) = 0 ;
|
||||
|
||||
// Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should
|
||||
// be called after calling ftServer::fileCancel().
|
||||
//
|
||||
virtual void stopMonitoringFileTunnels(const std::string& file_hash) = 0 ;
|
||||
|
||||
// Sets the file sharing strategy. It concerns all local files. It would
|
||||
// be better to handle this for each file, of course.
|
||||
|
Loading…
Reference in New Issue
Block a user