rib+tools: Make use of ndn::nfd::FaceMonitor from the ndn-cxx library

NFD still uses its own NotificationStream, as ApiFace needs to be
changed to use library's version of the class.

Change-Id: Ifc5727a555528a1aa48ccf7379fcbb61a33049d7
diff --git a/core/face-monitor.hpp b/core/face-monitor.hpp
deleted file mode 100644
index 521fc23..0000000
--- a/core/face-monitor.hpp
+++ /dev/null
@@ -1,48 +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/>.
- */
-
-#ifndef NFD_CORE_FACE_MONITOR_HPP
-#define NFD_CORE_FACE_MONITOR_HPP
-
-#include "notification-subscriber.hpp"
-
-#include <ndn-cxx/management/nfd-face-event-notification.hpp>
-
-namespace nfd {
-
-using ndn::nfd::FaceEventNotification;
-
-class FaceMonitor : public NotificationSubscriber<FaceEventNotification>
-{
-public:
-  FaceMonitor(ndn::Face& face)
-    : NotificationSubscriber<FaceEventNotification>(face, "ndn:/localhost/nfd/faces/events")
-  {
-  }
-};
-
-} // namespace nfd
-
-#endif // NFD_CORE_FACE_MONITOR_HPP
diff --git a/core/notification-subscriber.hpp b/core/notification-subscriber.hpp
deleted file mode 100644
index c359c82..0000000
--- a/core/notification-subscriber.hpp
+++ /dev/null
@@ -1,214 +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/>.
- */
-
-#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
diff --git a/rib/rib-manager.hpp b/rib/rib-manager.hpp
index c31256e..d08ab50 100644
--- a/rib/rib-manager.hpp
+++ b/rib/rib-manager.hpp
@@ -27,11 +27,11 @@
 #define NFD_RIB_RIB_MANAGER_HPP
 
 #include "rib.hpp"
-#include "face-monitor.hpp"
 #include "core/config-file.hpp"
 #include "rib-status-publisher.hpp"
 
 #include <ndn-cxx/security/validator-config.hpp>
+#include <ndn-cxx/management/nfd-face-monitor.hpp>
 #include <ndn-cxx/management/nfd-controller.hpp>
 #include <ndn-cxx/management/nfd-control-command.hpp>
 #include <ndn-cxx/management/nfd-control-response.hpp>
@@ -44,6 +44,8 @@
 using ndn::nfd::ControlResponse;
 using ndn::nfd::ControlParameters;
 
+using ndn::nfd::FaceEventNotification;
+
 class RibManager : noncopyable
 {
 public:
@@ -221,7 +223,7 @@
   ndn::KeyChain m_keyChain;
   ndn::ValidatorConfig m_localhostValidator;
   ndn::ValidatorConfig m_localhopValidator;
-  FaceMonitor m_faceMonitor;
+  ndn::nfd::FaceMonitor m_faceMonitor;
   bool m_isLocalhopEnabled;
 
   RibStatusPublisher m_ribStatusPublisher;
diff --git a/tests/core/notification-subscriber.cpp b/tests/core/notification-subscriber.cpp
deleted file mode 100644
index 12834f6..0000000
--- a/tests/core/notification-subscriber.cpp
+++ /dev/null
@@ -1,223 +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 "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
diff --git a/tools/nfd-autoreg.cpp b/tools/nfd-autoreg.cpp
index b0c46c9..a262220 100644
--- a/tools/nfd-autoreg.cpp
+++ b/tools/nfd-autoreg.cpp
@@ -27,6 +27,7 @@
 #include <ndn-cxx/name.hpp>
 
 #include <ndn-cxx/management/nfd-controller.hpp>
+#include <ndn-cxx/management/nfd-face-monitor.hpp>
 
 #include <boost/program_options/options_description.hpp>
 #include <boost/program_options/variables_map.hpp>
@@ -34,7 +35,6 @@
 
 #include "version.hpp"
 #include "core/face-uri.hpp"
-#include "core/face-monitor.hpp"
 #include "network.hpp"
 
 namespace po = boost::program_options;
@@ -43,6 +43,7 @@
 
 using namespace ndn::nfd;
 using ndn::Face;
+using ndn::nfd::FaceEventNotification;
 
 class AutoregServer : boost::noncopyable
 {