connection.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // connection.cpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #include "connection.hpp"
  11. #include <utility>
  12. #include <vector>
  13. #include "connection_manager.hpp"
  14. #include "request_handler.hpp"
  15. namespace http {
  16. namespace server {
  17. connection::connection(boost::asio::ip::tcp::socket socket,
  18. connection_manager& manager, request_handler& handler)
  19. : socket_(std::move(socket)),
  20. connection_manager_(manager),
  21. request_handler_(handler)
  22. {
  23. }
  24. void connection::start()
  25. {
  26. do_read();
  27. }
  28. void connection::stop()
  29. {
  30. socket_.close();
  31. }
  32. void connection::do_read()
  33. {
  34. auto self(shared_from_this());
  35. socket_.async_read_some(boost::asio::buffer(buffer_),
  36. [this, self](boost::system::error_code ec, std::size_t bytes_transferred)
  37. {
  38. if (!ec)
  39. {
  40. request_parser::result_type result;
  41. std::tie(result, std::ignore) = request_parser_.parse(
  42. request_, buffer_.data(), buffer_.data() + bytes_transferred);
  43. if (result == request_parser::good)
  44. {
  45. request_handler_.handle_request(request_, reply_);
  46. do_write();
  47. }
  48. else if (result == request_parser::bad)
  49. {
  50. reply_ = reply::stock_reply(reply::bad_request);
  51. do_write();
  52. }
  53. else
  54. {
  55. do_read();
  56. }
  57. }
  58. else if (ec != boost::asio::error::operation_aborted)
  59. {
  60. connection_manager_.stop(shared_from_this());
  61. }
  62. });
  63. }
  64. void connection::do_write()
  65. {
  66. auto self(shared_from_this());
  67. boost::asio::async_write(socket_, reply_.to_buffers(),
  68. [this, self](boost::system::error_code ec, std::size_t)
  69. {
  70. if (!ec)
  71. {
  72. // Initiate graceful connection closure.
  73. boost::system::error_code ignored_ec;
  74. socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both,
  75. ignored_ec);
  76. }
  77. if (ec != boost::asio::error::operation_aborted)
  78. {
  79. connection_manager_.stop(shared_from_this());
  80. }
  81. });
  82. }
  83. } // namespace server
  84. } // namespace http