Browse Source

clean code

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1794/head
R4SAS 2 years ago
parent
commit
96c4463d39
Signed by: r4sas
GPG Key ID: 66F6C87B98EBCFE2
  1. 2
      daemon/Daemon.cpp
  2. 2
      daemon/HTTPServer.cpp
  3. 4
      daemon/I2PControl.h
  4. 14
      daemon/I2PControlHandlers.cpp
  5. 12
      daemon/I2PControlHandlers.h
  6. 18
      libi2pd/NetDb.cpp
  7. 4
      libi2pd/NetDb.hpp
  8. 54
      libi2pd/RouterContext.cpp
  9. 78
      libi2pd/RouterInfo.cpp
  10. 4
      libi2pd/RouterInfo.h
  11. 242
      libi2pd/SSU2.cpp
  12. 18
      libi2pd/SSU2.h
  13. 546
      libi2pd/SSU2Session.cpp
  14. 22
      libi2pd/SSU2Session.h
  15. 10
      libi2pd/TransportSession.h
  16. 42
      libi2pd/Transports.cpp
  17. 8
      libi2pd/Transports.h
  18. 4
      libi2pd_client/AddressBook.cpp
  19. 4
      libi2pd_client/ClientContext.cpp
  20. 48
      libi2pd_client/I2PTunnel.cpp
  21. 8
      libi2pd_client/I2PTunnel.h
  22. 4
      libi2pd_client/SAM.cpp

2
daemon/Daemon.cpp

@ -162,7 +162,7 @@ namespace util
i2p::context.Init (); i2p::context.Init ();
i2p::transport::InitTransports (); i2p::transport::InitTransports ();
bool transit; i2p::config::GetOption("notransit", transit); bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit); i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);

2
daemon/HTTPServer.cpp

@ -250,7 +250,7 @@ namespace http {
break; break;
default: ; default: ;
} }
} }
} }
void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat) void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat)

4
daemon/I2PControl.h

@ -63,7 +63,7 @@ namespace client
void CreateCertificate (const char *crt_path, const char *key_path); void CreateCertificate (const char *crt_path, const char *key_path);
private: private:
// methods // methods
typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results); typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results);
@ -71,7 +71,7 @@ namespace client
void EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
// I2PControl // I2PControl
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value); typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
void PasswordHandler (const std::string& value); void PasswordHandler (const std::string& value);

14
daemon/I2PControlHandlers.cpp

@ -43,7 +43,7 @@ namespace client
// NetworkSetting // NetworkSetting
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlHandlers::InboundBandwidthLimit; m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlHandlers::InboundBandwidthLimit;
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlHandlers::OutboundBandwidthLimit; m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlHandlers::OutboundBandwidthLimit;
// ClientServicesInfo // ClientServicesInfo
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlHandlers::I2PTunnelInfoHandler; m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlHandlers::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlHandlers::HTTPProxyInfoHandler; m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlHandlers::HTTPProxyInfoHandler;
@ -51,7 +51,7 @@ namespace client
m_ClientServicesInfoHandlers["SAM"] = &I2PControlHandlers::SAMInfoHandler; m_ClientServicesInfoHandlers["SAM"] = &I2PControlHandlers::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlHandlers::BOBInfoHandler; m_ClientServicesInfoHandlers["BOB"] = &I2PControlHandlers::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlHandlers::I2CPInfoHandler; m_ClientServicesInfoHandlers["I2CP"] = &I2PControlHandlers::I2CPInfoHandler;
} }
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, int value) const void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
{ {
@ -76,7 +76,7 @@ namespace client
{ {
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value; ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
} }
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const
{ {
std::ostringstream buf; std::ostringstream buf;
@ -167,8 +167,8 @@ namespace client
void I2PControlHandlers::NetTotalSentBytes (std::ostringstream& results) void I2PControlHandlers::NetTotalSentBytes (std::ostringstream& results)
{ {
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ()); InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
} }
// network setting // network setting
void I2PControlHandlers::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results) void I2PControlHandlers::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{ {
@ -199,7 +199,7 @@ namespace client
int bw = i2p::context.GetBandwidthLimit(); int bw = i2p::context.GetBandwidthLimit();
InsertParam (results, "i2p.router.net.bw.out", bw); InsertParam (results, "i2p.router.net.bw.out", bw);
} }
// ClientServicesInfo // ClientServicesInfo
void I2PControlHandlers::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) void I2PControlHandlers::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
@ -217,7 +217,7 @@ namespace client
LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first); LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first);
} }
} }
void I2PControlHandlers::I2PTunnelInfoHandler (std::ostringstream& results) void I2PControlHandlers::I2PTunnelInfoHandler (std::ostringstream& results)
{ {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;

12
daemon/I2PControlHandlers.h

@ -29,14 +29,14 @@ namespace client
void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
protected: protected:
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const; void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const; void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const; void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const; void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
private: private:
// RouterInfo // RouterInfo
@ -53,12 +53,12 @@ namespace client
void OutboundBandwidth1S (std::ostringstream& results); void OutboundBandwidth1S (std::ostringstream& results);
void NetTotalReceivedBytes (std::ostringstream& results); void NetTotalReceivedBytes (std::ostringstream& results);
void NetTotalSentBytes (std::ostringstream& results); void NetTotalSentBytes (std::ostringstream& results);
// NetworkSetting // NetworkSetting
typedef void (I2PControlHandlers::*NetworkSettingRequestHandler)(const std::string& value, std::ostringstream& results); typedef void (I2PControlHandlers::*NetworkSettingRequestHandler)(const std::string& value, std::ostringstream& results);
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results); void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
void OutboundBandwidthLimit (const std::string& value, std::ostringstream& results); void OutboundBandwidthLimit (const std::string& value, std::ostringstream& results);
// ClientServicesInfo // ClientServicesInfo
typedef void (I2PControlHandlers::*ClientServicesInfoRequestHandler)(std::ostringstream& results); typedef void (I2PControlHandlers::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
void I2PTunnelInfoHandler (std::ostringstream& results); void I2PTunnelInfoHandler (std::ostringstream& results);
@ -67,7 +67,7 @@ namespace client
void SAMInfoHandler (std::ostringstream& results); void SAMInfoHandler (std::ostringstream& results);
void BOBInfoHandler (std::ostringstream& results); void BOBInfoHandler (std::ostringstream& results);
void I2CPInfoHandler (std::ostringstream& results); void I2CPInfoHandler (std::ostringstream& results);
private: private:
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers; std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;

18
libi2pd/NetDb.cpp

@ -274,7 +274,7 @@ namespace data
{ {
std::unique_lock<std::mutex> l(m_RouterInfosMutex); std::unique_lock<std::mutex> l(m_RouterInfosMutex);
r->Update (buf, len); r->Update (buf, len);
} }
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
{ {
@ -438,14 +438,14 @@ namespace data
// try reseeding from floodfill first if specified // try reseeding from floodfill first if specified
std::string riPath; std::string riPath;
if(i2p::config::GetOption("reseed.floodfill", riPath)) if(i2p::config::GetOption("reseed.floodfill", riPath))
{ {
auto ri = std::make_shared<RouterInfo>(riPath); auto ri = std::make_shared<RouterInfo>(riPath);
if (ri->IsFloodfill()) if (ri->IsFloodfill())
{ {
const uint8_t * riData = ri->GetBuffer(); const uint8_t * riData = ri->GetBuffer();
int riLen = ri->GetBufferLen(); int riLen = ri->GetBufferLen();
if (!i2p::data::netdb.AddRouterInfo(riData, riLen)) if (!i2p::data::netdb.AddRouterInfo(riData, riLen))
{ {
// bad router info // bad router info
LogPrint(eLogError, "NetDb: Bad router info"); LogPrint(eLogError, "NetDb: Bad router info");
@ -629,7 +629,7 @@ namespace data
it.second->SetUnreachable (false); it.second->SetUnreachable (false);
// find & mark expired routers // find & mark expired routers
if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & (RouterInfo::eSSUV4 | RouterInfo::eSSU2V4))) if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & (RouterInfo::eSSUV4 | RouterInfo::eSSU2V4)))
// non-reachable router, but reachable by ipv4 SSU or SSU2 means introducers // non-reachable router, but reachable by ipv4 SSU or SSU2 means introducers
{ {
if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
// RouterInfo expires after 1 hour if uses introducer // RouterInfo expires after 1 hour if uses introducer
@ -1218,7 +1218,7 @@ namespace data
router->IsSSU2PeerTesting (v4) && !excluded.count (router->GetIdentHash ()); router->IsSSU2PeerTesting (v4) && !excluded.count (router->GetIdentHash ());
}); });
} }
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const
{ {
return GetRandomRouter ( return GetRandomRouter (
@ -1243,11 +1243,11 @@ namespace data
return GetRandomRouter ( return GetRandomRouter (
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool [v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
{ {
return !router->IsHidden () && router->IsSSU2Introducer (v4) && return !router->IsHidden () && router->IsSSU2Introducer (v4) &&
!excluded.count (router->GetIdentHash ()); !excluded.count (router->GetIdentHash ());
}); });
} }
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
{ {
return GetRandomRouter ( return GetRandomRouter (
@ -1455,6 +1455,6 @@ namespace data
{ {
if (!r || r->GetBuffer ()) return; if (!r || r->GetBuffer ()) return;
r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ())); r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ()));
} }
} }
} }

4
libi2pd/NetDb.hpp

@ -125,8 +125,8 @@ namespace data
void ClearRouterInfos () { m_RouterInfos.clear (); }; void ClearRouterInfos () { m_RouterInfos.clear (); };
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r); void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };

54
libi2pd/RouterContext.cpp

@ -121,7 +121,7 @@ namespace i2p
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port; if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port;
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), ssu2Port); routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), ssu2Port);
} }
else else
{ {
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
@ -170,7 +170,7 @@ namespace i2p
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port; if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port;
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port); routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port);
} }
else else
{ {
if (!ipv4) // no other ssu2 addresses yet if (!ipv4) // no other ssu2 addresses yet
@ -201,8 +201,8 @@ namespace i2p
uint16_t port = rand () % (30777 - 9111) + 9111; // I2P network ports range uint16_t port = rand () % (30777 - 9111) + 9111; // I2P network ports range
if (port == 9150) port = 9151; // Tor browser if (port == 9150) port = 9151; // Tor browser
return port; return port;
} }
void RouterContext::UpdateRouterInfo () void RouterContext::UpdateRouterInfo ()
{ {
m_RouterInfo.CreateBuffer (m_Keys); m_RouterInfo.CreateBuffer (m_Keys);
@ -354,7 +354,7 @@ namespace i2p
(*it)->s = m_NTCP2Keys->staticPublicKey; (*it)->s = m_NTCP2Keys->staticPublicKey;
memcpy ((*it)->i, m_NTCP2Keys->iv, 16); memcpy ((*it)->i, m_NTCP2Keys->iv, 16);
it++; it++;
} }
else else
it = addresses.erase (it); it = addresses.erase (it);
updated = true; updated = true;
@ -382,9 +382,9 @@ namespace i2p
{ {
newPort = address->port; newPort = address->port;
break; break;
} }
if (!newPort) newPort = SelectRandomPort (); if (!newPort) newPort = SelectRandomPort ();
} }
bool updated = false; bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ()) for (auto& address : m_RouterInfo.GetAddresses ())
{ {
@ -419,8 +419,8 @@ namespace i2p
(*it)->s = m_SSU2Keys->staticPublicKey; (*it)->s = m_SSU2Keys->staticPublicKey;
(*it)->i = m_SSU2Keys->intro; (*it)->i = m_SSU2Keys->intro;
it++; it++;
} }
else else
it = addresses.erase (it); it = addresses.erase (it);
updated = true; updated = true;
} }
@ -438,12 +438,12 @@ namespace i2p
if (ipv6) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6); if (ipv6) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6);
} }
else else
{ {
uint8_t addressCaps = 0; uint8_t addressCaps = 0;
if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps); m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps);
} }
updated = true; updated = true;
} }
if (updated) if (updated)
@ -462,7 +462,7 @@ namespace i2p
address->host = host; address->host = host;
updated = true; updated = true;
} }
if (host.is_v6 () && address->IsV6 () && address->ssu && if (host.is_v6 () && address->IsV6 () && address->ssu &&
(!address->ssu->mtu || updated)) (!address->ssu->mtu || updated))
{ {
// update MTU // update MTU
@ -471,8 +471,8 @@ namespace i2p
{ {
LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu); LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ()); int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ());
if (mtu > maxMTU) if (mtu > maxMTU)
{ {
mtu = maxMTU; mtu = maxMTU;
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes"); LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes");
} }
@ -531,8 +531,8 @@ namespace i2p
} }
if (updated) if (updated)
UpdateRouterInfo (); UpdateRouterInfo ();
} }
void RouterContext::SetFloodfill (bool floodfill) void RouterContext::SetFloodfill (bool floodfill)
{ {
m_IsFloodfill = floodfill; m_IsFloodfill = floodfill;
@ -658,17 +658,17 @@ namespace i2p
for (auto it = addresses.begin (); it != addresses.end ();) for (auto it = addresses.begin (); it != addresses.end ();)
{ {
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportSSU) if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportSSU)
{ {
it = addresses.erase (it); it = addresses.erase (it);
updated = true; updated = true;
} }
else else
++it; ++it;
} }
if (updated) if (updated)
m_RouterInfo.UpdateSupportedTransports (); m_RouterInfo.UpdateSupportedTransports ();
} }
void RouterContext::SetUnreachableSSU2 (bool v4, bool v6) void RouterContext::SetUnreachableSSU2 (bool v4, bool v6)
{ {
if (IsSSU2Only ()) if (IsSSU2Only ())
@ -691,7 +691,7 @@ namespace i2p
// delete previous introducers // delete previous introducers
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr : addresses) for (auto& addr : addresses)
if (addr->ssu && (!addr->IsSSU2 () || IsSSU2Only ()) && if (addr->ssu && (!addr->IsSSU2 () || IsSSU2Only ()) &&
((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{ {
addr->published = false; addr->published = false;
@ -727,7 +727,7 @@ namespace i2p
i2p::config::GetOption ("ssu2.published", isSSU2Published); i2p::config::GetOption ("ssu2.published", isSSU2Published);
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr : addresses) for (auto& addr : addresses)
if (addr->ssu && (!addr->IsSSU2 () || isSSU2Published) && if (addr->ssu && (!addr->IsSSU2 () || isSSU2Published) &&
((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{ {
addr->published = true; addr->published = true;
@ -781,11 +781,11 @@ namespace i2p
} }
port = addr->port; port = addr->port;
} }
if (!port) if (!port)
{ {
i2p::config::GetOption("port", port); i2p::config::GetOption("port", port);
if (!port) port = SelectRandomPort (); if (!port) port = SelectRandomPort ();
} }
// SSU // SSU
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
if (!foundSSU && ssu) if (!foundSSU && ssu)
@ -871,11 +871,11 @@ namespace i2p
} }
if (addr->port) port = addr->port; if (addr->port) port = addr->port;
} }
if (!port) if (!port)
{ {
i2p::config::GetOption("port", port); i2p::config::GetOption("port", port);
if (!port) port = SelectRandomPort (); if (!port) port = SelectRandomPort ();
} }
// SSU // SSU
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
if (!foundSSU && ssu) if (!foundSSU && ssu)

78
libi2pd/RouterInfo.cpp

@ -257,29 +257,29 @@ namespace data
if (!ecode && !address->host.is_unspecified ()) isHost = true; if (!ecode && !address->host.is_unspecified ()) isHost = true;
} }
else if (!strcmp (key, "port")) else if (!strcmp (key, "port"))
{ {
try try
{ {
address->port = boost::lexical_cast<int>(value); address->port = boost::lexical_cast<int>(value);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ()); LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ());
} }
} }
else if (!strcmp (key, "mtu")) else if (!strcmp (key, "mtu"))
{ {
if (address->ssu) if (address->ssu)
{ {
try try
{ {
address->ssu->mtu = boost::lexical_cast<int>(value); address->ssu->mtu = boost::lexical_cast<int>(value);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogWarning, "RouterInfo: 'mtu' exception ", ex.what ()); LogPrint (eLogWarning, "RouterInfo: 'mtu' exception ", ex.what ());
} }
} }
else else
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2"); LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2");
} }
@ -347,38 +347,38 @@ namespace data
else if (!strcmp (key, "iport")) else if (!strcmp (key, "iport"))
{ {
try try
{ {
introducer.iPort = boost::lexical_cast<int>(value); introducer.iPort = boost::lexical_cast<int>(value);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogWarning, "RouterInfo: 'iport' exception ", ex.what ()); LogPrint (eLogWarning, "RouterInfo: 'iport' exception ", ex.what ());
} }
} }
else if (!strcmp (key, "itag")) else if (!strcmp (key, "itag"))
{ {
try try
{ {
introducer.iTag = boost::lexical_cast<uint32_t>(value); introducer.iTag = boost::lexical_cast<uint32_t>(value);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ()); LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ());
} }
} }
else if (!strcmp (key, "ikey") || !strcmp (key, "ih")) else if (!strcmp (key, "ikey") || !strcmp (key, "ih"))
Base64ToByteStream (value, strlen (value), introducer.iKey, 32); Base64ToByteStream (value, strlen (value), introducer.iKey, 32);
else if (!strcmp (key, "iexp")) else if (!strcmp (key, "iexp"))
{ {
try try
{ {
introducer.iExp = boost::lexical_cast<uint32_t>(value); introducer.iExp = boost::lexical_cast<uint32_t>(value);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogWarning, "RouterInfo: 'iexp' exception ", ex.what ()); LogPrint (eLogWarning, "RouterInfo: 'iexp' exception ", ex.what ());
} }
} }
} }
if (!s) return; if (!s) return;
} }
@ -431,10 +431,10 @@ namespace data
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ()))) ((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
numValid++; numValid++;
else else
{ {
it.iPort = 0; it.iPort = 0;
if (isV2) numValid++; if (isV2) numValid++;
} }
} }
if (numValid) if (numValid)
m_ReachableTransports |= supportedTransports; m_ReachableTransports |= supportedTransports;
@ -467,16 +467,16 @@ namespace data
int numValid = 0; int numValid = 0;
for (auto& it: address->ssu->introducers) for (auto& it: address->ssu->introducers)
{ {
if (it.iTag && ts <= it.iExp) if (it.iTag && ts <= it.iExp)
numValid++; numValid++;
else else
it.iTag = 0; it.iTag = 0;
} }
if (numValid) if (numValid)
m_ReachableTransports |= supportedTransports; m_ReachableTransports |= supportedTransports;
else else
address->ssu->introducers.resize (0); address->ssu->introducers.resize (0);
} }
} }
else else
{ {
@ -490,15 +490,15 @@ namespace data
ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu; ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (!address->ssu->introducers.empty ()) if (!address->ssu->introducers.empty ())
{ {
for (const auto& introducer: address->ssu->introducers) for (const auto& introducer: address->ssu->introducers)
if (!introducer.iPort && introducer.iHost.is_unspecified () && ts < introducer.iExp) // SSU2 if (!introducer.iPort && introducer.iHost.is_unspecified () && ts < introducer.iExp) // SSU2
ssu2addr->ssu->introducers.push_back (introducer); ssu2addr->ssu->introducers.push_back (introducer);
if (!ssu2addr->ssu->introducers.empty ()) if (!ssu2addr->ssu->introducers.empty ())
m_ReachableTransports |= supportedTransports; m_ReachableTransports |= supportedTransports;
} }
addresses->push_back(ssu2addr); addresses->push_back(ssu2addr);
} }
} }
if (supportedTransports) if (supportedTransports)
{ {
@ -982,7 +982,7 @@ namespace data
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const
{ {
if (v4) if (v4)
{ {
if (m_SupportedTransports & eSSU2V4) if (m_SupportedTransports & eSSU2V4)
return GetSSU2V4Address (); return GetSSU2V4Address ();
} }
@ -990,10 +990,10 @@ namespace data
{ {
if (m_SupportedTransports & eSSU2V6) if (m_SupportedTransports & eSSU2V6)
return GetSSU2V6Address (); return GetSSU2V6Address ();
} }
return nullptr; return nullptr;
} }
template<typename Filter> template<typename Filter>
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
{ {
@ -1025,7 +1025,7 @@ namespace data
return GetAddress ( return GetAddress (
[key, isV6](std::shared_ptr<const RouterInfo::Address> address)->bool [key, isV6](std::shared_ptr<const RouterInfo::Address> address)->bool
{ {
return address->IsSSU2 () && !memcmp (address->s, key, 32) && return address->IsSSU2 () && !memcmp (address->s, key, 32) &&
((isV6 && address->IsV6 ()) || (!isV6 && address->IsV4 ())); ((isV6 && address->IsV6 ()) || (!isV6 && address->IsV4 ()));
}); });
} }
@ -1099,8 +1099,8 @@ namespace data
return (address->IsSSU2 ()) && address->IsPeerTesting () && return (address->IsSSU2 ()) && address->IsPeerTesting () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU (); ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU ();
}); });
} }
bool RouterInfo::IsIntroducer (bool v4) const bool RouterInfo::IsIntroducer (bool v4) const
{ {
if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false;
@ -1122,7 +1122,7 @@ namespace data
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified (); ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified ();
}); });
} }
void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports)
{ {
for (auto& addr: *m_Addresses) for (auto& addr: *m_Addresses)
@ -1144,7 +1144,7 @@ namespace data
{ {
uint8_t transports = 0; uint8_t transports = 0;
switch (addr->transportStyle) switch (addr->transportStyle)
{ {
case eTransportNTCP: case eTransportNTCP:
if (addr->IsV4 ()) transports |= eNTCP2V4; if (addr->IsV4 ()) transports |= eNTCP2V4;
if (addr->IsV6 ()) if (addr->IsV6 ())
@ -1163,9 +1163,9 @@ namespace data
if (addr->IsV6 ()) transports |= eSSU2V6; if (addr->IsV6 ()) transports |= eSSU2V6;
if (addr->IsReachableSSU ()) if (addr->IsReachableSSU ())
m_ReachableTransports |= transports; m_ReachableTransports |= transports;
break; break;
default: ; default: ;
} }
m_SupportedTransports |= transports; m_SupportedTransports |= transports;
} }
} }
@ -1540,7 +1540,7 @@ namespace data
} }
} }
return false; return false;
} }
bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4) bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4)
{ {
@ -1559,6 +1559,6 @@ namespace data
} }
} }
return false; return false;
} }
} }
} }

4
libi2pd/RouterInfo.h

@ -276,7 +276,7 @@ namespace data
void RefreshTimestamp (); void RefreshTimestamp ();
const Addresses& GetAddresses () const { return *m_Addresses; }; const Addresses& GetAddresses () const { return *m_Addresses; };
CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; }; CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; };
void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; }; void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; };
private: private:
@ -321,7 +321,7 @@ namespace data
bool AddSSU2Introducer (const Introducer& introducer, bool v4); bool AddSSU2Introducer (const Introducer& introducer, bool v4);
bool RemoveSSU2Introducer (const IdentHash& h, bool v4); bool RemoveSSU2Introducer (const IdentHash& h, bool v4);
private: private:
void WriteToStream (std::ostream& s) const; void WriteToStream (std::ostream& s) const;

242
libi2pd/SSU2.cpp

@ -17,12 +17,12 @@
namespace i2p namespace i2p
{ {
namespace transport namespace transport
{ {
SSU2Server::SSU2Server (): SSU2Server::SSU2Server ():
RunnableServiceWithWork ("SSU2"), m_ReceiveService ("SSU2r"), RunnableServiceWithWork ("SSU2"), m_ReceiveService ("SSU2r"),
m_SocketV4 (m_ReceiveService.GetService ()), m_SocketV6 (m_ReceiveService.GetService ()), m_SocketV4 (m_ReceiveService.GetService ()), m_SocketV6 (m_ReceiveService.GetService ()),
m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()), m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()),
m_TerminationTimer (GetService ()), m_ResendTimer (GetService ()), m_TerminationTimer (GetService ()), m_ResendTimer (GetService ()),
m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()),
m_IsPublished (true), m_IsSyncClockFromPeers (true) m_IsPublished (true), m_IsSyncClockFromPeers (true)
{ {
@ -93,25 +93,25 @@ namespace transport
void SSU2Server::Stop () void SSU2Server::Stop ()
{ {
if (IsRunning ()) if (IsRunning ())
{ {
m_TerminationTimer.cancel (); m_TerminationTimer.cancel ();
m_ResendTimer.cancel (); m_ResendTimer.cancel ();
m_IntroducersUpdateTimer.cancel (); m_IntroducersUpdateTimer.cancel ();
m_IntroducersUpdateTimerV6.cancel (); m_IntroducersUpdateTimerV6.cancel ();
} }
auto sessions = m_Sessions; auto sessions = m_Sessions;
for (auto& it: sessions) for (auto& it: sessions)
{ {
it.second->RequestTermination (eSSU2TerminationReasonRouterShutdown); it.second->RequestTermination (eSSU2TerminationReasonRouterShutdown);
it.second->Done (); it.second->Done ();
} }
if (context.SupportsV4 () || context.SupportsV6 ()) if (context.SupportsV4 () || context.SupportsV6 ())
m_ReceiveService.Stop (); m_ReceiveService.Stop ();
m_SocketV4.close (); m_SocketV4.close ();
m_SocketV6.close (); m_SocketV6.close ();
StopIOService (); StopIOService ();
m_Sessions.clear (); m_Sessions.clear ();
@ -126,38 +126,38 @@ namespace transport
{ {
if (localAddress.is_unspecified ()) return; if (localAddress.is_unspecified ()) return;
if (localAddress.is_v4 ()) if (localAddress.is_v4 ())
{ {
m_AddressV4 = localAddress; m_AddressV4 = localAddress;
int mtu = i2p::util::net::GetMTU (localAddress); int mtu = i2p::util::net::GetMTU (localAddress);
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
i2p::context.SetMTU (mtu, true); i2p::context.SetMTU (mtu, true);
} }
else if (localAddress.is_v6 ()) else if (localAddress.is_v6 ())
{ {
m_AddressV6 = localAddress; m_AddressV6 = localAddress;
int maxMTU = i2p::util::net::GetMaxMTU (localAddress.to_v6 ()); int maxMTU = i2p::util::net::GetMaxMTU (localAddress.to_v6 ());
int mtu = i2p::util::net::GetMTU (localAddress); int mtu = i2p::util::net::GetMTU (localAddress);
if (mtu > maxMTU) mtu = maxMTU; if (mtu > maxMTU) mtu = maxMTU;
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
i2p::context.SetMTU (mtu, false); i2p::context.SetMTU (mtu, false);
} }
} }
bool SSU2Server::IsSupported (const boost::asio::ip::address& addr) const bool SSU2Server::IsSupported (const boost::asio::ip::address& addr) const
{ {
if (addr.is_v4 ()) if (addr.is_v4 ())
{ {
if (m_SocketV4.is_open ()) if (m_SocketV4.is_open ())
return true; return true;
} }
else if (addr.is_v6 ()) else if (addr.is_v6 ())
{ {
if (m_SocketV6.is_open ()) if (m_SocketV6.is_open ())
return true; return true;
} }
return false; return false;
} }
uint16_t SSU2Server::GetPort (bool v4) const uint16_t SSU2Server::GetPort (bool v4) const
{ {
@ -165,8 +165,8 @@ namespace transport
boost::asio::ip::udp::endpoint ep = v4 ? m_SocketV4.local_endpoint (ec) : m_SocketV6.local_endpoint (ec); boost::asio::ip::udp::endpoint ep = v4 ? m_SocketV4.local_endpoint (ec) : m_SocketV6.local_endpoint (ec);
if (ec) return 0; if (ec) return 0;
return ep.port (); return ep.port ();
} }
boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint) boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint)
{ {
boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4; boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4;
@ -253,7 +253,7 @@ namespace transport
{ {
ProcessNextPacket (packet->buf, packet->len, packet->from); ProcessNextPacket (packet->buf, packet->len, packet->from);
m_PacketsPool.ReleaseMt (packet); m_PacketsPool.ReleaseMt (packet);
if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated)
m_LastSession->FlushData (); m_LastSession->FlushData ();
} }
} }
@ -263,7 +263,7 @@ namespace transport
for (auto& packet: packets) for (auto& packet: packets)
ProcessNextPacket (packet->buf, packet->len, packet->from); ProcessNextPacket (packet->buf, packet->len, packet->from);
m_PacketsPool.ReleaseMt (packets); m_PacketsPool.ReleaseMt (packets);
if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated)
m_LastSession->FlushData (); m_LastSession->FlushData ();
} }
@ -289,7 +289,7 @@ namespace transport
m_Sessions.erase (it); m_Sessions.erase (it);
} }
} }
void SSU2Server::AddSessionByRouterHash (std::shared_ptr<SSU2Session> session) void SSU2Server::AddSessionByRouterHash (std::shared_ptr<SSU2Session> session)
{ {
if (session) if (session)
@ -323,10 +323,10 @@ namespace transport
if (it != m_SessionsByRouterHash.end ()) if (it != m_SessionsByRouterHash.end ())
return it->second; return it->second;
return nullptr; return nullptr;
} }
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
{ {
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;
@ -336,8 +336,8 @@ namespace transport
void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep)
{ {
m_PendingOutgoingSessions.erase (ep); m_PendingOutgoingSessions.erase (ep);
} }
std::shared_ptr<SSU2Session> SSU2Server::GetRandomSession ( std::shared_ptr<SSU2Session> SSU2Server::GetRandomSession (
i2p::data::RouterInfo::CompatibleTransports remoteTransports, const i2p::data::IdentHash& excluded) const i2p::data::RouterInfo::CompatibleTransports remoteTransports, const i2p::data::IdentHash& excluded) const
{ {
@ -349,7 +349,7 @@ namespace transport
std::advance (it, ind); std::advance (it, ind);
while (it != m_Sessions.end ()) while (it != m_Sessions.end ())
{ {
if ((it->second->GetRemoteTransports () & remoteTransports) && if ((it->second->GetRemoteTransports () & remoteTransports) &&
it->second->GetRemoteIdentity ()->GetIdentHash () != excluded) it->second->GetRemoteIdentity ()->GetIdentHash () != excluded)
return it->second; return it->second;
it++; it++;
@ -358,14 +358,14 @@ namespace transport
it = m_Sessions.begin (); it = m_Sessions.begin ();
while (it != m_Sessions.end () && ind) while (it != m_Sessions.end () && ind)
{ {
if ((it->second->GetRemoteTransports () & remoteTransports) && if ((it->second->GetRemoteTransports () & remoteTransports) &&
it->second->GetRemoteIdentity ()->GetIdentHash () != excluded) it->second->GetRemoteIdentity ()->GetIdentHash () != excluded)
return it->second; return it->second;
it++; ind--; it++; ind--;
} }
return nullptr; return nullptr;
} }
void SSU2Server::AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay) void SSU2Server::AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay)
{ {
m_Relays.emplace (tag, relay); m_Relays.emplace (tag, relay);
@ -409,7 +409,7 @@ namespace transport
switch (m_LastSession->GetState ()) switch (m_LastSession->GetState ())
{ {
case eSSU2SessionStateEstablished: case eSSU2SessionStateEstablished:
case eSSU2SessionStateSessionConfirmedSent: case eSSU2SessionStateSessionConfirmedSent:
m_LastSession->ProcessData (buf, len, senderEndpoint); m_LastSession->ProcessData (buf, len, senderEndpoint);
break; break;
case eSSU2SessionStateSessionCreatedSent: case eSSU2SessionStateSessionCreatedSent:
@ -417,10 +417,10 @@ namespace transport
{ {
m_LastSession->Done (); m_LastSession->Done ();
m_LastSession = nullptr; m_LastSession = nullptr;
} }
break; break;
case eSSU2SessionStateIntroduced: case eSSU2SessionStateIntroduced:
if (m_LastSession->GetRemoteEndpoint ().address ().is_unspecified ()) if (m_LastSession->GetRemoteEndpoint ().address ().is_unspecified ())
m_LastSession->SetRemoteEndpoint (senderEndpoint); m_LastSession->SetRemoteEndpoint (senderEndpoint);
if (m_LastSession->GetRemoteEndpoint () == senderEndpoint) if (m_LastSession->GetRemoteEndpoint () == senderEndpoint)
m_LastSession->ProcessHolePunch (buf, len); m_LastSession->ProcessHolePunch (buf, len);
@ -429,8 +429,8 @@ namespace transport
LogPrint (eLogWarning, "SSU2: HolePunch endpoint ", senderEndpoint, LogPrint (eLogWarning, "SSU2: HolePunch endpoint ", senderEndpoint,
" doesn't match RelayResponse ", m_LastSession->GetRemoteEndpoint ()); " doesn't match RelayResponse ", m_LastSession->GetRemoteEndpoint ());
m_LastSession->Done (); m_LastSession->Done ();
m_LastSession = nullptr; m_LastSession = nullptr;
} }
break; break;
case eSSU2SessionStatePeerTest: case eSSU2SessionStatePeerTest:
m_LastSession->SetRemoteEndpoint (senderEndpoint); m_LastSession->SetRemoteEndpoint (senderEndpoint);
@ -440,10 +440,10 @@ namespace transport
m_LastSession->ProcessData (buf, len, senderEndpoint); // we might receive termintaion block m_LastSession->ProcessData (buf, len, senderEndpoint); // we might receive termintaion block
if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated)
m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again
break; break;
case eSSU2SessionStateTerminated: case eSSU2SessionStateTerminated:
m_LastSession = nullptr; m_LastSession = nullptr;
break; break;
default: default:
LogPrint (eLogWarning, "SSU2: Invalid session state ", (int)m_LastSession->GetState ()); LogPrint (eLogWarning, "SSU2: Invalid session state ", (int)m_LastSession->GetState ());
} }
@ -456,7 +456,7 @@ namespace transport
{ {
if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent && if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent &&
it1->second->ProcessSessionCreated (buf, len)) it1->second->ProcessSessionCreated (buf, len))
m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint
else else
it1->second->ProcessRetry (buf, len); it1->second->ProcessRetry (buf, len);
} }
@ -524,41 +524,41 @@ namespace transport
{ {
auto session = it->second; auto session = it->second;
GetService ().post ([session]() { session->SendPeerTest (); }); GetService ().post ([session]() { session->SendPeerTest (); });
} }
return false; return false;
} }
// check is no pending session // check is no pending session
bool isValidEndpoint = !address->host.is_unspecified () && address->port; bool isValidEndpoint = !address->host.is_unspecified () && address->port;
if (isValidEndpoint) if (isValidEndpoint)
{ {
if (i2p::util::net::IsInReservedRange(address->host)) return false; if (i2p::util::net::IsInReservedRange(address->host)) return false;
auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (address->host, address->port)); auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (address->host, address->port));
if (s) if (s)
{ {
if (peerTest) if (peerTest)
{ {
// if peer test requested add it to the list for pending session // if peer test requested add it to the list for pending session
auto onEstablished = s->GetOnEstablished (); auto onEstablished = s->GetOnEstablished ();
if (onEstablished) if (onEstablished)
s->SetOnEstablished ([s, onEstablished]() s->SetOnEstablished ([s, onEstablished]()
{ {
onEstablished (); onEstablished ();
s->SendPeerTest (); s->SendPeerTest ();
}); });
else else
s->SetOnEstablished ([s]() { s->SendPeerTest (); }); s->SetOnEstablished ([s]() { s->SendPeerTest (); });
} }
return false; return false;
} }
} }
auto session = std::make_shared<SSU2Session> (*this, router, address); auto session = std::make_shared<SSU2Session> (*this, router, address);
if (peerTest) if (peerTest)
session->SetOnEstablished ([session]() {session->SendPeerTest (); }); session->SetOnEstablished ([session]() {session->SendPeerTest (); });
if (address->UsesIntroducer ()) if (address->UsesIntroducer ())
GetService ().post (std::bind (&SSU2Server::ConnectThroughIntroducer, this, session)); GetService ().post (std::bind (&SSU2Server::ConnectThroughIntroducer, this, session));
else if (isValidEndpoint) // we can't connect without endpoint else if (isValidEndpoint) // we can't connect without endpoint
GetService ().post ([session]() { session->Connect (); }); GetService ().post ([session]() { session->Connect (); });
else else
return false; return false;
@ -589,7 +589,7 @@ namespace transport
std::shared_ptr<i2p::data::RouterInfo> r; std::shared_ptr<i2p::data::RouterInfo> r;
uint32_t relayTag = 0; uint32_t relayTag = 0;
if (!address->ssu->introducers.empty ()) if (!address->ssu->introducers.empty ())
{ {
std::vector<int> indicies; std::vector<int> indicies;
for (int i = 0; i < (int)address->ssu->introducers.size (); i++) indicies.push_back(i); for (int i = 0; i < (int)address->ssu->introducers.size (); i++) indicies.push_back(i);
if (indicies.size () > 1) if (indicies.size () > 1)
@ -597,18 +597,18 @@ namespace transport
for (auto i: indicies) for (auto i: indicies)
{ {
const auto& introducer = address->ssu->introducers[indicies[i]]; const auto& introducer = address->ssu->introducers[indicies[i]];
if (introducer.iTag && ts < introducer.iExp) if (introducer.iTag && ts < introducer.iExp)
{ {
r = i2p::data::netdb.FindRouter (introducer.iKey); r = i2p::data::netdb.FindRouter (introducer.iKey);
if (r && r->IsReachableFrom (i2p::context.GetRouterInfo ())) if (r && r->IsReachableFrom (i2p::context.GetRouterInfo ()))
{ {
relayTag = introducer.iTag; relayTag = introducer.iTag;
if (relayTag) break; if (relayTag) break;
} }
} }
} }
} }
if (r) if (r)
{ {
if (relayTag) if (relayTag)
@ -620,10 +620,10 @@ namespace transport
bool isValidEndpoint = !addr->host.is_unspecified () && addr->port && bool isValidEndpoint = !addr->host.is_unspecified () && addr->port &&
!i2p::util::net::IsInReservedRange(addr->host); !i2p::util::net::IsInReservedRange(addr->host);
if (isValidEndpoint) if (isValidEndpoint)
{ {
auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (addr->host, addr->port)); auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (addr->host, addr->port));
if (!s) if (!s)
{ {
s = std::make_shared<SSU2Session> (*this, r, addr); s = std::make_shared<SSU2Session> (*this, r, addr);
s->SetOnEstablished ([session, s, relayTag]() { s->Introduce (session, relayTag); }); s->SetOnEstablished ([session, s, relayTag]() { s->Introduce (session, relayTag); });
s->Connect (); s->Connect ();
@ -637,10 +637,10 @@ namespace transport
onEstablished (); onEstablished ();
s->Introduce (session, relayTag); s->Introduce (session, relayTag);
}); });
else else
s->SetOnEstablished ([session, s, relayTag]() {s->Introduce (session, relayTag); }); s->SetOnEstablished ([session, s, relayTag]() {s->Introduce (session, relayTag); });
} }
} }
} }
} }
} }
@ -664,15 +664,15 @@ namespace transport
auto s = it->second; auto s = it->second;
if (it->second->IsEstablished ()) if (it->second->IsEstablished ())
GetService ().post ([s]() { s->SendPeerTest (); }); GetService ().post ([s]() { s->SendPeerTest (); });
else else
s->SetOnEstablished ([s]() { s->SendPeerTest (); }); s->SetOnEstablished ([s]() { s->SendPeerTest (); });
return true; return true;
} }
else else
CreateSession (router, addr, true); CreateSession (router, addr, true);
return true; return true;
} }
void SSU2Server::ScheduleTermination () void SSU2Server::ScheduleTermination ()
{ {
m_TerminationTimer.expires_from_now (boost::posix_time::seconds(SSU2_TERMINATION_CHECK_TIMEOUT)); m_TerminationTimer.expires_from_now (boost::posix_time::seconds(SSU2_TERMINATION_CHECK_TIMEOUT));
@ -718,7 +718,7 @@ namespace transport
it = m_SessionsByRouterHash.erase (it); it = m_SessionsByRouterHash.erase (it);
else else
it++; it++;
} }
for (auto it = m_Relays.begin (); it != m_Relays.begin ();) for (auto it = m_Relays.begin (); it != m_Relays.begin ();)
{ {
@ -726,8 +726,8 @@ namespace transport
it = m_Relays.erase (it); it = m_Relays.erase (it);
else else
it++; it++;
} }
for (auto it = m_IncomingTokens.begin (); it != m_IncomingTokens.end (); ) for (auto it = m_IncomingTokens.begin (); it != m_IncomingTokens.end (); )
{ {
if (ts > it->second.second) if (ts > it->second.second)
@ -743,7 +743,7 @@ namespace transport
else else
it++; it++;
} }
m_PacketsPool.CleanUpMt (); m_PacketsPool.CleanUpMt ();
m_SentPacketsPool.CleanUp (); m_SentPacketsPool.CleanUp ();
ScheduleTermination (); ScheduleTermination ();
@ -752,7 +752,7 @@ namespace transport
void SSU2Server::ScheduleResend (bool more) void SSU2Server::ScheduleResend (bool more)
{ {
m_ResendTimer.expires_from_now (boost::posix_time::milliseconds (more ? SSU2_RESEND_CHECK_MORE_TIMEOUT : m_ResendTimer.expires_from_now (boost::posix_time::milliseconds (more ? SSU2_RESEND_CHECK_MORE_TIMEOUT :
(SSU2_RESEND_CHECK_TIMEOUT + rand () % SSU2_RESEND_CHECK_TIMEOUT_VARIANCE))); (SSU2_RESEND_CHECK_TIMEOUT + rand () % SSU2_RESEND_CHECK_TIMEOUT_VARIANCE)));
m_ResendTimer.async_wait (std::bind (&SSU2Server::HandleResendTimer, m_ResendTimer.async_wait (std::bind (&SSU2Server::HandleResendTimer,
this, std::placeholders::_1)); this, std::placeholders::_1));
@ -765,10 +765,10 @@ namespace transport
size_t resentPacketsNum = 0; size_t resentPacketsNum = 0;
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it: m_Sessions) for (auto it: m_Sessions)
{ {
resentPacketsNum += it.second->Resend (ts); resentPacketsNum += it.second->Resend (ts);
if (resentPacketsNum > SSU2_MAX_RESEND_PACKETS) break; if (resentPacketsNum > SSU2_MAX_RESEND_PACKETS) break;
} }
for (auto it: m_PendingOutgoingSessions) for (auto it: m_PendingOutgoingSessions)
it.second->Resend (ts); it.second->Resend (ts);
ScheduleResend (resentPacketsNum > SSU2_MAX_RESEND_PACKETS); ScheduleResend (resentPacketsNum > SSU2_MAX_RESEND_PACKETS);
@ -788,7 +788,7 @@ namespace transport
if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second) if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second)
return 0; // token expired return 0; // token expired
return it->second.first; return it->second.first;
} }
return 0; return 0;
} }
@ -808,23 +808,23 @@ namespace transport
m_IncomingTokens.erase (ep); // drop previous m_IncomingTokens.erase (ep); // drop previous
uint64_t token; uint64_t token;
RAND_bytes ((uint8_t *)&token, 8); RAND_bytes ((uint8_t *)&token, 8);
auto ret = std::make_pair (token, i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT); auto ret = std::make_pair (token, i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT);
m_IncomingTokens.emplace (ep, ret); m_IncomingTokens.emplace (ep, ret);
return ret; return ret;
} }
std::list<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers, std::list<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers,
bool v4, const std::set<i2p::data::IdentHash>& excluded) const bool v4, const std::set<i2p::data::IdentHash>& excluded) const
{ {
std::list<std::shared_ptr<SSU2Session> > ret; std::list<std::shared_ptr<SSU2Session> > ret;
for (const auto& s : m_Sessions) for (const auto& s : m_Sessions)
{ {
if (s.second->IsEstablished () && (s.second->GetRelayTag () && s.second->IsOutgoing ()) && if (s.second->IsEstablished () && (s.second->GetRelayTag () && s.second->IsOutgoing ()) &&
!excluded.count (s.second->GetRemoteIdentity ()->GetIdentHash ()) && !excluded.count (s.second->GetRemoteIdentity ()->GetIdentHash ()) &&
((v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V4)) || ((v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V4)) ||
(!v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V6)))) (!v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V6))))
ret.push_back (s.second); ret.push_back (s.second);
} }
if ((int)ret.size () > maxNumIntroducers) if ((int)ret.size () > maxNumIntroducers)
{ {
// shink ret randomly // shink ret randomly
@ -838,7 +838,7 @@ namespace transport
} }
} }
return ret; return ret;
} }
void SSU2Server::UpdateIntroducers (bool v4) void SSU2Server::UpdateIntroducers (bool v4)
{ {
@ -850,11 +850,11 @@ namespace transport
{ {
std::shared_ptr<SSU2Session> session; std::shared_ptr<SSU2Session> session;
auto it1 = m_SessionsByRouterHash.find (it); auto it1 = m_SessionsByRouterHash.find (it);
if (it1 != m_SessionsByRouterHash.end ()) if (it1 != m_SessionsByRouterHash.end ())
{ {
session = it1->second; session = it1->second;
excluded.insert (it); excluded.insert (it);
} }
if (session && session->IsEstablished ()) if (session && session->IsEstablished ())
{ {
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION)
@ -863,10 +863,10 @@ namespace transport
newList.push_back (it); newList.push_back (it);
else else
session = nullptr; session = nullptr;
} }
if (!session) if (!session)
i2p::context.RemoveSSU2Introducer (it, v4); i2p::context.RemoveSSU2Introducer (it, v4);
} }
if (newList.size () < SSU2_MAX_NUM_INTRODUCERS) if (newList.size () < SSU2_MAX_NUM_INTRODUCERS)
{ {
auto sessions = FindIntroducers (SSU2_MAX_NUM_INTRODUCERS - newList.size (), v4, excluded); auto sessions = FindIntroducers (SSU2_MAX_NUM_INTRODUCERS - newList.size (), v4, excluded);
@ -875,24 +875,24 @@ namespace transport
// bump creation time for previous introducers if no new sessions found // bump creation time for previous introducers if no new sessions found
LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing");
for (auto& it : introducers) for (auto& it : introducers)
{ {
auto it1 = m_SessionsByRouterHash.find (it); auto it1 = m_SessionsByRouterHash.find (it);
if (it1 != m_SessionsByRouterHash.end ()) if (it1 != m_SessionsByRouterHash.end ())
{ {
auto session = it1->second; auto session = it1->second;
if (session->IsEstablished ()) if (session->IsEstablished ())
{ {
session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION);
if (std::find (newList.begin (), newList.end (), it) == newList.end ()) if (std::find (newList.begin (), newList.end (), it) == newList.end ())
{ {
newList.push_back (it); newList.push_back (it);
sessions.push_back (session); sessions.push_back (session);
} }
} }
} }
} }
} }
for (const auto& it : sessions) for (const auto& it : sessions)
{ {
i2p::data::RouterInfo::Introducer introducer; i2p::data::RouterInfo::Introducer introducer;
@ -902,13 +902,13 @@ namespace transport
excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ());
if (i2p::context.AddSSU2Introducer (introducer, v4)) if (i2p::context.AddSSU2Introducer (introducer, v4))
{ {
LogPrint (eLogDebug, "SSU2: Introducer added ", it->GetRelayTag (), " at ", LogPrint (eLogDebug, "SSU2: Introducer added ", it->GetRelayTag (), " at ",
i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ())); i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()));
newList.push_back (it->GetRemoteIdentity ()->GetIdentHash ()); newList.push_back (it->GetRemoteIdentity ()->GetIdentHash ());
if (newList.size () >= SSU2_MAX_NUM_INTRODUCERS) break; if (newList.size () >= SSU2_MAX_NUM_INTRODUCERS) break;
} }
} }
} }
introducers = newList; introducers = newList;
if (introducers.size () < SSU2_MAX_NUM_INTRODUCERS) if (introducers.size () < SSU2_MAX_NUM_INTRODUCERS)
@ -937,12 +937,12 @@ namespace transport
void SSU2Server::ScheduleIntroducersUpdateTimer () void SSU2Server::ScheduleIntroducersUpdateTimer ()
{ {
if (m_IsPublished) if (m_IsPublished)
{ {
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL));
m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, true)); this, std::placeholders::_1, true));
} }
} }
void SSU2Server::RescheduleIntroducersUpdateTimer () void SSU2Server::RescheduleIntroducersUpdateTimer ()
{ {
@ -954,18 +954,18 @@ namespace transport
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2));
m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, true)); this, std::placeholders::_1, true));
} }
} }
void SSU2Server::ScheduleIntroducersUpdateTimerV6 () void SSU2Server::ScheduleIntroducersUpdateTimerV6 ()
{ {
if (m_IsPublished) if (m_IsPublished)
{ {
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL));
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, false)); this, std::placeholders::_1, false));
} }
} }
void SSU2Server::RescheduleIntroducersUpdateTimerV6 () void SSU2Server::RescheduleIntroducersUpdateTimerV6 ()
{ {
@ -977,9 +977,9 @@ namespace transport
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2));
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, false)); this, std::placeholders::_1, false));
} }
} }
void SSU2Server::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4) void SSU2Server::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
@ -1004,7 +1004,7 @@ namespace transport
auto addr = i2p::context.GetRouterInfo ().GetSSU2V4Address (); auto addr = i2p::context.GetRouterInfo ().GetSSU2V4Address ();
if (addr && addr->ssu && addr->ssu->introducers.empty ()) if (addr && addr->ssu && addr->ssu->introducers.empty ())
i2p::context.SetUnreachableSSU2 (true, false); // v4 i2p::context.SetUnreachableSSU2 (true, false); // v4
UpdateIntroducers (true); UpdateIntroducers (true);
ScheduleIntroducersUpdateTimer (); ScheduleIntroducersUpdateTimer ();
} }
@ -1027,11 +1027,11 @@ namespace transport
auto addr = i2p::context.GetRouterInfo ().GetSSU2V6Address (); auto addr = i2p::context.GetRouterInfo ().GetSSU2V6Address ();
if (addr && addr->ssu && addr->ssu->introducers.empty ()) if (addr && addr->ssu && addr->ssu->introducers.empty ())
i2p::context.SetUnreachableSSU2 (false, true); // v6 i2p::context.SetUnreachableSSU2 (false, true); // v6
UpdateIntroducers (false); UpdateIntroducers (false);
ScheduleIntroducersUpdateTimerV6 (); ScheduleIntroducersUpdateTimerV6 ();
} }
} }
} }
} }
} }

18
libi2pd/SSU2.h

@ -28,7 +28,7 @@ namespace transport
const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes
const int SSU2_KEEP_ALIVE_INTERVAL = 30; // 30 seconds const int SSU2_KEEP_ALIVE_INTERVAL = 30; // 30 seconds
class SSU2Server: private i2p::util::RunnableServiceWithWork class SSU2Server: private i2p::util::RunnableServiceWithWork
{ {
struct Packet struct Packet
@ -60,7 +60,7 @@ namespace transport
bool IsSupported (const boost::asio::ip::address& addr) const; bool IsSupported (const boost::asio::ip::address& addr) const;
uint16_t GetPort (bool v4) const; uint16_t GetPort (bool v4) const;
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
void AddSession (std::shared_ptr<SSU2Session> session); void AddSession (std::shared_ptr<SSU2Session> session);
void RemoveSession (uint64_t connID); void RemoveSession (uint64_t connID);
void AddSessionByRouterHash (std::shared_ptr<SSU2Session> session); void AddSessionByRouterHash (std::shared_ptr<SSU2Session> session);
@ -70,7 +70,7 @@ namespace transport
std::shared_ptr<SSU2Session> FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const; std::shared_ptr<SSU2Session> FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const;
std::shared_ptr<SSU2Session> GetRandomSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports, std::shared_ptr<SSU2Session> GetRandomSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports,
const i2p::data::IdentHash& excluded) const; const i2p::data::IdentHash& excluded) const;
void AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay); void AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay);
void RemoveRelay (uint32_t tag); void RemoveRelay (uint32_t tag);
std::shared_ptr<SSU2Session> FindRelaySession (uint32_t tag); std::shared_ptr<SSU2Session> FindRelaySession (uint32_t tag);
@ -83,17 +83,17 @@ namespace transport
bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router, bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest = false); std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest = false);
bool StartPeerTest (std::shared_ptr<const i2p::data::RouterInfo> router, bool v4); bool StartPeerTest (std::shared_ptr<const i2p::data::RouterInfo> router, bool v4);
void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp); void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp);
uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const; uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const;
uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep); uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep);
std::pair<uint64_t, uint32_t> NewIncomingToken (const boost::asio::ip::udp::endpoint& ep); std::pair<uint64_t, uint32_t> NewIncomingToken (const boost::asio::ip::udp::endpoint& ep);
void RescheduleIntroducersUpdateTimer (); void RescheduleIntroducersUpdateTimer ();
void RescheduleIntroducersUpdateTimerV6 (); void RescheduleIntroducersUpdateTimerV6 ();
i2p::util::MemoryPool<SSU2SentPacket>& GetSentPacketsPool () { return m_SentPacketsPool; }; i2p::util::MemoryPool<SSU2SentPacket>& GetSentPacketsPool () { return m_SentPacketsPool; };
private: private:
boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint);
@ -111,13 +111,13 @@ namespace transport
void HandleResendTimer (const boost::system::error_code& ecode); void HandleResendTimer (const boost::system::error_code& ecode);
void ConnectThroughIntroducer (std::shared_ptr<SSU2Session> session); void ConnectThroughIntroducer (std::shared_ptr<SSU2Session> session);
std::list<std::shared_ptr<SSU2Session> > FindIntroducers (int maxNumIntroducers, std::list<std::shared_ptr<SSU2Session> > FindIntroducers (int maxNumIntroducers,
bool v4, const std::set<i2p::data::IdentHash>& excluded) const; bool v4, const std::set<i2p::data::IdentHash>& excluded) const;
void UpdateIntroducers (bool v4); void UpdateIntroducers (bool v4);
void ScheduleIntroducersUpdateTimer (); void ScheduleIntroducersUpdateTimer ();
void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4); void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4);
void ScheduleIntroducersUpdateTimerV6 (); void ScheduleIntroducersUpdateTimerV6 ();
private: private:
ReceiveService m_ReceiveService; ReceiveService m_ReceiveService;
@ -136,7 +136,7 @@ namespace transport
std::shared_ptr<SSU2Session> m_LastSession; std::shared_ptr<SSU2Session> m_LastSession;
bool m_IsPublished; // if we maintain introducers bool m_IsPublished; // if we maintain introducers
bool m_IsSyncClockFromPeers; bool m_IsSyncClockFromPeers;
public: public:
// for HTTP/I2PControl // for HTTP/I2PControl

546
libi2pd/SSU2Session.cpp

File diff suppressed because it is too large Load Diff

22
libi2pd/SSU2Session.h

@ -49,8 +49,8 @@ namespace transport
const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64;
// flags // flags
const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01;
enum SSU2MessageType enum SSU2MessageType
{ {
eSSU2SessionRequest = 0, eSSU2SessionRequest = 0,
@ -123,7 +123,7 @@ namespace transport
eSSU2PeerTestCodeCharlieAliceIsBanned = 69, eSSU2PeerTestCodeCharlieAliceIsBanned = 69,
eSSU2PeerTestCodeCharlieAliceIsUnknown = 70, eSSU2PeerTestCodeCharlieAliceIsUnknown = 70,
eSSU2PeerTestCodeUnspecified = 128 eSSU2PeerTestCodeUnspecified = 128
}; };
enum SSU2RelayResponseCode enum SSU2RelayResponseCode
{ {
@ -132,7 +132,7 @@ namespace transport
eSSU2RelayResponseCodeCharlieUnsupportedAddress = 65, eSSU2RelayResponseCodeCharlieUnsupportedAddress = 65,
eSSU2RelayResponseCodeCharlieSignatureFailure = 67, eSSU2RelayResponseCodeCharlieSignatureFailure = 67,
eSSU2RelayResponseCodeCharlieAliceIsUnknown = 70 eSSU2RelayResponseCodeCharlieAliceIsUnknown = 70
}; };
enum SSU2TerminationReason enum SSU2TerminationReason
{ {
@ -159,8 +159,8 @@ namespace transport
eSSU2TerminationReasonIncompatibleVersion = 20, eSSU2TerminationReasonIncompatibleVersion = 20,
eSSU2TerminationReasonWrongNetID = 21, eSSU2TerminationReasonWrongNetID = 21,
eSSU2TerminationReasonReplacedByNewSession = 22 eSSU2TerminationReasonReplacedByNewSession = 22
}; };
struct SSU2IncompleteMessage struct SSU2IncompleteMessage
{ {
struct Fragment struct Fragment
@ -185,7 +185,7 @@ namespace transport
uint64_t sendTime; // in milliseconds uint64_t sendTime; // in milliseconds
int numResends = 0; int numResends = 0;
}; };
// RouterInfo flags // RouterInfo flags
const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02; const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02;
@ -268,7 +268,7 @@ namespace transport
bool SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg); bool SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
void ResendHandshakePacket (); void ResendHandshakePacket ();
void ConnectAfterIntroduction (); void ConnectAfterIntroduction ();
void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len); void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len);
void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len); void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len);
@ -282,10 +282,10 @@ namespace transport
void SendQuickAck (); void SendQuickAck ();
void SendTermination (); void SendTermination ();
void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey, uint64_t token); void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey, uint64_t token);
void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message
void SendPathResponse (const uint8_t * data, size_t len); void SendPathResponse (const uint8_t * data, size_t len);
void SendPathChallenge (); void SendPathChallenge ();
void HandlePayload (const uint8_t * buf, size_t len); void HandlePayload (const uint8_t * buf, size_t len);
void HandleDateTime (const uint8_t * buf, size_t len); void HandleDateTime (const uint8_t * buf, size_t len);
void HandleAck (const uint8_t * buf, size_t len); void HandleAck (const uint8_t * buf, size_t len);
@ -316,7 +316,7 @@ namespace transport
size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg); size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg);
size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID); size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID);
size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen); size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen);
size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4); size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4);
size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen);
size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice
size_t CreateTerminationBlock (uint8_t * buf, size_t len); size_t CreateTerminationBlock (uint8_t * buf, size_t len);

10
libi2pd/TransportSession.h

@ -27,7 +27,7 @@ namespace transport
const size_t IPV4_HEADER_SIZE = 20; const size_t IPV4_HEADER_SIZE = 20;
const size_t IPV6_HEADER_SIZE = 40; const size_t IPV6_HEADER_SIZE = 40;
const size_t UDP_HEADER_SIZE = 8; const size_t UDP_HEADER_SIZE = 8;
class SignedData class SignedData
{ {
public: public:
@ -42,7 +42,7 @@ namespace transport
{ {
m_Stream.str(""); m_Stream.str("");
} }
void Insert (const uint8_t * buf, size_t len) void Insert (const uint8_t * buf, size_t len)
{ {
m_Stream.write ((char *)buf, len); m_Stream.write ((char *)buf, len);
@ -68,7 +68,7 @@ namespace transport
std::stringstream m_Stream; std::stringstream m_Stream;
}; };
class TransportSession class TransportSession
{ {
public: public:
@ -79,7 +79,7 @@ namespace transport
{ {
if (router) if (router)
m_RemoteIdentity = router->GetRouterIdentity (); m_RemoteIdentity = router->GetRouterIdentity ();
m_CreationTime = m_LastActivityTimestamp; m_CreationTime = m_LastActivityTimestamp;
} }
virtual ~TransportSession () {}; virtual ~TransportSession () {};
@ -109,7 +109,7 @@ namespace transport
uint32_t GetCreationTime () const { return m_CreationTime; }; uint32_t GetCreationTime () const { return m_CreationTime; };
void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers
virtual uint32_t GetRelayTag () const { return 0; }; virtual uint32_t GetRelayTag () const { return 0; };
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); }; virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0; virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;

42
libi2pd/Transports.cpp

@ -462,7 +462,7 @@ namespace transport
{ {
case i2p::data::RouterInfo::eNTCP2V4: case i2p::data::RouterInfo::eNTCP2V4:
case i2p::data::RouterInfo::eNTCP2V6: case i2p::data::RouterInfo::eNTCP2V6:
{ {
if (!m_NTCP2Server) continue; if (!m_NTCP2Server) continue;
std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eNTCP2V6) ? std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eNTCP2V6) ?
peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address ();
@ -493,7 +493,7 @@ namespace transport
return true; return true;
} }
break; break;
} }
case i2p::data::RouterInfo::eSSUV4: case i2p::data::RouterInfo::eSSUV4:
case i2p::data::RouterInfo::eSSUV6: case i2p::data::RouterInfo::eSSUV6:
{ {
@ -508,7 +508,7 @@ namespace transport
return true; return true;
} }
break; break;
} }
case i2p::data::RouterInfo::eNTCP2V6Mesh: case i2p::data::RouterInfo::eNTCP2V6Mesh:
{ {
if (!m_NTCP2Server) continue; if (!m_NTCP2Server) continue;
@ -518,14 +518,14 @@ namespace transport
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address); auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
m_NTCP2Server->Connect (s); m_NTCP2Server->Connect (s);
return true; return true;
} }
break; break;
} }
default: default:
LogPrint (eLogError, "Transports: Unknown transport ", (int)tr); LogPrint (eLogError, "Transports: Unknown transport ", (int)tr);
} }
} }
LogPrint (eLogInfo, "Transports: No compatible addresses available"); LogPrint (eLogInfo, "Transports: No compatible addresses available");
i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed
peer.Done (); peer.Done ();
@ -538,14 +538,14 @@ namespace transport
LogPrint (eLogInfo, "Transports: RouterInfo for ", ident.ToBase64 (), " not found, requested"); LogPrint (eLogInfo, "Transports: RouterInfo for ", ident.ToBase64 (), " not found, requested");
i2p::data::netdb.RequestDestination (ident, std::bind ( i2p::data::netdb.RequestDestination (ident, std::bind (
&Transports::RequestComplete, this, std::placeholders::_1, ident)); &Transports::RequestComplete, this, std::placeholders::_1, ident));
} }
return true; return true;
} }
void Transports::SetPriority (Peer& peer) const void Transports::SetPriority (Peer& peer) const
{ {
static const std::vector<i2p::data::RouterInfo::SupportedTransports> static const std::vector<i2p::data::RouterInfo::SupportedTransports>
ntcp2Priority = ntcp2Priority =
{ {
i2p::data::RouterInfo::eNTCP2V6, i2p::data::RouterInfo::eNTCP2V6,
i2p::data::RouterInfo::eNTCP2V4, i2p::data::RouterInfo::eNTCP2V4,
@ -554,8 +554,8 @@ namespace transport
i2p::data::RouterInfo::eNTCP2V6Mesh, i2p::data::RouterInfo::eNTCP2V6Mesh,
i2p::data::RouterInfo::eSSUV6, i2p::data::RouterInfo::eSSUV6,
i2p::data::RouterInfo::eSSUV4 i2p::data::RouterInfo::eSSUV4
}, },
ssu2Priority = ssu2Priority =
{ {
i2p::data::RouterInfo::eSSU2V6, i2p::data::RouterInfo::eSSU2V6,
i2p::data::RouterInfo::eSSU2V4, i2p::data::RouterInfo::eSSU2V4,
@ -564,7 +564,7 @@ namespace transport
i2p::data::RouterInfo::eNTCP2V6Mesh, i2p::data::RouterInfo::eNTCP2V6Mesh,
i2p::data::RouterInfo::eSSUV6, i2p::data::RouterInfo::eSSUV6,
i2p::data::RouterInfo::eSSUV4 i2p::data::RouterInfo::eSSUV4
}; };
if (!peer.router) return; if (!peer.router) return;
auto compatibleTransports = context.GetRouterInfo ().GetCompatibleTransports (false) & auto compatibleTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
peer.router->GetCompatibleTransports (true); peer.router->GetCompatibleTransports (true);
@ -574,9 +574,9 @@ namespace transport
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority; const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
for (auto transport: priority) for (auto transport: priority)
if (transport & compatibleTransports) if (transport & compatibleTransports)
peer.priority.push_back (transport); peer.priority.push_back (transport);
} }
void Transports::RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident) void Transports::RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident)
{ {
m_Service->post (std::bind (&Transports::HandleRequestComplete, this, r, ident)); m_Service->post (std::bind (&Transports::HandleRequestComplete, this, r, ident));
@ -834,7 +834,7 @@ namespace transport
auto session = it->second.sessions.front (); auto session = it->second.sessions.front ();
if (session) if (session)
session->SendLocalRouterInfo (true); session->SendLocalRouterInfo (true);
it->second.nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL + it->second.nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE; rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
} }
++it; ++it;
@ -1074,6 +1074,6 @@ namespace transport
i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish
} }
} }
} }
} }

8
libi2pd/Transports.h

@ -62,8 +62,8 @@ namespace transport
}; };
typedef EphemeralKeysSupplier<i2p::crypto::X25519Keys> X25519KeysPairSupplier; typedef EphemeralKeysSupplier<i2p::crypto::X25519Keys> X25519KeysPairSupplier;
const int PEER_ROUTER_INFO_UPDATE_INTERVAL = 31*60; // in seconds const int PEER_ROUTER_INFO_UPDATE_INTERVAL = 31*60; // in seconds
const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds
struct Peer struct Peer
{ {
int numAttempts; int numAttempts;
@ -77,8 +77,8 @@ namespace transport
numAttempts (0), router (r), creationTime (ts), numAttempts (0), router (r), creationTime (ts),
nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL) nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL)
{ {
} }
void Done () void Done ()
{ {
for (auto& it: sessions) for (auto& it: sessions)

4
libi2pd_client/AddressBook.cpp

@ -313,14 +313,14 @@ namespace client
{ {
i2p::config::GetOption("addressbook.enabled", m_IsEnabled); i2p::config::GetOption("addressbook.enabled", m_IsEnabled);
if (m_IsEnabled) if (m_IsEnabled)
{ {
if (!m_Storage) if (!m_Storage)
m_Storage = new AddressBookFilesystemStorage; m_Storage = new AddressBookFilesystemStorage;
m_Storage->Init(); m_Storage->Init();
LoadHosts (); /* try storage, then hosts.txt, then download */ LoadHosts (); /* try storage, then hosts.txt, then download */
StartSubscriptions (); StartSubscriptions ();
StartLookups (); StartLookups ();
} }
} }
void AddressBook::StartResolvers () void AddressBook::StartResolvers ()

4
libi2pd_client/ClientContext.cpp

@ -727,7 +727,7 @@ namespace client
std::string address = section.second.get<std::string> (I2P_SERVER_TUNNEL_ADDRESS, ""); std::string address = section.second.get<std::string> (I2P_SERVER_TUNNEL_ADDRESS, "");
bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true);
bool ssl = section.second.get(I2P_SERVER_TUNNEL_SSL, false); bool ssl = section.second.get(I2P_SERVER_TUNNEL_SSL, false);
// I2CP // I2CP
std::map<std::string, std::string> options; std::map<std::string, std::string> options;
ReadI2CPOptions (section, true, options); ReadI2CPOptions (section, true, options);
@ -868,7 +868,7 @@ namespace client
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper); bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper);
if (httpAddresshelper) if (httpAddresshelper)
i2p::config::GetOption("addressbook.enabled", httpAddresshelper); // addresshelper is not supported without address book i2p::config::GetOption("addressbook.enabled", httpAddresshelper); // addresshelper is not supported without address book
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
LogPrint(eLogInfo, "Clients: Starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); LogPrint(eLogInfo, "Clients: Starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
if (httpProxyKeys.length () > 0) if (httpProxyKeys.length () > 0)

48
libi2pd_client/I2PTunnel.cpp

@ -86,7 +86,7 @@ namespace client
static void MapToLoopback(std::shared_ptr<boost::asio::ip::tcp::socket> sock, const i2p::data::IdentHash & addr) static void MapToLoopback(std::shared_ptr<boost::asio::ip::tcp::socket> sock, const i2p::data::IdentHash & addr)
{ {
if (sock) if (sock)
{ {
// bind to 127.x.x.x address // bind to 127.x.x.x address
// where x.x.x are first three bytes from ident // where x.x.x are first three bytes from ident
auto ourIP = GetLoopbackAddressFor(addr); auto ourIP = GetLoopbackAddressFor(addr);
@ -101,7 +101,7 @@ namespace client
void I2PTunnelConnection::Connect (bool isUniqueLocal) void I2PTunnelConnection::Connect (bool isUniqueLocal)
{ {
if (m_Socket) if (m_Socket)
{ {
I2PTunnelSetSocketOptions (m_Socket); I2PTunnelSetSocketOptions (m_Socket);
#ifdef __linux__ #ifdef __linux__
if (isUniqueLocal && m_RemoteEndpoint.address ().is_v4 () && if (isUniqueLocal && m_RemoteEndpoint.address ().is_v4 () &&
@ -132,7 +132,7 @@ namespace client
} }
Connect (false); Connect (false);
} }
void I2PTunnelConnection::Terminate () void I2PTunnelConnection::Terminate ()
{ {
if (Kill()) return; if (Kill()) return;
@ -155,7 +155,7 @@ namespace client
m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
else else
m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
@ -253,7 +253,7 @@ namespace client
if (m_SSL) if (m_SSL)
boost::asio::async_write (*m_SSL, boost::asio::buffer (buf, len), boost::asio::transfer_all (), boost::asio::async_write (*m_SSL, boost::asio::buffer (buf, len), boost::asio::transfer_all (),
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1)); std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
else else
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (), boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (),
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1)); std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
} }
@ -269,9 +269,9 @@ namespace client
{ {
LogPrint (eLogDebug, "I2PTunnel: Connected"); LogPrint (eLogDebug, "I2PTunnel: Connected");
if (m_SSL) if (m_SSL)
m_SSL->async_handshake (boost::asio::ssl::stream_base::client, m_SSL->async_handshake (boost::asio::ssl::stream_base::client,
std::bind (&I2PTunnelConnection::HandleHandshake, shared_from_this (), std::placeholders::_1)); std::bind (&I2PTunnelConnection::HandleHandshake, shared_from_this (), std::placeholders::_1));
else else
Established (); Established ();
} }
} }
@ -289,7 +289,7 @@ namespace client
Established (); Established ();
} }
} }
void I2PTunnelConnection::Established () void I2PTunnelConnection::Established ()
{ {
if (m_IsQuiet) if (m_IsQuiet)
@ -305,8 +305,8 @@ namespace client
HandleStreamReceive (boost::system::error_code (), dest.size ()); HandleStreamReceive (boost::system::error_code (), dest.size ());
} }
Receive (); Receive ();
} }
void I2PClientTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len) void I2PClientTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len)
{ {
if (m_HeaderSent) if (m_HeaderSent)
@ -363,9 +363,9 @@ namespace client
StreamReceive (); // read more header StreamReceive (); // read more header
else else
{ {
LogPrint (eLogError, "I2PTunnel: HTTP header exceeds max size ", I2P_TUNNEL_HTTP_MAX_HEADER_SIZE); LogPrint (eLogError, "I2PTunnel: HTTP header exceeds max size ", I2P_TUNNEL_HTTP_MAX_HEADER_SIZE);
Terminate (); Terminate ();
} }
} }
} }
@ -376,7 +376,7 @@ namespace client
m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ()) m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ())
{ {
if (sslCtx) if (sslCtx)
SSL_set_tlsext_host_name(GetSSL ()->native_handle(), host.c_str ()); SSL_set_tlsext_host_name(GetSSL ()->native_handle(), host.c_str ());
} }
void I2PServerTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len) void I2PServerTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len)
@ -400,7 +400,7 @@ namespace client
// strip up some headers // strip up some headers
static const std::vector<std::string> excluded // list of excluded headers static const std::vector<std::string> excluded // list of excluded headers
{ {
"Keep-Alive:", "X-I2P" "Keep-Alive:", "X-I2P"
}; };
bool matched = false; bool matched = false;
for (const auto& it: excluded) for (const auto& it: excluded)
@ -422,8 +422,8 @@ namespace client
else else
m_OutHeader << "Connection: close\r\n"; m_OutHeader << "Connection: close\r\n";
connection = true; connection = true;
} }
else // forward as is else // forward as is
m_OutHeader << line << "\n"; m_OutHeader << line << "\n";
} }
} }
@ -455,7 +455,7 @@ namespace client
StreamReceive (); // read more header StreamReceive (); // read more header
else else
{ {
LogPrint (eLogError, "I2PTunnel: HTTP header exceeds max size ", I2P_TUNNEL_HTTP_MAX_HEADER_SIZE); LogPrint (eLogError, "I2PTunnel: HTTP header exceeds max size ", I2P_TUNNEL_HTTP_MAX_HEADER_SIZE);
Terminate (); Terminate ();
} }
} }
@ -526,7 +526,7 @@ namespace client
if (m_NeedsWebIrc) if (m_NeedsWebIrc)
{ {
m_NeedsWebIrc = false; m_NeedsWebIrc = false;
m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ())
<< " " << GetSocket ()->local_endpoint ().address () << std::endl; << " " << GetSocket ()->local_endpoint ().address () << std::endl;
} }
@ -719,7 +719,7 @@ namespace client
auto localDestination = GetLocalDestination (); auto localDestination = GetLocalDestination ();
if (localDestination) if (localDestination)
localDestination->StopAcceptingStreams (); localDestination->StopAcceptingStreams ();
ClearHandlers (); ClearHandlers ();
} }
@ -796,14 +796,14 @@ namespace client
void I2PServerTunnel::SetSSL (bool ssl) void I2PServerTunnel::SetSSL (bool ssl)
{ {
if (ssl) if (ssl)
{ {
m_SSLCtx = std::make_shared<boost::asio::ssl::context> (boost::asio::ssl::context::sslv23); m_SSLCtx = std::make_shared<boost::asio::ssl::context> (boost::asio::ssl::context::sslv23);
m_SSLCtx->set_verify_mode(boost::asio::ssl::context::verify_none); m_SSLCtx->set_verify_mode(boost::asio::ssl::context::verify_none);
} }
else else
m_SSLCtx = nullptr; m_SSLCtx = nullptr;
} }
void I2PServerTunnel::Accept () void I2PServerTunnel::Accept ()
{ {
if (m_PortDestination) if (m_PortDestination)
@ -1004,7 +1004,7 @@ namespace client
I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination, I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip) : boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip) :
m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress), m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress),
m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_Gzip (gzip) m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_Gzip (gzip)
{ {
} }

8
libi2pd_client/I2PTunnel.h

@ -36,7 +36,7 @@ namespace client
const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64 const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192; const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192;
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection> class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
{ {
public: public:
@ -73,7 +73,7 @@ namespace client
void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleWrite (const boost::system::error_code& ecode); void HandleWrite (const boost::system::error_code& ecode);
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
private: private:
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
@ -350,9 +350,9 @@ namespace client
void SetUniqueLocal (bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; } void SetUniqueLocal (bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; }
bool IsUniqueLocal () const { return m_IsUniqueLocal; } bool IsUniqueLocal () const { return m_IsUniqueLocal; }
void SetSSL (bool ssl); void SetSSL (bool ssl);
std::shared_ptr<boost::asio::ssl::context> GetSSLCtx () const { return m_SSLCtx; }; std::shared_ptr<boost::asio::ssl::context> GetSSLCtx () const { return m_SSLCtx; };
void SetLocalAddress (const std::string& localAddress); void SetLocalAddress (const std::string& localAddress);
const std::string& GetAddress() const { return m_Address; } const std::string& GetAddress() const { return m_Address; }

4
libi2pd_client/SAM.cpp

@ -1481,7 +1481,7 @@ namespace client
auto localDest = session->GetLocalDestination (); auto localDest = session->GetLocalDestination ();
auto datagramDest = localDest ? localDest->GetDatagramDestination () : nullptr; auto datagramDest = localDest ? localDest->GetDatagramDestination () : nullptr;
if (datagramDest) if (datagramDest)
{ {
i2p::data::IdentityEx dest; i2p::data::IdentityEx dest;
dest.FromBase64 (destination); dest.FromBase64 (destination);
if (session->Type == eSAMSessionTypeDatagram) if (session->Type == eSAMSessionTypeDatagram)
@ -1490,7 +1490,7 @@ namespace client
datagramDest->SendRawDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ()); datagramDest->SendRawDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ());
else else
LogPrint (eLogError, "SAM: Unexpected session type ", (int)session->Type, "for session ", sessionID); LogPrint (eLogError, "SAM: Unexpected session type ", (int)session->Type, "for session ", sessionID);
} }
else else
LogPrint (eLogError, "SAM: Datagram destination is not set for session ", sessionID); LogPrint (eLogError, "SAM: Datagram destination is not set for session ", sessionID);
} }

Loading…
Cancel
Save