NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
udp-channel.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "udp-channel.hpp"
27 #include "generic-link-service.hpp"
29 #include "core/global-io.hpp"
30 
31 namespace nfd {
32 
33 NFD_LOG_INIT("UdpChannel");
34 
35 using namespace boost::asio;
36 
38  const time::seconds& timeout)
39  : m_localEndpoint(localEndpoint)
40  , m_socket(getGlobalIoService())
41  , m_idleFaceTimeout(timeout)
42 {
43  setUri(FaceUri(m_localEndpoint));
44 }
45 
46 size_t
48 {
49  return m_channelFaces.size();
50 }
51 
52 void
53 UdpChannel::connect(const udp::Endpoint& remoteEndpoint,
54  ndn::nfd::FacePersistency persistency,
55  const FaceCreatedCallback& onFaceCreated,
56  const FaceCreationFailedCallback& onConnectFailed)
57 {
58  shared_ptr<Face> face;
59  try {
60  face = createFace(remoteEndpoint, persistency).second;
61  }
62  catch (const boost::system::system_error& e) {
63  NFD_LOG_WARN("[" << m_localEndpoint << "] Connect failed: " << e.what());
64  if (onConnectFailed)
65  onConnectFailed(504, std::string("Connect failed: ") + e.what());
66  return;
67  }
68 
69  // Need to invoke the callback regardless of whether or not we had already
70  // created the face so that control responses and such can be sent
71  onFaceCreated(face);
72 }
73 
74 void
76  const FaceCreationFailedCallback& onReceiveFailed)
77 {
78  if (isListening()) {
79  NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
80  return;
81  }
82 
83  m_socket.open(m_localEndpoint.protocol());
84  m_socket.set_option(ip::udp::socket::reuse_address(true));
85  if (m_localEndpoint.address().is_v6())
86  m_socket.set_option(ip::v6_only(true));
87 
88  m_socket.bind(m_localEndpoint);
89  this->waitForNewPeer(onFaceCreated, onReceiveFailed);
90 }
91 
92 void
93 UdpChannel::waitForNewPeer(const FaceCreatedCallback& onFaceCreated,
94  const FaceCreationFailedCallback& onReceiveFailed)
95 {
96  m_socket.async_receive_from(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
97  m_remoteEndpoint,
98  bind(&UdpChannel::handleNewPeer, this,
99  boost::asio::placeholders::error,
100  boost::asio::placeholders::bytes_transferred,
101  onFaceCreated, onReceiveFailed));
102 }
103 
104 void
105 UdpChannel::handleNewPeer(const boost::system::error_code& error,
106  size_t nBytesReceived,
107  const FaceCreatedCallback& onFaceCreated,
108  const FaceCreationFailedCallback& onReceiveFailed)
109 {
110  if (error) {
111  if (error == boost::asio::error::operation_aborted) // when the socket is closed by someone
112  return;
113 
114  NFD_LOG_DEBUG("[" << m_localEndpoint << "] Receive failed: " << error.message());
115  if (onReceiveFailed)
116  onReceiveFailed(500, "Receive failed: " + error.message());
117  return;
118  }
119 
120  NFD_LOG_DEBUG("[" << m_localEndpoint << "] New peer " << m_remoteEndpoint);
121 
122  bool isCreated = false;
123  shared_ptr<Face> face;
124  try {
125  std::tie(isCreated, face) = createFace(m_remoteEndpoint, ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
126  }
127  catch (const boost::system::system_error& e) {
128  NFD_LOG_WARN("[" << m_localEndpoint << "] Failed to create face for peer "
129  << m_remoteEndpoint << ": " << e.what());
130  if (onReceiveFailed)
131  onReceiveFailed(504, "Failed to create face for peer");
132  return;
133  }
134 
135  if (isCreated)
136  onFaceCreated(face);
137 
138  // dispatch the datagram to the face for processing
139  static_cast<face::UnicastUdpTransport*>(face->getTransport())->receiveDatagram(m_inputBuffer, nBytesReceived, error);
140 
141  this->waitForNewPeer(onFaceCreated, onReceiveFailed);
142 }
143 
144 std::pair<bool, shared_ptr<Face>>
145 UdpChannel::createFace(const udp::Endpoint& remoteEndpoint, ndn::nfd::FacePersistency persistency)
146 {
147  auto it = m_channelFaces.find(remoteEndpoint);
148  if (it != m_channelFaces.end()) {
149  // we already have a face for this endpoint, so reuse it
150  auto face = it->second;
151 
152  // TODO #3232: Remove persistency transitions from faces/create
153  // only on-demand -> persistent -> permanent transition is allowed
154  bool isTransitionAllowed = persistency != face->getPersistency() &&
155  (face->getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND ||
156  persistency == ndn::nfd::FACE_PERSISTENCY_PERMANENT);
157  if (isTransitionAllowed) {
158  face->setPersistency(persistency);
159  }
160  return {false, face};
161  }
162 
163  // else, create a new face
164  ip::udp::socket socket(getGlobalIoService(), m_localEndpoint.protocol());
165  socket.set_option(ip::udp::socket::reuse_address(true));
166  socket.bind(m_localEndpoint);
167  socket.connect(remoteEndpoint);
168 
169  auto linkService = make_unique<face::GenericLinkService>();
170  auto transport = make_unique<face::UnicastUdpTransport>(std::move(socket), persistency, m_idleFaceTimeout);
171  auto face = make_shared<Face>(std::move(linkService), std::move(transport));
172 
173  face->setPersistency(persistency);
174 
175  m_channelFaces[remoteEndpoint] = face;
177  [this, remoteEndpoint] {
178  NFD_LOG_TRACE("Erasing " << remoteEndpoint << " from channel face map");
179  m_channelFaces.erase(remoteEndpoint);
180  });
181 
182  return {true, face};
183 }
184 
185 } // namespace nfd
UdpChannel(const udp::Endpoint &localEndpoint, const time::seconds &timeout)
Create UDP channel for the local endpoint.
Definition: udp-channel.cpp:37
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
A Transport that communicates on a unicast UDP socket.
void connect(const udp::Endpoint &remoteEndpoint, ndn::nfd::FacePersistency persistency, const FaceCreatedCallback &onFaceCreated, const FaceCreationFailedCallback &onConnectFailed)
Create a face by establishing connection to remote endpoint.
Definition: udp-channel.cpp:53
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
bool isListening() const
size_t size() const
Get number of faces in the channel.
Definition: udp-channel.cpp:47
void setUri(const FaceUri &uri)
Definition: channel.cpp:35
boost::asio::ip::udp::endpoint Endpoint
Definition: udp-channel.hpp:34
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
void listen(const FaceCreatedCallback &onFaceCreated, const FaceCreationFailedCallback &onReceiveFailed)
Enable listening on the local endpoint, accept connections, and create faces when remote host makes a...
Definition: udp-channel.cpp:75
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
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Definition: tlv.hpp:39