Update processEvents to check for timeout.  Make PitEntry take a const Interest pointer.
diff --git a/ndn-cpp/node.cpp b/ndn-cpp/node.cpp
index 26a6ecd..b8773fc 100644
--- a/ndn-cpp/node.cpp
+++ b/ndn-cpp/node.cpp
@@ -3,6 +3,7 @@
  * See COPYING for copyright and distribution information.
  */
 
+#include <sys/time.h>
 #include "encoding/binary-xml-decoder.hpp"
 #include "c/encoding/binary-xml.h"
 #include "data.hpp"
@@ -13,50 +14,67 @@
 
 namespace ndn {
 
-Node::PitEntry::PitEntry(const Name &name, Closure *closure)
-: interest_(name), interestStructIsStale_(true), closure_(closure)
+// Use gettimeofday to return the current time in milliseconds.
+static inline double getNowMilliseconds()
 {
-  if (interest_.getInterestLifetimeMilliseconds() >= 0.0)
-    timeoutTime_ = ::clock() + (clock_t)((interest_.getInterestLifetimeMilliseconds() / 1000.0) * (double)CLOCKS_PER_SEC);
+  timeval t;
+  gettimeofday(&t, NULL);
+  return t.tv_sec * 1000.0 + t.tv_usec / 1000.0;
+}
+  
+Node::PitEntry::PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, Closure *closure)
+: interest_(interest), closure_(closure)
+{
+  // Set up timeoutTime_.
+  if (interest_->getInterestLifetimeMilliseconds() >= 0.0)
+    timeoutTimeMilliseconds_ = getNowMilliseconds() + interest_->getInterestLifetimeMilliseconds();
   else
     // No timeout.
-    timeoutTime_ = 0;
+    timeoutTimeMilliseconds_ = -1.0;
+  
+  // Set up interestStruct_.
+  // TODO: Doesn't this belong in the Interest class?
+  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_);  
 }
 
-const struct ndn_Interest &Node::PitEntry::getInterestStruct()
+bool Node::PitEntry::checkTimeout(Node *parent, double nowMilliseconds)
 {
-  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_);
+  if (timeoutTimeMilliseconds_ >= 0.0 && nowMilliseconds >= timeoutTimeMilliseconds_) {
+    shared_ptr<Data> dummyData;
+    UpcallInfo upcallInfo(parent, interest_, 0, dummyData);
     
-    interestStructIsStale_ = false;
+    // Ignore all exceptions.
+    try {
+      closure_->upcall(UPCALL_INTEREST_TIMED_OUT, upcallInfo);
+    }
+    catch (...) { }
+    
+    return true;
   }
-  
-  return interestStruct_;
+  else
+    return false;
 }
 
 void Node::expressInterest(const Name &name, Closure *closure, const Interest *interestTemplate)
 {
-  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());
-  }
+  shared_ptr<const Interest> interest;
+  if (interestTemplate)
+    interest.reset(new Interest
+      (name, interestTemplate->getMinSuffixComponents(), interestTemplate->getMaxSuffixComponents(),
+       interestTemplate->getPublisherPublicKeyDigest(), interestTemplate->getExclude(),
+       interestTemplate->getChildSelector(), interestTemplate->getAnswerOriginKind(),
+       interestTemplate->getScope(), interestTemplate->getInterestLifetimeMilliseconds()));
   else
-    pitEntry->getInterest().setInterestLifetimeMilliseconds(4000.0);   // default interest timeout value.
+    interest.reset(new Interest(name, 4000.0));
   
+  shared_ptr<PitEntry> pitEntry(new PitEntry(interest, closure));
   pit_.push_back(pitEntry);
   
-  shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest().wireEncode();  
+  shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest()->wireEncode();  
   
   // TODO: Check if we are already connected.
   transport_->connect(*this);
@@ -66,6 +84,17 @@
 void Node::processEvents()
 {
   transport_->processEvents();
+  
+  // 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);
+      
+      // Refresh now since the timeout callback might have delayed.
+      nowMilliseconds = getNowMilliseconds();
+    }
+  }
 }
 
 void Node::onReceivedElement(unsigned char *element, unsigned int elementLength)
@@ -78,8 +107,7 @@
     
     int iPitEntry = getEntryIndexForExpressedInterest(data->getName());
     if (iPitEntry >= 0) {
-      shared_ptr<Interest> interestCopy(new Interest(pit_[iPitEntry]->getInterest()));
-      UpcallInfo upcallInfo(this, interestCopy, 0, data);
+      UpcallInfo upcallInfo(this, pit_[iPitEntry]->getInterest(), 0, data);
       
       // Remove the PIT entry before the calling the callback.
       Closure *closure = pit_[iPitEntry]->getClosure();
@@ -108,7 +136,8 @@
 	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())
+          pit_[i]->getInterestStruct().name.nComponents > pit_[iResult]->getInterestStruct().name.nComponents)
+        // Update to the longer match.
         iResult = i;
     }
 	}
diff --git a/ndn-cpp/node.hpp b/ndn-cpp/node.hpp
index a9195d3..a7e5548 100644
--- a/ndn-cpp/node.hpp
+++ b/ndn-cpp/node.hpp
@@ -6,7 +6,6 @@
 #ifndef NDN_NODE_HPP
 #define NDN_NODE_HPP
 
-#include <time.h>
 #include "interest.hpp"
 #include "closure.hpp"
 #include "transport/udp-transport.hpp"
@@ -88,42 +87,45 @@
   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 interest A shared_ptr for the interest.
      * @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);
+    PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, Closure *closure);
     
-    Interest &getInterest() 
-    { 
-      // Assume that the caller will modify interest_, so mark it stale.
-      interestStructIsStale_ = true;
-      return interest_; 
-    }
+    const ptr_lib::shared_ptr<const Interest> &getInterest() { return interest_; }
     
     Closure *getClosure() { return closure_; }
     
     /**
-     * Get the struct ndn_Interest for the interest_.  If interestStructIsStale_, then this will
-     * re-build from interest_.  
+     * Get the struct ndn_Interest for the 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();
+    const struct ndn_Interest &getInterestStruct()
+    {
+      return interestStruct_;
+    }
+    
+    /**
+     * If this interest is timed out, call the timeout callback and return true.
+     * @param parent The parent Node for the UpcallInfo.
+     * @param nowMilliseconds The current time in milliseconds from gettimeofday.
+     * @return true if this interest timed out and the timeout callback was called, otherwise false.
+     */
+    bool checkTimeout(Node *parent, double nowMilliseconds);
     
   private:
-    Interest interest_;
+    ptr_lib::shared_ptr<const 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. */
+    double timeoutTimeMilliseconds_; /**< The time when the interest times out in milliseconds according to gettimeofday, or -1 for no timeout. */
   };
   
   /**
diff --git a/tests/test-get-async.cpp b/tests/test-get-async.cpp
index 94f3455..692ed36 100644
--- a/tests/test-get-async.cpp
+++ b/tests/test-get-async.cpp
@@ -17,14 +17,14 @@
 class MyClosure : public Closure {
 public:
   MyClosure()
-  : gotContentCount_(0)
+  : gotCallbackCount_(0)
   {  
   }
   
-  virtual UpcallResult upcall(UpcallKind kind, UpcallInfo &upcallInfo)
+  virtual UpcallResult upcall(UpcallKind kind, const UpcallInfo &upcallInfo)
   {
     if (kind == UPCALL_DATA || kind == UPCALL_DATA_UNVERIFIED) {
-      ++gotContentCount_;
+      ++gotCallbackCount_;
       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];
@@ -32,11 +32,16 @@
       
       return CLOSURE_RESULT_OK;
     }
+    else if (kind == UPCALL_INTEREST_TIMED_OUT) {
+      ++gotCallbackCount_;
+      cout << "Time out for interest  " << upcallInfo.getInterest()->getName().toUri() << endl;    
+      return CLOSURE_RESULT_OK;
+    }
     else
       return CLOSURE_RESULT_OK;
   }
   
-  int gotContentCount_;
+  int gotCallbackCount_;
 };
 
 int main(int argc, char** argv)
@@ -48,14 +53,12 @@
     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.gotContentCount_ < 1) {
+    while (closure.gotCallbackCount_ < 2) {
       face.processEvents();
       // We need to sleep for a few milliseconds so we don't use 100% of the CPU.
       usleep(10000);