A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
udp-socket-impl.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/node.h"
23 #include "ns3/inet-socket-address.h"
24 #include "ns3/inet6-socket-address.h"
25 #include "ns3/ipv4-route.h"
26 #include "ns3/ipv6-route.h"
27 #include "ns3/ipv4.h"
28 #include "ns3/ipv6.h"
29 #include "ns3/ipv4-header.h"
30 #include "ns3/ipv4-routing-protocol.h"
31 #include "ns3/ipv6-routing-protocol.h"
32 #include "ns3/udp-socket-factory.h"
33 #include "ns3/trace-source-accessor.h"
34 #include "ns3/ipv4-packet-info-tag.h"
35 #include "udp-socket-impl.h"
36 #include "udp-l4-protocol.h"
37 #include "ipv4-end-point.h"
38 #include "ipv6-end-point.h"
39 #include <limits>
40 
41 NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
42 
43 namespace ns3 {
44 
45 NS_OBJECT_ENSURE_REGISTERED (UdpSocketImpl);
46 
47 static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
48 
49 // Add attributes generic to all UdpSockets to base class UdpSocket
50 TypeId
51 UdpSocketImpl::GetTypeId (void)
52 {
53  static TypeId tid = TypeId ("ns3::UdpSocketImpl")
54  .SetParent<UdpSocket> ()
55  .AddConstructor<UdpSocketImpl> ()
56  .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
57  MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
58  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
59  CallbackValue (),
60  MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
61  MakeCallbackChecker ())
62  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
63  CallbackValue (),
64  MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback6),
65  MakeCallbackChecker ())
66  ;
67  return tid;
68 }
69 
71  : m_endPoint (0),
72  m_endPoint6 (0),
73  m_node (0),
74  m_udp (0),
75  m_errno (ERROR_NOTERROR),
76  m_shutdownSend (false),
77  m_shutdownRecv (false),
78  m_connected (false),
79  m_rxAvailable (0)
80 {
82  m_allowBroadcast = false;
83 }
84 
86 {
88 
89  // XXX todo: leave any multicast groups that have been joined
90  m_node = 0;
96  if (m_endPoint != 0)
97  {
98  NS_ASSERT (m_udp != 0);
107  NS_ASSERT (m_endPoint != 0);
108  m_udp->DeAllocate (m_endPoint);
109  NS_ASSERT (m_endPoint == 0);
110  }
111  if (m_endPoint6 != 0)
112  {
113  NS_ASSERT (m_udp != 0);
122  NS_ASSERT (m_endPoint6 != 0);
123  m_udp->DeAllocate (m_endPoint6);
124  NS_ASSERT (m_endPoint6 == 0);
125  }
126  m_udp = 0;
127 }
128 
129 void
130 UdpSocketImpl::SetNode (Ptr<Node> node)
131 {
133  m_node = node;
134 
135 }
136 void
137 UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
138 {
140  m_udp = udp;
141 }
142 
143 
144 enum Socket::SocketErrno
146 {
148  return m_errno;
149 }
150 
151 enum Socket::SocketType
153 {
154  return NS3_SOCK_DGRAM;
155 }
156 
157 Ptr<Node>
159 {
161  return m_node;
162 }
163 
164 void
165 UdpSocketImpl::Destroy (void)
166 {
168  m_endPoint = 0;
169 }
170 
171 void
172 UdpSocketImpl::Destroy6 (void)
173 {
175  m_endPoint6 = 0;
176 }
177 
178 int
179 UdpSocketImpl::FinishBind (void)
180 {
182  bool done = false;
183  if (m_endPoint != 0)
184  {
185  m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
186  m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
187  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
188  done = true;
189  }
190  if (m_endPoint6 != 0)
191  {
192  m_endPoint6->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp6, Ptr<UdpSocketImpl> (this)));
193  m_endPoint6->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp6, Ptr<UdpSocketImpl> (this)));
194  m_endPoint6->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy6, Ptr<UdpSocketImpl> (this)));
195  done = true;
196  }
197  if (done)
198  {
199  return 0;
200  }
201  return -1;
202 }
203 
204 int
206 {
208  m_endPoint = m_udp->Allocate ();
209  return FinishBind ();
210 }
211 
212 int
214 {
216  m_endPoint6 = m_udp->Allocate6 ();
217  return FinishBind ();
218 }
219 
220 int
221 UdpSocketImpl::Bind (const Address &address)
222 {
223  NS_LOG_FUNCTION (this << address);
224 
225  if (InetSocketAddress::IsMatchingType (address))
226  {
228  Ipv4Address ipv4 = transport.GetIpv4 ();
229  uint16_t port = transport.GetPort ();
230  if (ipv4 == Ipv4Address::GetAny () && port == 0)
231  {
232  m_endPoint = m_udp->Allocate ();
233  }
234  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
235  {
236  m_endPoint = m_udp->Allocate (port);
237  }
238  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
239  {
240  m_endPoint = m_udp->Allocate (ipv4);
241  }
242  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
243  {
244  m_endPoint = m_udp->Allocate (ipv4, port);
245  }
246  }
247  else if (Inet6SocketAddress::IsMatchingType (address))
248  {
250  Ipv6Address ipv6 = transport.GetIpv6 ();
251  uint16_t port = transport.GetPort ();
252  if (ipv6 == Ipv6Address::GetAny () && port == 0)
253  {
254  m_endPoint6 = m_udp->Allocate6 ();
255  }
256  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
257  {
258  m_endPoint6 = m_udp->Allocate6 (port);
259  }
260  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
261  {
262  m_endPoint6 = m_udp->Allocate6 (ipv6);
263  }
264  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
265  {
266  m_endPoint6 = m_udp->Allocate6 (ipv6, port);
267  }
268  }
269  else
270  {
271  NS_LOG_ERROR ("Not IsMatchingType");
272  m_errno = ERROR_INVAL;
273  return -1;
274  }
275 
276  return FinishBind ();
277 }
278 
279 int
281 {
283  m_shutdownSend = true;
284  return 0;
285 }
286 
287 int
289 {
291  m_shutdownRecv = true;
292  return 0;
293 }
294 
295 int
297 {
299  if (m_shutdownRecv == true && m_shutdownSend == true)
300  {
301  m_errno = Socket::ERROR_BADF;
302  return -1;
303  }
304  m_shutdownRecv = true;
305  m_shutdownSend = true;
306  return 0;
307 }
308 
309 int
311 {
312  NS_LOG_FUNCTION (this << address);
313  if (InetSocketAddress::IsMatchingType(address) == true)
314  {
316  m_defaultAddress = Address(transport.GetIpv4 ());
317  m_defaultPort = transport.GetPort ();
318  m_connected = true;
319  NotifyConnectionSucceeded ();
320  }
321  else if (Inet6SocketAddress::IsMatchingType(address) == true)
322  {
324  m_defaultAddress = Address(transport.GetIpv6 ());
325  m_defaultPort = transport.GetPort ();
326  m_connected = true;
327  NotifyConnectionSucceeded ();
328  }
329  else
330  {
331  return -1;
332  }
333 
334  return 0;
335 }
336 
337 int
339 {
340  m_errno = Socket::ERROR_OPNOTSUPP;
341  return -1;
342 }
343 
344 int
345 UdpSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
346 {
347  NS_LOG_FUNCTION (this << p << flags);
348 
349  if (!m_connected)
350  {
351  m_errno = ERROR_NOTCONN;
352  return -1;
353  }
354 
355  return DoSend (p);
356 }
357 
358 int
359 UdpSocketImpl::DoSend (Ptr<Packet> p)
360 {
361  NS_LOG_FUNCTION (this << p);
362  if ((m_endPoint == 0) && (InetSocketAddress::IsMatchingType(m_defaultAddress) == true))
363  {
364  if (Bind () == -1)
365  {
366  NS_ASSERT (m_endPoint == 0);
367  return -1;
368  }
369  NS_ASSERT (m_endPoint != 0);
370  }
371  else if ((m_endPoint6 == 0) && (Inet6SocketAddress::IsMatchingType(m_defaultAddress) == true))
372  {
373  if (Bind6 () == -1)
374  {
375  NS_ASSERT (m_endPoint6 == 0);
376  return -1;
377  }
378  NS_ASSERT (m_endPoint6 != 0);
379  }
380  if (m_shutdownSend)
381  {
382  m_errno = ERROR_SHUTDOWN;
383  return -1;
384  }
385 
386  return DoSendTo (p, (const Address)m_defaultAddress);
387 }
388 
389 int
390 UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
391 {
392  NS_LOG_FUNCTION (this << p << address);
393 
394  if (!m_connected)
395  {
396  NS_LOG_LOGIC ("Not connected");
397  if (InetSocketAddress::IsMatchingType(address) == true)
398  {
399  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
400  Ipv4Address ipv4 = transport.GetIpv4 ();
401  uint16_t port = transport.GetPort ();
402  return DoSendTo (p, ipv4, port);
403  }
404  else if (Inet6SocketAddress::IsMatchingType(address) == true)
405  {
406  Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
407  Ipv6Address ipv6 = transport.GetIpv6 ();
408  uint16_t port = transport.GetPort ();
409  return DoSendTo (p, ipv6, port);
410  }
411  else
412  {
413  return -1;
414  }
415  }
416  else
417  {
418  // connected UDP socket must use default addresses
419  NS_LOG_LOGIC ("Connected");
420  if (Ipv4Address::IsMatchingType(m_defaultAddress))
421  {
422  return DoSendTo (p, Ipv4Address::ConvertFrom(m_defaultAddress), m_defaultPort);
423  }
424  else if (Ipv6Address::IsMatchingType(m_defaultAddress))
425  {
426  return DoSendTo (p, Ipv6Address::ConvertFrom(m_defaultAddress), m_defaultPort);
427  }
428  }
429  m_errno = ERROR_AFNOSUPPORT;
430  return(-1);
431 }
432 
433 int
434 UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
435 {
436  NS_LOG_FUNCTION (this << p << dest << port);
437  if (m_boundnetdevice)
438  {
439  NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
440  }
441  if (m_endPoint == 0)
442  {
443  if (Bind () == -1)
444  {
445  NS_ASSERT (m_endPoint == 0);
446  return -1;
447  }
448  NS_ASSERT (m_endPoint != 0);
449  }
450  if (m_shutdownSend)
451  {
452  m_errno = ERROR_SHUTDOWN;
453  return -1;
454  }
455 
456  if (p->GetSize () > GetTxAvailable () )
457  {
458  m_errno = ERROR_MSGSIZE;
459  return -1;
460  }
461 
462  if (IsManualIpTos ())
463  {
464  SocketIpTosTag ipTosTag;
465  ipTosTag.SetTos (GetIpTos ());
466  p->AddPacketTag (ipTosTag);
467  }
468 
469  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
470 
471  // Locally override the IP TTL for this socket
472  // We cannot directly modify the TTL at this stage, so we set a Packet tag
473  // The destination can be either multicast, unicast/anycast, or
474  // either all-hosts broadcast or limited (subnet-directed) broadcast.
475  // For the latter two broadcast types, the TTL will later be set to one
476  // irrespective of what is set in these socket options. So, this tagging
477  // may end up setting the TTL of a limited broadcast packet to be
478  // the same as a unicast, but it will be fixed further down the stack
479  if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
480  {
481  SocketIpTtlTag tag;
482  tag.SetTtl (m_ipMulticastTtl);
483  p->AddPacketTag (tag);
484  }
485  else if (IsManualIpTtl () && GetIpTtl () != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
486  {
487  SocketIpTtlTag tag;
488  tag.SetTtl (GetIpTtl ());
489  p->AddPacketTag (tag);
490  }
491  {
492  SocketSetDontFragmentTag tag;
493  bool found = p->RemovePacketTag (tag);
494  if (!found)
495  {
496  if (m_mtuDiscover)
497  {
498  tag.Enable ();
499  }
500  else
501  {
502  tag.Disable ();
503  }
504  p->AddPacketTag (tag);
505  }
506  }
507  //
508  // If dest is set to the limited broadcast address (all ones),
509  // convert it to send a copy of the packet out of every
510  // interface as a subnet-directed broadcast.
511  // Exception: if the interface has a /32 address, there is no
512  // valid subnet-directed broadcast, so send it as limited broadcast
513  // Note also that some systems will only send limited broadcast packets
514  // out of the "default" interface; here we send it out all interfaces
515  //
516  if (dest.IsBroadcast ())
517  {
518  if (!m_allowBroadcast)
519  {
520  m_errno = ERROR_OPNOTSUPP;
521  return -1;
522  }
523  NS_LOG_LOGIC ("Limited broadcast start.");
524  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
525  {
526  // Get the primary address
527  Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0);
528  Ipv4Address addri = iaddr.GetLocal ();
529  if (addri == Ipv4Address ("127.0.0.1"))
530  continue;
531  // Check if interface-bound socket
532  if (m_boundnetdevice)
533  {
534  if (ipv4->GetNetDevice (i) != m_boundnetdevice)
535  continue;
536  }
537  Ipv4Mask maski = iaddr.GetMask ();
538  if (maski == Ipv4Mask::GetOnes ())
539  {
540  // if the network mask is 255.255.255.255, do not convert dest
541  NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << dest
542  << " (mask is " << maski << ")");
543  m_udp->Send (p->Copy (), addri, dest,
544  m_endPoint->GetLocalPort (), port);
545  NotifyDataSent (p->GetSize ());
546  NotifySend (GetTxAvailable ());
547  }
548  else
549  {
550  // Convert to subnet-directed broadcast
551  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
552  NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
553  << " (mask is " << maski << ")");
554  m_udp->Send (p->Copy (), addri, bcast,
555  m_endPoint->GetLocalPort (), port);
556  NotifyDataSent (p->GetSize ());
557  NotifySend (GetTxAvailable ());
558  }
559  }
560  NS_LOG_LOGIC ("Limited broadcast end.");
561  return p->GetSize ();
562  }
563  else if (m_endPoint->GetLocalAddress () != Ipv4Address::GetAny ())
564  {
565  m_udp->Send (p->Copy (), m_endPoint->GetLocalAddress (), dest,
566  m_endPoint->GetLocalPort (), port, 0);
567  NotifyDataSent (p->GetSize ());
568  NotifySend (GetTxAvailable ());
569  return p->GetSize ();
570  }
571  else if (ipv4->GetRoutingProtocol () != 0)
572  {
573  Ipv4Header header;
574  header.SetDestination (dest);
575  header.SetProtocol (UdpL4Protocol::PROT_NUMBER);
576  Socket::SocketErrno errno_;
577  Ptr<Ipv4Route> route;
578  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
579  // TBD-- we could cache the route and just check its validity
580  route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
581  if (route != 0)
582  {
583  NS_LOG_LOGIC ("Route exists");
584  if (!m_allowBroadcast)
585  {
586  uint32_t outputIfIndex = ipv4->GetInterfaceForDevice (route->GetOutputDevice ());
587  uint32_t ifNAddr = ipv4->GetNAddresses (outputIfIndex);
588  for (uint32_t addrI = 0; addrI < ifNAddr; ++addrI)
589  {
590  Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (outputIfIndex, addrI);
591  if (dest == ifAddr.GetBroadcast ())
592  {
593  m_errno = ERROR_OPNOTSUPP;
594  return -1;
595  }
596  }
597  }
598 
599  header.SetSource (route->GetSource ());
600  m_udp->Send (p->Copy (), header.GetSource (), header.GetDestination (),
601  m_endPoint->GetLocalPort (), port, route);
602  NotifyDataSent (p->GetSize ());
603  return p->GetSize ();
604  }
605  else
606  {
607  NS_LOG_LOGIC ("No route to destination");
608  NS_LOG_ERROR (errno_);
609  m_errno = errno_;
610  return -1;
611  }
612  }
613  else
614  {
615  NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
616  m_errno = ERROR_NOROUTETOHOST;
617  return -1;
618  }
619 
620  return 0;
621 }
622 
623 int
624 UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv6Address dest, uint16_t port)
625 {
626  NS_LOG_FUNCTION (this << p << dest << port);
627 
628  if (dest.IsIpv4MappedAddress ())
629  {
630  return (DoSendTo(p, dest.GetIpv4MappedAddress (), port));
631  }
632  if (m_boundnetdevice)
633  {
634  NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
635  }
636  if (m_endPoint6 == 0)
637  {
638  if (Bind6 () == -1)
639  {
640  NS_ASSERT (m_endPoint6 == 0);
641  return -1;
642  }
643  NS_ASSERT (m_endPoint6 != 0);
644  }
645  if (m_shutdownSend)
646  {
647  m_errno = ERROR_SHUTDOWN;
648  return -1;
649  }
650 
651  if (p->GetSize () > GetTxAvailable () )
652  {
653  m_errno = ERROR_MSGSIZE;
654  return -1;
655  }
656 
657  if (IsManualIpv6Tclass ())
658  {
659  SocketIpv6TclassTag ipTclassTag;
660  ipTclassTag.SetTclass (GetIpv6Tclass ());
661  p->AddPacketTag (ipTclassTag);
662  }
663 
664  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
665 
666  // Locally override the IP TTL for this socket
667  // We cannot directly modify the TTL at this stage, so we set a Packet tag
668  // The destination can be either multicast, unicast/anycast, or
669  // either all-hosts broadcast or limited (subnet-directed) broadcast.
670  // For the latter two broadcast types, the TTL will later be set to one
671  // irrespective of what is set in these socket options. So, this tagging
672  // may end up setting the TTL of a limited broadcast packet to be
673  // the same as a unicast, but it will be fixed further down the stack
674  if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
675  {
676  SocketIpv6HopLimitTag tag;
677  tag.SetHopLimit (m_ipMulticastTtl);
678  p->AddPacketTag (tag);
679  }
680  else if (IsManualIpv6HopLimit () && GetIpv6HopLimit () != 0 && !dest.IsMulticast ())
681  {
682  SocketIpv6HopLimitTag tag;
683  tag.SetHopLimit (GetIpv6HopLimit ());
684  p->AddPacketTag (tag);
685  }
686  // There is no analgous to an IPv4 broadcast address in IPv6.
687  // Instead, we use a set of link-local, site-local, and global
688  // multicast addresses. The Ipv6 routing layers should all
689  // provide an interface-specific route to these addresses such
690  // that we can treat these multicast addresses as "not broadcast"
691 
692  if (m_endPoint6->GetLocalAddress () != Ipv6Address::GetAny ())
693  {
694  m_udp->Send (p->Copy (), m_endPoint6->GetLocalAddress (), dest,
695  m_endPoint6->GetLocalPort (), port, 0);
696  NotifyDataSent (p->GetSize ());
697  NotifySend (GetTxAvailable ());
698  return p->GetSize ();
699  }
700  else if (ipv6->GetRoutingProtocol () != 0)
701  {
702  Ipv6Header header;
703  header.SetDestinationAddress (dest);
704  header.SetNextHeader (UdpL4Protocol::PROT_NUMBER);
705  Socket::SocketErrno errno_;
706  Ptr<Ipv6Route> route;
707  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
708  // TBD-- we could cache the route and just check its validity
709  route = ipv6->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
710  if (route != 0)
711  {
712  NS_LOG_LOGIC ("Route exists");
713  header.SetSourceAddress (route->GetSource ());
714  m_udp->Send (p->Copy (), header.GetSourceAddress (), header.GetDestinationAddress (),
715  m_endPoint6->GetLocalPort (), port, route);
716  NotifyDataSent (p->GetSize ());
717  return p->GetSize ();
718  }
719  else
720  {
721  NS_LOG_LOGIC ("No route to destination");
722  NS_LOG_ERROR (errno_);
723  m_errno = errno_;
724  return -1;
725  }
726  }
727  else
728  {
729  NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
730  m_errno = ERROR_NOROUTETOHOST;
731  return -1;
732  }
733 
734  return 0;
735 }
736 
737 // XXX maximum message size for UDP broadcast is limited by MTU
738 // size of underlying link; we are not checking that now.
739 uint32_t
741 {
743  // No finite send buffer is modelled, but we must respect
744  // the maximum size of an IP datagram (65535 bytes - headers).
745  return MAX_IPV4_UDP_DATAGRAM_SIZE;
746 }
747 
748 int
749 UdpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
750 {
751  NS_LOG_FUNCTION (this << p << flags << address);
752  if (InetSocketAddress::IsMatchingType (address))
753  {
754  if (IsManualIpTos ())
755  {
756  SocketIpTosTag ipTosTag;
757  ipTosTag.SetTos (GetIpTos ());
758  p->AddPacketTag (ipTosTag);
759  }
760 
762  Ipv4Address ipv4 = transport.GetIpv4 ();
763  uint16_t port = transport.GetPort ();
764  return DoSendTo (p, ipv4, port);
765  }
766  else if (Inet6SocketAddress::IsMatchingType (address))
767  {
768  if (IsManualIpv6Tclass ())
769  {
770  SocketIpv6TclassTag ipTclassTag;
771  ipTclassTag.SetTclass (GetIpv6Tclass ());
772  p->AddPacketTag (ipTclassTag);
773  }
774 
776  Ipv6Address ipv6 = transport.GetIpv6 ();
777  uint16_t port = transport.GetPort ();
778  return DoSendTo (p, ipv6, port);
779  }
780  return -1;
781 }
782 
783 uint32_t
785 {
787  // We separately maintain this state to avoid walking the queue
788  // every time this might be called
789  return m_rxAvailable;
790 }
791 
793 UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
794 {
795  NS_LOG_FUNCTION (this << maxSize << flags);
796  if (m_deliveryQueue.empty () )
797  {
798  m_errno = ERROR_AGAIN;
799  return 0;
800  }
801  Ptr<Packet> p = m_deliveryQueue.front ();
802  if (p->GetSize () <= maxSize)
803  {
804  m_deliveryQueue.pop ();
805  m_rxAvailable -= p->GetSize ();
806  }
807  else
808  {
809  p = 0;
810  }
811  return p;
812 }
813 
815 UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
816  Address &fromAddress)
817 {
818  NS_LOG_FUNCTION (this << maxSize << flags);
819  Ptr<Packet> packet = Recv (maxSize, flags);
820  if (packet != 0)
821  {
822  SocketAddressTag tag;
823  bool found;
824  found = packet->PeekPacketTag (tag);
825  NS_ASSERT (found);
826  fromAddress = tag.GetAddress ();
827  }
828  return packet;
829 }
830 
831 int
833 {
835  if (m_endPoint != 0)
836  {
837  address = InetSocketAddress (m_endPoint->GetLocalAddress (), m_endPoint->GetLocalPort ());
838  }
839  else
840  {
841  // It is possible to call this method on a socket without a name
842  // in which case, behavior is unspecified
843  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
844  }
845  return 0;
846 }
847 
848 int
849 UdpSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress)
850 {
851  NS_LOG_FUNCTION (interface << groupAddress);
852  /*
853  1) sanity check interface
854  2) sanity check that it has not been called yet on this interface/group
855  3) determine address family of groupAddress
856  4) locally store a list of (interface, groupAddress)
857  5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
858  */
859  return 0;
860 }
861 
862 int
863 UdpSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress)
864 {
865  NS_LOG_FUNCTION (interface << groupAddress);
866  /*
867  1) sanity check interface
868  2) determine address family of groupAddress
869  3) delete from local list of (interface, groupAddress); raise a LOG_WARN
870  if not already present (but return 0)
871  5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
872  */
873  return 0;
874 }
875 
876 void
878 {
879  NS_LOG_FUNCTION (netdevice);
880  Socket::BindToNetDevice (netdevice); // Includes sanity check
881  if (m_endPoint == 0)
882  {
883  if (Bind () == -1)
884  {
885  NS_ASSERT (m_endPoint == 0);
886  return;
887  }
888  NS_ASSERT (m_endPoint != 0);
889  }
890  m_endPoint->BindToNetDevice (netdevice);
891  return;
892 }
893 
894 void
895 UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
896  Ptr<Ipv4Interface> incomingInterface)
897 {
898  NS_LOG_FUNCTION (this << packet << header << port);
899 
900  if (m_shutdownRecv)
901  {
902  return;
903  }
904 
905  // Should check via getsockopt ()..
906  if (IsRecvPktInfo ())
907  {
908  Ipv4PacketInfoTag tag;
909  packet->RemovePacketTag (tag);
910  tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
911  packet->AddPacketTag (tag);
912  }
913 
914  //Check only version 4 options
915  if (IsIpRecvTos ())
916  {
917  SocketIpTosTag ipTosTag;
918  ipTosTag.SetTos (header.GetTos ());
919  packet->AddPacketTag (ipTosTag);
920  }
921 
922  if (IsIpRecvTtl ())
923  {
924  SocketIpTtlTag ipTtlTag;
925  ipTtlTag.SetTtl (header.GetTtl ());
926  packet->AddPacketTag (ipTtlTag);
927  }
928 
929  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
930  {
931  Address address = InetSocketAddress (header.GetSource (), port);
932  SocketAddressTag tag;
933  tag.SetAddress (address);
934  packet->AddPacketTag (tag);
935  m_deliveryQueue.push (packet);
936  m_rxAvailable += packet->GetSize ();
937  NotifyDataRecv ();
938  }
939  else
940  {
941  // In general, this case should not occur unless the
942  // receiving application reads data from this socket slowly
943  // in comparison to the arrival rate
944  //
945  // drop and trace packet
946  NS_LOG_WARN ("No receive buffer space available. Drop.");
947  m_dropTrace (packet);
948  }
949 }
950 
951 void
952 UdpSocketImpl::ForwardUp6 (Ptr<Packet> packet, Ipv6Header header, uint16_t port)
953 {
954  NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << port);
955 
956  if (m_shutdownRecv)
957  {
958  return;
959  }
960 
961 
962  //Check only version 6 options
963  if (IsIpv6RecvTclass ())
964  {
965  SocketIpv6TclassTag ipTclassTag;
966  ipTclassTag.SetTclass (header.GetTrafficClass ());
967  packet->AddPacketTag (ipTclassTag);
968  }
969 
970  if (IsIpv6RecvHopLimit ())
971  {
972  SocketIpv6HopLimitTag ipHopLimitTag;
973  ipHopLimitTag.SetHopLimit (header.GetHopLimit ());
974  packet->AddPacketTag (ipHopLimitTag);
975  }
976 
977  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
978  {
979  Address address = Inet6SocketAddress (header.GetSourceAddress (), port);
980  SocketAddressTag tag;
981  tag.SetAddress (address);
982  packet->AddPacketTag (tag);
983  m_deliveryQueue.push (packet);
984  m_rxAvailable += packet->GetSize ();
985  NotifyDataRecv ();
986  }
987  else
988  {
989  // In general, this case should not occur unless the
990  // receiving application reads data from this socket slowly
991  // in comparison to the arrival rate
992  //
993  // drop and trace packet
994  NS_LOG_WARN ("No receive buffer space available. Drop.");
995  m_dropTrace (packet);
996  }
997 }
998 
999 void
1000 UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1001  uint8_t icmpType, uint8_t icmpCode,
1002  uint32_t icmpInfo)
1003 {
1004  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1005  (uint32_t)icmpCode << icmpInfo);
1006  if (!m_icmpCallback.IsNull ())
1007  {
1008  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1009  }
1010 }
1011 
1012 void
1013 UdpSocketImpl::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1014  uint8_t icmpType, uint8_t icmpCode,
1015  uint32_t icmpInfo)
1016 {
1017  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1018  (uint32_t)icmpCode << icmpInfo);
1019  if (!m_icmpCallback6.IsNull ())
1020  {
1021  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1022  }
1023 }
1024 
1025 void
1026 UdpSocketImpl::SetRcvBufSize (uint32_t size)
1027 {
1028  m_rcvBufSize = size;
1029 }
1030 
1031 uint32_t
1032 UdpSocketImpl::GetRcvBufSize (void) const
1033 {
1034  return m_rcvBufSize;
1035 }
1036 
1037 void
1038 UdpSocketImpl::SetIpMulticastTtl (uint8_t ipTtl)
1039 {
1040  m_ipMulticastTtl = ipTtl;
1041 }
1042 
1043 uint8_t
1044 UdpSocketImpl::GetIpMulticastTtl (void) const
1045 {
1046  return m_ipMulticastTtl;
1047 }
1048 
1049 void
1050 UdpSocketImpl::SetIpMulticastIf (int32_t ipIf)
1051 {
1052  m_ipMulticastIf = ipIf;
1053 }
1054 
1055 int32_t
1056 UdpSocketImpl::GetIpMulticastIf (void) const
1057 {
1058  return m_ipMulticastIf;
1059 }
1060 
1061 void
1062 UdpSocketImpl::SetIpMulticastLoop (bool loop)
1063 {
1064  m_ipMulticastLoop = loop;
1065 }
1066 
1067 bool
1068 UdpSocketImpl::GetIpMulticastLoop (void) const
1069 {
1070  return m_ipMulticastLoop;
1071 }
1072 
1073 void
1074 UdpSocketImpl::SetMtuDiscover (bool discover)
1075 {
1076  m_mtuDiscover = discover;
1077 }
1078 bool
1079 UdpSocketImpl::GetMtuDiscover (void) const
1080 {
1081  return m_mtuDiscover;
1082 }
1083 
1084 bool
1086 {
1087  m_allowBroadcast = allowBroadcast;
1088  return true;
1089 }
1090 
1091 bool
1093 {
1094  return m_allowBroadcast;
1095 }
1096 
1097 
1098 } // namespace ns3
static bool IsMatchingType(const Address &address)
If the Address matches the type.
Ipv6Address GetLocalAddress()
Get the local address.
static Ipv4Mask GetOnes(void)
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
an Inet address class
Ipv4Address GetIpv4(void) const
static Ipv4Address GetAny(void)
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
bool IsIpv6RecvHopLimit(void) const
Ask if the socket is currently passing information about IPv6 Hop Limit up the stack.
Definition: socket.cc:507
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:174
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
virtual int Close(void)
Close a socket.
#define NS_ASSERT(condition)
Definition: assert.h:64
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:363
a polymophic address class
Definition: address.h:86
virtual int Bind(void)
Allocate a local IPv4 endpoint for this socket.
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
virtual enum SocketErrno GetErrno(void) const
bool IsIpRecvTos(void) const
Ask if the socket is currently passing information about IP Type of Service up the stack...
Definition: socket.cc:415
Packet header for IPv4.
Definition: ipv4-header.h:31
virtual int ShutdownRecv(void)
virtual int GetSockName(Address &address) const
bool PeekPacketTag(Tag &tag) const
Definition: packet.cc:881
virtual int MulticastLeaveGroup(uint32_t interfaceIndex, const Address &groupAddress)
Corresponds to socket option MCAST_LEAVE_GROUP.
uint16_t GetLocalPort()
Get the local port.
virtual uint32_t GetRxAvailable(void) const
virtual int Bind6(void)
Allocate a local IPv6 endpoint for this socket.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
virtual int MulticastJoinGroup(uint32_t interfaceIndex, const Address &groupAddress)
Corresponds to socket option MCAST_JOIN_GROUP.
virtual enum SocketType GetSocketType(void) const
An Inet6 address class.
This class implements a tag that carries an address of a packet across the socket interface...
Definition: socket.h:847
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
static bool IsMatchingType(const Address &address)
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
static InetSocketAddress ConvertFrom(const Address &address)
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
void SetIcmpCallback(Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
static Ipv4Address GetZero(void)
bool IsIpv6RecvTclass(void) const
Ask if the socket is currently passing information about IPv6 Traffic Class up the stack...
Definition: socket.cc:457
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv6Header, uint16_t > callback)
Set the reception callback.
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:329
virtual int ShutdownSend(void)
bool IsIpRecvTtl(void) const
Ask if the socket is currently passing information about IP_TTL up the stack.
Definition: socket.cc:482
Describes an IPv6 address.
Definition: ipv6-address.h:44
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
#define NS_LOG_WARN(msg)
Definition: log.h:246
Ptr< NetDevice > GetDevice(void) const
virtual int Listen(void)
Listen for incoming connections.
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:874
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &address)
Send data to a specified peer.
static bool IsMatchingType(const Address &addr)
If the address match.
uint16_t GetPort(void) const
Get the port.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
#define NS_LOG_ERROR(msg)
Definition: log.h:237
uint16_t GetPort(void) const
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:264
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
static Ipv4Address ConvertFrom(const Address &address)
Ptr< T > GetObject(void) const
Definition: object.h:332
static bool IsMatchingType(const Address &address)
static Ipv6Address ConvertFrom(const Address &address)
Convert the Address object into an Ipv6Address ones.
virtual Ptr< Node > GetNode(void) const