A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
udp-echo-client.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright 2007 University of Washington
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 #include "ns3/log.h"
19 #include "ns3/ipv4-address.h"
20 #include "ns3/ipv6-address.h"
21 #include "ns3/nstime.h"
22 #include "ns3/inet-socket-address.h"
23 #include "ns3/inet6-socket-address.h"
24 #include "ns3/socket.h"
25 #include "ns3/simulator.h"
26 #include "ns3/socket-factory.h"
27 #include "ns3/packet.h"
28 #include "ns3/uinteger.h"
29 #include "ns3/trace-source-accessor.h"
30 #include "udp-echo-client.h"
31 
32 namespace ns3 {
33 
34 NS_LOG_COMPONENT_DEFINE ("UdpEchoClientApplication");
35 NS_OBJECT_ENSURE_REGISTERED (UdpEchoClient);
36 
37 TypeId
39 {
40  static TypeId tid = TypeId ("ns3::UdpEchoClient")
42  .AddConstructor<UdpEchoClient> ()
43  .AddAttribute ("MaxPackets",
44  "The maximum number of packets the application will send",
45  UintegerValue (100),
46  MakeUintegerAccessor (&UdpEchoClient::m_count),
47  MakeUintegerChecker<uint32_t> ())
48  .AddAttribute ("Interval",
49  "The time to wait between packets",
50  TimeValue (Seconds (1.0)),
51  MakeTimeAccessor (&UdpEchoClient::m_interval),
52  MakeTimeChecker ())
53  .AddAttribute ("RemoteAddress",
54  "The destination Address of the outbound packets",
55  AddressValue (),
56  MakeAddressAccessor (&UdpEchoClient::m_peerAddress),
57  MakeAddressChecker ())
58  .AddAttribute ("RemotePort",
59  "The destination port of the outbound packets",
60  UintegerValue (0),
61  MakeUintegerAccessor (&UdpEchoClient::m_peerPort),
62  MakeUintegerChecker<uint16_t> ())
63  .AddAttribute ("PacketSize", "Size of echo data in outbound packets",
64  UintegerValue (100),
65  MakeUintegerAccessor (&UdpEchoClient::SetDataSize,
67  MakeUintegerChecker<uint32_t> ())
68  .AddTraceSource ("Tx", "A new packet is created and is sent",
70  ;
71  return tid;
72 }
73 
75 {
77  m_sent = 0;
78  m_socket = 0;
79  m_sendEvent = EventId ();
80  m_data = 0;
81  m_dataSize = 0;
82 }
83 
85 {
87  m_socket = 0;
88 
89  delete [] m_data;
90  m_data = 0;
91  m_dataSize = 0;
92 }
93 
94 void
96 {
97  m_peerAddress = ip;
98  m_peerPort = port;
99 }
100 
101 void
103 {
104  m_peerAddress = Address (ip);
105  m_peerPort = port;
106 }
107 
108 void
110 {
111  m_peerAddress = Address (ip);
112  m_peerPort = port;
113 }
114 
115 void
117 {
120 }
121 
122 void
124 {
126 
127  if (m_socket == 0)
128  {
129  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
132  {
133  m_socket->Bind();
135  }
136  else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
137  {
138  m_socket->Bind6();
140  }
141  }
142 
144 
145  ScheduleTransmit (Seconds (0.));
146 }
147 
148 void
150 {
152 
153  if (m_socket != 0)
154  {
155  m_socket->Close ();
157  m_socket = 0;
158  }
159 
161 }
162 
163 void
164 UdpEchoClient::SetDataSize (uint32_t dataSize)
165 {
166  NS_LOG_FUNCTION (dataSize);
167 
168  //
169  // If the client is setting the echo packet data size this way, we infer
170  // that she doesn't care about the contents of the packet at all, so
171  // neither will we.
172  //
173  delete [] m_data;
174  m_data = 0;
175  m_dataSize = 0;
176  m_size = dataSize;
177 }
178 
179 uint32_t
181 {
183  return m_size;
184 }
185 
186 void
187 UdpEchoClient::SetFill (std::string fill)
188 {
189  NS_LOG_FUNCTION (fill);
190 
191  uint32_t dataSize = fill.size () + 1;
192 
193  if (dataSize != m_dataSize)
194  {
195  delete [] m_data;
196  m_data = new uint8_t [dataSize];
197  m_dataSize = dataSize;
198  }
199 
200  memcpy (m_data, fill.c_str (), dataSize);
201 
202  //
203  // Overwrite packet size attribute.
204  //
205  m_size = dataSize;
206 }
207 
208 void
209 UdpEchoClient::SetFill (uint8_t fill, uint32_t dataSize)
210 {
211  if (dataSize != m_dataSize)
212  {
213  delete [] m_data;
214  m_data = new uint8_t [dataSize];
215  m_dataSize = dataSize;
216  }
217 
218  memset (m_data, fill, dataSize);
219 
220  //
221  // Overwrite packet size attribute.
222  //
223  m_size = dataSize;
224 }
225 
226 void
227 UdpEchoClient::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
228 {
229  if (dataSize != m_dataSize)
230  {
231  delete [] m_data;
232  m_data = new uint8_t [dataSize];
233  m_dataSize = dataSize;
234  }
235 
236  if (fillSize >= dataSize)
237  {
238  memcpy (m_data, fill, dataSize);
239  m_size = dataSize;
240  return;
241  }
242 
243  //
244  // Do all but the final fill.
245  //
246  uint32_t filled = 0;
247  while (filled + fillSize < dataSize)
248  {
249  memcpy (&m_data[filled], fill, fillSize);
250  filled += fillSize;
251  }
252 
253  //
254  // Last fill may be partial
255  //
256  memcpy (&m_data[filled], fill, dataSize - filled);
257 
258  //
259  // Overwrite packet size attribute.
260  //
261  m_size = dataSize;
262 }
263 
264 void
266 {
269 }
270 
271 void
273 {
275 
277 
278  Ptr<Packet> p;
279  if (m_dataSize)
280  {
281  //
282  // If m_dataSize is non-zero, we have a data buffer of the same size that we
283  // are expected to copy and send. This state of affairs is created if one of
284  // the Fill functions is called. In this case, m_size must have been set
285  // to agree with m_dataSize
286  //
287  NS_ASSERT_MSG (m_dataSize == m_size, "UdpEchoClient::Send(): m_size and m_dataSize inconsistent");
288  NS_ASSERT_MSG (m_data, "UdpEchoClient::Send(): m_dataSize but no m_data");
289  p = Create<Packet> (m_data, m_dataSize);
290  }
291  else
292  {
293  //
294  // If m_dataSize is zero, the client has indicated that she doesn't care
295  // about the data itself either by specifying the data size by setting
296  // the corresponding atribute or by not calling a SetFill function. In
297  // this case, we don't worry about it either. But we do allow m_size
298  // to have a value different from the (zero) m_dataSize.
299  //
300  p = Create<Packet> (m_size);
301  }
302  // call to the trace sinks before the packet is actually sent,
303  // so that tags added to the packet can be sent as well
304  m_txTrace (p);
305  m_socket->Send (p);
306 
307  ++m_sent;
308 
310  {
311  NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds () << "s client sent " << m_size << " bytes to " <<
313  }
315  {
316  NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds () << "s client sent " << m_size << " bytes to " <<
318  }
319 
320  if (m_sent < m_count)
321  {
323  }
324 }
325 
326 void
328 {
329  NS_LOG_FUNCTION (this << socket);
330  Ptr<Packet> packet;
331  Address from;
332  while ((packet = socket->RecvFrom (from)))
333  {
335  {
336  NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds () << "s client received " << packet->GetSize () << " bytes from " <<
337  InetSocketAddress::ConvertFrom (from).GetIpv4 () << " port " <<
339  }
340  else if (Inet6SocketAddress::IsMatchingType (from))
341  {
342  NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds () << "s client received " << packet->GetSize () << " bytes from " <<
343  Inet6SocketAddress::ConvertFrom (from).GetIpv6 () << " port " <<
345  }
346  }
347 }
348 
349 } // Namespace ns3