13 #include <http/http_messages.h> 14 #include <boost/bind.hpp> 23 constexpr
size_t MAX_LOGGED_MESSAGE_SIZE = 1024;
32 SocketCallback::operator()(boost::system::error_code ec,
size_t length) {
33 if (ec.value() == boost::asio::error::operation_aborted) {
36 callback_(ec, length);
44 const long request_timeout,
45 const long idle_timeout)
46 : request_timer_(io_service),
47 request_timeout_(request_timeout),
48 idle_timeout_(idle_timeout),
51 connection_pool_(connection_pool),
52 response_creator_(response_creator),
53 request_(response_creator_->createNewHttpRequest()),
55 acceptor_callback_(callback),
72 HttpConnection::stopThisConnection() {
76 .arg(getRemoteEndpointAddressAsText());
77 connection_pool_.
stop(shared_from_this());
90 boost::asio::placeholders::error);
94 }
catch (
const std::exception& ex) {
96 "connections: " << ex.
what());
107 SocketCallback cb(boost::bind(&HttpConnection::socketReadCallback,
109 boost::asio::placeholders::error,
110 boost::asio::placeholders::bytes_transferred));
111 socket_.
asyncReceive(static_cast<void*>(buf_.data()), buf_.size(),
115 stopThisConnection();
120 HttpConnection::doWrite() {
122 if (!output_buf_.empty()) {
126 SocketCallback cb(boost::bind(&HttpConnection::socketWriteCallback,
128 boost::asio::placeholders::error,
129 boost::asio::placeholders::bytes_transferred));
131 output_buf_.length(),
134 if (!request_->isPersistent()) {
135 stopThisConnection();
138 reinitProcessingState();
143 stopThisConnection();
149 output_buf_ = response->toString();
155 HttpConnection::acceptorCallback(
const boost::system::error_code& ec) {
156 if (!acceptor_.
isOpen()) {
161 stopThisConnection();
164 acceptor_callback_(ec);
168 HTTP_REQUEST_RECEIVE_START)
169 .arg(getRemoteEndpointAddressAsText())
170 .arg(static_cast<unsigned>(request_timeout_/1000));
178 HttpConnection::socketReadCallback(boost::system::error_code ec,
size_t length) {
182 if (ec.value() == boost::asio::error::operation_aborted) {
187 }
else if ((ec.value() != boost::asio::error::try_again) &&
188 (ec.value() != boost::asio::error::would_block)) {
189 stopThisConnection();
207 .arg(getRemoteEndpointAddressAsText());
209 std::string s(&buf_[0], buf_[0] + length);
210 parser_->postBuffer(static_cast<void*>(buf_.data()), length);
214 if (parser_->needData()) {
219 request_->finalize();
222 HTTP_CLIENT_REQUEST_RECEIVED)
223 .arg(getRemoteEndpointAddressAsText());
226 HTTP_CLIENT_REQUEST_RECEIVED_DETAILS)
227 .arg(getRemoteEndpointAddressAsText())
228 .arg(parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE));
230 }
catch (
const std::exception& ex) {
232 HTTP_BAD_CLIENT_REQUEST_RECEIVED)
233 .arg(getRemoteEndpointAddressAsText())
237 HTTP_BAD_CLIENT_REQUEST_RECEIVED_DETAILS)
238 .arg(getRemoteEndpointAddressAsText())
239 .arg(parser_->getBufferAsString(MAX_LOGGED_MESSAGE_SIZE));
245 HttpResponsePtr response = response_creator_->createHttpResponse(request_);
247 HTTP_SERVER_RESPONSE_SEND)
248 .arg(response->toBriefString())
249 .arg(getRemoteEndpointAddressAsText());
252 HTTP_SERVER_RESPONSE_SEND_DETAILS)
253 .arg(getRemoteEndpointAddressAsText())
255 MAX_LOGGED_MESSAGE_SIZE));
260 asyncSendResponse(response);
265 HttpConnection::socketWriteCallback(boost::system::error_code ec,
size_t length) {
269 if (ec.value() == boost::asio::error::operation_aborted) {
274 }
else if ((ec.value() != boost::asio::error::try_again) &&
275 (ec.value() != boost::asio::error::would_block)) {
276 stopThisConnection();
289 if (length <= output_buf_.size()) {
293 output_buf_.erase(0, length);
299 if (!request_->isPersistent()) {
300 stopThisConnection();
303 reinitProcessingState();
310 HttpConnection::reinitProcessingState() {
311 request_ = response_creator_->createNewHttpRequest();
312 parser_.reset(
new HttpRequestParser(*request_));
313 parser_->initModel();
318 HttpConnection::setupRequestTimer() {
323 request_timer_.
setup(boost::bind(&HttpConnection::requestTimeoutCallback,
325 request_timeout_, IntervalTimer::ONE_SHOT);
329 HttpConnection::setupIdleTimer() {
330 request_timer_.
setup(boost::bind(&HttpConnection::idleTimeoutCallback,
332 idle_timeout_, IntervalTimer::ONE_SHOT);
336 HttpConnection::requestTimeoutCallback() {
338 HTTP_CLIENT_REQUEST_TIMEOUT_OCCURRED)
339 .arg(getRemoteEndpointAddressAsText());
341 response_creator_->createStockHttpResponse(request_,
343 asyncSendResponse(response);
347 HttpConnection::idleTimeoutCallback() {
349 HTTP_IDLE_CONNECTION_TIMEOUT_OCCURRED)
350 .arg(getRemoteEndpointAddressAsText());
351 stopThisConnection();
355 HttpConnection::getRemoteEndpointAddressAsText()
const {
358 return (socket_.
getASIOSocket().remote_endpoint().address().to_string());
362 return (
"(unknown address)");
virtual void asyncSend(const void *data, size_t length, const IOEndpoint *endpoint, C &callback)
Send Asynchronously.
boost::shared_ptr< const HttpResponse > ConstHttpResponsePtr
Pointer to the const HttpResponse object.
const int DBGLVL_TRACE_BASIC
Trace basic operations.
static std::string logFormatHttpMessage(const std::string &message, const size_t limit=0)
Formats provided HTTP message for logging.
virtual void close()
Close socket.
void cancel()
Cancel the timer.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
A generic parser for HTTP requests.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The IOService class is a wrapper for the ASIO io_service class.
~HttpConnection()
Destructor.
Generic error reported within HttpConnection class.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
The TCPEndpoint class is a concrete derived class of IOEndpoint that represents an endpoint of a TCP ...
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
const int DBGLVL_TRACE_DETAIL_DATA
Trace data associated with detailed operations.
void asyncAccept(const TCPSocket< SocketCallback > &socket, C &callback)
Asynchronously accept new connection.
void stop(const HttpConnectionPtr &connection)
Stops a connection and removes it from the pool.
boost::function< void(const boost::system::error_code &)> HttpAcceptorCallback
Type of the callback for the TCP acceptor used in this library.
boost::shared_ptr< HttpResponseCreator > HttpResponseCreatorPtr
Pointer to the HttpResponseCreator object.
Defines the logger used by the top-level component of kea-dhcp-ddns.
void doRead()
Starts asynchronous read from the socket.
virtual boost::asio::ip::tcp::socket & getASIOSocket() const
Returns reference to the underlying ASIO socket.
void close()
Closes the socket.
virtual void asyncReceive(void *data, size_t length, size_t offset, IOEndpoint *endpoint, C &callback)
Receive Asynchronously.
bool isOpen() const
Checks if the acceptor is open.
void asyncAccept()
Asynchronously accepts new connection.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
isc::log::Logger http_logger("http")
Defines the logger used within libkea-http library.
const int DBGLVL_TRACE_DETAIL
Trace detailed operations.
const int DBGLVL_TRACE_BASIC_DATA
Trace data associated with the basic operations.
Pool of active HTTP connections.
void setup(const Callback &cbfunc, const long interval, const Mode &mode=REPEATING)
Register timer callback function and interval.