Debugging and resolving problems with interest serialization/deserialization
diff --git a/helper/ccnb-parser/ccnx-decoding-helper.h b/helper/ccnb-parser/ccnx-decoding-helper.h
deleted file mode 100644
index 375a57a..0000000
--- a/helper/ccnb-parser/ccnx-decoding-helper.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2011 University of California, Los Angeles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- */
-
-#ifndef _CCNX_DECODING_HELPER_H_
-#define _CCNX_DECODING_HELPER_H_
-
-namespace ns3 {
-
-class CcnxInterestHeader;
-class CcnxContentObjectHeader;
-
-/**
- * \brief Helper class to decode ccnb formatted CCNx message
- */
-class CcnxDecodingHelper
-{
-public:
-  static size_t
-  Deserialize (Buffer::Iterator start, const CcnxInterestHeader &interest);
-
-  static size_t
-  Deserialize (Buffer::Iterator start, const CcnxContentObjectHeader &contentObject);
-  
-private:
-};
-
-} // namespace ns3
-
-#endif // _CCNX_DECODING_HELPER_H_
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-attr.cc b/helper/ccnb-parser/syntax-tree/ccnb-parser-attr.cc
index 397e940..e4baf54 100644
--- a/helper/ccnb-parser/syntax-tree/ccnb-parser-attr.cc
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-attr.cc
@@ -28,10 +28,13 @@
 Attr::Attr (Buffer::Iterator &start, uint32_t length)
 {
   m_attr.reserve (length+2); // extra byte for potential \0 at the end
-  for (uint32_t i = 0; i < (length+1); i++)
+  uint32_t i = 0;
+  for (; !start.IsEnd () && i < (length+1); i++)
     {
       m_attr.push_back (start.ReadU8 ());
     }
+  if (i < (length+1) && start.IsEnd ())
+    throw CcnbDecodingException ();
   m_value = DynamicCast<Udata> (Block::ParseBlock (start));
   if (m_value == 0)
     throw CcnbDecodingException (); // "ATTR must be followed by UDATA field"
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.cc b/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.cc
index 4467891..a0a112c 100644
--- a/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.cc
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.cc
@@ -18,15 +18,30 @@
  * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
-#include "ccnb-parser-blob.h"
+#include "ns3/ccnb-parser-blob.h"
 
 namespace ns3 {
 namespace CcnbParser {
 
 Blob::Blob (Buffer::Iterator &start, uint32_t length)
 {
-  m_blob = Buffer (length);
-  start.Read (m_blob.Begin (), length);
+  m_blobSize = length;
+  m_blob = new char[length];
+  if (m_blob == 0 )
+    throw CcnbDecodingException (); // memory problem
+
+  uint32_t i = 0;
+  for (; !start.IsEnd () && i < length; i++)
+    {
+      m_blob[i] = start.ReadU8 ();
+    }
+  if (i < length && start.IsEnd ())
+    throw CcnbDecodingException ();
+}
+
+Blob::~Blob ()
+{
+  delete [] m_blob;
 }
 
 }
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.h b/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.h
index 4b22d62..f2ede3d 100644
--- a/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.h
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-blob.h
@@ -22,7 +22,6 @@
 #define _CCNB_PARSER_BLOB_H_
 
 #include "ccnb-parser-block.h"
-#include "ns3/buffer.h"
 
 namespace ns3 {
 namespace CcnbParser {
@@ -45,13 +44,15 @@
    * \see http://www.ccnx.org/releases/latest/doc/technical/BinaryEncoding.html
    */
   Blob (Buffer::Iterator &start, uint32_t length);
+  ~Blob ();
   
   virtual void accept( VoidNoArguVisitor &v )               { v.visit( *this ); }
   virtual void accept( VoidVisitor &v, boost::any param )   { v.visit( *this, param ); }
   virtual boost::any accept( NoArguVisitor &v )             { return v.visit( *this ); }
   virtual boost::any accept( Visitor &v, boost::any param ) { return v.visit( *this, param ); }
 
-  Buffer m_blob; ///< \brief field holding a parsed BLOB value of the block
+  char* m_blob; ///< \brief field holding a parsed BLOB value of the block
+  uint32_t  m_blobSize;
 };
 
 }
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-block.cc b/helper/ccnb-parser/syntax-tree/ccnb-parser-block.cc
index e1e09fd..2af8aef 100644
--- a/helper/ccnb-parser/syntax-tree/ccnb-parser-block.cc
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-block.cc
@@ -42,31 +42,38 @@
 
   // We will have problems if length field is more than 32 bits. Though it's really impossible
   uint8_t byte = 0;
-  while (!(byte & CCN_TT_HBIT))
+  while (!start.IsEnd() && !(byte & CCN_TT_HBIT))
     {
       value <<= 8;
       value += byte;
       byte = start.ReadU8 ();
     }
+  if (start.IsEnd())
+    CcnbDecodingException ();
+  
   value <<= 4;
   value += ( (byte&(~CCN_TT_HBIT)) >> 3);
 
+  /**
+   * Huh. After fighting with NS-3, it became apparent that Create<T>(...) construct
+   * doesn't work with references.  Just simply doesn't work.  wtf?
+   */
   switch (byte & CCN_TT_MASK)
     {
     case CCN_BLOB:
-      return Create<Blob> (start, value);
+      return Ptr<Blob> (new Blob(start, value));
     case CCN_UDATA:
-      return Create<Udata> (start, value);
+      return Ptr<Udata> (new Udata(start, value));
     case CCN_TAG:
-      return Create<Tag> (start, value);
+      return Ptr<Tag> (new Tag(start, value));
     case CCN_ATTR:
-      return Create<Attr> (start, value);
+      return Ptr<Attr> (new Attr(start, value));
     case CCN_DTAG:
-      return Create<Dtag> (start, value);
+      return Ptr<Dtag> (new Dtag(start, value));
     case CCN_DATTR:
-      return Create<Dattr> (start, value);
+      return Ptr<Dattr> (new Dattr(start, value));
     case CCN_EXT:
-      return Create<Ext> (start, value);
+      return Ptr<Ext> (new Ext(start, value));
     default:
       throw CcnbDecodingException ();
     }
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-dtag.cc.~HEAD~ b/helper/ccnb-parser/syntax-tree/ccnb-parser-dtag.cc.~HEAD~
new file mode 100644
index 0000000..8d9ecf7
--- /dev/null
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-dtag.cc.~HEAD~
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnb-parser-dtag.h"
+
+#include "ccnb-parser-base-attr.h"
+#include "ccnb-parser-base-tag.h"
+
+namespace ns3 {
+namespace CcnbParser {
+
+Dtag::Dtag (Buffer::Iterator &start, uint32_t dtag)
+{
+  m_dtag = dtag;
+
+  /**
+   * Hack
+   *
+   * Stop processing after encountering <Content> dtag.  Actual
+   * content (including virtual payload) will be stored in Packet
+   * buffer
+   */
+  if (dtag == CCN_DTAG_Content)
+    return; // hack #1. Do not process nesting block for <Content>
+  
+  // parse attributes until first nested block reached
+  while (!start.IsEnd () && start.PeekU8 ()!=CCN_CLOSE)
+    {
+      Ptr<Block> block = Block::ParseBlock (start);
+      if (DynamicCast<BaseAttr> (block)!=0)
+		m_attrs.push_back (block);
+	  else
+		{
+		  m_nestedTags.push_back (block);
+		  break;
+		}
+	}
+
+  // parse the rest of nested blocks
+  while (!start.IsEnd () && start.PeekU8 ()!=CCN_CLOSE)
+    {
+      // hack #2. Stop processing nested blocks if last block was <Content>
+      if (m_dtag == CCN_DTAG_ContentObject && // we are in <ContentObject>
+          DynamicCast<Dtag> (m_nestedTags.back())!=0 && // last block is DTAG
+          DynamicCast<Dtag> (m_nestedTags.back())->m_dtag == CCN_DTAG_Content) 
+        {
+          return; 
+        }
+
+      m_nestedTags.push_back (Block::ParseBlock (start));
+    }
+  if (start.IsEnd ())
+      throw CcnbDecodingException ();
+
+  start.ReadU8 (); // read CCN_CLOSE
+}
+
+}
+}
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-tag.cc b/helper/ccnb-parser/syntax-tree/ccnb-parser-tag.cc
index c288be9..5862ad4 100644
--- a/helper/ccnb-parser/syntax-tree/ccnb-parser-tag.cc
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-tag.cc
@@ -28,10 +28,13 @@
 Tag::Tag (Buffer::Iterator &start, uint32_t length)
 {
   m_tag.reserve (length+2); // extra byte for potential \0 at the end
-  for (uint32_t i = 0; i < (length+1); i++)
+  uint32_t i = 0;
+  for (; !start.IsEnd () && i < (length+1); i++)
     {
       m_tag.push_back (start.ReadU8 ());
     }
+  if (i < (length+1) && start.IsEnd ())
+    throw CcnbDecodingException ();
   
   // parse attributes until first nested block reached
   while (!start.IsEnd () && start.PeekU8 ()!=CCN_CLOSE)
diff --git a/helper/ccnb-parser/syntax-tree/ccnb-parser-udata.cc b/helper/ccnb-parser/syntax-tree/ccnb-parser-udata.cc
index 39217fd..91cba15 100644
--- a/helper/ccnb-parser/syntax-tree/ccnb-parser-udata.cc
+++ b/helper/ccnb-parser/syntax-tree/ccnb-parser-udata.cc
@@ -32,10 +32,14 @@
 
   m_udata.reserve (length+1); //just in case we will need \0 at the end later
   // this is actually the way Read method is implemented in network/src/buffer.cc
-  for (uint32_t i = 0; i < length; i++)
+  uint32_t i = 0;
+  for (; !start.IsEnd () && i < length; i++)
     {
       m_udata.push_back (start.ReadU8 ());
     }
+
+  if (i < length && start.IsEnd ())
+    throw CcnbDecodingException ();
 }
 
 }
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.cc b/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.cc
index 8548598..d562695 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.cc
+++ b/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.cc
@@ -35,13 +35,13 @@
 
 // We don't really care about any other fields
 void
-ContentObjectVisitor::visit (Dtag &n, boost::any param/*should be CcnxContentObjectHeader&*/)
+ContentObjectVisitor::visit (Dtag &n, boost::any param/*should be CcnxContentObjectHeader* */)
 {
   // uint32_t n.m_dtag;
   // std::list<Ptr<Block> > n.m_nestedBlocks;
   static NameComponentsVisitor nameComponentsVisitor;
   
-  CcnxContentObjectHeader &contentObject = boost::any_cast<CcnxContentObjectHeader&> (param);
+  CcnxContentObjectHeader &contentObject = *(boost::any_cast<CcnxContentObjectHeader*> (param));
   
   switch (n.m_dtag)
     {
@@ -59,7 +59,7 @@
         
         BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags)
           {
-            block->accept (nameComponentsVisitor, *name);
+            block->accept (nameComponentsVisitor, &(*name));
           }
         contentObject.SetName (name);
         break;
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.h b/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.h
index e15e290..ae6fe9b 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.h
+++ b/helper/ccnb-parser/visitors/ccnb-parser-content-object-visitor.h
@@ -41,7 +41,7 @@
 class ContentObjectVisitor : public VoidDepthFirstVisitor
 {
 public:
-  virtual void visit (Dtag &n, boost::any param/*should be CcnxContentObjectHeader&*/);
+  virtual void visit (Dtag &n, boost::any param/*should be CcnxContentObjectHeader* */);
 };
 
 }
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.cc b/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.cc
index 052cb8c..0bd0e46 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.cc
+++ b/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.cc
@@ -39,7 +39,7 @@
 
 // We don't care about any other fields
 void
-InterestVisitor::visit (Dtag &n, boost::any param/*should be CcnxInterestHeader&*/)
+InterestVisitor::visit (Dtag &n, boost::any param/*should be CcnxInterestHeader* */)
 {
   // uint32_t n.m_dtag;
   // std::list<Ptr<Block> > n.m_nestedBlocks;
@@ -49,7 +49,7 @@
   static TimestampVisitor          timestampVisitor;
   static NonceVisitor              nonceVisitor;
   
-  CcnxInterestHeader &interest = boost::any_cast<CcnxInterestHeader&> (param);
+  CcnxInterestHeader &interest = *(boost::any_cast<CcnxInterestHeader*> (param));
   
   switch (n.m_dtag)
     {
@@ -67,7 +67,7 @@
         
         BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags)
           {
-            block->accept (nameComponentsVisitor, *name);
+            block->accept (nameComponentsVisitor, &(*name));
           }
         interest.SetName (name);
         break;
@@ -97,7 +97,7 @@
         
         BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags)
           {
-            block->accept (nameComponentsVisitor, *exclude);
+            block->accept (nameComponentsVisitor, &(*exclude));
           }
         interest.SetExclude (exclude);
         break;
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.h b/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.h
index 136b173..35a1e13 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.h
+++ b/helper/ccnb-parser/visitors/ccnb-parser-interest-visitor.h
@@ -41,7 +41,7 @@
 class InterestVisitor : public VoidDepthFirstVisitor
 {
 public:
-  virtual void visit (Dtag &n, boost::any param/*should be CcnxInterestHeader&*/);
+  virtual void visit (Dtag &n, boost::any param/*should be CcnxInterestHeader* */);
 };
 
 }
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.cc b/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.cc
index 08bfe2e..314cb68 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.cc
+++ b/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.cc
@@ -28,13 +28,13 @@
 namespace CcnbParser {
 
 void
-NameComponentsVisitor::visit (Dtag &n, boost::any param/*should be CcnxNameComponents&*/)
+NameComponentsVisitor::visit (Dtag &n, boost::any param/*should be CcnxNameComponents* */)
 {
   // uint32_t n.m_dtag;
   // std::list<Ptr<Block> > n.m_nestedBlocks;
   static StringVisitor stringVisitor; 
  
-  CcnxNameComponents &components = boost::any_cast<CcnxNameComponents&> (param);
+  CcnxNameComponents &components = *(boost::any_cast<CcnxNameComponents*> (param));
 
   switch (n.m_dtag)
     {
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.h b/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.h
index e4b92cf..70257c5 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.h
+++ b/helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.h
@@ -33,7 +33,7 @@
 class NameComponentsVisitor : public VoidDepthFirstVisitor
 {
 public:
-  virtual void visit (Dtag &n, boost::any param/*should be CcnxNameComponents&*/);
+  virtual void visit (Dtag &n, boost::any param/*should be CcnxNameComponents* */);
 };
 
 }
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-nonce-visitor.cc b/helper/ccnb-parser/visitors/ccnb-parser-nonce-visitor.cc
index 7492adf..931f2fa 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-nonce-visitor.cc
+++ b/helper/ccnb-parser/visitors/ccnb-parser-nonce-visitor.cc
@@ -28,10 +28,10 @@
 NonceVisitor::visit (Blob &n) 
 {
   // Buffer n.m_blob;
-  if (n.m_blob.GetSize ()<4)
+  if (n.m_blobSize < 4)
     throw CcnbDecodingException ();
      
-  return boost::any (n.m_blob.Begin ().ReadU32 ());
+  return boost::any (*(reinterpret_cast<uint32_t*> (n.m_blob)));
 }
 
 boost::any
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.cc b/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.cc
index 33c9465..dfc61ed 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.cc
+++ b/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.cc
@@ -20,6 +20,7 @@
 
 #include "ccnb-parser-string-visitor.h"
 #include "ns3/ccnb-parser-udata.h"
+#include "ns3/ccnb-parser-blob.h"
 
 namespace ns3 {
 namespace CcnbParser {
@@ -28,7 +29,7 @@
 StringVisitor::visit (Blob &n) 
 {
   // Buffer n.m_blob;
-  throw CcnbDecodingException ();
+  return std::string (n.m_blob, n.m_blobSize);
 }
 
 boost::any
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.h b/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.h
index b2a2a29..2a1e8ed 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.h
+++ b/helper/ccnb-parser/visitors/ccnb-parser-string-visitor.h
@@ -35,7 +35,7 @@
 class StringVisitor : public NoArguDepthFirstVisitor
 {
 public:
-  virtual boost::any visit (Blob &n); ///< Throws parsing error if BLOB object is encountered
+  virtual boost::any visit (Blob &n);
   virtual boost::any visit (Udata &n);
 };
 
diff --git a/helper/ccnb-parser/visitors/ccnb-parser-timestamp-visitor.cc b/helper/ccnb-parser/visitors/ccnb-parser-timestamp-visitor.cc
index 4724bb4..22965aa 100644
--- a/helper/ccnb-parser/visitors/ccnb-parser-timestamp-visitor.cc
+++ b/helper/ccnb-parser/visitors/ccnb-parser-timestamp-visitor.cc
@@ -30,26 +30,27 @@
 TimestampVisitor::visit (Blob &n) 
 {
   // Buffer n.m_blob;
-  if (n.m_blob.GetSize ()<2)
+  if (n.m_blobSize < 2)
     throw CcnbDecodingException ();
 
-  Buffer::Iterator start = n.m_blob.Begin ();
+  const char *start = n.m_blob;
   
   intmax_t seconds = 0;
   intmax_t nanoseconds = 0;
 
-  for (uint32_t i=0; i < n.m_blob.GetSize ()-2; i++)
+  for (uint32_t i=0; i < n.m_blobSize-2; i++)
     {
-      seconds = (seconds << 8) | start.ReadU8 ();
+      seconds = (seconds << 8) | (uint8_t)start[i];
     }
-  uint8_t combo = start.ReadU8 (); // 4 most significant bits hold 4 least significant bits of number of seconds
-  seconds = (seconds << 8) | (combo >> 4);
+  uint8_t combo = start[n.m_blobSize-2]; // 4 most significant bits hold 4 least significant bits of number of seconds
+  seconds = (seconds << 4) | (combo >> 4);
+  std::cout << std::hex << (int) start[n.m_blobSize-2] << "\n";
 
   nanoseconds = combo & 0x0F; /*00001111*/ // 4 least significant bits hold 4 most significant bits of number of
-  nanoseconds = (nanoseconds << 8) | start.ReadU8 ();
-  nanoseconds = (intmax_t) ((nanoseconds / 4096.0/*2^12*/) * 1000000000 /*up-convert nanoseconds*/);
+  nanoseconds = (nanoseconds << 8) | start[n.m_blobSize-1];
+  nanoseconds = (intmax_t) ((nanoseconds / 4096.0/*2^12*/) * 1000000 /*up-convert useconds*/);
 
-  return boost::any (Time::FromInteger (seconds, Time::S) + Time::FromInteger (nanoseconds, Time::NS));
+  return boost::any (Time::FromInteger (seconds, Time::S) + Time::FromInteger (nanoseconds, Time::US));
 }
 
 boost::any