1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright 2007 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author:  Tom Henderson (tomhend@u.washington.edu)
19  */
20 #include "ns3/address.h"
21 #include "ns3/address-utils.h"
22 #include "ns3/log.h"
23 #include "ns3/inet-socket-address.h"
24 #include "ns3/inet6-socket-address.h"
25 #include "ns3/node.h"
26 #include "ns3/socket.h"
27 #include "ns3/udp-socket.h"
28 #include "ns3/simulator.h"
29 #include "ns3/socket-factory.h"
30 #include "ns3/packet.h"
31 #include "ns3/trace-source-accessor.h"
32 #include "ns3/udp-socket-factory.h"
33 #include "packet-sink.h"
34 #include "ns3/boolean.h"
35 #include "ns3/ipv4-packet-info-tag.h"
36 #include "ns3/ipv6-packet-info-tag.h"
37 
38 namespace ns3 {
39 
40 NS_LOG_COMPONENT_DEFINE ("PacketSink");
41 
42 NS_OBJECT_ENSURE_REGISTERED (PacketSink);
43 
44 TypeId
GetTypeId(void)45 PacketSink::GetTypeId (void)
46 {
47   static TypeId tid = TypeId ("ns3::PacketSink")
48     .SetParent<Application> ()
49     .SetGroupName("Applications")
50     .AddConstructor<PacketSink> ()
51     .AddAttribute ("Local",
52                    "The Address on which to Bind the rx socket.",
53                    AddressValue (),
54                    MakeAddressAccessor (&PacketSink::m_local),
55                    MakeAddressChecker ())
56     .AddAttribute ("Protocol",
57                    "The type id of the protocol to use for the rx socket.",
58                    TypeIdValue (UdpSocketFactory::GetTypeId ()),
59                    MakeTypeIdAccessor (&PacketSink::m_tid),
60                    MakeTypeIdChecker ())
61     .AddAttribute ("EnableSeqTsSizeHeader",
62                    "Enable optional header tracing of SeqTsSizeHeader",
63                    BooleanValue (false),
64                    MakeBooleanAccessor (&PacketSink::m_enableSeqTsSizeHeader),
65                    MakeBooleanChecker ())
66     .AddTraceSource ("Rx",
67                      "A packet has been received",
68                      MakeTraceSourceAccessor (&PacketSink::m_rxTrace),
69                      "ns3::Packet::AddressTracedCallback")
70     .AddTraceSource ("RxWithAddresses", "A packet has been received",
71                      MakeTraceSourceAccessor (&PacketSink::m_rxTraceWithAddresses),
72                      "ns3::Packet::TwoAddressTracedCallback")
73     .AddTraceSource ("RxWithSeqTsSize",
74                      "A packet with SeqTsSize header has been received",
75                      MakeTraceSourceAccessor (&PacketSink::m_rxTraceWithSeqTsSize),
76                      "ns3::PacketSink::SeqTsSizeCallback")
77   ;
78   return tid;
79 }
80 
PacketSink()81 PacketSink::PacketSink ()
82 {
83   NS_LOG_FUNCTION (this);
84   m_socket = 0;
85   m_totalRx = 0;
86 }
87 
~PacketSink()88 PacketSink::~PacketSink()
89 {
90   NS_LOG_FUNCTION (this);
91 }
92 
GetTotalRx() const93 uint64_t PacketSink::GetTotalRx () const
94 {
95   NS_LOG_FUNCTION (this);
96   return m_totalRx;
97 }
98 
99 Ptr<Socket>
GetListeningSocket(void) const100 PacketSink::GetListeningSocket (void) const
101 {
102   NS_LOG_FUNCTION (this);
103   return m_socket;
104 }
105 
106 std::list<Ptr<Socket> >
GetAcceptedSockets(void) const107 PacketSink::GetAcceptedSockets (void) const
108 {
109   NS_LOG_FUNCTION (this);
110   return m_socketList;
111 }
112 
DoDispose(void)113 void PacketSink::DoDispose (void)
114 {
115   NS_LOG_FUNCTION (this);
116   m_socket = 0;
117   m_socketList.clear ();
118 
119   // chain up
120   Application::DoDispose ();
121 }
122 
123 
124 // Application Methods
StartApplication()125 void PacketSink::StartApplication ()    // Called at time specified by Start
126 {
127   NS_LOG_FUNCTION (this);
128   // Create the socket if not already
129   if (!m_socket)
130     {
131       m_socket = Socket::CreateSocket (GetNode (), m_tid);
132       if (m_socket->Bind (m_local) == -1)
133         {
134           NS_FATAL_ERROR ("Failed to bind socket");
135         }
136       m_socket->Listen ();
137       m_socket->ShutdownSend ();
138       if (addressUtils::IsMulticast (m_local))
139         {
140           Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket);
141           if (udpSocket)
142             {
143               // equivalent to setsockopt (MCAST_JOIN_GROUP)
144               udpSocket->MulticastJoinGroup (0, m_local);
145             }
146           else
147             {
148               NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket");
149             }
150         }
151     }
152 
153   if (InetSocketAddress::IsMatchingType (m_local))
154     {
155       m_localPort = InetSocketAddress::ConvertFrom (m_local).GetPort ();
156     }
157   else if (Inet6SocketAddress::IsMatchingType (m_local))
158     {
159       m_localPort = Inet6SocketAddress::ConvertFrom (m_local).GetPort ();
160     }
161   else
162     {
163       m_localPort = 0;
164     }
165   m_socket->SetRecvCallback (MakeCallback (&PacketSink::HandleRead, this));
166   m_socket->SetRecvPktInfo (true);
167   m_socket->SetAcceptCallback (
168     MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
169     MakeCallback (&PacketSink::HandleAccept, this));
170   m_socket->SetCloseCallbacks (
171     MakeCallback (&PacketSink::HandlePeerClose, this),
172     MakeCallback (&PacketSink::HandlePeerError, this));
173 }
174 
StopApplication()175 void PacketSink::StopApplication ()     // Called at time specified by Stop
176 {
177   NS_LOG_FUNCTION (this);
178   while(!m_socketList.empty ()) //these are accepted sockets, close them
179     {
180       Ptr<Socket> acceptedSocket = m_socketList.front ();
181       m_socketList.pop_front ();
182       acceptedSocket->Close ();
183     }
184   if (m_socket)
185     {
186       m_socket->Close ();
187       m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
188     }
189 }
190 
HandleRead(Ptr<Socket> socket)191 void PacketSink::HandleRead (Ptr<Socket> socket)
192 {
193   NS_LOG_FUNCTION (this << socket);
194   Ptr<Packet> packet;
195   Address from;
196   Address localAddress;
197   while ((packet = socket->RecvFrom (from)))
198     {
199       if (packet->GetSize () == 0)
200         { //EOF
201           break;
202         }
203       m_totalRx += packet->GetSize ();
204       if (InetSocketAddress::IsMatchingType (from))
205         {
206           NS_LOG_INFO ("At time " << Simulator::Now ().As (Time::S)
207                        << " packet sink received "
208                        <<  packet->GetSize () << " bytes from "
209                        << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
210                        << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
211                        << " total Rx " << m_totalRx << " bytes");
212         }
213       else if (Inet6SocketAddress::IsMatchingType (from))
214         {
215           NS_LOG_INFO ("At time " << Simulator::Now ().As (Time::S)
216                        << " packet sink received "
217                        <<  packet->GetSize () << " bytes from "
218                        << Inet6SocketAddress::ConvertFrom(from).GetIpv6 ()
219                        << " port " << Inet6SocketAddress::ConvertFrom (from).GetPort ()
220                        << " total Rx " << m_totalRx << " bytes");
221         }
222 
223       if (!m_rxTrace.IsEmpty () || !m_rxTraceWithAddresses.IsEmpty () ||
224           (!m_rxTraceWithSeqTsSize.IsEmpty () && m_enableSeqTsSizeHeader))
225         {
226           Ipv4PacketInfoTag interfaceInfo;
227           Ipv6PacketInfoTag interface6Info;
228           if (packet->RemovePacketTag (interfaceInfo))
229             {
230               localAddress = InetSocketAddress (interfaceInfo.GetAddress (), m_localPort);
231             }
232           else if (packet->RemovePacketTag (interface6Info))
233             {
234               localAddress = Inet6SocketAddress (interface6Info.GetAddress (), m_localPort);
235             }
236           else
237             {
238               socket->GetSockName (localAddress);
239             }
240           m_rxTrace (packet, from);
241           m_rxTraceWithAddresses (packet, from, localAddress);
242 
243           if (!m_rxTraceWithSeqTsSize.IsEmpty () && m_enableSeqTsSizeHeader)
244             {
245               PacketReceived (packet, from, localAddress);
246             }
247         }
248     }
249 }
250 
251 void
PacketReceived(const Ptr<Packet> & p,const Address & from,const Address & localAddress)252 PacketSink::PacketReceived (const Ptr<Packet> &p, const Address &from,
253                             const Address &localAddress)
254 {
255   SeqTsSizeHeader header;
256   Ptr<Packet> buffer;
257 
258   auto itBuffer = m_buffer.find (from);
259   if (itBuffer == m_buffer.end ())
260     {
261       itBuffer = m_buffer.insert (std::make_pair (from, Create<Packet> (0))).first;
262     }
263 
264   buffer = itBuffer->second;
265   buffer->AddAtEnd (p);
266   buffer->PeekHeader (header);
267 
268   NS_ABORT_IF (header.GetSize () == 0);
269 
270   while (buffer->GetSize () >= header.GetSize ())
271     {
272       NS_LOG_DEBUG ("Removing packet of size " << header.GetSize () << " from buffer of size " << buffer->GetSize ());
273       Ptr<Packet> complete = buffer->CreateFragment (0, static_cast<uint32_t> (header.GetSize ()));
274       buffer->RemoveAtStart (static_cast<uint32_t> (header.GetSize ()));
275 
276       complete->RemoveHeader (header);
277 
278       m_rxTraceWithSeqTsSize (complete, from, localAddress, header);
279 
280       if (buffer->GetSize () > header.GetSerializedSize ())
281         {
282           buffer->PeekHeader (header);
283         }
284       else
285         {
286           break;
287         }
288     }
289 }
290 
HandlePeerClose(Ptr<Socket> socket)291 void PacketSink::HandlePeerClose (Ptr<Socket> socket)
292 {
293   NS_LOG_FUNCTION (this << socket);
294 }
295 
HandlePeerError(Ptr<Socket> socket)296 void PacketSink::HandlePeerError (Ptr<Socket> socket)
297 {
298   NS_LOG_FUNCTION (this << socket);
299 }
300 
HandleAccept(Ptr<Socket> s,const Address & from)301 void PacketSink::HandleAccept (Ptr<Socket> s, const Address& from)
302 {
303   NS_LOG_FUNCTION (this << s << from);
304   s->SetRecvCallback (MakeCallback (&PacketSink::HandleRead, this));
305   m_socketList.push_back (s);
306 }
307 
308 } // Namespace ns3
309