@ -360,6 +360,41 @@ static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
@@ -360,6 +360,41 @@ static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
strMsg . c_str ( ) ) ;
}
bool ReadHTTPRequestLine ( std : : basic_istream < char > & stream , int & proto ,
string & http_method , string & http_uri )
{
string str ;
getline ( stream , str ) ;
// HTTP request line is space-delimited
vector < string > vWords ;
boost : : split ( vWords , str , boost : : is_any_of ( " " ) ) ;
if ( vWords . size ( ) < 2 )
return false ;
// HTTP methods permitted: GET, POST
http_method = vWords [ 0 ] ;
if ( http_method ! = " GET " & & http_method ! = " POST " )
return false ;
// HTTP URI must be an absolute path, relative to current host
http_uri = vWords [ 1 ] ;
if ( http_uri . size ( ) = = 0 | | http_uri [ 0 ] ! = ' / ' )
return false ;
// parse proto, if present
string strProto = " " ;
if ( vWords . size ( ) > 2 )
strProto = vWords [ 2 ] ;
proto = 0 ;
const char * ver = strstr ( strProto . c_str ( ) , " HTTP/1. " ) ;
if ( ver ! = NULL )
proto = atoi ( ver + 7 ) ;
return true ;
}
int ReadHTTPStatus ( std : : basic_istream < char > & stream , int & proto )
{
string str ;
@ -375,7 +410,7 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
@@ -375,7 +410,7 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
return atoi ( vWords [ 1 ] . c_str ( ) ) ;
}
int ReadHTTPHeader ( std : : basic_istream < char > & stream , map < string , string > & mapHeadersRet )
int ReadHTTPHeaders ( std : : basic_istream < char > & stream , map < string , string > & mapHeadersRet )
{
int nLen = 0 ;
loop
@ -400,17 +435,15 @@ int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHea
@@ -400,17 +435,15 @@ int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHea
return nLen ;
}
int ReadHTTP ( std : : basic_istream < char > & stream , map < string , string > & mapHeadersRet , string & strMessageRet )
int ReadHTTPMessage ( std : : basic_istream < char > & stream , map < string ,
string > & mapHeadersRet , string & strMessageRet ,
int nProto )
{
mapHeadersRet . clear ( ) ;
strMessageRet = " " ;
// Read status
int nProto = 0 ;
int nStatus = ReadHTTPStatus ( stream , nProto ) ;
// Read header
int nLen = ReadHTTPHeader ( stream , mapHeadersRet ) ;
int nLen = ReadHTTPHeaders ( stream , mapHeadersRet ) ;
if ( nLen < 0 | | nLen > ( int ) MAX_SIZE )
return HTTP_INTERNAL_SERVER_ERROR ;
@ -432,7 +465,7 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
@@ -432,7 +465,7 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
mapHeadersRet [ " connection " ] = " close " ;
}
return nStatus ;
return HTTP_OK ;
}
bool HTTPAuthorized ( map < string , string > & mapHeaders )
@ -939,10 +972,17 @@ void ThreadRPCServer3(void* parg)
@@ -939,10 +972,17 @@ void ThreadRPCServer3(void* parg)
}
return ;
}
int nProto = 0 ;
map < string , string > mapHeaders ;
string strRequest ;
string strRequest , strMethod , strURI ;
// Read HTTP request line
if ( ! ReadHTTPRequestLine ( conn - > stream ( ) , nProto , strMethod , strURI ) )
break ;
ReadHTTP ( conn - > stream ( ) , mapHeaders , strRequest ) ;
// Read HTTP message headers and body
ReadHTTPMessage ( conn - > stream ( ) , mapHeaders , strRequest , nProto ) ;
// Check authorization
if ( mapHeaders . count ( " authorization " ) = = 0 )
@ -1074,10 +1114,15 @@ Object CallRPC(const string& strMethod, const Array& params)
@@ -1074,10 +1114,15 @@ Object CallRPC(const string& strMethod, const Array& params)
string strPost = HTTPPost ( strRequest , mapRequestHeaders ) ;
stream < < strPost < < std : : flush ;
// Receive reply
// Receive HTTP reply status
int nProto = 0 ;
int nStatus = ReadHTTPStatus ( stream , nProto ) ;
// Receive HTTP reply message headers and body
map < string , string > mapHeaders ;
string strReply ;
int nStatus = ReadHTTP ( stream , mapHeaders , strReply ) ;
ReadHTTPMessage ( stream , mapHeaders , strReply , nProto ) ;
if ( nStatus = = HTTP_UNAUTHORIZED )
throw runtime_error ( " incorrect rpcuser or rpcpassword (authorization failed) " ) ;
else if ( nStatus > = 400 & & nStatus ! = HTTP_BAD_REQUEST & & nStatus ! = HTTP_NOT_FOUND & & nStatus ! = HTTP_INTERNAL_SERVER_ERROR )