core: use markers in StatusDataset and NotificationStream
This commit also refactors FaceMonitor as generic NotificationSubscriber, and refactors AutoregServer to use FaceMonitor. refs #1837 #1838 Change-Id: I8b40dfae118853d1224c8290cf92e7cc0daa116f
This commit is contained in:
1 parent
b3033247ee
commit
15b12e759d
18 files changed
+750
-537
No files matched your search
+26
-13
@@ -1,11 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -20,7 +21,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#ifndef NFD_CORE_EVENT_EMITTER_HPP
|
||||
#define NFD_CORE_EVENT_EMITTER_HPP
|
||||
@@ -29,25 +30,27 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
struct empty {};
|
||||
struct empty
|
||||
{
|
||||
};
|
||||
|
||||
/** \class EventEmitter
|
||||
* \brief provides a lightweight event system
|
||||
*
|
||||
* To declare an event:
|
||||
* EventEmitter<TArgs> m_eventName;
|
||||
* EventEmitter<TArgs> onEventName;
|
||||
* To subscribe to an event:
|
||||
* eventSource->m_eventName += eventHandler;
|
||||
* eventSource->onEventName += eventHandler;
|
||||
* Multiple functions can subscribe to the same event.
|
||||
* To trigger an event:
|
||||
* m_eventName(args);
|
||||
* onEventName(args);
|
||||
* To clear event subscriptions:
|
||||
* m_eventName.clear();
|
||||
* onEventName.clear();
|
||||
*/
|
||||
|
||||
// four arguments
|
||||
template<typename T1 = empty, typename T2 = empty,
|
||||
typename T3 = empty, typename T4 = empty>
|
||||
typename T3 = empty, typename T4 = empty>
|
||||
class EventEmitter : noncopyable
|
||||
{
|
||||
public:
|
||||
@@ -199,6 +202,8 @@ EventEmitter<empty, empty, empty, empty>::operator()()
|
||||
std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)();
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +237,8 @@ EventEmitter<T1, empty, empty, empty>::operator()(const T1& a1)
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +273,8 @@ EventEmitter<T1, T2, empty, empty>::operator()
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1, a2);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,6 +309,8 @@ EventEmitter<T1, T2, T3, empty>::operator()
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1, a2, a3);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +345,8 @@ EventEmitter<T1, T2, T3, T4>::operator()
|
||||
typename std::vector<Handler>::iterator it;
|
||||
for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
|
||||
(*it)(a1, a2, a3, a4);
|
||||
if (m_handlers.empty()) // .clear has been called
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#include "face-monitor.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
#include <ndn-cxx/face.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("FaceMonitor");
|
||||
|
||||
FaceMonitor::FaceMonitor(ndn::Face& face)
|
||||
: m_face(face)
|
||||
, m_isStopped(true)
|
||||
{
|
||||
}
|
||||
|
||||
FaceMonitor::~FaceMonitor()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::removeAllSubscribers()
|
||||
{
|
||||
m_notificationCallbacks.clear();
|
||||
m_timeoutCallbacks.clear();
|
||||
stopNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::stopNotifications()
|
||||
{
|
||||
if (static_cast<bool>(m_lastInterestId))
|
||||
m_face.removePendingInterest(m_lastInterestId);
|
||||
m_isStopped = true;
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::startNotifications()
|
||||
{
|
||||
if (m_isStopped == false)
|
||||
return; // Notifications cycle has been started.
|
||||
m_isStopped = false;
|
||||
|
||||
Interest interest("/localhost/nfd/faces/events");
|
||||
interest
|
||||
.setMustBeFresh(true)
|
||||
.setChildSelector(1)
|
||||
.setInterestLifetime(time::seconds(60))
|
||||
;
|
||||
|
||||
NFD_LOG_DEBUG("startNotification: Interest Sent: " << interest);
|
||||
|
||||
m_lastInterestId = m_face.expressInterest(interest,
|
||||
bind(&FaceMonitor::onNotification, this, _2),
|
||||
bind(&FaceMonitor::onTimeout, this));
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::addSubscriber(const NotificationCallback& notificationCallback)
|
||||
{
|
||||
addSubscriber(notificationCallback, TimeoutCallback());
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::addSubscriber(const NotificationCallback& notificationCallback,
|
||||
const TimeoutCallback& timeoutCallback)
|
||||
{
|
||||
if (static_cast<bool>(notificationCallback))
|
||||
m_notificationCallbacks.push_back(notificationCallback);
|
||||
|
||||
if (static_cast<bool>(timeoutCallback))
|
||||
m_timeoutCallbacks.push_back(timeoutCallback);
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::onTimeout()
|
||||
{
|
||||
if (m_isStopped)
|
||||
return;
|
||||
|
||||
std::vector<TimeoutCallback>::iterator it;
|
||||
for (it = m_timeoutCallbacks.begin();
|
||||
it != m_timeoutCallbacks.end(); ++it) {
|
||||
(*it)();
|
||||
//One of the registered callbacks has cleared the vector,
|
||||
//return now as the iterator has been invalidated and
|
||||
//the vector is empty.
|
||||
if (m_timeoutCallbacks.empty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Interest newInterest("/localhost/nfd/faces/events");
|
||||
newInterest
|
||||
.setMustBeFresh(true)
|
||||
.setChildSelector(1)
|
||||
.setInterestLifetime(time::seconds(60))
|
||||
;
|
||||
|
||||
NFD_LOG_DEBUG("In onTimeout, sending interest: " << newInterest);
|
||||
|
||||
m_lastInterestId = m_face.expressInterest(newInterest,
|
||||
bind(&FaceMonitor::onNotification, this, _2),
|
||||
bind(&FaceMonitor::onTimeout, this));
|
||||
}
|
||||
|
||||
void
|
||||
FaceMonitor::onNotification(const Data& data)
|
||||
{
|
||||
if (m_isStopped)
|
||||
return;
|
||||
|
||||
m_lastSequence = data.getName().get(-1).toSegment();
|
||||
ndn::nfd::FaceEventNotification notification(data.getContent().blockFromValue());
|
||||
|
||||
std::vector<NotificationCallback>::iterator it;
|
||||
for (it = m_notificationCallbacks.begin();
|
||||
it != m_notificationCallbacks.end(); ++it) {
|
||||
(*it)(notification);
|
||||
if (m_notificationCallbacks.empty()) {
|
||||
//One of the registered callbacks has cleared the vector.
|
||||
//return back, as no one is interested in notifications anymore.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Setting up next notification
|
||||
Name nextNotification("/localhost/nfd/faces/events");
|
||||
nextNotification.appendSegment(m_lastSequence + 1);
|
||||
|
||||
Interest interest(nextNotification);
|
||||
interest.setInterestLifetime(time::seconds(60));
|
||||
|
||||
NFD_LOG_DEBUG("onNotification: Interest sent: " << interest);
|
||||
|
||||
m_lastInterestId = m_face.expressInterest(interest,
|
||||
bind(&FaceMonitor::onNotification, this, _2),
|
||||
bind(&FaceMonitor::onTimeout, this));
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+14
-71
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
@@ -21,83 +21,26 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
*/
|
||||
|
||||
#ifndef NFD_CORE_FACE_MONITOR_HPP
|
||||
#define NFD_CORE_FACE_MONITOR_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "notification-subscriber.hpp"
|
||||
|
||||
#include <ndn-cxx/management/nfd-face-event-notification.hpp>
|
||||
|
||||
namespace ndn {
|
||||
class Face;
|
||||
class PendingInterestId;
|
||||
}
|
||||
|
||||
namespace nfd {
|
||||
|
||||
using ndn::nfd::FaceEventNotification;
|
||||
|
||||
/**
|
||||
* \brief Helper class to subscribe to face notification events
|
||||
*
|
||||
* \todo Write test cases
|
||||
*/
|
||||
class FaceMonitor : noncopyable
|
||||
class FaceMonitor : public NotificationSubscriber<FaceEventNotification>
|
||||
{
|
||||
public:
|
||||
typedef function<void(const ndn::nfd::FaceEventNotification&)> NotificationCallback;
|
||||
typedef function<void()> TimeoutCallback;
|
||||
|
||||
typedef std::vector<NotificationCallback> NotificationCallbacks;
|
||||
typedef std::vector<TimeoutCallback> TimeoutCallbacks;
|
||||
|
||||
explicit
|
||||
FaceMonitor(ndn::Face& face);
|
||||
|
||||
~FaceMonitor();
|
||||
|
||||
/** \brief Stops all notifications. This method doesn't remove registered callbacks.
|
||||
*/
|
||||
void
|
||||
stopNotifications();
|
||||
|
||||
/** \brief Resumes notifications for added subscribers.
|
||||
*/
|
||||
void
|
||||
startNotifications();
|
||||
|
||||
/** \brief Removes all notification subscribers.
|
||||
*/
|
||||
void
|
||||
removeAllSubscribers();
|
||||
|
||||
/** \brief Adds a notification subscriber. This method doesn't return on timeouts.
|
||||
*/
|
||||
void
|
||||
addSubscriber(const NotificationCallback& notificationCallback);
|
||||
|
||||
/** \brief Adds a notification subscriber.
|
||||
*/
|
||||
void
|
||||
addSubscriber(const NotificationCallback& notificationCallback,
|
||||
const TimeoutCallback& timeoutCallback);
|
||||
|
||||
private:
|
||||
void
|
||||
onTimeout();
|
||||
|
||||
void
|
||||
onNotification(const Data& data);
|
||||
|
||||
private:
|
||||
ndn::Face& m_face;
|
||||
uint64_t m_lastSequence;
|
||||
bool m_isStopped;
|
||||
NotificationCallbacks m_notificationCallbacks;
|
||||
TimeoutCallbacks m_timeoutCallbacks;
|
||||
const ndn::PendingInterestId* m_lastInterestId;
|
||||
FaceMonitor(ndn::Face& face)
|
||||
: NotificationSubscriber<FaceEventNotification>(face, "ndn:/localhost/nfd/faces/events")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -23,63 +23,59 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_MGMT_NOTIFICATION_STREAM_HPP
|
||||
#define NFD_DAEMON_MGMT_NOTIFICATION_STREAM_HPP
|
||||
#ifndef NFD_CORE_NOTIFICATION_STREAM_HPP
|
||||
#define NFD_CORE_NOTIFICATION_STREAM_HPP
|
||||
|
||||
#include "mgmt/app-face.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
#include <ndn-cxx/encoding/encoding-buffer.hpp>
|
||||
#include <ndn-cxx/security/key-chain.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class NotificationStream
|
||||
/** \brief provides a publisher of Notification Stream
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/Notification
|
||||
*/
|
||||
template <class FaceBase>
|
||||
class NotificationStream : noncopyable
|
||||
{
|
||||
public:
|
||||
NotificationStream(shared_ptr<AppFace> face, const Name& prefix, ndn::KeyChain& keyChain);
|
||||
NotificationStream(FaceBase& face, const Name& prefix, ndn::KeyChain& keyChain)
|
||||
: m_face(face)
|
||||
, m_prefix(prefix)
|
||||
, m_keyChain(keyChain)
|
||||
, m_sequenceNo(0)
|
||||
{
|
||||
}
|
||||
|
||||
~NotificationStream();
|
||||
virtual
|
||||
~NotificationStream()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T> void
|
||||
postNotification(const T& notification);
|
||||
template<typename T> void
|
||||
postNotification(const T& notification)
|
||||
{
|
||||
Name dataName = m_prefix;
|
||||
dataName.appendSequenceNumber(m_sequenceNo);
|
||||
|
||||
shared_ptr<Data> data = make_shared<Data>(dataName);
|
||||
data->setContent(notification.wireEncode());
|
||||
data->setFreshnessPeriod(time::seconds(1));
|
||||
|
||||
m_keyChain.sign(*data);
|
||||
m_face.put(*data);
|
||||
|
||||
++m_sequenceNo;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<AppFace> m_face;
|
||||
FaceBase& m_face;
|
||||
const Name m_prefix;
|
||||
uint64_t m_sequenceNo;
|
||||
ndn::KeyChain& m_keyChain;
|
||||
uint64_t m_sequenceNo;
|
||||
};
|
||||
|
||||
inline
|
||||
NotificationStream::NotificationStream(shared_ptr<AppFace> face,
|
||||
const Name& prefix,
|
||||
ndn::KeyChain& keyChain)
|
||||
: m_face(face)
|
||||
, m_prefix(prefix)
|
||||
, m_sequenceNo(0)
|
||||
, m_keyChain(keyChain)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
NotificationStream::postNotification(const T& notification)
|
||||
{
|
||||
Name dataName(m_prefix);
|
||||
dataName.appendSegment(m_sequenceNo);
|
||||
shared_ptr<Data> data(make_shared<Data>(dataName));
|
||||
data->setContent(notification.wireEncode());
|
||||
data->setFreshnessPeriod(time::seconds(1));
|
||||
|
||||
m_keyChain.sign(*data);
|
||||
m_face->put(*data);
|
||||
|
||||
++m_sequenceNo;
|
||||
}
|
||||
|
||||
inline
|
||||
NotificationStream::~NotificationStream()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
#endif // NFD_DAEMON_MGMT_NOTIFICATION_STREAM_HPP
|
||||
#endif // NFD_CORE_NOTIFICATION_STREAM_HPP
|
||||
@@ -0,0 +1,214 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_CORE_NOTIFICATION_SUBSCRIBER_HPP
|
||||
#define NFD_CORE_NOTIFICATION_SUBSCRIBER_HPP
|
||||
|
||||
#include "event-emitter.hpp"
|
||||
|
||||
#include <ndn-cxx/face.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief provides a subscriber of Notification Stream
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/Notification
|
||||
* \tparam T type of Notification item, appears in payload of Data packets
|
||||
*/
|
||||
template<typename T>
|
||||
class NotificationSubscriber : noncopyable
|
||||
{
|
||||
public:
|
||||
/** \brief construct a NotificationSubscriber
|
||||
* \note The subscriber is not started after construction.
|
||||
* User should add one or more handlers to onNotification, and invoke .start().
|
||||
*/
|
||||
NotificationSubscriber(ndn::Face& face, const Name& prefix)
|
||||
: m_face(face)
|
||||
, m_prefix(prefix)
|
||||
, m_isRunning(false)
|
||||
, m_lastSequenceNo(std::numeric_limits<uint64_t>::max())
|
||||
, m_lastInterestId(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~NotificationSubscriber()
|
||||
{
|
||||
}
|
||||
|
||||
/** \return InterestLifetime of Interests to retrieve notifications
|
||||
* \details This must be greater than FreshnessPeriod of Notification Data packets,
|
||||
* to ensure correct operation of this subscriber implementation.
|
||||
*/
|
||||
static time::milliseconds
|
||||
getInterestLifetime()
|
||||
{
|
||||
return time::milliseconds(60000);
|
||||
}
|
||||
|
||||
bool
|
||||
isRunning() const
|
||||
{
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
/** \brief start or resume receiving notifications
|
||||
* \note onNotification must have at least one listener,
|
||||
* otherwise this operation has no effect.
|
||||
*/
|
||||
void
|
||||
start()
|
||||
{
|
||||
if (m_isRunning) // already running
|
||||
return;
|
||||
m_isRunning = true;
|
||||
|
||||
this->sendInitialInterest();
|
||||
}
|
||||
|
||||
/** \brief stop receiving notifications
|
||||
*/
|
||||
void
|
||||
stop()
|
||||
{
|
||||
if (!m_isRunning) // not running
|
||||
return;
|
||||
m_isRunning = false;
|
||||
|
||||
if (m_lastInterestId != 0)
|
||||
m_face.removePendingInterest(m_lastInterestId);
|
||||
m_lastInterestId = 0;
|
||||
}
|
||||
|
||||
public: // subscriptions
|
||||
/** \brief fires when a Notification is received
|
||||
* \note Removing all handlers will cause the subscriber to stop.
|
||||
*/
|
||||
EventEmitter<T> onNotification;
|
||||
|
||||
/** \brief fires when no Notification is received within .getInterestLifetime period
|
||||
*/
|
||||
EventEmitter<> onTimeout;
|
||||
|
||||
/** \brief fires when a Data packet in the Notification Stream cannot be decoded as T
|
||||
*/
|
||||
EventEmitter<Data> onDecodeError;
|
||||
|
||||
private:
|
||||
void
|
||||
sendInitialInterest()
|
||||
{
|
||||
if (this->shouldStop())
|
||||
return;
|
||||
|
||||
shared_ptr<Interest> interest = make_shared<Interest>(m_prefix);
|
||||
interest->setMustBeFresh(true);
|
||||
interest->setChildSelector(1);
|
||||
interest->setInterestLifetime(getInterestLifetime());
|
||||
|
||||
m_lastInterestId = m_face.expressInterest(*interest,
|
||||
bind(&NotificationSubscriber<T>::afterReceiveData, this, _2),
|
||||
bind(&NotificationSubscriber<T>::afterTimeout, this));
|
||||
}
|
||||
|
||||
void
|
||||
sendNextInterest()
|
||||
{
|
||||
if (this->shouldStop())
|
||||
return;
|
||||
|
||||
BOOST_ASSERT(m_lastSequenceNo !=
|
||||
std::numeric_limits<uint64_t>::max());// overflow or missing initial reply
|
||||
|
||||
Name nextName = m_prefix;
|
||||
nextName.appendSequenceNumber(m_lastSequenceNo + 1);
|
||||
|
||||
shared_ptr<Interest> interest = make_shared<Interest>(nextName);
|
||||
interest->setInterestLifetime(getInterestLifetime());
|
||||
|
||||
m_lastInterestId = m_face.expressInterest(*interest,
|
||||
bind(&NotificationSubscriber<T>::afterReceiveData, this, _2),
|
||||
bind(&NotificationSubscriber<T>::afterTimeout, this));
|
||||
}
|
||||
|
||||
/** \brief Check if the subscriber is or should be stopped.
|
||||
* \return true if the subscriber is stopped.
|
||||
*/
|
||||
bool
|
||||
shouldStop()
|
||||
{
|
||||
if (!m_isRunning)
|
||||
return true;
|
||||
if (onNotification.isEmpty()) {
|
||||
this->stop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
afterReceiveData(const Data& data)
|
||||
{
|
||||
if (this->shouldStop())
|
||||
return;
|
||||
|
||||
T notification;
|
||||
try {
|
||||
m_lastSequenceNo = data.getName().get(-1).toSequenceNumber();
|
||||
notification.wireDecode(data.getContent().blockFromValue());
|
||||
}
|
||||
catch (tlv::Error&) {
|
||||
this->onDecodeError(data);
|
||||
this->sendInitialInterest();
|
||||
return;
|
||||
}
|
||||
|
||||
this->onNotification(notification);
|
||||
|
||||
this->sendNextInterest();
|
||||
}
|
||||
|
||||
void
|
||||
afterTimeout()
|
||||
{
|
||||
if (this->shouldStop())
|
||||
return;
|
||||
|
||||
this->onTimeout();
|
||||
|
||||
this->sendInitialInterest();
|
||||
}
|
||||
|
||||
private:
|
||||
ndn::Face& m_face;
|
||||
Name m_prefix;
|
||||
bool m_isRunning;
|
||||
uint64_t m_lastSequenceNo;
|
||||
const ndn::PendingInterestId* m_lastInterestId;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_CORE_NOTIFICATION_SUBSCRIBER_HPP
|
||||
+28
-29
@@ -33,6 +33,9 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief provides a publisher of Status Dataset or other segmented octet stream
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
|
||||
*/
|
||||
template <class FaceBase>
|
||||
class SegmentPublisher : noncopyable
|
||||
{
|
||||
@@ -59,48 +62,44 @@ public:
|
||||
void
|
||||
publish()
|
||||
{
|
||||
Name segmentPrefix(m_prefix);
|
||||
segmentPrefix.appendVersion();
|
||||
|
||||
ndn::EncodingBuffer buffer;
|
||||
|
||||
generate(buffer);
|
||||
|
||||
const uint8_t* rawBuffer = buffer.buf();
|
||||
const uint8_t* segmentBegin = rawBuffer;
|
||||
const uint8_t* end = rawBuffer + buffer.size();
|
||||
|
||||
Name segmentPrefix(m_prefix);
|
||||
segmentPrefix.appendVersion();
|
||||
|
||||
uint64_t segmentNo = 0;
|
||||
do
|
||||
{
|
||||
const uint8_t* segmentEnd = segmentBegin + getMaxSegmentSize();
|
||||
if (segmentEnd > end)
|
||||
{
|
||||
segmentEnd = end;
|
||||
}
|
||||
|
||||
Name segmentName(segmentPrefix);
|
||||
segmentName.appendSegment(segmentNo);
|
||||
|
||||
shared_ptr<Data> data(make_shared<Data>(segmentName));
|
||||
data->setContent(segmentBegin, segmentEnd - segmentBegin);
|
||||
|
||||
segmentBegin = segmentEnd;
|
||||
if (segmentBegin >= end)
|
||||
{
|
||||
data->setFinalBlockId(segmentName[-1]);
|
||||
}
|
||||
|
||||
publishSegment(data);
|
||||
segmentNo++;
|
||||
do {
|
||||
const uint8_t* segmentEnd = segmentBegin + getMaxSegmentSize();
|
||||
if (segmentEnd > end) {
|
||||
segmentEnd = end;
|
||||
}
|
||||
while (segmentBegin < end);
|
||||
|
||||
Name segmentName(segmentPrefix);
|
||||
segmentName.appendSegment(segmentNo);
|
||||
|
||||
shared_ptr<Data> data = make_shared<Data>(segmentName);
|
||||
data->setContent(segmentBegin, segmentEnd - segmentBegin);
|
||||
|
||||
segmentBegin = segmentEnd;
|
||||
if (segmentBegin >= end) {
|
||||
data->setFinalBlockId(segmentName[-1]);
|
||||
}
|
||||
|
||||
publishSegment(data);
|
||||
++segmentNo;
|
||||
} while (segmentBegin < end);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** \brief In a derived class, write the octets into outBuffer.
|
||||
*/
|
||||
virtual size_t
|
||||
generate(ndn::EncodingBuffer& outBuffer) =0;
|
||||
generate(ndn::EncodingBuffer& outBuffer) = 0;
|
||||
|
||||
private:
|
||||
void
|
||||
|
||||
@@ -119,7 +119,7 @@ FaceManager::FaceManager(FaceTable& faceTable,
|
||||
, m_faceTable(faceTable)
|
||||
, m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
|
||||
, m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
|
||||
, m_notificationStream(m_face, FACE_EVENTS_PREFIX, keyChain)
|
||||
, m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
|
||||
, m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
|
||||
SIGNED_COMMAND_VERBS +
|
||||
(sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
#define NFD_DAEMON_MGMT_FACE_MANAGER_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include "core/notification-stream.hpp"
|
||||
#include "face/local-face.hpp"
|
||||
#include "mgmt/manager-base.hpp"
|
||||
#include "mgmt/face-status-publisher.hpp"
|
||||
#include "mgmt/channel-status-publisher.hpp"
|
||||
#include "mgmt/notification-stream.hpp"
|
||||
|
||||
#include <ndn-cxx/management/nfd-control-parameters.hpp>
|
||||
#include <ndn-cxx/management/nfd-control-response.hpp>
|
||||
@@ -174,7 +174,7 @@ private:
|
||||
FaceTable& m_faceTable;
|
||||
FaceStatusPublisher m_faceStatusPublisher;
|
||||
ChannelStatusPublisher m_channelStatusPublisher;
|
||||
NotificationStream m_notificationStream;
|
||||
NotificationStream<AppFace> m_notificationStream;
|
||||
|
||||
typedef function<void(FaceManager*,
|
||||
const Interest&,
|
||||
|
||||
+2
-2
@@ -118,8 +118,8 @@ RibManager::registerWithNfd()
|
||||
}
|
||||
|
||||
NFD_LOG_INFO("Start monitoring face create/destroy events");
|
||||
m_faceMonitor.addSubscriber(bind(&RibManager::onNotification, this, _1));
|
||||
m_faceMonitor.startNotifications();
|
||||
m_faceMonitor.onNotification += bind(&RibManager::onNotification, this, _1);
|
||||
m_faceMonitor.start();
|
||||
|
||||
fetchActiveFaces();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/notification-stream.hpp"
|
||||
#include "simple-notification.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "tests/dummy-client-face.hpp"
|
||||
|
||||
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(CoreNotificationStream, BaseFixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Post)
|
||||
{
|
||||
shared_ptr<DummyClientFace> face = makeDummyClientFace();
|
||||
ndn::KeyChain keyChain;
|
||||
NotificationStream<DummyClientFace> notificationStream(*face,
|
||||
"/localhost/nfd/NotificationStreamTest", keyChain);
|
||||
|
||||
SimpleNotification event1("msg1");
|
||||
notificationStream.postNotification(event1);
|
||||
face->processEvents();
|
||||
BOOST_REQUIRE_EQUAL(face->m_sentDatas.size(), 1);
|
||||
BOOST_CHECK_EQUAL(face->m_sentDatas[0].getName(),
|
||||
"/localhost/nfd/NotificationStreamTest/%FE%00");
|
||||
SimpleNotification decoded1;
|
||||
BOOST_CHECK_NO_THROW(decoded1.wireDecode(face->m_sentDatas[0].getContent().blockFromValue()));
|
||||
BOOST_CHECK_EQUAL(decoded1.getMessage(), "msg1");
|
||||
|
||||
SimpleNotification event2("msg2");
|
||||
notificationStream.postNotification(event2);
|
||||
face->processEvents();
|
||||
BOOST_REQUIRE_EQUAL(face->m_sentDatas.size(), 2);
|
||||
BOOST_CHECK_EQUAL(face->m_sentDatas[1].getName(),
|
||||
"/localhost/nfd/NotificationStreamTest/%FE%01");
|
||||
SimpleNotification decoded2;
|
||||
BOOST_CHECK_NO_THROW(decoded2.wireDecode(face->m_sentDatas[1].getContent().blockFromValue()));
|
||||
BOOST_CHECK_EQUAL(decoded2.getMessage(), "msg2");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace tests
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,223 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/notification-subscriber.hpp"
|
||||
#include "core/notification-stream.hpp"
|
||||
#include "simple-notification.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "tests/dummy-client-face.hpp"
|
||||
|
||||
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(CoreNotificationSubscriber, BaseFixture)
|
||||
|
||||
class EndToEndFixture : public BaseFixture
|
||||
{
|
||||
public:
|
||||
EndToEndFixture()
|
||||
: streamPrefix("ndn:/NotificationSubscriberTest")
|
||||
, publisherFace(makeDummyClientFace())
|
||||
, notificationStream(*publisherFace, streamPrefix, publisherKeyChain)
|
||||
, subscriberFace(makeDummyClientFace())
|
||||
, subscriber(*subscriberFace, streamPrefix)
|
||||
{
|
||||
}
|
||||
|
||||
/** \brief post one notification and deliver to subscriber
|
||||
*/
|
||||
void
|
||||
deliverNotification(const std::string& msg)
|
||||
{
|
||||
publisherFace->m_sentDatas.clear();
|
||||
SimpleNotification notification(msg);
|
||||
notificationStream.postNotification(notification);
|
||||
publisherFace->processEvents();
|
||||
BOOST_REQUIRE_EQUAL(publisherFace->m_sentDatas.size(), 1);
|
||||
|
||||
lastDeliveredSeqNo = publisherFace->m_sentDatas[0].getName().at(-1).toSequenceNumber();
|
||||
|
||||
lastNotification.setMessage("");
|
||||
subscriberFace->receive(publisherFace->m_sentDatas[0]);
|
||||
}
|
||||
|
||||
void
|
||||
afterNotification(const SimpleNotification& notification)
|
||||
{
|
||||
lastNotification = notification;
|
||||
}
|
||||
|
||||
void
|
||||
clearNotificationHandlers()
|
||||
{
|
||||
subscriber.onNotification.clear();
|
||||
}
|
||||
|
||||
void
|
||||
afterTimeout()
|
||||
{
|
||||
hasTimeout = true;
|
||||
}
|
||||
|
||||
void
|
||||
afterDecodeError(const Data& data)
|
||||
{
|
||||
lastDecodeErrorData = data;
|
||||
}
|
||||
|
||||
/** \return true if subscriberFace has an initial request as sole sent Interest
|
||||
*/
|
||||
bool
|
||||
hasInitialRequest() const
|
||||
{
|
||||
if (subscriberFace->m_sentInterests.size() != 1)
|
||||
return 0;
|
||||
|
||||
const Interest& interest = subscriberFace->m_sentInterests[0];
|
||||
return interest.getName() == streamPrefix &&
|
||||
interest.getChildSelector() == 1 &&
|
||||
interest.getMustBeFresh() &&
|
||||
interest.getInterestLifetime() ==
|
||||
NotificationSubscriber<SimpleNotification>::getInterestLifetime();
|
||||
}
|
||||
|
||||
/** \return sequence number of the continuation request sent from subscriberFace
|
||||
* or 0 if there's no such request as sole sent Interest
|
||||
*/
|
||||
uint64_t
|
||||
getRequestSeqNo() const
|
||||
{
|
||||
if (subscriberFace->m_sentInterests.size() != 1)
|
||||
return 0;
|
||||
|
||||
const Interest& interest = subscriberFace->m_sentInterests[0];
|
||||
const Name& name = interest.getName();
|
||||
if (streamPrefix.isPrefixOf(name) &&
|
||||
name.size() == streamPrefix.size() + 1 &&
|
||||
interest.getInterestLifetime() ==
|
||||
NotificationSubscriber<SimpleNotification>::getInterestLifetime())
|
||||
return name[-1].toSequenceNumber();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
Name streamPrefix;
|
||||
shared_ptr<DummyClientFace> publisherFace;
|
||||
ndn::KeyChain publisherKeyChain;
|
||||
NotificationStream<DummyClientFace> notificationStream;
|
||||
shared_ptr<DummyClientFace> subscriberFace;
|
||||
NotificationSubscriber<SimpleNotification> subscriber;
|
||||
|
||||
uint64_t lastDeliveredSeqNo;
|
||||
|
||||
SimpleNotification lastNotification;
|
||||
bool hasTimeout;
|
||||
Data lastDecodeErrorData;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(EndToEnd, EndToEndFixture)
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
|
||||
|
||||
// has no effect because onNotification has no handler
|
||||
subscriber.start();
|
||||
BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
|
||||
|
||||
subscriber.onNotification += bind(&EndToEndFixture::afterNotification, this, _1);
|
||||
subscriber.onTimeout += bind(&EndToEndFixture::afterTimeout, this);
|
||||
subscriber.onDecodeError += bind(&EndToEndFixture::afterDecodeError, this, _1);
|
||||
|
||||
// not received when subscriber is not running
|
||||
this->deliverNotification("n1");
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_CHECK(lastNotification.getMessage().empty());
|
||||
BOOST_CHECK_EQUAL(subscriberFace->m_sentInterests.size(), 0);
|
||||
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
subscriber.start();
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_REQUIRE_EQUAL(subscriber.isRunning(), true);
|
||||
BOOST_CHECK(this->hasInitialRequest());
|
||||
|
||||
// respond to initial request
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
this->deliverNotification("n2");
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n2");
|
||||
BOOST_CHECK_EQUAL(this->getRequestSeqNo(), lastDeliveredSeqNo + 1);
|
||||
|
||||
// respond to continuation request
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
this->deliverNotification("n3");
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n3");
|
||||
BOOST_CHECK_EQUAL(this->getRequestSeqNo(), lastDeliveredSeqNo + 1);
|
||||
|
||||
// timeout
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
lastNotification.setMessage("");
|
||||
subscriberFace->processEvents(
|
||||
NotificationSubscriber<SimpleNotification>::getInterestLifetime() +
|
||||
time::milliseconds(1000));
|
||||
BOOST_CHECK(lastNotification.getMessage().empty());
|
||||
BOOST_CHECK_EQUAL(hasTimeout, true);
|
||||
BOOST_CHECK(this->hasInitialRequest());
|
||||
|
||||
// decode error on sequence number
|
||||
Name wrongName = streamPrefix;
|
||||
wrongName.append("%07%07");
|
||||
Data wrongData(wrongName);
|
||||
publisherKeyChain.sign(wrongData);
|
||||
subscriberFace->receive(wrongData);
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
lastNotification.setMessage("");
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_CHECK(lastNotification.getMessage().empty());
|
||||
BOOST_CHECK_EQUAL(lastDecodeErrorData.getName(), wrongName);
|
||||
BOOST_CHECK(this->hasInitialRequest());
|
||||
|
||||
// decode error in payload
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
lastNotification.setMessage("");
|
||||
this->deliverNotification("\x07n4");
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_CHECK(lastNotification.getMessage().empty());
|
||||
BOOST_CHECK(this->hasInitialRequest());
|
||||
|
||||
// stop if handlers are cleared
|
||||
subscriber.onNotification += bind(&EndToEndFixture::clearNotificationHandlers, this);
|
||||
subscriberFace->m_sentInterests.clear();
|
||||
this->deliverNotification("n5");
|
||||
subscriberFace->processEvents(time::milliseconds(10));
|
||||
BOOST_CHECK_EQUAL(subscriberFace->m_sentInterests.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace tests
|
||||
} // namespace nfd
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "core/segment-publisher.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "tests/dummy-face.hpp"
|
||||
#include "tests/dummy-client-face.hpp"
|
||||
|
||||
#include <ndn-cxx/encoding/tlv.hpp>
|
||||
|
||||
@@ -38,10 +38,10 @@ namespace tests {
|
||||
NFD_LOG_INIT("SegmentPublisherTest");
|
||||
|
||||
template<int64_t N=10000>
|
||||
class TestSegmentPublisher : public SegmentPublisher<DummyFace>
|
||||
class TestSegmentPublisher : public SegmentPublisher<DummyClientFace>
|
||||
{
|
||||
public:
|
||||
TestSegmentPublisher(DummyFace& face,
|
||||
TestSegmentPublisher(DummyClientFace& face,
|
||||
const Name& prefix,
|
||||
ndn::KeyChain& keyChain)
|
||||
: SegmentPublisher(face, prefix, keyChain)
|
||||
@@ -90,7 +90,7 @@ class SegmentPublisherFixture : public BaseFixture
|
||||
{
|
||||
public:
|
||||
SegmentPublisherFixture()
|
||||
: m_face(makeDummyFace())
|
||||
: m_face(makeDummyClientFace())
|
||||
, m_publisher(*m_face, "/localhost/nfd/SegmentPublisherFixture", m_keyChain)
|
||||
{
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
shared_ptr<DummyFace> m_face;
|
||||
shared_ptr<DummyClientFace> m_face;
|
||||
TestSegmentPublisher<N> m_publisher;
|
||||
ndn::EncodingBuffer m_buffer;
|
||||
ndn::KeyChain m_keyChain;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_TESTS_CORE_SIMPLE_NOTIFICATION_HPP
|
||||
#define NFD_TESTS_CORE_SIMPLE_NOTIFICATION_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
class SimpleNotification
|
||||
{
|
||||
public:
|
||||
SimpleNotification()
|
||||
{
|
||||
}
|
||||
|
||||
SimpleNotification(const std::string& message)
|
||||
: m_message(message)
|
||||
{
|
||||
}
|
||||
|
||||
~SimpleNotification()
|
||||
{
|
||||
}
|
||||
|
||||
Block
|
||||
wireEncode() const
|
||||
{
|
||||
ndn::EncodingBuffer buffer;
|
||||
prependByteArrayBlock(buffer,
|
||||
0x8888,
|
||||
reinterpret_cast<const uint8_t*>(m_message.c_str()),
|
||||
m_message.size());
|
||||
return buffer.block();
|
||||
}
|
||||
|
||||
void
|
||||
wireDecode(const Block& block)
|
||||
{
|
||||
m_message.assign(reinterpret_cast<const char*>(block.value()),
|
||||
block.value_size());
|
||||
|
||||
// error for testing
|
||||
if (!m_message.empty() && m_message[0] == '\x07')
|
||||
throw tlv::Error("0x07 error");
|
||||
}
|
||||
|
||||
public:
|
||||
const std::string&
|
||||
getMessage() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
void
|
||||
setMessage(const std::string& message)
|
||||
{
|
||||
m_message = message;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_message;
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_TESTS_CORE_SIMPLE_NOTIFICATION_HPP
|
||||
@@ -1,142 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Foundation,
|
||||
* either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mgmt/notification-stream.hpp"
|
||||
#include "mgmt/internal-face.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
NFD_LOG_INIT("NotificationStreamTest");
|
||||
|
||||
|
||||
|
||||
class NotificationStreamFixture : public BaseFixture
|
||||
{
|
||||
public:
|
||||
NotificationStreamFixture()
|
||||
: m_callbackFired(false)
|
||||
, m_prefix("/localhost/nfd/NotificationStreamTest")
|
||||
, m_message("TestNotificationMessage")
|
||||
, m_sequenceNo(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~NotificationStreamFixture()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
validateCallback(const Data& data)
|
||||
{
|
||||
Name expectedName(m_prefix);
|
||||
expectedName.appendSegment(m_sequenceNo);
|
||||
BOOST_REQUIRE_EQUAL(data.getName(), expectedName);
|
||||
|
||||
ndn::Block payload = data.getContent();
|
||||
std::string message;
|
||||
|
||||
message.append(reinterpret_cast<const char*>(payload.value()), payload.value_size());
|
||||
|
||||
BOOST_REQUIRE_EQUAL(message, m_message);
|
||||
|
||||
m_callbackFired = true;
|
||||
++m_sequenceNo;
|
||||
}
|
||||
|
||||
void
|
||||
resetCallbackFired()
|
||||
{
|
||||
m_callbackFired = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool m_callbackFired;
|
||||
const std::string m_prefix;
|
||||
const std::string m_message;
|
||||
uint64_t m_sequenceNo;
|
||||
ndn::KeyChain m_keyChain;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(MgmtNotificationStream, NotificationStreamFixture)
|
||||
|
||||
class TestNotification
|
||||
{
|
||||
public:
|
||||
TestNotification(const std::string& message)
|
||||
: m_message(message)
|
||||
{
|
||||
}
|
||||
|
||||
~TestNotification()
|
||||
{
|
||||
}
|
||||
|
||||
Block
|
||||
wireEncode() const
|
||||
{
|
||||
ndn::EncodingBuffer buffer;
|
||||
|
||||
prependByteArrayBlock(buffer,
|
||||
ndn::Tlv::Content,
|
||||
reinterpret_cast<const uint8_t*>(m_message.c_str()),
|
||||
m_message.size());
|
||||
return buffer.block();
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string m_message;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestPostEvent)
|
||||
{
|
||||
shared_ptr<InternalFace> face(make_shared<InternalFace>());
|
||||
NotificationStream notificationStream(face, "/localhost/nfd/NotificationStreamTest", m_keyChain);
|
||||
|
||||
face->onReceiveData += bind(&NotificationStreamFixture::validateCallback, this, _1);
|
||||
|
||||
TestNotification event1(m_message);
|
||||
notificationStream.postNotification(event1);
|
||||
|
||||
BOOST_REQUIRE(m_callbackFired);
|
||||
|
||||
resetCallbackFired();
|
||||
|
||||
TestNotification event2(m_message);
|
||||
notificationStream.postNotification(event2);
|
||||
|
||||
BOOST_REQUIRE(m_callbackFired);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
||||
} // namespace tests
|
||||
} // namespace nfd
|
||||
@@ -23,8 +23,8 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_TESTS_DUMMY_FACE_HPP
|
||||
#define NFD_TESTS_DUMMY_FACE_HPP
|
||||
#ifndef NFD_TESTS_DUMMY_CLIENT_FACE_HPP
|
||||
#define NFD_TESTS_DUMMY_CLIENT_FACE_HPP
|
||||
|
||||
#include <ndn-cxx/face.hpp>
|
||||
#include <ndn-cxx/transport/transport.hpp>
|
||||
@@ -32,13 +32,14 @@
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
class DummyTransport : public ndn::Transport
|
||||
class DummyClientTransport : public ndn::Transport
|
||||
{
|
||||
public:
|
||||
void
|
||||
receive(const Block& block)
|
||||
{
|
||||
m_receiveCallback(block);
|
||||
if (static_cast<bool>(m_receiveCallback))
|
||||
m_receiveCallback(block);
|
||||
}
|
||||
|
||||
virtual void
|
||||
@@ -79,13 +80,13 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** \brief a Face for unit testing
|
||||
/** \brief a client-side face for unit testing
|
||||
*/
|
||||
class DummyFace : public ndn::Face
|
||||
class DummyClientFace : public ndn::Face
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
DummyFace(shared_ptr<DummyTransport> transport)
|
||||
DummyClientFace(shared_ptr<DummyClientTransport> transport)
|
||||
: Face(transport)
|
||||
, m_transport(transport)
|
||||
{
|
||||
@@ -103,20 +104,28 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
/** \brief sent Interests
|
||||
* \note After .expressInterest, .processEvents must be called before
|
||||
* the Interest would show up here.
|
||||
*/
|
||||
std::vector<Interest> m_sentInterests;
|
||||
/** \brief sent Datas
|
||||
* \note After .put, .processEvents must be called before
|
||||
* the Interest would show up here.
|
||||
*/
|
||||
std::vector<Data> m_sentDatas;
|
||||
|
||||
private:
|
||||
shared_ptr<DummyTransport> m_transport;
|
||||
shared_ptr<DummyClientTransport> m_transport;
|
||||
};
|
||||
|
||||
inline shared_ptr<DummyFace>
|
||||
makeDummyFace()
|
||||
inline shared_ptr<DummyClientFace>
|
||||
makeDummyClientFace()
|
||||
{
|
||||
return make_shared<DummyFace>(make_shared<DummyTransport>());
|
||||
return make_shared<DummyClientFace>(make_shared<DummyClientTransport>());
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_TESTS_DUMMY_FACE_HPP
|
||||
#endif // NFD_TESTS_DUMMY_CLIENT_FACE_HPP
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "rib/rib-manager.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
#include "tests/dummy-face.hpp"
|
||||
#include "tests/dummy-client-face.hpp"
|
||||
#include "rib/rib-status-publisher-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
, ADD_NEXTHOP_VERB("add-nexthop")
|
||||
, REMOVE_NEXTHOP_VERB("remove-nexthop")
|
||||
{
|
||||
face = nfd::tests::makeDummyFace();
|
||||
face = nfd::tests::makeDummyClientFace();
|
||||
|
||||
manager = make_shared<RibManager>(ndn::ref(*face));
|
||||
manager->registerWithNfd();
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
public:
|
||||
shared_ptr<RibManager> manager;
|
||||
shared_ptr<nfd::tests::DummyFace> face;
|
||||
shared_ptr<nfd::tests::DummyClientFace> face;
|
||||
|
||||
const Name COMMAND_PREFIX;
|
||||
const Name::Component ADD_NEXTHOP_VERB;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "rib/rib-status-publisher.hpp"
|
||||
|
||||
#include "rib-status-publisher-common.hpp"
|
||||
#include "tests/dummy-face.hpp"
|
||||
#include "tests/dummy-client-face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace rib {
|
||||
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(Basic)
|
||||
rib.insert(name, entry);
|
||||
|
||||
ndn::KeyChain keyChain;
|
||||
shared_ptr<nfd::tests::DummyFace> face = nfd::tests::makeDummyFace();
|
||||
shared_ptr<nfd::tests::DummyClientFace> face = nfd::tests::makeDummyClientFace();
|
||||
RibStatusPublisher publisher(rib, *face, "/localhost/nfd/rib/list", keyChain);
|
||||
|
||||
publisher.publish();
|
||||
|
||||
+6
-46
@@ -26,7 +26,6 @@
|
||||
#include <ndn-cxx/face.hpp>
|
||||
#include <ndn-cxx/name.hpp>
|
||||
|
||||
#include <ndn-cxx/management/nfd-face-event-notification.hpp>
|
||||
#include <ndn-cxx/management/nfd-controller.hpp>
|
||||
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
@@ -35,6 +34,7 @@
|
||||
|
||||
#include "version.hpp"
|
||||
#include "core/face-uri.hpp"
|
||||
#include "core/face-monitor.hpp"
|
||||
#include "network.hpp"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
@@ -49,7 +49,7 @@ class AutoregServer : boost::noncopyable
|
||||
public:
|
||||
AutoregServer()
|
||||
: m_controller(m_face)
|
||||
// , m_lastNotification(<undefined>)
|
||||
, m_faceMonitor(m_face)
|
||||
, m_cost(255)
|
||||
{
|
||||
}
|
||||
@@ -130,13 +130,8 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
onNotification(const Data& data)
|
||||
onNotification(const FaceEventNotification& notification)
|
||||
{
|
||||
m_lastNotification = data.getName().get(-1).toSegment();
|
||||
|
||||
// process
|
||||
FaceEventNotification notification(data.getContent().blockFromValue());
|
||||
|
||||
if (notification.getKind() == FACE_EVENT_CREATED &&
|
||||
!notification.isLocal() &&
|
||||
notification.isOnDemand())
|
||||
@@ -147,33 +142,6 @@ public:
|
||||
{
|
||||
std::cerr << "IGNORED: " << notification << std::endl;
|
||||
}
|
||||
|
||||
Name nextNotification("/localhost/nfd/faces/events");
|
||||
nextNotification
|
||||
.appendSegment(m_lastNotification + 1);
|
||||
|
||||
// no need to set freshness or child selectors
|
||||
m_face.expressInterest(nextNotification,
|
||||
bind(&AutoregServer::onNotification, this, _2),
|
||||
bind(&AutoregServer::onTimeout, this, _1));
|
||||
}
|
||||
|
||||
void
|
||||
onTimeout(const Interest& timedOutInterest)
|
||||
{
|
||||
// re-express the timed out interest, but reset Nonce, since it has to change
|
||||
|
||||
// To be robust against missing notification, use ChildSelector and MustBeFresh
|
||||
Interest interest("/localhost/nfd/faces/events");
|
||||
interest
|
||||
.setMustBeFresh(true)
|
||||
.setChildSelector(1)
|
||||
.setInterestLifetime(time::seconds(60))
|
||||
;
|
||||
|
||||
m_face.expressInterest(interest,
|
||||
bind(&AutoregServer::onNotification, this, _2),
|
||||
bind(&AutoregServer::onTimeout, this, _1));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -225,16 +193,8 @@ public:
|
||||
std::cout << " " << *network << std::endl;
|
||||
}
|
||||
|
||||
Interest interest("/localhost/nfd/faces/events");
|
||||
interest
|
||||
.setMustBeFresh(true)
|
||||
.setChildSelector(1)
|
||||
.setInterestLifetime(time::seconds(60))
|
||||
;
|
||||
|
||||
m_face.expressInterest(interest,
|
||||
bind(&AutoregServer::onNotification, this, _2),
|
||||
bind(&AutoregServer::onTimeout, this, _1));
|
||||
m_faceMonitor.onNotification += bind(&AutoregServer::onNotification, this, _1);
|
||||
m_faceMonitor.start();
|
||||
|
||||
boost::asio::signal_set signalSet(m_face.getIoService(), SIGINT, SIGTERM);
|
||||
signalSet.async_wait(bind(&AutoregServer::signalHandler, this));
|
||||
@@ -314,7 +274,7 @@ public:
|
||||
private:
|
||||
Face m_face;
|
||||
Controller m_controller;
|
||||
uint64_t m_lastNotification;
|
||||
FaceMonitor m_faceMonitor;
|
||||
std::vector<ndn::Name> m_autoregPrefixes;
|
||||
uint64_t m_cost;
|
||||
std::vector<Network> m_whiteList;
|
||||
|
||||
Reference in new issue
Block a user