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)>
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);
94typedef boost::shared_ptr<ConnectionPool> ConnectionPoolPtr;
111class Connection :
public boost::enable_shared_from_this<Connection> {
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);
412 boost::weak_ptr<ConnectionPool> conn_pool_;
421 std::shared_ptr<TCPSocket<SocketCallback>> tcp_socket_;
424 std::shared_ptr<TLSSocket<SocketCallback>> tls_socket_;
448 std::array<char, 32768> input_buf_;
451 uint64_t current_transid_;
460 std::atomic<bool> started_;
463 std::atomic<bool> need_handshake_;
466 std::atomic<bool> closed_;
473typedef boost::shared_ptr<Connection> ConnectionPtr;
482class ConnectionPool :
public boost::enable_shared_from_this<ConnectionPool> {
491 explicit ConnectionPool(
const IOServicePtr& io_service,
size_t max_url_connections)
492 : io_service_(io_service), destinations_(), pool_mutex_(),
493 max_url_connections_(max_url_connections) {
508 void processNextRequest(
const Url& url,
const TlsContextPtr& tls_context) {
510 std::lock_guard<std::mutex> lk(pool_mutex_);
511 return (processNextRequestInternal(url, tls_context));
513 return (processNextRequestInternal(url, tls_context));
522 void postProcessNextRequest(
const Url& url,
524 io_service_->post(std::bind(&ConnectionPool::processNextRequest,
525 shared_from_this(), url, tls_context));
548 void queueRequest(
const Url& url,
552 const long request_timeout,
558 std::lock_guard<std::mutex> lk(pool_mutex_);
559 return (queueRequestInternal(url, tls_context, request, response,
560 request_timeout, request_callback,
561 connect_callback, handshake_callback,
564 return (queueRequestInternal(url, tls_context, request, response,
565 request_timeout, request_callback,
566 connect_callback, handshake_callback,
575 std::lock_guard<std::mutex> lk(pool_mutex_);
594 void closeIfOutOfBand(
int socket_fd) {
596 std::lock_guard<std::mutex> lk(pool_mutex_);
597 closeIfOutOfBandInternal(socket_fd);
599 closeIfOutOfBandInternal(socket_fd);
612 void processNextRequestInternal(
const Url& url,
616 DestinationPtr destination = findDestination(url, tls_context);
619 destination->garbageCollectConnections();
620 if (!destination->queueEmpty()) {
623 ConnectionPtr connection = destination->getIdleConnection();
626 if (destination->connectionsFull()) {
631 connection.reset(
new Connection(io_service_, tls_context,
632 shared_from_this(), url));
633 destination->addConnection(connection);
638 RequestDescriptor desc = destination->popNextRequest();
639 connection->doTransaction(desc.request_, desc.response_,
640 desc.request_timeout_, desc.callback_,
641 desc.connect_callback_,
642 desc.handshake_callback_,
643 desc.close_callback_);
670 void queueRequestInternal(
const Url& url,
674 const long request_timeout,
679 ConnectionPtr connection;
681 DestinationPtr destination = findDestination(url, tls_context);
684 destination->garbageCollectConnections();
686 connection = destination->getIdleConnection();
689 destination = addDestination(url, tls_context);
693 if (destination->connectionsFull()) {
695 destination->pushRequest(RequestDescriptor(request, response,
705 connection.reset(
new Connection(io_service_, tls_context,
706 shared_from_this(), url));
707 destination->addConnection(connection);
711 connection->doTransaction(request, response, request_timeout, request_callback,
712 connect_callback, handshake_callback, close_callback);
719 void closeAllInternal() {
720 for (
auto const& destination : destinations_) {
721 destination.second->closeAllConnections();
724 destinations_.clear();
741 void closeIfOutOfBandInternal(
int socket_fd) {
742 for (
auto const& destination : destinations_) {
744 ConnectionPtr connection = destination.second->findBySocketFd(socket_fd);
746 if (!connection->isTransactionOngoing()) {
752 destination.second->closeConnection(connection);
762 struct RequestDescriptor {
778 const long& request_timeout,
783 : request_(request), response_(response),
784 request_timeout_(request_timeout), callback_(callback),
785 connect_callback_(connect_callback),
786 handshake_callback_(handshake_callback),
787 close_callback_(close_callback) {
797 long request_timeout_;
813 typedef std::pair<Url, TlsContextPtr> DestinationDescriptor;
819 const size_t QUEUE_SIZE_THRESHOLD = 2048;
821 const int QUEUE_WARN_SECS = 5;
829 Destination(Url
const& url,
TlsContextPtr tls_context,
size_t max_connections)
830 : url_(url), tls_context_(tls_context),
831 max_connections_(max_connections), connections_(), queue_(),
832 last_queue_warn_time_(min_date_time), last_queue_size_(0) {
837 closeAllConnections();
847 void addConnection(ConnectionPtr connection) {
848 if (connectionsFull()) {
849 isc_throw(BadValue,
"URL: " << url_.toText()
850 <<
", already at maximum connections: "
851 << max_connections_);
854 connections_.push_back(connection);
861 void closeConnection(ConnectionPtr connection) {
862 for (
auto it = connections_.begin(); it != connections_.end(); ++it) {
863 if (*it == connection) {
865 connections_.erase(it);
873 void closeAllConnections() {
875 while (!queue_.empty()) {
879 for (
auto const& connection : connections_) {
883 connections_.clear();
909 void garbageCollectConnections() {
910 for (
auto it = connections_.begin(); it != connections_.end();) {
911 (*it)->isClosedByPeer();
912 if (!(*it)->isClosed()) {
915 it = connections_.erase(it);
931 ConnectionPtr getIdleConnection() {
932 for (
auto const& connection : connections_) {
933 if (!connection->isTransactionOngoing() &&
934 !connection->isClosed()) {
939 return (ConnectionPtr());
948 ConnectionPtr findBySocketFd(
int socket_fd) {
949 for (
auto const& connection : connections_) {
950 if (connection->isMySocket(socket_fd)) {
955 return (ConnectionPtr());
961 bool connectionsEmpty() {
962 return (connections_.empty());
968 bool connectionsFull() {
969 return (connections_.size() >= max_connections_);
975 size_t connectionCount() {
976 return (connections_.size());
982 size_t getMaxConnections()
const {
983 return (max_connections_);
989 bool queueEmpty()
const {
990 return (queue_.empty());
999 void pushRequest(RequestDescriptor
const& desc) {
1001 size_t size = queue_.size();
1004 if ((size > QUEUE_SIZE_THRESHOLD) && (size > last_queue_size_)) {
1005 ptime now = microsec_clock::universal_time();
1006 if ((now - last_queue_warn_time_) > seconds(QUEUE_WARN_SECS)) {
1011 last_queue_warn_time_ = now;
1016 last_queue_size_ = size;
1022 RequestDescriptor popNextRequest() {
1023 if (queue_.empty()) {
1024 isc_throw(InvalidOperation,
"cannot pop, queue is empty");
1027 RequestDescriptor desc = queue_.front();
1040 size_t max_connections_;
1043 std::list<ConnectionPtr> connections_;
1046 std::queue<RequestDescriptor> queue_;
1049 ptime last_queue_warn_time_;
1052 size_t last_queue_size_;
1056 typedef boost::shared_ptr<Destination> DestinationPtr;
1065 DestinationPtr addDestination(
const Url& url,
1067 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1068 DestinationPtr destination(
new Destination(url, tls_context,
1069 max_url_connections_));
1070 destinations_[desc] = destination;
1071 return (destination);
1082 DestinationPtr findDestination(
const Url& url,
1084 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1085 auto it = destinations_.find(desc);
1086 if (it != destinations_.end()) {
1087 return (it->second);
1090 return (DestinationPtr());
1104 void removeDestination(
const Url& url,
1106 const DestinationDescriptor& desc = std::make_pair(url, tls_context);
1107 auto it = destinations_.find(desc);
1108 if (it != destinations_.end()) {
1109 it->second->closeAllConnections();
1110 destinations_.erase(it);
1118 std::map<DestinationDescriptor, DestinationPtr> destinations_;
1121 std::mutex pool_mutex_;
1124 size_t max_url_connections_;
1129 const ConnectionPoolPtr& conn_pool,
1131 : io_service_(io_service), conn_pool_(conn_pool), url_(url),
1132 tls_context_(tls_context), tcp_socket_(), tls_socket_(),
1133 timer_(new IntervalTimer(io_service)), current_request_(),
1134 current_response_(), parser_(), current_callback_(), buf_(),
1135 position_(0), input_buf_(), current_transid_(0), close_callback_(),
1136 started_(false), need_handshake_(false), closed_(false) {
1142 need_handshake_ =
true;
1146Connection::~Connection() {
1151Connection::resetState() {
1153 current_request_.reset();
1154 current_response_.reset();
1160Connection::closeCallback(
const bool clear) {
1161 if (close_callback_) {
1164 close_callback_(tcp_socket_->getNative());
1165 }
else if (tls_socket_) {
1166 close_callback_(tls_socket_->getNative());
1169 "internal error: can't find a socket to close");
1182Connection::isClosedByPeer() {
1184 if (started_ || closed_) {
1189 std::lock_guard<std::mutex> lk(mutex_);
1190 isClosedByPeerInternal();
1192 isClosedByPeerInternal();
1197Connection::isClosedByPeerInternal() {
1206 if (tcp_socket_->getASIOSocket().is_open() &&
1207 !tcp_socket_->isUsable()) {
1210 tcp_socket_->close();
1212 }
else if (tls_socket_) {
1213 if (tls_socket_->getASIOSocket().is_open() &&
1214 !tls_socket_->isUsable()) {
1217 tls_socket_->close();
1220 isc_throw(Unexpected,
"internal error: can't find the sending socket");
1227 const long request_timeout,
1233 std::lock_guard<std::mutex> lk(mutex_);
1234 doTransactionInternal(request, response, request_timeout,
1235 callback, connect_callback, handshake_callback,
1238 doTransactionInternal(request, response, request_timeout,
1239 callback, connect_callback, handshake_callback,
1247 const long request_timeout,
1254 current_request_ = request;
1255 current_response_ = response;
1256 parser_.reset(
new HttpResponseParser(*current_response_));
1257 parser_->initModel();
1258 current_callback_ = callback;
1259 handshake_callback_ = handshake_callback;
1260 close_callback_ = close_callback;
1265 buf_ = request->toString();
1273 .arg(request->toBriefString())
1274 .arg(url_.toText());
1280 MAX_LOGGED_MESSAGE_SIZE));
1283 scheduleTimer(request_timeout);
1288 TCPEndpoint endpoint(url_.getStrippedHostname(),
1289 static_cast<unsigned short>(url_.getPort()));
1290 SocketCallback socket_cb(std::bind(&Connection::connectCallback, shared_from_this(),
1291 connect_callback, current_transid_,
1296 tcp_socket_->open(&endpoint, socket_cb);
1300 tls_socket_->open(&endpoint, socket_cb);
1305 isc_throw(Unexpected,
"internal error: can't find a socket to open");
1307 }
catch (
const std::exception& ex) {
1314Connection::close() {
1316 std::lock_guard<std::mutex> lk(mutex_);
1317 return (closeInternal());
1319 return (closeInternal());
1324Connection::closeInternal() {
1326 closeCallback(
true);
1331 tcp_socket_->close();
1334 tls_socket_->close();
1341Connection::isMySocket(
int socket_fd)
const {
1343 return (tcp_socket_->getNative() == socket_fd);
1344 }
else if (tls_socket_) {
1345 return (tls_socket_->getNative() == socket_fd);
1348 std::cerr <<
"internal error: can't find my socket\n";
1353Connection::checkPrematureTimeout(
const uint64_t transid) {
1355 std::lock_guard<std::mutex> lk(mutex_);
1356 return (checkPrematureTimeoutInternal(transid));
1358 return (checkPrematureTimeoutInternal(transid));
1363Connection::checkPrematureTimeoutInternal(
const uint64_t transid) {
1369 if (!isTransactionOngoing() || (transid != current_transid_)) {
1371 .arg(isTransactionOngoing())
1373 .arg(current_transid_);
1381Connection::terminate(
const boost::system::error_code& ec,
1382 const std::string& parsing_error) {
1384 std::lock_guard<std::mutex> lk(mutex_);
1385 terminateInternal(ec, parsing_error);
1387 terminateInternal(ec, parsing_error);
1392Connection::terminateInternal(
const boost::system::error_code& ec,
1393 const std::string& parsing_error) {
1395 if (isTransactionOngoing()) {
1399 tcp_socket_->cancel();
1402 tls_socket_->cancel();
1405 if (!ec && current_response_->isFinalized()) {
1406 response = current_response_;
1410 .arg(url_.toText());
1416 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1417 "[HttpResponseParser is null]");
1420 std::string err = parsing_error.empty() ? ec.message() :
1430 if (!parsing_error.empty()) {
1435 parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE) :
1436 "[HttpResponseParser is null]");
1444 UnlockGuard<std::mutex> lock(mutex_);
1445 current_callback_(ec, response, parsing_error);
1447 current_callback_(ec, response, parsing_error);
1455 (!current_request_->isPersistent() ||
1456 (ec == boost::asio::error::timed_out))) {
1465 ConnectionPoolPtr conn_pool = conn_pool_.lock();
1467 conn_pool->postProcessNextRequest(url_, tls_context_);
1472Connection::scheduleTimer(
const long request_timeout) {
1473 if (request_timeout > 0) {
1474 timer_->setup(std::bind(&Connection::timerCallback,
this), request_timeout,
1480Connection::doHandshake(
const uint64_t transid) {
1482 if (!need_handshake_) {
1487 SocketCallback socket_cb(std::bind(&Connection::handshakeCallback,
1489 handshake_callback_,
1493 tls_socket_->handshake(socket_cb);
1496 terminate(boost::asio::error::not_connected);
1501Connection::doSend(
const uint64_t transid) {
1502 SocketCallback socket_cb(std::bind(&Connection::sendCallback,
1511 size_t remaining = buf_.size() - position_;
1513 tcp_socket_->asyncSend(&buf_[position_], remaining, socket_cb);
1518 tls_socket_->asyncSend(&buf_[position_], remaining, socket_cb);
1523 std::cerr <<
"internal error: can't find a socket to send to\n";
1525 "internal error: can't find a socket to send to");
1527 terminate(boost::asio::error::not_connected);
1532Connection::doReceive(
const uint64_t transid) {
1533 TCPEndpoint endpoint;
1534 SocketCallback socket_cb(std::bind(&Connection::receiveCallback,
1541 tcp_socket_->asyncReceive(
static_cast<void*
>(input_buf_.data()),
1542 input_buf_.size(), 0,
1543 &endpoint, socket_cb);
1547 tls_socket_->asyncReceive(
static_cast<void*
>(input_buf_.data()),
1548 input_buf_.size(), 0,
1549 &endpoint, socket_cb);
1553 std::cerr <<
"internal error: can't find a socket to receive from\n";
1555 "internal error: can't find a socket to receive from");
1558 terminate(boost::asio::error::not_connected);
1564 const uint64_t transid,
1565 const boost::system::error_code& ec) {
1566 if (checkPrematureTimeout(transid)) {
1571 if (connect_callback) {
1575 if (!connect_callback(ec, tcp_socket_->getNative())) {
1578 }
else if (tls_socket_) {
1579 if (!connect_callback(ec, tls_socket_->getNative())) {
1584 std::cerr <<
"internal error: can't find a socket to connect\n";
1588 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1596 (ec.value() != boost::asio::error::in_progress) &&
1597 (ec.value() != boost::asio::error::already_connected)) {
1602 doHandshake(transid);
1608 const uint64_t transid,
1609 const boost::system::error_code& ec) {
1610 need_handshake_ =
false;
1611 if (checkPrematureTimeout(transid)) {
1616 if (handshake_callback) {
1620 if (!handshake_callback(ec, tls_socket_->getNative())) {
1625 std::cerr <<
"internal error: can't find TLS socket\n";
1629 if (ec && (ec.value() == boost::asio::error::operation_aborted)) {
1641Connection::sendCallback(
const uint64_t transid,
1642 const boost::system::error_code& ec,
1644 if (checkPrematureTimeout(transid)) {
1649 if (ec.value() == boost::asio::error::operation_aborted) {
1654 }
else if ((ec.value() == boost::asio::error::would_block) ||
1655 (ec.value() == boost::asio::error::try_again)) {
1666 scheduleTimer(timer_->getInterval());
1670 if (length >= buf_.size() - position_) {
1671 position_ = buf_.size();
1673 position_ += length;
1678 if (position_ == buf_.size()) {
1687Connection::receiveCallback(
const uint64_t transid,
1688 const boost::system::error_code& ec,
1690 if (checkPrematureTimeout(transid)) {
1695 if (ec.value() == boost::asio::error::operation_aborted) {
1700 if ((ec.value() != boost::asio::error::try_again) &&
1701 (ec.value() != boost::asio::error::would_block)) {
1713 scheduleTimer(timer_->getInterval());
1715 if (runParser(ec, length)) {
1721Connection::runParser(
const boost::system::error_code& ec,
size_t length) {
1723 std::lock_guard<std::mutex> lk(mutex_);
1724 return (runParserInternal(ec, length));
1726 return (runParserInternal(ec, length));
1731Connection::runParserInternal(
const boost::system::error_code& ec,
1735 parser_->postBuffer(
static_cast<void*
>(input_buf_.data()), length);
1740 if (parser_->needData()) {
1743 }
else if (parser_->httpParseOk()) {
1747 current_response_->finalize();
1748 terminateInternal(ec);
1750 }
catch (
const std::exception& ex) {
1752 terminateInternal(ec, ex.what());
1758 terminateInternal(ec, parser_->getErrorMessage());
1765Connection::timerCallback() {
1767 terminate(boost::asio::error::timed_out);
1802 bool defer_thread_start =
false)
1803 : thread_pool_size_(thread_pool_size), thread_pool_() {
1804 if (thread_pool_size_ > 0) {
1806 thread_io_service_.reset(
new IOService());
1810 conn_pool_.reset(
new ConnectionPool(thread_io_service_, thread_pool_size_));
1814 defer_thread_start));
1817 .arg(thread_pool_size_);
1821 conn_pool_.reset(
new ConnectionPool(io_service, 1));
1839 thread_pool_->checkPausePermissions();
1846 thread_pool_->run();
1858 thread_pool_->stop();
1861 if (thread_io_service_) {
1862 thread_io_service_->stopAndPoll();
1863 thread_io_service_->stop();
1872 if (!thread_pool_) {
1877 thread_pool_->pause();
1885 if (!thread_pool_) {
1890 thread_pool_->run();
1899 return (thread_pool_->isRunning());
1911 return (thread_pool_->isStopped());
1923 return (thread_pool_->isPaused());
1934 return (thread_io_service_);
1941 return (thread_pool_size_);
1948 if (!thread_pool_) {
1951 return (thread_pool_->getThreadCount());
1960 size_t thread_pool_size_;
1971 size_t thread_pool_size,
bool defer_thread_start) {
1972 if (!multi_threading_enabled && thread_pool_size) {
1974 "HttpClient thread_pool_size must be zero "
1975 "when Kea core multi-threading is disabled");
1979 defer_thread_start));
2012 if (!request_callback) {
2016 impl_->conn_pool_->queueRequest(url, tls_context, request, response,
2018 request_callback, connect_callback,
2019 handshake_callback, close_callback);
2024 return (impl_->conn_pool_->closeIfOutOfBand(socket_fd));
2034 impl_->checkPermissions();
2054 return (impl_->getThreadIOService());
2059 return (impl_->getThreadPoolSize());
2064 return (impl_->getThreadCount());
2069 return (impl_->isRunning());
2074 return (impl_->isStopped());
2079 return (impl_->isPaused());
A generic exception that is thrown if a function is called in a prohibited way.
The IOService class is a wrapper for the ASIO io_context class.
Implements a pausable pool of IOService driven threads.
The TCPSocket class is a concrete derived class of IOAsioSocket that represents a TCP socket.
The TLSSocket class is a concrete derived class of IOAsioSocket that represents a TLS socket.
A generic error raised by the HttpClient class.
HttpClient implementation.
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.
HttpClientImpl(const IOServicePtr &io_service, size_t thread_pool_size=0, bool defer_thread_start=false)
Constructor.
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(const asiolink::IOServicePtr &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.
static std::string logFormatHttpMessage(const std::string &message, const size_t limit=0)
Formats provided HTTP message for logging.
Scheme getScheme() const
Returns parsed scheme.
bool isValid() const
Checks if the URL is valid.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
#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< isc::asiolink::IntervalTimer > IntervalTimerPtr
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.
std::function< void(boost::system::error_code ec, size_t length)> SocketCallbackFunction
Type of the function implementing a callback invoked by the SocketCallback functor.
Defines the logger used by the top-level component of kea-lfc.
HTTP request/response timeout value.
long value_
Timeout value specified.