refactor ccnx-wrapper
diff --git a/include/ccnx-pco.h b/include/ccnx-pco.h
new file mode 100644
index 0000000..4d22765
--- /dev/null
+++ b/include/ccnx-pco.h
@@ -0,0 +1,38 @@
+#ifndef CCNX_CONTENT_OBJECT_H
+#define CCNX_CONTENT_OBJECT_H
+
+#include <boost/exception/all.hpp>
+#include <boost/shared_ptr.hpp>
+#include "ccnx-wrapper.h"
+
+using namespace std;
+
+namespace Ccnx {
+
+struct MisformedContentObjectException : virtual boost::exception, virtual exception { };
+
+class ParsedContentObject 
+{
+public:
+  ParsedContentObject(const unsigned char *data, size_t len);
+  ParsedContentObject(const Bytes &bytes);
+  ParsedContentObject(const ParsedContentObject &other);
+  virtual ~ParsedContentObject();
+
+  Bytes
+  content();
+
+  string
+  name();
+
+protected:
+  ccn_parsed_ContentObject m_pco;
+  ccn_indexbuf *m_comps;
+  Bytes m_bytes;
+};
+
+typedef boost::shared_ptr<ParsedContentObject> PcoPtr;
+
+}
+
+#endif // CCNX_CONTENT_OBJECT_H
diff --git a/include/ccnx-wrapper.h b/include/ccnx-wrapper.h
index 575310b..c5f8b8d 100644
--- a/include/ccnx-wrapper.h
+++ b/include/ccnx-wrapper.h
@@ -10,6 +10,7 @@
 #include <ccn/signing.h>
 }
 
+#include <vector>
 #include <boost/exception/all.hpp>
 #include <boost/thread/recursive_mutex.hpp>
 #include <boost/thread/thread.hpp>
@@ -18,39 +19,27 @@
 #include <sstream>
 #include <map>
 
+using namespace std;
+
 namespace Ccnx {
 
-struct CcnxOperationException : virtual boost::exception, virtual std::exception { };
+typedef vector<unsigned char> Bytes;
 
-class CcnxWrapper;
+void
+readRaw(Bytes &bytes, const unsigned char *src, size_t len);
 
-class ContentObject
-{
-public:
-  ContentObject(const char *data, size_t len);
-  ~ContentObject();
-  void
-  dup(char **data, size_t *len);
-
-// exposed! use cautiously at your own risk.
-public:
-  char *m_data;
-  size_t m_len;
-};
-
-typedef boost::shared_ptr<ContentObject> ContentObjectPtr;
+struct CcnxOperationException : virtual boost::exception, virtual exception { };
 
 class CcnxWrapper {
 public:
-  typedef boost::function<void (std::string, const char *buf, size_t len)> DataCallback;
-  typedef boost::function<void (std::string)> InterestCallback;
-  typedef boost::function<TimeoutCallbackReturnValue (std::string)> TimeoutCallback;
-
+  typedef boost::function<void (string, Bytes)> DataCallback;
+  typedef boost::function<void (string)> InterestCallback;
   typedef enum
   {
     RESULT_OK,
     RESULT_REEXPRESS
   } TimeoutCallbackReturnValue;
+  typedef boost::function<TimeoutCallbackReturnValue (string)> TimeoutCallback;
 
 public:
 
@@ -58,34 +47,32 @@
   virtual ~CcnxWrapper();
 
   virtual int
-  setInterestFilter (const std::string &prefix, const InterestCallback &interestCallback);
+  setInterestFilter (const string &prefix, const InterestCallback &interestCallback);
 
   virtual void
-  clearInterestFilter (const std::string &prefix);
+  clearInterestFilter (const string &prefix);
 
   virtual int 
-  sendInterest (const std::string &strInterest, const RawDataCallback &rawDataCallback, int retry = 0, const TimeoutCallback &timeoutCallback = TimeoutCallback());
+  sendInterest (const string &strInterest, const DataCallback &dataCallback, int retry = 0, const TimeoutCallback &timeoutCallback = TimeoutCallback());
 
   virtual int 
-  publishData (const std::string &name, const char *buf, size_t len, int freshness);
+  publishData (const string &name, const char *buf, size_t len, int freshness);
 
-  ContentObjectPtr 
-  createContentObject(const std::string &name, const char *buf, size_t len, int freshness);
+  int
+  publishData (const string &name, const Bytes &content, int freshness);
+
+  static string
+  getLocalPrefix ();
+
+  static string
+  extractName(const unsigned char *data, ccn_indexbuf *comps);
+
+protected:
+  Bytes
+  createContentObject(const string &name, const char *buf, size_t len, int freshness);
 
   int 
-  putToCcnd (ContentObjectPtr co);
-
-  static std::string
-  getInterestName(ccn_upcall_info *info);
-
-  static std::string
-  getDataName(ccn_upcall_info *info);
-
-  static int
-  getContentFromContentObject(ContentObjectPtr co, char **data, size_t *len);
-
-  static std::string
-  getLocalPrefix ();
+  putToCcnd (Bytes &contentObject);
   
 protected:
   void
@@ -111,7 +98,7 @@
   ccnLoop ();
 
   int 
-  sendInterest (const std::string &strInterest, void *dataPass);
+  sendInterest (const string &strInterest, void *dataPass);
   /// @endcond
 
 protected:
@@ -123,24 +110,24 @@
   boost::thread m_thread;
   bool m_running;
   bool m_connected;
-  std::map<std::string, InterestCallback> m_registeredInterests;
+  map<string, InterestCallback> m_registeredInterests;
   // std::list< std::pair<std::string, InterestCallback> > m_registeredInterests;
 };
 
 typedef boost::shared_ptr<CcnxWrapper> CcnxWrapperPtr;
 
-class ClosurePass {
+class ClosurePass 
+{
 public:
   ClosurePass(int retry, const CcnxWrapper::DataCallback &dataCallback, const CcnxWrapper::TimeoutCallback &timeoutCallback);
   int getRetry() {return m_retry;}
   void decRetry() { m_retry--;}
-  virtual ~ClosurePass(){}
-  virtual void runCallback(std::string name, const char *data, size_t len);
-  virtual CcnxWrapper::TimeoutCallbackReturnValue runTimeoutCallback(std::string interest);
+  virtual ~ClosurePass();
+  virtual void runDataCallback(string name, const Bytes &content);
+  virtual CcnxWrapper::TimeoutCallbackReturnValue runTimeoutCallback(string interest);
 
 protected:
   int m_retry;
-  CallbackType m_type;
   CcnxWrapper::TimeoutCallback *m_timeoutCallback;
   CcnxWrapper::DataCallback *m_dataCallback;  
 };
diff --git a/src/ccnx-pco.cpp b/src/ccnx-pco.cpp
new file mode 100644
index 0000000..f592f53
--- /dev/null
+++ b/src/ccnx-pco.cpp
@@ -0,0 +1,55 @@
+#include "ccnx-pco.h"
+
+namespace Ccnx {
+
+ParsedContentObject::ParsedContentObject(const unsigned char *data, size_t len)
+            : m_comps(NULL)
+{
+  m_comps = ccn_indexbuf_create();
+  int res = ccn_parse_ContentObject(data, len, &m_pco, m_comps);
+  if (res < 0)
+  {
+    boost::throw_exception(MisformedContentObjectException());
+  }
+  readRaw(m_bytes, data, len);
+}
+
+ParsedContentObject::ParsedContentObject(const Bytes &bytes)
+{
+  ParsedContentObject((const unsigned char *)bytes[0], bytes.size());
+}
+
+ParsedContentObject::ParsedContentObject(const ParsedContentObject &other)
+{
+  ParsedContentObject(other.m_bytes); 
+}
+
+ParsedContentObject::~ParsedContentObject()
+{
+  ccn_indexbuf_destroy(&m_comps);
+  m_comps = NULL;
+}
+
+Bytes
+ParsedContentObject::content()
+{
+  const unsigned char *content;
+  size_t len;
+  Bytes bytes;
+  int res = ccn_content_get_value((const unsigned char *)m_bytes[0], m_pco.offset[CCN_PCO_E], &m_pco, &content, &len);
+  if (res < 0)
+  {
+    boost::throw_exception(MisformedContentObjectException());
+  }
+
+  readRaw(bytes, content, len);
+  return bytes;
+}
+
+string
+ParsedContentObject::name()
+{
+  return CcnxWrapper::extractName((const unsigned char *)m_bytes[0], m_comps);
+}
+
+}
diff --git a/src/ccnx-wrapper.cpp b/src/ccnx-wrapper.cpp
index 95d3130..58a2b7c 100644
--- a/src/ccnx-wrapper.cpp
+++ b/src/ccnx-wrapper.cpp
@@ -1,4 +1,7 @@
 #include "ccnx-wrapper.h"
+extern "C" {
+#include <ccn/fetch.h>
+}
 #include <poll.h>
 #include <boost/throw_exception.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -13,27 +16,17 @@
 
 namespace Ccnx {
 
-ContentObject::ContentObject(const char *data, size_t len)
-{
-  m_data = new char[len];
-  m_len = len;
-  memcpy(m_data, data, len);
-}
-
-ContentObject::~ContentObject()
-{
-  delete m_data;
-}
-
 void
-ContentObject::dup(char **data, size_t *len)
+readRaw(Bytes &bytes, const unsigned char *src, size_t len)
 {
-  char *tmp = new char[m_len];
-  memcpy(tmp, m_data, m_len);
-  (*data) = tmp;
-  (*len) = m_len;
+  if (len > 0)
+  {
+    bytes.resize(len);
+    memcpy(&bytes[0], src, len); 
+  }
 }
 
+
 CcnxWrapper::CcnxWrapper()
   : m_handle (0)
   , m_keyStore (0)
@@ -213,8 +206,7 @@
      } 
 }
 
-
-ContentObjectPtr 
+Bytes
 CcnxWrapper::createContentObject(const std::string &name, const char *buf, size_t len, int freshness)
 {
   ccn_charbuf *pname = ccn_charbuf_create();
@@ -236,25 +228,26 @@
   {
     // BOOST_THROW_EXCEPTION(CcnxOperationException() << errmsg_info_str("encode content failed"));
   }
-  
-  ContentObjectPtr co(new ContentObject((const char*)content->buf, content->length));
+
+  Bytes bytes;
+  readRaw(bytes, content->buf, content->length);
 
   ccn_charbuf_destroy (&pname);
   ccn_charbuf_destroy (&signed_info);
   ccn_charbuf_destroy (&content);
 
-  return co;
+  return bytes;
 }
 
 int
-CcnxWrapper::putToCcnd (ContentObjectPtr co)
+CcnxWrapper::putToCcnd (Bytes &contentObject)
 {
   recursive_mutex::scoped_lock lock(m_mutex);
   if (!m_running || !m_connected)
     return -1;
   
 
-  if (ccn_put(m_handle, co->m_data, co->m_len) < 0)
+  if (ccn_put(m_handle, (const unsigned char *)contentObject[0], contentObject.size()) < 0)
   {
     // BOOST_THROW_EXCEPTION(CcnxOperationException() << errmsg_info_str("ccnput failed"));
   }
@@ -265,37 +258,26 @@
 int
 CcnxWrapper::publishData (const string &name, const char *buf, size_t len, int freshness)
 {
-  ContentObjectPtr co = createContentObject(name, buf, len, freshness); 
+  Bytes co = createContentObject(name, buf, len, freshness); 
   return putToCcnd(co);
 }
 
-std::string
-CcnxWrapper::getInterestName(ccn_upcall_info *info)
+int
+CcnxWrapper::publishData (const string &name, const Bytes &content, int freshness)
 {
-  ostringstream interest (ostringstream::out);
-  for (int i = 0; i < info->interest_comps->n - 1; i++)
-  {
-    char *comp;
-    size_t size;
-    interest << "/";
-    ccn_name_comp_get(info->interest_ccnb, info->interest_comps, i, (const unsigned char **)&comp, &size);
-    string compStr(comp, size);
-    interest << compStr;
-  }
-
-  return interest.str();
+  publishData(name, (const char*)content[0], content.size(), freshness);
 }
 
-std::string
-CcnxWrapper::getDataName(ccn_upcall_info *info)
+string
+CcnxWrapper::extractName(const unsigned char *data, ccn_indexbuf *comps)
 {
   ostringstream name (ostringstream::out);
-  for (int i = 0; i < info->content_comps->n - 1; i++)
+  for (int i = 0; i < comps->n - 1; i++)
   {
     char *comp;
     size_t size;
     name << "/";
-    ccn_name_comp_get(info->content_ccnb, info->content_comps, i, (const unsigned char **)&comp, &size);
+    ccn_name_comp_get(data, comps, i, (const unsigned char **)&comp, &size);
     string compStr(comp, size);
     name << compStr;
   }
@@ -303,23 +285,6 @@
   return name.str();
 }
 
-int
-CcnxWrapper::getContentFromContentObject(ContentObjectPtr co, char **content, size_t *len)
-{
-  struct ccn_parsed_ContentObject pco;
-  struct ccn_indexbuf *comps = ccn_indexbuf_create();
-  int res1 = ccn_parse_ContentObject((const unsigned char *)co->m_data, co->m_len, &pco, comps);
-  int res2;
-
-  if (res1 >= 0)
-  {
-    res2 = ccn_content_get_value((const unsigned char *)co->m_data, pco.offset[CCN_PCO_E], &pco, (const unsigned char **)content, len);
-  }
-
-  ccn_indexbuf_destroy(&comps);
-
-  return (res1 < res2) ? res1 : res2;
-}
 
 static ccn_upcall_res
 incomingInterest(ccn_closure *selfp,
@@ -342,7 +307,7 @@
       return CCN_UPCALL_RESULT_OK;
     }
 
-  string interest = CcnxWrapper::getInterestName(info);
+  string interest = CcnxWrapper::extractName(info->interest_ccnb, info->interest_comps);
 
   (*f) (interest);
   return CCN_UPCALL_RESULT_OK;
@@ -372,7 +337,7 @@
         return CCN_UPCALL_RESULT_REEXPRESS;
       }
 
-      string interest = CcnxWrapper::getInterestName(info);
+      string interest = CcnxWrapper::extractName(info->interest_ccnb, info->interest_comps);
       CcnxWrapper::TimeoutCallbackReturnValue rv = cp->runTimeoutCallback(interest);
       switch(rv)
       {
@@ -387,16 +352,21 @@
       return CCN_UPCALL_RESULT_OK;
     }
 
-  char *pcontent;
+  const unsigned char *pcontent;
   size_t len;
-  if (ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, (const unsigned char **)&pcontent, &len) < 0)
+  if (ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, &pcontent, &len) < 0)
   {
     // BOOST_THROW_EXCEPTION(CcnxOperationException() << errmsg_info_str("decode ContentObject failed"));
   }
 
-  string name = CcnxWrapper::getDataName(info);
+  string name = CcnxWrapper::extractName(info->content_ccnb, info->content_comps);
 
-  cp->runCallback(name, pcontent, len);
+  Bytes content;
+  // copy content and do processing on the copy
+  // otherwise the pointed memory may have been changed during the processing
+  readRaw(content, pcontent, len);
+
+  cp->runDataCallback(name, content);
 
   return CCN_UPCALL_RESULT_OK;
 }
@@ -580,10 +550,10 @@
 
 
 void 
-ClosurePass::runCallback(std::string name, const char *data, size_t len) 
+ClosurePass::runDataCallback(std::string name, const Bytes &content) 
 {
-  if (m_callback != NULL) {
-    (*m_callback)(name, data, len);
+  if (m_dataCallback != NULL) {
+    (*m_dataCallback)(name, content);
   }
 }