diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index e4d765ac..5abd6112 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -498,7 +498,7 @@ namespace proxy { if (Kill()) return; LogPrint (eLogDebug, "HTTPProxy: Created new I2PTunnel stream, sSID=", stream->GetSendStreamID(), ", rSID=", stream->GetRecvStreamID()); - auto connection = std::make_shared(GetOwner(), m_sock, stream); + auto connection = std::make_shared(GetOwner(), m_sock, stream); GetOwner()->AddHandler (connection); connection->I2PConnect (reinterpret_cast(m_send_buf.data()), m_send_buf.length()); Done (shared_from_this()); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 6a9b3ffd..3f22ed03 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -236,14 +236,63 @@ namespace client } } - I2PTunnelConnectionHTTP::I2PTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, + void I2PClientTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len) + { + if (m_HeaderSent) + I2PTunnelConnection::Write (buf, len); + else + { + m_InHeader.clear (); + m_InHeader.write ((const char *)buf, len); + std::string line; + bool endOfHeader = false; + while (!endOfHeader) + { + std::getline(m_InHeader, line); + if (!m_InHeader.fail ()) + { + if (line == "\r") endOfHeader = true; + else + { + if (!m_ConnectionSent && !line.compare(0, 10, "Connection")) + { + m_OutHeader << "Connection: close\r\n"; + m_ConnectionSent = true; + } + else if (!m_ProxyConnectionSent && !line.compare(0, 16, "Proxy-Connection")) + { + m_OutHeader << "Proxy-Connection: close\r\n"; + m_ProxyConnectionSent = true; + } + else + m_OutHeader << line << "\n"; + } + } + else + break; + } + + if (endOfHeader) + { + if (!m_ConnectionSent) m_OutHeader << "Connection: close\r\n"; + if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n"; + m_OutHeader << "\r\n"; // end of header + m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header + m_InHeader.str (""); + m_HeaderSent = true; + I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ()); + } + } + } + + I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (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_HeaderSent (false), m_From (stream->GetRemoteIdentity ()) { } - void I2PTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len) + void I2PServerTunnelConnectionHTTP::Write (const uint8_t * buf, size_t len) { if (m_HeaderSent) I2PTunnelConnection::Write (buf, len); @@ -282,6 +331,7 @@ namespace client { m_OutHeader << "\r\n"; // end of header m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header + m_InHeader.str (""); m_HeaderSent = true; I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ()); } @@ -532,7 +582,7 @@ namespace client std::shared_ptr I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr stream) { - return std::make_shared (this, stream, + return std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), m_Host); } diff --git a/I2PTunnel.h b/I2PTunnel.h index 68f46e43..f0580554 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -64,11 +64,30 @@ namespace client bool m_IsQuiet; // don't send destination }; - class I2PTunnelConnectionHTTP: public I2PTunnelConnection + class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection + { + public: + + I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr socket, + std::shared_ptr stream): + I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false), + m_ConnectionSent (false), m_ProxyConnectionSent (false) {}; + + protected: + + void Write (const uint8_t * buf, size_t len); + + private: + + std::stringstream m_InHeader, m_OutHeader; + bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent; + }; + + class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection { public: - I2PTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, + I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& host);