Finish implementing registerPrefix.
diff --git a/ndn-cpp/node.cpp b/ndn-cpp/node.cpp
index a93ebd7..6a60e3b 100644
--- a/ndn-cpp/node.cpp
+++ b/ndn-cpp/node.cpp
@@ -6,6 +6,8 @@
 #include <sys/time.h>
 #include "encoding/binary-xml-decoder.hpp"
 #include "c/encoding/binary-xml.h"
+#include "forwarding-entry.hpp"
+#include "security/key-chain.hpp"
 #include "node.hpp"
 
 using namespace std;
@@ -33,11 +35,9 @@
   if (!transport_->getIsConnected())
     transport_->connect(*connectionInfo_, *this);
   
-  shared_ptr<PitEntry> pitEntry(new PitEntry(shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout));
-  pit_.push_back(pitEntry);
+  pit_.push_back(shared_ptr<PitEntry>(new PitEntry(shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout)));
   
-  shared_ptr<vector<unsigned char> > encoding = pitEntry->getInterest()->wireEncode();  
-  
+  shared_ptr<vector<unsigned char> > encoding = interest.wireEncode();  
   transport_->send(*encoding);
 }
 
@@ -71,7 +71,35 @@
 
 void Node::registerPrefixHelper(const Name &prefix, const OnInterest &onInterest, int flags)
 {
-  throw logic_error("need to finish implementing registerPrefix");
+  // Create a ForwardingEntry.
+  ForwardingEntry forwardingEntry("selfreg", prefix, PublisherPublicKeyDigest(), -1, 3, 2147483647);
+  ptr_lib::shared_ptr<vector<unsigned char> > content = forwardingEntry.wireEncode();
+
+  // Set the ForwardingEntry as the content of a Data packet and sign.
+  Data data;
+  data.setContent(*content);
+  data.getSignedInfo().setTimestampMilliseconds(time(NULL) * 1000.0);
+  // TODO: Should we sign with a different key?
+  KeyChain::defaultSign(data);
+  ptr_lib::shared_ptr<vector<unsigned char> > encodedData = data.wireEncode();
+  
+  // Create an interest where the name has the encoded Data packet.
+  Name interestName;
+  const unsigned char component0[] = "ndnx";
+  const unsigned char component2[] = "selfreg";
+  interestName.addComponent(component0, sizeof(component0) - 1);
+  interestName.addComponent(ndndId_);
+  interestName.addComponent(component2, sizeof(component2) - 1);
+  interestName.addComponent(*encodedData);
+  
+  Interest interest(interestName);
+  interest.setScope(1);
+  ptr_lib::shared_ptr<vector<unsigned char> > encodedInterest = interest.wireEncode();
+  
+  // Save the onInterest callback and send the registration interest.
+  registeredPrefixTable_.push_back(shared_ptr<PrefixEntry>(new PrefixEntry(shared_ptr<const Name>(new Name(prefix)), onInterest)));
+  
+  transport_->send(*encodedInterest);
 }
 
 void Node::processEvents()
@@ -94,7 +122,15 @@
 {
   BinaryXmlDecoder decoder(element, elementLength);
   
-  if (decoder.peekDTag(ndn_BinaryXml_DTag_ContentObject)) {
+  if (decoder.peekDTag(ndn_BinaryXml_DTag_Interest)) {
+    shared_ptr<Interest> interest(new Interest());
+    interest->wireDecode(element, elementLength);
+    
+    PrefixEntry *entry = getEntryForRegisteredPrefix(interest->getName());
+    if (entry)
+      entry->getOnInterest()(entry->getPrefix(), interest, *transport_);
+  }
+  else if (decoder.peekDTag(ndn_BinaryXml_DTag_ContentObject)) {
     shared_ptr<Data> data(new Data());
     data->wireDecode(element, elementLength);
     
@@ -137,6 +173,25 @@
 	return iResult;
 }
   
+Node::PrefixEntry *Node::getEntryForRegisteredPrefix(const Name &name)
+{
+  int iResult = -1;
+    
+	for (unsigned int i = 0; i < pit_.size(); ++i) {
+		if (registeredPrefixTable_[i]->getPrefix()->match(name)) {
+      if (iResult < 0 || 
+          registeredPrefixTable_[i]->getPrefix()->getComponentCount() > registeredPrefixTable_[iResult]->getPrefix()->getComponentCount())
+        // Update to the longer match.
+        iResult = i;
+    }
+	}
+    
+  if (iResult >= 0)
+  	return registeredPrefixTable_[iResult].get();
+  else
+    return 0;
+}
+
 Node::PitEntry::PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, const OnData &onData, const OnTimeout &onTimeout)
 : interest_(interest), onData_(onData), onTimeout_(onTimeout)
 {
diff --git a/ndn-cpp/node.hpp b/ndn-cpp/node.hpp
index 8bd59c2..b82ba8a 100644
--- a/ndn-cpp/node.hpp
+++ b/ndn-cpp/node.hpp
@@ -27,7 +27,8 @@
 /**
  * An OnInterest function object is used to pass a callback to registerPrefix.
  */
-typedef func_lib::function<void(const ptr_lib::shared_ptr<const Name> &, const ptr_lib::shared_ptr<const Interest> &)> OnInterest;
+typedef func_lib::function<void
+  (const ptr_lib::shared_ptr<const Name> &, const ptr_lib::shared_ptr<const Interest> &, Transport &)> OnInterest;
 
 class Face;
   
@@ -82,10 +83,8 @@
     /**
      * Create a new PitEntry and set the timeoutTime_ based on the current time and the interest lifetime.
      * @param interest A shared_ptr for the interest.
-     * @param onData A function object to call when a matching data packet is received.  This copies the function object, so you may need to
-     * use func_lib::ref() as appropriate.
+     * @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.
-     * This copies the function object, so you may need to use func_lib::ref() as appropriate.
      */
     PitEntry(const ptr_lib::shared_ptr<const Interest> &interest, const OnData &onData, const OnTimeout &onTimeout);
     
@@ -124,6 +123,27 @@
     const OnTimeout onTimeout_;
     double timeoutTimeMilliseconds_; /**< The time when the interest times out in milliseconds according to gettimeofday, or -1 for no timeout. */
   };
+
+  class PrefixEntry {
+  public:
+    /**
+     * Create a new PrefixEntry.
+     * @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)
+    {
+    }
+    
+    const ptr_lib::shared_ptr<const Name> &getPrefix() { return prefix_; }
+    
+    const OnInterest &getOnInterest() { return onInterest_; }
+    
+  private:
+    ptr_lib::shared_ptr<const Name> prefix_;
+    const OnInterest onInterest_;
+  };
   
   /**
    * An NdndIdFetcher receives the Data packet with the publisher public key digest for the connected NDN hub.
@@ -176,6 +196,13 @@
   int getEntryIndexForExpressedInterest(const Name &name);
   
   /**
+   * Find the first entry from the registeredPrefixTable_ where the entry prefix is the longest that matches name.
+   * @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 *getEntryForRegisteredPrefix(const Name &name);
+  
+  /**
    * Do the work of registerPrefix once we know we are connected with an ndndId_.
    * @param prefix
    * @param onInterest
@@ -186,6 +213,7 @@
   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_;
   Interest ndndIdFetcherInterest_;
   std::vector<unsigned char> ndndId_;
 };