websocket-factory.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "websocket-factory.hpp"
27 #include "core/logger.hpp"
28 
29 namespace nfd {
30 namespace face {
31 
32 namespace ip = boost::asio::ip;
33 
34 NFD_LOG_INIT("WebSocketFactory");
35 NFD_REGISTER_PROTOCOL_FACTORY(WebSocketFactory);
36 
37 const std::string&
39 {
40  static std::string id("websocket");
41  return id;
42 }
43 
44 
45 void
48 {
49  // websocket
50  // {
51  // listen yes
52  // port 9696
53  // enable_v4 yes
54  // enable_v6 yes
55  // }
56 
57  bool wantListen = false;
58  uint16_t port = 9696;
59  bool enableV4 = true;
60  bool enableV6 = true;
61 
62  if (configSection) {
63  wantListen = true;
64  for (const auto& pair : *configSection) {
65  const std::string& key = pair.first;
66 
67  if (key == "listen") {
68  wantListen = ConfigFile::parseYesNo(pair, "face_system.websocket");
69  }
70  else if (key == "port") {
71  port = ConfigFile::parseNumber<uint16_t>(pair, "face_system.websocket");
72  }
73  else if (key == "enable_v4") {
74  enableV4 = ConfigFile::parseYesNo(pair, "face_system.websocket");
75  }
76  else if (key == "enable_v6") {
77  enableV6 = ConfigFile::parseYesNo(pair, "face_system.websocket");
78  }
79  else {
80  BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.websocket." + key));
81  }
82  }
83  }
84 
85  if (!enableV4 && !enableV6) {
86  BOOST_THROW_EXCEPTION(ConfigFile::Error(
87  "IPv4 and IPv6 WebSocket channels have been disabled. Remove face_system.websocket section "
88  "to disable WebSocket channels or enable at least one channel type."));
89  }
90 
91  if (!enableV4 && enableV6) {
92  // websocketpp's IPv6 socket always accepts IPv4 connections.
93  BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
94  }
95 
96  if (!context.isDryRun) {
97  if (!wantListen) {
98  if (!m_channels.empty()) {
99  NFD_LOG_WARN("Cannot close WebSocket channel after initialization");
100  }
101  return;
102  }
103 
104  BOOST_ASSERT(enableV4);
105  websocket::Endpoint endpoint(enableV6 ? ip::tcp::v6() : ip::tcp::v4(), port);
106 
107  auto channel = this->createChannel(endpoint);
108  if (!channel->isListening()) {
109  channel->listen(context.addFace);
110  if (m_channels.size() > 1) {
111  NFD_LOG_WARN("Adding WebSocket channel for new endpoint; cannot close existing channels");
112  }
113  }
114  }
115 }
116 
117 void
118 WebSocketFactory::createFace(const FaceUri& uri,
119  ndn::nfd::FacePersistency persistency,
120  bool wantLocalFieldsEnabled,
121  const FaceCreatedCallback& onCreated,
122  const FaceCreationFailedCallback& onFailure)
123 {
124  onFailure(406, "Unsupported protocol");
125 }
126 
127 shared_ptr<WebSocketChannel>
129 {
130  auto channel = findChannel(endpoint);
131  if (channel)
132  return channel;
133 
134  channel = make_shared<WebSocketChannel>(endpoint);
135  m_channels[endpoint] = channel;
136 
137  return channel;
138 }
139 
140 shared_ptr<WebSocketChannel>
141 WebSocketFactory::createChannel(const std::string& localIp, const std::string& localPort)
142 {
143  websocket::Endpoint endpoint(ip::address::from_string(localIp),
144  boost::lexical_cast<uint16_t>(localPort));
145  return createChannel(endpoint);
146 }
147 
148 std::vector<shared_ptr<const Channel>>
150 {
151  return getChannelsFromMap(m_channels);
152 }
153 
154 shared_ptr<WebSocketChannel>
155 WebSocketFactory::findChannel(const websocket::Endpoint& endpoint) const
156 {
157  auto i = m_channels.find(endpoint);
158  if (i != m_channels.end())
159  return i->second;
160  else
161  return nullptr;
162 }
163 
164 } // namespace face
165 } // namespace nfd
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:62
std::vector< shared_ptr< const Channel > > getChannels() const override
#define NFD_REGISTER_PROTOCOL_FACTORY(PF)
registers a protocol factory
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:163
context for processing a config section in ProtocolFactory
Definition: face-system.hpp:77
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...
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 the face fails to be created.
Definition: channel.hpp:44
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
void createFace(const FaceUri &uri, ndn::nfd::FacePersistency persistency, bool wantLocalFieldsEnabled, const FaceCreatedCallback &onCreated, const FaceCreationFailedCallback &onFailure) override
unicast face creation is not supported and will always fail
function< void(const shared_ptr< Face > &newFace)> FaceCreatedCallback
Prototype for the callback that is invoked when the face is created (as a response to incoming connec...
Definition: channel.hpp:38
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()