@ -393,16 +393,6 @@ bool ClientAllowed(const boost::asio::ip::address& address)
return false ;
}
class AcceptedConnection
{
public :
virtual ~ AcceptedConnection ( ) { }
virtual std : : iostream & stream ( ) = 0 ;
virtual std : : string peer_address_to_string ( ) const = 0 ;
virtual void close ( ) = 0 ;
} ;
template < typename Protocol >
class AcceptedConnectionImpl : public AcceptedConnection
{
@ -819,6 +809,71 @@ static string JSONRPCExecBatch(const Array& vReq)
return write_string ( Value ( ret ) , false ) + " \n " ;
}
static bool HTTPReq_JSONRPC ( AcceptedConnection * conn ,
string & strRequest ,
map < string , string > & mapHeaders ,
bool fRun )
{
// Check authorization
if ( mapHeaders . count ( " authorization " ) = = 0 )
{
conn - > stream ( ) < < HTTPReply ( HTTP_UNAUTHORIZED , " " , false ) < < std : : flush ;
return false ;
}
if ( ! HTTPAuthorized ( mapHeaders ) )
{
LogPrintf ( " ThreadRPCServer incorrect password attempt from %s \n " , conn - > peer_address_to_string ( ) ) ;
/* Deter brute-forcing short passwords.
If this results in a DoS the user really
shouldn ' t have their RPC port exposed . */
if ( mapArgs [ " -rpcpassword " ] . size ( ) < 20 )
MilliSleep ( 250 ) ;
conn - > stream ( ) < < HTTPReply ( HTTP_UNAUTHORIZED , " " , false ) < < std : : flush ;
return false ;
}
JSONRequest jreq ;
try
{
// Parse request
Value valRequest ;
if ( ! read_string ( strRequest , valRequest ) )
throw JSONRPCError ( RPC_PARSE_ERROR , " Parse error " ) ;
string strReply ;
// singleton request
if ( valRequest . type ( ) = = obj_type ) {
jreq . parse ( valRequest ) ;
Value result = tableRPC . execute ( jreq . strMethod , jreq . params ) ;
// Send reply
strReply = JSONRPCReply ( result , Value : : null , jreq . id ) ;
// array of requests
} else if ( valRequest . type ( ) = = array_type )
strReply = JSONRPCExecBatch ( valRequest . get_array ( ) ) ;
else
throw JSONRPCError ( RPC_PARSE_ERROR , " Top-level object parse error " ) ;
conn - > stream ( ) < < HTTPReply ( HTTP_OK , strReply , fRun ) < < std : : flush ;
}
catch ( Object & objError )
{
ErrorReply ( conn - > stream ( ) , objError , jreq . id ) ;
return false ;
}
catch ( std : : exception & e )
{
ErrorReply ( conn - > stream ( ) , JSONRPCError ( RPC_PARSE_ERROR , e . what ( ) ) , jreq . id ) ;
return false ;
}
return true ;
}
void ServiceConnection ( AcceptedConnection * conn )
{
bool fRun = true ;
@ -835,67 +890,17 @@ void ServiceConnection(AcceptedConnection *conn)
// Read HTTP message headers and body
ReadHTTPMessage ( conn - > stream ( ) , mapHeaders , strRequest , nProto ) ;
if ( strURI ! = " / " ) {
conn - > stream ( ) < < HTTPReply ( HTTP_NOT_FOUND , " " , false ) < < std : : flush ;
break ;
}
// Check authorization
if ( mapHeaders . count ( " authorization " ) = = 0 )
{
conn - > stream ( ) < < HTTPReply ( HTTP_UNAUTHORIZED , " " , false ) < < std : : flush ;
break ;
}
if ( ! HTTPAuthorized ( mapHeaders ) )
{
LogPrintf ( " ThreadRPCServer incorrect password attempt from %s \n " , conn - > peer_address_to_string ( ) ) ;
/* Deter brute-forcing short passwords.
If this results in a DoS the user really
shouldn ' t have their RPC port exposed . */
if ( mapArgs [ " -rpcpassword " ] . size ( ) < 20 )
MilliSleep ( 250 ) ;
conn - > stream ( ) < < HTTPReply ( HTTP_UNAUTHORIZED , " " , false ) < < std : : flush ;
break ;
}
// HTTP Keep-Alive is false; close connection immediately
if ( mapHeaders [ " connection " ] = = " close " )
fRun = false ;
JSONRequest jreq ;
try
{
// Parse request
Value valRequest ;
if ( ! read_string ( strRequest , valRequest ) )
throw JSONRPCError ( RPC_PARSE_ERROR , " Parse error " ) ;
string strReply ;
// singleton request
if ( valRequest . type ( ) = = obj_type ) {
jreq . parse ( valRequest ) ;
Value result = tableRPC . execute ( jreq . strMethod , jreq . params ) ;
// Send reply
strReply = JSONRPCReply ( result , Value : : null , jreq . id ) ;
// array of requests
} else if ( valRequest . type ( ) = = array_type )
strReply = JSONRPCExecBatch ( valRequest . get_array ( ) ) ;
else
throw JSONRPCError ( RPC_PARSE_ERROR , " Top-level object parse error " ) ;
conn - > stream ( ) < < HTTPReply ( HTTP_OK , strReply , fRun ) < < std : : flush ;
}
catch ( Object & objError )
{
ErrorReply ( conn - > stream ( ) , objError , jreq . id ) ;
break ;
if ( strURI = = " / " ) {
if ( ! HTTPReq_JSONRPC ( conn , strRequest , mapHeaders , fRun ) )
break ;
}
catch ( std : : exception & e )
{
ErrorReply( conn- > stream ( ) , JSONRPCError ( RPC_PARSE_ERROR , e . what ( ) ) , jreq . id ) ;
else {
conn - > stream ( ) < < HTTPReply ( HTTP_NOT_FOUND , " " , false ) < < std : : flush ;
break ;
}
}