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