diff --git a/example/http/async_client/main.cc b/example/http/async_client/main.cc index 3bf0e07..6516cb1 100644 --- a/example/http/async_client/main.cc +++ b/example/http/async_client/main.cc @@ -3,7 +3,7 @@ #include "boost/asio/io_context.hpp" #include "webcc/logger.h" -#include "webcc/http_async_client.h" +#include "webcc/async_http_client.h" // In order to test this client, create a file index.html whose content is // simply "Hello, World!", then start a HTTP server with Python 3: @@ -19,15 +19,20 @@ void Test(boost::asio::io_context& ioc) { request->Build(); - webcc::HttpAsyncClientPtr client(new webcc::HttpAsyncClient(ioc)); + webcc::HttpAsyncClientPtr client(new webcc::AsyncHttpClient(ioc)); // Response handler. auto handler = [](std::shared_ptr response, - webcc::Error error) { + webcc::Error error, + bool timed_out) { if (error == webcc::kNoError) { std::cout << response->content() << std::endl; } else { - std::cout << webcc::DescribeError(error) << std::endl; + std::cout << webcc::DescribeError(error); + if (timed_out) { + std::cout << " (timed out)"; + } + std::cout << std::endl; } }; diff --git a/example/rest/book_async_client/main.cc b/example/rest/book_async_client/main.cc index 6f26bf5..51b0ceb 100644 --- a/example/rest/book_async_client/main.cc +++ b/example/rest/book_async_client/main.cc @@ -3,7 +3,7 @@ #include "json/json.h" #include "webcc/logger.h" -#include "webcc/rest_async_client.h" +#include "webcc/async_rest_client.h" // ----------------------------------------------------------------------------- @@ -44,7 +44,7 @@ class BookListClient { } private: - webcc::RestAsyncClient rest_client_; + webcc::AsyncRestClient rest_client_; }; // ----------------------------------------------------------------------------- @@ -84,7 +84,7 @@ public: } private: - webcc::RestAsyncClient rest_client_; + webcc::AsyncRestClient rest_client_; }; // ----------------------------------------------------------------------------- @@ -113,7 +113,8 @@ int main(int argc, char* argv[]) { // Response handler. auto handler = [](std::shared_ptr response, - webcc::Error error) { + webcc::Error error, + bool timed_out) { if (error == webcc::kNoError) { std::cout << response->content() << std::endl; } else { diff --git a/example/rest/book_client/main.cc b/example/rest/book_client/main.cc index 10afa3c..e24db3a 100644 --- a/example/rest/book_client/main.cc +++ b/example/rest/book_client/main.cc @@ -34,8 +34,8 @@ protected: void PrintError() { std::cout << webcc::DescribeError(rest_client_.error()); - if (rest_client_.timeout_occurred()) { - std::cout << " (timeout)"; + if (rest_client_.timed_out()) { + std::cout << " (timed out)"; } std::cout << std::endl; } diff --git a/src/webcc/CMakeLists.txt b/src/webcc/CMakeLists.txt index 4191382..6969bd0 100644 --- a/src/webcc/CMakeLists.txt +++ b/src/webcc/CMakeLists.txt @@ -2,10 +2,12 @@ add_definitions(-DBOOST_ASIO_NO_DEPRECATED) set(SRCS + async_http_client.cc + async_http_client.h + async_rest_client.cc + async_rest_client.h globals.cc globals.h - http_async_client.cc - http_async_client.h http_client.cc http_client.h http_connection.cc @@ -29,8 +31,6 @@ set(SRCS logger.cc logger.h queue.h - rest_async_client.cc - rest_async_client.h rest_client.cc rest_client.h rest_request_handler.cc @@ -48,7 +48,23 @@ set(SRCS if(WEBCC_ENABLE_SOAP) # SOAP specific sources. - file(GLOB SOAP_SRCS soap_*.cc soap_*.h) + set(SOAP_SRCS + soap_client.cc + soap_message.h + soap_request_handler.cc + soap_response.h + soap_xml.cc + soap_client.h + soap_request.cc + soap_request_handler.h + soap_server.h + soap_xml.h + soap_message.cc + soap_request.h + soap_response.cc + soap_service.h + ) + set(SRCS ${SRCS} ${SOAP_SRCS}) endif() diff --git a/src/webcc/async_http_client.cc b/src/webcc/async_http_client.cc new file mode 100644 index 0000000..ee35b75 --- /dev/null +++ b/src/webcc/async_http_client.cc @@ -0,0 +1,215 @@ +#include "webcc/async_http_client.h" + +#include "boost/asio/connect.hpp" +#include "boost/asio/read.hpp" +#include "boost/asio/write.hpp" + +#include "webcc/logger.h" +#include "webcc/utility.h" + +// NOTE: +// The timeout control is inspired by the following Asio example: +// example\cpp03\timeouts\async_tcp_client.cpp + +namespace webcc { + +AsyncHttpClient::AsyncHttpClient(boost::asio::io_context& io_context) + : socket_(io_context), + timeout_seconds_(kMaxReceiveSeconds), + deadline_(io_context) { + resolver_.reset(new tcp::resolver(io_context)); + response_.reset(new HttpResponse()); + response_parser_.reset(new HttpResponseParser(response_.get())); +} + +Error AsyncHttpClient::Request(std::shared_ptr request, + HttpResponseHandler response_handler) { + assert(request); + assert(response_handler); + + LOG_VERB("HTTP request:\n%s", request->Dump(4, "> ").c_str()); + + request_ = request; + response_handler_ = response_handler; + + std::string port = request->port(); + if (port.empty()) { + port = "80"; + } + + auto handler = std::bind(&AsyncHttpClient::ResolveHandler, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2); + + resolver_->async_resolve(tcp::v4(), request->host(), port, handler); + + return kNoError; +} + +void AsyncHttpClient::Stop() { + stopped_ = true; + boost::system::error_code ignored_ec; + socket_.close(ignored_ec); + deadline_.cancel(); +} + +void AsyncHttpClient::ResolveHandler(boost::system::error_code ec, + tcp::resolver::results_type results) { + if (ec) { + LOG_ERRO("Can't resolve host (%s): %s, %s", ec.message().c_str(), + request_->host().c_str(), request_->port().c_str()); + response_handler_(response_, kHostResolveError, timed_out_); + } else { + // Start the connect actor. + endpoints_ = results; + AsyncConnect(endpoints_.begin()); + + // Start the deadline actor. You will note that we're not setting any + // particular deadline here. Instead, the connect and input actors will + // update the deadline prior to each asynchronous operation. + deadline_.async_wait(std::bind(&AsyncHttpClient::CheckDeadline, this)); + } +} + +void AsyncHttpClient::AsyncConnect(EndpointIterator endpoint_iter) { + if (endpoint_iter != endpoints_.end()) { + LOG_VERB("Connecting to [%s]...", + EndpointToString(endpoint_iter->endpoint()).c_str()); + + // Set a deadline for the connect operation. + deadline_.expires_from_now(boost::posix_time::seconds(kMaxConnectSeconds)); + + timed_out_ = false; + + // Start the asynchronous connect operation. + socket_.async_connect(endpoint_iter->endpoint(), + std::bind(&AsyncHttpClient::ConnectHandler, + shared_from_this(), + std::placeholders::_1, + endpoint_iter)); + } else { + // There are no more endpoints to try. Shut down the client. + Stop(); + response_handler_(response_, kEndpointConnectError, timed_out_); + } +} + +void AsyncHttpClient::ConnectHandler(boost::system::error_code ec, + EndpointIterator endpoint_iter) { + if (stopped_) { + return; + } + + if (!socket_.is_open()) { + // The async_connect() function automatically opens the socket at the start + // of the asynchronous operation. If the socket is closed at this time then + // the timeout handler must have run first. + LOG_WARN("Connect timed out."); + + // Try the next available endpoint. + AsyncConnect(++endpoint_iter); + } else if (ec) { + // The connect operation failed before the deadline expired. + // We need to close the socket used in the previous connection attempt + // before starting a new one. + socket_.close(); + + // Try the next available endpoint. + AsyncConnect(++endpoint_iter); + } else { + // Connection established. + AsyncWrite(); + } +} + +void AsyncHttpClient::AsyncWrite() { + if (stopped_) { + return; + } + + deadline_.expires_from_now(boost::posix_time::seconds(kMaxSendSeconds)); + + boost::asio::async_write(socket_, + request_->ToBuffers(), + std::bind(&AsyncHttpClient::WriteHandler, + shared_from_this(), + std::placeholders::_1)); +} + +void AsyncHttpClient::WriteHandler(boost::system::error_code ec) { + if (stopped_) { + return; + } + + if (ec) { + Stop(); + response_handler_(response_, kSocketWriteError, timed_out_); + } else { + deadline_.expires_from_now(boost::posix_time::seconds(timeout_seconds_)); + AsyncRead(); + } +} + +void AsyncHttpClient::AsyncRead() { + socket_.async_read_some(boost::asio::buffer(buffer_), + std::bind(&AsyncHttpClient::ReadHandler, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2)); +} + +void AsyncHttpClient::ReadHandler(boost::system::error_code ec, + std::size_t length) { + if (stopped_) { + return; + } + + if (ec || length == 0) { + Stop(); + response_handler_(response_, kSocketReadError, timed_out_); + return; + } + + // Parse the response piece just read. + // If the content has been fully received, |finished()| will be true. + if (!response_parser_->Parse(buffer_.data(), length)) { + Stop(); + response_handler_(response_, kHttpError, timed_out_); + return; + } + + if (response_parser_->finished()) { + LOG_VERB("HTTP response:\n%s", response_->Dump(4, "> ").c_str()); + Stop(); + response_handler_(response_, kNoError, timed_out_); + return; + } + + AsyncRead(); +} + +void AsyncHttpClient::CheckDeadline() { + if (stopped_) { + return; + } + + if (deadline_.expires_at() <= + boost::asio::deadline_timer::traits_type::now()) { + // The deadline has passed. + // The socket is closed so that any outstanding asynchronous operations + // are canceled. + boost::system::error_code ignored_ec; + socket_.close(ignored_ec); + + deadline_.expires_at(boost::posix_time::pos_infin); + + timed_out_ = true; + } + + // Put the actor back to sleep. + deadline_.async_wait(std::bind(&AsyncHttpClient::CheckDeadline, + shared_from_this())); +} + +} // namespace webcc diff --git a/src/webcc/http_async_client.h b/src/webcc/async_http_client.h similarity index 63% rename from src/webcc/http_async_client.h rename to src/webcc/async_http_client.h index 6825b65..817db9d 100644 --- a/src/webcc/http_async_client.h +++ b/src/webcc/async_http_client.h @@ -1,5 +1,5 @@ -#ifndef WEBCC_HTTP_ASYNC_CLIENT_H_ -#define WEBCC_HTTP_ASYNC_CLIENT_H_ +#ifndef WEBCC_ASYNC_HTTP_CLIENT_H_ +#define WEBCC_ASYNC_HTTP_CLIENT_H_ #include #include @@ -16,13 +16,13 @@ namespace webcc { -typedef std::function HttpResponseHandler; +typedef std::function HttpResponseHandler; -class HttpAsyncClient : public std::enable_shared_from_this { +class AsyncHttpClient : public std::enable_shared_from_this { public: - explicit HttpAsyncClient(boost::asio::io_context& io_context); + explicit AsyncHttpClient(boost::asio::io_context& io_context); - DELETE_COPY_AND_ASSIGN(HttpAsyncClient); + DELETE_COPY_AND_ASSIGN(AsyncHttpClient); void set_timeout_seconds(int timeout_seconds) { timeout_seconds_ = timeout_seconds; @@ -32,16 +32,22 @@ class HttpAsyncClient : public std::enable_shared_from_this { // and call the |response_handler| when all these finish. Error Request(HttpRequestPtr request, HttpResponseHandler response_handler); + // Terminate all the actors to shut down the connection. It may be called by + // the user of the client class, or by the class itself in response to + // graceful termination or an unrecoverable error. + void Stop(); + private: using tcp = boost::asio::ip::tcp; + typedef tcp::resolver::results_type::iterator EndpointIterator; void ResolveHandler(boost::system::error_code ec, tcp::resolver::results_type results); - void AsyncConnect(tcp::resolver::results_type::iterator endpoint_it); + void AsyncConnect(EndpointIterator endpoint_iter); void ConnectHandler(boost::system::error_code ec, - tcp::resolver::results_type::iterator endpoint_it); + EndpointIterator endpoint_iter); void AsyncWrite(); void WriteHandler(boost::system::error_code ec); @@ -51,6 +57,9 @@ class HttpAsyncClient : public std::enable_shared_from_this { void CheckDeadline(); + bool stopped_ = false; + bool timed_out_ = false; + tcp::socket socket_; std::shared_ptr request_; @@ -70,11 +79,11 @@ class HttpAsyncClient : public std::enable_shared_from_this { int timeout_seconds_; // Timer for the timeout control. - boost::asio::deadline_timer deadline_timer_; + boost::asio::deadline_timer deadline_; }; -typedef std::shared_ptr HttpAsyncClientPtr; +typedef std::shared_ptr HttpAsyncClientPtr; } // namespace webcc -#endif // WEBCC_HTTP_ASYNC_CLIENT_H_ +#endif // WEBCC_ASYNC_HTTP_CLIENT_H_ diff --git a/src/webcc/rest_async_client.cc b/src/webcc/async_rest_client.cc similarity index 77% rename from src/webcc/rest_async_client.cc rename to src/webcc/async_rest_client.cc index dc0ea58..d2c26ce 100644 --- a/src/webcc/rest_async_client.cc +++ b/src/webcc/async_rest_client.cc @@ -1,8 +1,8 @@ -#include "webcc/rest_async_client.h" +#include "webcc/async_rest_client.h" namespace webcc { -void RestAsyncClient::Request(const std::string& method, +void AsyncRestClient::Request(const std::string& method, const std::string& url, const std::string& content, HttpResponseHandler response_handler) { @@ -20,7 +20,7 @@ void RestAsyncClient::Request(const std::string& method, request->Build(); - HttpAsyncClientPtr http_client(new HttpAsyncClient(io_context_)); + HttpAsyncClientPtr http_client(new AsyncHttpClient(io_context_)); http_client->Request(request, response_handler_); } diff --git a/src/webcc/rest_async_client.h b/src/webcc/async_rest_client.h similarity index 82% rename from src/webcc/rest_async_client.h rename to src/webcc/async_rest_client.h index 5cdfba1..bde667c 100644 --- a/src/webcc/rest_async_client.h +++ b/src/webcc/async_rest_client.h @@ -1,17 +1,17 @@ -#ifndef WEBCC_REST_ASYNC_CLIENT_H_ -#define WEBCC_REST_ASYNC_CLIENT_H_ +#ifndef WEBCC_ASYNC_REST_CLIENT_H_ +#define WEBCC_ASYNC_REST_CLIENT_H_ #include #include "webcc/globals.h" -#include "webcc/http_async_client.h" +#include "webcc/async_http_client.h" namespace webcc { -class RestAsyncClient { +class AsyncRestClient { public: - RestAsyncClient(boost::asio::io_context& io_context, - const std::string& host, const std::string& port) + AsyncRestClient(boost::asio::io_context& io_context, + const std::string& host, const std::string& port) : io_context_(io_context), host_(host), port_(port) { } @@ -57,4 +57,4 @@ class RestAsyncClient { } // namespace webcc -#endif // WEBCC_REST_ASYNC_CLIENT_H_ +#endif // WEBCC_ASYNC_REST_CLIENT_H_ diff --git a/src/webcc/http_async_client.cc b/src/webcc/http_async_client.cc deleted file mode 100644 index 23f55c0..0000000 --- a/src/webcc/http_async_client.cc +++ /dev/null @@ -1,155 +0,0 @@ -#include "webcc/http_async_client.h" - -#include "boost/asio/connect.hpp" -#include "boost/asio/read.hpp" -#include "boost/asio/write.hpp" - -#include "webcc/logger.h" - -namespace webcc { - -HttpAsyncClient::HttpAsyncClient(boost::asio::io_context& io_context) - : socket_(io_context), - timeout_seconds_(kMaxReceiveSeconds), - deadline_timer_(io_context) { - resolver_.reset(new tcp::resolver(io_context)); - response_.reset(new HttpResponse()); - response_parser_.reset(new HttpResponseParser(response_.get())); - - deadline_timer_.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - CheckDeadline(); -} - -Error HttpAsyncClient::Request(std::shared_ptr request, - HttpResponseHandler response_handler) { - assert(request); - assert(response_handler); - - request_ = request; - response_handler_ = response_handler; - - std::string port = request->port(); - if (port.empty()) { - port = "80"; - } - - auto handler = std::bind(&HttpAsyncClient::ResolveHandler, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2); - - resolver_->async_resolve(tcp::v4(), request->host(), port, handler); - - return kNoError; -} - -void HttpAsyncClient::ResolveHandler(boost::system::error_code ec, - tcp::resolver::results_type results) { - if (ec) { - LOG_ERRO("Can't resolve host (%s): %s, %s", ec.message().c_str(), - request_->host().c_str(), request_->port().c_str()); - response_handler_(response_, kHostResolveError); - } else { - endpoints_ = results; - AsyncConnect(endpoints_.begin()); - } -} - -void HttpAsyncClient::AsyncConnect(tcp::resolver::results_type::iterator endpoint_it) { - if (endpoint_it != endpoints_.end()) { - deadline_timer_.expires_from_now( - boost::posix_time::seconds(kMaxConnectSeconds)); - - socket_.async_connect(endpoint_it->endpoint(), - std::bind(&HttpAsyncClient::ConnectHandler, - shared_from_this(), - std::placeholders::_1, - endpoint_it)); - } -} - -void HttpAsyncClient::ConnectHandler( - boost::system::error_code ec, - tcp::resolver::results_type::iterator endpoint_it) { - if (ec) { - // Will be here if the endpoint is IPv6. - response_handler_(response_, kEndpointConnectError); - socket_.close(); - // Try the next available endpoint. - AsyncConnect(++endpoint_it); - } else { - AsyncWrite(); - } -} - -void HttpAsyncClient::AsyncWrite() { - deadline_timer_.expires_from_now(boost::posix_time::seconds(kMaxSendSeconds)); - - boost::asio::async_write(socket_, - request_->ToBuffers(), - std::bind(&HttpAsyncClient::WriteHandler, - shared_from_this(), - std::placeholders::_1)); -} - -void HttpAsyncClient::WriteHandler(boost::system::error_code ec) { - if (ec) { - response_handler_(response_, kSocketWriteError); - } else { - AsyncRead(); - } -} - -void HttpAsyncClient::AsyncRead() { - deadline_timer_.expires_from_now( - boost::posix_time::seconds(timeout_seconds_)); - - socket_.async_read_some(boost::asio::buffer(buffer_), - std::bind(&HttpAsyncClient::ReadHandler, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2)); -} - -void HttpAsyncClient::ReadHandler(boost::system::error_code ec, - std::size_t length) { - if (ec || length == 0) { - response_handler_(response_, kSocketReadError); - return; - } - - // Parse the response piece just read. - // If the content has been fully received, |finished()| will be true. - if (!response_parser_->Parse(buffer_.data(), length)) { - response_handler_(response_, kHttpError); - return; - } - - if (response_parser_->finished()) { - response_handler_(response_, kHttpError); - return; - } - - AsyncRead(); -} - -void HttpAsyncClient::CheckDeadline() { - if (deadline_timer_.expires_at() <= - boost::asio::deadline_timer::traits_type::now()) { - // The deadline has passed. - // The socket is closed so that any outstanding asynchronous operations - // are canceled. - boost::system::error_code ignored_ec; - socket_.close(ignored_ec); - - deadline_timer_.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - deadline_timer_.async_wait(std::bind(&HttpAsyncClient::CheckDeadline, - shared_from_this())); -} - -} // namespace webcc diff --git a/src/webcc/http_client.cc b/src/webcc/http_client.cc index 57d6214..91c2a15 100644 --- a/src/webcc/http_client.cc +++ b/src/webcc/http_client.cc @@ -22,15 +22,15 @@ namespace webcc { HttpClient::HttpClient() : socket_(io_context_), timeout_seconds_(kMaxReceiveSeconds), - deadline_timer_(io_context_) { - deadline_timer_.expires_at(boost::posix_time::pos_infin); + deadline_(io_context_) { + deadline_.expires_at(boost::posix_time::pos_infin); } bool HttpClient::Request(const HttpRequest& request) { response_.reset(new HttpResponse()); response_parser_.reset(new HttpResponseParser(response_.get())); - timeout_occurred_ = false; + timed_out_ = false; // Start the persistent actor that checks for deadline expiry. CheckDeadline(); @@ -69,8 +69,7 @@ Error HttpClient::Connect(const HttpRequest& request) { return kHostResolveError; } - deadline_timer_.expires_from_now( - boost::posix_time::seconds(kMaxConnectSeconds)); + deadline_.expires_from_now(boost::posix_time::seconds(kMaxConnectSeconds)); ec = boost::asio::error::would_block; @@ -90,7 +89,7 @@ Error HttpClient::Connect(const HttpRequest& request) { // or failed. if (ec || !socket_.is_open()) { if (!ec) { - timeout_occurred_ = true; + timed_out_ = true; } return kEndpointConnectError; } @@ -101,7 +100,7 @@ Error HttpClient::Connect(const HttpRequest& request) { Error HttpClient::SendReqeust(const HttpRequest& request) { LOG_VERB("HTTP request:\n%s", request.Dump(4, "> ").c_str()); - deadline_timer_.expires_from_now(boost::posix_time::seconds(kMaxSendSeconds)); + deadline_.expires_from_now(boost::posix_time::seconds(kMaxSendSeconds)); boost::system::error_code ec = boost::asio::error::would_block; @@ -114,7 +113,6 @@ Error HttpClient::SendReqeust(const HttpRequest& request) { io_context_.run_one(); } while (ec == boost::asio::error::would_block); - // TODO: timeout_occurred_ if (ec) { return kSocketWriteError; } @@ -134,8 +132,7 @@ Error HttpClient::ReadResponse() { } void HttpClient::DoReadResponse(Error* error) { - deadline_timer_.expires_from_now( - boost::posix_time::seconds(timeout_seconds_)); + deadline_.expires_from_now(boost::posix_time::seconds(timeout_seconds_)); boost::system::error_code ec = boost::asio::error::would_block; @@ -176,7 +173,7 @@ void HttpClient::DoReadResponse(Error* error) { } void HttpClient::CheckDeadline() { - if (deadline_timer_.expires_at() <= + if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now()) { // The deadline has passed. // The socket is closed so that any outstanding asynchronous operations @@ -184,14 +181,13 @@ void HttpClient::CheckDeadline() { boost::system::error_code ignored_ec; socket_.close(ignored_ec); - // TODO - timeout_occurred_ = true; + deadline_.expires_at(boost::posix_time::pos_infin); - deadline_timer_.expires_at(boost::posix_time::pos_infin); + timed_out_ = true; } // Put the actor back to sleep. - deadline_timer_.async_wait(std::bind(&HttpClient::CheckDeadline, this)); + deadline_.async_wait(std::bind(&HttpClient::CheckDeadline, this)); } } // namespace webcc diff --git a/src/webcc/http_client.h b/src/webcc/http_client.h index 05c15c5..ae926b1 100644 --- a/src/webcc/http_client.h +++ b/src/webcc/http_client.h @@ -31,7 +31,7 @@ class HttpClient { Error error() const { return error_; } - bool timeout_occurred() const { return timeout_occurred_; } + bool timed_out() const { return timed_out_; } // Connect to server, send request, wait until response is received. bool Request(const HttpRequest& request); @@ -59,14 +59,13 @@ class HttpClient { Error error_ = kNoError; // If the error was caused by timeout or not. - bool timeout_occurred_ = false; + bool timed_out_ = false; // Maximum seconds to wait before the client cancels the operation. // Only for receiving response from server. int timeout_seconds_; - // Timer for the timeout control. - boost::asio::deadline_timer deadline_timer_; + boost::asio::deadline_timer deadline_; }; } // namespace webcc diff --git a/src/webcc/rest_client.cc b/src/webcc/rest_client.cc index 7784df6..71cc101 100644 --- a/src/webcc/rest_client.cc +++ b/src/webcc/rest_client.cc @@ -10,7 +10,7 @@ bool RestClient::Request(const std::string& method, const std::string& content) { response_.reset(); error_ = kNoError; - timeout_occurred_ = false; + timed_out_ = false; HttpRequest request; @@ -29,7 +29,7 @@ bool RestClient::Request(const std::string& method, if (!http_client.Request(request)) { error_ = http_client.error(); - timeout_occurred_ = http_client.timeout_occurred(); + timed_out_ = http_client.timed_out(); return false; } diff --git a/src/webcc/rest_client.h b/src/webcc/rest_client.h index b67ffbd..2512324 100644 --- a/src/webcc/rest_client.h +++ b/src/webcc/rest_client.h @@ -33,7 +33,7 @@ class RestClient { Error error() const { return error_; } - bool timeout_occurred() const { return timeout_occurred_; } + bool timed_out() const { return timed_out_; } bool Get(const std::string& url) { return Request(kHttpGet, url, ""); @@ -71,7 +71,7 @@ class RestClient { Error error_ = kNoError; // If the error was caused by timeout or not. - bool timeout_occurred_ = false; + bool timed_out_ = false; }; } // namespace webcc diff --git a/src/webcc/soap_client.cc b/src/webcc/soap_client.cc index 48270ab..7892c2c 100644 --- a/src/webcc/soap_client.cc +++ b/src/webcc/soap_client.cc @@ -55,7 +55,7 @@ Error SoapClient::Call(const std::string& operation, } if (!http_client.Request(http_request)) { - timeout_occurred_ = http_client.timeout_occurred(); + timed_out_ = http_client.timed_out(); return http_client.error(); } diff --git a/src/webcc/soap_client.h b/src/webcc/soap_client.h index e6e4e13..3880f94 100644 --- a/src/webcc/soap_client.h +++ b/src/webcc/soap_client.h @@ -11,12 +11,11 @@ namespace webcc { // Base class for your SOAP client. // Set URL, host, port, etc. in your sub-class before make the call. -// class SoapClient { public: virtual ~SoapClient() = default; - bool timeout_occurred() const { return timeout_occurred_; } + bool timed_out() const { return timed_out_; } protected: SoapClient() = default; @@ -31,7 +30,7 @@ class SoapClient { int timeout_seconds_ = -1; // If the error was caused by timeout or not. - bool timeout_occurred_ = false; + bool timed_out_ = false; SoapNamespace soapenv_ns_; // SOAP envelope namespace. SoapNamespace service_ns_; // Namespace for your web service. diff --git a/src/webcc/utility.cc b/src/webcc/utility.cc index 5e9c1b2..0cf4f67 100644 --- a/src/webcc/utility.cc +++ b/src/webcc/utility.cc @@ -1,28 +1,37 @@ #include "webcc/utility.h" -#include +#include +#include using tcp = boost::asio::ip::tcp; namespace webcc { -// Print the resolved endpoints. -// NOTE: Endpoint is one word, don't use "end point". -void DumpEndpoints(const tcp::resolver::results_type& endpoints) { - std::cout << "Endpoints: " << endpoints.size() << std::endl; +void PrintEndpoint(std::ostream& ostream, + const boost::asio::ip::tcp::endpoint& endpoint) { + ostream << endpoint; + if (endpoint.protocol() == tcp::v4()) { + ostream << ", v4"; + } else if (endpoint.protocol() == tcp::v6()) { + ostream << ", v6"; + } +} +void PrintEndpoints(std::ostream& ostream, + const tcp::resolver::results_type& endpoints) { + ostream << "Endpoints: " << endpoints.size() << std::endl; tcp::resolver::results_type::iterator it = endpoints.begin(); for (; it != endpoints.end(); ++it) { - std::cout << " - " << it->endpoint(); - - if (it->endpoint().protocol() == tcp::v4()) { - std::cout << ", v4"; - } else if (it->endpoint().protocol() == tcp::v6()) { - std::cout << ", v6"; - } - - std::cout << std::endl; + ostream << " - "; + PrintEndpoint(ostream, it->endpoint()); + ostream << std::endl; } } +std::string EndpointToString(const boost::asio::ip::tcp::endpoint& endpoint) { + std::stringstream ss; + PrintEndpoint(ss, endpoint); + return ss.str(); +} + } // namespace webcc diff --git a/src/webcc/utility.h b/src/webcc/utility.h index b49d3b8..9e2ecdb 100644 --- a/src/webcc/utility.h +++ b/src/webcc/utility.h @@ -1,15 +1,22 @@ #ifndef WEBCC_UTILITY_H_ #define WEBCC_UTILITY_H_ +#include +#include + #include "boost/asio/ip/tcp.hpp" namespace webcc { -// Print the resolved endpoints. -// NOTE: Endpoint is one word, don't use "end point". -void DumpEndpoints( +void PrintEndpoint(std::ostream& ostream, + const boost::asio::ip::tcp::endpoint& endpoint); + +void PrintEndpoints( + std::ostream& ostream, const boost::asio::ip::tcp::resolver::results_type& endpoints); +std::string EndpointToString(const boost::asio::ip::tcp::endpoint& endpoint); + } // namespace webcc #endif // WEBCC_UTILITY_H_