#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "ns3/netanim-module.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/netanim-module.h"
#include "ns3/csma-helper.h"
#include "ns3/yans-wifi-channel.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/nqos-wifi-mac-helper.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/udp-echo-helper.h"
#include "ns3/ssid.h"
#include "ns3/rectangle.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/ipv4-flow-classifier.h"
#include "ns3/gnuplot.h"
#include "ns3/mobility-helper.h"
#include "ns3/gnuplot.h"
#include "ns3/flow-monitor.h"
#include "ns3/flow-monitor-helper.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/config-store-module.h"
#include "ns3/wifi-module.h"
#include "ns3/csma-module.h"
#include "ns3/olsr-helper.h"
#include "ns3/internet-module.h"
using namespace ns3;
using namespace std;
NS_LOG_COMPONENT_DEFINE ("simulationipv4");
int
main (int argc, char *argv[])
{
std::string phyMode ("ErpOfdmRate54Mbps");
std::string delay="0.1ms";
std::string datarate="1Gbps";
Config::SetDefault ("ns3::Ipv4GlobalRouting::RespondToInterfaceEvents", BooleanValue (true));
CommandLine cmd;
cmd.Parse (argc, argv);
NS_LOG_INFO ("Create 4 nodes.");
NodeContainer c;
c.Create (4);
NodeContainer n0n1 = NodeContainer (c.Get (0), c.Get (1));
NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
NodeContainer n1n3 = NodeContainer (c.Get (1), c.Get (3));
NodeContainer n2n3 = NodeContainer (c.Get (2), c.Get (3));
NodeContainer stationary= NodeContainer(c.Get(0),c.Get(1),c.Get(2),c.Get(3));
NodeContainer stations = NodeContainer(c.Get(3));
NodeContainer accesspoints = NodeContainer(c.Get(1),c.Get(2));
NS_LOG_INFO ("Create channels.");
PointToPointHelper p2p;
p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer d0d1 = p2p.Install (n0n1);
NetDeviceContainer d0d2 = p2p.Install (n0n2);
NetDeviceContainer MobileDevice1;
NetDeviceContainer MobileDevice2;
NetDeviceContainer AP1;
NetDeviceContainer AP2;
NetDeviceContainer dummy;
NetDeviceContainer wifiStationDevices;
NetDeviceContainer wifiApDevices;
WifiHelper wifi1;
wifi1.SetStandard (WIFI_PHY_STANDARD_80211g);
YansWifiPhyHelper phy1 = YansWifiPhyHelper::Default ();
phy1.Set ("RxGain", DoubleValue (0) );
phy1.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
YansWifiChannelHelper channel1;
channel1.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
channel1.AddPropagationLoss ("ns3::FriisPropagationLossModel");
phy1.SetChannel (channel1.Create ());
phy1.Set ("ChannelNumber", UintegerValue (1) );
NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
wifi1.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",StringValue (phyMode),
"ControlMode",StringValue (phyMode));
Ssid ssid = Ssid ("ns-3-ssid");
mac.SetType ("ns3::StaWifiMac","Ssid", SsidValue (ssid),"ActiveProbing", BooleanValue (false));
wifiStationDevices = wifi1.Install(phy1, mac, stations);
mac.SetType ("ns3::ApWifiMac","Ssid", SsidValue (ssid),"BeaconGeneration", BooleanValue (true),"BeaconInterval", TimeValue (Seconds (2.5)));
wifiApDevices = wifi1.Install(phy1,mac,accesspoints); //Add the mobile devices
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc1 = CreateObject<ListPositionAllocator> ();
positionAlloc1->Add (Vector (50.0, 0.0, 0.0));
positionAlloc1->Add (Vector (0.0, 10.0, 0.0));
positionAlloc1->Add (Vector (130.0,10.0, 0.0));
positionAlloc1->Add (Vector (50.0, 30.0, 0.0));
mobility.SetPositionAllocator (positionAlloc1);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (stationary);
InternetStackHelper stack;
stack.Install(c);
NS_LOG_INFO ("Assign IP Addresses.");
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i0i1 = ipv4.Assign (d0d1);
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer i0i2 = ipv4.Assign (d0d2);
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
Ipv4InterfaceContainer i1 = ipv4.Assign (wifiApDevices.Get(0));
Ipv4InterfaceContainer i3 = ipv4.Assign (wifiStationDevices);
ipv4.SetBase ("10.1.4.0", "255.255.255.0");
Ipv4InterfaceContainer i2 = ipv4.Assign (wifiApDevices.Get(1));
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
OnOffHelper onoff ("ns3::UdpSocketFactory",
InetSocketAddress (i3.GetAddress (0), port));
onoff.SetConstantRate (DataRate ("2kbps"));
onoff.SetAttribute ("PacketSize", UintegerValue (100));
ApplicationContainer apps = onoff.Install (c.Get (0));
apps.Start (Seconds (20.0));
apps.Stop (Seconds (25.0));
PacketSinkHelper sink ("ns3::UdpSocketFactory",
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
ApplicationContainer apps11,apps22;
apps11 = sink.Install (c.Get (3));
apps11.Start (Seconds (1.0));
apps11.Stop (Seconds (200.0));
p2p.EnablePcapAll ("simulationipv4");
phy1.EnablePcapAll ("simulationipv4");
NS_LOG_INFO ("Run Simulation.");
AnimationInterface anim ("simulationipv4.xml");
Simulator::Stop (Seconds(200.0));
Simulator::Run ();
uint32_t totalPacketsThrough = DynamicCast<PacketSink>(apps11.Get(0))->GetTotalRx ();
std::cout <<"Total received on client = "<< totalPacketsThrough<<endl;
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
}