@ -117,7 +117,7 @@ namespace tunnel
m . nextFragmentNum = 1 ;
m . nextFragmentNum = 1 ;
auto ret = m_IncompleteMessages . insert ( std : : pair < uint32_t , TunnelMessageBlockEx > ( msgID , m ) ) ;
auto ret = m_IncompleteMessages . insert ( std : : pair < uint32_t , TunnelMessageBlockEx > ( msgID , m ) ) ;
if ( ret . second )
if ( ret . second )
HandleOutOfSequenceFragment ( msgID , ret . first - > second ) ;
HandleOutOfSequenceFragments ( msgID , ret . first - > second ) ;
else
else
LogPrint ( eLogError , " TunnelMessage: Incomplete message " , msgID , " already exists " ) ;
LogPrint ( eLogError , " TunnelMessage: Incomplete message " , msgID , " already exists " ) ;
}
}
@ -168,7 +168,7 @@ namespace tunnel
else
else
{
{
msg . nextFragmentNum + + ;
msg . nextFragmentNum + + ;
HandleOutOfSequenceFragment ( msgID , msg ) ;
HandleOutOfSequenceFragments ( msgID , msg ) ;
}
}
}
}
else
else
@ -192,19 +192,31 @@ namespace tunnel
void TunnelEndpoint : : AddOutOfSequenceFragment ( uint32_t msgID , uint8_t fragmentNum , bool isLastFragment , std : : shared_ptr < I2NPMessage > data )
void TunnelEndpoint : : AddOutOfSequenceFragment ( uint32_t msgID , uint8_t fragmentNum , bool isLastFragment , std : : shared_ptr < I2NPMessage > data )
{
{
auto it = m_OutOfSequenceFragments . find ( msgID ) ;
if ( ! m_OutOfSequenceFragments . insert ( { { msgID , fragmentNum } , { fragmentNum , isLastFragment , data } } ) . second )
if ( it = = m_OutOfSequenceFragments . end ( ) )
LogPrint ( eLogInfo , " TunnelMessage: duplicate out-of-sequence fragment " , fragmentNum , " of message " , msgID ) ;
m_OutOfSequenceFragments . insert ( std : : pair < uint32_t , Fragment > ( msgID , { fragmentNum , isLastFragment , data } ) ) ;
}
}
void TunnelEndpoint : : HandleOutOfSequenceFragment ( uint32_t msgID , TunnelMessageBlockEx & msg )
void TunnelEndpoint : : HandleOutOfSequenceFragments ( uint32_t msgID , TunnelMessageBlockEx & msg )
{
{
auto it = m_OutOfSequenceFragments . find ( msgID ) ;
while ( ConcatNextOutOfSequenceFragment ( msgID , msg ) )
if ( it ! = m_OutOfSequenceFragments . end ( ) )
{
{
if ( ! msg . nextFragmentNum ) // message complete
{
HandleNextMessage ( msg ) ;
m_IncompleteMessages . erase ( msgID ) ;
break ;
}
}
}
bool TunnelEndpoint : : ConcatNextOutOfSequenceFragment ( uint32_t msgID , TunnelMessageBlockEx & msg )
{
auto it = m_OutOfSequenceFragments . find ( { msgID , msg . nextFragmentNum } ) ;
if ( it ! = m_OutOfSequenceFragments . end ( ) )
{
if ( it - > second . fragmentNum = = msg . nextFragmentNum )
if ( it - > second . fragmentNum = = msg . nextFragmentNum )
{
{
LogPrint ( eLogWarning , " TunnelMessage: Out-of-sequence fragment " , ( int ) it - > second . fragmentNum , " of message " , msgID , " found " ) ;
LogPrint ( eLogDebu g , " TunnelMessage: Out-of-sequence fragment " , ( int ) it - > second . fragmentNum , " of message " , msgID , " found " ) ;
size_t size = it - > second . data - > GetLength ( ) ;
size_t size = it - > second . data - > GetLength ( ) ;
if ( msg . data - > len + size > msg . data - > maxLen )
if ( msg . data - > len + size > msg . data - > maxLen )
{
{
@ -214,18 +226,19 @@ namespace tunnel
msg . data = newMsg ;
msg . data = newMsg ;
}
}
if ( msg . data - > Concat ( it - > second . data - > GetBuffer ( ) , size ) < size ) // concatenate out-of-sync fragment
if ( msg . data - > Concat ( it - > second . data - > GetBuffer ( ) , size ) < size ) // concatenate out-of-sync fragment
LogPrint ( eLogError , " Tunnel endpoint I2NP buffer overflow " , msg . data - > maxLen ) ;
LogPrint ( eLogError , " TunnelMessage: Tunnel endpoint I2NP buffer overflow " , msg . data - > maxLen ) ;
if ( it - > second . isLastFragment )
if ( it - > second . isLastFragment )
{
// message complete
// message complete
HandleNextMessage ( msg ) ;
msg . nextFragmentNum = 0 ;
m_IncompleteMessages . erase ( msgID ) ;
}
else
else
msg . nextFragmentNum + + ;
msg . nextFragmentNum + + ;
m_OutOfSequenceFragments . erase ( it ) ;
m_OutOfSequenceFragments . erase ( it ) ;
}
return true ;
}
else
LogPrint ( eLogError , " Tunnel message: next fragment " , ( int ) it - > second . fragmentNum , " of message " , msgID , " mismatch. " , ( int ) msg . nextFragmentNum , " expected " ) ;
}
}
return false ;
}
}
void TunnelEndpoint : : HandleNextMessage ( const TunnelMessageBlock & msg )
void TunnelEndpoint : : HandleNextMessage ( const TunnelMessageBlock & msg )