diff --git a/Daemon.cpp b/Daemon.cpp index ea98378b..3836bd96 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -72,6 +72,8 @@ namespace i2p if (i2p::util::config::GetArg("-unreachable", 0)) i2p::context.SetUnreachable (); + i2p::context.SetSupportsV6 (i2p::util::config::GetArg("-v6", 0)); + LogPrint("CMD parameters:"); for (int i = 0; i < argc; ++i) LogPrint(i, " ", argv[i]); diff --git a/RouterContext.cpp b/RouterContext.cpp index 2560e6d4..8832e81e 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -78,7 +78,7 @@ namespace i2p auto newAddress = boost::asio::ip::address::from_string (host); for (auto& address : m_RouterInfo.GetAddresses ()) { - if (address.host != newAddress) + if (address.host != newAddress && address.IsCompatible (newAddress)) { address.host = newAddress; updated = true; @@ -130,7 +130,15 @@ namespace i2p // update UpdateRouterInfo (); } - + + void RouterContext::SetSupportsV6 (bool supportsV6) + { + if (supportsV6) + m_RouterInfo.EnableV6 (); + else + m_RouterInfo.DisableV6 (); + } + bool RouterContext::Load () { std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ofstream::in); diff --git a/RouterContext.h b/RouterContext.h index e10a4192..35f11e2d 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -32,7 +32,9 @@ namespace i2p void SetUnreachable (); bool AcceptsTunnels () const { return m_AcceptsTunnels; }; void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; - + bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; + void SetSupportsV6 (bool supportsV6); + // implements LocalDestination const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const uint8_t * GetEncryptionPrivateKey () const { return m_Keys.GetPrivateKey (); }; diff --git a/RouterInfo.cpp b/RouterInfo.cpp index c88ae02c..960db401 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -458,7 +458,7 @@ namespace data addr.cost = 2; addr.date = 0; m_Addresses.push_back(addr); - m_SupportedTransports |= eNTCPV4; + m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eNTCPV4; } void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key) @@ -471,7 +471,7 @@ namespace data addr.date = 0; memcpy (addr.key, key, 32); m_Addresses.push_back(addr); - m_SupportedTransports |= eSSUV4; + m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eSSUV4; m_Caps |= eSSUTesting; m_Caps |= eSSUIntroducer; } @@ -560,6 +560,34 @@ namespace data return m_SupportedTransports & (eSSUV4 | eSSUV6); } + bool RouterInfo::IsV6 () const + { + return m_SupportedTransports & (eNTCPV6 | eSSUV6); + } + + void RouterInfo::EnableV6 () + { + if (!IsV6 ()) + m_SupportedTransports |= eNTCPV6; + } + + void RouterInfo::DisableV6 () + { + if (IsV6 ()) + { + m_SupportedTransports &= ~eNTCPV6; + for (size_t i = 0; i < m_Addresses.size (); i++) + { + if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportNTCP && + m_Addresses[i].host.is_v6 ()) + { + m_Addresses.erase (m_Addresses.begin () + i); + break; + } + } + } + } + bool RouterInfo::UsesIntroducer () const { return m_Caps & Caps::eUnreachable; // non-reachable diff --git a/RouterInfo.h b/RouterInfo.h index a4ccb159..d5d775b1 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -75,6 +75,12 @@ namespace data // SSU only Tag<32> key; // intro key for SSU std::vector introducers; + + bool IsCompatible (const boost::asio::ip::address& other) const + { + return (host.is_v4 () && other.is_v4 ()) || + (host.is_v6 () && other.is_v6 ()); + } }; RouterInfo (const std::string& fullPath); @@ -102,6 +108,9 @@ namespace data bool IsFloodfill () const; bool IsNTCP (bool v4only = true) const; bool IsSSU (bool v4only = true) const; + bool IsV6 () const; + void EnableV6 (); + void DisableV6 (); bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; bool UsesIntroducer () const; bool IsIntroducer () const { return m_Caps & eSSUIntroducer; }; diff --git a/Transports.cpp b/Transports.cpp index b3a01aee..cfe368e7 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -253,7 +253,7 @@ namespace transport { // existing session not found. create new // try NTCP first if message size < 16K - auto address = r->GetNTCPAddress (); + auto address = r->GetNTCPAddress (!context.SupportsV6 ()); if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE) { auto s = new NTCPClient (m_Service, address->host, address->port, *r);