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 freebsd linux netbsd openbsd windows
18 var ErrWriteToConnected
= errors
.New("use of WriteTo with pre-connected UDP")
20 func sockaddrToUDP(sa syscall
.Sockaddr
) Addr
{
21 switch sa
:= sa
.(type) {
22 case *syscall
.SockaddrInet4
:
23 return &UDPAddr
{sa
.Addr
[0:], sa
.Port
}
24 case *syscall
.SockaddrInet6
:
25 return &UDPAddr
{sa
.Addr
[0:], sa
.Port
}
30 func (a
*UDPAddr
) family() int {
31 if a
== nil ||
len(a
.IP
) <= IPv4len
{
32 return syscall
.AF_INET
34 if a
.IP
.To4() != nil {
35 return syscall
.AF_INET
37 return syscall
.AF_INET6
40 func (a
*UDPAddr
) isWildcard() bool {
41 if a
== nil || a
.IP
== nil {
44 return a
.IP
.IsUnspecified()
47 func (a
*UDPAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
48 return ipToSockaddr(family
, a
.IP
, a
.Port
)
51 func (a
*UDPAddr
) toAddr() sockaddr
{
52 if a
== nil { // nil *UDPAddr
53 return nil // nil interface
58 // UDPConn is the implementation of the Conn and PacketConn
59 // interfaces for UDP network connections.
64 func newUDPConn(fd
*netFD
) *UDPConn
{ return &UDPConn
{fd
} }
66 func (c
*UDPConn
) ok() bool { return c
!= nil && c
.fd
!= nil }
68 // Implementation of the Conn interface - see Conn for documentation.
70 // Read implements the Conn Read method.
71 func (c
*UDPConn
) Read(b
[]byte) (int, error
) {
73 return 0, syscall
.EINVAL
78 // Write implements the Conn Write method.
79 func (c
*UDPConn
) Write(b
[]byte) (int, error
) {
81 return 0, syscall
.EINVAL
86 // Close closes the UDP connection.
87 func (c
*UDPConn
) Close() error
{
94 // LocalAddr returns the local network address.
95 func (c
*UDPConn
) LocalAddr() Addr
{
102 // RemoteAddr returns the remote network address, a *UDPAddr.
103 func (c
*UDPConn
) RemoteAddr() Addr
{
110 // SetDeadline implements the Conn SetDeadline method.
111 func (c
*UDPConn
) SetDeadline(t time
.Time
) error
{
113 return syscall
.EINVAL
115 return setDeadline(c
.fd
, t
)
118 // SetReadDeadline implements the Conn SetReadDeadline method.
119 func (c
*UDPConn
) SetReadDeadline(t time
.Time
) error
{
121 return syscall
.EINVAL
123 return setReadDeadline(c
.fd
, t
)
126 // SetWriteDeadline implements the Conn SetWriteDeadline method.
127 func (c
*UDPConn
) SetWriteDeadline(t time
.Time
) error
{
129 return syscall
.EINVAL
131 return setWriteDeadline(c
.fd
, t
)
134 // SetReadBuffer sets the size of the operating system's
135 // receive buffer associated with the connection.
136 func (c
*UDPConn
) SetReadBuffer(bytes
int) error
{
138 return syscall
.EINVAL
140 return setReadBuffer(c
.fd
, bytes
)
143 // SetWriteBuffer sets the size of the operating system's
144 // transmit buffer associated with the connection.
145 func (c
*UDPConn
) SetWriteBuffer(bytes
int) error
{
147 return syscall
.EINVAL
149 return setWriteBuffer(c
.fd
, bytes
)
152 // UDP-specific methods.
154 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
155 // It returns the number of bytes copied into b and the return address
156 // that was on the packet.
158 // ReadFromUDP can be made to time out and return an error with Timeout() == true
159 // after a fixed time limit; see SetDeadline and SetReadDeadline.
160 func (c
*UDPConn
) ReadFromUDP(b
[]byte) (n
int, addr
*UDPAddr
, err error
) {
162 return 0, nil, syscall
.EINVAL
164 n
, sa
, err
:= c
.fd
.ReadFrom(b
)
165 switch sa
:= sa
.(type) {
166 case *syscall
.SockaddrInet4
:
167 addr
= &UDPAddr
{sa
.Addr
[0:], sa
.Port
}
168 case *syscall
.SockaddrInet6
:
169 addr
= &UDPAddr
{sa
.Addr
[0:], sa
.Port
}
174 // ReadFrom implements the PacketConn ReadFrom method.
175 func (c
*UDPConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
177 return 0, nil, syscall
.EINVAL
179 n
, uaddr
, err
:= c
.ReadFromUDP(b
)
180 return n
, uaddr
.toAddr(), err
183 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
185 // WriteToUDP can be made to time out and return
186 // an error with Timeout() == true after a fixed time limit;
187 // see SetDeadline and SetWriteDeadline.
188 // On packet-oriented connections, write timeouts are rare.
189 func (c
*UDPConn
) WriteToUDP(b
[]byte, addr
*UDPAddr
) (int, error
) {
191 return 0, syscall
.EINVAL
193 if c
.fd
.isConnected
{
194 return 0, &OpError
{"write", c
.fd
.net
, addr
, ErrWriteToConnected
}
196 sa
, err
:= addr
.sockaddr(c
.fd
.family
)
198 return 0, &OpError
{"write", c
.fd
.net
, addr
, err
}
200 return c
.fd
.WriteTo(b
, sa
)
203 // WriteTo implements the PacketConn WriteTo method.
204 func (c
*UDPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
206 return 0, syscall
.EINVAL
208 a
, ok
:= addr
.(*UDPAddr
)
210 return 0, &OpError
{"write", c
.fd
.net
, addr
, syscall
.EINVAL
}
212 return c
.WriteToUDP(b
, a
)
215 // File returns a copy of the underlying os.File, set to blocking mode.
216 // It is the caller's responsibility to close f when finished.
217 // Closing c does not affect f, and closing f does not affect c.
218 func (c
*UDPConn
) File() (f
*os
.File
, err error
) { return c
.fd
.dup() }
220 // DialUDP connects to the remote address raddr on the network net,
221 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used
222 // as the local address for the connection.
223 func DialUDP(net
string, laddr
, raddr
*UDPAddr
) (*UDPConn
, error
) {
225 case "udp", "udp4", "udp6":
227 return nil, UnknownNetworkError(net
)
230 return nil, &OpError
{"dial", net
, nil, errMissingAddress
}
232 fd
, err
:= internetSocket(net
, laddr
.toAddr(), raddr
.toAddr(), syscall
.SOCK_DGRAM
, 0, "dial", sockaddrToUDP
)
236 return newUDPConn(fd
), nil
239 // ListenUDP listens for incoming UDP packets addressed to the
240 // local address laddr. The returned connection c's ReadFrom
241 // and WriteTo methods can be used to receive and send UDP
242 // packets with per-packet addressing.
243 func ListenUDP(net
string, laddr
*UDPAddr
) (*UDPConn
, error
) {
245 case "udp", "udp4", "udp6":
247 return nil, UnknownNetworkError(net
)
250 return nil, &OpError
{"listen", net
, nil, errMissingAddress
}
252 fd
, err
:= internetSocket(net
, laddr
.toAddr(), nil, syscall
.SOCK_DGRAM
, 0, "listen", sockaddrToUDP
)
256 return newUDPConn(fd
), nil
259 // ListenMulticastUDP listens for incoming multicast UDP packets
260 // addressed to the group address gaddr on ifi, which specifies
261 // the interface to join. ListenMulticastUDP uses default
262 // multicast interface if ifi is nil.
263 func ListenMulticastUDP(net
string, ifi
*Interface
, gaddr
*UDPAddr
) (*UDPConn
, error
) {
265 case "udp", "udp4", "udp6":
267 return nil, UnknownNetworkError(net
)
269 if gaddr
== nil || gaddr
.IP
== nil {
270 return nil, &OpError
{"listenmulticast", net
, nil, errMissingAddress
}
272 fd
, err
:= internetSocket(net
, gaddr
.toAddr(), nil, syscall
.SOCK_DGRAM
, 0, "listen", sockaddrToUDP
)
277 ip4
:= gaddr
.IP
.To4()
279 err
:= listenIPv4MulticastUDP(c
, ifi
, ip4
)
285 err
:= listenIPv6MulticastUDP(c
, ifi
, gaddr
.IP
)
294 func listenIPv4MulticastUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
296 err
:= setIPv4MulticastInterface(c
.fd
, ifi
)
301 err
:= setIPv4MulticastLoopback(c
.fd
, false)
305 err
= joinIPv4GroupUDP(c
, ifi
, ip
)
312 func listenIPv6MulticastUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
314 err
:= setIPv6MulticastInterface(c
.fd
, ifi
)
319 err
:= setIPv6MulticastLoopback(c
.fd
, false)
323 err
= joinIPv6GroupUDP(c
, ifi
, ip
)
330 func joinIPv4GroupUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
331 err
:= joinIPv4Group(c
.fd
, ifi
, ip
)
333 return &OpError
{"joinipv4group", c
.fd
.net
, &IPAddr
{ip
}, err
}
338 func leaveIPv4GroupUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
339 err
:= leaveIPv4Group(c
.fd
, ifi
, ip
)
341 return &OpError
{"leaveipv4group", c
.fd
.net
, &IPAddr
{ip
}, err
}
346 func joinIPv6GroupUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
347 err
:= joinIPv6Group(c
.fd
, ifi
, ip
)
349 return &OpError
{"joinipv6group", c
.fd
.net
, &IPAddr
{ip
}, err
}
354 func leaveIPv6GroupUDP(c
*UDPConn
, ifi
*Interface
, ip IP
) error
{
355 err
:= leaveIPv6Group(c
.fd
, ifi
, ip
)
357 return &OpError
{"leaveipv6group", c
.fd
.net
, &IPAddr
{ip
}, err
}