21#include <boost/enable_shared_from_this.hpp>
22#include <boost/weak_ptr.hpp>
38using namespace boost::posix_time;
40namespace ph = std::placeholders;
47constexpr size_t MAX_LOGGED_MESSAGE_SIZE = 1024;
50typedef std::function<void(boost::system::error_code ec,
size_t length)>
51SocketCallbackFunction;
66 SocketCallback(SocketCallbackFunction socket_callback)
67 : callback_(socket_callback) {
76 void operator()(boost::system::error_code ec,
size_t length = 0) {
77 if (ec.value() == boost::asio::error::operation_aborted) {
80 callback_(ec, length);
86 SocketCallbackFunction callback_;
93typedef boost::shared_ptr<ConnectionPool> ConnectionPoolPtr;
110class Connection :
public boost::enable_shared_from_this<Connection> {
120 explicit Connection(
IOService& io_service,
122 const ConnectionPoolPtr& conn_pool,
148 const long request_timeout,
160 bool isTransactionOngoing()
const {
167 bool isClosed()
const {
175 void isClosedByPeer();
182 bool isMySocket(
int socket_fd)
const;
199 bool checkPrematureTimeout(
const uint64_t transid);
225 const long request_timeout,
234 void closeInternal();
242 void isClosedByPeerInternal();
261 bool checkPrematureTimeoutInternal(
const uint64_t transid);
280 void terminate(
const boost::system::error_code& ec,
281 const std::string& parsing_error =
"");
294 void terminateInternal(
const boost::system::error_code& ec,
295 const std::string& parsing_error =
"");
303 bool runParser(
const boost::system::error_code& ec,
size_t length);
313 bool runParserInternal(
const boost::system::error_code& ec,
size_t length);
318 void scheduleTimer(
const long request_timeout);
325 void doHandshake(
const uint64_t transid);
332 void doSend(
const uint64_t transid);
339 void doReceive(
const uint64_t transid);
352 const uint64_t transid,
353 const boost::system::error_code& ec);
365 const uint64_t transid,
366 const boost::system::error_code& ec);
378 void sendCallback(
const uint64_t transid,
const boost::system::error_code& ec,
387 void receiveCallback(
const uint64_t transid,
const boost::system::error_code& ec,
391 void timerCallback();
402 void closeCallback(
const bool clear =
false);
408 boost::weak_ptr<ConnectionPool> conn_pool_;
417 std::unique_ptr<TCPSocket<SocketCallback> > tcp_socket_;
420 std::unique_ptr<TLSSocket<SocketCallback> > tls_socket_;
441 std::array<char, 32768> input_buf_;
444 uint64_t current_transid_;
453 std::atomic<bool> started_;
456 std::atomic<bool> need_handshake_;
459 std::atomic<bool> closed_;
466typedef boost::shared_ptr<Connection> ConnectionPtr;
475class ConnectionPool :
public boost::enable_shared_from_this<ConnectionPool> {
484 explicit ConnectionPool(
IOService& io_service,
size_t max_url_connections)
485 : io_service_(io_service), destinations_(), pool_mutex_(),
486 max_url_connections_(max_url_connections) {
502 if (MultiThreadingMgr::instance().getMode()) {
503 std::lock_guard<std::mutex> lk(pool_mutex_);
504 return (processNextRequestInternal(url, tls_context));
506 return (processNextRequestInternal(url, tls_context));
515 void postProcessNextRequest(
const Url& url,
517 io_service_.post(std::bind(&ConnectionPool::processNextRequest,
518 shared_from_this(), url, tls_context));
541 void queueRequest(
const Url& url,
545 const long request_timeout,
550 if (MultiThreadingMgr::instance().getMode()) {
551 std::lock_guard<std::mutex> lk(pool_mutex_);
552 return (queueRequestInternal(url, tls_context, request, response,
553 request_timeout, request_callback,
554 connect_callback, handshake_callback,
557 return (queueRequestInternal(url, tls_context, request, response,
558 request_timeout, request_callback,
559 connect_callback, handshake_callback,
567 if (MultiThreadingMgr::instance().getMode()) {
568 std::lock_guard<std::mutex> lk(pool_mutex_);
587 void closeIfOutOfBand(
int socket_fd) {
588 if (MultiThreadingMgr::instance().getMode()) {
589 std::lock_guard<std::mutex> lk(pool_mutex_);
590 closeIfOutOfBandInternal(socket_fd);
592 closeIfOutOfBandInternal(socket_fd);
605 void processNextRequestInternal(
const Url& url,
609 DestinationPtr destination = findDestination(url, tls_context);
612 destination->garbageCollectConnections();
613 if (!destination->queueEmpty()) {
616 ConnectionPtr connection = destination->getIdleConnection();
619 if (destination->connectionsFull()) {
624 connection.reset(
new Connection(io_service_, tls_context,
625 shared_from_this(), url));
626 destination->addConnection(connection);
631 RequestDescriptor desc = destination->popNextRequest();
632 connection->doTransaction(desc.request_, desc.response_,
633 desc.request_timeout_, desc.callback_,
634 desc.connect_callback_,
635 desc.handshake_callback_,
636 desc.close_callback_);
663 void queueRequestInternal(
const Url& url,
667 const long request_timeout,
672 ConnectionPtr connection;
674 DestinationPtr destination = findDestination(url, tls_context);
677 destination->garbageCollectConnections();
679 connection = destination->getIdleConnection();
682 destination = addDestination(url, tls_context);
686 if (destination->connectionsFull()) {
688 destination->pushRequest(RequestDescriptor(request, response,
698 connection.reset(
new Connection(io_service_, tls_context,
699 shared_from_this(), url));
700 destination->addConnection(connection);
704 connection->doTransaction(request, response, request_timeout, request_callback,
705 connect_callback, handshake_callback, close_callback);
712 void closeAllInternal() {
713 for (
auto const& destination : destinations_) {
714 destination.second->closeAllConnections();
717 destinations_.clear();
734 void closeIfOutOfBandInternal(
int socket_fd) {
735 for (
auto const& destination : destinations_) {
737 ConnectionPtr connection = destination.second->findBySocketFd(socket_fd);
739 if (!connection->isTransactionOngoing()) {
745 destination.second->closeConnection(connection);
755 struct RequestDescriptor {
771 const long& request_timeout,
776 : request_(request), response_(response),
777 request_timeout_(request_timeout), callback_(callback),
778 connect_callback_(connect_callback),
779 handshake_callback_(handshake_callback),
780 close_callback_(close_callback) {
790 long request_timeout_;
806 typedef std::pair<Url, TlsContextPtr> DestinationDescriptor;
812 const size_t QUEUE_SIZE_THRESHOLD = 2048;
814 const int QUEUE_WARN_SECS = 5;
823 : url_(url), tls_context_(tls_context),
824 max_connections_(max_connections), connections_(), queue_(),
825 last_queue_warn_time_(min_date_time), last_queue_size_(0) {
830 closeAllConnections();
840 void addConnection(ConnectionPtr connection) {
841 if (connectionsFull()) {
843 <<
", already at maximum connections: "
844 << max_connections_);
847 connections_.push_back(connection);
854 void closeConnection(ConnectionPtr connection) {
855 for (
auto it = connections_.begin(); it != connections_.end(); ++it) {
856 if (*it == connection) {
858 connections_.erase(it);
866 void closeAllConnections() {
868 while (!queue_.empty()) {
872 for (
auto const& connection : connections_) {
876 connections_.clear();
902 void garbageCollectConnections() {
903 for (
auto it = connections_.begin(); it != connections_.end();) {
904 (*it)->isClosedByPeer();
905 if (!(*it)->isClosed()) {
908 it = connections_.erase(it);
924 ConnectionPtr getIdleConnection() {
925 for (
auto const& connection : connections_) {
926 if (!connection->isTransactionOngoing() &&
927 !connection->isClosed()) {
932 return (ConnectionPtr());
941 ConnectionPtr findBySocketFd(
int socket_fd) {
942 for (
auto const& connection : connections_) {
943 if (connection->isMySocket(socket_fd)) {
948 return (ConnectionPtr());
954 bool connectionsEmpty() {
955 return (connections_.empty());
961 bool connectionsFull() {
962 return (connections_.size() >= max_connections_);
968 size_t connectionCount() {
969 return (connections_.size());
975 size_t getMaxConnections()
const {
976 return (max_connections_);
982 bool queueEmpty()
const {
983 return (queue_.empty());
992 void pushRequest(RequestDescriptor desc) {
994 size_t size = queue_.size();
997 if ((size > QUEUE_SIZE_THRESHOLD) && (size > last_queue_size_)) {
998 ptime now = microsec_clock::universal_time();
999 if ((now - last_queue_warn_time_) > seconds(QUEUE_WARN_SECS)) {
1004 last_queue_warn_time_ = now;
1009 last_queue_size_ = size;
1015 RequestDescriptor popNextRequest() {
1016 if (queue_.empty()) {
1020 RequestDescriptor desc = queue_.front();
1033 size_t max_connections_;
1036 std::list<ConnectionPtr> connections_;
1039 std::queue<RequestDescriptor> queue_;
1042 ptime last_queue_warn_time_;
1045 size_t last_queue_size_;
1049 typedef boost::shared_ptr<Destination> DestinationPtr;
1058 DestinationPtr addDestination(
const Url& url,
1060 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1061 DestinationPtr destination(
new Destination(url, tls_context,
1062 max_url_connections_));
1063 destinations_[desc] = destination;
1064 return (destination);
1075 DestinationPtr findDestination(
const Url& url,
1077 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1078 auto it = destinations_.find(desc);
1079 if (it != destinations_.end()) {
1080 return (it->second);
1083 return (DestinationPtr());
1097 void removeDestination(
const Url& url,
1099 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1100 auto it = destinations_.find(desc);
1101 if (it != destinations_.end()) {
1102 it->second->closeAllConnections();
1103 destinations_.erase(it);
1111 std::map<DestinationDescriptor, DestinationPtr> destinations_;
1114 std::mutex pool_mutex_;
1117 size_t max_url_connections_;
1120Connection::Connection(
IOService& io_service,
1122 const ConnectionPoolPtr& conn_pool,
1124 : conn_pool_(conn_pool), url_(url), tls_context_(tls_context),
1125 tcp_socket_(), tls_socket_(), timer_(io_service),
1126 current_request_(), current_response_(), parser_(),
1127 current_callback_(), buf_(), input_buf_(), current_transid_(0),
1128 close_callback_(), started_(false), need_handshake_(false),
1131 tcp_socket_.reset(
new asiolink::TCPSocket<SocketCallback>(io_service));
1133 tls_socket_.reset(
new asiolink::TLSSocket<SocketCallback>(io_service,
1135 need_handshake_ =
true;
1139Connection::~Connection() {
1144Connection::resetState() {
1146 current_request_.reset();
1147 current_response_.reset();
1153Connection::closeCallback(
const bool clear) {
1154 if (close_callback_) {
1157 close_callback_(tcp_socket_->getNative());
1158 }
else if (tls_socket_) {
1159 close_callback_(tls_socket_->getNative());
1162 "internal error: can't find a socket to close");
1175Connection::isClosedByPeer() {
1177 if (started_ || closed_) {
1181 if (MultiThreadingMgr::instance().getMode()) {
1182 std::lock_guard<std::mutex> lk(mutex_);
1183 isClosedByPeerInternal();
1185 isClosedByPeerInternal();
1190Connection::isClosedByPeerInternal() {
1199 if (tcp_socket_->getASIOSocket().is_open() &&
1200 !tcp_socket_->isUsable()) {
1203 tcp_socket_->close();
1205 }
else if (tls_socket_) {
1206 if (tls_socket_->getASIOSocket().is_open() &&
1207 !tls_socket_->isUsable()) {
1210 tls_socket_->close();
1220 const long request_timeout,
1225 if (MultiThreadingMgr::instance().getMode()) {
1226 std::lock_guard<std::mutex> lk(mutex_);
1227 doTransactionInternal(request, response, request_timeout,
1228 callback, connect_callback, handshake_callback,
1231 doTransactionInternal(request, response, request_timeout,
1232 callback, connect_callback, handshake_callback,
1240 const long request_timeout,
1247 current_request_ = request;
1248 current_response_ = response;
1250 parser_->initModel();
1251 current_callback_ = callback;
1252 handshake_callback_ = handshake_callback;
1253 close_callback_ = close_callback;
1258 buf_ = request->toString();
1262 .arg(request->toBriefString())
1263 .arg(url_.toText());
1268 .arg(HttpMessageParserBase::logFormatHttpMessage(request->toString(),
1269 MAX_LOGGED_MESSAGE_SIZE));
1272 scheduleTimer(request_timeout);
1278 static_cast<unsigned short>(url_.getPort()));
1279 SocketCallback socket_cb(std::bind(&Connection::connectCallback, shared_from_this(),
1280 connect_callback, current_transid_,
1285 tcp_socket_->open(&endpoint, socket_cb);
1289 tls_socket_->open(&endpoint, socket_cb);
1296 }
catch (
const std::exception& ex) {
1303Connection::close() {
1304 if (MultiThreadingMgr::instance().getMode()) {
1305 std::lock_guard<std::mutex> lk(mutex_);
1306 return (closeInternal());
1308 return (closeInternal());
1313Connection::closeInternal() {
1315 closeCallback(
true);
1320 tcp_socket_->close();
1323 tls_socket_->close();
1330Connection::isMySocket(
int socket_fd)
const {
1332 return (tcp_socket_->getNative() == socket_fd);
1333 }
else if (tls_socket_) {
1334 return (tls_socket_->getNative() == socket_fd);
1337 std::cerr <<
"internal error: can't find my socket\n";
1342Connection::checkPrematureTimeout(
const uint64_t transid) {
1343 if (MultiThreadingMgr::instance().getMode()) {
1344 std::lock_guard<std::mutex> lk(mutex_);
1345 return (checkPrematureTimeoutInternal(transid));
1347 return (checkPrematureTimeoutInternal(transid));
1352Connection::checkPrematureTimeoutInternal(
const uint64_t transid) {
1358 if (!isTransactionOngoing() || (transid != current_transid_)) {
1360 .arg(isTransactionOngoing())
1362 .arg(current_transid_);
1370Connection::terminate(
const boost::system::error_code& ec,
1371 const std::string& parsing_error) {
1372 if (MultiThreadingMgr::instance().getMode()) {
1373 std::lock_guard<std::mutex> lk(mutex_);
1374 terminateInternal(ec, parsing_error);
1376 terminateInternal(ec, parsing_error);
1381Connection::terminateInternal(
const boost::system::error_code& ec,
1382 const std::string& parsing_error) {
1384 if (isTransactionOngoing()) {
1388 tcp_socket_->cancel();
1391 tls_socket_->cancel();
1394 if (!ec && current_response_->isFinalized()) {
1395 response = current_response_;
1399 .arg(url_.toText());
1405 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1406 "[HttpResponseParser is null]");
1409 std::string err = parsing_error.empty() ? ec.message() :
1419 if (!parsing_error.empty()) {
1424 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1425 "[HttpResponseParser is null]");
1432 if (MultiThreadingMgr::instance().getMode()) {
1434 current_callback_(ec, response, parsing_error);
1436 current_callback_(ec, response, parsing_error);
1444 (!current_request_->isPersistent() ||
1445 (ec == boost::asio::error::timed_out))) {
1454 ConnectionPoolPtr conn_pool = conn_pool_.lock();
1456 conn_pool->postProcessNextRequest(url_, tls_context_);
1461Connection::scheduleTimer(
const long request_timeout) {
1462 if (request_timeout > 0) {
1463 timer_.setup(std::bind(&Connection::timerCallback,
this), request_timeout,
1464 IntervalTimer::ONE_SHOT);
1469Connection::doHandshake(
const uint64_t transid) {
1471 if (!need_handshake_) {
1476 SocketCallback socket_cb(std::bind(&Connection::handshakeCallback,
1478 handshake_callback_,
1482 tls_socket_->handshake(socket_cb);
1485 terminate(boost::asio::error::not_connected);
1490Connection::doSend(
const uint64_t transid) {
1491 SocketCallback socket_cb(std::bind(&Connection::sendCallback,
1498 tcp_socket_->asyncSend(&buf_[0], buf_.size(), socket_cb);
1503 tls_socket_->asyncSend(&buf_[0], buf_.size(), socket_cb);
1508 std::cerr <<
"internal error: can't find a socket to send to\n";
1510 "internal error: can't find a socket to send to");
1512 terminate(boost::asio::error::not_connected);
1517Connection::doReceive(
const uint64_t transid) {
1519 SocketCallback socket_cb(std::bind(&Connection::receiveCallback,
1526 tcp_socket_->asyncReceive(
static_cast<void*
>(input_buf_.data()),
1527 input_buf_.size(), 0,
1528 &endpoint, socket_cb);
1532 tls_socket_->asyncReceive(
static_cast<void*
>(input_buf_.data()),
1533 input_buf_.size(), 0,
1534 &endpoint, socket_cb);
1538 std::cerr <<
"internal error: can't find a socket to receive from\n";
1540 "internal error: can't find a socket to receive from");
1543 terminate(boost::asio::error::not_connected);
1549 const uint64_t transid,
1550 const boost::system::error_code& ec) {
1551 if (checkPrematureTimeout(transid)) {
1556 if (connect_callback) {
1560 if (!connect_callback(ec, tcp_socket_->getNative())) {
1563 }
else if (tls_socket_) {
1564 if (!connect_callback(ec, tls_socket_->getNative())) {
1569 std::cerr <<
"internal error: can't find a socket to connect\n";
1573 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1581 (ec.value() != boost::asio::error::in_progress) &&
1582 (ec.value() != boost::asio::error::already_connected)) {
1587 doHandshake(transid);
1593 const uint64_t transid,
1594 const boost::system::error_code& ec) {
1595 need_handshake_ =
false;
1596 if (checkPrematureTimeout(transid)) {
1601 if (handshake_callback) {
1605 if (!handshake_callback(ec, tls_socket_->getNative())) {
1610 std::cerr <<
"internal error: can't find TLS socket\n";
1614 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1626Connection::sendCallback(
const uint64_t transid,
1627 const boost::system::error_code& ec,
1629 if (checkPrematureTimeout(transid)) {
1634 if (ec.value() == boost::asio::error::operation_aborted) {
1639 }
else if ((ec.value() == boost::asio::error::would_block) ||
1640 (ec.value() == boost::asio::error::try_again)) {
1651 scheduleTimer(timer_.getInterval());
1656 buf_.erase(0, length);
1670Connection::receiveCallback(
const uint64_t transid,
1671 const boost::system::error_code& ec,
1673 if (checkPrematureTimeout(transid)) {
1678 if (ec.value() == boost::asio::error::operation_aborted) {
1684 if ((ec.value() != boost::asio::error::try_again) &&
1685 (ec.value() != boost::asio::error::would_block)) {
1697 scheduleTimer(timer_.getInterval());
1699 if (runParser(ec, length)) {
1705Connection::runParser(
const boost::system::error_code& ec,
size_t length) {
1706 if (MultiThreadingMgr::instance().getMode()) {
1707 std::lock_guard<std::mutex> lk(mutex_);
1708 return (runParserInternal(ec, length));
1710 return (runParserInternal(ec, length));
1715Connection::runParserInternal(
const boost::system::error_code& ec,
1719 parser_->postBuffer(
static_cast<void*
>(input_buf_.data()), length);
1724 if (parser_->needData()) {
1727 }
else if (parser_->httpParseOk()) {
1731 current_response_->finalize();
1732 terminateInternal(ec);
1734 }
catch (
const std::exception& ex) {
1736 terminateInternal(ec, ex.what());
1742 terminateInternal(ec, parser_->getErrorMessage());
1749Connection::timerCallback() {
1751 terminate(boost::asio::error::timed_out);
1786 bool defer_thread_start =
false)
1787 : thread_pool_size_(thread_pool_size), thread_pool_() {
1788 if (thread_pool_size_ > 0) {
1790 thread_io_service_.reset(
new IOService());
1793 thread_pool_.reset(
new HttpThreadPool(thread_io_service_, thread_pool_size_,
1794 defer_thread_start));
1798 conn_pool_.reset(
new ConnectionPool(*thread_io_service_, thread_pool_size_));
1801 .arg(thread_pool_size_);
1805 conn_pool_.reset(
new ConnectionPool(io_service, 1));
1823 thread_pool_->checkPausePermissions();
1830 thread_pool_->run();
1842 thread_pool_->stop();
1851 if (!thread_pool_) {
1856 thread_pool_->pause();
1864 if (!thread_pool_) {
1869 thread_pool_->run();
1878 return (thread_pool_->isRunning());
1890 return (thread_pool_->isStopped());
1902 return (thread_pool_->isPaused());
1913 return (thread_io_service_);
1920 return (thread_pool_size_);
1927 if (!thread_pool_) {
1930 return (thread_pool_->getThreadCount());
1939 size_t thread_pool_size_;
1950 bool defer_thread_start ) {
1951 if (thread_pool_size > 0) {
1952 if (!MultiThreadingMgr::instance().getMode()) {
1954 "HttpClient thread_pool_size must be zero"
1955 "when Kea core multi-threading is disabled");
1960 defer_thread_start));
1980 if ((url.
getScheme() == Url::Scheme::HTTPS) && !tls_context) {
1992 if (!request_callback) {
1996 impl_->conn_pool_->queueRequest(url, tls_context, request, response,
1998 request_callback, connect_callback,
1999 handshake_callback, close_callback);
2004 return (impl_->conn_pool_->closeIfOutOfBand(socket_fd));
2014 impl_->checkPermissions();
2034 return (impl_->getThreadIOService());
2039 return (impl_->getThreadPoolSize());
2044 return (impl_->getThreadCount());
2049 return (impl_->isRunning());
2054 return (impl_->isStopped());
2059 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.
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.
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.
HttpClient(asiolink::IOService &io_service, size_t thread_pool_size=0, bool defer_thread_start=false)
Constructor.
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.
Implements a pausable pool of IOService driven threads.
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< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
boost::shared_ptr< HttpThreadPool > HttpThreadPoolPtr
Defines a pointer to a thread pool.
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.