blob: e57fa35d2eb505e1e3832b008a66662015896997 [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"
Alexander Afanasyev1922d492016-09-08 15:22:46 -070030
31#include "face/protocol-factory.hpp"
32
33#ifdef HAVE_TCP
Yanbiao Li73860e32015-08-19 16:30:16 -070034#include "face/tcp-factory.hpp"
Alexander Afanasyev1922d492016-09-08 15:22:46 -070035#endif // HAVE_TCP
36
37#ifdef HAVE_UDP
Yanbiao Li73860e32015-08-19 16:30:16 -070038#include "face/udp-factory.hpp"
Alexander Afanasyev1922d492016-09-08 15:22:46 -070039#endif // HAVE_UDP
40
Yukai Tu0a49d342015-09-13 12:54:22 +080041#include "fw/face-table.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070042
Junxiao Shicbc8e942016-09-06 03:17:45 +000043#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi25c6ce42016-09-09 13:49:59 +000044#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
Yanbiao Li73860e32015-08-19 16:30:16 -070045
46#ifdef HAVE_UNIX_SOCKETS
47#include "face/unix-stream-factory.hpp"
48#endif // HAVE_UNIX_SOCKETS
49
50#ifdef HAVE_LIBPCAP
51#include "face/ethernet-factory.hpp"
Davide Pesavento35120ea2015-11-17 21:13:18 +010052#include "face/ethernet-transport.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070053#endif // HAVE_LIBPCAP
54
55#ifdef HAVE_WEBSOCKET
56#include "face/websocket-factory.hpp"
57#endif // HAVE_WEBSOCKET
58
59namespace nfd {
60
61NFD_LOG_INIT("FaceManager");
62
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000063FaceManager::FaceManager(FaceTable& faceTable, Dispatcher& dispatcher, CommandAuthenticator& authenticator)
64 : NfdManagerBase(dispatcher, authenticator, "faces")
Yanbiao Li73860e32015-08-19 16:30:16 -070065 , m_faceTable(faceTable)
66{
67 registerCommandHandler<ndn::nfd::FaceCreateCommand>("create",
68 bind(&FaceManager::createFace, this, _2, _3, _4, _5));
69
Eric Newberryb5aa7f52016-09-03 20:36:12 -070070 registerCommandHandler<ndn::nfd::FaceUpdateCommand>("update",
71 bind(&FaceManager::updateFace, this, _2, _3, _4, _5));
72
Yanbiao Li73860e32015-08-19 16:30:16 -070073 registerCommandHandler<ndn::nfd::FaceDestroyCommand>("destroy",
74 bind(&FaceManager::destroyFace, this, _2, _3, _4, _5));
75
76 registerCommandHandler<ndn::nfd::FaceEnableLocalControlCommand>("enable-local-control",
77 bind(&FaceManager::enableLocalControl, this, _2, _3, _4, _5));
78
79 registerCommandHandler<ndn::nfd::FaceDisableLocalControlCommand>("disable-local-control",
80 bind(&FaceManager::disableLocalControl, this, _2, _3, _4, _5));
81
82 registerStatusDatasetHandler("list", bind(&FaceManager::listFaces, this, _1, _2, _3));
83 registerStatusDatasetHandler("channels", bind(&FaceManager::listChannels, this, _1, _2, _3));
84 registerStatusDatasetHandler("query", bind(&FaceManager::queryFaces, this, _1, _2, _3));
85
Junxiao Shiae04d342016-07-19 13:20:22 +000086 m_postNotification = registerNotificationStream("events");
Eric Newberry1b4ba052016-10-07 23:04:07 -070087 m_faceAddConn = m_faceTable.afterAdd.connect([this] (const Face& face) {
88 connectFaceStateChangeSignal(face);
89 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
90 });
91 m_faceRemoveConn = m_faceTable.beforeRemove.connect([this] (const Face& face) {
92 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
93 });
Yanbiao Li73860e32015-08-19 16:30:16 -070094}
95
96void
97FaceManager::setConfigFile(ConfigFile& configFile)
98{
99 configFile.addSectionHandler("face_system", bind(&FaceManager::processConfig, this, _1, _2, _3));
100}
101
102void
103FaceManager::createFace(const Name& topPrefix, const Interest& interest,
104 const ControlParameters& parameters,
105 const ndn::mgmt::CommandContinuation& done)
106{
107 FaceUri uri;
108 if (!uri.parse(parameters.getUri())) {
109 NFD_LOG_TRACE("failed to parse URI");
Eric Newberry42602412016-08-27 09:33:18 -0700110 done(ControlResponse(400, "Malformed command"));
111 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700112 }
113
114 if (!uri.isCanonical()) {
115 NFD_LOG_TRACE("received non-canonical URI");
Eric Newberry42602412016-08-27 09:33:18 -0700116 done(ControlResponse(400, "Non-canonical URI"));
117 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700118 }
119
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200120 auto factory = m_factories.find(uri.getScheme());
Yanbiao Li73860e32015-08-19 16:30:16 -0700121 if (factory == m_factories.end()) {
Eric Newberry42602412016-08-27 09:33:18 -0700122 NFD_LOG_TRACE("received create request for unsupported protocol");
123 done(ControlResponse(406, "Unsupported protocol"));
124 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700125 }
126
127 try {
128 factory->second->createFace(uri,
129 parameters.getFacePersistency(),
Eric Newberryf40551a2016-09-05 15:41:16 -0700130 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
131 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
Yanbiao Li73860e32015-08-19 16:30:16 -0700132 bind(&FaceManager::afterCreateFaceSuccess,
133 this, parameters, _1, done),
134 bind(&FaceManager::afterCreateFaceFailure,
Eric Newberry42602412016-08-27 09:33:18 -0700135 this, _1, _2, done));
Yanbiao Li73860e32015-08-19 16:30:16 -0700136 }
137 catch (const std::runtime_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700138 NFD_LOG_ERROR("Face creation failed: " << error.what());
139 done(ControlResponse(500, "Face creation failed due to internal error"));
140 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700141 }
142 catch (const std::logic_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700143 NFD_LOG_ERROR("Face creation failed: " << error.what());
144 done(ControlResponse(500, "Face creation failed due to internal error"));
145 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700146 }
147}
148
Eric Newberry42602412016-08-27 09:33:18 -0700149/**
150 * \todo #3232
151 * If the creation of this face would conflict with an existing face (e.g. same underlying
152 * protocol and remote address, or a NIC-associated permanent face), the command will fail
153 * with StatusCode 409.
154 */
Yanbiao Li73860e32015-08-19 16:30:16 -0700155void
Eric Newberry42602412016-08-27 09:33:18 -0700156FaceManager::afterCreateFaceSuccess(const ControlParameters& parameters,
Eric Newberryf40551a2016-09-05 15:41:16 -0700157 const shared_ptr<Face>& face,
Yanbiao Li73860e32015-08-19 16:30:16 -0700158 const ndn::mgmt::CommandContinuation& done)
159{
Eric Newberryf40551a2016-09-05 15:41:16 -0700160 // TODO: Re-enable check in #3232
161 //if (face->getId() != face::INVALID_FACEID) {
162 //// Face already exists
163 //ControlParameters response;
164 //response.setFaceId(face->getId());
165 //response.setUri(face->getRemoteUri().toString());
166 //response.setFacePersistency(face->getPersistency());
167 //
168 //auto linkService = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
169 //BOOST_ASSERT(linkService != nullptr);
170 //auto options = linkService->getOptions();
171 //response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false);
172 //
173 // NFD_LOG_TRACE("Attempted to create duplicate face of " << face->getId());
174 // done(ControlResponse(409, "Face with remote URI already exists").setBody(response.wireEncode()));
175 //}
176 //else {
177 // If scope non-local and flags set to enable local fields, request shouldn't
178 // have made it this far
179 BOOST_ASSERT(face->getScope() == ndn::nfd::FACE_SCOPE_LOCAL ||
180 !parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ||
181 (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
182 !parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)));
183
184 m_faceTable.add(face);
185
Eric Newberry42602412016-08-27 09:33:18 -0700186 ControlParameters response;
Eric Newberryf40551a2016-09-05 15:41:16 -0700187 response.setFaceId(face->getId());
188 response.setFacePersistency(face->getPersistency());
189 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
190 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
191 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
192 false);
Eric Newberry42602412016-08-27 09:33:18 -0700193
194 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
Eric Newberryf40551a2016-09-05 15:41:16 -0700195 //}
Eric Newberry42602412016-08-27 09:33:18 -0700196}
197
198void
199FaceManager::afterCreateFaceFailure(uint32_t status,
200 const std::string& reason,
201 const ndn::mgmt::CommandContinuation& done)
202{
203 NFD_LOG_DEBUG("Face creation failed: " << reason);
204
205 done(ControlResponse(status, reason));
Yanbiao Li73860e32015-08-19 16:30:16 -0700206}
207
208void
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700209FaceManager::updateFace(const Name& topPrefix, const Interest& interest,
210 const ControlParameters& parameters,
211 const ndn::mgmt::CommandContinuation& done)
212{
213 FaceId faceId = parameters.getFaceId();
214 if (faceId == 0) {
215 // Self-updating
216 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
217 if (incomingFaceIdTag == nullptr) {
218 NFD_LOG_TRACE("unable to determine face for self-update");
219 done(ControlResponse(404, "No FaceId specified and IncomingFaceId not available"));
220 return;
221 }
222 faceId = *incomingFaceIdTag;
223 }
224
225 Face* face = m_faceTable.get(faceId);
226
227 if (face == nullptr) {
228 NFD_LOG_TRACE("invalid face specified");
229 done(ControlResponse(404, "Specified face does not exist"));
230 return;
231 }
232
233 // Verify validity of requested changes
234 ControlParameters response;
235 bool areParamsValid = true;
236
237 if (parameters.hasFacePersistency()) {
238 // TODO #3232: Add FacePersistency updating
239 NFD_LOG_TRACE("received unsupported face persistency change");
240 areParamsValid = false;
241 response.setFacePersistency(parameters.getFacePersistency());
242 }
243
244 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
245 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
246 face->getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
247 NFD_LOG_TRACE("received request to enable local fields on non-local face");
248 areParamsValid = false;
249 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
250 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
251 }
252
253 if (!areParamsValid) {
254 done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
255 return;
256 }
257
258 // All specified properties are valid, so make changes
259
260 // TODO #3232: Add FacePersistency updating
261
262 setLinkServiceOptions(*face, parameters, response);
263
Eric Newberryf40551a2016-09-05 15:41:16 -0700264 // Set ControlResponse fields
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700265 response.setFaceId(faceId);
266 response.setFacePersistency(face->getPersistency());
Eric Newberryf40551a2016-09-05 15:41:16 -0700267 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
268 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
269 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
270 false);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700271
272 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
273}
274
275void
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700276FaceManager::destroyFace(const Name& topPrefix, const Interest& interest,
277 const ControlParameters& parameters,
278 const ndn::mgmt::CommandContinuation& done)
279{
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000280 Face* face = m_faceTable.get(parameters.getFaceId());
281 if (face != nullptr) {
282 face->close();
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700283 }
284
285 done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
286}
287
288void
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700289FaceManager::enableLocalControl(const Name& topPrefix, const Interest& interest,
290 const ControlParameters& parameters,
291 const ndn::mgmt::CommandContinuation& done)
292{
Junxiao Shicde37ad2015-12-24 01:02:05 -0700293 Face* face = findFaceForLocalControl(interest, parameters, done);
294 if (!face) {
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700295 return;
296 }
297
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700298 // enable-local-control will enable all local fields in GenericLinkService
Junxiao Shicde37ad2015-12-24 01:02:05 -0700299 auto service = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700300 if (service == nullptr) {
301 return done(ControlResponse(503, "LinkService type not supported"));
302 }
303
304 face::GenericLinkService::Options options = service->getOptions();
305 options.allowLocalFields = true;
306 service->setOptions(options);
307
308 return done(ControlResponse(200, "OK: enable all local fields on GenericLinkService")
309 .setBody(parameters.wireEncode()));
310}
311
312void
313FaceManager::disableLocalControl(const Name& topPrefix, const Interest& interest,
314 const ControlParameters& parameters,
315 const ndn::mgmt::CommandContinuation& done)
316{
Junxiao Shicde37ad2015-12-24 01:02:05 -0700317 Face* face = findFaceForLocalControl(interest, parameters, done);
318 if (!face) {
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700319 return;
320 }
321
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700322 // disable-local-control will disable all local fields in GenericLinkService
Junxiao Shicde37ad2015-12-24 01:02:05 -0700323 auto service = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700324 if (service == nullptr) {
325 return done(ControlResponse(503, "LinkService type not supported"));
326 }
327
328 face::GenericLinkService::Options options = service->getOptions();
329 options.allowLocalFields = false;
330 service->setOptions(options);
331
332 return done(ControlResponse(200, "OK: disable all local fields on GenericLinkService")
333 .setBody(parameters.wireEncode()));
334}
335
Junxiao Shicde37ad2015-12-24 01:02:05 -0700336Face*
337FaceManager::findFaceForLocalControl(const Interest& request,
338 const ControlParameters& parameters,
339 const ndn::mgmt::CommandContinuation& done)
Yanbiao Li73860e32015-08-19 16:30:16 -0700340{
Junxiao Shi0de23a22015-12-03 20:07:02 +0000341 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = request.getTag<lp::IncomingFaceIdTag>();
342 // NDNLPv2 says "application MUST be prepared to receive a packet without IncomingFaceId field",
343 // but it's fine to assert IncomingFaceId is available, because InternalFace lives inside NFD
344 // and is initialized synchronously with IncomingFaceId field enabled.
345 BOOST_ASSERT(incomingFaceIdTag != nullptr);
346
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000347 Face* face = m_faceTable.get(*incomingFaceIdTag);
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200348 if (face == nullptr) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000349 NFD_LOG_DEBUG("FaceId " << *incomingFaceIdTag << " not found");
Yanbiao Li73860e32015-08-19 16:30:16 -0700350 done(ControlResponse(410, "Face not found"));
Junxiao Shicde37ad2015-12-24 01:02:05 -0700351 return nullptr;
Yanbiao Li73860e32015-08-19 16:30:16 -0700352 }
353
Junxiao Shicde37ad2015-12-24 01:02:05 -0700354 if (face->getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200355 NFD_LOG_DEBUG("Cannot enable local control on non-local FaceId " << face->getId());
Yanbiao Li73860e32015-08-19 16:30:16 -0700356 done(ControlResponse(412, "Face is non-local"));
Junxiao Shicde37ad2015-12-24 01:02:05 -0700357 return nullptr;
Yanbiao Li73860e32015-08-19 16:30:16 -0700358 }
359
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000360 return face;
Yanbiao Li73860e32015-08-19 16:30:16 -0700361}
362
363void
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700364FaceManager::setLinkServiceOptions(Face& face,
365 const ControlParameters& parameters,
366 ControlParameters& response)
367{
368 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
369 BOOST_ASSERT(linkService != nullptr);
370
371 auto options = linkService->getOptions();
372 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
373 face.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
374 options.allowLocalFields = parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
375 }
376 linkService->setOptions(options);
377
378 // Set Flags for ControlResponse
379 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false);
380}
381
382void
Yanbiao Li73860e32015-08-19 16:30:16 -0700383FaceManager::listFaces(const Name& topPrefix, const Interest& interest,
384 ndn::mgmt::StatusDatasetContext& context)
385{
Eric Newberryc64d30a2015-12-26 11:07:27 -0700386 auto now = time::steady_clock::now();
Junxiao Shib84e6742016-07-19 13:16:22 +0000387 for (const Face& face : m_faceTable) {
388 ndn::nfd::FaceStatus status = collectFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700389 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700390 }
391 context.end();
392}
393
394void
395FaceManager::listChannels(const Name& topPrefix, const Interest& interest,
396 ndn::mgmt::StatusDatasetContext& context)
397{
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200398 std::set<const ProtocolFactory*> seenFactories;
Yanbiao Li73860e32015-08-19 16:30:16 -0700399
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200400 for (const auto& kv : m_factories) {
401 const ProtocolFactory* factory = kv.second.get();
402 bool inserted;
403 std::tie(std::ignore, inserted) = seenFactories.insert(factory);
Yanbiao Li73860e32015-08-19 16:30:16 -0700404
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200405 if (inserted) {
406 for (const auto& channel : factory->getChannels()) {
407 ndn::nfd::ChannelStatus entry;
408 entry.setLocalUri(channel->getUri().toString());
409 context.append(entry.wireEncode());
410 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700411 }
412 }
413
414 context.end();
415}
416
417void
418FaceManager::queryFaces(const Name& topPrefix, const Interest& interest,
419 ndn::mgmt::StatusDatasetContext& context)
420{
421 ndn::nfd::FaceQueryFilter faceFilter;
422 const Name& query = interest.getName();
423 try {
424 faceFilter.wireDecode(query[-1].blockFromValue());
425 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200426 catch (const tlv::Error& e) {
427 NFD_LOG_DEBUG("Malformed query filter: " << e.what());
428 return context.reject(ControlResponse(400, "Malformed filter"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700429 }
430
Eric Newberryc64d30a2015-12-26 11:07:27 -0700431 auto now = time::steady_clock::now();
Junxiao Shib84e6742016-07-19 13:16:22 +0000432 for (const Face& face : m_faceTable) {
433 if (!matchFilter(faceFilter, face)) {
Junxiao Shida93f1f2015-11-11 06:13:16 -0700434 continue;
Yanbiao Li73860e32015-08-19 16:30:16 -0700435 }
Junxiao Shib84e6742016-07-19 13:16:22 +0000436 ndn::nfd::FaceStatus status = collectFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700437 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700438 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200439
Yanbiao Li73860e32015-08-19 16:30:16 -0700440 context.end();
441}
442
443bool
Junxiao Shib84e6742016-07-19 13:16:22 +0000444FaceManager::matchFilter(const ndn::nfd::FaceQueryFilter& filter, const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700445{
446 if (filter.hasFaceId() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000447 filter.getFaceId() != static_cast<uint64_t>(face.getId())) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700448 return false;
449 }
450
451 if (filter.hasUriScheme() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000452 filter.getUriScheme() != face.getRemoteUri().getScheme() &&
453 filter.getUriScheme() != face.getLocalUri().getScheme()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700454 return false;
455 }
456
457 if (filter.hasRemoteUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000458 filter.getRemoteUri() != face.getRemoteUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700459 return false;
460 }
461
462 if (filter.hasLocalUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000463 filter.getLocalUri() != face.getLocalUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700464 return false;
465 }
466
467 if (filter.hasFaceScope() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000468 filter.getFaceScope() != face.getScope()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700469 return false;
470 }
471
472 if (filter.hasFacePersistency() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000473 filter.getFacePersistency() != face.getPersistency()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700474 return false;
475 }
476
477 if (filter.hasLinkType() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000478 filter.getLinkType() != face.getLinkType()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700479 return false;
480 }
481
482 return true;
483}
484
Eric Newberryc64d30a2015-12-26 11:07:27 -0700485ndn::nfd::FaceStatus
486FaceManager::collectFaceStatus(const Face& face, const time::steady_clock::TimePoint& now)
487{
488 ndn::nfd::FaceStatus status;
489
490 collectFaceProperties(face, status);
491
492 time::steady_clock::TimePoint expirationTime = face.getExpirationTime();
493 if (expirationTime != time::steady_clock::TimePoint::max()) {
494 status.setExpirationPeriod(std::max(time::milliseconds(0),
495 time::duration_cast<time::milliseconds>(expirationTime - now)));
496 }
497
498 const face::FaceCounters& counters = face.getCounters();
499 status.setNInInterests(counters.nInInterests)
500 .setNOutInterests(counters.nOutInterests)
501 .setNInDatas(counters.nInData)
502 .setNOutDatas(counters.nOutData)
503 .setNInNacks(counters.nInNacks)
504 .setNOutNacks(counters.nOutNacks)
505 .setNInBytes(counters.nInBytes)
506 .setNOutBytes(counters.nOutBytes);
507
508 return status;
509}
510
Junxiao Shida93f1f2015-11-11 06:13:16 -0700511template<typename FaceTraits>
Junxiao Shicde37ad2015-12-24 01:02:05 -0700512void
513FaceManager::collectFaceProperties(const Face& face, FaceTraits& traits)
Junxiao Shida93f1f2015-11-11 06:13:16 -0700514{
515 traits.setFaceId(face.getId())
516 .setRemoteUri(face.getRemoteUri().toString())
517 .setLocalUri(face.getLocalUri().toString())
518 .setFaceScope(face.getScope())
519 .setFacePersistency(face.getPersistency())
520 .setLinkType(face.getLinkType());
Eric Newberry1b4ba052016-10-07 23:04:07 -0700521
522 // Set Flag bits
523 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
524 if (linkService != nullptr) {
525 auto linkServiceOptions = linkService->getOptions();
526 traits.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, linkServiceOptions.allowLocalFields);
527 }
Junxiao Shida93f1f2015-11-11 06:13:16 -0700528}
529
530void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700531FaceManager::notifyFaceEvent(const Face& face, ndn::nfd::FaceEventKind kind)
Yanbiao Li73860e32015-08-19 16:30:16 -0700532{
533 ndn::nfd::FaceEventNotification notification;
Eric Newberry1b4ba052016-10-07 23:04:07 -0700534 notification.setKind(kind);
Junxiao Shiae04d342016-07-19 13:20:22 +0000535 collectFaceProperties(face, notification);
Yanbiao Li73860e32015-08-19 16:30:16 -0700536
Junxiao Shiae04d342016-07-19 13:20:22 +0000537 m_postNotification(notification.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700538}
539
540void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700541FaceManager::connectFaceStateChangeSignal(const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700542{
Eric Newberry1b4ba052016-10-07 23:04:07 -0700543 FaceId faceId = face.getId();
544 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
545 [this, faceId] (face::FaceState oldState, face::FaceState newState) {
546 const Face& face = *m_faceTable.get(faceId);
Yanbiao Li73860e32015-08-19 16:30:16 -0700547
Eric Newberry1b4ba052016-10-07 23:04:07 -0700548 if (newState == face::FaceState::UP) {
549 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
550 }
551 else if (newState == face::FaceState::DOWN) {
552 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
553 }
554 else if (newState == face::FaceState::CLOSED) {
555 m_faceStateChangeConn.erase(faceId);
556 }
557 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700558}
559
560void
561FaceManager::processConfig(const ConfigSection& configSection,
562 bool isDryRun,
563 const std::string& filename)
564{
565 bool hasSeenUnix = false;
566 bool hasSeenTcp = false;
567 bool hasSeenUdp = false;
568 bool hasSeenEther = false;
569 bool hasSeenWebSocket = false;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200570 auto nicList = listNetworkInterfaces();
Yanbiao Li73860e32015-08-19 16:30:16 -0700571
572 for (const auto& item : configSection) {
573 if (item.first == "unix") {
574 if (hasSeenUnix) {
575 BOOST_THROW_EXCEPTION(Error("Duplicate \"unix\" section"));
576 }
577 hasSeenUnix = true;
578
579 processSectionUnix(item.second, isDryRun);
580 }
581 else if (item.first == "tcp") {
582 if (hasSeenTcp) {
583 BOOST_THROW_EXCEPTION(Error("Duplicate \"tcp\" section"));
584 }
585 hasSeenTcp = true;
586
587 processSectionTcp(item.second, isDryRun);
588 }
589 else if (item.first == "udp") {
590 if (hasSeenUdp) {
591 BOOST_THROW_EXCEPTION(Error("Duplicate \"udp\" section"));
592 }
593 hasSeenUdp = true;
594
595 processSectionUdp(item.second, isDryRun, nicList);
596 }
597 else if (item.first == "ether") {
598 if (hasSeenEther) {
599 BOOST_THROW_EXCEPTION(Error("Duplicate \"ether\" section"));
600 }
601 hasSeenEther = true;
602
603 processSectionEther(item.second, isDryRun, nicList);
604 }
605 else if (item.first == "websocket") {
606 if (hasSeenWebSocket) {
607 BOOST_THROW_EXCEPTION(Error("Duplicate \"websocket\" section"));
608 }
609 hasSeenWebSocket = true;
610
611 processSectionWebSocket(item.second, isDryRun);
612 }
613 else {
614 BOOST_THROW_EXCEPTION(Error("Unrecognized option \"" + item.first + "\""));
615 }
616 }
617}
618
619void
620FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
621{
622 // ; the unix section contains settings of Unix stream faces and channels
623 // unix
624 // {
625 // path /var/run/nfd.sock ; Unix stream listener path
626 // }
627
628#if defined(HAVE_UNIX_SOCKETS)
Yanbiao Li73860e32015-08-19 16:30:16 -0700629 std::string path = "/var/run/nfd.sock";
630
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200631 for (const auto& i : configSection) {
632 if (i.first == "path") {
633 path = i.second.get_value<std::string>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700634 }
635 else {
636 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200637 i.first + "\" in \"unix\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700638 }
639 }
640
641 if (!isDryRun) {
642 if (m_factories.count("unix") > 0) {
643 return;
644 }
645
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200646 auto factory = make_shared<UnixStreamFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700647 m_factories.insert(std::make_pair("unix", factory));
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200648
649 auto channel = factory->createChannel(path);
650 channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700651 }
652#else
653 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
654 "cannot process \"unix\" section"));
655#endif // HAVE_UNIX_SOCKETS
656}
657
658void
659FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
660{
661 // ; the tcp section contains settings of TCP faces and channels
662 // tcp
663 // {
664 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
665 // port 6363 ; TCP listener port number
666 // }
667
Alexander Afanasyev1922d492016-09-08 15:22:46 -0700668#if defined(HAVE_TCP)
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200669 uint16_t port = 6363;
Yanbiao Li73860e32015-08-19 16:30:16 -0700670 bool needToListen = true;
671 bool enableV4 = true;
672 bool enableV6 = true;
673
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200674 for (const auto& i : configSection) {
675 if (i.first == "port") {
676 port = ConfigFile::parseNumber<uint16_t>(i, "tcp");
677 NFD_LOG_TRACE("TCP port set to " << port);
Yanbiao Li73860e32015-08-19 16:30:16 -0700678 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200679 else if (i.first == "listen") {
680 needToListen = ConfigFile::parseYesNo(i, "tcp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700681 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200682 else if (i.first == "enable_v4") {
683 enableV4 = ConfigFile::parseYesNo(i, "tcp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700684 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200685 else if (i.first == "enable_v6") {
686 enableV6 = ConfigFile::parseYesNo(i, "tcp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700687 }
688 else {
689 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200690 i.first + "\" in \"tcp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700691 }
692 }
693
694 if (!enableV4 && !enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200695 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 TCP channels have been disabled."
Yanbiao Li73860e32015-08-19 16:30:16 -0700696 " Remove \"tcp\" section to disable TCP channels or"
697 " re-enable at least one channel type."));
698 }
699
700 if (!isDryRun) {
701 if (m_factories.count("tcp") > 0) {
702 return;
703 }
704
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200705 auto factory = make_shared<TcpFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700706 m_factories.insert(std::make_pair("tcp", factory));
707
708 if (enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200709 tcp::Endpoint endpoint(boost::asio::ip::tcp::v4(), port);
710 shared_ptr<TcpChannel> v4Channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -0700711 if (needToListen) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200712 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700713 }
714
715 m_factories.insert(std::make_pair("tcp4", factory));
716 }
717
718 if (enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200719 tcp::Endpoint endpoint(boost::asio::ip::tcp::v6(), port);
720 shared_ptr<TcpChannel> v6Channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -0700721 if (needToListen) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200722 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700723 }
724
725 m_factories.insert(std::make_pair("tcp6", factory));
726 }
727 }
Alexander Afanasyev1922d492016-09-08 15:22:46 -0700728#else
729 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without TCP support, cannot process \"tcp\" section"));
730#endif // HAVE_TCP
Yanbiao Li73860e32015-08-19 16:30:16 -0700731}
732
733void
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200734FaceManager::processSectionUdp(const ConfigSection& configSection, bool isDryRun,
Yanbiao Li73860e32015-08-19 16:30:16 -0700735 const std::vector<NetworkInterfaceInfo>& nicList)
736{
737 // ; the udp section contains settings of UDP faces and channels
738 // udp
739 // {
740 // port 6363 ; UDP unicast port number
741 // idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
742 // keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
743
744 // ; NFD creates one UDP multicast face per NIC
745 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
746 // mcast_port 56363 ; UDP multicast port number
747 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
748 // }
749
Alexander Afanasyev1922d492016-09-08 15:22:46 -0700750#if defined(HAVE_UDP)
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200751 uint16_t port = 6363;
Yanbiao Li73860e32015-08-19 16:30:16 -0700752 bool enableV4 = true;
753 bool enableV6 = true;
754 size_t timeout = 600;
755 size_t keepAliveInterval = 25;
756 bool useMcast = true;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200757 auto mcastGroup = boost::asio::ip::address_v4::from_string("224.0.23.170");
758 uint16_t mcastPort = 56363;
Yanbiao Li73860e32015-08-19 16:30:16 -0700759
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200760 for (const auto& i : configSection) {
761 if (i.first == "port") {
762 port = ConfigFile::parseNumber<uint16_t>(i, "udp");
763 NFD_LOG_TRACE("UDP unicast port set to " << port);
764 }
765 else if (i.first == "enable_v4") {
766 enableV4 = ConfigFile::parseYesNo(i, "udp");
767 }
768 else if (i.first == "enable_v6") {
769 enableV6 = ConfigFile::parseYesNo(i, "udp");
770 }
771 else if (i.first == "idle_timeout") {
Yanbiao Li73860e32015-08-19 16:30:16 -0700772 try {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200773 timeout = i.second.get_value<size_t>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700774 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200775 catch (const boost::property_tree::ptree_bad_data&) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700776 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200777 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700778 }
779 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200780 else if (i.first == "keep_alive_interval") {
Yanbiao Li73860e32015-08-19 16:30:16 -0700781 try {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200782 keepAliveInterval = i.second.get_value<size_t>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700783 /// \todo Make use of keepAliveInterval
Yanbiao Li73860e32015-08-19 16:30:16 -0700784 (void)(keepAliveInterval);
785 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200786 catch (const boost::property_tree::ptree_bad_data&) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700787 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200788 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700789 }
790 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200791 else if (i.first == "mcast") {
792 useMcast = ConfigFile::parseYesNo(i, "udp");
Yanbiao Li73860e32015-08-19 16:30:16 -0700793 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200794 else if (i.first == "mcast_port") {
795 mcastPort = ConfigFile::parseNumber<uint16_t>(i, "udp");
796 NFD_LOG_TRACE("UDP multicast port set to " << mcastPort);
Yanbiao Li73860e32015-08-19 16:30:16 -0700797 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200798 else if (i.first == "mcast_group") {
799 boost::system::error_code ec;
800 mcastGroup = boost::asio::ip::address_v4::from_string(i.second.get_value<std::string>(), ec);
801 if (ec) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700802 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200803 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700804 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200805 NFD_LOG_TRACE("UDP multicast group set to " << mcastGroup);
Yanbiao Li73860e32015-08-19 16:30:16 -0700806 }
807 else {
808 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200809 i.first + "\" in \"udp\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700810 }
811 }
812
813 if (!enableV4 && !enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200814 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 UDP channels have been disabled."
Yanbiao Li73860e32015-08-19 16:30:16 -0700815 " Remove \"udp\" section to disable UDP channels or"
816 " re-enable at least one channel type."));
817 }
818 else if (useMcast && !enableV4) {
819 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
820 " have been disabled (conflicting configuration options set)"));
821 }
822
823 if (!isDryRun) {
824 shared_ptr<UdpFactory> factory;
825 bool isReload = false;
826 if (m_factories.count("udp") > 0) {
827 isReload = true;
828 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
829 }
830 else {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200831 factory = make_shared<UdpFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -0700832 m_factories.insert(std::make_pair("udp", factory));
833 }
834
835 if (!isReload && enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200836 udp::Endpoint endpoint(boost::asio::ip::udp::v4(), port);
837 shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
838 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700839
840 m_factories.insert(std::make_pair("udp4", factory));
841 }
842
843 if (!isReload && enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200844 udp::Endpoint endpoint(boost::asio::ip::udp::v6(), port);
845 shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
846 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
Yanbiao Li73860e32015-08-19 16:30:16 -0700847
Yanbiao Li73860e32015-08-19 16:30:16 -0700848 m_factories.insert(std::make_pair("udp6", factory));
849 }
850
Junxiao Shicde37ad2015-12-24 01:02:05 -0700851 std::set<shared_ptr<Face>> multicastFacesToRemove;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200852 for (const auto& i : factory->getMulticastFaces()) {
853 multicastFacesToRemove.insert(i.second);
854 }
855
Yanbiao Li73860e32015-08-19 16:30:16 -0700856 if (useMcast && enableV4) {
857 std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
858 for (const auto& nic : nicList) {
859 if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty()) {
860 ipv4MulticastInterfaces.push_back(nic);
861 }
862 }
863
864 bool isNicNameNecessary = false;
865#if defined(__linux__)
866 if (ipv4MulticastInterfaces.size() > 1) {
867 // On Linux if we have more than one MulticastUdpFace
868 // we need to specify the name of the interface
869 isNicNameNecessary = true;
870 }
871#endif
872
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200873 udp::Endpoint mcastEndpoint(mcastGroup, mcastPort);
Yanbiao Li73860e32015-08-19 16:30:16 -0700874 for (const auto& nic : ipv4MulticastInterfaces) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200875 udp::Endpoint localEndpoint(nic.ipv4Addresses[0], mcastPort);
876 auto newFace = factory->createMulticastFace(localEndpoint, mcastEndpoint,
Yukai Tu0a49d342015-09-13 12:54:22 +0800877 isNicNameNecessary ? nic.name : "");
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200878 m_faceTable.add(newFace);
879 multicastFacesToRemove.erase(newFace);
Yanbiao Li73860e32015-08-19 16:30:16 -0700880 }
881 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700882
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200883 for (const auto& face : multicastFacesToRemove) {
884 face->close();
Yanbiao Li73860e32015-08-19 16:30:16 -0700885 }
886 }
Alexander Afanasyev1922d492016-09-08 15:22:46 -0700887#else
888 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without UDP support, cannot process \"udp\" section"));
889#endif // HAVE_UDP
Yanbiao Li73860e32015-08-19 16:30:16 -0700890}
891
892void
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200893FaceManager::processSectionEther(const ConfigSection& configSection, bool isDryRun,
Yanbiao Li73860e32015-08-19 16:30:16 -0700894 const std::vector<NetworkInterfaceInfo>& nicList)
895{
896 // ; the ether section contains settings of Ethernet faces and channels
897 // ether
898 // {
899 // ; NFD creates one Ethernet multicast face per NIC
900 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
901 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
902 // }
903
904#if defined(HAVE_LIBPCAP)
susmit91e1d7c2016-10-03 16:16:57 -0600905 NetworkInterfacePredicate nicPredicate;
Yanbiao Li73860e32015-08-19 16:30:16 -0700906 bool useMcast = true;
907 ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
908
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200909 for (const auto& i : configSection) {
910 if (i.first == "mcast") {
911 useMcast = ConfigFile::parseYesNo(i, "ether");
Yanbiao Li73860e32015-08-19 16:30:16 -0700912 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200913 else if (i.first == "mcast_group") {
914 mcastGroup = ethernet::Address::fromString(i.second.get_value<std::string>());
Yanbiao Li73860e32015-08-19 16:30:16 -0700915 if (mcastGroup.isNull()) {
916 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200917 i.first + "\" in \"ether\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700918 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200919 NFD_LOG_TRACE("Ethernet multicast group set to " << mcastGroup);
Yanbiao Li73860e32015-08-19 16:30:16 -0700920 }
susmit91e1d7c2016-10-03 16:16:57 -0600921 else if (i.first == "whitelist") {
922 nicPredicate.parseWhitelist(i.second);
923 }
924 else if (i.first == "blacklist") {
925 nicPredicate.parseBlacklist(i.second);
926 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700927 else {
928 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200929 i.first + "\" in \"ether\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700930 }
931 }
932
933 if (!isDryRun) {
934 shared_ptr<EthernetFactory> factory;
935 if (m_factories.count("ether") > 0) {
936 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
937 }
938 else {
939 factory = make_shared<EthernetFactory>();
940 m_factories.insert(std::make_pair("ether", factory));
941 }
942
Junxiao Shicde37ad2015-12-24 01:02:05 -0700943 std::set<shared_ptr<Face>> multicastFacesToRemove;
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200944 for (const auto& i : factory->getMulticastFaces()) {
945 multicastFacesToRemove.insert(i.second);
946 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700947
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200948 if (useMcast) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700949 for (const auto& nic : nicList) {
susmit91e1d7c2016-10-03 16:16:57 -0600950 if (nic.isUp() && nic.isMulticastCapable() && nicPredicate(nic)) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700951 try {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200952 auto newFace = factory->createMulticastFace(nic, mcastGroup);
953 m_faceTable.add(newFace);
954 multicastFacesToRemove.erase(newFace);
Yanbiao Li73860e32015-08-19 16:30:16 -0700955 }
956 catch (const EthernetFactory::Error& factoryError) {
957 NFD_LOG_ERROR(factoryError.what() << ", continuing");
958 }
Davide Pesavento35120ea2015-11-17 21:13:18 +0100959 catch (const face::EthernetTransport::Error& faceError) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700960 NFD_LOG_ERROR(faceError.what() << ", continuing");
961 }
962 }
963 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700964 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700965
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200966 for (const auto& face : multicastFacesToRemove) {
967 face->close();
Yanbiao Li73860e32015-08-19 16:30:16 -0700968 }
969 }
970#else
971 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section"));
972#endif // HAVE_LIBPCAP
973}
974
975void
976FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
977{
978 // ; the websocket section contains settings of WebSocket faces and channels
979 // websocket
980 // {
981 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
982 // port 9696 ; WebSocket listener port number
983 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
984 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
985 // }
986
987#if defined(HAVE_WEBSOCKET)
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200988 uint16_t port = 9696;
Yanbiao Li73860e32015-08-19 16:30:16 -0700989 bool needToListen = true;
990 bool enableV4 = true;
991 bool enableV6 = true;
992
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200993 for (const auto& i : configSection) {
994 if (i.first == "port") {
995 port = ConfigFile::parseNumber<uint16_t>(i, "websocket");
996 NFD_LOG_TRACE("WebSocket port set to " << port);
Yanbiao Li73860e32015-08-19 16:30:16 -0700997 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200998 else if (i.first == "listen") {
999 needToListen = ConfigFile::parseYesNo(i, "websocket");
Yanbiao Li73860e32015-08-19 16:30:16 -07001000 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001001 else if (i.first == "enable_v4") {
1002 enableV4 = ConfigFile::parseYesNo(i, "websocket");
Yanbiao Li73860e32015-08-19 16:30:16 -07001003 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001004 else if (i.first == "enable_v6") {
1005 enableV6 = ConfigFile::parseYesNo(i, "websocket");
Yanbiao Li73860e32015-08-19 16:30:16 -07001006 }
1007 else {
1008 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001009 i.first + "\" in \"websocket\" section"));
Yanbiao Li73860e32015-08-19 16:30:16 -07001010 }
1011 }
1012
1013 if (!enableV4 && !enableV6) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001014 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 WebSocket channels have been disabled."
Yanbiao Li73860e32015-08-19 16:30:16 -07001015 " Remove \"websocket\" section to disable WebSocket channels or"
1016 " re-enable at least one channel type."));
1017 }
1018
1019 if (!enableV4 && enableV6) {
1020 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
1021 }
1022
1023 if (!isDryRun) {
1024 if (m_factories.count("websocket") > 0) {
1025 return;
1026 }
1027
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001028 auto factory = make_shared<WebSocketFactory>();
Yanbiao Li73860e32015-08-19 16:30:16 -07001029 m_factories.insert(std::make_pair("websocket", factory));
1030
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001031 shared_ptr<WebSocketChannel> channel;
1032
Yanbiao Li73860e32015-08-19 16:30:16 -07001033 if (enableV6 && enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001034 websocket::Endpoint endpoint(boost::asio::ip::address_v6::any(), port);
1035 channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -07001036
1037 m_factories.insert(std::make_pair("websocket46", factory));
1038 }
1039 else if (enableV4) {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001040 websocket::Endpoint endpoint(boost::asio::ip::address_v4::any(), port);
1041 channel = factory->createChannel(endpoint);
Yanbiao Li73860e32015-08-19 16:30:16 -07001042
1043 m_factories.insert(std::make_pair("websocket4", factory));
1044 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001045
1046 if (channel && needToListen) {
1047 channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
1048 }
Yanbiao Li73860e32015-08-19 16:30:16 -07001049 }
1050#else
1051 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without WebSocket, "
1052 "cannot process \"websocket\" section"));
1053#endif // HAVE_WEBSOCKET
1054}
1055
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02001056} // namespace nfd