|
|
@ -465,6 +465,7 @@ namespace transport |
|
|
|
auto ident = it->second->GetRemoteIdentity (); |
|
|
|
auto ident = it->second->GetRemoteIdentity (); |
|
|
|
if (ident) |
|
|
|
if (ident) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
std::lock_guard<std::mutex> l(m_SessionsByRouterHashMutex); |
|
|
|
auto it1 = m_SessionsByRouterHash.find (ident->GetIdentHash ()); |
|
|
|
auto it1 = m_SessionsByRouterHash.find (ident->GetIdentHash ()); |
|
|
|
if (it1 != m_SessionsByRouterHash.end () && it->second == it1->second.lock ()) |
|
|
|
if (it1 != m_SessionsByRouterHash.end () && it->second == it1->second.lock ()) |
|
|
|
m_SessionsByRouterHash.erase (it1); |
|
|
|
m_SessionsByRouterHash.erase (it1); |
|
|
@ -488,22 +489,26 @@ namespace transport |
|
|
|
auto ident = session->GetRemoteIdentity (); |
|
|
|
auto ident = session->GetRemoteIdentity (); |
|
|
|
if (ident) |
|
|
|
if (ident) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto ret = m_SessionsByRouterHash.emplace (ident->GetIdentHash (), session); |
|
|
|
std::shared_ptr<SSU2Session> oldSession; |
|
|
|
if (!ret.second) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
auto oldSession = ret.first->second.lock (); |
|
|
|
std::lock_guard<std::mutex> l(m_SessionsByRouterHashMutex); |
|
|
|
if (oldSession != session) |
|
|
|
auto ret = m_SessionsByRouterHash.emplace (ident->GetIdentHash (), session); |
|
|
|
|
|
|
|
if (!ret.second) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// session already exists
|
|
|
|
oldSession = ret.first->second.lock (); |
|
|
|
LogPrint (eLogWarning, "SSU2: Session to ", ident->GetIdentHash ().ToBase64 (), " already exists"); |
|
|
|
|
|
|
|
// move unsent msgs to new session
|
|
|
|
|
|
|
|
oldSession->MoveSendQueue (session); |
|
|
|
|
|
|
|
// terminate existing
|
|
|
|
|
|
|
|
GetService ().post (std::bind (&SSU2Session::RequestTermination, oldSession, eSSU2TerminationReasonReplacedByNewSession)); |
|
|
|
|
|
|
|
// update session
|
|
|
|
// update session
|
|
|
|
ret.first->second = session; |
|
|
|
ret.first->second = session; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (oldSession && oldSession != session) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// session already exists
|
|
|
|
|
|
|
|
LogPrint (eLogWarning, "SSU2: Session to ", ident->GetIdentHash ().ToBase64 (), " already exists"); |
|
|
|
|
|
|
|
// move unsent msgs to new session
|
|
|
|
|
|
|
|
oldSession->MoveSendQueue (session); |
|
|
|
|
|
|
|
// terminate existing
|
|
|
|
|
|
|
|
GetService ().post (std::bind (&SSU2Session::RequestTermination, oldSession, eSSU2TerminationReasonReplacedByNewSession)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -511,12 +516,13 @@ namespace transport |
|
|
|
bool SSU2Server::AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session) |
|
|
|
bool SSU2Server::AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!session) return false; |
|
|
|
if (!session) return false; |
|
|
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
std::lock_guard<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second; |
|
|
|
return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<SSU2Session> SSU2Server::FindSession (const i2p::data::IdentHash& ident) |
|
|
|
std::shared_ptr<SSU2Session> SSU2Server::FindSession (const i2p::data::IdentHash& ident) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
std::lock_guard<std::mutex> l(m_SessionsByRouterHashMutex); |
|
|
|
auto it = m_SessionsByRouterHash.find (ident); |
|
|
|
auto it = m_SessionsByRouterHash.find (ident); |
|
|
|
if (it != m_SessionsByRouterHash.end ()) |
|
|
|
if (it != m_SessionsByRouterHash.end ()) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -533,7 +539,7 @@ namespace transport |
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<SSU2Session> SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const |
|
|
|
std::shared_ptr<SSU2Session> SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
std::lock_guard<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
auto it = m_PendingOutgoingSessions.find (ep); |
|
|
|
auto it = m_PendingOutgoingSessions.find (ep); |
|
|
|
if (it != m_PendingOutgoingSessions.end ()) |
|
|
|
if (it != m_PendingOutgoingSessions.end ()) |
|
|
|
return it->second; |
|
|
|
return it->second; |
|
|
@ -542,7 +548,7 @@ namespace transport |
|
|
|
|
|
|
|
|
|
|
|
void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) |
|
|
|
void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
std::lock_guard<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
m_PendingOutgoingSessions.erase (ep); |
|
|
|
m_PendingOutgoingSessions.erase (ep); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -681,7 +687,7 @@ namespace transport |
|
|
|
if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent && |
|
|
|
if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent && |
|
|
|
it1->second->ProcessSessionCreated (buf, len)) |
|
|
|
it1->second->ProcessSessionCreated (buf, len)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
std::lock_guard<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint
|
|
|
|
m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -778,13 +784,12 @@ namespace transport |
|
|
|
if (router && address) |
|
|
|
if (router && address) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// check if no session
|
|
|
|
// check if no session
|
|
|
|
auto it = m_SessionsByRouterHash.find (router->GetIdentHash ()); |
|
|
|
auto existingSession = FindSession (router->GetIdentHash ()); |
|
|
|
if (it != m_SessionsByRouterHash.end ()) |
|
|
|
if (existingSession) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// session with router found, trying to send peer test if requested
|
|
|
|
// session with router found, trying to send peer test if requested
|
|
|
|
auto session = it->second.lock (); |
|
|
|
if (peerTest && existingSession->IsEstablished ()) |
|
|
|
if (peerTest && session && session->IsEstablished ()) |
|
|
|
GetService ().post ([existingSession]() { existingSession->SendPeerTest (); }); |
|
|
|
GetService ().post ([session]() { session->SendPeerTest (); }); |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
// check is no pending session
|
|
|
|
// check is no pending session
|
|
|
@ -841,18 +846,14 @@ namespace transport |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (it.iTag && ts < it.iExp) |
|
|
|
if (it.iTag && ts < it.iExp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto it1 = m_SessionsByRouterHash.find (it.iH); |
|
|
|
auto s = FindSession (it.iH); |
|
|
|
if (it1 != m_SessionsByRouterHash.end ()) |
|
|
|
if (s) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto s = it1->second.lock (); |
|
|
|
auto addr = s->GetAddress (); |
|
|
|
if (s) |
|
|
|
if (addr && addr->IsIntroducer ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto addr = s->GetAddress (); |
|
|
|
s->Introduce (session, it.iTag); |
|
|
|
if (addr && addr->IsIntroducer ()) |
|
|
|
return; |
|
|
|
{ |
|
|
|
|
|
|
|
s->Introduce (session, it.iTag); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -959,10 +960,7 @@ namespace transport |
|
|
|
if (!router) return false; |
|
|
|
if (!router) return false; |
|
|
|
auto addr = v4 ? router->GetSSU2V4Address () : router->GetSSU2V6Address (); |
|
|
|
auto addr = v4 ? router->GetSSU2V4Address () : router->GetSSU2V6Address (); |
|
|
|
if (!addr) return false; |
|
|
|
if (!addr) return false; |
|
|
|
std::shared_ptr<SSU2Session> session; |
|
|
|
auto session = FindSession (router->GetIdentHash ()); |
|
|
|
auto it = m_SessionsByRouterHash.find (router->GetIdentHash ()); |
|
|
|
|
|
|
|
if (it != m_SessionsByRouterHash.end ()) |
|
|
|
|
|
|
|
session = it->second.lock (); |
|
|
|
|
|
|
|
if (session) |
|
|
|
if (session) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto remoteAddr = session->GetAddress (); |
|
|
|
auto remoteAddr = session->GetAddress (); |
|
|
@ -992,16 +990,19 @@ namespace transport |
|
|
|
if (ecode != boost::asio::error::operation_aborted) |
|
|
|
if (ecode != boost::asio::error::operation_aborted) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto ts = i2p::util::GetSecondsSinceEpoch (); |
|
|
|
auto ts = i2p::util::GetSecondsSinceEpoch (); |
|
|
|
for (auto it = m_PendingOutgoingSessions.begin (); it != m_PendingOutgoingSessions.end ();) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if (it->second->IsTerminationTimeoutExpired (ts)) |
|
|
|
std::lock_guard<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
|
|
|
|
for (auto it = m_PendingOutgoingSessions.begin (); it != m_PendingOutgoingSessions.end ();) |
|
|
|
{ |
|
|
|
{ |
|
|
|
//it->second->Terminate ();
|
|
|
|
if (it->second->IsTerminationTimeoutExpired (ts)) |
|
|
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex); |
|
|
|
{ |
|
|
|
it = m_PendingOutgoingSessions.erase (it); |
|
|
|
//it->second->Terminate ();
|
|
|
|
|
|
|
|
it = m_PendingOutgoingSessions.erase (it); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
it++; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
it++; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (auto it: m_Sessions) |
|
|
|
for (auto it: m_Sessions) |
|
|
@ -1020,14 +1021,6 @@ namespace transport |
|
|
|
it.second->CleanUp (ts); |
|
|
|
it.second->CleanUp (ts); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (auto it = m_SessionsByRouterHash.begin (); it != m_SessionsByRouterHash.begin ();) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (it->second.expired ()) |
|
|
|
|
|
|
|
it = m_SessionsByRouterHash.erase (it); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
it++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ScheduleTermination (); |
|
|
|
ScheduleTermination (); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1084,6 +1077,17 @@ namespace transport |
|
|
|
it++; |
|
|
|
it++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::lock_guard<std::mutex> l(m_SessionsByRouterHashMutex); |
|
|
|
|
|
|
|
for (auto it = m_SessionsByRouterHash.begin (); it != m_SessionsByRouterHash.begin ();) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (it->second.expired ()) |
|
|
|
|
|
|
|
it = m_SessionsByRouterHash.erase (it); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
it++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
m_PacketsPool.CleanUpMt (); |
|
|
|
m_PacketsPool.CleanUpMt (); |
|
|
|
m_SentPacketsPool.CleanUp (); |
|
|
|
m_SentPacketsPool.CleanUp (); |
|
|
|
m_IncompleteMessagesPool.CleanUp (); |
|
|
|
m_IncompleteMessagesPool.CleanUp (); |
|
|
@ -1204,27 +1208,26 @@ namespace transport |
|
|
|
std::unordered_set<i2p::data::IdentHash> excluded; |
|
|
|
std::unordered_set<i2p::data::IdentHash> excluded; |
|
|
|
for (const auto& it : introducers) |
|
|
|
for (const auto& it : introducers) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::shared_ptr<SSU2Session> session; |
|
|
|
std::shared_ptr<SSU2Session> session = FindSession (it); |
|
|
|
auto it1 = m_SessionsByRouterHash.find (it); |
|
|
|
if (session) |
|
|
|
if (it1 != m_SessionsByRouterHash.end ()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
session = it1->second.lock (); |
|
|
|
|
|
|
|
excluded.insert (it); |
|
|
|
excluded.insert (it); |
|
|
|
} |
|
|
|
if (session) |
|
|
|
if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing () && // still session with introducer?
|
|
|
|
|
|
|
|
ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
session->SendKeepAlive (); |
|
|
|
if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing () && // still session with introducer?
|
|
|
|
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) |
|
|
|
ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) |
|
|
|
newList.push_back (it); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
impliedList.push_back (it); // keep in introducers list, but not publish
|
|
|
|
session->SendKeepAlive (); |
|
|
|
session = nullptr; |
|
|
|
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) |
|
|
|
|
|
|
|
newList.push_back (it); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
impliedList.push_back (it); // keep in introducers list, but not publish
|
|
|
|
|
|
|
|
session = nullptr; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
session = nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
session = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!session) |
|
|
|
if (!session) |
|
|
|
i2p::context.RemoveSSU2Introducer (it, v4); |
|
|
|
i2p::context.RemoveSSU2Introducer (it, v4); |
|
|
@ -1239,16 +1242,12 @@ namespace transport |
|
|
|
impliedList.clear (); |
|
|
|
impliedList.clear (); |
|
|
|
for (auto& it : introducers) |
|
|
|
for (auto& it : introducers) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto it1 = m_SessionsByRouterHash.find (it); |
|
|
|
auto session = FindSession (it); |
|
|
|
if (it1 != m_SessionsByRouterHash.end ()) |
|
|
|
if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto session = it1->second.lock (); |
|
|
|
session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); |
|
|
|
if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) |
|
|
|
if (std::find (newList.begin (), newList.end (), it) == newList.end ()) |
|
|
|
{ |
|
|
|
sessions.push_back (session); |
|
|
|
session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); |
|
|
|
|
|
|
|
if (std::find (newList.begin (), newList.end (), it) == newList.end ()) |
|
|
|
|
|
|
|
sessions.push_back (session); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|