blob: 1a92f739ad983c41d7f27c6d889ec0608081b110 [file] [log] [blame]
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "unix-stream-channel.hpp"
Junxiao Shi61e3cc52014-03-03 20:40:28 -07008#include "core/global-io.hpp"
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01009
10#include <boost/filesystem.hpp>
Davide Pesavento9cec8ee2014-02-19 11:21:59 +010011#include <sys/stat.h> // for chmod()
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010012
13namespace nfd {
14
15NFD_LOG_INIT("UnixStreamChannel");
16
17using namespace boost::asio::local;
18
Junxiao Shi61e3cc52014-03-03 20:40:28 -070019UnixStreamChannel::UnixStreamChannel(const unix_stream::Endpoint& endpoint)
20 : m_endpoint(endpoint)
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010021{
Junxiao Shi61e3cc52014-03-03 20:40:28 -070022 this->setUri(FaceUri(endpoint));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010023}
24
25UnixStreamChannel::~UnixStreamChannel()
26{
27 if (m_acceptor)
28 {
29 // use the non-throwing variants during destruction
30 // and ignore any errors
31 boost::system::error_code error;
32 m_acceptor->close(error);
33 boost::filesystem::remove(m_endpoint.path(), error);
34 }
35}
36
37void
38UnixStreamChannel::listen(const FaceCreatedCallback& onFaceCreated,
39 const ConnectFailedCallback& onAcceptFailed,
40 int backlog/* = acceptor::max_connections*/)
41{
42 if (m_acceptor) // already listening
43 return;
44
45 namespace fs = boost::filesystem;
46 fs::path p(m_endpoint.path());
47 if (fs::symlink_status(p).type() == fs::socket_file)
48 {
49 // for safety, remove an already existing file only if it's a socket
50 fs::remove(p);
51 }
52
Junxiao Shi61e3cc52014-03-03 20:40:28 -070053 m_acceptor = make_shared<stream_protocol::acceptor>(boost::ref(getGlobalIoService()));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010054 m_acceptor->open(m_endpoint.protocol());
55 m_acceptor->bind(m_endpoint);
56 m_acceptor->listen(backlog);
57
Davide Pesavento9cec8ee2014-02-19 11:21:59 +010058 if (::chmod(m_endpoint.path().c_str(), 0666) < 0)
59 {
60 throw Error("Failed to chmod() socket file at " + m_endpoint.path());
61 }
62
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010063 shared_ptr<stream_protocol::socket> clientSocket =
Junxiao Shi61e3cc52014-03-03 20:40:28 -070064 make_shared<stream_protocol::socket>(boost::ref(getGlobalIoService()));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010065 m_acceptor->async_accept(*clientSocket,
66 bind(&UnixStreamChannel::handleSuccessfulAccept, this, _1,
67 clientSocket, onFaceCreated, onAcceptFailed));
68}
69
70void
71UnixStreamChannel::createFace(const shared_ptr<stream_protocol::socket>& socket,
72 const FaceCreatedCallback& onFaceCreated)
73{
74 shared_ptr<UnixStreamFace> face = make_shared<UnixStreamFace>(boost::cref(socket));
75 onFaceCreated(face);
76}
77
78void
79UnixStreamChannel::handleSuccessfulAccept(const boost::system::error_code& error,
80 const shared_ptr<stream_protocol::socket>& socket,
81 const FaceCreatedCallback& onFaceCreated,
82 const ConnectFailedCallback& onAcceptFailed)
83{
84 if (error) {
85 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
86 return;
87
88 NFD_LOG_DEBUG("Connection failed: "
89 << error.category().message(error.value()));
90
91 onAcceptFailed("Connection failed: " +
92 error.category().message(error.value()));
93 return;
94 }
95
96 // prepare accepting the next connection
97 shared_ptr<stream_protocol::socket> clientSocket =
Junxiao Shi61e3cc52014-03-03 20:40:28 -070098 make_shared<stream_protocol::socket>(boost::ref(getGlobalIoService()));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010099 m_acceptor->async_accept(*clientSocket,
100 bind(&UnixStreamChannel::handleSuccessfulAccept, this, _1,
101 clientSocket, onFaceCreated, onAcceptFailed));
102
103 NFD_LOG_DEBUG("[" << m_endpoint << "] << Incoming connection");
104 createFace(socket, onFaceCreated);
105}
106
107} // namespace nfd