blob: 15c5cd7fc4890777b9e9669e859594ead5035321 [file] [log] [blame]
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010024
25#include "unix-stream-channel.hpp"
Junxiao Shi61e3cc52014-03-03 20:40:28 -070026#include "core/global-io.hpp"
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010027
28#include <boost/filesystem.hpp>
Davide Pesavento9cec8ee2014-02-19 11:21:59 +010029#include <sys/stat.h> // for chmod()
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010030
31namespace nfd {
32
33NFD_LOG_INIT("UnixStreamChannel");
34
35using namespace boost::asio::local;
36
Junxiao Shi61e3cc52014-03-03 20:40:28 -070037UnixStreamChannel::UnixStreamChannel(const unix_stream::Endpoint& endpoint)
38 : m_endpoint(endpoint)
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010039{
Junxiao Shi61e3cc52014-03-03 20:40:28 -070040 this->setUri(FaceUri(endpoint));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010041}
42
43UnixStreamChannel::~UnixStreamChannel()
44{
45 if (m_acceptor)
46 {
47 // use the non-throwing variants during destruction
48 // and ignore any errors
49 boost::system::error_code error;
50 m_acceptor->close(error);
51 boost::filesystem::remove(m_endpoint.path(), error);
52 }
53}
54
55void
56UnixStreamChannel::listen(const FaceCreatedCallback& onFaceCreated,
57 const ConnectFailedCallback& onAcceptFailed,
58 int backlog/* = acceptor::max_connections*/)
59{
60 if (m_acceptor) // already listening
61 return;
62
63 namespace fs = boost::filesystem;
64 fs::path p(m_endpoint.path());
65 if (fs::symlink_status(p).type() == fs::socket_file)
66 {
67 // for safety, remove an already existing file only if it's a socket
68 fs::remove(p);
69 }
70
Junxiao Shi61e3cc52014-03-03 20:40:28 -070071 m_acceptor = make_shared<stream_protocol::acceptor>(boost::ref(getGlobalIoService()));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010072 m_acceptor->open(m_endpoint.protocol());
73 m_acceptor->bind(m_endpoint);
74 m_acceptor->listen(backlog);
75
Davide Pesavento9cec8ee2014-02-19 11:21:59 +010076 if (::chmod(m_endpoint.path().c_str(), 0666) < 0)
77 {
78 throw Error("Failed to chmod() socket file at " + m_endpoint.path());
79 }
80
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010081 shared_ptr<stream_protocol::socket> clientSocket =
Junxiao Shi61e3cc52014-03-03 20:40:28 -070082 make_shared<stream_protocol::socket>(boost::ref(getGlobalIoService()));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010083 m_acceptor->async_accept(*clientSocket,
84 bind(&UnixStreamChannel::handleSuccessfulAccept, this, _1,
85 clientSocket, onFaceCreated, onAcceptFailed));
86}
87
88void
89UnixStreamChannel::createFace(const shared_ptr<stream_protocol::socket>& socket,
90 const FaceCreatedCallback& onFaceCreated)
91{
92 shared_ptr<UnixStreamFace> face = make_shared<UnixStreamFace>(boost::cref(socket));
93 onFaceCreated(face);
94}
95
96void
97UnixStreamChannel::handleSuccessfulAccept(const boost::system::error_code& error,
98 const shared_ptr<stream_protocol::socket>& socket,
99 const FaceCreatedCallback& onFaceCreated,
100 const ConnectFailedCallback& onAcceptFailed)
101{
102 if (error) {
103 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
104 return;
105
106 NFD_LOG_DEBUG("Connection failed: "
107 << error.category().message(error.value()));
108
109 onAcceptFailed("Connection failed: " +
110 error.category().message(error.value()));
111 return;
112 }
113
114 // prepare accepting the next connection
115 shared_ptr<stream_protocol::socket> clientSocket =
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700116 make_shared<stream_protocol::socket>(boost::ref(getGlobalIoService()));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100117 m_acceptor->async_accept(*clientSocket,
118 bind(&UnixStreamChannel::handleSuccessfulAccept, this, _1,
119 clientSocket, onFaceCreated, onAcceptFailed));
120
121 NFD_LOG_DEBUG("[" << m_endpoint << "] << Incoming connection");
122 createFace(socket, onFaceCreated);
123}
124
125} // namespace nfd