diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index d6d92388..520fc23f 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "Crypto.h" #include "Log.h" #include "FS.h" diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index e84bcb5f..a15bbb14 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -54,6 +54,7 @@ namespace client std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); + std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); if (httpProxyKeys.length () > 0) { @@ -70,7 +71,7 @@ namespace client } try { - m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); + m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); m_HttpProxy->Start(); } catch (std::exception& e) @@ -536,7 +537,8 @@ namespace client else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY) { // http proxy - clientTunnel = new i2p::proxy::HTTPProxy(address, port, localDestination); + std::string outproxy = section.second.get("outproxy", ""); + clientTunnel = new i2p::proxy::HTTPProxy(address, port, outproxy, localDestination); clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint (); } else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 526e779e..b1e1a545 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -86,6 +86,7 @@ namespace proxy { std::shared_ptr m_sock; std::shared_ptr m_proxysock; boost::asio::ip::tcp::resolver m_proxy_resolver; + std::string m_OutproxyUrl; i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; uint8_t m_socks_buf[255+8]; // for socks request/response @@ -99,7 +100,8 @@ namespace proxy { HTTPReqHandler(HTTPProxy * parent, std::shared_ptr sock) : I2PServiceHandler(parent), m_sock(sock), m_proxysock(std::make_shared(parent->GetService())), - m_proxy_resolver(parent->GetService()) {} + m_proxy_resolver(parent->GetService()), + m_OutproxyUrl(parent->GetOutproxyURL()) {} ~HTTPReqHandler() { Terminate(); } void Handle () { AsyncSockRead(); } /* overload */ }; @@ -324,10 +326,9 @@ namespace proxy { return true; /* request processed */ } } else { - std::string outproxyUrl; i2p::config::GetOption("httpproxy.outproxy", outproxyUrl); - if(outproxyUrl.size()) { - LogPrint (eLogDebug, "HTTPProxy: use outproxy ", outproxyUrl); - if(m_ProxyURL.parse(outproxyUrl)) + if(m_OutproxyUrl.size()) { + LogPrint (eLogDebug, "HTTPProxy: use outproxy ", m_OutproxyUrl); + if(m_ProxyURL.parse(m_OutproxyUrl)) ForwardToUpstreamProxy(); else GenericProxyError("Outproxy failure", "bad outproxy settings"); @@ -379,10 +380,19 @@ namespace proxy { if (m_ProxyURL.schema == "" || m_ProxyURL.schema == "http") { // handle upstream http proxy if (!m_ProxyURL.port) m_ProxyURL.port = 80; - boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port)); - m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) { - m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1)); - })); + if (m_ProxyURL.is_i2p()) + { + m_send_buf = m_recv_buf; + GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete, + shared_from_this(), std::placeholders::_1), m_ProxyURL.host, m_ProxyURL.port); + } + else + { + boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port)); + m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) { + m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1)); + })); + } } else if (m_ProxyURL.schema == "socks") { // handle upstream socks proxy if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified @@ -572,8 +582,9 @@ namespace proxy { Done (shared_from_this()); } - HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination): - TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) + HTTPProxy::HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr localDestination): + TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), + m_OutproxyUrl(outproxy) { } diff --git a/libi2pd_client/HTTPProxy.h b/libi2pd_client/HTTPProxy.h index 29b997eb..0adb2d2e 100644 --- a/libi2pd_client/HTTPProxy.h +++ b/libi2pd_client/HTTPProxy.h @@ -6,14 +6,20 @@ namespace proxy { class HTTPProxy: public i2p::client::TCPIPAcceptor { public: - - HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination = nullptr); + HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr localDestination); + HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination = nullptr) : + HTTPProxy(address, port, "", localDestination) {} ; ~HTTPProxy() {}; + std::string GetOutproxyURL() const { return m_OutproxyUrl; } + protected: // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); const char* GetName() { return "HTTP Proxy"; } + + private: + std::string m_OutproxyUrl; }; } // http } // i2p