@ -28,6 +28,7 @@
# include "I2PTunnel.h"
# include "I2PTunnel.h"
# include "Config.h"
# include "Config.h"
# include "HTTP.h"
# include "HTTP.h"
# include "I18N.h"
namespace i2p {
namespace i2p {
namespace proxy {
namespace proxy {
@ -71,8 +72,8 @@ namespace proxy {
void SentHTTPFailed ( const boost : : system : : error_code & ecode ) ;
void SentHTTPFailed ( const boost : : system : : error_code & ecode ) ;
void HandleStreamRequestComplete ( std : : shared_ptr < i2p : : stream : : Stream > stream ) ;
void HandleStreamRequestComplete ( std : : shared_ptr < i2p : : stream : : Stream > stream ) ;
/* error helpers */
/* error helpers */
void GenericProxyError ( const char * title , const char * description ) ;
void GenericProxyError ( const std : : string & title , const std : : string & description ) ;
void GenericProxyInfo ( const char * title , const char * description ) ;
void GenericProxyInfo ( const std : : string & title , const std : : string & description ) ;
void HostNotFound ( std : : string & host ) ;
void HostNotFound ( std : : string & host ) ;
void SendProxyError ( std : : string & content ) ;
void SendProxyError ( std : : string & content ) ;
@ -151,17 +152,17 @@ namespace proxy {
Done ( shared_from_this ( ) ) ;
Done ( shared_from_this ( ) ) ;
}
}
void HTTPReqHandler : : GenericProxyError ( const char * title , const char * description ) {
void HTTPReqHandler : : GenericProxyError ( const std : : string & title , const std : : string & description ) {
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " <h1>Proxy error: " < < title < < " </h1> \r \n " ;
ss < < " <h1> " < < tr ( " Proxy error " ) < < " : " < < title < < " </h1> \r \n " ;
ss < < " <p> " < < description < < " </p> \r \n " ;
ss < < " <p> " < < description < < " </p> \r \n " ;
std : : string content = ss . str ( ) ;
std : : string content = ss . str ( ) ;
SendProxyError ( content ) ;
SendProxyError ( content ) ;
}
}
void HTTPReqHandler : : GenericProxyInfo ( const char * title , const char * description ) {
void HTTPReqHandler : : GenericProxyInfo ( const std : : string & title , const std : : string & description ) {
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " <h1>Proxy info: " < < title < < " </h1> \r \n " ;
ss < < " <h1> " < < tr ( " Proxy info " ) < < " : " < < title < < " </h1> \r \n " ;
ss < < " <p> " < < description < < " </p> \r \n " ;
ss < < " <p> " < < description < < " </p> \r \n " ;
std : : string content = ss . str ( ) ;
std : : string content = ss . str ( ) ;
SendProxyError ( content ) ;
SendProxyError ( content ) ;
@ -169,9 +170,9 @@ namespace proxy {
void HTTPReqHandler : : HostNotFound ( std : : string & host ) {
void HTTPReqHandler : : HostNotFound ( std : : string & host ) {
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " <h1>Proxy error: Host not found</h1> \r \n "
ss < < " <h1> " < < tr ( " Proxy error: Host not found " ) < < " </h1> \r \n "
< < " <p>Remote host not found in router's addressbook</p> \r \n "
< < " <p> " < < tr ( " Remote host not found in router's addressbook " ) < < " </p> \r \n "
< < " <p>You may try to find this host on jump services below:</p> \r \n "
< < " <p> " < < tr ( " You may try to find this host on jump services below " ) < < " :</p> \r \n "
< < " <ul> \r \n " ;
< < " <ul> \r \n " ;
for ( const auto & js : jumpservices ) {
for ( const auto & js : jumpservices ) {
ss < < " <li><a href= \" " < < js . second < < host < < " \" > " < < js . first < < " </a></li> \r \n " ;
ss < < " <li><a href= \" " < < js . second < < host < < " \" > " < < js . first < < " </a></li> \r \n " ;
@ -216,7 +217,7 @@ namespace proxy {
b64 = i2p : : http : : UrlDecode ( value ) ;
b64 = i2p : : http : : UrlDecode ( value ) ;
// if we need update exists, request formed with update param
// if we need update exists, request formed with update param
if ( params [ " update " ] = = " true " ) { len + = std : : strlen ( " &update=true " ) ; confirm = true ; }
if ( params [ " update " ] = = " true " ) { len + = std : : strlen ( " &update=true " ) ; confirm = true ; }
url . query . replace ( pos , len , " " ) ;
url . query . replace ( pos - 1 , len + 1 , " " ) ; // +-1 for taking ? and & before parameter
return true ;
return true ;
}
}
@ -268,7 +269,7 @@ namespace proxy {
if ( m_req_len < 0 ) {
if ( m_req_len < 0 ) {
LogPrint ( eLogError , " HTTPProxy: unable to parse request " ) ;
LogPrint ( eLogError , " HTTPProxy: unable to parse request " ) ;
GenericProxyError ( " Invalid request " , " Proxy unable to parse your request " ) ;
GenericProxyError ( tr ( " Invalid request " ) , tr ( " Proxy unable to parse your request " ) ) ;
return true ; /* parse error */
return true ; /* parse error */
}
}
@ -283,7 +284,7 @@ namespace proxy {
if ( ! m_Addresshelper )
if ( ! m_Addresshelper )
{
{
LogPrint ( eLogWarning , " HTTPProxy: addresshelper request rejected " ) ;
LogPrint ( eLogWarning , " HTTPProxy: addresshelper request rejected " ) ;
GenericProxyError ( " Invalid request " , " addresshelper is not supported " ) ;
GenericProxyError ( tr ( " Invalid request " ) , tr ( " addresshelper is not supported " ) ) ;
return true ;
return true ;
}
}
if ( ! i2p : : client : : context . GetAddressBook ( ) . FindAddress ( m_RequestURL . host ) | | m_Confirm )
if ( ! i2p : : client : : context . GetAddressBook ( ) . FindAddress ( m_RequestURL . host ) | | m_Confirm )
@ -292,17 +293,19 @@ namespace proxy {
LogPrint ( eLogInfo , " HTTPProxy: added address from addresshelper for " , m_RequestURL . host ) ;
LogPrint ( eLogInfo , " HTTPProxy: added address from addresshelper for " , m_RequestURL . host ) ;
std : : string full_url = m_RequestURL . to_string ( ) ;
std : : string full_url = m_RequestURL . to_string ( ) ;
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " Host " < < m_RequestURL . host < < " added to router's addressbook from helper. "
ss < < tr ( " Host " ) < < " " < < m_RequestURL . host < < " " < < tr ( " added to router's addressbook from helper " ) < < " . " ;
< < " Click <a href= \" " < < full_url < < " \" >here</a> to proceed. " ;
ss < < tr ( " Click " ) < < " <a href= \" " < < full_url < < " \" > " < < tr ( " here " ) < < " </a> " < < tr ( " to proceed " ) < < " . " ;
GenericProxyInfo ( " Addresshelper found " , ss . str ( ) . c_ str( ) ) ;
GenericProxyInfo ( tr ( " Addresshelper found " ) , ss . str ( ) ) ;
return true ; /* request processed */
return true ; /* request processed */
}
}
else
else
{
{
std : : string full_url = m_RequestURL . to_string ( ) ;
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " Host " < < m_RequestURL . host < < " <font color=red>already in router's addressbook</font>. "
ss < < tr ( " Host " ) < < " " < < m_RequestURL . host < < " <font color=red> " < < tr ( " already in router's addressbook " ) < < " </font>. " ;
< < " Click <a href= \" " < < m_RequestURL . query < < " ?i2paddresshelper= " < < jump < < " &update=true \" >here</a> to update record. " ;
ss < < tr ( " Click " ) < < " <a href= \" " < < full_url < < ( full_url . find ( ' ? ' ) ! = std : : string : : npos ? " &i2paddresshelper= " : " ?i2paddresshelper= " ) ;
GenericProxyInfo ( " Addresshelper found " , ss . str ( ) . c_str ( ) ) ;
ss < < jump < < " &update=true \" > " < < tr ( " here " ) < < " </a> " < < tr ( " to update record " ) < < " . " ;
GenericProxyInfo ( tr ( " Addresshelper found " ) , ss . str ( ) ) ;
return true ; /* request processed */
return true ; /* request processed */
}
}
}
}
@ -315,7 +318,7 @@ namespace proxy {
auto pos = uri . find ( " : " ) ;
auto pos = uri . find ( " : " ) ;
if ( pos = = std : : string : : npos | | pos = = uri . size ( ) - 1 )
if ( pos = = std : : string : : npos | | pos = = uri . size ( ) - 1 )
{
{
GenericProxyError ( " Invalid Request " , " invalid request uri " ) ;
GenericProxyError ( tr ( " Invalid Request " ) , tr ( " invalid request uri " ) ) ;
return true ;
return true ;
}
}
else
else
@ -358,7 +361,7 @@ namespace proxy {
else
else
{
{
/* relative url and missing 'Host' header */
/* relative url and missing 'Host' header */
GenericProxyError ( " Invalid request " , " Can't detect destination host from request " ) ;
GenericProxyError ( tr ( " Invalid request " ) , tr ( " Can't detect destination host from request " ) ) ;
return true ;
return true ;
}
}
}
}
@ -375,11 +378,11 @@ namespace proxy {
if ( m_ProxyURL . parse ( m_OutproxyUrl ) )
if ( m_ProxyURL . parse ( m_OutproxyUrl ) )
ForwardToUpstreamProxy ( ) ;
ForwardToUpstreamProxy ( ) ;
else
else
GenericProxyError ( " Outproxy failure " , " bad outproxy settings " ) ;
GenericProxyError ( tr ( " Outproxy failure " ) , tr ( " bad outproxy settings " ) ) ;
} else {
} else {
LogPrint ( eLogWarning , " HTTPProxy: outproxy failure for " , dest_host , " : no outproxy enabled " ) ;
LogPrint ( eLogWarning , " HTTPProxy: outproxy failure for " , dest_host , " : no outproxy enabled " ) ;
std : : string message = " Host " + dest_host + " not inside I2P network, but outproxy is not enabled " ;
std : : stringstream ss ; ss < < tr ( " Host " ) < < " " < < dest_host < < " " < < tr ( " not inside I2P network, but outproxy is not enabled " ) ;
GenericProxyError ( " Outproxy failure " , me ssage . c_ str( ) ) ;
GenericProxyError ( tr ( " Outproxy failure " ) , ss . str ( ) ) ;
}
}
return true ;
return true ;
}
}
@ -467,13 +470,13 @@ namespace proxy {
else
else
{
{
// unknown type, complain
// unknown type, complain
GenericProxyError ( " unknown outproxy url " , m_ProxyURL . to_string ( ) . c_str ( ) ) ;
GenericProxyError ( tr ( " unknown outproxy url " ) , m_ProxyURL . to_string ( ) ) ;
}
}
}
}
void HTTPReqHandler : : HandleUpstreamProxyResolved ( const boost : : system : : error_code & ec , boost : : asio : : ip : : tcp : : resolver : : iterator it , ProxyResolvedHandler handler )
void HTTPReqHandler : : HandleUpstreamProxyResolved ( const boost : : system : : error_code & ec , boost : : asio : : ip : : tcp : : resolver : : iterator it , ProxyResolvedHandler handler )
{
{
if ( ec ) GenericProxyError ( " cannot resolve upstream proxy " , ec . message ( ) . c_str ( ) ) ;
if ( ec ) GenericProxyError ( tr ( " cannot resolve upstream proxy " ) , ec . message ( ) ) ;
else handler ( * it ) ;
else handler ( * it ) ;
}
}
@ -481,7 +484,7 @@ namespace proxy {
{
{
if ( ! ec ) {
if ( ! ec ) {
if ( m_RequestURL . host . size ( ) > 255 ) {
if ( m_RequestURL . host . size ( ) > 255 ) {
GenericProxyError ( " hostname too long " , m_RequestURL . host . c_str ( ) ) ;
GenericProxyError ( tr ( " hostname too long " ) , m_RequestURL . host ) ;
return ;
return ;
}
}
uint16_t port = m_RequestURL . port ;
uint16_t port = m_RequestURL . port ;
@ -508,13 +511,13 @@ namespace proxy {
reqsize + = host . size ( ) ;
reqsize + = host . size ( ) ;
m_socks_buf [ + + reqsize ] = 0 ;
m_socks_buf [ + + reqsize ] = 0 ;
boost : : asio : : async_write ( * m_proxysock , boost : : asio : : buffer ( m_socks_buf , reqsize ) , boost : : asio : : transfer_all ( ) , std : : bind ( & HTTPReqHandler : : HandleSocksProxySendHandshake , this , std : : placeholders : : _1 , std : : placeholders : : _2 ) ) ;
boost : : asio : : async_write ( * m_proxysock , boost : : asio : : buffer ( m_socks_buf , reqsize ) , boost : : asio : : transfer_all ( ) , std : : bind ( & HTTPReqHandler : : HandleSocksProxySendHandshake , this , std : : placeholders : : _1 , std : : placeholders : : _2 ) ) ;
} else GenericProxyError ( " cannot connect to upstream socks proxy " , ec . message ( ) . c_str ( ) ) ;
} else GenericProxyError ( tr ( " cannot connect to upstream socks proxy " ) , ec . message ( ) ) ;
}
}
void HTTPReqHandler : : HandleSocksProxySendHandshake ( const boost : : system : : error_code & ec , std : : size_t bytes_transferred )
void HTTPReqHandler : : HandleSocksProxySendHandshake ( const boost : : system : : error_code & ec , std : : size_t bytes_transferred )
{
{
LogPrint ( eLogDebug , " HTTPProxy: upstream socks handshake sent " ) ;
LogPrint ( eLogDebug , " HTTPProxy: upstream socks handshake sent " ) ;
if ( ec ) GenericProxyError ( " Cannot negotiate with socks proxy " , ec . message ( ) . c_str ( ) ) ;
if ( ec ) GenericProxyError ( tr ( " Cannot negotiate with socks proxy " ) , ec . message ( ) ) ;
else m_proxysock - > async_read_some ( boost : : asio : : buffer ( m_socks_buf , 8 ) , std : : bind ( & HTTPReqHandler : : HandleSocksProxyReply , this , std : : placeholders : : _1 , std : : placeholders : : _2 ) ) ;
else m_proxysock - > async_read_some ( boost : : asio : : buffer ( m_socks_buf , 8 ) , std : : bind ( & HTTPReqHandler : : HandleSocksProxyReply , this , std : : placeholders : : _1 , std : : placeholders : : _2 ) ) ;
}
}
@ -556,7 +559,7 @@ namespace proxy {
}
}
else
else
{
{
GenericProxyError ( " CONNECT error " , " Failed to Connect " ) ;
GenericProxyError ( tr ( " CONNECT error " ) , tr ( " Failed to Connect " ) ) ;
}
}
}
}
@ -567,7 +570,7 @@ namespace proxy {
m_send_buf = m_ClientResponse . to_string ( ) ;
m_send_buf = m_ClientResponse . to_string ( ) ;
boost : : asio : : async_write ( * m_sock , boost : : asio : : buffer ( m_send_buf ) , boost : : asio : : transfer_all ( ) , [ & ] ( const boost : : system : : error_code & ec , std : : size_t transferred )
boost : : asio : : async_write ( * m_sock , boost : : asio : : buffer ( m_send_buf ) , boost : : asio : : transfer_all ( ) , [ & ] ( const boost : : system : : error_code & ec , std : : size_t transferred )
{
{
if ( ec ) GenericProxyError ( " socks proxy error " , ec . message ( ) . c_str ( ) ) ;
if ( ec ) GenericProxyError ( tr ( " socks proxy error " ) , ec . message ( ) ) ;
else HandoverToUpstreamProxy ( ) ;
else HandoverToUpstreamProxy ( ) ;
} ) ;
} ) ;
} else {
} else {
@ -575,7 +578,7 @@ namespace proxy {
LogPrint ( eLogDebug , " HTTPProxy: send " , m_send_buf . size ( ) , " bytes " ) ;
LogPrint ( eLogDebug , " HTTPProxy: send " , m_send_buf . size ( ) , " bytes " ) ;
boost : : asio : : async_write ( * m_proxysock , boost : : asio : : buffer ( m_send_buf ) , boost : : asio : : transfer_all ( ) , [ & ] ( const boost : : system : : error_code & ec , std : : size_t transferred )
boost : : asio : : async_write ( * m_proxysock , boost : : asio : : buffer ( m_send_buf ) , boost : : asio : : transfer_all ( ) , [ & ] ( const boost : : system : : error_code & ec , std : : size_t transferred )
{
{
if ( ec ) GenericProxyError ( " failed to send request to upstream " , ec . message ( ) . c_str ( ) ) ;
if ( ec ) GenericProxyError ( tr ( " failed to send request to upstream " ) , ec . message ( ) ) ;
else HandoverToUpstreamProxy ( ) ;
else HandoverToUpstreamProxy ( ) ;
} ) ;
} ) ;
}
}
@ -593,18 +596,18 @@ namespace proxy {
ss < < " error code: " ;
ss < < " error code: " ;
ss < < ( int ) m_socks_buf [ 1 ] ;
ss < < ( int ) m_socks_buf [ 1 ] ;
std : : string msg = ss . str ( ) ;
std : : string msg = ss . str ( ) ;
GenericProxyError ( " Socks Proxy error " , msg . c_str ( ) ) ;
GenericProxyError ( tr ( " socks proxy error " ) , msg ) ;
}
}
}
}
else GenericProxyError ( " No Reply From socks proxy " , ec . message ( ) . c_str ( ) ) ;
else GenericProxyError ( tr ( " No Reply From socks proxy " ) , ec . message ( ) ) ;
}
}
void HTTPReqHandler : : HandleUpstreamHTTPProxyConnect ( const boost : : system : : error_code & ec )
void HTTPReqHandler : : HandleUpstreamHTTPProxyConnect ( const boost : : system : : error_code & ec )
{
{
if ( ! ec ) {
if ( ! ec ) {
LogPrint ( eLogDebug , " HTTPProxy: connected to http upstream " ) ;
LogPrint ( eLogDebug , " HTTPProxy: connected to http upstream " ) ;
GenericProxyError ( " cannot connect " , " http out proxy not implemented " ) ;
GenericProxyError ( tr ( " cannot connect " ) , tr ( " http out proxy not implemented " ) ) ;
} else GenericProxyError ( " cannot connect to upstream http proxy " , ec . message ( ) . c_str ( ) ) ;
} else GenericProxyError ( tr ( " cannot connect to upstream http proxy " ) , ec . message ( ) ) ;
}
}
/* will be called after some data received from client */
/* will be called after some data received from client */
@ -637,7 +640,7 @@ namespace proxy {
{
{
if ( ! stream ) {
if ( ! stream ) {
LogPrint ( eLogError , " HTTPProxy: error when creating the stream, check the previous warnings for more info " ) ;
LogPrint ( eLogError , " HTTPProxy: error when creating the stream, check the previous warnings for more info " ) ;
GenericProxyError ( " Host is down " , " Can't create connection to requested host, it may be down. Please try again later. " ) ;
GenericProxyError ( tr ( " Host is down " ) , tr ( " Can't create connection to requested host, it may be down. Please try again later. " ) ) ;
return ;
return ;
}
}
if ( Kill ( ) )
if ( Kill ( ) )