blob: 207c8c8a667c1dc7089b2d187c82168fb04ca8c0 [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2016, Regents of the University of California.
4 *
5 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
6 *
7 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License along with
16 * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
19 */
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080020//
21// connection.cpp
22// ~~~~~~~~~~~~~~
23//
24// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
25//
26// Distributed under the Boost Software License, Version 1.0. (See accompanying
27// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
28//
29
30#include "connection.hpp"
31#include <vector>
32#include <boost/bind.hpp>
33#include "connection_manager.hpp"
34#include "request_handler.hpp"
35
36namespace http {
37namespace server {
38
39connection::connection(boost::asio::io_service& io_service,
40 connection_manager& manager, request_handler& handler)
41 : socket_(io_service),
42 connection_manager_(manager),
43 request_handler_(handler)
44{
45}
46
47boost::asio::ip::tcp::socket& connection::socket()
48{
49 return socket_;
50}
51
52void connection::start()
53{
54 socket_.async_read_some(boost::asio::buffer(buffer_),
55 boost::bind(&connection::handle_read, shared_from_this(),
56 boost::asio::placeholders::error,
57 boost::asio::placeholders::bytes_transferred));
58}
59
60void connection::stop()
61{
62 socket_.close();
63}
64
65void connection::handle_read(const boost::system::error_code& e,
66 std::size_t bytes_transferred)
67{
68 if (!e)
69 {
70 boost::tribool result;
71 boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
72 request_, buffer_.data(), buffer_.data() + bytes_transferred);
73
74 if (result)
75 {
76 request_handler_.handle_request(request_, reply_);
77 boost::asio::async_write(socket_, reply_.to_buffers(),
78 boost::bind(&connection::handle_write, shared_from_this(),
79 boost::asio::placeholders::error));
80 }
81 else if (!result)
82 {
83 reply_ = reply::stock_reply(reply::bad_request);
84 boost::asio::async_write(socket_, reply_.to_buffers(),
85 boost::bind(&connection::handle_write, shared_from_this(),
86 boost::asio::placeholders::error));
87 }
88 else
89 {
90 socket_.async_read_some(boost::asio::buffer(buffer_),
91 boost::bind(&connection::handle_read, shared_from_this(),
92 boost::asio::placeholders::error,
93 boost::asio::placeholders::bytes_transferred));
94 }
95 }
96 else if (e != boost::asio::error::operation_aborted)
97 {
98 connection_manager_.stop(shared_from_this());
99 }
100}
101
102void connection::handle_write(const boost::system::error_code& e)
103{
104 if (!e)
105 {
106 // Initiate graceful connection closure.
107 boost::system::error_code ignored_ec;
108 socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
109 }
110
111 if (e != boost::asio::error::operation_aborted)
112 {
113 connection_manager_.stop(shared_from_this());
114 }
115}
116
117} // namespace server
118} // namespace http