aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@bitpay.com>2014-06-04 11:38:33 -0400
committerJeff Garzik <jgarzik@bitpay.com>2014-06-26 23:32:18 -0400
commit854d013012c2d457d5296227d212b053cbea5239 (patch)
treef383d7d138a65d988ba158fe11671a2e64a15cbe /src
parentc912e22db08d0a44ad6fd027c09bbdf79c34dbbc (diff)
RPC code movement: separate out JSON-RPC execution logic from HTTP server logic
Diffstat (limited to 'src')
-rw-r--r--src/rpcserver.cpp129
1 files changed, 72 insertions, 57 deletions
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index b85b17c812..49bc05e5d6 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -809,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;
@@ -825,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;
}
}