@ -3,6 +3,13 @@
@@ -3,6 +3,13 @@
# include <boost/lexical_cast.hpp>
# include <string>
# include <atomic>
# include <memory>
# include <set>
# include <boost/asio.hpp>
# include <mutex>
# include "I2PService.h"
# include "Destination.h"
# include "HTTPProxy.h"
# include "util.h"
# include "Identity.h"
@ -13,13 +20,12 @@
@@ -13,13 +20,12 @@
# include "I2PTunnel.h"
# include "Config.h"
# include "HTTP.h"
# include "HTTPServer.h"
namespace i2p
{
namespace proxy
{
namespace i2p {
namespace proxy {
static const size_t http_buffer_size = 8192 ;
class HTTPProxy Handler : public i2p : : client : : I2PServiceHandler , public std : : enable_shared_from_this < HTTPProxyHandler >
class HTTPReqHandler : public i2p : : client : : I2PServiceHandler , public std : : enable_shared_from_this < HTTPReqHandler >
{
private :
enum state
@ -36,7 +42,7 @@ namespace proxy
@@ -36,7 +42,7 @@ namespace proxy
void HandleSockRecv ( const boost : : system : : error_code & ecode , std : : size_t bytes_transfered ) ;
void Terminate ( ) ;
void AsyncSockRead ( ) ;
void HTTPRequestFailed ( /*std::string message*/ ) ;
void HTTPRequestFailed ( const char * message ) ;
void RedirectToJumpService ( ) ;
void ExtractRequest ( ) ;
bool IsI2PAddress ( ) ;
@ -59,26 +65,26 @@ namespace proxy
@@ -59,26 +65,26 @@ namespace proxy
public :
HTTPProxy Handler ( HTTPProxyServer * parent , std : : shared_ptr < boost : : asio : : ip : : tcp : : socket > sock ) :
HTTPReq Handler ( HTTPProxy * parent , std : : shared_ptr < boost : : asio : : ip : : tcp : : socket > sock ) :
I2PServiceHandler ( parent ) , m_sock ( sock )
{ EnterState ( GET_METHOD ) ; }
~ HTTPProxy Handler ( ) { Terminate ( ) ; }
~ HTTPReq Handler ( ) { Terminate ( ) ; }
void Handle ( ) { AsyncSockRead ( ) ; }
} ;
void HTTPProxy Handler : : AsyncSockRead ( )
void HTTPReq Handler : : AsyncSockRead ( )
{
LogPrint ( eLogDebug , " HTTPProxy: async sock read " ) ;
if ( m_sock ) {
m_sock - > async_receive ( boost : : asio : : buffer ( m_http_buff , http_buffer_size ) ,
std : : bind ( & HTTPProxy Handler : : HandleSockRecv , shared_from_this ( ) ,
std : : bind ( & HTTPReq Handler : : HandleSockRecv , shared_from_this ( ) ,
std : : placeholders : : _1 , std : : placeholders : : _2 ) ) ;
} else {
LogPrint ( eLogError , " HTTPProxy: no socket for read " ) ;
}
}
void HTTPProxy Handler : : Terminate ( ) {
void HTTPReq Handler : : Terminate ( ) {
if ( Kill ( ) ) return ;
if ( m_sock )
{
@ -91,30 +97,34 @@ namespace proxy
@@ -91,30 +97,34 @@ namespace proxy
/* All hope is lost beyond this point */
//TODO: handle this apropriately
void HTTPProxyHandler : : HTTPRequestFailed ( /*HTTPProxyHandler::errTypes error*/ )
{
static std : : string response = " HTTP/1.0 500 Internal Server Error \r \n Content-type: text/html \r \n Content-length: 0 \r \n \r \n " ;
boost : : asio : : async_write ( * m_sock , boost : : asio : : buffer ( response , response . size ( ) ) ,
std : : bind ( & HTTPProxyHandler : : SentHTTPFailed , shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
void HTTPReqHandler : : HTTPRequestFailed ( const char * message )
{
std : : size_t size = std : : strlen ( message ) ;
std : : stringstream ss ;
ss < < " HTTP/1.0 500 Internal Server Error \r \n "
< < " Content-Type: text/plain \r \n " ;
ss < < " Content-Length: " < < std : : to_string ( size + 2 ) < < " \r \n "
< < " \r \n " ; /* end of headers */
ss < < message < < " \r \n " ;
std : : string response = ss . str ( ) ;
boost : : asio : : async_write ( * m_sock , boost : : asio : : buffer ( response ) ,
std : : bind ( & HTTPReqHandler : : SentHTTPFailed , shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
}
void HTTPProxyHandler : : RedirectToJumpService ( /*HTTPProxyHandler::errTypes error*/ )
void HTTPReq Handler : : RedirectToJumpService ( /*HTTPReq Handler::errTypes error*/ )
{
std : : stringstream response ;
std : : string httpAddr ; i2p : : config : : GetOption ( " http.address " , httpAddr ) ;
uint16_t httpPort ; i2p : : config : : GetOption ( " http.port " , httpPort ) ;
response < < " HTTP/1.1 302 Found \r \n Location: http:// " < < httpAddr < < " : " < < httpPort < < " /?page=jumpservices&address= " < < m_address < < " \r \n \r \n " ;
boost : : asio : : async_write ( * m_sock , boost : : asio : : buffer ( response . str ( ) , response . str ( ) . length ( ) ) ,
std : : bind ( & HTTPProxyHandler : : SentHTTPFailed , shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
std : : stringstream ss ;
i2p : : http : : ShowJumpServices ( ss , m_address ) ;
boost : : asio : : async_write ( * m_sock , boost : : asio : : buffer ( ss . str ( ) ) ,
std : : bind ( & HTTPReqHandler : : SentHTTPFailed , shared_from_this ( ) , std : : placeholders : : _1 ) ) ;
}
void HTTPProxy Handler : : EnterState ( HTTPProxy Handler : : state nstate )
void HTTPReqHandler : : EnterState ( HTTPReqHandler : : state nstate )
{
m_state = nstate ;
}
void HTTPProxy Handler : : ExtractRequest ( )
void HTTPReq Handler : : ExtractRequest ( )
{
LogPrint ( eLogDebug , " HTTPProxy: request: " , m_method , " " , m_url ) ;
i2p : : http : : URL url ;
@ -127,18 +137,18 @@ namespace proxy
@@ -127,18 +137,18 @@ namespace proxy
LogPrint ( eLogDebug , " HTTPProxy: server: " , m_address , " , port: " , m_port , " , path: " , m_path ) ;
}
bool HTTPProxy Handler : : ValidateHTTPRequest ( )
bool HTTPReq Handler : : ValidateHTTPRequest ( )
{
if ( m_version ! = " HTTP/1.0 " & & m_version ! = " HTTP/1.1 " )
{
LogPrint ( eLogError , " HTTPProxy: unsupported version: " , m_version ) ;
HTTPRequestFailed ( ) ; //TODO: send right stuff
HTTPRequestFailed ( " unsupported HTTP version " ) ;
return false ;
}
return true ;
}
void HTTPProxy Handler : : HandleJumpServices ( )
void HTTPReq Handler : : HandleJumpServices ( )
{
static const char * helpermark1 = " ?i2paddresshelper= " ;
static const char * helpermark2 = " &i2paddresshelper= " ;
@ -170,7 +180,7 @@ namespace proxy
@@ -170,7 +180,7 @@ namespace proxy
m_path . erase ( addressHelperPos ) ;
}
bool HTTPProxy Handler : : IsI2PAddress ( )
bool HTTPReq Handler : : IsI2PAddress ( )
{
auto pos = m_address . rfind ( " .i2p " ) ;
if ( pos ! = std : : string : : npos & & ( pos + 4 ) = = m_address . length ( ) )
@ -180,7 +190,7 @@ namespace proxy
@@ -180,7 +190,7 @@ namespace proxy
return false ;
}
bool HTTPProxy Handler : : CreateHTTPRequest ( uint8_t * http_buff , std : : size_t len )
bool HTTPReq Handler : : CreateHTTPRequest ( uint8_t * http_buff , std : : size_t len )
{
ExtractRequest ( ) ; //TODO: parse earlier
if ( ! ValidateHTTPRequest ( ) ) return false ;
@ -235,7 +245,7 @@ namespace proxy
@@ -235,7 +245,7 @@ namespace proxy
return true ;
}
bool HTTPProxy Handler : : HandleData ( uint8_t * http_buff , std : : size_t len )
bool HTTPReq Handler : : HandleData ( uint8_t * http_buff , std : : size_t len )
{
while ( len > 0 )
{
@ -269,13 +279,13 @@ namespace proxy
@@ -269,13 +279,13 @@ namespace proxy
case ' \n ' : EnterState ( DONE ) ; break ;
default :
LogPrint ( eLogError , " HTTPProxy: rejected invalid request ending with: " , ( ( int ) * http_buff ) ) ;
HTTPRequestFailed ( ) ; //TODO: add correct code
HTTPRequestFailed ( " rejected invalid request " ) ;
return false ;
}
break ;
default :
LogPrint ( eLogError , " HTTPProxy: invalid state: " , m_state ) ;
HTTPRequestFailed ( ) ; //TODO: add correct code 500
HTTPRequestFailed ( " invalid parser state " ) ;
return false ;
}
http_buff + + ;
@ -286,7 +296,7 @@ namespace proxy
@@ -286,7 +296,7 @@ namespace proxy
return true ;
}
void HTTPProxy Handler : : HandleSockRecv ( const boost : : system : : error_code & ecode , std : : size_t len )
void HTTPReq Handler : : HandleSockRecv ( const boost : : system : : error_code & ecode , std : : size_t len )
{
LogPrint ( eLogDebug , " HTTPProxy: sock recv: " , len , " bytes " ) ;
if ( ecode )
@ -301,7 +311,7 @@ namespace proxy
@@ -301,7 +311,7 @@ namespace proxy
if ( m_state = = DONE )
{
LogPrint ( eLogDebug , " HTTPProxy: requested: " , m_url ) ;
GetOwner ( ) - > CreateStream ( std : : bind ( & HTTPProxy Handler : : HandleStreamRequestComplete ,
GetOwner ( ) - > CreateStream ( std : : bind ( & HTTPReq Handler : : HandleStreamRequestComplete ,
shared_from_this ( ) , std : : placeholders : : _1 ) , m_address , m_port ) ;
}
else
@ -310,14 +320,14 @@ namespace proxy
@@ -310,14 +320,14 @@ namespace proxy
}
void HTTPProxy Handler : : SentHTTPFailed ( const boost : : system : : error_code & ecode )
void HTTPReq Handler : : SentHTTPFailed ( const boost : : system : : error_code & ecode )
{
if ( ecode )
LogPrint ( eLogError , " HTTPProxy: Closing socket after sending failure because: " , ecode . message ( ) ) ;
Terminate ( ) ;
}
void HTTPProxy Handler : : HandleStreamRequestComplete ( std : : shared_ptr < i2p : : stream : : Stream > stream )
void HTTPReq Handler : : HandleStreamRequestComplete ( std : : shared_ptr < i2p : : stream : : Stream > stream )
{
if ( stream )
{
@ -331,19 +341,18 @@ namespace proxy
@@ -331,19 +341,18 @@ namespace proxy
else
{
LogPrint ( eLogError , " HTTPProxy: error when creating the stream, check the previous warnings for more info " ) ;
HTTPRequestFailed ( ) ; // TODO: Send correct error message host unreachable
HTTPRequestFailed ( " error when creating the stream, check logs " ) ;
}
}
HTTPProxyServer : : HTTPProxyServer ( const std : : string & address , int port , std : : shared_ptr < i2p : : client : : ClientDestination > localDestination ) :
HTTPProxy : : HTTPProxy ( const std : : string & address , int port , std : : shared_ptr < i2p : : client : : ClientDestination > localDestination ) :
TCPIPAcceptor ( address , port , localDestination ? localDestination : i2p : : client : : context . GetSharedLocalDestination ( ) )
{
}
std : : shared_ptr < i2p : : client : : I2PServiceHandler > HTTPProxyServer : : CreateHandler ( std : : shared_ptr < boost : : asio : : ip : : tcp : : socket > socket )
std : : shared_ptr < i2p : : client : : I2PServiceHandler > HTTPProxy : : CreateHandler ( std : : shared_ptr < boost : : asio : : ip : : tcp : : socket > socket )
{
return std : : make_shared < HTTPProxyHandler > ( this , socket ) ;
}
}
return std : : make_shared < HTTPReqHandler > ( this , socket ) ;
}
} // http
} // i2p