Merge remote-tracking branch 'git.irl/master'

Conflicts:
	include/ccnx-name.h
diff --git a/include/ccnx-closure.h b/include/ccnx-closure.h
index 66f79e8..f006d11 100644
--- a/include/ccnx-closure.h
+++ b/include/ccnx-closure.h
@@ -31,6 +31,9 @@
   virtual TimeoutCallbackReturnValue
   runTimeoutCallback(const Name &interest);
 
+  virtual Closure *
+  dup() const;
+
 protected:
   int m_retry;
   TimeoutCallback *m_timeoutCallback;
diff --git a/include/ccnx-name.h b/include/ccnx-name.h
index 8966e50..8b8be4a 100644
--- a/include/ccnx-name.h
+++ b/include/ccnx-name.h
@@ -36,6 +36,7 @@
 public:
   CcnxCharbuf();
   CcnxCharbuf(ccn_charbuf *buf);
+  CcnxCharbuf(const CcnxCharbuf &other);
   ~CcnxCharbuf();
 
   // expose internal data structure, use with caution!!
@@ -51,6 +52,9 @@
   length () const
   { return m_buf->length; }
   
+private:
+  void init(ccn_charbuf *buf);
+
 protected:
   ccn_charbuf *m_buf;
 };
diff --git a/include/ccnx-pco.h b/include/ccnx-pco.h
index 8711a3e..7956dad 100644
--- a/include/ccnx-pco.h
+++ b/include/ccnx-pco.h
@@ -25,9 +25,14 @@
   Name
   name() const;
 
+private:
+  void
+  init(const unsigned char *data, size_t len);
+
 protected:
-  Name m_name;
-  Bytes m_content;
+  ccn_parsed_ContentObject m_pco;
+  ccn_indexbuf *m_comps;
+  Bytes m_bytes;
 };
 
 typedef boost::shared_ptr<ParsedContentObject> PcoPtr;
diff --git a/include/ccnx-tunnel.h b/include/ccnx-tunnel.h
index 0525458..bc13f9a 100644
--- a/include/ccnx-tunnel.h
+++ b/include/ccnx-tunnel.h
@@ -40,7 +40,7 @@
   publishContentObject(const Name &name, const Bytes &contentObject, int freshness);
 
   virtual int
-  sendInterest (const Name &interest, Closure *closure, const Selectors &selectors = Selectors());
+  sendInterest (const Name &interest, const Closure *closure, const Selectors &selectors = Selectors());
 
 
   // prefix is topology-independent
@@ -75,6 +75,9 @@
   void
   handleTunneledData(const Name &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback);
 
+private:
+  CcnxTunnel(const CcnxTunnel &other) {}
+
 protected:
   // need a way to update local prefix, perhaps using macports trick, but eventually we need something more portable
   Name m_localPrefix;
@@ -95,6 +98,9 @@
   virtual TimeoutCallbackReturnValue
   runTimeoutCallback(const Name &interest) _OVERRIDE;
 
+  virtual Closure *
+  dup() const _OVERRIDE;
+
 private:
   CcnxTunnel *m_tunnel;
   Name m_originalInterest;
diff --git a/include/ccnx-wrapper.h b/include/ccnx-wrapper.h
index 12a5bc7..dd7d762 100644
--- a/include/ccnx-wrapper.h
+++ b/include/ccnx-wrapper.h
@@ -37,7 +37,7 @@
   clearInterestFilter (const Name &prefix);
 
   virtual int
-  sendInterest (const Name &interest, Closure *closure, const Selectors &selector = Selectors());
+  sendInterest (const Name &interest, const Closure *closure, const Selectors &selector = Selectors());
 
   virtual int
   publishData (const Name &name, const unsigned char *buf, size_t len, int freshness);
@@ -54,6 +54,9 @@
   int
   putToCcnd (const Bytes &contentObject);
 
+private:
+  CcnxWrapper(const CcnxWrapper &other) {}
+
 protected:
   void
   connectCcnd();
diff --git a/src/ccnx-closure.cpp b/src/ccnx-closure.cpp
index 5b30244..528c721 100644
--- a/src/ccnx-closure.cpp
+++ b/src/ccnx-closure.cpp
@@ -3,15 +3,17 @@
 namespace Ccnx {
 
 Closure::Closure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback)
-              : m_retry(retry), m_timeoutCallback(NULL)
+              : m_retry(retry), m_timeoutCallback(NULL), m_dataCallback(NULL)
 {
   m_timeoutCallback = new TimeoutCallback (timeoutCallback);
   m_dataCallback = new DataCallback (dataCallback);
 }
 
 Closure::Closure(const Closure &other)
+            :m_retry(other.m_retry), m_timeoutCallback(NULL), m_dataCallback(NULL)
 {
-  Closure(other.m_retry, *(other.m_dataCallback), *(other.m_timeoutCallback));
+  m_timeoutCallback = new TimeoutCallback(*(other.m_timeoutCallback));
+  m_dataCallback = new DataCallback(*(other.m_dataCallback));
 }
 
 Closure::~Closure ()
@@ -42,4 +44,11 @@
   }
 }
 
+Closure *
+Closure::dup() const
+{
+  Closure *closure = new Closure(*this);
+  return closure;
+}
+
 } // Ccnx
diff --git a/src/ccnx-name.cpp b/src/ccnx-name.cpp
index 9e9f9e0..9bc2663 100644
--- a/src/ccnx-name.cpp
+++ b/src/ccnx-name.cpp
@@ -6,6 +6,18 @@
 namespace Ccnx{
 CcnxCharbufPtr CcnxCharbuf::Null;
 
+void
+CcnxCharbuf::init(ccn_charbuf *buf)
+{
+  if (buf != NULL)
+  {
+    m_buf = ccn_charbuf_create();
+    ccn_charbuf_reserve(m_buf, buf->length);
+    memcpy(m_buf->buf, buf->buf, buf->length);
+    m_buf->length = buf->length;
+  }
+}
+
 CcnxCharbuf::CcnxCharbuf()
             : m_buf(NULL)
 {
@@ -15,13 +27,13 @@
 CcnxCharbuf::CcnxCharbuf(ccn_charbuf *buf)
             : m_buf(NULL)
 {
-  if (buf != NULL)
-  {
-    m_buf = ccn_charbuf_create();
-    ccn_charbuf_reserve(m_buf, buf->length);
-    memcpy(m_buf->buf, buf->buf, buf->length);
-    m_buf->length = buf->length;
-  }
+  init(buf);
+}
+
+CcnxCharbuf::CcnxCharbuf(const CcnxCharbuf &other)
+            : m_buf (NULL)
+{
+  init(other.m_buf);
 }
 
 CcnxCharbuf::~CcnxCharbuf()
diff --git a/src/ccnx-pco.cpp b/src/ccnx-pco.cpp
index 1d83b26..af10c7a 100644
--- a/src/ccnx-pco.cpp
+++ b/src/ccnx-pco.cpp
@@ -2,57 +2,62 @@
 
 namespace Ccnx {
 
-ParsedContentObject::ParsedContentObject(const unsigned char *data, size_t len)
+void
+ParsedContentObject::init(const unsigned char *data, size_t len)
 {
-  ccn_indexbuf *comps = ccn_indexbuf_create();
-  ccn_parsed_ContentObject pco;
-  int res = ccn_parse_ContentObject(data, len, &pco, comps);
+  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);
+}
 
-  const unsigned char *content;
-  size_t length;
-  res = ccn_content_get_value(data, pco.offset[CCN_PCO_E], &pco, &content, &length);
-  if (res < 0)
-  {
-    boost::throw_exception(MisformedContentObjectException());
-  }
-  readRaw(m_content, content, length);
-
-  m_name = Name(data, comps);
-  cout << "in Constructor: name " << m_name << endl;
-  cout << "content : " << string((const char *)&m_content[0], m_content.size()) << endl;
+ParsedContentObject::ParsedContentObject(const unsigned char *data, size_t len)
+            : m_comps(NULL)
+{
+  init(data, len);
 }
 
 ParsedContentObject::ParsedContentObject(const Bytes &bytes)
+            : m_comps(NULL)
 {
-  ParsedContentObject(head(bytes), bytes.size());
+  init(head(bytes), bytes.size());
 }
 
 ParsedContentObject::ParsedContentObject(const ParsedContentObject &other)
+            : m_comps(NULL)
 {
-  m_content = other.m_content;
-  m_name = other.m_name;
+  init(head(other.m_bytes), other.m_bytes.size());
 }
 
 ParsedContentObject::~ParsedContentObject()
 {
+  ccn_indexbuf_destroy(&m_comps);
+  m_comps = NULL;
 }
 
 Bytes
 ParsedContentObject::content() const
 {
-  cout << "content() : " << string((const char *)&m_content[0], m_content.size()) << endl;
-  return m_content;
+  const unsigned char *content;
+  size_t len;
+  Bytes bytes;
+  int res = ccn_content_get_value(head(m_bytes), m_pco.offset[CCN_PCO_E], &m_pco, &content, &len);
+  if (res < 0)
+  {
+    boost::throw_exception(MisformedContentObjectException());
+  }
+
+  readRaw(bytes, content, len);
+  return bytes;
 }
 
 Name
 ParsedContentObject::name() const
 {
-  cout <<"name() : " << m_name << endl;
-  return m_name;
+  return Name(head(m_bytes), m_comps);
 }
 
 }
diff --git a/src/ccnx-tunnel.cpp b/src/ccnx-tunnel.cpp
index 36b8f6f..6a7dd29 100644
--- a/src/ccnx-tunnel.cpp
+++ b/src/ccnx-tunnel.cpp
@@ -8,7 +8,7 @@
                           : CcnxWrapper()
                           , m_localPrefix("/")
 {
-  //refreshLocalPrefix();
+  refreshLocalPrefix();
 }
 
 CcnxTunnel::~CcnxTunnel()
@@ -28,21 +28,18 @@
 }
 
 int
-CcnxTunnel::sendInterest (const Name &interest, Closure *closure, const Selectors &selectors)
+CcnxTunnel::sendInterest (const Name &interest, const Closure *closure, const Selectors &selectors)
 {
   Name tunneledInterest = queryRoutableName(interest);
   Closure *cp = new TunnelClosure(closure, this, interest);
-  cout << "send interest in Tunnel" << endl;
   CcnxWrapper::sendInterest(tunneledInterest, cp, selectors);
+  delete cp;
 }
 
 void
 CcnxTunnel::handleTunneledData(const Name &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback)
 {
   ParsedContentObject pco(tunneledData);
-  Name n = pco.name();
-  Bytes b = pco.content();
-  cout <<"Parsed ContentObject" << n << b.size() << endl;
   originalDataCallback(pco.name(), pco.content());
 }
 
@@ -59,7 +56,6 @@
 CcnxTunnel::publishContentObject(const Name &name, const Bytes &contentObject, int freshness)
 {
   Name tunneledName = m_localPrefix + name;
-  cout << "Outer name " << tunneledName;
   Bytes tunneledCo = createContentObject(tunneledName, head(contentObject), contentObject.size(), freshness);
   return putToCcnd(tunneledCo);
 }
@@ -133,6 +129,13 @@
 {
 }
 
+Closure *
+TunnelClosure::dup() const
+{
+  Closure *closure = new TunnelClosure(m_retry, *m_dataCallback, m_tunnel, m_originalInterest, *m_timeoutCallback);
+  return closure;
+}
+
 void
 TunnelClosure::runDataCallback(const Name &name, const Bytes &content)
 {
diff --git a/src/ccnx-wrapper.cpp b/src/ccnx-wrapper.cpp
index 981fdd4..0f4a8d5 100644
--- a/src/ccnx-wrapper.cpp
+++ b/src/ccnx-wrapper.cpp
@@ -257,6 +257,8 @@
   switch (kind)
     {
     case CCN_UPCALL_FINAL:  // effecitve in unit tests
+      delete cp;
+      cp = NULL;
       delete selfp;
       return CCN_UPCALL_RESULT_OK;
 
@@ -303,7 +305,7 @@
   return CCN_UPCALL_RESULT_OK;
 }
 
-int CcnxWrapper::sendInterest (const Name &interest, Closure *closure, const Selectors &selectors)
+int CcnxWrapper::sendInterest (const Name &interest, const Closure *closure, const Selectors &selectors)
 {
   UniqueRecLock(m_mutex);
   if (!m_running || !m_connected)
@@ -313,7 +315,8 @@
   ccn_charbuf *pname = namePtr->getBuf();
   ccn_closure *dataClosure = new ccn_closure;
 
-  dataClosure->data = (void *)closure;
+  Closure *myClosure = closure->dup();
+  dataClosure->data = (void *)myClosure;
 
   dataClosure->p = &incomingData;