src/applications/v4ping/v4ping.cc
changeset 3821 9ea825f066a2
child 3932 76fabfcfd757
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/v4ping/v4ping.cc	Wed Oct 29 11:19:01 2008 -0700
@@ -0,0 +1,155 @@
+#include "v4ping.h"
+#include "ns3/icmpv4.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/socket.h"
+#include "ns3/uinteger.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/packet.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("V4Ping");
+NS_OBJECT_ENSURE_REGISTERED (V4Ping);
+
+TypeId 
+V4Ping::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::V4Ping")
+    .SetParent<Application> ()
+    .AddConstructor<V4Ping> ()
+    .AddAttribute ("Remote", 
+		   "The address of the machine we want to ping.",
+		   Ipv4AddressValue (),
+		   MakeIpv4AddressAccessor (&V4Ping::m_remote),
+		   MakeIpv4AddressChecker ())
+    .AddTraceSource ("Rtt",
+		     "The rtt calculated by the ping.",
+		     MakeTraceSourceAccessor (&V4Ping::m_traceRtt));
+    ;
+  return tid;
+}
+
+V4Ping::V4Ping ()
+  : m_socket (0),
+    m_seq (0)
+{}
+V4Ping::~V4Ping ()
+{}
+
+void
+V4Ping::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_socket = 0;
+  Application::DoDispose ();
+}
+
+uint32_t
+V4Ping::GetApplicationId (void) const
+{
+  Ptr<Node> node = GetNode ();
+  for (uint32_t i = 0; i < node->GetNApplications (); ++i)
+    {
+      if (node->GetApplication (i) == this)
+	{
+	  return i;
+	}
+    }
+  NS_ASSERT_MSG (false, "forgot to add application to node");
+  return 0; // quiet compiler
+}
+
+void
+V4Ping::Receive (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this << socket);
+  while (m_socket->GetRxAvailable () > 0)
+    {
+      Address from;
+      Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
+      NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
+      NS_ASSERT (InetSocketAddress::IsMatchingType (from));
+      InetSocketAddress realFrom = InetSocketAddress::ConvertFrom (from);
+      NS_ASSERT (realFrom.GetPort () == 1); // protocol should be icmp.
+      Ipv4Header ipv4;
+      p->RemoveHeader (ipv4);
+      NS_ASSERT (ipv4.GetProtocol () == 1); // protocol should be icmp.
+      Icmpv4Header icmp;
+      p->RemoveHeader (icmp);
+      if (icmp.GetType () == Icmpv4Header::ECHO_REPLY)
+	{
+	  Icmpv4Echo echo;
+	  p->RemoveHeader (echo);
+	  if (echo.GetSequenceNumber () == (m_seq - 1) &&
+	      echo.GetIdentifier () == 0)
+	    {
+	      Ptr<const Packet> data = echo.GetData ();
+	      if (data->GetSize () == 16)
+		{
+		  uint32_t *buf = (uint32_t *)data->PeekData ();
+		  if (buf[0] == GetNode ()->GetId () &&
+		      buf[1] == GetApplicationId ())
+		    {
+		      int64_t ts = buf[3];
+		      ts <<= 32;
+		      ts |= buf[2];
+		      Time sendTime = TimeStep (ts);
+		      NS_ASSERT (Simulator::Now () > sendTime);
+		      Time delta = Simulator::Now () - sendTime;
+		      m_traceRtt (delta);
+		    }
+		}
+	    }
+	}
+    }
+}
+
+void 
+V4Ping::StartApplication (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
+  NS_ASSERT (m_socket != 0);
+  m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp
+  m_socket->SetRecvCallback (MakeCallback (&V4Ping::Receive, this));
+  InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
+  int status;
+  status = m_socket->Bind (src);
+  NS_ASSERT (status != -1);
+  InetSocketAddress dst = InetSocketAddress (m_remote, 0);
+  status = m_socket->Connect (dst);
+  NS_ASSERT (status != -1);
+  Ptr<Packet> p = Create<Packet> ();
+  Icmpv4Echo echo;
+  echo.SetSequenceNumber (m_seq);
+  m_seq++;
+  echo.SetIdentifier (0);
+  uint32_t data[4];
+  data[0] = GetNode ()->GetId ();
+  data[1] = GetApplicationId ();
+  int64_t now = Simulator::Now ().GetTimeStep ();
+  data[2] = now & 0xffffffff;
+  now >>= 32;
+  data[3] = now & 0xffffffff;
+  Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) &data, 16);
+  echo.SetData (dataPacket);
+  p->AddHeader (echo);
+  Icmpv4Header header;
+  header.SetType (Icmpv4Header::ECHO);
+  header.SetCode (0);
+  p->AddHeader (header);
+  m_socket->Send (p, 0);
+  
+}
+void 
+V4Ping::StopApplication (void)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+} // namespace ns3