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
*
*/
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
# include "rsiface/rsiface.h"
# include "rsiface/rspeers.h"
2009-03-15 18:45:40 -04:00
# include "rsiface/rsfiles.h"
2009-02-28 13:19:00 -05:00
2010-01-13 15:56:55 -05:00
# include "pqi/authssl.h"
2009-02-28 13:19:00 -05:00
# include "pqi/p3connmgr.h"
2009-03-13 17:14:30 -04:00
# include "pqi/pqinotify.h"
2009-05-26 17:42:45 -04:00
# include "ft/ftserver.h"
# include "ft/ftdatamultiplex.h"
# include "ft/ftcontroller.h"
2009-04-13 16:26:13 -04:00
2009-03-12 16:08:02 -04:00
# include "p3turtle.h"
2009-02-28 13:19:00 -05:00
# include <iostream>
# include <errno.h>
# include <cmath>
# include <sstream>
2009-05-28 15:41:03 -04:00
# include <stdio.h>
2009-02-28 13:19:00 -05:00
# include "util/rsdebug.h"
# include "util/rsprint.h"
# include "pqi/pqinetwork.h"
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.
//
static const time_t TUNNEL_REQUESTS_LIFE_TIME = 120 ; /// life time for tunnel requests in the cache.
static const time_t SEARCH_REQUESTS_LIFE_TIME = 120 ; /// life time for search requests in the cache
static const time_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns.
2009-06-13 15:28:47 -04:00
static const time_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel.
2009-06-14 14:59:42 -04:00
static const time_t TUNNEL_MANAGEMENT_LAPS_TIME = 10 ; /// look into tunnels regularly every 10 sec.
2009-02-28 13:19:00 -05:00
2009-08-25 16:49:50 -04:00
p3turtle : : p3turtle ( p3ConnectMgr * cm , ftServer * fs )
2009-06-13 15:28:47 -04:00
: p3Service ( RS_SERVICE_TYPE_TURTLE ) , p3Config ( CONFIG_TYPE_TURTLE ) , mConnMgr ( cm )
2009-02-28 13:19:00 -05:00
{
2009-03-12 16:08:02 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-02-28 13:19:00 -05:00
2009-05-26 17:42:45 -04:00
_ft_server = fs ;
_ft_controller = fs - > getController ( ) ;
2009-03-23 10:45:51 -04:00
srand ( time ( NULL ) ) ;
2009-02-28 13:19:00 -05:00
addSerialType ( new RsTurtleSerialiser ( ) ) ;
2009-04-19 15:59:54 -04:00
_last_clean_time = 0 ;
_last_tunnel_management_time = 0 ;
2009-08-14 03:28:58 -04:00
_last_tunnel_campaign_time = 0 ;
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 ) ;
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
//
2009-06-14 14:59:42 -04:00
if ( now > TUNNEL_MANAGEMENT_LAPS_TIME + _last_tunnel_management_time | | _force_digg_new_tunnels )
2009-04-19 15:59:54 -04:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Calling tunnel management. " < < std : : endl ;
# endif
manageTunnels ( ) ;
2009-06-03 14:47:14 -04:00
2009-04-19 15:59:54 -04:00
_last_tunnel_management_time = now ;
}
// Clean every 10 sec.
//
2009-03-12 16:08:02 -04:00
if ( now > 10 + _last_clean_time )
{
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.
2009-03-12 16:08:02 -04:00
_last_clean_time = now ;
}
2009-03-12 17:07:00 -04:00
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
// -----------------------------------------------------------------------------------//
//
// This method handles peer connexion/deconnexion
// If A connects, new tunnels should be initiated from A
// If A disconnects, the tunnels passed through A should be closed.
//
2009-08-25 16:49:50 -04:00
void p3turtle : : statusChange ( const std : : list < pqipeer > & plist ) // derived from pqiMonitor
2009-04-19 15:59:54 -04:00
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-06-03 14:47:14 -04:00
// We actually do not shut down tunnels when peers get down: Tunnels that
// are not working properly get automatically removed after some time.
2009-05-26 17:42:45 -04:00
// save the list of active peers. This is useful for notifying the ftContoller
_online_peers = plist ;
std : : cerr < < " p3turtle: status change triggered. Saving list of " < < plist . size ( ) < < " peers. " < < std : : endl ;
2009-06-03 14:47:14 -04:00
/* if any have switched to 'connected' then we force digging new tunnels */
for ( std : : list < pqipeer > : : const_iterator pit = plist . begin ( ) ; pit ! = plist . end ( ) ; pit + + )
if ( ( pit - > state & RS_PEER_S_FRIEND ) & & ( pit - > actions & RS_PEER_CONNECTED ) )
_force_digg_new_tunnels = true ;
2009-04-19 15:59:54 -04:00
}
2009-05-26 17:42:45 -04:00
// adds a virtual peer to the list that is communicated ot ftController.
//
2009-08-25 16:49:50 -04:00
void p3turtle : : 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
{
_virtual_peers [ TurtleVirtualPeerId ( buff ) ] = tid ;
# ifdef P3TURTLE_DEBUG
assert ( _local_tunnels . find ( tid ) ! = _local_tunnels . end ( ) ) ;
# endif
_local_tunnels [ tid ] . vpid = TurtleVirtualPeerId ( buff ) ;
}
}
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.
//
void p3turtle : : manageTunnels ( )
{
2009-06-14 14:59:42 -04:00
// Collect hashes for which tunnel digging is necessary / recommended
2009-04-19 15:59:54 -04:00
2009-06-03 14:47:14 -04:00
std : : vector < TurtleFileHash > hashes_to_digg ;
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-06-14 14:59:42 -04:00
time_t now = time ( NULL ) ;
bool tunnel_campain = false ;
2009-12-28 16:11:00 -05:00
if ( now > _last_tunnel_campaign_time + REGULAR_TUNNEL_DIGGING_TIME )
2009-06-03 14:47:14 -04:00
{
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-14 14:59:42 -04:00
std : : cerr < < " Tunnel management: flaging all hashes for tunnels digging. " < < std : : endl ;
2009-04-19 15:59:54 -04:00
# endif
2009-06-14 14:59:42 -04:00
tunnel_campain = true ;
_last_tunnel_campaign_time = now ;
2009-06-03 14:47:14 -04:00
}
2009-06-14 14:59:42 -04:00
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
if ( it - > second . tunnels . empty ( ) // digg new tunnels is no tunnels are available
| | _force_digg_new_tunnels // digg new tunnels when forced to (e.g. a new peer has connected)
| | tunnel_campain ) // force digg new tunnels at regular (large) interval
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Tunnel management: digging new tunnels for hash " < < it - > first < < " . " < < std : : endl ;
# endif
hashes_to_digg . push_back ( it - > first ) ;
}
_force_digg_new_tunnels = false ;
2009-05-26 17:42:45 -04:00
}
2009-06-04 15:30:19 -04:00
for ( unsigned int i = 0 ; i < hashes_to_digg . size ( ) ; + + i )
2009-05-26 17:42:45 -04:00
diggTunnel ( hashes_to_digg [ i ] ) ;
2009-04-19 15:59:54 -04:00
}
2009-03-12 17:07:00 -04:00
void p3turtle : : autoWash ( )
2009-03-12 16:08:02 -04:00
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-04-19 15:59:54 -04:00
std : : cerr < < " In autowash. " < < std : : endl ;
# endif
2009-06-14 14:59:42 -04:00
// Remove hashes that are marked as such.
//
2010-03-12 14:39:23 -05:00
std : : vector < std : : pair < TurtleFileHash , TurtleVirtualPeerId > > peers_to_remove ;
2009-06-14 14:59:42 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
for ( unsigned int i = 0 ; i < _hashes_to_remove . size ( ) ; + + i )
{
std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . find ( _hashes_to_remove [ i ] ) ) ;
2009-08-25 16:49:50 -04:00
if ( it = = _incoming_file_hashes . end ( ) )
2009-06-14 14:59:42 -04:00
{
2010-03-07 09:42:13 -05:00
# ifdef P3TURTLE_DEBUG
2009-06-14 14:59:42 -04:00
std : : cerr < < " p3turtle: asked to stop monitoring file hash " < < _hashes_to_remove [ i ] < < " , but this hash is actually not handled by the turtle router. " < < std : : endl ;
2010-03-07 09:42:13 -05:00
# endif
2009-06-14 14:59:42 -04:00
continue ;
}
// copy the list of tunnels to remove.
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: stopping monitoring for file hash " < < _hashes_to_remove [ i ] < < " , and closing " < < it - > second . tunnels . size ( ) < < " tunnels ( " ;
# endif
std : : vector < TurtleTunnelId > tunnels_to_remove ;
2009-08-25 16:49:50 -04:00
for ( std : : vector < TurtleTunnelId > : : const_iterator it2 ( it - > second . tunnels . begin ( ) ) ; it2 ! = it - > second . tunnels . end ( ) ; + + it2 )
2009-06-14 14:59:42 -04:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < ( void * ) * it2 < < " , " ;
# endif
tunnels_to_remove . push_back ( * it2 ) ;
}
# ifdef P3TURTLE_DEBUG
std : : cerr < < " ) " < < std : : endl ;
# endif
for ( unsigned int k = 0 ; k < tunnels_to_remove . size ( ) ; + + k )
2010-03-12 14:39:23 -05:00
locked_closeTunnel ( tunnels_to_remove [ k ] , peers_to_remove ) ;
2009-06-14 14:59:42 -04:00
_incoming_file_hashes . erase ( it ) ;
}
if ( ! _hashes_to_remove . empty ( ) )
{
IndicateConfigChanged ( ) ; // initiates saving of handled hashes.
_hashes_to_remove . clear ( ) ;
}
}
2009-04-19 15:59:54 -04:00
// look for tunnels and stored temporary info that have not been used for a while.
time_t now = time ( NULL ) ;
2009-06-03 14:47:14 -04:00
// Search requests
//
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-02-09 16:53:49 -05:00
for ( std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : iterator it ( _search_requests_origins . begin ( ) ) ; it ! = _search_requests_origins . end ( ) ; )
2009-06-03 14:47:14 -04:00
if ( now > ( time_t ) ( it - > second . time_stamp + SEARCH_REQUESTS_LIFE_TIME ) )
{
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-03 14:47:14 -04:00
std : : cerr < < " removed search request " < < ( void * ) it - > first < < " , timeout. " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2010-02-09 16:53:49 -05:00
std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : iterator tmp ( it ) ;
+ + tmp ;
2009-06-03 14:47:14 -04:00
_search_requests_origins . erase ( it ) ;
2010-02-09 16:53:49 -05:00
it = tmp ;
2009-06-03 14:47:14 -04:00
}
2010-02-09 16:53:49 -05:00
else
+ + it ;
2009-06-03 14:47:14 -04:00
}
2009-04-13 16:26:13 -04:00
2009-06-03 14:47:14 -04:00
// Tunnel requests
//
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-02-09 16:53:49 -05:00
for ( std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : iterator it ( _tunnel_requests_origins . begin ( ) ) ; it ! = _tunnel_requests_origins . end ( ) ; )
2009-06-03 14:47:14 -04:00
if ( now > ( time_t ) ( it - > second . time_stamp + TUNNEL_REQUESTS_LIFE_TIME ) )
{
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-03 14:47:14 -04:00
std : : cerr < < " removed tunnel request " < < ( void * ) it - > first < < " , timeout. " < < std : : endl ;
2009-04-19 15:59:54 -04:00
# endif
2010-02-09 16:53:49 -05:00
std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : iterator tmp ( it ) ;
+ + tmp ;
2009-06-03 14:47:14 -04:00
_tunnel_requests_origins . erase ( it ) ;
2010-02-09 16:53:49 -05:00
it = tmp ;
2009-06-03 14:47:14 -04:00
}
2010-02-09 16:53:49 -05:00
else
+ + it ;
2009-06-03 14:47:14 -04:00
}
// Tunnels.
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-06-14 14:59:42 -04:00
std : : vector < TurtleTunnelId > tunnels_to_close ;
2009-06-03 14:47:14 -04:00
for ( std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it ( _local_tunnels . begin ( ) ) ; it ! = _local_tunnels . end ( ) ; + + it )
if ( now > ( time_t ) ( it - > second . time_stamp + MAXIMUM_TUNNEL_IDLE_TIME ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " removing tunnel " < < ( void * ) it - > first < < " : timeout. " < < std : : endl ;
# endif
tunnels_to_close . push_back ( it - > first ) ;
}
2009-06-14 14:59:42 -04:00
for ( unsigned int i = 0 ; i < tunnels_to_close . size ( ) ; + + i )
2010-03-12 14:39:23 -05:00
locked_closeTunnel ( tunnels_to_close [ i ] , peers_to_remove ) ;
2009-06-03 14:47:14 -04:00
}
// File hashes can only be removed by calling the 'stopMonitoringFileTunnels()' command.
2010-03-12 14:39:23 -05:00
// All calls to _ft_controller are done off-mutex, to avoir cross-lock
for ( uint32_t i = 0 ; i < peers_to_remove . size ( ) ; + + i )
_ft_controller - > removeFileSource ( peers_to_remove [ i ] . first , peers_to_remove [ i ] . second ) ;
2009-03-12 16:08:02 -04:00
}
2010-03-12 14:39:23 -05:00
void p3turtle : : locked_closeTunnel ( TurtleTunnelId tid , std : : vector < std : : pair < TurtleFileHash , TurtleVirtualPeerId > > & sources_to_remove )
2009-06-03 14:47:14 -04:00
{
// This is closing a given tunnel, removing it from file sources, and from the list of tunnels of its
2009-08-25 16:49:50 -04:00
// corresponding file hash. In the original turtle4privacy paradigm, they also send back and forward
2009-06-03 14:47:14 -04:00
// tunnel closing commands. I'm not sure this is necessary, because if a tunnel is closed somewhere, it's
// source is not going to be used and the tunnel will eventually disappear.
//
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it ( _local_tunnels . find ( tid ) ) ;
if ( it = = _local_tunnels . end ( ) )
{
2009-06-14 14:59:42 -04:00
std : : cerr < < " p3turtle: was asked to close tunnel " < < ( void * ) tid < < " , which actually doesn't exist. " < < std : : endl ;
2009-06-03 14:47:14 -04:00
return ;
}
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2009-06-15 16:34:34 -04:00
std : : cerr < < " p3turtle: Closing tunnel " < < ( void * ) tid < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-06-03 14:47:14 -04:00
2009-08-25 16:49:50 -04:00
if ( it - > second . local_src = = mConnMgr - > getOwnId ( ) ) // this is a starting tunnel. We thus remove
2009-06-03 14:47:14 -04:00
// - the virtual peer from the vpid list
// - the tunnel id from the file hash
// - the virtual peer from the file sources in the file transfer controller.
{
TurtleTunnelId tid = it - > first ;
TurtleVirtualPeerId vpid = it - > second . vpid ;
TurtleFileHash hash = it - > second . hash ;
# ifdef P3TURTLE_DEBUG
2009-06-14 14:59:42 -04:00
std : : cerr < < " Tunnel is a starting point. Also removing: " < < std : : endl ;
2009-06-03 14:47:14 -04:00
std : : cerr < < " Virtual Peer Id " < < vpid < < std : : endl ;
std : : cerr < < " Associated file source. " < < std : : endl ;
# endif
2010-03-12 14:39:23 -05:00
sources_to_remove . push_back ( std : : pair < TurtleFileHash , TurtleVirtualPeerId > ( hash , vpid ) ) ;
2009-06-03 14:47:14 -04:00
2010-02-05 17:45:52 -05:00
// Let's be cautious. Normally we should never be here without consistent information,
// but still, this happens, rarely.
2009-06-15 16:34:34 -04:00
//
2010-02-05 17:45:52 -05:00
if ( _virtual_peers . find ( vpid ) ! = _virtual_peers . end ( ) )
_virtual_peers . erase ( _virtual_peers . find ( vpid ) ) ;
std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . find ( hash ) ) ;
if ( it ! = _incoming_file_hashes . end ( ) )
{
std : : vector < TurtleTunnelId > & tunnels ( it - > second . tunnels ) ;
// Remove tunnel id from it's corresponding hash. For security we
// go through the whole tab, although the tunnel id should only be listed once
// in this tab.
//
for ( unsigned int i = 0 ; i < tunnels . size ( ) ; )
if ( tunnels [ i ] = = tid )
{
tunnels [ i ] = tunnels . back ( ) ;
tunnels . pop_back ( ) ;
}
else
+ + i ;
}
2009-06-03 14:47:14 -04:00
}
else if ( it - > second . local_dst = = mConnMgr - > getOwnId ( ) ) // This is a ending tunnel. We also remove the virtual peer id
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Tunnel is a ending point. Also removing associated outgoing hash. " ;
# endif
2010-02-05 17:45:52 -05:00
if ( _outgoing_file_hashes . find ( it - > second . hash ) ! = _outgoing_file_hashes . end ( ) )
_outgoing_file_hashes . erase ( _outgoing_file_hashes . find ( it - > second . hash ) ) ;
2009-06-03 14:47:14 -04:00
}
_local_tunnels . erase ( it ) ;
}
void p3turtle : : stopMonitoringFileTunnels ( const std : : string & hash )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
# ifdef P3TURTLE_DEBUG
2009-06-14 14:59:42 -04:00
std : : cerr < < " p3turtle: Marking hash " < < hash < < " to be removed during autowash. " < < std : : endl ;
2009-06-03 14:47:14 -04:00
# endif
2009-06-14 14:59:42 -04:00
// We don't do the deletion in this process, because it can cause a race with tunnel management.
_hashes_to_remove . push_back ( hash ) ;
2009-06-03 14:47:14 -04:00
}
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Config functions ------------------------------ //
2009-06-03 14:47:14 -04:00
// -----------------------------------------------------------------------------------//
//
RsSerialiser * p3turtle : : setupSerialiser ( )
{
2009-06-13 15:28:47 -04:00
RsSerialiser * rss = new RsSerialiser ;
rss - > addSerialType ( new RsTurtleSerialiser ) ;
2009-06-03 14:47:14 -04:00
return rss ;
}
2009-08-25 16:49:50 -04:00
std : : list < RsItem * > p3turtle : : saveList ( bool & cleanup )
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
std : : list < RsItem * > lst ;
2010-01-26 15:40:21 -05:00
# ifdef TO_REMOVE
2009-06-13 15:28:47 -04:00
RsTurtleSearchResultItem * item = new RsTurtleSearchResultItem ;
item - > PeerId ( " " ) ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
{
TurtleFileInfo finfo ;
finfo . name = it - > second . name ;
finfo . size = it - > second . size ;
finfo . hash = it - > first ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Saving item " < < finfo . name < < " , " < < finfo . hash < < " , " < < finfo . size < < std : : endl ;
# endif
item - > result . push_back ( finfo ) ;
}
lst . push_back ( item ) ;
2010-01-26 15:40:21 -05:00
# endif
2009-06-13 15:28:47 -04:00
return lst ;
2009-06-03 14:47:14 -04:00
}
2010-01-26 15:40:21 -05:00
2009-08-25 16:49:50 -04:00
bool p3turtle : : loadList ( std : : list < RsItem * > load )
2009-06-03 14:47:14 -04:00
{
2010-01-26 15:40:21 -05:00
# ifdef TO_REMOVE
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 )
{
RsTurtleSearchResultItem * item = dynamic_cast < RsTurtleSearchResultItem * > ( * it ) ;
# ifdef P3TURTLE_DEBUG
assert ( item ! = NULL ) ;
# endif
if ( item = = NULL )
continue ;
for ( std : : list < TurtleFileInfo > : : const_iterator it2 ( item - > result . begin ( ) ) ; it2 ! = item - > result . end ( ) ; + + it2 )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Restarting tunneling for: " < < it2 - > hash < < " " < < it2 - > size < < " " < < it2 - > name < < std : : endl ;
# endif
monitorFileTunnels ( it2 - > name , it2 - > hash , it2 - > size ) ;
}
delete item ;
}
2010-01-26 15:40:21 -05:00
# endif
2009-06-03 14:47:14 -04:00
return true ;
}
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
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-09-11 10:32:06 -04:00
static uint64_t s = time ( NULL ) ;
s = s * 1664525 + 1013904223 ; // pseudo random number generator from Wikipedia/Numerical Recipies.
return ( uint32_t ) ( s & 0x00000000ffffffff ) ;
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.
// The only important thing is that the saem hash 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
2009-04-13 16:26:13 -04:00
std : : string buff ( hash + mConnMgr - > getOwnId ( ) ) ;
uint32_t res = 0 ;
uint32_t decal = 0 ;
2009-04-16 16:30:59 -04:00
for ( int i = 0 ; i < ( int ) buff . length ( ) ; + + i )
2009-03-15 18:45:40 -04:00
{
2009-04-13 16:26:13 -04:00
res + = 7 * buff [ i ] + decal ;
2009-06-13 15:28:47 -04:00
if ( b )
decal = decal * 44497 + 15641 + ( res % 86243 ) ;
else
decal = decal * 86243 + 15649 + ( res % 44497 ) ;
2009-03-15 18:45:40 -04:00
}
2009-04-13 16:26:13 -04:00
return res ;
2009-02-28 13:19:00 -05:00
}
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Global routing. -------------------------------- //
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-02-28 13:19:00 -05:00
int p3turtle : : handleIncoming ( )
{
int nhandled = 0 ;
// While messages read
//
RsItem * item = NULL ;
while ( NULL ! = ( item = recvItem ( ) ) )
{
nhandled + + ;
2010-01-02 16:30:19 -05:00
RsTurtleGenericTunnelItem * gti = dynamic_cast < RsTurtleGenericTunnelItem * > ( item ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
if ( gti ! = NULL )
routeGenericTunnelItem ( gti ) ; /// Generic packets, that travel through established tunnels.
else /// These packets should be destroyed by the client.
{
/// Special packets that require specific treatment, because tunnels do not exist for these packets.
/// These packets are destroyed here, after treatment.
//
switch ( item - > PacketSubType ( ) )
{
case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST :
case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST : handleSearchRequest ( dynamic_cast < RsTurtleSearchRequestItem * > ( item ) ) ;
break ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult ( dynamic_cast < RsTurtleSearchResultItem * > ( item ) ) ;
break ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest ( dynamic_cast < RsTurtleOpenTunnelItem * > ( item ) ) ;
break ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult ( dynamic_cast < RsTurtleTunnelOkItem * > ( item ) ) ;
break ;
default :
std : : cerr < < " p3turtle::handleIncoming: Unknown packet subtype " < < item - > PacketSubType ( ) < < std : : endl ;
}
delete item ;
2009-02-28 13:19:00 -05:00
}
}
return nhandled ;
}
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// -------------------------------- Search handling. ------------------------------- //
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-03-12 16:08:02 -04:00
void p3turtle : : handleSearchRequest ( RsTurtleSearchRequestItem * item )
2009-02-28 13:19:00 -05:00
{
2009-03-13 17:14:30 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-08-25 16:49:50 -04:00
// take a look at the item:
// - If the item destimation is
2009-02-28 13:19:00 -05:00
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
2009-03-15 18:45:40 -04:00
std : : cerr < < " Received search request from peer " < < item - > PeerId ( ) < < " : " < < std : : endl ;
2009-03-12 17:07:00 -04:00
item - > print ( std : : cerr , 0 ) ;
2009-03-12 16:08:02 -04:00
# endif
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 ) ;
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
2009-03-12 17:07:00 -04:00
if ( item - > PeerId ( ) ! = mConnMgr - > getOwnId ( ) )
2009-02-28 13:19:00 -05:00
{
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Request not from us. Performing local search " < < std : : endl ;
# endif
2009-03-22 10:08:02 -04:00
if ( _sharing_strategy ! = SHARE_FRIENDS_ONLY | | item - > depth < 2 )
2009-03-12 16:08:02 -04:00
{
2009-03-22 10:08:02 -04:00
std : : list < TurtleFileInfo > result ;
2009-08-25 08:04:43 -04:00
item - > performLocalSearch ( result ) ;
2009-03-22 10:08:02 -04:00
2009-04-06 17:06:44 -04:00
RsTurtleSearchResultItem * res_item = NULL ;
uint32_t item_size = 0 ;
# ifdef P3TURTLE_DEBUG
2009-03-22 10:08:02 -04:00
if ( ! result . empty ( ) )
2009-04-06 17:06:44 -04:00
std : : cerr < < " " < < result . size ( ) < < " matches found. Sending back to origin ( " < < item - > PeerId ( ) < < " ). " < < std : : endl ;
# endif
while ( ! result . empty ( ) )
2009-03-22 10:08:02 -04:00
{
2009-04-06 17:06:44 -04:00
// Let's chop search results items into several chunks of finite size to avoid exceeding streamer's capacity.
//
static const uint32_t RSTURTLE_MAX_SEARCH_RESPONSE_SIZE = 10000 ;
if ( res_item = = NULL )
{
res_item = new RsTurtleSearchResultItem ;
item_size = 0 ;
res_item - > depth = 0 ;
res_item - > request_id = item - > request_id ;
res_item - > PeerId ( item - > PeerId ( ) ) ; // send back to the same guy
}
res_item - > result . push_back ( result . front ( ) ) ;
item_size + = 8 /* size */ + result . front ( ) . hash . size ( ) + result . front ( ) . name . size ( ) ;
result . pop_front ( ) ;
if ( item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE | | result . empty ( ) )
{
2009-03-12 16:08:02 -04:00
# ifdef P3TURTLE_DEBUG
2009-04-06 17:06:44 -04:00
std : : cerr < < " Sending back chunk of size " < < item_size < < " , for " < < res_item - > result . size ( ) < < " elements. " < < std : : endl ;
2009-03-12 16:08:02 -04:00
# endif
2009-04-06 17:06:44 -04:00
sendItem ( res_item ) ;
res_item = NULL ;
}
2009-03-22 10:08:02 -04:00
}
2009-03-12 16:08:02 -04:00
}
2009-03-22 10:08:02 -04:00
# ifdef P3TURTLE_DEBUG
else
std : : cerr < < " Rejecting local search because strategy is FRIENDS_ONLY and item depth= " < < item - > depth < < std : : endl ;
# endif
2009-02-28 13:19:00 -05:00
}
// If search depth not too large, also forward this search request to all other peers.
//
if ( item - > depth < TURTLE_MAX_SEARCH_DEPTH )
2009-03-12 16:08:02 -04:00
{
std : : list < std : : string > onlineIds ;
mConnMgr - > 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 )
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
+ + ( fwd_item - > depth ) ; // increase search depth
2009-03-12 17:07:00 -04:00
fwd_item - > PeerId ( * it ) ;
2009-02-28 13:19:00 -05:00
sendItem ( fwd_item ) ;
}
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
2009-04-19 15:59:54 -04:00
if ( it - > second . origin = = mConnMgr - > 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
//
void p3turtle : : routeGenericTunnelItem ( RsTurtleGenericTunnelItem * item )
2009-05-26 17:42:45 -04:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3Turtle: treating generic tunnel item: " < < std : : endl ;
2009-05-26 17:42:45 -04:00
item - > print ( std : : cerr , 1 ) ;
# endif
2010-01-02 16:30:19 -05:00
RsTurtleGenericTunnelItem : : Direction direction = item - > travelingDirection ( ) ;
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-01-02 16:30:19 -05:00
// look for the tunnel id.
//
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it ( _local_tunnels . find ( item - > tunnelId ( ) ) ) ;
2009-05-26 17:42:45 -04:00
if ( it = = _local_tunnels . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file map with unknown tunnel id " < < ( void * ) item - > tunnelId ( ) < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
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 ) ;
// Let's figure out whether this packet is for us or not.
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
if ( direction = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT & & tunnel . local_src ! = mConnMgr - > getOwnId ( ) )
{
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 ) ;
sendItem ( item ) ;
return ;
2009-05-26 17:42:45 -04:00
}
2010-01-02 16:30:19 -05:00
if ( direction = = RsTurtleGenericTunnelItem : : DIRECTION_SERVER & & tunnel . local_dst ! = mConnMgr - > getOwnId ( ) )
{
# 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
2010-01-02 16:30:19 -05:00
sendItem ( item ) ;
2009-05-26 17:42:45 -04:00
return ;
}
}
2010-01-02 16:30:19 -05:00
// The packet was not forwarded, so it is for us. Let's treat it.
// This is done off-mutex, to avoid various deadlocks
2009-05-26 17:42:45 -04:00
//
2010-01-11 11:00:42 -05:00
switch ( item - > PacketSubType ( ) )
{
case RS_TURTLE_SUBTYPE_FILE_REQUEST : handleRecvFileRequest ( dynamic_cast < RsTurtleFileRequestItem * > ( item ) ) ;
break ;
2010-01-02 16:30:19 -05:00
2010-01-11 11:00:42 -05:00
case RS_TURTLE_SUBTYPE_FILE_DATA : handleRecvFileData ( dynamic_cast < RsTurtleFileDataItem * > ( item ) ) ;
break ;
case RS_TURTLE_SUBTYPE_FILE_MAP : handleRecvFileMap ( dynamic_cast < RsTurtleFileMapItem * > ( item ) ) ;
break ;
case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : handleRecvFileMapRequest ( dynamic_cast < RsTurtleFileMapRequestItem * > ( item ) ) ;
break ;
default :
2010-01-26 15:40:21 -05:00
std : : cerr < < " WARNING: Unknown packet type received: id= " < < ( void * ) ( item - > PacketSubType ( ) ) < < " . Is somebody trying to DOS you ? " < < std : : endl ;
# ifdef P3TURTLE_DEBUG
2010-01-11 11:00:42 -05:00
exit ( - 1 ) ;
2010-01-26 15:40:21 -05:00
# endif
2010-01-11 11:00:42 -05:00
}
2010-01-02 16:30:19 -05:00
delete item ;
2009-05-26 17:42:45 -04:00
}
2010-01-02 16:30:19 -05:00
void p3turtle : : handleRecvFileRequest ( RsTurtleFileRequestItem * item )
2009-05-26 17:42:45 -04:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3Turtle: received file request item: " < < std : : endl ;
2009-05-26 17:42:45 -04:00
item - > print ( std : : cerr , 1 ) ;
# endif
2009-08-25 16:49:50 -04:00
// This is a new request. Let's add it to the request map, and forward it to
2009-05-26 17:42:45 -04:00
// open peers.
TurtleVirtualPeerId vpid ;
uint64_t size ;
TurtleFileHash hash ;
2010-01-02 16:30:19 -05:00
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-01-02 16:30:19 -05:00
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
if ( it2 = = _local_tunnels . end ( ) )
2009-05-26 17:42:45 -04:00
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file request with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
2010-01-02 16:30:19 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
std : : map < TurtleFileHash , FileInfo > : : const_iterator it ( _outgoing_file_hashes . find ( tunnel . hash ) ) ;
# ifdef P3TURTLE_DEBUG
assert ( ! tunnel . hash . empty ( ) ) ;
assert ( it ! = _outgoing_file_hashes . end ( ) ) ;
2009-06-13 15:28:47 -04:00
2010-01-02 16:30:19 -05:00
std : : cerr < < " This is an endpoint for this file request. " < < std : : endl ;
std : : cerr < < " Forwarding data request to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
size = it - > second . size ;
vpid = tunnel . vpid ;
hash = tunnel . hash ;
}
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
// This call is voluntarily off-mutex gards because it can cause cross mutex locks with the multiplexer.
// (Yeah, this bug was a shity hard one to catch).
//
_ft_server - > getMultiplexer ( ) - > recvDataRequest ( vpid , hash , size , item - > chunk_offset , item - > chunk_size ) ;
}
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
void p3turtle : : handleRecvFileData ( RsTurtleFileDataItem * item )
{
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3Turtle: received file data item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
2009-08-25 16:49:50 -04:00
# endif
2010-01-02 16:30:19 -05:00
TurtleVirtualPeerId vpid ;
uint64_t size ;
TurtleFileHash hash ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
{
2009-06-14 14:59:42 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-08-25 16:49:50 -04:00
# endif
2010-01-02 16:30:19 -05:00
return ;
}
2009-06-14 14:59:42 -04:00
2010-01-02 16:30:19 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . find ( tunnel . hash ) ) ;
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
assert ( ! tunnel . hash . empty ( ) ) ;
2009-05-26 17:42:45 -04:00
# endif
2010-01-02 16:30:19 -05:00
if ( it = = _incoming_file_hashes . end ( ) )
2009-05-26 17:42:45 -04:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " No tunnel for incoming data. Maybe the tunnel is being closed. " < < std : : endl ;
2009-05-26 17:42:45 -04:00
# endif
return ;
}
2010-01-02 16:30:19 -05:00
const TurtleFileHashInfo & hash_info ( it - > second ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " This is an endpoint for this data chunk. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
# endif
//_ft_server->getMultiplexer()->recvData(tunnel.vpid,tunnel.hash,hash_info.size,item->chunk_offset,item->chunk_size,item->chunk_data) ;
vpid = tunnel . vpid ;
hash = tunnel . hash ;
size = hash_info . size ;
// also update the hash time stamp to show that it's actually being downloaded.
it - > second . time_stamp = time ( NULL ) ;
2009-05-26 17:42:45 -04:00
}
2010-01-02 16:30:19 -05:00
2009-05-26 17:42:45 -04:00
_ft_server - > getMultiplexer ( ) - > recvData ( vpid , hash , size , item - > chunk_offset , item - > chunk_size , item - > chunk_data ) ;
2009-06-13 15:28:47 -04:00
item - > chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted
// down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData
2009-05-26 17:42:45 -04:00
}
2010-01-11 11:00:42 -05:00
void p3turtle : : handleRecvFileMapRequest ( RsTurtleFileMapRequestItem * item )
2009-12-28 16:11:00 -05:00
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file Map item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
2010-01-11 11:00:42 -05:00
std : : string hash , vpid ;
2009-12-28 16:11:00 -05:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2010-01-02 16:30:19 -05:00
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
2009-12-28 16:11:00 -05:00
2010-01-02 16:30:19 -05:00
if ( it2 = = _local_tunnels . end ( ) )
2009-12-28 16:11:00 -05:00
{
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
return ;
}
2010-01-02 16:30:19 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
2009-12-28 16:11:00 -05:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
assert ( ! tunnel . hash . empty ( ) ) ;
2010-01-11 11:00:42 -05:00
std : : cerr < < " This is an endpoint for this file map request. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2010-01-11 11:00:42 -05:00
// we should check that there is no backward call to the turtle router!
//
hash = tunnel . hash ;
vpid = tunnel . vpid ;
}
_ft_server - > getMultiplexer ( ) - > recvChunkMapRequest ( vpid , hash , item - > direction = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
}
void p3turtle : : handleRecvFileMap ( RsTurtleFileMapItem * item )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3Turtle: received file Map item: " < < std : : endl ;
item - > print ( std : : cerr , 1 ) ;
# endif
std : : string hash , vpid ;
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
std : : map < TurtleTunnelId , TurtleTunnel > : : iterator it2 ( _local_tunnels . find ( item - > tunnel_id ) ) ;
if ( it2 = = _local_tunnels . end ( ) )
2010-01-02 16:30:19 -05:00
{
2009-12-28 16:11:00 -05:00
# ifdef P3TURTLE_DEBUG
2010-01-11 11:00:42 -05:00
std : : cerr < < " p3turtle: got file data with unknown tunnel id " < < ( void * ) item - > tunnel_id < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2010-01-02 16:30:19 -05:00
return ;
2009-12-28 16:11:00 -05:00
}
2010-01-02 16:30:19 -05:00
2010-01-11 11:00:42 -05:00
TurtleTunnel & tunnel ( it2 - > second ) ;
2009-12-28 16:11:00 -05:00
# ifdef P3TURTLE_DEBUG
2010-01-11 11:00:42 -05:00
assert ( ! tunnel . hash . empty ( ) ) ;
2010-01-02 16:30:19 -05:00
std : : cerr < < " This is an endpoint for this file map. " < < std : : endl ;
std : : cerr < < " Forwarding data to the multiplexer. " < < std : : endl ;
std : : cerr < < " using peer_id= " < < tunnel . vpid < < " , hash= " < < tunnel . hash < < std : : endl ;
2009-12-28 16:11:00 -05:00
# endif
2010-01-11 11:00:42 -05:00
// We should check that there is no backward call to the turtle router!
2010-01-02 16:30:19 -05:00
//
2010-01-11 11:00:42 -05:00
vpid = tunnel . vpid ;
hash = tunnel . hash ;
2009-12-28 16:11:00 -05:00
}
2010-01-11 11:00:42 -05:00
_ft_server - > getMultiplexer ( ) - > recvChunkMap ( vpid , hash , item - > compressed_map , item - > direction = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ) ;
2009-12-28 16:11:00 -05:00
}
2009-05-26 17:42:45 -04:00
// Send a data request into the correct tunnel for the given file hash
2009-08-25 16:49:50 -04:00
void p3turtle : : sendDataRequest ( const std : : string & peerId , const std : : string & hash , uint64_t , uint64_t offset , uint32_t chunksize )
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileRequestItem * item = new RsTurtleFileRequestItem ;
item - > tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever.
item - > chunk_offset = offset ;
item - > chunk_size = chunksize ;
item - > PeerId ( tunnel . local_dst ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending file req (chunksize= " < < item - > chunk_size < < " , offset= " < < item - > chunk_offset < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < tunnel . local_dst < < std : : endl ;
# endif
sendItem ( item ) ;
}
// Send file data into the correct tunnel for the given file hash
void p3turtle : : sendFileData ( const std : : string & peerId , const std : : string & hash , uint64_t , uint64_t offset , uint32_t chunksize , void * data )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
2009-07-27 16:52:55 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle::sendData: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
2009-07-27 16:52:55 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
2009-06-03 14:47:14 -04:00
tunnel . time_stamp = time ( NULL ) ;
2009-05-26 17:42:45 -04:00
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileDataItem * item = new RsTurtleFileDataItem ;
2009-08-25 16:49:50 -04:00
item - > tunnel_id = tunnel_id ;
2009-05-26 17:42:45 -04:00
item - > chunk_offset = offset ;
item - > chunk_size = chunksize ;
item - > chunk_data = malloc ( chunksize ) ;
2009-07-27 16:52:55 -04:00
if ( item - > chunk_data = = NULL )
{
std : : cerr < < " p3turtle: Warning: failed malloc of " < < chunksize < < " bytes for sending data packet. " < < std : : endl ;
return ;
}
2009-05-26 17:42:45 -04:00
memcpy ( item - > chunk_data , ( void * ) ( ( uint8_t * ) data ) , chunksize ) ;
item - > PeerId ( tunnel . local_src ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending file data (chunksize= " < < item - > chunk_size < < " , offset= " < < item - > chunk_offset < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < tunnel . local_src < < std : : endl ;
# endif
sendItem ( item ) ;
}
2010-01-11 11:00:42 -05:00
void p3turtle : : sendChunkMapRequest ( const std : : string & peerId , const std : : string & hash )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileMapRequestItem * item = new RsTurtleFileMapRequestItem ;
item - > tunnel_id = tunnel_id ;
std : : string ownid = mConnMgr - > getOwnId ( ) ;
if ( tunnel . local_src = = ownid )
{
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_SERVER ;
item - > PeerId ( tunnel . local_dst ) ;
}
else if ( tunnel . local_dst = = ownid )
{
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ;
item - > PeerId ( tunnel . local_src ) ;
}
else
std : : cerr < < " p3turtle::sendChunkMap: consistency error! " < < std : : endl ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending chunk map req to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
void p3turtle : : sendChunkMap ( const std : : string & peerId , const std : : string & hash , const CompressedChunkMap & cmap )
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// get the proper tunnel for this file hash and peer id.
std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . find ( peerId ) ) ;
if ( it = = _virtual_peers . end ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle::senddataRequest: cannot find virtual peer " < < peerId < < " in VP list. " < < std : : endl ;
# endif
return ;
}
TurtleTunnelId tunnel_id = it - > second ;
TurtleTunnel & tunnel ( _local_tunnels [ tunnel_id ] ) ;
# ifdef P3TURTLE_DEBUG
assert ( hash = = tunnel . hash ) ;
# endif
RsTurtleFileMapItem * item = new RsTurtleFileMapItem ;
item - > tunnel_id = tunnel_id ;
item - > compressed_map = cmap ;
std : : string ownid = mConnMgr - > getOwnId ( ) ;
if ( tunnel . local_src = = ownid )
{
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_SERVER ;
item - > PeerId ( tunnel . local_dst ) ;
}
else if ( tunnel . local_dst = = ownid )
{
item - > direction = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT ;
item - > PeerId ( tunnel . local_src ) ;
}
else
std : : cerr < < " p3turtle::sendChunkMap: consistency error! " < < std : : endl ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: sending chunk map to peer " < < peerId < < " , hash=0x " < < hash < < " ) through tunnel " < < ( void * ) item - > tunnel_id < < " , next peer= " < < item - > PeerId ( ) < < std : : endl ;
# endif
sendItem ( item ) ;
}
2009-12-28 16:11:00 -05:00
// This function is actually not needed: Search request to the turtle router are:
// - distant search requests, handled by the router
// - search requests over files being downloaded, handled by rsFiles !!
//
//bool p3turtle::search(std::string hash, uint64_t, uint32_t hintflags, FileInfo &info) const
//{
// if(! (hintflags & RS_FILE_HINTS_TURTLE)) // this should not happen, but it's a security.
// return false;
//
// RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
//
//#ifdef P3TURTLE_DEBUG
// std::cerr << "p3turtle: received file search request for hash " << hash << "." << std::endl ;
//#endif
//
// std::map<TurtleFileHash,TurtleFileHashInfo>::const_iterator it = _incoming_file_hashes.find(hash) ;
//
// if(_incoming_file_hashes.end() != it)
// {
// info.fname = it->second.name;
// info.size = it->second.size;
// info.hash = it->first;
//
// for(unsigned int i=0;i<it->second.tunnels.size();++i)
// {
// TransferInfo ti;
// ti.peerId = getTurtlePeerId(it->second.tunnels[i]);
// ti.name = "Distant peer for hash=" + hash ;
// ti.tfRate = 0;
// info.peers.push_back(ti);
// }
//
//#ifdef P3TURTLE_DEBUG
// std::cerr << " Found these tunnels for that hash:. "<< std::endl ;
// for(unsigned int i=0;i<it->second.tunnels.size();++i)
// std::cerr << " " << (void*)it->second.tunnels[i] << std::endl ;
//
// std::cerr << " answered yes. "<< std::endl ;
//#endif
// return true ;
// }
// else
// {
//#ifdef P3TURTLE_DEBUG
// std::cerr << " responding false." << std::endl ;
//#endif
// return false ;
// }
//}
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
std : : cerr < < " performing tunnel request. OwnId = " < < mConnMgr - > getOwnId ( ) < < std : : endl ;
# endif
while ( mConnMgr - > getOwnId ( ) = = " " )
{
std : : cerr < < " ... waitting for connect manager to form own id. " < < std : : endl ;
# ifdef WIN32
Sleep ( 1000 ) ;
# else
sleep ( 1 ) ;
# endif
}
TurtleRequestId id = generateRandomRequestId ( ) ;
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 ;
}
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 ;
item - > PeerId ( mConnMgr - > getOwnId ( ) ) ;
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
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
2009-04-13 16:26:13 -04:00
std : : cerr < < " Received tunnel request from peer " < < item - > PeerId ( ) < < " : " < < std : : endl ;
item - > print ( std : : cerr , 0 ) ;
# endif
// If the item contains an already handled tunnel request, give up. This
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 ******/
if ( _tunnel_requests_origins . find ( item - > request_id ) ! = _tunnel_requests_origins . end ( ) )
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " This is a bouncing request. Ignoring and deleting item. " < < std : : endl ;
2009-03-15 18:45:40 -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 ) ;
2010-01-02 16:30:19 -05:00
}
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
// If it's not for us, perform a local search. If something found, forward the search result back.
// We're off-mutex here.
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
bool found = false ;
FileInfo info ;
if ( item - > PeerId ( ) ! = mConnMgr - > getOwnId ( ) )
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " Request not from us. Performing local search " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2010-01-02 16:30:19 -05:00
found = ( _sharing_strategy ! = SHARE_FRIENDS_ONLY | | item - > depth < 2 ) & & performLocalHashSearch ( item - > file_hash , info ) ;
}
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
if ( found )
{
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
std : : cerr < < " Local hash found. Sending tunnel ok to origin ( " < < item - > PeerId ( ) < < " ). " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2010-01-02 16:30:19 -05:00
// Send back tunnel ok to the same guy
//
RsTurtleTunnelOkItem * res_item = new RsTurtleTunnelOkItem ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
res_item - > request_id = item - > request_id ;
res_item - > tunnel_id = item - > partial_tunnel_id ^ generatePersonalFilePrint ( item - > file_hash , false ) ;
res_item - > PeerId ( item - > PeerId ( ) ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
sendItem ( res_item ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
// Note in the tunnels list that we have an ending tunnel here.
TurtleTunnel tt ;
tt . local_src = item - > PeerId ( ) ;
tt . hash = item - > file_hash ;
tt . local_dst = mConnMgr - > getOwnId ( ) ; // this means us
tt . time_stamp = time ( NULL ) ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
_local_tunnels [ res_item - > tunnel_id ] = tt ;
2009-04-13 16:26:13 -04:00
2010-01-02 16:30:19 -05:00
// We add a virtual peer for that tunnel+hash combination.
//
addDistantPeer ( item - > file_hash , res_item - > tunnel_id ) ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
// Store the size of the file, to be able to re-form data requests to the multiplexer.
//
_outgoing_file_hashes [ item - > file_hash ] = info ;
2009-05-26 17:42:45 -04:00
2010-01-02 16:30:19 -05:00
// We return straight, because when something is found, there's no need to digg a tunnel further.
return ;
}
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2010-01-02 16:30:19 -05:00
else
std : : cerr < < " No hash found locally, or local file not allowed for distant peers. Forwarding. " < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
}
// If search depth not too large, also forward this search request to all other peers.
//
if ( item - > depth < TURTLE_MAX_SEARCH_DEPTH )
{
std : : list < std : : string > onlineIds ;
mConnMgr - > getOnlineList ( onlineIds ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Forwarding tunnel request: Looking for online peers " < < std : : endl ;
# endif
for ( std : : list < std : : string > : : const_iterator it ( onlineIds . begin ( ) ) ; it ! = onlineIds . end ( ) ; + + it )
if ( * it ! = item - > PeerId ( ) )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Forwarding request to peer = " < < * it < < std : : endl ;
# endif
// Copy current item and modify it.
RsTurtleOpenTunnelItem * fwd_item = new RsTurtleOpenTunnelItem ( * item ) ;
+ + ( fwd_item - > depth ) ; // increase tunnel depth
fwd_item - > PeerId ( * it ) ;
sendItem ( fwd_item ) ;
}
}
# ifdef P3TURTLE_DEBUG
else
std : : cout < < " Dropping this item, as tunnel depth is " < < item - > depth < < std : : endl ;
# endif
}
void p3turtle : : handleTunnelResult ( RsTurtleTunnelOkItem * item )
{
2009-05-26 17:42:45 -04:00
bool new_tunnel = false ;
TurtleFileHash new_hash ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
// Find who actually sent the corresponding turtle tunnel request.
//
std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : const_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
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
2009-05-26 17:42:45 -04:00
// have forwarded but that it not in the list ??
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
std : : cerr < < __PRETTY_FUNCTION__ < < " : tunnel result has no peer direction! " < < std : : endl ;
return ;
}
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 ) ;
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
2009-05-26 17:42:45 -04:00
if ( it - > second . origin = = mConnMgr - > getOwnId ( ) )
{
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
2009-05-26 17:42:45 -04:00
// 1 - find which file hash issued this request. This is not costly, because there is not too much file hashes to be active
// at a time, and this mostly prevents from sending the hash back in the tunnel.
2009-04-19 15:59:54 -04:00
2009-05-26 17:42:45 -04:00
bool found = false ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
if ( it - > second . last_request = = item - > request_id )
{
found = true ;
2009-06-15 16:34:34 -04:00
// add the tunnel uniquely
bool found = false ;
for ( unsigned int j = 0 ; j < it - > second . tunnels . size ( ) ; + + j )
if ( it - > second . tunnels [ j ] = = item - > tunnel_id )
found = true ;
if ( ! found )
it - > second . tunnels . push_back ( item - > tunnel_id ) ;
2009-05-26 17:42:45 -04:00
tunnel . hash = it - > first ; // because it's a local tunnel
// Adds a virtual peer to the list of online peers.
// We do this later, because of the mutex protection.
//
new_tunnel = true ;
new_hash = it - > first ;
addDistantPeer ( new_hash , item - > tunnel_id ) ;
}
if ( ! found )
std : : cerr < < " p3turtle: error. Could not find hash that emmitted tunnel request " < < ( void * ) item - > tunnel_id < < std : : endl ;
}
else
{ // Nope, forward it back.
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " Forwarding result back to " < < it - > second . origin < < std : : endl ;
2009-04-13 16:26:13 -04:00
# endif
2009-05-26 17:42:45 -04:00
RsTurtleTunnelOkItem * fwd_item = new RsTurtleTunnelOkItem ( * item ) ; // copy the item
fwd_item - > PeerId ( it - > second . origin ) ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
sendItem ( fwd_item ) ;
}
}
2009-08-25 16:49:50 -04:00
// A new tunnel has been created. Add the corresponding virtual peer to the list, and
2009-05-26 17:42:45 -04:00
// notify the file transfer controller for the new file source. This should be done off-mutex
// so we deported this code here.
//
if ( new_tunnel )
{
_ft_controller - > addFileSource ( new_hash , _local_tunnels [ item - > tunnel_id ] . vpid ) ;
_ft_controller - > statusChange ( _online_peers ) ;
2009-04-13 16:26:13 -04:00
}
2009-03-12 16:08:02 -04:00
}
2009-02-28 13:19:00 -05:00
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
2009-08-25 16:49:50 -04:00
// ------------------------------ IO with libretroshare ----------------------------//
2009-04-13 16:26:13 -04:00
// -----------------------------------------------------------------------------------//
//
2009-08-25 08:04:43 -04:00
void RsTurtleStringSearchRequestItem : : performLocalSearch ( std : : list < TurtleFileInfo > & result ) const
2009-04-13 16:26:13 -04:00
{
/* call to core */
2009-08-25 16:49:50 -04:00
std : : list < DirDetails > initialResults ;
2009-04-13 16:26:13 -04:00
std : : list < std : : string > words ;
2009-02-28 13:19:00 -05:00
2009-04-13 16:26:13 -04:00
// to do: split search string into words.
2009-08-25 08:04:43 -04:00
words . push_back ( match_string ) ;
2009-08-25 16:49:50 -04:00
2010-02-03 15:59:54 -05:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Performing rsFiles->search() " < < std : : endl ;
# endif
2009-04-13 16:26:13 -04:00
// now, search!
2009-08-10 15:44:45 -04:00
rsFiles - > SearchKeywords ( words , initialResults , DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE ) ;
2009-04-13 16:26:13 -04:00
2010-02-03 15:59:54 -05:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < initialResults . size ( ) < < " matches found. " < < std : : endl ;
# endif
2009-04-13 16:26:13 -04:00
result . clear ( ) ;
2009-08-25 16:49:50 -04:00
for ( std : : list < DirDetails > : : const_iterator it ( initialResults . begin ( ) ) ; it ! = initialResults . end ( ) ; + + it )
2009-04-13 16:26:13 -04:00
{
2009-08-25 16:49:50 -04:00
// retain only file type
2010-02-03 15:59:54 -05:00
if ( it - > type = = DIR_TYPE_DIR )
{
# ifdef P3TURTLE_DEBUG
std : : cerr < < " Skipping directory " < < it - > name < < std : : endl ;
# endif
continue ;
}
2009-08-25 16:49:50 -04:00
2009-04-13 16:26:13 -04:00
TurtleFileInfo i ;
i . hash = it - > hash ;
2009-08-25 16:49:50 -04:00
i . size = it - > count ;
2009-04-13 16:26:13 -04:00
i . name = it - > name ;
result . push_back ( i ) ;
}
}
2009-08-25 08:04:43 -04:00
void RsTurtleRegExpSearchRequestItem : : performLocalSearch ( std : : list < TurtleFileInfo > & result ) const
{
/* call to core */
2009-08-25 16:49:50 -04:00
std : : list < DirDetails > initialResults ;
2009-08-25 08:04:43 -04:00
// to do: split search string into words.
Expression * exp = LinearizedExpression : : toExpr ( expr ) ;
2009-08-25 16:49:50 -04:00
2009-08-25 08:04:43 -04:00
// now, search!
rsFiles - > SearchBoolExp ( exp , initialResults , DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE ) ;
result . clear ( ) ;
2009-08-25 16:49:50 -04:00
for ( std : : list < DirDetails > : : const_iterator it ( initialResults . begin ( ) ) ; it ! = initialResults . end ( ) ; + + it )
2009-08-25 08:04:43 -04:00
{
TurtleFileInfo i ;
i . hash = it - > hash ;
2009-08-25 16:49:50 -04:00
i . size = it - > count ;
2009-08-25 08:04:43 -04:00
i . name = it - > name ;
result . push_back ( i ) ;
}
delete exp ;
}
2009-04-13 16:26:13 -04:00
2009-08-25 16:49:50 -04:00
TurtleRequestId p3turtle : : turtleSearch ( const std : : string & string_to_match )
2009-04-13 16:26:13 -04:00
{
// generate a new search id.
2009-08-25 16:49:50 -04:00
2009-04-13 16:26:13 -04:00
TurtleRequestId id = generateRandomRequestId ( ) ;
2009-03-13 17:14:30 -04:00
2009-04-13 16:26:13 -04:00
// Form a request packet that simulates a request from us.
//
2009-08-25 08:04:43 -04:00
RsTurtleStringSearchRequestItem * item = new RsTurtleStringSearchRequestItem ;
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
std : : cerr < < " performing search. OwnId = " < < mConnMgr - > getOwnId ( ) < < std : : endl ;
# endif
while ( mConnMgr - > getOwnId ( ) = = " " )
{
std : : cerr < < " ... waitting for connect manager to form own id. " < < std : : endl ;
# ifdef WIN32
Sleep ( 1000 ) ;
# else
sleep ( 1 ) ;
# endif
}
item - > PeerId ( mConnMgr - > getOwnId ( ) ) ;
item - > match_string = string_to_match ;
item - > request_id = id ;
item - > depth = 0 ;
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
std : : cerr < < " performing search. OwnId = " < < mConnMgr - > getOwnId ( ) < < std : : endl ;
# endif
while ( mConnMgr - > getOwnId ( ) = = " " )
{
std : : cerr < < " ... waitting for connect manager to form own id. " < < std : : endl ;
# ifdef WIN32
Sleep ( 1000 ) ;
# else
sleep ( 1 ) ;
# endif
}
item - > PeerId ( mConnMgr - > getOwnId ( ) ) ;
item - > expr = expr ;
item - > request_id = id ;
item - > depth = 0 ;
2009-08-25 16:49:50 -04:00
// send it
2009-08-25 08:04:43 -04:00
handleSearchRequest ( item ) ;
delete item ;
return id ;
}
2009-04-13 16:26:13 -04:00
2009-08-25 16:49:50 -04:00
void p3turtle : : monitorFileTunnels ( const std : : string & name , const std : : string & file_hash , uint64_t size )
2009-04-13 16:26:13 -04:00
{
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-03-13 17:14:30 -04:00
2010-03-12 14:39:23 -05:00
// First, check if the hash is tagged for removal (there's a delay)
2010-03-13 07:24:14 -05:00
for ( uint32_t i = 0 ; i < _hashes_to_remove . size ( ) ; + + i )
2010-03-12 14:39:23 -05:00
if ( _hashes_to_remove [ i ] = = file_hash )
{
_hashes_to_remove [ i ] = _hashes_to_remove . back ( ) ;
_hashes_to_remove . pop_back ( ) ;
# ifdef P3TURTLE_DEBUG
std : : cerr < < " p3turtle: File hash " < < file_hash < < " Was scheduled for removal. Canceling the removal. " < < std : : endl ;
# endif
}
// Then, check if the hash is already there
//
2009-05-26 17:42:45 -04:00
if ( _incoming_file_hashes . find ( file_hash ) ! = _incoming_file_hashes . end ( ) ) // download already asked.
2009-03-15 18:45:40 -04:00
{
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle: File hash " < < file_hash < < " already in pool. Returning. " < < std : : endl ;
2009-05-07 17:36:17 -04:00
# endif
2009-05-26 17:42:45 -04:00
return ;
}
2009-03-15 18:45:40 -04:00
# ifdef P3TURTLE_DEBUG
2009-05-26 17:42:45 -04:00
std : : cerr < < " p3turtle: Received order for turtle download fo hash " < < file_hash < < std : : endl ;
2009-05-07 17:36:17 -04:00
# endif
2009-03-15 18:45:40 -04:00
2009-05-26 17:42:45 -04:00
// No tunnels at start, but this triggers digging new tunnels.
//
_incoming_file_hashes [ file_hash ] . tunnels . clear ( ) ;
2009-06-03 14:47:14 -04:00
_force_digg_new_tunnels = true ;
2009-04-13 16:26:13 -04:00
2009-05-26 17:42:45 -04:00
// also should send associated request to the file transfer module.
_incoming_file_hashes [ file_hash ] . size = size ;
_incoming_file_hashes [ file_hash ] . name = name ;
2009-06-03 14:47:14 -04:00
_incoming_file_hashes [ file_hash ] . time_stamp = time ( NULL ) ;
2009-04-13 16:26:13 -04:00
}
2009-03-15 18:45:40 -04:00
2009-06-03 14:47:14 -04:00
IndicateConfigChanged ( ) ; // initiates saving of handled hashes.
2009-04-13 16:26:13 -04:00
}
2009-05-26 17:42:45 -04:00
void p3turtle : : returnSearchResult ( RsTurtleSearchResultItem * item )
2009-04-13 16:26:13 -04:00
{
2009-05-26 17:42:45 -04:00
// just cout for now, but it should be notified to the gui
2009-08-25 16:49:50 -04:00
2009-04-13 16:26:13 -04:00
# ifdef P3TURTLE_DEBUG
2009-08-25 08:04:43 -04:00
std : : cerr < < " Returning result for search request " < < ( void * ) item - > request_id < < " upwards. " < < std : : endl ;
2009-05-07 17:36:17 -04:00
# endif
2009-04-19 15:59:54 -04:00
2009-05-26 17:42:45 -04:00
rsicontrol - > getNotify ( ) . notifyTurtleSearchResult ( item - > request_id , item - > result ) ;
2009-04-19 15:59:54 -04:00
}
2010-01-02 16:30:19 -05:00
/// Warning: this function should never be called while the turtle mutex is locked.
/// Otherwize this is a possible source of cross-lock with the File mutex.
//
2009-08-25 16:49:50 -04:00
bool p3turtle : : performLocalHashSearch ( const TurtleFileHash & hash , FileInfo & info )
2009-04-19 15:59:54 -04:00
{
2010-02-18 17:57:45 -05:00
return rsFiles - > FileDetails ( hash , RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD , info ) ;
2009-04-19 15:59:54 -04:00
}
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
{
std : : ostringstream out ;
out < < num ;
return out . str ( ) ;
}
}
void p3turtle : : getInfo ( std : : vector < std : : vector < std : : string > > & hashes_info ,
std : : vector < std : : vector < std : : string > > & tunnels_info ,
std : : vector < std : : vector < std : : string > > & search_reqs_info ,
std : : vector < std : : vector < std : : string > > & tunnel_reqs_info ) const
{
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
time_t now = time ( NULL ) ;
hashes_info . clear ( ) ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
{
hashes_info . push_back ( std : : vector < std : : string > ( ) ) ;
std : : vector < std : : string > & hashes ( hashes_info . back ( ) ) ;
hashes . push_back ( it - > first ) ;
hashes . push_back ( it - > second . name ) ;
hashes . push_back ( printNumber ( it - > second . tunnels . size ( ) ) ) ;
hashes . push_back ( printNumber ( now - it - > second . time_stamp ) + " secs ago " ) ;
}
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
RsPeerDetails sslDetails ;
rsPeers - > getPeerDetails ( it - > second . local_src , sslDetails ) ;
tunnel . push_back ( sslDetails . name + " - " + sslDetails . location ) ;
rsPeers - > getPeerDetails ( it - > second . local_dst , sslDetails ) ;
tunnel . push_back ( sslDetails . name + " - " + sslDetails . location ) ;
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 " ) ;
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 )
{
search_reqs_info . push_back ( std : : vector < std : : string > ( ) ) ;
std : : vector < std : : string > & search_req ( search_reqs_info . back ( ) ) ;
search_req . push_back ( printNumber ( it - > first , true ) ) ;
2010-02-15 16:32:06 -05:00
RsPeerDetails sslDetails ;
rsPeers - > getPeerDetails ( it - > second . origin , sslDetails ) ;
search_req . push_back ( sslDetails . name + " - " + sslDetails . location ) ;
2009-08-25 08:04:43 -04:00
search_req . push_back ( printNumber ( now - it - > second . time_stamp ) + " secs ago " ) ;
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 )
{
tunnel_reqs_info . push_back ( std : : vector < std : : string > ( ) ) ;
std : : vector < std : : string > & tunnel_req ( tunnel_reqs_info . back ( ) ) ;
tunnel_req . push_back ( printNumber ( it - > first , true ) ) ;
2010-02-15 16:32:06 -05:00
RsPeerDetails sslDetails ;
rsPeers - > getPeerDetails ( it - > second . origin , sslDetails ) ;
tunnel_req . push_back ( sslDetails . name + " - " + sslDetails . location ) ;
2009-08-25 08:04:43 -04:00
tunnel_req . push_back ( printNumber ( now - it - > second . time_stamp ) + " secs ago " ) ;
2009-08-16 16:10:53 -04:00
}
}
2009-04-19 15:59:54 -04:00
# ifdef P3TURTLE_DEBUG
void p3turtle : : dumpState ( )
{
2009-05-26 17:42:45 -04:00
RsStackMutex stack ( mTurtleMtx ) ; /********** STACK LOCKED MTX ******/
2009-04-19 15:59:54 -04:00
time_t now = time ( NULL ) ;
std : : cerr < < std : : endl ;
std : : cerr < < " ********************** Turtle router dump ****************** " < < std : : endl ;
2009-05-26 17:42:45 -04:00
std : : cerr < < " Active incoming file hashes: " < < _incoming_file_hashes . size ( ) < < std : : endl ;
for ( std : : map < TurtleFileHash , TurtleFileHashInfo > : : const_iterator it ( _incoming_file_hashes . begin ( ) ) ; it ! = _incoming_file_hashes . end ( ) ; + + it )
2009-04-19 15:59:54 -04:00
{
2009-05-26 17:42:45 -04:00
std : : cerr < < " hash=0x " < < it - > first < < " , name= " < < it - > second . name < < " , size= " < < it - > second . size < < " , tunnel ids = " ;
for ( std : : vector < TurtleTunnelId > : : const_iterator it2 ( it - > second . tunnels . begin ( ) ) ; it2 ! = it - > second . tunnels . end ( ) ; + + it2 )
2009-04-19 15:59:54 -04:00
std : : cerr < < " " < < ( void * ) * it2 ;
2009-06-13 15:28:47 -04:00
std : : cerr < < " , last_req= " < < ( void * ) it - > second . last_request < < " , time_stamp = " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp < < " secs ago) " < < std : : endl ;
2009-04-19 15:59:54 -04:00
}
2009-05-26 17:42:45 -04:00
std : : cerr < < " Active outgoing file hashes: " < < _outgoing_file_hashes . size ( ) < < std : : endl ;
for ( std : : map < TurtleFileHash , FileInfo > : : const_iterator it ( _outgoing_file_hashes . begin ( ) ) ; it ! = _outgoing_file_hashes . end ( ) ; + + it )
2009-06-03 14:47:14 -04:00
std : : cerr < < " hash=0x " < < it - > first < < " , name= " < < it - > second . fname < < " , size= " < < it - > second . size < < std : : endl ;
2009-05-26 17:42:45 -04:00
2009-04-19 15:59:54 -04:00
std : : cerr < < " Local tunnels: " < < std : : endl ;
for ( std : : map < TurtleTunnelId , TurtleTunnel > : : const_iterator it ( _local_tunnels . begin ( ) ) ; it ! = _local_tunnels . end ( ) ; + + it )
2009-08-25 16:49:50 -04:00
std : : cerr < < " " < < ( void * ) it - > first < < " : from= "
< < it - > second . local_src < < " , to= " < < it - > second . local_dst
< < " , hash=0x " < < it - > second . hash < < " , ts= " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp < < " secs ago) "
2009-06-13 15:28:47 -04:00
< < " , peer id = " < < it - > second . vpid < < std : : endl ;
2009-04-19 15:59:54 -04:00
std : : cerr < < " buffered request origins: " < < std : : endl ;
std : : cerr < < " Search requests: " < < _search_requests_origins . size ( ) < < std : : endl ;
2009-06-03 14:47:14 -04:00
2009-04-19 15:59:54 -04:00
for ( std : : map < TurtleSearchRequestId , TurtleRequestInfo > : : const_iterator it ( _search_requests_origins . begin ( ) ) ; it ! = _search_requests_origins . end ( ) ; + + it )
2009-08-25 16:49:50 -04:00
std : : cerr < < " " < < ( void * ) it - > first < < " : from= " < < it - > second . origin
< < " , ts= " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp
2009-06-03 14:47:14 -04:00
< < " secs ago) " < < std : : endl ;
2009-04-19 15:59:54 -04:00
std : : cerr < < " Tunnel requests: " < < _tunnel_requests_origins . size ( ) < < std : : endl ;
for ( std : : map < TurtleTunnelRequestId , TurtleRequestInfo > : : const_iterator it ( _tunnel_requests_origins . begin ( ) ) ; it ! = _tunnel_requests_origins . end ( ) ; + + it )
2009-08-25 16:49:50 -04:00
std : : cerr < < " " < < ( void * ) it - > first < < " : from= " < < it - > second . origin
< < " , ts= " < < it - > second . time_stamp < < " ( " < < now - it - > second . time_stamp
2009-06-03 14:47:14 -04:00
< < " secs ago) " < < std : : endl ;
2009-05-26 17:42:45 -04:00
std : : cerr < < " Virtual peers: " < < std : : endl ;
for ( std : : map < TurtleVirtualPeerId , TurtleTunnelId > : : const_iterator it ( _virtual_peers . begin ( ) ) ; it ! = _virtual_peers . end ( ) ; + + it )
std : : cerr < < " id= " < < it - > first < < " , tunnel= " < < ( void * ) ( it - > second ) < < std : : endl ;
std : : cerr < < " Online peers: " < < std : : endl ;
for ( std : : list < pqipeer > : : const_iterator it ( _online_peers . begin ( ) ) ; it ! = _online_peers . end ( ) ; + + it )
std : : cerr < < " id= " < < it - > id < < " , name= " < < it - > name < < " , state= " < < it - > state < < " , actions= " < < it - > actions < < std : : endl ;
2009-04-19 15:59:54 -04:00
}
# endif
2009-03-15 18:45:40 -04:00