A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
pending-data.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 //
3 // Copyright (c) 2006 Georgia Tech Research Corporation
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: Rajib Bhattacharjea<raj.b@gatech.edu>
19 //
20 
21 
22 // This is a port of Data PDU Headers from:
23 // Georgia Tech Network Simulator
24 // George F. Riley. Georgia Tech, Spring 2002
25 
26 #include <iostream>
27 #include <algorithm>
28 
29 #include <cstring>
30 
31 #include "ns3/fatal-error.h"
32 #include "ns3/log.h"
33 
34 #include "pending-data.h"
35 
36 
37 NS_LOG_COMPONENT_DEFINE ("PendingData");
38 
39 namespace ns3
40 {
41 
42 PendingData::PendingData () : size (0), data (0),
43  msgSize (0), responseSize (0)
44 {
45  NS_LOG_FUNCTION (this);
46 }
47 
48 PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp)
49  : size (s), data (0), msgSize (msg), responseSize (resp)
50 {
51  NS_LOG_FUNCTION (this << s);
52  if (d)
53  {
54  data.push_back (Create<Packet> (d, size));
55  }
56 }
57 
58 PendingData::PendingData(const std::string& s)
59  : size (s.length () + 1), data (0),
60  msgSize (0), responseSize (0)
61 {
62  NS_LOG_FUNCTION (this << s.length () + 1);
63  data.push_back (Create<Packet> ((uint8_t*)s.c_str (), size));
64 }
65 
66 PendingData::PendingData(const PendingData& c)
67  : size (c.Size ()), data (c.data),
68  msgSize (c.msgSize), responseSize (c.responseSize)
69 {
70  NS_LOG_FUNCTION (this << c.Size ());
71 }
72 
73 PendingData::~PendingData()
74 {
75  NS_LOG_FUNCTION (this);
76 }
77 
78 PendingData* PendingData::Copy () const
79 {
80  NS_LOG_FUNCTION (this);
81  return new PendingData (*this);
82 };
83 
84 PendingData* PendingData::CopyS (uint32_t s)
85 { // Copy, but with new size (assumes no associated data);
86  NS_LOG_FUNCTION (this << s);
87  return new PendingData (s, 0, msgSize, responseSize);
88 }
89 
90 PendingData* PendingData::CopySD (uint32_t s, uint8_t* d)
91 { // Copy, but with new size (assumes no associated data);
92  NS_LOG_FUNCTION (this << s);
93  return new PendingData (s, d, msgSize, responseSize);
94 }
95 
96 void PendingData::Clear ()
97 { // Remove all pending data
98  NS_LOG_FUNCTION (this);
99  data.clear ();
100  size = 0;
101 }
102 
103 void PendingData::Add (uint32_t s, const uint8_t* d)
104 {
105  NS_LOG_FUNCTION (this << s);
106  if (d == 0)
107  {
108  data.push_back (Create<Packet> (d,s));
109  }
110  else
111  {
112  data.push_back (Create<Packet> (s));
113  }
114  size += s;
115 }
116 
117 void PendingData::Add (Ptr<Packet> p)
118 {
119  NS_LOG_FUNCTION (this);
120  data.push_back (p);
121  size += p->GetSize ();
122 }
123 
124 uint32_t PendingData::SizeFromSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset)
125 {
126  NS_LOG_FUNCTION (this << seqFront << seqOffset);
127  uint32_t o1 = OffsetFromSeq (seqFront, seqOffset); // Offset to start of unused data
128  return SizeFromOffset (o1); // Amount of data after offset
129 }
130 
131 uint32_t PendingData::SizeFromOffset (uint32_t offset)
132 { // Find out how much data is available from offset
133  NS_LOG_FUNCTION (this << offset);
134  // XXX should this return zero, or error out?
135  if (offset > size) return 0; // No data at requested offset
136  return size - offset; // Available data after offset
137 }
138 
139 uint32_t PendingData::OffsetFromSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset)
140 { // f is the first sequence number in this data, o is offset sequence
141  NS_LOG_FUNCTION (this << seqFront << seqOffset);
142  if (seqOffset < seqFront)
143  {
144  return 0; // HuH? Shouldn't happen
145  }
146  return seqOffset - seqFront;
147 }
148 
149 Ptr<Packet> PendingData::CopyFromOffset (uint32_t s, uint32_t o)
150 { // Make a copy of data from starting position "o" for "s" bytes
151  // Return NULL if results in zero length data
152  NS_LOG_FUNCTION (this << s << o);
153  uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data
154  if (s1 == 0)
155  {
156  return Create<Packet> (); // No data requested
157  }
158  if (data.size () != 0)
159  { // Actual data exists, make copy and return it
160  uint32_t count = 0;
161  std::vector<Ptr<Packet> >::size_type begin = 0;
162  bool beginFound = false;
163  std::vector<Ptr<Packet> >::size_type end = 0;
164  Ptr<Packet> outPacket;
165  Ptr<Packet> endFragment;
166  for (std::vector<Ptr<Packet> >::size_type i=0; i<data.size (); ++i)
167  {
168  count+=data[i]->GetSize ();
169  if (!beginFound)
170  {
171  if (count > o)
172  {
173  if (count >= o + s1) //then just copy within this packet
174  {
175  Ptr<Packet> toFragment = data[i];
176  uint32_t packetStart = count - toFragment->GetSize ();
177  uint32_t packetOffset = o - packetStart;
178  outPacket = toFragment->CreateFragment (packetOffset, s1);
179  return outPacket;
180  }
181  begin = i;
182  beginFound = true;
183  Ptr<Packet> toFragment = data[begin];
184  uint32_t packetStart = count - toFragment->GetSize ();
185  uint32_t packetOffset = o - packetStart;
186  uint32_t fragmentLength = count - o;
187  outPacket = toFragment->CreateFragment (packetOffset, fragmentLength);
188  }
189  }
190  else
191  {
192  if (count >= o + s1)
193  {
194  end = i;
195  Ptr<Packet> toFragment = data[end];
196  uint32_t packetStart = count - toFragment->GetSize ();
197  uint32_t fragmentLength = o + s1 - packetStart;
198  endFragment = toFragment->CreateFragment (0, fragmentLength);
199  break;
200  }
201  }
202  }
203  for (std::vector<Ptr<Packet> >::size_type i=begin+1; i<end; ++i)
204  {
205  outPacket->AddAtEnd (data[i]);
206  }
207  if (endFragment)
208  {
209  outPacket->AddAtEnd (endFragment);
210  }
211  NS_ASSERT (outPacket->GetSize () == s1);
212  return outPacket;
213  }
214  else
215  { // No actual data, just return dummy-data packet of correct size
216  return Create<Packet> (s1);
217  }
218 }
219 
220 Ptr<Packet> PendingData::CopyFromSeq (uint32_t s, const SequenceNumber32& f, const SequenceNumber32& o)
221 {
222  NS_LOG_FUNCTION (this << s << f << o);
223  return CopyFromOffset (s, OffsetFromSeq (f,o));
224 }
225 
226 uint32_t
227 PendingData::RemoveToSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset)
228 {
229  NS_LOG_FUNCTION (this << seqFront << seqOffset);
230  uint32_t count = OffsetFromSeq (seqFront, seqOffset);
231  NS_ASSERT_MSG (count <= size, "Trying to remove more data than in the buffer");
232  if (count == size)
233  {
234  Clear ();
235  return size;
236  }
237  // Remove whole packets, if possible, from the front of the data
238  // Do not perform buffer manipulations within packet; if a whole packet
239  // cannot be removed, leave it alone
240  std::vector<Ptr<Packet> >::iterator endI = data.begin ();
241  uint32_t current = 0;
242  // Any packet whose data has been completely acked can be removed
243  for (std::vector<Ptr<Packet> >::iterator dataI = data.begin (); dataI < data.end (); dataI++)
244  {
245  if (current + (*dataI)->GetSize () > count)
246  {
247  break;
248  }
249  current += (*dataI)->GetSize ();
250  ++endI;
251  }
252  data.erase (data.begin (), endI);
253  size -= current;
254  return current;
255 }
256 
257 } //namepsace ns3
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual uint32_t RemoveToSeq(const SequenceNumber32 &seqFront, const SequenceNumber32 &seqOffset)
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual uint32_t SizeFromOffset(uint32_t offset)
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
virtual uint32_t SizeFromSeq(const SequenceNumber32 &seqFront, const SequenceNumber32 &seqOffset)
virtual uint32_t OffsetFromSeq(const SequenceNumber32 &seqFront, const SequenceNumber32 &seqOffset)