43 #include <ndn-cxx/management/nfd-channel-status.hpp> 44 #include <ndn-cxx/management/nfd-face-status.hpp> 45 #include <ndn-cxx/management/nfd-face-event-notification.hpp> 47 #ifdef HAVE_UNIX_SOCKETS 49 #endif // HAVE_UNIX_SOCKETS 54 #endif // HAVE_LIBPCAP 58 #endif // HAVE_WEBSOCKET 68 , m_faceTable(faceTable)
70 registerCommandHandler<ndn::nfd::FaceCreateCommand>(
"create",
71 bind(&FaceManager::createFace,
this, _2, _3, _4, _5));
73 registerCommandHandler<ndn::nfd::FaceDestroyCommand>(
"destroy",
74 bind(&FaceManager::destroyFace,
this, _2, _3, _4, _5));
76 registerCommandHandler<ndn::nfd::FaceEnableLocalControlCommand>(
"enable-local-control",
77 bind(&FaceManager::enableLocalControl,
this, _2, _3, _4, _5));
79 registerCommandHandler<ndn::nfd::FaceDisableLocalControlCommand>(
"disable-local-control",
80 bind(&FaceManager::disableLocalControl,
this, _2, _3, _4, _5));
88 m_faceTable.
afterAdd.connect(bind(&FaceManager::afterFaceAdded,
this, _1, postNotification));
90 m_faceTable.
beforeRemove.connect(bind(&FaceManager::afterFaceRemoved,
this, _1, postNotification));
96 configFile.
addSectionHandler(
"face_system", bind(&FaceManager::processConfig,
this, _1, _2, _3));
100 FaceManager::createFace(
const Name& topPrefix,
const Interest& interest,
115 auto factory = m_factories.find(uri.
getScheme());
116 if (factory == m_factories.end()) {
121 factory->second->createFace(uri,
123 bind(&FaceManager::afterCreateFaceSuccess,
124 this, parameters, _1, done),
125 bind(&FaceManager::afterCreateFaceFailure,
128 catch (
const std::runtime_error& error) {
129 std::string errorMessage =
"Face creation failed: ";
130 errorMessage += error.what();
135 catch (
const std::logic_error& error) {
136 std::string errorMessage =
"Face creation failed: ";
137 errorMessage += error.what();
146 const shared_ptr<Face>& newFace,
149 m_faceTable.
add(newFace);
151 parameters.
setUri(newFace->getRemoteUri().toString());
158 FaceManager::destroyFace(
const Name& topPrefix,
const Interest& interest,
162 shared_ptr<Face> target = m_faceTable.
get(parameters.
getFaceId());
171 FaceManager::afterCreateFaceFailure(
const std::string& reason,
180 FaceManager::enableLocalControl(
const Name& topPrefix,
const Interest& interest,
184 Face*
face = findFaceForLocalControl(interest, parameters, done);
192 if (service ==
nullptr) {
198 service->setOptions(options);
200 return done(
ControlResponse(200,
"OK: enable all local fields on GenericLinkService")
205 FaceManager::disableLocalControl(
const Name& topPrefix,
const Interest& interest,
209 Face*
face = findFaceForLocalControl(interest, parameters, done);
217 if (service ==
nullptr) {
223 service->setOptions(options);
225 return done(
ControlResponse(200,
"OK: disable all local fields on GenericLinkService")
230 FaceManager::findFaceForLocalControl(
const Interest& request,
238 BOOST_ASSERT(incomingFaceIdTag !=
nullptr);
240 auto face = m_faceTable.
get(*incomingFaceIdTag);
241 if (
face ==
nullptr) {
242 NFD_LOG_DEBUG(
"FaceId " << *incomingFaceIdTag <<
" not found");
248 NFD_LOG_DEBUG(
"Cannot enable local control on non-local FaceId " <<
face->getId());
257 FaceManager::listFaces(
const Name& topPrefix,
const Interest& interest,
261 for (
const auto&
face : m_faceTable) {
269 FaceManager::listChannels(
const Name& topPrefix,
const Interest& interest,
272 std::set<const ProtocolFactory*> seenFactories;
274 for (
const auto& kv : m_factories) {
277 std::tie(std::ignore, inserted) = seenFactories.insert(factory);
280 for (
const auto& channel : factory->
getChannels()) {
292 FaceManager::queryFaces(
const Name& topPrefix,
const Interest& interest,
298 faceFilter.
wireDecode(query[-1].blockFromValue());
306 for (
const auto&
face : m_faceTable) {
307 if (!doesMatchFilter(faceFilter,
face)) {
321 filter.
getFaceId() !=
static_cast<uint64_t
>(face->getId())) {
326 filter.
getUriScheme() != face->getRemoteUri().getScheme() &&
327 filter.
getUriScheme() != face->getLocalUri().getScheme()) {
332 filter.
getRemoteUri() != face->getRemoteUri().toString()) {
337 filter.
getLocalUri() != face->getLocalUri().toString()) {
364 collectFaceProperties(face, status);
367 if (expirationTime != time::steady_clock::TimePoint::max()) {
369 time::duration_cast<time::milliseconds>(expirationTime - now)));
385 template<
typename FaceTraits>
387 FaceManager::collectFaceProperties(
const Face& face, FaceTraits& traits)
390 .setRemoteUri(face.getRemoteUri().toString())
391 .setLocalUri(face.getLocalUri().toString())
392 .setFaceScope(face.getScope())
393 .setFacePersistency(face.getPersistency())
394 .setLinkType(face.getLinkType());
398 FaceManager::afterFaceAdded(shared_ptr<Face> face,
403 collectFaceProperties(*face, notification);
409 FaceManager::afterFaceRemoved(shared_ptr<Face> face,
414 collectFaceProperties(*face, notification);
420 FaceManager::processConfig(
const ConfigSection& configSection,
422 const std::string& filename)
424 bool hasSeenUnix =
false;
425 bool hasSeenTcp =
false;
426 bool hasSeenUdp =
false;
427 bool hasSeenEther =
false;
428 bool hasSeenWebSocket =
false;
431 for (
const auto& item : configSection) {
432 if (item.first ==
"unix") {
434 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"unix\" section"));
438 processSectionUnix(item.second, isDryRun);
440 else if (item.first ==
"tcp") {
442 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"tcp\" section"));
446 processSectionTcp(item.second, isDryRun);
448 else if (item.first ==
"udp") {
450 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"udp\" section"));
454 processSectionUdp(item.second, isDryRun, nicList);
456 else if (item.first ==
"ether") {
458 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"ether\" section"));
462 processSectionEther(item.second, isDryRun, nicList);
464 else if (item.first ==
"websocket") {
465 if (hasSeenWebSocket) {
466 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"websocket\" section"));
468 hasSeenWebSocket =
true;
470 processSectionWebSocket(item.second, isDryRun);
473 BOOST_THROW_EXCEPTION(
Error(
"Unrecognized option \"" + item.first +
"\""));
479 FaceManager::processSectionUnix(
const ConfigSection& configSection,
bool isDryRun)
487 #if defined(HAVE_UNIX_SOCKETS) 488 std::string path =
"/var/run/nfd.sock";
490 for (
const auto& i : configSection) {
491 if (i.first ==
"path") {
492 path = i.second.get_value<std::string>();
496 i.first +
"\" in \"unix\" section"));
501 if (m_factories.count(
"unix") > 0) {
505 auto factory = make_shared<UnixStreamFactory>();
506 m_factories.insert(std::make_pair(
"unix", factory));
508 auto channel = factory->createChannel(path);
509 channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
512 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without Unix sockets support, " 513 "cannot process \"unix\" section"));
514 #endif // HAVE_UNIX_SOCKETS 518 FaceManager::processSectionTcp(
const ConfigSection& configSection,
bool isDryRun)
527 #if defined(HAVE_TCP) 528 uint16_t port = 6363;
529 bool needToListen =
true;
530 bool enableV4 =
true;
531 bool enableV6 =
true;
533 for (
const auto& i : configSection) {
534 if (i.first ==
"port") {
535 port = ConfigFile::parseNumber<uint16_t>(i,
"tcp");
538 else if (i.first ==
"listen") {
541 else if (i.first ==
"enable_v4") {
544 else if (i.first ==
"enable_v6") {
549 i.first +
"\" in \"tcp\" section"));
553 if (!enableV4 && !enableV6) {
554 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 and IPv6 TCP channels have been disabled." 555 " Remove \"tcp\" section to disable TCP channels or" 556 " re-enable at least one channel type."));
560 if (m_factories.count(
"tcp") > 0) {
564 auto factory = make_shared<TcpFactory>();
565 m_factories.insert(std::make_pair(
"tcp", factory));
569 shared_ptr<TcpChannel> v4Channel = factory->createChannel(endpoint);
571 v4Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
574 m_factories.insert(std::make_pair(
"tcp4", factory));
579 shared_ptr<TcpChannel> v6Channel = factory->createChannel(endpoint);
581 v6Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
584 m_factories.insert(std::make_pair(
"tcp6", factory));
588 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without TCP support, cannot process \"tcp\" section"));
593 FaceManager::processSectionUdp(
const ConfigSection& configSection,
bool isDryRun,
594 const std::vector<NetworkInterfaceInfo>& nicList)
609 #if defined(HAVE_UDP) 610 uint16_t port = 6363;
611 bool enableV4 =
true;
612 bool enableV6 =
true;
613 size_t timeout = 600;
614 size_t keepAliveInterval = 25;
615 bool useMcast =
true;
616 auto mcastGroup = boost::asio::ip::address_v4::from_string(
"224.0.23.170");
617 uint16_t mcastPort = 56363;
619 for (
const auto& i : configSection) {
620 if (i.first ==
"port") {
621 port = ConfigFile::parseNumber<uint16_t>(i,
"udp");
624 else if (i.first ==
"enable_v4") {
627 else if (i.first ==
"enable_v6") {
630 else if (i.first ==
"idle_timeout") {
632 timeout = i.second.get_value<
size_t>();
634 catch (
const boost::property_tree::ptree_bad_data&) {
636 i.first +
"\" in \"udp\" section"));
639 else if (i.first ==
"keep_alive_interval") {
641 keepAliveInterval = i.second.get_value<
size_t>();
643 (void)(keepAliveInterval);
645 catch (
const boost::property_tree::ptree_bad_data&) {
647 i.first +
"\" in \"udp\" section"));
650 else if (i.first ==
"mcast") {
653 else if (i.first ==
"mcast_port") {
654 mcastPort = ConfigFile::parseNumber<uint16_t>(i,
"udp");
657 else if (i.first ==
"mcast_group") {
658 boost::system::error_code ec;
659 mcastGroup = boost::asio::ip::address_v4::from_string(i.second.get_value<std::string>(), ec);
662 i.first +
"\" in \"udp\" section"));
668 i.first +
"\" in \"udp\" section"));
672 if (!enableV4 && !enableV6) {
673 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 and IPv6 UDP channels have been disabled." 674 " Remove \"udp\" section to disable UDP channels or" 675 " re-enable at least one channel type."));
677 else if (useMcast && !enableV4) {
678 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 multicast requested, but IPv4 channels" 679 " have been disabled (conflicting configuration options set)"));
683 shared_ptr<UdpFactory> factory;
684 bool isReload =
false;
685 if (m_factories.count(
"udp") > 0) {
687 factory = static_pointer_cast<
UdpFactory>(m_factories[
"udp"]);
690 factory = make_shared<UdpFactory>();
691 m_factories.insert(std::make_pair(
"udp", factory));
694 if (!isReload && enableV4) {
696 shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
697 v4Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
699 m_factories.insert(std::make_pair(
"udp4", factory));
702 if (!isReload && enableV6) {
704 shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
705 v6Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
707 m_factories.insert(std::make_pair(
"udp6", factory));
710 std::set<shared_ptr<Face>> multicastFacesToRemove;
711 for (
const auto& i : factory->getMulticastFaces()) {
712 multicastFacesToRemove.insert(i.second);
715 if (useMcast && enableV4) {
716 std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
717 for (
const auto& nic : nicList) {
718 if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty()) {
719 ipv4MulticastInterfaces.push_back(nic);
723 bool isNicNameNecessary =
false;
724 #if defined(__linux__) 725 if (ipv4MulticastInterfaces.size() > 1) {
728 isNicNameNecessary =
true;
733 for (
const auto& nic : ipv4MulticastInterfaces) {
734 udp::Endpoint localEndpoint(nic.ipv4Addresses[0], mcastPort);
735 auto newFace = factory->createMulticastFace(localEndpoint, mcastEndpoint,
736 isNicNameNecessary ? nic.name :
"");
737 m_faceTable.
add(newFace);
738 multicastFacesToRemove.erase(newFace);
742 for (
const auto& face : multicastFacesToRemove) {
747 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without UDP support, cannot process \"udp\" section"));
752 FaceManager::processSectionEther(
const ConfigSection& configSection,
bool isDryRun,
753 const std::vector<NetworkInterfaceInfo>& nicList)
763 #if defined(HAVE_LIBPCAP) 764 bool useMcast =
true;
767 for (
const auto& i : configSection) {
768 if (i.first ==
"mcast") {
771 else if (i.first ==
"mcast_group") {
773 if (mcastGroup.
isNull()) {
775 i.first +
"\" in \"ether\" section"));
777 NFD_LOG_TRACE(
"Ethernet multicast group set to " << mcastGroup);
781 i.first +
"\" in \"ether\" section"));
786 shared_ptr<EthernetFactory> factory;
787 if (m_factories.count(
"ether") > 0) {
791 factory = make_shared<EthernetFactory>();
792 m_factories.insert(std::make_pair(
"ether", factory));
795 std::set<shared_ptr<Face>> multicastFacesToRemove;
796 for (
const auto& i : factory->getMulticastFaces()) {
797 multicastFacesToRemove.insert(i.second);
801 for (
const auto& nic : nicList) {
802 if (nic.isUp() && nic.isMulticastCapable()) {
804 auto newFace = factory->createMulticastFace(nic, mcastGroup);
805 m_faceTable.
add(newFace);
806 multicastFacesToRemove.erase(newFace);
811 catch (
const face::EthernetTransport::Error& faceError) {
818 for (
const auto& face : multicastFacesToRemove) {
823 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without libpcap, cannot process \"ether\" section"));
824 #endif // HAVE_LIBPCAP 828 FaceManager::processSectionWebSocket(
const ConfigSection& configSection,
bool isDryRun)
839 #if defined(HAVE_WEBSOCKET) 840 uint16_t port = 9696;
841 bool needToListen =
true;
842 bool enableV4 =
true;
843 bool enableV6 =
true;
845 for (
const auto& i : configSection) {
846 if (i.first ==
"port") {
847 port = ConfigFile::parseNumber<uint16_t>(i,
"websocket");
850 else if (i.first ==
"listen") {
853 else if (i.first ==
"enable_v4") {
856 else if (i.first ==
"enable_v6") {
861 i.first +
"\" in \"websocket\" section"));
865 if (!enableV4 && !enableV6) {
866 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 and IPv6 WebSocket channels have been disabled." 867 " Remove \"websocket\" section to disable WebSocket channels or" 868 " re-enable at least one channel type."));
871 if (!enableV4 && enableV6) {
872 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD does not allow pure IPv6 WebSocket channel."));
876 if (m_factories.count(
"websocket") > 0) {
880 auto factory = make_shared<WebSocketFactory>();
881 m_factories.insert(std::make_pair(
"websocket", factory));
883 shared_ptr<WebSocketChannel> channel;
885 if (enableV6 && enableV4) {
887 channel = factory->createChannel(endpoint);
889 m_factories.insert(std::make_pair(
"websocket46", factory));
893 channel = factory->createChannel(endpoint);
895 m_factories.insert(std::make_pair(
"websocket4", factory));
898 if (channel && needToListen) {
904 "cannot process \"websocket\" section"));
905 #endif // HAVE_WEBSOCKET LinkType getLinkType() const
bool hasFaceScope() const
signal::Signal< FaceTable, shared_ptr< Face > > afterAdd
fires after a Face is added
void reject(const ControlResponse &resp=ControlResponse().setCode(400))
declare the non-existence of a response
void setConfigFile(ConfigFile &configFile)
Subscribe to face_system section for the config file.
ControlParameters & setFaceId(uint64_t faceId)
a collection of common functions shared by all NFD managers, such as communicating with the dispatche...
shared_ptr< T > getTag() const
get a tag item
GenericLinkService is a LinkService that implements the NDNLPv2 protocol.
#define NFD_LOG_DEBUG(expression)
bool parse(const std::string &uri)
exception-safe parsing
const std::string & getLocalUri() const
represents parameters in a ControlCommand request or response
std::function< void(const Block ¬ification)> PostNotification
a function to post a notification
bool allowLocalFields
enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy ...
represents a dispatcher on server side of NFD Management protocol
represents an Ethernet hardware address
static Address fromString(const std::string &str)
Creates an Address from a string containing an Ethernet address in hexadecimal notation, with colons or hyphens as separators.
static time_point now() noexcept
FaceStatus & setNInDatas(uint64_t nInDatas)
represents the underlying protocol and address used by a Face
const PacketCounter & nOutNacks
size_t wireEncode(EncodingImpl< TAG > &encoder) const
FaceScope getFaceScope() const
void add(shared_ptr< Face > face)
bool isCanonical() const
determine whether this FaceUri is in canonical form
virtual std::vector< shared_ptr< const Channel > > getChannels() const =0
Address getDefaultMulticastAddress()
Returns the default Ethernet multicast address for NDN.
FaceStatus & setNOutDatas(uint64_t nOutDatas)
represents a Face status change notification
const std::string & getRemoteUri() const
represents an Interest packet
#define NFD_LOG_ERROR(expression)
FaceEventNotification & setKind(FaceEventKind kind)
bool hasRemoteUri() const
FaceStatus & setNOutBytes(uint64_t nOutBytes)
FaceStatus & setNOutInterests(uint64_t nOutInterests)
C & setFaceId(uint64_t faceId)
ControlParameters & setUri(const std::string &uri)
const std::string & getScheme() const
get scheme (protocol)
provides a tag type for simple types
std::vector< NetworkInterfaceInfo > listNetworkInterfaces()
List configured network interfaces on the system and their info.
FaceStatus & setNInInterests(uint64_t nInInterests)
signal::Signal< FaceTable, shared_ptr< Face > > beforeRemove
fires before a Face is removed
FacePersistency getFacePersistency() const
FaceStatus & setNInBytes(uint64_t nInBytes)
size_t wireEncode(EncodingImpl< TAG > &encoder) const
prepend FaceEventNotification to the encoder
ndn::mgmt::ControlResponse ControlResponse
bool hasUriScheme() const
FaceStatus & setNInNacks(uint64_t nInNacks)
Copyright (c) 2011-2015 Regents of the University of California.
void addSectionHandler(const std::string §ionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
uint64_t getFaceId() const
Abstract base class for all protocol factories.
void end()
end the response successfully after appending zero or more blocks
boost::asio::ip::tcp::endpoint Endpoint
const PacketCounter & nOutData
const PacketCounter & nInInterests
FaceStatus & setExpirationPeriod(const time::milliseconds &expirationPeriod)
size_t wireEncode(EncodingImpl< TAG > &encoder) const
prepend FaceStatus to the encoder
boost::property_tree::ptree ConfigSection
Name abstraction to represent an absolute name.
const ByteCounter & nOutBytes
std::function< void(const ControlResponse &resp)> CommandContinuation
a function to be called after ControlCommandHandler completes
represents Face Query Filter
uint64_t getFaceId() const
boost::asio::ip::udp::endpoint Endpoint
const std::string & getUri() const
Options that control the behavior of GenericLinkService.
Exception of EthernetFactory.
const ByteCounter & nInBytes
static bool parseYesNo(const ConfigSection::value_type &option, const std::string §ionName)
parse a config option that can be either "yes" or "no"
#define NFD_LOG_INIT(name)
#define NFD_LOG_TRACE(expression)
ControlParameters & setFacePersistency(FacePersistency persistency)
FaceStatus & setNOutNacks(uint64_t nOutNacks)
void append(const Block &block)
append a Block to the response
represents NFD Channel Status dataset
boost::asio::ip::tcp::endpoint Endpoint
bool isNull() const
True if this is a null address (00:00:00:00:00:00)
ndn::mgmt::PostNotification registerNotificationStream(const std::string &verb)
const std::string & getUriScheme() const
provides a context for generating response to a StatusDataset request
FacePersistency getFacePersistency() const
shared_ptr< Face > get(FaceId id) const
bool hasFacePersistency() const
FaceManager(FaceTable &faceTable, Dispatcher &dispatcher, CommandValidator &validator)
void wireDecode(const Block &wire)
decode FaceQueryFilter
void registerStatusDatasetHandler(const std::string &verb, const ndn::mgmt::StatusDatasetHandler &handler)
const PacketCounter & nOutInterests
represents an error in TLV encoding or decoding
gives access to counters provided by Face
size_t wireEncode(EncodingImpl< TAG > &encoder) const
const PacketCounter & nInNacks
ChannelStatus & setLocalUri(const std::string localUri)
const Name & getName() const
const PacketCounter & nInData