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
*
*/
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>
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.
//
2012-09-23 15:58:08 -04:00
static const time_t TUNNEL_REQUESTS_LIFE_TIME = 120 ; /// life time for tunnel requests in the cache.
static const time_t SEARCH_REQUESTS_LIFE_TIME = 240 ; /// life time for search requests in the cache
2012-04-19 16:23:58 -04:00
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
2013-04-10 04:52:52 -04:00
p3turtle : : p3turtle ( p3LinkMgr * lm )
2011-07-09 14:39:34 -04:00
: 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
2012-11-25 09:26:32 -05:00
_turtle_routing_enabled = true ;
2012-11-25 17:49:00 -05:00
_turtle_routing_session_enabled = true ;
2011-04-07 16:16:43 -04:00
_random_bias = RSRandom : : random_u32 ( ) ;
2013-04-06 05:21:01 -04:00
_serialiser = new RsTurtleSerialiser ( ) ;
2011-04-07 16:16:43 -04:00
2013-04-06 05:21:01 -04:00
addSerialType ( _serialiser ) ;
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 ( ) ;
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
}
2012-11-25 09:26:32 -05:00
void p3turtle : : setEnabled ( bool b )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
_turtle_routing_enabled = b ;
if ( b )
std : : cerr < < " Enabling turtle routing " < < std : : endl ;
else
std : : cerr < < " Disabling turtle routing " < < std : : endl ;
IndicateConfigChanged ( ) ;
}
bool p3turtle : : enabled ( ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
return _turtle_routing_enabled ;
}
2012-11-25 17:49:00 -05:00
void p3turtle : : setSessionEnabled ( bool b )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
_turtle_routing_session_enabled = b ;
if ( b )
std : : cerr < < " Enabling turtle routing for this Session " < < std : : endl ;
else
std : : cerr < < " Disabling turtle routing for this Session " < < std : : endl ;
}
bool p3turtle : : sessionEnabled ( ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
return _turtle_routing_session_enabled ;
}
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
2012-11-25 17:49:00 -05:00
if ( _turtle_routing_enabled & & _turtle_routing_session_enabled )
2012-11-25 09:26:32 -05:00
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
// -----------------------------------------------------------------------------------//
//
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
//
2013-04-01 17:18:58 -04:00
for ( std : : map < TurtleFileHash , TurtleHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2012-09-23 15:58:08 -04:00
{
// get total tunnel speed.
//
uint32_t total_speed = 0 ;
for ( uint32_t i = 0 ; i < it - > second . tunnels . size ( ) ; + + i )
total_speed + = _local_tunnels [ it - > second . tunnels [ i ] ] . speed_Bps ;
static const float grow_speed = 1.0f ; // speed at which the time increases.
float tunnel_keeping_factor = ( std : : max ( 1.0f , ( float ) total_speed / ( float ) ( 50 * 1024 ) ) - 1.0f ) * grow_speed + 1.0f ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Total speed = " < < total_speed < < " , tunel factor = " < < tunnel_keeping_factor < < " new time = " < < time_t ( REGULAR_TUNNEL_DIGGING_TIME * tunnel_keeping_factor ) < < std : : endl ;
# endif
if ( ( it - > second . tunnels . empty ( ) & & now > = it - > second . last_digg_time + EMPTY_TUNNELS_DIGGING_TIME ) | | now > = it - > second . last_digg_time + time_t ( REGULAR_TUNNEL_DIGGING_TIME * tunnel_keeping_factor ) )
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
}
2012-09-23 15:58:08 -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
2013-06-20 15:12:33 -04:00
std : : vector < std : : pair < RsTurtleClientService * , std : : pair < TurtleFileHash , TurtleVirtualPeerId > > > services_vpids_to_remove ;
2010-03-12 14:39:23 -05:00
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 )
{
2013-04-01 17:18:58 -04:00
std : : map < TurtleFileHash , TurtleHashInfo > : : iterator it ( _incoming_file_hashes . find ( _hashes_to_remove [ i ] ) ) ;
2009-06-14 14:59:42 -04:00
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 )
2013-06-20 15:12:33 -04:00
locked_closeTunnel ( tunnels_to_remove [ k ] , services_vpids_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 ) ;
}
2013-06-20 15:12:33 -04:00
2009-06-14 14:59:42 -04:00
for ( unsigned int i = 0 ; i < tunnels_to_close . size ( ) ; + + i )
2013-06-20 15:12:33 -04:00
locked_closeTunnel ( tunnels_to_close [ i ] , services_vpids_to_remove ) ;
2009-06-03 14:47:14 -04:00
}
2013-06-20 15:12:33 -04:00
// Now remove all the virtual peers ids at the client services. Off mutex!
//
2010-03-12 14:39:23 -05:00
2013-06-20 15:12:33 -04:00
for ( uint32_t i = 0 ; i < services_vpids_to_remove . size ( ) ; + + i )
2013-04-10 04:52:52 -04:00
{
2013-06-20 15:12:33 -04:00
//#ifdef P3TURTLE_DEBUG
std : : cerr < < " removing virtual peer id " < < services_vpids_to_remove [ i ] . second . second < < " for service " < < services_vpids_to_remove [ i ] . first < < " , for hash " < < services_vpids_to_remove [ i ] . second . first < < std : : endl ;
//#endif
services_vpids_to_remove [ i ] . first - > removeVirtualPeer ( services_vpids_to_remove [ i ] . second . first , services_vpids_to_remove [ i ] . second . second ) ;
2013-04-10 04:52:52 -04:00
}
2009-03-12 16:08:02 -04:00
}
2013-06-20 15:12:33 -04:00
void p3turtle : : locked_closeTunnel ( TurtleTunnelId tid , std : : vector < std : : pair < RsTurtleClientService * , 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 ( ) )
{
2012-11-25 09:26:32 -05:00
std : : cerr < < " p3turtle: was asked to close tunnel " < < reinterpret_cast < 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
2013-06-20 15:12:33 -04:00
std : : pair < TurtleFileHash , TurtleVirtualPeerId > hash_vpid ( 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 ) ) ;
2013-04-01 17:18:58 -04:00
std : : map < TurtleFileHash , TurtleHashInfo > : : iterator it ( _incoming_file_hashes . find ( hash ) ) ;
2010-02-05 17:45:52 -05:00
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 ;
2013-06-20 15:12:33 -04:00
sources_to_remove . push_back ( std : : pair < RsTurtleClientService * , std : : pair < TurtleFileHash , TurtleVirtualPeerId > > ( it - > second . service , hash_vpid ) ) ;
2010-02-05 17:45:52 -05:00
}
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
2013-04-20 14:56:06 -04:00
std : : map < TurtleFileHash , RsTurtleClientService * > : : iterator itHash = _outgoing_file_hashes . find ( it - > second . hash ) ;
2010-07-04 01:50:33 -04:00
if ( itHash ! = _outgoing_file_hashes . end ( ) )
2013-06-20 15:12:33 -04:00
{
TurtleVirtualPeerId vpid = it - > second . vpid ;
TurtleFileHash hash = it - > second . hash ;
std : : pair < TurtleFileHash , TurtleVirtualPeerId > hash_vpid ( hash , vpid ) ;
sources_to_remove . push_back ( std : : pair < RsTurtleClientService * , std : : pair < TurtleFileHash , TurtleVirtualPeerId > > ( itHash - > second , hash_vpid ) ) ;
2010-07-04 01:50:33 -04:00
_outgoing_file_hashes . erase ( itHash ) ;
2013-06-20 15:12:33 -04:00
}
2009-06-03 14:47:14 -04:00
}
_local_tunnels . erase ( it ) ;
}
2013-04-01 17:18:58 -04:00
void p3turtle : : stopMonitoringTunnels ( const std : : string & hash )
2009-06-03 14:47:14 -04:00
{
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 ) ;
2012-11-25 09:26:32 -05:00
kv . key = " TURTLE_ENABLED " ;
kv . value = _turtle_routing_enabled ? " TRUE " : " FALSE " ;
vitem - > tlvkvs . pairs . push_back ( kv ) ;
2012-02-10 17:23:06 -05:00
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 )
{
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 )
2012-11-25 09:26:32 -05:00
{
2012-02-10 17:23:06 -05:00
if ( kit - > key = = " TURTLE_CONFIG_MAX_TR_RATE " )
{
int val ;
2012-05-03 09:41:03 -04:00
if ( sscanf ( kit - > value . c_str ( ) , " %d " , & val ) = = 1 )
{
setMaxTRForwardRate ( val ) ;
2012-11-25 09:26:32 -05:00
std : : cerr < < " Setting max TR forward rate to " < < val < < std : : endl ;
2012-05-03 09:41:03 -04:00
}
2012-02-10 17:23:06 -05:00
}
2012-11-25 09:26:32 -05:00
if ( kit - > key = = " TURTLE_ENABLED " )
{
_turtle_routing_enabled = ( kit - > value = = " TRUE " ) ;
if ( ! _turtle_routing_enabled )
std : : cerr < < " WARNING: turtle routing has been disabled. You can enable it again in config->server->turtle router. " < < std : : endl ;
}
}
2012-02-10 17:23:06 -05:00
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 + + ;
2012-12-01 14:22:22 -05:00
if ( ( ! ( _turtle_routing_enabled & & _turtle_routing_session_enabled ) ) | | ! ( RS_SERVICE_PERM_TURTLE & rsPeers - > servicePermissionFlags_sslid ( item - > PeerId ( ) ) ) )
2012-11-25 09:26:32 -05:00
delete item ;
else
2010-01-02 16:30:19 -05:00
{
2012-11-25 09:26:32 -05:00
RsTurtleGenericTunnelItem * gti = dynamic_cast < RsTurtleGenericTunnelItem * > ( item ) ;
if ( gti ! = NULL )
routeGenericTunnelItem ( gti ) ; /// Generic packets, that travel through established tunnels.
else /// These packets should be destroyed by the client.
2010-01-02 16:30:19 -05:00
{
2012-11-25 09:26:32 -05:00
/// 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
2012-11-25 09:26:32 -05:00
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult ( dynamic_cast < RsTurtleSearchResultItem * > ( item ) ) ;
break ;
2009-05-26 17:42:45 -04:00
2012-11-25 09:26:32 -05:00
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest ( dynamic_cast < RsTurtleOpenTunnelItem * > ( item ) ) ;
break ;
2009-05-26 17:42:45 -04:00
2012-11-25 09:26:32 -05:00
case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult ( dynamic_cast < RsTurtleTunnelOkItem * > ( item ) ) ;
break ;
2013-04-06 09:58:27 -04:00
2012-11-25 09:26:32 -05:00
default :
std : : cerr < < " p3turtle::handleIncoming: Unknown packet subtype " < < item - > PacketSubType ( ) < < std : : endl ;
}
delete item ;
2010-01-02 16:30:19 -05:00
}
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-08-25 08:04:43 -04:00
2013-04-01 17:18:58 -04:00
std : : list < TurtleFileInfo > result ;
item - > performLocalSearch ( result ) ;
2009-03-22 10:08:02 -04:00
2013-04-01 17:18:58 -04:00
RsTurtleSearchResultItem * res_item = NULL ;
uint32_t item_size = 0 ;
2009-04-06 17:06:44 -04:00
# ifdef P3TURTLE_DEBUG
2013-04-01 17:18:58 -04:00
if ( ! result . empty ( ) )
std : : cerr < < " " < < result . size ( ) < < " matches found. Sending back to origin ( " < < item - > PeerId ( ) < < " ). " < < std : : endl ;
2009-04-06 17:06:44 -04:00
# endif
2013-04-01 17:18:58 -04:00
while ( ! result . empty ( ) )
{
// 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 ;
2009-04-06 17:06:44 -04:00
2013-04-01 17:18:58 -04:00
if ( res_item = = NULL )
{
res_item = new RsTurtleSearchResultItem ;
item_size = 0 ;
2009-04-06 17:06:44 -04:00
2013-04-01 17:18:58 -04:00
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 ( ) ) ;
2009-04-06 17:06:44 -04:00
2013-04-01 17:18:58 -04:00
item_size + = 8 /* size */ + result . front ( ) . hash . size ( ) + result . front ( ) . name . size ( ) ;
result . pop_front ( ) ;
2009-04-06 17:06:44 -04:00
2013-04-01 17:18:58 -04:00
if ( item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE | | result . empty ( ) )
{
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
2013-04-01 17:18:58 -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
2013-04-01 17:18:58 -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-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.
//
2013-06-08 16:48:02 -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
{
2012-12-01 14:22:22 -05:00
if ( ! ( RS_SERVICE_PERM_TURTLE & rsPeers - > servicePermissionFlags_sslid ( * it ) ) )
continue ;
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
{
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
2013-04-06 05:21:01 -04:00
if ( item - > PeerId ( ) = = tunnel . local_dst )
item - > setTravelingDirection ( RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
else if ( item - > PeerId ( ) = = tunnel . local_src )
item - > setTravelingDirection ( RsTurtleGenericTunnelItem : : DIRECTION_SERVER ) ;
else
2013-06-17 16:38:20 -04:00
{
2013-06-20 15:12:33 -04:00
std : : cerr < < " (EE) p3turtle::routeGenericTunnelItem(): item mismatches tunnel src/dst ids. " < < std : : endl ;
2013-06-17 16:38:20 -04:00
std : : cerr < < " (EE) tunnel.local_src = " < < tunnel . local_src < < std : : endl ;
std : : cerr < < " (EE) tunnel.local_dst = " < < tunnel . local_dst < < std : : endl ;
std : : cerr < < " (EE) item->PeerId() = " < < item - > PeerId ( ) < < std : : endl ;
2013-06-20 15:12:33 -04:00
std : : cerr < < " (EE) This item is probably lost while tunnel route got redefined. Deleting this item. " < < std : : endl ;
2013-06-17 16:38:20 -04:00
delete item ;
return ;
}
2013-04-06 05:21:01 -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
2013-04-06 05:21:01 -04:00
if ( item - > PeerId ( ) = = tunnel . local_dst & & tunnel . local_src ! = mLinkMgr - > getOwnId ( ) ) //direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT &&
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 ( ) ;
2013-04-06 05:21:01 -04:00
// This has been disabled for compilation reasons. Not sure we actually need it.
//
//if(dynamic_cast<RsTurtleFileDataItem*>(item) != NULL)
// item->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA) ;
2011-09-04 16:01:30 -04:00
2010-01-02 16:30:19 -05:00
sendItem ( item ) ;
return ;
2009-05-26 17:42:45 -04:00
}
2013-04-06 05:21:01 -04:00
if ( item - > PeerId ( ) = = tunnel . local_src & & tunnel . local_dst ! = mLinkMgr - > getOwnId ( ) ) //direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER &&
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
2013-04-06 05:21:01 -04:00
handleRecvGenericTunnelItem ( item ) ;
2010-01-02 16:30:19 -05:00
delete item ;
2009-05-26 17:42:45 -04:00
}
2013-04-06 05:21:01 -04:00
void p3turtle : : handleRecvGenericTunnelItem ( RsTurtleGenericTunnelItem * item )
2009-12-28 16:11:00 -05:00
{
# ifdef P3TURTLE_DEBUG
2013-04-06 05:21:01 -04:00
std : : cerr < < " p3Turtle: received Generic tunnel item: " < < std : : endl ;
2009-12-28 16:11:00 -05:00
item - > print ( std : : cerr , 1 ) ;
# endif
2013-04-06 05:21:01 -04:00
std : : string hash ;
std : : string vpid ;
RsTurtleClientService * service ;
2010-01-11 11:00:42 -05:00
2013-04-06 09:58:27 -04:00
if ( ! getTunnelServiceInfo ( item - > tunnelId ( ) , vpid , hash , service ) )
return ;
2010-01-11 11:00:42 -05:00
2013-04-06 09:58:27 -04:00
service - > receiveTurtleData ( item , hash , vpid , item - > travelingDirection ( ) ) ;
}
2010-01-11 11:00:42 -05:00
2013-04-10 04:52:52 -04:00
//void p3turtle::handleRecvGenericDataItem(RsTurtleGenericDataItem *item)
//{
//#ifdef P3TURTLE_DEBUG
// std::cerr << "p3Turtle: received Generic Data item:" << std::endl ;
// item->print(std::cerr,1) ;
//#endif
// std::string virtual_peer_id ;
// std::string hash ;
// RsTurtleClientService *service ;
//
// if(!getTunnelServiceInfo(item->tunnelId(),virtual_peer_id,hash,service))
// return ;
//
// service->receiveTurtleData(item->data_bytes,item->data_size,hash,virtual_peer_id,item->travelingDirection()) ;
//}
2013-04-06 09:58:27 -04:00
bool p3turtle : : getTunnelServiceInfo ( TurtleTunnelId tunnel_id , std : : string & vpid , std : : string & hash , RsTurtleClientService * & service )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( tunnel_id ) ) ;
2010-01-11 11:00:42 -05:00
2013-04-06 09:58:27 -04:00
if ( it2 = = _local_tunnels . end ( ) )
{
# ifdef P3TURTLE_DEBUG
2013-10-02 15:56:01 -04:00
std : : cerr < < " p3turtle: unknown tunnel id " < < ( void * ) tunnel_id < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2013-04-06 09:58:27 -04:00
return false ;
}
2010-07-21 19:14:10 -04:00
2013-04-06 09:58:27 -04:00
TurtleTunnel & tunnel ( it2 - > second ) ;
2012-03-15 15:55:43 -04:00
2013-04-06 09:58:27 -04:00
# 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 ;
2012-03-15 15:55:43 -04:00
2013-04-20 14:56:06 -04:00
// Now sort out the case of client vs. server side items.
//
std : : string ownid = mLinkMgr - > getOwnId ( ) ;
2013-04-06 09:58:27 -04:00
2013-04-20 14:56:06 -04:00
if ( tunnel . local_src = = ownid )
2013-04-06 09:58:27 -04:00
{
2013-04-20 14:56:06 -04:00
std : : map < TurtleFileHash , TurtleHashInfo > : : const_iterator it = _incoming_file_hashes . find ( hash ) ;
if ( it = = _incoming_file_hashes . end ( ) )
{
2013-06-08 16:48:02 -04:00
std : : cerr < < " p3turtle::handleRecvGenericTunnelItem(): hash " < < hash < < " for tunnel " < < std : : hex < < it2 - > first < < std : : dec < < " has no attached service! Dropping the item. This is a serious consistency error. " < < std : : endl ;
2013-04-20 14:56:06 -04:00
return false ;
}
service = it - > second . service ;
2012-03-15 15:55:43 -04:00
}
2013-04-20 14:56:06 -04:00
else if ( tunnel . local_dst = = ownid )
{
std : : map < TurtleFileHash , RsTurtleClientService * > : : const_iterator it = _outgoing_file_hashes . find ( hash ) ;
if ( it = = _outgoing_file_hashes . end ( ) )
{
2013-06-08 16:48:02 -04:00
std : : cerr < < " p3turtle::handleRecvGenericTunnelItem(): hash " < < hash < < " for tunnel " < < std : : hex < < it2 - > first < < std : : dec < < " has no attached service! Dropping the item. This is a serious consistency error. " < < std : : endl ;
2013-04-20 14:56:06 -04:00
return false ;
}
2012-03-15 15:55:43 -04:00
2013-04-20 14:56:06 -04:00
service = it - > second ;
}
else
{
2013-06-08 16:48:02 -04:00
std : : cerr < < " p3turtle::handleRecvGenericTunnelItem(): hash " < < hash < < " for tunnel " < < std : : hex < < it2 - > first < < std : : dec < < " . Tunnel is not a end-point or a starting tunnel!! This is a serious consistency error. " < < std : : endl ;
2013-04-20 14:56:06 -04:00
return false ;
}
2013-04-18 17:41:13 -04:00
return true ;
2012-03-15 15:55:43 -04:00
}
2009-05-26 17:42:45 -04:00
// Send a data request into the correct tunnel for the given file hash
2013-04-06 05:21:01 -04:00
//
void p3turtle : : sendTurtleData ( const std : : string & virtual_peer_id , RsTurtleGenericTunnelItem * item )
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.
2013-04-06 05:21:01 -04:00
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( virtual_peer_id ) ) ;
2009-05-26 17:42:45 -04:00
if ( it = = _virtual_peers . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2013-04-06 09:16:54 -04:00
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < virtual_peer_id < < " in VP list. " < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2013-04-06 09:16:54 -04:00
delete item ;
2009-05-26 17:42:45 -04:00
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
2013-04-06 09:16:54 -04:00
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
std : : cerr < < " p3turtle::client asked to send a packet through tunnel that has previously been deleted. Not a big issue unless it happens in masses. " < < std : : endl ;
delete item ;
return ;
}
TurtleTunnel & tunnel ( it2 - > second ) ;
2009-05-26 17:42:45 -04:00
item - > tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever.
2010-01-11 11:00:42 -05:00
2011-07-09 14:39:34 -04:00
std : : string ownid = mLinkMgr - > getOwnId ( ) ;
2010-01-11 11:00:42 -05:00
2013-04-06 09:16:54 -04:00
if ( item - > shouldStampTunnel ( ) )
tunnel . time_stamp = time ( NULL ) ;
2010-01-11 11:00:42 -05:00
if ( tunnel . local_src = = ownid )
{
2013-04-06 05:21:01 -04:00
item - > setTravelingDirection ( RsTurtleGenericTunnelItem : : DIRECTION_SERVER ) ;
2010-01-11 11:00:42 -05:00
item - > PeerId ( tunnel . local_dst ) ;
2013-04-06 05:21:01 -04:00
_traffic_info_buffer . data_dn_Bps + = item - > serial_size ( ) ;
2010-01-11 11:00:42 -05:00
}
else if ( tunnel . local_dst = = ownid )
{
2013-04-06 05:21:01 -04:00
item - > setTravelingDirection ( RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
2010-01-11 11:00:42 -05:00
item - > PeerId ( tunnel . local_src ) ;
2013-04-06 05:21:01 -04:00
_traffic_info_buffer . data_up_Bps + = item - > serial_size ( ) ;
2010-01-11 11:00:42 -05:00
}
else
{
2013-04-06 05:21:01 -04:00
std : : cerr < < " p3Turtle::sendTurtleData(): asked to send a packet into a tunnel that is not registered. Dropping packet. " < < std : : endl ;
delete item ;
2010-01-11 11:00:42 -05:00
return ;
}
2010-07-21 19:14:10 -04:00
# ifdef P3TURTLE_DEBUG
2013-04-06 05:21:01 -04:00
std : : cerr < < " p3turtle: sending service packet to virtual peer id " < < virtual_peer_id < < " , hash=0x " < < tunnel . hash < < " , tunnel = " < < ( void * ) item - > tunnel_id < < " , next peer= " < < tunnel . local_dst < < std : : endl ;
2010-07-21 19:14:10 -04:00
# 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
2012-09-23 15:58:08 -04:00
# ifdef SUSPENDED
2011-04-07 16:16:43 -04:00
// 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.
//
2012-09-23 15:58:08 -04:00
2011-04-07 16:16:43 -04:00
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 ;
2012-09-23 15:58:08 -04:00
// also update local_tunnels is this is an ending tunnel.
//
std : : map < std : : string , FileInfo > : : const_iterator it = _outgoing_file_hashes . find ( item - > file_hash ) ;
if ( it ! = _outgoing_file_hashes . end ( ) )
for ( std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . begin ( ) ) ; it2 ! = _local_tunnels . end ( ) ; + + it2 )
if ( it2 - > second . hash = = item - > file_hash )
it2 - > second . local_src = item - > PeerId ( ) ;
2011-04-07 16:16:43 -04:00
}
2012-09-23 15:58:08 -04:00
# endif
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 ;
2013-04-01 17:18:58 -04:00
std : : string info ;
2013-04-20 14:56:06 -04:00
RsTurtleClientService * service = NULL ;
2010-01-02 16:30:19 -05:00
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
2013-04-20 14:56:06 -04:00
found = performLocalHashSearch ( item - > file_hash , item - > PeerId ( ) , service ) ;
2010-01-02 16:30:19 -05:00
}
{
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
2013-10-02 15:56:01 -04:00
TurtleTunnelId t_id = res_item - > tunnel_id ;
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
2013-10-02 15:56:01 -04:00
_local_tunnels [ t_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.
//
2013-10-02 15:56:01 -04:00
locked_addDistantPeer ( item - > file_hash , t_id ) ;
2009-05-26 17:42:45 -04:00
2013-04-01 17:18:58 -04:00
// Store some info string about the tunnel.
2010-01-02 16:30:19 -05:00
//
2013-04-20 14:56:06 -04:00
_outgoing_file_hashes [ item - > file_hash ] = service ;
// Notify the client service that there's a new virtual peer id available as a client.
//
2013-10-02 15:56:01 -04:00
service - > addVirtualPeer ( item - > file_hash , _local_tunnels [ t_id ] . vpid , RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
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.
2013-04-20 14:56:06 -04:00
//
2010-01-02 16:30:19 -05:00
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
2012-12-01 14:22:22 -05:00
for ( std : : list < std : : string > : : iterator it ( onlineIds . begin ( ) ) ; it ! = onlineIds . end ( ) ; )
if ( ! ( RS_SERVICE_PERM_TURTLE & rsPeers - > servicePermissionFlags_sslid ( * it ) ) )
{
std : : list < std : : string > : : iterator tmp = it + + ;
onlineIds . erase ( tmp ) ;
}
else
+ + it ;
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 )
2013-03-11 17:32:32 -04:00
{
2012-04-19 16:23:58 -04:00
forward_probability = 1.0f / nb_online_ids ;
2013-03-11 17:32:32 -04:00
// Setting forward_probability to 1/nb_online_ids forces at most one TR up per TR dn. But if we are overflooded by
// TR dn, we still need to control them to avoid flooding the pqiHandler outqueue. So we additionally moderate the
// forward probability so as to reduct the output rate accordingly.
//
if ( _traffic_info . tr_dn_Bps / ( float ) TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate )
forward_probability * = _max_tr_up_rate * TUNNEL_REQUEST_PACKET_SIZE / ( float ) _traffic_info . tr_dn_Bps ;
}
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 ;
2012-05-10 15:04:31 -04:00
std : : string new_vpid ;
2013-04-10 04:52:52 -04:00
RsTurtleClientService * service = NULL ;
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 ;
2013-04-01 17:18:58 -04:00
for ( std : : map < TurtleFileHash , TurtleHashInfo > : : iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2009-05-26 17:42:45 -04:00
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 ;
2013-04-10 04:52:52 -04:00
service = it - > second . service ;
2009-05-26 17:42:45 -04:00
2010-12-07 16:45:12 -05:00
locked_addDistantPeer ( new_hash , item - > tunnel_id ) ;
2012-05-10 15:04:31 -04:00
new_vpid = _local_tunnels [ item - > tunnel_id ] . vpid ; // save it for off-mutex usage.
2009-05-26 17:42:45 -04:00
}
if ( ! found )
2012-11-25 09:26:32 -05:00
std : : cerr < < " p3turtle: error. Could not find hash that emmitted tunnel request " < < reinterpret_cast < void * > ( item - > tunnel_id ) < < std : : endl ;
2009-05-26 17:42:45 -04:00
}
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.
//
2013-04-10 04:52:52 -04:00
if ( new_tunnel & & service ! = NULL )
2013-04-20 14:56:06 -04:00
service - > addVirtualPeer ( new_hash , new_vpid , RsTurtleGenericTunnelItem : : DIRECTION_SERVER ) ;
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!
2012-11-01 06:06:12 -04:00
rsFiles - > SearchKeywords ( words , initialResults , RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_NETWORK_WIDE , PeerId ( ) ) ;
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!
2012-11-01 06:06:12 -04:00
rsFiles - > SearchBoolExp ( exp , initialResults , RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_NETWORK_WIDE , PeerId ( ) ) ;
2009-08-25 08:04:43 -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-08-25 08:04:43 -04:00
{
2012-11-01 06:06:12 -04:00
// retain only file type
if ( it - > type = = DIR_TYPE_DIR )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Skipping directory " < < it - > name < < std : : endl ;
# endif
continue ;
}
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
2013-04-06 05:21:01 -04:00
void p3turtle : : monitorTunnels ( const std : : string & hash , RsTurtleClientService * client_service )
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 )
2013-04-01 17:18:58 -04:00
if ( _hashes_to_remove [ i ] = = hash )
2010-03-12 14:39:23 -05:00
{
_hashes_to_remove [ i ] = _hashes_to_remove . back ( ) ;
_hashes_to_remove . pop_back ( ) ;
# ifdef P3TURTLE_DEBUG
2013-04-01 17:18:58 -04:00
std : : cerr < < " p3turtle: File hash " < < hash < < " Was scheduled for removal. Canceling the removal. " < < std : : endl ;
2010-03-12 14:39:23 -05:00
# endif
}
// Then, check if the hash is already there
//
2013-04-01 17:18:58 -04:00
if ( _incoming_file_hashes . find ( hash ) ! = _incoming_file_hashes . end ( ) ) // download already asked.
2009-03-15 18:45:40 -04:00
{
# ifdef P3TURTLE_DEBUG
2013-04-01 17:18:58 -04:00
std : : cerr < < " p3turtle: File hash " < < 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
2013-04-01 17:18:58 -04:00
std : : cerr < < " p3turtle: Received order for turtle download fo hash " < < 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.
//
2013-04-01 17:18:58 -04:00
_incoming_file_hashes [ 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.
2013-04-01 17:18:58 -04:00
_incoming_file_hashes [ hash ] . last_digg_time = RSRandom : : random_u32 ( ) % 10 ;
2013-04-06 05:21:01 -04:00
_incoming_file_hashes [ hash ] . service = client_service ;
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.
//
2013-04-20 14:56:06 -04:00
bool p3turtle : : performLocalHashSearch ( const TurtleFileHash & hash , const std : : string & peer_id , RsTurtleClientService * & service )
2009-04-19 15:59:54 -04:00
{
2013-04-01 17:18:58 -04:00
if ( _registered_services . empty ( ) )
std : : cerr < < " Turtle router has no services registered. Tunnel requests cannot be handled. " < < std : : endl ;
2012-11-01 06:06:12 -04:00
2013-04-01 17:18:58 -04:00
for ( std : : list < RsTurtleClientService * > : : const_iterator it ( _registered_services . begin ( ) ) ; it ! = _registered_services . end ( ) ; + + it )
2013-04-20 14:56:06 -04:00
if ( ( * it ) - > handleTunnelRequest ( hash , peer_id ) )
{
service = * it ;
2013-04-01 17:18:58 -04:00
return true ;
2013-04-20 14:56:06 -04:00
}
2012-11-01 06:06:12 -04:00
2013-04-01 17:18:58 -04:00
return false ;
}
2012-11-01 06:06:12 -04:00
2012-11-04 09:52:38 -05:00
2013-04-01 17:18:58 -04:00
void p3turtle : : registerTunnelService ( RsTurtleClientService * service )
{
# ifdef P3TURTLE_DEBUG
for ( std : : list < RsTurtleClientService * > : : const_iterator it ( _registered_services . begin ( ) ) ; it ! = _registered_services . end ( ) ; + + it )
if ( service = = * it )
throw std : : runtime_error ( " p3turtle::registerTunnelService(): Cannot register the same service twice. Please fix the code! " ) ;
# endif
std : : cerr < < " p3turtle: registered new tunnel service " < < ( void * ) service < < std : : endl ;
_registered_services . push_back ( service ) ;
2013-04-06 05:21:01 -04:00
_serialiser - > registerClientService ( service ) ;
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 )
2013-03-11 17:32:32 -04:00
{
2012-04-19 16:23:58 -04:00
forward_probability = 1.0f / nb_online_ids ;
2013-03-11 17:32:32 -04:00
if ( _traffic_info . tr_dn_Bps / ( float ) TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate )
forward_probability * = _max_tr_up_rate * TUNNEL_REQUEST_PACKET_SIZE / ( float ) _traffic_info . tr_dn_Bps ;
}
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 ( ) ;
2013-04-01 17:18:58 -04:00
for ( std : : map < TurtleFileHash , TurtleHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2009-08-16 16:10:53 -04:00
{
hashes_info . push_back ( std : : vector < std : : string > ( ) ) ;
std : : vector < std : : string > & hashes ( hashes_info . back ( ) ) ;
hashes . push_back ( it - > first ) ;
2013-04-01 17:18:58 -04:00
//hashes.push_back(it->second.name) ;
hashes . push_back ( " Name not available " ) ;
2009-08-16 16:10:53 -04:00
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 ;
2013-04-01 17:18:58 -04:00
for ( std : : map < TurtleFileHash , TurtleHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2009-04-19 15:59:54 -04:00
{
2013-04-06 09:16:54 -04:00
std : : cerr < < " hash=0x " < < it - > first < < " , tunnel ids = " ;
2009-05-26 17:42:45 -04:00
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 ;
2012-09-06 07:46:03 -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 ;
2013-10-02 15:56:01 -04:00
for ( std : : map < TurtleFileHash , RsTurtleClientService * > : : const_iterator it ( _outgoing_file_hashes . begin ( ) ) ; it ! = _outgoing_file_hashes . end ( ) ; + + it )
2013-04-06 09:16:54 -04:00
std : : cerr < < " hash=0x " < < it - > first < < 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 ;
2013-04-10 04:52:52 -04:00
// 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