2009-02-28 13:19:00 -05:00
/*
2009-03-12 16:08:02 -04:00
* libretroshare / src / services : p3turtle . cc
2009-02-28 13:19:00 -05:00
*
* Services for RetroShare .
*
2009-03-12 16:08:02 -04:00
* Copyright 2009 by Cyril Soler
2009-02-28 13:19:00 -05:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
2009-03-12 16:08:02 -04:00
* Please report all bugs and problems to " csoler@users.sourceforge.net " .
2009-02-28 13:19:00 -05:00
*
*/
2010-07-21 19:14:10 -04:00
//#define P3TURTLE_DEBUG
2012-04-12 19:29:39 -04:00
# include <unistd.h>
2009-03-13 17:14:30 -04:00
# include <stdexcept>
2009-03-23 10:45:51 -04:00
# include <stdlib.h>
2009-05-28 15:41:03 -04:00
# include <assert.h>
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
# include <assert.h>
# endif
2009-02-28 13:19:00 -05:00
2010-08-06 05:40:23 -04:00
# include "retroshare/rsiface.h"
2009-02-28 13:19:00 -05:00
2010-01-13 15:56:55 -05:00
# include "pqi/authssl.h"
2011-07-09 14:39:34 -04:00
# include "pqi/p3linkmgr.h"
2012-01-14 08:27:48 -05:00
# include "retroshare/rspeers.h"
2009-03-13 17:14:30 -04:00
# include "pqi/pqinotify.h"
2009-05-26 17:42:45 -04:00
# include "ft/ftserver.h"
# include "ft/ftdatamultiplex.h"
# include "ft/ftcontroller.h"
2009-04-13 16:26:13 -04:00
2009-03-12 16:08:02 -04:00
# include "p3turtle.h"
2009-02-28 13:19:00 -05:00
# include <iostream>
# include <errno.h>
# include <cmath>
# include <sstream>
2009-05-28 15:41:03 -04:00
# include <stdio.h>
2009-02-28 13:19:00 -05:00
# include "util/rsdebug.h"
# include "util/rsprint.h"
2010-09-14 17:26:18 -04:00
# include "util/rsrandom.h"
2009-02-28 13:19:00 -05:00
# include "pqi/pqinetwork.h"
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
static std : : vector < int > TS_tunnel_length ( 8 , 0 ) ;
static std : : map < TurtleFileHash , std : : vector < std : : pair < time_t , TurtleTunnelRequestId > > > TS_request_time_stamps ;
static std : : map < TurtleTunnelRequestId , std : : vector < time_t > > TS_request_bounces ;
void TS_dumpState ( ) ;
# endif
2009-08-25 16:49:50 -04:00
// 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
2009-06-03 14:47:14 -04:00
// could ever be.
//
2011-03-15 19:09:31 -04:00
// 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.
// - changed tunnel speed estimate time lapse to 5 secs. Too small a value favors high variations.
// - the max number of tunnel requests per second is now enforced. It was before defaulting to
// QUEUE_LENGTH*0.1, meaning 0.5. I set it to 0.1.
//
2012-04-19 16:23:58 -04:00
// update of 19-04-12:
// - 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 = 60 ; /// life time for tunnel requests in the cache.
static const time_t SEARCH_REQUESTS_LIFE_TIME = 60 ; /// 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 float depth_peer_probability [ 7 ] = { 1.0f , 0.99f , 0.9f , 0.7f , 0.6f , 0.5 , 0.4f } ;
static const int TUNNEL_REQUEST_PACKET_SIZE = 50 ;
static const int MAX_TR_FORWARD_PER_SEC = 20 ;
static const int MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT = 30 ;
static const int MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT = 10 ;
static const int DISTANCE_SQUEEZING_POWER = 8 ;
2011-10-01 07:46:00 -04:00
2011-07-09 14:39:34 -04:00
p3turtle : : p3turtle ( p3LinkMgr * lm , ftServer * fs )
: p3Service ( RS_SERVICE_TYPE_TURTLE ) , p3Config ( CONFIG_TYPE_TURTLE ) , mLinkMgr ( lm ) , mTurtleMtx ( " p3turtle " )
2009-02-28 13:19:00 -05:00
{
2009-03-12 16:08:02 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-02-28 13:19:00 -05:00
2009-05-26 17:42:45 -04:00
_ft_server = fs ;
_ft_controller = fs - > getController ( ) ;
2011-04-07 16:16:43 -04:00
_random_bias = RSRandom : : random_u32 ( ) ;
2009-02-28 13:19:00 -05:00
addSerialType ( new RsTurtleSerialiser ( ) ) ;
2009-04-19 15:59:54 -04:00
_last_clean_time = 0 ;
_last_tunnel_management_time = 0 ;
2009-08-14 03:28:58 -04:00
_last_tunnel_campaign_time = 0 ;
2010-06-19 08:11:44 -04:00
_last_tunnel_speed_estimate_time = 0 ;
2011-05-26 18:11:06 -04:00
_traffic_info . reset ( ) ;
2011-06-23 15:16:10 -04:00
_sharing_strategy = SHARE_ENTIRE_NETWORK ;
2012-02-10 17:23:06 -05:00
_max_tr_up_rate = MAX_TR_FORWARD_PER_SEC ;
2009-02-28 13:19:00 -05:00
}
int p3turtle : : tick ( )
{
2009-06-03 14:47:14 -04:00
// Handle tunnel trafic
//
2009-02-28 13:19:00 -05:00
handleIncoming ( ) ; // handle incoming packets
2009-03-12 16:08:02 -04:00
time_t now = time ( NULL ) ;
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
static time_t last_now = now ;
if ( now - last_now > 2 )
std : : cerr < < " ******************* WARNING: now - last_now = " < < now - last_now < < std : : endl ;
last_now = now ;
# endif
bool should_autowash , should_estimatespeed ;
2011-02-08 14:37:01 -05:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2011-03-15 19:09:31 -04:00
should_autowash = now > TUNNEL_CLEANING_LAPS_TIME + _last_clean_time ;
2011-02-08 14:37:01 -05:00
should_estimatespeed = now > = TUNNEL_SPEED_ESTIMATE_LAPSE + _last_tunnel_speed_estimate_time ;
}
2009-06-03 14:47:14 -04:00
// 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
2009-04-19 15:59:54 -04:00
//
2012-04-19 16:23:58 -04:00
if ( now > = _last_tunnel_management_time + TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS ) // call every second
2009-04-19 15:59:54 -04:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Calling tunnel management. " < < std : : endl ;
# endif
manageTunnels ( ) ;
2009-06-03 14:47:14 -04:00
2011-05-26 18:11:06 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
_last_tunnel_management_time = now ;
2011-05-28 10:39:47 -04:00
// Update traffic statistics. The constants are important: they allow a smooth variation of the
// traffic speed, which is used to moderate tunnel requests statistics.
//
2012-04-19 16:23:58 -04:00
_traffic_info = _traffic_info * 0.9 + _traffic_info_buffer * ( 0.1 / ( float ) TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS ) ;
2011-05-26 18:11:06 -04:00
_traffic_info_buffer . reset ( ) ;
}
2009-04-19 15:59:54 -04:00
}
// Clean every 10 sec.
//
2011-02-08 14:37:01 -05:00
if ( should_autowash )
2009-03-12 16:08:02 -04:00
{
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Calling autowash. " < < std : : endl ;
# endif
2009-06-03 14:47:14 -04:00
autoWash ( ) ; // clean old/unused tunnels and file hashes, as well as search and tunnel requests.
2011-02-08 14:37:01 -05:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-03-12 16:08:02 -04:00
_last_clean_time = now ;
}
2009-03-12 17:07:00 -04:00
2011-02-08 14:37:01 -05:00
if ( should_estimatespeed )
2010-06-19 08:11:44 -04:00
{
estimateTunnelSpeeds ( ) ;
2011-02-08 14:37:01 -05:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-06-19 08:11:44 -04:00
_last_tunnel_speed_estimate_time = now ;
}
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
// Dump state for debugging, every 20 sec.
//
static time_t TS_last_dump = time ( NULL ) ;
if ( now > 20 + TS_last_dump )
{
TS_last_dump = now ;
TS_dumpState ( ) ;
}
# endif
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-03 14:47:14 -04:00
// Dump state for debugging, every 20 sec.
2009-04-19 15:59:54 -04:00
//
static time_t last_dump = time ( NULL ) ;
if ( now > 20 + last_dump )
{
last_dump = now ;
dumpState ( ) ;
}
# endif
2009-03-12 17:07:00 -04:00
return 0 ;
2009-03-12 16:08:02 -04:00
}
2009-04-19 15:59:54 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// ------------------------------ Tunnel maintenance. ------------------------------ //
2009-04-19 15:59:54 -04:00
// -----------------------------------------------------------------------------------//
//
2011-03-15 19:09:31 -04:00
# ifdef TO_REMOVE
2009-04-19 15:59:54 -04:00
// This method handles peer connexion/deconnexion
// If A connects, new tunnels should be initiated from A
// If A disconnects, the tunnels passed through A should be closed.
//
2009-08-25 16:49:50 -04:00
void p3turtle : : statusChange ( const std : : list < pqipeer > & plist ) // derived from pqiMonitor
2009-04-19 15:59:54 -04:00
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-06-03 14:47:14 -04:00
// We actually do not shut down tunnels when peers get down: Tunnels that
// are not working properly get automatically removed after some time.
2009-05-26 17:42:45 -04:00
// 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 ;
2009-06-03 14:47:14 -04:00
/* 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 ;
2009-04-19 15:59:54 -04:00
}
2011-03-15 19:09:31 -04:00
# endif
2009-04-19 15:59:54 -04:00
2009-05-26 17:42:45 -04:00
// adds a virtual peer to the list that is communicated ot ftController.
//
2010-12-07 16:45:12 -05:00
void p3turtle : : locked_addDistantPeer ( const TurtleFileHash & , TurtleTunnelId tid )
2009-05-26 17:42:45 -04:00
{
char buff [ 400 ] ;
2010-01-21 07:33:01 -05:00
sprintf ( buff , " Anonymous F2F tunnel %08x " , tid ) ;
2009-05-26 17:42:45 -04:00
2010-12-07 16:45:12 -05:00
_virtual_peers [ TurtleVirtualPeerId ( buff ) ] = tid ;
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
2010-12-07 16:45:12 -05:00
assert ( _local_tunnels . find ( tid ) ! = _local_tunnels . end ( ) ) ;
2009-05-26 17:42:45 -04:00
# endif
2010-12-07 16:45:12 -05:00
_local_tunnels [ tid ] . vpid = TurtleVirtualPeerId ( buff ) ;
2009-05-26 17:42:45 -04:00
}
2009-08-25 16:49:50 -04:00
void p3turtle : : getVirtualPeersList ( std : : list < pqipeer > & list )
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
list . clear ( ) ;
for ( std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . begin ( ) ) ; it ! = _virtual_peers . end ( ) ; + + it )
{
pqipeer vp ;
vp . id = it - > first ;
vp . name = " Virtual (distant) peer " ;
vp . state = RS_PEER_S_CONNECTED ;
vp . actions = RS_PEER_CONNECTED ;
list . push_back ( vp ) ;
}
}
2009-04-19 15:59:54 -04:00
// This method handles digging new tunnels as needed.
// New tunnels are dug when:
// - new peers have connected. The resulting tunnels should be checked against doubling.
// - new hashes are submitted for handling.
//
2011-03-15 19:09:31 -04:00
class hashPairComparator
{
public :
virtual bool operator ( ) ( const std : : pair < TurtleFileHash , time_t > & p1 , const std : : pair < TurtleFileHash , time_t > & p2 ) const
{
return p1 . second < p2 . second ;
}
} ;
2009-04-19 15:59:54 -04:00
void p3turtle : : manageTunnels ( )
{
2011-03-15 19:09:31 -04:00
// Collect hashes for which tunnel digging is necessary / recommended. Hashes get in the list for two reasons:
// - the hash has no tunnel -> tunnel digging every EMPTY_TUNNELS_DIGGING_TIME seconds
// - 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
// 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 ;
time_t now = time ( NULL ) ;
2009-04-19 15:59:54 -04:00
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2011-03-15 19:09:31 -04:00
// digg new tunnels if no tunnels are available and force digg new tunnels at regular (large) interval
//
2009-06-14 14:59:42 -04:00
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2011-03-15 19:09:31 -04:00
if ( ( it - > second . tunnels . empty ( ) & & now > = it - > second . last_digg_time + EMPTY_TUNNELS_DIGGING_TIME ) | | now > = it - > second . last_digg_time + REGULAR_TUNNEL_DIGGING_TIME )
2009-06-14 14:59:42 -04:00
{
# ifdef P3TURTLE_DEBUG
2011-03-15 19:09:31 -04:00
std : : cerr < < " pushed hash " < < it - > first < < " , for digging. Old = " < < now - it - > second . last_digg_time < < std : : endl ;
2009-06-14 14:59:42 -04:00
# endif
2011-03-15 19:09:31 -04:00
hashes_to_digg . push_back ( std : : pair < TurtleFileHash , time_t > ( it - > first , it - > second . last_digg_time ) ) ;
2009-06-14 14:59:42 -04:00
}
2009-05-26 17:42:45 -04:00
}
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
std : : cerr < < hashes_to_digg . size ( ) < < " hashes candidate for tunnel digging. " < < std : : endl ;
# endif
std : : sort ( hashes_to_digg . begin ( ) , hashes_to_digg . end ( ) , hashPairComparator ( ) ) ;
2009-05-26 17:42:45 -04:00
2011-03-15 19:09:31 -04:00
for ( unsigned int i = 0 ; i < MAX_TUNNEL_REQS_PER_SECOND & & i < hashes_to_digg . size ( ) ; + + i ) // Digg at most n tunnels per second.
{
# ifdef TUNNEL_STATISTICS
std : : cerr < < " !!!!!!!!!!!! Digging for " < < hashes_to_digg [ i ] . first < < std : : endl ;
# endif
diggTunnel ( hashes_to_digg [ i ] . first ) ;
}
2009-04-19 15:59:54 -04:00
}
2010-06-19 08:11:44 -04:00
void p3turtle : : estimateTunnelSpeeds ( )
{
RsStackMutex stack ( mTurtleMtx ) ;
for ( std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it ( _local_tunnels . begin ( ) ) ; it ! = _local_tunnels . end ( ) ; + + it )
{
TurtleTunnel & tunnel ( it - > second ) ;
float speed_estimate = tunnel . transfered_bytes / float ( TUNNEL_SPEED_ESTIMATE_LAPSE ) ;
tunnel . speed_Bps = 0.75 * tunnel . speed_Bps + 0.25 * speed_estimate ;
tunnel . transfered_bytes = 0 ;
}
}
2009-03-12 17:07:00 -04:00
void p3turtle : : autoWash ( )
2009-03-12 16:08:02 -04:00
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-04-19 15:59:54 -04:00
std : : cerr < < " In autowash. " < < std : : endl ;
# endif
2009-06-14 14:59:42 -04:00
// Remove hashes that are marked as such.
//
2010-03-12 14:39:23 -05:00
std : : vector < std : : pair < TurtleFileHash , TurtleVirtualPeerId > > peers_to_remove ;
2009-06-14 14:59:42 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
for ( unsigned int i = 0 ; i < _hashes_to_remove . size ( ) ; + + i )
{
std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . find ( _hashes_to_remove [ i ] ) ) ;
2009-08-25 16:49:50 -04:00
if ( it = = _incoming_file_hashes . end ( ) )
2009-06-14 14:59:42 -04:00
{
2010-03-07 09:42:13 -05:00
# ifdef P3TURTLE_DEBUG
2009-06-14 14:59:42 -04:00
std : : cerr < < " p3turtle: asked to stop monitoring file hash " < < _hashes_to_remove [ i ] < < " , but this hash is actually not handled by the turtle router. " < < std : : endl ;
2010-03-07 09:42:13 -05:00
# endif
2009-06-14 14:59:42 -04:00
continue ;
}
// copy the list of tunnels to remove.
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: stopping monitoring for file hash " < < _hashes_to_remove [ i ] < < " , and closing " < < it - > second . tunnels . size ( ) < < " tunnels ( " ;
# endif
std : : vector < TurtleTunnelId > tunnels_to_remove ;
2009-08-25 16:49:50 -04:00
for ( std : : vector < TurtleTunnelId > : : const_iterator it2 ( it - > second . tunnels . begin ( ) ) ; it2 ! = it - > second . tunnels . end ( ) ; + + it2 )
2009-06-14 14:59:42 -04:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < ( void * ) * it2 < < " , " ;
# endif
tunnels_to_remove . push_back ( * it2 ) ;
}
# ifdef P3TURTLE_DEBUG
std : : cerr < < " ) " < < std : : endl ;
# endif
for ( unsigned int k = 0 ; k < tunnels_to_remove . size ( ) ; + + k )
2010-03-12 14:39:23 -05:00
locked_closeTunnel ( tunnels_to_remove [ k ] , peers_to_remove ) ;
2009-06-14 14:59:42 -04:00
_incoming_file_hashes . erase ( it ) ;
}
if ( ! _hashes_to_remove . empty ( ) )
{
IndicateConfigChanged ( ) ; // initiates saving of handled hashes.
_hashes_to_remove . clear ( ) ;
}
}
2009-04-19 15:59:54 -04:00
// look for tunnels and stored temporary info that have not been used for a while.
time_t now = time ( NULL ) ;
2009-06-03 14:47:14 -04:00
// Search requests
//
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-02-09 16:53:49 -05:00
for ( std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : iterator it ( _search_requests_origins . begin ( ) ) ; it ! = _search_requests_origins . end ( ) ; )
2009-06-03 14:47:14 -04:00
if ( now > ( time_t ) ( it - > second . time_stamp + SEARCH_REQUESTS_LIFE_TIME ) )
{
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-03 14:47:14 -04:00
std : : cerr < < " removed search request " < < ( void * ) it - > first < < " , timeout. " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2010-02-09 16:53:49 -05:00
std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : iterator tmp ( it ) ;
+ + tmp ;
2009-06-03 14:47:14 -04:00
_search_requests_origins . erase ( it ) ;
2010-02-09 16:53:49 -05:00
it = tmp ;
2009-06-03 14:47:14 -04:00
}
2010-02-09 16:53:49 -05:00
else
+ + it ;
2009-06-03 14:47:14 -04:00
}
2009-04-13 16:26:13 -04:00
2009-06-03 14:47:14 -04:00
// Tunnel requests
//
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-02-09 16:53:49 -05:00
for ( std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : iterator it ( _tunnel_requests_origins . begin ( ) ) ; it ! = _tunnel_requests_origins . end ( ) ; )
2009-06-03 14:47:14 -04:00
if ( now > ( time_t ) ( it - > second . time_stamp + TUNNEL_REQUESTS_LIFE_TIME ) )
{
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-03 14:47:14 -04:00
std : : cerr < < " removed tunnel request " < < ( void * ) it - > first < < " , timeout. " < < std : : endl ;
2009-04-19 15:59:54 -04:00
# endif
2010-02-09 16:53:49 -05:00
std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : iterator tmp ( it ) ;
+ + tmp ;
2009-06-03 14:47:14 -04:00
_tunnel_requests_origins . erase ( it ) ;
2010-02-09 16:53:49 -05:00
it = tmp ;
2009-06-03 14:47:14 -04:00
}
2010-02-09 16:53:49 -05:00
else
+ + it ;
2009-06-03 14:47:14 -04:00
}
// Tunnels.
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-06-14 14:59:42 -04:00
std : : vector < TurtleTunnelId > tunnels_to_close ;
2009-06-03 14:47:14 -04:00
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 ) ;
}
2009-06-14 14:59:42 -04:00
for ( unsigned int i = 0 ; i < tunnels_to_close . size ( ) ; + + i )
2010-03-12 14:39:23 -05:00
locked_closeTunnel ( tunnels_to_close [ i ] , peers_to_remove ) ;
2009-06-03 14:47:14 -04:00
}
// File hashes can only be removed by calling the 'stopMonitoringFileTunnels()' command.
2010-03-12 14:39:23 -05:00
// All calls to _ft_controller are done off-mutex, to avoir cross-lock
for ( uint32_t i = 0 ; i < peers_to_remove . size ( ) ; + + i )
_ft_controller - > removeFileSource ( peers_to_remove [ i ] . first , peers_to_remove [ i ] . second ) ;
2009-03-12 16:08:02 -04:00
}
2010-03-12 14:39:23 -05:00
void p3turtle : : locked_closeTunnel ( TurtleTunnelId tid , std : : vector < std : : pair < TurtleFileHash , TurtleVirtualPeerId > > & sources_to_remove )
2009-06-03 14:47:14 -04:00
{
// This is closing a given tunnel, removing it from file sources, and from the list of tunnels of its
2009-08-25 16:49:50 -04:00
// corresponding file hash. In the original turtle4privacy paradigm, they also send back and forward
2011-03-15 19:09:31 -04:00
// tunnel closing commands. In our case, this is not necessary, because if a tunnel is closed somewhere, its
2009-06-03 14:47:14 -04:00
// source is not going to be used and the tunnel will eventually disappear.
//
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it ( _local_tunnels . find ( tid ) ) ;
if ( it = = _local_tunnels . end ( ) )
{
2009-06-14 14:59:42 -04:00
std : : cerr < < " p3turtle: was asked to close tunnel " < < ( void * ) tid < < " , which actually doesn't exist. " < < std : : endl ;
2009-06-03 14:47:14 -04:00
return ;
}
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-15 16:34:34 -04:00
std : : cerr < < " p3turtle: Closing tunnel " < < ( void * ) tid < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-06-03 14:47:14 -04:00
2011-07-09 14:39:34 -04:00
if ( it - > second . local_src = = mLinkMgr - > getOwnId ( ) ) // this is a starting tunnel. We thus remove
2009-06-03 14:47:14 -04:00
// - 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
2009-06-14 14:59:42 -04:00
std : : cerr < < " Tunnel is a starting point. Also removing: " < < std : : endl ;
2009-06-03 14:47:14 -04:00
std : : cerr < < " Virtual Peer Id " < < vpid < < std : : endl ;
std : : cerr < < " Associated file source. " < < std : : endl ;
# endif
2010-03-12 14:39:23 -05:00
sources_to_remove . push_back ( std : : pair < TurtleFileHash , TurtleVirtualPeerId > ( hash , vpid ) ) ;
2009-06-03 14:47:14 -04:00
2010-02-05 17:45:52 -05:00
// Let's be cautious. Normally we should never be here without consistent information,
// but still, this happens, rarely.
2009-06-15 16:34:34 -04:00
//
2010-02-05 17:45:52 -05:00
if ( _virtual_peers . find ( vpid ) ! = _virtual_peers . end ( ) )
_virtual_peers . erase ( _virtual_peers . find ( vpid ) ) ;
std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . find ( hash ) ) ;
if ( it ! = _incoming_file_hashes . end ( ) )
{
std : : vector < TurtleTunnelId > & tunnels ( it - > second . tunnels ) ;
// Remove tunnel id from it's corresponding hash. For security we
// go through the whole tab, although the tunnel id should only be listed once
// in this tab.
//
for ( unsigned int i = 0 ; i < tunnels . size ( ) ; )
if ( tunnels [ i ] = = tid )
{
tunnels [ i ] = tunnels . back ( ) ;
tunnels . pop_back ( ) ;
}
else
+ + i ;
}
2009-06-03 14:47:14 -04:00
}
2011-07-09 14:39:34 -04:00
else if ( it - > second . local_dst = = mLinkMgr - > getOwnId ( ) ) // This is a ending tunnel. We also remove the virtual peer id
2009-06-03 14:47:14 -04:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Tunnel is a ending point. Also removing associated outgoing hash. " ;
# endif
2010-07-04 01:50:33 -04:00
std : : map < TurtleFileHash , FileInfo > : : iterator itHash = _outgoing_file_hashes . find ( it - > second . hash ) ;
if ( itHash ! = _outgoing_file_hashes . end ( ) )
_outgoing_file_hashes . erase ( itHash ) ;
2009-06-03 14:47:14 -04:00
}
_local_tunnels . erase ( it ) ;
}
void p3turtle : : stopMonitoringFileTunnels ( const std : : string & hash )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
# ifdef P3TURTLE_DEBUG
2009-06-14 14:59:42 -04:00
std : : cerr < < " p3turtle: Marking hash " < < hash < < " to be removed during autowash. " < < std : : endl ;
2009-06-03 14:47:14 -04:00
# endif
2009-06-14 14:59:42 -04:00
// We don't do the deletion in this process, because it can cause a race with tunnel management.
_hashes_to_remove . push_back ( hash ) ;
2009-06-03 14:47:14 -04:00
}
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Config functions ------------------------------ //
2009-06-03 14:47:14 -04:00
// -----------------------------------------------------------------------------------//
//
RsSerialiser * p3turtle : : setupSerialiser ( )
{
2009-06-13 15:28:47 -04:00
RsSerialiser * rss = new RsSerialiser ;
rss - > addSerialType ( new RsTurtleSerialiser ) ;
2012-02-10 17:23:06 -05:00
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
2009-06-03 14:47:14 -04:00
return rss ;
}
2010-12-18 14:35:07 -05:00
2012-02-10 17:23:06 -05:00
bool p3turtle : : saveList ( bool & cleanup , std : : list < RsItem * > & lst )
2009-06-03 14:47:14 -04:00
{
2009-06-13 15:28:47 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: saving list... " < < std : : endl ;
# endif
2009-06-03 14:47:14 -04:00
cleanup = true ;
2009-06-13 15:28:47 -04:00
2012-02-10 17:23:06 -05:00
RsConfigKeyValueSet * vitem = new RsConfigKeyValueSet ;
RsTlvKeyValue kv ;
kv . key = " TURTLE_CONFIG_MAX_TR_RATE " ;
2012-04-15 10:37:44 -04:00
rs_sprintf ( kv . value , " %g " , _max_tr_up_rate ) ;
2012-02-10 17:23:06 -05:00
vitem - > tlvkvs . pairs . push_back ( kv ) ;
lst . push_back ( vitem ) ;
2009-06-13 15:28:47 -04:00
2010-12-18 14:35:07 -05:00
return true ;
2009-06-03 14:47:14 -04:00
}
2010-01-26 15:40:21 -05:00
2012-02-10 17:23:06 -05:00
bool p3turtle : : loadList ( std : : list < RsItem * > & load )
2009-06-03 14:47:14 -04:00
{
2009-06-13 15:28:47 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: loading list... " < < std : : endl ;
# endif
for ( std : : list < RsItem * > : : const_iterator it ( load . begin ( ) ) ; it ! = load . end ( ) ; + + it )
{
# ifdef P3TURTLE_DEBUG
assert ( item ! = NULL ) ;
# endif
2012-02-10 17:23:06 -05:00
RsConfigKeyValueSet * vitem = dynamic_cast < RsConfigKeyValueSet * > ( * it ) ;
2009-06-13 15:28:47 -04:00
2012-02-10 17:23:06 -05:00
if ( vitem ! = NULL )
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 " )
{
# ifdef CHAT_DEBUG
std : : cerr < < " Loaded config default nick name for chat: " < < kit - > value < < std : : endl ;
2009-06-13 15:28:47 -04:00
# endif
2012-02-10 17:23:06 -05:00
std : : istringstream is ( kit - > value ) ;
int val ;
is > > val ;
setMaxTRForwardRate ( val ) ;
}
delete vitem ;
2009-06-13 15:28:47 -04:00
}
2009-06-03 14:47:14 -04:00
return true ;
}
2012-02-10 17:23:06 -05:00
int p3turtle : : getMaxTRForwardRate ( ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
return _max_tr_up_rate ;
}
void p3turtle : : setMaxTRForwardRate ( int val )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
if ( val > MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT | | val < MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT )
std : : cerr < < " Warning: MAX_TR_FORWARD_PER_SEC value " < < val < < " read in config file is off limits [ " < < MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT < < " ... " < < MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT < < " ]. Ignoring! " < < std : : endl ;
else
{
_max_tr_up_rate = val ;
std : : cerr < < " p3turtle: Set max tr up rate to " < < val < < std : : endl ;
}
IndicateConfigChanged ( ) ;
}
2009-06-03 14:47:14 -04:00
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Helper functions ------------------------------ //
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-08-25 16:49:50 -04:00
uint32_t p3turtle : : generateRandomRequestId ( )
2009-03-13 17:14:30 -04:00
{
2010-09-14 17:26:18 -04:00
return RSRandom : : random_u32 ( ) ;
2009-03-13 17:14:30 -04:00
}
2009-09-11 10:32:06 -04:00
2009-08-25 16:49:50 -04:00
uint32_t p3turtle : : generatePersonalFilePrint ( const TurtleFileHash & hash , bool b )
2009-03-12 16:08:02 -04:00
{
2009-04-13 16:26:13 -04:00
// whatever cooking from the file hash and OwnId that cannot be recovered.
2010-09-14 17:26:18 -04:00
// The only important thing is that the saem couple (hash,SSL id) produces the same tunnel
2009-06-13 15:28:47 -04:00
// id. The result uses a boolean to allow generating non symmetric tunnel ids.
2009-03-12 16:08:02 -04:00
2011-07-09 14:39:34 -04:00
std : : string buff ( hash + mLinkMgr - > getOwnId ( ) ) ;
2009-04-13 16:26:13 -04:00
uint32_t res = 0 ;
uint32_t decal = 0 ;
2009-04-16 16:30:59 -04:00
for ( int i = 0 ; i < ( int ) buff . length ( ) ; + + i )
2009-03-15 18:45:40 -04:00
{
2009-04-13 16:26:13 -04:00
res + = 7 * buff [ i ] + decal ;
2009-06-13 15:28:47 -04:00
if ( b )
decal = decal * 44497 + 15641 + ( res % 86243 ) ;
else
decal = decal * 86243 + 15649 + ( res % 44497 ) ;
2009-03-15 18:45:40 -04:00
}
2009-04-13 16:26:13 -04:00
return res ;
2009-02-28 13:19:00 -05:00
}
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Global routing. -------------------------------- //
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-02-28 13:19:00 -05:00
int p3turtle : : handleIncoming ( )
{
int nhandled = 0 ;
// While messages read
//
RsItem * item = NULL ;
while ( NULL ! = ( item = recvItem ( ) ) )
{
nhandled + + ;
2010-01-02 16:30:19 -05:00
RsTurtleGenericTunnelItem * gti = dynamic_cast < RsTurtleGenericTunnelItem * > ( item ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
if ( gti ! = NULL )
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.
/// These packets are destroyed here, after treatment.
//
switch ( item - > PacketSubType ( ) )
{
case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST :
case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST : handleSearchRequest ( dynamic_cast < RsTurtleSearchRequestItem * > ( item ) ) ;
break ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult ( dynamic_cast < RsTurtleSearchResultItem * > ( item ) ) ;
break ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest ( dynamic_cast < RsTurtleOpenTunnelItem * > ( item ) ) ;
break ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult ( dynamic_cast < RsTurtleTunnelOkItem * > ( item ) ) ;
break ;
default :
std : : cerr < < " p3turtle::handleIncoming: Unknown packet subtype " < < item - > PacketSubType ( ) < < std : : endl ;
}
delete item ;
2009-02-28 13:19:00 -05:00
}
}
return nhandled ;
}
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Search handling. ------------------------------- //
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-03-12 16:08:02 -04:00
void p3turtle : : handleSearchRequest ( RsTurtleSearchRequestItem * item )
2009-02-28 13:19:00 -05:00
{
2009-03-13 17:14:30 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-08-25 16:49:50 -04:00
// take a look at the item:
// - If the item destimation is
2009-02-28 13:19:00 -05:00
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
2009-03-15 18:45:40 -04:00
std : : cerr < < " Received search request from peer " < < item - > PeerId ( ) < < " : " < < std : : endl ;
2009-03-12 17:07:00 -04:00
item - > print ( std : : cerr , 0 ) ;
2009-03-12 16:08:02 -04:00
# endif
2011-05-28 10:39:47 -04:00
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 ;
# 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 ;
}
2009-02-28 13:19:00 -05:00
// If the item contains an already handled search request, give up. This
// happens when the same search request gets relayed by different peers
//
2009-04-13 16:26:13 -04:00
if ( _search_requests_origins . find ( item - > request_id ) ! = _search_requests_origins . end ( ) )
2009-03-12 16:08:02 -04:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " This is a bouncing request. Ignoring and deleting it. " < < std : : endl ;
# endif
2009-02-28 13:19:00 -05:00
return ;
2009-03-12 16:08:02 -04:00
}
2009-02-28 13:19:00 -05:00
2009-08-25 16:49:50 -04:00
// This is a new request. Let's add it to the request map, and forward it to
2009-02-28 13:19:00 -05:00
// open peers.
2009-04-19 15:59:54 -04:00
TurtleRequestInfo & req ( _search_requests_origins [ item - > request_id ] ) ;
req . origin = item - > PeerId ( ) ;
req . time_stamp = time ( NULL ) ;
2011-05-31 17:22:18 -04:00
req . depth = item - > depth ;
2009-02-28 13:19:00 -05:00
2009-03-12 16:08:02 -04:00
// If it's not for us, perform a local search. If something found, forward the search result back.
2009-08-25 16:49:50 -04:00
2011-07-09 14:39:34 -04:00
if ( item - > PeerId ( ) ! = mLinkMgr - > getOwnId ( ) )
2009-02-28 13:19:00 -05:00
{
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Request not from us. Performing local search " < < std : : endl ;
# endif
2009-03-22 10:08:02 -04:00
if ( _sharing_strategy ! = SHARE_FRIENDS_ONLY | | item - > depth < 2 )
2009-03-12 16:08:02 -04:00
{
2009-03-22 10:08:02 -04:00
std : : list < TurtleFileInfo > result ;
2009-08-25 08:04:43 -04:00
item - > performLocalSearch ( result ) ;
2009-03-22 10:08:02 -04:00
2009-04-06 17:06:44 -04:00
RsTurtleSearchResultItem * res_item = NULL ;
uint32_t item_size = 0 ;
# ifdef P3TURTLE_DEBUG
2009-03-22 10:08:02 -04:00
if ( ! result . empty ( ) )
2009-04-06 17:06:44 -04:00
std : : cerr < < " " < < result . size ( ) < < " matches found. Sending back to origin ( " < < item - > PeerId ( ) < < " ). " < < std : : endl ;
# endif
while ( ! result . empty ( ) )
2009-03-22 10:08:02 -04:00
{
2009-04-06 17:06:44 -04:00
// 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 ( ) ) ;
item_size + = 8 /* size */ + result . front ( ) . hash . size ( ) + result . front ( ) . name . size ( ) ;
result . pop_front ( ) ;
if ( item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE | | result . empty ( ) )
{
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
2009-04-06 17:06:44 -04:00
std : : cerr < < " Sending back chunk of size " < < item_size < < " , for " < < res_item - > result . size ( ) < < " elements. " < < std : : endl ;
2009-03-12 16:08:02 -04:00
# endif
2009-04-06 17:06:44 -04:00
sendItem ( res_item ) ;
res_item = NULL ;
}
2009-03-22 10:08:02 -04:00
}
2009-03-12 16:08:02 -04:00
}
2009-03-22 10:08:02 -04:00
# ifdef P3TURTLE_DEBUG
else
std : : cerr < < " Rejecting local search because strategy is FRIENDS_ONLY and item depth= " < < item - > depth < < std : : endl ;
# endif
2009-02-28 13:19:00 -05:00
}
// If search depth not too large, also forward this search request to all other peers.
//
2011-04-07 16:16:43 -04:00
// We use a random factor on the depth test that is biased by a mix between the session id and the partial tunnel id
// to scramble a possible search-by-depth attack.
//
2011-04-10 15:22:15 -04:00
bool random_bypass = ( item - > depth = = TURTLE_MAX_SEARCH_DEPTH & & ( ( ( _random_bias ^ item - > request_id ) & 0x7 ) = = 2 ) ) ;
2011-10-21 17:39:36 -04:00
bool random_dshift = ( item - > depth = = 1 & & ( ( ( _random_bias ^ item - > request_id ) & 0x7 ) = = 6 ) ) ;
2011-04-07 16:16:43 -04:00
if ( item - > depth < TURTLE_MAX_SEARCH_DEPTH | | random_bypass )
2009-03-12 16:08:02 -04:00
{
std : : list < std : : string > onlineIds ;
2011-07-09 14:39:34 -04:00
mLinkMgr - > getOnlineList ( onlineIds ) ;
2009-03-15 18:45:40 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Looking for online peers " < < std : : endl ;
# endif
2009-03-12 16:08:02 -04:00
2009-03-12 17:07:00 -04:00
for ( std : : list < std : : string > : : const_iterator it ( onlineIds . begin ( ) ) ; it ! = onlineIds . end ( ) ; + + it )
2012-01-14 08:27:48 -05:00
{
uint32_t linkType = mLinkMgr - > getLinkType ( * it ) ;
if ( ( linkType & RS_NET_CONN_SPEED_TRICKLE ) | | ( linkType & RS_NET_CONN_SPEED_LOW ) ) // don't forward searches to slow link types (e.g relay peers)!
continue ;
2009-03-12 17:07:00 -04:00
if ( * it ! = item - > PeerId ( ) )
2009-02-28 13:19:00 -05:00
{
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Forwarding request to peer = " < < * it < < std : : endl ;
# endif
2009-02-28 13:19:00 -05:00
// Copy current item and modify it.
2009-08-25 08:04:43 -04:00
RsTurtleSearchRequestItem * fwd_item = item - > clone ( ) ;
2009-02-28 13:19:00 -05:00
2011-10-21 17:39:36 -04:00
// 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 ) ;
2009-03-12 17:07:00 -04:00
fwd_item - > PeerId ( * it ) ;
2009-02-28 13:19:00 -05:00
sendItem ( fwd_item ) ;
}
2012-01-14 08:27:48 -05:00
}
2009-03-12 16:08:02 -04:00
}
# ifdef P3TURTLE_DEBUG
else
std : : cout < < " Dropping this item, as search depth is " < < item - > depth < < std : : endl ;
# endif
2009-02-28 13:19:00 -05:00
}
2009-03-12 17:07:00 -04:00
void p3turtle : : handleSearchResult ( RsTurtleSearchResultItem * item )
2009-02-28 13:19:00 -05:00
{
2009-03-13 17:14:30 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-02-28 13:19:00 -05:00
// Find who actually sent the corresponding request.
//
2009-04-19 15:59:54 -04:00
std : : map < TurtleRequestId , TurtleRequestInfo > : : const_iterator it = _search_requests_origins . find ( item - > request_id ) ;
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Received search result: " < < std : : endl ;
2009-03-12 17:07:00 -04:00
item - > print ( std : : cerr , 0 ) ;
2009-03-12 16:08:02 -04:00
# endif
2009-04-13 16:26:13 -04:00
if ( it = = _search_requests_origins . end ( ) )
2009-02-28 13:19:00 -05:00
{
2009-08-25 16:49:50 -04:00
// This is an error: how could we receive a search result corresponding to a search item we
2009-02-28 13:19:00 -05:00
// have forwarded but that it not in the list ??
std : : cerr < < __PRETTY_FUNCTION__ < < " : search result has no peer direction! " < < std : : endl ;
return ;
}
// Is this result's target actually ours ?
2009-08-25 16:49:50 -04:00
2009-03-15 18:45:40 -04:00
+ + ( item - > depth ) ; // increase depth
2011-07-09 14:39:34 -04:00
if ( it - > second . origin = = mLinkMgr - > getOwnId ( ) )
2009-02-28 13:19:00 -05:00
returnSearchResult ( item ) ; // Yes, so send upward.
else
{ // Nope, so forward it back.
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
2009-04-19 15:59:54 -04:00
std : : cerr < < " Forwarding result back to " < < it - > second . origin < < std : : endl ;
2009-03-12 16:08:02 -04:00
# endif
2009-03-12 17:07:00 -04:00
RsTurtleSearchResultItem * fwd_item = new RsTurtleSearchResultItem ( * item ) ; // copy the item
2009-02-28 13:19:00 -05:00
2009-09-11 10:32:06 -04:00
// Normally here, we should setup the forward adress, so that the owner's
// of the files found can be further reached by a tunnel.
2009-02-28 13:19:00 -05:00
2009-04-19 15:59:54 -04:00
fwd_item - > PeerId ( it - > second . origin ) ;
2009-06-03 14:47:14 -04:00
fwd_item - > depth = 2 + ( rand ( ) % 256 ) ; // obfuscate the depth for non immediate friends.
2009-02-28 13:19:00 -05:00
sendItem ( fwd_item ) ;
}
}
2009-05-26 17:42:45 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// --------------------------------- File Transfer. -------------------------------- //
2009-05-26 17:42:45 -04:00
// -----------------------------------------------------------------------------------//
2010-01-02 16:30:19 -05:00
// Routing of turtle tunnel items in a generic manner. Most tunnel packets will use this function, except packets designed for
// contructing the tunnels and searching, namely TurtleSearchRequests/Results and OpenTunnel/TunnelOkItems
//
2011-09-04 16:01:30 -04:00
// Only packets coming from handleIncoming() end up here, so this function is able to catch the transiting traffic.
//
2010-01-02 16:30:19 -05:00
void p3turtle : : routeGenericTunnelItem ( RsTurtleGenericTunnelItem * item )
2009-05-26 17:42:45 -04:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3Turtle: treating generic tunnel item: " < < std : : endl ;
2009-05-26 17:42:45 -04:00
item - > print ( std : : cerr , 1 ) ;
# endif
2010-01-02 16:30:19 -05:00
RsTurtleGenericTunnelItem : : Direction direction = item - > travelingDirection ( ) ;
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-01-02 16:30:19 -05:00
// look for the tunnel id.
//
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it ( _local_tunnels . find ( item - > tunnelId ( ) ) ) ;
2009-05-26 17:42:45 -04:00
if ( it = = _local_tunnels . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file map with unknown tunnel id " < < ( void * ) item - > tunnelId ( ) < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2010-07-04 01:50:33 -04:00
delete item ;
2009-05-26 17:42:45 -04:00
return ;
}
TurtleTunnel & tunnel ( it - > second ) ;
2010-01-02 16:30:19 -05:00
// Only file data transfer updates tunnels time_stamp field, to avoid maintaining tunnel that are incomplete.
if ( item - > shouldStampTunnel ( ) )
tunnel . time_stamp = time ( NULL ) ;
2011-05-26 18:11:06 -04:00
tunnel . transfered_bytes + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2010-06-19 08:11:44 -04:00
2010-01-02 16:30:19 -05:00
// Let's figure out whether this packet is for us or not.
2009-05-26 17:42:45 -04:00
2011-07-09 14:39:34 -04:00
if ( direction = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT & & tunnel . local_src ! = mLinkMgr - > getOwnId ( ) )
2010-01-02 16:30:19 -05:00
{
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " Forwarding generic item to peer " < < tunnel . local_src < < std : : endl ;
2009-05-26 17:42:45 -04:00
# endif
2010-01-02 16:30:19 -05:00
item - > PeerId ( tunnel . local_src ) ;
2011-05-26 18:11:06 -04:00
_traffic_info_buffer . unknown_updn_Bps + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2011-09-04 16:01:30 -04:00
if ( dynamic_cast < RsTurtleFileDataItem * > ( item ) ! = NULL )
item - > setPriorityLevel ( QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA ) ;
2010-01-02 16:30:19 -05:00
sendItem ( item ) ;
return ;
2009-05-26 17:42:45 -04:00
}
2011-07-09 14:39:34 -04:00
if ( direction = = RsTurtleGenericTunnelItem : : DIRECTION_SERVER & & tunnel . local_dst ! = mLinkMgr - > getOwnId ( ) )
2010-01-02 16:30:19 -05:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Forwarding generic item to peer " < < tunnel . local_dst < < std : : endl ;
# endif
item - > PeerId ( tunnel . local_dst ) ;
2009-05-26 17:42:45 -04:00
2011-05-26 18:11:06 -04:00
_traffic_info_buffer . unknown_updn_Bps + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2010-01-02 16:30:19 -05:00
sendItem ( item ) ;
2009-05-26 17:42:45 -04:00
return ;
}
}
2010-01-02 16:30:19 -05:00
// The packet was not forwarded, so it is for us. Let's treat it.
// This is done off-mutex, to avoid various deadlocks
2009-05-26 17:42:45 -04:00
//
2010-01-11 11:00:42 -05:00
switch ( item - > PacketSubType ( ) )
{
case RS_TURTLE_SUBTYPE_FILE_REQUEST : handleRecvFileRequest ( dynamic_cast < RsTurtleFileRequestItem * > ( item ) ) ;
break ;
2010-01-02 16:30:19 -05:00
2010-01-11 11:00:42 -05:00
case RS_TURTLE_SUBTYPE_FILE_DATA : handleRecvFileData ( dynamic_cast < RsTurtleFileDataItem * > ( item ) ) ;
break ;
case RS_TURTLE_SUBTYPE_FILE_MAP : handleRecvFileMap ( dynamic_cast < RsTurtleFileMapItem * > ( item ) ) ;
break ;
case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : handleRecvFileMapRequest ( dynamic_cast < RsTurtleFileMapRequestItem * > ( item ) ) ;
break ;
2010-07-21 19:14:10 -04:00
case RS_TURTLE_SUBTYPE_FILE_CRC : handleRecvFileCRC32Map ( dynamic_cast < RsTurtleFileCrcItem * > ( item ) ) ;
break ;
case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : handleRecvFileCRC32MapRequest ( dynamic_cast < RsTurtleFileCrcRequestItem * > ( item ) ) ;
break ;
2012-03-15 15:55:43 -04:00
case RS_TURTLE_SUBTYPE_CHUNK_CRC : handleRecvChunkCRC ( dynamic_cast < RsTurtleChunkCrcItem * > ( item ) ) ;
break ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : handleRecvChunkCRCRequest ( dynamic_cast < RsTurtleChunkCrcRequestItem * > ( item ) ) ;
break ;
2010-07-21 19:14:10 -04:00
default :
std : : cerr < < " WARNING: Unknown packet type received: id= " < < ( void * ) ( item - > PacketSubType ( ) ) < < " . Is somebody trying to poison you ? " < < std : : endl ;
2010-01-26 15:40:21 -05:00
# ifdef P3TURTLE_DEBUG
2010-07-21 19:14:10 -04:00
exit ( - 1 ) ;
2010-01-26 15:40:21 -05:00
# endif
2010-01-11 11:00:42 -05:00
}
2010-01-02 16:30:19 -05:00
delete item ;
2009-05-26 17:42:45 -04:00
}
2010-01-02 16:30:19 -05:00
void p3turtle : : handleRecvFileRequest ( RsTurtleFileRequestItem * item )
2009-05-26 17:42:45 -04:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3Turtle: received file request item: " < < std : : endl ;
2009-05-26 17:42:45 -04:00
item - > print ( std : : cerr , 1 ) ;
# endif
2009-08-25 16:49:50 -04:00
// This is a new request. Let's add it to the request map, and forward it to
2009-05-26 17:42:45 -04:00
// open peers.
TurtleVirtualPeerId vpid ;
uint64_t size ;
TurtleFileHash hash ;
2010-01-02 16:30:19 -05:00
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-01-02 16:30:19 -05:00
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
if ( it2 = = _local_tunnels . end ( ) )
2009-05-26 17:42:45 -04:00
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file request with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
2010-01-02 16:30:19 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
std : : map < TurtleFileHash , FileInfo > : : const_iterator it ( _outgoing_file_hashes . find ( tunnel . hash ) ) ;
# ifdef P3TURTLE_DEBUG
assert ( ! tunnel . hash . empty ( ) ) ;
assert ( it ! = _outgoing_file_hashes . end ( ) ) ;
2009-06-13 15:28:47 -04:00
2010-01-02 16:30:19 -05:00
std : : cerr < < " This is an endpoint for this file request. " < < std : : endl ;
std : : cerr < < " Forwarding data request to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
size = it - > second . size ;
vpid = tunnel . vpid ;
hash = tunnel . hash ;
}
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
// This call is voluntarily off-mutex gards because it can cause cross mutex locks with the multiplexer.
// (Yeah, this bug was a shity hard one to catch).
//
_ft_server - > getMultiplexer ( ) - > recvDataRequest ( vpid , hash , size , item - > chunk_offset , item - > chunk_size ) ;
}
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
void p3turtle : : handleRecvFileData ( RsTurtleFileDataItem * item )
{
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3Turtle: received file data item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
2009-08-25 16:49:50 -04:00
# endif
2010-01-02 16:30:19 -05:00
TurtleVirtualPeerId vpid ;
uint64_t size ;
TurtleFileHash hash ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2011-05-26 18:11:06 -04:00
_traffic_info_buffer . data_dn_Bps + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2010-01-02 16:30:19 -05:00
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
2009-06-14 14:59:42 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-08-25 16:49:50 -04:00
# endif
2010-01-02 16:30:19 -05:00
return ;
}
2009-06-14 14:59:42 -04:00
2010-01-02 16:30:19 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . find ( tunnel . hash ) ) ;
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
assert ( ! tunnel . hash . empty ( ) ) ;
2009-05-26 17:42:45 -04:00
# endif
2010-01-02 16:30:19 -05:00
if ( it = = _incoming_file_hashes . end ( ) )
2009-05-26 17:42:45 -04:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " No tunnel for incoming data. Maybe the tunnel is being closed. " < < std : : endl ;
2009-05-26 17:42:45 -04:00
# endif
return ;
}
2010-01-02 16:30:19 -05:00
const TurtleFileHashInfo & hash_info ( it - > second ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " This is an endpoint for this data chunk. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
//_ft_server->getMultiplexer()->recvData(tunnel.vpid,tunnel.hash,hash_info.size,item->chunk_offset,item->chunk_size,item->chunk_data) ;
vpid = tunnel . vpid ;
hash = tunnel . hash ;
size = hash_info . size ;
// also update the hash time stamp to show that it's actually being downloaded.
2011-03-15 19:09:31 -04:00
//it->second.time_stamp = time(NULL) ;
2009-05-26 17:42:45 -04:00
}
2010-01-02 16:30:19 -05:00
2009-05-26 17:42:45 -04:00
_ft_server - > getMultiplexer ( ) - > recvData ( vpid , hash , size , item - > chunk_offset , item - > chunk_size , item - > chunk_data ) ;
2009-06-13 15:28:47 -04:00
item - > chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted
// down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData
2009-05-26 17:42:45 -04:00
}
2010-01-11 11:00:42 -05:00
void p3turtle : : handleRecvFileMapRequest ( RsTurtleFileMapRequestItem * item )
2009-12-28 16:11:00 -05:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file Map item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
2010-01-11 11:00:42 -05:00
std : : string hash , vpid ;
2009-12-28 16:11:00 -05:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-01-02 16:30:19 -05:00
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
2009-12-28 16:11:00 -05:00
2010-01-02 16:30:19 -05:00
if ( it2 = = _local_tunnels . end ( ) )
2009-12-28 16:11:00 -05:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
return ;
}
2010-01-02 16:30:19 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
2009-12-28 16:11:00 -05:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
assert ( ! tunnel . hash . empty ( ) ) ;
2010-01-11 11:00:42 -05:00
std : : cerr < < " This is an endpoint for this file map request. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2010-01-11 11:00:42 -05:00
// we should check that there is no backward call to the turtle router!
//
hash = tunnel . hash ;
vpid = tunnel . vpid ;
}
_ft_server - > getMultiplexer ( ) - > recvChunkMapRequest ( vpid , hash , item - > direction = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
}
void p3turtle : : handleRecvFileMap ( RsTurtleFileMapItem * item )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file Map item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
std : : string hash , vpid ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
2010-01-02 16:30:19 -05:00
{
2009-12-28 16:11:00 -05:00
# ifdef P3TURTLE_DEBUG
2010-01-11 11:00:42 -05:00
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2010-01-02 16:30:19 -05:00
return ;
2009-12-28 16:11:00 -05:00
}
2010-01-02 16:30:19 -05:00
2010-01-11 11:00:42 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
2009-12-28 16:11:00 -05:00
# ifdef P3TURTLE_DEBUG
2010-01-11 11:00:42 -05:00
assert ( ! tunnel . hash . empty ( ) ) ;
2010-01-02 16:30:19 -05:00
std : : cerr < < " This is an endpoint for this file map. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2010-01-11 11:00:42 -05:00
// We should check that there is no backward call to the turtle router!
2010-01-02 16:30:19 -05:00
//
2010-01-11 11:00:42 -05:00
vpid = tunnel . vpid ;
hash = tunnel . hash ;
2009-12-28 16:11:00 -05:00
}
2010-01-11 11:00:42 -05:00
_ft_server - > getMultiplexer ( ) - > recvChunkMap ( vpid , hash , item - > compressed_map , item - > direction = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
2009-12-28 16:11:00 -05:00
}
2010-07-21 19:14:10 -04:00
void p3turtle : : handleRecvFileCRC32MapRequest ( RsTurtleFileCrcRequestItem * item )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file CRC32 Map Request item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
std : : string hash , vpid ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
# endif
return ;
}
TurtleTunnel & tunnel ( it2 - > second ) ;
# ifdef P3TURTLE_DEBUG
assert ( ! tunnel . hash . empty ( ) ) ;
std : : cerr < < " This is an endpoint for this file crc request. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
// we should check that there is no backward call to the turtle router!
//
hash = tunnel . hash ;
vpid = tunnel . vpid ;
}
2010-07-29 17:07:07 -04:00
_ft_server - > getMultiplexer ( ) - > recvCRC32MapRequest ( vpid , hash ) ;
2010-07-21 19:14:10 -04:00
}
2012-03-15 15:55:43 -04:00
void p3turtle : : handleRecvChunkCRC ( RsTurtleChunkCrcItem * item )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file CRC32 Map Request item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
std : : string hash , vpid ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: chunk crc request with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
# endif
return ;
}
TurtleTunnel & tunnel ( it2 - > second ) ;
# ifdef P3TURTLE_DEBUG
assert ( ! tunnel . hash . empty ( ) ) ;
std : : cerr < < " This is an endpoint for this file crc request. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
// we should check that there is no backward call to the turtle router!
//
hash = tunnel . hash ;
vpid = tunnel . vpid ;
}
_ft_server - > getMultiplexer ( ) - > recvSingleChunkCrc ( vpid , hash , item - > chunk_number , item - > check_sum ) ;
}
void p3turtle : : handleRecvChunkCRCRequest ( RsTurtleChunkCrcRequestItem * item )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file CRC32 Map Request item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
std : : string hash , vpid ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: chunk crc request with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
# endif
return ;
}
TurtleTunnel & tunnel ( it2 - > second ) ;
# ifdef P3TURTLE_DEBUG
assert ( ! tunnel . hash . empty ( ) ) ;
std : : cerr < < " This is an endpoint for this file crc request. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
// we should check that there is no backward call to the turtle router!
//
hash = tunnel . hash ;
vpid = tunnel . vpid ;
}
2010-07-21 19:14:10 -04:00
2012-03-15 15:55:43 -04:00
_ft_server - > getMultiplexer ( ) - > recvSingleChunkCrcRequest ( vpid , hash , item - > chunk_number ) ;
}
2010-07-21 19:14:10 -04:00
void p3turtle : : handleRecvFileCRC32Map ( RsTurtleFileCrcItem * item )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file CRC32 Map item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
std : : string hash , vpid ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: got file CRC32 map with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
# endif
return ;
}
TurtleTunnel & tunnel ( it2 - > second ) ;
# ifdef P3TURTLE_DEBUG
assert ( ! tunnel . hash . empty ( ) ) ;
std : : cerr < < " This is an endpoint for this file map. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
// We should check that there is no backward call to the turtle router!
//
vpid = tunnel . vpid ;
hash = tunnel . hash ;
}
2010-07-29 17:07:07 -04:00
_ft_server - > getMultiplexer ( ) - > recvCRC32Map ( vpid , hash , item - > crc_map ) ;
2010-07-21 19:14:10 -04:00
}
2009-05-26 17:42:45 -04:00
// Send a data request into the correct tunnel for the given file hash
2010-09-03 15:23:49 -04:00
void p3turtle : : sendDataRequest ( const std : : string & peerId , const std : : string & , uint64_t , uint64_t offset , uint32_t chunksize )
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileRequestItem * item = new RsTurtleFileRequestItem ;
item - > tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever.
item - > chunk_offset = offset ;
item - > chunk_size = chunksize ;
item - > PeerId ( tunnel . local_dst ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending file req (chunksize= " < < item - > chunk_size < < " , offset= " < < item - > chunk_offset < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < tunnel . local_dst < < std : : endl ;
# endif
sendItem ( item ) ;
}
// Send file data into the correct tunnel for the given file hash
2010-09-03 15:23:49 -04:00
void p3turtle : : sendFileData ( const std : : string & peerId , const std : : string & , uint64_t , uint64_t offset , uint32_t chunksize , void * data )
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle::sendData: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
2009-06-03 14:47:14 -04:00
tunnel . time_stamp = time ( NULL ) ;
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileDataItem * item = new RsTurtleFileDataItem ;
2009-08-25 16:49:50 -04:00
item - > tunnel_id = tunnel_id ;
2009-05-26 17:42:45 -04:00
item - > chunk_offset = offset ;
item - > chunk_size = chunksize ;
item - > chunk_data = malloc ( chunksize ) ;
2009-07-27 16:52:55 -04:00
2011-05-26 18:11:06 -04:00
tunnel . transfered_bytes + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2010-06-19 08:11:44 -04:00
2009-07-27 16:52:55 -04:00
if ( item - > chunk_data = = NULL )
{
std : : cerr < < " p3turtle: Warning: failed malloc of " < < chunksize < < " bytes for sending data packet. " < < std : : endl ;
2010-07-04 01:50:33 -04:00
delete item ;
2009-07-27 16:52:55 -04:00
return ;
}
2009-05-26 17:42:45 -04:00
memcpy ( item - > chunk_data , ( void * ) ( ( uint8_t * ) data ) , chunksize ) ;
item - > PeerId ( tunnel . local_src ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending file data (chunksize= " < < item - > chunk_size < < " , offset= " < < item - > chunk_offset < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < tunnel . local_src < < std : : endl ;
# endif
2011-05-26 18:11:06 -04:00
_traffic_info_buffer . data_up_Bps + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2009-05-26 17:42:45 -04:00
sendItem ( item ) ;
}
2010-09-03 15:23:49 -04:00
void p3turtle : : sendChunkMapRequest ( const std : : string & peerId , const std : : string & , bool is_client )
2010-01-11 11:00:42 -05:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileMapRequestItem * item = new RsTurtleFileMapRequestItem ;
item - > tunnel_id = tunnel_id ;
2011-07-09 14:39:34 -04:00
std : : string ownid = mLinkMgr - > getOwnId ( ) ;
2010-01-11 11:00:42 -05:00
if ( tunnel . local_src = = ownid )
{
2010-07-25 15:04:31 -04:00
assert ( ! is_client ) ;
2010-01-11 11:00:42 -05:00
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_SERVER ;
item - > PeerId ( tunnel . local_dst ) ;
}
else if ( tunnel . local_dst = = ownid )
{
2010-07-25 15:04:31 -04:00
assert ( is_client ) ;
2010-01-11 11:00:42 -05:00
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ;
item - > PeerId ( tunnel . local_src ) ;
}
else
2010-07-25 15:04:31 -04:00
std : : cerr < < " p3turtle::sendChunkMapRequest: consistency error! " < < std : : endl ;
2010-01-11 11:00:42 -05:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending chunk map req to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
2010-09-03 15:23:49 -04:00
void p3turtle : : sendChunkMap ( const std : : string & peerId , const std : : string & , const CompressedChunkMap & cmap , bool is_client )
2010-01-11 11:00:42 -05:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileMapItem * item = new RsTurtleFileMapItem ;
item - > tunnel_id = tunnel_id ;
item - > compressed_map = cmap ;
2011-07-09 14:39:34 -04:00
std : : string ownid = mLinkMgr - > getOwnId ( ) ;
2010-01-11 11:00:42 -05:00
if ( tunnel . local_src = = ownid )
{
2010-07-25 15:04:31 -04:00
assert ( ! is_client ) ;
2010-01-11 11:00:42 -05:00
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_SERVER ;
item - > PeerId ( tunnel . local_dst ) ;
}
else if ( tunnel . local_dst = = ownid )
{
2010-07-25 15:04:31 -04:00
assert ( is_client ) ;
2010-01-11 11:00:42 -05:00
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ;
item - > PeerId ( tunnel . local_src ) ;
}
else
std : : cerr < < " p3turtle::sendChunkMap: consistency error! " < < std : : endl ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending chunk map to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
2012-03-15 15:55:43 -04:00
void p3turtle : : sendSingleChunkCRC ( const std : : string & peerId , const std : : string & , uint32_t chunk_number , const Sha1CheckSum & crc )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::sendCRC32MapRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleChunkCrcItem * item = new RsTurtleChunkCrcItem ;
item - > tunnel_id = tunnel_id ;
item - > chunk_number = chunk_number ;
item - > check_sum = crc ;
item - > PeerId ( tunnel . local_dst ) ;
2010-01-11 11:00:42 -05:00
2012-03-15 15:55:43 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending CRC32 map request to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
void p3turtle : : sendSingleChunkCRCRequest ( const std : : string & peerId , const std : : string & , uint32_t chunk_number )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::sendCRC32MapRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleChunkCrcRequestItem * item = new RsTurtleChunkCrcRequestItem ;
item - > tunnel_id = tunnel_id ;
item - > chunk_number = chunk_number ;
item - > PeerId ( tunnel . local_dst ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending CRC32 map request to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
2010-09-03 15:23:49 -04:00
void p3turtle : : sendCRC32MapRequest ( const std : : string & peerId , const std : : string & )
2010-07-21 19:14:10 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::sendCRC32MapRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileCrcRequestItem * item = new RsTurtleFileCrcRequestItem ;
item - > tunnel_id = tunnel_id ;
// item->crc_map = cmap ;
item - > PeerId ( tunnel . local_dst ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending CRC32 map request to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
2010-09-03 15:23:49 -04:00
void p3turtle : : sendCRC32Map ( const std : : string & peerId , const std : : string & , const CRC32Map & cmap )
2010-07-21 19:14:10 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileCrcItem * item = new RsTurtleFileCrcItem ;
item - > tunnel_id = tunnel_id ;
item - > crc_map = cmap ;
item - > PeerId ( tunnel . local_src ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending CRC32 map to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
2009-05-26 17:42:45 -04:00
bool p3turtle : : isTurtlePeer ( const std : : string & peer_id ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
return _virtual_peers . find ( peer_id ) ! = _virtual_peers . end ( ) ;
}
2009-08-25 16:49:50 -04:00
std : : string p3turtle : : getTurtlePeerId ( TurtleTunnelId tid ) const
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : const_iterator it ( _local_tunnels . find ( tid ) ) ;
2009-06-03 14:47:14 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
assert ( it ! = _local_tunnels . end ( ) ) ;
assert ( it - > second . vpid ! = " " ) ;
2009-06-03 14:47:14 -04:00
# endif
2009-05-26 17:42:45 -04:00
return it - > second . vpid ;
}
bool p3turtle : : isOnline ( const std : : string & peer_id ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// we could do something mre clever here...
//
return _virtual_peers . find ( peer_id ) ! = _virtual_peers . end ( ) ;
}
2009-03-12 17:07:00 -04:00
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Tunnel handling. ------------------------------- //
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-04-19 15:59:54 -04:00
TurtleRequestId p3turtle : : diggTunnel ( const TurtleFileHash & hash )
2009-04-13 16:26:13 -04:00
{
# ifdef P3TURTLE_DEBUG
2011-07-09 14:39:34 -04:00
std : : cerr < < " DiggTunnel: performing tunnel request. OwnId = " < < mLinkMgr - > getOwnId ( ) < < " for hash= " < < hash < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2011-07-09 14:39:34 -04:00
while ( mLinkMgr - > getOwnId ( ) = = " " )
2009-04-13 16:26:13 -04:00
{
2011-03-15 19:09:31 -04:00
std : : cerr < < " ... waiting for connect manager to form own id. " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# ifdef WIN32
Sleep ( 1000 ) ;
# else
sleep ( 1 ) ;
# endif
}
TurtleRequestId id = generateRandomRequestId ( ) ;
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-08-25 16:49:50 -04:00
// Store the request id, so that we can find the hash back when we get the response.
2009-05-26 17:42:45 -04:00
//
_incoming_file_hashes [ hash ] . last_request = id ;
2011-03-15 19:09:31 -04:00
_incoming_file_hashes [ hash ] . last_digg_time = time ( NULL ) ;
2009-05-26 17:42:45 -04:00
}
2009-04-19 15:59:54 -04:00
2009-04-13 16:26:13 -04:00
// Form a tunnel request packet that simulates a request from us.
//
RsTurtleOpenTunnelItem * item = new RsTurtleOpenTunnelItem ;
2011-07-09 14:39:34 -04:00
item - > PeerId ( mLinkMgr - > getOwnId ( ) ) ;
2009-04-13 16:26:13 -04:00
item - > file_hash = hash ;
item - > request_id = id ;
2009-06-13 15:28:47 -04:00
item - > partial_tunnel_id = generatePersonalFilePrint ( hash , true ) ;
2009-04-13 16:26:13 -04:00
item - > depth = 0 ;
2009-08-25 16:49:50 -04:00
// send it
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
TS_request_bounces [ item - > request_id ] . clear ( ) ; // forces initialization
# endif
2009-04-13 16:26:13 -04:00
handleTunnelRequest ( item ) ;
delete item ;
2009-04-19 15:59:54 -04:00
return id ;
2009-04-13 16:26:13 -04:00
}
void p3turtle : : handleTunnelRequest ( RsTurtleOpenTunnelItem * item )
{
2009-03-15 18:45:40 -04:00
# ifdef P3TURTLE_DEBUG
2011-04-10 15:22:15 -04:00
std : : cerr < < " Received tunnel request from peer " < < item - > PeerId ( ) < < " : " < < std : : endl ;
item - > print ( std : : cerr , 0 ) ;
2009-04-13 16:26:13 -04:00
# endif
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
if ( TS_request_bounces . find ( item - > request_id ) ! = TS_request_bounces . end ( ) )
TS_request_bounces [ item - > request_id ] . push_back ( time ( NULL ) ) ;
# endif
2011-05-28 16:36:52 -04:00
// TR forwarding. We must pay attention not to flood the network. The policy is to force a statistical behavior
// according to the followin grules:
// - below a number of tunnel request forwards per second MAX_TR_FORWARD_PER_SEC, we keep the traffic
// - if we get close to that limit, we drop long tunnels first with a probability that is larger for long tunnels
//
// Variables involved:
// distance_to_maximum : in [0,inf] is the proportion of the current up TR speed with respect to the maximum allowed speed. This is estimated
// as an average between the average number of TR over the 60 last seconds and the current TR up speed.
// corrected_distance : in [0,inf] is a squeezed version of distance: small values become very small and large values become very large.
// depth_peer_probability : basic probability of forwarding when the speed limit is reached.
// forward_probability : final probability of forwarding the packet, per peer.
//
// When the number of peers increases, the speed limit is reached faster, but the behavior per peer is the same.
//
float forward_probability ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
_traffic_info_buffer . tr_dn_Bps + = static_cast < RsTurtleItem * > ( item ) - > serial_size ( ) ;
2012-02-10 17:23:06 -05:00
float distance_to_maximum = std : : min ( 100.0f , _traffic_info . tr_up_Bps / ( float ) ( TUNNEL_REQUEST_PACKET_SIZE * _max_tr_up_rate ) ) ;
2011-05-28 16:36:52 -04:00
float corrected_distance = pow ( distance_to_maximum , DISTANCE_SQUEEZING_POWER ) ;
forward_probability = pow ( depth_peer_probability [ std : : min ( ( uint16_t ) 6 , item - > depth ) ] , corrected_distance ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Forwarding probability: depth= " < < item - > depth < < " , distance to max speed= " < < distance_to_maximum < < " , corrected= " < < corrected_distance < < " , prob.= " < < forward_probability < < std : : endl ;
# endif
2011-10-01 07:46:00 -04:00
// if(forward_probability < 0.1)
// {
//#ifdef P3TURTLE_DEBUG
// std::cerr << "Dropped packet!" << std::endl;
//#endif
// return ;
// }
2011-05-28 16:36:52 -04:00
}
2011-03-15 19:09:31 -04:00
2009-04-13 16:26:13 -04:00
// If the item contains an already handled tunnel request, give up. This
2010-01-02 16:30:19 -05:00
// happens when the same tunnel request gets relayed by different peers. We
// have to be very careful here, not to call ftController while mTurtleMtx is
// locked.
2009-04-13 16:26:13 -04:00
//
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2011-04-07 16:16:43 -04:00
std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : iterator it = _tunnel_requests_origins . find ( item - > request_id ) ;
if ( it ! = _tunnel_requests_origins . end ( ) )
2009-05-26 17:42:45 -04:00
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2011-04-07 16:16:43 -04:00
std : : cerr < < " This is a bouncing request. Ignoring and deleting item. " < < std : : endl ;
# endif
// This trick allows to shorten tunnels, favoring tunnels of smallest length, with a bias that
// depends on a mix between a session-based constant and the tunnel partial id. This means
// that for a given couple of (source,hash), the optimisation always performs the same.
// overall, 80% tunnels are re-routed. The probability of a tunnel to have optimal length is
// thus 0.875^n where n is the length of the tunnel, supposing that it has 2 branching peers
// at each node. This makes:
// n probability
// 1 0.875
// 2 0.76
// 3 0.67
// 4 0.58
// 5 0.512
//
// The lower the probability, the higher the anonymity level.
//
if ( it - > second . depth > item - > depth & & ( ( item - > partial_tunnel_id ^ _random_bias ) & 0x7 ) > 0 )
{
2011-04-10 15:22:15 -04:00
# ifdef P3TURTLE_DEBUG
2011-04-07 16:16:43 -04:00
std : : cerr < < " re-routing tunnel request. Item age difference = " < < time ( NULL ) - it - > second . time_stamp < < std : : endl ;
std : : cerr < < " - old source: " < < it - > second . origin < < " , old depth= " < < it - > second . depth < < std : : endl ;
std : : cerr < < " - new source: " < < item - > PeerId ( ) < < " , new depth= " < < item - > depth < < std : : endl ;
2011-04-10 15:22:15 -04:00
std : : cerr < < " - half id: " < < ( void * ) it - > first < < std : : endl ;
# endif
2011-04-07 16:16:43 -04:00
it - > second . origin = item - > PeerId ( ) ;
it - > second . depth = item - > depth ;
}
2009-05-26 17:42:45 -04:00
return ;
}
2010-01-02 16:30:19 -05:00
// This is a new request. Let's add it to the request map, and forward
// it to open peers, while the mutex is locked, so no-one can trigger the
// lock before the data is consistent.
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
TurtleRequestInfo & req ( _tunnel_requests_origins [ item - > request_id ] ) ;
req . origin = item - > PeerId ( ) ;
req . time_stamp = time ( NULL ) ;
2011-04-07 16:16:43 -04:00
req . depth = item - > depth ;
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
std : : cerr < < " storing tunnel request " < < ( void * ) ( item - > request_id ) < < std : : endl ;
+ + TS_tunnel_length [ item - > depth ] ;
TS_request_time_stamps [ item - > file_hash ] . push_back ( std : : pair < time_t , TurtleTunnelRequestId > ( time ( NULL ) , item - > request_id ) ) ;
# endif
2010-01-02 16:30:19 -05:00
}
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
// If it's not for us, perform a local search. If something found, forward the search result back.
// We're off-mutex here.
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
bool found = false ;
FileInfo info ;
2011-07-09 14:39:34 -04:00
if ( item - > PeerId ( ) ! = mLinkMgr - > getOwnId ( ) )
2010-01-02 16:30:19 -05:00
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " Request not from us. Performing local search " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2010-01-02 16:30:19 -05:00
found = ( _sharing_strategy ! = SHARE_FRIENDS_ONLY | | item - > depth < 2 ) & & performLocalHashSearch ( item - > file_hash , info ) ;
}
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
if ( found )
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " Local hash found. Sending tunnel ok to origin ( " < < item - > PeerId ( ) < < " ). " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2010-01-02 16:30:19 -05:00
// Send back tunnel ok to the same guy
//
RsTurtleTunnelOkItem * res_item = new RsTurtleTunnelOkItem ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
res_item - > request_id = item - > request_id ;
res_item - > tunnel_id = item - > partial_tunnel_id ^ generatePersonalFilePrint ( item - > file_hash , false ) ;
res_item - > PeerId ( item - > PeerId ( ) ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
sendItem ( res_item ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
// Note in the tunnels list that we have an ending tunnel here.
TurtleTunnel tt ;
tt . local_src = item - > PeerId ( ) ;
tt . hash = item - > file_hash ;
2011-07-09 14:39:34 -04:00
tt . local_dst = mLinkMgr - > getOwnId ( ) ; // this means us
2010-01-02 16:30:19 -05:00
tt . time_stamp = time ( NULL ) ;
2010-06-19 08:11:44 -04:00
tt . transfered_bytes = 0 ;
tt . speed_Bps = 0.0f ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
_local_tunnels [ res_item - > tunnel_id ] = tt ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
// We add a virtual peer for that tunnel+hash combination.
//
2010-12-07 16:45:12 -05:00
locked_addDistantPeer ( item - > file_hash , res_item - > tunnel_id ) ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
// Store the size of the file, to be able to re-form data requests to the multiplexer.
//
_outgoing_file_hashes [ item - > file_hash ] = info ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
// We return straight, because when something is found, there's no need to digg a tunnel further.
return ;
}
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
else
std : : cerr < < " No hash found locally, or local file not allowed for distant peers. Forwarding. " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
}
// If search depth not too large, also forward this search request to all other peers.
//
2011-05-28 10:39:47 -04:00
bool random_bypass = ( item - > depth > = TURTLE_MAX_SEARCH_DEPTH & & ( ( ( _random_bias ^ item - > partial_tunnel_id ) & 0x7 ) = = 2 ) ) ;
2011-10-21 17:39:36 -04:00
bool random_dshift = ( item - > depth = = 1 & & ( ( ( _random_bias ^ item - > partial_tunnel_id ) & 0x7 ) = = 6 ) ) ;
2011-04-07 16:16:43 -04:00
if ( item - > depth < TURTLE_MAX_SEARCH_DEPTH | | random_bypass )
2009-04-13 16:26:13 -04:00
{
std : : list < std : : string > onlineIds ;
2011-07-09 14:39:34 -04:00
mLinkMgr - > getOnlineList ( onlineIds ) ;
2012-04-19 16:23:58 -04:00
int nb_online_ids = onlineIds . size ( ) ;
if ( forward_probability * nb_online_ids < 1.0f & & nb_online_ids > 0 )
forward_probability = 1.0f / nb_online_ids ;
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Forwarding tunnel request: Looking for online peers " < < std : : endl ;
# endif
for ( std : : list < std : : string > : : const_iterator it ( onlineIds . begin ( ) ) ; it ! = onlineIds . end ( ) ; + + it )
2012-01-14 08:27:48 -05:00
{
uint32_t linkType = mLinkMgr - > getLinkType ( * it ) ;
if ( ( linkType & RS_NET_CONN_SPEED_TRICKLE ) | | ( linkType & RS_NET_CONN_SPEED_LOW ) ) // don't forward tunnel requests to slow link types (e.g relay peers)!
continue ;
2011-05-28 10:39:47 -04:00
if ( * it ! = item - > PeerId ( ) & & RSRandom : : random_f32 ( ) < = forward_probability )
2009-04-13 16:26:13 -04:00
{
# ifdef P3TURTLE_DEBUG
2011-05-28 10:39:47 -04:00
std : : cerr < < " Forwarding request to peer = " < < * it < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
// Copy current item and modify it.
RsTurtleOpenTunnelItem * fwd_item = new RsTurtleOpenTunnelItem ( * item ) ;
2011-10-21 17:39:36 -04:00
// 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 ) ; // increase tunnel depth
2009-04-13 16:26:13 -04:00
fwd_item - > PeerId ( * it ) ;
2011-05-26 18:11:06 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
_traffic_info_buffer . tr_up_Bps + = static_cast < RsTurtleItem * > ( fwd_item ) - > serial_size ( ) ;
}
2009-04-13 16:26:13 -04:00
sendItem ( fwd_item ) ;
}
2012-01-14 08:27:48 -05:00
}
2009-04-13 16:26:13 -04:00
}
# ifdef P3TURTLE_DEBUG
else
std : : cout < < " Dropping this item, as tunnel depth is " < < item - > depth < < std : : endl ;
# endif
}
void p3turtle : : handleTunnelResult ( RsTurtleTunnelOkItem * item )
{
2009-05-26 17:42:45 -04:00
bool new_tunnel = false ;
TurtleFileHash new_hash ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// Find who actually sent the corresponding turtle tunnel request.
//
2011-04-10 15:22:15 -04:00
std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : iterator it = _tunnel_requests_origins . find ( item - > request_id ) ;
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " Received tunnel result: " < < std : : endl ;
item - > print ( std : : cerr , 0 ) ;
2009-04-13 16:26:13 -04:00
# endif
2011-04-10 15:22:15 -04:00
2009-05-26 17:42:45 -04:00
if ( it = = _tunnel_requests_origins . end ( ) )
{
2009-08-25 16:49:50 -04:00
// This is an error: how could we receive a tunnel result corresponding to a tunnel item we
2011-04-10 15:22:15 -04:00
// have forwarded but that it not in the list ?? Actually that happens, when tunnel requests
// get too old, before the tunnelOk item gets back. But this is quite unusual.
2009-04-13 16:26:13 -04:00
2011-04-10 15:22:15 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < __PRETTY_FUNCTION__ < < " : tunnel result has no peer direction! " < < std : : endl ;
2011-04-10 15:22:15 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
2011-04-10 15:22:15 -04:00
if ( it - > second . responses . find ( item - > tunnel_id ) ! = it - > second . responses . end ( ) )
{
std : : cerr < < " p3turtle: ERROR: received a tunnel response twice. That should not happen. " < < std : : endl ;
return ;
}
else
it - > second . responses . insert ( item - > tunnel_id ) ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
// store tunnel info.
2009-06-13 15:28:47 -04:00
bool found = ( _local_tunnels . find ( item - > tunnel_id ) ! = _local_tunnels . end ( ) ) ;
2009-05-26 17:42:45 -04:00
TurtleTunnel & tunnel ( _local_tunnels [ item - > tunnel_id ] ) ;
2009-06-13 15:28:47 -04:00
if ( found )
2009-07-27 16:52:55 -04:00
{
# ifdef P3TURTLE_DEBUG
2009-06-13 15:28:47 -04:00
std : : cerr < < " Tunnel id " < < ( void * ) item - > tunnel_id < < " is already there. Not storing. " < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
}
2009-06-13 15:28:47 -04:00
else
{
tunnel . local_src = it - > second . origin ;
tunnel . local_dst = item - > PeerId ( ) ;
tunnel . hash = " " ;
tunnel . time_stamp = time ( NULL ) ;
2010-06-19 08:11:44 -04:00
tunnel . transfered_bytes = 0 ;
tunnel . speed_Bps = 0.0f ;
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-13 15:28:47 -04:00
std : : cerr < < " storing tunnel info. src= " < < tunnel . local_src < < " , dst= " < < tunnel . local_dst < < " , id= " < < item - > tunnel_id < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2009-06-13 15:28:47 -04:00
}
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
// Is this result's target actually ours ?
2009-04-13 16:26:13 -04:00
2011-07-09 14:39:34 -04:00
if ( it - > second . origin = = mLinkMgr - > getOwnId ( ) )
2009-05-26 17:42:45 -04:00
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-13 15:28:47 -04:00
std : : cerr < < " Tunnel starting point. Storing id= " < < ( void * ) item - > tunnel_id < < " for hash (unknown) and tunnel request id " < < it - > second . origin < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2009-05-26 17:42:45 -04:00
// Tunnel is ending here. Add it to the list of tunnels for the given hash.
2009-04-13 16:26:13 -04:00
2011-03-15 19:09:31 -04:00
// 1 - find which file hash issued this request. This is not costly,
// because there is not too much file hashes to be active at a time,
// and this mostly prevents from sending the hash back in the tunnel.
2009-04-19 15:59:54 -04:00
2009-05-26 17:42:45 -04:00
bool found = false ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
if ( it - > second . last_request = = item - > request_id )
{
found = true ;
2009-06-15 16:34:34 -04:00
// add the tunnel uniquely
bool found = false ;
for ( unsigned int j = 0 ; j < it - > second . tunnels . size ( ) ; + + j )
if ( it - > second . tunnels [ j ] = = item - > tunnel_id )
found = true ;
if ( ! found )
it - > second . tunnels . push_back ( item - > tunnel_id ) ;
2009-05-26 17:42:45 -04:00
tunnel . hash = it - > first ; // because it's a local tunnel
// Adds a virtual peer to the list of online peers.
// We do this later, because of the mutex protection.
//
new_tunnel = true ;
new_hash = it - > first ;
2010-12-07 16:45:12 -05:00
locked_addDistantPeer ( new_hash , item - > tunnel_id ) ;
2009-05-26 17:42:45 -04:00
}
if ( ! found )
std : : cerr < < " p3turtle: error. Could not find hash that emmitted tunnel request " < < ( void * ) item - > tunnel_id < < std : : endl ;
}
else
{ // Nope, forward it back.
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " Forwarding result back to " < < it - > second . origin < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2009-05-26 17:42:45 -04:00
RsTurtleTunnelOkItem * fwd_item = new RsTurtleTunnelOkItem ( * item ) ; // copy the item
fwd_item - > PeerId ( it - > second . origin ) ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
sendItem ( fwd_item ) ;
}
}
2009-08-25 16:49:50 -04:00
// A new tunnel has been created. Add the corresponding virtual peer to the list, and
2009-05-26 17:42:45 -04:00
// notify the file transfer controller for the new file source. This should be done off-mutex
// so we deported this code here.
//
if ( new_tunnel )
{
_ft_controller - > addFileSource ( new_hash , _local_tunnels [ item - > tunnel_id ] . vpid ) ;
_ft_controller - > statusChange ( _online_peers ) ;
2009-04-13 16:26:13 -04:00
}
2009-03-12 16:08:02 -04:00
}
2009-02-28 13:19:00 -05:00
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// ------------------------------ IO with libretroshare ----------------------------//
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-08-25 08:04:43 -04:00
void RsTurtleStringSearchRequestItem : : performLocalSearch ( std : : list < TurtleFileInfo > & result ) const
2009-04-13 16:26:13 -04:00
{
/* call to core */
2009-08-25 16:49:50 -04:00
std : : list < DirDetails > initialResults ;
2009-04-13 16:26:13 -04:00
std : : list < std : : string > words ;
2009-02-28 13:19:00 -05:00
2009-04-13 16:26:13 -04:00
// to do: split search string into words.
2009-08-25 08:04:43 -04:00
words . push_back ( match_string ) ;
2009-08-25 16:49:50 -04:00
2010-02-03 15:59:54 -05:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Performing rsFiles->search() " < < std : : endl ;
# endif
2009-04-13 16:26:13 -04:00
// now, search!
2009-08-10 15:44:45 -04:00
rsFiles - > SearchKeywords ( words , initialResults , DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE ) ;
2009-04-13 16:26:13 -04:00
2010-02-03 15:59:54 -05:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < initialResults . size ( ) < < " matches found. " < < std : : endl ;
# endif
2009-04-13 16:26:13 -04:00
result . clear ( ) ;
2009-08-25 16:49:50 -04:00
for ( std : : list < DirDetails > : : const_iterator it ( initialResults . begin ( ) ) ; it ! = initialResults . end ( ) ; + + it )
2009-04-13 16:26:13 -04:00
{
2009-08-25 16:49:50 -04:00
// retain only file type
2010-02-03 15:59:54 -05:00
if ( it - > type = = DIR_TYPE_DIR )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Skipping directory " < < it - > name < < std : : endl ;
# endif
continue ;
}
2009-08-25 16:49:50 -04:00
2009-04-13 16:26:13 -04:00
TurtleFileInfo i ;
i . hash = it - > hash ;
2009-08-25 16:49:50 -04:00
i . size = it - > count ;
2009-04-13 16:26:13 -04:00
i . name = it - > name ;
result . push_back ( i ) ;
}
}
2009-08-25 08:04:43 -04:00
void RsTurtleRegExpSearchRequestItem : : performLocalSearch ( std : : list < TurtleFileInfo > & result ) const
{
/* call to core */
2009-08-25 16:49:50 -04:00
std : : list < DirDetails > initialResults ;
2009-08-25 08:04:43 -04:00
// to do: split search string into words.
Expression * exp = LinearizedExpression : : toExpr ( expr ) ;
2009-08-25 16:49:50 -04:00
2011-06-28 04:18:54 -04:00
if ( exp = = NULL )
return ;
2009-08-25 08:04:43 -04:00
// now, search!
rsFiles - > SearchBoolExp ( exp , initialResults , DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE ) ;
result . clear ( ) ;
2009-08-25 16:49:50 -04:00
for ( std : : list < DirDetails > : : const_iterator it ( initialResults . begin ( ) ) ; it ! = initialResults . end ( ) ; + + it )
2009-08-25 08:04:43 -04:00
{
TurtleFileInfo i ;
i . hash = it - > hash ;
2009-08-25 16:49:50 -04:00
i . size = it - > count ;
2009-08-25 08:04:43 -04:00
i . name = it - > name ;
result . push_back ( i ) ;
}
delete exp ;
}
2009-04-13 16:26:13 -04:00
2009-08-25 16:49:50 -04:00
TurtleRequestId p3turtle : : turtleSearch ( const std : : string & string_to_match )
2009-04-13 16:26:13 -04:00
{
// generate a new search id.
2009-08-25 16:49:50 -04:00
2009-04-13 16:26:13 -04:00
TurtleRequestId id = generateRandomRequestId ( ) ;
2009-03-13 17:14:30 -04:00
2009-04-13 16:26:13 -04:00
// Form a request packet that simulates a request from us.
//
2009-08-25 08:04:43 -04:00
RsTurtleStringSearchRequestItem * item = new RsTurtleStringSearchRequestItem ;
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2011-07-09 14:39:34 -04:00
std : : cerr < < " performing search. OwnId = " < < mLinkMgr - > getOwnId ( ) < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2011-07-09 14:39:34 -04:00
while ( mLinkMgr - > getOwnId ( ) = = " " )
2009-04-13 16:26:13 -04:00
{
std : : cerr < < " ... waitting for connect manager to form own id. " < < std : : endl ;
# ifdef WIN32
Sleep ( 1000 ) ;
# else
sleep ( 1 ) ;
# endif
}
2011-07-09 14:39:34 -04:00
item - > PeerId ( mLinkMgr - > getOwnId ( ) ) ;
2009-04-13 16:26:13 -04:00
item - > match_string = string_to_match ;
item - > request_id = id ;
item - > depth = 0 ;
2009-08-25 16:49:50 -04:00
// send it
2009-04-13 16:26:13 -04:00
handleSearchRequest ( item ) ;
delete item ;
return id ;
}
2009-08-25 16:49:50 -04:00
TurtleRequestId p3turtle : : turtleSearch ( const LinearizedExpression & expr )
2009-08-25 08:04:43 -04:00
{
// generate a new search id.
2009-08-25 16:49:50 -04:00
2009-08-25 08:04:43 -04:00
TurtleRequestId id = generateRandomRequestId ( ) ;
// Form a request packet that simulates a request from us.
//
RsTurtleRegExpSearchRequestItem * item = new RsTurtleRegExpSearchRequestItem ;
# ifdef P3TURTLE_DEBUG
2011-07-09 14:39:34 -04:00
std : : cerr < < " performing search. OwnId = " < < mLinkMgr - > getOwnId ( ) < < std : : endl ;
2009-08-25 08:04:43 -04:00
# endif
2011-07-09 14:39:34 -04:00
while ( mLinkMgr - > getOwnId ( ) = = " " )
2009-08-25 08:04:43 -04:00
{
std : : cerr < < " ... waitting for connect manager to form own id. " < < std : : endl ;
# ifdef WIN32
Sleep ( 1000 ) ;
# else
sleep ( 1 ) ;
# endif
}
2011-07-09 14:39:34 -04:00
item - > PeerId ( mLinkMgr - > getOwnId ( ) ) ;
2009-08-25 08:04:43 -04:00
item - > expr = expr ;
item - > request_id = id ;
item - > depth = 0 ;
2009-08-25 16:49:50 -04:00
// send it
2009-08-25 08:04:43 -04:00
handleSearchRequest ( item ) ;
delete item ;
return id ;
}
2009-04-13 16:26:13 -04:00
2009-08-25 16:49:50 -04:00
void p3turtle : : monitorFileTunnels ( const std : : string & name , const std : : string & file_hash , uint64_t size )
2009-04-13 16:26:13 -04:00
{
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-03-13 17:14:30 -04:00
2010-03-12 14:39:23 -05:00
// First, check if the hash is tagged for removal (there's a delay)
2010-03-13 07:24:14 -05:00
for ( uint32_t i = 0 ; i < _hashes_to_remove . size ( ) ; + + i )
2010-03-12 14:39:23 -05:00
if ( _hashes_to_remove [ i ] = = file_hash )
{
_hashes_to_remove [ i ] = _hashes_to_remove . back ( ) ;
_hashes_to_remove . pop_back ( ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: File hash " < < file_hash < < " Was scheduled for removal. Canceling the removal. " < < std : : endl ;
# endif
}
// Then, check if the hash is already there
//
2009-05-26 17:42:45 -04:00
if ( _incoming_file_hashes . find ( file_hash ) ! = _incoming_file_hashes . end ( ) ) // download already asked.
2009-03-15 18:45:40 -04:00
{
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle: File hash " < < file_hash < < " already in pool. Returning. " < < std : : endl ;
2009-05-07 17:36:17 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
2009-03-15 18:45:40 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle: Received order for turtle download fo hash " < < file_hash < < std : : endl ;
2009-05-07 17:36:17 -04:00
# endif
2009-03-15 18:45:40 -04:00
2009-05-26 17:42:45 -04:00
// No tunnels at start, but this triggers digging new tunnels.
//
_incoming_file_hashes [ file_hash ] . tunnels . clear ( ) ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
// also should send associated request to the file transfer module.
_incoming_file_hashes [ file_hash ] . size = size ;
_incoming_file_hashes [ file_hash ] . name = name ;
2011-03-15 19:09:31 -04:00
_incoming_file_hashes [ file_hash ] . last_digg_time = RSRandom : : random_u32 ( ) % 10 ;
2009-04-13 16:26:13 -04:00
}
2009-03-15 18:45:40 -04:00
2009-06-03 14:47:14 -04:00
IndicateConfigChanged ( ) ; // initiates saving of handled hashes.
2009-04-13 16:26:13 -04:00
}
2009-05-26 17:42:45 -04:00
void p3turtle : : returnSearchResult ( RsTurtleSearchResultItem * item )
2009-04-13 16:26:13 -04:00
{
2009-05-26 17:42:45 -04:00
// just cout for now, but it should be notified to the gui
2009-08-25 16:49:50 -04:00
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-08-25 08:04:43 -04:00
std : : cerr < < " Returning result for search request " < < ( void * ) item - > request_id < < " upwards. " < < std : : endl ;
2009-05-07 17:36:17 -04:00
# endif
2009-04-19 15:59:54 -04:00
2009-05-26 17:42:45 -04:00
rsicontrol - > getNotify ( ) . notifyTurtleSearchResult ( item - > request_id , item - > result ) ;
2009-04-19 15:59:54 -04:00
}
2010-01-02 16:30:19 -05:00
/// 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.
//
2009-08-25 16:49:50 -04:00
bool p3turtle : : performLocalHashSearch ( const TurtleFileHash & hash , FileInfo & info )
2009-04-19 15:59:54 -04:00
{
2010-05-29 09:17:09 -04:00
return rsFiles - > FileDetails ( hash , RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD , info ) ;
2009-04-19 15:59:54 -04:00
}
2010-06-19 08:11:44 -04:00
static std : : string printFloatNumber ( float num , bool friendly = false )
2011-03-15 19:09:31 -04:00
{
2010-06-19 08:11:44 -04:00
if ( friendly )
{
char tmp [ 100 ] ;
std : : string units [ 4 ] = { " B/s " , " KB/s " , " MB/s " , " GB/s " } ;
int k = 0 ;
while ( num > = 800.0f & & k < 5 )
num / = 1024.0f , + + k ;
sprintf ( tmp , " %3.2f %s " , num , units [ k ] . c_str ( ) ) ;
return std : : string ( tmp ) ;
}
else
{
2012-04-15 10:37:44 -04:00
std : : string out ;
rs_sprintf ( out , " %g " , num ) ;
return out ;
2010-06-19 08:11:44 -04:00
}
}
2009-09-05 07:59:42 -04:00
static std : : string printNumber ( uint64_t num , bool hex = false )
2009-08-16 16:10:53 -04:00
{
if ( hex )
{
char tmp [ 100 ] ;
2010-01-21 07:33:01 -05:00
2010-02-08 18:09:46 -05:00
if ( num < ( ( ( uint64_t ) 1 ) < < 32 ) )
2010-01-21 07:33:01 -05:00
sprintf ( tmp , " %08x " , uint32_t ( num ) ) ;
else
2010-03-12 14:39:23 -05:00
sprintf ( tmp , " %08x%08x " , uint32_t ( num > > 32 ) , uint32_t ( num & ( ( ( ( uint64_t ) 1 ) < < 32 ) - 1 ) ) ) ;
2009-08-16 16:10:53 -04:00
return std : : string ( tmp ) ;
}
else
{
2012-04-15 10:37:44 -04:00
std : : string out ;
rs_sprintf ( out , " %lld " , num ) ;
return out ;
2009-08-16 16:10:53 -04:00
}
}
2011-05-26 18:11:06 -04:00
void p3turtle : : getTrafficStatistics ( TurtleTrafficStatisticsInfo & info ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
info = _traffic_info ;
2011-10-01 07:46:00 -04:00
2012-02-10 17:23:06 -05:00
float distance_to_maximum = std : : min ( 100.0f , info . tr_up_Bps / ( float ) ( TUNNEL_REQUEST_PACKET_SIZE * _max_tr_up_rate ) ) ;
2011-10-01 07:46:00 -04:00
info . forward_probabilities . clear ( ) ;
2012-04-19 16:23:58 -04:00
std : : list < std : : string > onlineIds ;
mLinkMgr - > getOnlineList ( onlineIds ) ;
int nb_online_ids = onlineIds . size ( ) ;
2011-10-01 07:46:00 -04:00
for ( int i = 0 ; i < = 6 ; + + i )
{
float corrected_distance = pow ( distance_to_maximum , DISTANCE_SQUEEZING_POWER ) ;
float forward_probability = pow ( depth_peer_probability [ i ] , corrected_distance ) ;
2012-04-19 16:23:58 -04:00
if ( forward_probability * nb_online_ids < 1.0f & & nb_online_ids > 0 )
forward_probability = 1.0f / nb_online_ids ;
2011-10-01 07:46:00 -04:00
info . forward_probabilities . push_back ( forward_probability ) ;
}
2011-05-26 18:11:06 -04:00
}
2009-08-16 16:10:53 -04:00
void p3turtle : : getInfo ( std : : vector < std : : vector < std : : string > > & hashes_info ,
std : : vector < std : : vector < std : : string > > & tunnels_info ,
2011-05-23 17:45:25 -04:00
std : : vector < TurtleRequestDisplayInfo > & search_reqs_info ,
std : : vector < TurtleRequestDisplayInfo > & tunnel_reqs_info ) const
2009-08-16 16:10:53 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
time_t now = time ( NULL ) ;
hashes_info . clear ( ) ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
{
hashes_info . push_back ( std : : vector < std : : string > ( ) ) ;
std : : vector < std : : string > & hashes ( hashes_info . back ( ) ) ;
hashes . push_back ( it - > first ) ;
hashes . push_back ( it - > second . name ) ;
hashes . push_back ( printNumber ( it - > second . tunnels . size ( ) ) ) ;
2011-03-15 19:09:31 -04:00
//hashes.push_back(printNumber(now - it->second.time_stamp)+" secs ago") ;
2009-08-16 16:10:53 -04:00
}
2010-03-06 18:29:47 -05:00
2009-08-16 16:10:53 -04:00
tunnels_info . clear ( ) ;
for ( std : : map < TurtleTunnelId , TurtleTunnel > : : const_iterator it ( _local_tunnels . begin ( ) ) ; it ! = _local_tunnels . end ( ) ; + + it )
{
tunnels_info . push_back ( std : : vector < std : : string > ( ) ) ;
std : : vector < std : : string > & tunnel ( tunnels_info . back ( ) ) ;
tunnel . push_back ( printNumber ( it - > first , true ) ) ;
2010-02-15 16:32:06 -05:00
2011-08-07 17:11:00 -04:00
std : : string name ;
if ( mLinkMgr - > getPeerName ( it - > second . local_src , name ) )
tunnel . push_back ( name ) ;
2011-04-25 10:15:57 -04:00
else
tunnel . push_back ( it - > second . local_src ) ;
2011-08-07 17:11:00 -04:00
if ( mLinkMgr - > getPeerName ( it - > second . local_dst , name ) )
tunnel . push_back ( name ) ;
2011-04-25 10:15:57 -04:00
else
tunnel . push_back ( it - > second . local_dst ) ;
2010-02-15 16:32:06 -05:00
2009-08-16 16:10:53 -04:00
tunnel . push_back ( it - > second . hash ) ;
2009-08-25 08:04:43 -04:00
tunnel . push_back ( printNumber ( now - it - > second . time_stamp ) + " secs ago " ) ;
2010-06-19 08:11:44 -04:00
tunnel . push_back ( printFloatNumber ( it - > second . speed_Bps , true ) ) ;
2009-08-16 16:10:53 -04:00
}
search_reqs_info . clear ( ) ;
for ( std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : const_iterator it ( _search_requests_origins . begin ( ) ) ; it ! = _search_requests_origins . end ( ) ; + + it )
{
2011-05-23 17:45:25 -04:00
TurtleRequestDisplayInfo info ;
2009-08-16 16:10:53 -04:00
2011-05-23 17:45:25 -04:00
info . request_id = it - > first ;
info . source_peer_id = it - > second . origin ;
info . age = now - it - > second . time_stamp ;
info . depth = it - > second . depth ;
2010-02-15 16:32:06 -05:00
2011-05-23 17:45:25 -04:00
search_reqs_info . push_back ( info ) ;
2009-08-16 16:10:53 -04:00
}
tunnel_reqs_info . clear ( ) ;
for ( std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : const_iterator it ( _tunnel_requests_origins . begin ( ) ) ; it ! = _tunnel_requests_origins . end ( ) ; + + it )
{
2011-05-23 17:45:25 -04:00
TurtleRequestDisplayInfo info ;
2009-08-16 16:10:53 -04:00
2011-05-23 17:45:25 -04:00
info . request_id = it - > first ;
info . source_peer_id = it - > second . origin ;
info . age = now - it - > second . time_stamp ;
info . depth = it - > second . depth ;
2011-04-25 10:15:57 -04:00
2011-05-23 17:45:25 -04:00
tunnel_reqs_info . push_back ( info ) ;
2009-08-16 16:10:53 -04:00
}
}
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
void p3turtle : : dumpState ( )
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-04-19 15:59:54 -04:00
time_t now = time ( NULL ) ;
std : : cerr < < std : : endl ;
std : : cerr < < " ********************** Turtle router dump ****************** " < < std : : endl ;
2009-05-26 17:42:45 -04:00
std : : cerr < < " Active incoming file hashes: " < < _incoming_file_hashes . size ( ) < < std : : endl ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2009-04-19 15:59:54 -04:00
{
2009-05-26 17:42:45 -04:00
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 )
2009-04-19 15:59:54 -04:00
std : : cerr < < " " < < ( void * ) * it2 ;
2009-06-13 15:28:47 -04:00
std : : cerr < < " , last_req= " < < ( void * ) it - > second . last_request < < " , time_stamp = " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp < < " secs ago) " < < std : : endl ;
2009-04-19 15:59:54 -04:00
}
2009-05-26 17:42:45 -04:00
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 )
2009-06-03 14:47:14 -04:00
std : : cerr < < " hash=0x " < < it - > first < < " , name= " < < it - > second . fname < < " , size= " < < it - > second . size < < std : : endl ;
2009-05-26 17:42:45 -04:00
2009-04-19 15:59:54 -04:00
std : : cerr < < " Local tunnels: " < < std : : endl ;
for ( std : : map < TurtleTunnelId , TurtleTunnel > : : const_iterator it ( _local_tunnels . begin ( ) ) ; it ! = _local_tunnels . end ( ) ; + + it )
2009-08-25 16:49:50 -04:00
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) "
2009-06-13 15:28:47 -04:00
< < " , peer id = " < < it - > second . vpid < < std : : endl ;
2009-04-19 15:59:54 -04:00
std : : cerr < < " buffered request origins: " < < std : : endl ;
std : : cerr < < " Search requests: " < < _search_requests_origins . size ( ) < < std : : endl ;
2009-06-03 14:47:14 -04:00
2009-04-19 15:59:54 -04:00
for ( std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : const_iterator it ( _search_requests_origins . begin ( ) ) ; it ! = _search_requests_origins . end ( ) ; + + it )
2009-08-25 16:49:50 -04:00
std : : cerr < < " " < < ( void * ) it - > first < < " : from= " < < it - > second . origin
< < " , ts= " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp
2009-06-03 14:47:14 -04:00
< < " secs ago) " < < std : : endl ;
2009-04-19 15:59:54 -04:00
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 )
2009-08-25 16:49:50 -04:00
std : : cerr < < " " < < ( void * ) it - > first < < " : from= " < < it - > second . origin
< < " , ts= " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp
2009-06-03 14:47:14 -04:00
< < " secs ago) " < < std : : endl ;
2009-05-26 17:42:45 -04:00
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 ;
std : : cerr < < " Online peers: " < < std : : endl ;
for ( std : : list < pqipeer > : : const_iterator it ( _online_peers . begin ( ) ) ; it ! = _online_peers . end ( ) ; + + it )
std : : cerr < < " id= " < < it - > id < < " , name= " < < it - > name < < " , state= " < < it - > state < < " , actions= " < < it - > actions < < std : : endl ;
2009-04-19 15:59:54 -04:00
}
# endif
2009-03-15 18:45:40 -04:00
2011-03-15 19:09:31 -04:00
# ifdef TUNNEL_STATISTICS
void p3turtle : : TS_dumpState ( )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
time_t now = time ( NULL ) ;
std : : cerr < < " Dumping tunnel statistics: " < < std : : endl ;
std : : cerr < < " TR Bounces: " < < TS_request_bounces . size ( ) < < std : : endl ;
for ( std : : map < TurtleTunnelRequestId , std : : vector < time_t > > : : const_iterator it ( TS_request_bounces . begin ( ) ) ; it ! = TS_request_bounces . end ( ) ; + + it )
{
std : : cerr < < ( void * ) it - > first < < " : " ;
for ( uint32_t i = 0 ; i < it - > second . size ( ) ; + + i )
std : : cerr < < it - > second [ i ] - it - > second [ 0 ] < < " " ;
std : : cerr < < std : : endl ;
}
std : : cerr < < " TR in cache: " < < _tunnel_requests_origins . size ( ) < < std : : endl ;
std : : cerr < < " TR by size: " ;
for ( int i = 0 ; i < 8 ; + + i )
std : : cerr < < " N( " < < i < < " )= " < < TS_tunnel_length [ i ] < < " , " ;
std : : cerr < < std : : endl ;
std : : cerr < < " Total different requested files: " < < TS_request_time_stamps . size ( ) < < std : : endl ;
for ( std : : map < TurtleFileHash , std : : vector < std : : pair < time_t , TurtleTunnelRequestId > > > : : const_iterator it ( TS_request_time_stamps . begin ( ) ) ; it ! = TS_request_time_stamps . end ( ) ; + + it )
{
std : : cerr < < " hash = " < < it - > first < < " : seconds ago: " ;
float average = 0 ;
for ( uint32_t i = std : : max ( 0 , ( int ) it - > second . size ( ) - 25 ) ; i < it - > second . size ( ) ; + + i )
{
std : : cerr < < now - it - > second [ i ] . first < < " ( " < < ( void * ) it - > second [ i ] . second < < " ) " ;
if ( i > 0 )
average + = it - > second [ i ] . first - it - > second [ i - 1 ] . first ;
}
if ( it - > second . size ( ) > 1 )
std : : cerr < < " , average delay= " < < average / ( float ) ( it - > second . size ( ) - 1 ) < < std : : endl ;
else
std : : cerr < < std : : endl ;
}
}
# endif