Refactor HTTPClient

This commit is contained in:
Vinnie Falco
2013-09-01 03:16:34 -07:00
parent 65df4b9daf
commit 5f1a8670dc
5 changed files with 454 additions and 478 deletions

View File

@@ -556,7 +556,7 @@ public:
{ {
if (!getConfig ().VALIDATORS_SITE.empty ()) if (!getConfig ().VALIDATORS_SITE.empty ())
{ {
HttpsClient::httpsGet ( HTTPClient::get (
true, true,
getApp().getIOService (), getApp().getIOService (),
getConfig ().VALIDATORS_SITE, getConfig ().VALIDATORS_SITE,
@@ -1434,7 +1434,7 @@ private:
deqSites.push_back (str (boost::format ("www.%s") % strDomain)); deqSites.push_back (str (boost::format ("www.%s") % strDomain));
deqSites.push_back (strDomain); deqSites.push_back (strDomain);
HttpsClient::httpsGet ( HTTPClient::get (
true, true,
getApp().getIOService (), getApp().getIOService (),
deqSites, deqSites,
@@ -1473,7 +1473,7 @@ private:
&& -1 == iPort && -1 == iPort
&& strScheme == "https") && strScheme == "https")
{ {
HttpsClient::httpsGet ( HTTPClient::get (
true, true,
getApp().getIOService (), getApp().getIOService (),
strDomain, strDomain,
@@ -1507,7 +1507,7 @@ private:
&& -1 == iPort && -1 == iPort
&& strScheme == "https") && strScheme == "https")
{ {
HttpsClient::httpsGet ( HTTPClient::get (
true, true,
getApp().getIOService (), getApp().getIOService (),
strDomain, strDomain,

View File

@@ -2729,7 +2729,7 @@ Json::Value RPCHandler::doSMS (Json::Value params, LoadType* loadType, Applicati
if (!params.isMember ("text")) if (!params.isMember ("text"))
return rpcError (rpcINVALID_PARAMS); return rpcError (rpcINVALID_PARAMS);
HttpsClient::sendSMS (getApp().getIOService (), params["text"].asString ()); HTTPClient::sendSMS (getApp().getIOService (), params["text"].asString ());
return "sms dispatched"; return "sms dispatched";
} }

View File

@@ -5,15 +5,21 @@
//============================================================================== //==============================================================================
// //
// Fetch a web page via https. // Fetch a web page via http or https.
// //
SETUP_LOG (HttpsClient) SETUP_LOG (HTTPClient)
class HTTPClientImp
: public boost::enable_shared_from_this <HTTPClientImp>
, public HTTPClient
, LeakChecked <HTTPClientImp>
{
public:
// VFALCO NOTE Why use getConfig ().SSL_CONTEXT instead of just passing it? // VFALCO NOTE Why use getConfig ().SSL_CONTEXT instead of just passing it?
// TODO Remove all theConfig deps from this file // TODO Remove all theConfig deps from this file
// //
HttpsClient::HttpsClient (boost::asio::io_service& io_service, HTTPClientImp (boost::asio::io_service& io_service,
const unsigned short port, const unsigned short port,
std::size_t responseMax) std::size_t responseMax)
: mSocket (io_service, getConfig ().SSL_CONTEXT) : mSocket (io_service, getConfig ().SSL_CONTEXT)
@@ -27,7 +33,10 @@ HttpsClient::HttpsClient (boost::asio::io_service& io_service,
mSocket.SSLSocket ().set_verify_mode (boost::asio::ssl::verify_none); mSocket.SSLSocket ().set_verify_mode (boost::asio::ssl::verify_none);
} }
void HttpsClient::makeGet (const std::string& strPath, boost::asio::streambuf& sb, const std::string& strHost) //--------------------------------------------------------------------------
void makeGet (const std::string& strPath, boost::asio::streambuf& sb,
const std::string& strHost)
{ {
std::ostream osRequest (&sb); std::ostream osRequest (&sb);
@@ -38,12 +47,15 @@ void HttpsClient::makeGet (const std::string& strPath, boost::asio::streambuf& s
"Connection: close\r\n\r\n"; "Connection: close\r\n\r\n";
} }
void HttpsClient::httpsRequest ( //--------------------------------------------------------------------------
void request (
bool bSSL, bool bSSL,
std::deque<std::string> deqSites, std::deque<std::string> deqSites,
FUNCTION_TYPE<void (boost::asio::streambuf& sb, const std::string& strHost)> build, FUNCTION_TYPE<void (boost::asio::streambuf& sb, const std::string& strHost)> build,
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) FUNCTION_TYPE<bool (const boost::system::error_code& ecResult,
int iStatus, const std::string& strData)> complete)
{ {
mSSL = bSSL; mSSL = bSSL;
mDeqSites = deqSites; mDeqSites = deqSites;
@@ -54,28 +66,33 @@ void HttpsClient::httpsRequest (
httpsNext (); httpsNext ();
} }
void HttpsClient::httpsGet ( //--------------------------------------------------------------------------
void get (
bool bSSL, bool bSSL,
std::deque<std::string> deqSites, std::deque<std::string> deqSites,
const std::string& strPath, const std::string& strPath,
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus,
const std::string& strData)> complete)
{ {
mComplete = complete; mComplete = complete;
mTimeout = timeout; mTimeout = timeout;
httpsRequest ( request (
bSSL, bSSL,
deqSites, deqSites,
BIND_TYPE (&HttpsClient::makeGet, shared_from_this (), strPath, P_1, P_2), BIND_TYPE (&HTTPClientImp::makeGet, shared_from_this (), strPath, P_1, P_2),
timeout, timeout,
complete); complete);
} }
void HttpsClient::httpsNext () //--------------------------------------------------------------------------
void httpsNext ()
{ {
WriteLog (lsTRACE, HttpsClient) << "Fetch: " << mDeqSites[0]; WriteLog (lsTRACE, HTTPClient) << "Fetch: " << mDeqSites[0];
boost::shared_ptr <boost::asio::ip::tcp::resolver::query> query ( boost::shared_ptr <boost::asio::ip::tcp::resolver::query> query (
new boost::asio::ip::tcp::resolver::query ( new boost::asio::ip::tcp::resolver::query (
@@ -86,24 +103,24 @@ void HttpsClient::httpsNext ()
mDeadline.expires_from_now (mTimeout, mShutdown); mDeadline.expires_from_now (mTimeout, mShutdown);
WriteLog (lsTRACE, HttpsClient) << "expires_from_now: " << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "expires_from_now: " << mShutdown.message ();
if (!mShutdown) if (!mShutdown)
{ {
mDeadline.async_wait ( mDeadline.async_wait (
boost::bind ( boost::bind (
&HttpsClient::handleDeadline, &HTTPClientImp::handleDeadline,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error)); boost::asio::placeholders::error));
} }
if (!mShutdown) if (!mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Resolving: " << mDeqSites[0]; WriteLog (lsTRACE, HTTPClient) << "Resolving: " << mDeqSites[0];
mResolver.async_resolve (*mQuery, mResolver.async_resolve (*mQuery,
boost::bind ( boost::bind (
&HttpsClient::handleResolve, &HTTPClientImp::handleResolve,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::error,
boost::asio::placeholders::iterator)); boost::asio::placeholders::iterator));
@@ -113,25 +130,25 @@ void HttpsClient::httpsNext ()
invokeComplete (mShutdown); invokeComplete (mShutdown);
} }
void HttpsClient::handleDeadline (const boost::system::error_code& ecResult) void handleDeadline (const boost::system::error_code& ecResult)
{ {
if (ecResult == boost::asio::error::operation_aborted) if (ecResult == boost::asio::error::operation_aborted)
{ {
// Timer canceled because deadline no longer needed. // Timer canceled because deadline no longer needed.
WriteLog (lsTRACE, HttpsClient) << "Deadline cancelled."; WriteLog (lsTRACE, HTTPClient) << "Deadline cancelled.";
nothing (); // Aborter is done. nothing (); // Aborter is done.
} }
else if (ecResult) else if (ecResult)
{ {
WriteLog (lsTRACE, HttpsClient) << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message (); WriteLog (lsTRACE, HTTPClient) << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message ();
// Can't do anything sound. // Can't do anything sound.
abort (); abort ();
} }
else else
{ {
WriteLog (lsTRACE, HttpsClient) << "Deadline arrived."; WriteLog (lsTRACE, HTTPClient) << "Deadline arrived.";
// Mark us as shutting down. // Mark us as shutting down.
// XXX Use our own error code. // XXX Use our own error code.
@@ -142,24 +159,24 @@ void HttpsClient::handleDeadline (const boost::system::error_code& ecResult)
// Stop the transaction. // Stop the transaction.
mSocket.async_shutdown (boost::bind ( mSocket.async_shutdown (boost::bind (
&HttpsClient::handleShutdown, &HTTPClientImp::handleShutdown,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error)); boost::asio::placeholders::error));
} }
} }
void HttpsClient::handleShutdown ( void handleShutdown (
const boost::system::error_code& ecResult const boost::system::error_code& ecResult
) )
{ {
if (ecResult) if (ecResult)
{ {
WriteLog (lsTRACE, HttpsClient) << "Shutdown error: " << mDeqSites[0] << ": " << ecResult.message (); WriteLog (lsTRACE, HTTPClient) << "Shutdown error: " << mDeqSites[0] << ": " << ecResult.message ();
} }
} }
void HttpsClient::handleResolve ( void handleResolve (
const boost::system::error_code& ecResult, const boost::system::error_code& ecResult,
boost::asio::ip::tcp::resolver::iterator itrEndpoint boost::asio::ip::tcp::resolver::iterator itrEndpoint
) )
@@ -169,37 +186,37 @@ void HttpsClient::handleResolve (
if (mShutdown) if (mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message ();
invokeComplete (mShutdown); invokeComplete (mShutdown);
} }
else else
{ {
WriteLog (lsTRACE, HttpsClient) << "Resolve complete."; WriteLog (lsTRACE, HTTPClient) << "Resolve complete.";
boost::asio::async_connect ( boost::asio::async_connect (
mSocket.lowest_layer (), mSocket.lowest_layer (),
itrEndpoint, itrEndpoint,
boost::bind ( boost::bind (
&HttpsClient::handleConnect, &HTTPClientImp::handleConnect,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error)); boost::asio::placeholders::error));
} }
} }
void HttpsClient::handleConnect (const boost::system::error_code& ecResult) void handleConnect (const boost::system::error_code& ecResult)
{ {
if (!mShutdown) if (!mShutdown)
mShutdown = ecResult; mShutdown = ecResult;
if (mShutdown) if (mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Connect error: " << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "Connect error: " << mShutdown.message ();
} }
if (!mShutdown) if (!mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Connected."; WriteLog (lsTRACE, HTTPClient) << "Connected.";
if (getConfig ().SSL_VERIFY) if (getConfig ().SSL_VERIFY)
{ {
@@ -207,7 +224,7 @@ void HttpsClient::handleConnect (const boost::system::error_code& ecResult)
if (mShutdown) if (mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message ();
} }
} }
} }
@@ -221,7 +238,7 @@ void HttpsClient::handleConnect (const boost::system::error_code& ecResult)
mSocket.async_handshake ( mSocket.async_handshake (
AutoSocket::ssl_socket::client, AutoSocket::ssl_socket::client,
boost::bind ( boost::bind (
&HttpsClient::handleRequest, &HTTPClientImp::handleRequest,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error)); boost::asio::placeholders::error));
} }
@@ -231,61 +248,61 @@ void HttpsClient::handleConnect (const boost::system::error_code& ecResult)
} }
} }
void HttpsClient::handleRequest (const boost::system::error_code& ecResult) void handleRequest (const boost::system::error_code& ecResult)
{ {
if (!mShutdown) if (!mShutdown)
mShutdown = ecResult; mShutdown = ecResult;
if (mShutdown) if (mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Handshake error:" << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "Handshake error:" << mShutdown.message ();
invokeComplete (mShutdown); invokeComplete (mShutdown);
} }
else else
{ {
WriteLog (lsTRACE, HttpsClient) << "Session started."; WriteLog (lsTRACE, HTTPClient) << "Session started.";
mBuild (mRequest, mDeqSites[0]); mBuild (mRequest, mDeqSites[0]);
mSocket.async_write ( mSocket.async_write (
mRequest, mRequest,
boost::bind (&HttpsClient::handleWrite, boost::bind (&HTTPClientImp::handleWrite,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::bytes_transferred));
} }
} }
void HttpsClient::handleWrite (const boost::system::error_code& ecResult, std::size_t bytes_transferred) void handleWrite (const boost::system::error_code& ecResult, std::size_t bytes_transferred)
{ {
if (!mShutdown) if (!mShutdown)
mShutdown = ecResult; mShutdown = ecResult;
if (mShutdown) if (mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Write error: " << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "Write error: " << mShutdown.message ();
invokeComplete (mShutdown); invokeComplete (mShutdown);
} }
else else
{ {
WriteLog (lsTRACE, HttpsClient) << "Wrote."; WriteLog (lsTRACE, HTTPClient) << "Wrote.";
mSocket.async_read_until ( mSocket.async_read_until (
mHeader, mHeader,
"\r\n\r\n", "\r\n\r\n",
boost::bind (&HttpsClient::handleHeader, boost::bind (&HTTPClientImp::handleHeader,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::bytes_transferred));
} }
} }
void HttpsClient::handleHeader (const boost::system::error_code& ecResult, std::size_t bytes_transferred) void handleHeader (const boost::system::error_code& ecResult, std::size_t bytes_transferred)
{ {
std::string strHeader ((std::istreambuf_iterator<char> (&mHeader)), std::istreambuf_iterator<char> ()); std::string strHeader ((std::istreambuf_iterator<char> (&mHeader)), std::istreambuf_iterator<char> ());
WriteLog (lsTRACE, HttpsClient) << "Header: \"" << strHeader << "\""; WriteLog (lsTRACE, HTTPClient) << "Header: \"" << strHeader << "\"";
static boost::regex reStatus ("\\`HTTP/1\\S+ (\\d{3}) .*\\'"); // HTTP/1.1 200 OK static boost::regex reStatus ("\\`HTTP/1\\S+ (\\d{3}) .*\\'"); // HTTP/1.1 200 OK
static boost::regex reSize ("\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'"); static boost::regex reSize ("\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'");
@@ -298,7 +315,7 @@ void HttpsClient::handleHeader (const boost::system::error_code& ecResult, std::
if (!bMatch) if (!bMatch)
{ {
// XXX Use our own error code. // XXX Use our own error code.
WriteLog (lsTRACE, HttpsClient) << "No status code"; WriteLog (lsTRACE, HTTPClient) << "No status code";
invokeComplete (boost::system::error_code (boost::system::errc::bad_address, boost::system::system_category ())); invokeComplete (boost::system::error_code (boost::system::errc::bad_address, boost::system::system_category ()));
return; return;
} }
@@ -331,21 +348,21 @@ void HttpsClient::handleHeader (const boost::system::error_code& ecResult, std::
mSocket.async_read ( mSocket.async_read (
mResponse.prepare (mResponseMax - mBody.size ()), mResponse.prepare (mResponseMax - mBody.size ()),
boost::asio::transfer_all (), boost::asio::transfer_all (),
boost::bind (&HttpsClient::handleData, boost::bind (&HTTPClientImp::handleData,
shared_from_this (), shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::bytes_transferred));
} }
} }
void HttpsClient::handleData (const boost::system::error_code& ecResult, std::size_t bytes_transferred) void handleData (const boost::system::error_code& ecResult, std::size_t bytes_transferred)
{ {
if (!mShutdown) if (!mShutdown)
mShutdown = ecResult; mShutdown = ecResult;
if (mShutdown && mShutdown != boost::asio::error::eof) if (mShutdown && mShutdown != boost::asio::error::eof)
{ {
WriteLog (lsTRACE, HttpsClient) << "Read error: " << mShutdown.message (); WriteLog (lsTRACE, HTTPClient) << "Read error: " << mShutdown.message ();
invokeComplete (mShutdown); invokeComplete (mShutdown);
} }
@@ -353,7 +370,7 @@ void HttpsClient::handleData (const boost::system::error_code& ecResult, std::si
{ {
if (mShutdown) if (mShutdown)
{ {
WriteLog (lsTRACE, HttpsClient) << "Complete."; WriteLog (lsTRACE, HTTPClient) << "Complete.";
nothing (); nothing ();
} }
@@ -367,7 +384,7 @@ void HttpsClient::handleData (const boost::system::error_code& ecResult, std::si
} }
// Call cancel the deadline timer and invoke the completion routine. // Call cancel the deadline timer and invoke the completion routine.
void HttpsClient::invokeComplete (const boost::system::error_code& ecResult, int iStatus, const std::string& strData) void invokeComplete (const boost::system::error_code& ecResult, int iStatus = 0, const std::string& strData = "")
{ {
boost::system::error_code ecCancel; boost::system::error_code ecCancel;
@@ -375,10 +392,10 @@ void HttpsClient::invokeComplete (const boost::system::error_code& ecResult, int
if (ecCancel) if (ecCancel)
{ {
WriteLog (lsTRACE, HttpsClient) << "HttpsClient::invokeComplete: Deadline cancel error: " << ecCancel.message (); WriteLog (lsTRACE, HTTPClient) << "invokeComplete: Deadline cancel error: " << ecCancel.message ();
} }
WriteLog (lsDEBUG, HttpsClient) << "HttpsClient::invokeComplete: Deadline popping: " << mDeqSites.size (); WriteLog (lsDEBUG, HTTPClient) << "invokeComplete: Deadline popping: " << mDeqSites.size ();
if (!mDeqSites.empty ()) if (!mDeqSites.empty ())
{ {
@@ -401,7 +418,42 @@ void HttpsClient::invokeComplete (const boost::system::error_code& ecResult, int
} }
} }
void HttpsClient::httpsGet ( static bool onSMSResponse (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)
{
WriteLog (lsINFO, HTTPClient) << "SMS: Response:" << iStatus << " :" << strData;
return true;
}
private:
typedef boost::shared_ptr<HTTPClient> pointer;
bool mSSL;
AutoSocket mSocket;
boost::asio::ip::tcp::resolver mResolver;
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> mQuery;
boost::asio::streambuf mRequest;
boost::asio::streambuf mHeader;
boost::asio::streambuf mResponse;
std::string mBody;
const unsigned short mPort;
int mResponseMax;
int mStatus;
FUNCTION_TYPE<void (boost::asio::streambuf& sb, const std::string& strHost)> mBuild;
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> mComplete;
boost::asio::deadline_timer mDeadline;
// If not success, we are shutting down.
boost::system::error_code mShutdown;
std::deque<std::string> mDeqSites;
boost::posix_time::time_duration mTimeout;
};
//------------------------------------------------------------------------------
void HTTPClient::get (
bool bSSL, bool bSSL,
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
std::deque<std::string> deqSites, std::deque<std::string> deqSites,
@@ -409,15 +461,16 @@ void HttpsClient::httpsGet (
const std::string& strPath, const std::string& strPath,
std::size_t responseMax, std::size_t responseMax,
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus,
const std::string& strData)> complete)
{ {
boost::shared_ptr <HTTPClientImp> client (
new HTTPClientImp (io_service, port, responseMax));
boost::shared_ptr<HttpsClient> client (new HttpsClient (io_service, port, responseMax)); client->get (bSSL, deqSites, strPath, timeout, complete);
client->httpsGet (bSSL, deqSites, strPath, timeout, complete);
} }
void HttpsClient::httpsGet ( void HTTPClient::get (
bool bSSL, bool bSSL,
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
std::string strSite, std::string strSite,
@@ -425,17 +478,18 @@ void HttpsClient::httpsGet (
const std::string& strPath, const std::string& strPath,
std::size_t responseMax, std::size_t responseMax,
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus,
const std::string& strData)> complete)
{ {
std::deque<std::string> deqSites (1, strSite); std::deque<std::string> deqSites (1, strSite);
boost::shared_ptr<HttpsClient> client (new HttpsClient (io_service, port, responseMax)); boost::shared_ptr <HTTPClientImp> client (
new HTTPClientImp (io_service, port, responseMax));
client->httpsGet (bSSL, deqSites, strPath, timeout, complete); client->get (bSSL, deqSites, strPath, timeout, complete);
} }
void HttpsClient::httpsRequest ( void HTTPClient::request (
bool bSSL, bool bSSL,
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
std::string strSite, std::string strSite,
@@ -443,26 +497,18 @@ void HttpsClient::httpsRequest (
FUNCTION_TYPE<void (boost::asio::streambuf& sb, const std::string& strHost)> setRequest, FUNCTION_TYPE<void (boost::asio::streambuf& sb, const std::string& strHost)> setRequest,
std::size_t responseMax, std::size_t responseMax,
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete) FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus,
const std::string& strData)> complete)
{ {
std::deque<std::string> deqSites (1, strSite); std::deque<std::string> deqSites (1, strSite);
boost::shared_ptr<HttpsClient> client (new HttpsClient (io_service, port, responseMax)); boost::shared_ptr <HTTPClientImp> client (
new HTTPClientImp (io_service, port, responseMax));
client->httpsRequest (bSSL, deqSites, setRequest, timeout, complete); client->request (bSSL, deqSites, setRequest, timeout, complete);
} }
#define SMS_TIMEOUT 30 void HTTPClient::sendSMS (boost::asio::io_service& io_service, const std::string& strText)
bool responseSMS (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)
{
WriteLog (lsINFO, HttpsClient) << "SMS: Response:" << iStatus << " :" << strData;
return true;
}
void HttpsClient::sendSMS (boost::asio::io_service& io_service, const std::string& strText)
{ {
std::string strScheme; std::string strScheme;
std::string strDomain; std::string strDomain;
@@ -471,11 +517,11 @@ void HttpsClient::sendSMS (boost::asio::io_service& io_service, const std::strin
if (getConfig ().SMS_URL == "" || !parseUrl (getConfig ().SMS_URL, strScheme, strDomain, iPort, strPath)) if (getConfig ().SMS_URL == "" || !parseUrl (getConfig ().SMS_URL, strScheme, strDomain, iPort, strPath))
{ {
WriteLog (lsWARNING, HttpsClient) << "SMSRequest: Bad URL:" << getConfig ().SMS_URL; WriteLog (lsWARNING, HTTPClient) << "SMSRequest: Bad URL:" << getConfig ().SMS_URL;
} }
else else
{ {
bool bSSL = strScheme == "https"; bool const bSSL = strScheme == "https";
std::deque<std::string> deqSites (1, strDomain); std::deque<std::string> deqSites (1, strDomain);
std::string strURI = std::string strURI =
@@ -488,15 +534,16 @@ void HttpsClient::sendSMS (boost::asio::io_service& io_service, const std::strin
% urlEncode (strText)); % urlEncode (strText));
// WriteLog (lsINFO) << "SMS: Request:" << strURI; // WriteLog (lsINFO) << "SMS: Request:" << strURI;
WriteLog (lsINFO, HttpsClient) << "SMS: Request: '" << strText << "'"; WriteLog (lsINFO, HTTPClient) << "SMS: Request: '" << strText << "'";
if (iPort < 0) if (iPort < 0)
iPort = bSSL ? 443 : 80; iPort = bSSL ? 443 : 80;
boost::shared_ptr<HttpsClient> client (new HttpsClient (io_service, iPort, maxClientHeaderBytes)); boost::shared_ptr <HTTPClientImp> client (
new HTTPClientImp (io_service, iPort, maxClientHeaderBytes));
client->httpsGet (bSSL, deqSites, strURI, boost::posix_time::seconds (SMS_TIMEOUT), client->get (bSSL, deqSites, strURI, boost::posix_time::seconds (smsTimeoutSeconds),
BIND_TYPE (&responseSMS, P_1, P_2, P_3)); BIND_TYPE (&HTTPClientImp::onSMSResponse, P_1, P_2, P_3));
} }
} }
// vim:ts=4

View File

@@ -7,43 +7,17 @@
#ifndef RIPPLE_NET_BASICS_HTTPCLIENT_H_INCLUDED #ifndef RIPPLE_NET_BASICS_HTTPCLIENT_H_INCLUDED
#define RIPPLE_NET_BASICS_HTTPCLIENT_H_INCLUDED #define RIPPLE_NET_BASICS_HTTPCLIENT_H_INCLUDED
// VFALCO TODO Make this an abstract interface. /** Provides an asynchronous HTTP client implementation with optional SSL.
//
/** Provides an asynchronous HTTPS client implementation.
*/ */
class HttpsClient class HTTPClient
: public boost::enable_shared_from_this <HttpsClient>
, LeakChecked <HttpsClient>
{ {
public: public:
HttpsClient ( enum
boost::asio::io_service& io_service, {
const unsigned short port, maxClientHeaderBytes = 32 * 1024
std::size_t responseMax };
);
// VFALCO NOTE Putting "https" is redundant, the class is static void get (
// already called HttpsClient.
//
// VFALCO TODO Rename these to request, get, and next.
//
void httpsRequest (
bool bSSL,
std::deque<std::string> deqSites,
FUNCTION_TYPE <void (boost::asio::streambuf& sb, const std::string& strHost)> build,
boost::posix_time::time_duration timeout,
FUNCTION_TYPE <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,
FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
// VFALCO TODO These statics all belong in some HttpsClientOperations class
//
static void httpsGet (
bool bSSL, bool bSSL,
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
std::deque <std::string> deqSites, std::deque <std::string> deqSites,
@@ -53,7 +27,7 @@ public:
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete); FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
static void httpsGet ( static void get (
bool bSSL, bool bSSL,
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
std::string strSite, std::string strSite,
@@ -63,7 +37,7 @@ public:
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete); FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
static void httpsRequest ( static void request (
bool bSSL, bool bSSL,
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
std::string strSite, std::string strSite,
@@ -73,57 +47,12 @@ public:
boost::posix_time::time_duration timeout, boost::posix_time::time_duration timeout,
FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete); FUNCTION_TYPE <bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> complete);
enum
{
smsTimeoutSeconds = 30
};
static void sendSMS (boost::asio::io_service& io_service, const std::string& strText); static void sendSMS (boost::asio::io_service& io_service, const std::string& strText);
private:
static const int maxClientHeaderBytes = 32 * 1024;
typedef boost::shared_ptr<HttpsClient> pointer;
bool mSSL;
AutoSocket mSocket;
boost::asio::ip::tcp::resolver mResolver;
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> mQuery;
boost::asio::streambuf mRequest;
boost::asio::streambuf mHeader;
boost::asio::streambuf mResponse;
std::string mBody;
const unsigned short mPort;
int mResponseMax;
int mStatus;
FUNCTION_TYPE<void (boost::asio::streambuf& sb, const std::string& strHost)> mBuild;
FUNCTION_TYPE<bool (const boost::system::error_code& ecResult, int iStatus, const std::string& strData)> mComplete;
boost::asio::deadline_timer mDeadline;
// If not success, we are shutting down.
boost::system::error_code mShutdown;
std::deque<std::string> mDeqSites;
boost::posix_time::time_duration mTimeout;
void handleDeadline (const boost::system::error_code& ecResult);
void handleResolve (const boost::system::error_code& ecResult, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
void handleConnect (const boost::system::error_code& ecResult);
void handleRequest (const boost::system::error_code& ecResult);
void handleWrite (const boost::system::error_code& ecResult, std::size_t bytes_transferred);
void handleHeader (const boost::system::error_code& ecResult, std::size_t bytes_transferred);
void handleData (const boost::system::error_code& ecResult, std::size_t bytes_transferred);
void handleShutdown (const boost::system::error_code& ecResult);
void httpsNext ();
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);
}; };
#endif #endif

View File

@@ -1130,7 +1130,7 @@ void RPCCall::fromNetwork (
const int RPC_REPLY_MAX_BYTES (128*1024*1024); const int RPC_REPLY_MAX_BYTES (128*1024*1024);
const int RPC_NOTIFY_SECONDS (30); const int RPC_NOTIFY_SECONDS (30);
HttpsClient::httpsRequest ( HTTPClient::request (
bSSL, bSSL,
io_service, io_service,
strIp, strIp,