Compare commits

...

5 Commits

Author SHA1 Message Date
lcharles123
71334e487b Merge 6e639f0e6a into 5f762845f0 2025-03-01 03:57:48 -10:00
orignal
5f762845f0 move BOB incoming connection logic from I2PTunnelConnection to BOB 2025-02-28 22:20:50 -05:00
orignal
539e7e988e reduce I2PTunnelConnection buffer size 2025-02-27 21:35:14 -05:00
orignal
2a4403f1e0 lazy creation of TunnelEnpoint for transit tunnel 2025-02-27 18:00:24 -05:00
lcharles123
6e639f0e6a Add yggdrasil as weak dependency to i2pd.service 2024-12-26 17:23:42 -03:00
7 changed files with 79 additions and 48 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

@@ -131,27 +131,35 @@ namespace tunnel
LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ()); LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ());
std::lock_guard<std::mutex> l(m_HandleMutex); std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); if (!m_Endpoint) m_Endpoint = std::make_unique<TunnelEndpoint>(false); // transit endpoint is always outbound
m_Endpoint->HandleDecryptedTunnelDataMsg (newMsg);
} }
void TransitTunnelEndpoint::FlushTunnelDataMsgs () void TransitTunnelEndpoint::FlushTunnelDataMsgs ()
{ {
std::lock_guard<std::mutex> l(m_HandleMutex); if (m_Endpoint)
m_Endpoint.FlushI2NPMsgs (); {
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint->FlushI2NPMsgs ();
}
} }
void TransitTunnelEndpoint::Cleanup () void TransitTunnelEndpoint::Cleanup ()
{ {
std::lock_guard<std::mutex> l(m_HandleMutex); if (m_Endpoint)
m_Endpoint.Cleanup (); {
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint->Cleanup ();
}
} }
std::string TransitTunnelEndpoint::GetNextPeerName () const std::string TransitTunnelEndpoint::GetNextPeerName () const
{ {
auto hash = m_Endpoint.GetCurrentHash (); if (!m_Endpoint) return "";
auto hash = m_Endpoint->GetCurrentHash ();
if (hash) if (hash)
{ {
const auto& sender = m_Endpoint.GetSender (); const auto& sender = m_Endpoint->GetSender ();
if (sender) if (sender)
{ {
auto transport = sender->GetCurrentTransport (); auto transport = sender->GetCurrentTransport ();

View File

@@ -97,20 +97,19 @@ namespace tunnel
TransitTunnelEndpoint (uint32_t receiveTunnelID, TransitTunnelEndpoint (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey) {};
m_Endpoint (false) {}; // transit endpoint is always outbound
void Cleanup () override; void Cleanup () override;
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override; void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
void FlushTunnelDataMsgs () override; void FlushTunnelDataMsgs () override;
size_t GetNumTransmittedBytes () const override { return m_Endpoint.GetNumReceivedBytes (); } size_t GetNumTransmittedBytes () const override { return m_Endpoint ? m_Endpoint->GetNumReceivedBytes () : 0; }
std::string GetNextPeerName () const override; std::string GetNextPeerName () const override;
private: private:
std::mutex m_HandleMutex; std::mutex m_HandleMutex;
TunnelEndpoint m_Endpoint; std::unique_ptr<TunnelEndpoint> m_Endpoint;
}; };
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID, std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -16,6 +16,24 @@ namespace i2p
{ {
namespace client namespace client
{ {
void BOBI2PTunnelIncomingConnection::Established ()
{
if (m_IsQuiet)
StreamReceive ();
else
{
// send destination first like received from I2P
std::string dest = GetStream ()->GetRemoteIdentity ()->ToBase64 ();
dest += "\n";
if (dest.size() <= I2P_TUNNEL_CONNECTION_BUFFER_SIZE)
memcpy (GetStreamBuffer (), dest.c_str (), dest.size ());
else
memset (GetStreamBuffer (), 0, I2P_TUNNEL_CONNECTION_BUFFER_SIZE);
HandleStreamReceive (boost::system::error_code (), dest.size ());
}
Receive ();
}
BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr<ClientDestination> localDestination): BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr<ClientDestination> localDestination):
BOBI2PTunnel (localDestination), m_Acceptor (localDestination->GetService (), ep) BOBI2PTunnel (localDestination), m_Acceptor (localDestination->GetService (), ep)
{ {
@@ -156,7 +174,7 @@ namespace client
{ {
if (stream) if (stream)
{ {
auto conn = std::make_shared<I2PTunnelConnection> (this, stream, m_Endpoint, m_IsQuiet); auto conn = std::make_shared<BOBI2PTunnelIncomingConnection> (this, stream, m_Endpoint, m_IsQuiet);
AddHandler (conn); AddHandler (conn);
conn->Connect (); conn->Connect ();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -71,6 +71,23 @@ namespace client
const char BOB_HELP_STATUS[] = "status <NICKNAME> - Display status of a nicknamed tunnel."; const char BOB_HELP_STATUS[] = "status <NICKNAME> - Display status of a nicknamed tunnel.";
const char BOB_HELP_HELP [] = "help <COMMAND> - Get help on a command."; const char BOB_HELP_HELP [] = "help <COMMAND> - Get help on a command.";
class BOBI2PTunnelIncomingConnection: public I2PTunnelConnection
{
public:
BOBI2PTunnelIncomingConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
const boost::asio::ip::tcp::endpoint& target, bool quiet):
I2PTunnelConnection (owner, stream, target), m_IsQuiet (quiet) {};
protected:
void Established () override;
private:
bool m_IsQuiet; // don't send destination
};
class BOBI2PTunnel: public I2PService class BOBI2PTunnel: public I2PService
{ {
public: public:

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -32,8 +32,7 @@ namespace client
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, uint16_t port): std::shared_ptr<const i2p::data::LeaseSet> leaseSet, uint16_t port):
I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ())
m_IsQuiet (true)
{ {
m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port); m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port);
} }
@@ -41,14 +40,13 @@ namespace client
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, I2PTunnelConnection::I2PTunnelConnection (I2PService * owner,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<i2p::stream::Stream> stream): std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<i2p::stream::Stream> stream):
I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream),
m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) m_RemoteEndpoint (socket->remote_endpoint ())
{ {
} }
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
const boost::asio::ip::tcp::endpoint& target, bool quiet, const boost::asio::ip::tcp::endpoint& target,std::shared_ptr<boost::asio::ssl::context> sslCtx):
std::shared_ptr<boost::asio::ssl::context> sslCtx): I2PServiceHandler(owner), m_Stream (stream), m_RemoteEndpoint (target)
I2PServiceHandler(owner), m_Stream (stream), m_RemoteEndpoint (target), m_IsQuiet (quiet)
{ {
m_Socket = std::make_shared<boost::asio::ip::tcp::socket> (owner->GetService ()); m_Socket = std::make_shared<boost::asio::ip::tcp::socket> (owner->GetService ());
if (sslCtx) if (sslCtx)
@@ -292,18 +290,7 @@ namespace client
void I2PTunnelConnection::Established () void I2PTunnelConnection::Established ()
{ {
if (m_IsQuiet) StreamReceive ();
StreamReceive ();
else
{
// send destination first like received from I2P
std::string dest = m_Stream->GetRemoteIdentity ()->ToBase64 ();
dest += "\n";
if(sizeof(m_StreamBuffer) >= dest.size()) {
memcpy (m_StreamBuffer, dest.c_str (), dest.size ());
}
HandleStreamReceive (boost::system::error_code (), dest.size ());
}
Receive (); Receive ();
} }
@@ -377,7 +364,7 @@ namespace client
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
const boost::asio::ip::tcp::endpoint& target, const std::string& host, const std::string& XI2P, const boost::asio::ip::tcp::endpoint& target, const std::string& host, const std::string& XI2P,
std::shared_ptr<boost::asio::ssl::context> sslCtx): std::shared_ptr<boost::asio::ssl::context> sslCtx):
I2PTunnelConnection (owner, stream, target, true, sslCtx), m_Host (host), m_XI2P (XI2P), I2PTunnelConnection (owner, stream, target, sslCtx), m_Host (host), m_XI2P (XI2P),
m_HeaderSent (false), m_ResponseHeaderSent (false) m_HeaderSent (false), m_ResponseHeaderSent (false)
{ {
if (sslCtx) if (sslCtx)
@@ -528,7 +515,7 @@ namespace client
I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass, const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass,
std::shared_ptr<boost::asio::ssl::context> sslCtx): std::shared_ptr<boost::asio::ssl::context> sslCtx):
I2PTunnelConnection (owner, stream, target, true, sslCtx), m_From (stream->GetRemoteIdentity ()), I2PTunnelConnection (owner, stream, target, sslCtx), m_From (stream->GetRemoteIdentity ()),
m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass) m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass)
{ {
} }
@@ -857,7 +844,7 @@ namespace client
std::shared_ptr<I2PTunnelConnection> I2PServerTunnel::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream) std::shared_ptr<I2PTunnelConnection> I2PServerTunnel::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
{ {
return std::make_shared<I2PTunnelConnection> (this, stream, GetEndpoint (), true, m_SSLCtx); return std::make_shared<I2PTunnelConnection> (this, stream, GetEndpoint (), m_SSLCtx);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -27,7 +27,7 @@ namespace i2p
{ {
namespace client namespace client
{ {
const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 65536; const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 16384;
const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
// for HTTP tunnels // for HTTP tunnels
@@ -45,7 +45,7 @@ namespace client
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API
I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
const boost::asio::ip::tcp::endpoint& target, bool quiet = true, const boost::asio::ip::tcp::endpoint& target,
std::shared_ptr<boost::asio::ssl::context> sslCtx = nullptr); // from I2P std::shared_ptr<boost::asio::ssl::context> sslCtx = nullptr); // from I2P
~I2PTunnelConnection (); ~I2PTunnelConnection ();
void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0); void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0);
@@ -54,25 +54,27 @@ namespace client
protected: protected:
virtual void Established ();
void Terminate (); void Terminate ();
void Receive (); void Receive ();
void StreamReceive (); void StreamReceive ();
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded
std::shared_ptr<boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; }; std::shared_ptr<boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
std::shared_ptr<i2p::stream::Stream> GetStream () const { return m_Stream; };
std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> > GetSSL () const { return m_SSL; }; std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> > GetSSL () const { return m_SSL; };
uint8_t * GetStreamBuffer () { return m_StreamBuffer; };
private: private:
void HandleConnect (const boost::system::error_code& ecode); void HandleConnect (const boost::system::error_code& ecode);
void HandleHandshake (const boost::system::error_code& ecode); void HandleHandshake (const boost::system::error_code& ecode);
void Established ();
void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleWrite (const boost::system::error_code& ecode); void HandleWrite (const boost::system::error_code& ecode);
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
private: private:
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
@@ -80,7 +82,6 @@ namespace client
std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> > m_SSL; std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> > m_SSL;
std::shared_ptr<i2p::stream::Stream> m_Stream; std::shared_ptr<i2p::stream::Stream> m_Stream;
boost::asio::ip::tcp::endpoint m_RemoteEndpoint; boost::asio::ip::tcp::endpoint m_RemoteEndpoint;
bool m_IsQuiet; // don't send destination
}; };
class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
@@ -94,7 +95,7 @@ namespace client
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len) override;
private: private:
@@ -112,8 +113,8 @@ namespace client
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len) override;
void WriteToStream (const uint8_t * buf, size_t len); void WriteToStream (const uint8_t * buf, size_t len) override;
private: private:
@@ -132,7 +133,7 @@ namespace client
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len) override;
private: private: