Added PitEntry and make expressInterest use the PIT.
diff --git a/ndn-cpp/node.cpp b/ndn-cpp/node.cpp
index fed4c8e..26a6ecd 100644
--- a/ndn-cpp/node.cpp
+++ b/ndn-cpp/node.cpp
@@ -13,14 +13,52 @@
 
 namespace ndn {
 
+Node::PitEntry::PitEntry(const Name &name, Closure *closure)
+: interest_(name), interestStructIsStale_(true), closure_(closure)
+{
+  if (interest_.getInterestLifetimeMilliseconds() >= 0.0)
+    timeoutTime_ = ::clock() + (clock_t)((interest_.getInterestLifetimeMilliseconds() / 1000.0) * (double)CLOCKS_PER_SEC);
+  else
+    // No timeout.
+    timeoutTime_ = 0;
+}
+
+const struct ndn_Interest &Node::PitEntry::getInterestStruct()
+{
+  if (interestStructIsStale_) {
+    nameComponents_.reserve(interest_.getName().getComponentCount());
+    excludeEntries_.reserve(interest_.getExclude().getEntryCount());
+    ndn_Interest_init
+      (&interestStruct_, &nameComponents_[0], nameComponents_.capacity(), &excludeEntries_[0], excludeEntries_.capacity());
+    interest_.get(interestStruct_);
+    
+    interestStructIsStale_ = false;
+  }
+  
+  return interestStruct_;
+}
+
 void Node::expressInterest(const Name &name, Closure *closure, const Interest *interestTemplate)
 {
-  Interest interest(name);
-  shared_ptr<vector<unsigned char> > encoding = interest.wireEncode();  
-
-  // TODO: This should go in the PIT.
-  tempClosure_ = closure;
+  shared_ptr<PitEntry> pitEntry(new PitEntry(name, closure));
+  if (interestTemplate) {
+		pitEntry->getInterest().setMinSuffixComponents(interestTemplate->getMinSuffixComponents());
+		pitEntry->getInterest().setMaxSuffixComponents(interestTemplate->getMaxSuffixComponents());
+		pitEntry->getInterest().getPublisherPublicKeyDigest() = interestTemplate->getPublisherPublicKeyDigest();
+		pitEntry->getInterest().getExclude() = interestTemplate->getExclude();
+		pitEntry->getInterest().setChildSelector(interestTemplate->getChildSelector());
+		pitEntry->getInterest().setAnswerOriginKind(interestTemplate->getAnswerOriginKind());
+		pitEntry->getInterest().setScope(interestTemplate->getScope());
+		pitEntry->getInterest().setInterestLifetimeMilliseconds(interestTemplate->getInterestLifetimeMilliseconds());
+  }
+  else
+    pitEntry->getInterest().setInterestLifetimeMilliseconds(4000.0);   // default interest timeout value.
   
+  pit_.push_back(pitEntry);
+  
+  shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest().wireEncode();  
+  
+  // TODO: Check if we are already connected.
   transport_->connect(*this);
   transport_->send(*encoding);
 }
@@ -38,9 +76,16 @@
     shared_ptr<Data> data(new Data());
     data->wireDecode(element, elementLength);
     
-    shared_ptr<Interest> dummyInterest;
-    UpcallInfo upcallInfo(this, dummyInterest, 0, data);
-    tempClosure_->upcall(UPCALL_DATA, upcallInfo);
+    int iPitEntry = getEntryIndexForExpressedInterest(data->getName());
+    if (iPitEntry >= 0) {
+      shared_ptr<Interest> interestCopy(new Interest(pit_[iPitEntry]->getInterest()));
+      UpcallInfo upcallInfo(this, interestCopy, 0, data);
+      
+      // Remove the PIT entry before the calling the callback.
+      Closure *closure = pit_[iPitEntry]->getClosure();
+      pit_.erase(pit_.begin() + iPitEntry);
+      closure->upcall(UPCALL_DATA, upcallInfo);
+    }
   }
 }
 
@@ -49,4 +94,26 @@
   transport_->close();
 }
 
+int Node::getEntryIndexForExpressedInterest(const Name &name)
+{
+  // TODO: Doesn't this belong in the Name class?
+  vector<struct ndn_NameComponent> nameComponents;
+  nameComponents.reserve(name.getComponentCount());
+  struct ndn_Name nameStruct;
+  ndn_Name_init(&nameStruct, &nameComponents[0], nameComponents.capacity());
+  name.get(nameStruct);
+  
+  int iResult = -1;
+    
+	for (unsigned int i = 0; i < pit_.size(); ++i) {
+		if (ndn_Interest_matchesName((struct ndn_Interest *)&pit_[i]->getInterestStruct(), &nameStruct)) {
+      if (iResult < 0 || 
+          pit_[i]->getInterest().getName().getComponentCount() > pit_[iResult]->getInterest().getName().getComponentCount())
+        iResult = i;
+    }
+	}
+    
+	return iResult;
+}
+
 }
diff --git a/ndn-cpp/node.hpp b/ndn-cpp/node.hpp
index 789a584..a9195d3 100644
--- a/ndn-cpp/node.hpp
+++ b/ndn-cpp/node.hpp
@@ -6,6 +6,7 @@
 #ifndef NDN_NODE_HPP
 #define NDN_NODE_HPP
 
+#include <time.h>
 #include "interest.hpp"
 #include "closure.hpp"
 #include "transport/udp-transport.hpp"
@@ -24,7 +25,7 @@
    * @param transport A pointer to a Transport object used for communication.
    */
   Node(const char *host, unsigned short port, const ptr_lib::shared_ptr<Transport> &transport)
-  : host_(host), port_(port), transport_(transport), tempClosure_(0)
+  : host_(host), port_(port), transport_(transport)
   {
   }
   
@@ -34,7 +35,7 @@
    * @param port The port of the NDN hub.
    */
   Node(const char *host, unsigned short port)
-  : host_(host), port_(port), transport_(new UdpTransport()), tempClosure_(0)
+  : host_(host), port_(port), transport_(new UdpTransport())
   {
   }
   
@@ -43,7 +44,7 @@
    * @param host The host of the NDN hub.
    */
   Node(const char *host)
-  : host_(host), port_(9695), transport_(new UdpTransport()), tempClosure_(0)
+  : host_(host), port_(9695), transport_(new UdpTransport())
   {
   }
 
@@ -83,10 +84,60 @@
   void shutdown();
 
 private:
+  class PitEntry {
+  public:
+    /**
+     * Create a new PitEntry and set the timeoutTime_ based on the current time and the interest lifetime.
+     * @param name The name for the interest.  You can use the non-const getInterest() to set other fields.
+     * (We do it like this to avoid invoking the Interest copy constructor.)
+     * @param closure A pointer to the closure with the callbacks to call on match. 
+     * The caller must manage the memory for the Closure.  This will not try to delete it.
+     */
+    PitEntry(const Name &name, Closure *closure);
+    
+    Interest &getInterest() 
+    { 
+      // Assume that the caller will modify interest_, so mark it stale.
+      interestStructIsStale_ = true;
+      return interest_; 
+    }
+    
+    Closure *getClosure() { return closure_; }
+    
+    /**
+     * Get the struct ndn_Interest for the interest_.  If interestStructIsStale_, then this will
+     * re-build from interest_.  
+     * WARNING: Assume that this PitEntry was created with new, so that no copy constructor is invoked between calls.
+     * This class is private to Node and only used by its methods, so this should be OK.
+     * TODO: Doesn't this functionality belong in the Interest class?
+     * @return A reference to the ndn_Interest struct.
+     * WARNING: The resulting pointers in are invalid uses getInterest() to manipulate the object which could reallocate memory.
+     */
+    const struct ndn_Interest &getInterestStruct();
+    
+  private:
+    Interest interest_;
+    std::vector<struct ndn_NameComponent> nameComponents_;
+    std::vector<struct ndn_ExcludeEntry> excludeEntries_;
+    struct ndn_Interest interestStruct_;
+    bool interestStructIsStale_;
+  
+    Closure *closure_;
+    clock_t timeoutTime_; /**< The clock time when the interest times out, of 0 for none. */
+  };
+  
+  /**
+   * Find the entry from the pit_ where the name conforms to the entry's interest selectors, and
+   * the entry interest name is the longest that matches name.
+   * @param name The name to find the interest for (from the incoming data packet).
+   * @return The index in pit_ of the pit entry, or -1 if not found.
+   */
+  int getEntryIndexForExpressedInterest(const Name &name);
+  
   ptr_lib::shared_ptr<Transport> transport_;
+  std::vector<ptr_lib::shared_ptr<PitEntry> > pit_;
   std::string host_;
   unsigned short port_;
-  Closure *tempClosure_;
 };
 
 }
diff --git a/tests/test-get-async.cpp b/tests/test-get-async.cpp
index 62cc2e5..94f3455 100644
--- a/tests/test-get-async.cpp
+++ b/tests/test-get-async.cpp
@@ -17,14 +17,14 @@
 class MyClosure : public Closure {
 public:
   MyClosure()
-  : gotContent_(false)
+  : gotContentCount_(0)
   {  
   }
   
   virtual UpcallResult upcall(UpcallKind kind, UpcallInfo &upcallInfo)
   {
     if (kind == UPCALL_DATA || kind == UPCALL_DATA_UNVERIFIED) {
-      gotContent_ = true;
+      ++gotContentCount_;
       cout << "Got data packet with name " << upcallInfo.getData()->getName().to_uri() << endl;
       for (unsigned int i = 0; i < upcallInfo.getData()->getContent().size(); ++i)
         cout << upcallInfo.getData()->getContent()[i];
@@ -36,7 +36,7 @@
       return CLOSURE_RESULT_OK;
   }
   
-  bool gotContent_;
+  int gotContentCount_;
 };
 
 int main(int argc, char** argv)
@@ -44,10 +44,18 @@
   try {
     MyClosure closure;
     Face face("E.hub.ndn.ucla.edu");
-    face.expressInterest(Name("/ndn/ucla.edu/apps/ndn-js-test/hello.txt/level2/%FD%05%0B%16%7D%95%0E"), &closure);
     
+    Name name1("/ndn/ucla.edu/apps/ndn-js-test/hello.txt/level2/%FD%05%0B%16%7D%95%0E");    
+    cout << "Express name  " << name1.toUri() << endl;
+    face.expressInterest(name1, &closure);
+#if 0
+    Name name2("/ndn/ucla.edu/apps/lwndn-test/howdy.txt/%FD%05%05%E8%0C%CE%1D");
+    cout << "Express name  " << name2.toUri() << endl;
+    face.expressInterest(name2, &closure);
+#endif
+
     // The main event loop.
-    while (!closure.gotContent_) {
+    while (closure.gotContentCount_ < 1) {
       face.processEvents();
       // We need to sleep for a few milliseconds so we don't use 100% of the CPU.
       usleep(10000);