diff --git a/ClientContext.cpp b/ClientContext.cpp index 19d841d3..304b53c6 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -303,7 +303,7 @@ namespace client LogPrint (eLogError, "Clients: I2P client tunnel with port ", port, " already exists"); numClientTunnels++; } - else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || type == I2P_TUNNELS_SECTION_TYPE_HTTP) + else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || type == I2P_TUNNELS_SECTION_TYPE_HTTP || type == I2P_TUNNELS_SECTION_TYPE_IRC) { // mandatory params std::string host = section.second.get (I2P_SERVER_TUNNEL_HOST); @@ -324,9 +324,16 @@ namespace client localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); - I2PServerTunnel * serverTunnel = (type == I2P_TUNNELS_SECTION_TYPE_HTTP) ? - new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort) : - new I2PServerTunnel (name, host, port, localDestination, inPort); + + I2PServerTunnel * serverTunnel; + if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) { + serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort); + } else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER) { + serverTunnel = new I2PServerTunnel (name, host, port, localDestination, inPort); + } else if (type == I2P_TUNNELS_SECTION_TYPE_IRC) { + serverTunnel = new I2PServerTunnelIRC (name, host, port, localDestination, inPort); + } + if (accessList.length () > 0) { std::set idents; diff --git a/ClientContext.h b/ClientContext.h index 30e495da..1be2960b 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -21,6 +21,7 @@ namespace client const char I2P_TUNNELS_SECTION_TYPE_CLIENT[] = "client"; const char I2P_TUNNELS_SECTION_TYPE_SERVER[] = "server"; const char I2P_TUNNELS_SECTION_TYPE_HTTP[] = "http"; + const char I2P_TUNNELS_SECTION_TYPE_IRC[] = "irc"; const char I2P_CLIENT_TUNNEL_PORT[] = "port"; const char I2P_CLIENT_TUNNEL_ADDRESS[] = "address"; const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination"; diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 4eb1c573..0904ed35 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -234,6 +234,47 @@ 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 ()) + { + } + + void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) + { + char *p = (char*)(buf + len); + *p = '\0'; + std::string line; + m_OutPacket.str (""); + m_InPacket.str (""); + m_InPacket.clear (); + m_InPacket.write ((const char *)buf, len); + + while (!m_InPacket.eof () && !m_InPacket.fail ()) + { + std::getline (m_InPacket, line); + auto pos = line.find ("USER"); + if (pos != std::string::npos && pos == 0) + { + pos = line.find (" "); + pos++; + pos = line.find (" ", pos); + pos++; + pos = line.find (" ", pos); + pos++; + auto nextpos = line.find (" ", pos); + m_OutPacket << line.substr (0, pos); + m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()); + m_OutPacket << line.substr (nextpos) << '\n'; + } else { + m_OutPacket << line << '\n'; + } + } + I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); + } + + /* This handler tries to stablish a connection with the desired server and dies if it fails to do so */ class I2PClientTunnelHandler: public I2PServiceHandler, public std::enable_shared_from_this { @@ -436,5 +477,18 @@ namespace client AddHandler (conn); conn->Connect (); } + + I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, + int port, std::shared_ptr localDestination, int inport): + I2PServerTunnel (name, address, port, localDestination, inport) + { + } + + void I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr stream) + { + auto conn = std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), GetAddress ()); + AddHandler (conn); + conn->Connect (); + } } } diff --git a/I2PTunnel.h b/I2PTunnel.h index 834897f7..dc791506 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -80,6 +80,26 @@ namespace client std::shared_ptr m_From; }; + class I2PTunnelConnectionIRC: public I2PTunnelConnection + { + public: + + I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, + std::shared_ptr socket, + const boost::asio::ip::tcp::endpoint& target, const std::string& host); + + 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; + }; + + class I2PClientTunnel: public TCPIPAcceptor { protected: @@ -163,6 +183,19 @@ namespace client std::string m_Host; }; + + class I2PServerTunnelIRC: public I2PServerTunnel + { + public: + + I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, + std::shared_ptr localDestination, int inport = 0); + + private: + + void CreateI2PConnection (std::shared_ptr stream); + }; + } }