22#include <boost/enable_shared_from_this.hpp>
23#include <boost/weak_ptr.hpp>
39using namespace boost::posix_time;
41namespace ph = std::placeholders;
48constexpr size_t MAX_LOGGED_MESSAGE_SIZE = 1024;
51typedef std::function<void(boost::system::error_code ec,
size_t length)>
52SocketCallbackFunction;
67 SocketCallback(SocketCallbackFunction socket_callback)
68 : callback_(socket_callback) {
77 void operator()(boost::system::error_code ec,
size_t length = 0) {
78 if (ec.value() == boost::asio::error::operation_aborted) {
81 callback_(ec, length);
87 SocketCallbackFunction callback_;
94typedef boost::shared_ptr<ConnectionPool> ConnectionPoolPtr;
111class Connection :
public boost::enable_shared_from_this<Connection> {
121 explicit Connection(
IOService& io_service,
123 const ConnectionPoolPtr& conn_pool,
149 const long request_timeout,
161 bool isTransactionOngoing()
const {
168 bool isClosed()
const {
176 void isClosedByPeer();
183 bool isMySocket(
int socket_fd)
const;
200 bool checkPrematureTimeout(
const uint64_t transid);
226 const long request_timeout,
235 void closeInternal();
243 void isClosedByPeerInternal();
262 bool checkPrematureTimeoutInternal(
const uint64_t transid);
281 void terminate(
const boost::system::error_code& ec,
282 const std::string& parsing_error =
"");
295 void terminateInternal(
const boost::system::error_code& ec,
296 const std::string& parsing_error =
"");
304 bool runParser(
const boost::system::error_code& ec,
size_t length);
314 bool runParserInternal(
const boost::system::error_code& ec,
size_t length);
319 void scheduleTimer(
const long request_timeout);
326 void doHandshake(
const uint64_t transid);
333 void doSend(
const uint64_t transid);
340 void doReceive(
const uint64_t transid);
353 const uint64_t transid,
354 const boost::system::error_code& ec);
366 const uint64_t transid,
367 const boost::system::error_code& ec);
379 void sendCallback(
const uint64_t transid,
const boost::system::error_code& ec,
388 void receiveCallback(
const uint64_t transid,
const boost::system::error_code& ec,
392 void timerCallback();
403 void closeCallback(
const bool clear =
false);
409 boost::weak_ptr<ConnectionPool> conn_pool_;
418 std::unique_ptr<TCPSocket<SocketCallback> > tcp_socket_;
421 std::unique_ptr<TLSSocket<SocketCallback> > tls_socket_;
442 std::array<char, 32768> input_buf_;
445 uint64_t current_transid_;
454 std::atomic<bool> started_;
457 std::atomic<bool> need_handshake_;
460 std::atomic<bool> closed_;
467typedef boost::shared_ptr<Connection> ConnectionPtr;
476class ConnectionPool :
public boost::enable_shared_from_this<ConnectionPool> {
485 explicit ConnectionPool(
IOService& io_service,
size_t max_url_connections)
486 : io_service_(io_service), destinations_(), pool_mutex_(),
487 max_url_connections_(max_url_connections) {
503 if (MultiThreadingMgr::instance().getMode()) {
504 std::lock_guard<std::mutex> lk(pool_mutex_);
505 return (processNextRequestInternal(url, tls_context));
507 return (processNextRequestInternal(url, tls_context));
516 void postProcessNextRequest(
const Url& url,
518 io_service_.post(std::bind(&ConnectionPool::processNextRequest,
519 shared_from_this(), url, tls_context));
542 void queueRequest(
const Url& url,
546 const long request_timeout,
551 if (MultiThreadingMgr::instance().getMode()) {
552 std::lock_guard<std::mutex> lk(pool_mutex_);
553 return (queueRequestInternal(url, tls_context, request, response,
554 request_timeout, request_callback,
555 connect_callback, handshake_callback,
558 return (queueRequestInternal(url, tls_context, request, response,
559 request_timeout, request_callback,
560 connect_callback, handshake_callback,
568 if (MultiThreadingMgr::instance().getMode()) {
569 std::lock_guard<std::mutex> lk(pool_mutex_);
588 void closeIfOutOfBand(
int socket_fd) {
589 if (MultiThreadingMgr::instance().getMode()) {
590 std::lock_guard<std::mutex> lk(pool_mutex_);
591 closeIfOutOfBandInternal(socket_fd);
593 closeIfOutOfBandInternal(socket_fd);
606 void processNextRequestInternal(
const Url& url,
610 DestinationPtr destination = findDestination(url, tls_context);
613 destination->garbageCollectConnections();
614 if (!destination->queueEmpty()) {
617 ConnectionPtr connection = destination->getIdleConnection();
620 if (destination->connectionsFull()) {
625 connection.reset(
new Connection(io_service_, tls_context,
626 shared_from_this(), url));
627 destination->addConnection(connection);
632 RequestDescriptor desc = destination->popNextRequest();
633 connection->doTransaction(desc.request_, desc.response_,
634 desc.request_timeout_, desc.callback_,
635 desc.connect_callback_,
636 desc.handshake_callback_,
637 desc.close_callback_);
664 void queueRequestInternal(
const Url& url,
668 const long request_timeout,
673 ConnectionPtr connection;
675 DestinationPtr destination = findDestination(url, tls_context);
678 destination->garbageCollectConnections();
680 connection = destination->getIdleConnection();
683 destination = addDestination(url, tls_context);
687 if (destination->connectionsFull()) {
689 destination->pushRequest(RequestDescriptor(request, response,
699 connection.reset(
new Connection(io_service_, tls_context,
700 shared_from_this(), url));
701 destination->addConnection(connection);
705 connection->doTransaction(request, response, request_timeout, request_callback,
706 connect_callback, handshake_callback, close_callback);
713 void closeAllInternal() {
714 for (
auto const& destination : destinations_) {
715 destination.second->closeAllConnections();
718 destinations_.clear();
735 void closeIfOutOfBandInternal(
int socket_fd) {
736 for (
auto const& destination : destinations_) {
738 ConnectionPtr connection = destination.second->findBySocketFd(socket_fd);
740 if (!connection->isTransactionOngoing()) {
746 destination.second->closeConnection(connection);
756 struct RequestDescriptor {
772 const long& request_timeout,
777 : request_(request), response_(response),
778 request_timeout_(request_timeout), callback_(callback),
779 connect_callback_(connect_callback),
780 handshake_callback_(handshake_callback),
781 close_callback_(close_callback) {
791 long request_timeout_;
807 typedef std::pair<Url, TlsContextPtr> DestinationDescriptor;
813 const size_t QUEUE_SIZE_THRESHOLD = 2048;
815 const int QUEUE_WARN_SECS = 5;
823 Destination(
Url const& url,
TlsContextPtr tls_context,
size_t max_connections)
824 : url_(url), tls_context_(tls_context),
825 max_connections_(max_connections), connections_(), queue_(),
826 last_queue_warn_time_(min_date_time), last_queue_size_(0) {
831 closeAllConnections();
841 void addConnection(ConnectionPtr connection) {
842 if (connectionsFull()) {
844 <<
", already at maximum connections: "
845 << max_connections_);
848 connections_.push_back(connection);
855 void closeConnection(ConnectionPtr connection) {
856 for (
auto it = connections_.begin(); it != connections_.end(); ++it) {
857 if (*it == connection) {
859 connections_.erase(it);
867 void closeAllConnections() {
869 while (!queue_.empty()) {
873 for (
auto const& connection : connections_) {
877 connections_.clear();
903 void garbageCollectConnections() {
904 for (
auto it = connections_.begin(); it != connections_.end();) {
905 (*it)->isClosedByPeer();
906 if (!(*it)->isClosed()) {
909 it = connections_.erase(it);
925 ConnectionPtr getIdleConnection() {
926 for (
auto const& connection : connections_) {
927 if (!connection->isTransactionOngoing() &&
928 !connection->isClosed()) {
933 return (ConnectionPtr());
942 ConnectionPtr findBySocketFd(
int socket_fd) {
943 for (
auto const& connection : connections_) {
944 if (connection->isMySocket(socket_fd)) {
949 return (ConnectionPtr());
955 bool connectionsEmpty() {
956 return (connections_.empty());
962 bool connectionsFull() {
963 return (connections_.size() >= max_connections_);
969 size_t connectionCount() {
970 return (connections_.size());
976 size_t getMaxConnections()
const {
977 return (max_connections_);
983 bool queueEmpty()
const {
984 return (queue_.empty());
993 void pushRequest(RequestDescriptor
const& desc) {
995 size_t size = queue_.size();
998 if ((size > QUEUE_SIZE_THRESHOLD) && (size > last_queue_size_)) {
999 ptime now = microsec_clock::universal_time();
1000 if ((now - last_queue_warn_time_) > seconds(QUEUE_WARN_SECS)) {
1005 last_queue_warn_time_ = now;
1010 last_queue_size_ = size;
1016 RequestDescriptor popNextRequest() {
1017 if (queue_.empty()) {
1021 RequestDescriptor desc = queue_.front();
1034 size_t max_connections_;
1037 std::list<ConnectionPtr> connections_;
1040 std::queue<RequestDescriptor> queue_;
1043 ptime last_queue_warn_time_;
1046 size_t last_queue_size_;
1050 typedef boost::shared_ptr<Destination> DestinationPtr;
1059 DestinationPtr addDestination(
const Url& url,
1061 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1062 DestinationPtr destination(
new Destination(url, tls_context,
1063 max_url_connections_));
1064 destinations_[desc] = destination;
1065 return (destination);
1076 DestinationPtr findDestination(
const Url& url,
1078 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1079 auto it = destinations_.find(desc);
1080 if (it != destinations_.end()) {
1081 return (it->second);
1084 return (DestinationPtr());
1098 void removeDestination(
const Url& url,
1100 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1101 auto it = destinations_.find(desc);
1102 if (it != destinations_.end()) {
1103 it->second->closeAllConnections();
1104 destinations_.erase(it);
1112 std::map<DestinationDescriptor, DestinationPtr> destinations_;
1115 std::mutex pool_mutex_;
1118 size_t max_url_connections_;
1121Connection::Connection(
IOService& io_service,
1123 const ConnectionPoolPtr& conn_pool,
1125 : conn_pool_(conn_pool), url_(url), tls_context_(tls_context),
1126 tcp_socket_(), tls_socket_(), timer_(io_service),
1127 current_request_(), current_response_(), parser_(),
1128 current_callback_(), buf_(), input_buf_(), current_transid_(0),
1129 close_callback_(), started_(false), need_handshake_(false),
1136 need_handshake_ =
true;
1140Connection::~Connection() {
1145Connection::resetState() {
1147 current_request_.reset();
1148 current_response_.reset();
1154Connection::closeCallback(
const bool clear) {
1155 if (close_callback_) {
1158 close_callback_(tcp_socket_->getNative());
1159 }
else if (tls_socket_) {
1160 close_callback_(tls_socket_->getNative());
1163 "internal error: can't find a socket to close");
1176Connection::isClosedByPeer() {
1178 if (started_ || closed_) {
1182 if (MultiThreadingMgr::instance().getMode()) {
1183 std::lock_guard<std::mutex> lk(mutex_);
1184 isClosedByPeerInternal();
1186 isClosedByPeerInternal();
1191Connection::isClosedByPeerInternal() {
1200 if (tcp_socket_->getASIOSocket().is_open() &&
1201 !tcp_socket_->isUsable()) {
1204 tcp_socket_->close();
1206 }
else if (tls_socket_) {
1207 if (tls_socket_->getASIOSocket().is_open() &&
1208 !tls_socket_->isUsable()) {
1211 tls_socket_->close();
1221 const long request_timeout,
1226 if (MultiThreadingMgr::instance().getMode()) {
1227 std::lock_guard<std::mutex> lk(mutex_);
1228 doTransactionInternal(request, response, request_timeout,
1229 callback, connect_callback, handshake_callback,
1232 doTransactionInternal(request, response, request_timeout,
1233 callback, connect_callback, handshake_callback,
1241 const long request_timeout,
1248 current_request_ = request;
1249 current_response_ = response;
1251 parser_->initModel();
1252 current_callback_ = callback;
1253 handshake_callback_ = handshake_callback;
1254 close_callback_ = close_callback;
1259 buf_ = request->toString();
1263 .arg(request->toBriefString())
1264 .arg(url_.toText());
1269 .arg(HttpMessageParserBase::logFormatHttpMessage(request->toString(),
1270 MAX_LOGGED_MESSAGE_SIZE));
1273 scheduleTimer(request_timeout);
1279 static_cast<unsigned short>(url_.getPort()));
1280 SocketCallback socket_cb(std::bind(&Connection::connectCallback, shared_from_this(),
1281 connect_callback, current_transid_,
1286 tcp_socket_->open(&endpoint, socket_cb);
1290 tls_socket_->open(&endpoint, socket_cb);
1297 }
catch (
const std::exception& ex) {
1304Connection::close() {
1305 if (MultiThreadingMgr::instance().getMode()) {
1306 std::lock_guard<std::mutex> lk(mutex_);
1307 return (closeInternal());
1309 return (closeInternal());
1314Connection::closeInternal() {
1316 closeCallback(
true);
1321 tcp_socket_->close();
1324 tls_socket_->close();
1331Connection::isMySocket(
int socket_fd)
const {
1333 return (tcp_socket_->getNative() == socket_fd);
1334 }
else if (tls_socket_) {
1335 return (tls_socket_->getNative() == socket_fd);
1338 std::cerr <<
"internal error: can't find my socket\n";
1343Connection::checkPrematureTimeout(
const uint64_t transid) {
1344 if (MultiThreadingMgr::instance().getMode()) {
1345 std::lock_guard<std::mutex> lk(mutex_);
1346 return (checkPrematureTimeoutInternal(transid));
1348 return (checkPrematureTimeoutInternal(transid));
1353Connection::checkPrematureTimeoutInternal(
const uint64_t transid) {
1359 if (!isTransactionOngoing() || (transid != current_transid_)) {
1361 .arg(isTransactionOngoing())
1363 .arg(current_transid_);
1371Connection::terminate(
const boost::system::error_code& ec,
1372 const std::string& parsing_error) {
1373 if (MultiThreadingMgr::instance().getMode()) {
1374 std::lock_guard<std::mutex> lk(mutex_);
1375 terminateInternal(ec, parsing_error);
1377 terminateInternal(ec, parsing_error);
1382Connection::terminateInternal(
const boost::system::error_code& ec,
1383 const std::string& parsing_error) {
1385 if (isTransactionOngoing()) {
1389 tcp_socket_->cancel();
1392 tls_socket_->cancel();
1395 if (!ec && current_response_->isFinalized()) {
1396 response = current_response_;
1400 .arg(url_.toText());
1406 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1407 "[HttpResponseParser is null]");
1410 std::string err = parsing_error.empty() ? ec.message() :
1420 if (!parsing_error.empty()) {
1425 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1426 "[HttpResponseParser is null]");
1433 if (MultiThreadingMgr::instance().getMode()) {
1435 current_callback_(ec, response, parsing_error);
1437 current_callback_(ec, response, parsing_error);
1445 (!current_request_->isPersistent() ||
1446 (ec == boost::asio::error::timed_out))) {
1455 ConnectionPoolPtr conn_pool = conn_pool_.lock();
1457 conn_pool->postProcessNextRequest(url_, tls_context_);
1462Connection::scheduleTimer(
const long request_timeout) {
1463 if (request_timeout > 0) {
1464 timer_.setup(std::bind(&Connection::timerCallback,
this), request_timeout,
1465 IntervalTimer::ONE_SHOT);
1470Connection::doHandshake(
const uint64_t transid) {
1472 if (!need_handshake_) {
1477 SocketCallback socket_cb(std::bind(&Connection::handshakeCallback,
1479 handshake_callback_,
1483 tls_socket_->handshake(socket_cb);
1486 terminate(boost::asio::error::not_connected);
1491Connection::doSend(
const uint64_t transid) {
1492 SocketCallback socket_cb(std::bind(&Connection::sendCallback,
1499 tcp_socket_->asyncSend(&buf_[0], buf_.size(), socket_cb);
1504 tls_socket_->asyncSend(&buf_[0], buf_.size(), socket_cb);
1509 std::cerr <<
"internal error: can't find a socket to send to\n";
1511 "internal error: can't find a socket to send to");
1513 terminate(boost::asio::error::not_connected);
1518Connection::doReceive(
const uint64_t transid) {
1520 SocketCallback socket_cb(std::bind(&Connection::receiveCallback,
1527 tcp_socket_->asyncReceive(
static_cast<void*
>(input_buf_.data()),
1528 input_buf_.size(), 0,
1529 &endpoint, socket_cb);
1533 tls_socket_->asyncReceive(
static_cast<void*
>(input_buf_.data()),
1534 input_buf_.size(), 0,
1535 &endpoint, socket_cb);
1539 std::cerr <<
"internal error: can't find a socket to receive from\n";
1541 "internal error: can't find a socket to receive from");
1544 terminate(boost::asio::error::not_connected);
1550 const uint64_t transid,
1551 const boost::system::error_code& ec) {
1552 if (checkPrematureTimeout(transid)) {
1557 if (connect_callback) {
1561 if (!connect_callback(ec, tcp_socket_->getNative())) {
1564 }
else if (tls_socket_) {
1565 if (!connect_callback(ec, tls_socket_->getNative())) {
1570 std::cerr <<
"internal error: can't find a socket to connect\n";
1574 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1582 (ec.value() != boost::asio::error::in_progress) &&
1583 (ec.value() != boost::asio::error::already_connected)) {
1588 doHandshake(transid);
1594 const uint64_t transid,
1595 const boost::system::error_code& ec) {
1596 need_handshake_ =
false;
1597 if (checkPrematureTimeout(transid)) {
1602 if (handshake_callback) {
1606 if (!handshake_callback(ec, tls_socket_->getNative())) {
1611 std::cerr <<
"internal error: can't find TLS socket\n";
1615 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1627Connection::sendCallback(
const uint64_t transid,
1628 const boost::system::error_code& ec,
1630 if (checkPrematureTimeout(transid)) {
1635 if (ec.value() == boost::asio::error::operation_aborted) {
1640 }
else if ((ec.value() == boost::asio::error::would_block) ||
1641 (ec.value() == boost::asio::error::try_again)) {
1652 scheduleTimer(timer_.getInterval());
1657 buf_.erase(0, length);
1671Connection::receiveCallback(
const uint64_t transid,
1672 const boost::system::error_code& ec,
1674 if (checkPrematureTimeout(transid)) {
1679 if (ec.value() == boost::asio::error::operation_aborted) {
1685 if ((ec.value() != boost::asio::error::try_again) &&
1686 (ec.value() != boost::asio::error::would_block)) {
1698 scheduleTimer(timer_.getInterval());
1700 if (runParser(ec, length)) {
1706Connection::runParser(
const boost::system::error_code& ec,
size_t length) {
1707 if (MultiThreadingMgr::instance().getMode()) {
1708 std::lock_guard<std::mutex> lk(mutex_);
1709 return (runParserInternal(ec, length));
1711 return (runParserInternal(ec, length));
1716Connection::runParserInternal(
const boost::system::error_code& ec,
1720 parser_->postBuffer(
static_cast<void*
>(input_buf_.data()), length);
1725 if (parser_->needData()) {
1728 }
else if (parser_->httpParseOk()) {
1732 current_response_->finalize();
1733 terminateInternal(ec);
1735 }
catch (
const std::exception& ex) {
1737 terminateInternal(ec, ex.what());
1743 terminateInternal(ec, parser_->getErrorMessage());
1750Connection::timerCallback() {
1752 terminate(boost::asio::error::timed_out);
1787 bool defer_thread_start =
false)
1788 : thread_pool_size_(thread_pool_size), thread_pool_() {
1789 if (thread_pool_size_ > 0) {
1791 thread_io_service_.reset(
new IOService());
1795 conn_pool_.reset(
new ConnectionPool(*thread_io_service_, thread_pool_size_));
1799 defer_thread_start));
1802 .arg(thread_pool_size_);
1806 conn_pool_.reset(
new ConnectionPool(io_service, 1));
1824 thread_pool_->checkPausePermissions();
1831 thread_pool_->run();
1843 thread_pool_->stop();
1852 if (!thread_pool_) {
1857 thread_pool_->pause();
1865 if (!thread_pool_) {
1870 thread_pool_->run();
1879 return (thread_pool_->isRunning());
1891 return (thread_pool_->isStopped());
1903 return (thread_pool_->isPaused());
1914 return (thread_io_service_);
1921 return (thread_pool_size_);
1928 if (!thread_pool_) {
1931 return (thread_pool_->getThreadCount());
1940 size_t thread_pool_size_;
1951 size_t thread_pool_size,
bool defer_thread_start) {
1952 if (!multi_threading_enabled && thread_pool_size) {
1954 "HttpClient thread_pool_size must be zero "
1955 "when Kea core multi-threading is disabled");
1959 defer_thread_start));
1979 if ((url.
getScheme() == Url::Scheme::HTTPS) && !tls_context) {
1991 if (!request_callback) {
1995 impl_->conn_pool_->queueRequest(url, tls_context, request, response,
1997 request_callback, connect_callback,
1998 handshake_callback, close_callback);
2003 return (impl_->conn_pool_->closeIfOutOfBand(socket_fd));
2013 impl_->checkPermissions();
2033 return (impl_->getThreadIOService());
2038 return (impl_->getThreadPoolSize());
2043 return (impl_->getThreadCount());
2048 return (impl_->isRunning());
2053 return (impl_->isStopped());
2058 return (impl_->isPaused());
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
The IOService class is a wrapper for the ASIO io_service class.
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
Implements a pausable pool of IOService driven threads.
The TCPEndpoint class is a concrete derived class of IOEndpoint that represents an endpoint of a TCP ...
A generic error raised by the HttpClient class.
HttpClient implementation.
HttpClientImpl(IOService &io_service, size_t thread_pool_size=0, bool defer_thread_start=false)
Constructor.
ConnectionPoolPtr conn_pool_
Holds a pointer to the connection pool.
uint16_t getThreadCount()
Fetches the number of threads in the pool.
~HttpClientImpl()
Destructor.
void pause()
Pauses the client's thread pool.
uint16_t getThreadPoolSize()
Fetches the maximum size of the thread pool.
void start()
Starts running the client's thread pool, if multi-threaded.
void stop()
Close all connections, and if multi-threaded, stops the client's thread pool.
asiolink::IOServicePtr getThreadIOService()
Fetches the internal IOService used in multi-threaded mode.
void checkPermissions()
Check if the current thread can perform thread pool state transition.
bool isPaused()
Indicates if the thread pool is paused.
void resume()
Resumes running the client's thread pool.
bool isStopped()
Indicates if the thread pool is stopped.
bool isRunning()
Indicates if the thread pool is running.
uint16_t getThreadCount() const
Fetches the number of threads in the pool.
bool isRunning()
Indicates if the thread pool is running.
HttpClient(asiolink::IOService &io_service, bool multi_threading_enabled, size_t thread_pool_size=0, bool defer_thread_start=false)
Constructor.
std::function< void(const boost::system::error_code &, const HttpResponsePtr &, const std::string &)> RequestHandler
Callback type used in call to HttpClient::asyncSendRequest.
void stop()
Halts client-side IO activity.
bool isPaused()
Indicates if the thread pool is paused.
void pause()
Pauses the client's thread pool.
std::function< void(const int)> CloseHandler
Optional handler invoked when client closes the connection to the server.
const asiolink::IOServicePtr getThreadIOService() const
Fetches a pointer to the internal IOService used to drive the thread-pool in multi-threaded mode.
void start()
Starts running the client's thread pool, if multi-threaded.
std::function< bool(const boost::system::error_code &, const int)> ConnectHandler
Optional handler invoked when client connects to the server.
uint16_t getThreadPoolSize() const
Fetches the maximum size of the thread pool.
std::function< bool(const boost::system::error_code &, const int)> HandshakeHandler
Optional handler invoked when client performs the TLS handshake with the server.
void closeIfOutOfBand(int socket_fd)
Closes a connection if it has an out-of-band socket event.
void resume()
Resumes running the client's 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.
bool isStopped()
Indicates if the thread pool is stopped.
void checkPermissions()
Check if the current thread can perform thread pool state transition.
A generic parser for HTTP responses.
Scheme getScheme() const
Returns parsed scheme.
bool isValid() const
Checks if the URL is valid.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< TlsContext > TlsContextPtr
The type of shared pointers to TlsContext objects.
boost::shared_ptr< IoServiceThreadPool > IoServiceThreadPoolPtr
Defines a pointer to a thread pool.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
const isc::log::MessageID HTTP_CLIENT_MT_STARTED
const isc::log::MessageID HTTP_CONNECTION_CLOSE_CALLBACK_FAILED
const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED
isc::log::Logger http_logger("http")
Defines the logger used within libkea-http library.
const isc::log::MessageID HTTP_SERVER_RESPONSE_RECEIVED
boost::shared_ptr< HttpResponseParser > HttpResponseParserPtr
Pointer to the HttpResponseParser.
const isc::log::MessageID HTTP_CLIENT_REQUEST_SEND
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED_DETAILS
const isc::log::MessageID HTTP_CLIENT_REQUEST_SEND_DETAILS
const isc::log::MessageID HTTP_CLIENT_QUEUE_SIZE_GROWING
const isc::log::MessageID HTTP_SERVER_RESPONSE_RECEIVED_DETAILS
boost::shared_ptr< HttpRequest > HttpRequestPtr
Pointer to the HttpRequest object.
const isc::log::MessageID HTTP_PREMATURE_CONNECTION_TIMEOUT_OCCURRED
const int DBGLVL_TRACE_BASIC
Trace basic operations.
const int DBGLVL_TRACE_DETAIL_DATA
Trace data associated with detailed operations.
const int DBGLVL_TRACE_BASIC_DATA
Trace data associated with the basic operations.
const int DBGLVL_TRACE_DETAIL
Trace detailed operations.
Defines the logger used by the top-level component of kea-lfc.
HTTP request/response timeout value.
long value_
Timeout value specified.