From 96c4463d39ac74a8ceb7527f3619775704a52cd6 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 9 Oct 2022 20:24:43 +0300 Subject: [PATCH] clean code Signed-off-by: R4SAS --- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 2 +- daemon/I2PControl.h | 4 +- daemon/I2PControlHandlers.cpp | 14 +- daemon/I2PControlHandlers.h | 12 +- libi2pd/NetDb.cpp | 18 +- libi2pd/NetDb.hpp | 4 +- libi2pd/RouterContext.cpp | 54 +-- libi2pd/RouterInfo.cpp | 78 ++--- libi2pd/RouterInfo.h | 4 +- libi2pd/SSU2.cpp | 242 +++++++------- libi2pd/SSU2.h | 18 +- libi2pd/SSU2Session.cpp | 546 +++++++++++++++---------------- libi2pd/SSU2Session.h | 22 +- libi2pd/TransportSession.h | 10 +- libi2pd/Transports.cpp | 42 +-- libi2pd/Transports.h | 8 +- libi2pd_client/AddressBook.cpp | 4 +- libi2pd_client/ClientContext.cpp | 4 +- libi2pd_client/I2PTunnel.cpp | 48 +-- libi2pd_client/I2PTunnel.h | 8 +- libi2pd_client/SAM.cpp | 4 +- 22 files changed, 574 insertions(+), 574 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 4d793c67..bff17e09 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -162,7 +162,7 @@ namespace util i2p::context.Init (); i2p::transport::InitTransports (); - + bool transit; i2p::config::GetOption("notransit", transit); i2p::context.SetAcceptsTunnels (!transit); uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index dfead4d2..8d57dedb 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -250,7 +250,7 @@ namespace http { break; default: ; } - } + } } void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat) diff --git a/daemon/I2PControl.h b/daemon/I2PControl.h index 9a80da9a..af152631 100644 --- a/daemon/I2PControl.h +++ b/daemon/I2PControl.h @@ -63,7 +63,7 @@ namespace client void CreateCertificate (const char *crt_path, const char *key_path); private: - + // methods 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 I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results); void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results); - + // I2PControl typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value); void PasswordHandler (const std::string& value); diff --git a/daemon/I2PControlHandlers.cpp b/daemon/I2PControlHandlers.cpp index 02508f29..15763948 100644 --- a/daemon/I2PControlHandlers.cpp +++ b/daemon/I2PControlHandlers.cpp @@ -43,7 +43,7 @@ namespace client // NetworkSetting m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlHandlers::InboundBandwidthLimit; m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlHandlers::OutboundBandwidthLimit; - + // ClientServicesInfo m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlHandlers::I2PTunnelInfoHandler; m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlHandlers::HTTPProxyInfoHandler; @@ -51,7 +51,7 @@ namespace client m_ClientServicesInfoHandlers["SAM"] = &I2PControlHandlers::SAMInfoHandler; m_ClientServicesInfoHandlers["BOB"] = &I2PControlHandlers::BOBInfoHandler; m_ClientServicesInfoHandlers["I2CP"] = &I2PControlHandlers::I2CPInfoHandler; - } + } 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; } - + void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const { std::ostringstream buf; @@ -167,8 +167,8 @@ namespace client void I2PControlHandlers::NetTotalSentBytes (std::ostringstream& results) { InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ()); - } - + } + // network setting void I2PControlHandlers::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { @@ -199,7 +199,7 @@ namespace client int bw = i2p::context.GetBandwidthLimit(); InsertParam (results, "i2p.router.net.bw.out", bw); } - + // ClientServicesInfo 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); } } - + void I2PControlHandlers::I2PTunnelInfoHandler (std::ostringstream& results) { boost::property_tree::ptree pt; diff --git a/daemon/I2PControlHandlers.h b/daemon/I2PControlHandlers.h index 32adce8b..e33a19fc 100644 --- a/daemon/I2PControlHandlers.h +++ b/daemon/I2PControlHandlers.h @@ -29,14 +29,14 @@ namespace client void RouterInfoHandler (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); - + protected: 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, 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: // RouterInfo @@ -53,12 +53,12 @@ namespace client void OutboundBandwidth1S (std::ostringstream& results); void NetTotalReceivedBytes (std::ostringstream& results); void NetTotalSentBytes (std::ostringstream& results); - + // NetworkSetting typedef void (I2PControlHandlers::*NetworkSettingRequestHandler)(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); - + // ClientServicesInfo typedef void (I2PControlHandlers::*ClientServicesInfoRequestHandler)(std::ostringstream& results); void I2PTunnelInfoHandler (std::ostringstream& results); @@ -67,7 +67,7 @@ namespace client void SAMInfoHandler (std::ostringstream& results); void BOBInfoHandler (std::ostringstream& results); void I2CPInfoHandler (std::ostringstream& results); - + private: std::map m_RouterInfoHandlers; diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 6042eaf2..5abe2fdc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -274,7 +274,7 @@ namespace data { std::unique_lock l(m_RouterInfosMutex); r->Update (buf, len); - } + } LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated { @@ -438,14 +438,14 @@ namespace data // try reseeding from floodfill first if specified std::string riPath; - if(i2p::config::GetOption("reseed.floodfill", riPath)) + if(i2p::config::GetOption("reseed.floodfill", riPath)) { auto ri = std::make_shared(riPath); - if (ri->IsFloodfill()) + if (ri->IsFloodfill()) { const uint8_t * riData = ri->GetBuffer(); int riLen = ri->GetBufferLen(); - if (!i2p::data::netdb.AddRouterInfo(riData, riLen)) + if (!i2p::data::netdb.AddRouterInfo(riData, riLen)) { // bad router info LogPrint(eLogError, "NetDb: Bad router info"); @@ -629,7 +629,7 @@ namespace data it.second->SetUnreachable (false); // find & mark expired routers 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) // RouterInfo expires after 1 hour if uses introducer @@ -1218,7 +1218,7 @@ namespace data router->IsSSU2PeerTesting (v4) && !excluded.count (router->GetIdentHash ()); }); } - + std::shared_ptr NetDb::GetRandomSSUV6Router () const { return GetRandomRouter ( @@ -1243,11 +1243,11 @@ namespace data return GetRandomRouter ( [v4, &excluded](std::shared_ptr router)->bool { - return !router->IsHidden () && router->IsSSU2Introducer (v4) && + return !router->IsHidden () && router->IsSSU2Introducer (v4) && !excluded.count (router->GetIdentHash ()); }); } - + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const { return GetRandomRouter ( @@ -1455,6 +1455,6 @@ namespace data { if (!r || r->GetBuffer ()) return; r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ())); - } + } } } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b14b84e7..26e0a41b 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -125,8 +125,8 @@ namespace data void ClearRouterInfos () { m_RouterInfos.clear (); }; std::shared_ptr NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; - void PopulateRouterInfoBuffer (std::shared_ptr r); - std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; + void PopulateRouterInfoBuffer (std::shared_ptr r); + std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 77d3763d..423bcfd7 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -121,7 +121,7 @@ namespace i2p uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port; routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), ssu2Port); - } + } else { addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; @@ -170,7 +170,7 @@ namespace i2p uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port; routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port); - } + } else { if (!ipv4) // no other ssu2 addresses yet @@ -201,8 +201,8 @@ namespace i2p uint16_t port = rand () % (30777 - 9111) + 9111; // I2P network ports range if (port == 9150) port = 9151; // Tor browser return port; - } - + } + void RouterContext::UpdateRouterInfo () { m_RouterInfo.CreateBuffer (m_Keys); @@ -354,7 +354,7 @@ namespace i2p (*it)->s = m_NTCP2Keys->staticPublicKey; memcpy ((*it)->i, m_NTCP2Keys->iv, 16); it++; - } + } else it = addresses.erase (it); updated = true; @@ -382,9 +382,9 @@ namespace i2p { newPort = address->port; break; - } + } if (!newPort) newPort = SelectRandomPort (); - } + } bool updated = false; for (auto& address : m_RouterInfo.GetAddresses ()) { @@ -419,8 +419,8 @@ namespace i2p (*it)->s = m_SSU2Keys->staticPublicKey; (*it)->i = m_SSU2Keys->intro; it++; - } - else + } + else it = addresses.erase (it); updated = true; } @@ -438,12 +438,12 @@ namespace i2p if (ipv6) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6); } else - { + { uint8_t addressCaps = 0; if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps); - } + } updated = true; } if (updated) @@ -462,7 +462,7 @@ namespace i2p address->host = host; updated = true; } - if (host.is_v6 () && address->IsV6 () && address->ssu && + if (host.is_v6 () && address->IsV6 () && address->ssu && (!address->ssu->mtu || updated)) { // update MTU @@ -471,8 +471,8 @@ namespace i2p { LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu); int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ()); - if (mtu > maxMTU) - { + if (mtu > maxMTU) + { mtu = maxMTU; LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes"); } @@ -531,8 +531,8 @@ namespace i2p } if (updated) UpdateRouterInfo (); - } - + } + void RouterContext::SetFloodfill (bool floodfill) { m_IsFloodfill = floodfill; @@ -658,17 +658,17 @@ namespace i2p for (auto it = addresses.begin (); it != addresses.end ();) { if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportSSU) - { + { it = addresses.erase (it); updated = true; - } + } else ++it; } if (updated) m_RouterInfo.UpdateSupportedTransports (); } - + void RouterContext::SetUnreachableSSU2 (bool v4, bool v6) { if (IsSSU2Only ()) @@ -691,7 +691,7 @@ namespace i2p // delete previous introducers auto& addresses = m_RouterInfo.GetAddresses (); for (auto& addr : addresses) - if (addr->ssu && (!addr->IsSSU2 () || IsSSU2Only ()) && + if (addr->ssu && (!addr->IsSSU2 () || IsSSU2Only ()) && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) { addr->published = false; @@ -727,7 +727,7 @@ namespace i2p i2p::config::GetOption ("ssu2.published", isSSU2Published); auto& addresses = m_RouterInfo.GetAddresses (); for (auto& addr : addresses) - if (addr->ssu && (!addr->IsSSU2 () || isSSU2Published) && + if (addr->ssu && (!addr->IsSSU2 () || isSSU2Published) && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) { addr->published = true; @@ -781,11 +781,11 @@ namespace i2p } port = addr->port; } - if (!port) - { + if (!port) + { i2p::config::GetOption("port", port); if (!port) port = SelectRandomPort (); - } + } // SSU bool ssu; i2p::config::GetOption("ssu", ssu); if (!foundSSU && ssu) @@ -871,11 +871,11 @@ namespace i2p } if (addr->port) port = addr->port; } - if (!port) - { + if (!port) + { i2p::config::GetOption("port", port); if (!port) port = SelectRandomPort (); - } + } // SSU bool ssu; i2p::config::GetOption("ssu", ssu); if (!foundSSU && ssu) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 60fd3358..d9c966d7 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -257,29 +257,29 @@ namespace data if (!ecode && !address->host.is_unspecified ()) isHost = true; } else if (!strcmp (key, "port")) - { - try - { + { + try + { address->port = boost::lexical_cast(value); } catch (std::exception& ex) { LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ()); - } - } + } + } else if (!strcmp (key, "mtu")) { if (address->ssu) { try - { + { address->ssu->mtu = boost::lexical_cast(value); } catch (std::exception& ex) { LogPrint (eLogWarning, "RouterInfo: 'mtu' exception ", ex.what ()); - } - } + } + } else LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2"); } @@ -347,38 +347,38 @@ namespace data else if (!strcmp (key, "iport")) { try - { + { introducer.iPort = boost::lexical_cast(value); } catch (std::exception& ex) { LogPrint (eLogWarning, "RouterInfo: 'iport' exception ", ex.what ()); - } - } + } + } else if (!strcmp (key, "itag")) { try - { + { introducer.iTag = boost::lexical_cast(value); - } + } catch (std::exception& ex) { LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ()); - } + } } else if (!strcmp (key, "ikey") || !strcmp (key, "ih")) Base64ToByteStream (value, strlen (value), introducer.iKey, 32); else if (!strcmp (key, "iexp")) { try - { + { introducer.iExp = boost::lexical_cast(value); } catch (std::exception& ex) { LogPrint (eLogWarning, "RouterInfo: 'iexp' exception ", ex.what ()); - } - } + } + } } if (!s) return; } @@ -431,10 +431,10 @@ namespace data ((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ()))) numValid++; else - { + { it.iPort = 0; if (isV2) numValid++; - } + } } if (numValid) m_ReachableTransports |= supportedTransports; @@ -467,16 +467,16 @@ namespace data int numValid = 0; for (auto& it: address->ssu->introducers) { - if (it.iTag && ts <= it.iExp) + if (it.iTag && ts <= it.iExp) numValid++; - else + else it.iTag = 0; } if (numValid) m_ReachableTransports |= supportedTransports; else address->ssu->introducers.resize (0); - } + } } else { @@ -490,15 +490,15 @@ namespace data ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); if (!address->ssu->introducers.empty ()) - { + { for (const auto& introducer: address->ssu->introducers) if (!introducer.iPort && introducer.iHost.is_unspecified () && ts < introducer.iExp) // SSU2 ssu2addr->ssu->introducers.push_back (introducer); if (!ssu2addr->ssu->introducers.empty ()) m_ReachableTransports |= supportedTransports; - } + } addresses->push_back(ssu2addr); - } + } } if (supportedTransports) { @@ -982,7 +982,7 @@ namespace data std::shared_ptr RouterInfo::GetSSU2Address (bool v4) const { if (v4) - { + { if (m_SupportedTransports & eSSU2V4) return GetSSU2V4Address (); } @@ -990,10 +990,10 @@ namespace data { if (m_SupportedTransports & eSSU2V6) return GetSSU2V6Address (); - } + } return nullptr; - } - + } + template std::shared_ptr RouterInfo::GetAddress (Filter filter) const { @@ -1025,7 +1025,7 @@ namespace data return GetAddress ( [key, isV6](std::shared_ptr address)->bool { - return address->IsSSU2 () && !memcmp (address->s, key, 32) && + return address->IsSSU2 () && !memcmp (address->s, key, 32) && ((isV6 && address->IsV6 ()) || (!isV6 && address->IsV4 ())); }); } @@ -1099,8 +1099,8 @@ namespace data return (address->IsSSU2 ()) && address->IsPeerTesting () && ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU (); }); - } - + } + bool RouterInfo::IsIntroducer (bool v4) const { if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; @@ -1122,7 +1122,7 @@ namespace data ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified (); }); } - + void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) { for (auto& addr: *m_Addresses) @@ -1144,7 +1144,7 @@ namespace data { uint8_t transports = 0; switch (addr->transportStyle) - { + { case eTransportNTCP: if (addr->IsV4 ()) transports |= eNTCP2V4; if (addr->IsV6 ()) @@ -1163,9 +1163,9 @@ namespace data if (addr->IsV6 ()) transports |= eSSU2V6; if (addr->IsReachableSSU ()) m_ReachableTransports |= transports; - break; - default: ; - } + break; + default: ; + } m_SupportedTransports |= transports; } } @@ -1540,7 +1540,7 @@ namespace data } } return false; - } + } bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4) { @@ -1559,6 +1559,6 @@ namespace data } } return false; - } + } } } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 6bc66b35..8f76707c 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -276,7 +276,7 @@ namespace data void RefreshTimestamp (); const Addresses& GetAddresses () const { return *m_Addresses; }; CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; }; - void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; }; + void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; }; private: @@ -321,7 +321,7 @@ namespace data bool AddSSU2Introducer (const Introducer& introducer, bool v4); bool RemoveSSU2Introducer (const IdentHash& h, bool v4); - + private: void WriteToStream (std::ostream& s) const; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 245169d8..0c71b14e 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -17,12 +17,12 @@ namespace i2p { namespace transport -{ +{ SSU2Server::SSU2Server (): RunnableServiceWithWork ("SSU2"), m_ReceiveService ("SSU2r"), 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_TerminationTimer (GetService ()), m_ResendTimer (GetService ()), + m_TerminationTimer (GetService ()), m_ResendTimer (GetService ()), m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), m_IsPublished (true), m_IsSyncClockFromPeers (true) { @@ -93,25 +93,25 @@ namespace transport void SSU2Server::Stop () { if (IsRunning ()) - { + { m_TerminationTimer.cancel (); m_ResendTimer.cancel (); m_IntroducersUpdateTimer.cancel (); m_IntroducersUpdateTimerV6.cancel (); - } - + } + auto sessions = m_Sessions; for (auto& it: sessions) - { + { it.second->RequestTermination (eSSU2TerminationReasonRouterShutdown); it.second->Done (); - } - + } + if (context.SupportsV4 () || context.SupportsV6 ()) m_ReceiveService.Stop (); m_SocketV4.close (); m_SocketV6.close (); - + StopIOService (); m_Sessions.clear (); @@ -126,38 +126,38 @@ namespace transport { if (localAddress.is_unspecified ()) return; if (localAddress.is_v4 ()) - { + { m_AddressV4 = localAddress; int mtu = i2p::util::net::GetMTU (localAddress); if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; i2p::context.SetMTU (mtu, true); - } + } else if (localAddress.is_v6 ()) - { + { m_AddressV6 = localAddress; int maxMTU = i2p::util::net::GetMaxMTU (localAddress.to_v6 ()); int mtu = i2p::util::net::GetMTU (localAddress); if (mtu > maxMTU) mtu = maxMTU; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; i2p::context.SetMTU (mtu, false); - } - } + } + } bool SSU2Server::IsSupported (const boost::asio::ip::address& addr) const { if (addr.is_v4 ()) - { - if (m_SocketV4.is_open ()) + { + if (m_SocketV4.is_open ()) return true; - } + } else if (addr.is_v6 ()) - { - if (m_SocketV6.is_open ()) + { + if (m_SocketV6.is_open ()) return true; } return false; - } + } 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); if (ec) return 0; return ep.port (); - } - + } + 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; @@ -253,7 +253,7 @@ namespace transport { ProcessNextPacket (packet->buf, packet->len, packet->from); m_PacketsPool.ReleaseMt (packet); - if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) + if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->FlushData (); } } @@ -263,7 +263,7 @@ namespace transport for (auto& packet: packets) ProcessNextPacket (packet->buf, packet->len, packet->from); m_PacketsPool.ReleaseMt (packets); - if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) + if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->FlushData (); } @@ -289,7 +289,7 @@ namespace transport m_Sessions.erase (it); } } - + void SSU2Server::AddSessionByRouterHash (std::shared_ptr session) { if (session) @@ -323,10 +323,10 @@ namespace transport if (it != m_SessionsByRouterHash.end ()) return it->second; return nullptr; - } + } std::shared_ptr SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const - { + { auto it = m_PendingOutgoingSessions.find (ep); if (it != m_PendingOutgoingSessions.end ()) return it->second; @@ -336,8 +336,8 @@ namespace transport void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) { m_PendingOutgoingSessions.erase (ep); - } - + } + std::shared_ptr SSU2Server::GetRandomSession ( i2p::data::RouterInfo::CompatibleTransports remoteTransports, const i2p::data::IdentHash& excluded) const { @@ -349,7 +349,7 @@ namespace transport std::advance (it, ind); while (it != m_Sessions.end ()) { - if ((it->second->GetRemoteTransports () & remoteTransports) && + if ((it->second->GetRemoteTransports () & remoteTransports) && it->second->GetRemoteIdentity ()->GetIdentHash () != excluded) return it->second; it++; @@ -358,14 +358,14 @@ namespace transport it = m_Sessions.begin (); while (it != m_Sessions.end () && ind) { - if ((it->second->GetRemoteTransports () & remoteTransports) && + if ((it->second->GetRemoteTransports () & remoteTransports) && it->second->GetRemoteIdentity ()->GetIdentHash () != excluded) return it->second; it++; ind--; - } + } return nullptr; - } - + } + void SSU2Server::AddRelay (uint32_t tag, std::shared_ptr relay) { m_Relays.emplace (tag, relay); @@ -409,7 +409,7 @@ namespace transport switch (m_LastSession->GetState ()) { case eSSU2SessionStateEstablished: - case eSSU2SessionStateSessionConfirmedSent: + case eSSU2SessionStateSessionConfirmedSent: m_LastSession->ProcessData (buf, len, senderEndpoint); break; case eSSU2SessionStateSessionCreatedSent: @@ -417,10 +417,10 @@ namespace transport { m_LastSession->Done (); m_LastSession = nullptr; - } + } break; case eSSU2SessionStateIntroduced: - if (m_LastSession->GetRemoteEndpoint ().address ().is_unspecified ()) + if (m_LastSession->GetRemoteEndpoint ().address ().is_unspecified ()) m_LastSession->SetRemoteEndpoint (senderEndpoint); if (m_LastSession->GetRemoteEndpoint () == senderEndpoint) m_LastSession->ProcessHolePunch (buf, len); @@ -429,8 +429,8 @@ namespace transport LogPrint (eLogWarning, "SSU2: HolePunch endpoint ", senderEndpoint, " doesn't match RelayResponse ", m_LastSession->GetRemoteEndpoint ()); m_LastSession->Done (); - m_LastSession = nullptr; - } + m_LastSession = nullptr; + } break; case eSSU2SessionStatePeerTest: m_LastSession->SetRemoteEndpoint (senderEndpoint); @@ -440,10 +440,10 @@ namespace transport m_LastSession->ProcessData (buf, len, senderEndpoint); // we might receive termintaion block if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again - break; + break; case eSSU2SessionStateTerminated: m_LastSession = nullptr; - break; + break; default: LogPrint (eLogWarning, "SSU2: Invalid session state ", (int)m_LastSession->GetState ()); } @@ -456,7 +456,7 @@ namespace transport { if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent && 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 it1->second->ProcessRetry (buf, len); } @@ -524,41 +524,41 @@ namespace transport { auto session = it->second; GetService ().post ([session]() { session->SendPeerTest (); }); - } + } return false; - } + } // check is no pending session bool isValidEndpoint = !address->host.is_unspecified () && address->port; if (isValidEndpoint) - { + { if (i2p::util::net::IsInReservedRange(address->host)) return false; auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (address->host, address->port)); if (s) - { + { if (peerTest) { // if peer test requested add it to the list for pending session auto onEstablished = s->GetOnEstablished (); if (onEstablished) - s->SetOnEstablished ([s, onEstablished]() - { - onEstablished (); - s->SendPeerTest (); - }); - else + s->SetOnEstablished ([s, onEstablished]() + { + onEstablished (); + s->SendPeerTest (); + }); + else s->SetOnEstablished ([s]() { s->SendPeerTest (); }); - } + } return false; - } - } - + } + } + auto session = std::make_shared (*this, router, address); if (peerTest) session->SetOnEstablished ([session]() {session->SendPeerTest (); }); if (address->UsesIntroducer ()) 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 (); }); else return false; @@ -589,7 +589,7 @@ namespace transport std::shared_ptr r; uint32_t relayTag = 0; if (!address->ssu->introducers.empty ()) - { + { std::vector indicies; for (int i = 0; i < (int)address->ssu->introducers.size (); i++) indicies.push_back(i); if (indicies.size () > 1) @@ -597,18 +597,18 @@ namespace transport 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) - { + { r = i2p::data::netdb.FindRouter (introducer.iKey); if (r && r->IsReachableFrom (i2p::context.GetRouterInfo ())) { relayTag = introducer.iTag; if (relayTag) break; } - } + } } - } + } if (r) { if (relayTag) @@ -620,10 +620,10 @@ namespace transport bool isValidEndpoint = !addr->host.is_unspecified () && addr->port && !i2p::util::net::IsInReservedRange(addr->host); if (isValidEndpoint) - { + { auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (addr->host, addr->port)); if (!s) - { + { s = std::make_shared (*this, r, addr); s->SetOnEstablished ([session, s, relayTag]() { s->Introduce (session, relayTag); }); s->Connect (); @@ -637,10 +637,10 @@ namespace transport onEstablished (); s->Introduce (session, relayTag); }); - else + else s->SetOnEstablished ([session, s, relayTag]() {s->Introduce (session, relayTag); }); - } - } + } + } } } } @@ -664,15 +664,15 @@ namespace transport auto s = it->second; if (it->second->IsEstablished ()) GetService ().post ([s]() { s->SendPeerTest (); }); - else - s->SetOnEstablished ([s]() { s->SendPeerTest (); }); - return true; + else + s->SetOnEstablished ([s]() { s->SendPeerTest (); }); + return true; } - else + else CreateSession (router, addr, true); return true; - } - + } + void SSU2Server::ScheduleTermination () { m_TerminationTimer.expires_from_now (boost::posix_time::seconds(SSU2_TERMINATION_CHECK_TIMEOUT)); @@ -718,7 +718,7 @@ namespace transport it = m_SessionsByRouterHash.erase (it); else it++; - } + } for (auto it = m_Relays.begin (); it != m_Relays.begin ();) { @@ -726,8 +726,8 @@ namespace transport it = m_Relays.erase (it); else it++; - } - + } + for (auto it = m_IncomingTokens.begin (); it != m_IncomingTokens.end (); ) { if (ts > it->second.second) @@ -743,7 +743,7 @@ namespace transport else it++; } - + m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); ScheduleTermination (); @@ -752,7 +752,7 @@ namespace transport 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))); m_ResendTimer.async_wait (std::bind (&SSU2Server::HandleResendTimer, this, std::placeholders::_1)); @@ -765,10 +765,10 @@ namespace transport size_t resentPacketsNum = 0; auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it: m_Sessions) - { + { resentPacketsNum += it.second->Resend (ts); if (resentPacketsNum > SSU2_MAX_RESEND_PACKETS) break; - } + } for (auto it: m_PendingOutgoingSessions) it.second->Resend (ts); ScheduleResend (resentPacketsNum > SSU2_MAX_RESEND_PACKETS); @@ -788,7 +788,7 @@ namespace transport if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second) return 0; // token expired return it->second.first; - } + } return 0; } @@ -808,23 +808,23 @@ namespace transport m_IncomingTokens.erase (ep); // drop previous uint64_t token; 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); return ret; - } + } - std::list > SSU2Server::FindIntroducers (int maxNumIntroducers, + std::list > SSU2Server::FindIntroducers (int maxNumIntroducers, bool v4, const std::set& excluded) const { std::list > ret; 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 ()) && ((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); - } + } if ((int)ret.size () > maxNumIntroducers) { // shink ret randomly @@ -838,7 +838,7 @@ namespace transport } } return ret; - } + } void SSU2Server::UpdateIntroducers (bool v4) { @@ -850,11 +850,11 @@ namespace transport { std::shared_ptr session; auto it1 = m_SessionsByRouterHash.find (it); - if (it1 != m_SessionsByRouterHash.end ()) - { + if (it1 != m_SessionsByRouterHash.end ()) + { session = it1->second; excluded.insert (it); - } + } if (session && session->IsEstablished ()) { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) @@ -863,10 +863,10 @@ namespace transport newList.push_back (it); else session = nullptr; - } + } if (!session) - i2p::context.RemoveSSU2Introducer (it, v4); - } + i2p::context.RemoveSSU2Introducer (it, v4); + } if (newList.size () < SSU2_MAX_NUM_INTRODUCERS) { 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 LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); for (auto& it : introducers) - { + { auto it1 = m_SessionsByRouterHash.find (it); if (it1 != m_SessionsByRouterHash.end ()) { auto session = it1->second; if (session->IsEstablished ()) - { + { 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); sessions.push_back (session); - } - } - } - } - } - + } + } + } + } + } + for (const auto& it : sessions) { i2p::data::RouterInfo::Introducer introducer; @@ -902,13 +902,13 @@ namespace transport excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); 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 ())); newList.push_back (it->GetRemoteIdentity ()->GetIdentHash ()); if (newList.size () >= SSU2_MAX_NUM_INTRODUCERS) break; - } - } - } + } + } + } introducers = newList; if (introducers.size () < SSU2_MAX_NUM_INTRODUCERS) @@ -937,12 +937,12 @@ namespace transport void SSU2Server::ScheduleIntroducersUpdateTimer () { if (m_IsPublished) - { + { m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); - } - } + } + } 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.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); - } + } } void SSU2Server::ScheduleIntroducersUpdateTimerV6 () { if (m_IsPublished) - { + { m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); - } - } + } + } 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.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); - } + } } - + void SSU2Server::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4) { if (ecode != boost::asio::error::operation_aborted) @@ -1004,7 +1004,7 @@ namespace transport auto addr = i2p::context.GetRouterInfo ().GetSSU2V4Address (); if (addr && addr->ssu && addr->ssu->introducers.empty ()) i2p::context.SetUnreachableSSU2 (true, false); // v4 - + UpdateIntroducers (true); ScheduleIntroducersUpdateTimer (); } @@ -1027,11 +1027,11 @@ namespace transport auto addr = i2p::context.GetRouterInfo ().GetSSU2V6Address (); if (addr && addr->ssu && addr->ssu->introducers.empty ()) i2p::context.SetUnreachableSSU2 (false, true); // v6 - + UpdateIntroducers (false); ScheduleIntroducersUpdateTimerV6 (); - } + } } - } + } } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 27af6bf8..773eb669 100644 --- a/libi2pd/SSU2.h +++ b/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_EXPIRATION = 4800; // 80 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 30; // 30 seconds - + class SSU2Server: private i2p::util::RunnableServiceWithWork { struct Packet @@ -60,7 +60,7 @@ namespace transport bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; - + void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); void AddSessionByRouterHash (std::shared_ptr session); @@ -70,7 +70,7 @@ namespace transport std::shared_ptr FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const; std::shared_ptr GetRandomSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports, const i2p::data::IdentHash& excluded) const; - + void AddRelay (uint32_t tag, std::shared_ptr relay); void RemoveRelay (uint32_t tag); std::shared_ptr FindRelaySession (uint32_t tag); @@ -83,17 +83,17 @@ namespace transport bool CreateSession (std::shared_ptr router, std::shared_ptr address, bool peerTest = false); bool StartPeerTest (std::shared_ptr router, bool v4); - + 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 GetIncomingToken (const boost::asio::ip::udp::endpoint& ep); std::pair NewIncomingToken (const boost::asio::ip::udp::endpoint& ep); - + void RescheduleIntroducersUpdateTimer (); void RescheduleIntroducersUpdateTimerV6 (); i2p::util::MemoryPool& GetSentPacketsPool () { return m_SentPacketsPool; }; - + private: 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 ConnectThroughIntroducer (std::shared_ptr session); - std::list > FindIntroducers (int maxNumIntroducers, + std::list > FindIntroducers (int maxNumIntroducers, bool v4, const std::set& excluded) const; void UpdateIntroducers (bool v4); void ScheduleIntroducersUpdateTimer (); void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4); void ScheduleIntroducersUpdateTimerV6 (); - + private: ReceiveService m_ReceiveService; @@ -136,7 +136,7 @@ namespace transport std::shared_ptr m_LastSession; bool m_IsPublished; // if we maintain introducers bool m_IsSyncClockFromPeers; - + public: // for HTTP/I2PControl diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 8dd4884e..7a6845d8 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -31,16 +31,16 @@ namespace transport LogPrint (eLogError, "SSU2: I2NP buffer overflow ", msg->maxLen); nextFragmentNum++; } - - + + SSU2Session::SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter, std::shared_ptr addr): TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT), m_Server (server), m_Address (addr), m_RemoteTransports (0), m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), - m_SendPacketNum (0), m_ReceivePacketNum (0), m_IsDataReceived (false), - m_WindowSize (SSU2_MIN_WINDOW_SIZE), m_RTT (SSU2_RESEND_INTERVAL), - m_RTO (SSU2_RESEND_INTERVAL*SSU2_kAPPA), m_RelayTag (0), + m_SendPacketNum (0), m_ReceivePacketNum (0), m_IsDataReceived (false), + m_WindowSize (SSU2_MIN_WINDOW_SIZE), m_RTT (SSU2_RESEND_INTERVAL), + m_RTO (SSU2_RESEND_INTERVAL*SSU2_kAPPA), m_RelayTag (0), m_ConnectTimer (server.GetService ()), m_TerminationReason (eSSU2TerminationReasonNormalClose), m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32) // min size { @@ -68,17 +68,17 @@ namespace transport void SSU2Session::Connect () { if (m_State == eSSU2SessionStateUnknown || m_State == eSSU2SessionStateTokenReceived) - { + { ScheduleConnectTimer (); auto token = m_Server.FindOutgoingToken (m_RemoteEndpoint); if (token) SendSessionRequest (token); else - { - m_State = eSSU2SessionStateUnknown; + { + m_State = eSSU2SessionStateUnknown; SendTokenRequest (); - } - } + } + } } void SSU2Session::ScheduleConnectTimer () @@ -98,7 +98,7 @@ namespace transport Terminate (); } } - + bool SSU2Session::Introduce (std::shared_ptr session, uint32_t relayTag) { // we are Alice @@ -155,15 +155,15 @@ namespace transport // create new connID uint64_t oldConnID = GetConnID (); RAND_bytes ((uint8_t *)&m_DestConnID, 8); - RAND_bytes ((uint8_t *)&m_SourceConnID, 8); + RAND_bytes ((uint8_t *)&m_SourceConnID, 8); // connect m_State = eSSU2SessionStateTokenReceived; m_Server.AddPendingOutgoingSession (shared_from_this ()); m_Server.RemoveSession (oldConnID); Connect (); } - } - + } + void SSU2Session::SendPeerTest () { // we are Alice @@ -181,23 +181,23 @@ namespace transport uint8_t payload[SSU2_MAX_PACKET_SIZE]; size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, nonce); if (payloadSize > 0) - { + { payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); LogPrint (eLogDebug, "SSU2: PeerTest sent to ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ())); - } - } + } + } void SSU2Session::SendKeepAlive () { if (IsEstablished ()) - { + { uint8_t payload[20]; size_t payloadSize = CreatePaddingBlock (payload, 20, 5); SendData (payload, payloadSize); - } - } - + } + } + void SSU2Session::Terminate () { if (m_State != eSSU2SessionStateTerminated) @@ -229,8 +229,8 @@ namespace transport SendTermination (); } m_State = eSSU2SessionStateClosing; - } - + } + void SSU2Session::Established () { m_State = eSSU2SessionStateEstablished; @@ -241,11 +241,11 @@ namespace transport m_ConnectTimer.cancel (); SetTerminationTimeout (SSU2_TERMINATION_TIMEOUT); transports.PeerConnected (shared_from_this ()); - if (m_OnEstablished) - { + if (m_OnEstablished) + { m_OnEstablished (); m_OnEstablished = nullptr; - } + } } void SSU2Session::Done () @@ -256,7 +256,7 @@ namespace transport void SSU2Session::SendLocalRouterInfo (bool update) { if (update || !IsOutgoing ()) - { + { auto s = shared_from_this (); m_Server.GetService ().post ([s]() { @@ -268,14 +268,14 @@ namespace transport if (payloadSize < s->m_MaxPayloadSize) payloadSize += s->CreatePaddingBlock (payload + payloadSize, s->m_MaxPayloadSize - payloadSize); s->SendData (payload, payloadSize); - } + } else s->SendFragmentedMessage (CreateDatabaseStoreMsg ()); }); - } + } + + } - } - void SSU2Session::SendI2NPMessages (const std::vector >& msgs) { m_Server.GetService ().post (std::bind (&SSU2Session::PostI2NPMessages, shared_from_this (), msgs)); @@ -289,16 +289,16 @@ namespace transport SendQueue (); if (m_SendQueue.size () > 0) // windows is full - { + { if (m_SendQueue.size () <= SSU2_MAX_OUTGOING_QUEUE_SIZE) Resend (i2p::util::GetMillisecondsSinceEpoch ()); - else + else { LogPrint (eLogWarning, "SSU2: Outgoing messages queue size to ", GetIdentHashBase64(), " exceeds ", SSU2_MAX_OUTGOING_QUEUE_SIZE); RequestTermination (eSSU2TerminationReasonTimeout); } - } + } } bool SSU2Session::SendQueue () @@ -317,7 +317,7 @@ namespace transport { m_SendQueue.pop_front (); continue; - } + } size_t len = msg->GetNTCP2Length () + 3; if (len > m_MaxPayloadSize) // message too long { @@ -338,12 +338,12 @@ namespace transport newPacket->payloadSize = ackBlockSize; // complete current packet if (packet->payloadSize > ackBlockSize) // more than just ack block - { + { ackBlockSent = true; // try to add padding if (packet->payloadSize + 16 < m_MaxPayloadSize) packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); - } + } else { // reduce ack block @@ -352,15 +352,15 @@ namespace transport // keep Ack block and drop some ranges ackBlockSent = true; packet->payloadSize = m_MaxPayloadSize - len; - if (packet->payloadSize & 0x01) packet->payloadSize--; // make it even + if (packet->payloadSize & 0x01) packet->payloadSize--; // make it even htobe16buf (packet->payload + 1, packet->payloadSize - 3); // new block size - } + } else // drop Ack block completely - packet->payloadSize = 0; + packet->payloadSize = 0; // msg fits single packet m_SendQueue.pop_front (); packet->payloadSize += CreateI2NPBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize, std::move (msg)); - } + } // send right a way uint32_t packetNum = SendData (packet->payload, packet->payloadSize); packet->sendTime = ts; @@ -394,7 +394,7 @@ namespace transport auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); if (extraSize >= 8) - { + { packet->payloadSize = CreateAckBlock (packet->payload, extraSize); ackBlockSent = true; if (packet->payloadSize + 12 < m_MaxPayloadSize) @@ -403,10 +403,10 @@ namespace transport packet->sendTime = ts; m_SentPackets.emplace (packetNum, packet); packet = m_Server.GetSentPacketsPool ().AcquireShared (); - } - else + } + else extraSize -= packet->payloadSize; - } + } size_t offset = extraSize > 0 ? (rand () % extraSize) : 0; if (offset + packet->payloadSize >= m_MaxPayloadSize) offset = 0; auto size = CreateFirstFragmentBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - offset - packet->payloadSize, msg); @@ -425,11 +425,11 @@ namespace transport extraSize -= offset; uint8_t flags = 0; if (msg->offset >= msg->len && packet->payloadSize + 16 < m_MaxPayloadSize) // last fragment - { + { packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); if (fragmentNum > 2) // 3 or more fragments flags |= SSU2_FLAG_IMMEDIATE_ACK_REQUESTED; - } + } uint32_t followonPacketNum = SendData (packet->payload, packet->payloadSize, flags); packet->sendTime = ts; m_SentPackets.emplace (followonPacketNum, packet); @@ -446,7 +446,7 @@ namespace transport ResendHandshakePacket (); m_SentHandshakePacket->sendTime = ts; return 0; - } + } // resend data packets if (m_SentPackets.empty ()) return 0; std::map > resentPackets; @@ -460,7 +460,7 @@ namespace transport m_SendQueue.clear (); RequestTermination (eSSU2TerminationReasonTimeout); return resentPackets.size (); - } + } else { uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize); @@ -489,16 +489,16 @@ namespace transport void SSU2Session::ResendHandshakePacket () { if (m_SentHandshakePacket) - { - m_Server.Send (m_SentHandshakePacket->header.buf, 16, m_SentHandshakePacket->headerX, 48, + { + m_Server.Send (m_SentHandshakePacket->header.buf, 16, m_SentHandshakePacket->headerX, 48, m_SentHandshakePacket->payload, m_SentHandshakePacket->payloadSize, m_RemoteEndpoint); if (m_SessionConfirmedFragment && m_State == eSSU2SessionStateSessionConfirmedSent) // resend second fragment of SessionConfirmed - m_Server.Send (m_SessionConfirmedFragment->header.buf, 16, + m_Server.Send (m_SessionConfirmedFragment->header.buf, 16, m_SessionConfirmedFragment->payload, m_SessionConfirmedFragment->payloadSize, m_RemoteEndpoint); - } - } - + } + } + bool SSU2Session::ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len) { // we are Bob @@ -517,16 +517,16 @@ namespace transport break; case eSSU2PeerTest: { - // TODO: remove later - const uint8_t nonce[12] = {0}; - uint64_t headerX[2]; - i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); + // TODO: remove later + const uint8_t nonce[12] = {0}; + uint64_t headerX[2]; + i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); LogPrint (eLogWarning, "SSU2: Unexpected PeerTest message SourceConnID=", connID, " DestConnID=", headerX[0]); break; - } + } case eSSU2HolePunch: LogPrint (eLogDebug, "SSU2: Late HolePunch for ", connID); - break; + break; default: { LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type, " from ", m_RemoteEndpoint, " of ", len, " bytes"); @@ -543,9 +543,9 @@ namespace transport m_SentHandshakePacket.reset (new HandshakePacket); auto ts = i2p::util::GetMillisecondsSinceEpoch (); m_SentHandshakePacket->sendTime = ts; - + Header& header = m_SentHandshakePacket->header; - uint8_t * headerX = m_SentHandshakePacket->headerX, + uint8_t * headerX = m_SentHandshakePacket->headerX, * payload = m_SentHandshakePacket->payload; // fill packet header.h.connID = m_DestConnID; // dest id @@ -568,7 +568,7 @@ namespace transport payload[payloadSize] = eSSU2BlkRelayTagRequest; memset (payload + payloadSize + 1, 0, 2); // size = 0 payloadSize += 3; - } + } payloadSize += CreatePaddingBlock (payload + payloadSize, 40 - payloadSize, 1); // KDF for session request m_NoiseState->MixHash ({ {header.buf, 16}, {headerX, 16} }); // h = SHA256(h || header) @@ -587,15 +587,15 @@ namespace transport m_SentHandshakePacket->payloadSize = payloadSize; // send if (m_State == eSSU2SessionStateTokenReceived || m_Server.AddPendingOutgoingSession (shared_from_this ())) - { + { m_State = eSSU2SessionStateSessionRequestSent; m_Server.Send (header.buf, 16, headerX, 48, payload, payloadSize, m_RemoteEndpoint); - } + } else { - LogPrint (eLogWarning, "SSU2: SessionRequest request to ", m_RemoteEndpoint, " already pending"); + LogPrint (eLogWarning, "SSU2: SessionRequest request to ", m_RemoteEndpoint, " already pending"); Terminate (); - } + } } void SSU2Session::ProcessSessionRequest (Header& header, uint8_t * buf, size_t len) @@ -634,10 +634,10 @@ namespace transport HandlePayload (decryptedPayload.data (), decryptedPayload.size ()); if (m_TerminationReason == eSSU2TerminationReasonNormalClose) - { + { m_Server.AddSession (shared_from_this ()); SendSessionCreated (headerX + 16); - } + } else SendRetry (); } @@ -649,12 +649,12 @@ namespace transport m_SentHandshakePacket.reset (new HandshakePacket); auto ts = i2p::util::GetMillisecondsSinceEpoch (); m_SentHandshakePacket->sendTime = ts; - + uint8_t kh2[32]; i2p::crypto::HKDF (m_NoiseState->m_CK, nullptr, 0, "SessCreateHeader", kh2, 32); // k_header_2 = HKDF(chainKey, ZEROLEN, "SessCreateHeader", 32) // fill packet Header& header = m_SentHandshakePacket->header; - uint8_t * headerX = m_SentHandshakePacket->headerX, + uint8_t * headerX = m_SentHandshakePacket->headerX, * payload = m_SentHandshakePacket->payload; header.h.connID = m_DestConnID; // dest id header.h.packetNum = 0; @@ -681,13 +681,13 @@ namespace transport } auto token = m_Server.NewIncomingToken (m_RemoteEndpoint); if (ts + SSU2_TOKEN_EXPIRATION_THRESHOLD > token.second) // not expired? - { + { payload[payloadSize] = eSSU2BlkNewToken; htobe16buf (payload + payloadSize + 1, 12); htobe32buf (payload + payloadSize + 3, token.second - SSU2_TOKEN_EXPIRATION_THRESHOLD); // expires memcpy (payload + payloadSize + 7, &token.first, 8); // token payloadSize += 15; - } + } payloadSize += CreatePaddingBlock (payload + payloadSize, maxPayloadSize - payloadSize); // KDF for SessionCreated m_NoiseState->MixHash ( { {header.buf, 16}, {headerX, 16} } ); // h = SHA256(h || header) @@ -757,7 +757,7 @@ namespace transport // we are Alice m_SentHandshakePacket.reset (new HandshakePacket); m_SentHandshakePacket->sendTime = i2p::util::GetMillisecondsSinceEpoch (); - + uint8_t kh2[32]; i2p::crypto::HKDF (m_NoiseState->m_CK, nullptr, 0, "SessionConfirmed", kh2, 32); // k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32) // fill packet @@ -778,7 +778,7 @@ namespace transport payloadSize = CreateRouterInfoBlock (payload, maxPayloadSize, i2p::context.GetSharedRouterInfo ()); header.h.flags[0] = 0x02; // frag 0, total fragments 2 // TODO: check if we need more fragments - } + } if (payloadSize < maxPayloadSize) payloadSize += CreatePaddingBlock (payload + payloadSize, maxPayloadSize - payloadSize); // KDF for Session Confirmed part 1 @@ -806,10 +806,10 @@ namespace transport payloadSize = m_MaxPayloadSize - 48 - (rand () % 16); if (m_SentHandshakePacket->payloadSize - payloadSize < 24) payloadSize -= 24; - } + } else header.h.flags[0] = 1; - } + } // Encrypt header header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24)); header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12)); @@ -828,12 +828,12 @@ namespace transport memset (header.h.flags, 0, 3); header.h.flags[0] = 0x12; // frag 1, total fragments 2 m_SessionConfirmedFragment->payloadSize = m_SentHandshakePacket->payloadSize - payloadSize; - memcpy (m_SessionConfirmedFragment->payload, m_SentHandshakePacket->payload + payloadSize, m_SessionConfirmedFragment->payloadSize); + memcpy (m_SessionConfirmedFragment->payload, m_SentHandshakePacket->payload + payloadSize, m_SessionConfirmedFragment->payloadSize); m_SentHandshakePacket->payloadSize = payloadSize; header.ll[0] ^= CreateHeaderMask (m_Address->i, m_SessionConfirmedFragment->payload + (m_SessionConfirmedFragment->payloadSize - 24)); header.ll[1] ^= CreateHeaderMask (kh2, m_SessionConfirmedFragment->payload + (m_SessionConfirmedFragment->payloadSize - 12)); m_Server.Send (header.buf, 16, m_SessionConfirmedFragment->payload, m_SessionConfirmedFragment->payloadSize, m_RemoteEndpoint); - } + } } bool SSU2Session::ProcessSessionConfirmed (uint8_t * buf, size_t len) @@ -860,18 +860,18 @@ namespace transport { LogPrint (eLogError, "SSU2: Too many fragments ", numFragments, " in SessionConfirmed"); return false; - } + } if (!(header.h.flags[0] & 0xF0)) { // first fragment if (!m_SessionConfirmedFragment) - { + { m_SessionConfirmedFragment.reset (new HandshakePacket); m_SessionConfirmedFragment->header = header; memcpy (m_SessionConfirmedFragment->payload, buf + 16, len - 16); m_SessionConfirmedFragment->payloadSize = len - 16; return true; // wait for second fragment - } + } else if (m_SessionConfirmedFragment->isSecondFragment) { // we have second fragment @@ -882,28 +882,28 @@ namespace transport m_SessionConfirmedFragment->isSecondFragment = false; buf = m_SessionConfirmedFragment->payload - 16; len = m_SessionConfirmedFragment->payloadSize + 16; - } + } else return true; } else { // second fragment - if (!m_SessionConfirmedFragment) - { + if (!m_SessionConfirmedFragment) + { // out of sequence, save it m_SessionConfirmedFragment.reset (new HandshakePacket); memcpy (m_SessionConfirmedFragment->payload, buf + 16, len - 16); m_SessionConfirmedFragment->payloadSize = len - 16; m_SessionConfirmedFragment->isSecondFragment = true; - return true; - } + return true; + } header = m_SessionConfirmedFragment->header; if (m_SessionConfirmedFragment->payloadSize + (len - 16) <= SSU2_MAX_PACKET_SIZE*2) - { + { memcpy (m_SessionConfirmedFragment->payload + m_SessionConfirmedFragment->payloadSize, buf + 16, len - 16); m_SessionConfirmedFragment->payloadSize += (len - 16); - } + } buf = m_SessionConfirmedFragment->payload - 16; len = m_SessionConfirmedFragment->payloadSize + 16; } @@ -972,7 +972,7 @@ namespace transport { LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb"); return false; - } + } SetRemoteIdentity (ri->GetRouterIdentity ()); AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now @@ -1027,13 +1027,13 @@ namespace transport memset (nonce, 0, 12); i2p::crypto::ChaCha20 (h + 16, 16, m_Address->i, nonce, h + 16); // send - if (m_Server.AddPendingOutgoingSession (shared_from_this ())) + if (m_Server.AddPendingOutgoingSession (shared_from_this ())) m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint); else { - LogPrint (eLogWarning, "SSU2: TokenRequest request to ", m_RemoteEndpoint, " already pending"); + LogPrint (eLogWarning, "SSU2: TokenRequest request to ", m_RemoteEndpoint, " already pending"); Terminate (); - } + } } void SSU2Session::ProcessTokenRequest (Header& header, uint8_t * buf, size_t len) @@ -1043,7 +1043,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Incorrect TokenRequest len ", len); return; - } + } uint8_t nonce[12] = {0}; uint8_t h[32]; memcpy (h, header.buf, 16); @@ -1141,13 +1141,13 @@ namespace transport // we should handle payload even for zero token to handle Datetime block and adjust clock in case of clock skew LogPrint (eLogWarning, "SSU2: Retry token is zero"); return false; - } + } InitNoiseXKState1 (*m_NoiseState, m_Address->s); // reset Noise TODO: check state SendSessionRequest (token); return true; } - void SSU2Session::SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, + void SSU2Session::SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey, uint64_t token) { // we are Charlie @@ -1171,7 +1171,7 @@ namespace transport htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); size_t payloadSize = 7; payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, ep); - payloadSize += CreateRelayResponseBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, + payloadSize += CreateRelayResponseBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, eSSU2RelayResponseCodeAccept, nonce, token, ep.address ().is_v4 ()); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); // encrypt @@ -1243,7 +1243,7 @@ namespace transport size_t payloadSize = 7; if (msg == 6 || msg == 7) payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, m_RemoteEndpoint); - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, + payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, msg, eSSU2PeerTestCodeAccept, nullptr, signedData, signedDataLen); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); // encrypt @@ -1257,8 +1257,8 @@ namespace transport i2p::crypto::ChaCha20 (h + 16, 16, introKey, n, h + 16); // send m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint); - } - + } + bool SSU2Session::ProcessPeerTest (uint8_t * buf, size_t len) { // we are Alice or Charlie @@ -1337,7 +1337,7 @@ namespace transport LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from); m_RemoteEndpoint = from; SendPathChallenge (); - } + } uint8_t payload[SSU2_MAX_PACKET_SIZE]; size_t payloadSize = len - 32; uint32_t packetNum = be32toh (header.h.packetNum); @@ -1385,7 +1385,7 @@ namespace transport LogPrint (eLogDebug, "SSU2: RouterInfo"); auto ri = ExtractRouterInfo (buf + offset, size); if (ri) - i2p::data::netdb.AddRouterInfo (ri->GetBuffer (), ri->GetBufferLen ()); // TODO: add ri + i2p::data::netdb.AddRouterInfo (ri->GetBuffer (), ri->GetBufferLen ()); // TODO: add ri break; } case eSSU2BlkI2NPMessage: @@ -1413,7 +1413,7 @@ namespace transport LogPrint (eLogDebug, "SSU2: Termination reason=", (int)buf[11]); if (IsEstablished () && buf[11] != eSSU2TerminationReasonTerminationReceived) RequestTermination (eSSU2TerminationReasonTerminationReceived); - else + else Done (); break; case eSSU2BlkRelayRequest: @@ -1471,7 +1471,7 @@ namespace transport SendPathResponse (buf + offset, size); break; case eSSU2BlkPathResponse: - { + { LogPrint (eLogDebug, "SSU2: Path response"); if (m_PathChallenge) { @@ -1479,9 +1479,9 @@ namespace transport SHA256 (buf + offset, size, hash); if (hash == *m_PathChallenge) m_PathChallenge.reset (nullptr); - } + } break; - } + } case eSSU2BlkFirstPacketNumber: break; case eSSU2BlkPadding: @@ -1500,11 +1500,11 @@ namespace transport switch (m_State) { case eSSU2SessionStateSessionRequestReceived: - case eSSU2SessionStateTokenRequestReceived: + case eSSU2SessionStateTokenRequestReceived: if (std::abs (offset) > SSU2_CLOCK_SKEW) m_TerminationReason = eSSU2TerminationReasonClockSkew; break; - case eSSU2SessionStateSessionCreatedReceived: + case eSSU2SessionStateSessionCreatedReceived: case eSSU2SessionStateTokenReceived: if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) || (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusTesting)) @@ -1522,19 +1522,19 @@ namespace transport LogPrint (eLogError, "SSU2: Clock skew detected ", offset, ". Check your clock"); i2p::context.SetError (eRouterErrorClockSkew); } - } - break; - default: ; - }; - } - + } + break; + default: ; + }; + } + void SSU2Session::HandleAck (const uint8_t * buf, size_t len) { if (m_State == eSSU2SessionStateSessionConfirmedSent) { Established (); return; - } + } if (m_SentPackets.empty ()) return; if (len < 5) return; // acnt @@ -1564,8 +1564,8 @@ namespace transport if (it == m_SentPackets.end () || it->first > lastPacketNum) return; // not found auto it1 = it; int numPackets = 0; - while (it1 != m_SentPackets.end () && it1->first <= lastPacketNum) - { + while (it1 != m_SentPackets.end () && it1->first <= lastPacketNum) + { if (ts && !it1->second->numResends) { if (ts > it1->second->sendTime) @@ -1575,28 +1575,28 @@ namespace transport m_RTO = m_RTT*SSU2_kAPPA; if (m_RTO < SSU2_MIN_RTO) m_RTO = SSU2_MIN_RTO; if (m_RTO > SSU2_MAX_RTO) m_RTO = SSU2_MAX_RTO; - } + } ts = 0; // update RTT one time per range - } + } it1++; numPackets++; - } + } m_SentPackets.erase (it, it1); if (numPackets > 0) { m_WindowSize += numPackets; if (m_WindowSize > SSU2_MAX_WINDOW_SIZE) m_WindowSize = SSU2_MAX_WINDOW_SIZE; - } + } } void SSU2Session::HandleAddress (const uint8_t * buf, size_t len) { boost::asio::ip::udp::endpoint ep; if (ExtractEndpoint (buf, len, ep)) - { + { LogPrint (eLogInfo, "SSU2: Our external address is ", ep); if (!i2p::util::net::IsInReservedRange (ep.address ())) - { + { i2p::context.UpdateAddress (ep.address ()); // check our port bool isV4 = ep.address ().is_v4 (); @@ -1606,30 +1606,30 @@ namespace transport { if (i2p::context.GetStatus () == eRouterStatusTesting) i2p::context.SetError (eRouterErrorSymmetricNAT); - } + } else { if (i2p::context.GetStatusV6 () == eRouterStatusTesting) i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); - } - } + } + } else { if (isV4) { if (i2p::context.GetError () == eRouterErrorSymmetricNAT) i2p::context.SetError (eRouterErrorNone); - } + } else { if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) i2p::context.SetErrorV6 (eRouterErrorNone); - } - } - } - } - } - + } + } + } + } + } + void SSU2Session::HandleFirstFragment (const uint8_t * buf, size_t len) { uint32_t msgID; memcpy (&msgID, buf + 1, 4); @@ -1671,7 +1671,7 @@ namespace transport auto it = m_IncompleteMessages.find (msgID); if (it != m_IncompleteMessages.end ()) { - if (it->second->nextFragmentNum == fragmentNum && fragmentNum < SSU2_MAX_NUM_FRAGMENTS && + if (it->second->nextFragmentNum == fragmentNum && fragmentNum < SSU2_MAX_NUM_FRAGMENTS && it->second->msg) { // in sequence @@ -1707,7 +1707,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Fragment number ", fragmentNum, " exceeds ", SSU2_MAX_NUM_FRAGMENTS); return; - } + } auto fragment = std::make_shared (); memcpy (fragment->buf, buf + 5, len -5); fragment->len = len - 5; @@ -1742,18 +1742,18 @@ namespace transport LogPrint (eLogWarning, "SSU2: RelayRequest session with relay tag ", relayTag, " not found"); // send relay response back to Alice uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = CreateRelayResponseBlock (payload, m_MaxPayloadSize, + size_t payloadSize = CreateRelayResponseBlock (payload, m_MaxPayloadSize, eSSU2RelayResponseCodeBobRelayTagNotFound, bufbe32toh (buf + 1), 0, false); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); - return; + return; } session->m_RelaySessions.emplace (bufbe32toh (buf + 1), // nonce std::make_pair (shared_from_this (), i2p::util::GetSecondsSinceEpoch ()) ); // send relay intro to Charlie auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); // Alice's RI - if (r) + if (r) i2p::data::netdb.PopulateRouterInfoBuffer (r); else LogPrint (eLogWarning, "SSU2: RelayRequest Alice's router info not found"); @@ -1775,7 +1775,7 @@ namespace transport bool isV4 = false; auto r = i2p::data::netdb.FindRouter (buf + 1); // Alice if (r) - { + { SignedData s; s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash @@ -1797,49 +1797,49 @@ namespace transport token = m_Server.GetIncomingToken (ep); isV4 = ep.address ().is_v4 (); SendHolePunch (bufbe32toh (buf + 33), ep, addr->i, token); - } + } else - { + { LogPrint (eLogWarning, "SSU2: RelayIntro unsupported address"); code = eSSU2RelayResponseCodeCharlieUnsupportedAddress; - } - } + } + } else { LogPrint (eLogWarning, "SSU2: RelayIntro unknown address"); - code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; - } + code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; + } } else { LogPrint (eLogWarning, "SSU2: RelayIntro can't extract endpoint"); - code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; - } + code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; + } } else { LogPrint (eLogWarning, "SSU2: RelayIntro signature verification failed"); code = eSSU2RelayResponseCodeCharlieSignatureFailure; } - } + } else { LogPrint (eLogError, "SSU2: RelayIntro unknown router to introduce"); code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; - } + } // send relay response to Bob uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = CreateRelayResponseBlock (payload, m_MaxPayloadSize, + size_t payloadSize = CreateRelayResponseBlock (payload, m_MaxPayloadSize, code, bufbe32toh (buf + 33), token, isV4); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); } void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len) - { + { uint32_t nonce = bufbe32toh (buf + 2); - if (m_State == eSSU2SessionStateIntroduced) - { + if (m_State == eSSU2SessionStateIntroduced) + { // HolePunch from Charlie // TODO: verify address and signature // verify nonce @@ -1848,17 +1848,17 @@ namespace transport if (len >= 8) { // new token - uint64_t token; + uint64_t token; memcpy (&token, buf + len - 8, 8); m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT); - } - return; - } - auto it = m_RelaySessions.find (nonce); + } + return; + } + auto it = m_RelaySessions.find (nonce); if (it != m_RelaySessions.end ()) { if (it->second.first && it->second.first->IsEstablished ()) - { + { // we are Bob, message from Charlie uint8_t payload[SSU2_MAX_PACKET_SIZE]; payload[0] = eSSU2BlkRelayResponse; @@ -1866,8 +1866,8 @@ namespace transport memcpy (payload + 3, buf, len); // forward to Alice as is size_t payloadSize = len + 3; payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - it->second.first->SendData (payload, payloadSize); - } + it->second.first->SendData (payload, payloadSize); + } else { // we are Alice, message from Bob @@ -1882,12 +1882,12 @@ namespace transport if (s.Verify (it->second.first->GetRemoteIdentity (), buf + 12 + csz)) { if (it->second.first->m_State == eSSU2SessionStateIntroduced) // HolePunch not received yet - { + { // update Charlie's endpoint if (ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint)) - { + { // update token - uint64_t token; + uint64_t token; memcpy (&token, buf + len - 8, 8); m_Server.UpdateOutgoingToken (it->second.first->m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT); @@ -1896,19 +1896,19 @@ namespace transport } else LogPrint (eLogWarning, "SSU2: RelayResponse can't extract endpoint"); - } + } } else - { + { LogPrint (eLogWarning, "SSU2: RelayResponse signature verification failed"); it->second.first->Done (); - } + } } else - { + { LogPrint (eLogInfo, "SSU2: RelayResponse status code=", (int)buf[1]); it->second.first->Done (); - } + } } m_RelaySessions.erase (it); } @@ -1921,13 +1921,13 @@ namespace transport if (len < 3) return; uint8_t msg = buf[0]; size_t offset = 3; // points to signed data - if (msg == 2 || msg == 4) offset += 32; // hash is presented for msg 2 and 4 only - if (len < offset + 5) return; - uint32_t nonce = bufbe32toh (buf + offset + 1); + if (msg == 2 || msg == 4) offset += 32; // hash is presented for msg 2 and 4 only + if (len < offset + 5) return; + uint32_t nonce = bufbe32toh (buf + offset + 1); switch (msg) // msg { case 1: // Bob from Alice - { + { auto session = m_Server.GetRandomSession ((buf[12] == 6) ? i2p::data::RouterInfo::eSSU2V4 : i2p::data::RouterInfo::eSSU2V6, GetRemoteIdentity ()->GetIdentHash ()); if (session) // session with Charlie @@ -1945,9 +1945,9 @@ namespace transport // doesn't fit one message, send RouterInfo in separate message session->SendData (payload, payloadSize); payloadSize = 0; - } + } // PeerTest to Charlie - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, 2, + payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, 2, eSSU2PeerTestCodeAccept, GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); session->SendData (payload, payloadSize); @@ -1956,11 +1956,11 @@ namespace transport { // Charlie not found, send error back to Alice uint8_t payload[SSU2_MAX_PACKET_SIZE], zeroHash[32] = {0}; - size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, 4, + size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, 4, eSSU2PeerTestCodeBobNoCharlieAvailable, zeroHash, buf + offset, len - offset); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); - } + } break; } case 2: // Charlie from Bob @@ -1973,7 +1973,7 @@ namespace transport s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (buf + 3, 32); // ahash - s.Insert (newSignedData.data (), asz + 10); // ver, nonce, ts, asz, Alice's endpoint + s.Insert (newSignedData.data (), asz + 10); // ver, nonce, ts, asz, Alice's endpoint s.Sign (i2p::context.GetPrivateKeys (), newSignedData.data () + 10 + asz); // send response (msg 3) back and msg 5 if accepted SSU2PeerTestCode code = eSSU2PeerTestCodeAccept; @@ -1982,39 +1982,39 @@ namespace transport { size_t signatureLen = r->GetIdentity ()->GetSignatureLen (); if (len >= offset + asz + 10 + signatureLen) - { + { s.Reset (); s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (buf + offset, asz + 10); // signed data if (s.Verify (r->GetIdentity (), buf + offset + asz + 10)) - { + { if (!m_Server.FindSession (r->GetIdentity ()->GetIdentHash ())) - { + { boost::asio::ip::udp::endpoint ep; std::shared_ptr addr; if (ExtractEndpoint (buf + offset + 10, asz, ep)) addr = r->GetSSU2Address (ep.address ().is_v4 ()); if (addr && m_Server.IsSupported (ep.address ())) - { + { // send msg 5 to Alice auto session = std::make_shared (m_Server, r, addr); - session->SetState (eSSU2SessionStatePeerTest); + session->SetState (eSSU2SessionStatePeerTest); session->m_RemoteEndpoint = ep; // might be different session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce); session->m_SourceConnID = ~session->m_DestConnID; m_Server.AddSession (session); session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i); - } + } else code = eSSU2PeerTestCodeCharlieUnsupportedAddress; } else code = eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected; } - else - code = eSSU2PeerTestCodeCharlieSignatureFailure; - } + else + code = eSSU2PeerTestCodeCharlieSignatureFailure; + } else // maformed message code = eSSU2PeerTestCodeCharlieReasonUnspecified; } @@ -2022,12 +2022,12 @@ namespace transport code = eSSU2PeerTestCodeCharlieAliceIsUnknown; // send msg 3 back to Bob uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, 3, + size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, 3, code, nullptr, newSignedData.data (), newSignedData.size ()); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); break; - } + } case 3: // Bob from Charlie { auto it = m_PeerTests.find (nonce); @@ -2047,7 +2047,7 @@ namespace transport payloadSize = 0; } // PeerTest to Alice - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, + payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, (SSU2PeerTestCode)buf[1], GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); if (payloadSize < m_MaxPayloadSize) payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); @@ -2059,33 +2059,33 @@ namespace transport break; } case 4: // Alice from Bob - { + { auto it = m_PeerTests.find (nonce); if (it != m_PeerTests.end ()) { if (buf[1] == eSSU2PeerTestCodeAccept) - { + { if (GetRouterStatus () == eRouterStatusUnknown) SetRouterStatus (eRouterStatusTesting); auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie if (r && it->second.first) - { + { uint8_t asz = buf[offset + 9]; SignedData s; s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (i2p::context.GetIdentity ()->GetIdentHash (), 32); // ahash - s.Insert (buf + offset, asz + 10); // ver, nonce, ts, asz, Alice's endpoint + s.Insert (buf + offset, asz + 10); // ver, nonce, ts, asz, Alice's endpoint if (s.Verify (r->GetIdentity (), buf + offset + asz + 10)) { it->second.first->SetRemoteIdentity (r->GetIdentity ()); auto addr = r->GetSSU2Address (m_Address->IsV4 ()); if (addr) - { + { it->second.first->m_Address = addr; if (it->second.first->m_State == eSSU2SessionStatePeerTestReceived) { - // msg 5 already received. send msg 6 + // msg 5 already received. send msg 6 SetRouterStatus (eRouterStatusOK); it->second.first->m_State = eSSU2SessionStatePeerTest; it->second.first->SendPeerTest (6, buf + offset, len - offset, addr->i); @@ -2093,13 +2093,13 @@ namespace transport else { if (GetRouterStatus () == eRouterStatusTesting) - { + { SetRouterStatus (eRouterStatusFirewalled); if (m_Address->IsV4 ()) m_Server.RescheduleIntroducersUpdateTimer (); else m_Server.RescheduleIntroducersUpdateTimerV6 (); - } + } } LogPrint (eLogDebug, "SSU2: Peer test 4 received from ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), " with information about ", i2p::data::GetIdentHashAbbreviation (i2p::data::IdentHash (buf + 3))); @@ -2108,14 +2108,14 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Peer test 4 address not found"); it->second.first->Done (); - } + } } else - { + { LogPrint (eLogWarning, "SSU2: Peer test 4 signature verification failed"); it->second.first->Done (); - } - } + } + } else { LogPrint (eLogWarning, "SSU2: Peer test 4 Charlie's Router Info is not found"); @@ -2128,25 +2128,25 @@ namespace transport if (GetRouterStatus () == eRouterStatusTesting) SetRouterStatus (eRouterStatusUnknown); it->second.first->Done (); - } + } m_PeerTests.erase (it); - } + } else LogPrint (eLogWarning, "SSU2: Unknown peer test 4 nonce ", nonce); break; - } + } case 5: // Alice from Charlie 1 if (htobe64 (((uint64_t)nonce << 32) | nonce) == m_SourceConnID) { if (m_Address) - { + { SetRouterStatus (eRouterStatusOK); SendPeerTest (6, buf + offset, len - offset, m_Address->i); - } + } else // we received msg 5 before msg 4 m_State = eSSU2SessionStatePeerTestReceived; - } + } else LogPrint (eLogWarning, "SSU2: Peer test 5 nonce mismatch ", nonce, " connID=", m_SourceConnID); break; @@ -2220,49 +2220,49 @@ namespace transport if (m_Address) return i2p::context.GetRouterInfo ().GetSSU2Address (m_Address->IsV4 ()); return nullptr; - } + } void SSU2Session::AdjustMaxPayloadSize () { auto addr = FindLocalAddress (); - if (addr && addr->ssu) - { + if (addr && addr->ssu) + { int mtu = addr->ssu->mtu; if (!mtu && addr->IsV4 ()) mtu = SSU2_MAX_PACKET_SIZE; - if (m_Address && m_Address->ssu && (!mtu || m_Address->ssu->mtu < mtu)) + if (m_Address && m_Address->ssu && (!mtu || m_Address->ssu->mtu < mtu)) mtu = m_Address->ssu->mtu; if (mtu) - { + { if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; m_MaxPayloadSize = mtu - (addr->IsV6 () ? IPV6_HEADER_SIZE: IPV4_HEADER_SIZE) - UDP_HEADER_SIZE - 32; LogPrint (eLogDebug, "SSU2: Session MTU=", mtu, ", max payload size=", m_MaxPayloadSize); - } - } - } - + } + } + } + RouterStatus SSU2Session::GetRouterStatus () const { if (m_Address) { - if (m_Address->IsV4 ()) + if (m_Address->IsV4 ()) return i2p::context.GetStatus (); - if (m_Address->IsV6 ()) + if (m_Address->IsV6 ()) return i2p::context.GetStatusV6 (); - } + } return eRouterStatusUnknown; - } - + } + void SSU2Session::SetRouterStatus (RouterStatus status) const { if (m_Address) - { + { if (m_Address->IsV4 ()) i2p::context.SetStatusSSU2 (status); else if (m_Address->IsV6 ()) i2p::context.SetStatusV6SSU2 (status); - } - } - + } + } + size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) { if (len < 9) return 0; @@ -2324,11 +2324,11 @@ namespace transport { auto d = std::div (acnt - 255, 255); acnt = 255; - if (d.quot > maxNumRanges) - { + if (d.quot > maxNumRanges) + { d.quot = maxNumRanges; d.rem = 0; - } + } // Acks only ragnes for acnt for (int i = 0; i < d.quot; i++) { @@ -2339,21 +2339,21 @@ namespace transport { buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = d.rem; numRanges++; - } - } + } + } while (it != m_OutOfSequencePackets.rend () && numRanges < maxNumRanges) { if (lastNum - (*it) > 255) - { + { // NACKs only ranges - if (lastNum > (*it) + 255*(maxNumRanges - numRanges)) break; // too many NACKs + if (lastNum > (*it) + 255*(maxNumRanges - numRanges)) break; // too many NACKs while (lastNum - (*it) > 255) { buf[8 + numRanges*2] = 255; buf[8 + numRanges*2 + 1] = 0; // NACKs 255, Acks 0 lastNum -= 255; numRanges++; } - } + } // NACKs and Acks ranges buf[8 + numRanges*2] = lastNum - (*it) - 1; // NACKs lastNum = *it; it++; @@ -2369,12 +2369,12 @@ namespace transport buf[8 + numRanges*2 + 1] = 255; // Acks 255 numAcks -= 255; numRanges++; - buf[8 + numRanges*2] = 0; // NACKs 0 + buf[8 + numRanges*2] = 0; // NACKs 0 if (numRanges >= maxNumRanges) break; - } + } if (numAcks > 255) numAcks = 255; buf[8 + numRanges*2 + 1] = (uint8_t)numAcks; // Acks - numRanges++; + numRanges++; } if (numRanges < maxNumRanges && it == m_OutOfSequencePackets.rend ()) { @@ -2386,8 +2386,8 @@ namespace transport buf[8 + numRanges*2] = nacks; buf[8 + numRanges*2 + 1] = std::min ((int)m_ReceivePacketNum + 1, 255); numRanges++; - } - } + } + } } } buf[7] = (uint8_t)acnt; // acnt @@ -2472,7 +2472,7 @@ namespace transport return payloadSize + 3; } - size_t SSU2Session::CreateRelayResponseBlock (uint8_t * buf, size_t len, + size_t SSU2Session::CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4) { buf[0] = eSSU2BlkRelayResponse; @@ -2483,20 +2483,20 @@ namespace transport buf[13] = 2; // ver size_t csz = 0; if (code == eSSU2RelayResponseCodeAccept) - { + { auto addr = i2p::context.GetRouterInfo ().GetSSU2Address (v4); if (!addr) { LogPrint (eLogError, "SSU2: Can't find local address for RelayResponse"); return 0; - } + } csz = CreateEndpoint (buf + 15, len - 15, boost::asio::ip::udp::endpoint (addr->host, addr->port)); - if (!csz) - { + if (!csz) + { LogPrint (eLogError, "SSU2: Can't create local endpoint for RelayResponse"); return 0; - } - } + } + } buf[14] = csz; // csz // signature size_t signatureLen = i2p::context.GetIdentity ()->GetSignatureLen (); @@ -2504,7 +2504,7 @@ namespace transport { LogPrint (eLogError, "SSU2: Buffer for RelayResponse signature is too small ", len); return 0; - } + } SignedData s; s.Insert ((const uint8_t *)"RelayAgreementOK", 16); // prologue if (code == eSSU2RelayResponseCodeAccept || code >= 64) // Charlie @@ -2520,14 +2520,14 @@ namespace transport { LogPrint (eLogError, "SSU2: Buffer for RelayResponse token is too small ", len); return 0; - } + } memcpy (buf + 3 + payloadSize, &token, 8); payloadSize += 8; - } + } htobe16buf (buf + 1, payloadSize); // size return payloadSize + 3; } - + size_t SSU2Session::CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen) { @@ -2541,23 +2541,23 @@ namespace transport buf[5] = 0; //flag size_t offset = 6; if (routerHash) - { + { memcpy (buf + offset, routerHash, 32); // router hash offset += 32; - } + } memcpy (buf + offset, signedData, signedDataLen); return payloadSize + 3; } size_t SSU2Session::CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce) { - auto localAddress = FindLocalAddress (); + auto localAddress = FindLocalAddress (); if (!localAddress || !localAddress->port || localAddress->host.is_unspecified () || - localAddress->host.is_v4 () != m_RemoteEndpoint.address ().is_v4 ()) + localAddress->host.is_v4 () != m_RemoteEndpoint.address ().is_v4 ()) { LogPrint (eLogWarning, "SSU2: Can't find local address for peer test"); return 0; - } + } // signed data auto ts = i2p::util::GetSecondsSinceEpoch (); uint8_t signedData[96]; @@ -2570,21 +2570,21 @@ namespace transport SignedData s; s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash - s.Insert (signedData, 10 + asz); // ver, nonce, ts, asz, Alice's endpoint + s.Insert (signedData, 10 + asz); // ver, nonce, ts, asz, Alice's endpoint s.Sign (i2p::context.GetPrivateKeys (), signedData + 10 + asz); - return CreatePeerTestBlock (buf, len, 1, eSSU2PeerTestCodeAccept, nullptr, + return CreatePeerTestBlock (buf, len, 1, eSSU2PeerTestCodeAccept, nullptr, signedData, 10 + asz + i2p::context.GetIdentity ()->GetSignatureLen ()); - } + } size_t SSU2Session::CreateTerminationBlock (uint8_t * buf, size_t len) - { + { buf[0] = eSSU2BlkTermination; htobe16buf (buf + 1, 9); htobe64buf (buf + 3, m_ReceivePacketNum); buf[11] = (uint8_t)m_TerminationReason; return 12; } - + std::shared_ptr SSU2Session::ExtractRouterInfo (const uint8_t * buf, size_t size) { if (size < 2) return nullptr; @@ -2655,13 +2655,13 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len); return; - } + } uint8_t payload[SSU2_MAX_PACKET_SIZE]; payload[0] = eSSU2BlkPathResponse; htobe16buf (payload + 1, len); memcpy (payload + 3, data, len); SendData (payload, len + 3); - } + } void SSU2Session::SendPathChallenge () { @@ -2670,18 +2670,18 @@ namespace transport size_t len = rand () % (m_MaxPayloadSize - 3); htobe16buf (payload + 1, len); if (len > 0) - { + { RAND_bytes (payload + 3, len); i2p::data::IdentHash * hash = new i2p::data::IdentHash (); SHA256 (payload + 3, len, *hash); m_PathChallenge.reset (hash); - } + } len += 3; if (len < m_MaxPayloadSize) len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len); SendData (payload, len); - } - + } + void SSU2Session::CleanUp (uint64_t ts) { for (auto it = m_IncompleteMessages.begin (); it != m_IncompleteMessages.end ();) @@ -2695,8 +2695,8 @@ namespace transport ++it; } if (!m_OutOfSequencePackets.empty ()) - { - if (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || + { + if (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + 255*8) { uint32_t packet = *m_OutOfSequencePackets.begin (); @@ -2706,9 +2706,9 @@ namespace transport packet--; m_ReceivePacketNum = packet - 1; UpdateReceivePacketNum (packet); - } + } else - LogPrint (eLogError, "SSU2: Out of sequence packet ", packet, " is less than last received ", m_ReceivePacketNum); + LogPrint (eLogError, "SSU2: Out of sequence packet ", packet, " is less than last received ", m_ReceivePacketNum); } if (m_OutOfSequencePackets.size () > 255*4) { @@ -2716,8 +2716,8 @@ namespace transport m_ReceivePacketNum = *m_OutOfSequencePackets.rbegin (); m_OutOfSequencePackets.clear (); } - } - + } + for (auto it = m_RelaySessions.begin (); it != m_RelaySessions.end ();) { if (ts > it->second.second + SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 6797e8ce..a4306e68 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -49,8 +49,8 @@ namespace transport const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; // flags - const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; - + const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; + enum SSU2MessageType { eSSU2SessionRequest = 0, @@ -123,7 +123,7 @@ namespace transport eSSU2PeerTestCodeCharlieAliceIsBanned = 69, eSSU2PeerTestCodeCharlieAliceIsUnknown = 70, eSSU2PeerTestCodeUnspecified = 128 - }; + }; enum SSU2RelayResponseCode { @@ -132,7 +132,7 @@ namespace transport eSSU2RelayResponseCodeCharlieUnsupportedAddress = 65, eSSU2RelayResponseCodeCharlieSignatureFailure = 67, eSSU2RelayResponseCodeCharlieAliceIsUnknown = 70 - }; + }; enum SSU2TerminationReason { @@ -159,8 +159,8 @@ namespace transport eSSU2TerminationReasonIncompatibleVersion = 20, eSSU2TerminationReasonWrongNetID = 21, eSSU2TerminationReasonReplacedByNewSession = 22 - }; - + }; + struct SSU2IncompleteMessage { struct Fragment @@ -185,7 +185,7 @@ namespace transport uint64_t sendTime; // in milliseconds int numResends = 0; }; - + // RouterInfo flags const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02; @@ -268,7 +268,7 @@ namespace transport bool SendFragmentedMessage (std::shared_ptr msg); void ResendHandshakePacket (); void ConnectAfterIntroduction (); - + void ProcessSessionRequest (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 SendTermination (); 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 SendPathChallenge (); - + void HandlePayload (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); @@ -316,7 +316,7 @@ namespace transport size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr msg); size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr 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 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, uint32_t nonce); // Alice size_t CreateTerminationBlock (uint8_t * buf, size_t len); diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 53192816..ecaef425 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -27,7 +27,7 @@ namespace transport const size_t IPV4_HEADER_SIZE = 20; const size_t IPV6_HEADER_SIZE = 40; const size_t UDP_HEADER_SIZE = 8; - + class SignedData { public: @@ -42,7 +42,7 @@ namespace transport { m_Stream.str(""); } - + void Insert (const uint8_t * buf, size_t len) { m_Stream.write ((char *)buf, len); @@ -68,7 +68,7 @@ namespace transport std::stringstream m_Stream; }; - + class TransportSession { public: @@ -79,7 +79,7 @@ namespace transport { if (router) m_RemoteIdentity = router->GetRouterIdentity (); - m_CreationTime = m_LastActivityTimestamp; + m_CreationTime = m_LastActivityTimestamp; } virtual ~TransportSession () {}; @@ -109,7 +109,7 @@ namespace transport uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers - + virtual uint32_t GetRelayTag () const { return 0; }; virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index f1214889..fdd32d35 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -462,7 +462,7 @@ namespace transport { case i2p::data::RouterInfo::eNTCP2V4: case i2p::data::RouterInfo::eNTCP2V6: - { + { if (!m_NTCP2Server) continue; std::shared_ptr address = (tr == i2p::data::RouterInfo::eNTCP2V6) ? peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); @@ -493,7 +493,7 @@ namespace transport return true; } break; - } + } case i2p::data::RouterInfo::eSSUV4: case i2p::data::RouterInfo::eSSUV6: { @@ -508,7 +508,7 @@ namespace transport return true; } break; - } + } case i2p::data::RouterInfo::eNTCP2V6Mesh: { if (!m_NTCP2Server) continue; @@ -518,14 +518,14 @@ namespace transport auto s = std::make_shared (*m_NTCP2Server, peer.router, address); m_NTCP2Server->Connect (s); return true; - } + } break; - } + } default: LogPrint (eLogError, "Transports: Unknown transport ", (int)tr); - } - } - + } + } + LogPrint (eLogInfo, "Transports: No compatible addresses available"); i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed peer.Done (); @@ -538,14 +538,14 @@ namespace transport LogPrint (eLogInfo, "Transports: RouterInfo for ", ident.ToBase64 (), " not found, requested"); i2p::data::netdb.RequestDestination (ident, std::bind ( &Transports::RequestComplete, this, std::placeholders::_1, ident)); - } + } return true; - } - + } + void Transports::SetPriority (Peer& peer) const { - static const std::vector - ntcp2Priority = + static const std::vector + ntcp2Priority = { i2p::data::RouterInfo::eNTCP2V6, i2p::data::RouterInfo::eNTCP2V4, @@ -554,8 +554,8 @@ namespace transport i2p::data::RouterInfo::eNTCP2V6Mesh, i2p::data::RouterInfo::eSSUV6, i2p::data::RouterInfo::eSSUV4 - }, - ssu2Priority = + }, + ssu2Priority = { i2p::data::RouterInfo::eSSU2V6, i2p::data::RouterInfo::eSSU2V4, @@ -564,7 +564,7 @@ namespace transport i2p::data::RouterInfo::eNTCP2V6Mesh, i2p::data::RouterInfo::eSSUV6, i2p::data::RouterInfo::eSSUV4 - }; + }; if (!peer.router) return; auto compatibleTransports = context.GetRouterInfo ().GetCompatibleTransports (false) & peer.router->GetCompatibleTransports (true); @@ -574,9 +574,9 @@ namespace transport const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority; for (auto transport: priority) if (transport & compatibleTransports) - peer.priority.push_back (transport); - } - + peer.priority.push_back (transport); + } + void Transports::RequestComplete (std::shared_ptr r, const i2p::data::IdentHash& ident) { m_Service->post (std::bind (&Transports::HandleRequestComplete, this, r, ident)); @@ -834,7 +834,7 @@ namespace transport auto session = it->second.sessions.front (); if (session) 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; } ++it; @@ -1074,6 +1074,6 @@ namespace transport i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish } - } + } } } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 362c5ead..c9e1c5f4 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -62,8 +62,8 @@ namespace transport }; typedef EphemeralKeysSupplier X25519KeysPairSupplier; - 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 = 31*60; // in seconds + const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds struct Peer { int numAttempts; @@ -77,8 +77,8 @@ namespace transport numAttempts (0), router (r), creationTime (ts), nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL) { - } - + } + void Done () { for (auto& it: sessions) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 7928792f..fe655643 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -313,14 +313,14 @@ namespace client { i2p::config::GetOption("addressbook.enabled", m_IsEnabled); if (m_IsEnabled) - { + { if (!m_Storage) m_Storage = new AddressBookFilesystemStorage; m_Storage->Init(); LoadHosts (); /* try storage, then hosts.txt, then download */ StartSubscriptions (); StartLookups (); - } + } } void AddressBook::StartResolvers () diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index a5e1c67c..33500705 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -727,7 +727,7 @@ namespace client std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, ""); bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); bool ssl = section.second.get(I2P_SERVER_TUNNEL_SSL, false); - + // I2CP std::map options; ReadI2CPOptions (section, true, options); @@ -868,7 +868,7 @@ namespace client std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", 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); LogPrint(eLogInfo, "Clients: Starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); if (httpProxyKeys.length () > 0) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 8bf0e38d..49c837f5 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -86,7 +86,7 @@ namespace client static void MapToLoopback(std::shared_ptr sock, const i2p::data::IdentHash & addr) { if (sock) - { + { // bind to 127.x.x.x address // where x.x.x are first three bytes from ident auto ourIP = GetLoopbackAddressFor(addr); @@ -101,7 +101,7 @@ namespace client void I2PTunnelConnection::Connect (bool isUniqueLocal) { if (m_Socket) - { + { I2PTunnelSetSocketOptions (m_Socket); #ifdef __linux__ if (isUniqueLocal && m_RemoteEndpoint.address ().is_v4 () && @@ -132,7 +132,7 @@ namespace client } Connect (false); } - + void I2PTunnelConnection::Terminate () { if (Kill()) return; @@ -155,7 +155,7 @@ namespace client m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - else + else m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -253,7 +253,7 @@ namespace client if (m_SSL) 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)); - else + else 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)); } @@ -269,9 +269,9 @@ namespace client { LogPrint (eLogDebug, "I2PTunnel: Connected"); 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)); - else + else Established (); } } @@ -289,7 +289,7 @@ namespace client Established (); } } - + void I2PTunnelConnection::Established () { if (m_IsQuiet) @@ -305,8 +305,8 @@ namespace client HandleStreamReceive (boost::system::error_code (), dest.size ()); } Receive (); - } - + } + void I2PClientTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len) { if (m_HeaderSent) @@ -363,9 +363,9 @@ namespace client StreamReceive (); // read more header 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 (); - } + } } } @@ -376,7 +376,7 @@ namespace client m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ()) { 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) @@ -400,7 +400,7 @@ namespace client // strip up some headers static const std::vector excluded // list of excluded headers { - "Keep-Alive:", "X-I2P" + "Keep-Alive:", "X-I2P" }; bool matched = false; for (const auto& it: excluded) @@ -422,8 +422,8 @@ namespace client else m_OutHeader << "Connection: close\r\n"; connection = true; - } - else // forward as is + } + else // forward as is m_OutHeader << line << "\n"; } } @@ -455,7 +455,7 @@ namespace client StreamReceive (); // read more header 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 (); } } @@ -526,7 +526,7 @@ namespace client if (m_NeedsWebIrc) { 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; } @@ -719,7 +719,7 @@ namespace client auto localDestination = GetLocalDestination (); if (localDestination) localDestination->StopAcceptingStreams (); - + ClearHandlers (); } @@ -796,14 +796,14 @@ namespace client void I2PServerTunnel::SetSSL (bool ssl) { if (ssl) - { + { m_SSLCtx = std::make_shared (boost::asio::ssl::context::sslv23); m_SSLCtx->set_verify_mode(boost::asio::ssl::context::verify_none); - } + } else m_SSLCtx = nullptr; - } - + } + void I2PServerTunnel::Accept () { if (m_PortDestination) @@ -1004,7 +1004,7 @@ namespace client I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr localDestination, 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) { } diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 4f61ef91..658f1cc7 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/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_B32[] = "X-I2P-DestB32"; // .b32.i2p address const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192; - + class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this { public: @@ -73,7 +73,7 @@ namespace client void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleWrite (const boost::system::error_code& ecode); void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); - + private: 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; } bool IsUniqueLocal () const { return m_IsUniqueLocal; } - void SetSSL (bool ssl); + void SetSSL (bool ssl); std::shared_ptr GetSSLCtx () const { return m_SSLCtx; }; - + void SetLocalAddress (const std::string& localAddress); const std::string& GetAddress() const { return m_Address; } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 5d0f4425..77a48efc 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1481,7 +1481,7 @@ namespace client auto localDest = session->GetLocalDestination (); auto datagramDest = localDest ? localDest->GetDatagramDestination () : nullptr; if (datagramDest) - { + { i2p::data::IdentityEx dest; dest.FromBase64 (destination); if (session->Type == eSAMSessionTypeDatagram) @@ -1490,7 +1490,7 @@ namespace client datagramDest->SendRawDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ()); else LogPrint (eLogError, "SAM: Unexpected session type ", (int)session->Type, "for session ", sessionID); - } + } else LogPrint (eLogError, "SAM: Datagram destination is not set for session ", sessionID); }