websocket-factory.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2017, 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-factory.hpp"
27 
28 namespace nfd {
29 namespace face {
30 
31 namespace ip = boost::asio::ip;
32 
33 NFD_LOG_INIT("WebSocketFactory");
34 NFD_REGISTER_PROTOCOL_FACTORY(WebSocketFactory);
35 
36 const std::string&
38 {
39  static std::string id("websocket");
40  return id;
41 }
42 
44  : ProtocolFactory(params)
45 {
46 }
47 
48 void
51 {
52  // websocket
53  // {
54  // listen yes
55  // port 9696
56  // enable_v4 yes
57  // enable_v6 yes
58  // }
59 
60  bool wantListen = false;
61  uint16_t port = 9696;
62  bool enableV4 = true;
63  bool enableV6 = true;
64 
65  if (configSection) {
66  wantListen = true;
67  for (const auto& pair : *configSection) {
68  const std::string& key = pair.first;
69 
70  if (key == "listen") {
71  wantListen = ConfigFile::parseYesNo(pair, "face_system.websocket");
72  }
73  else if (key == "port") {
74  port = ConfigFile::parseNumber<uint16_t>(pair, "face_system.websocket");
75  }
76  else if (key == "enable_v4") {
77  enableV4 = ConfigFile::parseYesNo(pair, "face_system.websocket");
78  }
79  else if (key == "enable_v6") {
80  enableV6 = ConfigFile::parseYesNo(pair, "face_system.websocket");
81  }
82  else {
83  BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.websocket." + key));
84  }
85  }
86  }
87 
88  if (!enableV4 && !enableV6) {
89  BOOST_THROW_EXCEPTION(ConfigFile::Error(
90  "IPv4 and IPv6 WebSocket channels have been disabled. Remove face_system.websocket section "
91  "to disable WebSocket channels or enable at least one channel type."));
92  }
93 
94  if (!enableV4 && enableV6) {
95  // websocketpp's IPv6 socket always accepts IPv4 connections.
96  BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
97  }
98 
99  if (!context.isDryRun) {
100  if (!wantListen) {
101  if (!m_channels.empty()) {
102  NFD_LOG_WARN("Cannot close WebSocket channel after initialization");
103  }
104  return;
105  }
106 
107  BOOST_ASSERT(enableV4);
108  websocket::Endpoint endpoint(enableV6 ? ip::tcp::v6() : ip::tcp::v4(), port);
109 
110  auto channel = this->createChannel(endpoint);
111  if (!channel->isListening()) {
112  channel->listen(this->addFace);
113  if (m_channels.size() > 1) {
114  NFD_LOG_WARN("Adding WebSocket channel for new endpoint; cannot close existing channels");
115  }
116  }
117  }
118 }
119 
120 void
122  const FaceCreatedCallback& onCreated,
123  const FaceCreationFailedCallback& onFailure)
124 {
125  onFailure(406, "Unsupported protocol");
126 }
127 
128 shared_ptr<WebSocketChannel>
130 {
131  auto it = m_channels.find(endpoint);
132  if (it != m_channels.end())
133  return it->second;
134 
135  auto channel = make_shared<WebSocketChannel>(endpoint);
136  m_channels[endpoint] = channel;
137 
138  return channel;
139 }
140 
141 std::vector<shared_ptr<const Channel>>
143 {
144  return getChannelsFromMap(m_channels);
145 }
146 
147 } // namespace face
148 } // namespace nfd
FaceCreatedCallback addFace
callback when a new face is created
static bool parseYesNo(const ConfigSection &node, const std::string &key, const std::string &sectionName)
parse a config option that can be either "yes" or "no"
Definition: config-file.cpp:59
#define NFD_REGISTER_PROTOCOL_FACTORY(PF)
registers a protocol factory
WebSocketFactory(const CtorParams &params)
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:163
context for processing a config section in ProtocolFactory
Definition: face-system.hpp:85
static std::vector< shared_ptr< const Channel > > getChannelsFromMap(const ChannelMap &channelMap)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
boost::optional< const ConfigSection & > OptionalConfigSection
an optional config file section
Definition: config-file.hpp:41
shared_ptr< WebSocketChannel > createChannel(const websocket::Endpoint &localEndpoint)
Create WebSocket-based channel using websocket::Endpoint.
function< void(uint32_t status, const std::string &reason)> FaceCreationFailedCallback
Prototype for the callback that is invoked when a face fails to be created.
Definition: channel.hpp:44
void createFace(const CreateFaceParams &params, const FaceCreatedCallback &onCreated, const FaceCreationFailedCallback &onFailure) override
unicast face creation is not supported and will always fail
Provides support for an underlying protocol.
Parameters to ProtocolFactory constructor.
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
std::vector< shared_ptr< const Channel > > getChannels() const override
Parameters to ProtocolFactory::createFace.
boost::asio::ip::tcp::endpoint Endpoint
void processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext &context) override
process face_system.websocket config section
static const std::string & getId()
function< void(const shared_ptr< Face > &newFace)> FaceCreatedCallback
Prototype for the callback that is invoked when a face is created (in response to an incoming connect...
Definition: channel.hpp:35