blob: 75626ab2dfa6b0f878cf375200480e0983c3c030 [file] [log] [blame]
Wentao Shang53df1632014-04-21 12:01:32 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi1e46be32015-01-08 20:18:05 -07003 * Copyright (c) 2014-2015, 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.
Wentao Shang53df1632014-04-21 12:01:32 -070010 *
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/>.
Junxiao Shia1937bf2014-11-06 11:43:40 -070024 */
Wentao Shang53df1632014-04-21 12:01:32 -070025
26#include "websocket-channel.hpp"
Yukai Tu2d6d5632015-10-26 11:06:02 -070027#include "generic-link-service.hpp"
28#include "websocket-transport.hpp"
Davide Pesavento6ad890a2015-03-09 03:43:17 +010029#include "core/global-io.hpp"
Wentao Shang98733142014-09-17 12:13:57 -070030
Wentao Shang53df1632014-04-21 12:01:32 -070031namespace nfd {
32
33NFD_LOG_INIT("WebSocketChannel");
34
Wentao Shang53df1632014-04-21 12:01:32 -070035WebSocketChannel::WebSocketChannel(const websocket::Endpoint& localEndpoint)
36 : m_localEndpoint(localEndpoint)
Wentao Shang98733142014-09-17 12:13:57 -070037 , m_pingInterval(10000)
Wentao Shang53df1632014-04-21 12:01:32 -070038{
Davide Pesavento6ad890a2015-03-09 03:43:17 +010039 setUri(FaceUri(m_localEndpoint, "ws"));
40
Yukai Tu2d6d5632015-10-26 11:06:02 -070041 // Be quiet
Wentao Shang53df1632014-04-21 12:01:32 -070042 m_server.clear_access_channels(websocketpp::log::alevel::all);
Yukai Tu2d6d5632015-10-26 11:06:02 -070043 m_server.clear_error_channels(websocketpp::log::elevel::all);
Wentao Shang53df1632014-04-21 12:01:32 -070044
Yukai Tu2d6d5632015-10-26 11:06:02 -070045 // Setup WebSocket server
46 m_server.init_asio(&getGlobalIoService());
Wentao Shang53df1632014-04-21 12:01:32 -070047 m_server.set_open_handler(bind(&WebSocketChannel::handleOpen, this, _1));
48 m_server.set_close_handler(bind(&WebSocketChannel::handleClose, this, _1));
Yukai Tu2d6d5632015-10-26 11:06:02 -070049 m_server.set_message_handler(bind(&WebSocketChannel::handleMessage, this, _1, _2));
Davide Pesavento6ad890a2015-03-09 03:43:17 +010050
51 // Detect disconnections using ping-pong messages
Yukai Tu2d6d5632015-10-26 11:06:02 -070052 m_server.set_pong_handler(bind(&WebSocketChannel::handlePong, this, _1));
53 m_server.set_pong_timeout_handler(bind(&WebSocketChannel::handlePongTimeout, this, _1));
Davide Pesavento6ad890a2015-03-09 03:43:17 +010054
Wentao Shang93ef6c92014-06-19 11:59:17 -040055 // Always set SO_REUSEADDR flag
56 m_server.set_reuse_addr(true);
Wentao Shang53df1632014-04-21 12:01:32 -070057}
58
Davide Pesavento6ad890a2015-03-09 03:43:17 +010059void
60WebSocketChannel::setPingInterval(time::milliseconds interval)
Wentao Shang53df1632014-04-21 12:01:32 -070061{
Yukai Tu2d6d5632015-10-26 11:06:02 -070062 BOOST_ASSERT(!m_server.is_listening());
63
Davide Pesavento6ad890a2015-03-09 03:43:17 +010064 m_pingInterval = interval;
Wentao Shang53df1632014-04-21 12:01:32 -070065}
66
67void
Wentao Shang98733142014-09-17 12:13:57 -070068WebSocketChannel::setPongTimeout(time::milliseconds timeout)
69{
Yukai Tu2d6d5632015-10-26 11:06:02 -070070 BOOST_ASSERT(!m_server.is_listening());
71
Wentao Shang98733142014-09-17 12:13:57 -070072 m_server.set_pong_timeout(static_cast<long>(timeout.count()));
73}
74
75void
Yukai Tu2d6d5632015-10-26 11:06:02 -070076WebSocketChannel::handlePongTimeout(websocketpp::connection_hdl hdl)
Wentao Shang98733142014-09-17 12:13:57 -070077{
Davide Pesavento6ad890a2015-03-09 03:43:17 +010078 auto it = m_channelFaces.find(hdl);
79 if (it != m_channelFaces.end()) {
Junxiao Shicde37ad2015-12-24 01:02:05 -070080 static_cast<face::WebSocketTransport*>(it->second->getTransport())->handlePongTimeout();
Yukai Tu2d6d5632015-10-26 11:06:02 -070081 }
82 else {
83 NFD_LOG_WARN("Pong timeout on unknown transport");
Davide Pesavento6ad890a2015-03-09 03:43:17 +010084 }
Wentao Shang98733142014-09-17 12:13:57 -070085}
86
87void
Yukai Tu2d6d5632015-10-26 11:06:02 -070088WebSocketChannel::handlePong(websocketpp::connection_hdl hdl)
Wentao Shang98733142014-09-17 12:13:57 -070089{
Davide Pesavento6ad890a2015-03-09 03:43:17 +010090 auto it = m_channelFaces.find(hdl);
91 if (it != m_channelFaces.end()) {
Junxiao Shicde37ad2015-12-24 01:02:05 -070092 static_cast<face::WebSocketTransport*>(it->second->getTransport())->handlePong();
Yukai Tu2d6d5632015-10-26 11:06:02 -070093 }
94 else {
95 NFD_LOG_WARN("Pong received on unknown transport");
Davide Pesavento6ad890a2015-03-09 03:43:17 +010096 }
Wentao Shang98733142014-09-17 12:13:57 -070097}
98
99void
Wentao Shang53df1632014-04-21 12:01:32 -0700100WebSocketChannel::handleMessage(websocketpp::connection_hdl hdl,
101 websocket::Server::message_ptr msg)
102{
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100103 auto it = m_channelFaces.find(hdl);
104 if (it != m_channelFaces.end()) {
Junxiao Shicde37ad2015-12-24 01:02:05 -0700105 static_cast<face::WebSocketTransport*>(it->second->getTransport())->receiveMessage(msg->get_payload());
Yukai Tu2d6d5632015-10-26 11:06:02 -0700106 }
107 else {
108 NFD_LOG_WARN("Message received on unknown transport");
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100109 }
Wentao Shang53df1632014-04-21 12:01:32 -0700110}
111
112void
113WebSocketChannel::handleOpen(websocketpp::connection_hdl hdl)
114{
Yukai Tu2d6d5632015-10-26 11:06:02 -0700115 auto linkService = make_unique<face::GenericLinkService>();
116 auto transport = make_unique<face::WebSocketTransport>(hdl, ref(m_server), m_pingInterval);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700117 auto face = make_shared<Face>(std::move(linkService), std::move(transport));
Wentao Shang98733142014-09-17 12:13:57 -0700118
Yukai Tu2d6d5632015-10-26 11:06:02 -0700119 m_channelFaces[hdl] = face;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700120 connectFaceClosedSignal(*face, [this, hdl] { m_channelFaces.erase(hdl); });
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100121
Yukai Tu2d6d5632015-10-26 11:06:02 -0700122 m_onFaceCreatedCallback(face);
Wentao Shang53df1632014-04-21 12:01:32 -0700123}
124
125void
126WebSocketChannel::handleClose(websocketpp::connection_hdl hdl)
127{
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100128 auto it = m_channelFaces.find(hdl);
129 if (it != m_channelFaces.end()) {
Junxiao Shicde37ad2015-12-24 01:02:05 -0700130 it->second->close();
Yukai Tu2d6d5632015-10-26 11:06:02 -0700131 }
132 else {
133 NFD_LOG_WARN("Close on unknown transport");
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100134 }
Wentao Shang53df1632014-04-21 12:01:32 -0700135}
136
Wentao Shang53df1632014-04-21 12:01:32 -0700137void
138WebSocketChannel::listen(const FaceCreatedCallback& onFaceCreated)
139{
Yukai Tu2d6d5632015-10-26 11:06:02 -0700140 if (m_server.is_listening()) {
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100141 NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
142 return;
143 }
Wentao Shang53df1632014-04-21 12:01:32 -0700144
145 m_onFaceCreatedCallback = onFaceCreated;
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100146 m_server.listen(m_localEndpoint);
Wentao Shang53df1632014-04-21 12:01:32 -0700147 m_server.start_accept();
148}
149
150size_t
151WebSocketChannel::size() const
152{
153 return m_channelFaces.size();
154}
155
156} // namespace nfd