1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "packet.h"
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 #include "ns3/simulator.h"
24 #include <string>
25 #include <cstdarg>
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("Packet");
30 
31 uint32_t Packet::m_globalUid = 0;
32 
33 TypeId
GetTypeId(void) const34 ByteTagIterator::Item::GetTypeId (void) const
35 {
36   return m_tid;
37 }
38 uint32_t
GetStart(void) const39 ByteTagIterator::Item::GetStart (void) const
40 {
41   return m_start;
42 }
43 uint32_t
GetEnd(void) const44 ByteTagIterator::Item::GetEnd (void) const
45 {
46   return m_end;
47 }
48 void
GetTag(Tag & tag) const49 ByteTagIterator::Item::GetTag (Tag &tag) const
50 {
51   if (tag.GetInstanceTypeId () != GetTypeId ())
52     {
53       NS_FATAL_ERROR ("The tag you provided is not of the right type.");
54     }
55   tag.Deserialize (m_buffer);
56 }
Item(TypeId tid,uint32_t start,uint32_t end,TagBuffer buffer)57 ByteTagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
58   : m_tid (tid),
59     m_start (start),
60     m_end (end),
61     m_buffer (buffer)
62 {
63 }
64 bool
HasNext(void) const65 ByteTagIterator::HasNext (void) const
66 {
67   return m_current.HasNext ();
68 }
69 ByteTagIterator::Item
Next(void)70 ByteTagIterator::Next (void)
71 {
72   ByteTagList::Iterator::Item i = m_current.Next ();
73   return ByteTagIterator::Item (i.tid,
74                                 i.start-m_current.GetOffsetStart (),
75                                 i.end-m_current.GetOffsetStart (),
76                                 i.buf);
77 }
ByteTagIterator(ByteTagList::Iterator i)78 ByteTagIterator::ByteTagIterator (ByteTagList::Iterator i)
79   : m_current (i)
80 {
81 }
82 
83 
PacketTagIterator(const struct PacketTagList::TagData * head)84 PacketTagIterator::PacketTagIterator (const struct PacketTagList::TagData *head)
85   : m_current (head)
86 {
87 }
88 bool
HasNext(void) const89 PacketTagIterator::HasNext (void) const
90 {
91   return m_current != 0;
92 }
93 PacketTagIterator::Item
Next(void)94 PacketTagIterator::Next (void)
95 {
96   NS_ASSERT (HasNext ());
97   const struct PacketTagList::TagData *prev = m_current;
98   m_current = m_current->next;
99   return PacketTagIterator::Item (prev);
100 }
101 
Item(const struct PacketTagList::TagData * data)102 PacketTagIterator::Item::Item (const struct PacketTagList::TagData *data)
103   : m_data (data)
104 {
105 }
106 TypeId
GetTypeId(void) const107 PacketTagIterator::Item::GetTypeId (void) const
108 {
109   return m_data->tid;
110 }
111 void
GetTag(Tag & tag) const112 PacketTagIterator::Item::GetTag (Tag &tag) const
113 {
114   NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
115   tag.Deserialize (TagBuffer ((uint8_t*)m_data->data,
116                               (uint8_t*)m_data->data + m_data->size));
117 }
118 
119 
120 Ptr<Packet>
Copy(void) const121 Packet::Copy (void) const
122 {
123   // we need to invoke the copy constructor directly
124   // rather than calling Create because the copy constructor
125   // is private.
126   return Ptr<Packet> (new Packet (*this), false);
127 }
128 
Packet()129 Packet::Packet ()
130   : m_buffer (),
131     m_byteTagList (),
132     m_packetTagList (),
133     /* The upper 32 bits of the packet id in
134      * metadata is for the system id. For non-
135      * distributed simulations, this is simply
136      * zero.  The lower 32 bits are for the
137      * global UID
138      */
139     m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, 0),
140     m_nixVector (0)
141 {
142   m_globalUid++;
143 }
144 
Packet(const Packet & o)145 Packet::Packet (const Packet &o)
146   : m_buffer (o.m_buffer),
147     m_byteTagList (o.m_byteTagList),
148     m_packetTagList (o.m_packetTagList),
149     m_metadata (o.m_metadata)
150 {
151   o.m_nixVector ? m_nixVector = o.m_nixVector->Copy ()
152     : m_nixVector = 0;
153 }
154 
155 Packet &
operator =(const Packet & o)156 Packet::operator = (const Packet &o)
157 {
158   if (this == &o)
159     {
160       return *this;
161     }
162   m_buffer = o.m_buffer;
163   m_byteTagList = o.m_byteTagList;
164   m_packetTagList = o.m_packetTagList;
165   m_metadata = o.m_metadata;
166   o.m_nixVector ? m_nixVector = o.m_nixVector->Copy ()
167     : m_nixVector = 0;
168   return *this;
169 }
170 
Packet(uint32_t size)171 Packet::Packet (uint32_t size)
172   : m_buffer (size),
173     m_byteTagList (),
174     m_packetTagList (),
175     /* The upper 32 bits of the packet id in
176      * metadata is for the system id. For non-
177      * distributed simulations, this is simply
178      * zero.  The lower 32 bits are for the
179      * global UID
180      */
181     m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, size),
182     m_nixVector (0)
183 {
184   m_globalUid++;
185 }
Packet(uint8_t const * buffer,uint32_t size,bool magic)186 Packet::Packet (uint8_t const *buffer, uint32_t size, bool magic)
187   : m_buffer (0, false),
188     m_byteTagList (),
189     m_packetTagList (),
190     m_metadata (0,0),
191     m_nixVector (0)
192 {
193   NS_ASSERT (magic);
194   Deserialize (buffer, size);
195 }
196 
Packet(uint8_t const * buffer,uint32_t size)197 Packet::Packet (uint8_t const*buffer, uint32_t size)
198   : m_buffer (),
199     m_byteTagList (),
200     m_packetTagList (),
201     /* The upper 32 bits of the packet id in
202      * metadata is for the system id. For non-
203      * distributed simulations, this is simply
204      * zero.  The lower 32 bits are for the
205      * global UID
206      */
207     m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, size),
208     m_nixVector (0)
209 {
210   m_globalUid++;
211   m_buffer.AddAtStart (size);
212   Buffer::Iterator i = m_buffer.Begin ();
213   i.Write (buffer, size);
214 }
215 
Packet(const Buffer & buffer,const ByteTagList & byteTagList,const PacketTagList & packetTagList,const PacketMetadata & metadata)216 Packet::Packet (const Buffer &buffer,  const ByteTagList &byteTagList,
217                 const PacketTagList &packetTagList, const PacketMetadata &metadata)
218   : m_buffer (buffer),
219     m_byteTagList (byteTagList),
220     m_packetTagList (packetTagList),
221     m_metadata (metadata),
222     m_nixVector (0)
223 {
224 }
225 
226 Ptr<Packet>
CreateFragment(uint32_t start,uint32_t length) const227 Packet::CreateFragment (uint32_t start, uint32_t length) const
228 {
229   NS_LOG_FUNCTION (this << start << length);
230   Buffer buffer = m_buffer.CreateFragment (start, length);
231   ByteTagList byteTagList = m_byteTagList;
232   byteTagList.Adjust (-start);
233   NS_ASSERT (m_buffer.GetSize () >= start + length);
234   uint32_t end = m_buffer.GetSize () - (start + length);
235   PacketMetadata metadata = m_metadata.CreateFragment (start, end);
236   // again, call the constructor directly rather than
237   // through Create because it is private.
238   Ptr<Packet> ret = Ptr<Packet> (new Packet (buffer, byteTagList, m_packetTagList, metadata), false);
239   ret->SetNixVector (GetNixVector ());
240   return ret;
241 }
242 
243 void
SetNixVector(Ptr<NixVector> nixVector)244 Packet::SetNixVector (Ptr<NixVector> nixVector)
245 {
246   m_nixVector = nixVector;
247 }
248 
249 Ptr<NixVector>
GetNixVector(void) const250 Packet::GetNixVector (void) const
251 {
252   return m_nixVector;
253 }
254 
255 void
AddHeader(const Header & header)256 Packet::AddHeader (const Header &header)
257 {
258   uint32_t size = header.GetSerializedSize ();
259   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << size);
260   m_buffer.AddAtStart (size);
261   m_byteTagList.Adjust (size);
262   m_byteTagList.AddAtStart (size);
263   header.Serialize (m_buffer.Begin ());
264   m_metadata.AddHeader (header, size);
265 }
266 uint32_t
RemoveHeader(Header & header,uint32_t size)267 Packet::RemoveHeader (Header &header, uint32_t size)
268 {
269   Buffer::Iterator end;
270   end = m_buffer.Begin ();
271   end.Next (size);
272   uint32_t deserialized = header.Deserialize (m_buffer.Begin (), end);
273   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
274   m_buffer.RemoveAtStart (deserialized);
275   m_byteTagList.Adjust (-deserialized);
276   m_metadata.RemoveHeader (header, deserialized);
277   return deserialized;
278 }
279 uint32_t
RemoveHeader(Header & header)280 Packet::RemoveHeader (Header &header)
281 {
282   uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
283   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
284   m_buffer.RemoveAtStart (deserialized);
285   m_byteTagList.Adjust (-deserialized);
286   m_metadata.RemoveHeader (header, deserialized);
287   return deserialized;
288 }
289 uint32_t
PeekHeader(Header & header) const290 Packet::PeekHeader (Header &header) const
291 {
292   uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
293   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
294   return deserialized;
295 }
296 uint32_t
PeekHeader(Header & header,uint32_t size) const297 Packet::PeekHeader (Header &header, uint32_t size) const
298 {
299   Buffer::Iterator end;
300   end = m_buffer.Begin ();
301   end.Next (size);
302   uint32_t deserialized = header.Deserialize (m_buffer.Begin (), end);
303   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
304   return deserialized;
305 }
306 void
AddTrailer(const Trailer & trailer)307 Packet::AddTrailer (const Trailer &trailer)
308 {
309   uint32_t size = trailer.GetSerializedSize ();
310   NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << size);
311   m_byteTagList.AddAtEnd (GetSize ());
312   m_buffer.AddAtEnd (size);
313   Buffer::Iterator end = m_buffer.End ();
314   trailer.Serialize (end);
315   m_metadata.AddTrailer (trailer, size);
316 }
317 uint32_t
RemoveTrailer(Trailer & trailer)318 Packet::RemoveTrailer (Trailer &trailer)
319 {
320   uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
321   NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
322   m_buffer.RemoveAtEnd (deserialized);
323   m_metadata.RemoveTrailer (trailer, deserialized);
324   return deserialized;
325 }
326 uint32_t
PeekTrailer(Trailer & trailer)327 Packet::PeekTrailer (Trailer &trailer)
328 {
329   uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
330   NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
331   return deserialized;
332 }
333 
334 void
AddAtEnd(Ptr<const Packet> packet)335 Packet::AddAtEnd (Ptr<const Packet> packet)
336 {
337   NS_LOG_FUNCTION (this << packet << packet->GetSize ());
338   m_byteTagList.AddAtEnd (GetSize ());
339   ByteTagList copy = packet->m_byteTagList;
340   copy.AddAtStart (0);
341   copy.Adjust (GetSize ());
342   m_byteTagList.Add (copy);
343   m_buffer.AddAtEnd (packet->m_buffer);
344   m_metadata.AddAtEnd (packet->m_metadata);
345 }
346 void
AddPaddingAtEnd(uint32_t size)347 Packet::AddPaddingAtEnd (uint32_t size)
348 {
349   NS_LOG_FUNCTION (this << size);
350   m_byteTagList.AddAtEnd (GetSize ());
351   m_buffer.AddAtEnd (size);
352   m_metadata.AddPaddingAtEnd (size);
353 }
354 void
RemoveAtEnd(uint32_t size)355 Packet::RemoveAtEnd (uint32_t size)
356 {
357   NS_LOG_FUNCTION (this << size);
358   m_buffer.RemoveAtEnd (size);
359   m_metadata.RemoveAtEnd (size);
360 }
361 void
RemoveAtStart(uint32_t size)362 Packet::RemoveAtStart (uint32_t size)
363 {
364   NS_LOG_FUNCTION (this << size);
365   m_buffer.RemoveAtStart (size);
366   m_byteTagList.Adjust (-size);
367   m_metadata.RemoveAtStart (size);
368 }
369 
370 void
RemoveAllByteTags(void)371 Packet::RemoveAllByteTags (void)
372 {
373   NS_LOG_FUNCTION (this);
374   m_byteTagList.RemoveAll ();
375 }
376 
377 uint32_t
CopyData(uint8_t * buffer,uint32_t size) const378 Packet::CopyData (uint8_t *buffer, uint32_t size) const
379 {
380   return m_buffer.CopyData (buffer, size);
381 }
382 
383 void
CopyData(std::ostream * os,uint32_t size) const384 Packet::CopyData (std::ostream *os, uint32_t size) const
385 {
386   return m_buffer.CopyData (os, size);
387 }
388 
389 uint64_t
GetUid(void) const390 Packet::GetUid (void) const
391 {
392   return m_metadata.GetUid ();
393 }
394 
395 void
PrintByteTags(std::ostream & os) const396 Packet::PrintByteTags (std::ostream &os) const
397 {
398   ByteTagIterator i = GetByteTagIterator ();
399   while (i.HasNext ())
400     {
401       ByteTagIterator::Item item = i.Next ();
402       os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
403       Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
404       if (constructor.IsNull ())
405         {
406           if (i.HasNext ())
407             {
408               os << " ";
409             }
410           continue;
411         }
412       Tag *tag = dynamic_cast<Tag *> (constructor ());
413       NS_ASSERT (tag != 0);
414       os << " ";
415       item.GetTag (*tag);
416       tag->Print (os);
417       if (i.HasNext ())
418         {
419           os << " ";
420         }
421       delete tag;
422     }
423 }
424 
425 std::string
ToString() const426 Packet::ToString() const
427 {
428   std::ostringstream oss;
429   Print (oss);
430   return oss.str();
431 }
432 
433 void
Print(std::ostream & os) const434 Packet::Print (std::ostream &os) const
435 {
436   PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
437   while (i.HasNext ())
438     {
439       PacketMetadata::Item item = i.Next ();
440       if (item.isFragment)
441         {
442           switch (item.type) {
443             case PacketMetadata::Item::PAYLOAD:
444               os << "Payload";
445               break;
446             case PacketMetadata::Item::HEADER:
447             case PacketMetadata::Item::TRAILER:
448               os << item.tid.GetName ();
449               break;
450             }
451           os << " Fragment [" << item.currentTrimedFromStart<<":"
452              << (item.currentTrimedFromStart + item.currentSize) << "]";
453         }
454       else
455         {
456           switch (item.type) {
457             case PacketMetadata::Item::PAYLOAD:
458               os << "Payload (size=" << item.currentSize << ")";
459               break;
460             case PacketMetadata::Item::HEADER:
461             case PacketMetadata::Item::TRAILER:
462               os << item.tid.GetName () << " (";
463               {
464                 NS_ASSERT (item.tid.HasConstructor ());
465                 Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
466                 NS_ASSERT (!constructor.IsNull ());
467                 ObjectBase *instance = constructor ();
468                 NS_ASSERT (instance != 0);
469                 Chunk *chunk = dynamic_cast<Chunk *> (instance);
470                 NS_ASSERT (chunk != 0);
471                 if (item.type == PacketMetadata::Item::HEADER)
472                   {
473                     Buffer::Iterator end = item.current;
474                     end.Next (item.currentSize); // move from start
475                     chunk->Deserialize (item.current, end);
476                   }
477                 else if (item.type == PacketMetadata::Item::TRAILER)
478                   {
479                     Buffer::Iterator start = item.current;
480                     start.Prev (item.currentSize); // move from end
481                     chunk->Deserialize (start, item.current);
482                   }
483                 else
484                   {
485                     chunk->Deserialize (item.current);
486                   }
487                 chunk->Print (os);
488                 delete chunk;
489               }
490               os << ")";
491               break;
492             }
493         }
494       if (i.HasNext ())
495         {
496           os << " ";
497         }
498     }
499 #if 0
500   // The code below will work only if headers and trailers
501   // define the right attributes which is not the case for
502   // now. So, as a temporary measure, we use the
503   // headers' and trailers' Print method as shown above.
504   PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
505   while (i.HasNext ())
506     {
507       PacketMetadata::Item item = i.Next ();
508       if (item.isFragment)
509         {
510           switch (item.type) {
511             case PacketMetadata::Item::PAYLOAD:
512               os << "Payload";
513               break;
514             case PacketMetadata::Item::HEADER:
515             case PacketMetadata::Item::TRAILER:
516               os << item.tid.GetName ();
517               break;
518             }
519           os << " Fragment [" << item.currentTrimedFromStart<<":"
520              << (item.currentTrimedFromStart + item.currentSize) << "]";
521         }
522       else
523         {
524           switch (item.type) {
525             case PacketMetadata::Item::PAYLOAD:
526               os << "Payload (size=" << item.currentSize << ")";
527               break;
528             case PacketMetadata::Item::HEADER:
529             case PacketMetadata::Item::TRAILER:
530               os << item.tid.GetName () << "(";
531               {
532                 NS_ASSERT (item.tid.HasConstructor ());
533                 Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
534                 NS_ASSERT (constructor.IsNull ());
535                 ObjectBase *instance = constructor ();
536                 NS_ASSERT (instance != 0);
537                 Chunk *chunk = dynamic_cast<Chunk *> (instance);
538                 NS_ASSERT (chunk != 0);
539                 chunk->Deserialize (item.current);
540                 for (uint32_t j = 0; j < item.tid.GetAttributeN (); j++)
541                   {
542                     std::string attrName = item.tid.GetAttributeName (j);
543                     std::string value;
544                     bool ok = chunk->GetAttribute (attrName, value);
545                     NS_ASSERT (ok);
546                     os << attrName << "=" << value;
547                     if ((j + 1) < item.tid.GetAttributeN ())
548                       {
549                         os << ",";
550                       }
551                   }
552               }
553               os << ")";
554               break;
555             }
556         }
557       if (i.HasNext ())
558         {
559           os << " ";
560         }
561     }
562 #endif
563 }
564 
565 PacketMetadata::ItemIterator
BeginItem(void) const566 Packet::BeginItem (void) const
567 {
568   return m_metadata.BeginItem (m_buffer);
569 }
570 
571 void
EnablePrinting(void)572 Packet::EnablePrinting (void)
573 {
574   NS_LOG_FUNCTION_NOARGS ();
575   PacketMetadata::Enable ();
576 }
577 
578 void
EnableChecking(void)579 Packet::EnableChecking (void)
580 {
581   NS_LOG_FUNCTION_NOARGS ();
582   PacketMetadata::EnableChecking ();
583 }
584 
GetSerializedSize(void) const585 uint32_t Packet::GetSerializedSize (void) const
586 {
587   uint32_t size = 0;
588 
589   if (m_nixVector)
590     {
591       // increment total size by the size of the nix-vector
592       // ensuring 4-byte boundary
593       size += ((m_nixVector->GetSerializedSize () + 3) & (~3));
594 
595       // add 4-bytes for entry of total length of nix-vector
596       size += 4;
597     }
598   else
599     {
600       // if no nix-vector, still have to add 4-bytes
601       // to account for the entry of total size for
602       // nix-vector in the buffer
603       size += 4;
604     }
605 
606   // increment total size by size of packet tag list
607   // ensuring 4-byte boundary
608   size += ((m_packetTagList.GetSerializedSize () + 3) & (~3));
609 
610   // add 4-bytes for entry of total length of packet tag list
611   size += 4;
612 
613   // increment total size by size of byte tag list
614   // ensuring 4-byte boundary
615   size += ((m_byteTagList.GetSerializedSize () + 3) & (~3));
616 
617   // add 4-bytes for entry of total length of byte tag list
618   size += 4;
619 
620   // increment total size by size of meta-data
621   // ensuring 4-byte boundary
622   size += ((m_metadata.GetSerializedSize () + 3) & (~3));
623 
624   // add 4-bytes for entry of total length of meta-data
625   size += 4;
626 
627   // increment total size by size of buffer
628   // ensuring 4-byte boundary
629   size += ((m_buffer.GetSerializedSize () + 3) & (~3));
630 
631   // add 4-bytes for entry of total length of buffer
632   size += 4;
633 
634   return size;
635 }
636 
637 uint32_t
Serialize(uint8_t * buffer,uint32_t maxSize) const638 Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
639 {
640   uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
641   uint32_t size = 0;
642 
643   // if nix-vector exists, serialize it
644   if (m_nixVector)
645     {
646       uint32_t nixSize = m_nixVector->GetSerializedSize ();
647       if (size + nixSize <= maxSize)
648         {
649           // put the total length of nix-vector in the
650           // buffer. this includes 4-bytes for total
651           // length itself
652           *p++ = nixSize + 4;
653           size += nixSize;
654 
655           // serialize the nix-vector
656           uint32_t serialized =
657             m_nixVector->Serialize (p, nixSize);
658           if (serialized)
659             {
660               // increment p by nixSize bytes
661               // ensuring 4-byte boundary
662               p += ((nixSize+3) & (~3)) / 4;
663             }
664           else
665             {
666               return 0;
667             }
668         }
669       else
670         {
671           return 0;
672         }
673     }
674   else
675     {
676       // no nix vector, set zero length,
677       // ie 4-bytes, since it must include
678       // length for itself
679       if (size + 4 <= maxSize)
680         {
681           size += 4;
682           *p++ = 4;
683         }
684       else
685         {
686           return 0;
687         }
688     }
689 
690   // Serialize byte tag list
691   uint32_t byteTagSize = m_byteTagList.GetSerializedSize ();
692   if (size + byteTagSize <= maxSize)
693     {
694       // put the total length of byte tag list in the
695       // buffer. this includes 4-bytes for total
696       // length itself
697       *p++ = byteTagSize + 4;
698       size += byteTagSize;
699 
700       // serialize the byte tag list
701       uint32_t serialized = m_byteTagList.Serialize (p, byteTagSize);
702       if (serialized)
703         {
704           // increment p by byteTagSize bytes
705           // ensuring 4-byte boundary
706           p += ((byteTagSize+3) & (~3)) / 4;
707         }
708       else
709         {
710           return 0;
711         }
712     }
713   else
714     {
715       return 0;
716     }
717 
718   // Serialize packet tag list
719   uint32_t packetTagSize = m_packetTagList.GetSerializedSize ();
720   if (size + packetTagSize <= maxSize)
721     {
722       // put the total length of packet tag list in the
723       // buffer. this includes 4-bytes for total
724       // length itself
725       *p++ = packetTagSize + 4;
726       size += packetTagSize;
727 
728       // serialize the packet tag list
729       uint32_t serialized = m_packetTagList.Serialize (p, packetTagSize);
730       if (serialized)
731         {
732           // increment p by packetTagSize bytes
733           // ensuring 4-byte boundary
734           p += ((packetTagSize+3) & (~3)) / 4;
735         }
736       else
737         {
738           return 0;
739         }
740     }
741   else
742     {
743       return 0;
744     }
745 
746   // Serialize Metadata
747   uint32_t metaSize = m_metadata.GetSerializedSize ();
748   if (size + metaSize <= maxSize)
749     {
750       // put the total length of metadata in the
751       // buffer. this includes 4-bytes for total
752       // length itself
753       *p++ = metaSize + 4;
754       size += metaSize;
755 
756       // serialize the metadata
757       uint32_t serialized = m_metadata.Serialize (reinterpret_cast<uint8_t *> (p), metaSize);
758       if (serialized)
759         {
760           // increment p by metaSize bytes
761           // ensuring 4-byte boundary
762           p += ((metaSize+3) & (~3)) / 4;
763         }
764       else
765         {
766           return 0;
767         }
768     }
769   else
770     {
771       return 0;
772     }
773 
774   // Serialize the packet contents
775   uint32_t bufSize = m_buffer.GetSerializedSize ();
776   if (size + bufSize <= maxSize)
777     {
778       // put the total length of the buffer in the
779       // buffer. this includes 4-bytes for total
780       // length itself
781       *p++ = bufSize + 4;
782 
783       // serialize the buffer
784       uint32_t serialized = m_buffer.Serialize (reinterpret_cast<uint8_t *> (p), bufSize);
785       if (!serialized)
786         {
787           return 0;
788         }
789     }
790   else
791     {
792       return 0;
793     }
794 
795   // Serialized successfully
796   return 1;
797 }
798 
799 uint32_t
Deserialize(const uint8_t * buffer,uint32_t size)800 Packet::Deserialize (const uint8_t* buffer, uint32_t size)
801 {
802   NS_LOG_FUNCTION (this);
803 
804   const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
805 
806   // read nix-vector
807   NS_ASSERT (!m_nixVector);
808   uint32_t nixSize = *p++;
809 
810   // if size less than nixSize, the buffer
811   // will be overrun, assert
812   NS_ASSERT (size >= nixSize);
813 
814   if (nixSize > 4)
815     {
816       Ptr<NixVector> nix = Create<NixVector> ();
817       uint32_t nixDeserialized = nix->Deserialize (p, nixSize);
818       if (!nixDeserialized)
819         {
820           // nix-vector not deserialized
821           // completely
822           return 0;
823         }
824       m_nixVector = nix;
825       // increment p by nixSize ensuring
826       // 4-byte boundary
827       p += ((((nixSize - 4) + 3) & (~3)) / 4);
828     }
829   size -= nixSize;
830 
831   // read byte tags
832   uint32_t byteTagSize = *p++;
833 
834   // if size less than byteTagSize, the buffer
835   // will be overrun, assert
836   NS_ASSERT (size >= byteTagSize);
837 
838   uint32_t byteTagDeserialized =
839     m_byteTagList.Deserialize (p, byteTagSize);
840   if (!byteTagDeserialized)
841     {
842       // byte tags not deserialized completely
843       return 0;
844     }
845   // increment p by byteTagSize ensuring
846   // 4-byte boundary
847   p += ((((byteTagSize - 4) + 3) & (~3)) / 4);
848   size -= byteTagSize;
849 
850   // read packet tags
851   uint32_t packetTagSize = *p++;
852 
853   // if size less than packetTagSize, the buffer
854   // will be overrun, assert
855   NS_ASSERT (size >= packetTagSize);
856 
857   uint32_t packetTagDeserialized =
858     m_packetTagList.Deserialize (p, packetTagSize);
859   if (!packetTagDeserialized)
860     {
861       // packet tags not deserialized completely
862       return 0;
863     }
864   // increment p by packetTagSize ensuring
865   // 4-byte boundary
866   p += ((((packetTagSize - 4) + 3) & (~3)) / 4);
867   size -= packetTagSize;
868 
869   // read metadata
870   uint32_t metaSize = *p++;
871 
872   // if size less than metaSize, the buffer
873   // will be overrun, assert
874   NS_ASSERT (size >= metaSize);
875 
876   uint32_t metadataDeserialized =
877     m_metadata.Deserialize (reinterpret_cast<const uint8_t *> (p), metaSize);
878   if (!metadataDeserialized)
879     {
880       // meta-data not deserialized
881       // completely
882       return 0;
883     }
884   // increment p by metaSize ensuring
885   // 4-byte boundary
886   p += ((((metaSize - 4) + 3) & (~3)) / 4);
887   size -= metaSize;
888 
889   // read buffer contents
890   uint32_t bufSize = *p++;
891 
892   // if size less than bufSize, the buffer
893   // will be overrun, assert
894   NS_ASSERT (size >= bufSize);
895 
896   uint32_t bufferDeserialized =
897     m_buffer.Deserialize (reinterpret_cast<const uint8_t *> (p), bufSize);
898   if (!bufferDeserialized)
899     {
900       // buffer not deserialized
901       // completely
902       return 0;
903     }
904   size -= bufSize;
905 
906   // return zero if did not deserialize the
907   // number of expected bytes
908   return (size == 0);
909 }
910 
911 void
AddByteTag(const Tag & tag) const912 Packet::AddByteTag (const Tag &tag) const
913 {
914   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
915   ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
916   TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
917                                 0,
918                                 GetSize ());
919   tag.Serialize (buffer);
920 }
921 void
AddByteTag(const Tag & tag,uint32_t start,uint32_t end) const922 Packet::AddByteTag (const Tag &tag, uint32_t start, uint32_t end) const
923 {
924   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
925   NS_ABORT_MSG_IF (end < start, "Invalid byte range");
926   ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
927   TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
928                                 static_cast<int32_t> (start),
929                                 static_cast<int32_t> (end));
930   tag.Serialize (buffer);
931 }
932 ByteTagIterator
GetByteTagIterator(void) const933 Packet::GetByteTagIterator (void) const
934 {
935   return ByteTagIterator (m_byteTagList.Begin (0, GetSize ()));
936 }
937 
938 bool
FindFirstMatchingByteTag(Tag & tag) const939 Packet::FindFirstMatchingByteTag (Tag &tag) const
940 {
941   TypeId tid = tag.GetInstanceTypeId ();
942   ByteTagIterator i = GetByteTagIterator ();
943   while (i.HasNext ())
944     {
945       ByteTagIterator::Item item = i.Next ();
946       if (tid == item.GetTypeId ())
947         {
948           item.GetTag (tag);
949           return true;
950         }
951     }
952   return false;
953 }
954 
955 void
AddPacketTag(const Tag & tag) const956 Packet::AddPacketTag (const Tag &tag) const
957 {
958   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
959   m_packetTagList.Add (tag);
960 }
961 
962 bool
RemovePacketTag(Tag & tag)963 Packet::RemovePacketTag (Tag &tag)
964 {
965   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
966   bool found = m_packetTagList.Remove (tag);
967   return found;
968 }
969 bool
ReplacePacketTag(Tag & tag)970 Packet::ReplacePacketTag (Tag &tag)
971 {
972   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
973   bool found = m_packetTagList.Replace (tag);
974   return found;
975 }
976 
977 bool
PeekPacketTag(Tag & tag) const978 Packet::PeekPacketTag (Tag &tag) const
979 {
980   bool found = m_packetTagList.Peek (tag);
981   return found;
982 }
983 void
RemoveAllPacketTags(void)984 Packet::RemoveAllPacketTags (void)
985 {
986   NS_LOG_FUNCTION (this);
987   m_packetTagList.RemoveAll ();
988 }
989 
990 void
PrintPacketTags(std::ostream & os) const991 Packet::PrintPacketTags (std::ostream &os) const
992 {
993   PacketTagIterator i = GetPacketTagIterator ();
994   while (i.HasNext ())
995     {
996       PacketTagIterator::Item item = i.Next ();
997       NS_ASSERT (item.GetTypeId ().HasConstructor ());
998       Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
999       NS_ASSERT (!constructor.IsNull ());
1000       ObjectBase *instance = constructor ();
1001       Tag *tag = dynamic_cast<Tag *> (instance);
1002       NS_ASSERT (tag != 0);
1003       item.GetTag (*tag);
1004       tag->Print (os);
1005       delete tag;
1006       if (i.HasNext ())
1007         {
1008           os << " ";
1009         }
1010     }
1011 }
1012 
1013 PacketTagIterator
GetPacketTagIterator(void) const1014 Packet::GetPacketTagIterator (void) const
1015 {
1016   return PacketTagIterator (m_packetTagList.Head ());
1017 }
1018 
operator <<(std::ostream & os,const Packet & packet)1019 std::ostream& operator<< (std::ostream& os, const Packet &packet)
1020 {
1021   packet.Print (os);
1022   return os;
1023 }
1024 
1025 } // namespace ns3
1026