blob: 8a9bb1cf68a6afc818196ab6942b72b6239b33a3 [file] [log] [blame]
Yanbiao Li73860e32015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yanbiao Lidf846e52016-01-30 21:53:47 -08003 * Copyright (c) 2014-2016, Regents of the University of California,
Yanbiao Li73860e32015-08-19 16:30:16 -07004 * 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 "face-manager.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070027#include "core/network-interface.hpp"
susmit91e1d7c2016-10-03 16:16:57 -060028#include "core/network-interface-predicate.hpp"
Junxiao Shi40cb61c2015-09-23 18:36:45 -070029#include "face/generic-link-service.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070030#include "face/tcp-factory.hpp"
31#include "face/udp-factory.hpp"
Yukai Tu0a49d342015-09-13 12:54:22 +080032#include "fw/face-table.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070033
Junxiao Shicbc8e942016-09-06 03:17:45 +000034#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi25c6ce42016-09-09 13:49:59 +000035#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
Yanbiao Li73860e32015-08-19 16:30:16 -070036
37#ifdef HAVE_UNIX_SOCKETS
38#include "face/unix-stream-factory.hpp"
39#endif // HAVE_UNIX_SOCKETS
40
41#ifdef HAVE_LIBPCAP
42#include "face/ethernet-factory.hpp"
Davide Pesavento35120ea2015-11-17 21:13:18 +010043#include "face/ethernet-transport.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070044#endif // HAVE_LIBPCAP
45
46#ifdef HAVE_WEBSOCKET
47#include "face/websocket-factory.hpp"
48#endif // HAVE_WEBSOCKET
49
50namespace nfd {
51
52NFD_LOG_INIT("FaceManager");
53
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000054FaceManager::FaceManager(FaceTable& faceTable, Dispatcher& dispatcher, CommandAuthenticator& authenticator)
55 : NfdManagerBase(dispatcher, authenticator, "faces")
Yanbiao Li73860e32015-08-19 16:30:16 -070056 , m_faceTable(faceTable)
57{
58 registerCommandHandler<ndn::nfd::FaceCreateCommand>("create",
59 bind(&FaceManager::createFace, this, _2, _3, _4, _5));
60
Eric Newberryb5aa7f52016-09-03 20:36:12 -070061 registerCommandHandler<ndn::nfd::FaceUpdateCommand>("update",
62 bind(&FaceManager::updateFace, this, _2, _3, _4, _5));
63
Yanbiao Li73860e32015-08-19 16:30:16 -070064 registerCommandHandler<ndn::nfd::FaceDestroyCommand>("destroy",
65 bind(&FaceManager::destroyFace, this, _2, _3, _4, _5));
66
67 registerCommandHandler<ndn::nfd::FaceEnableLocalControlCommand>("enable-local-control",
68 bind(&FaceManager::enableLocalControl, this, _2, _3, _4, _5));
69
70 registerCommandHandler<ndn::nfd::FaceDisableLocalControlCommand>("disable-local-control",
71 bind(&FaceManager::disableLocalControl, this, _2, _3, _4, _5));
72
73 registerStatusDatasetHandler("list", bind(&FaceManager::listFaces, this, _1, _2, _3));
74 registerStatusDatasetHandler("channels", bind(&FaceManager::listChannels, this, _1, _2, _3));
75 registerStatusDatasetHandler("query", bind(&FaceManager::queryFaces, this, _1, _2, _3));
76
Junxiao Shiae04d342016-07-19 13:20:22 +000077 m_postNotification = registerNotificationStream("events");
Eric Newberry1b4ba052016-10-07 23:04:07 -070078 m_faceAddConn = m_faceTable.afterAdd.connect([this] (const Face& face) {
79 connectFaceStateChangeSignal(face);
80 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
81 });
82 m_faceRemoveConn = m_faceTable.beforeRemove.connect([this] (const Face& face) {
83 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
84 });
Yanbiao Li73860e32015-08-19 16:30:16 -070085}
86
87void
88FaceManager::setConfigFile(ConfigFile& configFile)
89{
90 configFile.addSectionHandler("face_system", bind(&FaceManager::processConfig, this, _1, _2, _3));
91}
92
93void
94FaceManager::createFace(const Name& topPrefix, const Interest& interest,
95 const ControlParameters& parameters,
96 const ndn::mgmt::CommandContinuation& done)
97{
98 FaceUri uri;
99 if (!uri.parse(parameters.getUri())) {
100 NFD_LOG_TRACE("failed to parse URI");
Eric Newberry42602412016-08-27 09:33:18 -0700101 done(ControlResponse(400, "Malformed command"));
102 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700103 }
104
105 if (!uri.isCanonical()) {
106 NFD_LOG_TRACE("received non-canonical URI");
Eric Newberry42602412016-08-27 09:33:18 -0700107 done(ControlResponse(400, "Non-canonical URI"));
108 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700109 }
110
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200111 auto factory = m_factories.find(uri.getScheme());
Yanbiao Li73860e32015-08-19 16:30:16 -0700112 if (factory == m_factories.end()) {
Eric Newberry42602412016-08-27 09:33:18 -0700113 NFD_LOG_TRACE("received create request for unsupported protocol");
114 done(ControlResponse(406, "Unsupported protocol"));
115 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700116 }
117
118 try {
119 factory->second->createFace(uri,
120 parameters.getFacePersistency(),
Eric Newberryf40551a2016-09-05 15:41:16 -0700121 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
122 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
Yanbiao Li73860e32015-08-19 16:30:16 -0700123 bind(&FaceManager::afterCreateFaceSuccess,
124 this, parameters, _1, done),
125 bind(&FaceManager::afterCreateFaceFailure,
Eric Newberry42602412016-08-27 09:33:18 -0700126 this, _1, _2, done));
Yanbiao Li73860e32015-08-19 16:30:16 -0700127 }
128 catch (const std::runtime_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700129 NFD_LOG_ERROR("Face creation failed: " << error.what());
130 done(ControlResponse(500, "Face creation failed due to internal error"));
131 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700132 }
133 catch (const std::logic_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700134 NFD_LOG_ERROR("Face creation failed: " << error.what());
135 done(ControlResponse(500, "Face creation failed due to internal error"));
136 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700137 }
138}
139
Eric Newberry42602412016-08-27 09:33:18 -0700140/**
141 * \todo #3232
142 * If the creation of this face would conflict with an existing face (e.g. same underlying
143 * protocol and remote address, or a NIC-associated permanent face), the command will fail
144 * with StatusCode 409.
145 */
Yanbiao Li73860e32015-08-19 16:30:16 -0700146void
Eric Newberry42602412016-08-27 09:33:18 -0700147FaceManager::afterCreateFaceSuccess(const ControlParameters& parameters,
Eric Newberryf40551a2016-09-05 15:41:16 -0700148 const shared_ptr<Face>& face,
Yanbiao Li73860e32015-08-19 16:30:16 -0700149 const ndn::mgmt::CommandContinuation& done)
150{
Eric Newberryf40551a2016-09-05 15:41:16 -0700151 // TODO: Re-enable check in #3232
152 //if (face->getId() != face::INVALID_FACEID) {
153 //// Face already exists
154 //ControlParameters response;
155 //response.setFaceId(face->getId());
156 //response.setUri(face->getRemoteUri().toString());
157 //response.setFacePersistency(face->getPersistency());
158 //
159 //auto linkService = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
160 //BOOST_ASSERT(linkService != nullptr);
161 //auto options = linkService->getOptions();
162 //response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false);
163 //
164 // NFD_LOG_TRACE("Attempted to create duplicate face of " << face->getId());
165 // done(ControlResponse(409, "Face with remote URI already exists").setBody(response.wireEncode()));
166 //}
167 //else {
168 // If scope non-local and flags set to enable local fields, request shouldn't
169 // have made it this far
170 BOOST_ASSERT(face->getScope() == ndn::nfd::FACE_SCOPE_LOCAL ||
171 !parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ||
172 (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
173 !parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)));
174
175 m_faceTable.add(face);
176
Eric Newberry42602412016-08-27 09:33:18 -0700177 ControlParameters response;
Eric Newberryf40551a2016-09-05 15:41:16 -0700178 response.setFaceId(face->getId());
179 response.setFacePersistency(face->getPersistency());
180 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
181 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
182 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
183 false);
Eric Newberry42602412016-08-27 09:33:18 -0700184
185 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
Eric Newberryf40551a2016-09-05 15:41:16 -0700186 //}
Eric Newberry42602412016-08-27 09:33:18 -0700187}
188
189void
190FaceManager::afterCreateFaceFailure(uint32_t status,
191 const std::string& reason,
192 const ndn::mgmt::CommandContinuation& done)
193{
194 NFD_LOG_DEBUG("Face creation failed: " << reason);
195
196 done(ControlResponse(status, reason));
Yanbiao Li73860e32015-08-19 16:30:16 -0700197}
198
199void
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700200FaceManager::updateFace(const Name& topPrefix, const Interest& interest,
201 const ControlParameters& parameters,
202 const ndn::mgmt::CommandContinuation& done)
203{
204 FaceId faceId = parameters.getFaceId();
205 if (faceId == 0) {
206 // Self-updating
207 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
208 if (incomingFaceIdTag == nullptr) {
209 NFD_LOG_TRACE("unable to determine face for self-update");
210 done(ControlResponse(404, "No FaceId specified and IncomingFaceId not available"));
211 return;
212 }
213 faceId = *incomingFaceIdTag;
214 }
215
216 Face* face = m_faceTable.get(faceId);
217
218 if (face == nullptr) {
219 NFD_LOG_TRACE("invalid face specified");
220 done(ControlResponse(404, "Specified face does not exist"));
221 return;
222 }
223
224 // Verify validity of requested changes
225 ControlParameters response;
226 bool areParamsValid = true;
227
228 if (parameters.hasFacePersistency()) {
229 // TODO #3232: Add FacePersistency updating
230 NFD_LOG_TRACE("received unsupported face persistency change");
231 areParamsValid = false;
232 response.setFacePersistency(parameters.getFacePersistency());
233 }
234
235 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
236 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
237 face->getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
238 NFD_LOG_TRACE("received request to enable local fields on non-local face");
239 areParamsValid = false;
240 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
241 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
242 }
243
244 if (!areParamsValid) {
245 done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
246 return;
247 }
248
249 // All specified properties are valid, so make changes
250
251 // TODO #3232: Add FacePersistency updating
252
253 setLinkServiceOptions(*face, parameters, response);
254
Eric Newberryf40551a2016-09-05 15:41:16 -0700255 // Set ControlResponse fields
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700256 response.setFaceId(faceId);
257 response.setFacePersistency(face->getPersistency());
Eric Newberryf40551a2016-09-05 15:41:16 -0700258 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
259 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
260 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
261 false);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700262
263 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
264}
265
266void
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700267FaceManager::destroyFace(const Name& topPrefix, const Interest& interest,
268 const ControlParameters& parameters,
269 const ndn::mgmt::CommandContinuation& done)
270{
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000271 Face* face = m_faceTable.get(parameters.getFaceId());
272 if (face != nullptr) {
273 face->close();
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700274 }
275
276 done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
277}
278
279void
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700280FaceManager::enableLocalControl(const Name& topPrefix, const Interest& interest,
281 const ControlParameters& parameters,
282 const ndn::mgmt::CommandContinuation& done)
283{
Junxiao Shicde37ad2015-12-24 01:02:05 -0700284 Face* face = findFaceForLocalControl(interest, parameters, done);
285 if (!face) {
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700286 return;
287 }
288
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700289 // enable-local-control will enable all local fields in GenericLinkService
Junxiao Shicde37ad2015-12-24 01:02:05 -0700290 auto service = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700291 if (service == nullptr) {
292 return done(ControlResponse(503, "LinkService type not supported"));
293 }
294
295 face::GenericLinkService::Options options = service->getOptions();
296 options.allowLocalFields = true;
297 service->setOptions(options);
298
299 return done(ControlResponse(200, "OK: enable all local fields on GenericLinkService")
300 .setBody(parameters.wireEncode()));
301}
302
303void
304FaceManager::disableLocalControl(const Name& topPrefix, const Interest& interest,
305 const ControlParameters& parameters,
306 const ndn::mgmt::CommandContinuation& done)
307{
Junxiao Shicde37ad2015-12-24 01:02:05 -0700308 Face* face = findFaceForLocalControl(interest, parameters, done);
309 if (!face) {
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700310 return;
311 }
312
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700313 // disable-local-control will disable all local fields in GenericLinkService
Junxiao Shicde37ad2015-12-24 01:02:05 -0700314 auto service = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700315 if (service == nullptr) {
316 return done(ControlResponse(503, "LinkService type not supported"));
317 }
318
319 face::GenericLinkService::Options options = service->getOptions();
320 options.allowLocalFields = false;
321 service->setOptions(options);
322
323 return done(ControlResponse(200, "OK: disable all local fields on GenericLinkService")
324 .setBody(parameters.wireEncode()));
325}
326
Junxiao Shicde37ad2015-12-24 01:02:05 -0700327Face*
328FaceManager::findFaceForLocalControl(const Interest& request,
329 const ControlParameters& parameters,
330 const ndn::mgmt::CommandContinuation& done)
Yanbiao Li73860e32015-08-19 16:30:16 -0700331{
Junxiao Shi0de23a22015-12-03 20:07:02 +0000332 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = request.getTag<lp::IncomingFaceIdTag>();
333 // NDNLPv2 says "application MUST be prepared to receive a packet without IncomingFaceId field",
334 // but it's fine to assert IncomingFaceId is available, because InternalFace lives inside NFD
335 // and is initialized synchronously with IncomingFaceId field enabled.
336 BOOST_ASSERT(incomingFaceIdTag != nullptr);
337
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000338 Face* face = m_faceTable.get(*incomingFaceIdTag);
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200339 if (face == nullptr) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000340 NFD_LOG_DEBUG("FaceId " << *incomingFaceIdTag << " not found");
Yanbiao Li73860e32015-08-19 16:30:16 -0700341 done(ControlResponse(410, "Face not found"));
Junxiao Shicde37ad2015-12-24 01:02:05 -0700342 return nullptr;
Yanbiao Li73860e32015-08-19 16:30:16 -0700343 }
344
Junxiao Shicde37ad2015-12-24 01:02:05 -0700345 if (face->getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200346 NFD_LOG_DEBUG("Cannot enable local control on non-local FaceId " << face->getId());
Yanbiao Li73860e32015-08-19 16:30:16 -0700347 done(ControlResponse(412, "Face is non-local"));
Junxiao Shicde37ad2015-12-24 01:02:05 -0700348 return nullptr;
Yanbiao Li73860e32015-08-19 16:30:16 -0700349 }
350
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000351 return face;
Yanbiao Li73860e32015-08-19 16:30:16 -0700352}
353
354void
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700355FaceManager::setLinkServiceOptions(Face& face,
356 const ControlParameters& parameters,
357 ControlParameters& response)
358{
359 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
360 BOOST_ASSERT(linkService != nullptr);
361
362 auto options = linkService->getOptions();
363 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
364 face.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
365 options.allowLocalFields = parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
366 }
367 linkService->setOptions(options);
368
369 // Set Flags for ControlResponse
370 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false);
371}
372
373void
Yanbiao Li73860e32015-08-19 16:30:16 -0700374FaceManager::listFaces(const Name& topPrefix, const Interest& interest,
375 ndn::mgmt::StatusDatasetContext& context)
376{
Eric Newberryc64d30a2015-12-26 11:07:27 -0700377 auto now = time::steady_clock::now();
Junxiao Shib84e6742016-07-19 13:16:22 +0000378 for (const Face& face : m_faceTable) {
379 ndn::nfd::FaceStatus status = collectFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700380 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700381 }
382 context.end();
383}
384
385void
386FaceManager::listChannels(const Name& topPrefix, const Interest& interest,
387 ndn::mgmt::StatusDatasetContext& context)
388{
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200389 std::set<const ProtocolFactory*> seenFactories;
Yanbiao Li73860e32015-08-19 16:30:16 -0700390
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200391 for (const auto& kv : m_factories) {
392 const ProtocolFactory* factory = kv.second.get();
393 bool inserted;
394 std::tie(std::ignore, inserted) = seenFactories.insert(factory);
Yanbiao Li73860e32015-08-19 16:30:16 -0700395
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200396 if (inserted) {
397 for (const auto& channel : factory->getChannels()) {
398 ndn::nfd::ChannelStatus entry;
399 entry.setLocalUri(channel->getUri().toString());
400 context.append(entry.wireEncode());
401 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700402 }
403 }
404
405 context.end();
406}
407
408void
409FaceManager::queryFaces(const Name& topPrefix, const Interest& interest,
410 ndn::mgmt::StatusDatasetContext& context)
411{
412 ndn::nfd::FaceQueryFilter faceFilter;
413 const Name& query = interest.getName();
414 try {
415 faceFilter.wireDecode(query[-1].blockFromValue());
416 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200417 catch (const tlv::Error& e) {
418 NFD_LOG_DEBUG("Malformed query filter: " << e.what());
419 return context.reject(ControlResponse(400, "Malformed filter"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700420 }
421
Eric Newberryc64d30a2015-12-26 11:07:27 -0700422 auto now = time::steady_clock::now();
Junxiao Shib84e6742016-07-19 13:16:22 +0000423 for (const Face& face : m_faceTable) {
424 if (!matchFilter(faceFilter, face)) {
Junxiao Shida93f1f2015-11-11 06:13:16 -0700425 continue;
Yanbiao Li73860e32015-08-19 16:30:16 -0700426 }
Junxiao Shib84e6742016-07-19 13:16:22 +0000427 ndn::nfd::FaceStatus status = collectFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700428 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700429 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200430
Yanbiao Li73860e32015-08-19 16:30:16 -0700431 context.end();
432}
433
434bool
Junxiao Shib84e6742016-07-19 13:16:22 +0000435FaceManager::matchFilter(const ndn::nfd::FaceQueryFilter& filter, const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700436{
437 if (filter.hasFaceId() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000438 filter.getFaceId() != static_cast<uint64_t>(face.getId())) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700439 return false;
440 }
441
442 if (filter.hasUriScheme() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000443 filter.getUriScheme() != face.getRemoteUri().getScheme() &&
444 filter.getUriScheme() != face.getLocalUri().getScheme()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700445 return false;
446 }
447
448 if (filter.hasRemoteUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000449 filter.getRemoteUri() != face.getRemoteUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700450 return false;
451 }
452
453 if (filter.hasLocalUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000454 filter.getLocalUri() != face.getLocalUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700455 return false;
456 }
457
458 if (filter.hasFaceScope() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000459 filter.getFaceScope() != face.getScope()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700460 return false;
461 }
462
463 if (filter.hasFacePersistency() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000464 filter.getFacePersistency() != face.getPersistency()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700465 return false;
466 }
467
468 if (filter.hasLinkType() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000469 filter.getLinkType() != face.getLinkType()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700470 return false;
471 }
472
473 return true;
474}
475
Eric Newberryc64d30a2015-12-26 11:07:27 -0700476ndn::nfd::FaceStatus
477FaceManager::collectFaceStatus(const Face& face, const time::steady_clock::TimePoint& now)
478{
479 ndn::nfd::FaceStatus status;
480
481 collectFaceProperties(face, status);
482
483 time::steady_clock::TimePoint expirationTime = face.getExpirationTime();
484 if (expirationTime != time::steady_clock::TimePoint::max()) {
485 status.setExpirationPeriod(std::max(time::milliseconds(0),
486 time::duration_cast<time::milliseconds>(expirationTime - now)));
487 }
488
489 const face::FaceCounters& counters = face.getCounters();
490 status.setNInInterests(counters.nInInterests)
491 .setNOutInterests(counters.nOutInterests)
492 .setNInDatas(counters.nInData)
493 .setNOutDatas(counters.nOutData)
494 .setNInNacks(counters.nInNacks)
495 .setNOutNacks(counters.nOutNacks)
496 .setNInBytes(counters.nInBytes)
497 .setNOutBytes(counters.nOutBytes);
498
499 return status;
500}
501
Junxiao Shida93f1f2015-11-11 06:13:16 -0700502template<typename FaceTraits>
Junxiao Shicde37ad2015-12-24 01:02:05 -0700503void
504FaceManager::collectFaceProperties(const Face& face, FaceTraits& traits)
Junxiao Shida93f1f2015-11-11 06:13:16 -0700505{
506 traits.setFaceId(face.getId())
507 .setRemoteUri(face.getRemoteUri().toString())
508 .setLocalUri(face.getLocalUri().toString())
509 .setFaceScope(face.getScope())
510 .setFacePersistency(face.getPersistency())
511 .setLinkType(face.getLinkType());
Eric Newberry1b4ba052016-10-07 23:04:07 -0700512
513 // Set Flag bits
514 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
515 if (linkService != nullptr) {
516 auto linkServiceOptions = linkService->getOptions();
517 traits.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, linkServiceOptions.allowLocalFields);
518 }
Junxiao Shida93f1f2015-11-11 06:13:16 -0700519}
520
521void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700522FaceManager::notifyFaceEvent(const Face& face, ndn::nfd::FaceEventKind kind)
Yanbiao Li73860e32015-08-19 16:30:16 -0700523{
524 ndn::nfd::FaceEventNotification notification;
Eric Newberry1b4ba052016-10-07 23:04:07 -0700525 notification.setKind(kind);
Junxiao Shiae04d342016-07-19 13:20:22 +0000526 collectFaceProperties(face, notification);
Yanbiao Li73860e32015-08-19 16:30:16 -0700527
Junxiao Shiae04d342016-07-19 13:20:22 +0000528 m_postNotification(notification.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700529}
530
531void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700532FaceManager::connectFaceStateChangeSignal(const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700533{
Eric Newberry1b4ba052016-10-07 23:04:07 -0700534 FaceId faceId = face.getId();
535 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
536 [this, faceId] (face::FaceState oldState, face::FaceState newState) {
537 const Face& face = *m_faceTable.get(faceId);
Yanbiao Li73860e32015-08-19 16:30:16 -0700538
Eric Newberry1b4ba052016-10-07 23:04:07 -0700539 if (newState == face::FaceState::UP) {
540 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
541 }
542 else if (newState == face::FaceState::DOWN) {
543 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
544 }
545 else if (newState == face::FaceState::CLOSED) {
546 m_faceStateChangeConn.erase(faceId);
547 }
548 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700549}
550
551void
552FaceManager::processConfig(const ConfigSection& configSection,
553 bool isDryRun,
554 const std::string& filename)
555{
556 bool hasSeenUnix = false;
557 bool hasSeenTcp = false;
558 bool hasSeenUdp = false;
559 bool hasSeenEther = false;
560 bool hasSeenWebSocket = false;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200561 auto nicList = listNetworkInterfaces();
Yanbiao Li73860e32015-08-19 16:30:16 -0700562
563 for (const auto& item : configSection) {
564 if (item.first == "unix") {
565 if (hasSeenUnix) {
566 BOOST_THROW_EXCEPTION(Error("Duplicate \"unix\" section"));
567 }
568 hasSeenUnix = true;
569
570 processSectionUnix(item.second, isDryRun);
571 }
572 else if (item.first == "tcp") {
573 if (hasSeenTcp) {
574 BOOST_THROW_EXCEPTION(Error("Duplicate \"tcp\" section"));
575 }
576 hasSeenTcp = true;
577
578 processSectionTcp(item.second, isDryRun);
579 }
580 else if (item.first == "udp") {
581 if (hasSeenUdp) {
582 BOOST_THROW_EXCEPTION(Error("Duplicate \"udp\" section"));
583 }
584 hasSeenUdp = true;
585
586 processSectionUdp(item.second, isDryRun, nicList);
587 }
588 else if (item.first == "ether") {
589 if (hasSeenEther) {
590 BOOST_THROW_EXCEPTION(Error("Duplicate \"ether\" section"));
591 }
592 hasSeenEther = true;
593
594 processSectionEther(item.second, isDryRun, nicList);
595 }
596 else if (item.first == "websocket") {
597 if (hasSeenWebSocket) {
598 BOOST_THROW_EXCEPTION(Error("Duplicate \"websocket\" section"));
599 }
600 hasSeenWebSocket = true;
601
602 processSectionWebSocket(item.second, isDryRun);
603 }
604 else {
605 BOOST_THROW_EXCEPTION(Error("Unrecognized option \"" + item.first + "\""));
606 }
607 }
608}
609
610void
611FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
612{
613 // ; the unix section contains settings of Unix stream faces and channels
614 // unix
615 // {
616 // path /var/run/nfd.sock ; Unix stream listener path
617 // }
618
619#if defined(HAVE_UNIX_SOCKETS)
Yanbiao Li73860e32015-08-19 16:30:16 -0700620 std::string path = "/var/run/nfd.sock";
621
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200622 for (const auto& i : configSection) {
623 if (i.first == "path") {
624 path = i.second.get_value<std::string>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700625 }
626 else {
627 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200628 i.first + "\" in \"unix\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700629 }
630 }
631
632 if (!isDryRun) {
633 if (m_factories.count("unix") > 0) {
634 return;
635 }
636
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200637 auto factory = make_shared<UnixStreamFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700638 m_factories.insert(std::make_pair("unix", factory));
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200639
640 auto channel = factory->createChannel(path);
641 channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700642 }
643#else
644 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
645 "cannot process \"unix\" section"));
646#endif // HAVE_UNIX_SOCKETS
647}
648
649void
650FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
651{
652 // ; the tcp section contains settings of TCP faces and channels
653 // tcp
654 // {
655 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
656 // port 6363 ; TCP listener port number
657 // }
658
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200659 uint16_t port = 6363;
Yanbiao Li73860e32015-08-19 16:30:16 -0700660 bool needToListen = true;
661 bool enableV4 = true;
662 bool enableV6 = true;
663
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200664 for (const auto& i : configSection) {
665 if (i.first == "port") {
666 port = ConfigFile::parseNumber<uint16_t>(i, "tcp");
667 NFD_LOG_TRACE("TCP port set to " << port);
Yanbiao Li73860e32015-08-19 16:30:16 -0700668 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200669 else if (i.first == "listen") {
670 needToListen = ConfigFile::parseYesNo(i, "tcp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700671 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200672 else if (i.first == "enable_v4") {
673 enableV4 = ConfigFile::parseYesNo(i, "tcp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700674 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200675 else if (i.first == "enable_v6") {
676 enableV6 = ConfigFile::parseYesNo(i, "tcp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700677 }
678 else {
679 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200680 i.first + "\" in \"tcp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700681 }
682 }
683
684 if (!enableV4 && !enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200685 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 TCP channels have been disabled."
Yanbiao Li73860e32015-08-19 16:30:16 -0700686 " Remove \"tcp\" section to disable TCP channels or"
687 " re-enable at least one channel type."));
688 }
689
690 if (!isDryRun) {
691 if (m_factories.count("tcp") > 0) {
692 return;
693 }
694
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200695 auto factory = make_shared<TcpFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700696 m_factories.insert(std::make_pair("tcp", factory));
697
698 if (enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200699 tcp::Endpoint endpoint(boost::asio::ip::tcp::v4(), port);
700 shared_ptr<TcpChannel> v4Channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -0700701 if (needToListen) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200702 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700703 }
704
705 m_factories.insert(std::make_pair("tcp4", factory));
706 }
707
708 if (enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200709 tcp::Endpoint endpoint(boost::asio::ip::tcp::v6(), port);
710 shared_ptr<TcpChannel> v6Channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -0700711 if (needToListen) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200712 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700713 }
714
715 m_factories.insert(std::make_pair("tcp6", factory));
716 }
717 }
718}
719
720void
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200721FaceManager::processSectionUdp(const ConfigSection& configSection, bool isDryRun,
Yanbiao Li73860e32015-08-19 16:30:16 -0700722 const std::vector<NetworkInterfaceInfo>& nicList)
723{
724 // ; the udp section contains settings of UDP faces and channels
725 // udp
726 // {
727 // port 6363 ; UDP unicast port number
728 // idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
729 // keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
730
731 // ; NFD creates one UDP multicast face per NIC
732 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
733 // mcast_port 56363 ; UDP multicast port number
734 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
735 // }
736
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200737 uint16_t port = 6363;
Yanbiao Li73860e32015-08-19 16:30:16 -0700738 bool enableV4 = true;
739 bool enableV6 = true;
740 size_t timeout = 600;
741 size_t keepAliveInterval = 25;
742 bool useMcast = true;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200743 auto mcastGroup = boost::asio::ip::address_v4::from_string("224.0.23.170");
744 uint16_t mcastPort = 56363;
Yanbiao Li73860e32015-08-19 16:30:16 -0700745
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200746 for (const auto& i : configSection) {
747 if (i.first == "port") {
748 port = ConfigFile::parseNumber<uint16_t>(i, "udp");
749 NFD_LOG_TRACE("UDP unicast port set to " << port);
750 }
751 else if (i.first == "enable_v4") {
752 enableV4 = ConfigFile::parseYesNo(i, "udp");
753 }
754 else if (i.first == "enable_v6") {
755 enableV6 = ConfigFile::parseYesNo(i, "udp");
756 }
757 else if (i.first == "idle_timeout") {
Yanbiao Li73860e32015-08-19 16:30:16 -0700758 try {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200759 timeout = i.second.get_value<size_t>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700760 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200761 catch (const boost::property_tree::ptree_bad_data&) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700762 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200763 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700764 }
765 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200766 else if (i.first == "keep_alive_interval") {
Yanbiao Li73860e32015-08-19 16:30:16 -0700767 try {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200768 keepAliveInterval = i.second.get_value<size_t>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700769 /// \todo Make use of keepAliveInterval
Yanbiao Li73860e32015-08-19 16:30:16 -0700770 (void)(keepAliveInterval);
771 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200772 catch (const boost::property_tree::ptree_bad_data&) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700773 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200774 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700775 }
776 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200777 else if (i.first == "mcast") {
778 useMcast = ConfigFile::parseYesNo(i, "udp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700779 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200780 else if (i.first == "mcast_port") {
781 mcastPort = ConfigFile::parseNumber<uint16_t>(i, "udp");
782 NFD_LOG_TRACE("UDP multicast port set to " << mcastPort);
Yanbiao Li73860e32015-08-19 16:30:16 -0700783 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200784 else if (i.first == "mcast_group") {
785 boost::system::error_code ec;
786 mcastGroup = boost::asio::ip::address_v4::from_string(i.second.get_value<std::string>(), ec);
787 if (ec) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700788 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200789 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700790 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200791 NFD_LOG_TRACE("UDP multicast group set to " << mcastGroup);
Yanbiao Li73860e32015-08-19 16:30:16 -0700792 }
793 else {
794 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200795 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700796 }
797 }
798
799 if (!enableV4 && !enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200800 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 UDP channels have been disabled."
Yanbiao Li73860e32015-08-19 16:30:16 -0700801 " Remove \"udp\" section to disable UDP channels or"
802 " re-enable at least one channel type."));
803 }
804 else if (useMcast && !enableV4) {
805 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
806 " have been disabled (conflicting configuration options set)"));
807 }
808
809 if (!isDryRun) {
810 shared_ptr<UdpFactory> factory;
811 bool isReload = false;
812 if (m_factories.count("udp") > 0) {
813 isReload = true;
814 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
815 }
816 else {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200817 factory = make_shared<UdpFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700818 m_factories.insert(std::make_pair("udp", factory));
819 }
820
821 if (!isReload && enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200822 udp::Endpoint endpoint(boost::asio::ip::udp::v4(), port);
823 shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
824 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700825
826 m_factories.insert(std::make_pair("udp4", factory));
827 }
828
829 if (!isReload && enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200830 udp::Endpoint endpoint(boost::asio::ip::udp::v6(), port);
831 shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
832 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700833
Yanbiao Li73860e32015-08-19 16:30:16 -0700834 m_factories.insert(std::make_pair("udp6", factory));
835 }
836
Junxiao Shicde37ad2015-12-24 01:02:05 -0700837 std::set<shared_ptr<Face>> multicastFacesToRemove;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200838 for (const auto& i : factory->getMulticastFaces()) {
839 multicastFacesToRemove.insert(i.second);
840 }
841
Yanbiao Li73860e32015-08-19 16:30:16 -0700842 if (useMcast && enableV4) {
843 std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
844 for (const auto& nic : nicList) {
845 if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty()) {
846 ipv4MulticastInterfaces.push_back(nic);
847 }
848 }
849
850 bool isNicNameNecessary = false;
851#if defined(__linux__)
852 if (ipv4MulticastInterfaces.size() > 1) {
853 // On Linux if we have more than one MulticastUdpFace
854 // we need to specify the name of the interface
855 isNicNameNecessary = true;
856 }
857#endif
858
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200859 udp::Endpoint mcastEndpoint(mcastGroup, mcastPort);
Yanbiao Li73860e32015-08-19 16:30:16 -0700860 for (const auto& nic : ipv4MulticastInterfaces) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200861 udp::Endpoint localEndpoint(nic.ipv4Addresses[0], mcastPort);
862 auto newFace = factory->createMulticastFace(localEndpoint, mcastEndpoint,
Yukai Tu0a49d342015-09-13 12:54:22 +0800863 isNicNameNecessary ? nic.name : "");
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200864 m_faceTable.add(newFace);
865 multicastFacesToRemove.erase(newFace);
Yanbiao Li73860e32015-08-19 16:30:16 -0700866 }
867 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700868
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200869 for (const auto& face : multicastFacesToRemove) {
870 face->close();
Yanbiao Li73860e32015-08-19 16:30:16 -0700871 }
872 }
873}
874
875void
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200876FaceManager::processSectionEther(const ConfigSection& configSection, bool isDryRun,
Yanbiao Li73860e32015-08-19 16:30:16 -0700877 const std::vector<NetworkInterfaceInfo>& nicList)
878{
879 // ; the ether section contains settings of Ethernet faces and channels
880 // ether
881 // {
882 // ; NFD creates one Ethernet multicast face per NIC
883 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
884 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
885 // }
886
887#if defined(HAVE_LIBPCAP)
susmit91e1d7c2016-10-03 16:16:57 -0600888 NetworkInterfacePredicate nicPredicate;
Yanbiao Li73860e32015-08-19 16:30:16 -0700889 bool useMcast = true;
890 ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
891
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200892 for (const auto& i : configSection) {
893 if (i.first == "mcast") {
894 useMcast = ConfigFile::parseYesNo(i, "ether");
Yanbiao Li73860e32015-08-19 16:30:16 -0700895 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200896 else if (i.first == "mcast_group") {
897 mcastGroup = ethernet::Address::fromString(i.second.get_value<std::string>());
Yanbiao Li73860e32015-08-19 16:30:16 -0700898 if (mcastGroup.isNull()) {
899 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200900 i.first + "\" in \"ether\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700901 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200902 NFD_LOG_TRACE("Ethernet multicast group set to " << mcastGroup);
Yanbiao Li73860e32015-08-19 16:30:16 -0700903 }
susmit91e1d7c2016-10-03 16:16:57 -0600904 else if (i.first == "whitelist") {
905 nicPredicate.parseWhitelist(i.second);
906 }
907 else if (i.first == "blacklist") {
908 nicPredicate.parseBlacklist(i.second);
909 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700910 else {
911 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200912 i.first + "\" in \"ether\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700913 }
914 }
915
916 if (!isDryRun) {
917 shared_ptr<EthernetFactory> factory;
918 if (m_factories.count("ether") > 0) {
919 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
920 }
921 else {
922 factory = make_shared<EthernetFactory>();
923 m_factories.insert(std::make_pair("ether", factory));
924 }
925
Junxiao Shicde37ad2015-12-24 01:02:05 -0700926 std::set<shared_ptr<Face>> multicastFacesToRemove;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200927 for (const auto& i : factory->getMulticastFaces()) {
928 multicastFacesToRemove.insert(i.second);
929 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700930
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200931 if (useMcast) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700932 for (const auto& nic : nicList) {
susmit91e1d7c2016-10-03 16:16:57 -0600933 if (nic.isUp() && nic.isMulticastCapable() && nicPredicate(nic)) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700934 try {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200935 auto newFace = factory->createMulticastFace(nic, mcastGroup);
936 m_faceTable.add(newFace);
937 multicastFacesToRemove.erase(newFace);
Yanbiao Li73860e32015-08-19 16:30:16 -0700938 }
939 catch (const EthernetFactory::Error& factoryError) {
940 NFD_LOG_ERROR(factoryError.what() << ", continuing");
941 }
Davide Pesavento35120ea2015-11-17 21:13:18 +0100942 catch (const face::EthernetTransport::Error& faceError) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700943 NFD_LOG_ERROR(faceError.what() << ", continuing");
944 }
945 }
946 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700947 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700948
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200949 for (const auto& face : multicastFacesToRemove) {
950 face->close();
Yanbiao Li73860e32015-08-19 16:30:16 -0700951 }
952 }
953#else
954 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section"));
955#endif // HAVE_LIBPCAP
956}
957
958void
959FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
960{
961 // ; the websocket section contains settings of WebSocket faces and channels
962 // websocket
963 // {
964 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
965 // port 9696 ; WebSocket listener port number
966 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
967 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
968 // }
969
970#if defined(HAVE_WEBSOCKET)
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200971 uint16_t port = 9696;
Yanbiao Li73860e32015-08-19 16:30:16 -0700972 bool needToListen = true;
973 bool enableV4 = true;
974 bool enableV6 = true;
975
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200976 for (const auto& i : configSection) {
977 if (i.first == "port") {
978 port = ConfigFile::parseNumber<uint16_t>(i, "websocket");
979 NFD_LOG_TRACE("WebSocket port set to " << port);
Yanbiao Li73860e32015-08-19 16:30:16 -0700980 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200981 else if (i.first == "listen") {
982 needToListen = ConfigFile::parseYesNo(i, "websocket");
Yanbiao Li73860e32015-08-19 16:30:16 -0700983 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200984 else if (i.first == "enable_v4") {
985 enableV4 = ConfigFile::parseYesNo(i, "websocket");
Yanbiao Li73860e32015-08-19 16:30:16 -0700986 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200987 else if (i.first == "enable_v6") {
988 enableV6 = ConfigFile::parseYesNo(i, "websocket");
Yanbiao Li73860e32015-08-19 16:30:16 -0700989 }
990 else {
991 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200992 i.first + "\" in \"websocket\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700993 }
994 }
995
996 if (!enableV4 && !enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200997 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 WebSocket channels have been disabled."
Yanbiao Li73860e32015-08-19 16:30:16 -0700998 " Remove \"websocket\" section to disable WebSocket channels or"
999 " re-enable at least one channel type."));
1000 }
1001
1002 if (!enableV4 && enableV6) {
1003 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
1004 }
1005
1006 if (!isDryRun) {
1007 if (m_factories.count("websocket") > 0) {
1008 return;
1009 }
1010
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001011 auto factory = make_shared<WebSocketFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -07001012 m_factories.insert(std::make_pair("websocket", factory));
1013
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001014 shared_ptr<WebSocketChannel> channel;
1015
Yanbiao Li73860e32015-08-19 16:30:16 -07001016 if (enableV6 && enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001017 websocket::Endpoint endpoint(boost::asio::ip::address_v6::any(), port);
1018 channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -07001019
1020 m_factories.insert(std::make_pair("websocket46", factory));
1021 }
1022 else if (enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001023 websocket::Endpoint endpoint(boost::asio::ip::address_v4::any(), port);
1024 channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -07001025
1026 m_factories.insert(std::make_pair("websocket4", factory));
1027 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001028
1029 if (channel && needToListen) {
1030 channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
1031 }
Yanbiao Li73860e32015-08-19 16:30:16 -07001032 }
1033#else
1034 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without WebSocket, "
1035 "cannot process \"websocket\" section"));
1036#endif // HAVE_WEBSOCKET
1037}
1038
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001039} // namespace nfd