Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(45)

Unified Diff: src/nist/model/nist-udp-groupecho-server.cc

Issue 326890043: Public Safety Communication modeling tools based on ns-3
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/nist/model/nist-udp-groupecho-server.h ('k') | src/nist/model/nist-udp-server.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/nist/model/nist-udp-groupecho-server.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/nist/model/nist-udp-groupecho-server.cc
@@ -0,0 +1,435 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2007 University of Washington
+ *
+ * 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
+ *
+ * Modified by: NIST
+ */
+
+#include "ns3/log.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/address-utils.h"
+#include "ns3/nstime.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/socket.h"
+#include "ns3/udp-socket.h"
+#include "ns3/simulator.h"
+#include "ns3/socket-factory.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+#include <iomanip>
+#include "ns3/boolean.h"
+
+#include "nist-udp-groupecho-server.h"
+#include <sstream>
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("NistUdpGroupEchoServerApplication");
+
+NS_OBJECT_ENSURE_REGISTERED (NistUdpGroupEchoServer);
+
+TypeId
+NistUdpGroupEchoServer::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::NistUdpGroupEchoServer")
+ .SetParent<Application> ()
+ .AddConstructor<NistUdpGroupEchoServer> ()
+ .AddAttribute ("Port", "Port on which we listen for incoming packets.",
+ UintegerValue (9),
+ MakeUintegerAccessor (&NistUdpGroupEchoServer::m_port),
+ MakeUintegerChecker<uint16_t> ())
+ .AddAttribute ("EchoPort", "Port on which we echo packets to client.",
+ UintegerValue (0),
+ MakeUintegerAccessor (&NistUdpGroupEchoServer::m_port_client),
+ MakeUintegerChecker<uint16_t> ())
+ .AddAttribute ("Timeout", "Inactive client session expiration time <seconds>.\nSessionTime < 0 : Server echoes group clients indefinitely\nSessionTime == 0 : Server echoes single client (Default)\nSessionTime > 0 : Server forwards packets to group. Session timeout units are seconds.",
+ DoubleValue (0),
+ MakeDoubleAccessor (&NistUdpGroupEchoServer::m_timeout),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("Echo", "Server echoes back client. True (default) | False",
+ BooleanValue (true),
+ MakeBooleanAccessor (&NistUdpGroupEchoServer::m_echoback),
+ MakeBooleanChecker ())
+ .AddTraceSource ("Rx", "A packet has been received",
+ MakeTraceSourceAccessor (&NistUdpGroupEchoServer::m_rxTrace),
+ "ns3::Packet::PacketAddressTracedCallback")
+ ;
+
+ return tid;
+}
+
+NistUdpGroupEchoServer::NistUdpGroupEchoServer ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+NistUdpGroupEchoServer::~NistUdpGroupEchoServer()
+{
+ NS_LOG_FUNCTION (this);
+ m_socket = 0;
+ m_socket6 = 0;
+}
+
+void
+NistUdpGroupEchoServer::AddClient (const Address& address)
+{
+ client src_client;
+ std::ostringstream os;
+ InetSocketAddress clientAddress = InetSocketAddress::ConvertFrom (address);
+
+ os << clientAddress.GetIpv4 () << ":" << clientAddress.GetPort ();
+ std::string ipaddrskey = os.str ();
+
+ src_client.addrs = address;
+ src_client.echo_addrs = InetSocketAddress (clientAddress.GetIpv4 (), m_port_client);
+ src_client.tstamp = Simulator::Now ();
+
+ m_clients[ipaddrskey] = src_client;
+
+ this->PrintClients ();
+}
+
+void
+NistUdpGroupEchoServer::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ Application::DoDispose ();
+}
+
+void
+NistUdpGroupEchoServer::StartApplication (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_INFO("Starting NistUdpGroupEchoServer with SessionTime: " << m_timeout);
+ if (m_socket == 0)
+ {
+ TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+ m_socket = Socket::CreateSocket (GetNode (), tid);
+ InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), m_port);
+ m_socket->Bind (local);
+ if (addressUtils::IsMulticast (m_local))
+ {
+ Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket);
+ if (udpSocket)
+ {
+ // equivalent to setsockopt (MCAST_JOIN_GROUP)
+ udpSocket->MulticastJoinGroup (0, m_local);
+ }
+ else
+ {
+ NS_FATAL_ERROR ("Error: Failed to join multicast group");
+ }
+ }
+ }
+
+ if (m_socket6 == 0)
+ {
+ TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+ m_socket6 = Socket::CreateSocket (GetNode (), tid);
+ Inet6SocketAddress local6 = Inet6SocketAddress (Ipv6Address::GetAny (), m_port);
+ m_socket6->Bind (local6);
+ if (addressUtils::IsMulticast (local6))
+ {
+ Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket6);
+ if (udpSocket)
+ {
+ // equivalent to setsockopt (MCAST_JOIN_GROUP)
+ udpSocket->MulticastJoinGroup (0, local6);
+ }
+ else
+ {
+ NS_FATAL_ERROR ("Error: Failed to join multicast group");
+ }
+ }
+ }
+
+ m_socket->SetRecvCallback (MakeCallback (&NistUdpGroupEchoServer::HandleRead, this));
+ m_socket6->SetRecvCallback (MakeCallback (&NistUdpGroupEchoServer::HandleRead, this));
+}
+
+void
+NistUdpGroupEchoServer::StopApplication ()
+{
+ NS_LOG_FUNCTION (this);
+
+ if (m_socket != 0)
+ {
+ m_socket->Close ();
+ m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
+ }
+ if (m_socket6 != 0)
+ {
+ m_socket6->Close ();
+ m_socket6->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
+ }
+}
+
+void
+NistUdpGroupEchoServer::HandleRead (Ptr<Socket> socket)
+{
+ NS_LOG_FUNCTION (this << socket);
+
+ Ptr<Packet> packet;
+ Address from, echo_addrs;
+ std::map<std::string,client>::iterator it, tempit;
+ std::string ipaddrskey;
+ std::ostringstream os;
+ client src_client;
+ double lapse;
+
+ while ((packet = socket->RecvFrom (from)))
+ {
+ m_rxTrace (packet, from);
+ if (InetSocketAddress::IsMatchingType (from))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds () << " server received " << packet->GetSize () << " bytes from " <<
+ InetSocketAddress::ConvertFrom (from).GetIpv4 () << " port " <<
+ InetSocketAddress::ConvertFrom (from).GetPort ());
+
+ os << InetSocketAddress::ConvertFrom (from).GetIpv4 () << ":" << InetSocketAddress::ConvertFrom (from).GetPort ();
+
+ InetSocketAddress inet_addrs = InetSocketAddress::ConvertFrom (from);
+ inet_addrs.SetPort(m_port_client);
+ echo_addrs = inet_addrs;
+ }
+ else if (Inet6SocketAddress::IsMatchingType (from))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds () << " server received " << packet->GetSize () << " bytes from " <<
+ Inet6SocketAddress::ConvertFrom (from).GetIpv6 () << " port " <<
+ Inet6SocketAddress::ConvertFrom (from).GetPort ());
+ os << Inet6SocketAddress::ConvertFrom (from).GetIpv6 () << ":" << Inet6SocketAddress::ConvertFrom (from).GetPort ();
+
+ Inet6SocketAddress inet6_addrs = Inet6SocketAddress::ConvertFrom (from);
+ inet6_addrs.SetPort(m_port_client);
+ echo_addrs = inet6_addrs;
+ }
+
+
+ packet->RemoveAllPacketTags ();
+ packet->RemoveAllByteTags ();
+
+ /* Update clients group with new/existing client.
+ * If exist, update timestamp. Else, add client to group with new timestamp.
+ * Echo packet.
+ */
+
+ ipaddrskey = os.str ();
+
+ it = m_clients.find(ipaddrskey);
+ if (it != m_clients.end ())
+ {
+ // Client is a group member. Udate timestamp.
+ //std::cout<<"Client found; old timestamp: " << it->second.tstamp.GetSeconds ()<<std::endl;
+ it->second.tstamp = Simulator::Now ();
+ //std::cout<<"New timestamp: " << it->second.tstamp.GetSeconds ()<<std::endl;
+ }
+ else // Add client to group
+ {
+ //client src_client;
+ src_client.addrs = from;
+ src_client.echo_addrs = echo_addrs;
+ src_client.tstamp = Simulator::Now ();
+ m_clients[ipaddrskey] = src_client;
+ }
+
+ if(g_log.IsEnabled (LOG_DEBUG))
+ this->PrintClients ();
+
+ /* Echoing packet to group.
+ * Iterate through all the clients, check timestamp.
+ * If timestamp has expired, remove client.
+ * Else, echo/fwd packet to client.*/
+
+ /* m_timeout < 0 : Server serves group clients indefinitely
+ * m_timeout == 0 : Server behaves as single echo-client (no group echo)
+ * m_timeout > 0 : Server group echo clients that have been active within
+ * the m_timeout elapsed time.
+ */
+ Address addrs_dest;
+ if (m_timeout < 0)
+ {
+ // Server serves group clients indefinitely.
+ for (it = m_clients.begin ();
+ it!=m_clients.end (); ++it)
+ {
+ // If no echo back, neglect client source
+ if (!m_echoback && it->first == ipaddrskey)
+ continue;
+
+ // Check elapsed time
+ lapse = Simulator::Now ().GetSeconds () - it->second.tstamp.GetSeconds ();
+
+ // Set destination address with the agreed client port.
+ if (m_port_client !=0)
+ addrs_dest = it->second.echo_addrs;
+ else
+ addrs_dest = it->second.addrs;
+
+ // Forward packet
+ NS_LOG_LOGIC ("Echoing packet");
+ socket->SendTo (packet, 0, addrs_dest);
+
+ if (InetSocketAddress::IsMatchingType (addrs_dest))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " server sent "
+ << packet->GetSize ()
+ << " bytes to "
+ << InetSocketAddress::ConvertFrom (addrs_dest).GetIpv4 ()
+ << " port "
+ << InetSocketAddress::ConvertFrom (addrs_dest).GetPort ());
+ }
+ else if (Inet6SocketAddress::IsMatchingType (addrs_dest))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " server sent "
+ << packet->GetSize ()
+ << " bytes to "
+ << Inet6SocketAddress::ConvertFrom (addrs_dest).GetIpv6 ()
+ << " port "
+ << Inet6SocketAddress::ConvertFrom (addrs_dest).GetPort ());
+ }
+ }
+ }
+ else if (m_timeout == 0)
+ {
+ // Only one client allowed in group.
+ it = m_clients.find(ipaddrskey);
+ if (m_echoback)
+ {
+ // Set destination address with the agreed client port.
+ if (m_port_client !=0)
+ addrs_dest = it->second.echo_addrs;
+ else
+ addrs_dest = it->second.addrs;
+
+ // Forward packet
+ NS_LOG_LOGIC ("Echoing packet");
+ socket->SendTo (packet, 0, addrs_dest);
+
+ if (InetSocketAddress::IsMatchingType (addrs_dest))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " server sent "
+ << packet->GetSize ()
+ << " bytes to "
+ << InetSocketAddress::ConvertFrom (addrs_dest).GetIpv4 ()
+ << " port "
+ << InetSocketAddress::ConvertFrom (addrs_dest).GetPort ());
+ }
+ else if (Inet6SocketAddress::IsMatchingType (addrs_dest))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " server sent "
+ << packet->GetSize ()
+ << " bytes to "
+ << Inet6SocketAddress::ConvertFrom (addrs_dest).GetIpv6 ()
+ << " port "
+ << Inet6SocketAddress::ConvertFrom (addrs_dest).GetPort ());
+ }
+ }
+ // Remove client
+ m_clients.erase (it);
+ }
+ else //if (m_timeout > 0)
+ {
+ for (it = m_clients.begin ();
+ it!=m_clients.end (); ++it)
+ {
+ // If no echo back, neglect client source
+ if (!m_echoback && it->first == ipaddrskey)
+ continue;
+
+ // Check elapsed time
+ lapse = Simulator::Now ().GetSeconds () - it->second.tstamp.GetSeconds ();
+
+ if (lapse < m_timeout)
+ {
+ // Set destination address with the agreed client port.
+ if (m_port_client !=0)
+ addrs_dest = it->second.echo_addrs;
+ else
+ addrs_dest = it->second.addrs;
+
+ // Forward packet
+ NS_LOG_LOGIC ("Echoing packet");
+ socket->SendTo (packet, 0, addrs_dest);
+
+
+ if (InetSocketAddress::IsMatchingType (addrs_dest))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " server sent "
+ << packet->GetSize ()
+ << " bytes to "
+ << InetSocketAddress::ConvertFrom (addrs_dest).GetIpv4 ()
+ << " port "
+ << InetSocketAddress::ConvertFrom (addrs_dest).GetPort ());
+ }
+ else if (Inet6SocketAddress::IsMatchingType (addrs_dest))
+ {
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " server sent "
+ << packet->GetSize ()
+ << " bytes to "
+ << Inet6SocketAddress::ConvertFrom (addrs_dest).GetIpv6 ()
+ << " port "
+ << Inet6SocketAddress::ConvertFrom (addrs_dest).GetPort ());
+ }
+ }
+ else // Time has expired. Remove client.
+ {
+ //NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds () <<" client " << it->first << " session time expired! ");
+ tempit = it;
+ --it;
+ m_clients.erase (tempit);
+ }
+ }
+ }//end for
+ }//end while
+}
+
+void
+NistUdpGroupEchoServer::PrintClients (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+ << " number of clients: " << m_clients.size ());
+ if( m_clients.size () > 0 )
+ {
+ // Check time lapse
+ double tstamp = Simulator::Now ().GetSeconds ();
+ double lapse;
+ NS_LOG_INFO (std::setfill ('-') << std::setw(57) << "-" << std::setfill (' '));
+ NS_LOG_INFO (std::setw(23) << "Client " << std::setw(10) << "Session");
+ NS_LOG_INFO (std::setfill ('-') << std::setw(57) << "-" << std::setfill (' '));
+ for (std::map<std::string,client>::iterator it = m_clients.begin ();
+ it!=m_clients.end (); ++it)
+ {
+ lapse = tstamp - it->second.tstamp.GetSeconds ();
+ if (m_timeout < 0 || lapse < m_timeout)
+ NS_LOG_INFO (std::setw(23) << it->first << " " << std::setw(10) << lapse);
+ else
+ NS_LOG_INFO (std::setw(23) << it->first << " " << std::setw(10) << lapse << " **Session Expired!**");
+ }
+ NS_LOG_INFO (std::setfill ('=') << std::setw(57) << "=" << std::setfill (' '));
+ }
+}
+
+} // Namespace ns3
« no previous file with comments | « src/nist/model/nist-udp-groupecho-server.h ('k') | src/nist/model/nist-udp-server.h » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b