NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
websocket-channel.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2021, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "websocket-channel.hpp"
27 #include "face.hpp"
28 #include "generic-link-service.hpp"
29 #include "websocket-transport.hpp"
30 #include "common/global.hpp"
31 
32 namespace nfd {
33 namespace face {
34 
36 
38  : m_localEndpoint(localEndpoint)
39  , m_pingInterval(10_s)
40 {
41  setUri(FaceUri(m_localEndpoint, "ws"));
42  NFD_LOG_CHAN_INFO("Creating channel");
43 
44  // Be quiet
47 
48  // Setup WebSocket server
49  m_server.init_asio(&getGlobalIoService());
50  m_server.set_tcp_pre_bind_handler([isV6 = m_localEndpoint.address().is_v6()] (const auto& acceptor) {
51  if (isV6) {
52  acceptor->set_option(boost::asio::ip::v6_only(true));
53  }
54  return websocketpp::lib::error_code{};
55  });
56  m_server.set_open_handler(std::bind(&WebSocketChannel::handleOpen, this, _1));
57  m_server.set_close_handler(std::bind(&WebSocketChannel::handleClose, this, _1));
58  m_server.set_message_handler(std::bind(&WebSocketChannel::handleMessage, this, _1, _2));
59 
60  // Detect disconnections using ping-pong messages
61  m_server.set_pong_handler(std::bind(&WebSocketChannel::handlePong, this, _1));
62  m_server.set_pong_timeout_handler(std::bind(&WebSocketChannel::handlePongTimeout, this, _1));
63 
64  // Always set SO_REUSEADDR flag
65  m_server.set_reuse_addr(true);
66 }
67 
68 void
69 WebSocketChannel::setPingInterval(time::milliseconds interval)
70 {
71  BOOST_ASSERT(!m_server.is_listening());
72 
73  m_pingInterval = interval;
74 }
75 
76 void
78 {
79  BOOST_ASSERT(!m_server.is_listening());
80 
81  m_server.set_pong_timeout(static_cast<long>(timeout.count()));
82 }
83 
84 void
86 {
87  auto it = m_channelFaces.find(hdl);
88  if (it != m_channelFaces.end()) {
89  static_cast<WebSocketTransport*>(it->second->getTransport())->handlePongTimeout();
90  }
91  else {
92  NFD_LOG_CHAN_WARN("Pong timeout on unknown transport");
93  }
94 }
95 
96 void
98 {
99  auto it = m_channelFaces.find(hdl);
100  if (it != m_channelFaces.end()) {
101  static_cast<WebSocketTransport*>(it->second->getTransport())->handlePong();
102  }
103  else {
104  NFD_LOG_CHAN_WARN("Pong received on unknown transport");
105  }
106 }
107 
108 void
109 WebSocketChannel::handleMessage(websocketpp::connection_hdl hdl,
111 {
112  auto it = m_channelFaces.find(hdl);
113  if (it != m_channelFaces.end()) {
114  static_cast<WebSocketTransport*>(it->second->getTransport())->receiveMessage(msg->get_payload());
115  }
116  else {
117  NFD_LOG_CHAN_WARN("Message received on unknown transport");
118  }
119 }
120 
121 void
122 WebSocketChannel::handleOpen(websocketpp::connection_hdl hdl)
123 {
124  NFD_LOG_CHAN_TRACE("Incoming connection from " << m_server.get_con_from_hdl(hdl)->get_remote_endpoint());
125 
126  auto linkService = make_unique<GenericLinkService>();
127  auto transport = make_unique<WebSocketTransport>(hdl, m_server, m_pingInterval);
128  auto face = make_shared<Face>(std::move(linkService), std::move(transport));
129  face->setChannel(shared_from_this()); // use weak_from_this() in C++17
130 
131  BOOST_ASSERT(m_channelFaces.count(hdl) == 0);
132  m_channelFaces[hdl] = face;
133  connectFaceClosedSignal(*face, [this, hdl] { m_channelFaces.erase(hdl); });
134 
135  m_onFaceCreatedCallback(face);
136 }
137 
138 void
139 WebSocketChannel::handleClose(websocketpp::connection_hdl hdl)
140 {
141  auto it = m_channelFaces.find(hdl);
142  if (it != m_channelFaces.end()) {
143  it->second->close();
144  }
145  else {
146  NFD_LOG_CHAN_WARN("Close on unknown transport");
147  }
148 }
149 
150 void
152 {
153  if (isListening()) {
154  NFD_LOG_CHAN_WARN("Already listening");
155  return;
156  }
157 
158  m_onFaceCreatedCallback = onFaceCreated;
159 
160  m_server.listen(m_localEndpoint);
161  m_server.start_accept();
162  NFD_LOG_CHAN_DEBUG("Started listening");
163 }
164 
165 } // namespace face
166 } // namespace nfd
static level const all
Special aggregate value representing "all levels".
Definition: levels.hpp:152
void listen(const FaceCreatedCallback &onFaceCreated)
Enable listening on the local endpoint, accept connections, and create faces when remote host makes a...
void set_pong_timeout_handler(pong_timeout_handler h)
Definition: endpoint.hpp:302
void handlePong(websocketpp::connection_hdl hdl)
void setUri(const FaceUri &uri)
Definition: channel.cpp:35
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31
void set_open_handler(open_handler h)
Definition: endpoint.hpp:277
Class implementing WebSocket-based channel to create faces.
void setPongTimeout(time::milliseconds timeout)
connection_type::message_ptr message_ptr
Type of message pointers that this endpoint uses.
Definition: endpoint.hpp:70
lib::weak_ptr< void > connection_hdl
A handle to uniquely identify a connection.
detail::SimulatorIo & getGlobalIoService()
Returns the global io_service instance for the calling thread.
Definition: global.cpp:49
connection_ptr get_con_from_hdl(connection_hdl hdl, lib::error_code &ec)
Retrieves a connection_ptr from a connection_hdl (exception free)
Definition: endpoint.hpp:643
void set_close_handler(close_handler h)
Definition: endpoint.hpp:282
void connectFaceClosedSignal(Face &face, std::function< void()> f)
Invokes a callback when a face is closed.
Definition: channel.cpp:47
#define NFD_LOG_CHAN_DEBUG(msg)
Log a message at DEBUG level.
Definition: channel-log.hpp:49
WebSocketChannel(const websocket::Endpoint &localEndpoint)
Create WebSocket channel for the local endpoint.
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:39
#define NFD_LOG_CHAN_INFO(msg)
Log a message at INFO level.
Definition: channel-log.hpp:52
#define NFD_LOG_CHAN_TRACE(msg)
Log a message at TRACE level.
Definition: channel-log.hpp:46
#define NFD_LOG_CHAN_WARN(msg)
Log a message at WARN level.
Definition: channel-log.hpp:55
void start_accept(lib::error_code &ec)
Starts the server&#39;s async connection acceptance loop (exception free)
void set_pong_handler(pong_handler h)
Definition: endpoint.hpp:297
void clear_error_channels(log::level channels)
Clear Error logging channels.
Definition: endpoint.hpp:253
bool isListening() const final
Returns whether the channel is listening.
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
void handlePongTimeout(websocketpp::connection_hdl hdl)
void clear_access_channels(log::level channels)
Clear Access logging channels.
Definition: endpoint.hpp:231
std::function< void(const shared_ptr< Face > &)> FaceCreatedCallback
Prototype for the callback that is invoked when a face is created (in response to an incoming connect...
Definition: channel.hpp:86
A Transport that communicates on a WebSocket connection.
void set_pong_timeout(long dur)
Set pong timeout.
Definition: endpoint.hpp:399
boost::asio::ip::tcp::endpoint Endpoint
void set_message_handler(message_handler h)
Definition: endpoint.hpp:322
static level const all
Special aggregate value representing "all levels".
Definition: levels.hpp:80
boost::chrono::milliseconds milliseconds
Definition: time.hpp:48