diff --git a/ClientContext.cpp b/ClientContext.cpp index 2cdd3ae9..8d675286 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -319,6 +319,7 @@ namespace client int inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); + std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, true); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); // I2CP @@ -336,7 +337,7 @@ namespace client if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort, gzip); else if (type == I2P_TUNNELS_SECTION_TYPE_IRC) - serverTunnel = new I2PServerTunnelIRC (name, host, port, localDestination, inPort, gzip); + serverTunnel = new I2PServerTunnelIRC (name, host, port, localDestination, webircpass, inPort, gzip); else // regular server tunnel by default serverTunnel = new I2PServerTunnel (name, host, port, localDestination, inPort, gzip); diff --git a/ClientContext.h b/ClientContext.h index 8126a17a..a05c2161 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -35,7 +35,8 @@ namespace client const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_SERVER_TUNNEL_INPORT[] = "inport"; const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist"; - const char I2P_SERVER_TUNNEL_GZIP[] = "gzip"; + const char I2P_SERVER_TUNNEL_GZIP[] = "gzip"; + const char I2P_SERVER_TUNNEL_WEBIRC_PASSWORD[] = "webircpassword"; class ClientContext { diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index e2b75232..ad06328b 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -236,13 +236,21 @@ namespace client I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, - const boost::asio::ip::tcp::endpoint& target, const std::string& host): - I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_From (stream->GetRemoteIdentity ()) + const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass): + I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()), + m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass) { } void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) { + if (m_NeedsWebIrc) { + m_NeedsWebIrc = false; + m_OutPacket.str (""); + m_OutPacket << "WEBIRC " << this->m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " 127.0.0.1\n"; + I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); + } + std::string line; m_OutPacket.str (""); m_InPacket.clear (); @@ -477,16 +485,19 @@ namespace client } I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, int inport, bool gzip): - I2PServerTunnel (name, address, port, localDestination, inport, gzip) + int port, std::shared_ptr localDestination, + const std::string& webircpass, int inport, bool gzip): + I2PServerTunnel (name, address, port, localDestination, inport, gzip), + m_WebircPass (webircpass) { } void I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr stream) { - auto conn = std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), GetAddress ()); + auto conn = std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), this->m_WebircPass); AddHandler (conn); conn->Connect (); } + } } diff --git a/I2PTunnel.h b/I2PTunnel.h index 9b704033..bec0f9a4 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -86,17 +86,18 @@ namespace client I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, - const boost::asio::ip::tcp::endpoint& target, const std::string& host); + const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); protected: void Write (const uint8_t * buf, size_t len); private: - - std::string m_Host; + std::shared_ptr m_From; std::stringstream m_OutPacket, m_InPacket; + bool m_NeedsWebIrc; + std::string m_WebircPass; }; @@ -189,11 +190,16 @@ namespace client public: I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, - std::shared_ptr localDestination, int inport = 0, bool gzip = true); + std::shared_ptr localDestination, const std::string& webircpass, + int inport = 0, bool gzip = true); + + private: + + void CreateI2PConnection (std::shared_ptr stream); private: - void CreateI2PConnection (std::shared_ptr stream); + std::string m_WebircPass; }; } diff --git a/SOCKS.cpp b/SOCKS.cpp index e95eccbe..73833191 100644 --- a/SOCKS.cpp +++ b/SOCKS.cpp @@ -638,11 +638,9 @@ namespace proxy { LogPrint(eLogInfo, "SOCKS: forwarding to upstream"); EnterState(UPSTREAM_RESOLVE); - auto & service = GetOwner()->GetService(); boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress,boost::lexical_cast(m_UpstreamProxyPort) ); m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - + std::placeholders::_1, std::placeholders::_2)); } void SOCKSHandler::AsyncUpstreamSockRead() diff --git a/Tunnel.cpp b/Tunnel.cpp index 37dd6d67..5e237d87 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -244,8 +244,7 @@ namespace tunnel block.deliveryType = eDeliveryTypeLocal; block.data = msg; - std::unique_lock l(m_SendMutex); - m_Gateway.SendTunnelDataMsg (block); + SendTunnelDataMsg ({block}); } void OutboundTunnel::SendTunnelDataMsg (const std::vector& msgs) @@ -268,6 +267,38 @@ namespace tunnel s << " ⇒ "; } + ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel (): + OutboundTunnel (std::make_shared ()), + m_NumSentBytes (0) + { + } + + void ZeroHopsOutboundTunnel::SendTunnelDataMsg (const std::vector& msgs) + { + for (auto& msg : msgs) + { + switch (msg.deliveryType) + { + case eDeliveryTypeLocal: + i2p::HandleI2NPMessage (msg.data); + break; + case eDeliveryTypeTunnel: + i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); + break; + case eDeliveryTypeRouter: + i2p::transport::transports.SendMessage (msg.hash, msg.data); + break; + default: + LogPrint (eLogError, "Tunnel: Unknown delivery type ", (int)msg.deliveryType); + } + } + } + + void ZeroHopsOutboundTunnel::Print (std::stringstream& s) const + { + s << GetTunnelID () << ":me ⇒ "; + } + Tunnels tunnels; Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), @@ -661,6 +692,7 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnel: Creating zero hops inbound tunnel"); CreateZeroHopsInboundTunnel (); + CreateZeroHopsOutboundTunnel (); if (!m_ExploratoryPool) { m_ExploratoryPool = CreateTunnelPool (2, 2, 5, 5); // 2-hop exploratory, 5 tunnels @@ -785,23 +817,20 @@ namespace tunnel void Tunnels::CreateZeroHopsInboundTunnel () { - /*CreateTunnel ( - std::make_shared (std::vector > - { - i2p::context.GetIdentity () - }));*/ auto inboundTunnel = std::make_shared (); + inboundTunnel->SetState (eTunnelStateEstablished); m_InboundTunnels.push_back (inboundTunnel); m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel; - - // create paired outbound tunnel, TODO: move to separate function - CreateTunnel ( - std::make_shared (std::vector > - { - i2p::context.GetIdentity () - }, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ())); } + void Tunnels::CreateZeroHopsOutboundTunnel () + { + auto outboundTunnel = std::make_shared (); + outboundTunnel->SetState (eTunnelStateEstablished); + m_OutboundTunnels.push_back (outboundTunnel); + // we don't insert into m_Tunnels + } + int Tunnels::GetTransitTunnelsExpirationTimeout () { int timeout = 0; diff --git a/Tunnel.h b/Tunnel.h index 34d0a0ab..fe6022ac 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -100,9 +100,9 @@ namespace tunnel Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}; void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); - void SendTunnelDataMsg (const std::vector& msgs); // multiple messages + virtual void SendTunnelDataMsg (const std::vector& msgs); // multiple messages const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; - size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; + virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; void Print (std::stringstream& s) const; // implements TunnelBase @@ -143,6 +143,20 @@ namespace tunnel size_t m_NumReceivedBytes; }; + class ZeroHopsOutboundTunnel: public OutboundTunnel + { + public: + + ZeroHopsOutboundTunnel (); + void SendTunnelDataMsg (const std::vector& msgs); + void Print (std::stringstream& s) const; + size_t GetNumSentBytes () const { return m_NumSentBytes; }; + + private: + + size_t m_NumSentBytes; + }; + class Tunnels { public: @@ -191,7 +205,8 @@ namespace tunnel void ManageTunnelPools (); void CreateZeroHopsInboundTunnel (); - + void CreateZeroHopsOutboundTunnel (); + private: bool m_IsRunning; diff --git a/version.h b/version.h index 49b52b96..0550dcc9 100644 --- a/version.h +++ b/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 4 +#define I2PD_VERSION_MINOR 5 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)