1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright 2007 University of Washington
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;
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.
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
19 #include "ns3/ipv4-address.h"
20 #include "ns3/nstime.h"
21 #include "ns3/inet-socket-address.h"
22 #include "ns3/socket.h"
23 #include "ns3/simulator.h"
24 #include "ns3/socket-factory.h"
25 #include "ns3/packet.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/trace-source-accessor.h"
28 #include "udp-echo-client.h"
32 NS_LOG_COMPONENT_DEFINE ("UdpEchoClientApplication");
33 NS_OBJECT_ENSURE_REGISTERED (UdpEchoClient);
36 UdpEchoClient::GetTypeId (void)
38 static TypeId tid = TypeId ("ns3::UdpEchoClient")
39 .SetParent<Application> ()
40 .AddConstructor<UdpEchoClient> ()
41 .AddAttribute ("MaxPackets",
42 "The maximum number of packets the application will send",
44 MakeUintegerAccessor (&UdpEchoClient::m_count),
45 MakeUintegerChecker<uint32_t> ())
46 .AddAttribute ("Interval",
47 "The time to wait between packets",
48 TimeValue (Seconds (1.0)),
49 MakeTimeAccessor (&UdpEchoClient::m_interval),
51 .AddAttribute ("RemoteAddress",
52 "The destination Ipv4Address of the outbound packets",
54 MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
55 MakeIpv4AddressChecker ())
56 .AddAttribute ("RemotePort",
57 "The destination port of the outbound packets",
59 MakeUintegerAccessor (&UdpEchoClient::m_peerPort),
60 MakeUintegerChecker<uint16_t> ())
61 .AddAttribute ("PacketSize", "Size of echo data in outbound packets",
63 MakeUintegerAccessor (&UdpEchoClient::SetDataSize,
64 &UdpEchoClient::GetDataSize),
65 MakeUintegerChecker<uint32_t> ())
66 .AddTraceSource ("Tx", "A new packet is created and is sent",
67 MakeTraceSourceAccessor (&UdpEchoClient::m_txTrace))
72 UdpEchoClient::UdpEchoClient ()
74 NS_LOG_FUNCTION_NOARGS ();
77 m_sendEvent = EventId ();
82 UdpEchoClient::~UdpEchoClient()
84 NS_LOG_FUNCTION_NOARGS ();
93 UdpEchoClient::SetRemote (Ipv4Address ip, uint16_t port)
100 UdpEchoClient::DoDispose (void)
102 NS_LOG_FUNCTION_NOARGS ();
103 Application::DoDispose ();
107 UdpEchoClient::StartApplication (void)
109 NS_LOG_FUNCTION_NOARGS ();
113 TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
114 m_socket = Socket::CreateSocket (GetNode(), tid);
116 m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
119 m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::HandleRead, this));
121 ScheduleTransmit (Seconds(0.));
125 UdpEchoClient::StopApplication ()
127 NS_LOG_FUNCTION_NOARGS ();
132 m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
135 Simulator::Cancel(m_sendEvent);
139 UdpEchoClient::SetDataSize (uint32_t dataSize)
141 NS_LOG_FUNCTION (dataSize);
144 // If the client is setting the echo packet data size this way, we infer
145 // that she doesn't care about the contents of the packet at all, so
155 UdpEchoClient::GetDataSize (void) const
157 NS_LOG_FUNCTION_NOARGS ();
162 UdpEchoClient::SetFill (std::string fill)
164 NS_LOG_FUNCTION (fill);
166 uint32_t dataSize = fill.size () + 1;
168 if (dataSize != m_dataSize)
171 m_data = new uint8_t [dataSize];
172 m_dataSize = dataSize;
175 memcpy (m_data, fill.c_str (), dataSize);
178 // Overwrite packet size attribute.
184 UdpEchoClient::SetFill (uint8_t fill, uint32_t dataSize)
186 if (dataSize != m_dataSize)
189 m_data = new uint8_t [dataSize];
190 m_dataSize = dataSize;
193 memset (m_data, fill, dataSize);
196 // Overwrite packet size attribute.
202 UdpEchoClient::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
204 if (dataSize != m_dataSize)
207 m_data = new uint8_t [dataSize];
208 m_dataSize = dataSize;
211 if (fillSize >= dataSize)
213 memcpy (m_data, fill, dataSize);
218 // Do all but the final fill.
221 while (filled + fillSize < dataSize)
223 memcpy (&m_data[filled], fill, fillSize);
228 // Last fill may be partial
230 memcpy(&m_data[filled], fill, dataSize - filled);
233 // Overwrite packet size attribute.
239 UdpEchoClient::ScheduleTransmit (Time dt)
241 NS_LOG_FUNCTION_NOARGS ();
242 m_sendEvent = Simulator::Schedule(dt, &UdpEchoClient::Send, this);
246 UdpEchoClient::Send (void)
248 NS_LOG_FUNCTION_NOARGS ();
250 NS_ASSERT (m_sendEvent.IsExpired ());
256 // If m_dataSize is non-zero, we have a data buffer of the same size that we
257 // are expected to copy and send. This state of affairs is created if one of
258 // the Fill functions is called. In this case, m_size must have been set
259 // to agree with m_dataSize
261 NS_ASSERT_MSG (m_dataSize == m_size, "UdpEchoClient::Send(): m_size and m_dataSize inconsistent");
262 NS_ASSERT_MSG (m_data, "UdpEchoClient::Send(): m_dataSize but no m_data");
263 p = Create<Packet> (m_data, m_dataSize);
268 // If m_dataSize is zero, the client has indicated that she doesn't care
269 // about the data itself either by specifying the data size by setting
270 // the corresponding atribute or by not calling a SetFill function. In
271 // this case, we don't worry about it either. But we do allow m_size
272 // to have a value different from the (zero) m_dataSize.
274 p = Create<Packet> (m_size);
276 // call to the trace sinks before the packet is actually sent,
277 // so that tags added to the packet can be sent as well
283 NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_peerAddress);
285 if (m_sent < m_count)
287 ScheduleTransmit (m_interval);
292 UdpEchoClient::HandleRead (Ptr<Socket> socket)
294 NS_LOG_FUNCTION (this << socket);
297 while (packet = socket->RecvFrom (from))
299 if (InetSocketAddress::IsMatchingType (from))
301 InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
302 NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<