NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
datagram-transport.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #ifndef NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
27 #define NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
28 
29 #include "transport.hpp"
30 #include "core/global-io.hpp"
31 
32 #include <array>
33 
34 namespace nfd {
35 namespace face {
36 
37 struct Unicast {};
38 struct Multicast {};
39 
44 template<class Protocol, class Addressing = Unicast>
46 {
47 public:
48  typedef Protocol protocol;
49 
54  explicit
55  DatagramTransport(typename protocol::socket&& socket);
56 
59  void
60  receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
61  const boost::system::error_code& error);
62 
63 protected:
64  virtual void
65  doClose() override;
66 
67  virtual void
68  doSend(Transport::Packet&& packet) override;
69 
70  void
71  handleSend(const boost::system::error_code& error,
72  size_t nBytesSent, const Block& payload);
73 
74  void
75  handleReceive(const boost::system::error_code& error,
76  size_t nBytesReceived);
77 
78  void
79  processErrorCode(const boost::system::error_code& error);
80 
81  bool
82  hasBeenUsedRecently() const;
83 
84  void
85  resetRecentUsage();
86 
87  static EndpointId
88  makeEndpointId(const typename protocol::endpoint& ep);
89 
90 protected:
91  typename protocol::socket m_socket;
92  typename protocol::endpoint m_sender;
93 
95 
96 private:
97  std::array<uint8_t, ndn::MAX_NDN_PACKET_SIZE> m_receiveBuffer;
98  bool m_hasBeenUsedRecently;
99 };
100 
101 
102 template<class T, class U>
103 DatagramTransport<T, U>::DatagramTransport(typename DatagramTransport::protocol::socket&& socket)
104  : m_socket(std::move(socket))
105  , m_hasBeenUsedRecently(false)
106 {
107  m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
109  boost::asio::placeholders::error,
110  boost::asio::placeholders::bytes_transferred));
111 }
112 
113 template<class T, class U>
114 void
116 {
117  NFD_LOG_FACE_TRACE(__func__);
118 
119  if (m_socket.is_open()) {
120  // Cancel all outstanding operations and close the socket.
121  // Use the non-throwing variants and ignore errors, if any.
122  boost::system::error_code error;
123  m_socket.cancel(error);
124  m_socket.close(error);
125  }
126 
127  // Ensure that the Transport stays alive at least until
128  // all pending handlers are dispatched
129  getGlobalIoService().post([this] {
130  this->setState(TransportState::CLOSED);
131  });
132 }
133 
134 template<class T, class U>
135 void
137 {
138  NFD_LOG_FACE_TRACE(__func__);
139 
140  m_socket.async_send(boost::asio::buffer(packet.packet),
142  boost::asio::placeholders::error,
143  boost::asio::placeholders::bytes_transferred,
144  packet.packet));
145 }
146 
147 template<class T, class U>
148 void
149 DatagramTransport<T, U>::receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
150  const boost::system::error_code& error)
151 {
152  if (error)
153  return processErrorCode(error);
154 
155  NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
156 
157  bool isOk = false;
158  Block element;
159  std::tie(isOk, element) = Block::fromBuffer(buffer, nBytesReceived);
160  if (!isOk) {
161  NFD_LOG_FACE_WARN("Failed to parse incoming packet");
162  // This packet won't extend the face lifetime
163  return;
164  }
165  if (element.size() != nBytesReceived) {
166  NFD_LOG_FACE_WARN("Received datagram size and decoded element size don't match");
167  // This packet won't extend the face lifetime
168  return;
169  }
170  m_hasBeenUsedRecently = true;
171 
172  Transport::Packet tp(std::move(element));
173  tp.remoteEndpoint = makeEndpointId(m_sender);
174  this->receive(std::move(tp));
175 }
176 
177 template<class T, class U>
178 void
179 DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error,
180  size_t nBytesReceived)
181 {
182  receiveDatagram(m_receiveBuffer.data(), nBytesReceived, error);
183 
184  if (m_socket.is_open())
185  m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
187  boost::asio::placeholders::error,
188  boost::asio::placeholders::bytes_transferred));
189 }
190 
191 template<class T, class U>
192 void
193 DatagramTransport<T, U>::handleSend(const boost::system::error_code& error,
194  size_t nBytesSent, const Block& payload)
195 // 'payload' is unused; it's needed to retain the underlying Buffer
196 {
197  if (error)
198  return processErrorCode(error);
199 
200  NFD_LOG_FACE_TRACE("Successfully sent: " << nBytesSent << " bytes");
201 }
202 
203 template<class T, class U>
204 void
205 DatagramTransport<T, U>::processErrorCode(const boost::system::error_code& error)
206 {
207  NFD_LOG_FACE_TRACE(__func__);
208 
209  if (getState() == TransportState::CLOSING ||
210  getState() == TransportState::FAILED ||
211  getState() == TransportState::CLOSED ||
212  error == boost::asio::error::operation_aborted)
213  // transport is shutting down, ignore any errors
214  return;
215 
217  NFD_LOG_FACE_DEBUG("Permanent face ignores error: " << error.message());
218  return;
219  }
220 
221  if (error != boost::asio::error::eof)
222  NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
223 
224  this->setState(TransportState::FAILED);
225  doClose();
226 }
227 
228 template<class T, class U>
229 inline bool
231 {
232  return m_hasBeenUsedRecently;
233 }
234 
235 template<class T, class U>
236 inline void
238 {
239  m_hasBeenUsedRecently = false;
240 }
241 
242 template<class T, class U>
244 DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint& ep)
245 {
246  return 0;
247 }
248 
249 } // namespace face
250 } // namespace nfd
251 
252 #endif // NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
#define NFD_LOG_INCLASS_DECLARE()
Definition: logger.hpp:36
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
Definition: face-log.hpp:74
stores a packet along with the remote endpoint
Definition: transport.hpp:113
STL namespace.
detail::SimulatorIo & getGlobalIoService()
Definition: global-io.cpp:48
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
Implements Transport for datagram-based protocols.
#define NFD_LOG_FACE_DEBUG(msg)
Log a message at DEBUG level.
Definition: face-log.hpp:77
size_t size() const
Definition: block.cpp:504
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
EndpointId remoteEndpoint
identifies the remote endpoint
Definition: transport.hpp:132
void post(const std::function< void()> &callback)
Definition: global-io.cpp:34
DatagramTransport(typename protocol::socket &&socket)
Construct datagram transport.
uint64_t EndpointId
identifies an endpoint on the link
Definition: transport.hpp:109
the lower part of a Face
Definition: transport.hpp:104
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
Definition: face-log.hpp:83