NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
websocket-transport.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "websocket-transport.hpp"
27 
28 namespace nfd {
29 namespace face {
30 
31 NFD_LOG_INIT("WebSocketTransport");
32 
33 WebSocketTransport::WebSocketTransport(websocketpp::connection_hdl hdl,
34  websocket::Server& server,
35  time::milliseconds pingInterval)
36  : m_handle(hdl)
37  , m_server(server)
38  , m_pingInterval(pingInterval)
39 {
40  const auto& sock = m_server.get_con_from_hdl(hdl)->get_socket();
41  this->setLocalUri(FaceUri(sock.local_endpoint(), "ws"));
42  this->setRemoteUri(FaceUri(sock.remote_endpoint(), "wsclient"));
43 
44  if (sock.local_endpoint().address().is_loopback() &&
45  sock.remote_endpoint().address().is_loopback())
46  this->setScope(ndn::nfd::FACE_SCOPE_LOCAL);
47  else
48  this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
49 
50  this->setPersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
51  this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
52  this->setMtu(MTU_UNLIMITED);
53 
54  this->schedulePing();
55 
56  NFD_LOG_FACE_INFO("Creating transport");
57 }
58 
59 void
60 WebSocketTransport::beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
61 {
62  if (newPersistency != ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
63  BOOST_THROW_EXCEPTION(
64  std::invalid_argument("WebSocketTransport supports only FACE_PERSISTENCY_ON_DEMAND"));
65  }
66 }
67 
68 void
69 WebSocketTransport::doSend(Transport::Packet&& packet)
70 {
71  NFD_LOG_FACE_TRACE(__func__);
72 
73  websocketpp::lib::error_code error;
74  m_server.send(m_handle, packet.packet.wire(), packet.packet.size(),
75  websocketpp::frame::opcode::binary, error);
76  if (error)
77  return processErrorCode(error);
78 
79  NFD_LOG_FACE_TRACE("Successfully sent: " << packet.packet.size() << " bytes");
80 }
81 
82 void
83 WebSocketTransport::receiveMessage(const std::string& msg)
84 {
85  NFD_LOG_FACE_TRACE("Received: " << msg.size() << " bytes");
86 
87  bool isOk = false;
88  Block element;
89  std::tie(isOk, element) = Block::fromBuffer(reinterpret_cast<const uint8_t*>(msg.c_str()), msg.size());
90  if (!isOk) {
91  NFD_LOG_FACE_WARN("Failed to parse message payload");
92  return;
93  }
94 
95  this->receive(Transport::Packet(std::move(element)));
96 }
97 
98 void
99 WebSocketTransport::schedulePing()
100 {
101  m_pingEventId = scheduler::schedule(m_pingInterval, bind(&WebSocketTransport::sendPing, this));
102 }
103 
104 void
105 WebSocketTransport::sendPing()
106 {
107  NFD_LOG_FACE_TRACE(__func__);
108 
109  ++this->nOutPings;
110 
111  websocketpp::lib::error_code error;
112  m_server.ping(m_handle, "NFD-WebSocket", error);
113  if (error)
114  return processErrorCode(error);
115 
116  this->schedulePing();
117 }
118 
119 void
120 WebSocketTransport::handlePong()
121 {
122  NFD_LOG_FACE_TRACE(__func__);
123 
124  ++this->nInPongs;
125 }
126 
127 void
128 WebSocketTransport::handlePongTimeout()
129 {
130  NFD_LOG_FACE_WARN(__func__);
131  this->setState(TransportState::FAILED);
132  doClose();
133 }
134 
135 void
136 WebSocketTransport::processErrorCode(const websocketpp::lib::error_code& error)
137 {
138  NFD_LOG_FACE_TRACE(__func__);
139 
140  if (getState() == TransportState::CLOSING ||
141  getState() == TransportState::FAILED ||
142  getState() == TransportState::CLOSED)
143  // transport is shutting down, ignore any errors
144  return;
145 
146  NFD_LOG_FACE_WARN("Send or ping operation failed: " << error.message());
147 
148  this->setState(TransportState::FAILED);
149  doClose();
150 }
151 
152 void
153 WebSocketTransport::doClose()
154 {
155  NFD_LOG_FACE_TRACE(__func__);
156 
157  m_pingEventId.cancel();
158 
159  // use the non-throwing variant and ignore errors, if any
160  websocketpp::lib::error_code error;
161  m_server.close(m_handle, websocketpp::close::status::normal, "closed by NFD", error);
162 
163  this->setState(TransportState::CLOSED);
164 }
165 
166 } // namespace face
167 } // namespace nfd
static std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset)
Try to construct block from Buffer.
Definition: block.cpp:253
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
Definition: face-log.hpp:74
const ssize_t MTU_UNLIMITED
indicates the transport has no limit on payload size
Definition: transport.hpp:95
websocketpp::server< websocketpp::config::asio > Server
Definition: websocketpp.hpp:46
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
stores a packet along with the remote endpoint
Definition: transport.hpp:113
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
the transport is being closed due to a failure
#define NFD_LOG_FACE_INFO(msg)
Log a message at INFO level.
Definition: face-log.hpp:80
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
the transport is closed, and can be safely deallocated
the transport is requested to be closed
#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_FACE_WARN(msg)
Log a message at WARN level.
Definition: face-log.hpp:83