2874 lines
50 KiB
C++
2874 lines
50 KiB
C++
/* -*- 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::PbbTlvBlock (void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PbbTlvBlock::~PbbTlvBlock (void)
|
|
{
|
|
Clear ();
|
|
}
|
|
|
|
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)
|
|
{
|
|
for (Iterator iter = Begin (); iter != End (); iter++)
|
|
{
|
|
*iter = 0;
|
|
}
|
|
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::PbbAddressTlvBlock (void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PbbAddressTlvBlock::~PbbAddressTlvBlock (void)
|
|
{
|
|
Clear ();
|
|
}
|
|
|
|
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)
|
|
{
|
|
for (Iterator iter = Begin (); iter != End (); iter++)
|
|
{
|
|
*iter = 0;
|
|
}
|
|
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;
|
|
}
|
|
|
|
PbbPacket::~PbbPacket (void)
|
|
{
|
|
MessageClear ();
|
|
}
|
|
|
|
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)
|
|
{
|
|
for (MessageIterator iter = MessageBegin (); iter != MessageEnd (); iter++)
|
|
{
|
|
*iter = 0;
|
|
}
|
|
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 ("ns3::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 ()
|
|
{
|
|
AddressBlockClear ();
|
|
}
|
|
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
for (AddressBlockIterator iter = AddressBlockBegin ();
|
|
iter != AddressBlockEnd ();
|
|
iter++)
|
|
{
|
|
*iter = 0;
|
|
}
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
PbbTlv::~PbbTlv (void)
|
|
{
|
|
m_value.RemoveAtEnd (m_value.GetSize ());
|
|
}
|
|
|
|
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)
|
|
{
|
|
m_hasValue = true;
|
|
m_value.AddAtStart (size);
|
|
m_value.Begin ().Write (buffer, size);
|
|
}
|
|
|
|
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 */
|