/*

  Network Topology consists of three nodes, connected via p2p link
  
         
           O---------0---------0
       node 0    node 1      node 2  
           <<------Traffic-----------
           */


#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
#include "ns3/global-route-manager.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("3nodeExample");


  int 
main (int argc, char *argv[])
{
   
  // Create the OnOff application to send UDP datagrams of size 210 bytes at a rate of 448 Kb/s
  Config::SetDefault ("ns3::OnOffApplication::PacketSize", StringValue ("125"));
  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("10kb/s"));

  LogComponentEnable("3nodeExample", LOG_LEVEL_LOGIC);
  LogComponentEnable("3nodeExample", LOG_PREFIX_FUNC);
  LogComponentEnable("3nodeExample", LOG_PREFIX_TIME);
  NS_LOG_FUNCTION ("");


  LogComponentEnable("OnOffApplication", LOG_LEVEL_INFO);
  LogComponentEnable("OnOffApplication", LOG_LEVEL_INFO);
  LogComponentEnable("OnOffApplication", LOG_PREFIX_TIME);
  LogComponentEnable("OnOffApplication", LOG_PREFIX_TIME);

  NS_LOG_LOGIC ("Creating Nodes");
  NodeContainer nodes;
  nodes.Create (3);
  NodeContainer n0n1 = NodeContainer (nodes.Get(0), nodes.Get (1));
  NodeContainer n1n2 = NodeContainer (nodes.Get(1), nodes.Get (2));
  
  NS_LOG_LOGIC ("Creating Links");
  PointToPointHelper p2plink;
  p2plink.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  p2plink.SetChannelAttribute ("Delay", StringValue ("2ms"));

  NS_LOG_LOGIC ("Installing NetDevices");
  NetDeviceContainer d0d1, d1d2;
  d0d1 = p2plink.Install (n0n1);
  d1d2 = p2plink.Install (n1n2);
  
  NS_LOG_LOGIC ("Installing Internet Stack");
  InternetStackHelper stack;
  stack.Install (nodes);

  NS_LOG_LOGIC ("Setting IP Addresses");
  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer i0i1 = address.Assign (d0d1);
  address.SetBase ("10.2.2.0", "255.255.255.0");
  Ipv4InterfaceContainer i1i2 = address.Assign (d1d2);
  
  GlobalRouteManager::PopulateRoutingTables ();
   
  NS_LOG_INFO ("Create Applications.");
  
  uint16_t port = 9;  
 
  OnOffHelper onoff1 ("ns3::UdpSocketFactory", Address (InetSocketAddress (i0i1.GetAddress (0), port)));
  onoff1.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
  onoff1.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
  
  ApplicationContainer apps1 = onoff1.Install (nodes.Get (2));
  apps1.Start (Seconds (1.0));
  apps1.Stop (Seconds (2.01));
  
  // Create a packet sink to receive these packets
  PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny(), port));
  ApplicationContainer sink1 = sink.Install (nodes.Get (0));
  sink1.Start (Seconds (1.0));
  sink1.Stop (Seconds (2.01));

 //Simulator::Schedule (Seconds (1.25),&Ipv4::SetDown,i0i1.Get(1),i0i1.GetInterface(1));
 //Simulator::Schedule (Seconds (1.25),&Ipv4::SetDown,i0i1.Get(0),i0i1.GetInterface(0));
 //Simulator::Schedule (Seconds (1.25),&Ipv4::SetDown,i1i2.Get(0),i1i2.GetInterface(0));
 //Simulator::Schedule (Seconds (1.25),&Ipv4::SetDown,i1i2.Get(1),i1i2.GetInterface(1));
 
 //Simulator::Schedule (Seconds (1.75),&Ipv4::SetUp,i0i1.Get(1),i0i1.GetInterface(1)); 
 //Simulator::Schedule (Seconds (1.75),&Ipv4::SetUp,i0i1.Get(0),i0i1.GetInterface(0)); 
 //Simulator::Schedule (Seconds (1.75),&Ipv4::SetUp,i1i2.Get(0),i1i2.GetInterface(0)); 
 //Simulator::Schedule (Seconds (1.75),&Ipv4::SetUp,i1i2.Get(1),i1i2.GetInterface(1)); 

  NS_LOG_INFO ("Configure Tracing");
  std::ofstream ascii;
  ascii.open ("3nodenew.tr");
  PointToPointHelper::EnablePcapAll ("3nodenew");
  PointToPointHelper::EnableAsciiAll (ascii);
  
  NS_LOG_INFO ("Run Simulation");
  Simulator::Stop (Seconds (3.0));
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}


