src/applications/udp-echo/udp-echo-client.cc
author Wilson Thong <wilsonwk@ee.cityu.edu.hk>
Thu Aug 13 09:47:53 2009 +0200 (2009-08-13)
changeset 4710 e56da5fd6697
parent 4577 84c133267507
child 5152 f14eff131d13
permissions -rw-r--r--
bug 638: add missing tx trace source
     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/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"
    29 
    30 namespace ns3 {
    31 
    32 NS_LOG_COMPONENT_DEFINE ("UdpEchoClientApplication");
    33 NS_OBJECT_ENSURE_REGISTERED (UdpEchoClient);
    34 
    35 TypeId
    36 UdpEchoClient::GetTypeId (void)
    37 {
    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",
    43                    UintegerValue (100),
    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),
    50                    MakeTimeChecker ())
    51     .AddAttribute ("RemoteAddress", 
    52                    "The destination Ipv4Address of the outbound packets",
    53                    Ipv4AddressValue (),
    54                    MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
    55                    MakeIpv4AddressChecker ())
    56     .AddAttribute ("RemotePort", 
    57                    "The destination port of the outbound packets",
    58                    UintegerValue (0),
    59                    MakeUintegerAccessor (&UdpEchoClient::m_peerPort),
    60                    MakeUintegerChecker<uint16_t> ())
    61     .AddAttribute ("PacketSize", "Size of echo data in outbound packets",
    62                    UintegerValue (100),
    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))
    68     ;
    69   return tid;
    70 }
    71 
    72 UdpEchoClient::UdpEchoClient ()
    73 {
    74   NS_LOG_FUNCTION_NOARGS ();
    75   m_sent = 0;
    76   m_socket = 0;
    77   m_sendEvent = EventId ();
    78   m_data = 0;
    79   m_dataSize = 0;
    80 }
    81 
    82 UdpEchoClient::~UdpEchoClient()
    83 {
    84   NS_LOG_FUNCTION_NOARGS ();
    85   m_socket = 0;
    86 
    87   delete [] m_data;
    88   m_data = 0;
    89   m_dataSize = 0;
    90 }
    91 
    92 void 
    93 UdpEchoClient::SetRemote (Ipv4Address ip, uint16_t port)
    94 {
    95   m_peerAddress = ip;
    96   m_peerPort = port;
    97 }
    98 
    99 void
   100 UdpEchoClient::DoDispose (void)
   101 {
   102   NS_LOG_FUNCTION_NOARGS ();
   103   Application::DoDispose ();
   104 }
   105 
   106 void 
   107 UdpEchoClient::StartApplication (void)
   108 {
   109   NS_LOG_FUNCTION_NOARGS ();
   110 
   111   if (m_socket == 0)
   112     {
   113       TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
   114       m_socket = Socket::CreateSocket (GetNode(), tid);
   115       m_socket->Bind ();
   116       m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
   117     }
   118 
   119   m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::HandleRead, this));
   120 
   121   ScheduleTransmit (Seconds(0.));
   122 }
   123 
   124 void 
   125 UdpEchoClient::StopApplication ()
   126 {
   127   NS_LOG_FUNCTION_NOARGS ();
   128 
   129   if (m_socket != 0) 
   130     {
   131       m_socket->Close ();
   132       m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
   133     }
   134 
   135   Simulator::Cancel(m_sendEvent);
   136 }
   137 
   138 void 
   139 UdpEchoClient::SetDataSize (uint32_t dataSize)
   140 {
   141   NS_LOG_FUNCTION (dataSize);
   142 
   143   //
   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 
   146   // neither will we.
   147   //
   148   delete [] m_data;
   149   m_data = 0;
   150   m_dataSize = 0;
   151   m_size = dataSize;
   152 }
   153 
   154 uint32_t 
   155 UdpEchoClient::GetDataSize (void) const
   156 {
   157   NS_LOG_FUNCTION_NOARGS ();
   158   return m_size;
   159 }
   160 
   161 void 
   162 UdpEchoClient::SetFill (std::string fill)
   163 {
   164   NS_LOG_FUNCTION (fill);
   165 
   166   uint32_t dataSize = fill.size () + 1;
   167 
   168   if (dataSize != m_dataSize)
   169     {
   170       delete [] m_data;
   171       m_data = new uint8_t [dataSize];
   172       m_dataSize = dataSize;
   173     }
   174 
   175   memcpy (m_data, fill.c_str (), dataSize);
   176 
   177   //
   178   // Overwrite packet size attribute.
   179   //
   180   m_size = dataSize;
   181 }
   182 
   183 void 
   184 UdpEchoClient::SetFill (uint8_t fill, uint32_t dataSize)
   185 {
   186   if (dataSize != m_dataSize)
   187     {
   188       delete [] m_data;
   189       m_data = new uint8_t [dataSize];
   190       m_dataSize = dataSize;
   191     }
   192 
   193   memset (m_data, fill, dataSize);
   194 
   195   //
   196   // Overwrite packet size attribute.
   197   //
   198   m_size = dataSize;
   199 }
   200 
   201 void 
   202 UdpEchoClient::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
   203 {
   204   if (dataSize != m_dataSize)
   205     {
   206       delete [] m_data;
   207       m_data = new uint8_t [dataSize];
   208       m_dataSize = dataSize;
   209     }
   210 
   211   if (fillSize >= dataSize)
   212     {
   213       memcpy (m_data, fill, dataSize);
   214       return;
   215     }
   216 
   217   //
   218   // Do all but the final fill.
   219   //
   220   uint32_t filled = 0;
   221   while (filled + fillSize < dataSize)
   222     {
   223       memcpy (&m_data[filled], fill, fillSize);
   224       filled += fillSize;
   225     }
   226 
   227   //
   228   // Last fill may be partial
   229   //
   230   memcpy(&m_data[filled], fill, dataSize - filled);
   231 
   232   //
   233   // Overwrite packet size attribute.
   234   //
   235   m_size = dataSize;
   236 }
   237 
   238 void 
   239 UdpEchoClient::ScheduleTransmit (Time dt)
   240 {
   241   NS_LOG_FUNCTION_NOARGS ();
   242   m_sendEvent = Simulator::Schedule(dt, &UdpEchoClient::Send, this);
   243 }
   244 
   245 void 
   246 UdpEchoClient::Send (void)
   247 {
   248   NS_LOG_FUNCTION_NOARGS ();
   249 
   250   NS_ASSERT (m_sendEvent.IsExpired ());
   251 
   252   Ptr<Packet> p;
   253   if (m_dataSize)
   254     {
   255       //
   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
   260       //
   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);
   264     }
   265   else
   266     {
   267       //
   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.
   273       //
   274       p = Create<Packet> (m_size);
   275     }
   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
   278   m_txTrace (p);
   279   m_socket->Send (p);
   280 
   281   ++m_sent;
   282 
   283   NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_peerAddress);
   284 
   285   if (m_sent < m_count) 
   286     {
   287       ScheduleTransmit (m_interval);
   288     }
   289 }
   290 
   291 void
   292 UdpEchoClient::HandleRead (Ptr<Socket> socket)
   293 {
   294   NS_LOG_FUNCTION (this << socket);
   295   Ptr<Packet> packet;
   296   Address from;
   297   while (packet = socket->RecvFrom (from))
   298     {
   299       if (InetSocketAddress::IsMatchingType (from))
   300         {
   301           InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
   302           NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
   303             address.GetIpv4());
   304         }
   305     }
   306 }
   307 
   308 } // Namespace ns3