diff --git a/modules/ripple_app/peers/ripple_UniqueNodeList.cpp b/modules/ripple_app/peers/ripple_UniqueNodeList.cpp index 399152bc35..44737ec4e6 100644 --- a/modules/ripple_app/peers/ripple_UniqueNodeList.cpp +++ b/modules/ripple_app/peers/ripple_UniqueNodeList.cpp @@ -556,7 +556,7 @@ public: { if (!getConfig ().VALIDATORS_SITE.empty ()) { - HttpsClient::httpsGet ( + HTTPClient::get ( true, getApp().getIOService (), getConfig ().VALIDATORS_SITE, @@ -1434,7 +1434,7 @@ private: deqSites.push_back (str (boost::format ("www.%s") % strDomain)); deqSites.push_back (strDomain); - HttpsClient::httpsGet ( + HTTPClient::get ( true, getApp().getIOService (), deqSites, @@ -1473,7 +1473,7 @@ private: && -1 == iPort && strScheme == "https") { - HttpsClient::httpsGet ( + HTTPClient::get ( true, getApp().getIOService (), strDomain, @@ -1507,7 +1507,7 @@ private: && -1 == iPort && strScheme == "https") { - HttpsClient::httpsGet ( + HTTPClient::get ( true, getApp().getIOService (), strDomain, diff --git a/modules/ripple_app/rpc/RPCHandler.cpp b/modules/ripple_app/rpc/RPCHandler.cpp index d50864a99d..5741932050 100644 --- a/modules/ripple_app/rpc/RPCHandler.cpp +++ b/modules/ripple_app/rpc/RPCHandler.cpp @@ -2729,7 +2729,7 @@ Json::Value RPCHandler::doSMS (Json::Value params, LoadType* loadType, Applicati if (!params.isMember ("text")) return rpcError (rpcINVALID_PARAMS); - HttpsClient::sendSMS (getApp().getIOService (), params["text"].asString ()); + HTTPClient::sendSMS (getApp().getIOService (), params["text"].asString ()); return "sms dispatched"; } diff --git a/modules/ripple_net/basics/HTTPClient.cpp b/modules/ripple_net/basics/HTTPClient.cpp index 3a43be4645..86e8671b0f 100644 --- a/modules/ripple_net/basics/HTTPClient.cpp +++ b/modules/ripple_net/basics/HTTPClient.cpp @@ -5,403 +5,455 @@ //============================================================================== // -// Fetch a web page via https. +// Fetch a web page via http or https. // -SETUP_LOG (HttpsClient) +SETUP_LOG (HTTPClient) -// VFALCO NOTE Why use getConfig ().SSL_CONTEXT instead of just passing it? -// TODO Remove all theConfig deps from this file -// -HttpsClient::HttpsClient (boost::asio::io_service& io_service, - const unsigned short port, - std::size_t responseMax) - : mSocket (io_service, getConfig ().SSL_CONTEXT) - , mResolver (io_service) - , mHeader (maxClientHeaderBytes) - , mPort (port) - , mResponseMax (responseMax) - , mDeadline (io_service) +class HTTPClientImp + : public boost::enable_shared_from_this + , public HTTPClient + , LeakChecked { - if (!getConfig ().SSL_VERIFY) - 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) -{ - 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 deqSites, - FUNCTION_TYPE build, - boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete) -{ - mSSL = bSSL; - mDeqSites = deqSites; - mBuild = build; - mComplete = complete; - mTimeout = timeout; - - httpsNext (); -} - -void HttpsClient::httpsGet ( - bool bSSL, - std::deque deqSites, - const std::string& strPath, - boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete) -{ - - mComplete = complete; - mTimeout = timeout; - - httpsRequest ( - bSSL, - deqSites, - BIND_TYPE (&HttpsClient::makeGet, shared_from_this (), strPath, P_1, P_2), - timeout, - complete); -} - -void HttpsClient::httpsNext () -{ - WriteLog (lsTRACE, HttpsClient) << "Fetch: " << mDeqSites[0]; - - boost::shared_ptr query ( - new boost::asio::ip::tcp::resolver::query ( - mDeqSites[0], - lexicalCast (mPort), - boost::asio::ip::resolver_query_base::numeric_service)); - mQuery = query; - - mDeadline.expires_from_now (mTimeout, mShutdown); - - WriteLog (lsTRACE, HttpsClient) << "expires_from_now: " << mShutdown.message (); - - if (!mShutdown) +public: + // VFALCO NOTE Why use getConfig ().SSL_CONTEXT instead of just passing it? + // TODO Remove all theConfig deps from this file + // + HTTPClientImp (boost::asio::io_service& io_service, + const unsigned short port, + std::size_t responseMax) + : mSocket (io_service, getConfig ().SSL_CONTEXT) + , mResolver (io_service) + , mHeader (maxClientHeaderBytes) + , mPort (port) + , mResponseMax (responseMax) + , mDeadline (io_service) { - mDeadline.async_wait ( - boost::bind ( - &HttpsClient::handleDeadline, - shared_from_this (), - boost::asio::placeholders::error)); + if (!getConfig ().SSL_VERIFY) + mSocket.SSLSocket ().set_verify_mode (boost::asio::ssl::verify_none); } - if (!mShutdown) - { - WriteLog (lsTRACE, HttpsClient) << "Resolving: " << mDeqSites[0]; + //-------------------------------------------------------------------------- - mResolver.async_resolve (*mQuery, - boost::bind ( - &HttpsClient::handleResolve, - shared_from_this (), - boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); + void 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"; } - if (mShutdown) - invokeComplete (mShutdown); -} + //-------------------------------------------------------------------------- -void HttpsClient::handleDeadline (const boost::system::error_code& ecResult) -{ - if (ecResult == boost::asio::error::operation_aborted) + void request ( + bool bSSL, + std::deque deqSites, + FUNCTION_TYPE build, + boost::posix_time::time_duration timeout, + FUNCTION_TYPE complete) { - // Timer canceled because deadline no longer needed. - WriteLog (lsTRACE, HttpsClient) << "Deadline cancelled."; + mSSL = bSSL; + mDeqSites = deqSites; + mBuild = build; + mComplete = complete; + mTimeout = timeout; - nothing (); // Aborter is done. - } - else if (ecResult) - { - WriteLog (lsTRACE, HttpsClient) << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message (); - - // Can't do anything sound. - abort (); - } - else - { - WriteLog (lsTRACE, HttpsClient) << "Deadline arrived."; - - // Mark us as shutting down. - // XXX Use our own error code. - mShutdown = boost::system::error_code (boost::system::errc::bad_address, boost::system::system_category ()); - - // Cancel any resolving. - mResolver.cancel (); - - // Stop the transaction. - mSocket.async_shutdown (boost::bind ( - &HttpsClient::handleShutdown, - shared_from_this (), - boost::asio::placeholders::error)); - - } -} - -void HttpsClient::handleShutdown ( - const boost::system::error_code& ecResult -) -{ - if (ecResult) - { - WriteLog (lsTRACE, HttpsClient) << "Shutdown error: " << mDeqSites[0] << ": " << ecResult.message (); - } -} - -void HttpsClient::handleResolve ( - const boost::system::error_code& ecResult, - boost::asio::ip::tcp::resolver::iterator itrEndpoint -) -{ - if (!mShutdown) - mShutdown = ecResult; - - if (mShutdown) - { - WriteLog (lsTRACE, HttpsClient) << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message (); - - invokeComplete (mShutdown); - } - else - { - WriteLog (lsTRACE, HttpsClient) << "Resolve complete."; - - boost::asio::async_connect ( - mSocket.lowest_layer (), - itrEndpoint, - boost::bind ( - &HttpsClient::handleConnect, - shared_from_this (), - boost::asio::placeholders::error)); - } -} - -void HttpsClient::handleConnect (const boost::system::error_code& ecResult) -{ - if (!mShutdown) - mShutdown = ecResult; - - if (mShutdown) - { - WriteLog (lsTRACE, HttpsClient) << "Connect error: " << mShutdown.message (); + httpsNext (); } - if (!mShutdown) - { - WriteLog (lsTRACE, HttpsClient) << "Connected."; + //-------------------------------------------------------------------------- - if (getConfig ().SSL_VERIFY) + void get ( + bool bSSL, + std::deque deqSites, + const std::string& strPath, + boost::posix_time::time_duration timeout, + FUNCTION_TYPE complete) + { + + mComplete = complete; + mTimeout = timeout; + + request ( + bSSL, + deqSites, + BIND_TYPE (&HTTPClientImp::makeGet, shared_from_this (), strPath, P_1, P_2), + timeout, + complete); + } + + //-------------------------------------------------------------------------- + + void httpsNext () + { + WriteLog (lsTRACE, HTTPClient) << "Fetch: " << mDeqSites[0]; + + boost::shared_ptr query ( + new boost::asio::ip::tcp::resolver::query ( + mDeqSites[0], + lexicalCast (mPort), + boost::asio::ip::resolver_query_base::numeric_service)); + mQuery = query; + + mDeadline.expires_from_now (mTimeout, mShutdown); + + WriteLog (lsTRACE, HTTPClient) << "expires_from_now: " << mShutdown.message (); + + if (!mShutdown) { - mShutdown = mSocket.verify (mDeqSites[0]); + mDeadline.async_wait ( + boost::bind ( + &HTTPClientImp::handleDeadline, + shared_from_this (), + boost::asio::placeholders::error)); + } + if (!mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "Resolving: " << mDeqSites[0]; + + mResolver.async_resolve (*mQuery, + boost::bind ( + &HTTPClientImp::handleResolve, + shared_from_this (), + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); + } + + if (mShutdown) + invokeComplete (mShutdown); + } + + void handleDeadline (const boost::system::error_code& ecResult) + { + if (ecResult == boost::asio::error::operation_aborted) + { + // Timer canceled because deadline no longer needed. + WriteLog (lsTRACE, HTTPClient) << "Deadline cancelled."; + + nothing (); // Aborter is done. + } + else if (ecResult) + { + WriteLog (lsTRACE, HTTPClient) << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message (); + + // Can't do anything sound. + abort (); + } + else + { + WriteLog (lsTRACE, HTTPClient) << "Deadline arrived."; + + // Mark us as shutting down. + // XXX Use our own error code. + mShutdown = boost::system::error_code (boost::system::errc::bad_address, boost::system::system_category ()); + + // Cancel any resolving. + mResolver.cancel (); + + // Stop the transaction. + mSocket.async_shutdown (boost::bind ( + &HTTPClientImp::handleShutdown, + shared_from_this (), + boost::asio::placeholders::error)); + + } + } + + void handleShutdown ( + const boost::system::error_code& ecResult + ) + { + if (ecResult) + { + WriteLog (lsTRACE, HTTPClient) << "Shutdown error: " << mDeqSites[0] << ": " << ecResult.message (); + } + } + + void handleResolve ( + const boost::system::error_code& ecResult, + boost::asio::ip::tcp::resolver::iterator itrEndpoint + ) + { + if (!mShutdown) + mShutdown = ecResult; + + if (mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message (); + + invokeComplete (mShutdown); + } + else + { + WriteLog (lsTRACE, HTTPClient) << "Resolve complete."; + + boost::asio::async_connect ( + mSocket.lowest_layer (), + itrEndpoint, + boost::bind ( + &HTTPClientImp::handleConnect, + shared_from_this (), + boost::asio::placeholders::error)); + } + } + + void handleConnect (const boost::system::error_code& ecResult) + { + if (!mShutdown) + mShutdown = ecResult; + + if (mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "Connect error: " << mShutdown.message (); + } + + if (!mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "Connected."; + + if (getConfig ().SSL_VERIFY) + { + mShutdown = mSocket.verify (mDeqSites[0]); + + if (mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message (); + } + } + } + + if (mShutdown) + { + invokeComplete (mShutdown); + } + else if (mSSL) + { + mSocket.async_handshake ( + AutoSocket::ssl_socket::client, + boost::bind ( + &HTTPClientImp::handleRequest, + shared_from_this (), + boost::asio::placeholders::error)); + } + else + { + handleRequest (ecResult); + } + } + + void handleRequest (const boost::system::error_code& ecResult) + { + if (!mShutdown) + mShutdown = ecResult; + + if (mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "Handshake error:" << mShutdown.message (); + + invokeComplete (mShutdown); + } + else + { + WriteLog (lsTRACE, HTTPClient) << "Session started."; + + mBuild (mRequest, mDeqSites[0]); + + mSocket.async_write ( + mRequest, + boost::bind (&HTTPClientImp::handleWrite, + shared_from_this (), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + } + + void handleWrite (const boost::system::error_code& ecResult, std::size_t bytes_transferred) + { + if (!mShutdown) + mShutdown = ecResult; + + if (mShutdown) + { + WriteLog (lsTRACE, HTTPClient) << "Write error: " << mShutdown.message (); + + invokeComplete (mShutdown); + } + else + { + WriteLog (lsTRACE, HTTPClient) << "Wrote."; + + mSocket.async_read_until ( + mHeader, + "\r\n\r\n", + boost::bind (&HTTPClientImp::handleHeader, + shared_from_this (), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + } + + void handleHeader (const boost::system::error_code& ecResult, std::size_t bytes_transferred) + { + std::string strHeader ((std::istreambuf_iterator (&mHeader)), std::istreambuf_iterator ()); + WriteLog (lsTRACE, HTTPClient) << "Header: \"" << strHeader << "\""; + + 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 reBody ("\\`.*\\r\\n\\r\\n(.*)\\'"); + + boost::smatch smMatch; + + bool bMatch = boost::regex_match (strHeader, smMatch, reStatus); // Match status code. + + if (!bMatch) + { + // XXX Use our own error code. + WriteLog (lsTRACE, HTTPClient) << "No status code"; + invokeComplete (boost::system::error_code (boost::system::errc::bad_address, boost::system::system_category ())); + return; + } + + mStatus = lexicalCastThrow (std::string (smMatch[1])); + + if (boost::regex_match (strHeader, smMatch, reBody)) // we got some body + mBody = smMatch[1]; + + if (boost::regex_match (strHeader, smMatch, reSize)) + { + int size = lexicalCastThrow (std::string(smMatch[1])); + + if (size < mResponseMax) + mResponseMax = size; + } + + if (mResponseMax == 0) + { + // no body wanted or available + invokeComplete (ecResult, mStatus); + } + else if (mBody.size () >= mResponseMax) + { + // we got the whole thing + invokeComplete (ecResult, mStatus, mBody); + } + else + { + mSocket.async_read ( + mResponse.prepare (mResponseMax - mBody.size ()), + boost::asio::transfer_all (), + boost::bind (&HTTPClientImp::handleData, + shared_from_this (), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + } + + void handleData (const boost::system::error_code& ecResult, std::size_t bytes_transferred) + { + if (!mShutdown) + mShutdown = ecResult; + + if (mShutdown && mShutdown != boost::asio::error::eof) + { + WriteLog (lsTRACE, HTTPClient) << "Read error: " << mShutdown.message (); + + invokeComplete (mShutdown); + } + else + { if (mShutdown) { - WriteLog (lsTRACE, HttpsClient) << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message (); + WriteLog (lsTRACE, HTTPClient) << "Complete."; + + nothing (); + } + else + { + mResponse.commit (bytes_transferred); + std::string strBody ((std::istreambuf_iterator (&mResponse)), std::istreambuf_iterator ()); + invokeComplete (ecResult, mStatus, mBody + strBody); } } } - if (mShutdown) + // Call cancel the deadline timer and invoke the completion routine. + void invokeComplete (const boost::system::error_code& ecResult, int iStatus = 0, const std::string& strData = "") { - 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); - } -} + boost::system::error_code ecCancel; -void HttpsClient::handleRequest (const boost::system::error_code& ecResult) -{ - if (!mShutdown) - mShutdown = ecResult; + (void) mDeadline.cancel (ecCancel); - if (mShutdown) - { - WriteLog (lsTRACE, HttpsClient) << "Handshake error:" << mShutdown.message (); - - invokeComplete (mShutdown); - } - else - { - WriteLog (lsTRACE, HttpsClient) << "Session started."; - - mBuild (mRequest, mDeqSites[0]); - - mSocket.async_write ( - mRequest, - boost::bind (&HttpsClient::handleWrite, - shared_from_this (), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } -} - -void HttpsClient::handleWrite (const boost::system::error_code& ecResult, std::size_t bytes_transferred) -{ - if (!mShutdown) - mShutdown = ecResult; - - if (mShutdown) - { - WriteLog (lsTRACE, HttpsClient) << "Write error: " << mShutdown.message (); - - invokeComplete (mShutdown); - } - else - { - WriteLog (lsTRACE, HttpsClient) << "Wrote."; - - mSocket.async_read_until ( - mHeader, - "\r\n\r\n", - boost::bind (&HttpsClient::handleHeader, - shared_from_this (), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } -} - -void HttpsClient::handleHeader (const boost::system::error_code& ecResult, std::size_t bytes_transferred) -{ - std::string strHeader ((std::istreambuf_iterator (&mHeader)), std::istreambuf_iterator ()); - WriteLog (lsTRACE, HttpsClient) << "Header: \"" << strHeader << "\""; - - 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 reBody ("\\`.*\\r\\n\\r\\n(.*)\\'"); - - boost::smatch smMatch; - - bool bMatch = boost::regex_match (strHeader, smMatch, reStatus); // Match status code. - - if (!bMatch) - { - // XXX Use our own error code. - WriteLog (lsTRACE, HttpsClient) << "No status code"; - invokeComplete (boost::system::error_code (boost::system::errc::bad_address, boost::system::system_category ())); - return; - } - - mStatus = lexicalCastThrow (std::string (smMatch[1])); - - if (boost::regex_match (strHeader, smMatch, reBody)) // we got some body - mBody = smMatch[1]; - - if (boost::regex_match (strHeader, smMatch, reSize)) - { - int size = lexicalCastThrow (std::string(smMatch[1])); - - if (size < mResponseMax) - mResponseMax = size; - } - - if (mResponseMax == 0) - { - // no body wanted or available - invokeComplete (ecResult, mStatus); - } - else if (mBody.size () >= mResponseMax) - { - // we got the whole thing - invokeComplete (ecResult, mStatus, mBody); - } - else - { - mSocket.async_read ( - mResponse.prepare (mResponseMax - mBody.size ()), - boost::asio::transfer_all (), - boost::bind (&HttpsClient::handleData, - shared_from_this (), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } -} - -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) - { - WriteLog (lsTRACE, HttpsClient) << "Read error: " << mShutdown.message (); - - invokeComplete (mShutdown); - } - else - { - if (mShutdown) + if (ecCancel) { - WriteLog (lsTRACE, HttpsClient) << "Complete."; - - nothing (); + WriteLog (lsTRACE, HTTPClient) << "invokeComplete: Deadline cancel error: " << ecCancel.message (); } - else + + WriteLog (lsDEBUG, HTTPClient) << "invokeComplete: Deadline popping: " << mDeqSites.size (); + + if (!mDeqSites.empty ()) { - mResponse.commit (bytes_transferred); - std::string strBody ((std::istreambuf_iterator (&mResponse)), std::istreambuf_iterator ()); - invokeComplete (ecResult, mStatus, mBody + strBody); + mDeqSites.pop_front (); + } + + bool bAgain = true; + + if (mDeqSites.empty () || !ecResult) + { + // 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); + } + + if (!mDeqSites.empty () && bAgain) + { + httpsNext (); } } -} -// 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) -{ - boost::system::error_code ecCancel; - - (void) mDeadline.cancel (ecCancel); - - if (ecCancel) + static bool onSMSResponse (const boost::system::error_code& ecResult, int iStatus, const std::string& strData) { - WriteLog (lsTRACE, HttpsClient) << "HttpsClient::invokeComplete: Deadline cancel error: " << ecCancel.message (); + WriteLog (lsINFO, HTTPClient) << "SMS: Response:" << iStatus << " :" << strData; + + return true; } - WriteLog (lsDEBUG, HttpsClient) << "HttpsClient::invokeComplete: Deadline popping: " << mDeqSites.size (); +private: + typedef boost::shared_ptr pointer; - if (!mDeqSites.empty ()) - { - mDeqSites.pop_front (); - } + bool mSSL; + AutoSocket mSocket; + boost::asio::ip::tcp::resolver mResolver; + boost::shared_ptr 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 mBuild; + FUNCTION_TYPE mComplete; - bool bAgain = true; + boost::asio::deadline_timer mDeadline; - if (mDeqSites.empty () || !ecResult) - { - // 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); - } + // If not success, we are shutting down. + boost::system::error_code mShutdown; - if (!mDeqSites.empty () && bAgain) - { - httpsNext (); - } -} + std::deque mDeqSites; + boost::posix_time::time_duration mTimeout; +}; -void HttpsClient::httpsGet ( +//------------------------------------------------------------------------------ + +void HTTPClient::get ( bool bSSL, boost::asio::io_service& io_service, std::deque deqSites, @@ -409,15 +461,16 @@ void HttpsClient::httpsGet ( const std::string& strPath, std::size_t responseMax, boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete) + FUNCTION_TYPE complete) { + boost::shared_ptr client ( + new HTTPClientImp (io_service, port, responseMax)); - boost::shared_ptr client (new HttpsClient (io_service, port, responseMax)); - - client->httpsGet (bSSL, deqSites, strPath, timeout, complete); + client->get (bSSL, deqSites, strPath, timeout, complete); } -void HttpsClient::httpsGet ( +void HTTPClient::get ( bool bSSL, boost::asio::io_service& io_service, std::string strSite, @@ -425,17 +478,18 @@ void HttpsClient::httpsGet ( const std::string& strPath, std::size_t responseMax, boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete) + FUNCTION_TYPE complete) { - std::deque deqSites (1, strSite); - boost::shared_ptr client (new HttpsClient (io_service, port, responseMax)); + boost::shared_ptr 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, boost::asio::io_service& io_service, std::string strSite, @@ -443,26 +497,18 @@ void HttpsClient::httpsRequest ( FUNCTION_TYPE setRequest, std::size_t responseMax, boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete) + FUNCTION_TYPE complete) { - std::deque deqSites (1, strSite); - boost::shared_ptr client (new HttpsClient (io_service, port, responseMax)); + boost::shared_ptr 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 - -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) +void HTTPClient::sendSMS (boost::asio::io_service& io_service, const std::string& strText) { std::string strScheme; 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)) { - WriteLog (lsWARNING, HttpsClient) << "SMSRequest: Bad URL:" << getConfig ().SMS_URL; + WriteLog (lsWARNING, HTTPClient) << "SMSRequest: Bad URL:" << getConfig ().SMS_URL; } else { - bool bSSL = strScheme == "https"; + bool const bSSL = strScheme == "https"; std::deque deqSites (1, strDomain); std::string strURI = @@ -488,15 +534,16 @@ void HttpsClient::sendSMS (boost::asio::io_service& io_service, const std::strin % urlEncode (strText)); // WriteLog (lsINFO) << "SMS: Request:" << strURI; - WriteLog (lsINFO, HttpsClient) << "SMS: Request: '" << strText << "'"; + WriteLog (lsINFO, HTTPClient) << "SMS: Request: '" << strText << "'"; if (iPort < 0) iPort = bSSL ? 443 : 80; - boost::shared_ptr client (new HttpsClient (io_service, iPort, maxClientHeaderBytes)); + boost::shared_ptr client ( + new HTTPClientImp (io_service, iPort, maxClientHeaderBytes)); - client->httpsGet (bSSL, deqSites, strURI, boost::posix_time::seconds (SMS_TIMEOUT), - BIND_TYPE (&responseSMS, P_1, P_2, P_3)); + client->get (bSSL, deqSites, strURI, boost::posix_time::seconds (smsTimeoutSeconds), + BIND_TYPE (&HTTPClientImp::onSMSResponse, P_1, P_2, P_3)); } } -// vim:ts=4 + diff --git a/modules/ripple_net/basics/HTTPClient.h b/modules/ripple_net/basics/HTTPClient.h index 4cbd765128..0ffabf6526 100644 --- a/modules/ripple_net/basics/HTTPClient.h +++ b/modules/ripple_net/basics/HTTPClient.h @@ -7,43 +7,17 @@ #ifndef RIPPLE_NET_BASICS_HTTPCLIENT_H_INCLUDED #define RIPPLE_NET_BASICS_HTTPCLIENT_H_INCLUDED -// VFALCO TODO Make this an abstract interface. -// -/** Provides an asynchronous HTTPS client implementation. +/** Provides an asynchronous HTTP client implementation with optional SSL. */ -class HttpsClient - : public boost::enable_shared_from_this - , LeakChecked +class HTTPClient { public: - HttpsClient ( - boost::asio::io_service& io_service, - const unsigned short port, - std::size_t responseMax - ); + enum + { + maxClientHeaderBytes = 32 * 1024 + }; - // VFALCO NOTE Putting "https" is redundant, the class is - // already called HttpsClient. - // - // VFALCO TODO Rename these to request, get, and next. - // - void httpsRequest ( - bool bSSL, - std::deque deqSites, - FUNCTION_TYPE build, - boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete); - - void httpsGet ( - bool bSSL, - std::deque deqSites, - const std::string& strPath, - boost::posix_time::time_duration timeout, - FUNCTION_TYPE complete); - - // VFALCO TODO These statics all belong in some HttpsClientOperations class - // - static void httpsGet ( + static void get ( bool bSSL, boost::asio::io_service& io_service, std::deque deqSites, @@ -53,7 +27,7 @@ public: boost::posix_time::time_duration timeout, FUNCTION_TYPE complete); - static void httpsGet ( + static void get ( bool bSSL, boost::asio::io_service& io_service, std::string strSite, @@ -63,7 +37,7 @@ public: boost::posix_time::time_duration timeout, FUNCTION_TYPE complete); - static void httpsRequest ( + static void request ( bool bSSL, boost::asio::io_service& io_service, std::string strSite, @@ -73,57 +47,12 @@ public: boost::posix_time::time_duration timeout, FUNCTION_TYPE complete); + enum + { + smsTimeoutSeconds = 30 + }; + static void sendSMS (boost::asio::io_service& io_service, const std::string& strText); - -private: - static const int maxClientHeaderBytes = 32 * 1024; - - typedef boost::shared_ptr pointer; - - bool mSSL; - AutoSocket mSocket; - boost::asio::ip::tcp::resolver mResolver; - boost::shared_ptr 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 mBuild; - FUNCTION_TYPE mComplete; - - boost::asio::deadline_timer mDeadline; - - // If not success, we are shutting down. - boost::system::error_code mShutdown; - - std::deque 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 - diff --git a/modules/ripple_net/rpc/RPCCall.cpp b/modules/ripple_net/rpc/RPCCall.cpp index b9eed3b1d5..483ce7fd78 100644 --- a/modules/ripple_net/rpc/RPCCall.cpp +++ b/modules/ripple_net/rpc/RPCCall.cpp @@ -1130,7 +1130,7 @@ void RPCCall::fromNetwork ( const int RPC_REPLY_MAX_BYTES (128*1024*1024); const int RPC_NOTIFY_SECONDS (30); - HttpsClient::httpsRequest ( + HTTPClient::request ( bSSL, io_service, strIp,