aboutsummaryrefslogtreecommitdiff
path: root/src/bitcoinrpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bitcoinrpc.cpp')
-rw-r--r--src/bitcoinrpc.cpp80
1 files changed, 60 insertions, 20 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 21e37c75e1..8c04f577d1 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -11,7 +11,6 @@
#include "bitcoinrpc.h"
#include "db.h"
-#undef printf
#include <boost/asio.hpp>
#include <boost/asio/ip/v6_only.hpp>
#include <boost/bind.hpp>
@@ -26,8 +25,6 @@
#include <boost/shared_ptr.hpp>
#include <list>
-#define printf OutputDebugStringF
-
using namespace std;
using namespace boost;
using namespace boost::asio;
@@ -179,14 +176,12 @@ Value help(const Array& params, bool fHelp)
Value stop(const Array& params, bool fHelp)
{
+ // Accept the deprecated and ignored 'detach´ boolean argument
if (fHelp || params.size() > 1)
throw runtime_error(
- "stop <detach>\n"
- "<detach> is true or false to detach the database or not for this stop only\n"
- "Stop Bitcoin server (and possibly override the detachdb config value).");
+ "stop\n"
+ "Stop Bitcoin server.");
// Shutdown will take long enough that the response should get back
- if (params.size() > 0)
- bitdb.SetDetach(params[0].get_bool());
StartShutdown();
return "Bitcoin server stopping";
}
@@ -362,6 +357,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;
@@ -377,7 +407,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
@@ -402,17 +432,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;
@@ -434,7 +462,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)
@@ -941,10 +969,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)
@@ -1076,10 +1111,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)