diff --git a/SSU.cpp b/SSU.cpp index 41946c0a..3ee9c69f 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -274,12 +274,17 @@ namespace transport void SSUServer::CreateSession (std::shared_ptr router, bool peerTest) { - std::shared_ptr session; if (router) { + if (router->UsesIntroducer ()) + { + CreateSessionThroughIntroducer (router, peerTest); + return; + } auto address = router->GetSSUAddress (!context.SupportsV6 ()); if (address) { + std::shared_ptr session; boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); auto it = m_Sessions.find (remoteEndpoint); if (it != m_Sessions.end ()) @@ -296,63 +301,82 @@ namespace transport std::unique_lock l(m_SessionsMutex); m_Sessions[remoteEndpoint] = session; } - if (!router->UsesIntroducer ()) - { - // connect directly - LogPrint ("Creating new SSU session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ", - remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); - session->Connect (); - } - else + // connect + LogPrint ("Creating new SSU session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ", + remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); + session->Connect (); + } + } + else + LogPrint (eLogWarning, "Router ", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), " doesn't have SSU address"); + } + } + + void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest) + { + if (router && router->UsesIntroducer ()) + { + auto address = router->GetSSUAddress (!context.SupportsV6 ()); + if (address) + { + boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); + auto it = m_Sessions.find (remoteEndpoint); + // check if session if presented alredy + if (it != m_Sessions.end ()) + { + auto session = it->second; + if (peerTest && session->GetState () == eSessionStateEstablished) + session->SendPeerTest (); + return; + } + // create new session + int numIntroducers = address->introducers.size (); + if (numIntroducers > 0) + { + std::shared_ptr introducerSession; + const i2p::data::RouterInfo::Introducer * introducer = nullptr; + // we might have a session to introducer already + for (int i = 0; i < numIntroducers; i++) { - // connect through introducer - int numIntroducers = address->introducers.size (); - if (numIntroducers > 0) + introducer = &(address->introducers[i]); + it = m_Sessions.find (boost::asio::ip::udp::endpoint (introducer->iHost, introducer->iPort)); + if (it != m_Sessions.end ()) { - std::shared_ptr introducerSession; - const i2p::data::RouterInfo::Introducer * introducer = nullptr; - // we might have a session to introducer already - for (int i = 0; i < numIntroducers; i++) - { - introducer = &(address->introducers[i]); - it = m_Sessions.find (boost::asio::ip::udp::endpoint (introducer->iHost, introducer->iPort)); - if (it != m_Sessions.end ()) - { - introducerSession = it->second; - break; - } - } - - if (introducerSession) // session found - LogPrint ("Session to introducer already exists"); - else // create new - { - LogPrint ("Creating new session to introducer"); - introducer = &(address->introducers[0]); // TODO: - boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort); - introducerSession = std::make_shared (*this, introducerEndpoint, router); - std::unique_lock l(m_SessionsMutex); - m_Sessions[introducerEndpoint] = introducerSession; - } - // introduce - LogPrint ("Introduce new SSU session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), - "] through introducer ", introducer->iHost, ":", introducer->iPort); - session->WaitForIntroduction (); - if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable - { - uint8_t buf[1]; - Send (buf, 0, remoteEndpoint); // send HolePunch - } - introducerSession->Introduce (*introducer); - } - else - { - LogPrint (eLogWarning, "Can't connect to unreachable router. No introducers presented"); - std::unique_lock l(m_SessionsMutex); - m_Sessions.erase (remoteEndpoint); + introducerSession = it->second; + break; } } + + if (introducerSession) // session found + LogPrint ("Session to introducer already exists"); + else // create new + { + LogPrint ("Creating new session to introducer"); + introducer = &(address->introducers[0]); // TODO: + boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort); + introducerSession = std::make_shared (*this, introducerEndpoint, router); + std::unique_lock l(m_SessionsMutex); + m_Sessions[introducerEndpoint] = introducerSession; + } + // create session + auto session = std::make_shared (*this, remoteEndpoint, router, peerTest); + { + std::unique_lock l(m_SessionsMutex); + m_Sessions[remoteEndpoint] = session; + } + // introduce + LogPrint ("Introduce new SSU session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), + "] through introducer ", introducer->iHost, ":", introducer->iPort); + session->WaitForIntroduction (); + if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable + { + uint8_t buf[1]; + Send (buf, 0, remoteEndpoint); // send HolePunch + } + introducerSession->Introduce (*introducer); } + else + LogPrint (eLogWarning, "Can't connect to unreachable router. No introducers presented"); } else LogPrint (eLogWarning, "Router ", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), " doesn't have SSU address"); diff --git a/SSU.h b/SSU.h index bf660523..96b9199d 100644 --- a/SSU.h +++ b/SSU.h @@ -41,6 +41,7 @@ namespace transport void Start (); void Stop (); void CreateSession (std::shared_ptr router, bool peerTest = false); + void CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest = false); std::shared_ptr FindSession (std::shared_ptr router) const; std::shared_ptr FindSession (const boost::asio::ip::udp::endpoint& e) const; std::shared_ptr GetRandomEstablishedSession (std::shared_ptr excluded);