1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
14 func sockaddrToUDP(sa syscall
.Sockaddr
) Addr
{
15 switch sa
:= sa
.(type) {
16 case *syscall
.SockaddrInet4
:
17 return &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
}
18 case *syscall
.SockaddrInet6
:
19 return &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
, Zone
: zoneCache
.name(int(sa
.ZoneId
))}
24 func (a
*UDPAddr
) family() int {
25 if a
== nil ||
len(a
.IP
) <= IPv4len
{
26 return syscall
.AF_INET
28 if a
.IP
.To4() != nil {
29 return syscall
.AF_INET
31 return syscall
.AF_INET6
34 func (a
*UDPAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
38 return ipToSockaddr(family
, a
.IP
, a
.Port
, a
.Zone
)
41 func (a
*UDPAddr
) toLocal(net
string) sockaddr
{
42 return &UDPAddr
{loopbackIP(net
), a
.Port
, a
.Zone
}
45 func (c
*UDPConn
) readFrom(b
[]byte) (int, *UDPAddr
, error
) {
47 n
, sa
, err
:= c
.fd
.readFrom(b
)
48 switch sa
:= sa
.(type) {
49 case *syscall
.SockaddrInet4
:
50 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
}
51 case *syscall
.SockaddrInet6
:
52 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
, Zone
: zoneCache
.name(int(sa
.ZoneId
))}
57 func (c
*UDPConn
) readMsg(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UDPAddr
, err error
) {
58 var sa syscall
.Sockaddr
59 n
, oobn
, flags
, sa
, err
= c
.fd
.readMsg(b
, oob
)
60 switch sa
:= sa
.(type) {
61 case *syscall
.SockaddrInet4
:
62 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
}
63 case *syscall
.SockaddrInet6
:
64 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
, Zone
: zoneCache
.name(int(sa
.ZoneId
))}
69 func (c
*UDPConn
) writeTo(b
[]byte, addr
*UDPAddr
) (int, error
) {
71 return 0, ErrWriteToConnected
74 return 0, errMissingAddress
76 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
80 return c
.fd
.writeTo(b
, sa
)
83 func (c
*UDPConn
) writeMsg(b
, oob
[]byte, addr
*UDPAddr
) (n
, oobn
int, err error
) {
84 if c
.fd
.isConnected
&& addr
!= nil {
85 return 0, 0, ErrWriteToConnected
87 if !c
.fd
.isConnected
&& addr
== nil {
88 return 0, 0, errMissingAddress
90 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
94 return c
.fd
.writeMsg(b
, oob
, sa
)
97 func dialUDP(ctx context
.Context
, net
string, laddr
, raddr
*UDPAddr
) (*UDPConn
, error
) {
98 fd
, err
:= internetSocket(ctx
, net
, laddr
, raddr
, syscall
.SOCK_DGRAM
, 0, "dial")
102 return newUDPConn(fd
), nil
105 func listenUDP(ctx context
.Context
, network
string, laddr
*UDPAddr
) (*UDPConn
, error
) {
106 fd
, err
:= internetSocket(ctx
, network
, laddr
, nil, syscall
.SOCK_DGRAM
, 0, "listen")
110 return newUDPConn(fd
), nil
113 func listenMulticastUDP(ctx context
.Context
, network
string, ifi
*Interface
, gaddr
*UDPAddr
) (*UDPConn
, error
) {
114 fd
, err
:= internetSocket(ctx
, network
, gaddr
, nil, syscall
.SOCK_DGRAM
, 0, "listen")
119 if ip4
:= gaddr
.IP
.To4(); ip4
!= nil {
120 if err
:= listenIPv4MulticastUDP(c
, ifi
, ip4
); err
!= nil {
125 if err
:= listenIPv6MulticastUDP(c
, ifi
, gaddr
.IP
); err
!= nil {
133 func listenIPv4MulticastUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
135 if err
:= setIPv4MulticastInterface(c
.fd
, ifi
); err
!= nil {
139 if err
:= setIPv4MulticastLoopback(c
.fd
, false); err
!= nil {
142 if err
:= joinIPv4Group(c
.fd
, ifi
, ip
); err
!= nil {
148 func listenIPv6MulticastUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
150 if err
:= setIPv6MulticastInterface(c
.fd
, ifi
); err
!= nil {
154 if err
:= setIPv6MulticastLoopback(c
.fd
, false); err
!= nil {
157 if err
:= joinIPv6Group(c
.fd
, ifi
, ip
); err
!= nil {