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