00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2008 INRIA 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation; 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> 00019 */ 00020 #ifndef TAG_LIST_H 00021 #define TAG_LIST_H 00022 00023 #include <stdint.h> 00024 #include "ns3/type-id.h" 00025 #include "tag-buffer.h" 00026 00027 namespace ns3 { 00028 00029 struct TagListData; 00030 00031 /** 00032 * \ingroup packet 00033 * 00034 * \brief keep track of the tags stored in a packet. 00035 * 00036 * This class is mostly private to the Packet implementation and users 00037 * should never have to access it directly. 00038 * 00039 * \internal 00040 * The implementation of this class is a bit tricky so, there are a couple 00041 * of things to keep in mind here: 00042 * 00043 * - it stores all tags in a single byte buffer: each tag is stored 00044 * as 4 32bit integers (TypeId, tag data size, start, end) followed 00045 * by the tag data as generated by Tag::Serialize. 00046 * 00047 * - the struct TagListData structure which contains the tag byte buffer 00048 * is shared and, thus, reference-counted. This data structure is unshared 00049 * as-needed to emulate COW semantics. 00050 * 00051 * - each tag tags a unique set of bytes identified by the pair of offsets 00052 * (start,end). These offsets are provided by Buffer::GetCurrentStartOffset 00053 * and Buffer::GetCurrentEndOffset which means that they are relative to 00054 * the start of the 'virtual byte buffer' as explained in the documentation 00055 * for the ns3::Buffer class. Whenever the origin of the offset of the Buffer 00056 * instance associated to this TagList instance changes, the Buffer class 00057 * reports this to its container Packet class as a bool return value 00058 * in Buffer::AddAtStart and Buffer::AddAtEnd. In both cases, when this happens 00059 * the Packet class calls TagList::AddAtEnd and TagList::AddAtStart to update 00060 * the byte offsets of each tag in the TagList. 00061 * 00062 * - whenever bytes are removed from the packet byte buffer, the TagList offsets 00063 * are never updated because we rely on the fact that they will be updated in 00064 * either the next call to Packet::AddHeader or Packet::AddTrailer or when 00065 * the user iterates the tag list with Packet::GetTagIterator and 00066 * TagIterator::Next. 00067 */ 00068 class TagList 00069 { 00070 public: 00071 00072 class Iterator 00073 { 00074 public: 00075 struct Item 00076 { 00077 TypeId tid; 00078 uint32_t size; 00079 int32_t start; 00080 int32_t end; 00081 TagBuffer buf; 00082 Item (TagBuffer buf); 00083 private: 00084 friend class TagList; 00085 friend class TagList::Iterator; 00086 }; 00087 bool HasNext (void) const; 00088 struct TagList::Iterator::Item Next (void); 00089 uint32_t GetOffsetStart (void) const; 00090 private: 00091 friend class TagList; 00092 Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd); 00093 void PrepareForNext (void); 00094 uint8_t *m_current; 00095 uint8_t *m_end; 00096 int32_t m_offsetStart; 00097 int32_t m_offsetEnd; 00098 uint32_t m_nextTid; 00099 uint32_t m_nextSize; 00100 int32_t m_nextStart; 00101 int32_t m_nextEnd; 00102 }; 00103 00104 TagList (); 00105 TagList (const TagList &o); 00106 TagList &operator = (const TagList &o); 00107 ~TagList (); 00108 00109 /** 00110 * \param tid the typeid of the tag added 00111 * \param bufferSize the size of the tag when its serialization will 00112 * be completed. Typically, the return value of Tag::GetSerializedSize 00113 * \param start offset which uniquely identifies the first byte tagged by this tag. 00114 * \param end offset which uniquely identifies the last byte tagged by this tag. 00115 * \returns a buffer which can be used to write the tag data. 00116 * 00117 * 00118 */ 00119 TagBuffer Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end); 00120 00121 /** 00122 * \param o the other list of tags to aggregate. 00123 * 00124 * Aggregate the two lists of tags. 00125 */ 00126 void Add (const TagList &o); 00127 00128 void RemoveAll (void); 00129 00130 /** 00131 * \param offsetStart the offset which uniquely identifies the first data byte 00132 * present in the byte buffer associated to this TagList. 00133 * \param offsetEnd the offset which uniquely identifies the last data byte 00134 * present in the byte buffer associated to this TagList. 00135 * \returns an iterator 00136 * 00137 * The returned iterator will allow you to loop through the set of tags present 00138 * in this list: the boundaries of each tag as reported by their start and 00139 * end offsets will be included within the input offsetStart and offsetEnd. 00140 */ 00141 TagList::Iterator Begin (int32_t offsetStart, int32_t offsetEnd) const; 00142 00143 /** 00144 * Adjust the offsets stored internally by the adjustment delta and 00145 * make sure that all offsets are smaller than appendOffset which represents 00146 * the location where new bytes have been added to the byte buffer. 00147 */ 00148 void AddAtEnd (int32_t adjustment, int32_t appendOffset); 00149 /** 00150 * Adjust the offsets stored internally by the adjustment delta and 00151 * make sure that all offsets are bigger than prependOffset which represents 00152 * the location where new bytes have been added to the byte buffer. 00153 */ 00154 void AddAtStart (int32_t adjustment, int32_t prependOffset); 00155 00156 private: 00157 bool IsDirtyAtEnd (int32_t appendOffset); 00158 bool IsDirtyAtStart (int32_t prependOffset); 00159 TagList::Iterator BeginAll (void) const; 00160 00161 struct TagListData *Allocate (uint32_t size); 00162 void Deallocate (struct TagListData *data); 00163 00164 uint16_t m_used; 00165 struct TagListData *m_data; 00166 }; 00167 00168 } // namespace ns3 00169 00170 #endif /* TAG_LIST_H */