/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/* vim: set ts=2 sw=2 sta expandtab ai si cin: */
/*
* Copyright (c) 2009 Drexel University
*
* 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: Tom Wambold <tom5760@gmail.com>
*/
/* These classes implement RFC 5444 - The Generalized Mobile Ad Hoc Network
* (MANET) Packet/PbbMessage Format
* See: http://tools.ietf.org/html/rfc5444 for details */
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
#include "ns3/assert.h"
#include "packetbb.h"
static const uint8_t VERSION = 0;
/* Packet flags */
static const uint8_t PHAS_SEQ_NUM = 0x8;
static const uint8_t PHAS_TLV = 0x4;
/* PbbMessage flags */
static const uint8_t MHAS_ORIG = 0x80;
static const uint8_t MHAS_HOP_LIMIT = 0x40;
static const uint8_t MHAS_HOP_COUNT = 0x20;
static const uint8_t MHAS_SEQ_NUM = 0x10;
/* Address block flags */
static const uint8_t AHAS_HEAD = 0x80;
static const uint8_t AHAS_FULL_TAIL = 0x40;
static const uint8_t AHAS_ZERO_TAIL = 0x20;
static const uint8_t AHAS_SINGLE_PRE_LEN = 0x10;
static const uint8_t AHAS_MULTI_PRE_LEN = 0x08;
/* TLV Flags */
static const uint8_t THAS_TYPE_EXT = 0x80;
static const uint8_t THAS_SINGLE_INDEX = 0x40;
static const uint8_t THAS_MULTI_INDEX = 0x20;
static const uint8_t THAS_VALUE = 0x10;
static const uint8_t THAS_EXT_LEN = 0x08;
static const uint8_t TIS_MULTIVALUE = 0x04;
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (PbbPacket);
PbbTlvBlock::Iterator
PbbTlvBlock::Begin (void)
{
return m_tlvList.begin ();
}
PbbTlvBlock::ConstIterator
PbbTlvBlock::Begin (void) const
{
return m_tlvList.begin ();
}
PbbTlvBlock::Iterator
PbbTlvBlock::End (void)
{
return m_tlvList.end ();
}
PbbTlvBlock::ConstIterator
PbbTlvBlock::End (void) const
{
return m_tlvList.end ();
}
int
PbbTlvBlock::Size (void) const
{
return m_tlvList.size ();
}
bool
PbbTlvBlock::Empty (void) const
{
return m_tlvList.empty ();
}
Ptr<PbbTlv>
PbbTlvBlock::Front (void) const
{
return m_tlvList.front ();
}
Ptr<PbbTlv>
PbbTlvBlock::Back (void) const
{
return m_tlvList.back ();
}
void
PbbTlvBlock::PushFront (Ptr<PbbTlv> tlv)
{
m_tlvList.push_front (tlv);
}
void
PbbTlvBlock::PopFront (void)
{
m_tlvList.pop_front ();
}
void
PbbTlvBlock::PushBack (Ptr<PbbTlv> tlv)
{
m_tlvList.push_back (tlv);
}
void
PbbTlvBlock::PopBack (void)
{
m_tlvList.pop_back ();
}
PbbTlvBlock::Iterator
PbbTlvBlock::Insert (PbbTlvBlock::Iterator position, const Ptr<PbbTlv> tlv)
{
return m_tlvList.insert (position, tlv);
}
PbbTlvBlock::Iterator
PbbTlvBlock::Erase (PbbTlvBlock::Iterator position)
{
return m_tlvList.erase (position);
}
PbbTlvBlock::Iterator
PbbTlvBlock::Erase (PbbTlvBlock::Iterator first, PbbTlvBlock::Iterator last)
{
return m_tlvList.erase (first, last);
}
void
PbbTlvBlock::Clear (void)
{
m_tlvList.clear ();
}
uint32_t
PbbTlvBlock::GetSerializedSize (void) const
{
/* tlv size */
uint32_t size = 2;
for (ConstIterator iter = Begin (); iter != End (); iter++)
{
size += (*iter)->GetSerializedSize ();
}
return size;
}
void
PbbTlvBlock::Serialize (Buffer::Iterator &start) const
{
if (Empty ())
{
start.WriteHtonU16 (0);
return;
}
/* We need to write the size of the TLV block in front, so save its
* position. */
Buffer::Iterator tlvsize = start;
start.Next (2);
for (ConstIterator iter = Begin (); iter != End (); iter++)
{
(*iter)->Serialize (start);
}
/* - 2 to not include the size field */
uint16_t size = start.GetDistanceFrom (tlvsize) - 2;
tlvsize.WriteHtonU16 (size);
}
void
PbbTlvBlock::Deserialize (Buffer::Iterator &start)
{
uint16_t size = start.ReadNtohU16 ();
Buffer::Iterator tlvstart = start;
if (size > 0)
{
while (start.GetDistanceFrom (tlvstart) < size)
{
Ptr<PbbTlv> newtlv = Create<PbbTlv> ();
newtlv->Deserialize (start);
PushBack (newtlv);
}
}
}
void
PbbTlvBlock::Print (std::ostream &os) const
{
Print (os, 0);
}
void
PbbTlvBlock::Print (std::ostream &os, int level) const
{
std::string prefix = "";
for (int i = 0; i < level; i++)
{
prefix.append("\t");
}
os << prefix << "TLV Block {" << std::endl;
os << prefix << "\tsize = " << Size () << std::endl;
os << prefix << "\tmembers [" << std::endl;
for (ConstIterator iter = Begin (); iter != End (); iter++)
{
(*iter)->Print (os, level+2);
}
os << prefix << "\t]" << std::endl;
os << prefix << "}" << std::endl;
}
bool
PbbTlvBlock::operator== (const PbbTlvBlock &other) const
{
if (Size () != other.Size ())
{
return false;
}
ConstIterator ti, oi;
for (ti = Begin (), oi = other.Begin ();
ti != End () && oi != other.End ();
ti++, oi++)
{
if (**ti != **oi)
{
return false;
}
}
return true;
}
bool
PbbTlvBlock::operator!= (const PbbTlvBlock &other) const
{
return !(*this == other);
}
/* End PbbTlvBlock class */
PbbAddressTlvBlock::Iterator
PbbAddressTlvBlock::Begin (void)
{
return m_tlvList.begin ();
}
PbbAddressTlvBlock::ConstIterator
PbbAddressTlvBlock::Begin (void) const
{
return m_tlvList.begin ();
}
PbbAddressTlvBlock::Iterator
PbbAddressTlvBlock::End (void)
{
return m_tlvList.end ();
}
PbbAddressTlvBlock::ConstIterator
PbbAddressTlvBlock::End (void) const
{
return m_tlvList.end ();
}
int
PbbAddressTlvBlock::Size (void) const
{
return m_tlvList.size ();
}
bool
PbbAddressTlvBlock::Empty (void) const
{
return m_tlvList.empty ();
}
Ptr<PbbAddressTlv>
PbbAddressTlvBlock::Front (void) const
{
return m_tlvList.front ();
}
Ptr<PbbAddressTlv>
PbbAddressTlvBlock::Back (void) const
{
return m_tlvList.back ();
}
void
PbbAddressTlvBlock::PushFront (Ptr<PbbAddressTlv> tlv)
{
m_tlvList.push_front (tlv);
}
void
PbbAddressTlvBlock::PopFront (void)
{
m_tlvList.pop_front ();
}
void
PbbAddressTlvBlock::PushBack (Ptr<PbbAddressTlv> tlv)
{
m_tlvList.push_back (tlv);
}
void
PbbAddressTlvBlock::PopBack (void)
{
m_tlvList.pop_back ();
}
PbbAddressTlvBlock::Iterator
PbbAddressTlvBlock::Insert (PbbAddressTlvBlock::Iterator position, const Ptr<PbbAddressTlv> tlv)
{
return m_tlvList.insert (position, tlv);
}
PbbAddressTlvBlock::Iterator
PbbAddressTlvBlock::Erase (PbbAddressTlvBlock::Iterator position)
{
return m_tlvList.erase (position);
}
PbbAddressTlvBlock::Iterator
PbbAddressTlvBlock::Erase (PbbAddressTlvBlock::Iterator first, PbbAddressTlvBlock::Iterator last)
{
return m_tlvList.erase (first, last);
}
void
PbbAddressTlvBlock::Clear (void)
{
m_tlvList.clear ();
}
uint32_t
PbbAddressTlvBlock::GetSerializedSize (void) const
{
/* tlv size */
uint32_t size = 2;
for (ConstIterator iter = Begin (); iter != End (); iter++)
{
size += (*iter)->GetSerializedSize ();
}
return size;
}
void
PbbAddressTlvBlock::Serialize (Buffer::Iterator &start) const
{
if (Empty ())
{
start.WriteHtonU16 (0);
return;
}
/* We need to write the size of the TLV block in front, so save its
* position. */
Buffer::Iterator tlvsize = start;
start.Next (2);
for (ConstIterator iter = Begin (); iter != End (); iter++)
{
(*iter)->Serialize (start);
}
/* - 2 to not include the size field */
uint16_t size = start.GetDistanceFrom (tlvsize) - 2;
tlvsize.WriteHtonU16 (size);
}
void
PbbAddressTlvBlock::Deserialize (Buffer::Iterator &start)
{
uint16_t size = start.ReadNtohU16 ();
Buffer::Iterator tlvstart = start;
if (size > 0)
{
while (start.GetDistanceFrom (tlvstart) < size)
{
Ptr<PbbAddressTlv> newtlv = Create<PbbAddressTlv> ();
newtlv->Deserialize (start);
PushBack (newtlv);
}
}
}
void
PbbAddressTlvBlock::Print (std::ostream &os) const
{
Print (os, 0);
}
void
PbbAddressTlvBlock::Print (std::ostream &os, int level) const
{
std::string prefix = "";
for (int i = 0; i < level; i++)
{
prefix.append("\t");
}
os << prefix << "TLV Block {" << std::endl;
os << prefix << "\tsize = " << Size () << std::endl;
os << prefix << "\tmembers [" << std::endl;
for (ConstIterator iter = Begin (); iter != End (); iter++)
{
(*iter)->Print (os, level+2);
}
os << prefix << "\t]" << std::endl;
os << prefix << "}" << std::endl;
}
bool
PbbAddressTlvBlock::operator== (const PbbAddressTlvBlock &other) const
{
if (Size () != other.Size ())
{
return false;
}
ConstIterator it, ot;
for (it = Begin (), ot = other.Begin ();
it != End () && ot != other.End ();
it++, ot++)
{
if (**it != **ot)
{
return false;
}
}
return true;
}
bool
PbbAddressTlvBlock::operator!= (const PbbAddressTlvBlock &other) const
{
return !(*this == other);
}
/* End PbbAddressTlvBlock Class */
PbbPacket::PbbPacket (void)
{
m_refCount = 1;
m_version = VERSION;
m_hasseqnum = false;
}
uint8_t
PbbPacket::GetVersion (void) const
{
return m_version;
}
void
PbbPacket::SetSequenceNumber (uint16_t number)
{
m_seqnum = number;
m_hasseqnum = true;
}
uint16_t
PbbPacket::GetSequenceNumber (void) const
{
NS_ASSERT (HasSequenceNumber ());
return m_seqnum;
}
bool
PbbPacket::HasSequenceNumber (void) const
{
return m_hasseqnum;
}
/* Manipulating Packet TLVs */
PbbPacket::TlvIterator
PbbPacket::TlvBegin (void)
{
return m_tlvList.Begin ();
}
PbbPacket::ConstTlvIterator
PbbPacket::TlvBegin (void) const
{
return m_tlvList.Begin ();
}
PbbPacket::TlvIterator
PbbPacket::TlvEnd (void)
{
return m_tlvList.End ();
}
PbbPacket::ConstTlvIterator
PbbPacket::TlvEnd (void) const
{
return m_tlvList.End ();
}
int
PbbPacket::TlvSize (void) const
{
return m_tlvList.Size ();
}
bool
PbbPacket::TlvEmpty (void) const
{
return m_tlvList.Empty ();
}
Ptr<PbbTlv>
PbbPacket::TlvFront (void)
{
return m_tlvList.Front ();
}
const Ptr<PbbTlv>
PbbPacket::TlvFront (void) const
{
return m_tlvList.Front ();
}
Ptr<PbbTlv>
PbbPacket::TlvBack (void)
{
return m_tlvList.Back ();
}
const Ptr<PbbTlv>
PbbPacket::TlvBack (void) const
{
return m_tlvList.Back ();
}
void
PbbPacket::TlvPushFront (Ptr<PbbTlv> tlv)
{
m_tlvList.PushFront (tlv);
}
void
PbbPacket::TlvPopFront (void)
{
m_tlvList.PopFront ();
}
void
PbbPacket::TlvPushBack (Ptr<PbbTlv> tlv)
{
m_tlvList.PushBack (tlv);
}
void
PbbPacket::TlvPopBack (void)
{
m_tlvList.PopBack ();
}
PbbPacket::TlvIterator
PbbPacket::Erase (PbbPacket::TlvIterator position)
{
return m_tlvList.Erase (position);
}
PbbPacket::TlvIterator
PbbPacket::Erase (PbbPacket::TlvIterator first, PbbPacket::TlvIterator last)
{
return m_tlvList.Erase (first, last);
}
void
PbbPacket::TlvClear (void)
{
m_tlvList.Clear ();
}
/* Manipulating Packet Messages */
PbbPacket::MessageIterator
PbbPacket::MessageBegin (void)
{
return m_messageList.begin ();
}
PbbPacket::ConstMessageIterator
PbbPacket::MessageBegin (void) const
{
return m_messageList.begin ();
}
PbbPacket::MessageIterator
PbbPacket::MessageEnd (void)
{
return m_messageList.end ();
}
PbbPacket::ConstMessageIterator
PbbPacket::MessageEnd (void) const
{
return m_messageList.end ();
}
int
PbbPacket::MessageSize (void) const
{
return m_messageList.size ();
}
bool
PbbPacket::MessageEmpty (void) const
{
return m_messageList.empty ();
}
Ptr<PbbMessage>
PbbPacket::MessageFront (void)
{
return m_messageList.front ();
}
const Ptr<PbbMessage>
PbbPacket::MessageFront (void) const
{
return m_messageList.front ();
}
Ptr<PbbMessage>
PbbPacket::MessageBack (void)
{
return m_messageList.back ();
}
const Ptr<PbbMessage>
PbbPacket::MessageBack (void) const
{
return m_messageList.back ();
}
void
PbbPacket::MessagePushFront (Ptr<PbbMessage> tlv)
{
m_messageList.push_front (tlv);
}
void
PbbPacket::MessagePopFront (void)
{
m_messageList.pop_front ();
}
void
PbbPacket::MessagePushBack (Ptr<PbbMessage> tlv)
{
m_messageList.push_back (tlv);
}
void
PbbPacket::MessagePopBack (void)
{
m_messageList.pop_back ();
}
PbbPacket::MessageIterator
PbbPacket::Erase (PbbPacket::MessageIterator position)
{
return m_messageList.erase (position);
}
PbbPacket::MessageIterator
PbbPacket::Erase (PbbPacket::MessageIterator first,
PbbPacket::MessageIterator last)
{
return m_messageList.erase (first, last);
}
void
PbbPacket::MessageClear (void)
{
m_messageList.clear ();
}
void
PbbPacket::Ref (void) const
{
m_refCount++;
}
void
PbbPacket::Unref (void) const
{
m_refCount--;
if (m_refCount == 0)
{
delete this;
}
}
TypeId
PbbPacket::GetTypeId (void)
{
static TypeId tid = TypeId ("PbbPacket")
.SetParent<Header> ()
.AddConstructor<PbbPacket> ()
;
return tid;
}
TypeId
PbbPacket::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
uint32_t
PbbPacket::GetSerializedSize (void) const
{
/* Version number + flags */
uint32_t size = 1;
if (HasSequenceNumber())
{
size += 2;
}
if (!TlvEmpty ())
{
size += m_tlvList.GetSerializedSize ();
}
for (ConstMessageIterator iter = MessageBegin ();
iter != MessageEnd ();
iter++)
{
size += (*iter)->GetSerializedSize ();
}
return size;
}
void
PbbPacket::Serialize (Buffer::Iterator start) const
{
/* We remember the start, so we can write the flags after we check for a
* sequence number and TLV. */
Buffer::Iterator bufref = start;
start.Next ();
uint8_t flags = VERSION;
/* Make room for 4 bit flags */
flags <<= 4;
if (HasSequenceNumber ())
{
flags |= PHAS_SEQ_NUM;
start.WriteHtonU16 (GetSequenceNumber ());
}
if (!TlvEmpty ())
{
flags |= PHAS_TLV;
m_tlvList.Serialize (start);
}
bufref.WriteU8(flags);
for (ConstMessageIterator iter = MessageBegin ();
iter != MessageEnd ();
iter++)
{
(*iter)->Serialize (start);
}
}
uint32_t
PbbPacket::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator begin = start;
uint8_t flags = start.ReadU8 ();
if (flags & PHAS_SEQ_NUM)
{
SetSequenceNumber (start.ReadNtohU16 ());
}
if (flags & PHAS_TLV)
{
m_tlvList.Deserialize (start);
}
while (!start.IsEnd())
{
Ptr<PbbMessage> newmsg = PbbMessage::DeserializeMessage (start);
if (newmsg == 0)
{
return start.GetDistanceFrom (begin);
}
MessagePushBack (newmsg);
}
flags >>= 4;
m_version = flags;
return start.GetDistanceFrom (begin);
}
void
PbbPacket::Print (std::ostream &os) const
{
os << "PbbPacket {" << std::endl;
if (HasSequenceNumber ())
{
os << "\tsequence number = " << GetSequenceNumber ();
}
os << std::endl;
m_tlvList.Print (os, 1);
for (ConstMessageIterator iter = MessageBegin ();
iter != MessageEnd ();
iter++)
{
(*iter)->Print (os, 1);
}
os << "}" << std::endl;
}
bool
PbbPacket::operator== (const PbbPacket &other) const
{
if (GetVersion () != other.GetVersion ())
{
return false;
}
if (HasSequenceNumber () != other.HasSequenceNumber ())
{
return false;
}
if (HasSequenceNumber ())
{
if (GetSequenceNumber () != other.GetSequenceNumber ())
return false;
}
if (m_tlvList != other.m_tlvList)
{
return false;
}
if (MessageSize () != other.MessageSize ())
{
return false;
}
ConstMessageIterator tmi, omi;
for (tmi = MessageBegin (), omi = other.MessageBegin ();
tmi != MessageEnd () && omi != other.MessageEnd ();
tmi++, omi++)
{
if (**tmi != **omi)
{
return false;
}
}
return true;
}
bool
PbbPacket::operator!= (const PbbPacket &other) const
{
return !(*this == other);
}
/* End PbbPacket class */
PbbMessage::PbbMessage ()
{
m_refCount = 1;
/* Default to IPv4 */
m_addrSize = IPV4;
m_hasOriginatorAddress = false;
m_hasHopLimit = false;
m_hasHopCount = false;
m_hasSequenceNumber = false;
}
PbbMessage::~PbbMessage ()
{
}
void
PbbMessage::SetType (uint8_t type)
{
m_type = type;
}
uint8_t
PbbMessage::GetType (void) const
{
return m_type;
}
PbbAddressLength
PbbMessage::GetAddressLength (void) const
{
return m_addrSize;
}
void
PbbMessage::SetOriginatorAddress (Address address)
{
m_originatorAddress = address;
m_hasOriginatorAddress = true;
}
Address
PbbMessage::GetOriginatorAddress (void) const
{
NS_ASSERT (HasOriginatorAddress ());
return m_originatorAddress;
}
bool
PbbMessage::HasOriginatorAddress (void) const
{
return m_hasOriginatorAddress;
}
void
PbbMessage::SetHopLimit (uint8_t hopLimit)
{
m_hopLimit = hopLimit;
m_hasHopLimit = true;
}
uint8_t
PbbMessage::GetHopLimit (void) const
{
NS_ASSERT (HasHopLimit ());
return m_hopLimit;
}
bool
PbbMessage::HasHopLimit (void) const
{
return m_hasHopLimit;
}
void
PbbMessage::SetHopCount (uint8_t hopCount)
{
m_hopCount = hopCount;
m_hasHopCount = true;
}
uint8_t
PbbMessage::GetHopCount (void) const
{
NS_ASSERT (HasHopCount ());
return m_hopCount;
}
bool
PbbMessage::HasHopCount (void) const
{
return m_hasHopCount;
}
void
PbbMessage::SetSequenceNumber (uint16_t sequenceNumber)
{
m_sequenceNumber = sequenceNumber;
m_hasSequenceNumber = true;
}
uint16_t
PbbMessage::GetSequenceNumber (void) const
{
NS_ASSERT (HasSequenceNumber ());
return m_sequenceNumber;
}
bool
PbbMessage::HasSequenceNumber (void) const
{
return m_hasSequenceNumber;
}
/* Manipulating PbbMessage TLVs */
PbbMessage::TlvIterator
PbbMessage::TlvBegin (void)
{
return m_tlvList.Begin();
}
PbbMessage::ConstTlvIterator
PbbMessage::TlvBegin (void) const
{
return m_tlvList.Begin();
}
PbbMessage::TlvIterator
PbbMessage::TlvEnd (void)
{
return m_tlvList.End();
}
PbbMessage::ConstTlvIterator
PbbMessage::TlvEnd (void) const
{
return m_tlvList.End();
}
int
PbbMessage::TlvSize (void) const
{
return m_tlvList.Size();
}
bool
PbbMessage::TlvEmpty (void) const
{
return m_tlvList.Empty();
}
Ptr<PbbTlv>
PbbMessage::TlvFront (void)
{
return m_tlvList.Front();
}
const Ptr<PbbTlv>
PbbMessage::TlvFront (void) const
{
return m_tlvList.Front();
}
Ptr<PbbTlv>
PbbMessage::TlvBack (void)
{
return m_tlvList.Back();
}
const Ptr<PbbTlv>
PbbMessage::TlvBack (void) const
{
return m_tlvList.Back();
}
void
PbbMessage::TlvPushFront (Ptr<PbbTlv> tlv)
{
m_tlvList.PushFront(tlv);
}
void
PbbMessage::TlvPopFront (void)
{
m_tlvList.PopFront();
}
void
PbbMessage::TlvPushBack (Ptr<PbbTlv> tlv)
{
m_tlvList.PushBack(tlv);
}
void
PbbMessage::TlvPopBack (void)
{
m_tlvList.PopBack();
}
PbbMessage::TlvIterator
PbbMessage::TlvErase (PbbMessage::TlvIterator position)
{
return m_tlvList.Erase(position);
}
PbbMessage::TlvIterator
PbbMessage::TlvErase (PbbMessage::TlvIterator first, PbbMessage::TlvIterator last)
{
return m_tlvList.Erase(first, last);
}
void
PbbMessage::TlvClear (void)
{
return m_tlvList.Clear();
}
/* Manipulating Address Block and Address TLV pairs */
PbbMessage::AddressBlockIterator
PbbMessage::AddressBlockBegin (void)
{
return m_addressBlockList.begin();
}
PbbMessage::ConstAddressBlockIterator
PbbMessage::AddressBlockBegin (void) const
{
return m_addressBlockList.begin();
}
PbbMessage::AddressBlockIterator
PbbMessage::AddressBlockEnd (void)
{
return m_addressBlockList.end();
}
PbbMessage::ConstAddressBlockIterator
PbbMessage::AddressBlockEnd (void) const
{
return m_addressBlockList.end();
}
int
PbbMessage::AddressBlockSize (void) const
{
return m_addressBlockList.size();
}
bool
PbbMessage::AddressBlockEmpty (void) const
{
return m_addressBlockList.empty();
}
Ptr<PbbAddressBlock>
PbbMessage::AddressBlockFront (void)
{
return m_addressBlockList.front();
}
const Ptr<PbbAddressBlock>
PbbMessage::AddressBlockFront (void) const
{
return m_addressBlockList.front();
}
Ptr<PbbAddressBlock>
PbbMessage::AddressBlockBack (void)
{
return m_addressBlockList.back();
}
const Ptr<PbbAddressBlock>
PbbMessage::AddressBlockBack (void) const
{
return m_addressBlockList.back();
}
void
PbbMessage::AddressBlockPushFront (Ptr<PbbAddressBlock> tlv)
{
m_addressBlockList.push_front(tlv);
}
void
PbbMessage::AddressBlockPopFront (void)
{
m_addressBlockList.pop_front();
}
void
PbbMessage::AddressBlockPushBack (Ptr<PbbAddressBlock> tlv)
{
m_addressBlockList.push_back(tlv);
}
void
PbbMessage::AddressBlockPopBack (void)
{
m_addressBlockList.pop_back();
}
PbbMessage::AddressBlockIterator
PbbMessage::AddressBlockErase (PbbMessage::AddressBlockIterator position)
{
return m_addressBlockList.erase(position);
}
PbbMessage::AddressBlockIterator
PbbMessage::AddressBlockErase (PbbMessage::AddressBlockIterator first,
PbbMessage::AddressBlockIterator last)
{
return m_addressBlockList.erase(first, last);
}
void
PbbMessage::AddressBlockClear (void)
{
return m_addressBlockList.clear();
}
void
PbbMessage::Ref (void) const
{
m_refCount++;
}
void
PbbMessage::Unref (void) const
{
m_refCount--;
if (m_refCount == 0)
{
delete this;
}
}
uint32_t
PbbMessage::GetSerializedSize (void) const
{
/* msg-type + (msg-flags + msg-addr-length) + 2msg-size */
uint32_t size = 4;
if (HasOriginatorAddress())
{
size += GetAddressLength() + 1;
}
if (HasHopLimit())
{
size++;
}
if (HasHopCount())
{
size++;
}
if (HasSequenceNumber())
{
size += 2;
}
size += m_tlvList.GetSerializedSize ();
for (ConstAddressBlockIterator iter = AddressBlockBegin ();
iter != AddressBlockEnd ();
iter++)
{
size += (*iter)->GetSerializedSize ();
}
return size;
}
void
PbbMessage::Serialize (Buffer::Iterator &start) const
{
Buffer::Iterator front = start;
start.WriteU8 (GetType());
/* Save a reference to the spot where we will later write the flags */
Buffer::Iterator bufref = start;
start.Next (1);
uint8_t flags = 0;
flags = GetAddressLength ();
Buffer::Iterator sizeref = start;
start.Next (2);
if (HasOriginatorAddress ())
{
flags |= MHAS_ORIG;
SerializeOriginatorAddress (start);
}
if (HasHopLimit ())
{
flags |= MHAS_HOP_LIMIT;
start.WriteU8 (GetHopLimit ());
}
if (HasHopCount ())
{
flags |= MHAS_HOP_COUNT;
start.WriteU8 (GetHopCount ());
}
if (HasSequenceNumber ())
{
flags |= MHAS_SEQ_NUM;
start.WriteHtonU16 (GetSequenceNumber ());
}
bufref.WriteU8(flags);
m_tlvList.Serialize (start);
for (ConstAddressBlockIterator iter = AddressBlockBegin ();
iter != AddressBlockEnd ();
iter++)
{
(*iter)->Serialize (start);
}
sizeref.WriteHtonU16 (front.GetDistanceFrom (start));
}
Ptr<PbbMessage>
PbbMessage::DeserializeMessage (Buffer::Iterator &start)
{
/* We need to read the msg-addr-len field to determine what kind of object to
* construct. */
start.Next ();
uint8_t addrlen = start.ReadU8 ();
start.Prev (2); /* Go back to the start */
/* The first four bytes of the flag is the address length. Set the last four
* bytes to 0 to read it. */
addrlen = (addrlen & 0xf);
Ptr<PbbMessage> newmsg;
switch (addrlen)
{
case 0:
case IPV4:
newmsg = Create<PbbMessageIpv4> ();
break;
case IPV6:
newmsg = Create<PbbMessageIpv6> ();
break;
default:
return 0;
break;
}
newmsg->Deserialize (start);
return newmsg;
}
void
PbbMessage::Deserialize (Buffer::Iterator &start)
{
Buffer::Iterator front = start;
SetType (start.ReadU8 ());
uint8_t flags = start.ReadU8 ();
uint16_t size = start.ReadNtohU16 ();
if (flags & MHAS_ORIG)
{
SetOriginatorAddress (DeserializeOriginatorAddress (start));
}
if (flags & MHAS_HOP_LIMIT)
{
SetHopLimit (start.ReadU8 ());
}
if (flags & MHAS_HOP_COUNT)
{
SetHopCount (start.ReadU8 ());
}
if (flags & MHAS_SEQ_NUM)
{
SetSequenceNumber (start.ReadNtohU16 ());
}
m_tlvList.Deserialize (start);
if (size > 0)
{
while (start.GetDistanceFrom(front) < size)
{
Ptr<PbbAddressBlock> newab = AddressBlockDeserialize (start);
AddressBlockPushBack (newab);
}
}
}
void
PbbMessage::Print (std::ostream &os) const
{
Print (os, 0);
}
void
PbbMessage::Print (std::ostream &os, int level) const
{
std::string prefix = "";
for (int i = 0; i < level; i++)
{
prefix.append ("\t");
}
os << prefix << "PbbMessage {" << std::endl;
os << prefix << "\tmessage type = " << (int)GetType () << std::endl;
os << prefix << "\taddress size = " << GetAddressLength () << std::endl;
if (HasOriginatorAddress ())
{
os << prefix << "\toriginator address = ";
PrintOriginatorAddress (os);
os << std::endl;
}
if (HasHopLimit ())
{
os << prefix << "\thop limit = " << (int)GetHopLimit () << std::endl;
}
if (HasHopCount ())
{
os << prefix << "\thop count = " << (int)GetHopCount () << std::endl;
}
if (HasSequenceNumber ())
{
os << prefix << "\tseqnum = " << GetSequenceNumber () << std::endl;
}
m_tlvList.Print (os, level+1);
for (ConstAddressBlockIterator iter = AddressBlockBegin ();
iter != AddressBlockEnd ();
iter++)
{
(*iter)->Print (os, level+1);
}
os << prefix << "}" << std::endl;
}
bool
PbbMessage::operator== (const PbbMessage &other) const
{
if (GetAddressLength () != other.GetAddressLength ())
{
return false;
}
if (GetType () != other.GetType ())
{
return false;
}
if (HasOriginatorAddress () != other.HasOriginatorAddress ())
{
return false;
}
if (HasOriginatorAddress ())
{
if (GetOriginatorAddress () != other.GetOriginatorAddress ())
{
return false;
}
}
if (HasHopLimit () != other.HasHopLimit ())
{
return false;
}
if (HasHopLimit ())
{
if (GetHopLimit () != other.GetHopLimit ())
{
return false;
}
}
if (HasHopCount () != other.HasHopCount ())
{
return false;
}
if (HasHopCount ())
{
if (GetHopCount () != other.GetHopCount ())
{
return false;
}
}
if (HasSequenceNumber () != other.HasSequenceNumber ())
{
return false;
}
if (HasSequenceNumber ())
{
if (GetSequenceNumber () != other.GetSequenceNumber ())
{
return false;
}
}
if (m_tlvList != other.m_tlvList)
{
return false;
}
if (AddressBlockSize () != other.AddressBlockSize ())
{
return false;
}
ConstAddressBlockIterator tai, oai;
for (tai = AddressBlockBegin (), oai = other.AddressBlockBegin ();
tai != AddressBlockEnd () && oai != other.AddressBlockEnd ();
tai++, oai++)
{
if (**tai != **oai)
{
return false;
}
}
return true;
}
bool
PbbMessage::operator!= (const PbbMessage &other) const
{
return !(*this == other);
}
/* End PbbMessage Class */
PbbMessageIpv4::PbbMessageIpv4 ()
{
}
PbbMessageIpv4::~PbbMessageIpv4 ()
{
}
PbbAddressLength
PbbMessageIpv4::GetAddressLength (void) const
{
return IPV4;
}
void
PbbMessageIpv4::SerializeOriginatorAddress (Buffer::Iterator &start) const
{
uint8_t buffer[GetAddressLength () + 1];
Ipv4Address::ConvertFrom (GetOriginatorAddress ()).Serialize(buffer);
start.Write (buffer, GetAddressLength () + 1);
}
Address
PbbMessageIpv4::DeserializeOriginatorAddress (Buffer::Iterator &start) const
{
uint8_t buffer[GetAddressLength () + 1];
start.Read(buffer, GetAddressLength () + 1);
return Ipv4Address::Deserialize (buffer);
}
void
PbbMessageIpv4::PrintOriginatorAddress (std::ostream &os) const
{
Ipv4Address::ConvertFrom (GetOriginatorAddress ()).Print (os);
}
Ptr<PbbAddressBlock>
PbbMessageIpv4::AddressBlockDeserialize (Buffer::Iterator &start) const
{
Ptr<PbbAddressBlock> newab = Create<PbbAddressBlockIpv4> ();
newab->Deserialize (start);
return newab;
}
/* End PbbMessageIpv4 Class */
PbbMessageIpv6::PbbMessageIpv6 ()
{
}
PbbMessageIpv6::~PbbMessageIpv6 ()
{
}
PbbAddressLength
PbbMessageIpv6::GetAddressLength (void) const
{
return IPV6;
}
void
PbbMessageIpv6::SerializeOriginatorAddress (Buffer::Iterator &start) const
{
uint8_t buffer[GetAddressLength () + 1];
Ipv6Address::ConvertFrom (GetOriginatorAddress ()).Serialize(buffer);
start.Write (buffer, GetAddressLength () + 1);
}
Address
PbbMessageIpv6::DeserializeOriginatorAddress (Buffer::Iterator &start) const
{
uint8_t buffer[GetAddressLength () + 1];
start.Read(buffer, GetAddressLength () + 1);
return Ipv6Address::Deserialize (buffer);
}
void
PbbMessageIpv6::PrintOriginatorAddress (std::ostream &os) const
{
Ipv6Address::ConvertFrom (GetOriginatorAddress ()).Print (os);
}
Ptr<PbbAddressBlock>
PbbMessageIpv6::AddressBlockDeserialize (Buffer::Iterator &start) const
{
Ptr<PbbAddressBlock> newab = Create<PbbAddressBlockIpv6> ();
newab->Deserialize (start);
return newab;
}
/* End PbbMessageIpv6 Class */
PbbAddressBlock::PbbAddressBlock ()
{
m_refCount = 1;
}
PbbAddressBlock::~PbbAddressBlock ()
{
}
/* Manipulating the address block */
PbbAddressBlock::AddressIterator
PbbAddressBlock::AddressBegin (void)
{
return m_addressList.begin();
}
PbbAddressBlock::ConstAddressIterator
PbbAddressBlock::AddressBegin (void) const
{
return m_addressList.begin();
}
PbbAddressBlock::AddressIterator
PbbAddressBlock::AddressEnd (void)
{
return m_addressList.end();
}
PbbAddressBlock::ConstAddressIterator
PbbAddressBlock::AddressEnd (void) const
{
return m_addressList.end();
}
int
PbbAddressBlock::AddressSize (void) const
{
return m_addressList.size();
}
bool
PbbAddressBlock::AddressEmpty (void) const
{
return m_addressList.empty();
}
Address
PbbAddressBlock::AddressFront (void) const
{
return m_addressList.front();
}
Address
PbbAddressBlock::AddressBack (void) const
{
return m_addressList.back();
}
void
PbbAddressBlock::AddressPushFront (Address tlv)
{
m_addressList.push_front(tlv);
}
void
PbbAddressBlock::AddressPopFront (void)
{
m_addressList.pop_front();
}
void
PbbAddressBlock::AddressPushBack (Address tlv)
{
m_addressList.push_back(tlv);
}
void
PbbAddressBlock::AddressPopBack (void)
{
m_addressList.pop_back();
}
PbbAddressBlock::AddressIterator
PbbAddressBlock::AddressErase (PbbAddressBlock::AddressIterator position)
{
return m_addressList.erase(position);
}
PbbAddressBlock::AddressIterator
PbbAddressBlock::AddressErase (PbbAddressBlock::AddressIterator first,
PbbAddressBlock::AddressIterator last)
{
return m_addressList.erase(first, last);
}
void
PbbAddressBlock::AddressClear (void)
{
return m_addressList.clear();
}
/* Manipulating the prefix list */
PbbAddressBlock::PrefixIterator
PbbAddressBlock::PrefixBegin (void)
{
return m_prefixList.begin ();
}
PbbAddressBlock::ConstPrefixIterator
PbbAddressBlock::PrefixBegin (void) const
{
return m_prefixList.begin ();
}
PbbAddressBlock::PrefixIterator
PbbAddressBlock::PrefixEnd (void)
{
return m_prefixList.end ();
}
PbbAddressBlock::ConstPrefixIterator
PbbAddressBlock::PrefixEnd (void) const
{
return m_prefixList.end ();
}
int
PbbAddressBlock::PrefixSize (void) const
{
return m_prefixList.size ();
}
bool
PbbAddressBlock::PrefixEmpty (void) const
{
return m_prefixList.empty ();
}
uint8_t
PbbAddressBlock::PrefixFront (void) const
{
return m_prefixList.front ();
}
uint8_t
PbbAddressBlock::PrefixBack (void) const
{
return m_prefixList.back ();
}
void
PbbAddressBlock::PrefixPushFront (uint8_t prefix)
{
m_prefixList.push_front (prefix);
}
void
PbbAddressBlock::PrefixPopFront (void)
{
m_prefixList.pop_front ();
}
void
PbbAddressBlock::PrefixPushBack (uint8_t prefix)
{
m_prefixList.push_back (prefix);
}
void
PbbAddressBlock::PrefixPopBack (void)
{
m_prefixList.pop_back ();
}
PbbAddressBlock::PrefixIterator
PbbAddressBlock::PrefixInsert (PbbAddressBlock::PrefixIterator position, const uint8_t value)
{
return m_prefixList.insert (position, value);
}
PbbAddressBlock::PrefixIterator
PbbAddressBlock::PrefixErase (PbbAddressBlock::PrefixIterator position)
{
return m_prefixList.erase (position);
}
PbbAddressBlock::PrefixIterator
PbbAddressBlock::PrefixErase (PbbAddressBlock::PrefixIterator first, PbbAddressBlock::PrefixIterator last)
{
return m_prefixList.erase (first, last);
}
void
PbbAddressBlock::PrefixClear (void)
{
m_prefixList.clear ();
}
/* Manipulating the TLV block */
PbbAddressBlock::TlvIterator
PbbAddressBlock::TlvBegin (void)
{
return m_addressTlvList.Begin();
}
PbbAddressBlock::ConstTlvIterator
PbbAddressBlock::TlvBegin (void) const
{
return m_addressTlvList.Begin();
}
PbbAddressBlock::TlvIterator
PbbAddressBlock::TlvEnd (void)
{
return m_addressTlvList.End();
}
PbbAddressBlock::ConstTlvIterator
PbbAddressBlock::TlvEnd (void) const
{
return m_addressTlvList.End();
}
int
PbbAddressBlock::TlvSize (void) const
{
return m_addressTlvList.Size();
}
bool
PbbAddressBlock::TlvEmpty (void) const
{
return m_addressTlvList.Empty();
}
Ptr<PbbAddressTlv>
PbbAddressBlock::TlvFront (void)
{
return m_addressTlvList.Front();
}
const Ptr<PbbAddressTlv>
PbbAddressBlock::TlvFront (void) const
{
return m_addressTlvList.Front();
}
Ptr<PbbAddressTlv>
PbbAddressBlock::TlvBack (void)
{
return m_addressTlvList.Back();
}
const Ptr<PbbAddressTlv>
PbbAddressBlock::TlvBack (void) const
{
return m_addressTlvList.Back();
}
void
PbbAddressBlock::TlvPushFront (Ptr<PbbAddressTlv> tlv)
{
m_addressTlvList.PushFront(tlv);
}
void
PbbAddressBlock::TlvPopFront (void)
{
m_addressTlvList.PopFront();
}
void
PbbAddressBlock::TlvPushBack (Ptr<PbbAddressTlv> tlv)
{
m_addressTlvList.PushBack(tlv);
}
void
PbbAddressBlock::TlvPopBack (void)
{
m_addressTlvList.PopBack();
}
PbbAddressBlock::TlvIterator
PbbAddressBlock::TlvErase (PbbAddressBlock::TlvIterator position)
{
return m_addressTlvList.Erase(position);
}
PbbAddressBlock::TlvIterator
PbbAddressBlock::TlvErase (PbbAddressBlock::TlvIterator first,
PbbAddressBlock::TlvIterator last)
{
return m_addressTlvList.Erase(first, last);
}
void
PbbAddressBlock::TlvClear (void)
{
return m_addressTlvList.Clear();
}
void
PbbAddressBlock::Ref (void) const
{
m_refCount++;
}
void
PbbAddressBlock::Unref (void) const
{
m_refCount--;
if (m_refCount == 0)
{
delete this;
}
}
uint32_t
PbbAddressBlock::GetSerializedSize (void) const
{
/* num-addr + flags */
uint32_t size = 2;
if (AddressSize () == 1)
{
size += GetAddressLength () + PrefixSize();
}
else if (AddressSize () > 0)
{
uint8_t head[GetAddressLength ()];
uint8_t headlen = 0;
uint8_t tail[GetAddressLength ()];
uint8_t taillen = 0;
GetHeadTail (head, headlen, tail, taillen);
if (headlen > 0)
{
size += 1 + headlen;
}
if (taillen > 0)
{
size++;
if (!HasZeroTail (tail, taillen))
{
size += taillen;
}
}
/* mid size */
size += (GetAddressLength () - headlen - taillen) * AddressSize ();
size += PrefixSize ();
}
size += m_addressTlvList.GetSerializedSize ();
return size;
}
void
PbbAddressBlock::Serialize (Buffer::Iterator &start) const
{
start.WriteU8 (AddressSize ());
if (AddressSize () == 1)
{
start.WriteU8 (0);
uint8_t buf[GetAddressLength ()];
SerializeAddress (buf, AddressBegin ());
start.Write (buf, GetAddressLength ());
if (PrefixSize () == 1)
{
start.WriteU8 (PrefixFront ());
}
}
else if (AddressSize () > 0)
{
Buffer::Iterator bufref = start;
uint8_t flags = 0;
start.Next ();
uint8_t head[GetAddressLength ()];
uint8_t tail[GetAddressLength ()];
uint8_t headlen = 0;
uint8_t taillen = 0;
GetHeadTail (head, headlen, tail, taillen);
if (headlen > 0)
{
flags |= AHAS_HEAD;
start.WriteU8 (headlen);
start.Write (head, headlen);
}
if (taillen > 0)
{
start.WriteU8 (taillen);
if (HasZeroTail (tail, taillen))
{
flags |= AHAS_ZERO_TAIL;
}
else
{
flags |= AHAS_FULL_TAIL;
start.Write (tail, taillen);
}
}
if (headlen + taillen < GetAddressLength ())
{
uint8_t mid[GetAddressLength ()];
for (PbbAddressBlock::ConstAddressIterator iter = AddressBegin ();
iter != AddressEnd ();
iter++)
{
SerializeAddress (mid, iter);
start.Write (mid + headlen, GetAddressLength () - headlen - taillen);
}
}
flags |= GetPrefixFlags ();
bufref.WriteU8 (flags);
for (ConstPrefixIterator iter = PrefixBegin ();
iter != PrefixEnd ();
iter++)
{
start.WriteU8 (*iter);
}
}
m_addressTlvList.Serialize (start);
}
void
PbbAddressBlock::Deserialize (Buffer::Iterator &start)
{
uint8_t numaddr = start.ReadU8 ();
uint8_t flags = start.ReadU8 ();
if (numaddr > 0)
{
uint8_t headlen = 0;
uint8_t taillen = 0;
uint8_t addrtmp[GetAddressLength ()];
memset(addrtmp, 0, GetAddressLength ());
if (flags & AHAS_HEAD)
{
headlen = start.ReadU8 ();
start.Read (addrtmp, headlen);
}
if ((flags & AHAS_FULL_TAIL) ^ (flags & AHAS_ZERO_TAIL))
{
taillen = start.ReadU8 ();
if (flags & AHAS_FULL_TAIL)
{
start.Read (addrtmp + GetAddressLength () - taillen, taillen);
}
}
for (int i = 0; i < numaddr; i++)
{
start.Read (addrtmp + headlen, GetAddressLength () - headlen - taillen);
AddressPushBack (DeserializeAddress (addrtmp));
}
if (flags & AHAS_SINGLE_PRE_LEN)
{
PrefixPushBack (start.ReadU8 ());
}
else if (flags & AHAS_MULTI_PRE_LEN)
{
for (int i = 0; i < numaddr; i++)
{
PrefixPushBack (start.ReadU8 ());
}
}
}
m_addressTlvList.Deserialize (start);
}
void
PbbAddressBlock::Print (std::ostream &os) const
{
Print (os, 0);
}
void
PbbAddressBlock::Print (std::ostream &os, int level) const
{
std::string prefix = "";
for (int i = 0; i < level; i++)
{
prefix.append ("\t");
}
os << prefix << "PbbAddressBlock {" << std::endl;
os << prefix << "\taddresses = " << std::endl;
for (ConstAddressIterator iter = AddressBegin ();
iter != AddressEnd ();
iter++)
{
os << prefix << "\t\t";
PrintAddress(os, iter);
os << std::endl;
}
os << prefix << "\tprefixes = " << std::endl;
for (ConstPrefixIterator iter = PrefixBegin ();
iter != PrefixEnd ();
iter++)
{
os << prefix << "\t\t" << (int)(*iter) << std::endl;
}
m_addressTlvList.Print (os, level+1);
}
bool
PbbAddressBlock::operator== (const PbbAddressBlock &other) const
{
if (AddressSize () != other.AddressSize ())
{
return false;
}
ConstAddressIterator tai, oai;
for (tai = AddressBegin (), oai = other.AddressBegin ();
tai != AddressEnd () && oai != other.AddressEnd ();
tai++, oai++)
{
if (*tai != *oai)
{
return false;
}
}
if (PrefixSize () != other.PrefixSize ())
{
return false;
}
ConstPrefixIterator tpi, opi;
for (tpi = PrefixBegin (), opi = other.PrefixBegin ();
tpi != PrefixEnd () && opi != other.PrefixEnd ();
tpi++, opi++)
{
if (*tpi != *opi)
{
return false;
}
}
if (m_addressTlvList != other.m_addressTlvList)
{
return false;
}
return true;
}
bool
PbbAddressBlock::operator!= (const PbbAddressBlock &other) const
{
return !(*this == other);
}
uint8_t
PbbAddressBlock::GetPrefixFlags (void) const
{
switch (PrefixSize ())
{
case 0:
return 0;
break;
case 1:
return AHAS_SINGLE_PRE_LEN;
break;
default:
return AHAS_MULTI_PRE_LEN;
break;
}
/* Quiet compiler */
return 0;
}
void
PbbAddressBlock::GetHeadTail (uint8_t *head, uint8_t &headlen,
uint8_t *tail, uint8_t &taillen) const
{
headlen = GetAddressLength ();
taillen = headlen;
/* Temporary automatic buffers to store serialized addresses */
uint8_t * buflast = new uint8_t[GetAddressLength ()];
uint8_t * bufcur = new uint8_t[GetAddressLength ()];
uint8_t * tmp;
SerializeAddress (buflast, AddressBegin ());
/* Skip the first item */
for (PbbAddressBlock::ConstAddressIterator iter = AddressBegin ()++;
iter != AddressEnd ();
iter++)
{
SerializeAddress (bufcur, iter);
int i;
for (i = 0; i < headlen; i++)
{
if (buflast[i] != bufcur[i])
{
headlen = i;
break;
}
}
/* If headlen == fulllen - 1, then tail is 0 */
if (headlen <= GetAddressLength () - 1)
{
for (i = GetAddressLength () - 1;
GetAddressLength () - 1 - i <= taillen && i > headlen;
i--)
{
if (buflast[i] != bufcur[i])
{
break;
}
}
taillen = GetAddressLength () - 1 - i;
}
else if (headlen == 0)
{
taillen = 0;
break;
}
tmp = buflast;
buflast = bufcur;
bufcur = tmp;
}
memcpy(head, bufcur, headlen);
memcpy(tail, bufcur + (GetAddressLength () - taillen), taillen);
delete[] buflast;
delete[] bufcur;
}
bool
PbbAddressBlock::HasZeroTail (const uint8_t *tail, uint8_t taillen) const
{
int i;
for (i = 0; i < taillen; i++)
{
if (tail[i] != 0)
{
break;
}
}
return i == taillen;
}
/* End PbbAddressBlock Class */
PbbAddressBlockIpv4::PbbAddressBlockIpv4 ()
{
}
PbbAddressBlockIpv4::~PbbAddressBlockIpv4 ()
{
}
uint8_t
PbbAddressBlockIpv4::GetAddressLength (void) const
{
return 4;
}
void
PbbAddressBlockIpv4::SerializeAddress (uint8_t *buffer, ConstAddressIterator iter) const
{
Ipv4Address::ConvertFrom (*iter).Serialize (buffer);
}
Address
PbbAddressBlockIpv4::DeserializeAddress (uint8_t *buffer) const
{
return Ipv4Address::Deserialize (buffer);
}
void
PbbAddressBlockIpv4::PrintAddress (std::ostream &os, ConstAddressIterator iter) const
{
Ipv4Address::ConvertFrom (*iter).Print (os);
}
/* End PbbAddressBlockIpv4 Class */
PbbAddressBlockIpv6::PbbAddressBlockIpv6 ()
{
}
PbbAddressBlockIpv6::~PbbAddressBlockIpv6 ()
{
}
uint8_t
PbbAddressBlockIpv6::GetAddressLength (void) const
{
return 16;
}
void
PbbAddressBlockIpv6::SerializeAddress (uint8_t *buffer, ConstAddressIterator iter) const
{
Ipv6Address::ConvertFrom (*iter).Serialize (buffer);
}
Address
PbbAddressBlockIpv6::DeserializeAddress (uint8_t *buffer) const
{
return Ipv6Address::Deserialize (buffer);
}
void
PbbAddressBlockIpv6::PrintAddress (std::ostream &os, ConstAddressIterator iter) const
{
Ipv6Address::ConvertFrom (*iter).Print (os);
}
/* End PbbAddressBlockIpv6 Class */
PbbTlv::PbbTlv (void)
{
m_refCount = 1;
m_hasTypeExt = false;
m_hasIndexStart = false;
m_hasIndexStop = false;
m_isMultivalue = false;
m_hasValue = false;
}
void
PbbTlv::SetType (uint8_t type)
{
m_type = type;
}
uint8_t
PbbTlv::GetType (void) const
{
return m_type;
}
void
PbbTlv::SetTypeExt (uint8_t typeExt)
{
m_typeExt = typeExt;
m_hasTypeExt = true;
}
uint8_t
PbbTlv::GetTypeExt (void) const
{
NS_ASSERT (HasTypeExt ());
return m_typeExt;
}
bool
PbbTlv::HasTypeExt (void) const
{
return m_hasTypeExt;
}
void
PbbTlv::SetIndexStart (uint8_t index)
{
m_indexStart = index;
m_hasIndexStart = true;
}
uint8_t
PbbTlv::GetIndexStart (void) const
{
NS_ASSERT (HasIndexStart ());
return m_indexStart;
}
bool
PbbTlv::HasIndexStart (void) const
{
return m_hasIndexStart;
}
void
PbbTlv::SetIndexStop (uint8_t index)
{
m_indexStop = index;
m_hasIndexStop = true;
}
uint8_t
PbbTlv::GetIndexStop (void) const
{
NS_ASSERT (HasIndexStop ());
return m_indexStop;
}
bool
PbbTlv::HasIndexStop (void) const
{
return m_hasIndexStop;
}
void
PbbTlv::SetMultivalue (bool isMultivalue)
{
m_isMultivalue = isMultivalue;
}
bool
PbbTlv::IsMultivalue (void) const
{
return m_isMultivalue;
}
void
PbbTlv::SetValue (Buffer start)
{
m_hasValue = true;
m_value = start;
}
void
PbbTlv::SetValue (const uint8_t * buffer, uint32_t size)
{
Buffer value;
value.AddAtStart (size);
value.Begin ().Write (buffer, size);
SetValue (value);
}
Buffer
PbbTlv::GetValue (void) const
{
NS_ASSERT (HasValue ());
return m_value;
}
bool
PbbTlv::HasValue (void) const
{
return m_hasValue;
}
void
PbbTlv::Ref (void) const
{
m_refCount++;
}
void
PbbTlv::Unref (void) const
{
m_refCount--;
if (m_refCount == 0)
{
delete this;
}
}
uint32_t
PbbTlv::GetSerializedSize (void) const
{
/* type + flags */
uint32_t size = 2;
if (HasTypeExt ())
{
size++;
}
if (HasIndexStart ())
{
size++;
}
if (HasIndexStop ())
{
size++;
}
if (HasValue ())
{
if (GetValue ().GetSize () > 255)
{
size += 2;
}
else
{
size++;
}
size += GetValue ().GetSize ();
}
return size;
}
void
PbbTlv::Serialize (Buffer::Iterator &start) const
{
start.WriteU8 (GetType ());
Buffer::Iterator bufref = start;
uint8_t flags = 0;
start.Next();
if (HasTypeExt())
{
flags |= THAS_TYPE_EXT;
start.WriteU8 (GetTypeExt ());
}
if (HasIndexStart ())
{
start.WriteU8 (GetIndexStart ());
if (HasIndexStop ())
{
flags |= THAS_MULTI_INDEX;
start.WriteU8 (GetIndexStop ());
}
else
{
flags |= THAS_SINGLE_INDEX;
}
}
if (HasValue ())
{
flags |= THAS_VALUE;
uint32_t size = GetValue ().GetSize ();
if (size > 255)
{
flags |= THAS_EXT_LEN;
start.WriteHtonU16 (size);
}
else
{
start.WriteU8 (size);
}
if (IsMultivalue ())
{
flags |= TIS_MULTIVALUE;
}
start.Write(GetValue ().Begin (), GetValue ().End ());
}
bufref.WriteU8 (flags);
}
void
PbbTlv::Deserialize (Buffer::Iterator &start)
{
SetType (start.ReadU8 ());
uint8_t flags = start.ReadU8 ();
if (flags & THAS_TYPE_EXT)
{
SetTypeExt (start.ReadU8 ());
}
if (flags & THAS_MULTI_INDEX)
{
SetIndexStart (start.ReadU8 ());
SetIndexStop (start.ReadU8 ());
}
else if (flags & THAS_SINGLE_INDEX)
{
SetIndexStart (start.ReadU8 ());
}
if (flags & THAS_VALUE)
{
uint16_t len = 0;
if (flags & THAS_EXT_LEN)
{
len = start.ReadNtohU16 ();
}
else
{
len = start.ReadU8 ();
}
m_value.AddAtStart (len);
Buffer::Iterator valueStart = start;
start.Next (len);
m_value.Begin ().Write (valueStart, start);
m_hasValue = true;
}
}
void
PbbTlv::Print (std::ostream &os) const
{
Print (os, 0);
}
void
PbbTlv::Print (std::ostream &os, int level) const
{
std::string prefix = "";
for (int i = 0; i < level; i++)
{
prefix.append ("\t");
}
os << prefix << "PbbTlv {" << std::endl;
os << prefix << "\ttype = " << (int)GetType () << std::endl;
if (HasTypeExt ())
{
os << prefix << "\ttypeext = " << (int)GetTypeExt () << std::endl;
}
if (HasIndexStart ())
{
os << prefix << "\tindexStart = " << (int)GetIndexStart () << std::endl;
}
if (HasIndexStop ())
{
os << prefix << "\tindexStop = " << (int)GetIndexStop () << std::endl;
}
os << prefix << "\tisMultivalue = " << IsMultivalue () << std::endl;
if (HasValue ())
{
os << prefix << "\thas value; size = " << GetValue (). GetSize () << std::endl;
}
os << prefix << "}" << std::endl;
}
bool
PbbTlv::operator== (const PbbTlv &other) const
{
if (GetType () != other.GetType ())
{
return false;
}
if (HasTypeExt () != other.HasTypeExt ())
{
return false;
}
if (HasTypeExt ())
{
if (GetTypeExt () != other.GetTypeExt ())
{
return false;
}
}
if (HasValue () != other.HasValue ())
{
return false;
}
if (HasValue ())
{
Buffer tv = GetValue ();
Buffer ov = other.GetValue ();
if (tv.GetSize () != ov.GetSize ())
{
return false;
}
/* The docs say I probably shouldn't use Buffer::PeekData, but I think it
* is justified in this case. */
if (memcmp (tv.PeekData (), ov.PeekData (), tv.GetSize ()) != 0)
{
return false;
}
}
return true;
}
bool
PbbTlv::operator!= (const PbbTlv &other) const
{
return !(*this == other);
}
/* End PbbTlv Class */
void
PbbAddressTlv::SetIndexStart (uint8_t index)
{
PbbTlv::SetIndexStart (index);
}
uint8_t
PbbAddressTlv::GetIndexStart (void) const
{
return PbbTlv::GetIndexStart ();
}
bool
PbbAddressTlv::HasIndexStart (void) const
{
return PbbTlv::HasIndexStart ();
}
void
PbbAddressTlv::SetIndexStop (uint8_t index)
{
PbbTlv::SetIndexStop (index);
}
uint8_t
PbbAddressTlv::GetIndexStop (void) const
{
return PbbTlv::GetIndexStop ();
}
bool
PbbAddressTlv::HasIndexStop (void) const
{
return PbbTlv::HasIndexStop ();
}
void
PbbAddressTlv::SetMultivalue (bool isMultivalue)
{
PbbTlv::SetMultivalue (isMultivalue);
}
bool
PbbAddressTlv::IsMultivalue (void) const
{
return PbbTlv::IsMultivalue ();
}
} /* namespace ns3 */