int ReadHTTP (std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet, std::string& strMessageRet) { mapHeadersRet.clear (); strMessageRet = ""; // Read status int nStatus = ReadHTTPStatus (stream); // Read header int nLen = ReadHTTPHeader (stream, mapHeadersRet); if (nLen < 0 || nLen > gMaxHTTPHeaderSize) return 500; // Read message if (nLen > 0) { std::vector<char> vch (nLen); stream.read (&vch[0], nLen); strMessageRet = std::string (vch.begin (), vch.end ()); } return nStatus; }
json_spirit::Object CallRPC(const std::string& strMethod, const json_spirit::Array& params) { if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") throw std::runtime_error(strprintf( _("You must set rpcpassword=<password> in the configuration file:\n%s\n" "If the file does not exist, create it with owner-readable-only file permissions."), GetConfigFile().string().c_str())); // Connect to localhost bool fUseSSL = GetBoolArg("-rpcssl", false); boost::asio::io_service io_service; boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23); context.set_options(boost::asio::ssl::context::no_sslv2); boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslStream(io_service, context); SSLIOStreamDevice<boost::asio::ip::tcp> d(sslStream, fUseSSL); boost::iostreams::stream< SSLIOStreamDevice<boost::asio::ip::tcp> > stream(d); bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started do { bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))); if (fConnected) break; if (fWait) MilliSleep(1000); else throw std::runtime_error("couldn't connect to server"); } while (fWait); // HTTP basic authentication std::string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); std::map<std::string, std::string> mapRequestHeaders; mapRequestHeaders["Authorization"] = std::string("Basic ") + strUserPass64; // Send request std::string strRequest = JSONRPCRequest(strMethod, params, 1); std::string strPost = HTTPPost(strRequest, mapRequestHeaders); stream << strPost << std::flush; // Receive HTTP reply status int nProto = 0; int nStatus = ReadHTTPStatus(stream, nProto); // Receive HTTP reply message headers and body std::map<std::string, std::string> mapHeaders; std::string strReply; ReadHTTPMessage(stream, mapHeaders, strReply, nProto); if (nStatus == HTTP_UNAUTHORIZED) throw std::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) throw std::runtime_error(strprintf("server returned HTTP error %d", nStatus)); else if (strReply.empty()) throw std::runtime_error("no response from server"); // Parse reply json_spirit::Value valReply; if (!read_string(strReply, valReply)) throw std::runtime_error("couldn't parse reply from server"); const json_spirit::Object& reply = valReply.get_obj(); if (reply.empty()) throw std::runtime_error("expected reply to have result, error and id properties"); return reply; }