Compare commits

...

7 Commits

Author SHA1 Message Date
lcharles123
cd2cf62373 Merge 6e639f0e6a into 3d19fa12f6 2025-02-16 01:36:49 +00:00
orignal
3d19fa12f6 create new tunnel immediately if last one failed 2025-02-15 15:27:14 -05:00
orignal
48aaecacce check outbound tunnels only for LeaseSet request 2025-02-14 21:53:38 -05:00
orignal
4bb86b6a86 don't request LeaseSet until destination if ready 2025-02-14 18:18:28 -05:00
orignal
0588116489 make token always non-zero 2025-02-14 13:08:22 -05:00
orignal
78a37cc00f changed some log levels 2025-02-12 15:56:22 -05:00
lcharles123
6e639f0e6a Add yggdrasil as weak dependency to i2pd.service 2024-12-26 17:23:42 -03:00
6 changed files with 39 additions and 12 deletions

View File

@@ -2,6 +2,7 @@
Description=I2P Router written in C++ Description=I2P Router written in C++
Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/ Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/
After=network.target After=network.target
Wants=yggdrasil.service
[Service] [Service]
User=i2pd User=i2pd

View File

@@ -1251,18 +1251,21 @@ namespace transport
} }
uint64_t token; uint64_t token;
RAND_bytes ((uint8_t *)&token, 8); RAND_bytes ((uint8_t *)&token, 8);
m_IncomingTokens.emplace (ep, std::make_pair (token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT))); if (!token) token = 1; // token can't be zero
m_IncomingTokens.try_emplace (ep, token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT));
return token; return token;
} }
std::pair<uint64_t, uint32_t> SSU2Server::NewIncomingToken (const boost::asio::ip::udp::endpoint& ep) std::pair<uint64_t, uint32_t> SSU2Server::NewIncomingToken (const boost::asio::ip::udp::endpoint& ep)
{ {
m_IncomingTokens.erase (ep); // drop previous
uint64_t token; uint64_t token;
RAND_bytes ((uint8_t *)&token, 8); RAND_bytes ((uint8_t *)&token, 8);
auto ret = std::make_pair (token, uint32_t(i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT)); if (!token) token = 1; // token can't be zero
m_IncomingTokens.emplace (ep, ret); uint32_t expires = i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT;
return ret; auto [it, inserted] = m_IncomingTokens.try_emplace (ep, token, expires);
if (!inserted)
it->second = { token, expires }; // override
return it->second;
} }
std::vector<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers, std::vector<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers,

View File

@@ -351,10 +351,13 @@ namespace tunnel
{ {
it.second.first->SetState (eTunnelStateFailed); it.second.first->SetState (eTunnelStateFailed);
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex); std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
if (m_OutboundTunnels.size () > 1 || m_NumOutboundTunnels <= 1) // don't fail last tunnel if (m_OutboundTunnels.size () > 1) // don't fail last tunnel
m_OutboundTunnels.erase (it.second.first); m_OutboundTunnels.erase (it.second.first);
else else
{
it.second.first->SetState (eTunnelStateTestFailed); it.second.first->SetState (eTunnelStateTestFailed);
CreateOutboundTunnel (); // create new tunnel immediately because last one failed
}
} }
else if (it.second.first->GetState () != eTunnelStateExpiring) else if (it.second.first->GetState () != eTunnelStateExpiring)
it.second.first->SetState (eTunnelStateTestFailed); it.second.first->SetState (eTunnelStateTestFailed);
@@ -368,13 +371,16 @@ namespace tunnel
bool failed = false; bool failed = false;
{ {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex); std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
if (m_InboundTunnels.size () > 1 || m_NumInboundTunnels <= 1) // don't fail last tunnel if (m_InboundTunnels.size () > 1) // don't fail last tunnel
{ {
m_InboundTunnels.erase (it.second.second); m_InboundTunnels.erase (it.second.second);
failed = true; failed = true;
} }
else else
{
it.second.second->SetState (eTunnelStateTestFailed); it.second.second->SetState (eTunnelStateTestFailed);
CreateInboundTunnel (); // create new tunnel immediately because last one failed
}
} }
if (failed && m_LocalDestination) if (failed && m_LocalDestination)
m_LocalDestination->SetLeaseSetUpdated (true); m_LocalDestination->SetLeaseSetUpdated (true);

View File

@@ -297,7 +297,7 @@ namespace client
} }
else else
{ {
LogPrint (eLogCritical, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType); LogPrint (eLogInfo, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType);
keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true); keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true);
std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out);
size_t len = keys.GetFullLen (); size_t len = keys.GetFullLen ();
@@ -871,7 +871,7 @@ namespace client
} }
else else
LogPrint (eLogWarning, "Clients: Unknown section type = ", type, " of ", name, " in ", tunConf); LogPrint (eLogError, "Clients: Unknown section type = ", type, " of ", name, " in ", tunConf);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {

View File

@@ -29,13 +29,15 @@ namespace client
const std::map<std::string, std::string>& params): const std::map<std::string, std::string>& params):
LeaseSetDestination (service, isPublic, &params), LeaseSetDestination (service, isPublic, &params),
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()), m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()),
m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread), m_LeaseSetCreationTimer (service) m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread),
m_LeaseSetCreationTimer (service), m_ReadinessCheckTimer (service)
{ {
} }
void I2CPDestination::Stop () void I2CPDestination::Stop ()
{ {
m_LeaseSetCreationTimer.cancel (); m_LeaseSetCreationTimer.cancel ();
m_ReadinessCheckTimer.cancel ();
LeaseSetDestination::Stop (); LeaseSetDestination::Stop ();
m_Owner = nullptr; m_Owner = nullptr;
} }
@@ -88,7 +90,7 @@ namespace client
void I2CPDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) void I2CPDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
{ {
boost::asio::post (GetService (), std::bind (&I2CPDestination::PostCreateNewLeaseSet, this, tunnels)); boost::asio::post (GetService (), std::bind (&I2CPDestination::PostCreateNewLeaseSet, GetSharedFromThis (), tunnels));
} }
void I2CPDestination::PostCreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels) void I2CPDestination::PostCreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
@@ -98,6 +100,20 @@ namespace client
LogPrint (eLogInfo, "I2CP: LeaseSet is being created"); LogPrint (eLogInfo, "I2CP: LeaseSet is being created");
return; return;
} }
m_ReadinessCheckTimer.cancel ();
auto pool = GetTunnelPool ();
if (!pool || pool->GetOutboundTunnels ().empty ())
{
// try again later
m_ReadinessCheckTimer.expires_from_now (boost::posix_time::seconds(I2CP_DESTINATION_READINESS_CHECK_INTERVAL));
m_ReadinessCheckTimer.async_wait(
[s=GetSharedFromThis (), tunnels=std::move(tunnels)](const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
s->PostCreateNewLeaseSet (tunnels);
});
return;
}
uint8_t priv[256] = {0}; uint8_t priv[256] = {0};
i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only
m_LeaseSetExpirationTime = ls.GetExpirationTime (); m_LeaseSetExpirationTime = ls.GetExpirationTime ();

View File

@@ -31,6 +31,7 @@ namespace client
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535; const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds
const int I2CP_DESTINATION_READINESS_CHECK_INTERVAL = 5; // in seconds
const int I2CP_SESSION_ACK_REQUEST_INTERVAL = 12100; // in milliseconds const int I2CP_SESSION_ACK_REQUEST_INTERVAL = 12100; // in milliseconds
const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
@@ -131,7 +132,7 @@ namespace client
uint8_t m_ECIESx25519PrivateKey[32]; uint8_t m_ECIESx25519PrivateKey[32];
uint64_t m_LeaseSetExpirationTime; uint64_t m_LeaseSetExpirationTime;
bool m_IsCreatingLeaseSet, m_IsSameThread; bool m_IsCreatingLeaseSet, m_IsSameThread;
boost::asio::deadline_timer m_LeaseSetCreationTimer; boost::asio::deadline_timer m_LeaseSetCreationTimer, m_ReadinessCheckTimer;
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool; i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool;
}; };