Skip to content

Commit

Permalink
Avoid a copy in RPC output
Browse files Browse the repository at this point in the history
Split up HTTPReply into HTTPReply and HTTPReplyHeader, so that
the message data can be streamed directly.

Also removes a c_str(), which would have prevented binary
output with NUL characters in it.
  • Loading branch information
laanwj committed Aug 6, 2014
1 parent 5e94d00 commit e17151a
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 9 deletions.
23 changes: 15 additions & 8 deletions src/rpcprotocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ string HTTPError(int nStatus, bool keepalive, bool headersOnly)
headersOnly, "text/plain");
}

string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
bool headersOnly, const char *contentType)
string HTTPReplyHeader(int nStatus, bool keepalive, size_t contentLength, const char *contentType)
{
return strprintf(
"HTTP/1.1 %d %s\r\n"
Expand All @@ -103,17 +102,25 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
"Content-Length: %u\r\n"
"Content-Type: %s\r\n"
"Server: bitcoin-json-rpc/%s\r\n"
"\r\n"
"%s",
"\r\n",
nStatus,
httpStatusDescription(nStatus),
rfc1123Time(),
keepalive ? "keep-alive" : "close",
(headersOnly ? 0 : strMsg.size()),
contentLength,
contentType,
FormatFullVersion(),
(headersOnly ? "" : strMsg.c_str())
);
FormatFullVersion());
}

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,
Expand Down
2 changes: 2 additions & 0 deletions src/rpcprotocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ class SSLIOStreamDevice : public boost::iostreams::device<boost::iostreams::bidi
std::string HTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
std::string HTTPError(int nStatus, bool keepalive,
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,
bool headerOnly = false,
const char *contentType = "application/json");
Expand Down
2 changes: 1 addition & 1 deletion src/rpcserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
else
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)
{
Expand Down

0 comments on commit e17151a

Please sign in to comment.