2013-11-02 10:35:33 -04:00
/*
* libretroshare / src / services : p3grouter . cc
*
* Services for RetroShare .
*
* Copyright 2013 by Cyril Soler
*
* 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 .
*
* Please report all bugs and problems to " csoler@users.sourceforge.net " .
*
*/
2014-03-17 16:56:06 -04:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decentralized routing
// =====================
//
// Main idea: Each peer holds a local routing table, a matrix with probabilities that each friend
// is a correct path for a given key ID.
//
// The routing tables are updated as messages go back and forth. Successful
// interactions feed the routing table with information of where to route the
// packets.
//
// The routing is kept probabilistic, meaning that the optimal route is not
// always chosen, but the randomness helps updating the routing probabilities.
//
// Services that might use the router (All services really...)
// - Messenger
// - sends/receives messages to distant peers
// - Channels, forums, posted, etc.
// - send messages to the origin of the channel/forum/posted
//
// Decentralized routing algorithm:
// - message passing
// - upward:
// * Forward msg to friends according to probabilities.
// * If all equal, send to all friends (or a rando subset of them).
// * keep the local routing info in a cache that is saved (Which peer issued the msg)
// - which probability was used to chose this friend (will be useful
// to compute the routing contribution if the msg is ACK-ed)
2014-03-29 10:18:05 -04:00
//
// Two probabilities are computed:
// - routing probabilities among connected friends
// * this is computed by the routing matrix
// - branching factor N
2015-04-21 15:02:14 -04:00
// * depends on the depth of the items. Currently branching is 3 at origin and 1 elsewhere.
2014-03-29 10:18:05 -04:00
// * depends on the distribution of probabilities (min and max)
//
// Once computed,
// - the item is forwarded randomly to N peers drawn from the list of connected peers with the given probabilities.
// - the depth of the item is incremented randomly
2014-03-17 16:56:06 -04:00
//
// - downward: look into routing cache. If info not present, drop the item.
// Forward item into stored direction.
//
// - routing probability computation: count number of times a reliable info is obtained from
// which direction for which identity
// * the count is a floating point number, since weights can be assigned to each info
// (especially for importance sampling)
// * init: all friends have equal count of 0 (or 1, well, we'll have to make this right).
// * We use importance sampling, meaning that when peer relays a msg from ID:
// count[ID, peer] += 1.0 / importance
//
// ... where importance was the probability of chosing peer for the
// route upward.
//
// * probability of forward is proportional to count.
//
// - routing cache
// * this cache stores messages IDs (like turtle router) but is saved on disk
// * it is used to remember where to send back responses to messages, and
// with what probability the route was chosen.
// * cache items have a TTL and the cache is cleaned regularly.
//
// - routing matrix
// * the structure is fed by other services, when they receive key IDs.
// * stores for each identity the count of how many times each peer gave reliable info for that ID.
// That information should be enough to route packets in the correct direction.
// * saved to disk.
// * all contributions should have a time stamp. Regularly, the oldest contributions are removed.
//
// - Routed packets: we use a common packet type for all services:
//
// We need two abstract item types:
//
// * Data packet
// - packet unique ID (sha1, or uint64_t)
// - destination ID (for Dn packets, the destination is the source!)
// - packet type: Id request, Message, etc.
// - packet service ID (Can be messenging, channels, etc).
// - packet data (void* + size_t)
// - flags (such as ACK or response required, and packet direction)
2014-03-29 10:18:05 -04:00
// - routed directions and probabilities
2014-03-17 16:56:06 -04:00
// * ACK packet.
// - packet unique ID (the id of the corresponding data)
// - flags (reason for ACK. Could be data delivered, or error, too far, etc)
//
// - Data storage packets
// * We need storage packets for the matrix states.
// * General routing options info?
//
// - Main difficulties:
// * have a good re-try strategy if a msg does not arrive.
// * handle peer availability. In forward mode: easy. In backward mode:
// difficult. We should wait, and send back the packet if possible.
// * robustness
// * security: avoid flooding, and message alteration.
//
2015-04-09 17:34:50 -04:00
// Data pipeline
// =============
//
// sendData()
// |
// +--> encrypt/sign ---> store in _pending_messages
//
// receiveTurtleData()
// |
// +-------------------------------------------------+
// tick() |
// | |
// +--> HandleLowLevelServiceItems() |
// | | |
// | +--> handleLowLevelServiceItem(item) <------------+
// | |
// | +--> handleIncomingTransactionAckItem()
// | |
// | +--> handleIncomingTransactionChunkItem()
// | |
// | +---> addDataChunk()
// | |
// | +---> push item to _incoming_items list
// |
// +--> handleIncoming()
// | |
// | +---> handleIncomingReceiptItem(GRouterSignedReceiptItem*)
// | | |
// | +---> handleIncomingDataItem(GRouterDataItem*) |
// | | |
// | +----------------------------+
// | |
// | |
// | [for US?] ----<Y>----------------+-----> verifySignedData()
// | | |
// | <N> +-----> notifyClient()
// | | |
// | | +-----> send Receipt item ---+
// | | |
// | +----> Store In _pending_messages |
// | |
// +--> routePendingObjects() |
// | | |
// | +--> locked_collectAvailablePeers()/locked_collectAvailableTunnels() |
// | | |
// | +--> sliceDataItem() |
// | | |
// | +--> locked_sendTransactionData() <-----------------------------------------------+
// | |
// | +--> mTurtle->sendTurtleData(virtual_pid,turtle_item) / sendItem()
// |
// +--> handleTunnels()
// | |
// | +---> mTurtle->stopMonitoringTunnels(hash) ;
// | +---> mTurtle->monitoringTunnels(hash) ;
// |
// +--> autoWash()
//
2014-03-17 16:56:06 -04:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////
2015-01-23 15:04:23 -05:00
# include <unistd.h>
2014-03-31 17:21:11 -04:00
# include <math.h>
2013-11-02 10:35:33 -04:00
# include "util/rsrandom.h"
2015-01-11 17:18:28 -05:00
# include "util/rsprint.h"
2015-03-28 13:23:52 -04:00
# include "util/rsmemory.h"
2013-11-02 10:35:33 -04:00
# include "serialiser/rsconfigitems.h"
2015-01-11 17:18:28 -05:00
# include "services/p3idservice.h"
# include "turtle/p3turtle.h"
2015-03-14 10:33:23 -04:00
# include "gxs/rsgixs.h"
2013-11-02 10:35:33 -04:00
# include "p3grouter.h"
# include "grouteritems.h"
2013-11-08 17:22:40 -05:00
# include "groutertypes.h"
2013-12-24 11:41:07 -05:00
# include "grouterclientservice.h"
2013-11-02 10:35:33 -04:00
2014-03-29 19:03:04 -04:00
/**********************/
2015-05-14 09:44:57 -04:00
//#define GROUTER_DEBUG
2014-03-29 19:03:04 -04:00
/**********************/
2014-03-29 10:18:05 -04:00
const std : : string p3GRouter : : SERVICE_INFO_APP_NAME = " Global Router " ;
2015-03-14 10:33:23 -04:00
p3GRouter : : p3GRouter ( p3ServiceControl * sc , RsGixs * is )
: p3Service ( ) , p3Config ( ) , mServiceControl ( sc ) , mGixs ( is ) , grMtx ( " GRouter " )
2013-11-02 10:35:33 -04:00
{
addSerialType ( new RsGRouterSerialiser ( ) ) ;
2013-11-05 16:15:26 -05:00
2014-04-07 17:36:43 -04:00
_last_autowash_time = 0 ;
_last_debug_output_time = 0 ;
_last_config_changed = 0 ;
2014-04-11 17:56:10 -04:00
_last_matrix_update_time = 0 ;
2014-04-21 08:39:30 -04:00
_debug_enabled = true ;
2014-04-07 17:36:43 -04:00
_random_salt = RSRandom : : random_u64 ( ) ;
2013-12-28 16:47:15 -05:00
_changed = false ;
2013-11-02 10:35:33 -04:00
}
int p3GRouter : : tick ( )
{
2015-04-09 17:34:50 -04:00
time_t now = time ( NULL ) ;
// Sort incoming service data
//
handleLowLevelServiceItems ( ) ;
// Handle high level global router data
//
handleIncoming ( ) ;
// Take each item in the list of pending messages and receipts. If the destination peer is available
// or if the tunnel is available, the item will be sent there.
//
routePendingObjects ( ) ;
// clean things up. Remove unused requests, old stuff etc.
autoWash ( ) ;
2013-11-02 10:35:33 -04:00
2015-01-11 17:18:28 -05:00
// Go through the list of active tunnel requests and pending objects to ask for new tunnels
// or close existing tunnel requests.
//
handleTunnels ( ) ;
2013-11-05 16:15:26 -05:00
2015-04-09 17:34:50 -04:00
// Update routing matrix
//
if ( now > _last_matrix_update_time + RS_GROUTER_MATRIX_UPDATE_PERIOD )
{
RsStackMutex mtx ( grMtx ) ;
2014-04-12 15:58:45 -04:00
2015-04-09 17:34:50 -04:00
_last_matrix_update_time = now ;
_routing_matrix . updateRoutingProbabilities ( ) ; // This should be locked.
2015-10-25 17:16:16 -04:00
_routing_matrix . cleanUp ( ) ; // This should be locked.
2015-04-09 17:34:50 -04:00
}
2013-11-02 10:35:33 -04:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
// Debug dump everything
//
if ( now > _last_debug_output_time + RS_GROUTER_DEBUG_OUTPUT_PERIOD )
{
_last_debug_output_time = now ;
if ( _debug_enabled )
debugDump ( ) ;
}
2014-03-29 19:03:04 -04:00
# endif
2013-12-28 16:47:15 -05:00
2015-04-09 17:34:50 -04:00
// If content has changed, save config, at most every RS_GROUTER_MIN_CONFIG_SAVE_PERIOD seconds appart
// Otherwise, always save at least every RS_GROUTER_MAX_CONFIG_SAVE_PERIOD seconds
//
if ( _changed & & now > _last_config_changed + RS_GROUTER_MIN_CONFIG_SAVE_PERIOD )
{
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
grouter_debug ( ) < < " p3GRouter::tick(): triggering config save. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-28 16:47:15 -05:00
2015-04-09 17:34:50 -04:00
_changed = false ;
_last_config_changed = now ;
IndicateConfigChanged ( ) ;
}
2013-12-28 16:47:15 -05:00
2015-04-09 17:34:50 -04:00
return 0 ;
2013-11-02 10:35:33 -04:00
}
RsSerialiser * p3GRouter : : setupSerialiser ( )
{
RsSerialiser * rss = new RsSerialiser ;
rss - > addSerialType ( new RsGRouterSerialiser ) ;
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
return rss ;
}
2015-01-11 17:18:28 -05:00
bool p3GRouter : : registerKey ( const RsGxsId & authentication_key , const GRouterServiceId & client_id , const std : : string & description )
2013-11-02 10:35:33 -04:00
{
2015-01-19 08:53:36 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2013-12-27 15:06:47 -05:00
2015-01-19 08:53:36 -05:00
if ( _registered_services . find ( client_id ) = = _registered_services . end ( ) )
{
2015-01-11 17:18:28 -05:00
std : : cerr < < __PRETTY_FUNCTION__ < < " : unable to register key " < < authentication_key < < " for client id " < < client_id < < " : client id is not known. " < < std : : endl ;
2015-01-19 08:53:36 -05:00
return false ;
}
2013-11-02 10:35:33 -04:00
2015-01-19 08:53:36 -05:00
GRouterPublishedKeyInfo info ;
info . service_id = client_id ;
2015-01-11 17:18:28 -05:00
info . authentication_key = authentication_key ;
info . description_string = description . substr ( 0 , 20 ) ;
2013-12-22 12:04:13 -05:00
2015-01-11 17:18:28 -05:00
Sha1CheckSum hash = makeTunnelHash ( authentication_key , client_id ) ;
2013-12-22 12:04:13 -05:00
2015-01-11 17:18:28 -05:00
_owned_key_ids [ hash ] = info ;
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
grouter_debug ( ) < < " Registered the following key: " < < std : : endl ;
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < " Auth GXS Id : " < < authentication_key < < std : : endl ;
2015-01-19 08:53:36 -05:00
grouter_debug ( ) < < " Client id : " < < std : : hex < < client_id < < std : : dec < < std : : endl ;
grouter_debug ( ) < < " Description : " < < info . description_string < < std : : endl ;
2015-12-07 22:39:45 -05:00
grouter_debug ( ) < < " Hash : " < < hash < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-11-02 10:35:33 -04:00
2015-01-19 08:53:36 -05:00
return true ;
2015-01-11 17:18:28 -05:00
}
bool p3GRouter : : unregisterKey ( const RsGxsId & key_id , const GRouterServiceId & sid )
{
2015-01-19 08:53:36 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2013-12-27 15:06:47 -05:00
2015-01-11 17:18:28 -05:00
Sha1CheckSum hash = makeTunnelHash ( key_id , sid ) ;
2013-12-22 12:04:13 -05:00
2015-01-11 17:18:28 -05:00
std : : map < Sha1CheckSum , GRouterPublishedKeyInfo > : : iterator it = _owned_key_ids . find ( hash ) ;
2013-12-22 12:04:13 -05:00
2015-01-11 17:18:28 -05:00
if ( it = = _owned_key_ids . end ( ) )
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
std : : cerr < < " p3GRouter::unregisterKey(): key " < < key_id < < " not found. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-01-11 17:18:28 -05:00
return false ;
}
2013-12-27 15:06:47 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < " p3GRouter::unregistered the following key: " < < std : : endl ;
grouter_debug ( ) < < " Key id : " < < key_id . toStdString ( ) < < std : : endl ;
grouter_debug ( ) < < " Client id : " < < std : : hex < < it - > second . service_id < < std : : dec < < std : : endl ;
grouter_debug ( ) < < " Description : " < < it - > second . description_string < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-22 12:04:13 -05:00
2015-01-11 17:18:28 -05:00
_owned_key_ids . erase ( it ) ;
2013-11-02 10:35:33 -04:00
2015-01-11 17:18:28 -05:00
return true ;
}
2015-04-09 17:34:50 -04:00
//===========================================================================================================================//
// Service data handling //
//===========================================================================================================================//
void p3GRouter : : handleLowLevelServiceItems ( )
{
// While messages read
//
RsItem * item = NULL ;
while ( NULL ! = ( item = recvItem ( ) ) )
2015-07-11 21:37:48 -04:00
{
RsGRouterTransactionItem * gtitem = dynamic_cast < RsGRouterTransactionItem * > ( item ) ;
if ( gtitem )
{
handleLowLevelServiceItem ( gtitem ) ;
}
else
{
delete ( item ) ;
}
}
2015-04-09 17:34:50 -04:00
}
void p3GRouter : : handleLowLevelServiceItem ( RsGRouterTransactionItem * item )
{
switch ( item - > PacketSubType ( ) )
{
2015-07-11 21:37:48 -04:00
case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN :
{
RsGRouterTransactionAcknItem * trans_ack_item = dynamic_cast < RsGRouterTransactionAcknItem * > ( item ) ;
if ( trans_ack_item )
{
handleLowLevelTransactionAckItem ( trans_ack_item ) ;
}
2015-04-09 17:34:50 -04:00
break ;
2015-07-11 21:37:48 -04:00
}
case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK :
{
RsGRouterTransactionChunkItem * chunk_item = dynamic_cast < RsGRouterTransactionChunkItem * > ( item ) ;
if ( chunk_item )
{
handleLowLevelTransactionChunkItem ( chunk_item ) ;
}
2015-04-09 17:34:50 -04:00
break ;
2015-07-11 21:37:48 -04:00
}
2015-04-09 17:34:50 -04:00
default :
std : : cerr < < " p3GRouter::handleIncoming: Unknown packet subtype " < < item - > PacketSubType ( ) < < std : : endl ;
}
delete item ;
}
2015-01-11 17:18:28 -05:00
//===========================================================================================================================//
// Turtle management //
//===========================================================================================================================//
2015-01-15 15:33:24 -05:00
bool p3GRouter : : handleTunnelRequest ( const RsFileHash & hash , const RsPeerId & /*peer_id*/ )
2015-01-11 17:18:28 -05:00
{
// tunnel request is answered according to the following rules:
// - we are the destination => always accept
// - we know the destination and have RCPT items to send back => always accept
// - we know the destination and have a route (according to matrix) => accept with high probability
// - we don't know the destination => accept with very low probability
2013-12-22 12:04:13 -05:00
2015-01-15 15:33:24 -05:00
if ( _owned_key_ids . find ( hash ) = = _owned_key_ids . end ( ) )
return false ;
2014-04-12 15:58:45 -04:00
# ifdef GROUTER_DEBUG
2015-01-22 09:33:19 -05:00
std : : cerr < < " p3GRouter::handleTunnelRequest(). Got req for hash " < < hash < < " , responding OK " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-01-19 08:53:36 -05:00
return true ;
2015-01-11 17:18:28 -05:00
}
2015-04-09 17:34:50 -04:00
void p3GRouter : : handleLowLevelTransactionChunkItem ( RsGRouterTransactionChunkItem * chunk_item )
2015-01-11 17:18:28 -05:00
{
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " item is a transaction item. " < < std : : endl ;
2014-04-12 15:58:45 -04:00
# endif
2013-12-27 15:06:47 -05:00
2015-04-12 17:43:52 -04:00
RsPeerId pid = chunk_item - > PeerId ( ) ;
2015-04-09 17:34:50 -04:00
RsGRouterAbstractMsgItem * generic_item = NULL ;
{
RS_STACK_MUTEX ( grMtx ) ;
2015-01-15 15:33:24 -05:00
2015-04-12 17:43:52 -04:00
generic_item = _incoming_data_pipes [ pid ] . addDataChunk ( dynamic_cast < RsGRouterTransactionChunkItem * > ( chunk_item - > duplicate ( ) ) ) ; // addDataChunk takes ownership over chunk_item
2015-04-09 17:34:50 -04:00
}
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
// send to client off-mutex
if ( generic_item = = NULL )
2015-01-15 15:33:24 -05:00
return ;
2015-04-09 17:34:50 -04:00
2015-05-14 09:44:57 -04:00
generic_item - > PeerId ( pid ) ;
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " transaction is finished. Passing newly created item to client. " < < std : : endl ;
std : : cerr < < " sending a ACK item " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-11-02 10:35:33 -04:00
2015-04-09 17:34:50 -04:00
RsGRouterTransactionAcknItem ackn_item ;
ackn_item . propagation_id = generic_item - > routing_id ;
2015-04-12 17:43:52 -04:00
locked_sendTransactionData ( pid , ackn_item ) ;
2015-01-15 15:33:24 -05:00
{
RS_STACK_MUTEX ( grMtx ) ;
2015-04-09 17:34:50 -04:00
_incoming_items . push_back ( generic_item ) ;
}
}
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
void p3GRouter : : handleLowLevelTransactionAckItem ( RsGRouterTransactionAcknItem * trans_ack_item )
{
# ifdef GROUTER_DEBUG
std : : cerr < < " item is a transaction ACK. " < < std : : endl ;
# endif
RS_STACK_MUTEX ( grMtx ) ;
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . find ( trans_ack_item - > propagation_id ) ;
2015-01-19 08:53:36 -05:00
2015-04-27 18:01:31 -04:00
if ( it ! = _pending_messages . end ( ) & & it - > second . data_status = = RS_GROUTER_DATA_STATUS_ONGOING )
2015-04-09 17:34:50 -04:00
{
it - > second . data_status = RS_GROUTER_DATA_STATUS_SENT ;
2015-04-20 17:24:22 -04:00
it - > second . last_sent_TS = time ( NULL ) ;
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " setting new status as sent/awaiting receipt. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-04-09 17:34:50 -04:00
}
2015-04-12 17:43:52 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
else
2015-04-12 17:43:52 -04:00
std : : cerr < < " Note: no routing ID corresponds to this ACK item. This probably corresponds to a signed receipt " < < std : : endl ;
# endif
2015-04-09 17:34:50 -04:00
}
2013-12-22 12:04:13 -05:00
2015-04-09 17:34:50 -04:00
void p3GRouter : : receiveTurtleData ( RsTurtleGenericTunnelItem * gitem , const RsFileHash & hash , const RsPeerId & virtual_peer_id , RsTurtleGenericTunnelItem : : Direction direction )
{
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " p3GRouter::receiveTurtleData() " < < std : : endl ;
std : : cerr < < " Received data for hash : " < < hash < < std : : endl ;
std : : cerr < < " Virtual peer id : " < < virtual_peer_id < < std : : endl ;
std : : cerr < < " Direction : " < < direction < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
// turtle data is received.
// This function
// - possibly packs multi-item blocks back together
// - converts it into a grouter generic item (by deserialising it)
RsTurtleGenericDataItem * item = dynamic_cast < RsTurtleGenericDataItem * > ( gitem ) ;
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
if ( item = = NULL )
2015-01-19 08:53:36 -05:00
{
2015-04-09 17:34:50 -04:00
std : : cerr < < " ERROR: item is not a data item. That is an error. " < < std : : endl ;
return ;
}
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " data size : " < < item - > data_size < < std : : endl ;
std : : cerr < < " data bytes : " < < RsDirUtil : : sha1sum ( ( unsigned char * ) item - > data_bytes , item - > data_size ) < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
// Items come out of the pipe in order. We need to recover all chunks before we de-serialise the content and have it handled by handleIncoming()
2013-12-22 12:04:13 -05:00
2015-04-09 17:34:50 -04:00
RsItem * itm = RsGRouterSerialiser ( ) . deserialise ( item - > data_bytes , & item - > data_size ) ;
2013-12-22 12:04:13 -05:00
2015-12-07 10:02:04 -05:00
if ( itm = = NULL )
{
std : : cerr < < " (EE) p3GRouter::receiveTurtleData(): cannot de-serialise data. Somthing wrong in the format. Item data (size= " < < item - > data_size < < " ): " < < RsUtil : : BinToHex ( ( char * ) item - > data_bytes , item - > data_size ) < < std : : endl ;
return ;
}
2015-04-09 17:34:50 -04:00
itm - > PeerId ( virtual_peer_id ) ;
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
// At this point we can have either a transaction chunk, or a transaction ACK.
// We handle them both here
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
RsGRouterTransactionChunkItem * chunk_item = dynamic_cast < RsGRouterTransactionChunkItem * > ( itm ) ;
RsGRouterTransactionAcknItem * trans_ack_item = NULL ;
2015-01-20 08:04:10 -05:00
2015-04-09 17:34:50 -04:00
if ( chunk_item ! = NULL )
handleLowLevelTransactionChunkItem ( chunk_item ) ;
else if ( NULL ! = ( trans_ack_item = dynamic_cast < RsGRouterTransactionAcknItem * > ( itm ) ) )
handleLowLevelTransactionAckItem ( trans_ack_item ) ;
else
{
std : : cerr < < " ERROR: cannot deserialise turtle item. " < < std : : endl ;
if ( itm )
delete itm ;
2015-01-15 15:33:24 -05:00
}
}
void GRouterTunnelInfo : : removeVirtualPeer ( const TurtleVirtualPeerId & vpid )
{
2015-04-09 17:34:50 -04:00
std : : set < TurtleVirtualPeerId , RsGRouterTransactionChunkItem * > : : iterator it = virtual_peers . find ( vpid ) ;
2015-01-15 15:33:24 -05:00
if ( it = = virtual_peers . end ( ) )
{
std : : cerr < < " ERROR: removing a virtual peer that does not exist. This is an error! " < < std : : endl ;
return ;
}
virtual_peers . erase ( it ) ;
}
void GRouterTunnelInfo : : addVirtualPeer ( const TurtleVirtualPeerId & vpid )
{
2015-04-09 17:34:50 -04:00
if ( virtual_peers . find ( vpid ) ! = virtual_peers . end ( ) )
2015-01-15 15:33:24 -05:00
std : : cerr < < " ERROR: adding a virtual peer that already exist. This is an error! " < < std : : endl ;
2013-12-22 12:04:13 -05:00
2015-04-09 17:34:50 -04:00
virtual_peers . insert ( vpid ) ;
2013-12-22 12:04:13 -05:00
2015-01-15 15:33:24 -05:00
time_t now = time ( NULL ) ;
if ( first_tunnel_ok_TS = = 0 ) first_tunnel_ok_TS = now ;
2015-01-19 08:53:36 -05:00
last_tunnel_ok_TS = now ;
2015-01-15 15:33:24 -05:00
}
2015-04-19 11:04:24 -04:00
2015-04-09 17:34:50 -04:00
RsGRouterAbstractMsgItem * GRouterDataInfo : : addDataChunk ( RsGRouterTransactionChunkItem * chunk )
2015-01-15 15:33:24 -05:00
{
2015-04-18 15:59:27 -04:00
last_activity_TS = time ( NULL ) ;
2015-04-19 11:04:24 -04:00
// perform some checking
if ( chunk - > total_size > MAX_GROUTER_DATA_SIZE + 10000 | | chunk - > chunk_size > chunk - > total_size | | chunk - > chunk_start > = chunk - > total_size )
{
std : : cerr < < " ERROR: chunk size is unconsistent, or too large: size= " < < chunk - > chunk_size < < " , start= " < < chunk - > chunk_start < < " , total size= " < < chunk - > total_size < < " . Chunk will be dropped. Data pipe will be reset. " < < std : : endl ;
clear ( ) ;
delete chunk ;
return NULL ;
}
// now add that chunk.
2015-04-09 17:34:50 -04:00
if ( incoming_data_buffer = = NULL )
2015-01-15 15:33:24 -05:00
{
if ( chunk - > chunk_start ! = 0 )
{
std : : cerr < < " ERROR: chunk numbering is wrong. First chunk is not starting at 0. Dropping. " < < std : : endl ;
delete chunk ;
return NULL ;
}
2015-04-09 17:34:50 -04:00
incoming_data_buffer = chunk ;
2015-01-15 15:33:24 -05:00
}
else
{
2015-04-09 17:34:50 -04:00
if ( incoming_data_buffer - > chunk_size ! = chunk - > chunk_start | | incoming_data_buffer - > total_size ! = chunk - > total_size )
2015-01-15 15:33:24 -05:00
{
std : : cerr < < " ERROR: chunk numbering is wrong. Dropping. " < < std : : endl ;
delete chunk ;
2015-04-09 17:34:50 -04:00
delete incoming_data_buffer ;
2015-08-21 20:45:41 -04:00
incoming_data_buffer = NULL ;
return NULL ;
2015-01-15 15:33:24 -05:00
}
2015-04-09 17:34:50 -04:00
incoming_data_buffer - > chunk_data = ( uint8_t * ) realloc ( ( uint8_t * ) incoming_data_buffer - > chunk_data , incoming_data_buffer - > chunk_size + chunk - > chunk_size ) ;
memcpy ( & incoming_data_buffer - > chunk_data [ incoming_data_buffer - > chunk_size ] , chunk - > chunk_data , chunk - > chunk_size ) ;
incoming_data_buffer - > chunk_size + = chunk - > chunk_size ;
2015-01-15 15:33:24 -05:00
delete chunk ;
}
// if finished, return it.
2015-04-09 17:34:50 -04:00
if ( incoming_data_buffer - > total_size = = incoming_data_buffer - > chunk_size )
2015-01-15 15:33:24 -05:00
{
2015-04-09 17:34:50 -04:00
RsItem * data_item = RsGRouterSerialiser ( ) . deserialise ( incoming_data_buffer - > chunk_data , & incoming_data_buffer - > chunk_size ) ;
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
incoming_data_buffer - > chunk_data = NULL ;
delete incoming_data_buffer ;
incoming_data_buffer = NULL ;
2015-01-15 15:33:24 -05:00
2015-01-19 08:53:36 -05:00
return dynamic_cast < RsGRouterAbstractMsgItem * > ( data_item ) ;
2015-01-15 15:33:24 -05:00
}
else
return NULL ;
2015-01-11 17:18:28 -05:00
}
2015-01-15 15:33:24 -05:00
2015-01-11 17:18:28 -05:00
void p3GRouter : : addVirtualPeer ( const TurtleFileHash & hash , const TurtleVirtualPeerId & virtual_peer_id , RsTurtleGenericTunnelItem : : Direction dir )
{
2015-01-19 08:53:36 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-15 15:33:24 -05:00
2015-01-11 17:18:28 -05:00
// Server side tunnels. This is incoming data. Nothing to do.
2013-12-22 12:04:13 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
std : : cerr < < " p3GRouter::addVirtualPeer(). Received vpid " < < virtual_peer_id < < " for hash " < < hash < < " , direction= " < < dir < < std : : endl ;
2015-01-19 08:53:36 -05:00
std : : cerr < < " direction = " < < dir < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-22 12:04:13 -05:00
2015-01-19 08:53:36 -05:00
// client side. We set the tunnel flags to READY.
2014-03-29 10:18:05 -04:00
2015-01-11 17:18:28 -05:00
if ( dir = = RsTurtleGenericTunnelItem : : DIRECTION_SERVER )
{
2015-01-19 08:53:36 -05:00
bool found = false ;
2013-11-02 10:35:33 -04:00
2015-01-19 08:53:36 -05:00
// linear search. Bad, but not really a problem. New virtual peers come quite rarely.
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it ( _pending_messages . begin ( ) ) ; it ! = _pending_messages . end ( ) ; + + it )
if ( it - > second . tunnel_hash = = hash )
{
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
std : : cerr < < " setting tunnel state to READY. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-01-19 08:53:36 -05:00
it - > second . tunnel_status = RS_GROUTER_TUNNEL_STATUS_READY ;
found = true ;
2015-01-23 07:13:13 -05:00
// don't break here, because we might send multiple items though the same tunnel.
2015-01-19 08:53:36 -05:00
}
2014-03-29 10:18:05 -04:00
2015-01-19 08:53:36 -05:00
if ( ! found )
{
std : : cerr < < " ERROR: cannot find corresponding pending message. " < < std : : endl ;
return ;
}
}
2015-01-11 17:18:28 -05:00
if ( dir = = RsTurtleGenericTunnelItem : : DIRECTION_CLIENT )
{
}
2013-12-22 12:04:13 -05:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
std : : cerr < < " adding VPID. " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2013-12-22 12:04:13 -05:00
2015-04-09 17:34:50 -04:00
_tunnels [ hash ] . addVirtualPeer ( virtual_peer_id ) ;
2014-03-29 10:18:05 -04:00
}
2015-04-09 17:34:50 -04:00
2015-01-11 17:18:28 -05:00
void p3GRouter : : removeVirtualPeer ( const TurtleFileHash & hash , const TurtleVirtualPeerId & virtual_peer_id )
{
2015-04-09 17:34:50 -04:00
RS_STACK_MUTEX ( grMtx ) ;
2013-12-22 12:04:13 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " p3GRouter::removeVirtualPeer(). Removing vpid " < < virtual_peer_id < < " for hash " < < hash < < std : : endl ;
2015-01-15 15:33:24 -05:00
std : : cerr < < " removing VPID. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2014-03-29 10:18:05 -04:00
2015-01-15 15:33:24 -05:00
// make sure the VPID exists.
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
std : : map < TurtleFileHash , GRouterTunnelInfo > : : iterator it = _tunnels . find ( hash ) ;
2013-12-22 12:04:13 -05:00
2015-04-09 17:34:50 -04:00
if ( it = = _tunnels . end ( ) )
2015-01-15 15:33:24 -05:00
{
2015-01-22 04:50:44 -05:00
std : : cerr < < " no virtual peers at all for this hash: " < < hash < < " ! This is a consistency error. " < < std : : endl ;
2015-01-15 15:33:24 -05:00
return ;
}
it - > second . removeVirtualPeer ( virtual_peer_id ) ;
2015-01-19 08:53:36 -05:00
2015-04-12 17:43:52 -04:00
# ifdef GROUTER_DEBUG
std : : cerr < < " setting tunnel status in pending message. " < < std : : endl ;
# endif
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it2 ( _pending_messages . begin ( ) ) ; it2 ! = _pending_messages . end ( ) ; + + it2 )
if ( it2 - > second . tunnel_hash = = hash & & it - > second . virtual_peers . empty ( ) )
it2 - > second . tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ;
2015-06-14 08:22:49 -04:00
if ( it - > second . virtual_peers . empty ( ) )
{
# ifdef GROUTER_DEBUG
std : : cerr < < " last virtual peer removed. Also deleting hash entry. " < < std : : endl ;
# endif
_tunnels . erase ( it ) ;
}
2014-03-29 10:18:05 -04:00
}
2015-01-11 17:18:28 -05:00
void p3GRouter : : connectToTurtleRouter ( p3turtle * pt )
2014-03-29 10:18:05 -04:00
{
2015-01-11 17:18:28 -05:00
mTurtle = pt ;
2015-01-19 08:53:36 -05:00
pt - > registerTunnelService ( this ) ;
2015-01-11 17:18:28 -05:00
}
2014-03-31 17:21:11 -04:00
2015-01-11 17:18:28 -05:00
//===========================================================================================================================//
// Tunnel management //
//===========================================================================================================================//
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
class item_comparator_001
2014-04-12 15:58:45 -04:00
{
2015-04-09 17:34:50 -04:00
public :
template < typename N , class T >
bool operator ( ) ( const std : : pair < N , T > & p1 , const std : : pair < N , T > & p2 ) const
{
return p1 . first < p2 . first ;
}
} ;
2014-03-29 10:18:05 -04:00
2015-01-11 17:18:28 -05:00
void p3GRouter : : handleTunnels ( )
2014-03-29 10:18:05 -04:00
{
2015-04-21 15:02:14 -04:00
// This function is responsible for asking for tunnels, and removing requests from the turtle router.
2015-04-09 17:34:50 -04:00
// To remove the unnecessary TR activity generated by multiple peers trying to send the same message,
// only peers which haven't passed on any data to direct friends, or for which the best friends are not online
// will be allowed to monitor tunnels.
2015-01-11 17:18:28 -05:00
// Go through the list of pending messages
2015-04-21 15:02:14 -04:00
// - if tunnels are pending for too long => remove from turtle
2015-01-11 17:18:28 -05:00
// - if item is waiting for too long => tunnels are waitin
2014-03-31 17:21:11 -04:00
2015-01-11 17:18:28 -05:00
// We need a priority queue of items to handle, starting from the most ancient items, with a delay that varies with
// how much time they have been waiting. When a turtle slot it freed, we take the next item in the queue and
// activate tunnel handling for it.
2014-03-31 17:21:11 -04:00
2015-01-11 17:18:28 -05:00
// possible pending message status:
// - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_READY : tunnel is ready. Waiting a few seconds to be used (this is to allow multiple tunnels to come).
// - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_PENDING : tunnel was asked.
// - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_UNMANAGED: not tunnel managed at the moment.
2014-03-31 17:21:11 -04:00
2015-01-11 17:18:28 -05:00
// 1 - make a priority list of messages to ask tunnels for
2014-04-11 17:56:10 -04:00
2015-04-21 15:02:14 -04:00
// Compute the priority of pending messages, according to the number of attempts and how far in the past they have been tried for the last time.
2015-01-11 17:18:28 -05:00
// Delay after which a message is re-sent, depending on the number of attempts already made.
2014-04-11 17:56:10 -04:00
2015-04-20 17:24:22 -04:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-15 15:33:24 -05:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-20 17:24:22 -04:00
if ( ! _pending_messages . empty ( ) )
{
grouter_debug ( ) < < " p3GRouter::handleTunnels() " < < std : : endl ;
grouter_debug ( ) < < " building priority list of items to send... " < < std : : endl ;
}
2015-01-22 04:50:44 -05:00
# endif
2014-03-29 10:18:05 -04:00
2015-01-11 17:18:28 -05:00
time_t now = time ( NULL ) ;
std : : vector < std : : pair < int , GRouterRoutingInfo * > > priority_list ;
2014-03-31 17:21:11 -04:00
2015-01-11 17:18:28 -05:00
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . begin ( ) ; it ! = _pending_messages . end ( ) ; + + it )
{
2014-04-11 17:56:10 -04:00
# ifdef GROUTER_DEBUG
2015-01-22 09:33:19 -05:00
grouter_debug ( ) < < " " < < std : : hex < < it - > first < < std : : dec
2015-04-18 15:59:27 -04:00
< < " , data_status= " < < it - > second . data_status < < " , tunnel_status= " < < it - > second . tunnel_status
< < " , last received: " < < now - it - > second . received_time_TS < < " (secs ago) "
< < " , last TR: " < < now - it - > second . last_tunnel_request_TS < < " (secs ago) "
2015-04-20 17:24:22 -04:00
< < " , last sent: " < < now - it - > second . last_sent_TS < < " (secs ago) " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
if ( it - > second . data_status = = RS_GROUTER_DATA_STATUS_PENDING & & ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_TUNNELS ) )
2015-01-11 17:18:28 -05:00
{
2015-01-22 09:33:19 -05:00
if ( it - > second . tunnel_status = = RS_GROUTER_TUNNEL_STATUS_UNMANAGED & & it - > second . last_tunnel_request_TS + MAX_TUNNEL_UNMANAGED_TIME < now )
2015-01-11 17:18:28 -05:00
{
uint32_t item_delay = now - it - > second . last_tunnel_request_TS ;
2015-04-20 17:24:22 -04:00
int item_priority = item_delay ;
2013-11-02 10:35:33 -04:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-01-20 08:04:10 -05:00
grouter_debug ( ) < < " delay= " < < item_delay < < " attempts= " < < it - > second . sending_attempts < < " , priority= " < < item_priority < < std : : endl ;
2014-04-11 17:56:10 -04:00
# endif
2015-01-11 17:18:28 -05:00
if ( item_priority > 0 )
priority_list . push_back ( std : : make_pair ( item_priority , & it - > second ) ) ;
}
else if ( it - > second . tunnel_status = = RS_GROUTER_TUNNEL_STATUS_PENDING & & it - > second . last_tunnel_request_TS + MAX_TUNNEL_WAIT_TIME < now )
{
mTurtle - > stopMonitoringTunnels ( it - > second . tunnel_hash ) ;
2014-04-11 17:56:10 -04:00
2015-01-11 17:18:28 -05:00
it - > second . tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ;
2014-04-11 17:56:10 -04:00
2014-03-31 17:21:11 -04:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
grouter_debug ( ) < < " stopping tunnels for this message. " < < std : : endl ; ;
2014-03-31 17:21:11 -04:00
# endif
2015-01-11 17:18:28 -05:00
}
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
else if ( it - > second . tunnel_status = = RS_GROUTER_TUNNEL_STATUS_READY )
grouter_debug ( ) < < " tunnel is available. " < < std : : endl ;
2015-01-11 17:18:28 -05:00
else
grouter_debug ( ) < < " doing nothing. " < < std : : endl ;
2014-03-31 17:21:11 -04:00
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-01-11 17:18:28 -05:00
}
2015-04-20 17:24:22 -04:00
else
2015-04-09 17:34:50 -04:00
{
2015-01-23 07:13:13 -05:00
# ifdef GROUTER_DEBUG
std : : cerr < < " closing pending tunnels. " < < std : : endl ;
# endif
mTurtle - > stopMonitoringTunnels ( it - > second . tunnel_hash ) ;
2015-04-18 15:59:27 -04:00
it - > second . tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ;
2015-04-09 17:34:50 -04:00
}
2015-04-12 17:43:52 -04:00
2015-04-20 17:24:22 -04:00
// also check that all tunnels are actually active, to remove any old dead tunnels
//
// if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_READY)
// {
// std::map<TurtleFileHash,GRouterTunnelInfo>::iterator it2 = _tunnels.find(it->second.tunnel_hash) ;
//
// if(it2 == _tunnels.end() || it2->second.virtual_peers.empty()) ;
// {
// std::cerr << " re-setting tunnel status to PENDING, as no tunnels are actually present." << std::endl;
// it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ;
// }
// }
2015-01-11 17:18:28 -05:00
}
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
if ( ! priority_list . empty ( ) )
grouter_debug ( ) < < " sorting... " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2014-01-03 17:41:20 -05:00
2015-04-12 17:43:52 -04:00
2015-04-09 17:34:50 -04:00
std : : sort ( priority_list . begin ( ) , priority_list . end ( ) , item_comparator_001 ( ) ) ;
2014-01-03 17:41:20 -05:00
2015-01-11 17:18:28 -05:00
// take tunnels from item priority list, and enable tunnel handling, while respecting max number of active tunnels limit
2013-11-02 10:35:33 -04:00
2015-01-11 17:18:28 -05:00
for ( uint32_t i = 0 ; i < priority_list . size ( ) ; + + i )
{
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-18 15:59:27 -04:00
grouter_debug ( ) < < " asking tunnel management for msg= " < < priority_list [ i ] . second - > data_item - > routing_id < < " hash= " < < priority_list [ i ] . second - > tunnel_hash < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2013-11-02 10:35:33 -04:00
2015-01-23 14:28:10 -05:00
mTurtle - > monitorTunnels ( priority_list [ i ] . second - > tunnel_hash , this , false ) ;
2015-01-11 17:18:28 -05:00
priority_list [ i ] . second - > tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ;
priority_list [ i ] . second - > last_tunnel_request_TS = now ;
2015-04-20 17:24:22 -04:00
priority_list [ i ] . second - > sending_attempts + + ;
2015-01-11 17:18:28 -05:00
}
2013-11-02 10:35:33 -04:00
}
2015-01-11 17:18:28 -05:00
void p3GRouter : : routePendingObjects ( )
2013-11-02 10:35:33 -04:00
{
2015-04-09 17:34:50 -04:00
// Go throught he list of pending messages. For those with a peer ready, send the message to that peer.
// The peer might be:
// - a virtual peer id that actually is a tunnel
// - a real friend node
// Tunnels and friends will used whenever available. Of course this might cause a message to arrive multiple times, but we
// don't really care since the GR takes care of duplicates already.
//
// Which tunnels are available is handled by handleTunnels()
//
2013-11-02 10:35:33 -04:00
2015-01-11 17:18:28 -05:00
time_t now = time ( NULL ) ;
2014-03-29 10:18:05 -04:00
2015-01-23 07:13:13 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-01-22 09:33:19 -05:00
if ( ! _pending_messages . empty ( ) )
std : : cerr < < " p3GRouter::routePendingObjects() " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-26 15:10:46 -04:00
bool pending_messages_changed = false ;
2013-11-02 10:35:33 -04:00
2015-04-09 17:34:50 -04:00
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . begin ( ) ; it ! = _pending_messages . end ( ) ; + + it )
{
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " message " < < std : : hex < < it - > first < < std : : dec < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-04-09 17:34:50 -04:00
if ( it - > second . data_status = = RS_GROUTER_DATA_STATUS_PENDING )
2015-04-26 15:10:46 -04:00
{
// Look for tunnels and friends where to send the data. Send to both.
2013-11-05 16:15:26 -05:00
2015-04-26 15:10:46 -04:00
std : : list < RsPeerId > peers ;
2013-12-22 12:04:13 -05:00
2015-04-26 15:10:46 -04:00
if ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_TUNNELS )
locked_collectAvailableTunnels ( it - > second . tunnel_hash , peers ) ;
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
// For now, disable friends. We'll first check that the good old tunnel system works as before.
2015-04-12 17:43:52 -04:00
2015-04-26 15:10:46 -04:00
if ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_FRIENDS )
locked_collectAvailableFriends ( it - > second . data_item - > destination_key , peers , it - > second . incoming_routes . ids , it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_IS_ORIGIN ) ;
2015-04-17 17:37:26 -04:00
2015-04-26 15:10:46 -04:00
if ( peers . empty ( ) )
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " no direct friends available " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
if ( it - > second . received_time_TS + DIRECT_FRIEND_TRY_DELAY < now & & ! ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_TUNNELS ) )
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " enabling tunnels for this message. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-26 15:10:46 -04:00
it - > second . routing_flags | = GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_TUNNELS ;
}
continue ;
2015-01-20 08:04:10 -05:00
}
2014-04-12 15:58:45 -04:00
2015-04-26 15:10:46 -04:00
// slice the data appropriately and send.
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
std : : list < RsGRouterTransactionChunkItem * > chunks ;
sliceDataItem ( it - > second . data_item , chunks ) ;
2015-04-09 17:34:50 -04:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
if ( ! peers . empty ( ) )
std : : cerr < < " sending to peers: " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-26 15:10:46 -04:00
for ( std : : list < RsPeerId > : : const_iterator itpid ( peers . begin ( ) ) ; itpid ! = peers . end ( ) ; + + itpid )
for ( std : : list < RsGRouterTransactionChunkItem * > : : const_iterator it2 ( chunks . begin ( ) ) ; it2 ! = chunks . end ( ) ; + + it2 )
locked_sendTransactionData ( * itpid , * ( * it2 ) ) ;
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
// delete temporary items
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
for ( std : : list < RsGRouterTransactionChunkItem * > : : const_iterator cit = chunks . begin ( ) ; cit ! = chunks . end ( ) ; + + cit )
delete * cit ;
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
// change item state in waiting list
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
it - > second . data_status = RS_GROUTER_DATA_STATUS_ONGOING ;
it - > second . data_transaction_TS = now ;
pending_messages_changed = true ;
}
2015-04-12 17:43:52 -04:00
else if ( it - > second . data_status = = RS_GROUTER_DATA_STATUS_ONGOING & & now > MAX_TRANSACTION_ACK_WAITING_TIME + it - > second . data_transaction_TS )
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-12 17:43:52 -04:00
std : : cerr < < " waited too long for this transation. Switching back to PENDING. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2014-04-11 17:56:10 -04:00
2015-04-12 17:43:52 -04:00
it - > second . data_status = RS_GROUTER_DATA_STATUS_PENDING ;
}
2015-04-20 17:24:22 -04:00
else if ( it - > second . data_status = = RS_GROUTER_DATA_STATUS_SENT )
{
2015-04-26 15:10:46 -04:00
if ( ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_IS_ORIGIN ) & & it - > second . last_sent_TS + MAX_DELAY_FOR_RESEND < now )
{
2015-04-20 17:24:22 -04:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " item was not received. Re-setting status to PENDING " < < std : : endl ;
2015-04-20 17:24:22 -04:00
# endif
2015-04-26 15:10:46 -04:00
it - > second . data_status = RS_GROUTER_DATA_STATUS_PENDING ;
}
else
{
2015-04-20 17:24:22 -04:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " item was sent. Desactivating tunnels. " < < std : : endl ;
2015-04-20 17:24:22 -04:00
# endif
2015-04-26 15:10:46 -04:00
it - > second . routing_flags & = ~ GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_TUNNELS ;
}
2015-04-20 17:24:22 -04:00
}
2015-04-26 15:10:46 -04:00
// We treat this case apart, so as to make sure that receipt items are always forwarded wen possible even if the data_status
// is not set correctly.
if ( it - > second . receipt_item ! = NULL & & ! it - > second . incoming_routes . ids . empty ( ) )
2015-04-12 17:43:52 -04:00
{
// send the receipt through all incoming routes, as soon as it gets delivered.
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-12 17:43:52 -04:00
std : : cerr < < " receipt should be sent back. Trying all incoming routes... " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-12 17:43:52 -04:00
std : : list < RsGRouterTransactionChunkItem * > chunks ;
2015-04-17 17:37:26 -04:00
for ( std : : set < RsPeerId > : : iterator it2 = it - > second . incoming_routes . ids . begin ( ) ; it2 ! = it - > second . incoming_routes . ids . end ( ) ; )
2015-04-18 15:59:27 -04:00
if ( mServiceControl - > isPeerConnected ( getServiceInfo ( ) . mServiceType , * it2 ) | | mTurtle - > isTurtlePeer ( * it2 ) )
2015-04-12 17:43:52 -04:00
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-12 17:43:52 -04:00
std : : cerr < < " sending receipt back to " < < * it2 < < " which is online. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-26 15:10:46 -04:00
if ( chunks . empty ( ) )
sliceDataItem ( it - > second . receipt_item , chunks ) ;
2015-04-12 17:43:52 -04:00
for ( std : : list < RsGRouterTransactionChunkItem * > : : const_iterator it3 ( chunks . begin ( ) ) ; it3 ! = chunks . end ( ) ; + + it3 )
locked_sendTransactionData ( * it2 , * ( * it3 ) ) ;
// then remove from the set.
2015-04-17 17:37:26 -04:00
std : : set < RsPeerId > : : iterator it2tmp = it2 ;
2015-04-12 17:43:52 -04:00
+ + it2tmp ;
it - > second . incoming_routes . ids . erase ( it2 ) ;
it2 = it2tmp ;
2015-04-26 15:10:46 -04:00
pending_messages_changed = true ;
2015-04-12 17:43:52 -04:00
}
else
+ + it2 ;
for ( std : : list < RsGRouterTransactionChunkItem * > : : const_iterator cit = chunks . begin ( ) ; cit ! = chunks . end ( ) ; + + cit )
delete * cit ;
// Because signed receipts are small items, we take the bet that if the item could be sent, then it was received.
// otherwise, we should mark that incomng route as being handled, wait for the ACK and deal with it by updating
// it->second.data_status at that time.
if ( it - > second . incoming_routes . ids . empty ( ) )
it - > second . data_status = RS_GROUTER_DATA_STATUS_DONE ;
}
2015-04-09 17:34:50 -04:00
}
2015-04-26 15:10:46 -04:00
if ( pending_messages_changed )
IndicateConfigChanged ( ) ;
2015-04-09 17:34:50 -04:00
}
2015-04-17 17:37:26 -04:00
void p3GRouter : : locked_collectAvailableFriends ( const GRouterKeyId & gxs_id , std : : list < RsPeerId > & friend_peers , const std : : set < RsPeerId > & incoming_routes , bool is_origin )
2015-04-09 17:34:50 -04:00
{
// The strategy is the following:
// if origin
// send to multiple neighbors : best and random
2015-04-21 15:02:14 -04:00
// else
2015-04-09 17:34:50 -04:00
// send to a single "best" neighbor (determined by threshold over routing probability),
std : : set < RsPeerId > ids ;
mServiceControl - > getPeersConnected ( getServiceInfo ( ) . mServiceType , ids ) ;
std : : vector < float > probas ;
std : : vector < RsPeerId > tmp_peers ;
2015-04-17 17:37:26 -04:00
// remove previous peers
2015-04-09 17:34:50 -04:00
for ( std : : set < RsPeerId > : : const_iterator it ( ids . begin ( ) ) ; it ! = ids . end ( ) ; + + it )
2015-04-17 17:37:26 -04:00
if ( incoming_routes . find ( * it ) = = incoming_routes . end ( ) )
tmp_peers . push_back ( * it ) ;
if ( tmp_peers . empty ( ) )
return ;
2015-04-09 17:34:50 -04:00
_routing_matrix . computeRoutingProbabilities ( gxs_id , tmp_peers , probas ) ;
2014-03-29 10:18:05 -04:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " locked_getAvailableFriends() " < < std : : endl ;
std : : cerr < < " getting connected friends, computing routing probabilities " < < std : : endl ;
2015-04-17 17:37:26 -04:00
for ( uint32_t i = 0 ; i < tmp_peers . size ( ) ; + + i )
2015-04-09 17:34:50 -04:00
std : : cerr < < " " < < tmp_peers [ i ] < < " , probability: " < < probas [ i ] < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-09 17:34:50 -04:00
uint32_t max_count = is_origin ? 3 : 1 ;
float probability_threshold = is_origin ? 0.0 : 0.5 ;
2014-04-11 17:56:10 -04:00
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
std : : cerr < < " position at origin: " < < is_origin < < " => mac_count= " < < max_count < < " , proba threshold= " < < probability_threshold < < std : : endl ;
# endif
2015-04-17 17:37:26 -04:00
2015-04-09 17:34:50 -04:00
std : : vector < std : : pair < float , RsPeerId > > mypairs ;
for ( uint32_t i = 0 ; i < tmp_peers . size ( ) ; + + i )
mypairs . push_back ( std : : make_pair ( probas [ i ] , tmp_peers [ i ] ) ) ;
// now sort them up
std : : sort ( mypairs . begin ( ) , mypairs . end ( ) , item_comparator_001 ( ) ) ;
// take the max_count peers that are still above min_probability
uint32_t n = 0 ;
for ( std : : vector < std : : pair < float , RsPeerId > > : : const_reverse_iterator it = mypairs . rbegin ( ) ; it ! = mypairs . rend ( ) & & n < max_count ; + + it )
if ( ( * it ) . first > = probability_threshold )
2015-04-17 17:37:26 -04:00
{
2015-04-09 17:34:50 -04:00
friend_peers . push_back ( ( * it ) . second ) , + + n ;
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-17 17:37:26 -04:00
std : : cerr < < " keeping " < < ( * it ) . second < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-17 17:37:26 -04:00
if ( ! is_origin ) // only collect one peer if we're not at origin.
break ;
}
2015-04-09 17:34:50 -04:00
}
void p3GRouter : : locked_collectAvailableTunnels ( const TurtleFileHash & hash , std : : list < RsPeerId > & tunnel_peers )
{
time_t now = time ( NULL ) ;
// Now go through available virtual peers. Select the ones that are interesting, and set them as potential destinations.
std : : map < TurtleFileHash , GRouterTunnelInfo > : : const_iterator vpit = _tunnels . find ( hash ) ;
if ( vpit = = _tunnels . end ( ) )
return ;
if ( vpit - > second . virtual_peers . empty ( ) )
{
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " no peers available. Cannot send!! " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-09 17:34:50 -04:00
return ;
}
if ( vpit - > second . last_tunnel_ok_TS + TUNNEL_OK_WAIT_TIME > now )
{
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " . Still waiting delay (stabilisation). " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-09 17:34:50 -04:00
return ;
}
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
// for now, just take one. But in the future, we will need some policy to temporarily store objects at proxy peers, etc.
2015-01-19 08:53:36 -05:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " " < < vpit - > second . virtual_peers . size ( ) < < " virtual peers available. " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-09 17:34:50 -04:00
TurtleVirtualPeerId vpid = * ( vpit - > second . virtual_peers . begin ( ) ) ;
2015-01-19 08:53:36 -05:00
2015-04-09 17:34:50 -04:00
tunnel_peers . push_back ( vpid ) ;
}
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
bool p3GRouter : : locked_sendTransactionData ( const RsPeerId & pid , const RsGRouterTransactionItem & trans_item )
{
if ( mTurtle - > isTurtlePeer ( pid ) )
{
2015-01-23 07:13:13 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " sending to tunnel vpid " < < pid < < std : : endl ;
2015-01-23 07:13:13 -05:00
# endif
2015-04-09 17:34:50 -04:00
uint32_t turtle_data_size = trans_item . serial_size ( ) ;
uint8_t * turtle_data = ( uint8_t * ) malloc ( turtle_data_size ) ;
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
if ( turtle_data = = NULL )
{
std : : cerr < < " ERROR: Cannot allocate turtle data memory for size " < < turtle_data_size < < std : : endl ;
return false ;
}
if ( ! trans_item . serialise ( turtle_data , turtle_data_size ) )
{
std : : cerr < < " ERROR: cannot serialise RsGRouterTransactionChunkItem. " < < std : : endl ;
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
free ( turtle_data ) ;
return false ;
}
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
RsTurtleGenericDataItem * turtle_item = new RsTurtleGenericDataItem ;
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
turtle_item - > data_size = turtle_data_size ;
turtle_item - > data_bytes = turtle_data ;
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
# ifdef GROUTER_DEBUG
std : : cerr < < " sending to vpid " < < pid < < std : : endl ;
# endif
mTurtle - > sendTurtleData ( pid , turtle_item ) ;
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
return true ;
}
else
{
2015-01-23 07:13:13 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " sending to pid " < < pid < < std : : endl ;
2015-01-23 07:13:13 -05:00
# endif
2015-04-09 17:34:50 -04:00
RsGRouterTransactionItem * item_copy = trans_item . duplicate ( ) ;
2015-04-12 17:43:52 -04:00
item_copy - > PeerId ( pid ) ;
2015-01-23 07:13:13 -05:00
2015-04-09 17:34:50 -04:00
sendItem ( item_copy ) ;
return true ;
}
2013-11-02 10:35:33 -04:00
}
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
void p3GRouter : : autoWash ( )
2014-01-03 17:41:20 -05:00
{
2015-04-09 17:34:50 -04:00
bool items_deleted = false ;
2015-04-18 15:59:27 -04:00
time_t now = time ( NULL ) ;
2015-04-15 16:48:30 -04:00
std : : map < GRouterMsgPropagationId , GRouterClientService * > failed_msgs ;
2015-04-09 17:34:50 -04:00
{
RS_STACK_MUTEX ( grMtx ) ;
2015-04-18 15:59:27 -04:00
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . begin ( ) ; it ! = _pending_messages . end ( ) ; )
2015-04-26 15:10:46 -04:00
if ( ( it - > second . data_status = = RS_GROUTER_DATA_STATUS_DONE & &
( ! ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_IS_DESTINATION )
| | it - > second . received_time_TS + MAX_DESTINATION_KEEP_TIME < now ) )
| | ( ( it - > second . received_time_TS + GROUTER_ITEM_MAX_CACHE_KEEP_TIME < now )
& & ! ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_IS_ORIGIN )
& & ! ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_IS_DESTINATION )
) ) // is the item too old for cache
2015-04-18 15:59:27 -04:00
{
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
grouter_debug ( ) < < " Removing cached item " < < std : : hex < < it - > first < < std : : dec < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2016-01-07 21:01:50 -05:00
//GRouterClientService *client = NULL ;
//GRouterServiceId service_id = 0;
2014-01-03 17:41:20 -05:00
2015-04-18 15:59:27 -04:00
if ( it - > second . data_status ! = RS_GROUTER_DATA_STATUS_DONE )
2016-01-07 21:01:50 -05:00
{
GRouterClientService * client = NULL ;
if ( locked_getLocallyRegisteredClientFromServiceId ( it - > second . client_id , client ) )
failed_msgs [ it - > first ] = client ;
else
std : : cerr < < " ERROR: client id " < < it - > second . client_id < < " not registered. Consistency error. " < < std : : endl ;
}
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
delete it - > second . data_item ;
2015-04-26 15:10:46 -04:00
2015-04-09 17:34:50 -04:00
if ( it - > second . receipt_item ! = NULL )
delete it - > second . receipt_item ;
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator tmp ( it ) ;
+ + tmp ;
_pending_messages . erase ( it ) ;
it = tmp ;
items_deleted = true ;
}
else
+ + it ;
2015-01-15 15:33:24 -05:00
2015-04-12 17:43:52 -04:00
// also check all existing tunnels
2015-01-15 15:33:24 -05:00
2015-04-18 15:59:27 -04:00
for ( std : : map < TurtleFileHash , GRouterTunnelInfo > : : iterator it = _tunnels . begin ( ) ; it ! = _tunnels . end ( ) ; + + it )
2015-04-12 17:43:52 -04:00
{
2015-04-18 15:59:27 -04:00
std : : list < TurtleVirtualPeerId > vpids_to_remove ;
for ( std : : set < TurtleVirtualPeerId > : : iterator it2 = it - > second . virtual_peers . begin ( ) ; it2 ! = it - > second . virtual_peers . end ( ) ; + + it2 )
if ( ! mTurtle - > isTurtlePeer ( * it2 ) )
{
vpids_to_remove . push_back ( * it2 ) ;
# ifdef GROUTER_DEBUG
std : : cerr < < " " < < * it2 < < " is not an active tunnel for hash " < < it - > first < < " . Removing virtual peer id. " < < std : : endl ;
# endif
}
for ( std : : list < TurtleVirtualPeerId > : : const_iterator it2 = vpids_to_remove . begin ( ) ; it2 ! = vpids_to_remove . end ( ) ; + + it2 )
it - > second . removeVirtualPeer ( * it2 ) ;
2015-04-12 17:43:52 -04:00
}
2015-04-18 15:59:27 -04:00
// Also clean incoming data pipes
for ( std : : map < RsPeerId , GRouterDataInfo > : : iterator it ( _incoming_data_pipes . begin ( ) ) ; it ! = _incoming_data_pipes . end ( ) ; )
if ( it - > second . last_activity_TS + MAX_INACTIVE_DATA_PIPE_DELAY < now )
{
# ifdef GROUTER_DEBUG
std : : cerr < < " removing data pipe for peer " < < it - > first < < " which is too old. " < < std : : endl ;
# endif
std : : map < RsPeerId , GRouterDataInfo > : : iterator ittmp = it ;
+ + ittmp ;
it - > second . clear ( ) ;
_incoming_data_pipes . erase ( it ) ;
2015-04-25 14:22:07 -04:00
it = ittmp ;
2015-04-18 15:59:27 -04:00
}
else
+ + it ;
2015-04-12 17:43:52 -04:00
}
2015-04-18 15:59:27 -04:00
// Look into pending items.
2015-04-15 16:48:30 -04:00
for ( std : : map < GRouterMsgPropagationId , GRouterClientService * > : : const_iterator it ( failed_msgs . begin ( ) ) ; it ! = failed_msgs . end ( ) ; + + it )
2015-04-12 17:43:52 -04:00
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-15 16:48:30 -04:00
std : : cerr < < " notifying client for message id " < < std : : hex < < it - > first < < " state = FAILED " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-15 16:48:30 -04:00
it - > second - > notifyDataStatus ( it - > first , GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED ) ;
2015-04-12 17:43:52 -04:00
}
2015-04-09 17:34:50 -04:00
if ( items_deleted )
_changed = true ;
}
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
bool p3GRouter : : sliceDataItem ( RsGRouterAbstractMsgItem * item , std : : list < RsGRouterTransactionChunkItem * > & chunks )
{
try
{
// Split the item into chunks. This function ensures that chunks in the list are valid. Memory ownership is left to the
// calling client. In case of error, all allocated memory is deleted.
2014-01-03 17:41:20 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-12 17:43:52 -04:00
std : : cerr < < " p3GRouter::sliceDataItem() " < < std : : endl ;
2015-04-09 17:34:50 -04:00
std : : cerr < < " item dump before send: " < < std : : endl ;
item - > print ( std : : cerr , 2 ) ;
2014-03-29 19:03:04 -04:00
# endif
2014-01-03 17:41:20 -05:00
2015-04-09 17:34:50 -04:00
uint32_t size = item - > serial_size ( ) ;
2014-01-03 17:41:20 -05:00
2015-04-09 17:34:50 -04:00
RsTemporaryMemory data ( size ) ; // data will be freed on return, whatever the route taken.
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
if ( data = = NULL )
{
std : : cerr < < " ERROR: cannot allocate memory. Size= " < < size < < std : : endl ;
throw ;
}
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
if ( ! item - > serialise ( data , size ) )
{
std : : cerr < < " ERROR: cannot serialise. " < < std : : endl ;
throw ;
}
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
uint32_t offset = 0 ;
static const uint32_t CHUNK_SIZE = 15000 ;
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
while ( offset < size )
{
uint32_t chunk_size = std : : min ( size - offset , CHUNK_SIZE ) ;
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
RsGRouterTransactionChunkItem * chunk_item = new RsGRouterTransactionChunkItem ;
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
chunk_item - > propagation_id = item - > routing_id ;
chunk_item - > total_size = size ;
chunk_item - > chunk_start = offset ;
chunk_item - > chunk_size = chunk_size ;
chunk_item - > chunk_data = ( uint8_t * ) malloc ( chunk_size ) ;
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " preparing to send a chunk [ " < < offset < < " -> " < < offset + chunk_size < < " / " < < size < < " ] " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-01-15 15:33:24 -05:00
2015-04-09 17:34:50 -04:00
if ( chunk_item - > chunk_data = = NULL )
{
std : : cerr < < " ERROR: Cannot allocate memory for size " < < chunk_size < < std : : endl ;
delete chunk_item ;
throw ;
}
memcpy ( chunk_item - > chunk_data , & data [ offset ] , chunk_size ) ;
offset + = chunk_size ;
chunks . push_back ( chunk_item ) ;
}
return true ;
}
catch ( . . . )
{
for ( std : : list < RsGRouterTransactionChunkItem * > : : const_iterator it ( chunks . begin ( ) ) ; it ! = chunks . end ( ) ; + + it )
delete * it ;
chunks . clear ( ) ;
return false ;
}
2014-01-03 17:41:20 -05:00
}
2013-11-02 10:35:33 -04:00
2015-04-09 17:34:50 -04:00
void p3GRouter : : handleIncoming ( )
2013-11-02 10:35:33 -04:00
{
2015-04-09 17:34:50 -04:00
while ( ! _incoming_items . empty ( ) )
{
RsGRouterAbstractMsgItem * item = _incoming_items . front ( ) ;
_incoming_items . pop_front ( ) ;
2013-11-02 10:35:33 -04:00
2015-04-09 17:34:50 -04:00
RsGRouterGenericDataItem * generic_data_item ;
RsGRouterSignedReceiptItem * receipt_item ;
if ( NULL ! = ( generic_data_item = dynamic_cast < RsGRouterGenericDataItem * > ( item ) ) )
handleIncomingDataItem ( generic_data_item ) ;
else if ( NULL ! = ( receipt_item = dynamic_cast < RsGRouterSignedReceiptItem * > ( item ) ) )
handleIncomingReceiptItem ( receipt_item ) ;
else
std : : cerr < < " Item has unknown type (not data nor signed receipt). Dropping! " < < std : : endl ;
2014-04-12 15:58:45 -04:00
2015-04-09 17:34:50 -04:00
delete item ;
}
2013-11-02 10:35:33 -04:00
}
2015-04-09 17:34:50 -04:00
void p3GRouter : : handleIncomingReceiptItem ( RsGRouterSignedReceiptItem * receipt_item )
2014-04-19 12:02:11 -04:00
{
2015-01-22 09:33:19 -05:00
bool changed = false ;
2014-04-19 12:02:11 -04:00
# ifdef GROUTER_DEBUG
2015-01-20 08:04:10 -05:00
std : : cerr < < " Handling incoming signed receipt item. " < < std : : endl ;
2015-01-19 08:53:36 -05:00
std : : cerr < < " Item content: " < < std : : endl ;
receipt_item - > print ( std : : cerr , 2 ) ;
2014-04-19 12:02:11 -04:00
# endif
2015-01-20 08:04:10 -05:00
// Because we don't do proxy-transmission yet, the client needs to be notified. Otherwise, we will need to
2015-01-19 08:53:36 -05:00
// first check if we're a proxy or not. We also remove the message from the global router sending list.
// in the proxy case, we should only store the receipt.
2014-04-11 17:56:10 -04:00
2015-04-15 16:48:30 -04:00
GRouterClientService * client_service = NULL ;
GRouterServiceId service_id ;
GRouterMsgPropagationId mid = 0 ;
2015-01-19 08:53:36 -05:00
{
RS_STACK_MUTEX ( grMtx ) ;
std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . find ( receipt_item - > routing_id ) ;
2015-01-20 08:04:10 -05:00
if ( it = = _pending_messages . end ( ) )
2015-01-19 08:53:36 -05:00
{
2015-01-20 08:04:10 -05:00
std : : cerr < < " ERROR: no routing ID corresponds to this message. Inconsistency! " < < std : : endl ;
return ;
}
2015-01-19 08:53:36 -05:00
2015-04-18 15:59:27 -04:00
// check hash.
if ( receipt_item - > data_hash ! = it - > second . item_hash )
2015-01-20 08:04:10 -05:00
{
std : : cerr < < " checking receipt hash : FAILED. Receipt is dropped. " < < std : : endl ;
return ;
2015-01-19 08:53:36 -05:00
}
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
else
2015-01-20 08:04:10 -05:00
std : : cerr < < " checking receipt hash : OK " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-18 15:59:27 -04:00
// check signature.
2014-04-19 12:02:11 -04:00
2015-01-20 08:04:10 -05:00
if ( ! verifySignedDataItem ( receipt_item ) )
{
std : : cerr < < " checking receipt signature : FAILED. Receipt is dropped. " < < std : : endl ;
return ;
}
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-20 08:04:10 -05:00
std : : cerr < < " checking receipt signature : OK. " < < std : : endl ;
std : : cerr < < " removing messsage from cache. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-22 12:04:13 -05:00
2015-04-20 17:24:22 -04:00
if ( it - > second . routing_flags & GRouterRoutingInfo : : ROUTING_FLAGS_IS_ORIGIN )
{
2015-04-15 16:48:30 -04:00
# ifdef GROUTER_DEBUG
2015-04-20 17:24:22 -04:00
std : : cerr < < " message is at origin. Setting message transmission to DONE " < < std : : endl ;
2015-04-15 16:48:30 -04:00
# endif
2015-04-20 17:24:22 -04:00
it - > second . data_status = RS_GROUTER_DATA_STATUS_DONE ;
2015-04-18 15:59:27 -04:00
2016-01-07 21:01:50 -05:00
if ( locked_getLocallyRegisteredClientFromServiceId ( it - > second . client_id , client_service ) )
2015-04-20 17:24:22 -04:00
mid = it - > first ;
else
{
mid = 0 ;
std : : cerr < < " ERROR: cannot retrieve service ID for message " < < std : : hex < < it - > first < < std : : dec < < std : : endl ;
}
}
2015-04-18 15:59:27 -04:00
else
{
2015-04-15 16:48:30 -04:00
# ifdef GROUTER_DEBUG
2015-04-20 17:24:22 -04:00
std : : cerr < < " message is not at origin. Setting message transmission to RECEIPT_OK " < < std : : endl ;
2015-04-15 16:48:30 -04:00
# endif
2015-04-20 17:24:22 -04:00
it - > second . data_status = RS_GROUTER_DATA_STATUS_RECEIPT_OK ;
it - > second . receipt_item = receipt_item - > duplicate ( ) ;
}
2015-04-15 16:48:30 -04:00
2015-04-20 17:24:22 -04:00
changed = true ;
2015-01-11 17:18:28 -05:00
}
2015-04-15 16:48:30 -04:00
if ( mid ! = 0 )
{
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-15 16:48:30 -04:00
std : : cerr < < " notifying client " < < ( void * ) client_service < < " that msg " < < std : : hex < < mid < < std : : dec < < " was received. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-04-15 16:48:30 -04:00
client_service - > notifyDataStatus ( mid , GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED ) ;
}
2014-04-12 15:58:45 -04:00
2015-04-20 17:24:22 -04:00
// also note the incoming route in the routing matrix
if ( ! mTurtle - > isTurtlePeer ( receipt_item - > PeerId ( ) ) )
{
# ifdef GROUTER_DEBUG
std : : cerr < < " receipt item comes from a direct friend. Marking route in routing matrix. " < < std : : endl ;
# endif
addRoutingClue ( receipt_item - > signature . keyId , receipt_item - > PeerId ( ) ) ;
}
2015-01-22 09:33:19 -05:00
if ( changed )
IndicateConfigChanged ( ) ;
2015-01-11 17:18:28 -05:00
}
2014-04-19 12:02:11 -04:00
2015-04-18 15:59:27 -04:00
Sha1CheckSum p3GRouter : : computeDataItemHash ( RsGRouterGenericDataItem * data_item )
{
uint32_t total_size = data_item - > signed_data_size ( ) + data_item - > signature . TlvSize ( ) ;
RsTemporaryMemory mem ( total_size ) ;
uint32_t offset = 0 ;
data_item - > serialise_signed_data ( mem , total_size ) ;
offset + = data_item - > signed_data_size ( ) ;
data_item - > signature . SetTlv ( mem , total_size , & offset ) ;
return RsDirUtil : : sha1sum ( mem , total_size ) ;
}
2015-04-09 17:34:50 -04:00
void p3GRouter : : handleIncomingDataItem ( RsGRouterGenericDataItem * data_item )
2015-01-11 17:18:28 -05:00
{
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
std : : cerr < < " Handling incoming data item. " < < std : : endl ;
2015-01-19 08:53:36 -05:00
std : : cerr < < " Item content: " < < std : : endl ;
2015-04-09 17:34:50 -04:00
data_item - > print ( std : : cerr , 2 ) ;
2014-03-29 19:03:04 -04:00
# endif
2014-03-29 10:18:05 -04:00
2015-04-26 15:10:46 -04:00
// we find 3 things:
// A - is the item for us ?
// B - signature and hash check ?
// C - item is already known ?
// Store the item? if !C
// Send a receipt? if A && B
// Notify client? if A && !C
//
2015-01-19 08:53:36 -05:00
GRouterClientService * client = NULL ;
2015-04-09 17:34:50 -04:00
GRouterServiceId service_id = data_item - > service_id ;
2015-04-18 15:59:27 -04:00
RsGRouterSignedReceiptItem * receipt_item = NULL ;
2015-04-26 15:10:46 -04:00
Sha1CheckSum item_hash = computeDataItemHash ( data_item ) ;
bool item_is_already_known = false ;
2015-04-09 17:34:50 -04:00
bool item_is_for_us = false ;
2015-04-26 15:10:46 -04:00
bool cache_has_changed = false ;
2014-04-11 17:56:10 -04:00
2015-04-26 15:10:46 -04:00
// A - Find client and service ID from destination key.
# ifdef GROUTER_DEBUG
std : : cerr < < " step A: find if the item is for us or not, and whether it's aready in cache or not. " < < std : : endl ;
# endif
2015-01-19 08:53:36 -05:00
{
2015-01-22 09:33:19 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
std : : map < GRouterServiceId , GRouterClientService * > : : const_iterator its = _registered_services . find ( service_id ) ;
if ( its = = _registered_services . end ( ) )
2015-01-22 09:33:19 -05:00
{
2015-04-26 15:10:46 -04:00
std : : cerr < < " ERROR: client id " < < service_id < < " not registered. Consistency error. " < < std : : endl ;
2015-01-22 09:33:19 -05:00
return ;
}
2015-04-09 17:34:50 -04:00
client = its - > second ;
// also check wether this item is for us or not
item_is_for_us = _owned_key_ids . find ( makeTunnelHash ( data_item - > destination_key , service_id ) ) ! = _owned_key_ids . end ( ) ;
2014-03-29 10:18:05 -04:00
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-27 18:01:31 -04:00
std : : cerr < < " item is " < < ( item_is_for_us ? " " : " not " ) < < " for us. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-27 18:01:31 -04:00
std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . find ( data_item - > routing_id ) ;
2015-04-09 17:34:50 -04:00
2015-04-27 18:01:31 -04:00
if ( it ! = _pending_messages . end ( ) )
2015-04-18 15:59:27 -04:00
{
2015-04-27 18:01:31 -04:00
if ( it - > second . item_hash ! = item_hash )
{
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-27 18:01:31 -04:00
std : : cerr < < " ERROR: item is already known but data hash does not match. Dropping that item. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-27 18:01:31 -04:00
return ;
}
item_is_already_known = true ;
receipt_item = it - > second . receipt_item ;
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
2015-04-27 18:01:31 -04:00
std : : cerr < < " item is already in cache. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
# endif
2015-04-27 18:01:31 -04:00
}
2015-04-26 15:10:46 -04:00
# ifdef GROUTER_DEBUG
2015-04-27 18:01:31 -04:00
else
std : : cerr < < " item is new. " < < std : : endl ;
2015-04-26 15:10:46 -04:00
# endif
}
// At this point, if item is already known, it is guarrantied to be identical to the stored item.
// If the item is for us, and not already known, check the signature and hash, and generate a signed receipt
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
if ( item_is_for_us & & ! item_is_already_known )
{
# ifdef GROUTER_DEBUG
std : : cerr < < " step B: item is for us and is new, so make sure it's authentic and create a receipt " < < std : : endl ;
# endif
if ( ! verifySignedDataItem ( data_item ) ) // we should get proper flags out of this
2015-04-09 17:34:50 -04:00
{
2015-04-26 15:10:46 -04:00
std : : cerr < < " verifying item signature: FAILED! Droping that item " ;
2015-07-09 16:55:11 -04:00
std : : cerr < < " You probably received a message from a person you don't have key. " < < std : : endl ;
std : : cerr < < " Signature key ID: " < < data_item - > signature . keyId < < std : : endl ;
2015-04-26 15:10:46 -04:00
return ;
2015-04-09 17:34:50 -04:00
}
2015-04-18 15:59:27 -04:00
# ifdef GROUTER_DEBUG
else
2015-04-26 15:10:46 -04:00
std : : cerr < < " verifying item signature: CHECKED! " ;
2015-04-18 15:59:27 -04:00
# endif
// No we need to send a signed receipt to the sender.
receipt_item = new RsGRouterSignedReceiptItem ;
2015-04-26 15:10:46 -04:00
receipt_item - > data_hash = item_hash ;
2015-04-18 15:59:27 -04:00
receipt_item - > routing_id = data_item - > routing_id ;
receipt_item - > destination_key = data_item - > signature . keyId ;
receipt_item - > flags = 0 ;
2013-12-22 12:04:13 -05:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " preparing signed receipt. " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-04-18 15:59:27 -04:00
if ( ! signDataItem ( receipt_item , data_item - > destination_key ) )
{
2015-04-26 15:10:46 -04:00
std : : cerr < < " signing: FAILED. Receipt dropped. ERROR. Packet dropped as well. " < < std : : endl ;
2015-04-18 15:59:27 -04:00
return ;
}
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " signing: OK. " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-01-19 08:53:36 -05:00
}
2014-04-11 17:56:10 -04:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
else
2015-04-26 15:10:46 -04:00
std : : cerr < < " step B: skipped, since item is not for us, or already known. " < < std : : endl ;
2015-01-22 04:50:44 -05:00
# endif
2015-01-19 08:53:36 -05:00
2015-04-26 15:10:46 -04:00
// now store the item in _pending_messages whether it is for us or not (if the item is for us, this prevents receiving multiple
// copies of the message)
# ifdef GROUTER_DEBUG
std : : cerr < < " step C: store the item is cache. " < < std : : endl ;
# endif
{
RS_STACK_MUTEX ( grMtx ) ;
2015-01-19 08:53:36 -05:00
2015-04-26 15:10:46 -04:00
GRouterRoutingInfo & info ( _pending_messages [ data_item - > routing_id ] ) ;
2014-04-11 17:56:10 -04:00
2015-04-26 15:10:46 -04:00
if ( info . data_item = = NULL ) // item is not for us
{
2014-04-11 17:56:10 -04:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
std : : cerr < < " item is new. Storing it. " < < std : : endl ;
2014-04-11 17:56:10 -04:00
# endif
2014-04-19 12:02:11 -04:00
2015-04-26 15:10:46 -04:00
info . data_item = data_item - > duplicate ( ) ;
info . receipt_item = receipt_item ; // inited before, or NULL.
info . tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ;
info . last_sent_TS = 0 ;
2016-01-07 21:01:50 -05:00
info . client_id = data_item - > service_id ;
2015-04-26 15:10:46 -04:00
info . item_hash = item_hash ;
info . last_tunnel_request_TS = 0 ;
info . sending_attempts = 0 ;
info . received_time_TS = time ( NULL ) ;
info . tunnel_hash = makeTunnelHash ( data_item - > destination_key , data_item - > service_id ) ;
2015-04-09 17:34:50 -04:00
2015-04-26 15:10:46 -04:00
if ( item_is_for_us )
2015-04-18 15:59:27 -04:00
{
2015-04-26 15:10:46 -04:00
// don't store if item is for us. No need to take that much memory.
free ( info . data_item - > data_bytes ) ;
info . data_item - > data_size = 0 ;
info . data_item - > data_bytes = NULL ;
2015-04-18 15:59:27 -04:00
info . routing_flags = GRouterRoutingInfo : : ROUTING_FLAGS_IS_DESTINATION | GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_FRIENDS ;
2015-04-26 15:10:46 -04:00
info . data_status = RS_GROUTER_DATA_STATUS_RECEIPT_OK ;
2015-04-18 15:59:27 -04:00
}
2015-04-26 15:10:46 -04:00
else
{
info . routing_flags = GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_FRIENDS ; // don't allow tunnels just yet
info . data_status = RS_GROUTER_DATA_STATUS_PENDING ;
}
2015-04-18 15:59:27 -04:00
}
2015-04-26 15:10:46 -04:00
# ifdef GROUTER_DEBUG
else
std : : cerr < < " item is already in cache. " < < std : : endl ;
std : : cerr < < " storing incoming route from " < < data_item - > PeerId ( ) < < std : : endl ;
# endif
info . incoming_routes . ids . insert ( data_item - > PeerId ( ) ) ;
cache_has_changed = true ;
2015-04-18 15:59:27 -04:00
}
2015-04-26 15:10:46 -04:00
// if the item is for us and is not already known, notify the client.
if ( item_is_for_us & & ! item_is_already_known )
2015-01-20 08:04:10 -05:00
{
2015-04-26 15:10:46 -04:00
// compute the hash before decryption.
# ifdef GROUTER_DEBUG
std : : cerr < < " step D: item is for us and is new: decrypting and notifying client. " < < std : : endl ;
# endif
RsGRouterGenericDataItem * decrypted_item = data_item - > duplicate ( ) ;
if ( ! decryptDataItem ( decrypted_item ) )
{
std : : cerr < < " decrypting item : FAILED! Item cannot be passed to the client. " < < std : : endl ;
delete decrypted_item ;
2015-01-20 08:04:10 -05:00
2015-04-26 15:10:46 -04:00
return ;
}
2014-04-19 12:02:11 -04:00
# ifdef GROUTER_DEBUG
2015-04-26 15:10:46 -04:00
else
std : : cerr < < " decrypting item : OK! " < < std : : endl ;
std : : cerr < < " notyfying client. " < < std : : endl ;
2014-04-19 12:02:11 -04:00
# endif
2015-12-25 22:37:06 -05:00
if ( client - > acceptDataFromPeer ( decrypted_item - > signature . keyId ) )
{
client - > receiveGRouterData ( decrypted_item - > destination_key , decrypted_item - > signature . keyId , service_id , decrypted_item - > data_bytes , decrypted_item - > data_size ) ;
decrypted_item - > data_bytes = NULL ;
decrypted_item - > data_size = 0 ;
}
2015-04-18 15:59:27 -04:00
2015-04-26 15:10:46 -04:00
delete decrypted_item ;
}
# ifdef GROUTER_DEBUG
else
std : : cerr < < " step D: item is not for us or not new: skipping this step. " < < std : : endl ;
# endif
if ( cache_has_changed )
IndicateConfigChanged ( ) ;
2015-01-19 08:53:36 -05:00
}
2016-01-07 21:01:50 -05:00
bool p3GRouter : : locked_getLocallyRegisteredClientFromServiceId ( const GRouterServiceId & service_id , GRouterClientService * & client )
2015-01-19 08:53:36 -05:00
{
client = NULL ;
2015-12-07 22:39:45 -05:00
2015-01-22 09:33:19 -05:00
std : : map < GRouterServiceId , GRouterClientService * > : : const_iterator its = _registered_services . find ( service_id ) ;
2015-01-19 08:53:36 -05:00
2015-01-22 09:33:19 -05:00
if ( its = = _registered_services . end ( ) )
{
std : : cerr < < " ERROR: client id " < < service_id < < " not registered. Consistency error. " < < std : : endl ;
return false ;
2015-01-22 04:50:44 -05:00
}
2015-01-19 08:53:36 -05:00
2015-01-22 09:33:19 -05:00
client = its - > second ;
2015-01-19 08:53:36 -05:00
return true ;
2013-11-02 10:35:33 -04:00
}
2015-10-25 17:16:16 -04:00
void p3GRouter : : addTrackingInfo ( const RsGxsMessageId & mid , const RsPeerId & peer_id )
{
RS_STACK_MUTEX ( grMtx ) ;
# ifdef GROUTER_DEBUG
2015-10-27 22:41:29 -04:00
grouter_debug ( ) < < " Received new routing clue for key " < < mid < < " from peer " < < peer_id < < std : : endl ;
2015-10-25 17:16:16 -04:00
# endif
_routing_matrix . addTrackingInfo ( mid , peer_id ) ;
2015-10-27 22:41:29 -04:00
_changed = true ;
2015-10-25 17:16:16 -04:00
}
2014-10-22 17:00:20 -04:00
void p3GRouter : : addRoutingClue ( const GRouterKeyId & id , const RsPeerId & peer_id )
{
2015-01-15 15:33:24 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2014-10-22 17:00:20 -04:00
# ifdef GROUTER_DEBUG
grouter_debug ( ) < < " Received new routing clue for key " < < id < < " from peer " < < peer_id < < std : : endl ;
# endif
_routing_matrix . addRoutingClue ( id , peer_id , RS_GROUTER_BASE_WEIGHT_GXS_PACKET ) ;
2015-10-27 22:41:29 -04:00
_changed = true ;
2014-10-22 17:00:20 -04:00
}
2015-01-11 17:18:28 -05:00
bool p3GRouter : : registerClientService ( const GRouterServiceId & id , GRouterClientService * service )
{
2015-01-15 15:33:24 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-11 17:18:28 -05:00
_registered_services [ id ] = service ;
return true ;
}
2013-12-24 11:41:07 -05:00
2015-01-11 17:18:28 -05:00
bool p3GRouter : : encryptDataItem ( RsGRouterGenericDataItem * item , const RsGxsId & destination_key )
2013-11-02 10:35:33 -04:00
{
2015-01-11 17:18:28 -05:00
assert ( ! ( item - > flags & RS_GROUTER_DATA_FLAGS_ENCRYPTED ) ) ;
2014-04-11 17:56:10 -04:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
std : : cerr < < " Encrypting data for key " < < destination_key < < std : : endl ;
std : : cerr < < " Decrypted size = " < < item - > data_size < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-03-14 10:33:23 -04:00
uint8_t * encrypted_data = NULL ;
uint32_t encrypted_size = 0 ;
uint32_t error_status ;
if ( ! mGixs - > encryptData ( item - > data_bytes , item - > data_size , encrypted_data , encrypted_size , destination_key , true , error_status ) )
{
std : : cerr < < " (EE) Cannot encrypt: " ;
if ( error_status = = RsGixs : : RS_GIXS_ERROR_KEY_NOT_AVAILABLE ) std : : cerr < < " key not available for ID = " < < destination_key < < std : : endl ;
if ( error_status = = RsGixs : : RS_GIXS_ERROR_UNKNOWN ) std : : cerr < < " unknown error for ID = " < < destination_key < < std : : endl ;
return false ;
}
2015-01-11 17:18:28 -05:00
2015-01-23 10:16:04 -05:00
free ( item - > data_bytes ) ;
2015-01-11 17:18:28 -05:00
item - > data_bytes = encrypted_data ;
item - > data_size = encrypted_size ;
item - > flags | = RS_GROUTER_DATA_FLAGS_ENCRYPTED ;
2014-03-29 10:18:05 -04:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
std : : cerr < < " Encrypted size = " < < encrypted_size < < std : : endl ;
2015-04-09 17:34:50 -04:00
std : : cerr < < " First bytes of encrypted data: " < < RsUtil : : BinToHex ( ( const char * ) encrypted_data , std : : min ( encrypted_size , 30u ) ) < < " ... " < < std : : endl ;
2015-01-11 17:18:28 -05:00
std : : cerr < < " Encrypted data hash = " < < RsDirUtil : : sha1sum ( ( const uint8_t * ) encrypted_data , encrypted_size ) < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-01-11 17:18:28 -05:00
return true ;
}
bool p3GRouter : : decryptDataItem ( RsGRouterGenericDataItem * item )
{
2015-01-19 08:53:36 -05:00
assert ( item - > flags & RS_GROUTER_DATA_FLAGS_ENCRYPTED ) ;
2014-03-29 10:18:05 -04:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-19 08:53:36 -05:00
std : : cerr < < " decrypting data for key " < < item - > destination_key < < std : : endl ;
std : : cerr < < " encrypted size = " < < item - > data_size < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-03-14 10:33:23 -04:00
uint8_t * decrypted_data = NULL ;
uint32_t decrypted_size = 0 ;
uint32_t error_status ;
2015-04-09 17:34:50 -04:00
if ( ! mGixs - > decryptData ( item - > data_bytes , item - > data_size , decrypted_data , decrypted_size , item - > destination_key , error_status ) )
2015-03-14 10:33:23 -04:00
{
if ( error_status = = RsGixs : : RS_GIXS_ERROR_KEY_NOT_AVAILABLE )
std : : cerr < < " (EE) Cannot decrypt incoming message. Key " < < item - > destination_key < < " unknown. " < < std : : endl ;
else
std : : cerr < < " (EE) Cannot decrypt incoming message. Unknown error. " < < std : : endl ;
2015-05-14 09:44:57 -04:00
return false ;
2015-03-14 10:33:23 -04:00
}
2015-01-19 08:53:36 -05:00
2015-01-23 10:16:04 -05:00
free ( item - > data_bytes ) ;
2015-01-19 08:53:36 -05:00
item - > data_bytes = decrypted_data ;
item - > data_size = decrypted_size ;
item - > flags & = ~ RS_GROUTER_DATA_FLAGS_ENCRYPTED ;
return true ;
}
2013-11-02 10:35:33 -04:00
2015-01-20 08:04:10 -05:00
bool p3GRouter : : signDataItem ( RsGRouterAbstractMsgItem * item , const RsGxsId & signing_id )
2015-01-11 17:18:28 -05:00
{
try
{
RsTlvSecurityKey signature_key ;
2014-04-11 17:56:10 -04:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
std : : cerr < < " p3GRouter::signDataItem() " < < std : : endl ;
std : : cerr < < " Key ID = " < < signing_id < < std : : endl ;
std : : cerr < < " Getting key material... " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2015-01-11 17:18:28 -05:00
uint32_t data_size = item - > signed_data_size ( ) ;
2015-04-18 15:59:27 -04:00
RsTemporaryMemory data ( data_size ) ;
2013-12-28 16:47:15 -05:00
2015-01-11 17:18:28 -05:00
if ( data = = NULL )
throw std : : runtime_error ( " Cannot allocate memory for signing data. " ) ;
2014-04-19 12:02:11 -04:00
2015-03-14 10:33:23 -04:00
if ( ! item - > serialise_signed_data ( data , data_size ) )
throw std : : runtime_error ( " Cannot serialise signed data. " ) ;
2014-04-15 18:10:53 -04:00
2015-03-14 10:33:23 -04:00
uint32_t error_status ;
if ( ! mGixs - > signData ( data , data_size , signing_id , item - > signature , error_status ) )
throw std : : runtime_error ( " Cannot sign for id " + signing_id . toStdString ( ) + " . Signature call failed. " ) ;
2013-12-24 11:41:07 -05:00
2015-01-22 04:50:44 -05:00
# ifdef GROUTER_DEBUG
std : : cerr < < " Created signature for data hash: " < < RsDirUtil : : sha1sum ( data , data_size ) < < " and key id= " < < signing_id < < std : : endl ;
# endif
2015-01-11 17:18:28 -05:00
return true ;
}
catch ( std : : exception & e )
{
std : : cerr < < " signing failed. Error: " < < e . what ( ) < < std : : endl ;
2015-03-14 10:33:23 -04:00
2015-01-11 17:18:28 -05:00
item - > signature . TlvClear ( ) ;
return false ;
}
2013-11-02 10:35:33 -04:00
}
2015-01-20 08:04:10 -05:00
bool p3GRouter : : verifySignedDataItem ( RsGRouterAbstractMsgItem * item )
2013-12-27 15:06:47 -05:00
{
2015-01-11 17:18:28 -05:00
try
{
RsTlvSecurityKey signature_key ;
2013-12-24 11:41:07 -05:00
2015-01-11 17:18:28 -05:00
uint32_t data_size = item - > signed_data_size ( ) ;
2015-03-28 14:07:01 -04:00
RsTemporaryMemory data ( data_size ) ;
2015-03-28 13:23:52 -04:00
if ( data = = NULL )
throw std : : runtime_error ( " Cannot allocate data. " ) ;
2013-12-24 11:41:07 -05:00
2015-01-11 17:18:28 -05:00
if ( ! item - > serialise_signed_data ( data , data_size ) )
throw std : : runtime_error ( " Cannot serialise signed data. " ) ;
2013-12-24 11:41:07 -05:00
2015-01-11 17:18:28 -05:00
2015-03-14 10:33:23 -04:00
uint32_t error_status ;
if ( ! mGixs - > validateData ( data , data_size , item - > signature , true , error_status ) )
{
switch ( error_status )
{
2015-07-09 16:55:11 -04:00
case RsGixs : : RS_GIXS_ERROR_KEY_NOT_AVAILABLE : std : : cerr < < " (EE) Key for GXS Id " < < item - > signature . keyId < < " is not available. Cannot verify. " < < std : : endl ;
2015-03-14 10:33:23 -04:00
break ;
case RsGixs : : RS_GIXS_ERROR_SIGNATURE_MISMATCH : std : : cerr < < " (EE) Signature mismatch. Spoofing/Corrupted/MITM?. " < < std : : endl ;
break ;
2015-07-09 16:55:11 -04:00
default : std : : cerr < < " (EE) Signature verification failed on GRouter message. Unknown error status: " < < error_status < < std : : endl ;
break ;
2015-03-14 10:33:23 -04:00
}
return false ;
}
2015-01-11 17:18:28 -05:00
return true ;
}
catch ( std : : exception & e )
{
std : : cerr < < " signature verification failed. Error: " < < e . what ( ) < < std : : endl ;
return false ;
}
2013-12-27 15:06:47 -05:00
}
2015-01-22 09:33:19 -05:00
bool p3GRouter : : cancel ( GRouterMsgPropagationId mid )
{
{
RS_STACK_MUTEX ( grMtx ) ;
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-22 09:33:19 -05:00
std : : cerr < < " p3GRouter::cancel(). Canceling message ID " < < mid < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-28 16:47:15 -05:00
2015-01-22 09:33:19 -05:00
std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it = _pending_messages . find ( mid ) ;
2014-04-11 17:56:10 -04:00
2015-01-22 09:33:19 -05:00
if ( it = = _pending_messages . end ( ) )
{
std : : cerr < < " ERROR: message ID is unknown. " < < std : : endl ;
return false ;
}
2014-04-19 12:02:11 -04:00
2015-01-22 09:33:19 -05:00
delete it - > second . data_item ;
if ( it - > second . receipt_item )
delete it - > second . receipt_item ;
2014-04-11 17:56:10 -04:00
2015-01-22 09:33:19 -05:00
_pending_messages . erase ( it ) ;
}
2013-11-02 10:35:33 -04:00
2015-01-22 09:33:19 -05:00
IndicateConfigChanged ( ) ;
return true ;
2013-12-27 15:06:47 -05:00
}
2015-01-23 10:16:04 -05:00
bool p3GRouter : : sendData ( const RsGxsId & destination , const GRouterServiceId & client_id , const uint8_t * data , uint32_t data_size , const RsGxsId & signing_id , GRouterMsgPropagationId & propagation_id )
2013-11-02 10:35:33 -04:00
{
2015-04-09 17:34:50 -04:00
// std::cerr << "GRouter currently disabled." << std::endl;
// return false;
2015-01-22 04:50:44 -05:00
if ( data_size > MAX_GROUTER_DATA_SIZE )
{
std : : cerr < < " GRouter max size limit exceeded (size= " < < data_size < < " , max= " < < MAX_GROUTER_DATA_SIZE < < " ). Please send a smaller object! " < < std : : endl ;
2015-04-18 15:59:27 -04:00
return false ;
2015-01-22 04:50:44 -05:00
}
2015-04-18 15:59:27 -04:00
// Make sure we have a unique id (at least locally). There's little chances that an id of the same value is out there anyway.
2015-01-11 17:18:28 -05:00
//
{
RsStackMutex mtx ( grMtx ) ;
do { propagation_id = RSRandom : : random_u64 ( ) ; } while ( _pending_messages . find ( propagation_id ) ! = _pending_messages . end ( ) ) ;
}
// create the signed data item
RsGRouterGenericDataItem * data_item = new RsGRouterGenericDataItem ;
2015-01-23 10:16:04 -05:00
data_item - > data_bytes = ( uint8_t * ) malloc ( data_size ) ;
memcpy ( data_item - > data_bytes , data , data_size ) ;
2015-01-11 17:18:28 -05:00
data_item - > data_size = data_size ;
data_item - > routing_id = propagation_id ;
data_item - > randomized_distance = 0 ;
2015-04-09 17:34:50 -04:00
data_item - > service_id = client_id ;
2015-01-11 17:18:28 -05:00
data_item - > destination_key = destination ;
2015-04-09 17:34:50 -04:00
data_item - > flags = 0 ; // this is unused for now.
2015-01-11 17:18:28 -05:00
// First, encrypt.
if ( ! encryptDataItem ( data_item , destination ) )
{
std : : cerr < < " Cannot encrypt data item. Some error occured! " < < std : : endl ;
2015-03-28 13:23:52 -04:00
delete data_item ;
2015-01-11 17:18:28 -05:00
return false ;
}
// Then, sign the encrypted data, so that the signature can be checked by non priviledged users.
if ( ! signDataItem ( data_item , signing_id ) )
{
std : : cerr < < " Cannot sign data item. Some error occured! " < < std : : endl ;
2015-03-28 13:23:52 -04:00
delete data_item ;
2015-01-11 17:18:28 -05:00
return false ;
}
// Verify the signature. If that fails, there's a bug somewhere!!
if ( ! verifySignedDataItem ( data_item ) )
{
std : : cerr < < " Cannot verify data item that was just signed. Some error occured! " < < std : : endl ;
2015-03-28 13:23:52 -04:00
delete data_item ;
2015-01-11 17:18:28 -05:00
return false ;
}
// push the item into pending messages.
//
GRouterRoutingInfo info ;
time_t now = time ( NULL ) ;
info . data_item = data_item ;
2015-01-23 07:13:13 -05:00
info . receipt_item = NULL ;
2015-01-11 17:18:28 -05:00
info . data_status = RS_GROUTER_DATA_STATUS_PENDING ;
info . tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ;
2015-04-20 17:24:22 -04:00
info . last_sent_TS = 0 ;
2016-01-07 21:01:50 -05:00
info . client_id = client_id ;
2015-01-11 17:18:28 -05:00
info . last_tunnel_request_TS = 0 ;
2015-04-18 15:59:27 -04:00
info . item_hash = computeDataItemHash ( data_item ) ;
2015-01-11 17:18:28 -05:00
info . sending_attempts = 0 ;
2015-04-17 17:37:26 -04:00
info . routing_flags = GRouterRoutingInfo : : ROUTING_FLAGS_IS_ORIGIN | GRouterRoutingInfo : : ROUTING_FLAGS_ALLOW_FRIENDS ; // don't allow tunnels just yet
2015-01-11 17:18:28 -05:00
info . received_time_TS = now ;
info . tunnel_hash = makeTunnelHash ( destination , client_id ) ;
2014-03-29 10:18:05 -04:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-09 17:34:50 -04:00
grouter_debug ( ) < < " p3GRouter::sendGRouterData(): pushing the following item in the msg pending list: " < < std : : endl ;
2015-04-17 17:37:26 -04:00
grouter_debug ( ) < < " routing id = " < < std : : hex < < propagation_id < < std : : dec < < std : : endl ;
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < " data_item.size = " < < info . data_item - > data_size < < std : : endl ;
grouter_debug ( ) < < " data_item.byte = " < < RsDirUtil : : sha1sum ( info . data_item - > data_bytes , info . data_item - > data_size ) < < std : : endl ;
2015-01-22 04:50:44 -05:00
grouter_debug ( ) < < " destination = " < < data_item - > destination_key < < std : : endl ;
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < " signed by key = " < < data_item - > signature . keyId < < std : : endl ;
grouter_debug ( ) < < " data status = " < < info . data_status < < std : : endl ;
grouter_debug ( ) < < " tunnel status = " < < info . tunnel_status < < std : : endl ;
grouter_debug ( ) < < " sending attempt= " < < info . sending_attempts < < std : : endl ;
grouter_debug ( ) < < " distance = " < < info . data_item - > randomized_distance < < std : : endl ;
grouter_debug ( ) < < " recv time = " < < info . received_time_TS < < std : : endl ;
2015-04-09 17:34:50 -04:00
grouter_debug ( ) < < " client id = " < < std : : hex < < data_item - > service_id < < std : : dec < < std : : endl ;
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < " tunnel hash = " < < info . tunnel_hash < < std : : endl ;
2015-04-18 15:59:27 -04:00
grouter_debug ( ) < < " item hash = " < < info . item_hash < < std : : endl ;
2015-04-17 17:37:26 -04:00
grouter_debug ( ) < < " routing flags = " < < info . routing_flags < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-24 11:41:07 -05:00
2015-01-11 17:18:28 -05:00
{
2015-01-15 15:33:24 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-11 17:18:28 -05:00
_pending_messages [ propagation_id ] = info ;
}
2015-01-22 09:33:19 -05:00
IndicateConfigChanged ( ) ;
2015-01-11 17:18:28 -05:00
return true ;
2013-11-02 10:35:33 -04:00
}
2015-01-11 17:18:28 -05:00
Sha1CheckSum p3GRouter : : makeTunnelHash ( const RsGxsId & destination , const GRouterServiceId & client )
2013-12-22 12:04:13 -05:00
{
2015-01-11 17:18:28 -05:00
assert ( destination . SIZE_IN_BYTES = = 16 ) ;
assert ( Sha1CheckSum : : SIZE_IN_BYTES = = 20 ) ;
2013-12-22 12:04:13 -05:00
2015-01-11 17:18:28 -05:00
uint8_t bytes [ 20 ] ;
memcpy ( bytes , destination . toByteArray ( ) , 16 ) ;
bytes [ 16 ] = 0 ;
bytes [ 17 ] = 0 ;
bytes [ 18 ] = ( client > > 8 ) & 0xff ;
bytes [ 19 ] = client & 0xff ;
2013-12-22 12:04:13 -05:00
2015-12-07 22:39:45 -05:00
return RsDirUtil : : sha1sum ( bytes , 20 ) ;
2013-12-22 12:04:13 -05:00
}
2016-01-07 21:01:50 -05:00
# ifdef TO_REMOVE
bool p3GRouter : : locked_getGxsOwnIdAndClientIdFromHash ( const TurtleFileHash & sum , RsGxsId & gxs_id , GRouterServiceId & client_id )
2015-01-15 15:33:24 -05:00
{
assert ( gxs_id . SIZE_IN_BYTES = = 16 ) ;
assert ( Sha1CheckSum : : SIZE_IN_BYTES = = 20 ) ;
2013-12-22 12:04:13 -05:00
2015-12-07 22:39:45 -05:00
//gxs_id = RsGxsId(sum.toByteArray());// takes the first 16 bytes
//client_id = sum.toByteArray()[19] + (sum.toByteArray()[18] << 8) ;
std : : map < Sha1CheckSum , GRouterPublishedKeyInfo > : : const_iterator it = _owned_key_ids . find ( sum ) ;
if ( it = = _owned_key_ids . end ( ) )
return false ;
gxs_id = it - > second . authentication_key ;
client_id = it - > second . service_id ;
return true ;
2015-01-15 15:33:24 -05:00
}
2016-01-07 21:01:50 -05:00
# endif
2015-01-11 17:18:28 -05:00
bool p3GRouter : : loadList ( std : : list < RsItem * > & items )
2013-11-02 10:35:33 -04:00
{
2015-04-15 16:48:30 -04:00
{
2015-01-15 15:33:24 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2013-12-27 15:06:47 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-15 16:48:30 -04:00
grouter_debug ( ) < < " p3GRouter::loadList() : " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-27 15:06:47 -05:00
2015-04-15 16:48:30 -04:00
_routing_matrix . loadList ( items ) ;
2013-12-27 15:06:47 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-04-15 16:48:30 -04:00
// remove all existing objects.
//
grouter_debug ( ) < < " removing all existing items ( " < < _pending_messages . size ( ) < < " items to delete). " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-27 15:06:47 -05:00
2015-04-15 16:48:30 -04:00
if ( ! _pending_messages . empty ( ) )
std : : cerr < < " WARNING: pending msg list is not empty. List will be cleared. " < < std : : endl ;
2015-01-22 04:50:44 -05:00
2015-04-15 16:48:30 -04:00
// clear the existing list.
//
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it ( _pending_messages . begin ( ) ) ; it ! = _pending_messages . end ( ) ; + + it )
delete it - > second . data_item ;
2013-12-27 15:06:47 -05:00
2015-04-15 16:48:30 -04:00
_pending_messages . clear ( ) ;
2013-12-27 15:06:47 -05:00
2015-04-15 16:48:30 -04:00
for ( std : : list < RsItem * > : : const_iterator it ( items . begin ( ) ) ; it ! = items . end ( ) ; + + it )
2015-01-22 04:50:44 -05:00
{
2015-04-15 16:48:30 -04:00
RsGRouterRoutingInfoItem * itm1 = NULL ;
if ( NULL ! = ( itm1 = dynamic_cast < RsGRouterRoutingInfoItem * > ( * it ) ) )
{
2015-04-18 15:59:27 -04:00
// clean data state
itm1 - > tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ;
2015-04-15 16:48:30 -04:00
_pending_messages [ itm1 - > data_item - > routing_id ] = * itm1 ;
2013-12-27 15:06:47 -05:00
2015-04-15 16:48:30 -04:00
itm1 - > data_item = NULL ; // prevents deletion.
2015-04-18 15:59:27 -04:00
itm1 - > receipt_item = NULL ; // prevents deletion.
2015-04-15 16:48:30 -04:00
}
2013-12-27 15:06:47 -05:00
2015-04-15 16:48:30 -04:00
delete * it ;
}
2015-01-11 17:18:28 -05:00
}
2015-04-25 09:47:37 -04:00
# ifdef GROUTER_DEBUG
2015-04-15 16:48:30 -04:00
debugDump ( ) ;
2015-04-25 09:47:37 -04:00
# endif
2015-12-30 18:20:09 -05:00
items . clear ( ) ;
2015-01-22 04:50:44 -05:00
return true ;
2013-11-02 10:35:33 -04:00
}
2013-12-27 15:06:47 -05:00
bool p3GRouter : : saveList ( bool & cleanup , std : : list < RsItem * > & items )
2013-11-02 10:35:33 -04:00
{
2015-01-22 04:50:44 -05:00
// We save
// - the routing clues
// - the pending items
2013-12-22 12:04:13 -05:00
2015-01-22 04:50:44 -05:00
cleanup = true ; // the client should delete the items.
2013-12-27 15:06:47 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-22 04:50:44 -05:00
grouter_debug ( ) < < " p3GRouter::saveList()... " < < std : : endl ;
grouter_debug ( ) < < " saving routing clues. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-27 15:06:47 -05:00
2015-01-22 04:50:44 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-15 15:33:24 -05:00
_routing_matrix . saveList ( items ) ;
2013-12-27 15:06:47 -05:00
2014-03-29 19:03:04 -04:00
# ifdef GROUTER_DEBUG
2015-01-11 17:18:28 -05:00
grouter_debug ( ) < < " saving pending items. " < < std : : endl ;
2014-03-29 19:03:04 -04:00
# endif
2013-12-27 15:06:47 -05:00
2015-01-22 04:50:44 -05:00
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : const_iterator it ( _pending_messages . begin ( ) ) ; it ! = _pending_messages . end ( ) ; + + it )
{
RsGRouterRoutingInfoItem * item = new RsGRouterRoutingInfoItem ;
2013-12-27 15:06:47 -05:00
2015-01-22 04:50:44 -05:00
* ( GRouterRoutingInfo * ) item = it - > second ; // copy all members
2013-12-27 15:06:47 -05:00
2015-01-22 04:50:44 -05:00
item - > data_item = it - > second . data_item - > duplicate ( ) ; // deep copy, because we call delete on the object, and the item might be removed before we handle it in the client.
2015-04-18 15:59:27 -04:00
if ( it - > second . receipt_item ! = NULL )
item - > receipt_item = it - > second . receipt_item - > duplicate ( ) ;
2015-01-22 09:33:19 -05:00
2015-01-22 04:50:44 -05:00
items . push_back ( item ) ;
2015-01-11 17:18:28 -05:00
}
2013-12-27 15:06:47 -05:00
2015-01-22 04:50:44 -05:00
return true ;
2013-11-02 10:35:33 -04:00
}
2014-04-07 17:36:43 -04:00
bool p3GRouter : : getRoutingMatrixInfo ( RsGRouter : : GRouterRoutingMatrixInfo & info )
2014-03-29 10:18:05 -04:00
{
2015-01-15 15:33:24 -05:00
RS_STACK_MUTEX ( grMtx ) ;
info . per_friend_probabilities . clear ( ) ;
2014-03-29 10:18:05 -04:00
info . friend_ids . clear ( ) ;
info . published_keys . clear ( ) ;
2014-03-29 19:03:04 -04:00
std : : set < RsPeerId > ids ;
2014-04-19 12:02:11 -04:00
mServiceControl - > getPeersConnected ( getServiceInfo ( ) . mServiceType , ids ) ;
2014-03-29 10:18:05 -04:00
2015-01-23 07:13:13 -05:00
info . published_keys = _owned_key_ids ;
2014-03-29 10:18:05 -04:00
2014-03-29 19:03:04 -04:00
for ( std : : set < RsPeerId > : : const_iterator it ( ids . begin ( ) ) ; it ! = ids . end ( ) ; + + it )
2014-03-29 10:18:05 -04:00
info . friend_ids . push_back ( * it ) ;
std : : vector < GRouterKeyId > known_keys ;
std : : vector < float > probas ;
_routing_matrix . getListOfKnownKeys ( known_keys ) ;
for ( uint32_t i = 0 ; i < known_keys . size ( ) ; + + i )
{
_routing_matrix . computeRoutingProbabilities ( known_keys [ i ] , info . friend_ids , probas ) ;
info . per_friend_probabilities [ known_keys [ i ] ] = probas ;
}
return true ;
}
2014-04-07 17:36:43 -04:00
bool p3GRouter : : getRoutingCacheInfo ( std : : vector < GRouterRoutingCacheInfo > & infos )
2014-03-29 10:18:05 -04:00
{
2015-01-23 07:13:13 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2015-01-15 15:33:24 -05:00
infos . clear ( ) ;
2014-03-29 10:18:05 -04:00
2015-01-23 07:13:13 -05:00
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : const_iterator it ( _pending_messages . begin ( ) ) ; it ! = _pending_messages . end ( ) ; + + it )
{
GRouterRoutingCacheInfo cinfo ;
2014-03-29 10:18:05 -04:00
2015-01-23 07:13:13 -05:00
cinfo . mid = it - > first ;
2015-04-18 15:59:27 -04:00
cinfo . local_origin = it - > second . incoming_routes . ids ;
2015-01-22 04:50:44 -05:00
cinfo . destination = it - > second . data_item - > destination_key ;
2015-01-23 07:13:13 -05:00
cinfo . routing_time = it - > second . received_time_TS ;
cinfo . last_tunnel_attempt_time = it - > second . last_tunnel_request_TS ;
2015-04-20 17:24:22 -04:00
cinfo . last_sent_time = it - > second . last_sent_TS ;
2015-01-23 07:13:13 -05:00
cinfo . receipt_available = ( it - > second . receipt_item ! = NULL ) ;
cinfo . data_status = it - > second . data_status ;
cinfo . tunnel_status = it - > second . tunnel_status ;
cinfo . data_size = it - > second . data_item - > data_size ;
2015-04-18 15:59:27 -04:00
cinfo . item_hash = it - > second . item_hash ;
2015-01-23 07:13:13 -05:00
infos . push_back ( cinfo ) ;
}
return true ;
2014-03-29 10:18:05 -04:00
}
2015-10-26 23:38:10 -04:00
bool p3GRouter : : getTrackingInfo ( const RsGxsMessageId & mid , RsPeerId & provider_id )
{
RS_STACK_MUTEX ( grMtx ) ;
return _routing_matrix . getTrackingInfo ( mid , provider_id ) ;
}
2013-11-05 16:15:26 -05:00
// Dump everything
//
void p3GRouter : : debugDump ( )
{
2015-01-15 15:33:24 -05:00
RS_STACK_MUTEX ( grMtx ) ;
2013-12-27 15:06:47 -05:00
2013-11-05 16:15:26 -05:00
time_t now = time ( NULL ) ;
2014-04-13 15:27:50 -04:00
grouter_debug ( ) < < " Full dump of Global Router state: " < < std : : endl ;
grouter_debug ( ) < < " Owned keys : " < < std : : endl ;
2013-11-05 16:15:26 -05:00
2015-01-11 17:18:28 -05:00
for ( std : : map < Sha1CheckSum , GRouterPublishedKeyInfo > : : const_iterator it ( _owned_key_ids . begin ( ) ) ; it ! = _owned_key_ids . end ( ) ; + + it )
2013-11-05 16:15:26 -05:00
{
2016-01-07 21:01:50 -05:00
grouter_debug ( ) < < " Hash : " < < it - > first < < std : : endl ;
grouter_debug ( ) < < " Key : " < < it - > second . authentication_key < < std : : endl ;
2014-04-13 15:27:50 -04:00
grouter_debug ( ) < < " Service id : " < < std : : hex < < it - > second . service_id < < std : : dec < < std : : endl ;
grouter_debug ( ) < < " Description : " < < it - > second . description_string < < std : : endl ;
2013-11-05 16:15:26 -05:00
}
2014-04-13 15:27:50 -04:00
grouter_debug ( ) < < " Registered services: " < < std : : endl ;
2013-11-05 16:15:26 -05:00
for ( std : : map < GRouterServiceId , GRouterClientService * > : : const_iterator it ( _registered_services . begin ( ) ) ; it ! = _registered_services . end ( ) ; + + it )
2014-04-13 15:27:50 -04:00
grouter_debug ( ) < < " " < < std : : hex < < it - > first < < " " < < std : : dec < < ( void * ) it - > second < < std : : endl ;
2013-11-05 16:15:26 -05:00
2014-04-13 15:27:50 -04:00
grouter_debug ( ) < < " Data items: " < < std : : endl ;
2014-03-29 10:18:05 -04:00
2015-04-15 16:48:30 -04:00
static const std : : string statusString [ 6 ] = { " Unkn " , " Pend " , " Sent " , " Receipt OK " , " Ongoing " , " Done " } ;
2014-03-29 10:18:05 -04:00
for ( std : : map < GRouterMsgPropagationId , GRouterRoutingInfo > : : iterator it ( _pending_messages . begin ( ) ) ; it ! = _pending_messages . end ( ) ; + + it )
2015-01-11 17:18:28 -05:00
{
2016-01-07 21:01:50 -05:00
grouter_debug ( ) < < " Msg id: " < < std : : hex < < it - > first < < std : : dec ;
grouter_debug ( ) < < " data hash: " < < it - > second . item_hash ;
grouter_debug ( ) < < " client id: " < < std : : hex < < it - > second . client_id < < std : : dec ;
grouter_debug ( ) < < " Flags: " < < std : : hex < < it - > second . routing_flags < < std : : dec ;
grouter_debug ( ) < < " Destination: " < < it - > second . data_item - > destination_key ;
grouter_debug ( ) < < " Received: " < < now - it - > second . received_time_TS < < " secs ago. " ;
grouter_debug ( ) < < " Last sent: " < < now - it - > second . last_sent_TS < < " secs ago. " ;
grouter_debug ( ) < < " Transaction TS: " < < now - it - > second . data_transaction_TS < < " secs ago. " ;
grouter_debug ( ) < < " Data Status: " < < statusString [ it - > second . data_status ] < < std : : endl ;
grouter_debug ( ) < < " Tunl Status: " < < statusString [ it - > second . tunnel_status ] < < std : : endl ;
grouter_debug ( ) < < " Receipt ok: " < < ( it - > second . receipt_item ! = NULL ) < < std : : endl ;
2015-01-11 17:18:28 -05:00
}
grouter_debug ( ) < < " Tunnels: " < < std : : endl ;
2015-04-09 17:34:50 -04:00
for ( std : : map < TurtleFileHash , GRouterTunnelInfo > : : const_iterator it ( _tunnels . begin ( ) ) ; it ! = _tunnels . end ( ) ; + + it )
2015-01-11 17:18:28 -05:00
{
grouter_debug ( ) < < " hash: " < < it - > first < < " , first received: " < < now - it - > second . last_tunnel_ok_TS < < " (secs ago), last received: " < < now - it - > second . last_tunnel_ok_TS < < std : : endl ;
2015-04-09 17:34:50 -04:00
for ( std : : set < TurtleVirtualPeerId > : : const_iterator it2 = it - > second . virtual_peers . begin ( ) ; it2 ! = it - > second . virtual_peers . end ( ) ; + + it2 )
grouter_debug ( ) < < " " < < ( * it2 ) < < std : : endl ;
2015-01-11 17:18:28 -05:00
}
2014-03-29 10:18:05 -04:00
2015-04-09 17:34:50 -04:00
grouter_debug ( ) < < " Incoming data pipes: " < < std : : endl ;
for ( std : : map < RsPeerId , GRouterDataInfo > : : const_iterator it ( _incoming_data_pipes . begin ( ) ) ; it ! = _incoming_data_pipes . end ( ) ; + + it )
if ( it - > second . incoming_data_buffer ! = NULL )
grouter_debug ( ) < < " " < < it - > first < < " : offset= " < < it - > second . incoming_data_buffer - > chunk_start < < " size= " < < it - > second . incoming_data_buffer - > chunk_size < < " over " < < it - > second . incoming_data_buffer - > total_size < < std : : endl ;
else
grouter_debug ( ) < < " " < < it - > first < < " empty. " < < std : : endl ;
grouter_debug ( ) < < " Routing matrix: " < < std : : endl ;
2013-11-05 16:15:26 -05:00
2015-10-27 22:41:29 -04:00
if ( _debug_enabled )
_routing_matrix . debugDump ( ) ;
2013-11-05 16:15:26 -05:00
}
2013-11-02 10:35:33 -04:00