NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
unix-stream-channel.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "unix-stream-channel.hpp"
27 #include "generic-link-service.hpp"
29 #include "core/global-io.hpp"
30 
31 #include <boost/filesystem.hpp>
32 #include <sys/stat.h> // for chmod()
33 
34 namespace nfd {
35 
36 NFD_LOG_INIT("UnixStreamChannel");
37 
39  : m_endpoint(endpoint)
40  , m_acceptor(getGlobalIoService())
41  , m_socket(getGlobalIoService())
42 {
43  setUri(FaceUri(m_endpoint));
44 }
45 
47 {
48  if (isListening()) {
49  // use the non-throwing variants during destruction
50  // and ignore any errors
51  boost::system::error_code error;
52  m_acceptor.close(error);
53  NFD_LOG_DEBUG("[" << m_endpoint << "] Removing socket file");
54  boost::filesystem::remove(m_endpoint.path(), error);
55  }
56 }
57 
58 void
60  const FaceCreationFailedCallback& onAcceptFailed,
61  int backlog/* = acceptor::max_connections*/)
62 {
63  if (isListening()) {
64  NFD_LOG_WARN("[" << m_endpoint << "] Already listening");
65  return;
66  }
67 
68  namespace fs = boost::filesystem;
69 
70  fs::path socketPath(m_endpoint.path());
71  fs::file_type type = fs::symlink_status(socketPath).type();
72 
73  if (type == fs::socket_file) {
74  boost::system::error_code error;
75  boost::asio::local::stream_protocol::socket socket(getGlobalIoService());
76  socket.connect(m_endpoint, error);
77  NFD_LOG_TRACE("[" << m_endpoint << "] connect() on existing socket file returned: "
78  + error.message());
79  if (!error) {
80  // someone answered, leave the socket alone
81  BOOST_THROW_EXCEPTION(Error("Socket file at " + m_endpoint.path()
82  + " belongs to another NFD process"));
83  }
84  else if (error == boost::asio::error::connection_refused ||
85  error == boost::asio::error::timed_out) {
86  // no one is listening on the remote side,
87  // we can safely remove the stale socket
88  NFD_LOG_DEBUG("[" << m_endpoint << "] Removing stale socket file");
89  fs::remove(socketPath);
90  }
91  }
92  else if (type != fs::file_not_found) {
93  BOOST_THROW_EXCEPTION(Error(m_endpoint.path() + " already exists and is not a socket file"));
94  }
95 
96  m_acceptor.open();
97  m_acceptor.bind(m_endpoint);
98  m_acceptor.listen(backlog);
99 
100  if (::chmod(m_endpoint.path().c_str(), 0666) < 0) {
101  BOOST_THROW_EXCEPTION(Error("chmod(" + m_endpoint.path() + ") failed: " +
102  std::strerror(errno)));
103  }
104 
105  // start accepting connections
106  accept(onFaceCreated, onAcceptFailed);
107 }
108 
109 void
110 UnixStreamChannel::accept(const FaceCreatedCallback& onFaceCreated,
111  const FaceCreationFailedCallback& onAcceptFailed)
112 {
113  m_acceptor.async_accept(m_socket, bind(&UnixStreamChannel::handleAccept, this,
114  boost::asio::placeholders::error,
115  onFaceCreated, onAcceptFailed));
116 }
117 
118 void
119 UnixStreamChannel::handleAccept(const boost::system::error_code& error,
120  const FaceCreatedCallback& onFaceCreated,
121  const FaceCreationFailedCallback& onAcceptFailed)
122 {
123  if (error) {
124  if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
125  return;
126 
127  NFD_LOG_DEBUG("[" << m_endpoint << "] Accept failed: " << error.message());
128  if (onAcceptFailed)
129  onAcceptFailed(error.message());
130  return;
131  }
132 
133  NFD_LOG_DEBUG("[" << m_endpoint << "] Incoming connection");
134 
135  auto linkService = make_unique<face::GenericLinkService>();
136  auto transport = make_unique<face::UnixStreamTransport>(std::move(m_socket));
137  auto face = make_shared<Face>(std::move(linkService), std::move(transport));
138  onFaceCreated(face);
139 
140  // prepare accepting the next connection
141  accept(onFaceCreated, onAcceptFailed);
142 }
143 
144 } // namespace nfd
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
function< void(const std::string &reason)> FaceCreationFailedCallback
Prototype for the callback that is invoked when the face fails to be created.
Definition: channel.hpp:44
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
UnixStreamChannel-related error.
detail::SimulatorIo & getGlobalIoService()
Definition: global-io.cpp:48
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
UnixStreamChannel(const unix_stream::Endpoint &endpoint)
Create UnixStream channel for the specified endpoint.
void setUri(const FaceUri &uri)
Definition: channel.cpp:35
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
void listen(const FaceCreatedCallback &onFaceCreated, const FaceCreationFailedCallback &onAcceptFailed, int backlog=boost::asio::local::stream_protocol::acceptor::max_connections)
Enable listening on the local endpoint, accept connections, and create faces when a connection is mad...
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
function< void(const shared_ptr< Face > &newFace)> FaceCreatedCallback
Prototype for the callback that is invoked when the face is created (as a response to incoming connec...
Definition: channel.hpp:38
boost::asio::local::stream_protocol::endpoint Endpoint