Use PendingInterestHandle and ScopedRegisteredPrefixHandle

Refs: #3919, #4316
Change-Id: I1cc5dcda07ae50e5c1afa067d1a00227f71c2233
diff --git a/src/access-manager.cpp b/src/access-manager.cpp
index 5fb34ab..368c44a 100644
--- a/src/access-manager.cpp
+++ b/src/access-manager.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2018, Regents of the University of California
+/*
+ * Copyright (c) 2014-2019, Regents of the University of California
  *
  * NAC library is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -52,7 +52,7 @@
   // kek looks like a cert, but doesn't have ValidityPeriod
   m_ims.insert(*kek);
 
-  auto serveFromIms = [this] (const Name& prefix, const Interest& interest) {
+  auto serveFromIms = [this] (const Name&, const Interest& interest) {
     auto data = m_ims.find(interest);
     if (data != nullptr) {
       NDN_LOG_DEBUG("Serving " << data->getName() << " from InMemoryStorage");
@@ -68,16 +68,10 @@
     NDN_LOG_ERROR("Failed to register prefix " << prefix << ": " << msg);
   };
 
-  m_kekRegId = m_face.setInterestFilter(kekPrefix, serveFromIms, handleError);
+  m_kekReg = m_face.setInterestFilter(kekPrefix, serveFromIms, handleError);
 
   auto kdkPrefix = Name(m_nacKey.getIdentity()).append(KDK).append(nacKeyId);
-  m_kdkRegId = m_face.setInterestFilter(kdkPrefix, serveFromIms, handleError);
-}
-
-AccessManager::~AccessManager()
-{
-  m_face.unsetInterestFilter(m_kekRegId);
-  m_face.unsetInterestFilter(m_kdkRegId);
+  m_kdkReg = m_face.setInterestFilter(kdkPrefix, serveFromIms, handleError);
 }
 
 Data
diff --git a/src/access-manager.hpp b/src/access-manager.hpp
index d2a6f74..3491955 100644
--- a/src/access-manager.hpp
+++ b/src/access-manager.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2018, Regents of the University of California
+/*
+ * Copyright (c) 2014-2019, Regents of the University of California
  *
  * NAC library is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -70,8 +70,6 @@
   AccessManager(const Identity& identity, const Name& dataset,
                 KeyChain& keyChain, Face& face);
 
-  ~AccessManager();
-
   /**
    * @brief Authorize a member identified by its certificate @p memberCert to decrypt data
    *        under the policy
@@ -131,8 +129,8 @@
   Face& m_face;
 
   InMemoryStoragePersistent m_ims; // for KEK and KDKs
-  const RegisteredPrefixId* m_kekRegId;
-  const RegisteredPrefixId* m_kdkRegId;
+  ScopedRegisteredPrefixHandle m_kekReg;
+  ScopedRegisteredPrefixHandle m_kdkReg;
 };
 
 } // namespace nac
diff --git a/src/decryptor.cpp b/src/decryptor.cpp
index 25043d5..80ccb93 100644
--- a/src/decryptor.cpp
+++ b/src/decryptor.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2018, Regents of the University of California
+/*
+ * Copyright (c) 2014-2019, Regents of the University of California
  *
  * NAC library is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -40,20 +40,20 @@
 Decryptor::~Decryptor()
 {
   for (auto& i : m_cks) {
-    if (i.second.pendingInterest != nullptr) {
-      m_face.removePendingInterest(i.second.pendingInterest);
-      i.second.pendingInterest = nullptr;
-
+    if (i.second.pendingInterest) {
+      i.second.pendingInterest->cancel();
       for (const auto& p : i.second.pendingDecrypts) {
-        p.onFailure(ErrorCode::CkRetrievalFailure, "Cancel pending decrypt as ContentKey is being destroyed");
+        p.onFailure(ErrorCode::CkRetrievalFailure,
+                    "Cancel pending decrypt as ContentKey is being destroyed");
       }
-      i.second.pendingDecrypts.clear(); // not really necessary, but just in case
     }
   }
 }
 
 void
-Decryptor::decrypt(const Block& encryptedContent, const DecryptSuccessCallback& onSuccess, const ErrorCallback& onFailure)
+Decryptor::decrypt(const Block& encryptedContent,
+                   const DecryptSuccessCallback& onSuccess,
+                   const ErrorCallback& onFailure)
 {
   EncryptedContent ec(encryptedContent);
   if (!ec.hasKeyLocator()) {
@@ -104,7 +104,7 @@
                                                        .setMustBeFresh(false) // ?
                                                        .setCanBePrefix(true),
     [=] (const Interest& ckInterest, const Data& ckData) {
-      ck->second.pendingInterest = nullptr;
+      ck->second.pendingInterest = nullopt;
       // @TODO verify if the key is legit
       Name kdkPrefix, kdkIdentity, kdkKeyName;
       std::tie(kdkPrefix, kdkIdentity, kdkKeyName) =
@@ -127,13 +127,13 @@
       fetchKdk(ck, kdkPrefix, ckData, onFailure, N_RETRIES);
     },
     [=] (const Interest& i, const lp::Nack& nack) {
-      ck->second.pendingInterest = nullptr;
+      ck->second.pendingInterest = nullopt;
       onFailure(ErrorCode::CkRetrievalFailure,
                 "Retrieval of CK [" + i.getName().toUri() + "] failed. "
                 "Got NACK (" + boost::lexical_cast<std::string>(nack.getReason()) + ")");
     },
     [=] (const Interest& i) {
-      ck->second.pendingInterest = nullptr;
+      ck->second.pendingInterest = nullopt;
       if (nTriesLeft > 1) {
         fetchCk(ck, onFailure, nTriesLeft - 1);
       }
@@ -164,8 +164,8 @@
   ck->second.pendingInterest = m_face.expressInterest(Interest(kdkName)
                                                      .setMustBeFresh(true)
                                                      .setCanBePrefix(false),
-    [=] (const Interest& ckInterest, const Data& kdkData) {
-      ck->second.pendingInterest = nullptr;
+    [=] (const Interest&, const Data& kdkData) {
+      ck->second.pendingInterest = nullopt;
       // @TODO verify if the key is legit
 
       bool isOk = decryptAndImportKdk(kdkData, onFailure);
@@ -176,13 +176,13 @@
                                          onFailure);
     },
     [=] (const Interest& i, const lp::Nack& nack) {
-      ck->second.pendingInterest = nullptr;
+      ck->second.pendingInterest = nullopt;
       onFailure(ErrorCode::KdkRetrievalFailure,
                 "Retrieval of KDK [" + i.getName().toUri() + "] failed. "
                 "Got NACK (" + boost::lexical_cast<std::string>(nack.getReason()) + ")");
     },
     [=] (const Interest& i) {
-      ck->second.pendingInterest = nullptr;
+      ck->second.pendingInterest = nullopt;
       if (nTriesLeft > 1) {
         fetchKdk(ck, kdkPrefix, ckData, onFailure, nTriesLeft - 1);
       }
diff --git a/src/decryptor.hpp b/src/decryptor.hpp
index d2d6406..edc6f2d 100644
--- a/src/decryptor.hpp
+++ b/src/decryptor.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2018, Regents of the University of California
+/*
+ * Copyright (c) 2014-2019, Regents of the University of California
  *
  * NAC library is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -44,7 +44,7 @@
   {
     bool isRetrieved = false;
     Buffer bits;
-    const PendingInterestId* pendingInterest = nullptr;
+    optional<PendingInterestHandle> pendingInterest;
 
     struct PendingDecrypt
     {
diff --git a/src/encryptor.cpp b/src/encryptor.cpp
index 885c79b..68ac6eb 100644
--- a/src/encryptor.cpp
+++ b/src/encryptor.cpp
@@ -39,14 +39,13 @@
   , m_ckDataSigningInfo{std::move(ckDataSigningInfo)}
   , m_isKekRetrievalInProgress(false)
   , m_onFailure(onFailure)
-  , m_ckRegId{nullptr}
   , m_keyChain{keyChain}
   , m_face{face}
   , m_scheduler{face.getIoService()}
 {
   regenerateCk();
 
-  auto serveFromIms = [this] (const Name& prefix, const Interest& interest) {
+  auto serveFromIms = [this] (const Name&, const Interest& interest) {
     auto data = m_ims.find(interest);
     if (data != nullptr) {
       NDN_LOG_DEBUG("Serving " << data->getName() << " from InMemoryStorage");
@@ -62,15 +61,12 @@
     NDN_LOG_ERROR("Failed to register prefix " << prefix << ": " << msg);
   };
 
-  m_ckRegId = m_face.setInterestFilter(Name(ckPrefix).append(CK), serveFromIms, handleError);
+  m_ckReg = m_face.setInterestFilter(Name(ckPrefix).append(CK), serveFromIms, handleError);
 }
 
 Encryptor::~Encryptor()
 {
-  m_face.unsetInterestFilter(m_ckRegId);
-  if (m_kekPendingInterest != nullptr) {
-    m_face.removePendingInterest(m_kekPendingInterest);
-  }
+  m_kekPendingInterest.cancel();
 }
 
 void
@@ -140,51 +136,46 @@
                                     const ErrorCallback& onFailure,
                                     size_t nTriesLeft)
 {
-  // interest for <access-prefix>/KEK to retrieve  <access-prefix>/KEK/<key-id> KekData
+  // interest for <access-prefix>/KEK to retrieve <access-prefix>/KEK/<key-id> KekData
 
   NDN_LOG_DEBUG("Fetching KEK " << Name(m_accessPrefix).append(KEK));
 
-  BOOST_ASSERT(m_kekPendingInterest == nullptr);
-  m_kekPendingInterest =
-    m_face.expressInterest(Interest(Name(m_accessPrefix).append(KEK))
-                             .setMustBeFresh(true)
-                             .setCanBePrefix(true),
-                           [=] (const Interest&, const Data& kek) {
-                             m_kekPendingInterest = nullptr;
-                             // @todo verify if the key is legit
-                             m_kek = kek;
-                             if (makeAndPublishCkData(onFailure)) {
-                               onReady();
-                             }
-                             // otherwise, failure has been already declared
-                           },
-                           [=] (const Interest& i, const lp::Nack& nack) {
-                             m_kekPendingInterest = nullptr;
-                             if (nTriesLeft > 1) {
-                               m_scheduler.schedule(RETRY_DELAY_AFTER_NACK, [=] {
-                                 fetchKekAndPublishCkData(onReady, onFailure, nTriesLeft - 1);
-                               });
-                             }
-                             else {
-                               onFailure(ErrorCode::KekRetrievalFailure,
-                                         "Retrieval of KEK [" + i.getName().toUri() + "] failed. "
-                                         "Got NACK (" + boost::lexical_cast<std::string>(nack.getReason()) + ")");
-                               NDN_LOG_DEBUG("Scheduling retry from NACK");
-                               m_scheduler.schedule(RETRY_DELAY_KEK_RETRIEVAL, [this] { retryFetchingKek(); });
-                             }
-                           },
-                           [=] (const Interest& i) {
-                             m_kekPendingInterest = nullptr;
-                             if (nTriesLeft > 1) {
-                               fetchKekAndPublishCkData(onReady, onFailure, nTriesLeft - 1);
-                             }
-                             else {
-                               onFailure(ErrorCode::KekRetrievalTimeout,
-                                         "Retrieval of KEK [" + i.getName().toUri() + "] timed out");
-                               NDN_LOG_DEBUG("Scheduling retry after all timeouts");
-                               m_scheduler.schedule(RETRY_DELAY_KEK_RETRIEVAL, [this] { retryFetchingKek(); });
-                             }
-                           });
+  auto kekInterest = Interest(Name(m_accessPrefix).append(KEK))
+                     .setCanBePrefix(true)
+                     .setMustBeFresh(true);
+  m_kekPendingInterest = m_face.expressInterest(kekInterest,
+    [=] (const Interest&, const Data& kek) {
+      // @todo verify if the key is legit
+      m_kek = kek;
+      if (makeAndPublishCkData(onFailure)) {
+        onReady();
+      }
+      // otherwise, failure has been already declared
+    },
+    [=] (const Interest& i, const lp::Nack& nack) {
+      if (nTriesLeft > 1) {
+        m_scheduler.schedule(RETRY_DELAY_AFTER_NACK, [=] {
+          fetchKekAndPublishCkData(onReady, onFailure, nTriesLeft - 1);
+        });
+      }
+      else {
+        onFailure(ErrorCode::KekRetrievalFailure, "Retrieval of KEK [" + i.getName().toUri() +
+                  "] failed. Got NACK with reason " + boost::lexical_cast<std::string>(nack.getReason()));
+        NDN_LOG_DEBUG("Scheduling retry from NACK");
+        m_scheduler.schedule(RETRY_DELAY_KEK_RETRIEVAL, [this] { retryFetchingKek(); });
+      }
+    },
+    [=] (const Interest& i) {
+      if (nTriesLeft > 1) {
+        fetchKekAndPublishCkData(onReady, onFailure, nTriesLeft - 1);
+      }
+      else {
+        onFailure(ErrorCode::KekRetrievalTimeout,
+                  "Retrieval of KEK [" + i.getName().toUri() + "] timed out");
+        NDN_LOG_DEBUG("Scheduling retry after all timeouts");
+        m_scheduler.schedule(RETRY_DELAY_KEK_RETRIEVAL, [this] { retryFetchingKek(); });
+      }
+    });
 }
 
 bool
@@ -207,7 +198,7 @@
     NDN_LOG_DEBUG("Publishing CK data: " << ckData->getName());
     return true;
   }
-  catch (const std::runtime_error& error) {
+  catch (const std::runtime_error&) {
     onFailure(ErrorCode::EncryptionFailure, "Failed to encrypt generated CK with KEK " + m_kek->getName().toUri());
     return false;
   }
diff --git a/src/encryptor.hpp b/src/encryptor.hpp
index 21a9297..9656674 100644
--- a/src/encryptor.hpp
+++ b/src/encryptor.hpp
@@ -139,8 +139,8 @@
   ErrorCallback m_onFailure;
 
   InMemoryStoragePersistent m_ims; // for encrypted CKs
-  const RegisteredPrefixId* m_ckRegId = nullptr;
-  const PendingInterestId* m_kekPendingInterest = nullptr;
+  ScopedRegisteredPrefixHandle m_ckReg;
+  PendingInterestHandle m_kekPendingInterest;
 
   KeyChain& m_keyChain;
   Face& m_face;