blob: 520bb7da27e1a3d301eb8d2c27b6c4516087ed72 [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()) {
Yukai Tu2d6d5632015-10-26 11:06:02 -070080 static_cast<face::WebSocketTransport*>(it->second->getLpFace()->getTransport())->handlePongTimeout();
81 }
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()) {
Yukai Tu2d6d5632015-10-26 11:06:02 -070092 static_cast<face::WebSocketTransport*>(it->second->getLpFace()->getTransport())->handlePong();
93 }
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()) {
Yukai Tu2d6d5632015-10-26 11:06:02 -0700105 static_cast<face::WebSocketTransport*>(it->second->getLpFace()->getTransport())->receiveMessage(msg->get_payload());
106 }
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);
117 auto lpFace = make_unique<face::LpFace>(std::move(linkService), std::move(transport));
118 auto face = make_shared<face::LpFaceWrapper>(std::move(lpFace));
Wentao Shang98733142014-09-17 12:13:57 -0700119
Yukai Tu2d6d5632015-10-26 11:06:02 -0700120 face->getLpFace()->afterStateChange.connect(
121 [this, hdl] (face::FaceState oldState, face::FaceState newState) {
122 if (newState == face::FaceState::CLOSED) {
123 m_channelFaces.erase(hdl);
Wentao Shangd397d772015-04-29 12:09:31 -0700124 }
Yukai Tu2d6d5632015-10-26 11:06:02 -0700125 });
126 m_channelFaces[hdl] = face;
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100127
Yukai Tu2d6d5632015-10-26 11:06:02 -0700128 m_onFaceCreatedCallback(face);
Wentao Shang53df1632014-04-21 12:01:32 -0700129}
130
131void
132WebSocketChannel::handleClose(websocketpp::connection_hdl hdl)
133{
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100134 auto it = m_channelFaces.find(hdl);
135 if (it != m_channelFaces.end()) {
Yukai Tu2d6d5632015-10-26 11:06:02 -0700136 it->second->getLpFace()->close();
137 }
138 else {
139 NFD_LOG_WARN("Close on unknown transport");
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100140 }
Wentao Shang53df1632014-04-21 12:01:32 -0700141}
142
Wentao Shang53df1632014-04-21 12:01:32 -0700143void
144WebSocketChannel::listen(const FaceCreatedCallback& onFaceCreated)
145{
Yukai Tu2d6d5632015-10-26 11:06:02 -0700146 if (m_server.is_listening()) {
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100147 NFD_LOG_WARN("[" << m_localEndpoint << "] Already listening");
148 return;
149 }
Wentao Shang53df1632014-04-21 12:01:32 -0700150
151 m_onFaceCreatedCallback = onFaceCreated;
Davide Pesavento6ad890a2015-03-09 03:43:17 +0100152 m_server.listen(m_localEndpoint);
Wentao Shang53df1632014-04-21 12:01:32 -0700153 m_server.start_accept();
154}
155
156size_t
157WebSocketChannel::size() const
158{
159 return m_channelFaces.size();
160}
161
162} // namespace nfd