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
craigdo@1496
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
craigdo@1496
     2
/*
craigdo@1496
     3
 * Copyright 2007 University of Washington
craigdo@1496
     4
 * 
craigdo@1496
     5
 * This program is free software; you can redistribute it and/or modify
craigdo@1496
     6
 * it under the terms of the GNU General Public License version 2 as
craigdo@1496
     7
 * published by the Free Software Foundation;
craigdo@1496
     8
 *
craigdo@1496
     9
 * This program is distributed in the hope that it will be useful,
craigdo@1496
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
craigdo@1496
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
craigdo@1496
    12
 * GNU General Public License for more details.
craigdo@1496
    13
 *
craigdo@1496
    14
 * You should have received a copy of the GNU General Public License
craigdo@1496
    15
 * along with this program; if not, write to the Free Software
craigdo@1496
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
craigdo@1496
    17
 */
craigdo@1504
    18
#include "ns3/log.h"
craigdo@1496
    19
#include "ns3/ipv4-address.h"
craigdo@1496
    20
#include "ns3/nstime.h"
craigdo@1496
    21
#include "ns3/inet-socket-address.h"
craigdo@1496
    22
#include "ns3/socket.h"
craigdo@1496
    23
#include "ns3/simulator.h"
craigdo@1496
    24
#include "ns3/socket-factory.h"
craigdo@1496
    25
#include "ns3/packet.h"
mathieu@2494
    26
#include "ns3/uinteger.h"
wilsonwk@4710
    27
#include "ns3/trace-source-accessor.h"
craigdo@1496
    28
#include "udp-echo-client.h"
craigdo@1496
    29
craigdo@1496
    30
namespace ns3 {
craigdo@1496
    31
craigdo@1504
    32
NS_LOG_COMPONENT_DEFINE ("UdpEchoClientApplication");
mathieu@2494
    33
NS_OBJECT_ENSURE_REGISTERED (UdpEchoClient);
craigdo@1496
    34
mathieu@2494
    35
TypeId
mathieu@2494
    36
UdpEchoClient::GetTypeId (void)
mathieu@2494
    37
{
mathieu@2602
    38
  static TypeId tid = TypeId ("ns3::UdpEchoClient")
mathieu@2494
    39
    .SetParent<Application> ()
mathieu@2494
    40
    .AddConstructor<UdpEchoClient> ()
craigdo@3257
    41
    .AddAttribute ("MaxPackets", 
craigdo@3257
    42
                   "The maximum number of packets the application will send",
mathieu@2965
    43
                   UintegerValue (100),
mathieu@2494
    44
                   MakeUintegerAccessor (&UdpEchoClient::m_count),
mathieu@2494
    45
                   MakeUintegerChecker<uint32_t> ())
craigdo@3257
    46
    .AddAttribute ("Interval", 
craigdo@3257
    47
                   "The time to wait between packets",
mathieu@2965
    48
                   TimeValue (Seconds (1.0)),
mathieu@2494
    49
                   MakeTimeAccessor (&UdpEchoClient::m_interval),
mathieu@2494
    50
                   MakeTimeChecker ())
craigdo@3382
    51
    .AddAttribute ("RemoteAddress", 
craigdo@3382
    52
                   "The destination Ipv4Address of the outbound packets",
mathieu@2965
    53
                   Ipv4AddressValue (),
mathieu@2494
    54
                   MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
mathieu@2494
    55
                   MakeIpv4AddressChecker ())
craigdo@3257
    56
    .AddAttribute ("RemotePort", 
craigdo@3257
    57
                   "The destination port of the outbound packets",
mathieu@2965
    58
                   UintegerValue (0),
mathieu@2494
    59
                   MakeUintegerAccessor (&UdpEchoClient::m_peerPort),
mathieu@2494
    60
                   MakeUintegerChecker<uint16_t> ())
craigdo@4577
    61
    .AddAttribute ("PacketSize", "Size of echo data in outbound packets",
mathieu@2965
    62
                   UintegerValue (100),
craigdo@4577
    63
                   MakeUintegerAccessor (&UdpEchoClient::SetDataSize,
craigdo@4577
    64
                                         &UdpEchoClient::GetDataSize),
mathieu@2494
    65
                   MakeUintegerChecker<uint32_t> ())
wilsonwk@4710
    66
    .AddTraceSource ("Tx", "A new packet is created and is sent",
wilsonwk@4710
    67
                     MakeTraceSourceAccessor (&UdpEchoClient::m_txTrace))
mathieu@2494
    68
    ;
mathieu@2494
    69
  return tid;
mathieu@2494
    70
}
mathieu@2494
    71
mathieu@2494
    72
UdpEchoClient::UdpEchoClient ()
craigdo@1496
    73
{
mathieu@2983
    74
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2494
    75
  m_sent = 0;
mathieu@2494
    76
  m_socket = 0;
mathieu@2494
    77
  m_sendEvent = EventId ();
craigdo@4577
    78
  m_data = 0;
craigdo@4577
    79
  m_dataSize = 0;
craigdo@1496
    80
}
craigdo@1496
    81
craigdo@1496
    82
UdpEchoClient::~UdpEchoClient()
craigdo@1496
    83
{
mathieu@2983
    84
  NS_LOG_FUNCTION_NOARGS ();
craigdo@4410
    85
  m_socket = 0;
craigdo@4577
    86
craigdo@4577
    87
  delete [] m_data;
craigdo@4577
    88
  m_data = 0;
craigdo@4577
    89
  m_dataSize = 0;
craigdo@1496
    90
}
craigdo@1496
    91
mathieu@2766
    92
void 
mathieu@2766
    93
UdpEchoClient::SetRemote (Ipv4Address ip, uint16_t port)
mathieu@2766
    94
{
mathieu@2766
    95
  m_peerAddress = ip;
mathieu@2766
    96
  m_peerPort = port;
mathieu@2766
    97
}
mathieu@2766
    98
craigdo@1496
    99
void
craigdo@1496
   100
UdpEchoClient::DoDispose (void)
craigdo@1496
   101
{
mathieu@2983
   102
  NS_LOG_FUNCTION_NOARGS ();
craigdo@1496
   103
  Application::DoDispose ();
craigdo@1496
   104
}
craigdo@1496
   105
craigdo@1496
   106
void 
craigdo@1496
   107
UdpEchoClient::StartApplication (void)
craigdo@1496
   108
{
mathieu@2983
   109
  NS_LOG_FUNCTION_NOARGS ();
craigdo@1496
   110
craigdo@3025
   111
  if (m_socket == 0)
craigdo@1496
   112
    {
tomh@3125
   113
      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
tomh@3116
   114
      m_socket = Socket::CreateSocket (GetNode(), tid);
craigdo@1496
   115
      m_socket->Bind ();
mathieu@2494
   116
      m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
craigdo@1496
   117
    }
craigdo@1496
   118
tomh@3102
   119
  m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::HandleRead, this));
craigdo@1500
   120
craigdo@1496
   121
  ScheduleTransmit (Seconds(0.));
craigdo@1496
   122
}
craigdo@1496
   123
craigdo@1496
   124
void 
craigdo@1496
   125
UdpEchoClient::StopApplication ()
craigdo@1496
   126
{
mathieu@2983
   127
  NS_LOG_FUNCTION_NOARGS ();
craigdo@1500
   128
craigdo@3025
   129
  if (m_socket != 0) 
craigdo@1500
   130
    {
craigdo@4410
   131
      m_socket->Close ();
tomh@3102
   132
      m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
craigdo@1500
   133
    }
craigdo@1500
   134
craigdo@1500
   135
  Simulator::Cancel(m_sendEvent);
craigdo@1496
   136
}
craigdo@1496
   137
craigdo@1496
   138
void 
craigdo@4577
   139
UdpEchoClient::SetDataSize (uint32_t dataSize)
craigdo@4577
   140
{
craigdo@4577
   141
  NS_LOG_FUNCTION (dataSize);
craigdo@4577
   142
craigdo@4577
   143
  //
craigdo@4577
   144
  // If the client is setting the echo packet data size this way, we infer
craigdo@4577
   145
  // that she doesn't care about the contents of the packet at all, so 
craigdo@4577
   146
  // neither will we.
craigdo@4577
   147
  //
craigdo@4577
   148
  delete [] m_data;
craigdo@4577
   149
  m_data = 0;
craigdo@4577
   150
  m_dataSize = 0;
craigdo@4577
   151
  m_size = dataSize;
craigdo@4577
   152
}
craigdo@4577
   153
craigdo@4577
   154
uint32_t 
craigdo@4577
   155
UdpEchoClient::GetDataSize (void) const
craigdo@4577
   156
{
craigdo@4577
   157
  NS_LOG_FUNCTION_NOARGS ();
craigdo@4577
   158
  return m_size;
craigdo@4577
   159
}
craigdo@4577
   160
craigdo@4577
   161
void 
craigdo@4577
   162
UdpEchoClient::SetFill (std::string fill)
craigdo@4577
   163
{
craigdo@4577
   164
  NS_LOG_FUNCTION (fill);
craigdo@4577
   165
craigdo@4577
   166
  uint32_t dataSize = fill.size () + 1;
craigdo@4577
   167
craigdo@4577
   168
  if (dataSize != m_dataSize)
craigdo@4577
   169
    {
craigdo@4577
   170
      delete [] m_data;
craigdo@4577
   171
      m_data = new uint8_t [dataSize];
craigdo@4577
   172
      m_dataSize = dataSize;
craigdo@4577
   173
    }
craigdo@4577
   174
craigdo@4577
   175
  memcpy (m_data, fill.c_str (), dataSize);
craigdo@4577
   176
craigdo@4577
   177
  //
craigdo@4577
   178
  // Overwrite packet size attribute.
craigdo@4577
   179
  //
craigdo@4577
   180
  m_size = dataSize;
craigdo@4577
   181
}
craigdo@4577
   182
craigdo@4577
   183
void 
craigdo@4577
   184
UdpEchoClient::SetFill (uint8_t fill, uint32_t dataSize)
craigdo@4577
   185
{
craigdo@4577
   186
  if (dataSize != m_dataSize)
craigdo@4577
   187
    {
craigdo@4577
   188
      delete [] m_data;
craigdo@4577
   189
      m_data = new uint8_t [dataSize];
craigdo@4577
   190
      m_dataSize = dataSize;
craigdo@4577
   191
    }
craigdo@4577
   192
craigdo@4577
   193
  memset (m_data, fill, dataSize);
craigdo@4577
   194
craigdo@4577
   195
  //
craigdo@4577
   196
  // Overwrite packet size attribute.
craigdo@4577
   197
  //
craigdo@4577
   198
  m_size = dataSize;
craigdo@4577
   199
}
craigdo@4577
   200
craigdo@4577
   201
void 
craigdo@4577
   202
UdpEchoClient::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
craigdo@4577
   203
{
craigdo@4577
   204
  if (dataSize != m_dataSize)
craigdo@4577
   205
    {
craigdo@4577
   206
      delete [] m_data;
craigdo@4577
   207
      m_data = new uint8_t [dataSize];
craigdo@4577
   208
      m_dataSize = dataSize;
craigdo@4577
   209
    }
craigdo@4577
   210
craigdo@4577
   211
  if (fillSize >= dataSize)
craigdo@4577
   212
    {
craigdo@4577
   213
      memcpy (m_data, fill, dataSize);
craigdo@4577
   214
      return;
craigdo@4577
   215
    }
craigdo@4577
   216
craigdo@4577
   217
  //
craigdo@4577
   218
  // Do all but the final fill.
craigdo@4577
   219
  //
craigdo@4577
   220
  uint32_t filled = 0;
craigdo@4577
   221
  while (filled + fillSize < dataSize)
craigdo@4577
   222
    {
craigdo@4577
   223
      memcpy (&m_data[filled], fill, fillSize);
craigdo@4577
   224
      filled += fillSize;
craigdo@4577
   225
    }
craigdo@4577
   226
craigdo@4577
   227
  //
craigdo@4577
   228
  // Last fill may be partial
craigdo@4577
   229
  //
craigdo@4577
   230
  memcpy(&m_data[filled], fill, dataSize - filled);
craigdo@4577
   231
craigdo@4577
   232
  //
craigdo@4577
   233
  // Overwrite packet size attribute.
craigdo@4577
   234
  //
craigdo@4577
   235
  m_size = dataSize;
craigdo@4577
   236
}
craigdo@4577
   237
craigdo@4577
   238
void 
craigdo@1496
   239
UdpEchoClient::ScheduleTransmit (Time dt)
craigdo@1496
   240
{
mathieu@2983
   241
  NS_LOG_FUNCTION_NOARGS ();
craigdo@1496
   242
  m_sendEvent = Simulator::Schedule(dt, &UdpEchoClient::Send, this);
craigdo@1496
   243
}
craigdo@1496
   244
craigdo@1496
   245
void 
craigdo@1496
   246
UdpEchoClient::Send (void)
craigdo@1496
   247
{
mathieu@2983
   248
  NS_LOG_FUNCTION_NOARGS ();
craigdo@1496
   249
craigdo@1496
   250
  NS_ASSERT (m_sendEvent.IsExpired ());
craigdo@1496
   251
wilsonwk@4710
   252
  Ptr<Packet> p;
craigdo@4577
   253
  if (m_dataSize)
craigdo@4577
   254
    {
craigdo@4577
   255
      //
craigdo@4577
   256
      // If m_dataSize is non-zero, we have a data buffer of the same size that we
craigdo@4577
   257
      // are expected to copy and send.  This state of affairs is created if one of
craigdo@4577
   258
      // the Fill functions is called.  In this case, m_size must have been set
craigdo@4577
   259
      // to agree with m_dataSize
craigdo@4577
   260
      //
craigdo@4577
   261
      NS_ASSERT_MSG (m_dataSize == m_size, "UdpEchoClient::Send(): m_size and m_dataSize inconsistent");
craigdo@4577
   262
      NS_ASSERT_MSG (m_data, "UdpEchoClient::Send(): m_dataSize but no m_data");
wilsonwk@4710
   263
      p = Create<Packet> (m_data, m_dataSize);
craigdo@4577
   264
    }
craigdo@4577
   265
  else
craigdo@4577
   266
    {
craigdo@4577
   267
      //
craigdo@4577
   268
      // If m_dataSize is zero, the client has indicated that she doesn't care 
craigdo@4577
   269
      // about the data itself either by specifying the data size by setting
craigdo@4577
   270
      // the corresponding atribute or by not calling a SetFill function.  In 
craigdo@4577
   271
      // this case, we don't worry about it either.  But we do allow m_size
craigdo@4577
   272
      // to have a value different from the (zero) m_dataSize.
craigdo@4577
   273
      //
wilsonwk@4710
   274
      p = Create<Packet> (m_size);
craigdo@4577
   275
    }
wilsonwk@4710
   276
  // call to the trace sinks before the packet is actually sent,
wilsonwk@4710
   277
  // so that tags added to the packet can be sent as well
wilsonwk@4710
   278
  m_txTrace (p);
wilsonwk@4710
   279
  m_socket->Send (p);
craigdo@4577
   280
craigdo@1496
   281
  ++m_sent;
craigdo@1496
   282
mathieu@2494
   283
  NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_peerAddress);
craigdo@1499
   284
craigdo@1496
   285
  if (m_sent < m_count) 
craigdo@1496
   286
    {
craigdo@1496
   287
      ScheduleTransmit (m_interval);
craigdo@1496
   288
    }
craigdo@1496
   289
}
craigdo@1496
   290
craigdo@1500
   291
void
tomh@3098
   292
UdpEchoClient::HandleRead (Ptr<Socket> socket)
craigdo@1500
   293
{
tomh@3098
   294
  NS_LOG_FUNCTION (this << socket);
tomh@3098
   295
  Ptr<Packet> packet;
tomh@3271
   296
  Address from;
tomh@3271
   297
  while (packet = socket->RecvFrom (from))
craigdo@1500
   298
    {
tomh@3098
   299
      if (InetSocketAddress::IsMatchingType (from))
tomh@3098
   300
        {
tomh@3098
   301
          InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
tomh@3098
   302
          NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
tomh@3098
   303
            address.GetIpv4());
tomh@3098
   304
        }
craigdo@1500
   305
    }
craigdo@1500
   306
}
craigdo@1500
   307
craigdo@1496
   308
} // Namespace ns3