blob: 9be7c9431d8743b70fae47116dc1a8cc60a4db2c [file] [log] [blame]
Yanbiao Li73860e32015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi38b24c72017-01-05 02:59:31 +00003 * Copyright (c) 2014-2017, 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"
Junxiao Shi40cb61c2015-09-23 18:36:45 -070027#include "face/generic-link-service.hpp"
Junxiao Shib8590312016-12-29 21:22:25 +000028#include "face/protocol-factory.hpp"
Yukai Tu0a49d342015-09-13 12:54:22 +080029#include "fw/face-table.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070030
Junxiao Shicbc8e942016-09-06 03:17:45 +000031#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi25c6ce42016-09-09 13:49:59 +000032#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
Yanbiao Li73860e32015-08-19 16:30:16 -070033
Yanbiao Li73860e32015-08-19 16:30:16 -070034namespace nfd {
35
36NFD_LOG_INIT("FaceManager");
37
Junxiao Shiea47bde2017-01-26 17:49:16 +000038FaceManager::FaceManager(FaceSystem& faceSystem,
39 Dispatcher& dispatcher, CommandAuthenticator& authenticator)
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000040 : NfdManagerBase(dispatcher, authenticator, "faces")
Junxiao Shiea47bde2017-01-26 17:49:16 +000041 , m_faceSystem(faceSystem)
42 , m_faceTable(faceSystem.getFaceTable())
Yanbiao Li73860e32015-08-19 16:30:16 -070043{
Yanbiao Li58ba3f92017-02-15 14:27:18 +000044 // register handlers for ControlCommand
Yanbiao Li73860e32015-08-19 16:30:16 -070045 registerCommandHandler<ndn::nfd::FaceCreateCommand>("create",
46 bind(&FaceManager::createFace, this, _2, _3, _4, _5));
47
Eric Newberryb5aa7f52016-09-03 20:36:12 -070048 registerCommandHandler<ndn::nfd::FaceUpdateCommand>("update",
49 bind(&FaceManager::updateFace, this, _2, _3, _4, _5));
50
Yanbiao Li73860e32015-08-19 16:30:16 -070051 registerCommandHandler<ndn::nfd::FaceDestroyCommand>("destroy",
52 bind(&FaceManager::destroyFace, this, _2, _3, _4, _5));
53
Yanbiao Li58ba3f92017-02-15 14:27:18 +000054 // register handlers for StatusDataset
Yanbiao Li73860e32015-08-19 16:30:16 -070055 registerStatusDatasetHandler("list", bind(&FaceManager::listFaces, this, _1, _2, _3));
56 registerStatusDatasetHandler("channels", bind(&FaceManager::listChannels, this, _1, _2, _3));
57 registerStatusDatasetHandler("query", bind(&FaceManager::queryFaces, this, _1, _2, _3));
58
Yanbiao Li58ba3f92017-02-15 14:27:18 +000059 // register notification stream
Junxiao Shiae04d342016-07-19 13:20:22 +000060 m_postNotification = registerNotificationStream("events");
Eric Newberry1b4ba052016-10-07 23:04:07 -070061 m_faceAddConn = m_faceTable.afterAdd.connect([this] (const Face& face) {
62 connectFaceStateChangeSignal(face);
63 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
64 });
65 m_faceRemoveConn = m_faceTable.beforeRemove.connect([this] (const Face& face) {
66 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
67 });
Yanbiao Li73860e32015-08-19 16:30:16 -070068}
69
70void
71FaceManager::setConfigFile(ConfigFile& configFile)
72{
Junxiao Shib8590312016-12-29 21:22:25 +000073 m_faceSystem.setConfigFile(configFile);
Yanbiao Li73860e32015-08-19 16:30:16 -070074}
75
76void
77FaceManager::createFace(const Name& topPrefix, const Interest& interest,
78 const ControlParameters& parameters,
79 const ndn::mgmt::CommandContinuation& done)
80{
81 FaceUri uri;
82 if (!uri.parse(parameters.getUri())) {
83 NFD_LOG_TRACE("failed to parse URI");
Eric Newberry42602412016-08-27 09:33:18 -070084 done(ControlResponse(400, "Malformed command"));
85 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070086 }
87
88 if (!uri.isCanonical()) {
89 NFD_LOG_TRACE("received non-canonical URI");
Eric Newberry42602412016-08-27 09:33:18 -070090 done(ControlResponse(400, "Non-canonical URI"));
91 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070092 }
93
Junxiao Shi38b24c72017-01-05 02:59:31 +000094 ProtocolFactory* factory = m_faceSystem.getFactoryByScheme(uri.getScheme());
Junxiao Shib8590312016-12-29 21:22:25 +000095 if (factory == nullptr) {
Eric Newberry42602412016-08-27 09:33:18 -070096 NFD_LOG_TRACE("received create request for unsupported protocol");
97 done(ControlResponse(406, "Unsupported protocol"));
98 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070099 }
100
101 try {
Junxiao Shib8590312016-12-29 21:22:25 +0000102 factory->createFace(uri,
103 parameters.getFacePersistency(),
104 parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
105 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED),
106 bind(&FaceManager::afterCreateFaceSuccess, this, parameters, _1, done),
107 bind(&FaceManager::afterCreateFaceFailure, this, _1, _2, done));
Yanbiao Li73860e32015-08-19 16:30:16 -0700108 }
109 catch (const std::runtime_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700110 NFD_LOG_ERROR("Face creation failed: " << error.what());
111 done(ControlResponse(500, "Face creation failed due to internal error"));
112 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700113 }
114 catch (const std::logic_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700115 NFD_LOG_ERROR("Face creation failed: " << error.what());
116 done(ControlResponse(500, "Face creation failed due to internal error"));
117 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700118 }
119}
120
121void
Eric Newberry42602412016-08-27 09:33:18 -0700122FaceManager::afterCreateFaceSuccess(const ControlParameters& parameters,
Eric Newberryf40551a2016-09-05 15:41:16 -0700123 const shared_ptr<Face>& face,
Yanbiao Li73860e32015-08-19 16:30:16 -0700124 const ndn::mgmt::CommandContinuation& done)
125{
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000126 if (face->getId() != face::INVALID_FACEID) {// Face already exists
127 NFD_LOG_TRACE("Attempted to create duplicate face of " << face->getId());
128
129 ControlParameters response = collectFaceProperties(*face);
130 response.setUri(face->getRemoteUri().toString());
131 done(ControlResponse(409, "Face with remote URI already exists").setBody(response.wireEncode()));
132 return;
133 }
134
Eric Newberryf40551a2016-09-05 15:41:16 -0700135 // If scope non-local and flags set to enable local fields, request shouldn't
136 // have made it this far
137 BOOST_ASSERT(face->getScope() == ndn::nfd::FACE_SCOPE_LOCAL ||
138 !parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ||
139 (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
140 !parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)));
141
142 m_faceTable.add(face);
143
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000144 ControlParameters response = collectFaceProperties(*face);
Eric Newberry42602412016-08-27 09:33:18 -0700145 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
146}
147
148void
149FaceManager::afterCreateFaceFailure(uint32_t status,
150 const std::string& reason,
151 const ndn::mgmt::CommandContinuation& done)
152{
153 NFD_LOG_DEBUG("Face creation failed: " << reason);
154
155 done(ControlResponse(status, reason));
Yanbiao Li73860e32015-08-19 16:30:16 -0700156}
157
158void
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700159FaceManager::updateFace(const Name& topPrefix, const Interest& interest,
160 const ControlParameters& parameters,
161 const ndn::mgmt::CommandContinuation& done)
162{
163 FaceId faceId = parameters.getFaceId();
164 if (faceId == 0) {
165 // Self-updating
166 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
167 if (incomingFaceIdTag == nullptr) {
168 NFD_LOG_TRACE("unable to determine face for self-update");
169 done(ControlResponse(404, "No FaceId specified and IncomingFaceId not available"));
170 return;
171 }
172 faceId = *incomingFaceIdTag;
173 }
174
175 Face* face = m_faceTable.get(faceId);
176
177 if (face == nullptr) {
178 NFD_LOG_TRACE("invalid face specified");
179 done(ControlResponse(404, "Specified face does not exist"));
180 return;
181 }
182
183 // Verify validity of requested changes
184 ControlParameters response;
185 bool areParamsValid = true;
186
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700187 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
188 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
189 face->getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
190 NFD_LOG_TRACE("received request to enable local fields on non-local face");
191 areParamsValid = false;
192 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
193 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
194 }
195
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000196 // check whether the requested FacePersistency change is valid if it's present
197 if (parameters.hasFacePersistency()) {
198 auto persistency = parameters.getFacePersistency();
199 if (!face->getTransport()->canChangePersistencyTo(persistency)) {
200 NFD_LOG_TRACE("cannot change face persistency to " << persistency);
201 areParamsValid = false;
202 response.setFacePersistency(persistency);
203 }
204 }
205
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700206 if (!areParamsValid) {
207 done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
208 return;
209 }
210
211 // All specified properties are valid, so make changes
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000212 if (parameters.hasFacePersistency()) {
213 face->setPersistency(parameters.getFacePersistency());
214 }
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700215 setLinkServiceOptions(*face, parameters, response);
216
Eric Newberryf40551a2016-09-05 15:41:16 -0700217 // Set ControlResponse fields
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000218 response = collectFaceProperties(*face);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700219
220 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
221}
222
223void
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700224FaceManager::destroyFace(const Name& topPrefix, const Interest& interest,
225 const ControlParameters& parameters,
226 const ndn::mgmt::CommandContinuation& done)
227{
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000228 Face* face = m_faceTable.get(parameters.getFaceId());
229 if (face != nullptr) {
230 face->close();
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700231 }
232
233 done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
234}
235
236void
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700237FaceManager::setLinkServiceOptions(Face& face,
238 const ControlParameters& parameters,
239 ControlParameters& response)
240{
241 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
242 BOOST_ASSERT(linkService != nullptr);
243
244 auto options = linkService->getOptions();
245 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
246 face.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
247 options.allowLocalFields = parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
248 }
249 linkService->setOptions(options);
250
251 // Set Flags for ControlResponse
252 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false);
253}
254
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000255ControlParameters
256FaceManager::collectFaceProperties(const Face& face)
257{
258 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
259 BOOST_ASSERT(linkService != nullptr);
260 auto options = linkService->getOptions();
261
262 return ControlParameters()
263 .setFaceId(face.getId())
264 .setFacePersistency(face.getPersistency())
265 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false);
266}
267
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700268void
Yanbiao Li73860e32015-08-19 16:30:16 -0700269FaceManager::listFaces(const Name& topPrefix, const Interest& interest,
270 ndn::mgmt::StatusDatasetContext& context)
271{
Eric Newberryc64d30a2015-12-26 11:07:27 -0700272 auto now = time::steady_clock::now();
Junxiao Shib84e6742016-07-19 13:16:22 +0000273 for (const Face& face : m_faceTable) {
274 ndn::nfd::FaceStatus status = collectFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700275 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700276 }
277 context.end();
278}
279
280void
281FaceManager::listChannels(const Name& topPrefix, const Interest& interest,
282 ndn::mgmt::StatusDatasetContext& context)
283{
Junxiao Shib8590312016-12-29 21:22:25 +0000284 std::set<const ProtocolFactory*> factories = m_faceSystem.listProtocolFactories();
285 for (const ProtocolFactory* factory : factories) {
286 for (const auto& channel : factory->getChannels()) {
287 ndn::nfd::ChannelStatus entry;
288 entry.setLocalUri(channel->getUri().toString());
289 context.append(entry.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700290 }
291 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700292 context.end();
293}
294
295void
296FaceManager::queryFaces(const Name& topPrefix, const Interest& interest,
297 ndn::mgmt::StatusDatasetContext& context)
298{
299 ndn::nfd::FaceQueryFilter faceFilter;
300 const Name& query = interest.getName();
301 try {
302 faceFilter.wireDecode(query[-1].blockFromValue());
303 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200304 catch (const tlv::Error& e) {
305 NFD_LOG_DEBUG("Malformed query filter: " << e.what());
306 return context.reject(ControlResponse(400, "Malformed filter"));
Yanbiao Li73860e32015-08-19 16:30:16 -0700307 }
308
Eric Newberryc64d30a2015-12-26 11:07:27 -0700309 auto now = time::steady_clock::now();
Junxiao Shib84e6742016-07-19 13:16:22 +0000310 for (const Face& face : m_faceTable) {
311 if (!matchFilter(faceFilter, face)) {
Junxiao Shida93f1f2015-11-11 06:13:16 -0700312 continue;
Yanbiao Li73860e32015-08-19 16:30:16 -0700313 }
Junxiao Shib84e6742016-07-19 13:16:22 +0000314 ndn::nfd::FaceStatus status = collectFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700315 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700316 }
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200317
Yanbiao Li73860e32015-08-19 16:30:16 -0700318 context.end();
319}
320
321bool
Junxiao Shib84e6742016-07-19 13:16:22 +0000322FaceManager::matchFilter(const ndn::nfd::FaceQueryFilter& filter, const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700323{
324 if (filter.hasFaceId() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000325 filter.getFaceId() != static_cast<uint64_t>(face.getId())) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700326 return false;
327 }
328
329 if (filter.hasUriScheme() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000330 filter.getUriScheme() != face.getRemoteUri().getScheme() &&
331 filter.getUriScheme() != face.getLocalUri().getScheme()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700332 return false;
333 }
334
335 if (filter.hasRemoteUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000336 filter.getRemoteUri() != face.getRemoteUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700337 return false;
338 }
339
340 if (filter.hasLocalUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000341 filter.getLocalUri() != face.getLocalUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700342 return false;
343 }
344
345 if (filter.hasFaceScope() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000346 filter.getFaceScope() != face.getScope()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700347 return false;
348 }
349
350 if (filter.hasFacePersistency() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000351 filter.getFacePersistency() != face.getPersistency()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700352 return false;
353 }
354
355 if (filter.hasLinkType() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000356 filter.getLinkType() != face.getLinkType()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700357 return false;
358 }
359
360 return true;
361}
362
Eric Newberryc64d30a2015-12-26 11:07:27 -0700363ndn::nfd::FaceStatus
364FaceManager::collectFaceStatus(const Face& face, const time::steady_clock::TimePoint& now)
365{
366 ndn::nfd::FaceStatus status;
367
368 collectFaceProperties(face, status);
369
370 time::steady_clock::TimePoint expirationTime = face.getExpirationTime();
371 if (expirationTime != time::steady_clock::TimePoint::max()) {
372 status.setExpirationPeriod(std::max(time::milliseconds(0),
373 time::duration_cast<time::milliseconds>(expirationTime - now)));
374 }
375
376 const face::FaceCounters& counters = face.getCounters();
377 status.setNInInterests(counters.nInInterests)
378 .setNOutInterests(counters.nOutInterests)
379 .setNInDatas(counters.nInData)
380 .setNOutDatas(counters.nOutData)
381 .setNInNacks(counters.nInNacks)
382 .setNOutNacks(counters.nOutNacks)
383 .setNInBytes(counters.nInBytes)
384 .setNOutBytes(counters.nOutBytes);
385
386 return status;
387}
388
Junxiao Shida93f1f2015-11-11 06:13:16 -0700389template<typename FaceTraits>
Junxiao Shicde37ad2015-12-24 01:02:05 -0700390void
391FaceManager::collectFaceProperties(const Face& face, FaceTraits& traits)
Junxiao Shida93f1f2015-11-11 06:13:16 -0700392{
393 traits.setFaceId(face.getId())
394 .setRemoteUri(face.getRemoteUri().toString())
395 .setLocalUri(face.getLocalUri().toString())
396 .setFaceScope(face.getScope())
397 .setFacePersistency(face.getPersistency())
398 .setLinkType(face.getLinkType());
Eric Newberry1b4ba052016-10-07 23:04:07 -0700399
400 // Set Flag bits
401 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
402 if (linkService != nullptr) {
403 auto linkServiceOptions = linkService->getOptions();
404 traits.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, linkServiceOptions.allowLocalFields);
405 }
Junxiao Shida93f1f2015-11-11 06:13:16 -0700406}
407
408void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700409FaceManager::notifyFaceEvent(const Face& face, ndn::nfd::FaceEventKind kind)
Yanbiao Li73860e32015-08-19 16:30:16 -0700410{
411 ndn::nfd::FaceEventNotification notification;
Eric Newberry1b4ba052016-10-07 23:04:07 -0700412 notification.setKind(kind);
Junxiao Shiae04d342016-07-19 13:20:22 +0000413 collectFaceProperties(face, notification);
Yanbiao Li73860e32015-08-19 16:30:16 -0700414
Junxiao Shiae04d342016-07-19 13:20:22 +0000415 m_postNotification(notification.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700416}
417
418void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700419FaceManager::connectFaceStateChangeSignal(const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700420{
Eric Newberry1b4ba052016-10-07 23:04:07 -0700421 FaceId faceId = face.getId();
422 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
423 [this, faceId] (face::FaceState oldState, face::FaceState newState) {
424 const Face& face = *m_faceTable.get(faceId);
Yanbiao Li73860e32015-08-19 16:30:16 -0700425
Eric Newberry1b4ba052016-10-07 23:04:07 -0700426 if (newState == face::FaceState::UP) {
427 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
428 }
429 else if (newState == face::FaceState::DOWN) {
430 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
431 }
432 else if (newState == face::FaceState::CLOSED) {
433 m_faceStateChangeConn.erase(faceId);
434 }
435 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700436}
437
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200438} // namespace nfd