|
|
@ -360,6 +360,41 @@ static string HTTPReply(int nStatus, const string& strMsg, bool keepalive) |
|
|
|
strMsg.c_str()); |
|
|
|
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) |
|
|
|
int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto) |
|
|
|
{ |
|
|
|
{ |
|
|
|
string str; |
|
|
|
string str; |
|
|
@ -375,7 +410,7 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto) |
|
|
|
return atoi(vWords[1].c_str()); |
|
|
|
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; |
|
|
|
int nLen = 0; |
|
|
|
loop |
|
|
|
loop |
|
|
@ -400,17 +435,15 @@ int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHea |
|
|
|
return nLen; |
|
|
|
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(); |
|
|
|
mapHeadersRet.clear(); |
|
|
|
strMessageRet = ""; |
|
|
|
strMessageRet = ""; |
|
|
|
|
|
|
|
|
|
|
|
// Read status
|
|
|
|
|
|
|
|
int nProto = 0; |
|
|
|
|
|
|
|
int nStatus = ReadHTTPStatus(stream, nProto); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Read header
|
|
|
|
// Read header
|
|
|
|
int nLen = ReadHTTPHeader(stream, mapHeadersRet); |
|
|
|
int nLen = ReadHTTPHeaders(stream, mapHeadersRet); |
|
|
|
if (nLen < 0 || nLen > (int)MAX_SIZE) |
|
|
|
if (nLen < 0 || nLen > (int)MAX_SIZE) |
|
|
|
return HTTP_INTERNAL_SERVER_ERROR; |
|
|
|
return HTTP_INTERNAL_SERVER_ERROR; |
|
|
|
|
|
|
|
|
|
|
@ -432,7 +465,7 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe |
|
|
|
mapHeadersRet["connection"] = "close"; |
|
|
|
mapHeadersRet["connection"] = "close"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nStatus; |
|
|
|
return HTTP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool HTTPAuthorized(map<string, string>& mapHeaders) |
|
|
|
bool HTTPAuthorized(map<string, string>& mapHeaders) |
|
|
@ -939,10 +972,17 @@ void ThreadRPCServer3(void* parg) |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int nProto = 0; |
|
|
|
map<string, string> mapHeaders; |
|
|
|
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
|
|
|
|
// Check authorization
|
|
|
|
if (mapHeaders.count("authorization") == 0) |
|
|
|
if (mapHeaders.count("authorization") == 0) |
|
|
@ -1074,10 +1114,15 @@ Object CallRPC(const string& strMethod, const Array& params) |
|
|
|
string strPost = HTTPPost(strRequest, mapRequestHeaders); |
|
|
|
string strPost = HTTPPost(strRequest, mapRequestHeaders); |
|
|
|
stream << strPost << std::flush; |
|
|
|
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; |
|
|
|
map<string, string> mapHeaders; |
|
|
|
string strReply; |
|
|
|
string strReply; |
|
|
|
int nStatus = ReadHTTP(stream, mapHeaders, strReply); |
|
|
|
ReadHTTPMessage(stream, mapHeaders, strReply, nProto); |
|
|
|
|
|
|
|
|
|
|
|
if (nStatus == HTTP_UNAUTHORIZED) |
|
|
|
if (nStatus == HTTP_UNAUTHORIZED) |
|
|
|
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); |
|
|
|
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) |
|
|
|
else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) |
|
|
|