00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2005,2006,2007 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 BUFFER_H 00021 #define BUFFER_H 00022 00023 #include <stdint.h> 00024 #include <vector> 00025 00026 #define BUFFER_HEURISTICS 1 00027 #define BUFFER_USE_INLINE 1 00028 00029 00030 #ifdef BUFFER_USE_INLINE 00031 #define BUFFER_INLINE inline 00032 #else 00033 #define BUFFER_INLINE 00034 #endif 00035 00036 namespace ns3 { 00037 00038 /** 00039 * \ingroup packet 00040 * 00041 * \brief automatically resized byte buffer 00042 * 00043 * This represents a buffer of bytes. Its size is 00044 * automatically adjusted to hold any data prepended 00045 * or appended by the user. Its implementation is optimized 00046 * to ensure that the number of buffer resizes is minimized, 00047 * by creating new Buffers of the maximum size ever used. 00048 * The correct maximum size is learned at runtime during use by 00049 * recording the maximum size of each packet. 00050 * 00051 * \internal 00052 * The implementation of the Buffer class uses a COW (Copy On Write) 00053 * technique to ensure that the underlying data buffer which holds 00054 * the data bytes is shared among a lot of Buffer instances despite 00055 * data being added or removed from them. 00056 * 00057 * When multiple Buffer instances hold a reference to the same 00058 * underlying BufferData object, they must be able to detect when 00059 * the operation they want to perform should trigger a copy of the 00060 * BufferData. If the BufferData::m_count field is one, it means that 00061 * there exist only one instance of Buffer which references the 00062 * BufferData instance so, it is safe to modify it. It is also 00063 * safe to modify the content of a BufferData if the modification 00064 * falls outside of the "dirty area" defined by the BufferData. 00065 * In every other case, the BufferData must be copied before 00066 * being modified. 00067 * 00068 * To understand the way the Buffer::Add and Buffer::Remove methods 00069 * work, you first need to understand the "virtual offsets" used to 00070 * keep track of the content of buffers. Each Buffer instance 00071 * contains real data bytes in its BufferData instance but it also 00072 * contains "virtual zero data" which typically is used to represent 00073 * application-level payload. No memory is allocated to store the 00074 * zero bytes of application-level payload unless the user fragments 00075 * a Buffer: this application-level payload is kept track of with 00076 * a pair of integers which describe where in the buffer content 00077 * the "virtual zero area" starts and ends. 00078 * 00079 * ***: unused bytes 00080 * xxx: bytes "added" at the front of the zero area 00081 * ...: bytes "added" at the back of the zero area 00082 * 000: virtual zero bytes 00083 * 00084 * Real byte buffer: |********xxxxxxxxxxxx.........*****| 00085 * |--------^ m_start 00086 * |-------------------^ m_zeroAreaStart 00087 * |-----------------------------^ m_end - (m_zeroAreaEnd - m_zeroAreaStart) 00088 * virtual byte buffer: |xxxxxxxxxxxx0000000000000.........| 00089 * |--------^ m_start 00090 * |--------------------^ m_zeroAreaStart 00091 * |---------------------------------^ m_zeroAreaEnd 00092 * |------------------------------------------^ m_end 00093 * 00094 * A simple state invariant is that m_start <= m_zeroStart <= m_zeroEnd <= m_end 00095 */ 00096 class Buffer 00097 { 00098 public: 00099 /** 00100 * \brief iterator in a Buffer instance 00101 */ 00102 class Iterator 00103 { 00104 public: 00105 Iterator (); 00106 /** 00107 * go forward by one byte 00108 */ 00109 void Next (void); 00110 /** 00111 * go backward by one byte 00112 */ 00113 void Prev (void); 00114 /** 00115 * \param delta number of bytes to go forward 00116 */ 00117 void Next (uint32_t delta); 00118 /** 00119 * \param delta number of bytes to go backward 00120 */ 00121 void Prev (uint32_t delta); 00122 /** 00123 * \param o the second iterator 00124 * \return number of bytes included between the two iterators 00125 * 00126 * This method works only if the two iterators point 00127 * to the same underlying buffer. Debug builds ensure 00128 * this with an assert. 00129 */ 00130 uint32_t GetDistanceFrom (Iterator const &o) const; 00131 00132 /** 00133 * \return true if this iterator points to the end of the byte array. 00134 * false otherwise. 00135 */ 00136 bool IsEnd (void) const; 00137 /** 00138 * \return true if this iterator points to the start of the byte array. 00139 * false otherwise. 00140 */ 00141 bool IsStart (void) const; 00142 00143 /** 00144 * \param data data to write in buffer 00145 * 00146 * Write the data in buffer and avance the iterator position 00147 * by one byte. 00148 */ 00149 BUFFER_INLINE void WriteU8 (uint8_t data); 00150 /** 00151 * \param data data to write in buffer 00152 * \param len number of times data must be written in buffer 00153 * 00154 * Write the data in buffer len times and avance the iterator position 00155 * by len byte. 00156 */ 00157 BUFFER_INLINE void WriteU8 (uint8_t data, uint32_t len); 00158 /** 00159 * \param data data to write in buffer 00160 * 00161 * Write the data in buffer and avance the iterator position 00162 * by two bytes. The format of the data written in the byte 00163 * buffer is non-portable. We only ensure that readU16 will 00164 * return exactly what we wrote with writeU16 if the program 00165 * is run on the same machine. 00166 */ 00167 void WriteU16 (uint16_t data); 00168 /** 00169 * \param data data to write in buffer 00170 * 00171 * Write the data in buffer and avance the iterator position 00172 * by four bytes. The format of the data written in the byte 00173 * buffer is non-portable. We only ensure that readU32 will 00174 * return exactly what we wrote with writeU32 if the program 00175 * is run on the same machine. 00176 */ 00177 void WriteU32 (uint32_t data); 00178 /** 00179 * \param data data to write in buffer 00180 * 00181 * Write the data in buffer and avance the iterator position 00182 * by eight bytes. The format of the data written in the byte 00183 * buffer is non-portable. We only ensure that readU64 will 00184 * return exactly what we wrote with writeU64 if the program 00185 * is run on the same machine. 00186 */ 00187 void WriteU64 (uint64_t data); 00188 /** 00189 * \param data data to write in buffer 00190 * 00191 * Write the data in buffer and avance the iterator position 00192 * by two bytes. The data is written in network order and the 00193 * input data is expected to be in host order. 00194 */ 00195 void WriteHtolsbU16 (uint16_t data); 00196 /** 00197 * \param data data to write in buffer 00198 * 00199 * Write the data in buffer and avance the iterator position 00200 * by four bytes. The data is written in least significant byte order and the 00201 * input data is expected to be in host order. 00202 */ 00203 void WriteHtolsbU32 (uint32_t data); 00204 /** 00205 * \param data data to write in buffer 00206 * 00207 * Write the data in buffer and avance the iterator position 00208 * by eight bytes. The data is written in least significant byte order and the 00209 * input data is expected to be in host order. 00210 */ 00211 void WriteHtolsbU64 (uint64_t data); 00212 /** 00213 * \param data data to write in buffer 00214 * 00215 * Write the data in buffer and avance the iterator position 00216 * by two bytes. The data is written in least significant byte order and the 00217 * input data is expected to be in host order. 00218 */ 00219 void WriteHtonU16 (uint16_t data); 00220 /** 00221 * \param data data to write in buffer 00222 * 00223 * Write the data in buffer and avance the iterator position 00224 * by four bytes. The data is written in network order and the 00225 * input data is expected to be in host order. 00226 */ 00227 void WriteHtonU32 (uint32_t data); 00228 /** 00229 * \param data data to write in buffer 00230 * 00231 * Write the data in buffer and avance the iterator position 00232 * by eight bytes. The data is written in network order and the 00233 * input data is expected to be in host order. 00234 */ 00235 void WriteHtonU64 (uint64_t data); 00236 /** 00237 * \param buffer a byte buffer to copy in the internal buffer. 00238 * \param size number of bytes to copy. 00239 * 00240 * Write the data in buffer and avance the iterator position 00241 * by size bytes. 00242 */ 00243 void Write (uint8_t const*buffer, uint32_t size); 00244 /** 00245 * \param start the start of the data to copy 00246 * \param end the end of the data to copy 00247 * 00248 * Write the data delimited by start and end in internal buffer 00249 * and avance the iterator position by the number of bytes 00250 * copied. 00251 * The input interators _must_ not point to the same Buffer as 00252 * we do to avoid overlapping copies. This is enforced 00253 * in debug builds by asserts. 00254 */ 00255 void Write (Iterator start, Iterator end); 00256 00257 /** 00258 * \return the byte read in the buffer. 00259 * 00260 * Read data and advance the Iterator by the number of bytes 00261 * read. 00262 */ 00263 BUFFER_INLINE uint8_t ReadU8 (void); 00264 /** 00265 * \return the two bytes read in the buffer. 00266 * 00267 * Read data and advance the Iterator by the number of bytes 00268 * read. 00269 * The data is read in the format written by writeU16. 00270 */ 00271 uint16_t ReadU16 (void); 00272 /** 00273 * \return the four bytes read in the buffer. 00274 * 00275 * Read data and advance the Iterator by the number of bytes 00276 * read. 00277 * The data is read in the format written by writeU32. 00278 */ 00279 uint32_t ReadU32 (void); 00280 /** 00281 * \return the eight bytes read in the buffer. 00282 * 00283 * Read data and advance the Iterator by the number of bytes 00284 * read. 00285 * The data is read in the format written by writeU64. 00286 */ 00287 uint64_t ReadU64 (void); 00288 /** 00289 * \return the two bytes read in the buffer. 00290 * 00291 * Read data and advance the Iterator by the number of bytes 00292 * read. 00293 * The data is read in network format and return in host format. 00294 */ 00295 uint16_t ReadNtohU16 (void); 00296 /** 00297 * \return the four bytes read in the buffer. 00298 * 00299 * Read data and advance the Iterator by the number of bytes 00300 * read. 00301 * The data is read in network format and return in host format. 00302 */ 00303 uint32_t ReadNtohU32 (void); 00304 /** 00305 * \return the eight bytes read in the buffer. 00306 * 00307 * Read data and advance the Iterator by the number of bytes 00308 * read. 00309 * The data is read in network format and return in host format. 00310 */ 00311 uint64_t ReadNtohU64 (void); 00312 /** 00313 * \return the two bytes read in the buffer. 00314 * 00315 * Read data and advance the Iterator by the number of bytes 00316 * read. 00317 * The data is read in network format and return in host format. 00318 */ 00319 uint16_t ReadLsbtohU16 (void); 00320 /** 00321 * \return the four bytes read in the buffer. 00322 * 00323 * Read data and advance the Iterator by the number of bytes 00324 * read. 00325 * The data is read in network format and return in host format. 00326 */ 00327 uint32_t ReadLsbtohU32 (void); 00328 /** 00329 * \return the eight bytes read in the buffer. 00330 * 00331 * Read data and advance the Iterator by the number of bytes 00332 * read. 00333 * The data is read in network format and return in host format. 00334 */ 00335 uint64_t ReadLsbtohU64 (void); 00336 /** 00337 * \param buffer buffer to copy data into 00338 * \param size number of bytes to copy 00339 * 00340 * Copy size bytes of data from the internal buffer to the 00341 * input buffer and avance the Iterator by the number of 00342 * bytes read. 00343 */ 00344 void Read (uint8_t *buffer, uint32_t size); 00345 00346 /** 00347 * \brief Calculate the checksum. 00348 * \param size size of the buffer. 00349 * \return checksum 00350 */ 00351 uint16_t CalculateIpChecksum(uint16_t size); 00352 00353 /** 00354 * \brief Calculate the checksum. 00355 * \param size size of the buffer. 00356 * \param initialChecksum initial value 00357 * \return checksum 00358 */ 00359 uint16_t CalculateIpChecksum(uint16_t size, uint32_t initialChecksum); 00360 00361 /** 00362 * \returns the size of the underlying buffer we are iterating 00363 */ 00364 uint32_t GetSize (void) const; 00365 00366 private: 00367 friend class Buffer; 00368 Iterator (Buffer const*buffer); 00369 Iterator (Buffer const*buffer, bool); 00370 void Construct (const Buffer *buffer); 00371 bool CheckNoZero (uint32_t start, uint32_t end) const; 00372 bool Check (uint32_t i) const; 00373 00374 /* offset in virtual bytes from the start of the data buffer to the 00375 * start of the "virtual zero area". 00376 */ 00377 uint32_t m_zeroStart; 00378 /* offset in virtual bytes from the start of the data buffer to the 00379 * end of the "virtual zero area". 00380 */ 00381 uint32_t m_zeroEnd; 00382 /* offset in virtual bytes from the start of the data buffer to the 00383 * start of the data which can be read by this iterator 00384 */ 00385 uint32_t m_dataStart; 00386 /* offset in virtual bytes from the start of the data buffer to the 00387 * end of the data which can be read by this iterator 00388 */ 00389 uint32_t m_dataEnd; 00390 /* offset in virtual bytes from the start of the data buffer to the 00391 * current position represented by this iterator. 00392 */ 00393 uint32_t m_current; 00394 /* a pointer to the underlying byte buffer. All offsets are relative 00395 * to this pointer. 00396 */ 00397 uint8_t *m_data; 00398 }; 00399 00400 /** 00401 * \return the number of bytes stored in this buffer. 00402 */ 00403 uint32_t GetSize (void) const; 00404 00405 /** 00406 * \return a pointer to the start of the internal 00407 * byte buffer. 00408 * 00409 * The returned pointer points to an area of 00410 * memory which is ns3::Buffer::GetSize () bytes big. 00411 * Please, try to never ever use this method. It is really 00412 * evil and is present only for a few specific uses. 00413 */ 00414 uint8_t const*PeekData (void) const; 00415 00416 /** 00417 * \param start size to reserve 00418 * \returns true if the buffer needed resizing, false otherwise. 00419 * 00420 * Add bytes at the start of the Buffer. The 00421 * content of these bytes is undefined but debugging 00422 * builds initialize them to 0x33. 00423 * Any call to this method invalidates any Iterator 00424 * pointing to this Buffer. 00425 */ 00426 bool AddAtStart (uint32_t start); 00427 /** 00428 * \param end size to reserve 00429 * \returns true if the buffer needed resizing, false otherwise. 00430 * 00431 * Add bytes at the end of the Buffer. The 00432 * content of these bytes is undefined but debugging 00433 * builds initialize them to 0x33. 00434 * Any call to this method invalidates any Iterator 00435 * pointing to this Buffer. 00436 */ 00437 bool AddAtEnd (uint32_t end); 00438 00439 /** 00440 * \param o the buffer to append to the end of this buffer. 00441 * 00442 * Add bytes at the end of the Buffer. 00443 * Any call to this method invalidates any Iterator 00444 * pointing to this Buffer. 00445 */ 00446 void AddAtEnd (const Buffer &o); 00447 /** 00448 * \param start size to remove 00449 * 00450 * Remove bytes at the start of the Buffer. 00451 * Any call to this method invalidates any Iterator 00452 * pointing to this Buffer. 00453 */ 00454 void RemoveAtStart (uint32_t start); 00455 /** 00456 * \param end size to remove 00457 * 00458 * Remove bytes at the end of the Buffer. 00459 * Any call to this method invalidates any Iterator 00460 * pointing to this Buffer. 00461 */ 00462 void RemoveAtEnd (uint32_t end); 00463 00464 /** 00465 * \param start offset from start of packet 00466 * \param length 00467 * 00468 * \return a fragment of size length starting at offset 00469 * start. 00470 */ 00471 Buffer CreateFragment (uint32_t start, uint32_t length) const; 00472 00473 /** 00474 * \return an Iterator which points to the 00475 * start of this Buffer. 00476 */ 00477 Buffer::Iterator Begin (void) const; 00478 /** 00479 * \return an Iterator which points to the 00480 * end of this Buffer. 00481 */ 00482 Buffer::Iterator End (void) const; 00483 00484 Buffer CreateFullCopy (void) const; 00485 00486 int32_t GetCurrentStartOffset (void) const; 00487 int32_t GetCurrentEndOffset (void) const; 00488 00489 Buffer (Buffer const &o); 00490 Buffer &operator = (Buffer const &o); 00491 Buffer (); 00492 Buffer (uint32_t dataSize); 00493 ~Buffer (); 00494 private: 00495 00496 void TransformIntoRealBuffer (void) const; 00497 bool CheckInternalState (void) const; 00498 void Initialize (uint32_t zeroSize); 00499 uint32_t GetInternalSize (void) const; 00500 uint32_t GetInternalEnd (void) const; 00501 static void Recycle (struct BufferData *data); 00502 static struct BufferData *Create (uint32_t size); 00503 00504 /* This structure is described in the buffer.cc file. 00505 */ 00506 struct BufferData *m_data; 00507 #ifdef BUFFER_HEURISTICS 00508 /* keep track of the maximum value of m_zeroAreaStart across 00509 * the lifetime of a Buffer instance. This variable is used 00510 * purely as a source of information for the heuristics which 00511 * decide on the position of the zero area in new buffers. 00512 * It is read from the Buffer destructor to update the global 00513 * heuristic data and these global heuristic data are used from 00514 * the Buffer constructor to choose an initial value for 00515 * m_zeroAreaStart. 00516 * It is possible to disable all these heuristics by undefining the 00517 * BUFFER_HEURISTICS macro at the top of buffer.h 00518 */ 00519 uint32_t m_maxZeroAreaStart; 00520 #endif /* BUFFER_HEURISTICS */ 00521 /* offset to the start of the virtual zero area from the start 00522 * of m_data->m_data 00523 */ 00524 uint32_t m_zeroAreaStart; 00525 /* offset to the end of the virtual zero area from the start 00526 * of m_data->m_data 00527 */ 00528 uint32_t m_zeroAreaEnd; 00529 /* offset to the start of the data referenced by this Buffer 00530 * instance from the start of m_data->m_data 00531 */ 00532 uint32_t m_start; 00533 /* offset to the end of the data referenced by this Buffer 00534 * instance from the start of m_data->m_data 00535 */ 00536 uint32_t m_end; 00537 }; 00538 00539 } // namespace ns3 00540 00541 #ifdef BUFFER_USE_INLINE 00542 00543 #include "ns3/assert.h" 00544 #include <string.h> 00545 00546 namespace ns3 { 00547 00548 void 00549 Buffer::Iterator::WriteU8 (uint8_t data) 00550 { 00551 NS_ASSERT (Check (m_current)); 00552 00553 if (m_current < m_zeroStart) 00554 { 00555 m_data[m_current] = data; 00556 m_current++; 00557 } 00558 else 00559 { 00560 m_data[m_current - (m_zeroEnd-m_zeroStart)] = data; 00561 m_current++; 00562 } 00563 } 00564 00565 void 00566 Buffer::Iterator::WriteU8 (uint8_t data, uint32_t len) 00567 { 00568 NS_ASSERT (CheckNoZero (m_current, m_current + len)); 00569 if (m_current <= m_zeroStart) 00570 { 00571 memset (&(m_data[m_current]), data, len); 00572 m_current += len; 00573 } 00574 else 00575 { 00576 uint8_t *buffer = &m_data[m_current - (m_zeroEnd-m_zeroStart)]; 00577 memset (buffer, data, len); 00578 m_current += len; 00579 } 00580 } 00581 00582 uint8_t 00583 Buffer::Iterator::ReadU8 (void) 00584 { 00585 NS_ASSERT (m_current >= m_dataStart && 00586 m_current <= m_dataEnd); 00587 00588 if (m_current < m_zeroStart) 00589 { 00590 uint8_t data = m_data[m_current]; 00591 m_current++; 00592 return data; 00593 } 00594 else if (m_current < m_zeroEnd) 00595 { 00596 m_current++; 00597 return 0; 00598 } 00599 else 00600 { 00601 uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)]; 00602 m_current++; 00603 return data; 00604 } 00605 } 00606 00607 00608 } // namespace ns3 00609 00610 #endif /* BUFFER_USE_INLINE */ 00611 00612 #endif /* BUFFER_H */