NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: 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  bool wantLocalFieldsEnabled,
70  const FaceCreatedCallback& onFaceCreated,
71  const FaceCreationFailedCallback& onConnectFailed,
72  const time::seconds& timeout/* = time::seconds(4)*/)
73 {
74  auto it = m_channelFaces.find(remoteEndpoint);
75  if (it != m_channelFaces.end()) {
76  onFaceCreated(it->second);
77  return;
78  }
79 
80  auto clientSocket = make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
81 
82  scheduler::EventId connectTimeoutEvent = scheduler::schedule(timeout,
83  bind(&TcpChannel::handleConnectTimeout, this, clientSocket, onConnectFailed));
84 
85  clientSocket->async_connect(remoteEndpoint,
86  bind(&TcpChannel::handleConnect, this,
87  boost::asio::placeholders::error, clientSocket,
88  wantLocalFieldsEnabled, connectTimeoutEvent,
89  onFaceCreated, onConnectFailed));
90 }
91 
92 size_t
94 {
95  return m_channelFaces.size();
96 }
97 
98 void
99 TcpChannel::createFace(ip::tcp::socket&& socket,
100  bool isOnDemand,
101  bool wantLocalFieldsEnabled,
102  const FaceCreatedCallback& onFaceCreated)
103 {
104  shared_ptr<Face> face;
105  tcp::Endpoint remoteEndpoint = socket.remote_endpoint();
106 
107  auto it = m_channelFaces.find(remoteEndpoint);
108  if (it == m_channelFaces.end()) {
109  auto persistency = isOnDemand ? ndn::nfd::FACE_PERSISTENCY_ON_DEMAND
111  auto linkService = make_unique<face::GenericLinkService>();
112  auto options = linkService->getOptions();
113  options.allowLocalFields = wantLocalFieldsEnabled;
114  linkService->setOptions(options);
115 
116  auto transport = make_unique<face::TcpTransport>(std::move(socket), persistency);
117 
118  face = make_shared<Face>(std::move(linkService), std::move(transport));
119 
120  m_channelFaces[remoteEndpoint] = face;
122  [this, remoteEndpoint] {
123  NFD_LOG_TRACE("Erasing " << remoteEndpoint << " from channel face map");
124  m_channelFaces.erase(remoteEndpoint);
125  });
126  }
127  else {
128  // we already have a face for this endpoint, just reuse it
129  face = it->second;
130 
131  boost::system::error_code error;
132  socket.shutdown(ip::tcp::socket::shutdown_both, error);
133  socket.close(error);
134  }
135 
136  // Need to invoke the callback regardless of whether or not we have already created
137  // the face so that control responses and such can be sent.
138  onFaceCreated(face);
139 }
140 
141 void
142 TcpChannel::accept(const FaceCreatedCallback& onFaceCreated,
143  const FaceCreationFailedCallback& onAcceptFailed)
144 {
145  m_acceptor.async_accept(m_acceptSocket, bind(&TcpChannel::handleAccept, this,
146  boost::asio::placeholders::error,
147  onFaceCreated, onAcceptFailed));
148 }
149 
150 void
151 TcpChannel::handleAccept(const boost::system::error_code& error,
152  const FaceCreatedCallback& onFaceCreated,
153  const FaceCreationFailedCallback& onAcceptFailed)
154 {
155  if (error) {
156  if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
157  return;
158 
159  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Accept failed: " << error.message());
160  if (onAcceptFailed)
161  onAcceptFailed(500, "Accept failed: " + error.message());
162  return;
163  }
164 
165  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Connection from " << m_acceptSocket.remote_endpoint());
166 
167  createFace(std::move(m_acceptSocket), true, false, onFaceCreated);
168 
169  // prepare accepting the next connection
170  accept(onFaceCreated, onAcceptFailed);
171 }
172 
173 void
174 TcpChannel::handleConnect(const boost::system::error_code& error,
175  const shared_ptr<ip::tcp::socket>& socket,
176  bool wantLocalFieldsEnabled,
177  const scheduler::EventId& connectTimeoutEvent,
178  const FaceCreatedCallback& onFaceCreated,
179  const FaceCreationFailedCallback& onConnectFailed)
180 {
181  scheduler::cancel(connectTimeoutEvent);
182 
183 #if (BOOST_VERSION == 105400)
184  // To handle regression in Boost 1.54
185  // https://svn.boost.org/trac/boost/ticket/8795
186  boost::system::error_code anotherErrorCode;
187  socket->remote_endpoint(anotherErrorCode);
188  if (error || anotherErrorCode) {
189 #else
190  if (error) {
191 #endif
192  if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
193  return;
194 
195  NFD_LOG_WARN("[" << m_localEndpoint << "] Connect failed: " << error.message());
196 
197  socket->close();
198 
199  if (onConnectFailed)
200  onConnectFailed(504, "Connect failed: " + error.message());
201  return;
202  }
203 
204  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Connected to " << socket->remote_endpoint());
205 
206  createFace(std::move(*socket), false, wantLocalFieldsEnabled, onFaceCreated);
207 }
208 
209 void
210 TcpChannel::handleConnectTimeout(const shared_ptr<ip::tcp::socket>& socket,
211  const FaceCreationFailedCallback& onConnectFailed)
212 {
213  NFD_LOG_DEBUG("Connect to remote endpoint timed out");
214 
215  // abort the connection attempt
216  boost::system::error_code error;
217  socket->close(error);
218 
219  if (onConnectFailed)
220  onConnectFailed(504, "Connect to remote endpoint timed out");
221 }
222 
223 } // namespace nfd
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
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
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_TRACE(expression)
Definition: logger.hpp:54
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 connect(const tcp::Endpoint &remoteEndpoint, bool wantLocalFieldsEnabled, 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
void setUri(const FaceUri &uri)
Definition: channel.cpp:35
function< void(uint32_t status, const std::string &reason)> FaceCreationFailedCallback
Prototype for the callback that is invoked when the face fails to be created.
Definition: channel.hpp:44
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
Definition: scheduler.cpp:47
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
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
bool isListening() const
size_t size() const
Get number of faces in the channel.
Definition: tcp-channel.cpp:93