blob: cdbf1b2c4bede453e9719ecc0cc400b0a44fa961 [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"
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080031#include "connection_manager.hpp"
32#include "request_handler.hpp"
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080033#include <boost/bind.hpp>
34#include <vector>
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080035
36namespace http {
37namespace server {
38
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080039connection::connection(boost::asio::io_service& io_service, connection_manager& manager,
40 request_handler& handler)
41 : socket_(io_service)
42 , connection_manager_(manager)
43 , request_handler_(handler)
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080044{
45}
46
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080047boost::asio::ip::tcp::socket&
48connection::socket()
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080049{
50 return socket_;
51}
52
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080053void
54connection::start()
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080055{
56 socket_.async_read_some(boost::asio::buffer(buffer_),
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080057 boost::bind(&connection::handle_read, shared_from_this(),
58 boost::asio::placeholders::error,
59 boost::asio::placeholders::bytes_transferred));
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080060}
61
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080062void
63connection::stop()
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080064{
65 socket_.close();
66}
67
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080068void
69connection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred)
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080070{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080071 if (!e) {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080072 boost::tribool result;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080073 boost::tie(result, boost::tuples::ignore) =
74 request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080075
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080076 if (result) {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080077 request_handler_.handle_request(request_, reply_);
78 boost::asio::async_write(socket_, reply_.to_buffers(),
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080079 boost::bind(&connection::handle_write, shared_from_this(),
80 boost::asio::placeholders::error));
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080081 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080082 else if (!result) {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080083 reply_ = reply::stock_reply(reply::bad_request);
84 boost::asio::async_write(socket_, reply_.to_buffers(),
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080085 boost::bind(&connection::handle_write, shared_from_this(),
86 boost::asio::placeholders::error));
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080087 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080088 else {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080089 socket_.async_read_some(boost::asio::buffer(buffer_),
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080090 boost::bind(&connection::handle_read, shared_from_this(),
91 boost::asio::placeholders::error,
92 boost::asio::placeholders::bytes_transferred));
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080093 }
94 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080095 else if (e != boost::asio::error::operation_aborted) {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -080096 connection_manager_.stop(shared_from_this());
97 }
98}
99
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800100void
101connection::handle_write(const boost::system::error_code& e)
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -0800102{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800103 if (!e) {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -0800104 // Initiate graceful connection closure.
105 boost::system::error_code ignored_ec;
106 socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
107 }
108
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800109 if (e != boost::asio::error::operation_aborted) {
Zhenkai Zhua9a7e1d2013-02-25 18:29:07 -0800110 connection_manager_.stop(shared_from_this());
111 }
112}
113
114} // namespace server
115} // namespace http