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 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
: zoneToString(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
) isWildcard() bool {
35 if a
== nil || a
.IP
== nil {
38 return a
.IP
.IsUnspecified()
41 func (a
*UDPAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
45 return ipToSockaddr(family
, a
.IP
, a
.Port
, a
.Zone
)
48 // UDPConn is the implementation of the Conn and PacketConn interfaces
49 // for UDP network connections.
54 func newUDPConn(fd
*netFD
) *UDPConn
{ return &UDPConn
{conn
{fd
}} }
56 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
57 // It returns the number of bytes copied into b and the return address
58 // that was on the packet.
60 // ReadFromUDP can be made to time out and return an error with
61 // Timeout() == true after a fixed time limit; see SetDeadline and
63 func (c
*UDPConn
) ReadFromUDP(b
[]byte) (n
int, addr
*UDPAddr
, err error
) {
65 return 0, nil, syscall
.EINVAL
67 n
, sa
, err
:= c
.fd
.readFrom(b
)
68 switch sa
:= sa
.(type) {
69 case *syscall
.SockaddrInet4
:
70 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
}
71 case *syscall
.SockaddrInet6
:
72 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
, Zone
: zoneToString(int(sa
.ZoneId
))}
77 // ReadFrom implements the PacketConn ReadFrom method.
78 func (c
*UDPConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
80 return 0, nil, syscall
.EINVAL
82 n
, addr
, err
:= c
.ReadFromUDP(b
)
83 return n
, addr
.toAddr(), err
86 // ReadMsgUDP reads a packet from c, copying the payload into b and
87 // the associated out-of-band data into oob. It returns the number
88 // of bytes copied into b, the number of bytes copied into oob, the
89 // flags that were set on the packet and the source address of the
91 func (c
*UDPConn
) ReadMsgUDP(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UDPAddr
, err error
) {
93 return 0, 0, 0, nil, syscall
.EINVAL
95 var sa syscall
.Sockaddr
96 n
, oobn
, flags
, sa
, err
= c
.fd
.readMsg(b
, oob
)
97 switch sa
:= sa
.(type) {
98 case *syscall
.SockaddrInet4
:
99 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
}
100 case *syscall
.SockaddrInet6
:
101 addr
= &UDPAddr
{IP
: sa
.Addr
[0:], Port
: sa
.Port
, Zone
: zoneToString(int(sa
.ZoneId
))}
106 // WriteToUDP writes a UDP packet to addr via c, copying the payload
109 // WriteToUDP can be made to time out and return an error with
110 // Timeout() == true after a fixed time limit; see SetDeadline and
111 // SetWriteDeadline. On packet-oriented connections, write timeouts
113 func (c
*UDPConn
) WriteToUDP(b
[]byte, addr
*UDPAddr
) (int, error
) {
115 return 0, syscall
.EINVAL
117 if c
.fd
.isConnected
{
118 return 0, &OpError
{"write", c
.fd
.net
, addr
, ErrWriteToConnected
}
121 return 0, &OpError
{Op
: "write", Net
: c
.fd
.net
, Addr
: nil, Err
: errMissingAddress
}
123 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
125 return 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
127 return c
.fd
.writeTo(b
, sa
)
130 // WriteTo implements the PacketConn WriteTo method.
131 func (c
*UDPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
133 return 0, syscall
.EINVAL
135 a
, ok
:= addr
.(*UDPAddr
)
137 return 0, &OpError
{"write", c
.fd
.net
, addr
, syscall
.EINVAL
}
139 return c
.WriteToUDP(b
, a
)
142 // WriteMsgUDP writes a packet to addr via c, copying the payload from
143 // b and the associated out-of-band data from oob. It returns the
144 // number of payload and out-of-band bytes written.
145 func (c
*UDPConn
) WriteMsgUDP(b
, oob
[]byte, addr
*UDPAddr
) (n
, oobn
int, err error
) {
147 return 0, 0, syscall
.EINVAL
149 if c
.fd
.isConnected
{
150 return 0, 0, &OpError
{"write", c
.fd
.net
, addr
, ErrWriteToConnected
}
153 return 0, 0, &OpError
{Op
: "write", Net
: c
.fd
.net
, Addr
: nil, Err
: errMissingAddress
}
155 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
157 return 0, 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
159 return c
.fd
.writeMsg(b
, oob
, sa
)
162 // DialUDP connects to the remote address raddr on the network net,
163 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
164 // used as the local address for the connection.
165 func DialUDP(net
string, laddr
, raddr
*UDPAddr
) (*UDPConn
, error
) {
167 case "udp", "udp4", "udp6":
169 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: raddr
, Err
: UnknownNetworkError(net
)}
172 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: nil, Err
: errMissingAddress
}
174 return dialUDP(net
, laddr
, raddr
, noDeadline
)
177 func dialUDP(net
string, laddr
, raddr
*UDPAddr
, deadline time
.Time
) (*UDPConn
, error
) {
178 fd
, err
:= internetSocket(net
, laddr
, raddr
, deadline
, syscall
.SOCK_DGRAM
, 0, "dial", sockaddrToUDP
)
180 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: raddr
, Err
: err
}
182 return newUDPConn(fd
), nil
185 // ListenUDP listens for incoming UDP packets addressed to the local
186 // address laddr. Net must be "udp", "udp4", or "udp6". If laddr has
187 // a port of 0, ListenUDP will choose an available port.
188 // The LocalAddr method of the returned UDPConn can be used to
189 // discover the port. The returned connection's ReadFrom and WriteTo
190 // methods can be used to receive and send UDP packets with per-packet
192 func ListenUDP(net
string, laddr
*UDPAddr
) (*UDPConn
, error
) {
194 case "udp", "udp4", "udp6":
196 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: UnknownNetworkError(net
)}
201 fd
, err
:= internetSocket(net
, laddr
, nil, noDeadline
, syscall
.SOCK_DGRAM
, 0, "listen", sockaddrToUDP
)
203 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: err
}
205 return newUDPConn(fd
), nil
208 // ListenMulticastUDP listens for incoming multicast UDP packets
209 // addressed to the group address gaddr on ifi, which specifies the
210 // interface to join. ListenMulticastUDP uses default multicast
211 // interface if ifi is nil.
212 func ListenMulticastUDP(net
string, ifi
*Interface
, gaddr
*UDPAddr
) (*UDPConn
, error
) {
214 case "udp", "udp4", "udp6":
216 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: gaddr
, Err
: UnknownNetworkError(net
)}
218 if gaddr
== nil || gaddr
.IP
== nil {
219 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: errMissingAddress
}
221 fd
, err
:= internetSocket(net
, gaddr
, nil, noDeadline
, syscall
.SOCK_DGRAM
, 0, "listen", sockaddrToUDP
)
223 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: gaddr
, Err
: err
}
226 if ip4
:= gaddr
.IP
.To4(); ip4
!= nil {
227 if err
:= listenIPv4MulticastUDP(c
, ifi
, ip4
); err
!= nil {
229 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: &IPAddr
{IP
: ip4
}, Err
: err
}
232 if err
:= listenIPv6MulticastUDP(c
, ifi
, gaddr
.IP
); err
!= nil {
234 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: &IPAddr
{IP
: gaddr
.IP
}, Err
: err
}
240 func listenIPv4MulticastUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
242 if err
:= setIPv4MulticastInterface(c
.fd
, ifi
); err
!= nil {
246 if err
:= setIPv4MulticastLoopback(c
.fd
, false); err
!= nil {
249 if err
:= joinIPv4Group(c
.fd
, ifi
, ip
); err
!= nil {
255 func listenIPv6MulticastUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
257 if err
:= setIPv6MulticastInterface(c
.fd
, ifi
); err
!= nil {
261 if err
:= setIPv6MulticastLoopback(c
.fd
, false); err
!= nil {
264 if err
:= joinIPv6Group(c
.fd
, ifi
, ip
); err
!= nil {