Added support for removePendingInterest and removeRegisteredPrefix.
diff --git a/ndn-cpp/face.cpp b/ndn-cpp/face.cpp
index 342a585..febdc7b 100644
--- a/ndn-cpp/face.cpp
+++ b/ndn-cpp/face.cpp
@@ -10,17 +10,17 @@
 
 namespace ndn {
   
-void 
+unsigned int 
 Face::expressInterest(const Name& name, const Interest *interestTemplate, const OnData& onData, const OnTimeout& onTimeout)
 {
   if (interestTemplate)
-    node_.expressInterest(Interest
+    return node_.expressInterest(Interest
       (name, interestTemplate->getMinSuffixComponents(), interestTemplate->getMaxSuffixComponents(),
        interestTemplate->getPublisherPublicKeyDigest(), interestTemplate->getExclude(),
        interestTemplate->getChildSelector(), interestTemplate->getAnswerOriginKind(),
        interestTemplate->getScope(), interestTemplate->getInterestLifetimeMilliseconds()), onData, onTimeout);
   else
-    node_.expressInterest(Interest(name, 4000.0), onData, onTimeout);  
+    return node_.expressInterest(Interest(name, 4000.0), onData, onTimeout);  
 }
 
 void 
diff --git a/ndn-cpp/face.hpp b/ndn-cpp/face.hpp
index c3ced09..26161ab 100644
--- a/ndn-cpp/face.hpp
+++ b/ndn-cpp/face.hpp
@@ -45,11 +45,12 @@
    * use func_lib::ref() as appropriate.
    * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
    * This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @return The pending interest ID which can be used with removePendingInterest.
    */
-  void 
+  unsigned int 
   expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout = OnTimeout())
   {
-    node_.expressInterest(interest, onData, onTimeout);
+    return node_.expressInterest(interest, onData, onTimeout);
   }
 
   /**
@@ -61,8 +62,9 @@
    * use func_lib::ref() as appropriate.
    * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
    * This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @return The pending interest ID which can be used with removePendingInterest.
    */
-  void 
+  unsigned int 
   expressInterest(const Name& name, const Interest *interestTemplate, const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
 
   /**
@@ -73,11 +75,24 @@
    * use func_lib::ref() as appropriate.
    * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
    * This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @return The pending interest ID which can be used with removePendingInterest.
    */
-  void 
+  unsigned int 
   expressInterest(const Name& name, const OnData& onData, const OnTimeout& onTimeout = OnTimeout()) 
   {
-    expressInterest(name, 0, onData, onTimeout);
+    return expressInterest(name, 0, onData, onTimeout);
+  }
+
+  /**
+   * Remove the pending interest entry with the pendingInterestId from the pending interest table.
+   * This does not affect another pending interest with a different pendingInterestId, even it if has the same interest name.
+   * If there is no entry with the pendingInterestId, do nothing.
+   * @param pendingInterestId The ID returned from expressInterest.
+   */
+  void
+  removePendingInterest(unsigned int pendingInterestId)
+  {
+    node_.removePendingInterest(pendingInterestId);
   }
   
   /**
@@ -90,13 +105,26 @@
    * @param flags The flags for finer control of which interests are forward to the application.  If omitted, use 
    * the default flags defined by the default ForwardingFlags constructor.
    * @param wireFormat A WireFormat object used to encode the input. If omitted, use WireFormat getDefaultWireFormat().
+   * @return The registered prefix ID which can be used with removeRegisteredPrefix.
    */
-  void 
+  unsigned int 
   registerPrefix
     (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags = ForwardingFlags(), 
      WireFormat& wireFormat = *WireFormat::getDefaultWireFormat())
   {
-    node_.registerPrefix(prefix, onInterest, onRegisterFailed, flags, wireFormat);
+    return node_.registerPrefix(prefix, onInterest, onRegisterFailed, flags, wireFormat);
+  }
+
+  /**
+   * Remove the registered prefix entry with the registeredPrefixId from the pending interest table.  
+   * This does not affect another registered prefix with a different registeredPrefixId, even it if has the same prefix name.
+   * If there is no entry with the registeredPrefixId, do nothing.
+   * @param registeredPrefixId The ID returned from registerPrefix.
+   */
+  void
+  removeRegisteredPrefix(unsigned int registeredPrefixId)
+  {
+    node_.removeRegisteredPrefix(registeredPrefixId);
   }
   
   /**
diff --git a/ndn-cpp/node.cpp b/ndn-cpp/node.cpp
index 0309174..a86bdff 100644
--- a/ndn-cpp/node.cpp
+++ b/ndn-cpp/node.cpp
@@ -65,6 +65,9 @@
 0x30, 0x18, 0xeb, 0x90, 0xfb, 0x17, 0xd3, 0xce, 0xb5
 };
 
+unsigned int Node::PendingInterest::lastPendingInterestId_ = 0;
+unsigned int Node::RegisteredPrefix::lastRegisteredPrefixId_ = 0;
+
 /**
  * Set the KeyLocator using the full SELFREG_PUBLIC_KEY_DER, sign the data packet using SELFREG_PRIVATE_KEY_DER 
  * and set the signature.
@@ -120,33 +123,64 @@
 {
 }
 
-void 
+unsigned int 
 Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
 {
   // TODO: Properly check if we are already connected to the expected host.
   if (!transport_->getIsConnected())
     transport_->connect(*connectionInfo_, *this);
   
-  pit_.push_back(shared_ptr<PitEntry>(new PitEntry(shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout)));
+  unsigned int pendingInterestId = PendingInterest::getNextPendingInterestId();
+  pendingInterestTable_.push_back(shared_ptr<PendingInterest>(new PendingInterest
+    (pendingInterestId, shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout)));
   
   Blob encoding = interest.wireEncode();  
   transport_->send(*encoding);
+  
+  return pendingInterestId;
 }
 
-void 
+void
+Node::removePendingInterest(unsigned int pendingInterestId)
+{
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though pendingInterestId should be unique.
+  for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
+    if (pendingInterestTable_[i]->getPendingInterestId() == pendingInterestId)
+      pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
+  }
+}
+
+unsigned int 
 Node::registerPrefix
   (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags, WireFormat& wireFormat)
 {
+  // Get the registeredPrefixId now so we can return it to the caller.
+  unsigned int registeredPrefixId = RegisteredPrefix::getNextRegisteredPrefixId();
+
   if (ndndId_.size() == 0) {
     // First fetch the ndndId of the connected hub.
     NdndIdFetcher fetcher
       (shared_ptr<NdndIdFetcher::Info>(new NdndIdFetcher::Info
-        (this, prefix, onInterest, onRegisterFailed, flags, wireFormat)));
+        (this, registeredPrefixId, prefix, onInterest, onRegisterFailed, flags, wireFormat)));
     // It is OK for func_lib::function make a copy of the function object because the Info is in a shared_ptr.
     expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
   }
   else
-    registerPrefixHelper(make_shared<const Name>(prefix), onInterest, onRegisterFailed, flags, wireFormat);
+    registerPrefixHelper(registeredPrefixId, make_shared<const Name>(prefix), onInterest, onRegisterFailed, flags, wireFormat);
+  
+  return registeredPrefixId;
+}
+
+void
+Node::removeRegisteredPrefix(unsigned int registeredPrefixId)
+{
+  // Go backwards through the list so we can erase entries.
+  // Remove all entries even though pendingInterestId should be unique.
+  for (int i = (int)registeredPrefixTable_.size() - 1; i >= 0; --i) {
+    if (registeredPrefixTable_[i]->getRegisteredPrefixId() == registeredPrefixId)
+      registeredPrefixTable_.erase(registeredPrefixTable_.begin() + i);
+  }
 }
 
 void 
@@ -158,7 +192,7 @@
     // TODO: If there are multiple connected hubs, the NDN ID is really stored per connected hub.
     info_->node_.ndndId_ = signature->getPublisherPublicKeyDigest().getPublisherPublicKeyDigest();
     info_->node_.registerPrefixHelper
-      (info_->prefix_, info_->onInterest_, info_->onRegisterFailed_, info_->flags_, info_->wireFormat_);
+      (info_->registeredPrefixId_, info_->prefix_, info_->onInterest_, info_->onRegisterFailed_, info_->flags_, info_->wireFormat_);
   }
   else
     info_->onRegisterFailed_(info_->prefix_);
@@ -172,7 +206,7 @@
 
 void 
 Node::registerPrefixHelper
-  (const shared_ptr<const Name>& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
+  (unsigned int registeredPrefixId, const shared_ptr<const Name>& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
    const ForwardingFlags& flags, WireFormat& wireFormat)
 {
   // Create a ForwardingEntry.
@@ -201,7 +235,7 @@
   Blob encodedInterest = interest.wireEncode();
   
   // Save the onInterest callback and send the registration interest.
-  registeredPrefixTable_.push_back(shared_ptr<PrefixEntry>(new PrefixEntry(prefix, onInterest)));
+  registeredPrefixTable_.push_back(shared_ptr<RegisteredPrefix>(new RegisteredPrefix(registeredPrefixId, prefix, onInterest)));
   
   transport_->send(*encodedInterest);
 }
@@ -213,9 +247,9 @@
   
   // Check for PIT entry timeouts.  Go backwards through the list so we can erase entries.
   double nowMilliseconds = getNowMilliseconds();
-  for (int i = (int)pit_.size() - 1; i >= 0; --i) {
-    if (pit_[i]->checkTimeout(this, nowMilliseconds)) {
-      pit_.erase(pit_.begin() + i);
+  for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
+    if (pendingInterestTable_[i]->checkTimeout(this, nowMilliseconds)) {
+      pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
       
       // Refresh now since the timeout callback might have delayed.
       nowMilliseconds = getNowMilliseconds();
@@ -232,7 +266,7 @@
     shared_ptr<Interest> interest(new Interest());
     interest->wireDecode(element, elementLength);
     
-    PrefixEntry *entry = getEntryForRegisteredPrefix(interest->getName());
+    RegisteredPrefix *entry = getEntryForRegisteredPrefix(interest->getName());
     if (entry)
       entry->getOnInterest()(entry->getPrefix(), interest, *transport_);
   }
@@ -243,9 +277,9 @@
     int iPitEntry = getEntryIndexForExpressedInterest(data->getName());
     if (iPitEntry >= 0) {
       // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
-      const OnData onData = pit_[iPitEntry]->getOnData();
-      const shared_ptr<const Interest> interest = pit_[iPitEntry]->getInterest();
-      pit_.erase(pit_.begin() + iPitEntry);
+      const OnData onData = pendingInterestTable_[iPitEntry]->getOnData();
+      const shared_ptr<const Interest> interest = pendingInterestTable_[iPitEntry]->getInterest();
+      pendingInterestTable_.erase(pendingInterestTable_.begin() + iPitEntry);
       onData(interest, data);
     }
   }
@@ -269,10 +303,11 @@
   
   int iResult = -1;
     
-	for (size_t i = 0; i < pit_.size(); ++i) {
-		if (ndn_Interest_matchesName((struct ndn_Interest *)&pit_[i]->getInterestStruct(), &nameStruct)) {
+	for (size_t i = 0; i < pendingInterestTable_.size(); ++i) {
+		if (ndn_Interest_matchesName((struct ndn_Interest *)&pendingInterestTable_[i]->getInterestStruct(), &nameStruct)) {
       if (iResult < 0 || 
-          pit_[i]->getInterestStruct().name.nComponents > pit_[iResult]->getInterestStruct().name.nComponents)
+          pendingInterestTable_[i]->getInterestStruct().name.nComponents > 
+          pendingInterestTable_[iResult]->getInterestStruct().name.nComponents)
         // Update to the longer match.
         iResult = i;
     }
@@ -281,7 +316,7 @@
 	return iResult;
 }
   
-Node::PrefixEntry*
+Node::RegisteredPrefix*
 Node::getEntryForRegisteredPrefix(const Name& name)
 {
   int iResult = -1;
@@ -301,8 +336,9 @@
     return 0;
 }
 
-Node::PitEntry::PitEntry(const shared_ptr<const Interest>& interest, const OnData& onData, const OnTimeout& onTimeout)
-: interest_(interest), onData_(onData), onTimeout_(onTimeout)
+Node::PendingInterest::PendingInterest
+  (unsigned int pendingInterestId, const shared_ptr<const Interest>& interest, const OnData& onData, const OnTimeout& onTimeout)
+: pendingInterestId_(pendingInterestId), interest_(interest), onData_(onData), onTimeout_(onTimeout)
 {
   // Set up timeoutTime_.
   if (interest_->getInterestLifetimeMilliseconds() >= 0.0)
@@ -321,7 +357,7 @@
 }
 
 bool 
-Node::PitEntry::checkTimeout(Node *parent, double nowMilliseconds)
+Node::PendingInterest::checkTimeout(Node *parent, double nowMilliseconds)
 {
   if (timeoutTimeMilliseconds_ >= 0.0 && nowMilliseconds >= timeoutTimeMilliseconds_) {
     if (onTimeout_) {
diff --git a/ndn-cpp/node.hpp b/ndn-cpp/node.hpp
index 3b79658..794120c 100644
--- a/ndn-cpp/node.hpp
+++ b/ndn-cpp/node.hpp
@@ -56,11 +56,21 @@
    * use func_lib::ref() as appropriate.
    * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
    * This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @return The pending interest ID which can be used with removePendingInterest.
    */
-  void 
+  unsigned int 
   expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout);
   
   /**
+   * Remove the pending interest entry with the pendingInterestId from the pending interest table.
+   * This does not affect another pending interest with a different pendingInterestId, even it if has the same interest name.
+   * If there is no entry with the pendingInterestId, do nothing.
+   * @param pendingInterestId The ID returned from expressInterest.
+   */
+  void
+  removePendingInterest(unsigned int pendingInterestId);
+  
+  /**
    * Register prefix with the connected NDN hub and call onInterest when a matching interest is received.
    * @param prefix A reference to a Name for the prefix to register.  This copies the Name.
    * @param onInterest A function object to call when a matching interest is received.  This copies the function object, so you may need to
@@ -69,13 +79,23 @@
    * This calls onRegisterFailed(prefix) where prefix is the prefix given to registerPrefix.
    * @param flags The flags for finer control of which interests are forward to the application.
    * @param wireFormat A WireFormat object used to encode the input. If omitted, use WireFormat getDefaultWireFormat().
+   * @return The registered prefix ID which can be used with removeRegisteredPrefix.
    */
-  void 
+  unsigned int 
   registerPrefix
     (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags, 
      WireFormat& wireFormat);
 
   /**
+   * Remove the registered prefix entry with the registeredPrefixId from the pending interest table.  
+   * This does not affect another registered prefix with a different registeredPrefixId, even it if has the same prefix name.
+   * If there is no entry with the registeredPrefixId, do nothing.
+   * @param registeredPrefixId The ID returned from registerPrefix.
+   */
+  void
+  removeRegisteredPrefix(unsigned int registeredPrefixId);
+
+  /**
    * Process any data to receive.  For each element received, call onReceivedElement.
    * This is non-blocking and will return immediately if there is no data to receive.
    * You should repeatedly call this from an event loop, with calls to sleep as needed so that the loop doesn't use 100% of the CPU.
@@ -98,15 +118,33 @@
   shutdown();
 
 private:
-  class PitEntry {
+  class PendingInterest {
   public:
     /**
      * Create a new PitEntry and set the timeoutTime_ based on the current time and the interest lifetime.
+     * @param pendingInterestId A unique ID for this entry, which you should get with getNextPendingInteresId().
      * @param interest A shared_ptr for the interest.
      * @param onData A function object to call when a matching data packet is received.
      * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
      */
-    PitEntry(const ptr_lib::shared_ptr<const Interest>& interest, const OnData& onData, const OnTimeout& onTimeout);
+    PendingInterest
+      (unsigned int pendingInterestId, const ptr_lib::shared_ptr<const Interest>& interest, const OnData& onData, 
+       const OnTimeout& onTimeout);
+    
+    /**
+     * Return the next unique pending interest ID.
+     */
+    static unsigned int 
+    getNextPendingInterestId()
+    {
+      return ++lastPendingInterestId_;
+    }
+    
+    /**
+     * Return the pendingInterestId given to the constructor.
+     */
+    unsigned int 
+    getPendingInterestId() { return pendingInterestId_; }
     
     const ptr_lib::shared_ptr<const Interest>& 
     getInterest() { return interest_; }
@@ -143,23 +181,41 @@
     std::vector<struct ndn_ExcludeEntry> excludeEntries_;
     struct ndn_Interest interestStruct_;
   
+    static unsigned int lastPendingInterestId_; /**< A class variable used to get the next unique ID. */
+    unsigned int pendingInterestId_;            /**< A unique identifier for this entry so it can be deleted */
     const OnData onData_;
     const OnTimeout onTimeout_;
     double timeoutTimeMilliseconds_; /**< The time when the interest times out in milliseconds according to gettimeofday, or -1 for no timeout. */
   };
 
-  class PrefixEntry {
+  class RegisteredPrefix {
   public:
     /**
      * Create a new PrefixEntry.
+     * @param registeredPrefixId A unique ID for this entry, which you should get with getNextRegisteredPrefixId().
      * @param prefix A shared_ptr for the prefix.
      * @param onInterest A function object to call when a matching data packet is received.
      */
-    PrefixEntry(const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest)
-    : prefix_(prefix), onInterest_(onInterest)
+    RegisteredPrefix(unsigned int registeredPrefixId, const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest)
+    : registeredPrefixId_(registeredPrefixId), prefix_(prefix), onInterest_(onInterest)
     {
     }
     
+    /**
+     * Return the next unique entry ID.
+     */
+    static unsigned int 
+    getNextRegisteredPrefixId()
+    {
+      return ++lastRegisteredPrefixId_;
+    }
+    
+    /**
+     * Return the registeredPrefixId given to the constructor.
+     */
+    unsigned int 
+    getRegisteredPrefixId() { return registeredPrefixId_; }
+    
     const ptr_lib::shared_ptr<const Name>& 
     getPrefix() { return prefix_; }
     
@@ -167,6 +223,8 @@
     getOnInterest() { return onInterest_; }
     
   private:
+    static unsigned int lastRegisteredPrefixId_; /**< A class variable used to get the next unique ID. */
+    unsigned int registeredPrefixId_;            /**< A unique identifier for this entry so it can be deleted */
     ptr_lib::shared_ptr<const Name> prefix_;
     const OnInterest onInterest_;
   };
@@ -200,14 +258,25 @@
     
     class Info {
     public:
-      Info(Node *node, const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
-           const ForwardingFlags& flags, WireFormat& wireFormat)
-      : node_(*node), prefix_(new Name(prefix)), onInterest_(onInterest), onRegisterFailed_(onRegisterFailed), 
+      /**
+       * 
+       * @param node
+       * @param registeredPrefixId The PrefixEntry::getNextRegisteredPrefixId() which registerPrefix got so it could return it to the caller.
+       * @param prefix
+       * @param onInterest
+       * @param onRegisterFailed
+       * @param flags
+       * @param wireFormat
+       */
+      Info(Node *node, unsigned int registeredPrefixId, const Name& prefix, const OnInterest& onInterest, 
+           const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags, WireFormat& wireFormat)
+      : node_(*node), registeredPrefixId_(registeredPrefixId), prefix_(new Name(prefix)), onInterest_(onInterest), onRegisterFailed_(onRegisterFailed), 
         flags_(flags), wireFormat_(wireFormat)
       {      
       }
       
       Node& node_;
+      unsigned int registeredPrefixId_;
       ptr_lib::shared_ptr<const Name> prefix_;
       const OnInterest onInterest_;
       const OnRegisterFailed onRegisterFailed_;
@@ -233,11 +302,12 @@
    * @param name The name to find the PrefixEntry for (from the incoming interest packet).
    * @return A pointer to the entry, or 0 if not found.
    */
-  PrefixEntry*
+  RegisteredPrefix*
   getEntryForRegisteredPrefix(const Name& name);
 
   /**
    * Do the work of registerPrefix once we know we are connected with an ndndId_.
+   * @param registeredPrefixId The PrefixEntry::getNextRegisteredPrefixId() which registerPrefix got so it could return it to the caller.
    * @param prefix
    * @param onInterest
    * @param onRegisterFailed
@@ -246,13 +316,13 @@
    */  
   void 
   registerPrefixHelper
-    (const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
-     const ForwardingFlags& flags, WireFormat& wireFormat);
+    (unsigned int registeredPrefixId, const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest, 
+     const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags, WireFormat& wireFormat);
   
   ptr_lib::shared_ptr<Transport> transport_;
   ptr_lib::shared_ptr<const Transport::ConnectionInfo> connectionInfo_;
-  std::vector<ptr_lib::shared_ptr<PitEntry> > pit_;
-  std::vector<ptr_lib::shared_ptr<PrefixEntry> > registeredPrefixTable_;
+  std::vector<ptr_lib::shared_ptr<PendingInterest> > pendingInterestTable_;
+  std::vector<ptr_lib::shared_ptr<RegisteredPrefix> > registeredPrefixTable_;
   Interest ndndIdFetcherInterest_;
   Blob ndndId_;
 };