publish and handle SSU addreses without host

This commit is contained in:
orignal 2021-02-28 18:58:25 -05:00
parent 8bab4f60ef
commit 11c924bbe7
3 changed files with 64 additions and 66 deletions

View File

@ -329,7 +329,7 @@ namespace data
if (isHost) if (isHost)
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6; supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
else else
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
} }
} }
if (supportedTransports) if (supportedTransports)
@ -545,7 +545,7 @@ namespace data
std::string caps; std::string caps;
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING; if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
if (address.ssu && address.ssu->introducers.empty ()) if (IsReachable ())
isPublished = true; isPublished = true;
else else
caps += CAPS_FLAG_V4; caps += CAPS_FLAG_V4;

View File

@ -445,7 +445,7 @@ namespace transport
if (router && address) if (router && address)
{ {
if (router->UsesIntroducer ()) if (router->UsesIntroducer ())
m_Service.post (std::bind (&SSUServer::CreateSessionThroughIntroducer, this, router, peerTest)); // always V4 thread m_Service.post (std::bind (&SSUServer::CreateSessionThroughIntroducer, this, router, address, peerTest)); // always V4 thread
else else
{ {
boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port);
@ -477,13 +477,13 @@ namespace transport
} }
} }
void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest) void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest)
{ {
if (router && router->UsesIntroducer ()) if (router && router->UsesIntroducer () && address)
{ {
auto address = router->GetSSUAddress (true); // v4 only for now if (!address->host.is_unspecified () && address->port)
if (address) {
{
boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port);
auto it = m_Sessions.find (remoteEndpoint); auto it = m_Sessions.find (remoteEndpoint);
// check if session is presented already // check if session is presented already
@ -494,70 +494,67 @@ namespace transport
session->SendPeerTest (); session->SendPeerTest ();
return; return;
} }
// create new session }
int numIntroducers = address->ssu->introducers.size (); // create new session
if (numIntroducers > 0) int numIntroducers = address->ssu->introducers.size ();
if (numIntroducers > 0)
{
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
std::shared_ptr<SSUSession> introducerSession;
const i2p::data::RouterInfo::Introducer * introducer = nullptr;
// we might have a session to introducer already
for (int i = 0; i < numIntroducers; i++)
{ {
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); auto intr = &(address->ssu->introducers[i]);
std::shared_ptr<SSUSession> introducerSession; if (intr->iExp > 0 && ts > intr->iExp) continue; // skip expired introducer
const i2p::data::RouterInfo::Introducer * introducer = nullptr; boost::asio::ip::udp::endpoint ep (intr->iHost, intr->iPort);
// we might have a session to introducer already if (ep.address ().is_v4 ()) // ipv4 only
for (int i = 0; i < numIntroducers; i++)
{ {
auto intr = &(address->ssu->introducers[i]); if (!introducer) introducer = intr; // we pick first one for now
if (intr->iExp > 0 && ts > intr->iExp) continue; // skip expired introducer auto it = m_Sessions.find (ep);
boost::asio::ip::udp::endpoint ep (intr->iHost, intr->iPort); if (it != m_Sessions.end ())
if (ep.address ().is_v4 ()) // ipv4 only
{ {
if (!introducer) introducer = intr; // we pick first one for now introducerSession = it->second;
it = m_Sessions.find (ep); break;
if (it != m_Sessions.end ())
{
introducerSession = it->second;
break;
}
} }
} }
if (!introducer)
{
LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no ipv4 non-expired introducers presented");
return;
}
if (introducerSession) // session found
LogPrint (eLogWarning, "SSU: Session to introducer already exists");
else // create new
{
LogPrint (eLogDebug, "SSU: Creating new session to introducer ", introducer->iHost);
boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort);
introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = introducerSession;
}
#if BOOST_VERSION >= 104900
if (!address->host.is_unspecified () && address->port)
#endif
{
// create session
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
m_Sessions[remoteEndpoint] = session;
// introduce
LogPrint (eLogInfo, "SSU: Introduce new 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, router);
} }
else if (!introducer)
LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no introducers present"); {
LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no ipv4 non-expired introducers presented");
return;
}
if (introducerSession) // session found
LogPrint (eLogWarning, "SSU: Session to introducer already exists");
else // create new
{
LogPrint (eLogDebug, "SSU: Creating new session to introducer ", introducer->iHost);
boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort);
introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = introducerSession;
}
if (!address->host.is_unspecified () && address->port)
{
// create session
boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port);
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
m_Sessions[remoteEndpoint] = session;
// introduce
LogPrint (eLogInfo, "SSU: Introduce new 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, router);
} }
else else
LogPrint (eLogWarning, "SSU: Router ", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), " doesn't have SSU address"); LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no introducers present");
} }
} }

View File

@ -90,7 +90,8 @@ namespace transport
void HandleReceivedPackets (std::vector<SSUPacket *> packets, void HandleReceivedPackets (std::vector<SSUPacket *> packets,
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> >* sessions); std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> >* sessions);
void CreateSessionThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest = false); void CreateSessionThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest = false);
template<typename Filter> template<typename Filter>
std::shared_ptr<SSUSession> GetRandomV4Session (Filter filter); std::shared_ptr<SSUSession> GetRandomV4Session (Filter filter);
template<typename Filter> template<typename Filter>