Compare commits

...

9 commits

Author SHA1 Message Date
self-related 40e5d4c5e3
Merge 32a70562c4 into d3630fb2b2 2024-10-25 21:32:24 +02:00
orignal d3630fb2b2 assign name to main thread
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2024-10-25 13:25:33 -04:00
orignal 500afe745f use min hole punch interval for connection attempts 2024-10-24 18:49:11 -04:00
orignal 26901e2945 try recently connected SSU2 address if no other transports found 2024-10-23 20:39:00 -04:00
orignal 64bde69967
Merge pull request #2108 from SystemFailureNet/openssl
Please disable LibreSSL workaround when LibreSSL version >= 4.0.0
2024-10-21 21:38:50 -04:00
orignal ddf30784ec connected recently mutex 2024-10-21 21:22:16 -04:00
orignal ea14b00d63 save router's endpoint to profile and try to use it next time without requesting introducers 2024-10-21 20:58:09 -04:00
SystemFailure f98a310235 Revert LibreSSL workaround when LibreSSL version >= 4.0.0 2024-10-18 13:17:47 +00:00
self-related 32a70562c4
Fix UPnP: error 2 2024-08-19 00:07:22 +03:00
8 changed files with 97 additions and 31 deletions

View file

@ -122,7 +122,7 @@ namespace transport
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
#endif
m_upnpUrlsInitialized=err!=0;
if (err == UPNP_IGD_VALID_CONNECTED)
if (err == UPNP_IGD_VALID_CONNECTED || err == UPNP_IGD_VALID_NOT_CONNECTED)
{
#if (MINIUPNPC_API_VERSION < 18)
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -25,6 +25,7 @@
#include "RouterContext.h"
#include "ClientContext.h"
#include "Transports.h"
#include "util.h"
void handle_signal(int sig)
{
@ -220,6 +221,7 @@ namespace i2p
void DaemonLinux::run ()
{
i2p::util::SetThreadName ("Daemon");
while (running)
{
std::this_thread::sleep_for (std::chrono::seconds(1));

View file

@ -997,7 +997,7 @@ namespace crypto
}
else
{
#if defined(LIBRESSL_VERSION_NUMBER)
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x4000000fL
std::vector<uint8_t> m(msgLen + 16);
if (msg == buf)
{

View file

@ -11,6 +11,7 @@
#include <memory>
#include <future>
#include <boost/asio.hpp>
#include "Identity.h"
namespace i2p
@ -67,6 +68,11 @@ namespace data
bool IsUseful() const;
bool IsDuplicated () const { return m_IsDuplicated; };
const boost::asio::ip::udp::endpoint& GetLastEndpoint () const { return m_LastEndpoint; }
void SetLastEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_LastEndpoint = ep; }
bool HasLastEndpoint (bool v4) const { return !m_LastEndpoint.address ().is_unspecified () && m_LastEndpoint.port () &&
((v4 && m_LastEndpoint.address ().is_v4 ()) || (!v4 && m_LastEndpoint.address ().is_v6 ())); }
private:
@ -90,6 +96,8 @@ namespace data
uint32_t m_NumTimesRejected;
bool m_HasConnected; // successful trusted(incoming or NTCP2) connection
bool m_IsDuplicated;
// connectivity
boost::asio::ip::udp::endpoint m_LastEndpoint; // SSU2 for non-published addresses
};
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);

View file

@ -216,15 +216,16 @@ namespace transport
return ep.port ();
}
bool SSU2Server::IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep)
bool SSU2Server::IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep, bool max)
{
if (!ep.port () || ep.address ().is_unspecified ()) return false;
std::lock_guard<std::mutex> l(m_ConnectedRecentlyMutex);
auto it = m_ConnectedRecently.find (ep);
if (it != m_ConnectedRecently.end ())
{
if (i2p::util::GetSecondsSinceEpoch () <= it->second + SSU2_HOLE_PUNCH_EXPIRATION)
if (i2p::util::GetSecondsSinceEpoch () <= it->second + (max ? SSU2_MAX_HOLE_PUNCH_EXPIRATION : SSU2_MIN_HOLE_PUNCH_EXPIRATION))
return true;
else
else if (max)
m_ConnectedRecently.erase (it);
}
return false;
@ -233,7 +234,8 @@ namespace transport
void SSU2Server::AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts)
{
if (!ep.port () || ep.address ().is_unspecified () ||
i2p::util::GetSecondsSinceEpoch () > ts + SSU2_HOLE_PUNCH_EXPIRATION) return;
i2p::util::GetSecondsSinceEpoch () > ts + SSU2_MAX_HOLE_PUNCH_EXPIRATION) return;
std::lock_guard<std::mutex> l(m_ConnectedRecentlyMutex);
auto [it, added] = m_ConnectedRecently.try_emplace (ep, ts);
if (!added && ts > it->second)
it->second = ts; // renew timestamp of existing endpoint
@ -833,6 +835,29 @@ namespace transport
}
}
bool SSU2Server::CheckPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep, bool peerTest)
{
auto s = FindPendingOutgoingSession (ep);
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]() { s->SendPeerTest (); });
}
return true;
}
return false;
}
bool SSU2Server::CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest)
{
@ -852,34 +877,28 @@ namespace transport
if (isValidEndpoint)
{
if (i2p::transport::transports.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]() { s->SendPeerTest (); });
}
return false;
}
if (CheckPendingOutgoingSession (boost::asio::ip::udp::endpoint (address->host, address->port), peerTest)) return false;
}
auto session = std::make_shared<SSU2Session> (*this, router, address);
if (!isValidEndpoint && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
{
// router doesn't publish endpoint, but we connected before and hole punch might be alive
auto ep = router->GetProfile ()->GetLastEndpoint ();
if (IsConnectedRecently (ep, false))
{
if (CheckPendingOutgoingSession (ep, peerTest)) return false;
session->SetRemoteEndpoint (ep);
isValidEndpoint = true;
}
}
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
if (isValidEndpoint) // we know endpoint
GetService ().post ([session]() { session->Connect (); });
else if (address->UsesIntroducer ()) // we don't know endpoint yet
GetService ().post (std::bind (&SSU2Server::ConnectThroughIntroducer, this, session));
else
return false;
}
@ -1129,7 +1148,7 @@ namespace transport
for (auto it = m_ConnectedRecently.begin (); it != m_ConnectedRecently.end (); )
{
if (ts > it->second + SSU2_HOLE_PUNCH_EXPIRATION)
if (ts > it->second + SSU2_MAX_HOLE_PUNCH_EXPIRATION)
it = m_ConnectedRecently.erase (it);
else
it++;

View file

@ -42,7 +42,8 @@ namespace transport
const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds
const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds
const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds
const int SSU2_HOLE_PUNCH_EXPIRATION = 150; // in seconds
const int SSU2_MIN_HOLE_PUNCH_EXPIRATION = 45; // in seconds
const int SSU2_MAX_HOLE_PUNCH_EXPIRATION = 181; // in seconds
const size_t SSU2_MAX_NUM_PACKETS_PER_BATCH = 64;
class SSU2Server: private i2p::util::RunnableServiceWithWork
@ -77,7 +78,7 @@ namespace transport
bool UsesProxy () const { return m_IsThroughProxy; };
bool IsSupported (const boost::asio::ip::address& addr) const;
uint16_t GetPort (bool v4) const;
bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep);
bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep, bool max = true);
void AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts);
std::mt19937& GetRng () { return m_Rng; }
bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; }
@ -147,6 +148,7 @@ namespace transport
void ScheduleResend (bool more);
void HandleResendTimer (const boost::system::error_code& ecode);
bool CheckPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep, bool peerTest);
void ConnectThroughIntroducer (std::shared_ptr<SSU2Session> session);
std::vector<std::shared_ptr<SSU2Session> > FindIntroducers (int maxNumIntroducers,
bool v4, const std::unordered_set<i2p::data::IdentHash>& excluded);
@ -193,6 +195,7 @@ namespace transport
std::shared_ptr<const i2p::data::IdentityEx> m_PendingTimeOffsetFrom;
std::mt19937 m_Rng;
std::map<boost::asio::ip::udp::endpoint, uint64_t> m_ConnectedRecently; // endpoint -> last activity time in seconds
mutable std::mutex m_ConnectedRecentlyMutex;
std::unordered_map<uint32_t, std::pair <std::weak_ptr<SSU2PeerTestSession>, uint64_t > > m_RequestedPeerTests; // nonce->(Alice, timestamp)
std::list<Packet *> m_ReceivedPacketsQueue;
mutable std::mutex m_ReceivedPacketsQueueMutex;

View file

@ -226,6 +226,13 @@ namespace transport
if (m_Server.AddPendingOutgoingSession (shared_from_this ()))
{
m_Server.RemoveSession (GetConnID ());
// update endpoint in profile because we know it now
auto identity = GetRemoteIdentity ();
if (identity)
{
auto profile = i2p::data::GetRouterProfile (identity->GetIdentHash ());
if (profile) profile->SetLastEndpoint (m_RemoteEndpoint);
}
// connect
LogPrint (eLogDebug, "SSU2: Connecting after introduction to ", GetIdentHashBase64());
Connect ();
@ -1169,6 +1176,8 @@ namespace transport
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
return false;
}
if (!m_Address->published)
ri->GetProfile ()->SetLastEndpoint (m_RemoteEndpoint);
SetRemoteIdentity (ri->GetRouterIdentity ());
AdjustMaxPayloadSize ();
m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now

View file

@ -672,6 +672,31 @@ namespace transport
if (transport & compatibleTransports)
peer->priority.push_back (transport);
}
if (peer->priority.empty ())
{
// try recently connected SSU2 if any
auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
peer->router->GetCompatibleTransports (false);
if (supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6))
{
auto ep = peer->router->GetProfile ()->GetLastEndpoint ();
if (!ep.address ().is_unspecified () && ep.port ())
{
if (ep.address ().is_v4 ())
{
if ((supportedTransports & i2p::data::RouterInfo::eSSU2V4) &&
m_SSU2Server->IsConnectedRecently (ep, false))
peer->priority.push_back (i2p::data::RouterInfo::eSSU2V4);
}
else if (ep.address ().is_v6 ())
{
if ((supportedTransports & i2p::data::RouterInfo::eSSU2V6) &&
m_SSU2Server->IsConnectedRecently (ep))
peer->priority.push_back (i2p::data::RouterInfo::eSSU2V6);
}
}
}
}
}
void Transports::RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident)