Merge pull request #4640

733177e Remove size limit in RPC client, keep it in server (Wladimir J. van der Laan)
e17151a Avoid a copy in RPC output (Wladimir J. van der Laan)
This commit is contained in:
Wladimir J. van der Laan 2014-08-07 10:39:19 +02:00
commit 0b588168ab
No known key found for this signature in database
GPG key ID: 74810B012346C9A6
4 changed files with 23 additions and 14 deletions

View file

@ -126,7 +126,7 @@ Object CallRPC(const string& strMethod, const Array& params)
// Receive HTTP reply message headers and body // Receive HTTP reply message headers and body
map<string, string> mapHeaders; map<string, string> mapHeaders;
string strReply; string strReply;
ReadHTTPMessage(stream, mapHeaders, strReply, nProto); ReadHTTPMessage(stream, mapHeaders, strReply, nProto, std::numeric_limits<size_t>::max());
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)");

View file

@ -93,8 +93,7 @@ string HTTPError(int nStatus, bool keepalive, bool headersOnly)
headersOnly, "text/plain"); headersOnly, "text/plain");
} }
string HTTPReply(int nStatus, const string& strMsg, bool keepalive, string HTTPReplyHeader(int nStatus, bool keepalive, size_t contentLength, const char *contentType)
bool headersOnly, const char *contentType)
{ {
return strprintf( return strprintf(
"HTTP/1.1 %d %s\r\n" "HTTP/1.1 %d %s\r\n"
@ -103,17 +102,25 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
"Content-Length: %u\r\n" "Content-Length: %u\r\n"
"Content-Type: %s\r\n" "Content-Type: %s\r\n"
"Server: bitcoin-json-rpc/%s\r\n" "Server: bitcoin-json-rpc/%s\r\n"
"\r\n" "\r\n",
"%s",
nStatus, nStatus,
httpStatusDescription(nStatus), httpStatusDescription(nStatus),
rfc1123Time(), rfc1123Time(),
keepalive ? "keep-alive" : "close", keepalive ? "keep-alive" : "close",
(headersOnly ? 0 : strMsg.size()), contentLength,
contentType, contentType,
FormatFullVersion(), FormatFullVersion());
(headersOnly ? "" : strMsg.c_str()) }
);
string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
bool headersOnly, const char *contentType)
{
if (headersOnly)
{
return HTTPReplyHeader(nStatus, keepalive, 0, contentType);
} else {
return HTTPReplyHeader(nStatus, keepalive, strMsg.size(), contentType) + strMsg;
}
} }
bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto, bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
@ -194,14 +201,14 @@ int ReadHTTPHeaders(std::basic_istream<char>& stream, map<string, string>& mapHe
int ReadHTTPMessage(std::basic_istream<char>& stream, map<string, int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
string>& mapHeadersRet, string& strMessageRet, string>& mapHeadersRet, string& strMessageRet,
int nProto) int nProto, size_t max_size)
{ {
mapHeadersRet.clear(); mapHeadersRet.clear();
strMessageRet = ""; strMessageRet = "";
// Read header // Read header
int nLen = ReadHTTPHeaders(stream, mapHeadersRet); int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
if (nLen < 0 || nLen > (int)MAX_SIZE) if (nLen < 0 || (size_t)nLen > max_size)
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
// Read message // Read message

View file

@ -143,6 +143,8 @@ private:
std::string HTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders); std::string HTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
std::string HTTPError(int nStatus, bool keepalive, std::string HTTPError(int nStatus, bool keepalive,
bool headerOnly = false); bool headerOnly = false);
std::string HTTPReplyHeader(int nStatus, bool keepalive, size_t contentLength,
const char *contentType = "application/json");
std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive, std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive,
bool headerOnly = false, bool headerOnly = false,
const char *contentType = "application/json"); const char *contentType = "application/json");
@ -151,7 +153,7 @@ bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto); int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto);
int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet); int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet);
int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet, int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet,
std::string& strMessageRet, int nProto); std::string& strMessageRet, int nProto, size_t max_size);
std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id); std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id);
json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id); json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id); std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);

View file

@ -862,7 +862,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
else else
throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error"); throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << std::flush; conn->stream() << HTTPReplyHeader(HTTP_OK, fRun, strReply.size()) << strReply << std::flush;
} }
catch (Object& objError) catch (Object& objError)
{ {
@ -891,7 +891,7 @@ void ServiceConnection(AcceptedConnection *conn)
break; break;
// Read HTTP message headers and body // Read HTTP message headers and body
ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto); ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto, MAX_SIZE);
// HTTP Keep-Alive is false; close connection immediately // HTTP Keep-Alive is false; close connection immediately
if (mapHeaders["connection"] == "close") if (mapHeaders["connection"] == "close")