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"
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"
45 NS_OBJECT_ENSURE_REGISTERED (UdpSocketImpl);
47 static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
51 UdpSocketImpl::GetTypeId (
void)
53 static TypeId tid = TypeId (
"ns3::UdpSocketImpl")
54 .SetParent<UdpSocket> ()
55 .AddConstructor<UdpSocketImpl> ()
56 .AddTraceSource (
"Drop",
"Drop UDP packet due to receive buffer overflow",
58 .AddAttribute (
"IcmpCallback",
"Callback invoked whenever an icmp error is received on this socket.",
60 MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
61 MakeCallbackChecker ())
62 .AddAttribute (
"IcmpCallback6",
"Callback invoked whenever an icmpv6 error is received on this socket.",
64 MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback6),
65 MakeCallbackChecker ())
75 m_errno (ERROR_NOTERROR),
76 m_shutdownSend (false),
77 m_shutdownRecv (false),
82 m_allowBroadcast =
false;
108 m_udp->DeAllocate (m_endPoint);
111 if (m_endPoint6 != 0)
123 m_udp->DeAllocate (m_endPoint6);
137 UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
144 enum Socket::SocketErrno
151 enum Socket::SocketType
154 return NS3_SOCK_DGRAM;
165 UdpSocketImpl::Destroy (
void)
172 UdpSocketImpl::Destroy6 (
void)
179 UdpSocketImpl::FinishBind (
void)
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)));
190 if (m_endPoint6 != 0)
208 m_endPoint = m_udp->Allocate ();
209 return FinishBind ();
216 m_endPoint6 = m_udp->Allocate6 ();
217 return FinishBind ();
229 uint16_t port = transport.
GetPort ();
232 m_endPoint = m_udp->Allocate ();
236 m_endPoint = m_udp->Allocate (port);
240 m_endPoint = m_udp->Allocate (ipv4);
244 m_endPoint = m_udp->Allocate (ipv4, port);
251 uint16_t port = transport.
GetPort ();
254 m_endPoint6 = m_udp->Allocate6 ();
258 m_endPoint6 = m_udp->Allocate6 (port);
262 m_endPoint6 = m_udp->Allocate6 (ipv6);
266 m_endPoint6 = m_udp->Allocate6 (ipv6, port);
272 m_errno = ERROR_INVAL;
276 return FinishBind ();
283 m_shutdownSend =
true;
291 m_shutdownRecv =
true;
299 if (m_shutdownRecv ==
true && m_shutdownSend ==
true)
301 m_errno = Socket::ERROR_BADF;
304 m_shutdownRecv =
true;
305 m_shutdownSend =
true;
317 m_defaultPort = transport.
GetPort ();
319 NotifyConnectionSucceeded ();
325 m_defaultPort = transport.
GetPort ();
327 NotifyConnectionSucceeded ();
340 m_errno = Socket::ERROR_OPNOTSUPP;
351 m_errno = ERROR_NOTCONN;
382 m_errno = ERROR_SHUTDOWN;
386 return DoSendTo (p, (
const Address)m_defaultAddress);
390 UdpSocketImpl::DoSendTo (Ptr<Packet> p,
const Address &address)
400 Ipv4Address ipv4 = transport.GetIpv4 ();
401 uint16_t port = transport.GetPort ();
402 return DoSendTo (p, ipv4, port);
407 Ipv6Address ipv6 = transport.GetIpv6 ();
408 uint16_t port = transport.GetPort ();
409 return DoSendTo (p, ipv6, port);
429 m_errno = ERROR_AFNOSUPPORT;
434 UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
437 if (m_boundnetdevice)
439 NS_LOG_LOGIC (
"Bound interface number " << m_boundnetdevice->GetIfIndex ());
452 m_errno = ERROR_SHUTDOWN;
458 m_errno = ERROR_MSGSIZE;
462 if (IsManualIpTos ())
464 SocketIpTosTag ipTosTag;
465 ipTosTag.SetTos (GetIpTos ());
466 p->AddPacketTag (ipTosTag);
469 Ptr<Ipv4> ipv4 = m_node->
GetObject<Ipv4> ();
479 if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
482 tag.SetTtl (m_ipMulticastTtl);
483 p->AddPacketTag (tag);
485 else if (IsManualIpTtl () && GetIpTtl () != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
488 tag.SetTtl (GetIpTtl ());
489 p->AddPacketTag (tag);
492 SocketSetDontFragmentTag tag;
493 bool found = p->RemovePacketTag (tag);
504 p->AddPacketTag (tag);
516 if (dest.IsBroadcast ())
518 if (!m_allowBroadcast)
520 m_errno = ERROR_OPNOTSUPP;
524 for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
527 Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0);
528 Ipv4Address addri = iaddr.GetLocal ();
529 if (addri == Ipv4Address (
"127.0.0.1"))
532 if (m_boundnetdevice)
534 if (ipv4->GetNetDevice (i) != m_boundnetdevice)
537 Ipv4Mask maski = iaddr.GetMask ();
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 ());
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 ());
561 return p->GetSize ();
565 m_udp->Send (p->Copy (), m_endPoint->GetLocalAddress (), dest,
566 m_endPoint->GetLocalPort (), port, 0);
567 NotifyDataSent (p->GetSize ());
569 return p->GetSize ();
571 else if (ipv4->GetRoutingProtocol () != 0)
574 header.SetDestination (dest);
575 header.SetProtocol (UdpL4Protocol::PROT_NUMBER);
576 Socket::SocketErrno errno_;
577 Ptr<Ipv4Route> route;
578 Ptr<NetDevice> oif = m_boundnetdevice;
580 route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
584 if (!m_allowBroadcast)
586 uint32_t outputIfIndex = ipv4->GetInterfaceForDevice (route->GetOutputDevice ());
587 uint32_t ifNAddr = ipv4->GetNAddresses (outputIfIndex);
588 for (uint32_t addrI = 0; addrI < ifNAddr; ++addrI)
590 Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (outputIfIndex, addrI);
591 if (dest == ifAddr.GetBroadcast ())
593 m_errno = ERROR_OPNOTSUPP;
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 ();
616 m_errno = ERROR_NOROUTETOHOST;
624 UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv6Address dest, uint16_t port)
628 if (dest.IsIpv4MappedAddress ())
630 return (DoSendTo(p, dest.GetIpv4MappedAddress (), port));
632 if (m_boundnetdevice)
634 NS_LOG_LOGIC (
"Bound interface number " << m_boundnetdevice->GetIfIndex ());
636 if (m_endPoint6 == 0)
647 m_errno = ERROR_SHUTDOWN;
653 m_errno = ERROR_MSGSIZE;
657 if (IsManualIpv6Tclass ())
659 SocketIpv6TclassTag ipTclassTag;
660 ipTclassTag.SetTclass (GetIpv6Tclass ());
661 p->AddPacketTag (ipTclassTag);
664 Ptr<Ipv6> ipv6 = m_node->
GetObject<Ipv6> ();
674 if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
676 SocketIpv6HopLimitTag tag;
677 tag.SetHopLimit (m_ipMulticastTtl);
678 p->AddPacketTag (tag);
680 else if (IsManualIpv6HopLimit () && GetIpv6HopLimit () != 0 && !dest.IsMulticast ())
682 SocketIpv6HopLimitTag tag;
683 tag.SetHopLimit (GetIpv6HopLimit ());
684 p->AddPacketTag (tag);
696 NotifyDataSent (p->GetSize ());
698 return p->GetSize ();
700 else if (ipv6->GetRoutingProtocol () != 0)
703 header.SetDestinationAddress (dest);
704 header.SetNextHeader (UdpL4Protocol::PROT_NUMBER);
705 Socket::SocketErrno errno_;
706 Ptr<Ipv6Route> route;
707 Ptr<NetDevice> oif = m_boundnetdevice;
709 route = ipv6->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
713 header.SetSourceAddress (route->GetSource ());
714 m_udp->Send (p->Copy (), header.GetSourceAddress (), header.GetDestinationAddress (),
716 NotifyDataSent (p->GetSize ());
717 return p->GetSize ();
730 m_errno = ERROR_NOROUTETOHOST;
745 return MAX_IPV4_UDP_DATAGRAM_SIZE;
754 if (IsManualIpTos ())
757 ipTosTag.SetTos (GetIpTos ());
763 uint16_t port = transport.
GetPort ();
764 return DoSendTo (p, ipv4, port);
768 if (IsManualIpv6Tclass ())
771 ipTclassTag.SetTclass (GetIpv6Tclass ());
777 uint16_t port = transport.
GetPort ();
778 return DoSendTo (p, ipv6, port);
789 return m_rxAvailable;
796 if (m_deliveryQueue.empty () )
798 m_errno = ERROR_AGAIN;
804 m_deliveryQueue.pop ();
805 m_rxAvailable -= p->
GetSize ();
826 fromAddress = tag.GetAddress ();
837 address =
InetSocketAddress (m_endPoint->GetLocalAddress (), m_endPoint->GetLocalPort ());
890 m_endPoint->BindToNetDevice (netdevice);
908 Ipv4PacketInfoTag tag;
910 tag.SetRecvIf (incomingInterface->
GetDevice ()->GetIfIndex ());
917 SocketIpTosTag ipTosTag;
918 ipTosTag.SetTos (header.
GetTos ());
924 SocketIpTtlTag ipTtlTag;
925 ipTtlTag.SetTtl (header.
GetTtl ());
929 if ((m_rxAvailable + packet->
GetSize ()) <= m_rcvBufSize)
931 Address address = InetSocketAddress (header.
GetSource (), port);
932 SocketAddressTag tag;
933 tag.SetAddress (address);
935 m_deliveryQueue.push (packet);
936 m_rxAvailable += packet->
GetSize ();
946 NS_LOG_WARN (
"No receive buffer space available. Drop.");
947 m_dropTrace (packet);
952 UdpSocketImpl::ForwardUp6 (Ptr<Packet> packet, Ipv6Header header, uint16_t port)
954 NS_LOG_FUNCTION (
this << packet << header.GetSourceAddress () << port);
965 SocketIpv6TclassTag ipTclassTag;
966 ipTclassTag.SetTclass (header.GetTrafficClass ());
967 packet->AddPacketTag (ipTclassTag);
972 SocketIpv6HopLimitTag ipHopLimitTag;
973 ipHopLimitTag.SetHopLimit (header.GetHopLimit ());
974 packet->AddPacketTag (ipHopLimitTag);
977 if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
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 ();
994 NS_LOG_WARN (
"No receive buffer space available. Drop.");
995 m_dropTrace (packet);
1000 UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1001 uint8_t icmpType, uint8_t icmpCode,
1004 NS_LOG_FUNCTION (
this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1005 (uint32_t)icmpCode << icmpInfo);
1006 if (!m_icmpCallback.IsNull ())
1008 m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1013 UdpSocketImpl::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1014 uint8_t icmpType, uint8_t icmpCode,
1017 NS_LOG_FUNCTION (
this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1018 (uint32_t)icmpCode << icmpInfo);
1019 if (!m_icmpCallback6.IsNull ())
1021 m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1026 UdpSocketImpl::SetRcvBufSize (uint32_t size)
1028 m_rcvBufSize = size;
1032 UdpSocketImpl::GetRcvBufSize (
void)
const
1034 return m_rcvBufSize;
1038 UdpSocketImpl::SetIpMulticastTtl (uint8_t ipTtl)
1040 m_ipMulticastTtl = ipTtl;
1044 UdpSocketImpl::GetIpMulticastTtl (
void)
const
1046 return m_ipMulticastTtl;
1050 UdpSocketImpl::SetIpMulticastIf (int32_t ipIf)
1052 m_ipMulticastIf = ipIf;
1056 UdpSocketImpl::GetIpMulticastIf (
void)
const
1058 return m_ipMulticastIf;
1062 UdpSocketImpl::SetIpMulticastLoop (
bool loop)
1064 m_ipMulticastLoop = loop;
1068 UdpSocketImpl::GetIpMulticastLoop (
void)
const
1070 return m_ipMulticastLoop;
1074 UdpSocketImpl::SetMtuDiscover (
bool discover)
1076 m_mtuDiscover = discover;
1079 UdpSocketImpl::GetMtuDiscover (
void)
const
1081 return m_mtuDiscover;
1087 m_allowBroadcast = allowBroadcast;
1094 return m_allowBroadcast;
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.
Ipv4Address GetIpv4(void) const
static Ipv4Address GetAny(void)
#define NS_LOG_FUNCTION(parameters)
bool IsIpv6RecvHopLimit(void) const
Ask if the socket is currently passing information about IPv6 Hop Limit up the stack.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
void AddPacketTag(const Tag &tag) const
virtual int Close(void)
Close a socket.
#define NS_ASSERT(condition)
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
uint32_t GetSize(void) const
#define NS_LOG_FUNCTION_NOARGS()
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.
a polymophic address class
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...
virtual int ShutdownRecv(void)
virtual int GetSockName(Address &address) const
bool PeekPacketTag(Tag &tag) const
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
This class implements a tag that carries an address of a packet across the socket interface...
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
static bool IsMatchingType(const Address &address)
#define NS_LOG_LOGIC(msg)
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...
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.
virtual int ShutdownSend(void)
bool IsIpRecvTtl(void) const
Ask if the socket is currently passing information about IP_TTL up the stack.
Describes an IPv6 address.
Ipv4 addresses are stored in host order in this class.
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.
Ptr< NetDevice > GetDevice(void) const
virtual int Listen(void)
Listen for incoming connections.
bool RemovePacketTag(Tag &tag)
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)
uint16_t GetPort(void) const
static Ipv4Address ConvertFrom(const Address &address)
Ptr< T > GetObject(void) const
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