#include "HttpConnection.h" #include namespace Http { HttpConnection::HttpConnection(asio::io_service& ioService, HttpRequestHandler& handler) : m_strand(ioService), m_socket(ioService), m_requestHandler(handler), m_dataState(false, 0), m_dataIncomplete(false) { } HttpConnection::~HttpConnection() { } asio::ip::tcp::socket& HttpConnection::Socket() { return m_socket; } void HttpConnection::Start() { m_socket.async_read_some(asio::buffer(m_data), m_strand.wrap(std::bind(&HttpConnection::HandleRead, shared_from_this(), std::placeholders::_1, std::placeholders::_2))); } void HttpConnection::HandleRead(const asio::error_code& ec, std::size_t length) { if (!ec) { size_t dataLocation; Utilities::Tribool result; Buffer::iterator dataIterator; if (!m_dataIncomplete) { m_dataState = m_requestParser.Parse(m_request, m_data.data(), m_data.data() + length); dataLocation = std::get<1>(m_dataState) - m_data.data(); } else { std::get<1>(m_dataState) = m_data.data(); dataLocation = 0; } std::tie(result, dataIterator) = m_dataState; if (result && length < m_request.headers.GetContentLength() + dataLocation) { m_dataIncomplete = true; result = Utilities::Tribool::Indeterminate; } else { m_dataIncomplete = false; } if (result) { std::string data; while (dataIterator != m_data.data() + length) data.push_back(*dataIterator++); HttpReply reply = m_requestHandler.HandleRequest(m_request, data); asio::async_write(m_socket, reply.ToBuffers(), m_strand.wrap(std::bind(&HttpConnection::HandleWrite, shared_from_this(), std::placeholders::_1))); } else if (!result) { HttpReply reply = HttpReply::StockReply(HttpReply::Status::BadRequest); asio::async_write(m_socket, reply.ToBuffers(), m_strand.wrap(std::bind(&HttpConnection::HandleWrite, shared_from_this(), std::placeholders::_1))); } else { m_socket.async_read_some(asio::buffer(m_data), m_strand.wrap(std::bind(&HttpConnection::HandleRead, shared_from_this(), std::placeholders::_1, std::placeholders::_2))); } } } void HttpConnection::HandleWrite(const asio::error_code& ec) { if (!ec) { asio::error_code ignored_ec; m_socket.shutdown(asio::ip::tcp::socket::shutdown_both, ignored_ec); } } } // namespace Http