2014-10-05 12:54:59 +00:00
# include <algorithm>
2015-01-02 12:35:38 +00:00
# include <cassert>
2017-10-27 12:42:54 +00:00
# include <string>
2016-05-11 19:12:38 +00:00
# include "Crypto.h"
2014-10-05 12:54:59 +00:00
# include "Log.h"
2016-02-11 00:00:00 +00:00
# include "FS.h"
2014-12-25 21:47:15 +00:00
# include "Timestamp.h"
2017-04-22 00:04:16 +00:00
# include "NetDb.hpp"
2015-01-06 00:32:46 +00:00
# include "Destination.h"
2016-04-27 16:08:08 +00:00
# include "util.h"
2014-10-05 12:54:59 +00:00
namespace i2p
{
2014-10-16 16:37:39 +00:00
namespace client
2014-10-05 12:54:59 +00:00
{
2016-05-23 14:33:01 +00:00
LeaseSetDestination : : LeaseSetDestination ( bool isPublic , const std : : map < std : : string , std : : string > * params ) :
2017-08-31 16:08:22 +00:00
m_IsRunning ( false ) , m_Thread ( nullptr ) , m_IsPublic ( isPublic ) ,
m_PublishReplyToken ( 0 ) , m_LastSubmissionTime ( 0 ) , m_PublishConfirmationTimer ( m_Service ) ,
2019-01-11 18:58:02 +00:00
m_PublishVerificationTimer ( m_Service ) , m_PublishDelayTimer ( m_Service ) , m_CleanupTimer ( m_Service ) ,
2019-09-06 15:02:19 +00:00
m_LeaseSetType ( DEFAULT_LEASESET_TYPE ) , m_AuthType ( i2p : : data : : ENCRYPTED_LEASESET_AUTH_TYPE_NONE )
2014-10-05 12:54:59 +00:00
{
2016-10-26 00:00:00 +00:00
int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH ;
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY ;
int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH ;
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY ;
2016-01-24 01:52:21 +00:00
int numTags = DEFAULT_TAGS_TO_SEND ;
2015-06-10 19:32:55 +00:00
std : : shared_ptr < std : : vector < i2p : : data : : IdentHash > > explicitPeers ;
2018-01-06 03:48:51 +00:00
try
2017-10-04 16:27:08 +00:00
{
2018-01-06 03:48:51 +00:00
if ( params )
2017-10-04 16:27:08 +00:00
{
2016-10-26 00:00:00 +00:00
auto it = params - > find ( I2CP_PARAM_INBOUND_TUNNEL_LENGTH ) ;
if ( it ! = params - > end ( ) )
inLen = std : : stoi ( it - > second ) ;
it = params - > find ( I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH ) ;
if ( it ! = params - > end ( ) )
outLen = std : : stoi ( it - > second ) ;
it = params - > find ( I2CP_PARAM_INBOUND_TUNNELS_QUANTITY ) ;
if ( it ! = params - > end ( ) )
inQty = std : : stoi ( it - > second ) ;
it = params - > find ( I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY ) ;
if ( it ! = params - > end ( ) )
outQty = std : : stoi ( it - > second ) ;
it = params - > find ( I2CP_PARAM_TAGS_TO_SEND ) ;
if ( it ! = params - > end ( ) )
numTags = std : : stoi ( it - > second ) ;
LogPrint ( eLogInfo , " Destination: parameters for tunnel set to: " , inQty , " inbound ( " , inLen , " hops), " , outQty , " outbound ( " , outLen , " hops), " , numTags , " tags " ) ;
it = params - > find ( I2CP_PARAM_EXPLICIT_PEERS ) ;
if ( it ! = params - > end ( ) )
2015-06-10 19:32:55 +00:00
{
2016-10-26 00:00:00 +00:00
explicitPeers = std : : make_shared < std : : vector < i2p : : data : : IdentHash > > ( ) ;
std : : stringstream ss ( it - > second ) ;
std : : string b64 ;
while ( std : : getline ( ss , b64 , ' , ' ) )
{
i2p : : data : : IdentHash ident ;
ident . FromBase64 ( b64 ) ;
explicitPeers - > push_back ( ident ) ;
LogPrint ( eLogInfo , " Destination: Added to explicit peers list: " , b64 ) ;
}
2015-06-10 19:32:55 +00:00
}
2017-10-04 16:27:08 +00:00
it = params - > find ( I2CP_PARAM_INBOUND_NICKNAME ) ;
2018-01-06 03:48:51 +00:00
if ( it ! = params - > end ( ) ) m_Nickname = it - > second ;
2017-12-20 16:38:35 +00:00
else // try outbound
2018-01-06 03:48:51 +00:00
{
2017-12-20 16:38:35 +00:00
it = params - > find ( I2CP_PARAM_OUTBOUND_NICKNAME ) ;
2018-01-06 03:48:51 +00:00
if ( it ! = params - > end ( ) ) m_Nickname = it - > second ;
2018-07-10 09:39:21 +00:00
// otherwise we set default nickname in Start when we know local address
2017-12-20 16:38:35 +00:00
}
2019-01-11 18:58:02 +00:00
it = params - > find ( I2CP_PARAM_LEASESET_TYPE ) ;
if ( it ! = params - > end ( ) )
m_LeaseSetType = std : : stoi ( it - > second ) ;
2019-09-06 15:02:19 +00:00
if ( m_LeaseSetType = = i2p : : data : : NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 )
{
// authentication for encrypted LeaseSet
it = params - > find ( I2CP_PARAM_LEASESET_AUTH_TYPE ) ;
if ( it ! = params - > end ( ) )
{
auto authType = std : : stoi ( it - > second ) ;
if ( authType > = i2p : : data : : ENCRYPTED_LEASESET_AUTH_TYPE_NONE & & authType < = i2p : : data : : ENCRYPTED_LEASESET_AUTH_TYPE_PSK )
m_AuthType = authType ;
else
LogPrint ( eLogError , " Destination: Unknown auth type " , authType ) ;
}
}
2019-06-07 18:51:08 +00:00
it = params - > find ( I2CP_PARAM_LEASESET_PRIV_KEY ) ;
if ( it ! = params - > end ( ) )
{
m_LeaseSetPrivKey . reset ( new i2p : : data : : Tag < 32 > ( ) ) ;
if ( m_LeaseSetPrivKey - > FromBase64 ( it - > second ) ! = 32 )
{
LogPrint ( eLogError , " Destination: invalid value i2cp.leaseSetPrivKey " , it - > second ) ;
m_LeaseSetPrivKey . reset ( nullptr ) ;
}
}
2015-06-10 19:32:55 +00:00
}
2018-01-06 03:48:51 +00:00
}
catch ( std : : exception & ex )
2017-10-04 16:27:08 +00:00
{
2016-10-26 00:00:00 +00:00
LogPrint ( eLogError , " Destination: unable to parse parameters for destination: " , ex . what ( ) ) ;
}
2016-01-24 01:52:21 +00:00
SetNumTags ( numTags ) ;
2016-10-26 00:00:00 +00:00
m_Pool = i2p : : tunnel : : tunnels . CreateTunnelPool ( inLen , outLen , inQty , outQty ) ;
2015-06-10 19:32:55 +00:00
if ( explicitPeers )
m_Pool - > SetExplicitPeers ( explicitPeers ) ;
2016-11-15 15:20:09 +00:00
if ( params )
{
auto itr = params - > find ( I2CP_PARAM_MAX_TUNNEL_LATENCY ) ;
if ( itr ! = params - > end ( ) ) {
auto maxlatency = std : : stoi ( itr - > second ) ;
itr = params - > find ( I2CP_PARAM_MIN_TUNNEL_LATENCY ) ;
if ( itr ! = params - > end ( ) ) {
auto minlatency = std : : stoi ( itr - > second ) ;
if ( minlatency > 0 & & maxlatency > 0 ) {
// set tunnel pool latency
LogPrint ( eLogInfo , " Destination: requiring tunnel latency [ " , minlatency , " ms, " , maxlatency , " ms] " ) ;
m_Pool - > RequireLatency ( minlatency , maxlatency ) ;
}
}
}
}
2014-10-05 12:54:59 +00:00
}
2016-05-23 14:33:01 +00:00
LeaseSetDestination : : ~ LeaseSetDestination ( )
2014-10-05 12:54:59 +00:00
{
2017-08-31 16:08:22 +00:00
if ( m_IsRunning )
2014-12-19 17:07:54 +00:00
Stop ( ) ;
2014-10-13 15:21:57 +00:00
if ( m_Pool )
2017-08-31 16:08:22 +00:00
i2p : : tunnel : : tunnels . DeleteTunnelPool ( m_Pool ) ;
2016-12-02 00:23:55 +00:00
for ( auto & it : m_LeaseSetRequests )
it . second - > Complete ( nullptr ) ;
2017-08-31 16:08:22 +00:00
}
2014-10-05 12:54:59 +00:00
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : Run ( )
2014-10-09 14:05:28 +00:00
{
2014-12-02 02:26:51 +00:00
while ( m_IsRunning )
{
try
2017-08-31 16:08:22 +00:00
{
2014-12-16 03:50:11 +00:00
m_Service . run ( ) ;
2014-12-02 02:26:51 +00:00
}
catch ( std : : exception & ex )
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogError , " Destination: runtime exception: " , ex . what ( ) ) ;
2017-08-31 16:08:22 +00:00
}
}
}
2014-10-09 14:05:28 +00:00
2016-05-23 18:31:22 +00:00
bool LeaseSetDestination : : Start ( )
2017-08-31 16:08:22 +00:00
{
2015-01-03 20:20:11 +00:00
if ( ! m_IsRunning )
2017-08-31 16:08:22 +00:00
{
2017-10-04 16:40:43 +00:00
if ( m_Nickname . empty ( ) )
m_Nickname = i2p : : data : : GetIdentHashAbbreviation ( GetIdentHash ( ) ) ; // set default nickname
2017-04-03 19:05:10 +00:00
LoadTags ( ) ;
2015-01-03 20:20:11 +00:00
m_IsRunning = true ;
2015-12-16 19:52:48 +00:00
m_Pool - > SetLocalDestination ( shared_from_this ( ) ) ;
2017-08-31 16:08:22 +00:00
m_Pool - > SetActive ( true ) ;
2015-01-23 17:48:25 +00:00
m_CleanupTimer . expires_from_now ( boost : : posix_time : : minutes ( DESTINATION_CLEANUP_TIMEOUT ) ) ;
2016-05-23 14:33:01 +00:00
m_CleanupTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandleCleanupTimer ,
2017-08-31 16:08:22 +00:00
shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
2016-11-28 18:47:10 +00:00
m_Thread = new std : : thread ( std : : bind ( & LeaseSetDestination : : Run , shared_from_this ( ) ) ) ;
2017-08-31 16:08:22 +00:00
2016-05-23 18:31:22 +00:00
return true ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
else
return false ;
2014-10-09 14:05:28 +00:00
}
2017-08-31 16:08:22 +00:00
2016-05-23 18:31:22 +00:00
bool LeaseSetDestination : : Stop ( )
2017-08-31 16:08:22 +00:00
{
2015-01-03 20:20:11 +00:00
if ( m_IsRunning )
2017-08-31 16:08:22 +00:00
{
2015-01-23 17:48:25 +00:00
m_CleanupTimer . cancel ( ) ;
2016-02-11 19:45:33 +00:00
m_PublishConfirmationTimer . cancel ( ) ;
2017-08-31 16:08:22 +00:00
m_PublishVerificationTimer . cancel ( ) ;
2016-11-28 19:37:17 +00:00
2015-01-03 20:20:11 +00:00
m_IsRunning = false ;
if ( m_Pool )
2017-08-31 16:08:22 +00:00
{
2015-01-03 20:20:11 +00:00
m_Pool - > SetLocalDestination ( nullptr ) ;
i2p : : tunnel : : tunnels . StopTunnelPool ( m_Pool ) ;
2017-08-31 16:08:22 +00:00
}
2015-01-03 20:20:11 +00:00
m_Service . stop ( ) ;
if ( m_Thread )
2017-08-31 16:08:22 +00:00
{
m_Thread - > join ( ) ;
2015-01-03 20:20:11 +00:00
delete m_Thread ;
m_Thread = 0 ;
2017-08-31 16:08:22 +00:00
}
2017-04-03 19:05:10 +00:00
SaveTags ( ) ;
2016-11-29 03:47:37 +00:00
CleanUp ( ) ; // GarlicDestination
2016-05-23 18:31:22 +00:00
return true ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
else
return false ;
2017-08-31 16:08:22 +00:00
}
2018-01-02 16:34:58 +00:00
bool LeaseSetDestination : : Reconfigure ( std : : map < std : : string , std : : string > params )
{
auto itr = params . find ( " i2cp.dontPublishLeaseSet " ) ;
if ( itr ! = params . end ( ) )
{
m_IsPublic = itr - > second ! = " true " ;
}
int inLen , outLen , inQuant , outQuant , numTags , minLatency , maxLatency ;
std : : map < std : : string , int & > intOpts = {
{ I2CP_PARAM_INBOUND_TUNNEL_LENGTH , inLen } ,
{ I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH , outLen } ,
{ I2CP_PARAM_INBOUND_TUNNELS_QUANTITY , inQuant } ,
{ I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY , outQuant } ,
{ I2CP_PARAM_TAGS_TO_SEND , numTags } ,
{ I2CP_PARAM_MIN_TUNNEL_LATENCY , minLatency } ,
{ I2CP_PARAM_MAX_TUNNEL_LATENCY , maxLatency }
} ;
auto pool = GetTunnelPool ( ) ;
inLen = pool - > GetNumInboundHops ( ) ;
outLen = pool - > GetNumOutboundHops ( ) ;
inQuant = pool - > GetNumInboundTunnels ( ) ;
outQuant = pool - > GetNumOutboundTunnels ( ) ;
minLatency = 0 ;
maxLatency = 0 ;
2018-01-02 17:06:10 +00:00
for ( auto & opt : intOpts )
2018-01-02 16:34:58 +00:00
{
itr = params . find ( opt . first ) ;
if ( itr ! = params . end ( ) )
{
opt . second = std : : stoi ( itr - > second ) ;
}
}
pool - > RequireLatency ( minLatency , maxLatency ) ;
return pool - > Reconfigure ( inLen , outLen , inQuant , outQuant ) ;
}
2019-03-27 20:04:46 +00:00
std : : shared_ptr < i2p : : data : : LeaseSet > LeaseSetDestination : : FindLeaseSet ( const i2p : : data : : IdentHash & ident )
2014-10-05 12:54:59 +00:00
{
2016-10-12 13:39:16 +00:00
std : : shared_ptr < i2p : : data : : LeaseSet > remoteLS ;
2016-07-22 13:56:17 +00:00
{
2016-10-12 13:39:16 +00:00
std : : lock_guard < std : : mutex > lock ( m_RemoteLeaseSetsMutex ) ;
auto it = m_RemoteLeaseSets . find ( ident ) ;
if ( it ! = m_RemoteLeaseSets . end ( ) )
remoteLS = it - > second ;
}
2017-08-31 16:08:22 +00:00
if ( remoteLS )
2016-10-12 13:39:16 +00:00
{
if ( ! remoteLS - > IsExpired ( ) )
2016-07-22 13:56:17 +00:00
{
2016-10-12 13:39:16 +00:00
if ( remoteLS - > ExpiresSoon ( ) )
2016-07-22 13:56:17 +00:00
{
LogPrint ( eLogDebug , " Destination: Lease Set expires soon, updating before expire " ) ;
// update now before expiration for smooth handover
2016-10-12 13:39:16 +00:00
auto s = shared_from_this ( ) ;
RequestDestination ( ident , [ s , ident ] ( std : : shared_ptr < i2p : : data : : LeaseSet > ls ) {
2016-07-22 13:56:17 +00:00
if ( ls & & ! ls - > IsExpired ( ) )
{
ls - > PopulateLeases ( ) ;
2016-10-10 13:04:24 +00:00
{
2016-10-12 13:39:16 +00:00
std : : lock_guard < std : : mutex > _lock ( s - > m_RemoteLeaseSetsMutex ) ;
s - > m_RemoteLeaseSets [ ident ] = ls ;
2016-10-10 13:04:24 +00:00
}
2016-07-22 13:56:17 +00:00
}
} ) ;
}
2016-10-12 13:39:16 +00:00
return remoteLS ;
2016-07-22 13:56:17 +00:00
}
2014-10-05 12:54:59 +00:00
else
2016-10-25 18:07:34 +00:00
{
2016-02-08 00:45:06 +00:00
LogPrint ( eLogWarning , " Destination: remote LeaseSet expired " ) ;
2016-10-25 18:07:34 +00:00
std : : lock_guard < std : : mutex > lock ( m_RemoteLeaseSetsMutex ) ;
m_RemoteLeaseSets . erase ( ident ) ;
return nullptr ;
}
2017-08-31 16:08:22 +00:00
}
2014-10-16 16:37:39 +00:00
else
2017-08-31 16:08:22 +00:00
{
2014-10-16 16:37:39 +00:00
auto ls = i2p : : data : : netdb . FindLeaseSet ( ident ) ;
2016-02-13 01:56:29 +00:00
if ( ls & & ! ls - > IsExpired ( ) )
2014-10-16 16:37:39 +00:00
{
2016-02-08 00:45:06 +00:00
ls - > PopulateLeases ( ) ; // since we don't store them in netdb
2016-10-12 13:39:16 +00:00
std : : lock_guard < std : : mutex > _lock ( m_RemoteLeaseSetsMutex ) ;
2016-10-03 15:01:31 +00:00
m_RemoteLeaseSets [ ident ] = ls ;
2014-10-16 16:37:39 +00:00
return ls ;
2017-08-31 16:08:22 +00:00
}
2014-10-16 16:37:39 +00:00
}
return nullptr ;
2016-10-03 15:01:31 +00:00
}
2014-10-05 12:54:59 +00:00
2016-05-25 19:10:28 +00:00
std : : shared_ptr < const i2p : : data : : LocalLeaseSet > LeaseSetDestination : : GetLeaseSet ( )
2014-10-05 12:54:59 +00:00
{
if ( ! m_Pool ) return nullptr ;
if ( ! m_LeaseSet )
UpdateLeaseSet ( ) ;
2019-04-10 16:04:19 +00:00
auto ls = GetLeaseSetMt ( ) ;
return ( ls & & ls - > GetInnerLeaseSet ( ) ) ? ls - > GetInnerLeaseSet ( ) : ls ; // always non-encrypted
2019-03-10 13:22:42 +00:00
}
std : : shared_ptr < const i2p : : data : : LocalLeaseSet > LeaseSetDestination : : GetLeaseSetMt ( )
{
2016-10-25 18:07:34 +00:00
std : : lock_guard < std : : mutex > l ( m_LeaseSetMutex ) ;
2014-10-05 12:54:59 +00:00
return m_LeaseSet ;
2017-08-31 16:08:22 +00:00
}
2019-03-10 13:22:42 +00:00
void LeaseSetDestination : : SetLeaseSet ( std : : shared_ptr < const i2p : : data : : LocalLeaseSet > newLeaseSet )
2016-05-29 13:33:50 +00:00
{
2017-08-31 16:08:22 +00:00
{
2016-10-25 18:07:34 +00:00
std : : lock_guard < std : : mutex > l ( m_LeaseSetMutex ) ;
2019-03-10 13:22:42 +00:00
m_LeaseSet = newLeaseSet ;
2016-10-25 18:07:34 +00:00
}
2016-09-01 13:48:04 +00:00
i2p : : garlic : : GarlicDestination : : SetLeaseSetUpdated ( ) ;
2016-05-29 13:33:50 +00:00
if ( m_IsPublic )
{
2018-03-23 15:41:36 +00:00
auto s = shared_from_this ( ) ;
m_Service . post ( [ s ] ( void )
{
s - > m_PublishVerificationTimer . cancel ( ) ;
s - > Publish ( ) ;
} ) ;
2016-05-29 13:33:50 +00:00
}
2017-08-31 16:08:22 +00:00
}
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : UpdateLeaseSet ( )
2014-10-05 12:54:59 +00:00
{
2017-08-31 16:08:22 +00:00
int numTunnels = m_Pool - > GetNumInboundTunnels ( ) + 2 ; // 2 backup tunnels
if ( numTunnels > i2p : : data : : MAX_NUM_LEASES ) numTunnels = i2p : : data : : MAX_NUM_LEASES ; // 16 tunnels maximum
2016-05-29 13:33:50 +00:00
CreateNewLeaseSet ( m_Pool - > GetInboundTunnels ( numTunnels ) ) ;
2017-08-31 16:08:22 +00:00
}
2014-10-16 16:37:39 +00:00
2016-05-23 14:33:01 +00:00
bool LeaseSetDestination : : SubmitSessionKey ( const uint8_t * key , const uint8_t * tag )
2014-12-08 20:36:00 +00:00
{
2014-12-16 03:50:11 +00:00
struct
2014-12-08 20:36:00 +00:00
{
2014-12-16 03:50:11 +00:00
uint8_t k [ 32 ] , t [ 32 ] ;
2017-08-31 16:08:22 +00:00
} data ;
2014-12-16 03:50:11 +00:00
memcpy ( data . k , key , 32 ) ;
memcpy ( data . t , tag , 32 ) ;
2016-02-17 03:57:38 +00:00
auto s = shared_from_this ( ) ;
m_Service . post ( [ s , data ] ( void )
2014-12-09 19:15:02 +00:00
{
2016-02-17 03:57:38 +00:00
s - > AddSessionKey ( data . k , data . t ) ;
2014-12-16 03:50:11 +00:00
} ) ;
return true ;
2014-12-08 20:36:00 +00:00
}
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : ProcessGarlicMessage ( std : : shared_ptr < I2NPMessage > msg )
2014-10-16 16:37:39 +00:00
{
2017-08-31 16:08:22 +00:00
m_Service . post ( std : : bind ( & LeaseSetDestination : : HandleGarlicMessage , shared_from_this ( ) , msg ) ) ;
2014-10-16 16:37:39 +00:00
}
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : ProcessDeliveryStatusMessage ( std : : shared_ptr < I2NPMessage > msg )
2014-10-16 16:37:39 +00:00
{
2020-01-06 19:37:40 +00:00
uint32_t msgID = bufbe32toh ( msg - > GetPayload ( ) + DELIVERY_STATUS_MSGID_OFFSET ) ;
m_Service . post ( std : : bind ( & LeaseSetDestination : : HandleDeliveryStatusMessage , shared_from_this ( ) , msgID ) ) ;
2014-10-16 16:37:39 +00:00
}
2020-01-07 20:20:55 +00:00
void LeaseSetDestination : : HandleI2NPMessage ( const uint8_t * buf , size_t len )
2014-10-16 16:37:39 +00:00
{
2020-01-16 17:47:08 +00:00
I2NPMessageType typeID = ( I2NPMessageType ) ( buf [ I2NP_HEADER_TYPEID_OFFSET ] ) ;
2020-01-07 20:20:55 +00:00
LeaseSetDestination : : HandleCloveI2NPMessage ( typeID , buf + I2NP_HEADER_SIZE , GetI2NPMessageLength ( buf , len ) - I2NP_HEADER_SIZE ) ;
2020-01-06 20:31:20 +00:00
}
2020-01-16 17:47:08 +00:00
bool LeaseSetDestination : : HandleCloveI2NPMessage ( I2NPMessageType typeID , const uint8_t * payload , size_t len )
2020-01-06 20:31:20 +00:00
{
2015-01-02 04:00:33 +00:00
switch ( typeID )
2017-08-31 16:08:22 +00:00
{
2014-10-16 16:37:39 +00:00
case eI2NPData :
2020-01-06 20:31:20 +00:00
HandleDataMessage ( payload , len ) ;
2014-10-16 16:37:39 +00:00
break ;
2015-06-30 01:40:43 +00:00
case eI2NPDeliveryStatus :
// we assume tunnel tests non-encrypted
2020-01-06 20:31:20 +00:00
HandleDeliveryStatusMessage ( bufbe32toh ( payload + DELIVERY_STATUS_MSGID_OFFSET ) ) ;
2017-08-31 16:08:22 +00:00
break ;
2014-10-16 16:37:39 +00:00
case eI2NPDatabaseStore :
2020-01-06 20:31:20 +00:00
HandleDatabaseStoreMessage ( payload , len ) ;
2014-12-25 21:47:15 +00:00
break ;
case eI2NPDatabaseSearchReply :
2020-01-06 20:31:20 +00:00
HandleDatabaseSearchReplyMessage ( payload , len ) ;
2017-08-31 16:08:22 +00:00
break ;
2014-10-16 16:37:39 +00:00
default :
2020-01-07 20:20:55 +00:00
LogPrint ( eLogWarning , " Destination: Unexpected I2NP message type " , typeID ) ;
2020-01-06 20:31:20 +00:00
return false ;
2017-08-31 16:08:22 +00:00
}
2020-01-06 20:31:20 +00:00
return true ;
2017-08-31 16:08:22 +00:00
}
2014-10-16 16:37:39 +00:00
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : HandleDatabaseStoreMessage ( const uint8_t * buf , size_t len )
2014-10-16 16:37:39 +00:00
{
2015-01-03 02:11:40 +00:00
uint32_t replyToken = bufbe32toh ( buf + DATABASE_STORE_REPLY_TOKEN_OFFSET ) ;
size_t offset = DATABASE_STORE_HEADER_SIZE ;
2017-08-31 16:08:22 +00:00
if ( replyToken )
2015-01-30 20:29:33 +00:00
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogInfo , " Destination: Reply token is ignored for DatabaseStore " ) ;
2014-10-16 16:37:39 +00:00
offset + = 36 ;
2015-01-30 20:29:33 +00:00
}
2016-11-07 23:32:22 +00:00
i2p : : data : : IdentHash key ( buf + DATABASE_STORE_KEY_OFFSET ) ;
2015-04-07 16:02:25 +00:00
std : : shared_ptr < i2p : : data : : LeaseSet > leaseSet ;
2019-03-07 19:52:59 +00:00
switch ( buf [ DATABASE_STORE_TYPE_OFFSET ] )
2014-10-16 16:37:39 +00:00
{
2019-03-07 19:52:59 +00:00
case i2p : : data : : NETDB_STORE_TYPE_LEASESET : // 1
case i2p : : data : : NETDB_STORE_TYPE_STANDARD_LEASESET2 : // 3
2014-10-16 16:37:39 +00:00
{
2019-03-07 19:52:59 +00:00
LogPrint ( eLogDebug , " Destination: Remote LeaseSet " ) ;
std : : lock_guard < std : : mutex > lock ( m_RemoteLeaseSetsMutex ) ;
auto it = m_RemoteLeaseSets . find ( key ) ;
if ( it ! = m_RemoteLeaseSets . end ( ) )
2017-08-31 16:08:22 +00:00
{
2019-03-07 19:52:59 +00:00
leaseSet = it - > second ;
if ( leaseSet - > IsNewer ( buf + offset , len - offset ) )
{
leaseSet - > Update ( buf + offset , len - offset ) ;
if ( leaseSet - > IsValid ( ) & & leaseSet - > GetIdentHash ( ) = = key )
LogPrint ( eLogDebug , " Destination: Remote LeaseSet updated " ) ;
else
{
LogPrint ( eLogDebug , " Destination: Remote LeaseSet update failed " ) ;
m_RemoteLeaseSets . erase ( it ) ;
leaseSet = nullptr ;
}
}
else
LogPrint ( eLogDebug , " Destination: Remote LeaseSet is older. Not updated " ) ;
}
else
{
if ( buf [ DATABASE_STORE_TYPE_OFFSET ] = = i2p : : data : : NETDB_STORE_TYPE_LEASESET )
leaseSet = std : : make_shared < i2p : : data : : LeaseSet > ( buf + offset , len - offset ) ; // LeaseSet
else
leaseSet = std : : make_shared < i2p : : data : : LeaseSet2 > ( buf [ DATABASE_STORE_TYPE_OFFSET ] , buf + offset , len - offset ) ; // LeaseSet2
2016-11-07 23:32:22 +00:00
if ( leaseSet - > IsValid ( ) & & leaseSet - > GetIdentHash ( ) = = key )
2019-03-07 19:52:59 +00:00
{
if ( leaseSet - > GetIdentHash ( ) ! = GetIdentHash ( ) )
{
LogPrint ( eLogDebug , " Destination: New remote LeaseSet added " ) ;
m_RemoteLeaseSets [ key ] = leaseSet ;
}
else
LogPrint ( eLogDebug , " Destination: Own remote LeaseSet dropped " ) ;
}
2016-02-17 03:57:38 +00:00
else
{
2019-03-07 19:52:59 +00:00
LogPrint ( eLogError , " Destination: New remote LeaseSet failed " ) ;
2016-02-17 03:57:38 +00:00
leaseSet = nullptr ;
}
2015-04-08 14:34:16 +00:00
}
2019-03-07 19:52:59 +00:00
break ;
2014-10-16 16:37:39 +00:00
}
2019-03-07 19:52:59 +00:00
case i2p : : data : : NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 : // 5
2017-08-31 16:08:22 +00:00
{
2019-03-07 19:52:59 +00:00
auto it2 = m_LeaseSetRequests . find ( key ) ;
2019-03-22 19:32:13 +00:00
if ( it2 ! = m_LeaseSetRequests . end ( ) & & it2 - > second - > requestedBlindedKey )
2015-04-08 14:34:16 +00:00
{
2019-06-07 18:51:08 +00:00
auto ls2 = std : : make_shared < i2p : : data : : LeaseSet2 > ( buf + offset , len - offset , it2 - > second - > requestedBlindedKey , m_LeaseSetPrivKey ? * m_LeaseSetPrivKey : nullptr ) ;
2019-03-07 19:52:59 +00:00
if ( ls2 - > IsValid ( ) )
2016-02-11 19:45:33 +00:00
{
2019-03-07 19:52:59 +00:00
m_RemoteLeaseSets [ ls2 - > GetIdentHash ( ) ] = ls2 ; // ident is not key
2019-03-27 20:04:46 +00:00
m_RemoteLeaseSets [ key ] = ls2 ; // also store as key for next lookup
2019-03-07 19:52:59 +00:00
leaseSet = ls2 ;
2016-02-11 19:45:33 +00:00
}
2015-04-08 14:34:16 +00:00
}
else
2019-03-07 19:52:59 +00:00
LogPrint ( eLogInfo , " Destination: Couldn't find request for encrypted LeaseSet2 " ) ;
break ;
2017-08-31 16:08:22 +00:00
}
2019-03-07 19:52:59 +00:00
default :
LogPrint ( eLogError , " Destination: Unexpected client's DatabaseStore type " , buf [ DATABASE_STORE_TYPE_OFFSET ] , " , dropped " ) ;
2017-08-31 16:08:22 +00:00
}
2016-11-07 23:32:22 +00:00
auto it1 = m_LeaseSetRequests . find ( key ) ;
2014-12-28 20:45:58 +00:00
if ( it1 ! = m_LeaseSetRequests . end ( ) )
{
it1 - > second - > requestTimeoutTimer . cancel ( ) ;
2016-11-17 03:28:13 +00:00
if ( it1 - > second ) it1 - > second - > Complete ( leaseSet ) ;
2014-12-28 20:45:58 +00:00
m_LeaseSetRequests . erase ( it1 ) ;
2017-08-31 16:08:22 +00:00
}
2015-01-05 11:36:09 +00:00
}
2014-11-28 18:01:35 +00:00
2016-10-10 12:59:48 +00:00
void LeaseSetDestination : : HandleDatabaseSearchReplyMessage ( const uint8_t * buf , size_t len )
2014-12-25 21:47:15 +00:00
{
i2p : : data : : IdentHash key ( buf ) ;
int num = buf [ 32 ] ; // num
2015-12-18 13:11:56 +00:00
LogPrint ( eLogDebug , " Destination: DatabaseSearchReply for " , key . ToBase64 ( ) , " num= " , num ) ;
2014-12-25 21:47:15 +00:00
auto it = m_LeaseSetRequests . find ( key ) ;
2014-12-27 00:09:44 +00:00
if ( it ! = m_LeaseSetRequests . end ( ) )
2014-12-25 21:47:15 +00:00
{
2015-12-13 15:51:43 +00:00
auto request = it - > second ;
2014-12-25 21:47:15 +00:00
bool found = false ;
2014-12-27 00:09:44 +00:00
if ( request - > excluded . size ( ) < MAX_NUM_FLOODFILLS_PER_REQUEST )
2017-08-31 16:08:22 +00:00
{
2014-12-25 21:47:15 +00:00
for ( int i = 0 ; i < num ; i + + )
2016-10-25 18:07:34 +00:00
{
i2p : : data : : IdentHash peerHash ( buf + 33 + i * 32 ) ;
if ( ! request - > excluded . count ( peerHash ) & & ! i2p : : data : : netdb . FindRouter ( peerHash ) )
2014-12-25 21:47:15 +00:00
{
2016-10-25 18:07:34 +00:00
LogPrint ( eLogInfo , " Destination: Found new floodfill, request it " ) ; // TODO: recheck this message
i2p : : data : : netdb . RequestDestination ( peerHash ) ;
2017-08-31 16:08:22 +00:00
}
2016-10-25 18:07:34 +00:00
}
2017-08-31 16:08:22 +00:00
2016-10-17 22:45:20 +00:00
auto floodfill = i2p : : data : : netdb . GetClosestFloodfill ( key , request - > excluded ) ;
if ( floodfill )
{
LogPrint ( eLogInfo , " Destination: Requesting " , key . ToBase64 ( ) , " at " , floodfill - > GetIdentHash ( ) . ToBase64 ( ) ) ;
if ( SendLeaseSetRequest ( key , floodfill , request ) )
found = true ;
2017-08-31 16:08:22 +00:00
}
}
2014-12-25 21:47:15 +00:00
if ( ! found )
2017-08-31 16:08:22 +00:00
{
2016-10-17 22:45:20 +00:00
LogPrint ( eLogInfo , " Destination: " , key . ToBase64 ( ) , " was not found on " , MAX_NUM_FLOODFILLS_PER_REQUEST , " floodfills " ) ;
2016-11-17 03:28:13 +00:00
request - > Complete ( nullptr ) ;
2014-12-27 00:09:44 +00:00
m_LeaseSetRequests . erase ( key ) ;
2017-08-31 16:08:22 +00:00
}
}
else
2015-12-18 13:11:56 +00:00
LogPrint ( eLogWarning , " Destination: Request for " , key . ToBase64 ( ) , " not found " ) ;
2017-08-31 16:08:22 +00:00
}
2020-01-06 19:37:40 +00:00
void LeaseSetDestination : : HandleDeliveryStatusMessage ( uint32_t msgID )
2014-11-28 18:01:35 +00:00
{
if ( msgID = = m_PublishReplyToken )
{
2016-06-29 21:59:56 +00:00
LogPrint ( eLogDebug , " Destination: Publishing LeaseSet confirmed for " , GetIdentHash ( ) . ToBase32 ( ) ) ;
2014-12-07 21:10:25 +00:00
m_ExcludedFloodfills . clear ( ) ;
2014-11-28 18:01:35 +00:00
m_PublishReplyToken = 0 ;
2016-02-11 19:45:33 +00:00
// schedule verification
m_PublishVerificationTimer . expires_from_now ( boost : : posix_time : : seconds ( PUBLISH_VERIFICATION_TIMEOUT ) ) ;
2016-05-23 14:33:01 +00:00
m_PublishVerificationTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandlePublishVerificationTimer ,
2017-08-31 16:08:22 +00:00
shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
2014-11-28 18:01:35 +00:00
}
else
2020-01-06 19:37:40 +00:00
i2p : : garlic : : GarlicDestination : : HandleDeliveryStatusMessage ( msgID ) ;
2017-08-31 16:08:22 +00:00
}
2014-10-16 16:37:39 +00:00
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : SetLeaseSetUpdated ( )
2017-08-31 16:08:22 +00:00
{
2014-10-16 16:37:39 +00:00
UpdateLeaseSet ( ) ;
2014-11-28 18:01:35 +00:00
}
2017-08-31 16:08:22 +00:00
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : Publish ( )
2017-08-31 16:08:22 +00:00
{
2019-03-10 13:22:42 +00:00
auto leaseSet = GetLeaseSetMt ( ) ;
if ( ! leaseSet | | ! m_Pool )
2014-11-28 18:01:35 +00:00
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogError , " Destination: Can't publish non-existing LeaseSet " ) ;
2014-11-28 18:01:35 +00:00
return ;
}
if ( m_PublishReplyToken )
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogDebug , " Destination: Publishing LeaseSet is pending " ) ;
2014-11-28 18:01:35 +00:00
return ;
}
2017-02-13 01:52:46 +00:00
auto ts = i2p : : util : : GetSecondsSinceEpoch ( ) ;
if ( ts < m_LastSubmissionTime + PUBLISH_MIN_INTERVAL )
{
LogPrint ( eLogDebug , " Destination: Publishing LeaseSet is too fast. Wait for " , PUBLISH_MIN_INTERVAL , " seconds " ) ;
m_PublishDelayTimer . cancel ( ) ;
m_PublishDelayTimer . expires_from_now ( boost : : posix_time : : seconds ( PUBLISH_MIN_INTERVAL ) ) ;
m_PublishDelayTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandlePublishDelayTimer ,
2017-08-31 16:08:22 +00:00
shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
2017-02-13 01:52:46 +00:00
return ;
2017-08-31 16:08:22 +00:00
}
2014-11-28 18:01:35 +00:00
auto outbound = m_Pool - > GetNextOutboundTunnel ( ) ;
if ( ! outbound )
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogError , " Destination: Can't publish LeaseSet. No outbound tunnels " ) ;
2014-11-28 18:01:35 +00:00
return ;
}
2016-05-25 16:55:58 +00:00
auto inbound = m_Pool - > GetNextInboundTunnel ( ) ;
if ( ! inbound )
{
LogPrint ( eLogError , " Destination: Can't publish LeaseSet. No inbound tunnels " ) ;
return ;
}
2019-03-10 13:22:42 +00:00
auto floodfill = i2p : : data : : netdb . GetClosestFloodfill ( leaseSet - > GetIdentHash ( ) , m_ExcludedFloodfills ) ;
2014-11-28 18:01:35 +00:00
if ( ! floodfill )
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogError , " Destination: Can't publish LeaseSet, no more floodfills found " ) ;
2014-12-07 21:10:25 +00:00
m_ExcludedFloodfills . clear ( ) ;
2014-11-28 18:01:35 +00:00
return ;
2017-08-31 16:08:22 +00:00
}
2014-12-07 21:10:25 +00:00
m_ExcludedFloodfills . insert ( floodfill - > GetIdentHash ( ) ) ;
2015-12-18 13:11:56 +00:00
LogPrint ( eLogDebug , " Destination: Publish LeaseSet of " , GetIdentHash ( ) . ToBase32 ( ) ) ;
2015-11-03 14:15:49 +00:00
RAND_bytes ( ( uint8_t * ) & m_PublishReplyToken , 4 ) ;
2019-03-10 13:22:42 +00:00
auto msg = WrapMessage ( floodfill , i2p : : CreateDatabaseStoreMsg ( leaseSet , m_PublishReplyToken , inbound ) ) ;
2014-12-16 03:50:11 +00:00
m_PublishConfirmationTimer . expires_from_now ( boost : : posix_time : : seconds ( PUBLISH_CONFIRMATION_TIMEOUT ) ) ;
2016-05-23 14:33:01 +00:00
m_PublishConfirmationTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandlePublishConfirmationTimer ,
2017-08-31 16:08:22 +00:00
shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
outbound - > SendTunnelDataMsg ( floodfill - > GetIdentHash ( ) , 0 , msg ) ;
2017-02-13 01:52:46 +00:00
m_LastSubmissionTime = ts ;
2014-11-28 18:01:35 +00:00
}
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : HandlePublishConfirmationTimer ( const boost : : system : : error_code & ecode )
2014-11-28 18:01:35 +00:00
{
if ( ecode ! = boost : : asio : : error : : operation_aborted )
2017-08-31 16:08:22 +00:00
{
2014-11-28 18:01:35 +00:00
if ( m_PublishReplyToken )
{
m_PublishReplyToken = 0 ;
2017-11-17 19:28:48 +00:00
if ( GetIdentity ( ) - > GetCryptoKeyType ( ) = = i2p : : data : : CRYPTO_KEY_TYPE_ELGAMAL )
{
2018-01-06 03:48:51 +00:00
LogPrint ( eLogWarning , " Destination: Publish confirmation was not received in " , PUBLISH_CONFIRMATION_TIMEOUT , " seconds, will try again " ) ;
2017-11-17 19:28:48 +00:00
Publish ( ) ;
}
else
{
LogPrint ( eLogWarning , " Destination: Publish confirmation was not received in " , PUBLISH_CONFIRMATION_TIMEOUT , " seconds from Java floodfill for crypto type " , ( int ) GetIdentity ( ) - > GetCryptoKeyType ( ) ) ;
2019-04-08 19:22:42 +00:00
// Java floodfill never sends confirmation back for unknown crypto type
2017-11-17 19:28:48 +00:00
// assume it successive and try to verify
m_PublishVerificationTimer . expires_from_now ( boost : : posix_time : : seconds ( PUBLISH_VERIFICATION_TIMEOUT ) ) ;
m_PublishVerificationTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandlePublishVerificationTimer ,
shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
2018-01-06 03:48:51 +00:00
2017-11-17 19:28:48 +00:00
}
2014-11-28 18:01:35 +00:00
}
}
2014-10-16 16:37:39 +00:00
}
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : HandlePublishVerificationTimer ( const boost : : system : : error_code & ecode )
2016-02-11 19:45:33 +00:00
{
if ( ecode ! = boost : : asio : : error : : operation_aborted )
2017-08-31 16:08:22 +00:00
{
2019-04-10 16:04:19 +00:00
auto ls = GetLeaseSetMt ( ) ;
if ( ! ls )
{
LogPrint ( eLogWarning , " Destination: couldn't verify LeaseSet for " , GetIdentHash ( ) . ToBase32 ( ) ) ;
return ;
}
2016-02-11 19:45:33 +00:00
auto s = shared_from_this ( ) ;
2019-04-17 16:42:43 +00:00
// we must capture this for gcc 4.7 due the bug
2019-04-10 16:04:19 +00:00
RequestLeaseSet ( ls - > GetStoreHash ( ) ,
2019-04-17 16:42:43 +00:00
[ s , ls , this ] ( std : : shared_ptr < const i2p : : data : : LeaseSet > leaseSet )
2016-02-11 19:45:33 +00:00
{
2017-08-31 16:08:22 +00:00
if ( leaseSet )
2016-02-11 19:45:33 +00:00
{
2019-04-10 16:04:19 +00:00
if ( * ls = = * leaseSet )
2017-02-12 15:08:52 +00:00
{
// we got latest LeasetSet
2019-04-10 16:04:19 +00:00
LogPrint ( eLogDebug , " Destination: published LeaseSet verified for " , s - > GetIdentHash ( ) . ToBase32 ( ) ) ;
2017-02-12 15:08:52 +00:00
s - > m_PublishVerificationTimer . expires_from_now ( boost : : posix_time : : seconds ( PUBLISH_REGULAR_VERIFICATION_INTERNAL ) ) ;
2017-08-31 16:08:22 +00:00
s - > m_PublishVerificationTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandlePublishVerificationTimer , s , std : : placeholders : : _1 ) ) ;
2017-02-12 15:08:52 +00:00
return ;
2017-08-31 16:08:22 +00:00
}
2017-02-12 15:08:52 +00:00
else
2019-04-10 16:04:19 +00:00
LogPrint ( eLogDebug , " Destination: LeaseSet is different than just published for " , s - > GetIdentHash ( ) . ToBase32 ( ) ) ;
2017-08-31 16:08:22 +00:00
}
2016-02-11 19:45:33 +00:00
else
2019-04-10 16:04:19 +00:00
LogPrint ( eLogWarning , " Destination: couldn't find published LeaseSet for " , s - > GetIdentHash ( ) . ToBase32 ( ) ) ;
2016-02-11 19:45:33 +00:00
// we have to publish again
2016-07-14 20:59:26 +00:00
s - > Publish ( ) ;
2016-02-11 19:45:33 +00:00
} ) ;
}
}
2017-02-13 01:52:46 +00:00
void LeaseSetDestination : : HandlePublishDelayTimer ( const boost : : system : : error_code & ecode )
{
if ( ecode ! = boost : : asio : : error : : operation_aborted )
Publish ( ) ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 14:33:01 +00:00
bool LeaseSetDestination : : RequestDestination ( const i2p : : data : : IdentHash & dest , RequestComplete requestComplete )
2014-12-25 21:47:15 +00:00
{
2017-08-31 16:08:22 +00:00
if ( ! m_Pool | | ! IsReady ( ) )
{
if ( requestComplete )
2016-08-09 02:15:09 +00:00
m_Service . post ( [ requestComplete ] ( void ) { requestComplete ( nullptr ) ; } ) ;
2015-01-03 03:37:46 +00:00
return false ;
2017-08-31 16:08:22 +00:00
}
2019-03-07 19:52:59 +00:00
m_Service . post ( std : : bind ( & LeaseSetDestination : : RequestLeaseSet , shared_from_this ( ) , dest , requestComplete , nullptr ) ) ;
return true ;
}
2019-03-27 20:04:46 +00:00
bool LeaseSetDestination : : RequestDestinationWithEncryptedLeaseSet ( std : : shared_ptr < const i2p : : data : : BlindedPublicKey > dest , RequestComplete requestComplete )
2019-03-07 19:52:59 +00:00
{
2019-04-02 20:32:18 +00:00
if ( ! dest | | ! m_Pool | | ! IsReady ( ) )
2019-03-07 19:52:59 +00:00
{
if ( requestComplete )
m_Service . post ( [ requestComplete ] ( void ) { requestComplete ( nullptr ) ; } ) ;
return false ;
}
2019-04-02 20:32:18 +00:00
auto storeHash = dest - > GetStoreHash ( ) ;
auto leaseSet = FindLeaseSet ( storeHash ) ;
2019-03-27 20:04:46 +00:00
if ( leaseSet )
{
if ( requestComplete )
m_Service . post ( [ requestComplete , leaseSet ] ( void ) { requestComplete ( leaseSet ) ; } ) ;
return true ;
}
2019-04-02 20:32:18 +00:00
m_Service . post ( std : : bind ( & LeaseSetDestination : : RequestLeaseSet , shared_from_this ( ) , storeHash , requestComplete , dest ) ) ;
2014-12-25 21:47:15 +00:00
return true ;
}
2016-08-08 15:53:38 +00:00
void LeaseSetDestination : : CancelDestinationRequest ( const i2p : : data : : IdentHash & dest , bool notify )
2015-12-13 19:40:43 +00:00
{
auto s = shared_from_this ( ) ;
2016-08-08 15:53:38 +00:00
m_Service . post ( [ dest , notify , s ] ( void )
2015-12-13 19:40:43 +00:00
{
auto it = s - > m_LeaseSetRequests . find ( dest ) ;
if ( it ! = s - > m_LeaseSetRequests . end ( ) )
2017-08-31 16:08:22 +00:00
{
auto requestComplete = it - > second ;
2016-02-14 04:02:58 +00:00
s - > m_LeaseSetRequests . erase ( it ) ;
2016-11-17 03:28:13 +00:00
if ( notify & & requestComplete ) requestComplete - > Complete ( nullptr ) ;
2017-08-31 16:08:22 +00:00
}
} ) ;
2015-12-13 19:40:43 +00:00
}
2017-08-31 16:08:22 +00:00
2019-03-27 20:04:46 +00:00
void LeaseSetDestination : : CancelDestinationRequestWithEncryptedLeaseSet ( std : : shared_ptr < const i2p : : data : : BlindedPublicKey > dest , bool notify )
2019-03-07 19:52:59 +00:00
{
2019-04-02 20:32:18 +00:00
if ( dest )
CancelDestinationRequest ( dest - > GetStoreHash ( ) , notify ) ;
2019-03-07 19:52:59 +00:00
}
2019-03-22 19:32:13 +00:00
void LeaseSetDestination : : RequestLeaseSet ( const i2p : : data : : IdentHash & dest , RequestComplete requestComplete , std : : shared_ptr < const i2p : : data : : BlindedPublicKey > requestedBlindedKey )
2014-12-25 21:47:15 +00:00
{
std : : set < i2p : : data : : IdentHash > excluded ;
auto floodfill = i2p : : data : : netdb . GetClosestFloodfill ( dest , excluded ) ;
if ( floodfill )
{
2015-12-13 15:51:43 +00:00
auto request = std : : make_shared < LeaseSetRequest > ( m_Service ) ;
2019-03-22 19:32:13 +00:00
request - > requestedBlindedKey = requestedBlindedKey ; // for encrypted LeaseSet2
2016-12-02 21:10:49 +00:00
if ( requestComplete )
request - > requestComplete . push_back ( requestComplete ) ;
2016-11-19 22:24:38 +00:00
auto ts = i2p : : util : : GetSecondsSinceEpoch ( ) ;
2015-12-13 15:51:43 +00:00
auto ret = m_LeaseSetRequests . insert ( std : : pair < i2p : : data : : IdentHash , std : : shared_ptr < LeaseSetRequest > > ( dest , request ) ) ;
2015-01-09 03:04:41 +00:00
if ( ret . second ) // inserted
2014-12-27 00:09:44 +00:00
{
2016-11-19 22:24:38 +00:00
request - > requestTime = ts ;
2015-01-09 03:04:41 +00:00
if ( ! SendLeaseSetRequest ( dest , floodfill , request ) )
{
// request failed
2016-11-19 22:24:38 +00:00
m_LeaseSetRequests . erase ( ret . first ) ;
2016-12-02 21:10:49 +00:00
if ( requestComplete ) requestComplete ( nullptr ) ;
2015-01-09 03:04:41 +00:00
}
2017-08-31 16:08:22 +00:00
}
2015-01-09 03:04:41 +00:00
else // duplicate
{
2016-11-17 03:28:13 +00:00
LogPrint ( eLogInfo , " Destination: Request of LeaseSet " , dest . ToBase64 ( ) , " is pending already " ) ;
2016-11-19 22:24:38 +00:00
if ( ts > ret . first - > second - > requestTime + MAX_LEASESET_REQUEST_TIMEOUT )
2017-08-31 16:08:22 +00:00
{
2016-12-11 19:17:09 +00:00
// something went wrong
2016-11-19 22:24:38 +00:00
m_LeaseSetRequests . erase ( ret . first ) ;
2016-12-11 19:17:09 +00:00
if ( requestComplete ) requestComplete ( nullptr ) ;
}
else if ( requestComplete )
ret . first - > second - > requestComplete . push_back ( requestComplete ) ;
2017-08-31 16:08:22 +00:00
}
}
2014-12-25 21:47:15 +00:00
else
2017-08-31 16:08:22 +00:00
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogError , " Destination: Can't request LeaseSet, no floodfills found " ) ;
2016-12-02 21:10:49 +00:00
if ( requestComplete ) requestComplete ( nullptr ) ;
2017-08-31 16:08:22 +00:00
}
}
bool LeaseSetDestination : : SendLeaseSetRequest ( const i2p : : data : : IdentHash & dest ,
2015-12-13 15:51:43 +00:00
std : : shared_ptr < const i2p : : data : : RouterInfo > nextFloodfill , std : : shared_ptr < LeaseSetRequest > request )
2014-12-25 21:47:15 +00:00
{
2016-02-26 21:17:29 +00:00
if ( ! request - > replyTunnel | | ! request - > replyTunnel - > IsEstablished ( ) )
request - > replyTunnel = m_Pool - > GetNextInboundTunnel ( ) ;
if ( ! request - > replyTunnel ) LogPrint ( eLogError , " Destination: Can't send LeaseSet request, no inbound tunnels found " ) ;
if ( ! request - > outboundTunnel | | ! request - > outboundTunnel - > IsEstablished ( ) )
request - > outboundTunnel = m_Pool - > GetNextOutboundTunnel ( ) ;
if ( ! request - > outboundTunnel ) LogPrint ( eLogError , " Destination: Can't send LeaseSet request, no outbound tunnels found " ) ;
2017-08-31 16:08:22 +00:00
2016-02-26 21:17:29 +00:00
if ( request - > replyTunnel & & request - > outboundTunnel )
2017-08-31 16:08:22 +00:00
{
2014-12-25 21:47:15 +00:00
request - > excluded . insert ( nextFloodfill - > GetIdentHash ( ) ) ;
request - > requestTimeoutTimer . cancel ( ) ;
2014-12-30 17:25:08 +00:00
uint8_t replyKey [ 32 ] , replyTag [ 32 ] ;
2017-08-31 16:08:22 +00:00
RAND_bytes ( replyKey , 32 ) ; // random session key
2015-11-03 14:15:49 +00:00
RAND_bytes ( replyTag , 32 ) ; // random session tag
2014-12-30 17:25:08 +00:00
AddSessionKey ( replyKey , replyTag ) ;
2015-06-22 02:29:50 +00:00
auto msg = WrapMessage ( nextFloodfill ,
2017-08-31 16:08:22 +00:00
CreateLeaseSetDatabaseLookupMsg ( dest , request - > excluded ,
2016-02-26 21:17:29 +00:00
request - > replyTunnel , replyKey , replyTag ) ) ;
request - > outboundTunnel - > SendTunnelDataMsg (
2014-12-25 21:47:15 +00:00
{
2017-08-31 16:08:22 +00:00
i2p : : tunnel : : TunnelMessageBlock
{
2014-12-25 21:47:15 +00:00
i2p : : tunnel : : eDeliveryTypeRouter ,
2015-06-22 02:29:50 +00:00
nextFloodfill - > GetIdentHash ( ) , 0 , msg
2014-12-25 21:47:15 +00:00
}
2017-08-31 16:08:22 +00:00
} ) ;
2014-12-25 21:47:15 +00:00
request - > requestTimeoutTimer . expires_from_now ( boost : : posix_time : : seconds ( LEASESET_REQUEST_TIMEOUT ) ) ;
2016-05-23 14:33:01 +00:00
request - > requestTimeoutTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandleRequestTimoutTimer ,
2016-02-11 19:45:33 +00:00
shared_from_this ( ) , std : : placeholders : : _1 , dest ) ) ;
2017-08-31 16:08:22 +00:00
}
2014-12-25 21:47:15 +00:00
else
2014-12-27 00:09:44 +00:00
return false ;
return true ;
2017-08-31 16:08:22 +00:00
}
2014-12-25 21:47:15 +00:00
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : HandleRequestTimoutTimer ( const boost : : system : : error_code & ecode , const i2p : : data : : IdentHash & dest )
2014-12-25 21:47:15 +00:00
{
if ( ecode ! = boost : : asio : : error : : operation_aborted )
{
auto it = m_LeaseSetRequests . find ( dest ) ;
if ( it ! = m_LeaseSetRequests . end ( ) )
{
bool done = false ;
uint64_t ts = i2p : : util : : GetSecondsSinceEpoch ( ) ;
if ( ts < it - > second - > requestTime + MAX_LEASESET_REQUEST_TIMEOUT )
{
auto floodfill = i2p : : data : : netdb . GetClosestFloodfill ( dest , it - > second - > excluded ) ;
if ( floodfill )
2016-02-26 21:17:29 +00:00
{
// reset tunnels, because one them might fail
it - > second - > outboundTunnel = nullptr ;
2017-08-31 16:08:22 +00:00
it - > second - > replyTunnel = nullptr ;
2016-02-26 21:17:29 +00:00
done = ! SendLeaseSetRequest ( dest , floodfill , it - > second ) ;
}
2014-12-25 21:47:15 +00:00
else
done = true ;
}
else
2017-08-31 16:08:22 +00:00
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogWarning , " Destination: " , dest . ToBase64 ( ) , " was not found within " , MAX_LEASESET_REQUEST_TIMEOUT , " seconds " ) ;
2014-12-25 21:47:15 +00:00
done = true ;
}
2017-08-31 16:08:22 +00:00
2014-12-25 21:47:15 +00:00
if ( done )
{
2017-08-31 16:08:22 +00:00
auto requestComplete = it - > second ;
2014-12-25 21:47:15 +00:00
m_LeaseSetRequests . erase ( it ) ;
2016-11-17 03:28:13 +00:00
if ( requestComplete ) requestComplete - > Complete ( nullptr ) ;
2017-08-31 16:08:22 +00:00
}
}
}
2015-01-23 17:48:25 +00:00
}
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : HandleCleanupTimer ( const boost : : system : : error_code & ecode )
2015-01-23 17:48:25 +00:00
{
if ( ecode ! = boost : : asio : : error : : operation_aborted )
{
2016-02-07 22:45:11 +00:00
CleanupExpiredTags ( ) ;
2015-01-28 19:20:28 +00:00
CleanupRemoteLeaseSets ( ) ;
2016-09-08 14:16:42 +00:00
CleanupDestination ( ) ;
2015-01-23 17:48:25 +00:00
m_CleanupTimer . expires_from_now ( boost : : posix_time : : minutes ( DESTINATION_CLEANUP_TIMEOUT ) ) ;
2016-05-23 14:33:01 +00:00
m_CleanupTimer . async_wait ( std : : bind ( & LeaseSetDestination : : HandleCleanupTimer ,
2015-11-03 14:15:49 +00:00
shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
2015-01-23 17:48:25 +00:00
}
2017-08-31 16:08:22 +00:00
}
2015-01-28 19:20:28 +00:00
2016-05-23 14:33:01 +00:00
void LeaseSetDestination : : CleanupRemoteLeaseSets ( )
2015-01-28 19:20:28 +00:00
{
2016-02-08 00:45:06 +00:00
auto ts = i2p : : util : : GetMillisecondsSinceEpoch ( ) ;
2016-07-22 13:56:17 +00:00
std : : lock_guard < std : : mutex > lock ( m_RemoteLeaseSetsMutex ) ;
2015-01-28 19:20:28 +00:00
for ( auto it = m_RemoteLeaseSets . begin ( ) ; it ! = m_RemoteLeaseSets . end ( ) ; )
{
2016-02-10 03:42:01 +00:00
if ( it - > second - > IsEmpty ( ) | | ts > it - > second - > GetExpirationTime ( ) ) // leaseset expired
2015-01-28 19:20:28 +00:00
{
2015-12-18 13:11:56 +00:00
LogPrint ( eLogWarning , " Destination: Remote LeaseSet " , it - > second - > GetIdentHash ( ) . ToBase64 ( ) , " expired " ) ;
2015-01-28 19:20:28 +00:00
it = m_RemoteLeaseSets . erase ( it ) ;
2017-08-31 16:08:22 +00:00
}
else
2016-08-05 18:23:54 +00:00
+ + it ;
2015-01-28 19:20:28 +00:00
}
2017-08-31 16:08:22 +00:00
}
2016-05-26 19:53:32 +00:00
2016-05-23 14:33:01 +00:00
ClientDestination : : ClientDestination ( const i2p : : data : : PrivateKeys & keys , bool isPublic , const std : : map < std : : string , std : : string > * params ) :
2017-11-24 20:37:17 +00:00
LeaseSetDestination ( isPublic , params ) , m_Keys ( keys ) , m_StreamingAckDelay ( DEFAULT_INITIAL_ACK_DELAY ) ,
m_DatagramDestination ( nullptr ) , m_RefCounter ( 0 ) ,
2019-09-06 15:02:19 +00:00
m_ReadyChecker ( GetService ( ) )
2016-05-23 14:33:01 +00:00
{
2019-02-12 19:56:39 +00:00
if ( keys . IsOfflineSignature ( ) & & GetLeaseSetType ( ) = = i2p : : data : : NETDB_STORE_TYPE_LEASESET )
SetLeaseSetType ( i2p : : data : : NETDB_STORE_TYPE_STANDARD_LEASESET2 ) ; // offline keys can be published with LS2 only
2019-01-15 23:41:00 +00:00
m_EncryptionKeyType = GetIdentity ( ) - > GetCryptoKeyType ( ) ;
2019-01-15 20:43:21 +00:00
// extract encryption type params for LS2
if ( GetLeaseSetType ( ) = = i2p : : data : : NETDB_STORE_TYPE_STANDARD_LEASESET2 & & params )
{
auto it = params - > find ( I2CP_PARAM_LEASESET_ENCRYPTION_TYPE ) ;
if ( it ! = params - > end ( ) )
2019-01-15 23:41:00 +00:00
m_EncryptionKeyType = std : : stoi ( it - > second ) ;
2019-01-15 20:43:21 +00:00
}
2020-01-12 15:03:30 +00:00
memset ( m_EncryptionPrivateKey , 0 , 256 ) ;
memset ( m_EncryptionPublicKey , 0 , 256 ) ;
if ( isPublic )
2019-01-15 23:41:00 +00:00
PersistTemporaryKeys ( ) ;
2016-05-29 13:33:50 +00:00
else
2019-01-15 23:41:00 +00:00
i2p : : data : : PrivateKeys : : GenerateCryptoKeyPair ( m_EncryptionKeyType , m_EncryptionPrivateKey , m_EncryptionPublicKey ) ;
2020-01-12 15:03:30 +00:00
2019-01-15 23:41:00 +00:00
m_Decryptor = i2p : : data : : PrivateKeys : : CreateDecryptor ( m_EncryptionKeyType , m_EncryptionPrivateKey ) ;
2016-05-23 14:33:01 +00:00
if ( isPublic )
LogPrint ( eLogInfo , " Destination: Local address " , GetIdentHash ( ) . ToBase32 ( ) , " created " ) ;
2017-11-24 20:37:17 +00:00
2019-07-16 20:31:17 +00:00
try
{
if ( params )
{
// extract streaming params
auto it = params - > find ( I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY ) ;
if ( it ! = params - > end ( ) )
m_StreamingAckDelay = std : : stoi ( it - > second ) ;
if ( GetLeaseSetType ( ) = = i2p : : data : : NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 )
{
// authentication for encrypted LeaseSet
2019-09-06 15:02:19 +00:00
auto authType = GetAuthType ( ) ;
if ( authType > 0 )
2019-07-16 20:31:17 +00:00
{
m_AuthKeys = std : : make_shared < std : : vector < i2p : : data : : AuthPublicKey > > ( ) ;
2019-09-06 15:02:19 +00:00
if ( authType = = i2p : : data : : ENCRYPTED_LEASESET_AUTH_TYPE_DH )
2019-07-16 20:31:17 +00:00
ReadAuthKey ( I2CP_PARAM_LEASESET_CLIENT_DH , params ) ;
2019-09-06 15:02:19 +00:00
else if ( authType = = i2p : : data : : ENCRYPTED_LEASESET_AUTH_TYPE_PSK )
2019-07-16 20:31:17 +00:00
ReadAuthKey ( I2CP_PARAM_LEASESET_CLIENT_PSK , params ) ;
else
2019-09-06 15:02:19 +00:00
LogPrint ( eLogError , " Destination: Unexpected auth type " , authType ) ;
2019-07-16 20:31:17 +00:00
if ( m_AuthKeys - > size ( ) )
LogPrint ( eLogInfo , " Destination: " , m_AuthKeys - > size ( ) , " auth keys read " ) ;
else
{
2019-09-06 15:02:19 +00:00
LogPrint ( eLogError , " Destination: No auth keys read for auth type " , authType ) ;
2019-07-16 20:31:17 +00:00
m_AuthKeys = nullptr ;
}
}
}
}
}
catch ( std : : exception & ex )
2017-11-24 20:37:17 +00:00
{
2019-07-16 20:31:17 +00:00
LogPrint ( eLogError , " Destination: unable to parse parameters for destination: " , ex . what ( ) ) ;
2017-11-24 20:37:17 +00:00
}
2017-08-31 16:08:22 +00:00
}
2016-05-23 14:33:01 +00:00
2017-08-31 16:08:22 +00:00
ClientDestination : : ~ ClientDestination ( )
2016-05-23 18:31:22 +00:00
{
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
bool ClientDestination : : Start ( )
{
if ( LeaseSetDestination : : Start ( ) )
2017-08-31 16:08:22 +00:00
{
2016-05-25 20:18:02 +00:00
m_StreamingDestination = std : : make_shared < i2p : : stream : : StreamingDestination > ( GetSharedFromThis ( ) ) ; // TODO:
2017-08-31 16:08:22 +00:00
m_StreamingDestination - > Start ( ) ;
2016-08-05 18:23:54 +00:00
for ( auto & it : m_StreamingDestinationsByPorts )
2016-05-23 18:31:22 +00:00
it . second - > Start ( ) ;
return true ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
else
return false ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
bool ClientDestination : : Stop ( )
{
if ( LeaseSetDestination : : Stop ( ) )
{
2016-08-30 17:27:57 +00:00
m_ReadyChecker . cancel ( ) ;
2016-05-23 18:31:22 +00:00
m_StreamingDestination - > Stop ( ) ;
2016-12-02 00:23:55 +00:00
//m_StreamingDestination->SetOwner (nullptr);
2016-05-23 18:31:22 +00:00
m_StreamingDestination = nullptr ;
2016-08-05 18:23:54 +00:00
for ( auto & it : m_StreamingDestinationsByPorts )
2017-08-31 16:08:22 +00:00
{
2016-05-23 18:31:22 +00:00
it . second - > Stop ( ) ;
2016-12-02 00:23:55 +00:00
//it.second->SetOwner (nullptr);
2016-11-26 03:36:35 +00:00
}
m_StreamingDestinationsByPorts . clear ( ) ;
if ( m_DatagramDestination )
2017-08-31 16:08:22 +00:00
{
2016-11-26 03:36:35 +00:00
delete m_DatagramDestination ;
m_DatagramDestination = nullptr ;
2017-08-31 16:08:22 +00:00
}
2018-01-06 04:01:44 +00:00
return true ;
2016-05-23 18:31:22 +00:00
}
else
return false ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
2016-10-19 14:23:02 +00:00
# ifdef I2LUA
2016-08-30 17:27:57 +00:00
void ClientDestination : : Ready ( ReadyPromise & p )
{
ScheduleCheckForReady ( & p ) ;
}
void ClientDestination : : ScheduleCheckForReady ( ReadyPromise * p )
{
// tick every 100ms
m_ReadyChecker . expires_from_now ( boost : : posix_time : : milliseconds ( 100 ) ) ;
m_ReadyChecker . async_wait ( [ & , p ] ( const boost : : system : : error_code & ecode ) {
HandleCheckForReady ( ecode , p ) ;
} ) ;
}
void ClientDestination : : HandleCheckForReady ( const boost : : system : : error_code & ecode , ReadyPromise * p )
{
if ( ecode ) // error happened
p - > set_value ( nullptr ) ;
else if ( IsReady ( ) ) // we are ready
p - > set_value ( std : : shared_ptr < ClientDestination > ( this ) ) ;
else // we are not ready
ScheduleCheckForReady ( p ) ;
}
2016-10-19 14:23:02 +00:00
# endif
2017-08-31 16:08:22 +00:00
2016-10-10 12:59:48 +00:00
void ClientDestination : : HandleDataMessage ( const uint8_t * buf , size_t len )
2016-05-23 18:31:22 +00:00
{
uint32_t length = bufbe32toh ( buf ) ;
2018-04-29 14:53:04 +00:00
if ( length > len - 4 )
{
LogPrint ( eLogError , " Destination: Data message length " , length , " exceeds buffer length " , len ) ;
return ;
}
2016-05-23 18:31:22 +00:00
buf + = 4 ;
// we assume I2CP payload
uint16_t fromPort = bufbe16toh ( buf + 4 ) , // source
2017-08-31 16:08:22 +00:00
toPort = bufbe16toh ( buf + 6 ) ; // destination
2016-05-23 18:31:22 +00:00
switch ( buf [ 9 ] )
{
case PROTOCOL_TYPE_STREAMING :
{
// streaming protocol
auto dest = GetStreamingDestination ( toPort ) ;
if ( dest )
dest - > HandleDataMessagePayload ( buf , length ) ;
else
LogPrint ( eLogError , " Destination: Missing streaming destination " ) ;
}
break ;
case PROTOCOL_TYPE_DATAGRAM :
// datagram protocol
if ( m_DatagramDestination )
m_DatagramDestination - > HandleDataMessagePayload ( fromPort , toPort , buf , length ) ;
else
LogPrint ( eLogError , " Destination: Missing datagram destination " ) ;
break ;
2019-07-10 01:33:55 +00:00
case PROTOCOL_TYPE_RAW :
// raw datagram
if ( m_DatagramDestination )
m_DatagramDestination - > HandleDataMessagePayload ( fromPort , toPort , buf , length , true ) ;
else
LogPrint ( eLogError , " Destination: Missing raw datagram destination " ) ;
break ;
2016-05-23 18:31:22 +00:00
default :
LogPrint ( eLogError , " Destination: Data: unexpected protocol " , buf [ 9 ] ) ;
}
}
2017-08-31 16:08:22 +00:00
void ClientDestination : : CreateStream ( StreamRequestComplete streamRequestComplete , const i2p : : data : : IdentHash & dest , int port )
2016-05-23 18:31:22 +00:00
{
2017-08-31 16:08:22 +00:00
if ( ! streamRequestComplete )
2016-05-23 18:31:22 +00:00
{
LogPrint ( eLogError , " Destination: request callback is not specified in CreateStream " ) ;
return ;
2017-08-31 16:08:22 +00:00
}
2017-08-31 14:38:26 +00:00
auto leaseSet = FindLeaseSet ( dest ) ;
if ( leaseSet )
streamRequestComplete ( CreateStream ( leaseSet , port ) ) ;
2016-05-23 18:31:22 +00:00
else
{
2017-08-31 14:38:26 +00:00
auto s = GetSharedFromThis ( ) ;
RequestDestination ( dest ,
2019-03-27 20:04:46 +00:00
[ s , streamRequestComplete , port ] ( std : : shared_ptr < const i2p : : data : : LeaseSet > ls )
2017-08-31 14:38:26 +00:00
{
if ( ls )
streamRequestComplete ( s - > CreateStream ( ls , port ) ) ;
2016-05-23 18:31:22 +00:00
else
2017-08-31 14:38:26 +00:00
streamRequestComplete ( nullptr ) ;
} ) ;
2016-05-23 18:31:22 +00:00
}
}
2019-03-27 20:04:46 +00:00
void ClientDestination : : CreateStream ( StreamRequestComplete streamRequestComplete , std : : shared_ptr < const i2p : : data : : BlindedPublicKey > dest , int port )
{
if ( ! streamRequestComplete )
{
LogPrint ( eLogError , " Destination: request callback is not specified in CreateStream " ) ;
return ;
}
auto s = GetSharedFromThis ( ) ;
RequestDestinationWithEncryptedLeaseSet ( dest ,
[ s , streamRequestComplete , port ] ( std : : shared_ptr < i2p : : data : : LeaseSet > ls )
{
if ( ls )
streamRequestComplete ( s - > CreateStream ( ls , port ) ) ;
else
streamRequestComplete ( nullptr ) ;
} ) ;
}
2016-05-23 18:31:22 +00:00
std : : shared_ptr < i2p : : stream : : Stream > ClientDestination : : CreateStream ( std : : shared_ptr < const i2p : : data : : LeaseSet > remote , int port )
{
if ( m_StreamingDestination )
return m_StreamingDestination - > CreateNewOutgoingStream ( remote , port ) ;
else
return nullptr ;
}
2017-08-31 16:08:22 +00:00
std : : shared_ptr < i2p : : stream : : StreamingDestination > ClientDestination : : GetStreamingDestination ( int port ) const
{
if ( port )
2016-05-23 18:31:22 +00:00
{
auto it = m_StreamingDestinationsByPorts . find ( port ) ;
if ( it ! = m_StreamingDestinationsByPorts . end ( ) )
return it - > second ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
// if port is zero or not found, use default destination
2017-08-31 16:08:22 +00:00
return m_StreamingDestination ;
2016-05-23 18:31:22 +00:00
}
2017-08-31 16:08:22 +00:00
2016-05-23 18:31:22 +00:00
void ClientDestination : : AcceptStreams ( const i2p : : stream : : StreamingDestination : : Acceptor & acceptor )
{
if ( m_StreamingDestination )
m_StreamingDestination - > SetAcceptor ( acceptor ) ;
}
void ClientDestination : : StopAcceptingStreams ( )
{
if ( m_StreamingDestination )
m_StreamingDestination - > ResetAcceptor ( ) ;
}
2017-08-31 16:08:22 +00:00
2016-05-23 18:31:22 +00:00
bool ClientDestination : : IsAcceptingStreams ( ) const
{
if ( m_StreamingDestination )
return m_StreamingDestination - > IsAcceptorSet ( ) ;
return false ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
2016-12-24 13:53:35 +00:00
void ClientDestination : : AcceptOnce ( const i2p : : stream : : StreamingDestination : : Acceptor & acceptor )
{
if ( m_StreamingDestination )
m_StreamingDestination - > AcceptOnce ( acceptor ) ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
std : : shared_ptr < i2p : : stream : : StreamingDestination > ClientDestination : : CreateStreamingDestination ( int port , bool gzip )
{
2017-08-31 16:08:22 +00:00
auto dest = std : : make_shared < i2p : : stream : : StreamingDestination > ( GetSharedFromThis ( ) , port , gzip ) ;
2016-05-23 18:31:22 +00:00
if ( port )
m_StreamingDestinationsByPorts [ port ] = dest ;
2017-08-31 16:08:22 +00:00
else // update default
2016-05-23 18:31:22 +00:00
m_StreamingDestination = dest ;
return dest ;
2017-08-31 16:08:22 +00:00
}
2016-08-22 02:29:55 +00:00
i2p : : datagram : : DatagramDestination * ClientDestination : : CreateDatagramDestination ( )
2016-05-23 18:31:22 +00:00
{
2016-08-22 01:17:09 +00:00
if ( m_DatagramDestination = = nullptr )
2016-08-22 02:29:55 +00:00
m_DatagramDestination = new i2p : : datagram : : DatagramDestination ( GetSharedFromThis ( ) ) ;
2017-08-31 16:08:22 +00:00
return m_DatagramDestination ;
2016-05-23 18:31:22 +00:00
}
std : : vector < std : : shared_ptr < const i2p : : stream : : Stream > > ClientDestination : : GetAllStreams ( ) const
{
std : : vector < std : : shared_ptr < const i2p : : stream : : Stream > > ret ;
if ( m_StreamingDestination )
{
for ( auto & it : m_StreamingDestination - > GetStreams ( ) )
ret . push_back ( it . second ) ;
2017-08-31 16:08:22 +00:00
}
2016-05-23 18:31:22 +00:00
for ( auto & it : m_StreamingDestinationsByPorts )
for ( auto & it1 : it . second - > GetStreams ( ) )
ret . push_back ( it1 . second ) ;
return ret ;
2017-08-31 16:08:22 +00:00
}
2016-05-29 13:33:50 +00:00
2019-01-15 23:41:00 +00:00
void ClientDestination : : PersistTemporaryKeys ( )
2016-05-29 13:33:50 +00:00
{
std : : string ident = GetIdentHash ( ) . ToBase32 ( ) ;
std : : string path = i2p : : fs : : DataDirPath ( " destinations " , ( ident + " .dat " ) ) ;
std : : ifstream f ( path , std : : ifstream : : binary ) ;
if ( f ) {
f . read ( ( char * ) m_EncryptionPublicKey , 256 ) ;
f . read ( ( char * ) m_EncryptionPrivateKey , 256 ) ;
return ;
}
2019-01-15 23:41:00 +00:00
LogPrint ( eLogInfo , " Destination: Creating new temporary keys of type for address " , ident , " .b32.i2p " ) ;
2019-01-15 20:43:21 +00:00
memset ( m_EncryptionPrivateKey , 0 , 256 ) ;
memset ( m_EncryptionPublicKey , 0 , 256 ) ;
2020-01-12 15:03:30 +00:00
i2p : : data : : PrivateKeys : : GenerateCryptoKeyPair ( m_EncryptionKeyType , m_EncryptionPrivateKey , m_EncryptionPublicKey ) ;
// TODO:: persist crypto key type
2016-05-29 13:33:50 +00:00
std : : ofstream f1 ( path , std : : ofstream : : binary | std : : ofstream : : out ) ;
if ( f1 ) {
f1 . write ( ( char * ) m_EncryptionPublicKey , 256 ) ;
f1 . write ( ( char * ) m_EncryptionPrivateKey , 256 ) ;
return ;
}
LogPrint ( eLogError , " Destinations: Can't save keys to " , path ) ;
2017-08-31 16:08:22 +00:00
}
2016-05-29 13:33:50 +00:00
void ClientDestination : : CreateNewLeaseSet ( std : : vector < std : : shared_ptr < i2p : : tunnel : : InboundTunnel > > tunnels )
{
2019-03-10 13:22:42 +00:00
std : : shared_ptr < i2p : : data : : LocalLeaseSet > leaseSet ;
2019-01-11 18:58:02 +00:00
if ( GetLeaseSetType ( ) = = i2p : : data : : NETDB_STORE_TYPE_LEASESET )
{
2019-03-10 13:22:42 +00:00
leaseSet = std : : make_shared < i2p : : data : : LocalLeaseSet > ( GetIdentity ( ) , m_EncryptionPublicKey , tunnels ) ;
2019-01-11 18:58:02 +00:00
// sign
Sign ( leaseSet - > GetBuffer ( ) , leaseSet - > GetBufferLen ( ) - leaseSet - > GetSignatureLen ( ) , leaseSet - > GetSignature ( ) ) ;
}
else
{
2019-04-10 16:04:19 +00:00
// standard LS2 (type 3) first
2019-01-14 00:17:02 +00:00
auto keyLen = m_Decryptor ? m_Decryptor - > GetPublicKeyLen ( ) : 256 ;
2019-08-07 19:43:03 +00:00
bool isPublishedEncrypted = GetLeaseSetType ( ) = = i2p : : data : : NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 ;
2019-04-10 16:04:19 +00:00
auto ls2 = std : : make_shared < i2p : : data : : LocalLeaseSet2 > ( i2p : : data : : NETDB_STORE_TYPE_STANDARD_LEASESET2 ,
2019-08-07 19:43:03 +00:00
m_Keys , m_EncryptionKeyType , keyLen , m_EncryptionPublicKey , tunnels , IsPublic ( ) , isPublishedEncrypted ) ;
if ( isPublishedEncrypted ) // encrypt if type 5
2019-09-06 15:02:19 +00:00
ls2 = std : : make_shared < i2p : : data : : LocalEncryptedLeaseSet2 > ( ls2 , m_Keys , GetAuthType ( ) , m_AuthKeys ) ;
2019-04-10 16:04:19 +00:00
leaseSet = ls2 ;
2019-01-11 18:58:02 +00:00
}
2016-05-29 13:33:50 +00:00
SetLeaseSet ( leaseSet ) ;
2017-08-31 16:08:22 +00:00
}
2016-09-08 14:16:42 +00:00
void ClientDestination : : CleanupDestination ( )
{
if ( m_DatagramDestination ) m_DatagramDestination - > CleanUp ( ) ;
}
2017-11-09 01:45:53 +00:00
bool ClientDestination : : Decrypt ( const uint8_t * encrypted , uint8_t * data , BN_CTX * ctx ) const
2017-11-08 18:49:48 +00:00
{
if ( m_Decryptor )
2018-03-09 19:56:06 +00:00
return m_Decryptor - > Decrypt ( encrypted , data , ctx , true ) ;
2017-11-08 18:49:48 +00:00
else
LogPrint ( eLogError , " Destinations: decryptor is not set " ) ;
2017-11-09 01:45:53 +00:00
return false ;
2017-11-08 18:49:48 +00:00
}
2019-07-16 20:31:17 +00:00
void ClientDestination : : ReadAuthKey ( const std : : string & group , const std : : map < std : : string , std : : string > * params )
{
for ( auto it : * params )
if ( it . first . length ( ) > = group . length ( ) & & ! it . first . compare ( 0 , group . length ( ) , group ) )
{
auto pos = it . second . find ( ' : ' ) ;
if ( pos ! = std : : string : : npos )
{
i2p : : data : : AuthPublicKey pubKey ;
if ( pubKey . FromBase64 ( it . second . substr ( pos + 1 ) ) )
m_AuthKeys - > push_back ( pubKey ) ;
else
LogPrint ( eLogError , " Destination: Unexpected auth key " , it . second . substr ( pos + 1 ) ) ;
}
}
}
2014-10-16 16:37:39 +00:00
}
2014-10-05 12:54:59 +00:00
}