/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * 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 * * Authors: Joe Kopena * * These applications are used in the WiFi Distance Test experiment, * described and implemented in test02.cc. That file should be in the * same place as this file. The applications have two very simple * jobs, they just generate and receive packets. We could use the * standard Application classes included in the NS-3 distribution. * These have been written just to change the behavior a little, and * provide more examples. * */ #include #include "ns3/core-module.h" #include "ns3/network-module.h" #include "ns3/network-module.h" #include "ns3/internet-stack-module.h" #include "ns3/stats-module.h" #include "wifi-example-apps.h" using namespace ns3; NS_LOG_COMPONENT_DEFINE ("WiFiDistanceApps"); TypeId Sender::GetTypeId(void) { static TypeId tid = TypeId ("Sender") .SetParent () .AddConstructor () .AddAttribute ("PacketSize", "The size of packets transmitted.", UintegerValue(64), MakeUintegerAccessor(&Sender::m_pktSize), MakeUintegerChecker(1)) .AddAttribute("Destination", "Target host address.", Ipv4AddressValue("255.255.255.255"), MakeIpv4AddressAccessor(&Sender::m_destAddr), MakeIpv4AddressChecker()) .AddAttribute("Port", "Destination app port.", UintegerValue(1603), MakeUintegerAccessor(&Sender::m_destPort), MakeUintegerChecker()) .AddAttribute("NumPackets", "Total number of packets to send.", UintegerValue(30), MakeUintegerAccessor(&Sender::m_numPkts), MakeUintegerChecker(1)) .AddAttribute ("Interval", "Delay between transmissions.", RandomVariableValue(ConstantVariable(0.5)), MakeRandomVariableAccessor(&Sender::m_interval), MakeRandomVariableChecker()) .AddTraceSource ("Tx", "A new packet is created and is sent", MakeTraceSourceAccessor (&Sender::m_txTrace)) ; return tid; } Sender::Sender() { NS_LOG_FUNCTION_NOARGS (); m_socket = 0; } Sender::~Sender() { NS_LOG_FUNCTION_NOARGS (); } void Sender::DoDispose (void) { NS_LOG_FUNCTION_NOARGS (); m_socket = 0; // chain up Application::DoDispose (); } void Sender::StartApplication() { NS_LOG_FUNCTION_NOARGS (); if (m_socket == 0) { Ptr socketFactory = GetNode()->GetObject (UdpSocketFactory::GetTypeId()); m_socket = socketFactory->CreateSocket (); m_socket->Bind (); } m_count = 0; Simulator::Cancel(m_sendEvent); m_sendEvent = Simulator::ScheduleNow(&Sender::SendPacket, this); // end Sender::StartApplication } void Sender::StopApplication() { NS_LOG_FUNCTION_NOARGS (); Simulator::Cancel(m_sendEvent); // end Sender::StopApplication } void Sender::SendPacket() { // NS_LOG_FUNCTION_NOARGS (); NS_LOG_INFO("Sending packet at " << Simulator::Now() << " to " << m_destAddr); Ptr packet = Create(m_pktSize); TimestampTag timestamp; timestamp.SetTimestamp(Simulator::Now()); packet->AddByteTag (timestamp); // Could connect the socket since the address never changes; using SendTo // here simply because all of the standard apps do not. m_socket->SendTo(packet, 0, InetSocketAddress(m_destAddr, m_destPort)); // Report the event to the trace. m_txTrace(packet); if (++m_count < m_numPkts) { m_sendEvent = Simulator::Schedule(Seconds(m_interval.GetValue()), &Sender::SendPacket, this); } // end Sender::SendPacket } //---------------------------------------------------------------------- //-- Receiver //------------------------------------------------------ TypeId Receiver::GetTypeId(void) { static TypeId tid = TypeId ("Receiver") .SetParent () .AddConstructor () .AddAttribute("Port", "Listening port.", UintegerValue(1603), MakeUintegerAccessor(&Receiver::m_port), MakeUintegerChecker()) ; return tid; } Receiver::Receiver() : m_calc(0), m_delay(0) { NS_LOG_FUNCTION_NOARGS (); m_socket = 0; } Receiver::~Receiver() { NS_LOG_FUNCTION_NOARGS (); } void Receiver::DoDispose (void) { NS_LOG_FUNCTION_NOARGS (); m_socket = 0; // chain up Application::DoDispose (); } void Receiver::StartApplication() { NS_LOG_FUNCTION_NOARGS (); if (m_socket == 0) { Ptr socketFactory = GetNode()->GetObject (UdpSocketFactory::GetTypeId()); m_socket = socketFactory->CreateSocket(); InetSocketAddress local = InetSocketAddress(Ipv4Address::GetAny(), m_port); m_socket->Bind(local); } m_socket->SetRecvCallback(MakeCallback(&Receiver::Receive, this)); // end Receiver::StartApplication } void Receiver::StopApplication() { NS_LOG_FUNCTION_NOARGS (); if (m_socket != 0) { m_socket->SetRecvCallback(MakeNullCallback > ()); } // end Receiver::StopApplication } void Receiver::SetCounter(Ptr > calc) { m_calc = calc; // end Receiver::SetCounter } void Receiver::SetDelayTracker(Ptr delay) { m_delay = delay; // end Receiver::SetDelayTracker } void Receiver::Receive(Ptr socket) { // NS_LOG_FUNCTION (this << socket << packet << from); Ptr packet; Address from; while (packet = socket->RecvFrom(from)) { if (InetSocketAddress::IsMatchingType (from)) { InetSocketAddress address = InetSocketAddress::ConvertFrom (from); NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << address.GetIpv4()); } TimestampTag timestamp; // Should never not be found since the sender is adding it, but // you never know. if (packet->FindFirstMatchingByteTag(timestamp)) { Time tx = timestamp.GetTimestamp(); if (m_delay != 0) { m_delay->Update(Simulator::Now() - tx); } } if (m_calc != 0) { m_calc->Update(); } // end receiving packets } // end Receiver::Receive } //---------------------------------------------------------------------- //-- TimestampTag //------------------------------------------------------ TypeId TimestampTag::GetTypeId(void) { static TypeId tid = TypeId ("TimestampTag") .SetParent () .AddConstructor () .AddAttribute ("Timestamp", "Some momentous point in time!", EmptyAttributeValue(), MakeTimeAccessor(&TimestampTag::GetTimestamp), MakeTimeChecker()) ; return tid; } TypeId TimestampTag::GetInstanceTypeId(void) const { return GetTypeId (); } uint32_t TimestampTag::GetSerializedSize (void) const { return 8; } void TimestampTag::Serialize (TagBuffer i) const { int64_t t = m_timestamp.GetNanoSeconds(); i.Write((const uint8_t *)&t, 8); } void TimestampTag::Deserialize (TagBuffer i) { int64_t t; i.Read((uint8_t *)&t, 8); m_timestamp = NanoSeconds(t); } void TimestampTag::SetTimestamp(Time time) { m_timestamp = time; } Time TimestampTag::GetTimestamp(void) const { return m_timestamp; } void TimestampTag::Print(std::ostream &os) const { os << "t=" << m_timestamp; }