20 #include <boost/enable_shared_from_this.hpp>
21 #include <boost/weak_ptr.hpp>
37 namespace ph = std::placeholders;
44 constexpr
size_t MAX_LOGGED_MESSAGE_SIZE = 1024;
47 typedef std::function<void(boost::system::error_code ec, size_t length)>
48 SocketCallbackFunction;
55 class SocketCallback {
63 SocketCallback(SocketCallbackFunction socket_callback)
73 void operator()(boost::system::error_code ec,
size_t length = 0) {
74 if (ec.value() == boost::asio::error::operation_aborted) {
90 typedef boost::shared_ptr<ConnectionPool> ConnectionPoolPtr;
107 class Connection :
public boost::enable_shared_from_this<Connection> {
117 explicit Connection(
IOService& io_service,
119 const ConnectionPoolPtr& conn_pool,
145 const long request_timeout,
157 bool isTransactionOngoing()
const {
164 bool isClosed()
const {
172 void isClosedByPeer();
179 bool isMySocket(
int socket_fd)
const;
196 bool checkPrematureTimeout(
const uint64_t transid);
222 const long request_timeout,
231 void closeInternal();
239 void isClosedByPeerInternal();
258 bool checkPrematureTimeoutInternal(
const uint64_t transid);
277 void terminate(
const boost::system::error_code& ec,
278 const std::string& parsing_error =
"");
291 void terminateInternal(
const boost::system::error_code& ec,
292 const std::string& parsing_error =
"");
300 bool runParser(
const boost::system::error_code& ec,
size_t length);
310 bool runParserInternal(
const boost::system::error_code& ec,
size_t length);
315 void scheduleTimer(
const long request_timeout);
322 void doHandshake(
const uint64_t transid);
329 void doSend(
const uint64_t transid);
336 void doReceive(
const uint64_t transid);
349 const uint64_t transid,
350 const boost::system::error_code& ec);
362 const uint64_t transid,
363 const boost::system::error_code& ec);
375 void sendCallback(
const uint64_t transid,
const boost::system::error_code& ec,
384 void receiveCallback(
const uint64_t transid,
const boost::system::error_code& ec,
388 void timerCallback();
399 void closeCallback(
const bool clear =
false);
405 boost::weak_ptr<ConnectionPool> conn_pool_;
414 std::unique_ptr<TCPSocket<SocketCallback> > tcp_socket_;
417 std::unique_ptr<TLSSocket<SocketCallback> > tls_socket_;
438 std::array<char, 32768> input_buf_;
441 uint64_t current_transid_;
450 std::atomic<bool> started_;
453 std::atomic<bool> need_handshake_;
456 std::atomic<bool> closed_;
463 typedef boost::shared_ptr<Connection> ConnectionPtr;
472 class ConnectionPool :
public boost::enable_shared_from_this<ConnectionPool> {
481 explicit ConnectionPool(
IOService& io_service,
size_t max_url_connections)
482 : io_service_(io_service), destinations_(), pool_mutex_(),
483 max_url_connections_(max_url_connections) {
499 if (MultiThreadingMgr::instance().getMode()) {
500 std::lock_guard<std::mutex> lk(pool_mutex_);
501 return (processNextRequestInternal(url, tls_context));
503 return (processNextRequestInternal(url, tls_context));
512 void postProcessNextRequest(
const Url& url,
514 io_service_.post(std::bind(&ConnectionPool::processNextRequest,
515 shared_from_this(), url, tls_context));
538 void queueRequest(
const Url& url,
542 const long request_timeout,
547 if (MultiThreadingMgr::instance().getMode()) {
548 std::lock_guard<std::mutex> lk(pool_mutex_);
549 return (queueRequestInternal(url, tls_context, request, response,
550 request_timeout, request_callback,
551 connect_callback, handshake_callback,
554 return (queueRequestInternal(url, tls_context, request, response,
555 request_timeout, request_callback,
556 connect_callback, handshake_callback,
564 if (MultiThreadingMgr::instance().getMode()) {
565 std::lock_guard<std::mutex> lk(pool_mutex_);
584 void closeIfOutOfBand(
int socket_fd) {
585 if (MultiThreadingMgr::instance().getMode()) {
586 std::lock_guard<std::mutex> lk(pool_mutex_);
587 closeIfOutOfBandInternal(socket_fd);
589 closeIfOutOfBandInternal(socket_fd);
602 void processNextRequestInternal(
const Url& url,
606 DestinationPtr destination = findDestination(url, tls_context);
609 destination->garbageCollectConnections();
610 if (!destination->queueEmpty()) {
613 ConnectionPtr connection = destination->getIdleConnection();
616 if (destination->connectionsFull()) {
621 connection.reset(
new Connection(io_service_, tls_context,
622 shared_from_this(), url));
623 destination->addConnection(connection);
628 RequestDescriptor desc = destination->popNextRequest();
629 connection->doTransaction(desc.request_, desc.response_,
630 desc.request_timeout_, desc.callback_,
631 desc.connect_callback_,
632 desc.handshake_callback_,
633 desc.close_callback_);
660 void queueRequestInternal(
const Url& url,
664 const long request_timeout,
669 ConnectionPtr connection;
671 DestinationPtr destination = findDestination(url, tls_context);
674 destination->garbageCollectConnections();
676 connection = destination->getIdleConnection();
679 destination = addDestination(url, tls_context);
683 if (destination->connectionsFull()) {
685 destination->pushRequest(RequestDescriptor(request, response,
695 connection.reset(
new Connection(io_service_, tls_context,
696 shared_from_this(), url));
697 destination->addConnection(connection);
701 connection->doTransaction(request, response, request_timeout, request_callback,
702 connect_callback, handshake_callback, close_callback);
709 void closeAllInternal() {
710 for (
auto const& destination : destinations_) {
711 destination.second->closeAllConnections();
714 destinations_.clear();
731 void closeIfOutOfBandInternal(
int socket_fd) {
732 for (
auto const& destination : destinations_) {
734 ConnectionPtr connection = destination.second->findBySocketFd(socket_fd);
736 if (!connection->isTransactionOngoing()) {
742 destination.second->closeConnection(connection);
752 struct RequestDescriptor {
768 const long& request_timeout,
773 : request_(request), response_(response),
774 request_timeout_(request_timeout),
callback_(callback),
775 connect_callback_(connect_callback),
776 handshake_callback_(handshake_callback),
777 close_callback_(close_callback) {
787 long request_timeout_;
803 typedef std::pair<Url, TlsContextPtr> DestinationDescriptor;
815 : url_(url), tls_context_(tls_context),
816 max_connections_(max_connections), connections_(), queue_() {
821 closeAllConnections();
831 void addConnection(ConnectionPtr connection) {
832 if (connectionsFull()) {
834 <<
", already at maximum connections: "
835 << max_connections_);
838 connections_.push_back(connection);
845 void closeConnection(ConnectionPtr connection) {
846 for (
auto it = connections_.begin(); it != connections_.end(); ++it) {
847 if (*it == connection) {
849 connections_.erase(it);
857 void closeAllConnections() {
859 while (!queue_.empty()) {
863 for (
auto const& connection : connections_) {
867 connections_.clear();
893 void garbageCollectConnections() {
894 for (
auto it = connections_.begin(); it != connections_.end();) {
895 (*it)->isClosedByPeer();
896 if (!(*it)->isClosed()) {
899 it = connections_.erase(it);
915 ConnectionPtr getIdleConnection() {
916 for (
auto const& connection : connections_) {
917 if (!connection->isTransactionOngoing() &&
918 !connection->isClosed()) {
923 return (ConnectionPtr());
932 ConnectionPtr findBySocketFd(
int socket_fd) {
933 for (
auto const& connection : connections_) {
934 if (connection->isMySocket(socket_fd)) {
939 return (ConnectionPtr());
945 bool connectionsEmpty() {
946 return (connections_.empty());
952 bool connectionsFull() {
953 return (connections_.size() >= max_connections_);
959 size_t connectionCount() {
960 return (connections_.size());
966 size_t getMaxConnections()
const {
967 return (max_connections_);
973 bool queueEmpty()
const {
974 return (queue_.empty());
980 void pushRequest(RequestDescriptor desc) {
987 RequestDescriptor popNextRequest() {
988 if (queue_.empty()) {
992 RequestDescriptor desc = queue_.front();
1005 size_t max_connections_;
1008 std::list<ConnectionPtr> connections_;
1011 std::queue<RequestDescriptor> queue_;
1015 typedef boost::shared_ptr<Destination> DestinationPtr;
1024 DestinationPtr addDestination(
const Url& url,
1026 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1027 DestinationPtr destination(
new Destination(url, tls_context,
1028 max_url_connections_));
1029 destinations_[desc] = destination;
1030 return (destination);
1041 DestinationPtr findDestination(
const Url& url,
1043 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1044 auto it = destinations_.find(desc);
1045 if (it != destinations_.end()) {
1046 return (it->second);
1049 return (DestinationPtr());
1063 void removeDestination(
const Url& url,
1065 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1066 auto it = destinations_.find(desc);
1067 if (it != destinations_.end()) {
1068 it->second->closeAllConnections();
1069 destinations_.erase(it);
1077 std::map<DestinationDescriptor, DestinationPtr> destinations_;
1080 std::mutex pool_mutex_;
1083 size_t max_url_connections_;
1086 Connection::Connection(
IOService& io_service,
1088 const ConnectionPoolPtr& conn_pool,
1090 : conn_pool_(conn_pool), url_(url), tls_context_(tls_context),
1091 tcp_socket_(), tls_socket_(), timer_(io_service),
1092 current_request_(), current_response_(), parser_(),
1093 current_callback_(), buf_(), input_buf_(), current_transid_(0),
1094 close_callback_(), started_(false), need_handshake_(false),
1097 tcp_socket_.reset(
new asiolink::TCPSocket<SocketCallback>(io_service));
1099 tls_socket_.reset(
new asiolink::TLSSocket<SocketCallback>(io_service,
1101 need_handshake_ =
true;
1105 Connection::~Connection() {
1110 Connection::resetState() {
1112 current_request_.reset();
1113 current_response_.reset();
1119 Connection::closeCallback(
const bool clear) {
1120 if (close_callback_) {
1123 close_callback_(tcp_socket_->getNative());
1124 }
else if (tls_socket_) {
1125 close_callback_(tls_socket_->getNative());
1128 "internal error: can't find a socket to close");
1141 Connection::isClosedByPeer() {
1143 if (started_ || closed_) {
1147 if (MultiThreadingMgr::instance().getMode()) {
1148 std::lock_guard<std::mutex> lk(mutex_);
1149 isClosedByPeerInternal();
1151 isClosedByPeerInternal();
1156 Connection::isClosedByPeerInternal() {
1165 if (tcp_socket_->getASIOSocket().is_open() &&
1166 !tcp_socket_->isUsable()) {
1169 tcp_socket_->close();
1171 }
else if (tls_socket_) {
1172 if (tls_socket_->getASIOSocket().is_open() &&
1173 !tls_socket_->isUsable()) {
1176 tls_socket_->close();
1186 const long request_timeout,
1191 if (MultiThreadingMgr::instance().getMode()) {
1192 std::lock_guard<std::mutex> lk(mutex_);
1193 doTransactionInternal(request, response, request_timeout,
1194 callback, connect_callback, handshake_callback,
1197 doTransactionInternal(request, response, request_timeout,
1198 callback, connect_callback, handshake_callback,
1206 const long request_timeout,
1213 current_request_ = request;
1214 current_response_ = response;
1216 parser_->initModel();
1217 current_callback_ = callback;
1218 handshake_callback_ = handshake_callback;
1219 close_callback_ = close_callback;
1224 buf_ = request->toString();
1228 .arg(request->toBriefString())
1229 .arg(url_.toText());
1234 .arg(HttpMessageParserBase::logFormatHttpMessage(request->toString(),
1235 MAX_LOGGED_MESSAGE_SIZE));
1238 scheduleTimer(request_timeout);
1244 static_cast<unsigned short>(url_.getPort()));
1245 SocketCallback socket_cb(std::bind(&Connection::connectCallback, shared_from_this(),
1246 connect_callback, current_transid_,
1251 tcp_socket_->open(&endpoint, socket_cb);
1255 tls_socket_->open(&endpoint, socket_cb);
1262 }
catch (
const std::exception& ex) {
1269 Connection::close() {
1270 if (MultiThreadingMgr::instance().getMode()) {
1271 std::lock_guard<std::mutex> lk(mutex_);
1272 return (closeInternal());
1274 return (closeInternal());
1279 Connection::closeInternal() {
1281 closeCallback(
true);
1286 tcp_socket_->close();
1289 tls_socket_->close();
1296 Connection::isMySocket(
int socket_fd)
const {
1298 return (tcp_socket_->getNative() == socket_fd);
1299 }
else if (tls_socket_) {
1300 return (tls_socket_->getNative() == socket_fd);
1303 std::cerr <<
"internal error: can't find my socket\n";
1308 Connection::checkPrematureTimeout(
const uint64_t transid) {
1309 if (MultiThreadingMgr::instance().getMode()) {
1310 std::lock_guard<std::mutex> lk(mutex_);
1311 return (checkPrematureTimeoutInternal(transid));
1313 return (checkPrematureTimeoutInternal(transid));
1318 Connection::checkPrematureTimeoutInternal(
const uint64_t transid) {
1324 if (!isTransactionOngoing() || (transid != current_transid_)) {
1326 .arg(isTransactionOngoing())
1328 .arg(current_transid_);
1336 Connection::terminate(
const boost::system::error_code& ec,
1337 const std::string& parsing_error) {
1338 if (MultiThreadingMgr::instance().getMode()) {
1339 std::lock_guard<std::mutex> lk(mutex_);
1340 terminateInternal(ec, parsing_error);
1342 terminateInternal(ec, parsing_error);
1347 Connection::terminateInternal(
const boost::system::error_code& ec,
1348 const std::string& parsing_error) {
1350 if (isTransactionOngoing()) {
1354 tcp_socket_->cancel();
1357 tls_socket_->cancel();
1360 if (!ec && current_response_->isFinalized()) {
1361 response = current_response_;
1365 .arg(url_.toText());
1371 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1372 "[HttpResponseParser is null]");
1375 std::string err = parsing_error.empty() ? ec.message() :
1385 if (!parsing_error.empty()) {
1390 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1391 "[HttpResponseParser is null]");
1398 if (MultiThreadingMgr::instance().getMode()) {
1400 current_callback_(ec, response, parsing_error);
1402 current_callback_(ec, response, parsing_error);
1410 (!current_request_->isPersistent() ||
1411 (ec == boost::asio::error::timed_out))) {
1420 ConnectionPoolPtr conn_pool = conn_pool_.lock();
1422 conn_pool->postProcessNextRequest(url_, tls_context_);
1427 Connection::scheduleTimer(
const long request_timeout) {
1428 if (request_timeout > 0) {
1429 timer_.setup(std::bind(&Connection::timerCallback,
this), request_timeout,
1435 Connection::doHandshake(
const uint64_t transid) {
1437 if (!need_handshake_) {
1442 SocketCallback socket_cb(std::bind(&Connection::handshakeCallback,
1444 handshake_callback_,
1448 tls_socket_->handshake(socket_cb);
1451 terminate(boost::asio::error::not_connected);
1456 Connection::doSend(
const uint64_t transid) {
1457 SocketCallback socket_cb(std::bind(&Connection::sendCallback,
1464 tcp_socket_->asyncSend(&buf_[0], buf_.size(), socket_cb);
1469 tls_socket_->asyncSend(&buf_[0], buf_.size(), socket_cb);
1474 std::cerr <<
"internal error: can't find a socket to send to\n";
1476 "internal error: can't find a socket to send to");
1478 terminate(boost::asio::error::not_connected);
1483 Connection::doReceive(
const uint64_t transid) {
1485 SocketCallback socket_cb(std::bind(&Connection::receiveCallback,
1492 tcp_socket_->asyncReceive(static_cast<void*>(input_buf_.data()),
1493 input_buf_.size(), 0,
1494 &endpoint, socket_cb);
1498 tls_socket_->asyncReceive(static_cast<void*>(input_buf_.data()),
1499 input_buf_.size(), 0,
1500 &endpoint, socket_cb);
1504 std::cerr <<
"internal error: can't find a socket to receive from\n";
1506 "internal error: can't find a socket to receive from");
1509 terminate(boost::asio::error::not_connected);
1515 const uint64_t transid,
1516 const boost::system::error_code& ec) {
1517 if (checkPrematureTimeout(transid)) {
1522 if (connect_callback) {
1526 if (!connect_callback(ec, tcp_socket_->getNative())) {
1529 }
else if (tls_socket_) {
1530 if (!connect_callback(ec, tls_socket_->getNative())) {
1535 std::cerr <<
"internal error: can't find a socket to connect\n";
1539 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1547 (ec.value() != boost::asio::error::in_progress) &&
1548 (ec.value() != boost::asio::error::already_connected)) {
1553 doHandshake(transid);
1559 const uint64_t transid,
1560 const boost::system::error_code& ec) {
1561 need_handshake_ =
false;
1562 if (checkPrematureTimeout(transid)) {
1567 if (handshake_callback) {
1571 if (!handshake_callback(ec, tls_socket_->getNative())) {
1576 std::cerr <<
"internal error: can't find TLS socket\n";
1580 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1592 Connection::sendCallback(
const uint64_t transid,
1593 const boost::system::error_code& ec,
1595 if (checkPrematureTimeout(transid)) {
1600 if (ec.value() == boost::asio::error::operation_aborted) {
1605 }
else if ((ec.value() == boost::asio::error::would_block) ||
1606 (ec.value() == boost::asio::error::try_again)) {
1617 scheduleTimer(timer_.getInterval());
1622 buf_.erase(0, length);
1636 Connection::receiveCallback(
const uint64_t transid,
1637 const boost::system::error_code& ec,
1639 if (checkPrematureTimeout(transid)) {
1644 if (ec.value() == boost::asio::error::operation_aborted) {
1649 }
if ((ec.value() != boost::asio::error::try_again) &&
1650 (ec.value() != boost::asio::error::would_block)) {
1662 scheduleTimer(timer_.getInterval());
1664 if (runParser(ec, length)) {
1670 Connection::runParser(
const boost::system::error_code& ec,
size_t length) {
1671 if (MultiThreadingMgr::instance().getMode()) {
1672 std::lock_guard<std::mutex> lk(mutex_);
1673 return (runParserInternal(ec, length));
1675 return (runParserInternal(ec, length));
1680 Connection::runParserInternal(
const boost::system::error_code& ec,
1684 parser_->postBuffer(static_cast<void*>(input_buf_.data()), length);
1689 if (parser_->needData()) {
1692 }
else if (parser_->httpParseOk()) {
1696 current_response_->finalize();
1697 terminateInternal(ec);
1699 }
catch (
const std::exception& ex) {
1701 terminateInternal(ec, ex.what());
1707 terminateInternal(ec, parser_->getErrorMessage());
1714 Connection::timerCallback() {
1716 terminate(boost::asio::error::timed_out);
1751 bool defer_thread_start =
false)
1752 : thread_pool_size_(thread_pool_size), thread_pool_() {
1753 if (thread_pool_size_ > 0) {
1755 thread_io_service_.reset(
new IOService());
1758 thread_pool_.reset(
new HttpThreadPool(thread_io_service_, thread_pool_size_,
1759 defer_thread_start));
1763 conn_pool_.reset(
new ConnectionPool(*thread_io_service_, thread_pool_size_));
1770 conn_pool_.reset(
new ConnectionPool(io_service, 1));
1784 thread_pool_->run();
1796 thread_pool_->stop();
1805 if (!thread_pool_) {
1810 thread_pool_->pause();
1818 if (!thread_pool_) {
1823 thread_pool_->run();
1832 return (thread_pool_->isRunning());
1844 return (thread_pool_->isStopped());
1856 return (thread_pool_->isPaused());
1867 return (thread_io_service_);
1874 return (thread_pool_size_);
1881 if (!thread_pool_) {
1884 return (thread_pool_->getThreadCount());
1893 size_t thread_pool_size_;
1904 bool defer_thread_start ) {
1905 if (thread_pool_size > 0) {
1906 if (!MultiThreadingMgr::instance().getMode()) {
1908 "HttpClient thread_pool_size must be zero"
1909 "when Kea core multi-threading is disabled");
1914 defer_thread_start));
1934 if ((url.
getScheme() == Url::Scheme::HTTPS) && !tls_context) {
1946 if (!request_callback) {
1950 impl_->conn_pool_->queueRequest(url, tls_context, request, response,
1952 request_callback, connect_callback,
1953 handshake_callback, close_callback);
1958 return (impl_->conn_pool_->closeIfOutOfBand(socket_fd));
1983 return (impl_->getThreadIOService());
1988 return (impl_->getThreadPoolSize());
1993 return (impl_->getThreadCount());
1998 return (impl_->isRunning());
2003 return (impl_->isStopped());
2008 return (impl_->isPaused());
void stop()
Halts client-side IO activity.
const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED
bool isRunning()
Indicates if the thread pool is running.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED_DETAILS
std::function< bool(const boost::system::error_code &, const int)> ConnectHandler
Optional handler invoked when client connects to the server.
const int DBGLVL_TRACE_BASIC
Trace basic operations.
uint16_t getThreadPoolSize() const
Fetches the maximum size of the thread pool.
void asyncSendRequest(const Url &url, const asiolink::TlsContextPtr &tls_context, const HttpRequestPtr &request, const HttpResponsePtr &response, const RequestHandler &request_callback, const RequestTimeout &request_timeout=RequestTimeout(10000), const ConnectHandler &connect_callback=ConnectHandler(), const HandshakeHandler &handshake_callback=HandshakeHandler(), const CloseHandler &close_callback=CloseHandler())
Queues new asynchronous HTTP request for a given URL.
std::function< void()> callback_
The callback function.
long value_
Timeout value specified.
const asiolink::IOServicePtr getThreadIOService() const
Fetches a pointer to the internal IOService used to drive the thread-pool in multi-threaded mode...
std::function< void(const boost::system::error_code &, const HttpResponsePtr &, const std::string &)> RequestHandler
Callback type used in call to HttpClient::asyncSendRequest.
void pause()
Pauses the client's thread pool.
HttpClient(asiolink::IOService &io_service, size_t thread_pool_size=0, bool defer_thread_start=false)
Constructor.
HTTP request/response timeout value.
void start()
Starts running the client's thread pool, if multi-threaded.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
const isc::log::MessageID HTTP_SERVER_RESPONSE_RECEIVED_DETAILS
std::function< void(const int)> CloseHandler
Optional handler invoked when client closes the connection to the server.
bool isValid() const
Checks if the URL is valid.
bool isStopped()
Indicates if the thread pool is stopped.
const isc::log::MessageID HTTP_PREMATURE_CONNECTION_TIMEOUT_OCCURRED
const isc::log::MessageID HTTP_SERVER_RESPONSE_RECEIVED
HttpClientImpl(IOService &io_service, size_t thread_pool_size=0, bool defer_thread_start=false)
Constructor.
The IOService class is a wrapper for the ASIO io_service class.
boost::shared_ptr< TlsContext > TlsContextPtr
The type of shared pointers to TlsContext objects.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
The TCPEndpoint class is a concrete derived class of IOEndpoint that represents an endpoint of a TCP ...
~HttpClientImpl()
Destructor.
const isc::log::MessageID HTTP_CLIENT_REQUEST_SEND
void resume()
Resumes running the client's thread pool.
ConnectionPoolPtr conn_pool_
Holds a pointer to the connection pool.
A generic parser for HTTP responses.
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
void resume()
Resumes running the client's thread pool.
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
const isc::log::MessageID HTTP_CLIENT_REQUEST_SEND_DETAILS
A generic exception that is thrown when an unexpected error condition occurs.
const int DBGLVL_TRACE_DETAIL_DATA
Trace data associated with detailed operations.
void stop()
Close all connections, and if multi-threaded, stops the client's thread pool.
void start()
Starts running the client's thread pool, if multi-threaded.
bool isPaused()
Indicates if the thread pool is paused.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
const isc::log::MessageID HTTP_CLIENT_MT_STARTED
Defines the logger used by the top-level component of kea-dhcp-ddns.
boost::shared_ptr< HttpResponseParser > HttpResponseParserPtr
Pointer to the HttpResponseParser.
std::function< bool(const boost::system::error_code &, const int)> HandshakeHandler
Optional handler invoked when client performs the TLS handshake with the server.
void pause()
Pauses the client's thread pool.
A generic exception that is thrown if a function is called in a prohibited way.
Scheme getScheme() const
Returns parsed scheme.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Implements a pausable pool of IOService driven threads.
isc::log::Logger http_logger("http")
Defines the logger used within libkea-http library.
const isc::log::MessageID HTTP_CONNECTION_CLOSE_CALLBACK_FAILED
bool isPaused()
Indicates if the thread pool is paused.
bool isRunning()
Indicates if the thread pool is running.
boost::shared_ptr< HttpRequest > HttpRequestPtr
Pointer to the HttpRequest object.
uint16_t getThreadPoolSize()
Fetches the maximum size of the thread pool.
boost::shared_ptr< HttpThreadPool > HttpThreadPoolPtr
Defines a pointer to a thread pool.
uint16_t getThreadCount() const
Fetches the number of threads in the pool.
void closeIfOutOfBand(int socket_fd)
Closes a connection if it has an out-of-band socket event.
const int DBGLVL_TRACE_DETAIL
Trace detailed operations.
uint16_t getThreadCount()
Fetches the number of threads in the pool.
asiolink::IOServicePtr getThreadIOService()
Fetches the internal IOService used in multi-threaded mode.
bool isStopped()
Indicates if the thread pool is stopped.
A generic error raised by the HttpClient class.
const int DBGLVL_TRACE_BASIC_DATA
Trace data associated with the basic operations.
HttpClient implementation.