src/common/packet.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu Nov 12 13:01:01 2009 +0100 (2009-11-12)
changeset 5505 c0ac392289c3
parent 5334 92aafeab5e4f
child 5938 69bcae35bc81
permissions -rw-r--r--
replace RefCountBase with SimpleRefCount<> to avoid duplicate refcounting implementations.
mathieu@150
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@9
     2
/*
mathieu@9
     3
 * Copyright (c) 2005,2006 INRIA
mathieu@9
     4
 *
mathieu@9
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@9
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@9
     7
 * published by the Free Software Foundation;
mathieu@9
     8
 *
mathieu@9
     9
 * This program is distributed in the hope that it will be useful,
mathieu@9
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@9
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@9
    12
 * GNU General Public License for more details.
mathieu@9
    13
 *
mathieu@9
    14
 * You should have received a copy of the GNU General Public License
mathieu@9
    15
 * along with this program; if not, write to the Free Software
mathieu@9
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@9
    17
 *
mathieu@9
    18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@9
    19
 */
mathieu@9
    20
#include "packet.h"
mathieu@286
    21
#include "ns3/assert.h"
mathieu@3158
    22
#include "ns3/log.h"
boyko@5334
    23
#include "ns3/test.h"
boyko@5334
    24
#include <string>
boyko@5334
    25
#include <stdarg.h>
mathieu@3158
    26
mathieu@3158
    27
NS_LOG_COMPONENT_DEFINE ("Packet");
mathieu@9
    28
mathieu@16
    29
namespace ns3 {
mathieu@9
    30
mathieu@463
    31
uint32_t Packet::m_globalUid = 0;
mathieu@91
    32
mathieu@3035
    33
TypeId 
mathieu@4502
    34
ByteTagIterator::Item::GetTypeId (void) const
mathieu@3035
    35
{
mathieu@3035
    36
  return m_tid;
mathieu@3035
    37
}
mathieu@3035
    38
uint32_t 
mathieu@4502
    39
ByteTagIterator::Item::GetStart (void) const
mathieu@3035
    40
{
mathieu@3035
    41
  return m_start;
mathieu@3035
    42
}
mathieu@3035
    43
uint32_t 
mathieu@4502
    44
ByteTagIterator::Item::GetEnd (void) const
mathieu@3035
    45
{
mathieu@3035
    46
  return m_end;
mathieu@3035
    47
}
mathieu@3035
    48
void 
mathieu@4502
    49
ByteTagIterator::Item::GetTag (Tag &tag) const
mathieu@3035
    50
{
mathieu@3035
    51
  if (tag.GetInstanceTypeId () != GetTypeId ())
mathieu@3035
    52
    {
mathieu@3035
    53
      NS_FATAL_ERROR ("The tag you provided is not of the right type.");
mathieu@3035
    54
    }
mathieu@3035
    55
  tag.Deserialize (m_buffer);
mathieu@3035
    56
}
mathieu@4502
    57
ByteTagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
mathieu@3035
    58
  : m_tid (tid),
mathieu@3035
    59
    m_start (start),
mathieu@3035
    60
    m_end (end),
mathieu@3035
    61
    m_buffer (buffer)
mathieu@3035
    62
{}
mathieu@3035
    63
bool 
mathieu@4502
    64
ByteTagIterator::HasNext (void) const
mathieu@3035
    65
{
mathieu@3035
    66
  return m_current.HasNext ();
mathieu@3035
    67
}
mathieu@4502
    68
ByteTagIterator::Item 
mathieu@4502
    69
ByteTagIterator::Next (void)
mathieu@3035
    70
{
mathieu@4502
    71
  ByteTagList::Iterator::Item i = m_current.Next ();
mathieu@4502
    72
  return ByteTagIterator::Item (i.tid, 
mathieu@4502
    73
                                i.start-m_current.GetOffsetStart (), 
mathieu@4502
    74
                                i.end-m_current.GetOffsetStart (), 
mathieu@4502
    75
                                i.buf);
mathieu@3035
    76
}
mathieu@4502
    77
ByteTagIterator::ByteTagIterator (ByteTagList::Iterator i)
mathieu@3035
    78
  : m_current (i)
mathieu@3035
    79
{}
mathieu@3035
    80
mathieu@3035
    81
mathieu@4502
    82
PacketTagIterator::PacketTagIterator (const struct PacketTagList::TagData *head)
mathieu@4502
    83
  : m_current (head)
mathieu@4502
    84
{}
mathieu@4502
    85
bool 
mathieu@4502
    86
PacketTagIterator::HasNext (void) const
mathieu@4502
    87
{
mathieu@4502
    88
  return m_current != 0;
mathieu@4502
    89
}
mathieu@4502
    90
PacketTagIterator::Item 
mathieu@4502
    91
PacketTagIterator::Next (void)
mathieu@4502
    92
{
mathieu@4502
    93
  NS_ASSERT (HasNext ());
mathieu@4502
    94
  const struct PacketTagList::TagData *prev = m_current;
mathieu@4502
    95
  m_current = m_current->next;
mathieu@4502
    96
  return PacketTagIterator::Item (prev);
mathieu@4502
    97
}
mathieu@4502
    98
mathieu@4502
    99
PacketTagIterator::Item::Item (const struct PacketTagList::TagData *data)
mathieu@4502
   100
  : m_data (data)
mathieu@4502
   101
{}
mathieu@4502
   102
TypeId 
mathieu@4502
   103
PacketTagIterator::Item::GetTypeId (void) const
mathieu@4502
   104
{
mathieu@4502
   105
  return m_data->tid;
mathieu@4502
   106
}
mathieu@4502
   107
void 
mathieu@4502
   108
PacketTagIterator::Item::GetTag (Tag &tag) const
mathieu@4502
   109
{
mathieu@4502
   110
  NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
mathieu@4502
   111
  tag.Deserialize (TagBuffer ((uint8_t*)m_data->data, (uint8_t*)m_data->data+PACKET_TAG_MAX_SIZE));
mathieu@4502
   112
}
mathieu@4502
   113
mathieu@4502
   114
mathieu@1865
   115
Ptr<Packet> 
mathieu@1865
   116
Packet::Copy (void) const
mathieu@1865
   117
{
mathieu@1865
   118
  // we need to invoke the copy constructor directly
mathieu@1865
   119
  // rather than calling Create because the copy constructor
mathieu@1865
   120
  // is private.
mathieu@1865
   121
  return Ptr<Packet> (new Packet (*this), false);
mathieu@1865
   122
}
mathieu@1865
   123
mathieu@9
   124
Packet::Packet ()
mathieu@150
   125
  : m_buffer (),
mathieu@4502
   126
    m_byteTagList (),
mathieu@4502
   127
    m_packetTagList (),
mathieu@1865
   128
    m_metadata (m_globalUid, 0),
mathieu@5505
   129
    m_nixVector (0)
mathieu@91
   130
{
mathieu@463
   131
  m_globalUid++;
mathieu@91
   132
}
mathieu@9
   133
mathieu@1865
   134
Packet::Packet (const Packet &o)
mathieu@1865
   135
  : m_buffer (o.m_buffer),
mathieu@4502
   136
    m_byteTagList (o.m_byteTagList),
mathieu@4502
   137
    m_packetTagList (o.m_packetTagList),
mathieu@5505
   138
    m_metadata (o.m_metadata)
jpelkey@5224
   139
{
jpelkey@5224
   140
  o.m_nixVector ? m_nixVector = o.m_nixVector->Copy () 
jpelkey@5224
   141
                : m_nixVector = 0;
jpelkey@5224
   142
}
mathieu@1865
   143
mathieu@1865
   144
Packet &
mathieu@1865
   145
Packet::operator = (const Packet &o)
mathieu@1865
   146
{
mathieu@1865
   147
  if (this == &o)
mathieu@1865
   148
    {
mathieu@1865
   149
      return *this;
mathieu@1865
   150
    }
mathieu@1865
   151
  m_buffer = o.m_buffer;
mathieu@4502
   152
  m_byteTagList = o.m_byteTagList;
mathieu@4502
   153
  m_packetTagList = o.m_packetTagList;
mathieu@1865
   154
  m_metadata = o.m_metadata;
jpelkey@5224
   155
  o.m_nixVector ? m_nixVector = o.m_nixVector->Copy () 
jpelkey@5224
   156
                : m_nixVector = 0;
mathieu@1865
   157
  return *this;
mathieu@1865
   158
}
mathieu@1865
   159
mathieu@9
   160
Packet::Packet (uint32_t size)
mathieu@150
   161
  : m_buffer (size),
mathieu@4502
   162
    m_byteTagList (),
mathieu@4502
   163
    m_packetTagList (),
mathieu@1865
   164
    m_metadata (m_globalUid, size),
mathieu@5505
   165
    m_nixVector (0)
mathieu@91
   166
{
mathieu@463
   167
  m_globalUid++;
mathieu@91
   168
}
mathieu@239
   169
Packet::Packet (uint8_t const*buffer, uint32_t size)
mathieu@239
   170
  : m_buffer (),
mathieu@4502
   171
    m_byteTagList (),
mathieu@4502
   172
    m_packetTagList (),
mathieu@1865
   173
    m_metadata (m_globalUid, size),
mathieu@5505
   174
    m_nixVector (0)
mathieu@239
   175
{
mathieu@463
   176
  m_globalUid++;
mathieu@239
   177
  m_buffer.AddAtStart (size);
mathieu@239
   178
  Buffer::Iterator i = m_buffer.Begin ();
mathieu@239
   179
  i.Write (buffer, size);
mathieu@239
   180
}
mathieu@239
   181
mathieu@4502
   182
Packet::Packet (const Buffer &buffer,  const ByteTagList &byteTagList, 
mathieu@4502
   183
                const PacketTagList &packetTagList, const PacketMetadata &metadata)
mathieu@150
   184
  : m_buffer (buffer),
mathieu@4502
   185
    m_byteTagList (byteTagList),
mathieu@4502
   186
    m_packetTagList (packetTagList),
mathieu@1865
   187
    m_metadata (metadata),
mathieu@5505
   188
    m_nixVector (0)
mathieu@9
   189
{}
mathieu@9
   190
mathieu@1865
   191
Ptr<Packet>
mathieu@122
   192
Packet::CreateFragment (uint32_t start, uint32_t length) const
mathieu@9
   193
{
mathieu@3158
   194
  NS_LOG_FUNCTION (this << start << length);
mathieu@463
   195
  Buffer buffer = m_buffer.CreateFragment (start, length);
mathieu@819
   196
  NS_ASSERT (m_buffer.GetSize () >= start + length);
mathieu@819
   197
  uint32_t end = m_buffer.GetSize () - (start + length);
mathieu@888
   198
  PacketMetadata metadata = m_metadata.CreateFragment (start, end);
mathieu@1865
   199
  // again, call the constructor directly rather than
mathieu@1865
   200
  // through Create because it is private.
mathieu@4502
   201
  return Ptr<Packet> (new Packet (buffer, m_byteTagList, m_packetTagList, metadata), false);
mathieu@9
   202
}
mathieu@9
   203
jpelkey@5224
   204
void
jpelkey@5224
   205
Packet::SetNixVector (Ptr<NixVector> nixVector)
jpelkey@5224
   206
{
jpelkey@5224
   207
  m_nixVector = nixVector;
jpelkey@5224
   208
}
jpelkey@5224
   209
jpelkey@5224
   210
Ptr<NixVector>
jpelkey@5224
   211
Packet::GetNixVector (void) const
jpelkey@5224
   212
{
jpelkey@5224
   213
  return m_nixVector;
jpelkey@5224
   214
} 
jpelkey@5224
   215
mathieu@9
   216
uint32_t 
mathieu@122
   217
Packet::GetSize (void) const
mathieu@9
   218
{
mathieu@150
   219
  return m_buffer.GetSize ();
mathieu@9
   220
}
mathieu@9
   221
mathieu@2663
   222
void
mathieu@2663
   223
Packet::AddHeader (const Header &header)
mathieu@2663
   224
{
mathieu@2663
   225
  uint32_t size = header.GetSerializedSize ();
mathieu@4484
   226
  NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << size);
mathieu@3035
   227
  uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
mathieu@3035
   228
  bool resized = m_buffer.AddAtStart (size);
mathieu@3035
   229
  if (resized)
mathieu@3035
   230
    {
mathieu@4502
   231
      m_byteTagList.AddAtStart (m_buffer.GetCurrentStartOffset () + size - orgStart,
mathieu@4502
   232
                                m_buffer.GetCurrentStartOffset () + size);
mathieu@3035
   233
    }
mathieu@2663
   234
  header.Serialize (m_buffer.Begin ());
mathieu@2663
   235
  m_metadata.AddHeader (header, size);
mathieu@2663
   236
}
mathieu@2663
   237
uint32_t
mathieu@2663
   238
Packet::RemoveHeader (Header &header)
mathieu@2663
   239
{
mathieu@2663
   240
  uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
mathieu@4484
   241
  NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
mathieu@2663
   242
  m_buffer.RemoveAtStart (deserialized);
mathieu@2663
   243
  m_metadata.RemoveHeader (header, deserialized);
mathieu@2663
   244
  return deserialized;
mathieu@2663
   245
}
mathieu@3364
   246
uint32_t
mathieu@3738
   247
Packet::PeekHeader (Header &header) const
mathieu@3364
   248
{
mathieu@3364
   249
  uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
mathieu@4484
   250
  NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
mathieu@3364
   251
  return deserialized;
mathieu@3364
   252
}
mathieu@2663
   253
void
mathieu@2663
   254
Packet::AddTrailer (const Trailer &trailer)
mathieu@2663
   255
{
mathieu@2663
   256
  uint32_t size = trailer.GetSerializedSize ();
mathieu@4484
   257
  NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << size);
mathieu@3237
   258
  uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
mathieu@3035
   259
  bool resized = m_buffer.AddAtEnd (size);
mathieu@3035
   260
  if (resized)
mathieu@3035
   261
    {
mathieu@4502
   262
      m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - orgStart,
mathieu@4502
   263
                              m_buffer.GetCurrentEndOffset () - size);
mathieu@3035
   264
    }
mathieu@2663
   265
  Buffer::Iterator end = m_buffer.End ();
mathieu@2663
   266
  trailer.Serialize (end);
mathieu@2663
   267
  m_metadata.AddTrailer (trailer, size);
mathieu@2663
   268
}
mathieu@2663
   269
uint32_t
mathieu@2663
   270
Packet::RemoveTrailer (Trailer &trailer)
mathieu@2663
   271
{
mathieu@2663
   272
  uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
mathieu@4484
   273
  NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
mathieu@2663
   274
  m_buffer.RemoveAtEnd (deserialized);
mathieu@2663
   275
  m_metadata.RemoveTrailer (trailer, deserialized);
mathieu@2663
   276
  return deserialized;
mathieu@2663
   277
}
mathieu@3364
   278
uint32_t
mathieu@3364
   279
Packet::PeekTrailer (Trailer &trailer)
mathieu@3364
   280
{
mathieu@3364
   281
  uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
mathieu@4484
   282
  NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
mathieu@3364
   283
  return deserialized;
mathieu@3364
   284
}
mathieu@2663
   285
mathieu@9
   286
void 
mathieu@1865
   287
Packet::AddAtEnd (Ptr<const Packet> packet)
mathieu@9
   288
{
mathieu@4484
   289
  NS_LOG_FUNCTION (this << packet << packet->GetSize ());
mathieu@3035
   290
  uint32_t aStart = m_buffer.GetCurrentStartOffset ();
mathieu@3035
   291
  uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
mathieu@2992
   292
  m_buffer.AddAtEnd (packet->m_buffer);
mathieu@3035
   293
  uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
mathieu@4502
   294
  m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart, 
mathieu@4502
   295
                          appendPrependOffset);
mathieu@4502
   296
  ByteTagList copy = packet->m_byteTagList;
mathieu@3035
   297
  copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
mathieu@3035
   298
                   appendPrependOffset);
mathieu@4502
   299
  m_byteTagList.Add (copy);
mathieu@1865
   300
  m_metadata.AddAtEnd (packet->m_metadata);
mathieu@9
   301
}
mathieu@463
   302
void
mathieu@463
   303
Packet::AddPaddingAtEnd (uint32_t size)
mathieu@9
   304
{
mathieu@3158
   305
  NS_LOG_FUNCTION (this << size);
mathieu@3035
   306
  uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
mathieu@3035
   307
  bool resized = m_buffer.AddAtEnd (size);
mathieu@3035
   308
  if (resized)
mathieu@3035
   309
    {
mathieu@4502
   310
      m_byteTagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
mathieu@4502
   311
                              m_buffer.GetCurrentEndOffset () - size);
mathieu@3035
   312
    }
mathieu@888
   313
  m_metadata.AddPaddingAtEnd (size);
mathieu@9
   314
}
mathieu@9
   315
void 
mathieu@122
   316
Packet::RemoveAtEnd (uint32_t size)
mathieu@9
   317
{
mathieu@3158
   318
  NS_LOG_FUNCTION (this << size);
mathieu@150
   319
  m_buffer.RemoveAtEnd (size);
mathieu@888
   320
  m_metadata.RemoveAtEnd (size);
mathieu@9
   321
}
mathieu@9
   322
void 
mathieu@122
   323
Packet::RemoveAtStart (uint32_t size)
mathieu@9
   324
{
mathieu@3158
   325
  NS_LOG_FUNCTION (this << size);
mathieu@150
   326
  m_buffer.RemoveAtStart (size);
mathieu@888
   327
  m_metadata.RemoveAtStart (size);
mathieu@9
   328
}
mathieu@9
   329
mathieu@9
   330
void 
mathieu@4502
   331
Packet::RemoveAllByteTags (void)
mathieu@9
   332
{
mathieu@3158
   333
  NS_LOG_FUNCTION (this);
mathieu@4502
   334
  m_byteTagList.RemoveAll ();
mathieu@9
   335
}
mathieu@9
   336
mathieu@90
   337
uint8_t const *
mathieu@122
   338
Packet::PeekData (void) const
mathieu@90
   339
{
mathieu@4483
   340
  NS_LOG_FUNCTION (this);
boyko@4486
   341
  uint32_t oldStart = m_buffer.GetCurrentStartOffset ();
boyko@4486
   342
  uint8_t const * data = m_buffer.PeekData ();
boyko@4486
   343
  uint32_t newStart = m_buffer.GetCurrentStartOffset ();
mathieu@4502
   344
 
boyko@4486
   345
  // Update tag offsets if buffer offsets were changed
mathieu@4502
   346
  const_cast<ByteTagList &>(m_byteTagList).AddAtStart (newStart - oldStart, newStart);
boyko@4486
   347
  return data;
mathieu@90
   348
}
mathieu@90
   349
mathieu@91
   350
uint32_t 
mathieu@3764
   351
Packet::CopyData (uint8_t *buffer, uint32_t size) const
mathieu@3764
   352
{
mathieu@3764
   353
  Buffer::Iterator i = m_buffer.Begin ();
mathieu@3764
   354
  uint32_t cur = 0;
mathieu@3764
   355
  while (!i.IsEnd () && cur < size)
mathieu@3764
   356
    {
mathieu@3764
   357
      buffer[cur] = i.ReadU8 ();
mathieu@3764
   358
      cur++;
mathieu@3764
   359
    }
mathieu@3764
   360
  return cur;
mathieu@3764
   361
}
mathieu@3764
   362
mathieu@4518
   363
void
mathieu@4518
   364
Packet::CopyData(std::ostream *os, uint32_t size) const
mathieu@4518
   365
{
mathieu@4518
   366
  return m_buffer.CopyData (os, size);
mathieu@4518
   367
}
mathieu@4518
   368
mathieu@3764
   369
uint32_t 
mathieu@122
   370
Packet::GetUid (void) const
mathieu@91
   371
{
mathieu@888
   372
  return m_metadata.GetUid ();
mathieu@91
   373
}
mathieu@91
   374
mathieu@463
   375
void 
mathieu@4502
   376
Packet::PrintByteTags (std::ostream &os) const
mathieu@1241
   377
{
mathieu@4502
   378
  ByteTagIterator i = GetByteTagIterator ();
mathieu@3208
   379
  while (i.HasNext ())
mathieu@3208
   380
    {
mathieu@4502
   381
      ByteTagIterator::Item item = i.Next ();
mathieu@3208
   382
      os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
mathieu@3208
   383
      Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
mathieu@3208
   384
      if (constructor.IsNull ())
mathieu@3208
   385
        {
mathieu@3208
   386
          if (i.HasNext ())
mathieu@3208
   387
            {
mathieu@3208
   388
              os << " ";
mathieu@3208
   389
            }
mathieu@3208
   390
          continue;
mathieu@3208
   391
        }
mathieu@3208
   392
      Tag *tag = dynamic_cast<Tag *> (constructor ());
mathieu@3208
   393
      NS_ASSERT (tag != 0);
mathieu@3208
   394
      os << " ";
mathieu@3230
   395
      item.GetTag (*tag);
mathieu@3208
   396
      tag->Print (os);
mathieu@3208
   397
      if (i.HasNext ())
mathieu@3208
   398
        {
mathieu@3208
   399
          os << " ";
mathieu@3208
   400
        }
mathieu@3208
   401
      delete tag;
mathieu@3208
   402
    }
mathieu@1241
   403
}
mathieu@1241
   404
mathieu@1241
   405
void 
mathieu@463
   406
Packet::Print (std::ostream &os) const
mathieu@789
   407
{
mathieu@2660
   408
  PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
mathieu@2660
   409
  while (i.HasNext ())
mathieu@2660
   410
    {
mathieu@2660
   411
      PacketMetadata::Item item = i.Next ();
mathieu@2660
   412
      if (item.isFragment)
mathieu@2660
   413
        {
mathieu@2660
   414
          switch (item.type) {
mathieu@2660
   415
          case PacketMetadata::Item::PAYLOAD:
mathieu@2660
   416
            os << "Payload";
mathieu@2660
   417
            break;
mathieu@2660
   418
          case PacketMetadata::Item::HEADER:
mathieu@2660
   419
          case PacketMetadata::Item::TRAILER:
mathieu@2660
   420
            os << item.tid.GetName ();
mathieu@2660
   421
            break;
mathieu@2660
   422
          }
mathieu@2660
   423
          os << " Fragment [" << item.currentTrimedFromStart<<":"
mathieu@2660
   424
             << (item.currentTrimedFromStart + item.currentSize) << "]";
mathieu@2660
   425
        }
mathieu@2660
   426
      else
mathieu@2660
   427
        {
mathieu@2660
   428
          switch (item.type) {
mathieu@2660
   429
          case PacketMetadata::Item::PAYLOAD:
mathieu@2660
   430
            os << "Payload (size=" << item.currentSize << ")";
mathieu@2660
   431
            break;
mathieu@2660
   432
          case PacketMetadata::Item::HEADER:
mathieu@2660
   433
          case PacketMetadata::Item::TRAILER:
mathieu@2660
   434
            os << item.tid.GetName () << " (";
mathieu@2660
   435
            {
mathieu@2660
   436
              NS_ASSERT (item.tid.HasConstructor ());
mathieu@2660
   437
              Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
mathieu@2660
   438
              NS_ASSERT (!constructor.IsNull ());
mathieu@2660
   439
              ObjectBase *instance = constructor ();
mathieu@2660
   440
              NS_ASSERT (instance != 0);
mathieu@2660
   441
              Chunk *chunk = dynamic_cast<Chunk *> (instance);
mathieu@2660
   442
              NS_ASSERT (chunk != 0);
mathieu@2660
   443
              chunk->Deserialize (item.current);
mathieu@2660
   444
              chunk->Print (os);
mathieu@2790
   445
              delete chunk;
mathieu@2660
   446
            }
mathieu@2660
   447
            os << ")";
mathieu@2660
   448
            break;
mathieu@2660
   449
          }          
mathieu@2660
   450
        }
mathieu@2660
   451
      if (i.HasNext ())
mathieu@2660
   452
        {
mathieu@2660
   453
          os << " ";
mathieu@2660
   454
        }
mathieu@2660
   455
    }
mathieu@2660
   456
#if 0
mathieu@2660
   457
  // The code below will work only if headers and trailers
mathieu@2660
   458
  // define the right attributes which is not the case for
mathieu@2660
   459
  // now. So, as a temporary measure, we use the 
mathieu@2660
   460
  // headers' and trailers' Print method as shown above.
mathieu@2647
   461
  PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
mathieu@2647
   462
  while (i.HasNext ())
mathieu@2647
   463
    {
mathieu@2647
   464
      PacketMetadata::Item item = i.Next ();
mathieu@2647
   465
      if (item.isFragment)
mathieu@2647
   466
        {
mathieu@2647
   467
          switch (item.type) {
mathieu@2647
   468
          case PacketMetadata::Item::PAYLOAD:
mathieu@2647
   469
            os << "Payload";
mathieu@2647
   470
            break;
mathieu@2647
   471
          case PacketMetadata::Item::HEADER:
mathieu@2647
   472
          case PacketMetadata::Item::TRAILER:
mathieu@2647
   473
            os << item.tid.GetName ();
mathieu@2647
   474
            break;
mathieu@2647
   475
          }
mathieu@2647
   476
          os << " Fragment [" << item.currentTrimedFromStart<<":"
mathieu@2647
   477
             << (item.currentTrimedFromStart + item.currentSize) << "]";
mathieu@2647
   478
        }
mathieu@2647
   479
      else
mathieu@2647
   480
        {
mathieu@2647
   481
          switch (item.type) {
mathieu@2647
   482
          case PacketMetadata::Item::PAYLOAD:
mathieu@2647
   483
            os << "Payload (size=" << item.currentSize << ")";
mathieu@2647
   484
            break;
mathieu@2647
   485
          case PacketMetadata::Item::HEADER:
mathieu@2647
   486
          case PacketMetadata::Item::TRAILER:
mathieu@2647
   487
            os << item.tid.GetName () << "(";
mathieu@2647
   488
            {
mathieu@2647
   489
              NS_ASSERT (item.tid.HasConstructor ());
mathieu@2647
   490
              Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
mathieu@2647
   491
              NS_ASSERT (constructor.IsNull ());
mathieu@2647
   492
              ObjectBase *instance = constructor ();
mathieu@2647
   493
              NS_ASSERT (instance != 0);
mathieu@2647
   494
              Chunk *chunk = dynamic_cast<Chunk *> (instance);
mathieu@2647
   495
              NS_ASSERT (chunk != 0);
mathieu@2647
   496
              chunk->Deserialize (item.current);
mathieu@2693
   497
              for (uint32_t j = 0; j < item.tid.GetAttributeN (); j++)
mathieu@2647
   498
                {
mathieu@2647
   499
                  std::string attrName = item.tid.GetAttributeName (j);
mathieu@2647
   500
                  std::string value;
mathieu@2647
   501
                  bool ok = chunk->GetAttribute (attrName, value);
mathieu@2647
   502
                  NS_ASSERT (ok);
mathieu@2647
   503
                  os << attrName << "=" << value;
mathieu@2693
   504
                  if ((j + 1) < item.tid.GetAttributeN ())
mathieu@2647
   505
                    {
mathieu@2647
   506
                      os << ",";
mathieu@2647
   507
                    }
mathieu@2647
   508
                }
mathieu@2647
   509
            }
mathieu@2647
   510
            os << ")";
mathieu@2647
   511
            break;
mathieu@2647
   512
          }          
mathieu@2647
   513
        }
mathieu@2647
   514
      if (i.HasNext ())
mathieu@2647
   515
        {
mathieu@2647
   516
          os << " ";
mathieu@2647
   517
        }
mathieu@2647
   518
    }
mathieu@2660
   519
#endif   
mathieu@789
   520
}
mathieu@463
   521
mathieu@2639
   522
PacketMetadata::ItemIterator 
mathieu@2639
   523
Packet::BeginItem (void) const
mathieu@806
   524
{
mathieu@2639
   525
  return m_metadata.BeginItem (m_buffer);
mathieu@806
   526
}
mathieu@806
   527
mathieu@875
   528
void
mathieu@3553
   529
Packet::EnablePrinting (void)
mathieu@3553
   530
{
mathieu@3553
   531
  NS_LOG_FUNCTION_NOARGS ();
mathieu@883
   532
  PacketMetadata::Enable ();
mathieu@875
   533
}
mathieu@463
   534
mathieu@3553
   535
void
mathieu@3553
   536
Packet::EnableChecking (void)
mathieu@3553
   537
{
mathieu@3553
   538
  NS_LOG_FUNCTION_NOARGS ();
mathieu@3553
   539
  PacketMetadata::EnableChecking ();
mathieu@3553
   540
}
mathieu@3553
   541
mathieu@1138
   542
Buffer 
mathieu@1142
   543
Packet::Serialize (void) const
mathieu@1138
   544
{
mathieu@3158
   545
  NS_LOG_FUNCTION (this);
mathieu@1144
   546
  Buffer buffer;
mathieu@1144
   547
  uint32_t reserve;
mathieu@1144
   548
mathieu@1144
   549
  // write metadata
mathieu@1144
   550
  reserve = m_metadata.GetSerializedSize ();
mathieu@1144
   551
  buffer.AddAtStart (reserve);
mathieu@1144
   552
  m_metadata.Serialize (buffer.Begin (), reserve);
mathieu@1144
   553
mathieu@1144
   554
  // write tags
mathieu@3039
   555
  //XXX
mathieu@3039
   556
  //reserve = m_tags.GetSerializedSize ();
mathieu@3039
   557
  //buffer.AddAtStart (reserve);
mathieu@3039
   558
  //m_tags.Serialize (buffer.Begin (), reserve);
mathieu@1144
   559
  
mathieu@1144
   560
  // aggregate byte buffer, metadata, and tags
mathieu@1144
   561
  Buffer tmp = m_buffer.CreateFullCopy ();
mathieu@3039
   562
  tmp.AddAtEnd (buffer);
mathieu@1144
   563
  
mathieu@1150
   564
  // write byte buffer size.
mathieu@3039
   565
  tmp.AddAtStart (4);
mathieu@3039
   566
  tmp.Begin ().WriteU32 (m_buffer.GetSize ());
mathieu@1144
   567
mathieu@3039
   568
  return tmp;
mathieu@1138
   569
}
mathieu@1138
   570
void 
mathieu@1138
   571
Packet::Deserialize (Buffer buffer)
mathieu@1138
   572
{
mathieu@3158
   573
  NS_LOG_FUNCTION (this);
mathieu@1138
   574
  Buffer buf = buffer;
mathieu@1144
   575
  // read size
mathieu@1138
   576
  uint32_t packetSize = buf.Begin ().ReadU32 ();
mathieu@1138
   577
  buf.RemoveAtStart (4);
mathieu@1144
   578
mathieu@1144
   579
  // read buffer.
mathieu@1150
   580
  buf.RemoveAtEnd (buf.GetSize () - packetSize);
mathieu@1138
   581
  m_buffer = buf;
mathieu@3039
   582
  buffer.RemoveAtStart (4 + packetSize);
mathieu@3039
   583
mathieu@1144
   584
mathieu@1144
   585
  // read tags
mathieu@3039
   586
  //XXX
mathieu@3039
   587
  //uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
mathieu@3039
   588
  //buffer.RemoveAtStart (tagsDeserialized);
mathieu@1144
   589
mathieu@1144
   590
  // read metadata
mathieu@1144
   591
  uint32_t metadataDeserialized = 
mathieu@1144
   592
    m_metadata.Deserialize (buffer.Begin ());
mathieu@1144
   593
  buffer.RemoveAtStart (metadataDeserialized);
mathieu@1138
   594
}
mathieu@1138
   595
mathieu@3035
   596
void 
mathieu@4502
   597
Packet::AddByteTag (const Tag &tag) const
mathieu@3035
   598
{
mathieu@4484
   599
  NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
mathieu@4502
   600
  ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
mathieu@3040
   601
  TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (), 
mathieu@4502
   602
                                m_buffer.GetCurrentStartOffset (),
mathieu@4502
   603
                                m_buffer.GetCurrentEndOffset ());
mathieu@3035
   604
  tag.Serialize (buffer);
mathieu@3035
   605
}
mathieu@4502
   606
ByteTagIterator 
mathieu@4502
   607
Packet::GetByteTagIterator (void) const
mathieu@3035
   608
{
mathieu@4502
   609
  return ByteTagIterator (m_byteTagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
mathieu@3035
   610
}
mathieu@3035
   611
mathieu@3035
   612
bool 
mathieu@4502
   613
Packet::FindFirstMatchingByteTag (Tag &tag) const
mathieu@3035
   614
{
mathieu@3035
   615
  TypeId tid = tag.GetInstanceTypeId ();
mathieu@4502
   616
  ByteTagIterator i = GetByteTagIterator ();
mathieu@3035
   617
  while (i.HasNext ())
mathieu@3035
   618
    {
mathieu@4502
   619
      ByteTagIterator::Item item = i.Next ();
mathieu@3035
   620
      if (tid == item.GetTypeId ())
mathieu@3035
   621
        {
mathieu@3035
   622
          item.GetTag (tag);
mathieu@3035
   623
          return true;
mathieu@3035
   624
        }
mathieu@3035
   625
    }
mathieu@3035
   626
  return false;
mathieu@3035
   627
}
mathieu@3035
   628
mathieu@4502
   629
void 
mathieu@4502
   630
Packet::AddPacketTag (const Tag &tag) const
mathieu@4502
   631
{
mathieu@4502
   632
  NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
mathieu@4502
   633
  m_packetTagList.Add (tag);
mathieu@4502
   634
}
mathieu@4502
   635
bool 
mathieu@4502
   636
Packet::RemovePacketTag (Tag &tag)
mathieu@4502
   637
{
mathieu@4502
   638
  NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
mathieu@4502
   639
  bool found = m_packetTagList.Remove (tag);
mathieu@4502
   640
  return found;
mathieu@4502
   641
}
mathieu@4502
   642
bool 
mathieu@4502
   643
Packet::PeekPacketTag (Tag &tag) const
mathieu@4502
   644
{
mathieu@4502
   645
  bool found = m_packetTagList.Peek (tag);
mathieu@4502
   646
  return found;
mathieu@4502
   647
}
mathieu@4502
   648
void 
mathieu@4502
   649
Packet::RemoveAllPacketTags (void)
mathieu@4502
   650
{
mathieu@4502
   651
  NS_LOG_FUNCTION (this);
mathieu@4502
   652
  m_packetTagList.RemoveAll ();
mathieu@4502
   653
}
mathieu@4502
   654
mathieu@4502
   655
void 
mathieu@4502
   656
Packet::PrintPacketTags (std::ostream &os) const
mathieu@4502
   657
{
mathieu@4502
   658
  PacketTagIterator i = GetPacketTagIterator ();
mathieu@4502
   659
  while (i.HasNext ())
mathieu@4502
   660
    {
mathieu@4502
   661
      PacketTagIterator::Item item = i.Next ();
mathieu@4502
   662
      NS_ASSERT (item.GetTypeId ().HasConstructor ());
mathieu@4502
   663
      Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
mathieu@4502
   664
      NS_ASSERT (!constructor.IsNull ());
mathieu@4502
   665
      ObjectBase *instance = constructor ();
mathieu@4502
   666
      Tag *tag = dynamic_cast<Tag *> (instance);
mathieu@4502
   667
      NS_ASSERT (tag != 0);
mathieu@4502
   668
      item.GetTag (*tag);
mathieu@4502
   669
      tag->Print (os);
mathieu@4502
   670
      delete tag;
mathieu@4502
   671
      if (i.HasNext ())
mathieu@4502
   672
        {
mathieu@4502
   673
          os << " ";
mathieu@4502
   674
        }
mathieu@4502
   675
    }
mathieu@4502
   676
}
mathieu@4502
   677
mathieu@4502
   678
PacketTagIterator 
mathieu@4502
   679
Packet::GetPacketTagIterator (void) const
mathieu@4502
   680
{
mathieu@4502
   681
  return PacketTagIterator (m_packetTagList.Head ());
mathieu@4502
   682
}
mathieu@4502
   683
mathieu@1360
   684
std::ostream& operator<< (std::ostream& os, const Packet &packet)
mathieu@1360
   685
{
mathieu@1360
   686
  packet.Print (os);
mathieu@1360
   687
  return os;
mathieu@1360
   688
}
mathieu@1360
   689
boyko@5334
   690
//-----------------------------------------------------------------------------
boyko@5334
   691
// Unit tests
boyko@5334
   692
//-----------------------------------------------------------------------------
mathieu@3035
   693
namespace {
mathieu@3035
   694
mathieu@3040
   695
class ATestTagBase : public Tag
mathieu@3035
   696
{
mathieu@3035
   697
public:
mathieu@3035
   698
  ATestTagBase () : m_error (false) {}
mathieu@3035
   699
  bool m_error;
mathieu@3035
   700
};
mathieu@3035
   701
mathieu@3035
   702
template <int N>
mathieu@3035
   703
class ATestTag : public ATestTagBase
mathieu@3035
   704
{
mathieu@3035
   705
public:
mathieu@3035
   706
  static TypeId GetTypeId (void) {
mathieu@3035
   707
    std::ostringstream oss;
mathieu@3035
   708
    oss << "anon::ATestTag<" << N << ">";
mathieu@3035
   709
    static TypeId tid = TypeId (oss.str ().c_str ())
mathieu@3040
   710
      .SetParent<Tag> ()
mathieu@3035
   711
      .AddConstructor<ATestTag<N> > ()
mathieu@3035
   712
      .HideFromDocumentation ()
mathieu@3035
   713
      ;
mathieu@3035
   714
    return tid;
mathieu@3035
   715
  }
mathieu@3035
   716
  virtual TypeId GetInstanceTypeId (void) const {
mathieu@3035
   717
    return GetTypeId ();
mathieu@3035
   718
  }
mathieu@3035
   719
  virtual uint32_t GetSerializedSize (void) const {
mathieu@3035
   720
    return N;
mathieu@3035
   721
  }
mathieu@3040
   722
  virtual void Serialize (TagBuffer buf) const {
mathieu@3035
   723
    for (uint32_t i = 0; i < N; ++i)
mathieu@3035
   724
      {
mathieu@3035
   725
        buf.WriteU8 (N);
mathieu@3035
   726
      }
mathieu@3035
   727
  }
mathieu@3040
   728
  virtual void Deserialize (TagBuffer buf) {
mathieu@3035
   729
    for (uint32_t i = 0; i < N; ++i)
mathieu@3035
   730
      {
mathieu@3035
   731
        uint8_t v = buf.ReadU8 ();
mathieu@3035
   732
        if (v != N)
mathieu@3035
   733
          {
mathieu@3035
   734
            m_error = true;
mathieu@3035
   735
          }
mathieu@3035
   736
      }
mathieu@3035
   737
  }
mathieu@3208
   738
  virtual void Print (std::ostream &os) const {
mathieu@3208
   739
    os << N;
mathieu@3208
   740
  }
mathieu@3035
   741
  ATestTag ()
mathieu@3035
   742
    : ATestTagBase () {}
mathieu@3035
   743
};
mathieu@3035
   744
mathieu@3048
   745
class ATestHeaderBase : public Header
mathieu@3048
   746
{
mathieu@3048
   747
public:
mathieu@3048
   748
  ATestHeaderBase () : Header (), m_error (false) {}
mathieu@3048
   749
  bool m_error;
mathieu@3048
   750
};
mathieu@3048
   751
mathieu@3048
   752
template <int N>
mathieu@3048
   753
class ATestHeader : public ATestHeaderBase
mathieu@3048
   754
{
mathieu@3048
   755
public:
mathieu@3048
   756
  static TypeId GetTypeId (void) {
mathieu@3048
   757
    std::ostringstream oss;
mathieu@3048
   758
    oss << "anon::ATestHeader<" << N << ">";
mathieu@3048
   759
    static TypeId tid = TypeId (oss.str ().c_str ())
mathieu@3048
   760
      .SetParent<Header> ()
mathieu@3048
   761
      .AddConstructor<ATestHeader<N> > ()
mathieu@3048
   762
      .HideFromDocumentation ()
mathieu@3048
   763
      ;
mathieu@3048
   764
    return tid;
mathieu@3048
   765
  }
mathieu@3048
   766
  virtual TypeId GetInstanceTypeId (void) const {
mathieu@3048
   767
    return GetTypeId ();
mathieu@3048
   768
  }
mathieu@3048
   769
  virtual uint32_t GetSerializedSize (void) const {
mathieu@3048
   770
    return N;
mathieu@3048
   771
  }
mathieu@3048
   772
  virtual void Serialize (Buffer::Iterator iter) const {
mathieu@3048
   773
    for (uint32_t i = 0; i < N; ++i)
mathieu@3048
   774
      {
mathieu@3048
   775
        iter.WriteU8 (N);
mathieu@3048
   776
      }
mathieu@3048
   777
  }
mathieu@3048
   778
  virtual uint32_t Deserialize (Buffer::Iterator iter) {
mathieu@3048
   779
    for (uint32_t i = 0; i < N; ++i)
mathieu@3048
   780
      {
mathieu@3048
   781
        uint8_t v = iter.ReadU8 ();
mathieu@3048
   782
        if (v != N)
mathieu@3048
   783
          {
mathieu@3048
   784
            m_error = true;
mathieu@3048
   785
          }
mathieu@3048
   786
      }
mathieu@3048
   787
    return N;
mathieu@3048
   788
  }
mathieu@3048
   789
  virtual void Print (std::ostream &os) const {
mathieu@3048
   790
  }
mathieu@3048
   791
  ATestHeader ()
mathieu@3048
   792
    : ATestHeaderBase () {}
mathieu@3048
   793
mathieu@3048
   794
};
mathieu@3048
   795
mathieu@3237
   796
class ATestTrailerBase : public Trailer
mathieu@3237
   797
{
mathieu@3237
   798
public:
mathieu@3237
   799
  ATestTrailerBase () : Trailer (), m_error (false) {}
mathieu@3237
   800
  bool m_error;
mathieu@3237
   801
};
mathieu@3237
   802
mathieu@3237
   803
template <int N>
mathieu@3237
   804
class ATestTrailer : public ATestTrailerBase
mathieu@3237
   805
{
mathieu@3237
   806
public:
mathieu@3237
   807
  static TypeId GetTypeId (void) {
mathieu@3237
   808
    std::ostringstream oss;
mathieu@3237
   809
    oss << "anon::ATestTrailer<" << N << ">";
mathieu@3237
   810
    static TypeId tid = TypeId (oss.str ().c_str ())
mathieu@3237
   811
      .SetParent<Header> ()
mathieu@3237
   812
      .AddConstructor<ATestTrailer<N> > ()
mathieu@3237
   813
      .HideFromDocumentation ()
mathieu@3237
   814
      ;
mathieu@3237
   815
    return tid;
mathieu@3237
   816
  }
mathieu@3237
   817
  virtual TypeId GetInstanceTypeId (void) const {
mathieu@3237
   818
    return GetTypeId ();
mathieu@3237
   819
  }
mathieu@3237
   820
  virtual uint32_t GetSerializedSize (void) const {
mathieu@3237
   821
    return N;
mathieu@3237
   822
  }
mathieu@3237
   823
  virtual void Serialize (Buffer::Iterator iter) const {
mathieu@3237
   824
    iter.Prev (N);
mathieu@3237
   825
    for (uint32_t i = 0; i < N; ++i)
mathieu@3237
   826
      {
mathieu@3237
   827
        iter.WriteU8 (N);
mathieu@3237
   828
      }
mathieu@3237
   829
  }
mathieu@3237
   830
  virtual uint32_t Deserialize (Buffer::Iterator iter) {
mathieu@3237
   831
    iter.Prev (N);
mathieu@3237
   832
    for (uint32_t i = 0; i < N; ++i)
mathieu@3237
   833
      {
mathieu@3237
   834
        uint8_t v = iter.ReadU8 ();
mathieu@3237
   835
        if (v != N)
mathieu@3237
   836
          {
mathieu@3237
   837
            m_error = true;
mathieu@3237
   838
          }
mathieu@3237
   839
      }
mathieu@3237
   840
    return N;
mathieu@3237
   841
  }
mathieu@3237
   842
  virtual void Print (std::ostream &os) const {
mathieu@3237
   843
  }
mathieu@3237
   844
  ATestTrailer ()
mathieu@3237
   845
    : ATestTrailerBase () {}
mathieu@3237
   846
mathieu@3237
   847
};
mathieu@3237
   848
mathieu@3237
   849
mathieu@3035
   850
struct Expected
mathieu@3035
   851
{
mathieu@3035
   852
  Expected (uint32_t n_, uint32_t start_, uint32_t end_)
mathieu@3035
   853
    : n (n_), start (start_), end (end_) {}
mathieu@3035
   854
  
mathieu@3035
   855
  uint32_t n;
mathieu@3035
   856
  uint32_t start;
mathieu@3035
   857
  uint32_t end;
mathieu@3035
   858
};
mathieu@3035
   859
mathieu@3035
   860
}
mathieu@3035
   861
mathieu@3237
   862
// tag name, start, end
mathieu@3035
   863
#define E(a,b,c) a,b,c
mathieu@3035
   864
mathieu@3035
   865
#define CHECK(p, n, ...)                                \
boyko@5334
   866
  DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)
gjc@772
   867
boyko@5334
   868
class PacketTest: public TestCase 
mathieu@3035
   869
{
gjc@772
   870
public:
mathieu@3035
   871
  PacketTest ();
boyko@5334
   872
  virtual bool DoRun (void);
mathieu@3035
   873
private:
boyko@5334
   874
  void DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
boyko@5334
   875
};
gjc@772
   876
gjc@772
   877
gjc@772
   878
PacketTest::PacketTest ()
boyko@5334
   879
  : TestCase ("Packet") {}
gjc@772
   880
boyko@5334
   881
void
mathieu@3035
   882
PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
mathieu@3035
   883
{
mathieu@3035
   884
  std::vector<struct Expected> expected;
mathieu@3035
   885
  va_list ap;
mathieu@3035
   886
  va_start (ap, n);
mathieu@3035
   887
  for (uint32_t k = 0; k < n; ++k)
mathieu@3035
   888
    {
mathieu@3035
   889
      uint32_t N = va_arg (ap, uint32_t);
mathieu@3035
   890
      uint32_t start = va_arg (ap, uint32_t);
mathieu@3035
   891
      uint32_t end = va_arg (ap, uint32_t);
mathieu@3035
   892
      expected.push_back (Expected (N, start, end));
mathieu@3035
   893
    }
mathieu@3035
   894
  va_end (ap);
mathieu@3035
   895
mathieu@4502
   896
  ByteTagIterator i = p->GetByteTagIterator ();
mathieu@3035
   897
  uint32_t j = 0;
mathieu@3035
   898
  while (i.HasNext () && j < expected.size ())
mathieu@3035
   899
    {
mathieu@4502
   900
      ByteTagIterator::Item item = i.Next ();
mathieu@3035
   901
      struct Expected e = expected[j];
mathieu@3035
   902
      std::ostringstream oss;
mathieu@3035
   903
      oss << "anon::ATestTag<" << e.n << ">";
boyko@5334
   904
      NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
boyko@5334
   905
      NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
boyko@5334
   906
      NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
mathieu@3035
   907
      ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
boyko@5334
   908
      NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
mathieu@3035
   909
      item.GetTag (*tag);
boyko@5334
   910
      NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
mathieu@3035
   911
      delete tag;
mathieu@3035
   912
      j++;
mathieu@3035
   913
    }
boyko@5334
   914
  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
boyko@5334
   915
  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
mathieu@3035
   916
}
gjc@772
   917
gjc@772
   918
bool
boyko@5334
   919
PacketTest::DoRun (void)
gjc@772
   920
{
mathieu@1865
   921
  Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
mathieu@1865
   922
  Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
mathieu@1865
   923
  Ptr<Packet> packet = Create<Packet> ();
mathieu@1865
   924
  packet->AddAtEnd (pkt1);
mathieu@1865
   925
  packet->AddAtEnd (pkt2);
gjc@772
   926
  
boyko@5334
   927
  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
gjc@772
   928
mathieu@1865
   929
  std::string msg = std::string (reinterpret_cast<const char *>(packet->PeekData ()),
mathieu@1865
   930
                                 packet->GetSize ());
boyko@5334
   931
  NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
gjc@772
   932
mathieu@3035
   933
mathieu@3035
   934
  Ptr<const Packet> p = Create<Packet> (1000);
mathieu@3035
   935
mathieu@4502
   936
  p->AddByteTag (ATestTag<1> ());
mathieu@3035
   937
  CHECK (p, 1, E (1, 0, 1000));
mathieu@3035
   938
  Ptr<const Packet> copy = p->Copy ();
mathieu@3035
   939
  CHECK (copy, 1, E (1, 0, 1000));
mathieu@3035
   940
mathieu@4502
   941
  p->AddByteTag (ATestTag<2> ());
mathieu@3035
   942
  CHECK (p, 2, E (1, 0, 1000), E(2, 0, 1000));
mathieu@3035
   943
  CHECK (copy, 1, E (1, 0, 1000));
mathieu@3035
   944
mathieu@3046
   945
  {
mathieu@3046
   946
    Packet c0 = *copy;
mathieu@3046
   947
    Packet c1 = *copy;
mathieu@3046
   948
    c0 = c1;
mathieu@3046
   949
    CHECK (&c0, 1, E (1, 0, 1000));
mathieu@3046
   950
    CHECK (&c1, 1, E (1, 0, 1000));
mathieu@3046
   951
    CHECK (copy, 1, E (1, 0, 1000));
mathieu@4502
   952
    c0.AddByteTag (ATestTag<10> ());
mathieu@3046
   953
    CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
mathieu@3046
   954
    CHECK (&c1, 1, E (1, 0, 1000));
mathieu@3046
   955
    CHECK (copy, 1, E (1, 0, 1000));
mathieu@3046
   956
  }
mathieu@3046
   957
mathieu@3035
   958
  Ptr<Packet> frag0 = p->CreateFragment (0, 10);
mathieu@3035
   959
  Ptr<Packet> frag1 = p->CreateFragment (10, 90);
mathieu@3035
   960
  Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
mathieu@4502
   961
  frag0->AddByteTag (ATestTag<3> ());
mathieu@3035
   962
  CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
mathieu@4502
   963
  frag1->AddByteTag (ATestTag<4> ());
mathieu@3035
   964
  CHECK (frag1, 3, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90));
mathieu@4502
   965
  frag2->AddByteTag (ATestTag<5> ());
mathieu@3035
   966
  CHECK (frag2, 3, E (1, 0, 900), E(2, 0, 900), E (5, 0, 900));
mathieu@3035
   967
mathieu@3035
   968
  frag1->AddAtEnd (frag2);
mathieu@3035
   969
  CHECK (frag1, 6, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90), E (1, 90, 990), E(2, 90, 990), E (5, 90, 990));
mathieu@3035
   970
mathieu@3035
   971
  CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
mathieu@3035
   972
  frag0->AddAtEnd (frag1);
mathieu@3035
   973
  CHECK (frag0, 9, 
mathieu@3035
   974
         E (1, 0, 10), E(2, 0, 10), E (3, 0, 10),
mathieu@3035
   975
         E (1, 10, 100), E(2, 10, 100), E (4, 10, 100), 
mathieu@3035
   976
         E (1, 100, 1000), E(2, 100, 1000), E (5, 100, 1000));
mathieu@3035
   977
mathieu@3048
   978
mathieu@3048
   979
  // force caching a buffer of the right size.
mathieu@3048
   980
  frag0 = Create<Packet> (1000);
mathieu@3048
   981
  frag0->AddHeader (ATestHeader<10> ());
mathieu@3048
   982
  frag0 = 0;
mathieu@3048
   983
mathieu@3048
   984
  p = Create<Packet> (1000);
mathieu@4502
   985
  p->AddByteTag (ATestTag<20> ());
mathieu@3048
   986
  CHECK (p, 1, E (20, 0, 1000));
mathieu@3048
   987
  frag0 = p->CreateFragment (10, 90);
mathieu@3048
   988
  CHECK (p, 1, E (20, 0, 1000));
mathieu@3048
   989
  CHECK (frag0, 1, E (20, 0, 90));
mathieu@3048
   990
  p = 0;
mathieu@3048
   991
  frag0->AddHeader (ATestHeader<10> ());
mathieu@3048
   992
  CHECK (frag0, 1, E (20, 10, 100));
mathieu@3048
   993
mathieu@3237
   994
  {
mathieu@3237
   995
    Ptr<Packet> tmp = Create<Packet> (100);
mathieu@4502
   996
    tmp->AddByteTag (ATestTag<20> ());
mathieu@3237
   997
    CHECK (tmp, 1, E (20, 0, 100));
mathieu@3237
   998
    tmp->AddHeader (ATestHeader<10> ());
mathieu@3237
   999
    CHECK (tmp, 1, E (20, 10, 110));
mathieu@3237
  1000
    ATestHeader<10> h;
mathieu@3237
  1001
    tmp->RemoveHeader (h);
mathieu@3237
  1002
    CHECK (tmp, 1, E (20, 0, 100));
mathieu@3237
  1003
    tmp->AddHeader (ATestHeader<10> ());
mathieu@3237
  1004
    CHECK (tmp, 1, E (20, 10, 110));
mathieu@3237
  1005
mathieu@3237
  1006
    tmp = Create<Packet> (100);
mathieu@4502
  1007
    tmp->AddByteTag (ATestTag<20> ());
mathieu@3237
  1008
    CHECK (tmp, 1, E (20, 0, 100));
mathieu@3237
  1009
    tmp->AddTrailer (ATestTrailer<10> ());
mathieu@3237
  1010
    CHECK (tmp, 1, E (20, 0, 100));
mathieu@3237
  1011
    ATestTrailer<10> t;
mathieu@3237
  1012
    tmp->RemoveTrailer (t);
mathieu@3237
  1013
    CHECK (tmp, 1, E (20, 0, 100));
mathieu@3237
  1014
    tmp->AddTrailer (ATestTrailer<10> ());
mathieu@3237
  1015
    CHECK (tmp, 1, E (20, 0, 100));
mathieu@3237
  1016
    
mathieu@3237
  1017
  }
mathieu@3298
  1018
mathieu@3298
  1019
  {
mathieu@3298
  1020
    Ptr<Packet> tmp = Create<Packet> (0);
mathieu@3298
  1021
    tmp->AddHeader (ATestHeader<156> ());
mathieu@4502
  1022
    tmp->AddByteTag (ATestTag<20> ());
mathieu@3298
  1023
    CHECK (tmp, 1, E (20, 0, 156));
mathieu@3298
  1024
    tmp->RemoveAtStart (120);
mathieu@3298
  1025
    CHECK (tmp, 1, E (20, 0, 36));
mathieu@3298
  1026
    Ptr<Packet> a = Create<Packet> (0);
mathieu@3298
  1027
    a->AddAtEnd (tmp);
mathieu@3298
  1028
    CHECK (a, 1, E (20, 0, 36));
mathieu@3300
  1029
  }
mathieu@3300
  1030
mathieu@3300
  1031
  {
mathieu@3300
  1032
    Ptr<Packet> tmp = Create<Packet> (0);
mathieu@4502
  1033
    tmp->AddByteTag (ATestTag<20> ());
mathieu@3300
  1034
    CHECK (tmp, 0, E (20, 0, 0));
mathieu@3300
  1035
  }
mathieu@3301
  1036
  {
mathieu@3301
  1037
    Ptr<Packet> tmp = Create<Packet> (1000);
mathieu@4502
  1038
    tmp->AddByteTag (ATestTag<20> ());
mathieu@3301
  1039
    CHECK (tmp, 1, E (20, 0, 1000));
mathieu@3301
  1040
    tmp->RemoveAtStart (1000);
mathieu@3301
  1041
    CHECK (tmp, 0,  E (0,0,0));
mathieu@3301
  1042
    Ptr<Packet> a = Create<Packet> (10);
mathieu@4502
  1043
    a->AddByteTag (ATestTag<10> ());
mathieu@3301
  1044
    CHECK (a, 1, E (10, 0, 10));
mathieu@3301
  1045
    tmp->AddAtEnd (a);
mathieu@3301
  1046
    CHECK (tmp, 1, E (10, 0, 10));
mathieu@3301
  1047
  }
mathieu@4502
  1048
mathieu@4502
  1049
  {
mathieu@4502
  1050
    Packet p;
mathieu@4502
  1051
    ATestTag<10> a;
mathieu@4502
  1052
    p.AddPacketTag (a);
boyko@5334
  1053
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
mathieu@4502
  1054
    ATestTag<11> b;
mathieu@4502
  1055
    p.AddPacketTag (b);
boyko@5334
  1056
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
boyko@5334
  1057
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
mathieu@4502
  1058
    Packet copy = p;
boyko@5334
  1059
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
boyko@5334
  1060
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
mathieu@4502
  1061
    ATestTag<12> c;
boyko@5334
  1062
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
mathieu@4502
  1063
    copy.AddPacketTag (c);
boyko@5334
  1064
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
boyko@5334
  1065
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
boyko@5334
  1066
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
boyko@5334
  1067
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
mathieu@4502
  1068
    copy.RemovePacketTag (b);
boyko@5334
  1069
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
boyko@5334
  1070
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
mathieu@4502
  1071
    p.RemovePacketTag (a);
boyko@5334
  1072
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
boyko@5334
  1073
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
boyko@5334
  1074
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
boyko@5334
  1075
    NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
mathieu@4502
  1076
    p.RemoveAllPacketTags ();
boyko@5334
  1077
    NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
mathieu@4502
  1078
  }
mathieu@4502
  1079
boyko@4486
  1080
  {
boyko@4486
  1081
    // bug 572                                                                  
boyko@4486
  1082
    Ptr<Packet> tmp = Create<Packet> (1000);
mathieu@4502
  1083
    tmp->AddByteTag (ATestTag<20> ());
boyko@4486
  1084
    CHECK (tmp, 1, E (20, 0, 1000));
boyko@4486
  1085
    tmp->AddHeader (ATestHeader<2> ());
boyko@4486
  1086
    CHECK (tmp, 1, E (20, 2, 1002));
boyko@4486
  1087
    tmp->RemoveAtStart (1);
boyko@4486
  1088
    CHECK (tmp, 1, E (20, 1, 1001));
boyko@4486
  1089
    tmp->PeekData ();
boyko@4486
  1090
    CHECK (tmp, 1, E (20, 1, 1001));
boyko@4486
  1091
  }
mathieu@3048
  1092
boyko@5334
  1093
  return GetErrorStatus ();
boyko@5334
  1094
}
boyko@5334
  1095
//-----------------------------------------------------------------------------
boyko@5334
  1096
class PacketTestSuite : public TestSuite
boyko@5334
  1097
{
boyko@5334
  1098
public:
boyko@5334
  1099
  PacketTestSuite ();
boyko@5334
  1100
};
boyko@5334
  1101
boyko@5334
  1102
PacketTestSuite::PacketTestSuite ()
boyko@5334
  1103
  : TestSuite ("packet", UNIT)
boyko@5334
  1104
{
boyko@5334
  1105
  AddTestCase (new PacketTest);
gjc@772
  1106
}
gjc@772
  1107
boyko@5334
  1108
PacketTestSuite g_packetTestSuite;
boyko@5334
  1109
boyko@5334
  1110
mathieu@4502
  1111
} // namespace ns3