Merge branch 'autoclient'

This commit is contained in:
Arthur Britto
2013-02-01 19:30:36 -08:00
16 changed files with 506 additions and 321 deletions

View File

@@ -1056,7 +1056,6 @@ STAmount STAmount::setRate(uint64 rate)
// <-- saTakerGot: Actual
// <-- saTakerIssuerFee: Actual
// <-- saOfferIssuerFee: Actual
// <-- bRemove: remove offer it is either fullfilled or unfunded
bool STAmount::applyOffer(
const uint32 uTakerPaysRate, const uint32 uOfferPaysRate,
const STAmount& saOfferRate,

View File

@@ -67,6 +67,18 @@ public:
std::swap(mSecure, s.mSecure);
}
boost::system::error_code verify(const std::string& strDomain)
{
boost::system::error_code ec;
mSocket->set_verify_mode(boost::asio::ssl::verify_peer);
// XXX Verify semantics of RFC 2818 are what we want.
mSocket->set_verify_callback(boost::asio::ssl::rfc2818_verification(strDomain), ec);
return ec;
}
void async_handshake(handshake_type type, callback cbFunc)
{
if ((type == ssl_socket::client) || (mSecure))
@@ -140,7 +152,6 @@ public:
boost::asio::async_write(PlainSocket(), buffers, handler);
}
template <typename Allocator, typename Handler>
void async_write(boost::asio::basic_streambuf<Allocator>& buffers, Handler handler)
{
@@ -150,7 +161,6 @@ public:
boost::asio::async_write(PlainSocket(), buffers, handler);
}
template <typename Buf, typename Condition, typename Handler>
void async_read(const Buf& buffers, Condition cond, Handler handler)
{

View File

@@ -3,6 +3,8 @@
#include <cstdlib>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/algorithm/string.hpp>
@@ -573,6 +575,12 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
return (this->*(commandsA[i].pfpFunc))(jvParams);
}
// Place the async result somewhere useful.
void callRPCHandler(Json::Value* jvOutput, const Json::Value& jvInput)
{
(*jvOutput) = jvInput;
}
int commandLineRPC(const std::vector<std::string>& vCmd)
{
Json::Value jvOutput;
@@ -615,16 +623,21 @@ int commandLineRPC(const std::vector<std::string>& vCmd)
if (!theConfig.RPC_ADMIN_PASSWORD.empty())
jvRequest["admin_password"] = theConfig.RPC_ADMIN_PASSWORD;
jvOutput = callRPC(
theConfig.RPC_IP,
theConfig.RPC_PORT,
theConfig.RPC_USER,
theConfig.RPC_PASSWORD,
boost::asio::io_service isService;
callRPC(
isService,
theConfig.RPC_IP, theConfig.RPC_PORT,
theConfig.RPC_USER, theConfig.RPC_PASSWORD,
"",
jvRequest.isMember("method") // Allow parser to rewrite method.
? jvRequest["method"].asString()
: vCmd[0],
jvParams); // Parsed, execute.
jvParams, // Parsed, execute.
false,
boost::bind(callRPCHandler, &jvOutput, _1));
isService.run(); // This blocks until there is no more outstanding async calls.
if (jvOutput.isMember("result"))
{
@@ -681,7 +694,67 @@ int commandLineRPC(const std::vector<std::string>& vCmd)
return nRet;
}
Json::Value callRPC(const std::string& strIp, const int iPort, const std::string& strUsername, const std::string& strPassword, const std::string& strPath, const std::string& strMethod, const Json::Value& jvParams)
#define RPC_NOTIFY_MAX_BYTES 8192
#define RPC_NOTIFY_SECONDS 10
bool responseRPC(
boost::function<void(const Json::Value& jvInput)> callbackFuncP,
const boost::system::error_code& ecResult, int iStatus, const std::string& strData)
{
if (callbackFuncP)
{
// Only care about the result, if we care to deliver it callbackFuncP.
// Receive reply
if (iStatus == 401)
throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
else if ((iStatus >= 400) && (iStatus != 400) && (iStatus != 404) && (iStatus != 500)) // ?
throw std::runtime_error(strprintf("server returned HTTP error %d", iStatus));
else if (strData.empty())
throw std::runtime_error("no response from server");
// Parse reply
cLog(lsDEBUG) << "RPC reply: " << strData << std::endl;
Json::Reader reader;
Json::Value jvReply;
if (!reader.parse(strData, jvReply))
throw std::runtime_error("couldn't parse reply from server");
if (jvReply.isNull())
throw std::runtime_error("expected reply to have result, error and id properties");
Json::Value jvResult(Json::objectValue);
jvResult["result"] = jvReply;
(callbackFuncP)(jvResult);
}
return false;
}
// Build the request.
void requestRPC(const std::string& strMethod, const Json::Value& jvParams, const std::map<std::string, std::string>& mHeaders, const std::string& strPath, boost::asio::streambuf& sb, const std::string& strHost)
{
std::ostream osRequest(&sb);
osRequest <<
createHTTPPost(
strHost,
strPath,
JSONRPCRequest(strMethod, jvParams, Json::Value(1)),
mHeaders);
}
void callRPC(
boost::asio::io_service& io_service,
const std::string& strIp, const int iPort,
const std::string& strUsername, const std::string& strPassword,
const std::string& strPath, const std::string& strMethod,
const Json::Value& jvParams, const bool bSSL,
boost::function<void(const Json::Value& jvInput)> callbackFuncP)
{
// Connect to localhost
if (!theConfig.QUIET)
@@ -692,55 +765,31 @@ Json::Value callRPC(const std::string& strIp, const int iPort, const std::string
// std::cerr << "Method: " << strMethod << std::endl;
}
boost::asio::ip::tcp::endpoint
endpoint(boost::asio::ip::address::from_string(strIp), iPort);
boost::asio::ip::tcp::iostream stream;
stream.connect(endpoint);
if (stream.fail())
throw std::runtime_error("couldn't connect to server");
// cLog(lsDEBUG) << "connected" << std::endl;
// HTTP basic authentication
std::string strUserPass64 = EncodeBase64(strUsername + ":" + strPassword);
std::map<std::string, std::string> mapRequestHeaders;
mapRequestHeaders["Authorization"] = std::string("Basic ") + strUserPass64;
// Log(lsDEBUG) << "requesting" << std::endl;
// Send request
std::string strRequest = JSONRPCRequest(strMethod, jvParams, Json::Value(1));
// Log(lsDEBUG) << "requesting" << std::endl;
// cLog(lsDEBUG) << "send request " << strMethod << " : " << strRequest << std::endl;
std::string strPost = createHTTPPost(strPath, strRequest, mapRequestHeaders);
stream << strPost << std::flush;
// std::cerr << "post " << strPost << std::endl;
// Receive reply
std::map<std::string, std::string> mapHeaders;
std::string strReply;
int nStatus = ReadHTTP(stream, mapHeaders, strReply);
if (nStatus == 401)
throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
else if ((nStatus >= 400) && (nStatus != 400) && (nStatus != 404) && (nStatus != 500)) // ?
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
cLog(lsDEBUG) << "RPC reply: " << strReply << std::endl;
Json::Reader reader;
Json::Value valReply;
if (!reader.parse(strReply, valReply))
throw std::runtime_error("couldn't parse reply from server");
if (valReply.isNull())
throw std::runtime_error("expected reply to have result, error and id properties");
return valReply;
HttpsClient::httpsRequest(
bSSL,
io_service,
strIp,
iPort,
boost::bind(
&requestRPC,
strMethod,
jvParams,
mapRequestHeaders,
"/", _1, _2),
RPC_NOTIFY_MAX_BYTES,
boost::posix_time::seconds(RPC_NOTIFY_SECONDS),
boost::bind(&responseRPC, callbackFuncP, _1, _2, _3));
}
// vim:ts=4

View File

@@ -48,8 +48,14 @@ public:
};
extern int commandLineRPC(const std::vector<std::string>& vCmd);
extern Json::Value callRPC(const std::string& strIp, const int iPort, const std::string& strUsername, const std::string& strPassword, const std::string& strPath, const std::string& strMethod, const Json::Value& params);
extern void callRPC(
boost::asio::io_service& io_service,
const std::string& strIp, const int iPort,
const std::string& strUsername, const std::string& strPassword,
const std::string& strPath, const std::string& strMethod,
const Json::Value& jvParams, const bool bSSL,
boost::function<void(const Json::Value& jvInput)> callbackFuncP = 0);
#endif
// vim:ts=4

View File

@@ -134,26 +134,31 @@ void Config::setup(const std::string& strConf, bool bTestNet, bool bQuiet)
if (strXdgConfigHome.empty())
{
// $XDG_CONFIG_HOME was not set, use default based on $HOME.
strXdgConfigHome = str(boost::format("%s/.config") % strHome);
strXdgConfigHome = boost::str(boost::format("%s/.config") % strHome);
}
if (strXdgDataHome.empty())
{
// $XDG_DATA_HOME was not set, use default based on $HOME.
strXdgDataHome = str(boost::format("%s/.local/share") % strHome);
strXdgDataHome = boost::str(boost::format("%s/.local/share") % strHome);
}
CONFIG_DIR = str(boost::format("%s/" SYSTEM_NAME) % strXdgConfigHome);
CONFIG_DIR = boost::str(boost::format("%s/" SYSTEM_NAME) % strXdgConfigHome);
CONFIG_FILE = CONFIG_DIR / strConfFile;
DATA_DIR = str(boost::format("%s/" SYSTEM_NAME) % strXdgDataHome);
DATA_DIR = boost::str(boost::format("%s/" SYSTEM_NAME) % strXdgDataHome);
boost::filesystem::create_directories(CONFIG_DIR, ec);
if (ec)
throw std::runtime_error(str(boost::format("Can not create %s") % CONFIG_DIR));
throw std::runtime_error(boost::str(boost::format("Can not create %s") % CONFIG_DIR));
}
}
SSL_CONTEXT.set_default_verify_paths(ec);
if (ec)
throw std::runtime_error(boost::str(boost::format("Failed to set_default_verify_paths: %s") % ec.message()));
// Update default values
load();
@@ -164,10 +169,11 @@ void Config::setup(const std::string& strConf, bool bTestNet, bool bQuiet)
boost::filesystem::create_directories(DATA_DIR, ec);
if (ec)
throw std::runtime_error(str(boost::format("Can not create %s") % DATA_DIR));
throw std::runtime_error(boost::str(boost::format("Can not create %s") % DATA_DIR));
}
Config::Config()
: SSL_CONTEXT(boost::asio::ssl::context::sslv23)
{
//
// Defaults

View File

@@ -2,6 +2,8 @@
#define __CONFIG__
#include <string>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/filesystem.hpp>
#include "types.h"
@@ -29,7 +31,7 @@
#define VALIDATORS_FILE_NAME "validators.txt"
const int DOMAIN_BYTES_MAX = 256;
const int PUBLIC_BYTES_MAX = 2048; // Maximum bytes for an account public key.
const int PUBLIC_BYTES_MAX = 33; // Maximum bytes for an account public key.
const int SYSTEM_PEER_PORT = 6561;
const int SYSTEM_WEBSOCKET_PORT = 6562;
@@ -167,6 +169,8 @@ public:
uint32 SIGN_VALIDATION;
uint32 SIGN_PROPOSAL;
boost::asio::ssl::context SSL_CONTEXT; // Generic SSL context.
Config();
int getSize(SizedItemName);

View File

@@ -12,73 +12,100 @@
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/system/error_code.hpp>
#include "Config.h"
#include "Log.h"
SETUP_LOG();
using namespace boost::system;
using namespace boost::asio;
HttpsClient::HttpsClient(
boost::asio::io_service& io_service,
const unsigned short port,
const std::string& strPath,
std::size_t responseMax
) :
mCtx(boost::asio::ssl::context::sslv23),
mSocket(io_service, theConfig.SSL_CONTEXT),
mResolver(io_service),
mSocketSsl(io_service, mCtx),
mResponse(responseMax),
mStrPath(strPath),
mPort(port),
mDeadline(io_service)
{
}
void HttpsClient::httpsGet(
std::deque<std::string> deqSites,
boost::posix_time::time_duration timeout,
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
void HttpsClient::makeGet(const std::string& strPath, boost::asio::streambuf& sb, const std::string& strHost)
{
std::ostream osRequest(&sb);
osRequest <<
"GET " << strPath << " HTTP/1.0\r\n"
"Host: " << strHost << "\r\n"
"Accept: */*\r\n" // YYY Do we need this line?
"Connection: close\r\n\r\n";
}
void HttpsClient::httpsRequest(
bool bSSL,
std::deque<std::string> deqSites,
boost::function<void(boost::asio::streambuf& sb, const std::string& strHost)> build,
boost::posix_time::time_duration timeout,
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete)
{
mSSL = bSSL;
mDeqSites = deqSites;
mBuild = build;
mComplete = complete;
mTimeout = timeout;
httpsNext();
}
void HttpsClient::httpsGet(
bool bSSL,
std::deque<std::string> deqSites,
const std::string& strPath,
boost::posix_time::time_duration timeout,
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) {
mComplete = complete;
mTimeout = timeout;
httpsRequest(
bSSL,
deqSites,
boost::bind(&HttpsClient::makeGet, shared_from_this(), strPath, _1, _2),
timeout,
complete);
}
void HttpsClient::httpsNext()
{
// std::cerr << "Fetch: " << mDeqSites[0] << std::endl;
cLog(lsTRACE) << "Fetch: " << mDeqSites[0];
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> query(new boost::asio::ip::tcp::resolver::query(mDeqSites[0], boost::lexical_cast<std::string>(mPort),
ip::resolver_query_base::numeric_service|ip::resolver_query_base::numeric_service));
ip::resolver_query_base::numeric_service));
mQuery = query;
mCtx.set_default_verify_paths(mShutdown);
if (mShutdown)
{
std::cerr << "set_default_verify_paths: " << mShutdown.message() << std::endl;
}
mDeadline.expires_from_now(mTimeout, mShutdown);
if (!mShutdown)
{
mDeadline.expires_from_now(mTimeout, mShutdown);
// std::cerr << "expires_from_now: " << mShutdown.message() << std::endl;
}
cLog(lsTRACE) << "expires_from_now: " << mShutdown.message();
if (!mShutdown)
{
mDeadline.async_wait(
boost::bind(
&HttpsClient::ShandleDeadline,
&HttpsClient::handleDeadline,
shared_from_this(),
boost::asio::placeholders::error));
}
if (!mShutdown)
{
// std::cerr << "Resolving: " << mDeqSites[0] << std::endl;
cLog(lsTRACE) << "Resolving: " << mDeqSites[0];
mResolver.async_resolve(*mQuery,
boost::bind(
&HttpsClient::ShandleResolve,
&HttpsClient::handleResolve,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
@@ -93,22 +120,20 @@ void HttpsClient::handleDeadline(const boost::system::error_code& ecResult)
if (ecResult == boost::asio::error::operation_aborted)
{
// Timer canceled because deadline no longer needed.
// std::cerr << "Deadline cancelled." << std::endl;
cLog(lsTRACE) << "Deadline cancelled.";
nothing(); // Aborter is done.
}
else if (ecResult)
{
std::cerr << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message() << std::endl;
cLog(lsTRACE) << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message();
// Can't do anything sound.
abort();
}
else
{
boost::system::error_code ec_shutdown;
std::cerr << "Deadline arrived." << std::endl;
cLog(lsTRACE) << "Deadline arrived.";
// Mark us as shutting down.
// XXX Use our own error code.
@@ -118,15 +143,24 @@ void HttpsClient::handleDeadline(const boost::system::error_code& ecResult)
mResolver.cancel();
// Stop the transaction.
mSocketSsl.shutdown(ec_shutdown);
mSocket.async_shutdown(boost::bind(
&HttpsClient::handleShutdown,
shared_from_this(),
boost::asio::placeholders::error));
if (ec_shutdown)
{
std::cerr << "Shutdown error: " << mDeqSites[0] << ": " << ec_shutdown.message() << std::endl;
}
}
}
void HttpsClient::handleShutdown(
const boost::system::error_code& ecResult
)
{
if (ecResult)
{
cLog(lsTRACE) << "Shutdown error: " << mDeqSites[0] << ": " << ecResult.message();
}
}
void HttpsClient::handleResolve(
const boost::system::error_code& ecResult,
boost::asio::ip::tcp::resolver::iterator itrEndpoint
@@ -137,19 +171,19 @@ void HttpsClient::handleResolve(
if (mShutdown)
{
// std::cerr << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message() << std::endl;
cLog(lsTRACE) << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message();
invokeComplete(mShutdown);
}
else
else
{
// std::cerr << "Resolve complete." << std::endl;
cLog(lsTRACE) << "Resolve complete.";
boost::asio::async_connect(
mSocketSsl.lowest_layer(),
mSocket.lowest_layer(),
itrEndpoint,
boost::bind(
&HttpsClient::ShandleConnect,
&HttpsClient::handleConnect,
shared_from_this(),
boost::asio::placeholders::error));
}
@@ -162,35 +196,38 @@ void HttpsClient::handleConnect(const boost::system::error_code& ecResult)
if (mShutdown)
{
std::cerr << "Connect error: " << mShutdown.message() << std::endl;
cLog(lsTRACE) << "Connect error: " << mShutdown.message();
}
if (!mShutdown)
{
// std::cerr << "Connected." << std::endl;
cLog(lsTRACE) << "Connected.";
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_peer);
// XXX Verify semantics of RFC 2818 are what we want.
mSocketSsl.set_verify_callback(boost::asio::ssl::rfc2818_verification(mDeqSites[0]), mShutdown);
mShutdown = mSocket.verify(mDeqSites[0]);
if (mShutdown)
{
std::cerr << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message() << std::endl;
cLog(lsTRACE) << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message();
}
}
if (!mShutdown)
{
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::client,
boost::bind(&HttpsClient::ShandleRequest,
shared_from_this(),
boost::asio::placeholders::error));
}
else
if (mShutdown)
{
invokeComplete(mShutdown);
}
else if (mSSL)
{
mSocket.async_handshake(
AutoSocket::ssl_socket::client,
boost::bind(
&HttpsClient::handleRequest,
shared_from_this(),
boost::asio::placeholders::error));
}
else
{
handleRequest(ecResult);
}
}
void HttpsClient::handleRequest(const boost::system::error_code& ecResult)
@@ -200,64 +237,58 @@ void HttpsClient::handleRequest(const boost::system::error_code& ecResult)
if (mShutdown)
{
std::cerr << "Handshake error:" << mShutdown.message() << std::endl;
cLog(lsTRACE) << "Handshake error:" << mShutdown.message();
invokeComplete(mShutdown);
}
else
{
// std::cerr << "SSL session started." << std::endl;
cLog(lsTRACE) << "Session started.";
std::ostream osRequest(&mRequest);
mBuild(mRequest, mDeqSites[0]);
osRequest <<
"GET " << mStrPath << " HTTP/1.0\r\n"
"Host: " << mDeqSites[0] << "\r\n"
"Accept: */*\r\n" // YYY Do we need this line?
"Connection: close\r\n\r\n";
boost::asio::async_write(
mSocketSsl,
mSocket.async_write(
mRequest,
boost::bind(&HttpsClient::ShandleWrite,
boost::bind(&HttpsClient::handleWrite,
shared_from_this(),
boost::asio::placeholders::error));
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
void HttpsClient::handleWrite(const boost::system::error_code& ecResult)
void HttpsClient::handleWrite(const boost::system::error_code& ecResult, std::size_t bytes_transferred)
{
if (!mShutdown)
mShutdown = ecResult;
if (mShutdown)
{
std::cerr << "Write error: " << mShutdown.message() << std::endl;
cLog(lsTRACE) << "Write error: " << mShutdown.message();
invokeComplete(mShutdown);
}
else
{
// std::cerr << "Wrote." << std::endl;
cLog(lsTRACE) << "Wrote.";
boost::asio::async_read(
mSocketSsl,
mSocket.async_read(
mResponse,
boost::asio::transfer_all(),
boost::bind(&HttpsClient::ShandleData,
boost::bind(&HttpsClient::handleData,
shared_from_this(),
boost::asio::placeholders::error));
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
void HttpsClient::handleData(const boost::system::error_code& ecResult)
void HttpsClient::handleData(const boost::system::error_code& ecResult, std::size_t bytes_transferred)
{
if (!mShutdown)
mShutdown = ecResult;
if (mShutdown && mShutdown != boost::asio::error::eof)
{
std::cerr << "Read error: " << mShutdown.message() << std::endl;
cLog(lsTRACE) << "Read error: " << mShutdown.message();
invokeComplete(mShutdown);
}
@@ -265,13 +296,14 @@ void HttpsClient::handleData(const boost::system::error_code& ecResult)
{
if (mShutdown)
{
// std::cerr << "Complete." << std::endl;
cLog(lsTRACE) << "Complete.";
nothing();
}
else
{
// XXX According to boost example code, this is what we should expect for success.
std::cerr << "Complete, no eof." << std::endl;
cLog(lsTRACE) << "Complete, no eof.";
}
parseData();
@@ -279,7 +311,7 @@ void HttpsClient::handleData(const boost::system::error_code& ecResult)
}
// Call cancel the deadline timer and invoke the completion routine.
void HttpsClient::invokeComplete(const boost::system::error_code& ecResult, std::string strData)
void HttpsClient::invokeComplete(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)
{
boost::system::error_code ecCancel;
@@ -287,16 +319,22 @@ void HttpsClient::invokeComplete(const boost::system::error_code& ecResult, std:
if (ecCancel)
{
std::cerr << "Deadline cancel error: " << ecCancel.message() << std::endl;
cLog(lsTRACE) << "Deadline cancel error: " << ecCancel.message();
}
mDeqSites.pop_front();
if (mDeqSites.empty())
bool bAgain = true;
if (mDeqSites.empty() || !ecResult)
{
mComplete(ecResult ? ecResult : ecCancel, strData);
// ecResult: !0 = had an error, last entry
// iStatus: result, if no error
// strData: data, if no error
bAgain = mComplete && mComplete(ecResult ? ecResult : ecCancel, iStatus, strData);
}
else
if (!mDeqSites.empty() && bAgain)
{
httpsNext();
}
@@ -309,21 +347,21 @@ void HttpsClient::parseData()
static boost::regex reStatus("\\`HTTP/1\\S+ (\\d{3}) .*\\'"); // HTTP/1.1 200 OK
static boost::regex reBody("\\`(?:.*?\\r\\n\\r\\n){1}(.*)\\'");
boost::smatch smMatch;
boost::smatch smStatus;
boost::smatch smBody;
bool bMatch = boost::regex_match(strData, smMatch, reStatus) // Match status code.
&& !smMatch[1].compare("200")
&& boost::regex_match(strData, smMatch, reBody); // Match body.
bool bMatch = boost::regex_match(strData, smStatus, reStatus) // Match status code.
&& boost::regex_match(strData, smBody, reBody); // Match body.
// std::cerr << "Data:" << strData << std::endl;
// std::cerr << "Match: " << bMatch << std::endl;
// std::cerr << "Body:" << smMatch[1] << std::endl;
// std::cerr << "Body:" << smBody[1] << std::endl;
if (bMatch)
{
boost::system::error_code noErr;
invokeComplete(noErr, smMatch[1]);
invokeComplete(noErr, lexical_cast_st<int>(smStatus[1]), smBody[1]);
}
else
{
@@ -333,33 +371,52 @@ void HttpsClient::parseData()
}
void HttpsClient::httpsGet(
bool bSSL,
boost::asio::io_service& io_service,
std::deque<std::string> deqSites,
const unsigned short port,
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) {
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, strPath, responseMax));
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, responseMax));
client->httpsGet(deqSites, timeout, complete);
client->httpsGet(bSSL, deqSites, strPath, timeout, complete);
}
void HttpsClient::httpsGet(
bool bSSL,
boost::asio::io_service& io_service,
std::string strSite,
const unsigned short port,
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) {
std::deque<std::string> deqSites(1, strSite);
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, strPath, responseMax));
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, responseMax));
client->httpsGet(deqSites, timeout, complete);
client->httpsGet(bSSL, deqSites, strPath, timeout, complete);
}
void HttpsClient::httpsRequest(
bool bSSL,
boost::asio::io_service& io_service,
std::string strSite,
const unsigned short port,
boost::function<void(boost::asio::streambuf& sb, const std::string& strHost)> setRequest,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) {
std::deque<std::string> deqSites(1, strSite);
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, responseMax));
client->httpsRequest(bSSL, deqSites, setRequest, timeout, complete);
}
// vim:ts=4

View File

@@ -11,6 +11,7 @@
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include "AutoSocket.h"
//
// Async https client.
@@ -21,15 +22,15 @@ class HttpsClient : public boost::enable_shared_from_this<HttpsClient>
private:
typedef boost::shared_ptr<HttpsClient> pointer;
boost::asio::ssl::context mCtx;
bool mSSL;
AutoSocket mSocket;
boost::asio::ip::tcp::resolver mResolver;
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> mQuery;
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> mSocketSsl;
boost::asio::streambuf mRequest;
boost::asio::streambuf mResponse;
const std::string mStrPath;
const unsigned short mPort;
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> mComplete;
boost::function<void(boost::asio::streambuf& sb, const std::string& strHost)> mBuild;
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> mComplete;
boost::asio::deadline_timer mDeadline;
@@ -40,65 +41,76 @@ private:
boost::posix_time::time_duration mTimeout;
void handleDeadline(const boost::system::error_code& ecResult);
static void ShandleDeadline(pointer This, const boost::system::error_code& ecResult)
{ This->handleDeadline(ecResult); }
void handleResolve(const boost::system::error_code& ecResult, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
static void ShandleResolve(pointer This, const boost::system::error_code& ecResult, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
{ This->handleResolve(ecResult, endpoint_iterator); }
void handleConnect(const boost::system::error_code& ecResult);
static void ShandleConnect(pointer This, const boost::system::error_code& ecResult)
{ This->handleConnect(ecResult); }
void handleRequest(const boost::system::error_code& ecResult);
static void ShandleRequest(pointer This, const boost::system::error_code& ecResult)
{ This->handleRequest(ecResult); }
void handleWrite(const boost::system::error_code& ecResult);
static void ShandleWrite(pointer This, const boost::system::error_code& ecResult)
{ This->handleWrite(ecResult); }
void handleWrite(const boost::system::error_code& ecResult, std::size_t bytes_transferred);
void handleData(const boost::system::error_code& ecResult);
static void ShandleData(pointer This, const boost::system::error_code& ecResult)
{ This->handleData(ecResult); }
void handleData(const boost::system::error_code& ecResult, std::size_t bytes_transferred);
void handleShutdown(const boost::system::error_code& ecResult);
void parseData();
void httpsNext();
void invokeComplete(const boost::system::error_code& ecResult, std::string strData = "");
void invokeComplete(const boost::system::error_code& ecResult, int iStatus = 0, const std::string& strData = "");
void makeGet(const std::string& strPath, boost::asio::streambuf& sb, const std::string& strHost);
public:
HttpsClient(
boost::asio::io_service& io_service,
const unsigned short port,
const std::string& strPath,
std::size_t responseMax
);
void httpsGet(
void httpsRequest(
bool bSSL,
std::deque<std::string> deqSites,
boost::function<void(boost::asio::streambuf& sb, const std::string& strHost)> build,
boost::posix_time::time_duration timeout,
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
void httpsGet(
bool bSSL,
std::deque<std::string> deqSites,
const std::string& strPath,
boost::posix_time::time_duration timeout,
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
static void httpsGet(
bool bSSL,
boost::asio::io_service& io_service,
std::deque<std::string> deqSites,
const unsigned short port,
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
static void httpsGet(
bool bSSL,
boost::asio::io_service& io_service,
std::string strSite,
const unsigned short port,
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
static void httpsRequest(
bool bSSL,
boost::asio::io_service& io_service,
std::string strSite,
const unsigned short port,
boost::function<void(boost::asio::streambuf& sb, const std::string& strHost)> build,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
boost::function<bool(const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
};
#endif
// vim:ts=4

View File

@@ -152,7 +152,7 @@ TER OfferCreateTransactor::takeOffers(
STAmount saTakerFunds = mEngine->getNodes().accountFunds(uTakerAccountID, saTakerPays);
SLE::pointer sleOfferAccount; // Owner of offer.
if (!saOfferFunds.isPositive())
if (!saOfferFunds.isPositive()) // Includes zero.
{
// Offer is unfunded, possibly due to previous balance action.
cLog(lsINFO) << "takeOffers: offer unfunded: delete";

View File

@@ -29,7 +29,7 @@ enum http_status_type
extern std::string JSONRPCRequest(const std::string& strMethod, const Json::Value& params,
const Json::Value& id);
extern std::string createHTTPPost(const std::string& strPath, const std::string& strMsg,
extern std::string createHTTPPost(const std::string& strHost, const std::string& strPath, const std::string& strMsg,
const std::map<std::string, std::string>& mapRequestHeaders);
extern int ReadHTTP(std::basic_istream<char>& stream,

View File

@@ -2304,11 +2304,8 @@ Json::Value RPCHandler::doLedgerHeader(Json::Value jvRequest)
jvResult["ledger_data"] = strHex(s.peekData());
if (mRole == ADMIN)
{
// As admin, they can trust us, so we provide this information.
lpLedger->addJson(jvResult, 0);
}
// This information isn't verified, they should only use it if they trust us.
lpLedger->addJson(jvResult, 0);
return jvResult;
}

View File

@@ -1,5 +1,6 @@
#include <boost/thread.hpp>
#include "Application.h"
#include "RPCSub.h"
#include "CallRPC.h"
@@ -7,7 +8,7 @@
SETUP_LOG();
RPCSub::RPCSub(const std::string& strUrl, const std::string& strUsername, const std::string& strPassword)
: mUrl(strUrl), mUsername(strUsername), mPassword(strPassword)
: mUrl(strUrl), mSSL(false), mUsername(strUsername), mPassword(strPassword)
{
std::string strScheme;
@@ -15,17 +16,22 @@ RPCSub::RPCSub(const std::string& strUrl, const std::string& strUsername, const
{
throw std::runtime_error("Failed to parse url.");
}
else if (strScheme == "https")
{
mSSL = true;
}
else if (strScheme != "http")
{
throw std::runtime_error("Only http is supported.");
throw std::runtime_error("Only http and https is supported.");
}
mSeq = 1;
if (mPort < 0)
mPort = 80;
mPort = mSSL ? 443 : 80;
}
// XXX Could probably create a bunch of send jobs in a single get of the lock.
void RPCSub::sendThread()
{
Json::Value jvEvent;
@@ -58,12 +64,18 @@ void RPCSub::sendThread()
// Send outside of the lock.
if (bSend)
{
// XXX Might not need this in a try.
try
{
cLog(lsDEBUG) << boost::str(boost::format("callRPC calling: %s") % mIp);
// Drop result.
(void) callRPC(mIp, mPort, mUsername, mPassword, mPath, "event", jvEvent);
callRPC(
theApp->getIOService(),
mIp, mPort,
mUsername, mPassword,
mPath, "event",
jvEvent,
mSSL);
}
catch (const std::exception& e)
{

View File

@@ -15,6 +15,7 @@ class RPCSub : public InfoSub
std::string mUrl;
std::string mIp;
int mPort;
bool mSSL;
std::string mUsername;
std::string mPassword;
std::string mPath;

View File

@@ -791,16 +791,23 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str
}
// Given a section with IPs, parse and persist it for a validator.
void UniqueNodeList::responseIps(const std::string& strSite, const RippleAddress& naNodePublic, const boost::system::error_code& err, const std::string& strIpsFile)
bool UniqueNodeList::responseIps(const std::string& strSite, const RippleAddress& naNodePublic, const boost::system::error_code& err, int iStatus, const std::string& strIpsFile)
{
if (!err)
{
section secFile = ParseSection(strIpsFile, true);
bool bReject = !err && iStatus != 200;
processIps(strSite, naNodePublic, sectionEntries(secFile, SECTION_IPS));
if (!bReject)
{
if (!err)
{
section secFile = ParseSection(strIpsFile, true);
processIps(strSite, naNodePublic, sectionEntries(secFile, SECTION_IPS));
}
fetchFinish();
}
fetchFinish();
return bReject;
}
// Process section [ips_url].
@@ -820,13 +827,14 @@ void UniqueNodeList::getIpsUrl(const RippleAddress& naNodePublic, section secSit
&& strScheme == "https")
{
HttpsClient::httpsGet(
true,
theApp->getIOService(),
strDomain,
443,
strPath,
NODE_FILE_BYTES_MAX,
boost::posix_time::seconds(NODE_FETCH_SECONDS),
boost::bind(&UniqueNodeList::responseIps, this, strDomain, naNodePublic, _1, _2));
boost::bind(&UniqueNodeList::responseIps, this, strDomain, naNodePublic, _1, _2, _3));
}
else
{
@@ -835,16 +843,23 @@ void UniqueNodeList::getIpsUrl(const RippleAddress& naNodePublic, section secSit
}
// After fetching a ripple.txt from a web site, given a section with validators, parse and persist it.
void UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, const RippleAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string& strValidatorsFile)
bool UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, const RippleAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, int iStatus, const std::string& strValidatorsFile)
{
if (!err)
{
section secFile = ParseSection(strValidatorsFile, true);
bool bReject = !err && iStatus != 200;
processValidators(strSite, strValidatorsUrl, naNodePublic, vsValidator, sectionEntries(secFile, SECTION_VALIDATORS));
if (!bReject)
{
if (!err)
{
section secFile = ParseSection(strValidatorsFile, true);
processValidators(strSite, strValidatorsUrl, naNodePublic, vsValidator, sectionEntries(secFile, SECTION_VALIDATORS));
}
getIpsUrl(naNodePublic, secSite);
}
getIpsUrl(naNodePublic, secSite);
return bReject;
}
// Process section [validators_url].
@@ -863,13 +878,14 @@ void UniqueNodeList::getValidatorsUrl(const RippleAddress& naNodePublic, section
&& strScheme == "https")
{
HttpsClient::httpsGet(
true,
theApp->getIOService(),
strDomain,
443,
strPath,
NODE_FILE_BYTES_MAX,
boost::posix_time::seconds(NODE_FETCH_SECONDS),
boost::bind(&UniqueNodeList::responseValidators, this, strValidatorsUrl, naNodePublic, secSite, strDomain, _1, _2));
boost::bind(&UniqueNodeList::responseValidators, this, strValidatorsUrl, naNodePublic, secSite, strDomain, _1, _2, _3));
}
else
{
@@ -905,118 +921,125 @@ void UniqueNodeList::processFile(const std::string& strDomain, const RippleAddre
}
// Given a ripple.txt, process it.
void UniqueNodeList::responseFetch(const std::string& strDomain, const boost::system::error_code& err, const std::string& strSiteFile)
bool UniqueNodeList::responseFetch(const std::string& strDomain, const boost::system::error_code& err, int iStatus, const std::string& strSiteFile)
{
section secSite = ParseSection(strSiteFile, true);
bool bGood = !err;
bool bReject = !err && iStatus != 200;
if (bGood)
if (!bReject)
{
cLog(lsTRACE) << boost::format("Validator: '%s' received " NODE_FILE_NAME ".") % strDomain;
}
else
{
cLog(lsTRACE)
<< boost::format("Validator: '%s' unable to retrieve " NODE_FILE_NAME ": %s")
% strDomain
% err.message();
}
section secSite = ParseSection(strSiteFile, true);
bool bGood = !err;
//
// Verify file domain
//
std::string strSite;
if (bGood && !sectionSingleB(secSite, SECTION_DOMAIN, strSite))
{
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " missing single entry for " SECTION_DOMAIN ".")
% strDomain;
}
if (bGood && strSite != strDomain)
{
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_DOMAIN " does not match: %s")
% strDomain
% strSite;
}
//
// Process public key
//
std::string strNodePublicKey;
if (bGood && !sectionSingleB(secSite, SECTION_PUBLIC_KEY, strNodePublicKey))
{
// Bad [validation_public_key] section.
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " does not have single entry.")
% strDomain;
}
RippleAddress naNodePublic;
if (bGood && !naNodePublic.setNodePublic(strNodePublicKey))
{
// Bad public key.
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " is bad: ")
% strDomain
% strNodePublicKey;
}
if (bGood)
{
// cLog(lsTRACE) << boost::format("naNodePublic: '%s'") % naNodePublic.humanNodePublic();
seedDomain sdCurrent;
bool bFound = getSeedDomains(strDomain, sdCurrent);
assert(bFound);
uint256 iSha256 = Serializer::getSHA512Half(strSiteFile);
bool bChangedB = sdCurrent.iSha256 != iSha256;
sdCurrent.strDomain = strDomain;
// XXX If the node public key is changing, delete old public key information?
// XXX Only if no other refs to keep it arround, other wise we have an attack vector.
sdCurrent.naPublicKey = naNodePublic;
// cLog(lsTRACE) << boost::format("sdCurrent.naPublicKey: '%s'") % sdCurrent.naPublicKey.humanNodePublic();
sdCurrent.tpFetch = boost::posix_time::second_clock::universal_time();
sdCurrent.iSha256 = iSha256;
setSeedDomains(sdCurrent, true);
if (bChangedB)
if (bGood)
{
cLog(lsTRACE) << boost::format("Validator: '%s' processing new " NODE_FILE_NAME ".") % strDomain;
processFile(strDomain, naNodePublic, secSite);
cLog(lsTRACE) << boost::format("Validator: '%s' received " NODE_FILE_NAME ".") % strDomain;
}
else
{
cLog(lsTRACE) << boost::format("Validator: '%s' no change for " NODE_FILE_NAME ".") % strDomain;
cLog(lsTRACE)
<< boost::format("Validator: '%s' unable to retrieve " NODE_FILE_NAME ": %s")
% strDomain
% err.message();
}
//
// Verify file domain
//
std::string strSite;
if (bGood && !sectionSingleB(secSite, SECTION_DOMAIN, strSite))
{
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " missing single entry for " SECTION_DOMAIN ".")
% strDomain;
}
if (bGood && strSite != strDomain)
{
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_DOMAIN " does not match: %s")
% strDomain
% strSite;
}
//
// Process public key
//
std::string strNodePublicKey;
if (bGood && !sectionSingleB(secSite, SECTION_PUBLIC_KEY, strNodePublicKey))
{
// Bad [validation_public_key] section.
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " does not have single entry.")
% strDomain;
}
RippleAddress naNodePublic;
if (bGood && !naNodePublic.setNodePublic(strNodePublicKey))
{
// Bad public key.
bGood = false;
cLog(lsTRACE)
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " is bad: ")
% strDomain
% strNodePublicKey;
}
if (bGood)
{
// cLog(lsTRACE) << boost::format("naNodePublic: '%s'") % naNodePublic.humanNodePublic();
seedDomain sdCurrent;
bool bFound = getSeedDomains(strDomain, sdCurrent);
assert(bFound);
uint256 iSha256 = Serializer::getSHA512Half(strSiteFile);
bool bChangedB = sdCurrent.iSha256 != iSha256;
sdCurrent.strDomain = strDomain;
// XXX If the node public key is changing, delete old public key information?
// XXX Only if no other refs to keep it arround, other wise we have an attack vector.
sdCurrent.naPublicKey = naNodePublic;
// cLog(lsTRACE) << boost::format("sdCurrent.naPublicKey: '%s'") % sdCurrent.naPublicKey.humanNodePublic();
sdCurrent.tpFetch = boost::posix_time::second_clock::universal_time();
sdCurrent.iSha256 = iSha256;
setSeedDomains(sdCurrent, true);
if (bChangedB)
{
cLog(lsTRACE) << boost::format("Validator: '%s' processing new " NODE_FILE_NAME ".") % strDomain;
processFile(strDomain, naNodePublic, secSite);
}
else
{
cLog(lsTRACE) << boost::format("Validator: '%s' no change for " NODE_FILE_NAME ".") % strDomain;
fetchFinish();
}
}
else
{
// Failed: Update
// XXX If we have public key, perhaps try look up in CAS?
fetchFinish();
}
}
else
{
// Failed: Update
// XXX If we have public key, perhaps try look up in CAS?
fetchFinish();
}
return bReject;
}
// Get the ripple.txt and process it.
@@ -1033,13 +1056,14 @@ void UniqueNodeList::fetchProcess(std::string strDomain)
deqSites.push_back(strDomain);
HttpsClient::httpsGet(
true,
theApp->getIOService(),
deqSites,
443,
NODE_FILE_PATH,
NODE_FILE_BYTES_MAX,
boost::posix_time::seconds(NODE_FETCH_SECONDS),
boost::bind(&UniqueNodeList::responseFetch, this, strDomain, _1, _2));
boost::bind(&UniqueNodeList::responseFetch, this, strDomain, _1, _2, _3));
}
void UniqueNodeList::fetchTimerHandler(const boost::system::error_code& err)
@@ -1549,18 +1573,25 @@ bool UniqueNodeList::nodeLoad(boost::filesystem::path pConfig)
return true;
}
void UniqueNodeList::validatorsResponse(const boost::system::error_code& err, std::string strResponse)
bool UniqueNodeList::validatorsResponse(const boost::system::error_code& err, int iStatus, std::string strResponse)
{
cLog(lsTRACE) << "Fetch '" VALIDATORS_FILE_NAME "' complete.";
bool bReject = !err && iStatus != 200;
if (!err)
if (!bReject)
{
nodeProcess("network", strResponse, theConfig.VALIDATORS_SITE);
}
else
{
cLog(lsWARNING) << "Error: " << err.message();
cLog(lsTRACE) << "Fetch '" VALIDATORS_FILE_NAME "' complete.";
if (!err)
{
nodeProcess("network", strResponse, theConfig.VALIDATORS_SITE);
}
else
{
cLog(lsWARNING) << "Error: " << err.message();
}
}
return bReject;
}
void UniqueNodeList::nodeNetwork()
@@ -1568,13 +1599,14 @@ void UniqueNodeList::nodeNetwork()
if (!theConfig.VALIDATORS_SITE.empty())
{
HttpsClient::httpsGet(
true,
theApp->getIOService(),
theConfig.VALIDATORS_SITE,
443,
theConfig.VALIDATORS_URI,
VALIDATORS_FILE_BYTES_MAX,
boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS),
boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2));
boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2, _3));
}
}

View File

@@ -98,7 +98,7 @@ private:
bool scoreRound(std::vector<scoreNode>& vsnNodes);
void responseFetch(const std::string& strDomain, const boost::system::error_code& err, const std::string& strSiteFile);
bool responseFetch(const std::string& strDomain, const boost::system::error_code& err, int iStatus, const std::string& strSiteFile);
boost::posix_time::ptime mtpScoreNext; // When to start scoring.
boost::posix_time::ptime mtpScoreStart; // Time currently started scoring.
@@ -122,8 +122,8 @@ private:
void getValidatorsUrl(const RippleAddress& naNodePublic, section secSite);
void getIpsUrl(const RippleAddress& naNodePublic, section secSite);
void responseIps(const std::string& strSite, const RippleAddress& naNodePublic, const boost::system::error_code& err, const std::string& strIpsFile);
void responseValidators(const std::string& strValidatorsUrl, const RippleAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string& strValidatorsFile);
bool responseIps(const std::string& strSite, const RippleAddress& naNodePublic, const boost::system::error_code& err, int iStatus, const std::string& strIpsFile);
bool responseValidators(const std::string& strValidatorsUrl, const RippleAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, int iStatus, const std::string& strValidatorsFile);
void processIps(const std::string& strSite, const RippleAddress& naNodePublic, section::mapped_type* pmtVecStrIps);
int processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const RippleAddress& naNodePublic, validatorSource vsWhy, section::mapped_type* pmtVecStrValidators);
@@ -136,7 +136,7 @@ private:
bool getSeedNodes(const RippleAddress& naNodePublic, seedNode& dstSeedNode);
void setSeedNodes(const seedNode& snSource, bool bNext);
void validatorsResponse(const boost::system::error_code& err, std::string strResponse);
bool validatorsResponse(const boost::system::error_code& err, int iStatus, const std::string strResponse);
void nodeProcess(const std::string& strSite, const std::string& strValidators, const std::string& strSource);
public:

View File

@@ -39,15 +39,15 @@ Json::Value JSONRPCError(int code, const std::string& message)
// and to be compatible with other JSON-RPC implementations.
//
std::string createHTTPPost(const std::string& strPath, const std::string& strMsg, const std::map<std::string, std::string>& mapRequestHeaders)
std::string createHTTPPost(const std::string& strHost, const std::string& strPath, const std::string& strMsg, const std::map<std::string, std::string>& mapRequestHeaders)
{
std::ostringstream s;
s << "POST "
<< (strPath.empty() ? "/" : strPath)
<< " HTTP/1.1\r\n"
<< " HTTP/1.0\r\n"
<< "User-Agent: " SYSTEM_NAME "-json-rpc/" << FormatFullVersion() << "\r\n"
<< "Host: 127.0.0.1\r\n"
<< "Host: " << strHost << "\r\n"
<< "Content-Type: application/json\r\n"
<< "Content-Length: " << strMsg.size() << "\r\n"
<< "Accept: application/json\r\n";