model: Major API changes

Interest and ContentObject are no longer derived from Header class.
Instead, they are encapsulating payload and, optionally, wire-formatted
Packet object.

Refs #1005 (http://redmine.named-data.net/)
diff --git a/model/wire/ndnsim.cc b/model/wire/ndnsim.cc
new file mode 100644
index 0000000..747d264
--- /dev/null
+++ b/model/wire/ndnsim.cc
@@ -0,0 +1,406 @@
+/** -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/* 
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ * 
+ * BSD license, See the doc/LICENSE file for more information
+ * 
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ndnsim.h"
+
+NDN_NAMESPACE_BEGIN
+
+namespace wire {
+namespace ndnSIM {
+
+
+class Name
+{
+public:
+  Name ()
+    : m_name (Create<ndn::Name> ())
+  {
+  }
+  
+  Name (Ptr<ndn::Name> name)
+    : m_name (name)
+  {
+  }
+
+  Ptr<Name>
+  GetName ()
+  {
+    return m_name;
+  }
+  
+  size_t
+  GetSerializedSize () const
+  {
+    size_t nameSerializedSize = 2;
+
+    for (std::list<std::string>::const_iterator i = m_name->begin ();
+         i != m_name->end ();
+         i++)
+      {
+        nameSerializedSize += 2 + i->size ();
+      }
+    NS_ASSERT_MSG (nameSerializedSize < 30000, "Name is too long (> 30kbytes)");
+
+    return nameSerializedSize;
+  }
+
+  uint32_t
+  Serialize (Buffer::Iterator start) const
+  {
+    Buffer::Iterator i = start;
+
+    i.WriteU16 (static_cast<uint16_t> (m_name->GetSerializedSize ()-2));
+
+    for (std::list<std::string>::const_iterator item = m_name->begin ();
+         item != m_name->end ();
+         item++)
+      {
+        i.WriteU16 (static_cast<uint16_t> (item->size ()));
+        i.Write (reinterpret_cast<const uint8_t*> (item->c_str ()), item->size ());
+      }
+
+    return i.GetDistanceFrom (start);
+  }
+
+  uint32_t
+  Deserialize (Buffer::Iterator start)
+  {
+    Buffer::Iterator i = start;
+
+    uint16_t nameLength = i.ReadU16 ();
+    while (nameLength > 0)
+      {
+        uint16_t length = i.ReadU16 ();
+        nameLength = nameLength - 2 - length;
+
+        uint8_t tmp[length];
+        i.Read (tmp, length);
+
+        m_name->Add (string (reinterpret_cast<const char*> (tmp), length));
+      }
+
+    return i.GetDistanceFrom (start);
+  }
+
+private:
+  Ptr<ndn::Name> m_name;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+Interest::Interest ()
+  : m_interest (Create<ndn::Interest> ())
+{
+}
+
+Interest::Interest (Ptr<ndn::Interest> interest)
+  : m_interest (interest)
+{
+}
+
+Ptr<ndn::Interest>
+Interest::GetInterest ()
+{
+  return m_interest;
+}
+
+
+TypeId
+Interest::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ndn::Interest::ndnSIM")
+    .SetGroupName ("Ndn")
+    .AddParent<Header> ()
+    .AddConstructor<Interest> ()
+    ;
+  return tid;
+}
+
+TypeId
+Interest::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+Ptr<Packet>
+Interest::ToWire (Ptr<const ndn::Interest> interest)
+{
+  Ptr<const Packet> p = interest->GetWire ();
+  if (!p)
+    {
+      p = Create<Packet> (*interest->GetPayload ());
+      Interest wireEncoding (interest);
+      p->AddHeader (wireEncoding);
+      interest->SetWire (p);
+    }
+  
+  return p->Copy ();
+}
+
+Ptr<ndn::Interest>
+Interest::FromWire (Ptr<Packet> packet)
+{
+  Ptr<ndn::Interest> interest = Create<ndn::Interest> ();
+  // interest->SetWire (packet->Copy ()); /* not sure if this is needed */
+
+  Interest wireEncoding (interest);
+  packet->RemoveHeader (wireEncoding);
+
+  interest->SetPayload (packet);
+
+  return interest;
+}
+
+uint32_t
+Interest::GetSerializedSize (void) const
+{
+  size_t size =
+    1/*version*/ + 1 /*type*/ + 2/*length*/ +
+    (4/*nonce*/ + 1/*scope*/ + 1/*nack type*/ + 2/*timestamp*/ +
+     (Name (ConstCast<ns3::Name> (m_interest->GetNamePtr ())).GetSerializedSize ()) +
+     (2 + 0)/* selectors */ +
+     (2 + 0)/* options */);
+  
+  NS_LOG_INFO ("Serialize size = " << size);
+  return size;
+}
+    
+void
+Interest::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (0x80); // version
+  start.WriteU8 (0x00); // packet type
+
+  start.WriteU16 (GetSerializedSize () - 4);
+
+  start.WriteU32 (m_nonce);
+  start.WriteU8 (m_scope);
+  start.WriteU8 (m_nackType);
+
+  NS_ASSERT_MSG (0 <= m_interest->GetInterestLifetime.ToInteger (Time::S) && m_interest->GetInterestLifetime.ToInteger (Time::S) < 65535,
+                 "Incorrect InterestLifetime (should not be smaller than 0 and larger than 65535");
+  
+  // rounding timestamp value to seconds
+  start.WriteU16 (static_cast<uint16_t> (m_interest->GetInterestLifetime.ToInteger (Time::S)));
+
+  uint32_t offset = Name (ConstCast<ns3::Name> (m_interest->GetNamePtr ())).Serialize (start);
+  start.Next (offset);
+  
+  start.WriteU16 (0); // no selectors
+  start.WriteU16 (0); // no options
+}
+
+uint32_t
+Interest::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  
+  if (i.ReadU8 () != 0x80)
+    throw new InterestException ();
+
+  if (i.ReadU8 () != 0x00)
+    throw new InterestException ();
+
+  i.ReadU16 (); // length, don't need it right now
+  
+  m_interest->SetNonce (i.ReadU32 ());
+  m_interest->SetScope (i.ReadU8 ());
+  m_interest->SetNackType (i.ReadU8 ());
+
+  m_interest->SetInterestLifetime (Seconds (i.ReadU16 ()));
+
+  Name name;
+  uint32_t offset = name.Deserialize (i);
+  m_interest->SetName (name->GetName ());
+  i.Next (offset);
+  
+  i.ReadU16 ();
+  i.ReadU16 ();
+
+  NS_ASSERT (GetSerializedSize () == (i.GetDistanceFrom (start)));
+
+  return i.GetDistanceFrom (start);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+TypeId
+Data::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ndn::Data::ndnSIM")
+    .SetGroupName ("Ndn")
+    .SetParent<Header> ()
+    .AddConstructor<Data> ()
+    ;
+  return tid;
+}
+
+TypeId
+Data::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+  
+
+Data::Data ()
+  : m_data (Create<ndn::ContentObject> ())
+{
+}
+
+Data::Data (Ptr<ndn::ContentObject> data)
+  : m_data (data)
+{
+}
+
+Ptr<ndn::ContentObject>
+GetData ()
+{
+  return m_data;
+}
+
+Ptr<Packet>
+Data::ToWire (Ptr<const ndn::ContentObject> data)
+{
+  Ptr<const Packet> p = data->GetWire ();
+  if (!p)
+    {
+      p = Create<Packet> (*data->GetPayload ());
+      Data wireEncoding (data);
+      p->AddHeader (wireEncoding);
+      data->SetWire (p);
+    }
+  
+  return p->Copy ();
+}
+
+Ptr<ndn::ContentObject>
+Data::FromWire (Ptr<Packet> packet)
+{
+  Ptr<ndn::ContentObject> data = Create<ndn::ContentObject> ();
+  // data->SetWire (packet->Copy ()); /* not sure if this is needed */
+
+  Data wireEncoding (data);
+  packet->RemoveHeader (wireEncoding);
+
+  data->SetPayload (packet);
+
+  return data;
+}
+
+uint32_t
+Data::GetSerializedSize () const
+{
+  uint32_t size = 1 + 1 + 2 +
+    ((2 + 2) + (Name (ConstCast<ns3::Name> (m_data->GetNamePtr ())).GetSerializedSize ()) + (2 + 2 + 4 + 2 + 2 + (2 + 0)));
+  if (m_data->GetSignature () != 0)
+    size += 4;
+  
+  NS_LOG_INFO ("Serialize size = " << size);
+  return size;
+}
+
+void
+Data::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (0x80); // version
+  start.WriteU8 (0x01); // packet type
+  start.WriteU16 (GetSerializedSize () - 4); // length
+  
+  if (m_data->GetSignature () != 0)
+    {
+      start.WriteU16 (6); // signature length
+      start.WriteU16 (0xFF00); // "fake" simulator signature
+      start.WriteU32 (m_data->GetSignature ());
+    }
+  else
+    {
+      start.WriteU16 (2); // signature length
+      start.WriteU16 (0); // empty signature
+    }
+
+  // name
+  uint32_t offset = Name (ConstCast<ns3::Name> (m_data->GetNamePtr ())).Serialize (start);
+  start.Next (offset);
+
+  // content
+  // for now assume that contentdata length is zero
+  start.WriteU16 (2 + 4 + 2 + 2 + (2 + 0));
+  start.WriteU16 (4 + 2 + 2 + (2 + 0));
+  start.WriteU32 (static_cast<uint32_t> (m_data->GetTimestamp.ToInteger (Time::S)));
+  start.WriteU16 (static_cast<uint16_t> (m_data->GetFreshness.ToInteger (Time::S)));
+  start.WriteU16 (0); // reserved 
+  start.WriteU16 (0); // Length (ContentInfoOptions)
+
+  // that's it folks
+}
+
+uint32_t
+Data::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  if (i.ReadU8 () != 0x80)
+    throw new ContentObjectException ();
+
+  if (i.ReadU8 () != 0x01)
+    throw new ContentObjectException ();
+
+  i.ReadU16 (); // length
+
+  uint32_t signatureLength = i.ReadU16 ();
+  if (signatureLength == 6)
+    {
+      if (i.ReadU16 () != 0xFF00) // signature type
+        throw new ContentObjectException ();
+      m_data.SetSignature (i.ReadU32 ());
+    }
+  else if (signatureLength == 2)
+    {
+      if (i.ReadU16 () != 0) // signature type
+        throw new ContentObjectException ();
+      m_data.SetSignature (0);
+    }
+  else
+    throw new ContentObjectException ();
+
+  Name name;
+  uint32_t offset = name.Deserialize (i);
+  m_data->SetName (name->GetName ());
+  i.Next (offset);
+
+  if (i.ReadU16 () != (2 + 4 + 2 + 2 + (2 + 0))) // content length
+    throw new ContentObjectException ();
+
+  if (i.ReadU16 () != (4 + 2 + 2 + (2 + 0))) // Length (content Info)
+    throw new ContentObjectException ();
+
+  m_data->SetTimestamp (Seconds (i.ReadU32 ()));
+  m_data->SetFreshness (Seconds (i.ReadU16 ()));
+
+  if (i.ReadU16 () != 0) // Reserved
+    throw new ContentObjectException ();
+  if (i.ReadU16 () != 0) // Length (ContentInfoOptions)
+    throw new ContentObjectException ();
+
+  NS_ASSERT_MSG (i.GetDistanceFrom (start) == GetSerializedSize (),
+                 "Something wrong with ContentObject::Deserialize");
+  
+  return i.GetDistanceFrom (start);
+}
+
+}
+}
+
+NDN_NAMESPACE_END