diff --git a/SConstruct b/SConstruct index 6371da57e..32e614c5a 100644 --- a/SConstruct +++ b/SConstruct @@ -88,7 +88,7 @@ PROTO_SRCS = env.Protoc([], 'src/ripple.proto', PROTOCOUTDIR='obj', PROTOCPYTHON env.Clean(PROTO_SRCS, 'site_scons/site_tools/protoc.pyc') # Remove unused source files. -UNUSED_SRCS = ['src/HttpReply.cpp'] +UNUSED_SRCS = [] for file in UNUSED_SRCS: NEWCOIN_SRCS.remove(file) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 7e5c58783..8fed71d8a 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1,7 +1,5 @@ #include "RPCServer.h" -#include "RequestParser.h" -#include "HttpReply.h" #include "HttpsClient.h" #include "Application.h" #include "RPC.h" @@ -22,6 +20,7 @@ #include #include #include +#include #include @@ -107,45 +106,73 @@ Json::Value RPCServer::RPCError(int iError) void RPCServer::connected() { //std::cout << "RPC request" << std::endl; - if (mSocket.remote_endpoint().address().to_string()=="127.0.0.1") mRole=ADMIN; - else mRole=GUEST; + if (mSocket.remote_endpoint().address().to_string()=="127.0.0.1") mRole = ADMIN; + else mRole = GUEST; - mSocket.async_read_some(boost::asio::buffer(mReadBuffer), - boost::bind(&RPCServer::Shandle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); + boost::asio::async_read_until(mSocket, mLineBuffer, "\r\n", + boost::bind(&RPCServer::handle_read_line, shared_from_this(), boost::asio::placeholders::error)); } -void RPCServer::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) +void RPCServer::handle_read_req(const boost::system::error_code& e) { - if (!e) + std::string req; + + if (mLineBuffer.size()) { - boost::tribool result; - result = mRequestParser.parse( - mIncomingRequest, mReadBuffer.data(), mReadBuffer.data() + bytes_transferred); + req.assign(boost::asio::buffer_cast(mLineBuffer.data()), mLineBuffer.size()); + mLineBuffer.consume(mLineBuffer.size()); + } - if (result) + req += strCopy(mQueryVec); + mReplyStr = handleRequest(req); + boost::asio::async_write(mSocket, boost::asio::buffer(mReplyStr), + boost::bind(&RPCServer::handle_write, shared_from_this(), boost::asio::placeholders::error)); +} + +void RPCServer::handle_read_line(const boost::system::error_code& e) +{ + if (e) + return; + + HTTPRequestAction action = mHTTPRequest.consume(mLineBuffer); + + if (action == haDO_REQUEST) + { // request with no body + cLog(lsWARNING) << "RPC HTTP request with no body"; + boost::system::error_code ignore_ec; + mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_ec); + return; + } + else if (action == haREAD_LINE) + { + boost::asio::async_read_until(mSocket, mLineBuffer, "\r\n", + boost::bind(&RPCServer::handle_read_line, shared_from_this(), + boost::asio::placeholders::error)); + } + else if (action == haREAD_RAW) + { + int rLen = mHTTPRequest.getDataSize(); + assert(rLen > 0); + + int alreadyHave = mLineBuffer.size(); + + if (alreadyHave < rLen) { - mReplyStr = handleRequest(mIncomingRequest.mBody); - - sendReply(); - } - else if (!result) - { // bad request - std::cout << "bad request: " << mIncomingRequest.mBody <= 1); - BOOST_FOREACH(HttpHeader& h, mIncomingRequest.headers) - { - if (boost::iequals(h.name, "connection")) - { - if (boost::iequals(h.value, "keep-alive")) - keep_alive = true; - if (boost::iequals(h.value, "close")) - keep_alive = false; - } - } - if (keep_alive) - { - mIncomingRequest.method.clear(); - mIncomingRequest.uri.clear(); - mIncomingRequest.mBody.clear(); - mIncomingRequest.headers.clear(); - mRequestParser.reset(); - mSocket.async_read_some(boost::asio::buffer(mReadBuffer), - boost::bind(&RPCServer::Shandle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else + HTTPRequestAction action = mHTTPRequest.requestDone(false); + if (action == haCLOSE_CONN) { boost::system::error_code ignored_ec; mSocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); } + else + { + boost::asio::async_read_until(mSocket, mLineBuffer, "\r\n", + boost::bind(&RPCServer::handle_read_line, shared_from_this(), boost::asio::placeholders::error)); + } } if (e != boost::asio::error::operation_aborted) diff --git a/src/RPCServer.h b/src/RPCServer.h index 8997707d1..7d7695599 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -8,8 +8,7 @@ #include "../json/value.h" -#include "HttpRequest.h" -#include "RequestParser.h" +#include "HTTPRequest.h" #include "NewcoinAddress.h" #include "NetworkOPs.h" #include "SerializedLedger.h" @@ -91,11 +90,12 @@ private: NetworkOPs* mNetOps; boost::asio::ip::tcp::socket mSocket; - boost::array mReadBuffer; + + boost::asio::streambuf mLineBuffer; + std::vector mQueryVec; std::string mReplyStr; - HttpRequest mIncomingRequest; - HttpRequestParser mRequestParser; + HTTPRequest mHTTPRequest; enum { GUEST, USER, ADMIN }; int mRole; @@ -106,15 +106,10 @@ private: RPCServer& operator=(const RPCServer&); // no implementation void handle_write(const boost::system::error_code& ec); - static void Shandle_write(pointer This, const boost::system::error_code& ec) - { This->handle_write(ec); } - - void handle_read(const boost::system::error_code& ec, std::size_t bytes_transferred); - static void Shandle_read(pointer This, const boost::system::error_code& ec, std::size_t bytes_transferred) - { This->handle_read(ec, bytes_transferred); } + void handle_read_line(const boost::system::error_code& ec); + void handle_read_req(const boost::system::error_code& ec); std::string handleRequest(const std::string& requestStr); - void sendReply(); Json::Value doCommand(const std::string& command, Json::Value& params); int getParamCount(const Json::Value& params);