blob: 229992767e03509e8996bdeba12d36e4f7657dad [file] [log] [blame]
Yanbiao Li73860e32015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Eric Newberry944f38b2017-07-20 20:54:22 -04002/*
Davide Pesavento15b55052018-01-27 19:09:28 -05003 * Copyright (c) 2014-2018, 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"
Davide Pesaventoa3148082018-04-12 18:21:54 -040027
28#include "core/logger.hpp"
Junxiao Shi40cb61c2015-09-23 18:36:45 -070029#include "face/generic-link-service.hpp"
Junxiao Shib8590312016-12-29 21:22:25 +000030#include "face/protocol-factory.hpp"
Yukai Tu0a49d342015-09-13 12:54:22 +080031#include "fw/face-table.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070032
Junxiao Shicbc8e942016-09-06 03:17:45 +000033#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi25c6ce42016-09-09 13:49:59 +000034#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
Davide Pesavento28181322018-11-08 16:44:50 -050035#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
36#include <ndn-cxx/mgmt/nfd/face-query-filter.hpp>
37#include <ndn-cxx/mgmt/nfd/face-status.hpp>
Yanbiao Li73860e32015-08-19 16:30:16 -070038
Yanbiao Li73860e32015-08-19 16:30:16 -070039namespace nfd {
40
Davide Pesaventoa3148082018-04-12 18:21:54 -040041NFD_LOG_INIT(FaceManager);
Yanbiao Li73860e32015-08-19 16:30:16 -070042
Junxiao Shiea47bde2017-01-26 17:49:16 +000043FaceManager::FaceManager(FaceSystem& faceSystem,
Davide Pesaventocfb1a312018-03-01 01:30:56 -050044 Dispatcher& dispatcher,
45 CommandAuthenticator& authenticator)
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000046 : NfdManagerBase(dispatcher, authenticator, "faces")
Junxiao Shiea47bde2017-01-26 17:49:16 +000047 , m_faceSystem(faceSystem)
48 , m_faceTable(faceSystem.getFaceTable())
Yanbiao Li73860e32015-08-19 16:30:16 -070049{
Yanbiao Li58ba3f92017-02-15 14:27:18 +000050 // register handlers for ControlCommand
Davide Pesavento28181322018-11-08 16:44:50 -050051 registerCommandHandler<ndn::nfd::FaceCreateCommand>("create", bind(&FaceManager::createFace, this, _4, _5));
52 registerCommandHandler<ndn::nfd::FaceUpdateCommand>("update", bind(&FaceManager::updateFace, this, _3, _4, _5));
53 registerCommandHandler<ndn::nfd::FaceDestroyCommand>("destroy", bind(&FaceManager::destroyFace, this, _4, _5));
Yanbiao Li73860e32015-08-19 16:30:16 -070054
Yanbiao Li58ba3f92017-02-15 14:27:18 +000055 // register handlers for StatusDataset
Davide Pesavento28181322018-11-08 16:44:50 -050056 registerStatusDatasetHandler("list", bind(&FaceManager::listFaces, this, _3));
57 registerStatusDatasetHandler("channels", bind(&FaceManager::listChannels, this, _3));
58 registerStatusDatasetHandler("query", bind(&FaceManager::queryFaces, this, _2, _3));
Yanbiao Li73860e32015-08-19 16:30:16 -070059
Yanbiao Li58ba3f92017-02-15 14:27:18 +000060 // register notification stream
Junxiao Shiae04d342016-07-19 13:20:22 +000061 m_postNotification = registerNotificationStream("events");
Eric Newberry1b4ba052016-10-07 23:04:07 -070062 m_faceAddConn = m_faceTable.afterAdd.connect([this] (const Face& face) {
63 connectFaceStateChangeSignal(face);
64 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
65 });
66 m_faceRemoveConn = m_faceTable.beforeRemove.connect([this] (const Face& face) {
67 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
68 });
Yanbiao Li73860e32015-08-19 16:30:16 -070069}
70
71void
Davide Pesavento28181322018-11-08 16:44:50 -050072FaceManager::createFace(const ControlParameters& parameters,
Yanbiao Li73860e32015-08-19 16:30:16 -070073 const ndn::mgmt::CommandContinuation& done)
74{
Eric Newberry78e32b02017-04-01 14:34:44 +000075 FaceUri remoteUri;
76 if (!remoteUri.parse(parameters.getUri())) {
77 NFD_LOG_TRACE("failed to parse remote URI: " << parameters.getUri());
Eric Newberry42602412016-08-27 09:33:18 -070078 done(ControlResponse(400, "Malformed command"));
79 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070080 }
81
Eric Newberry78e32b02017-04-01 14:34:44 +000082 if (!remoteUri.isCanonical()) {
83 NFD_LOG_TRACE("received non-canonical remote URI: " << remoteUri.toString());
84 done(ControlResponse(400, "Non-canonical remote URI"));
Eric Newberry42602412016-08-27 09:33:18 -070085 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070086 }
87
Davide Pesavento87fc0f82018-04-11 23:43:51 -040088 optional<FaceUri> localUri;
Eric Newberry78e32b02017-04-01 14:34:44 +000089 if (parameters.hasLocalUri()) {
90 localUri = FaceUri{};
91
92 if (!localUri->parse(parameters.getLocalUri())) {
93 NFD_LOG_TRACE("failed to parse local URI: " << parameters.getLocalUri());
94 done(ControlResponse(400, "Malformed command"));
95 return;
96 }
97
98 if (!localUri->isCanonical()) {
99 NFD_LOG_TRACE("received non-canonical local URI: " << localUri->toString());
100 done(ControlResponse(400, "Non-canonical local URI"));
101 return;
102 }
103 }
104
Davide Pesaventoe5eebad2017-04-06 20:23:26 -0400105 face::ProtocolFactory* factory = m_faceSystem.getFactoryByScheme(remoteUri.getScheme());
Junxiao Shib8590312016-12-29 21:22:25 +0000106 if (factory == nullptr) {
Eric Newberry78e32b02017-04-01 14:34:44 +0000107 NFD_LOG_TRACE("received create request for unsupported protocol: " << remoteUri.getScheme());
Eric Newberry42602412016-08-27 09:33:18 -0700108 done(ControlResponse(406, "Unsupported protocol"));
109 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700110 }
111
Davide Pesavento15b55052018-01-27 19:09:28 -0500112 face::FaceParams faceParams;
113 faceParams.persistency = parameters.getFacePersistency();
Eric Newberry0c3e57b2018-01-25 20:54:46 -0700114 if (parameters.hasBaseCongestionMarkingInterval()) {
115 faceParams.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
116 }
117 if (parameters.hasDefaultCongestionThreshold()) {
118 faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
119 }
Eric Newberry812d6152018-06-06 15:06:01 -0700120 if (parameters.hasMtu()) {
121 faceParams.mtu = parameters.getMtu();
122 }
Davide Pesavento15b55052018-01-27 19:09:28 -0500123 faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
124 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
125 faceParams.wantLpReliability = parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) &&
126 parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
Eric Newberry0c3e57b2018-01-25 20:54:46 -0700127 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
128 faceParams.wantCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
129 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700130 try {
Davide Pesavento15b55052018-01-27 19:09:28 -0500131 factory->createFace({remoteUri, localUri, faceParams},
Davide Pesavento28181322018-11-08 16:44:50 -0500132 [this, parameters, done] (const auto& face) {
133 this->afterCreateFaceSuccess(face, parameters, done);
134 },
135 [done] (uint32_t status, const std::string& reason) {
136 NFD_LOG_DEBUG("Face creation failed: " << reason);
137 done(ControlResponse(status, reason));
138 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700139 }
140 catch (const std::runtime_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700141 NFD_LOG_ERROR("Face creation failed: " << error.what());
142 done(ControlResponse(500, "Face creation failed due to internal error"));
143 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700144 }
145 catch (const std::logic_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700146 NFD_LOG_ERROR("Face creation failed: " << error.what());
147 done(ControlResponse(500, "Face creation failed due to internal error"));
148 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700149 }
150}
151
Davide Pesavento28181322018-11-08 16:44:50 -0500152template<typename T>
153static void
154copyMtu(const Face& face, T& to)
155{
156 auto transport = face.getTransport();
157 BOOST_ASSERT(transport != nullptr);
158
159 if (transport->getMtu() > 0) {
160 to.setMtu(std::min(static_cast<size_t>(transport->getMtu()), ndn::MAX_NDN_PACKET_SIZE));
161 }
162 else if (transport->getMtu() == face::MTU_UNLIMITED) {
163 to.setMtu(ndn::MAX_NDN_PACKET_SIZE);
164 }
165}
166
167static ControlParameters
168makeUpdateFaceResponse(const Face& face)
169{
170 ControlParameters params;
171 params.setFaceId(face.getId())
172 .setFacePersistency(face.getPersistency());
173
174 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
175 if (linkService != nullptr) {
176 const auto& options = linkService->getOptions();
177 params.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
178 .setDefaultCongestionThreshold(options.defaultCongestionThreshold)
179 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false)
180 .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled, false)
181 .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking, false);
182 }
183
184 return params;
185}
186
187static ControlParameters
188makeCreateFaceResponse(const Face& face)
189{
190 ControlParameters params = makeUpdateFaceResponse(face);
191 params.setUri(face.getRemoteUri().toString())
192 .setLocalUri(face.getLocalUri().toString());
193
194 copyMtu(face, params);
195
196 return params;
197}
198
Yanbiao Li73860e32015-08-19 16:30:16 -0700199void
Davide Pesavento28181322018-11-08 16:44:50 -0500200FaceManager::afterCreateFaceSuccess(const shared_ptr<Face>& face,
201 const ControlParameters& parameters,
Yanbiao Li73860e32015-08-19 16:30:16 -0700202 const ndn::mgmt::CommandContinuation& done)
203{
Davide Pesavento28181322018-11-08 16:44:50 -0500204 if (face->getId() != face::INVALID_FACEID) { // Face already exists
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000205 NFD_LOG_TRACE("Attempted to create duplicate face of " << face->getId());
Davide Pesavento28181322018-11-08 16:44:50 -0500206 ControlParameters response = makeCreateFaceResponse(*face);
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000207 done(ControlResponse(409, "Face with remote URI already exists").setBody(response.wireEncode()));
208 return;
209 }
210
Eric Newberryf40551a2016-09-05 15:41:16 -0700211 // If scope non-local and flags set to enable local fields, request shouldn't
212 // have made it this far
213 BOOST_ASSERT(face->getScope() == ndn::nfd::FACE_SCOPE_LOCAL ||
214 !parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ||
215 (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
216 !parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)));
217
218 m_faceTable.add(face);
219
Davide Pesavento28181322018-11-08 16:44:50 -0500220 ControlParameters response = makeCreateFaceResponse(*face);
Eric Newberry42602412016-08-27 09:33:18 -0700221 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
222}
223
Davide Pesavento28181322018-11-08 16:44:50 -0500224static void
225updateLinkServiceOptions(Face& face, const ControlParameters& parameters)
Eric Newberry42602412016-08-27 09:33:18 -0700226{
Davide Pesavento28181322018-11-08 16:44:50 -0500227 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
228 if (linkService == nullptr) {
229 return;
230 }
231 auto options = linkService->getOptions();
Eric Newberry42602412016-08-27 09:33:18 -0700232
Davide Pesavento28181322018-11-08 16:44:50 -0500233 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
234 face.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
235 options.allowLocalFields = parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
236 }
237 if (parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
238 options.reliabilityOptions.isEnabled = parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
239 }
240 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
241 options.allowCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
242 }
243 if (parameters.hasBaseCongestionMarkingInterval()) {
244 options.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
245 }
246 if (parameters.hasDefaultCongestionThreshold()) {
247 options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
248 }
249
250 linkService->setOptions(options);
Yanbiao Li73860e32015-08-19 16:30:16 -0700251}
252
253void
Davide Pesavento28181322018-11-08 16:44:50 -0500254FaceManager::updateFace(const Interest& interest,
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700255 const ControlParameters& parameters,
256 const ndn::mgmt::CommandContinuation& done)
257{
258 FaceId faceId = parameters.getFaceId();
Davide Pesavento28181322018-11-08 16:44:50 -0500259 if (faceId == 0) { // Self-update
260 auto incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700261 if (incomingFaceIdTag == nullptr) {
262 NFD_LOG_TRACE("unable to determine face for self-update");
263 done(ControlResponse(404, "No FaceId specified and IncomingFaceId not available"));
264 return;
265 }
266 faceId = *incomingFaceIdTag;
267 }
268
269 Face* face = m_faceTable.get(faceId);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700270 if (face == nullptr) {
271 NFD_LOG_TRACE("invalid face specified");
272 done(ControlResponse(404, "Specified face does not exist"));
273 return;
274 }
275
276 // Verify validity of requested changes
277 ControlParameters response;
278 bool areParamsValid = true;
279
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700280 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
281 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
282 face->getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
283 NFD_LOG_TRACE("received request to enable local fields on non-local face");
284 areParamsValid = false;
285 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
286 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
287 }
288
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000289 // check whether the requested FacePersistency change is valid if it's present
290 if (parameters.hasFacePersistency()) {
291 auto persistency = parameters.getFacePersistency();
292 if (!face->getTransport()->canChangePersistencyTo(persistency)) {
293 NFD_LOG_TRACE("cannot change face persistency to " << persistency);
294 areParamsValid = false;
295 response.setFacePersistency(persistency);
296 }
297 }
298
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700299 if (!areParamsValid) {
300 done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
301 return;
302 }
303
304 // All specified properties are valid, so make changes
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000305 if (parameters.hasFacePersistency()) {
306 face->setPersistency(parameters.getFacePersistency());
307 }
Davide Pesavento28181322018-11-08 16:44:50 -0500308 updateLinkServiceOptions(*face, parameters);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700309
Davide Pesavento28181322018-11-08 16:44:50 -0500310 // Prepare and send ControlResponse
311 response = makeUpdateFaceResponse(*face);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700312 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
313}
314
315void
Davide Pesavento28181322018-11-08 16:44:50 -0500316FaceManager::destroyFace(const ControlParameters& parameters,
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700317 const ndn::mgmt::CommandContinuation& done)
318{
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000319 Face* face = m_faceTable.get(parameters.getFaceId());
320 if (face != nullptr) {
321 face->close();
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700322 }
323
324 done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
325}
326
Davide Pesavento28181322018-11-08 16:44:50 -0500327template<typename T>
328static void
329copyFaceProperties(const Face& face, T& to)
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700330{
Davide Pesavento28181322018-11-08 16:44:50 -0500331 to.setFaceId(face.getId())
332 .setRemoteUri(face.getRemoteUri().toString())
333 .setLocalUri(face.getLocalUri().toString())
334 .setFaceScope(face.getScope())
335 .setFacePersistency(face.getPersistency())
336 .setLinkType(face.getLinkType());
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700337
Davide Pesavento28181322018-11-08 16:44:50 -0500338 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
339 if (linkService != nullptr) {
340 const auto& options = linkService->getOptions();
341 to.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields)
342 .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled)
343 .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700344 }
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700345}
346
Davide Pesavento28181322018-11-08 16:44:50 -0500347static ndn::nfd::FaceStatus
348makeFaceStatus(const Face& face, const time::steady_clock::TimePoint& now)
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000349{
Davide Pesavento28181322018-11-08 16:44:50 -0500350 ndn::nfd::FaceStatus status;
351 copyFaceProperties(face, status);
352
353 auto expirationTime = face.getExpirationTime();
354 if (expirationTime != time::steady_clock::TimePoint::max()) {
355 status.setExpirationPeriod(std::max(0_ms,
356 time::duration_cast<time::milliseconds>(expirationTime - now)));
357 }
358
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000359 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
Davide Pesavento28181322018-11-08 16:44:50 -0500360 if (linkService != nullptr) {
361 const auto& options = linkService->getOptions();
362 status.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
363 .setDefaultCongestionThreshold(options.defaultCongestionThreshold);
Eric Newberry812d6152018-06-06 15:06:01 -0700364 }
365
Davide Pesavento28181322018-11-08 16:44:50 -0500366 copyMtu(face, status);
367
368 const auto& counters = face.getCounters();
369 status.setNInInterests(counters.nInInterests)
370 .setNOutInterests(counters.nOutInterests)
371 .setNInData(counters.nInData)
372 .setNOutData(counters.nOutData)
373 .setNInNacks(counters.nInNacks)
374 .setNOutNacks(counters.nOutNacks)
375 .setNInBytes(counters.nInBytes)
376 .setNOutBytes(counters.nOutBytes);
377
378 return status;
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000379}
380
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700381void
Davide Pesavento28181322018-11-08 16:44:50 -0500382FaceManager::listFaces(ndn::mgmt::StatusDatasetContext& context)
Yanbiao Li73860e32015-08-19 16:30:16 -0700383{
Eric Newberryc64d30a2015-12-26 11:07:27 -0700384 auto now = time::steady_clock::now();
Davide Pesavento28181322018-11-08 16:44:50 -0500385 for (const auto& face : m_faceTable) {
386 ndn::nfd::FaceStatus status = makeFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700387 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700388 }
389 context.end();
390}
391
392void
Davide Pesavento28181322018-11-08 16:44:50 -0500393FaceManager::listChannels(ndn::mgmt::StatusDatasetContext& context)
Yanbiao Li73860e32015-08-19 16:30:16 -0700394{
Davide Pesavento28181322018-11-08 16:44:50 -0500395 auto factories = m_faceSystem.listProtocolFactories();
Davide Pesaventoe5eebad2017-04-06 20:23:26 -0400396 for (const auto* factory : factories) {
Junxiao Shib8590312016-12-29 21:22:25 +0000397 for (const auto& channel : factory->getChannels()) {
398 ndn::nfd::ChannelStatus entry;
399 entry.setLocalUri(channel->getUri().toString());
400 context.append(entry.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700401 }
402 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700403 context.end();
404}
405
Davide Pesavento28181322018-11-08 16:44:50 -0500406static bool
407matchFilter(const ndn::nfd::FaceQueryFilter& filter, const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700408{
409 if (filter.hasFaceId() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000410 filter.getFaceId() != static_cast<uint64_t>(face.getId())) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700411 return false;
412 }
413
414 if (filter.hasUriScheme() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000415 filter.getUriScheme() != face.getRemoteUri().getScheme() &&
416 filter.getUriScheme() != face.getLocalUri().getScheme()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700417 return false;
418 }
419
420 if (filter.hasRemoteUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000421 filter.getRemoteUri() != face.getRemoteUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700422 return false;
423 }
424
425 if (filter.hasLocalUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000426 filter.getLocalUri() != face.getLocalUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700427 return false;
428 }
429
430 if (filter.hasFaceScope() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000431 filter.getFaceScope() != face.getScope()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700432 return false;
433 }
434
435 if (filter.hasFacePersistency() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000436 filter.getFacePersistency() != face.getPersistency()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700437 return false;
438 }
439
440 if (filter.hasLinkType() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000441 filter.getLinkType() != face.getLinkType()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700442 return false;
443 }
444
445 return true;
446}
447
Junxiao Shicde37ad2015-12-24 01:02:05 -0700448void
Davide Pesavento28181322018-11-08 16:44:50 -0500449FaceManager::queryFaces(const Interest& interest,
450 ndn::mgmt::StatusDatasetContext& context)
Junxiao Shida93f1f2015-11-11 06:13:16 -0700451{
Davide Pesavento28181322018-11-08 16:44:50 -0500452 ndn::nfd::FaceQueryFilter faceFilter;
453 try {
454 faceFilter.wireDecode(interest.getName()[-1].blockFromValue());
Eric Newberry1b4ba052016-10-07 23:04:07 -0700455 }
Davide Pesavento28181322018-11-08 16:44:50 -0500456 catch (const tlv::Error& e) {
457 NFD_LOG_DEBUG("Malformed query filter: " << e.what());
458 return context.reject(ControlResponse(400, "Malformed filter"));
459 }
460
461 auto now = time::steady_clock::now();
462 for (const auto& face : m_faceTable) {
463 if (matchFilter(faceFilter, face)) {
464 ndn::nfd::FaceStatus status = makeFaceStatus(face, now);
465 context.append(status.wireEncode());
466 }
467 }
468 context.end();
Junxiao Shida93f1f2015-11-11 06:13:16 -0700469}
470
471void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700472FaceManager::notifyFaceEvent(const Face& face, ndn::nfd::FaceEventKind kind)
Yanbiao Li73860e32015-08-19 16:30:16 -0700473{
474 ndn::nfd::FaceEventNotification notification;
Eric Newberry1b4ba052016-10-07 23:04:07 -0700475 notification.setKind(kind);
Davide Pesavento28181322018-11-08 16:44:50 -0500476 copyFaceProperties(face, notification);
Yanbiao Li73860e32015-08-19 16:30:16 -0700477
Junxiao Shiae04d342016-07-19 13:20:22 +0000478 m_postNotification(notification.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700479}
480
481void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700482FaceManager::connectFaceStateChangeSignal(const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700483{
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400484 using face::FaceState;
485
Eric Newberry1b4ba052016-10-07 23:04:07 -0700486 FaceId faceId = face.getId();
487 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400488 [this, faceId, &face] (FaceState oldState, FaceState newState) {
489 if (newState == FaceState::UP) {
Eric Newberry1b4ba052016-10-07 23:04:07 -0700490 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
491 }
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400492 else if (newState == FaceState::DOWN) {
Eric Newberry1b4ba052016-10-07 23:04:07 -0700493 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
494 }
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400495 else if (newState == FaceState::CLOSED) {
496 // cannot use face.getId() because it may already be reset to INVALID_FACEID
Eric Newberry1b4ba052016-10-07 23:04:07 -0700497 m_faceStateChangeConn.erase(faceId);
498 }
499 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700500}
501
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200502} // namespace nfd