src/applications/onoff-application.cc
changeset 524 082ffdd8fbd7
parent 519 b045a3ab4595
child 543 a730800a31d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/onoff-application.cc	Fri May 04 15:04:07 2007 +0200
@@ -0,0 +1,277 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: George F. Riley<riley@ece.gatech.edu>
+//
+
+// ns3 - On/Off Data Source Application class
+// George F. Riley, Georgia Tech, Spring 2007
+// Adapted from ApplicationOnOff in GTNetS.
+
+#include "ns3/ipv4-address.h"
+#include "ns3/node.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+#include "ns3/random-variable.h"
+#include "ns3/socket.h"
+#include "ns3/simulator.h"
+#include "ns3/i-udp.h"
+#include "onoff-application.h"
+
+using namespace std;
+
+namespace ns3 {
+
+// Defaults for rate/size
+DataRate OnOffApplication::g_defaultRate = DataRate(500000);
+uint32_t OnOffApplication::g_defaultSize = 512;
+
+// Constructors
+
+  OnOffApplication::OnOffApplication(Node * n, 
+                                     const Ipv4Address  rip,   // Remote IP addr
+                                     uint16_t       rport, // Remote port
+                                     const  RandomVariable& ontime,
+                                     const  RandomVariable& offtime,
+                                     DataRate  rate,
+                                     uint32_t size)
+    :  Application(n), 
+      m_socket(0),      // Socket allocated on Start
+      m_peerIP(rip),
+      m_peerPort(rport),
+      m_connected(false),
+      m_onTime(ontime.Copy()),
+      m_offTime(offtime.Copy()),
+      m_cbrRate(rate),
+      m_pktSize(size), 
+      m_residualBits(0),
+      m_lastStartTime((HighPrecision)0),
+      m_maxBytes(0xffffffff),
+      m_totBytes(0),
+      m_startStopScheduled(false),
+      m_sendScheduled(false)
+{
+}
+
+OnOffApplication::OnOffApplication(Node * n, const OnOffApplication& c)
+  : Application(n), 
+    m_socket(0),
+    m_peerIP(c.m_peerIP),
+    m_peerPort(c.m_peerPort),
+    m_connected(c.m_connected),
+    m_onTime(c.m_onTime->Copy()),
+    m_offTime(c.m_offTime->Copy()),
+    m_cbrRate(c.m_cbrRate),
+    m_pktSize(c.m_pktSize),
+    m_residualBits(c.m_residualBits),
+    m_lastStartTime(c.m_lastStartTime),
+    m_maxBytes(c.m_maxBytes),
+    m_totBytes(c.m_totBytes),
+    m_startStopScheduled(false),
+    m_sendScheduled(false)
+{
+}
+
+OnOffApplication::~OnOffApplication()
+{}
+
+void
+OnOffApplication::DoDispose (void)
+{
+  if (m_socket != 0)
+    {
+      m_socket->Unref ();
+      m_socket = 0;
+    }
+  delete m_onTime;
+  delete m_offTime;
+
+  m_onTime = 0;
+  m_offTime = 0;
+
+  // chain up
+  Application::DoDispose ();
+}
+
+#ifdef REMOVE_THIS
+// Handler Methods
+void OnOffApplication::Handle(Event* e, Time_t t)
+{
+  AppOOEvent* ev = (AppOOEvent*)e;
+  switch (ev->event) {
+    case AppOOEvent::SEND_PKT :
+      {
+        SendPkt(false);         // Send the packet
+        return;
+      }
+    case AppOOEvent::START_GEN :
+      {
+        DEBUG0((cout << "StartGen at " << Simulator::Now() << endl));
+        lastStartTime = Simulator::Now();
+        ScheduleNextTx();
+        Time_t onInterval = onTime->Value();
+        pendingOO->event = AppOOEvent::STOP_GEN;
+         // Schedule the stop event
+        Simulator::Schedule(pendingOO, onInterval, this);
+        return;
+      }
+    case AppOOEvent::STOP_GEN :
+      {
+        DEBUG0((cout << "StopGen at " << Simulator::Now() << endl));
+        if (totBytes < maxBytes)
+          { // Only schedule if not execeeded maxBytes
+            Time_t offInterval = offTime->Value();
+            pendingOO->event = AppOOEvent::START_GEN;
+            // Schedule the start event
+            Simulator::Schedule(pendingOO, offInterval, this);
+          }
+        if (pendingEvent)
+          {
+            // Calculate residual bits since last packet sent
+            residualBits += (uint32_t)(cbrRate*(Simulator::Now()-lastStartTime));
+            Simulator::Cancel(pendingEvent);
+            delete pendingEvent;
+            pendingEvent = 0;
+          }
+        return;
+      }
+  }
+  Application::Handle(e, t);  // May be application event
+}
+#endif
+
+// Application Methods
+void OnOffApplication::StartApplication()    // Called at time specified by Start
+{
+  // Create the socket if not already
+  if (!m_socket)
+    { // Create the socket using the specified layer 4 protocol
+#ifdef NOTYET
+      m_socket = PeekNode()->GetKernel()->CreateGenericSocket(*m_l4Proto);
+      m_socket->Bind();  // Choose any available port local port
+      m_socket->Connect(*m_peerIP, m_peerPort,
+                        MakeCallback(&OnOffApplication::ConnectionSucceeded,
+                                     this),
+                        MakeCallback(&OnOffApplication::ConnectionFailed,
+                                     this));
+#endif
+      
+      IUdp *udp = PeekNode ()->QueryInterface<IUdp> (IUdp::iid);
+      m_socket = udp->CreateSocket ();
+      udp->Unref ();
+      m_socket->Connect (m_peerIP, m_peerPort);
+    }
+  StopApplication();                         // Insure no pending event
+  // If we are not yet connected, there is nothing to do here
+  // The ConnectionComplete upcall will start timers at that time
+  //if (!m_connected) return;
+  ScheduleStartEvent();
+}
+
+void OnOffApplication::StopApplication()     // Called at time specified by Stop
+{
+  if (m_startStopScheduled)
+    { // Cancel the startStop event
+      Simulator::Cancel(m_startStopEvent);
+      m_startStopScheduled = false;
+    }
+  if (m_sendScheduled)
+    { // Cancel the pending send packet event
+      Simulator::Cancel(m_sendEvent);
+      m_sendScheduled = false;
+      // Calculate residual bits since last packet sent
+      Time delta(Simulator::Now() - m_lastStartTime);
+      m_residualBits += (uint32_t)(m_cbrRate.GetBitRate() * delta.GetSeconds());
+    }
+}
+
+OnOffApplication* OnOffApplication::Copy() const
+{
+  return new OnOffApplication(*this);
+}
+
+// Event handlers
+void OnOffApplication::StartSending()
+{
+  m_startStopScheduled = true;
+  ScheduleNextTx();  // Schedule the send packet event
+}
+
+void OnOffApplication::StopSending()
+{
+  m_startStopScheduled = true;
+  if (m_sendScheduled) Simulator::Cancel(m_sendEvent);
+}
+
+// Private helpers
+void OnOffApplication::ScheduleNextTx()
+{
+  if (m_totBytes < m_maxBytes)
+    {
+      uint32_t bits = m_pktSize * 8 - m_residualBits;
+      Time nextTime(Seconds (bits / 
+        static_cast<double>(m_cbrRate.GetBitRate()))); // Time till next packet
+      m_sendScheduled = true;
+      m_sendEvent = Simulator::Schedule(nextTime, &OnOffApplication::SendPacket, this);
+    }
+  else
+    { // All done, cancel any pending events
+      StopApplication();
+    }
+}
+
+void OnOffApplication::ScheduleStartEvent()
+{  // Schedules the event to start sending data (switch to the "On" state)
+  Time offInterval = Seconds(m_offTime->GetValue());
+  m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
+  m_startStopScheduled = true;
+}
+
+void OnOffApplication::ScheduleStopEvent()
+{  // Schedules the event to stop sending data (switch to "Off" state)
+  Time onInterval = Seconds(m_onTime->GetValue());
+  Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
+  m_startStopScheduled = true;
+}
+
+  
+void OnOffApplication::SendPacket()
+{
+  NS_ASSERT (m_sendScheduled);
+  m_sendScheduled = false;
+  m_socket->Send(0, m_pktSize);
+#ifdef NOTYET
+  m_socket->Send(0, m_pktSize); // Send the packet
+#endif
+  m_totBytes += m_pktSize;
+  m_lastStartTime = Simulator::Now();
+  m_residualBits = 0;
+  ScheduleNextTx();
+}
+
+void OnOffApplication::ConnectionSucceeded(Socket*)
+{
+  m_connected = true;
+  ScheduleStartEvent();
+}
+  
+void OnOffApplication::ConnectionFailed(Socket*)
+{
+  cout << "OnOffApplication, Connection Failed" << endl;
+}
+
+} // Namespace ns3