| /** -*- 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" |
| |
| using namespace std; |
| |
| #include <ns3/header.h> |
| #include <ns3/packet.h> |
| #include <ns3/log.h> |
| |
| NS_LOG_COMPONENT_DEFINE ("ndn.wire.ndnSIM"); |
| |
| NDN_NAMESPACE_BEGIN |
| |
| namespace wire { |
| namespace ndnSIM { |
| |
| NS_OBJECT_ENSURE_REGISTERED (Interest); |
| NS_OBJECT_ENSURE_REGISTERED (Data); |
| |
| |
| class Name |
| { |
| public: |
| Name () |
| : m_name (Create<ndn::Name> ()) |
| { |
| } |
| |
| Name (Ptr<ndn::Name> name) |
| : m_name (name) |
| { |
| } |
| |
| Ptr<ndn::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> (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") |
| .SetParent<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) |
| { |
| Ptr<Packet> packet = Create<Packet> (*interest->GetPayload ()); |
| Interest wireEncoding (ConstCast<ndn::Interest> (interest)); |
| packet->AddHeader (wireEncoding); |
| interest->SetWire (packet); |
| |
| p = packet; |
| } |
| |
| return p->Copy (); |
| } |
| |
| Ptr<ndn::Interest> |
| Interest::FromWire (Ptr<Packet> packet) |
| { |
| Ptr<ndn::Interest> interest = Create<ndn::Interest> (); |
| interest->SetWire (packet->Copy ()); |
| |
| 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<ndn::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_interest->GetNonce ()); |
| start.WriteU8 (m_interest->GetScope ()); |
| start.WriteU8 (m_interest->GetNack ()); |
| |
| 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<ndn::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->SetNack (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); |
| } |
| |
| void |
| Interest::Print (std::ostream &os) const |
| { |
| m_interest->Print (os); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| |
| 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> |
| Data::GetData () |
| { |
| return m_data; |
| } |
| |
| Ptr<Packet> |
| Data::ToWire (Ptr<const ndn::ContentObject> data) |
| { |
| Ptr<const Packet> p = data->GetWire (); |
| if (!p) |
| { |
| Ptr<Packet> packet = Create<Packet> (*data->GetPayload ()); |
| Data wireEncoding (ConstCast<ndn::ContentObject> (data)); |
| packet->AddHeader (wireEncoding); |
| data->SetWire (packet); |
| |
| p = packet; |
| } |
| |
| return p->Copy (); |
| } |
| |
| Ptr<ndn::ContentObject> |
| Data::FromWire (Ptr<Packet> packet) |
| { |
| Ptr<ndn::ContentObject> data = Create<ndn::ContentObject> (); |
| data->SetWire (packet->Copy ()); |
| |
| 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<ndn::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<ndn::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); |
| } |
| |
| void |
| Data::Print (std::ostream &os) const |
| { |
| m_data->Print (os); |
| } |
| |
| } // ndnSIM |
| } // wire |
| |
| NDN_NAMESPACE_END |