fixed tunnel build race condition

This commit is contained in:
orignal 2014-09-26 10:15:34 -04:00
parent 79d2f69837
commit 9cd62d8873
3 changed files with 36 additions and 13 deletions

View File

@ -330,7 +330,10 @@ namespace i2p
i2p::tunnel::tunnels.AddInboundTunnel (static_cast<i2p::tunnel::InboundTunnel *>(tunnel)); i2p::tunnel::tunnels.AddInboundTunnel (static_cast<i2p::tunnel::InboundTunnel *>(tunnel));
} }
else else
{
LogPrint ("Inbound tunnel ", tunnel->GetTunnelID (), " has been declined"); LogPrint ("Inbound tunnel ", tunnel->GetTunnelID (), " has been declined");
tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);
}
} }
else else
{ {
@ -386,7 +389,10 @@ namespace i2p
i2p::tunnel::tunnels.AddOutboundTunnel (static_cast<i2p::tunnel::OutboundTunnel *>(tunnel)); i2p::tunnel::tunnels.AddOutboundTunnel (static_cast<i2p::tunnel::OutboundTunnel *>(tunnel));
} }
else else
{
LogPrint ("Outbound tunnel ", tunnel->GetTunnelID (), " has been declined"); LogPrint ("Outbound tunnel ", tunnel->GetTunnelID (), " has been declined");
tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);
}
} }
else else
LogPrint ("Pending tunnel for message ", replyMsgID, " not found"); LogPrint ("Pending tunnel for message ", replyMsgID, " not found");

View File

@ -246,7 +246,10 @@ namespace tunnel
{ {
auto it = m_PendingTunnels.find(replyMsgID); auto it = m_PendingTunnels.find(replyMsgID);
if (it != m_PendingTunnels.end ()) if (it != m_PendingTunnels.end ())
{
it->second->SetState (eTunnelStateBuildReplyReceived);
return it->second; return it->second;
}
return nullptr; return nullptr;
} }
@ -369,23 +372,35 @@ namespace tunnel
void Tunnels::ManageTunnels () void Tunnels::ManageTunnels ()
{ {
// check pending tunnel. delete non-successive // check pending tunnel. delete failed or timeout
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it = m_PendingTunnels.begin (); it != m_PendingTunnels.end ();) for (auto it = m_PendingTunnels.begin (); it != m_PendingTunnels.end ();)
{ {
if (it->second->GetState () == eTunnelStatePending) auto tunnel = it->second;
switch (tunnel->GetState ())
{ {
if (ts > it->second->GetCreationTime () + TUNNEL_CREATION_TIMEOUT) case eTunnelStatePending:
{ if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT)
LogPrint ("Pending tunnel build request ", it->first, " was not successive. Deleted"); {
delete it->second; LogPrint ("Pending tunnel build request ", it->first, " timeout. Deleted");
delete tunnel;
it = m_PendingTunnels.erase (it);
}
else
it++;
break;
case eTunnelStateBuildFailed:
LogPrint ("Pending tunnel build request ", it->first, " failed. Deleted");
delete tunnel;
it = m_PendingTunnels.erase (it); it = m_PendingTunnels.erase (it);
} break;
else case eTunnelStateBuildReplyReceived:
// intermidiate state, will be either established of build failed
it++; it++;
} break;
else default:
it = m_PendingTunnels.erase (it); it = m_PendingTunnels.erase (it);
}
} }
ManageInboundTunnels (); ManageInboundTunnels ();
@ -405,7 +420,7 @@ namespace tunnel
if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{ {
LogPrint ("Tunnel ", tunnel->GetTunnelID (), " expired"); LogPrint ("Tunnel ", tunnel->GetTunnelID (), " expired");
auto pool = (*it)->GetTunnelPool (); auto pool = tunnel->GetTunnelPool ();
if (pool) if (pool)
pool->TunnelExpired (tunnel); pool->TunnelExpired (tunnel);
it = m_OutboundTunnels.erase (it); it = m_OutboundTunnels.erase (it);

View File

@ -23,12 +23,14 @@ namespace tunnel
{ {
const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
const int TUNNEL_CREATION_TIMEOUT = 20; // 20 seconds const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message
enum TunnelState enum TunnelState
{ {
eTunnelStatePending, eTunnelStatePending,
eTunnelStateBuildReplyReceived,
eTunnelStateBuildFailed,
eTunnelStateEstablished, eTunnelStateEstablished,
eTunnelStateTestFailed, eTunnelStateTestFailed,
eTunnelStateFailed, eTunnelStateFailed,