43 #include <ndn-cxx/lp/tags.hpp> 44 #include <ndn-cxx/mgmt/nfd/channel-status.hpp> 46 #ifdef HAVE_UNIX_SOCKETS 48 #endif // HAVE_UNIX_SOCKETS 53 #endif // HAVE_LIBPCAP 57 #endif // HAVE_WEBSOCKET 65 , m_faceTable(faceTable)
67 registerCommandHandler<ndn::nfd::FaceCreateCommand>(
"create",
68 bind(&FaceManager::createFace,
this, _2, _3, _4, _5));
70 registerCommandHandler<ndn::nfd::FaceUpdateCommand>(
"update",
71 bind(&FaceManager::updateFace,
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 connectFaceStateChangeSignal(face);
91 m_faceRemoveConn = m_faceTable.
beforeRemove.connect([
this] (
const Face& face) {
99 configFile.
addSectionHandler(
"face_system", bind(&FaceManager::processConfig,
this, _1, _2, _3));
103 FaceManager::createFace(
const Name& topPrefix,
const Interest& interest,
120 auto factory = m_factories.find(uri.
getScheme());
121 if (factory == m_factories.end()) {
122 NFD_LOG_TRACE(
"received create request for unsupported protocol");
128 factory->second->createFace(uri,
132 bind(&FaceManager::afterCreateFaceSuccess,
133 this, parameters, _1, done),
134 bind(&FaceManager::afterCreateFaceFailure,
135 this, _1, _2, done));
137 catch (
const std::runtime_error& error) {
139 done(
ControlResponse(500,
"Face creation failed due to internal error"));
142 catch (
const std::logic_error& error) {
144 done(
ControlResponse(500,
"Face creation failed due to internal error"));
157 const shared_ptr<Face>&
face,
184 m_faceTable.
add(face);
199 FaceManager::afterCreateFaceFailure(uint32_t status,
200 const std::string& reason,
209 FaceManager::updateFace(
const Name& topPrefix,
const Interest& interest,
217 if (incomingFaceIdTag ==
nullptr) {
219 done(
ControlResponse(404,
"No FaceId specified and IncomingFaceId not available"));
222 faceId = *incomingFaceIdTag;
225 Face* face = m_faceTable.
get(faceId);
227 if (face ==
nullptr) {
235 bool areParamsValid =
true;
239 NFD_LOG_TRACE(
"received unsupported face persistency change");
240 areParamsValid =
false;
247 NFD_LOG_TRACE(
"received request to enable local fields on non-local face");
248 areParamsValid =
false;
253 if (!areParamsValid) {
262 setLinkServiceOptions(*face, parameters, response);
276 FaceManager::destroyFace(
const Name& topPrefix,
const Interest& interest,
281 if (face !=
nullptr) {
289 FaceManager::enableLocalControl(
const Name& topPrefix,
const Interest& interest,
293 Face* face = findFaceForLocalControl(interest, parameters, done);
300 if (service ==
nullptr) {
306 service->setOptions(options);
308 return done(
ControlResponse(200,
"OK: enable all local fields on GenericLinkService")
313 FaceManager::disableLocalControl(
const Name& topPrefix,
const Interest& interest,
317 Face* face = findFaceForLocalControl(interest, parameters, done);
324 if (service ==
nullptr) {
330 service->setOptions(options);
332 return done(
ControlResponse(200,
"OK: disable all local fields on GenericLinkService")
337 FaceManager::findFaceForLocalControl(
const Interest& request,
345 BOOST_ASSERT(incomingFaceIdTag !=
nullptr);
347 Face* face = m_faceTable.
get(*incomingFaceIdTag);
348 if (face ==
nullptr) {
349 NFD_LOG_DEBUG(
"FaceId " << *incomingFaceIdTag <<
" not found");
364 FaceManager::setLinkServiceOptions(
Face& face,
369 BOOST_ASSERT(linkService !=
nullptr);
371 auto options = linkService->getOptions();
376 linkService->setOptions(options);
383 FaceManager::listFaces(
const Name& topPrefix,
const Interest& interest,
387 for (
const Face& face : m_faceTable) {
395 FaceManager::listChannels(
const Name& topPrefix,
const Interest& interest,
398 std::set<const ProtocolFactory*> seenFactories;
400 for (
const auto& kv : m_factories) {
403 std::tie(std::ignore, inserted) = seenFactories.insert(factory);
406 for (
const auto& channel : factory->
getChannels()) {
418 FaceManager::queryFaces(
const Name& topPrefix,
const Interest& interest,
424 faceFilter.
wireDecode(query[-1].blockFromValue());
432 for (
const Face& face : m_faceTable) {
433 if (!matchFilter(faceFilter, face)) {
490 collectFaceProperties(face, status);
493 if (expirationTime != time::steady_clock::TimePoint::max()) {
495 time::duration_cast<time::milliseconds>(expirationTime - now)));
511 template<
typename FaceTraits>
513 FaceManager::collectFaceProperties(
const Face& face, FaceTraits& traits)
524 if (linkService !=
nullptr) {
525 auto linkServiceOptions = linkService->
getOptions();
535 collectFaceProperties(face, notification);
537 m_postNotification(notification.
wireEncode());
541 FaceManager::connectFaceStateChangeSignal(
const Face& face)
546 const Face& face = *m_faceTable.
get(faceId);
555 m_faceStateChangeConn.erase(faceId);
561 FaceManager::processConfig(
const ConfigSection& configSection,
563 const std::string& filename)
565 bool hasSeenUnix =
false;
566 bool hasSeenTcp =
false;
567 bool hasSeenUdp =
false;
568 bool hasSeenEther =
false;
569 bool hasSeenWebSocket =
false;
572 for (
const auto& item : configSection) {
573 if (item.first ==
"unix") {
575 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"unix\" section"));
579 processSectionUnix(item.second, isDryRun);
581 else if (item.first ==
"tcp") {
583 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"tcp\" section"));
587 processSectionTcp(item.second, isDryRun);
589 else if (item.first ==
"udp") {
591 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"udp\" section"));
595 processSectionUdp(item.second, isDryRun, nicList);
597 else if (item.first ==
"ether") {
599 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"ether\" section"));
603 processSectionEther(item.second, isDryRun, nicList);
605 else if (item.first ==
"websocket") {
606 if (hasSeenWebSocket) {
607 BOOST_THROW_EXCEPTION(
Error(
"Duplicate \"websocket\" section"));
609 hasSeenWebSocket =
true;
611 processSectionWebSocket(item.second, isDryRun);
614 BOOST_THROW_EXCEPTION(
Error(
"Unrecognized option \"" + item.first +
"\""));
620 FaceManager::processSectionUnix(
const ConfigSection& configSection,
bool isDryRun)
628 #if defined(HAVE_UNIX_SOCKETS) 629 std::string path =
"/var/run/nfd.sock";
631 for (
const auto& i : configSection) {
632 if (i.first ==
"path") {
633 path = i.second.get_value<std::string>();
637 i.first +
"\" in \"unix\" section"));
642 if (m_factories.count(
"unix") > 0) {
646 auto factory = make_shared<UnixStreamFactory>();
647 m_factories.insert(std::make_pair(
"unix", factory));
649 auto channel = factory->createChannel(path);
650 channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
653 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without Unix sockets support, " 654 "cannot process \"unix\" section"));
655 #endif // HAVE_UNIX_SOCKETS 659 FaceManager::processSectionTcp(
const ConfigSection& configSection,
bool isDryRun)
668 #if defined(HAVE_TCP) 669 uint16_t port = 6363;
670 bool needToListen =
true;
671 bool enableV4 =
true;
672 bool enableV6 =
true;
674 for (
const auto& i : configSection) {
675 if (i.first ==
"port") {
676 port = ConfigFile::parseNumber<uint16_t>(i,
"tcp");
679 else if (i.first ==
"listen") {
682 else if (i.first ==
"enable_v4") {
685 else if (i.first ==
"enable_v6") {
690 i.first +
"\" in \"tcp\" section"));
694 if (!enableV4 && !enableV6) {
695 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 and IPv6 TCP channels have been disabled." 696 " Remove \"tcp\" section to disable TCP channels or" 697 " re-enable at least one channel type."));
701 if (m_factories.count(
"tcp") > 0) {
705 auto factory = make_shared<TcpFactory>();
706 m_factories.insert(std::make_pair(
"tcp", factory));
710 shared_ptr<TcpChannel> v4Channel = factory->createChannel(endpoint);
712 v4Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
715 m_factories.insert(std::make_pair(
"tcp4", factory));
720 shared_ptr<TcpChannel> v6Channel = factory->createChannel(endpoint);
722 v6Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
725 m_factories.insert(std::make_pair(
"tcp6", factory));
729 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without TCP support, cannot process \"tcp\" section"));
734 FaceManager::processSectionUdp(
const ConfigSection& configSection,
bool isDryRun,
735 const std::vector<NetworkInterfaceInfo>& nicList)
750 #if defined(HAVE_UDP) 751 uint16_t port = 6363;
752 bool enableV4 =
true;
753 bool enableV6 =
true;
754 size_t timeout = 600;
755 size_t keepAliveInterval = 25;
756 bool useMcast =
true;
757 auto mcastGroup = boost::asio::ip::address_v4::from_string(
"224.0.23.170");
758 uint16_t mcastPort = 56363;
760 for (
const auto& i : configSection) {
761 if (i.first ==
"port") {
762 port = ConfigFile::parseNumber<uint16_t>(i,
"udp");
765 else if (i.first ==
"enable_v4") {
768 else if (i.first ==
"enable_v6") {
771 else if (i.first ==
"idle_timeout") {
773 timeout = i.second.get_value<
size_t>();
775 catch (
const boost::property_tree::ptree_bad_data&) {
777 i.first +
"\" in \"udp\" section"));
780 else if (i.first ==
"keep_alive_interval") {
782 keepAliveInterval = i.second.get_value<
size_t>();
784 (void)(keepAliveInterval);
786 catch (
const boost::property_tree::ptree_bad_data&) {
788 i.first +
"\" in \"udp\" section"));
791 else if (i.first ==
"mcast") {
794 else if (i.first ==
"mcast_port") {
795 mcastPort = ConfigFile::parseNumber<uint16_t>(i,
"udp");
798 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);
803 i.first +
"\" in \"udp\" section"));
809 i.first +
"\" in \"udp\" section"));
813 if (!enableV4 && !enableV6) {
814 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 and IPv6 UDP channels have been disabled." 815 " Remove \"udp\" section to disable UDP channels or" 816 " re-enable at least one channel type."));
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)"));
824 shared_ptr<UdpFactory> factory;
825 bool isReload =
false;
826 if (m_factories.count(
"udp") > 0) {
828 factory = static_pointer_cast<
UdpFactory>(m_factories[
"udp"]);
831 factory = make_shared<UdpFactory>();
832 m_factories.insert(std::make_pair(
"udp", factory));
835 if (!isReload && enableV4) {
837 shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
838 v4Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
840 m_factories.insert(std::make_pair(
"udp4", factory));
843 if (!isReload && enableV6) {
845 shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
846 v6Channel->listen(bind(&
FaceTable::add, &m_faceTable, _1),
nullptr);
848 m_factories.insert(std::make_pair(
"udp6", factory));
851 std::set<shared_ptr<Face>> multicastFacesToRemove;
852 for (
const auto& i : factory->getMulticastFaces()) {
853 multicastFacesToRemove.insert(i.second);
856 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);
864 bool isNicNameNecessary =
false;
865 #if defined(__linux__) 866 if (ipv4MulticastInterfaces.size() > 1) {
869 isNicNameNecessary =
true;
874 for (
const auto& nic : ipv4MulticastInterfaces) {
875 udp::Endpoint localEndpoint(nic.ipv4Addresses[0], mcastPort);
876 auto newFace = factory->createMulticastFace(localEndpoint, mcastEndpoint,
877 isNicNameNecessary ? nic.name :
"");
878 m_faceTable.
add(newFace);
879 multicastFacesToRemove.erase(newFace);
883 for (
const auto& face : multicastFacesToRemove) {
888 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without UDP support, cannot process \"udp\" section"));
893 FaceManager::processSectionEther(
const ConfigSection& configSection,
bool isDryRun,
894 const std::vector<NetworkInterfaceInfo>& nicList)
904 #if defined(HAVE_LIBPCAP) 906 bool useMcast =
true;
909 for (
const auto& i : configSection) {
910 if (i.first ==
"mcast") {
913 else if (i.first ==
"mcast_group") {
915 if (mcastGroup.
isNull()) {
917 i.first +
"\" in \"ether\" section"));
919 NFD_LOG_TRACE(
"Ethernet multicast group set to " << mcastGroup);
921 else if (i.first ==
"whitelist") {
924 else if (i.first ==
"blacklist") {
929 i.first +
"\" in \"ether\" section"));
934 shared_ptr<EthernetFactory> factory;
935 if (m_factories.count(
"ether") > 0) {
939 factory = make_shared<EthernetFactory>();
940 m_factories.insert(std::make_pair(
"ether", factory));
943 std::set<shared_ptr<Face>> multicastFacesToRemove;
944 for (
const auto& i : factory->getMulticastFaces()) {
945 multicastFacesToRemove.insert(i.second);
949 for (
const auto& nic : nicList) {
950 if (nic.isUp() && nic.isMulticastCapable() && nicPredicate(nic)) {
952 auto newFace = factory->createMulticastFace(nic, mcastGroup);
953 m_faceTable.
add(newFace);
954 multicastFacesToRemove.erase(newFace);
966 for (
const auto& face : multicastFacesToRemove) {
971 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD was compiled without libpcap, cannot process \"ether\" section"));
972 #endif // HAVE_LIBPCAP 976 FaceManager::processSectionWebSocket(
const ConfigSection& configSection,
bool isDryRun)
987 #if defined(HAVE_WEBSOCKET) 988 uint16_t port = 9696;
989 bool needToListen =
true;
990 bool enableV4 =
true;
991 bool enableV6 =
true;
993 for (
const auto& i : configSection) {
994 if (i.first ==
"port") {
995 port = ConfigFile::parseNumber<uint16_t>(i,
"websocket");
998 else if (i.first ==
"listen") {
1001 else if (i.first ==
"enable_v4") {
1004 else if (i.first ==
"enable_v6") {
1009 i.first +
"\" in \"websocket\" section"));
1013 if (!enableV4 && !enableV6) {
1014 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"IPv4 and IPv6 WebSocket channels have been disabled." 1015 " Remove \"websocket\" section to disable WebSocket channels or" 1016 " re-enable at least one channel type."));
1019 if (!enableV4 && enableV6) {
1020 BOOST_THROW_EXCEPTION(
ConfigFile::Error(
"NFD does not allow pure IPv6 WebSocket channel."));
1024 if (m_factories.count(
"websocket") > 0) {
1028 auto factory = make_shared<WebSocketFactory>();
1029 m_factories.insert(std::make_pair(
"websocket", factory));
1031 shared_ptr<WebSocketChannel> channel;
1033 if (enableV6 && enableV4) {
1035 channel = factory->createChannel(endpoint);
1037 m_factories.insert(std::make_pair(
"websocket46", factory));
1039 else if (enableV4) {
1041 channel = factory->createChannel(endpoint);
1043 m_factories.insert(std::make_pair(
"websocket4", factory));
1046 if (channel && needToListen) {
1052 "cannot process \"websocket\" section"));
1053 #endif // HAVE_WEBSOCKET signal::Signal< FaceTable, Face & > afterAdd
fires after a face is added
LinkType getLinkType() const
bool hasFaceScope() const
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)
shared_ptr< T > getTag() const
get a tag item
GenericLinkService is a LinkService that implements the NDNLPv2 protocol.
face went UP (from DOWN state)
static bool parseYesNo(const ConfigSection &node, const std::string &key, const std::string §ionName)
parse a config option that can be either "yes" or "no"
bool parse(const std::string &uri)
exception-safe parsing
const std::string & getLocalUri() const
represents parameters in a ControlCommand request or response
generalization of a network interface
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.
TransportState
indicates the state of a transport
static time_point now() noexcept
FaceStatus & setNInDatas(uint64_t nInDatas)
represents the underlying protocol and address used by a Face
configuration file parsing utility
const PacketCounter & nOutNacks
size_t wireEncode(EncodingImpl< TAG > &encoder) const
FaceScope getFaceScope() const
void add(shared_ptr< Face > face)
add a face
bool isCanonical() const
determine whether this FaceUri is in canonical form
virtual std::vector< shared_ptr< const Channel > > getChannels() const =0
std::string toString() const
write as a string
Address getDefaultMulticastAddress()
Returns the default Ethernet multicast address for NDN.
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
FaceStatus & setNOutDatas(uint64_t nOutDatas)
represents a Face status change notification
const std::string & getRemoteUri() const
represents an Interest packet
#define NFD_LOG_DEBUG(expression)
FaceEventNotification & setKind(FaceEventKind kind)
FaceUri getLocalUri() const
FaceUri getRemoteUri() const
LinkService * getLinkService() const
bool hasRemoteUri() const
FaceStatus & setNOutBytes(uint64_t nOutBytes)
void parseWhitelist(const boost::property_tree::ptree &list)
FaceStatus & setNOutInterests(uint64_t nOutInterests)
C & setFaceId(uint64_t faceId)
const std::string & getScheme() const
get scheme (protocol)
Face * get(FaceId id) const
get face by FaceId
time::steady_clock::TimePoint getExpirationTime() const
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)
FacePersistency getFacePersistency() const
FaceStatus & setNInBytes(uint64_t nInBytes)
Represents a predicate to accept or reject a NetworkInterfaceInfo.
#define NFD_LOG_TRACE(expression)
#define NFD_LOG_ERROR(expression)
size_t wireEncode(EncodingImpl< TAG > &encoder) const
prepend FaceEventNotification to the encoder
ndn::mgmt::ControlResponse ControlResponse
bool hasUriScheme() const
FaceStatus & setNInNacks(uint64_t nInNacks)
ndn::nfd::LinkType getLinkType() const
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
the transport is closed, and can be safely deallocated
const PacketCounter & nOutData
const PacketCounter & nInInterests
FaceStatus & setExpirationPeriod(const time::milliseconds &expirationPeriod)
size_t wireEncode(EncodingImpl< TAG > &encoder) const
prepend FaceStatus to the encoder
ndn::nfd::FaceScope getScope() const
signal::Signal< Transport, FaceState, FaceState > & afterStateChange
signals after face state changed
boost::property_tree::ptree ConfigSection
Name abstraction to represent an absolute name.
const ByteCounter & nOutBytes
bool hasFlagBit(size_t bit) const
FaceManager(FaceTable &faceTable, Dispatcher &dispatcher, CommandAuthenticator &authenticator)
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.
provides ControlCommand authorization according to NFD configuration file
const ByteCounter & nInBytes
bool hasFacePersistency() const
void parseBlacklist(const boost::property_tree::ptree &list)
ndn::nfd::FacePersistency getPersistency() const
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
bool getFlagBit(size_t bit) const
boost::asio::ip::tcp::endpoint Endpoint
face went DOWN (from UP state)
void close()
request the face to be closed
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 Options & getOptions() const
get Options used by GenericLinkService
const std::string & getUriScheme() const
provides a context for generating response to a StatusDataset request
FacePersistency getFacePersistency() const
uint64_t FaceId
identifies a face
a collection of common functions shared by all NFD managers, such as communicating with the dispatche...
#define NFD_LOG_INIT(name)
bool hasFacePersistency() const
bit that controls whether local fields are enabled on a face
void wireDecode(const Block &wire)
decode FaceQueryFilter
void registerStatusDatasetHandler(const std::string &verb, const ndn::mgmt::StatusDatasetHandler &handler)
ControlParameters & setFlagBit(size_t bit, bool value, bool wantMask=true)
set a bit in Flags
const FaceCounters & getCounters() const
const PacketCounter & nOutInterests
represents an error in TLV encoding or decoding
gives access to counters provided by Face
the transport is down temporarily, and is being recovered
size_t wireEncode(EncodingImpl< TAG > &encoder) const
const PacketCounter & nInNacks
ChannelStatus & setLocalUri(const std::string localUri)
const Name & getName() const
const PacketCounter & nInData