Added Closure class
diff --git a/Makefile.am b/Makefile.am
index b498eed..0e49f84 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,7 @@
 
 libndn_cpp_a_SOURCES = \
   config.h ndn-cpp/common.hpp \
+  ndn-cpp/Closure.hpp \
   ndn-cpp/ContentObject.cpp ndn-cpp/c/ContentObject.h ndn-cpp/ContentObject.hpp \
   ndn-cpp/Interest.cpp ndn-cpp/c/Interest.h ndn-cpp/Interest.hpp \
   ndn-cpp/Key.cpp ndn-cpp/c/Key.h ndn-cpp/Key.hpp \
diff --git a/Makefile.in b/Makefile.in
index ca0c617..dc90771 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -438,6 +438,7 @@
 
 libndn_cpp_a_SOURCES = \
   config.h ndn-cpp/common.hpp \
+  ndn-cpp/Closure.hpp \
   ndn-cpp/ContentObject.cpp ndn-cpp/c/ContentObject.h ndn-cpp/ContentObject.hpp \
   ndn-cpp/Interest.cpp ndn-cpp/c/Interest.h ndn-cpp/Interest.hpp \
   ndn-cpp/Key.cpp ndn-cpp/c/Key.h ndn-cpp/Key.hpp \
diff --git a/ndn-cpp/Closure.hpp b/ndn-cpp/Closure.hpp
new file mode 100644
index 0000000..99dafdb
--- /dev/null
+++ b/ndn-cpp/Closure.hpp
@@ -0,0 +1,68 @@
+/**
+ * @author: Jeff Thompson
+ * This is a port of py from PyCCN, written by: 
+ * Derek Kulinski <takeda@takeda.tk>
+ * Jeff Burke <jburke@ucla.edu>
+ * 
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_CLOSURE_HPP
+#define	NDN_CLOSURE_HPP
+
+#include "Common.hpp"
+
+namespace ndn {
+
+enum UpcallResult {
+  CLOSURE_RESULT_ERR               = -1, // upcall detected an error
+  CLOSURE_RESULT_OK                =  0, // normal upcall return
+  CLOSURE_RESULT_REEXPRESS         =  1, // reexpress the same interest again
+  CLOSURE_RESULT_INTEREST_CONSUMED =  2, // upcall claims to consume interest
+  CLOSURE_RESULT_VERIFY            =  3, // force an unverified result to be verified
+  CLOSURE_RESULT_FETCHKEY          =  4  // get the key in the key locator and re-call the interest
+};
+
+enum UpcallKind {
+  UPCALL_FINAL              = 0, // handler is about to be deregistered
+  UPCALL_INTEREST           = 1, // incoming interest
+  UPCALL_CONSUMED_INTEREST  = 2, // incoming interest, someone has answered
+  UPCALL_CONTENT            = 3, // incoming verified content
+  UPCALL_INTEREST_TIMED_OUT = 4, // interest timed out
+  UPCALL_CONTENT_UNVERIFIED = 5, // content that has not been verified
+  UPCALL_CONTENT_BAD        = 6  // verification failed  
+};
+
+class NDN;
+class Interest;
+class ContentObject;
+
+class UpcallInfo {
+public:
+  UpcallInfo(NDN *ndn, ptr_lib::shared_ptr<Interest> interest, int matchedComps, ptr_lib::shared_ptr<ContentObject> contentObject) 
+  {
+    ndn_ = ndn;
+    interest_ = interest;
+    contentObject_ = contentObject;
+  }
+  
+  NDN *getNDN() { return ndn_; }
+  
+  ptr_lib::shared_ptr<Interest> getInterest() { return interest_; }
+  
+  ptr_lib::shared_ptr<ContentObject> getContentObject() { return contentObject_; }
+  
+private:
+  NDN *ndn_;
+  ptr_lib::shared_ptr<Interest> interest_;
+  ptr_lib::shared_ptr<ContentObject> contentObject_;
+};
+
+class Closure {
+public:
+  virtual UpcallResult upcall(UpcallKind kind, UpcallInfo &upcallInfo) = 0;
+};
+
+}
+
+#endif
diff --git a/ndn-cpp/NDN.cpp b/ndn-cpp/NDN.cpp
index ba47698..cd1dbe6 100644
--- a/ndn-cpp/NDN.cpp
+++ b/ndn-cpp/NDN.cpp
@@ -8,6 +8,8 @@
 #include "ContentObject.hpp"
 #include "NDN.hpp"
 
+using namespace std;
+
 namespace ndn {
 
 void NDN::onReceivedElement(unsigned char *element, unsigned int elementLength)
@@ -15,15 +17,11 @@
   BinaryXMLDecoder decoder(element, elementLength);
   
   if (decoder.peekDTag(ndn_BinaryXML_DTag_ContentObject)) {
-    ContentObject contentObject;
-    contentObject.decode(element, elementLength);
-
-#if 0
-    cout << "Got content with name " << contentObject.getName().to_uri() << endl;
-    for (unsigned int i = 0; i < contentObject.getContent().size(); ++i)
-      cout << contentObject.getContent()[i];
-    cout << endl;
-#endif
+    ptr_lib::shared_ptr<ContentObject> contentObject(new ContentObject());
+    contentObject->decode(element, elementLength);
+    
+    UpcallInfo upcallInfo(this, ptr_lib::shared_ptr<Interest>(), 0, contentObject);
+    closure_->upcall(UPCALL_CONTENT, upcallInfo);
   }
 }
 
diff --git a/ndn-cpp/NDN.hpp b/ndn-cpp/NDN.hpp
index a89918b..9c8c691 100644
--- a/ndn-cpp/NDN.hpp
+++ b/ndn-cpp/NDN.hpp
@@ -6,13 +6,22 @@
 #ifndef NDN_NDN_HPP
 #define	NDN_NDN_HPP
 
+#include "Closure.hpp"
 #include "encoding/BinaryXMLElementReader.hpp"
 
 namespace ndn {
 
 class NDN : public ElementListener {
 public:
+  NDN(Closure *closure)
+  {
+    closure_ = closure;
+  }
+  
   virtual void onReceivedElement(unsigned char *element, unsigned int elementLength);
+  
+private:
+  Closure *closure_;
 };
 
 }
diff --git a/tests/test-get-async.cpp b/tests/test-get-async.cpp
index 3ea187e..011c28f 100644
--- a/tests/test-get-async.cpp
+++ b/tests/test-get-async.cpp
@@ -8,11 +8,30 @@
 #include <iostream>
 #include <ndn-cpp/Interest.hpp>
 #include <ndn-cpp/ContentObject.hpp>
-#include <ndn-cpp/encoding/BinaryXMLStructureDecoder.hpp>
 #include <ndn-cpp/transport/TcpTransport.hpp>
+#include <ndn-cpp/c/encoding/BinaryXMLElementReader.h>
+#include <ndn-cpp/NDN.hpp>
 
 using namespace std;
 using namespace ndn;
+
+class MyClosure : public Closure {
+public:
+  virtual UpcallResult upcall(UpcallKind kind, UpcallInfo &upcallInfo)
+  {
+    if (kind == UPCALL_CONTENT || kind == UPCALL_CONTENT_UNVERIFIED) {
+      cout << "Got content with name " << upcallInfo.getContentObject()->getName().to_uri() << endl;
+      for (unsigned int i = 0; i < upcallInfo.getContentObject()->getContent().size(); ++i)
+        cout << upcallInfo.getContentObject()->getContent()[i];
+      cout << endl;
+      
+      return CLOSURE_RESULT_OK;
+    }
+    else
+      return CLOSURE_RESULT_OK;
+  }
+};
+
 int main(int argc, char** argv)
 {
   try {
@@ -25,33 +44,15 @@
     transport.connect((char *)"E.hub.ndn.ucla.edu", 9695);
     transport.send(&encoding[0], encoding.size());
 
-    BinaryXMLStructureDecoder structureDecoder;
-    vector<unsigned char> element;
-    while (true) {
-      while (true) {
-        unsigned char buffer[8000];
-        unsigned int nBytes = transport.receive(buffer, sizeof(buffer));
-        element.insert(element.end(), buffer, buffer + nBytes);
-
-        if (structureDecoder.findElementEnd(&element[0], element.size()))
-          break;
-      }
-      
-      if (element[0] == 0x04)
-        // Assume this is a ContentObject.
-        break;
-      
-      // Erase this element and try again.
-      element.erase(element.begin(), element.begin() + structureDecoder.getOffset());
-    }
-        
-    ContentObject contentObject;
-    contentObject.decode(&element[0], structureDecoder.getOffset());
+    MyClosure closure;
+    NDN ndn(&closure);
     
-    cout << "Got content with name " << contentObject.getName().to_uri() << endl;
-    for (unsigned int i = 0; i < contentObject.getContent().size(); ++i)
-      cout << contentObject.getContent()[i];
-    cout << endl;
+    ndn_BinaryXMLElementReader elementReader;
+    ndn_BinaryXMLElementReader_init(&elementReader, (struct ndn_ElementListener *)&ndn);
+    
+    unsigned char buffer[8000];
+    unsigned int nBytes = transport.receive(buffer, sizeof(buffer));
+    ndn_BinaryXMLElementReader_onReceivedData(&elementReader, buffer, nBytes);    
   } catch (exception &e) {
     cout << "exception: " << e.what() << endl;
   }