NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
tcp-channel.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "tcp-channel.hpp"
27 #include "generic-link-service.hpp"
28 #include "tcp-transport.hpp"
29 #include "core/global-io.hpp"
30 
31 namespace nfd {
32 
33 NFD_LOG_INIT("TcpChannel");
34 
35 namespace ip = boost::asio::ip;
36 
38  : m_localEndpoint(localEndpoint)
39  , m_acceptor(getGlobalIoService())
40  , m_acceptSocket(getGlobalIoService())
41 {
42  setUri(FaceUri(m_localEndpoint));
43 }
44 
45 void
47  const FaceCreationFailedCallback& onAcceptFailed,
48  int backlog/* = tcp::acceptor::max_connections*/)
49 {
50  if (isListening()) {
51  NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
52  return;
53  }
54 
55  m_acceptor.open(m_localEndpoint.protocol());
56  m_acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
57  if (m_localEndpoint.address().is_v6())
58  m_acceptor.set_option(ip::v6_only(true));
59 
60  m_acceptor.bind(m_localEndpoint);
61  m_acceptor.listen(backlog);
62 
63  // start accepting connections
64  accept(onFaceCreated, onAcceptFailed);
65 }
66 
67 void
68 TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
69  const FaceCreatedCallback& onFaceCreated,
70  const FaceCreationFailedCallback& onConnectFailed,
71  const time::seconds& timeout/* = time::seconds(4)*/)
72 {
73  auto it = m_channelFaces.find(remoteEndpoint);
74  if (it != m_channelFaces.end()) {
75  onFaceCreated(it->second);
76  return;
77  }
78 
79  auto clientSocket = make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
80 
81  scheduler::EventId connectTimeoutEvent = scheduler::schedule(timeout,
82  bind(&TcpChannel::handleConnectTimeout, this, clientSocket, onConnectFailed));
83 
84  clientSocket->async_connect(remoteEndpoint,
85  bind(&TcpChannel::handleConnect, this,
86  boost::asio::placeholders::error,
87  clientSocket, connectTimeoutEvent,
88  onFaceCreated, onConnectFailed));
89 }
90 
91 size_t
93 {
94  return m_channelFaces.size();
95 }
96 
97 void
98 TcpChannel::createFace(ip::tcp::socket&& socket,
99  const FaceCreatedCallback& onFaceCreated,
100  bool isOnDemand)
101 {
102  shared_ptr<Face> face;
103  tcp::Endpoint remoteEndpoint = socket.remote_endpoint();
104 
105  auto it = m_channelFaces.find(remoteEndpoint);
106  if (it == m_channelFaces.end()) {
107  auto persistency = isOnDemand ? ndn::nfd::FACE_PERSISTENCY_ON_DEMAND
109  auto linkService = make_unique<face::GenericLinkService>();
110  auto transport = make_unique<face::TcpTransport>(std::move(socket), persistency);
111  face = make_shared<Face>(std::move(linkService), std::move(transport));
112 
113  m_channelFaces[remoteEndpoint] = face;
115  [this, remoteEndpoint] {
116  NFD_LOG_TRACE("Erasing " << remoteEndpoint << " from channel face map");
117  m_channelFaces.erase(remoteEndpoint);
118  });
119  }
120  else {
121  // we already have a face for this endpoint, just reuse it
122  face = it->second;
123 
124  boost::system::error_code error;
125  socket.shutdown(ip::tcp::socket::shutdown_both, error);
126  socket.close(error);
127  }
128 
129  // Need to invoke the callback regardless of whether or not we have already created
130  // the face so that control responses and such can be sent.
131  onFaceCreated(face);
132 }
133 
134 void
135 TcpChannel::accept(const FaceCreatedCallback& onFaceCreated,
136  const FaceCreationFailedCallback& onAcceptFailed)
137 {
138  m_acceptor.async_accept(m_acceptSocket, bind(&TcpChannel::handleAccept, this,
139  boost::asio::placeholders::error,
140  onFaceCreated, onAcceptFailed));
141 }
142 
143 void
144 TcpChannel::handleAccept(const boost::system::error_code& error,
145  const FaceCreatedCallback& onFaceCreated,
146  const FaceCreationFailedCallback& onAcceptFailed)
147 {
148  if (error) {
149  if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
150  return;
151 
152  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Accept failed: " << error.message());
153  if (onAcceptFailed)
154  onAcceptFailed(error.message());
155  return;
156  }
157 
158  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Connection from " << m_acceptSocket.remote_endpoint());
159 
160  createFace(std::move(m_acceptSocket), onFaceCreated, true);
161 
162  // prepare accepting the next connection
163  accept(onFaceCreated, onAcceptFailed);
164 }
165 
166 void
167 TcpChannel::handleConnect(const boost::system::error_code& error,
168  const shared_ptr<ip::tcp::socket>& socket,
169  const scheduler::EventId& connectTimeoutEvent,
170  const FaceCreatedCallback& onFaceCreated,
171  const FaceCreationFailedCallback& onConnectFailed)
172 {
173  scheduler::cancel(connectTimeoutEvent);
174 
175 #if (BOOST_VERSION == 105400)
176  // To handle regression in Boost 1.54
177  // https://svn.boost.org/trac/boost/ticket/8795
178  boost::system::error_code anotherErrorCode;
179  socket->remote_endpoint(anotherErrorCode);
180  if (error || anotherErrorCode) {
181 #else
182  if (error) {
183 #endif
184  if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
185  return;
186 
187  NFD_LOG_WARN("[" << m_localEndpoint << "] Connect failed: " << error.message());
188 
189  socket->close();
190 
191  if (onConnectFailed)
192  onConnectFailed(error.message());
193  return;
194  }
195 
196  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Connected to " << socket->remote_endpoint());
197 
198  createFace(std::move(*socket), onFaceCreated, false);
199 }
200 
201 void
202 TcpChannel::handleConnectTimeout(const shared_ptr<ip::tcp::socket>& socket,
203  const FaceCreationFailedCallback& onConnectFailed)
204 {
205  NFD_LOG_DEBUG("Connect to remote endpoint timed out");
206 
207  // abort the connection attempt
208  boost::system::error_code error;
209  socket->close(error);
210 
211  if (onConnectFailed)
212  onConnectFailed("Connect to remote endpoint timed out");
213 }
214 
215 } // 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
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:53
void listen(const FaceCreatedCallback &onFaceCreated, const FaceCreationFailedCallback &onAcceptFailed, int backlog=boost::asio::ip::tcp::acceptor::max_connections)
Enable listening on the local endpoint, accept connections, and create faces when remote host makes a...
Definition: tcp-channel.cpp:46
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
void connectFaceClosedSignal(Face &face, const std::function< void()> &f)
invokes a callback when the face is closed
Definition: channel.cpp:41
detail::SimulatorIo & getGlobalIoService()
Definition: global-io.cpp:48
void connect(const tcp::Endpoint &remoteEndpoint, const FaceCreatedCallback &onFaceCreated, const FaceCreationFailedCallback &onConnectFailed, const time::seconds &timeout=time::seconds(4))
Create a face by establishing connection to remote endpoint.
Definition: tcp-channel.cpp:68
TcpChannel(const tcp::Endpoint &localEndpoint)
Create TCP channel for the local endpoint.
Definition: tcp-channel.cpp:37
std::shared_ptr< ns3::EventId > EventId
Definition: scheduler.hpp:39
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
boost::asio::ip::tcp::endpoint Endpoint
Definition: tcp-channel.hpp:35
void setUri(const FaceUri &uri)
Definition: channel.cpp:35
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
Definition: scheduler.cpp:47
#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
bool isListening() const
size_t size() const
Get number of faces in the channel.
Definition: tcp-channel.cpp:92