NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
datagram-face.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_FACE_HPP
27 #define NFD_DAEMON_FACE_DATAGRAM_FACE_HPP
28 
29 #include "face.hpp"
30 #include "core/global-io.hpp"
31 
32 namespace nfd {
33 
34 struct Unicast {};
35 struct Multicast {};
36 
37 template<class Protocol, class Addressing = Unicast>
38 class DatagramFace : public Face
39 {
40 public:
41  typedef Protocol protocol;
42 
47  DatagramFace(const FaceUri& remoteUri, const FaceUri& localUri,
48  typename protocol::socket socket);
49 
50  // from Face
51  void
52  sendInterest(const Interest& interest) DECL_OVERRIDE;
53 
54  void
55  sendData(const Data& data) DECL_OVERRIDE;
56 
57  void
58  close() DECL_OVERRIDE;
59 
60  void
61  receiveDatagram(const uint8_t* buffer,
62  size_t nBytesReceived,
63  const boost::system::error_code& error);
64 
65 protected:
66  void
67  processErrorCode(const boost::system::error_code& error);
68 
69  void
70  handleSend(const boost::system::error_code& error,
71  size_t nBytesSent,
72  const Block& payload);
73 
74  void
75  handleReceive(const boost::system::error_code& error,
76  size_t nBytesReceived);
77 
78  void
79  keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face);
80 
81  void
82  closeSocket();
83 
84  bool
85  hasBeenUsedRecently() const;
86 
90  void
91  resetRecentUsage();
92 
93 protected:
94  typename protocol::socket m_socket;
95 
96  NFD_LOG_INCLASS_DECLARE();
97 
98 private:
99  uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
100  bool m_hasBeenUsedRecently;
101 };
102 
103 
104 template<class T, class U>
105 inline
106 DatagramFace<T, U>::DatagramFace(const FaceUri& remoteUri, const FaceUri& localUri,
107  typename DatagramFace::protocol::socket socket)
108  : Face(remoteUri, localUri, false, std::is_same<U, Multicast>::value)
109  , m_socket(std::move(socket))
110 {
111  NFD_LOG_FACE_INFO("Creating face");
112 
113  m_socket.async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
115  boost::asio::placeholders::error,
116  boost::asio::placeholders::bytes_transferred));
117 }
118 
119 template<class T, class U>
120 inline void
122 {
123  NFD_LOG_FACE_TRACE(__func__);
124 
125  this->emitSignal(onSendInterest, interest);
126 
127  const Block& payload = interest.wireEncode();
128  m_socket.async_send(boost::asio::buffer(payload.wire(), payload.size()),
129  bind(&DatagramFace<T, U>::handleSend, this,
130  boost::asio::placeholders::error,
131  boost::asio::placeholders::bytes_transferred,
132  payload));
133 }
134 
135 template<class T, class U>
136 inline void
138 {
139  NFD_LOG_FACE_TRACE(__func__);
140 
141  this->emitSignal(onSendData, data);
142 
143  const Block& payload = data.wireEncode();
144  m_socket.async_send(boost::asio::buffer(payload.wire(), payload.size()),
145  bind(&DatagramFace<T, U>::handleSend, this,
146  boost::asio::placeholders::error,
147  boost::asio::placeholders::bytes_transferred,
148  payload));
149 }
150 
151 template<class T, class U>
152 inline void
154 {
155  if (!m_socket.is_open())
156  return;
157 
158  NFD_LOG_FACE_INFO("Closing face");
159 
160  closeSocket();
161  this->fail("Face closed");
162 }
163 
164 template<class T, class U>
165 inline void
166 DatagramFace<T, U>::processErrorCode(const boost::system::error_code& error)
167 {
168  if (error == boost::asio::error::operation_aborted) // when cancel() is called
169  return;
170 
172  NFD_LOG_FACE_DEBUG("Permanent face ignores error: " << error.message());
173  return;
174  }
175 
176  if (!m_socket.is_open()) {
177  this->fail("Tunnel closed");
178  return;
179  }
180 
181  if (error != boost::asio::error::eof)
182  NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
183 
184  closeSocket();
185 
186  if (error == boost::asio::error::eof)
187  this->fail("Tunnel closed");
188  else
189  this->fail(error.message());
190 }
191 
192 template<class T, class U>
193 inline void
194 DatagramFace<T, U>::handleSend(const boost::system::error_code& error,
195  size_t nBytesSent,
196  const Block& payload)
197 // 'payload' is unused; it's needed to retain the underlying Buffer
198 {
199  if (error)
200  return processErrorCode(error);
201 
202  NFD_LOG_FACE_TRACE("Successfully sent: " << nBytesSent << " bytes");
203  this->getMutableCounters().getNOutBytes() += nBytesSent;
204 }
205 
206 template<class T, class U>
207 inline void
208 DatagramFace<T, U>::handleReceive(const boost::system::error_code& error,
209  size_t nBytesReceived)
210 {
211  receiveDatagram(m_inputBuffer, nBytesReceived, error);
212 
213  if (m_socket.is_open())
214  m_socket.async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
216  boost::asio::placeholders::error,
217  boost::asio::placeholders::bytes_transferred));
218 }
219 
220 template<class T, class U>
221 inline void
223  size_t nBytesReceived,
224  const boost::system::error_code& error)
225 {
226  if (error)
227  return processErrorCode(error);
228 
229  NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
230  this->getMutableCounters().getNInBytes() += nBytesReceived;
231 
232  bool isOk = false;
233  Block element;
234  std::tie(isOk, element) = Block::fromBuffer(buffer, nBytesReceived);
235  if (!isOk)
236  {
237  NFD_LOG_FACE_WARN("Failed to parse incoming packet");
238  // This message won't extend the face lifetime
239  return;
240  }
241 
242  if (element.size() != nBytesReceived)
243  {
244  NFD_LOG_FACE_WARN("Received datagram size and decoded element size don't match");
245  // This message won't extend the face lifetime
246  return;
247  }
248 
249  if (!this->decodeAndDispatchInput(element))
250  {
251  NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << element.type());
252  // This message won't extend the face lifetime
253  return;
254  }
255 
256  m_hasBeenUsedRecently = true;
257 }
258 
259 template<class T, class U>
260 inline void
262 {
263  NFD_LOG_FACE_TRACE(__func__);
264 }
265 
266 template<class T, class U>
267 inline void
269 {
270  NFD_LOG_FACE_TRACE(__func__);
271 
272  // use the non-throwing variants and ignore errors, if any
273  boost::system::error_code error;
274  m_socket.shutdown(protocol::socket::shutdown_both, error);
275  m_socket.close(error);
276  // after this, handlers will be called with an error code
277 
278  // ensure that the Face object is alive at least until all pending
279  // handlers are dispatched
281  this, this->shared_from_this()));
282 }
283 
284 template<class T, class U>
285 inline bool
287 {
288  return m_hasBeenUsedRecently;
289 }
290 
291 template<class T, class U>
292 inline void
294 {
295  m_hasBeenUsedRecently = false;
296 }
297 
298 } // namespace nfd
299 
300 #endif // NFD_DAEMON_FACE_DATAGRAM_FACE_HPP
void processErrorCode(const boost::system::error_code &error)
Copyright (c) 2011-2015 Regents of the University of California.
static std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset)
Try to construct block from Buffer.
Definition: block.cpp:253
bool hasBeenUsedRecently() const
Copyright (c) 2013-2015 Regents of the University of California.
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
Definition: face.hpp:321
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
void sendData(const Data &data) 1
send a Data
STL namespace.
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:45
#define DECL_OVERRIDE
expands to &#39;override&#39; if compiler supports this feature, otherwise expands to nothing ...
Definition: common.hpp:49
void sendInterest(const Interest &interest) 1
send an Interest
void handleReceive(const boost::system::error_code &error, size_t nBytesReceived)
represents a face
Definition: face.hpp:57
size_t size() const
Definition: block.cpp:504
#define emitSignal(...)
(implementation detail)
Definition: signal-emit.hpp:76
#define NFD_LOG_FACE_DEBUG(msg)
Log a message at DEBUG level.
Definition: face.hpp:324
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
void close() 1
Close the face.
#define NFD_LOG_FACE_INFO(msg)
Log a message at INFO level.
Definition: face.hpp:327
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:38
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: interest.cpp:217
void handleSend(const boost::system::error_code &error, size_t nBytesSent, const Block &payload)
void keepFaceAliveUntilAllHandlersExecuted(const shared_ptr< Face > &face)
uint32_t type() const
Definition: block.hpp:346
const uint8_t * wire() const
Definition: block.cpp:495
void receiveDatagram(const uint8_t *buffer, size_t nBytesReceived, const boost::system::error_code &error)
boost::asio::io_service & getGlobalIoService()
Definition: global-io.hpp:35
represents a Data packet
Definition: data.hpp:39
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
Definition: face.hpp:330
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Definition: tlv.hpp:39
void resetRecentUsage()
Set m_hasBeenUsedRecently to false.