@ -114,6 +114,8 @@ namespace transport
@@ -114,6 +114,8 @@ namespace transport
{
if ( m_State = = eSSU2SessionStateUnknown | | m_State = = eSSU2SessionStateTokenReceived )
{
LogPrint ( eLogDebug , " SSU2: Connecting to " , GetRemoteEndpoint ( ) ,
" ( " , i2p : : data : : GetIdentHashAbbreviation ( GetRemoteIdentity ( ) - > GetIdentHash ( ) ) , " ) " ) ;
ScheduleConnectTimer ( ) ;
auto token = m_Server . FindOutgoingToken ( m_RemoteEndpoint ) ;
if ( token )
@ -243,7 +245,7 @@ namespace transport
@@ -243,7 +245,7 @@ namespace transport
if ( IsEstablished ( ) )
{
uint8_t payload [ 20 ] ;
size_t payloadSize = CreatePaddingBlock ( payload , 20 , 5 ) ;
size_t payloadSize = CreatePaddingBlock ( payload , 20 , 8 ) ;
SendData ( payload , payloadSize ) ;
}
}
@ -269,7 +271,16 @@ namespace transport
@@ -269,7 +271,16 @@ namespace transport
m_ReceivedI2NPMsgIDs . clear ( ) ;
m_Server . RemoveSession ( m_SourceConnID ) ;
transports . PeerDisconnected ( shared_from_this ( ) ) ;
LogPrint ( eLogDebug , " SSU2: Session terminated " ) ;
auto remoteIdentity = GetRemoteIdentity ( ) ;
if ( remoteIdentity )
{
LogPrint ( eLogDebug , " SSU2: Session with " , GetRemoteEndpoint ( ) ,
" ( " , i2p : : data : : GetIdentHashAbbreviation ( GetRemoteIdentity ( ) - > GetIdentHash ( ) ) , " ) terminated " ) ;
}
else
{
LogPrint ( eLogDebug , " SSU2: Session with " , GetRemoteEndpoint ( ) , " terminated " ) ;
}
}
}
@ -298,6 +309,8 @@ namespace transport
@@ -298,6 +309,8 @@ namespace transport
m_OnEstablished ( ) ;
m_OnEstablished = nullptr ;
}
LogPrint ( eLogDebug , " SSU2: Session with " , GetRemoteEndpoint ( ) ,
" ( " , i2p : : data : : GetIdentHashAbbreviation ( GetRemoteIdentity ( ) - > GetIdentHash ( ) ) , " ) established " ) ;
}
void SSU2Session : : Done ( )
@ -1053,6 +1066,17 @@ namespace transport
@@ -1053,6 +1066,17 @@ namespace transport
LogPrint ( eLogError , " SSU2: SessionConfirmed malformed RouterInfo block " ) ;
return false ;
}
auto ts = i2p : : util : : GetMillisecondsSinceEpoch ( ) ;
if ( ts > ri - > GetTimestamp ( ) + i2p : : data : : NETDB_MIN_EXPIRATION_TIMEOUT * 1000LL ) // 90 minutes
{
LogPrint ( eLogError , " SSU2: RouterInfo in SessionConfirmed is too old for " , ( ts - ri - > GetTimestamp ( ) ) / 1000LL , " seconds " ) ;
return false ;
}
if ( ts + i2p : : data : : NETDB_EXPIRATION_TIMEOUT_THRESHOLD * 1000LL < ri - > GetTimestamp ( ) ) // 2 minutes
{
LogPrint ( eLogError , " SSU2: RouterInfo in SessionConfirmed is from future for " , ( ri - > GetTimestamp ( ) - ts ) / 1000LL , " seconds " ) ;
return false ;
}
m_Address = m_RemoteEndpoint . address ( ) . is_v6 ( ) ? ri - > GetSSU2V6Address ( ) : ri - > GetSSU2V4Address ( ) ;
if ( ! m_Address | | memcmp ( S , m_Address - > s , 32 ) )
{
@ -1486,7 +1510,7 @@ namespace transport
@@ -1486,7 +1510,7 @@ namespace transport
auto size = bufbe16toh ( buf + offset ) ;
offset + = 2 ;
LogPrint ( eLogDebug , " SSU2: Block type " , ( int ) blk , " of size " , size ) ;
if ( size > len )
if ( offset + size > len )
{
LogPrint ( eLogError , " SSU2: Unexpected block length " , size ) ;
break ;
@ -1532,16 +1556,21 @@ namespace transport
@@ -1532,16 +1556,21 @@ namespace transport
break ;
case eSSU2BlkTermination :
{
uint8_t rsn = buf [ 11 ] ; // reason
LogPrint ( eLogDebug , " SSU2: Termination reason= " , ( int ) rsn ) ;
if ( IsEstablished ( ) & & rsn ! = eSSU2TerminationReasonTerminationReceived )
RequestTermination ( eSSU2TerminationReasonTerminationReceived ) ;
else if ( m_State ! = eSSU2SessionStateTerminated )
if ( size > = 9 )
{
if ( m_State = = eSSU2SessionStateClosing & & rsn = = eSSU2TerminationReasonTerminationReceived )
m_State = eSSU2SessionStateClosingConfirmed ;
Done ( ) ;
uint8_t rsn = buf [ offset + 8 ] ; // reason
LogPrint ( eLogDebug , " SSU2: Termination reason= " , ( int ) rsn ) ;
if ( IsEstablished ( ) & & rsn ! = eSSU2TerminationReasonTerminationReceived )
RequestTermination ( eSSU2TerminationReasonTerminationReceived ) ;
else if ( m_State ! = eSSU2SessionStateTerminated )
{
if ( m_State = = eSSU2SessionStateClosing & & rsn = = eSSU2TerminationReasonTerminationReceived )
m_State = eSSU2SessionStateClosingConfirmed ;
Done ( ) ;
}
}
else
LogPrint ( eLogWarning , " SSU2: Unexpected termination block size " , size ) ;
break ;
}
case eSSU2BlkRelayRequest :
@ -1635,8 +1664,8 @@ namespace transport
@@ -1635,8 +1664,8 @@ namespace transport
break ;
case eSSU2SessionStateSessionCreatedReceived :
case eSSU2SessionStateTokenReceived :
if ( ( m_RemoteEndpoint . address ( ) . is_v4 ( ) & & i2p : : context . GetStatus ( ) = = eRouterStatusTesting ) | |
( m_RemoteEndpoint . address ( ) . is_v6 ( ) & & i2p : : context . GetStatus V6 ( ) = = eRouterStatusTesting ) )
if ( ( m_RemoteEndpoint . address ( ) . is_v4 ( ) & & i2p : : context . GetTesting ( ) ) | |
( m_RemoteEndpoint . address ( ) . is_v6 ( ) & & i2p : : context . GetTesting V6 ( ) ) )
{
if ( m_Server . IsSyncClockFromPeers ( ) )
{
@ -1734,14 +1763,14 @@ namespace transport
@@ -1734,14 +1763,14 @@ namespace transport
LogPrint ( eLogInfo , " SSU2: Our port " , ep . port ( ) , " received from " , m_RemoteEndpoint , " is different from " , m_Server . GetPort ( isV4 ) ) ;
if ( isV4 )
{
if ( i2p : : context . GetStatus ( ) = = eRouterStatusTesting )
if ( i2p : : context . GetTesting ( ) )
i2p : : context . SetError ( eRouterErrorSymmetricNAT ) ;
else if ( m_State = = eSSU2SessionStatePeerTest )
i2p : : context . SetError ( eRouterErrorFullConeNAT ) ;
}
else
{
if ( i2p : : context . GetStatus V6 ( ) = = eRouterStatusTesting )
if ( i2p : : context . GetTesting V6 ( ) )
i2p : : context . SetErrorV6 ( eRouterErrorSymmetricNAT ) ;
else if ( m_State = = eSSU2SessionStatePeerTest )
i2p : : context . SetErrorV6 ( eRouterErrorFullConeNAT ) ;
@ -2214,7 +2243,7 @@ namespace transport
@@ -2214,7 +2243,7 @@ namespace transport
if ( buf [ 1 ] = = eSSU2PeerTestCodeAccept )
{
if ( GetRouterStatus ( ) = = eRouterStatusUnknown )
SetRouterStatus ( eRouterStatusTesting ) ;
SetTestingState ( true ) ;
auto r = i2p : : data : : netdb . FindRouter ( buf + 3 ) ; // find Charlie
if ( r & & it - > second . first )
{
@ -2240,13 +2269,17 @@ namespace transport
@@ -2240,13 +2269,17 @@ namespace transport
}
else
{
if ( GetRouterStatus ( ) = = eRouterStatusTesting )
if ( GetTestingState ( ) )
{
SetRouterStatus ( eRouterStatusFirewalled ) ;
if ( m_Address - > IsV4 ( ) )
m_Server . RescheduleIntroducersUpdateTimer ( ) ;
else
m_Server . RescheduleIntroducersUpdateTimerV6 ( ) ;
SetTestingState ( false ) ;
if ( GetRouterStatus ( ) ! = eRouterStatusFirewalled )
{
SetRouterStatus ( eRouterStatusFirewalled ) ;
if ( m_Address - > IsV4 ( ) )
m_Server . RescheduleIntroducersUpdateTimer ( ) ;
else
m_Server . RescheduleIntroducersUpdateTimerV6 ( ) ;
}
}
}
LogPrint ( eLogDebug , " SSU2: Peer test 4 received from " , i2p : : data : : GetIdentHashAbbreviation ( GetRemoteIdentity ( ) - > GetIdentHash ( ) ) ,
@ -2275,7 +2308,7 @@ namespace transport
@@ -2275,7 +2308,7 @@ namespace transport
{
LogPrint ( eLogInfo , " SSU2: Peer test 4 error code " , ( int ) buf [ 1 ] , " from " ,
i2p : : data : : GetIdentHashAbbreviation ( buf [ 1 ] < 64 ? GetRemoteIdentity ( ) - > GetIdentHash ( ) : i2p : : data : : IdentHash ( buf + 3 ) ) ) ;
if ( GetRouterStatus ( ) = = eRouterStatusTesting )
if ( GetTestingState ( ) )
SetRouterStatus ( eRouterStatusUnknown ) ;
it - > second . first - > Done ( ) ;
}
@ -2429,6 +2462,29 @@ namespace transport
@@ -2429,6 +2462,29 @@ namespace transport
}
}
bool SSU2Session : : GetTestingState ( ) const
{
if ( m_Address )
{
if ( m_Address - > IsV4 ( ) )
return i2p : : context . GetTesting ( ) ;
if ( m_Address - > IsV6 ( ) )
return i2p : : context . GetTestingV6 ( ) ;
}
return false ;
}
void SSU2Session : : SetTestingState ( bool testing ) const
{
if ( m_Address )
{
if ( m_Address - > IsV4 ( ) )
i2p : : context . SetTesting ( testing ) ;
else if ( m_Address - > IsV6 ( ) )
i2p : : context . SetTestingV6 ( testing ) ;
}
}
size_t SSU2Session : : CreateAddressBlock ( uint8_t * buf , size_t len , const boost : : asio : : ip : : udp : : endpoint & ep )
{
if ( len < 9 ) return 0 ;
@ -2841,7 +2897,7 @@ namespace transport
@@ -2841,7 +2897,7 @@ namespace transport
void SSU2Session : : SendPathResponse ( const uint8_t * data , size_t len )
{
if ( len < 8 | | len > m_MaxPayloadSize - 3 )
if ( len > m_MaxPayloadSize - 3 )
{
LogPrint ( eLogWarning , " SSU2: Incorrect data size for path response " , len ) ;
return ;
@ -2850,7 +2906,10 @@ namespace transport
@@ -2850,7 +2906,10 @@ namespace transport
payload [ 0 ] = eSSU2BlkPathResponse ;
htobe16buf ( payload + 1 , len ) ;
memcpy ( payload + 3 , data , len ) ;
SendData ( payload , len + 3 ) ;
size_t payloadSize = len + 3 ;
if ( payloadSize < m_MaxPayloadSize )
payloadSize + = CreatePaddingBlock ( payload + payloadSize , m_MaxPayloadSize - payloadSize , payloadSize < 8 ? 8 : 0 ) ;
SendData ( payload , payloadSize ) ;
}
void SSU2Session : : SendPathChallenge ( )
@ -2868,7 +2927,7 @@ namespace transport
@@ -2868,7 +2927,7 @@ namespace transport
}
len + = 3 ;
if ( len < m_MaxPayloadSize )
len + = CreatePaddingBlock ( payload + len , m_MaxPayloadSize - len ) ;
len + = CreatePaddingBlock ( payload + len , m_MaxPayloadSize - len , len < 8 ? 8 : 0 ) ;
SendData ( payload , len ) ;
}