]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgo/go/net/udpsock.go
libgo: update to Go1.14beta1
[thirdparty/gcc.git] / libgo / go / net / udpsock.go
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.
4
5 package net
6
7 import (
8 "context"
9 "syscall"
10 )
11
12 // BUG(mikio): On Plan 9, the ReadMsgUDP and
13 // WriteMsgUDP methods of UDPConn are not implemented.
14
15 // BUG(mikio): On Windows, the File method of UDPConn is not
16 // implemented.
17
18 // BUG(mikio): On JS, methods and functions related to UDPConn are not
19 // implemented.
20
21 // UDPAddr represents the address of a UDP end point.
22 type UDPAddr struct {
23 IP IP
24 Port int
25 Zone string // IPv6 scoped addressing zone
26 }
27
28 // Network returns the address's network name, "udp".
29 func (a *UDPAddr) Network() string { return "udp" }
30
31 func (a *UDPAddr) String() string {
32 if a == nil {
33 return "<nil>"
34 }
35 ip := ipEmptyString(a.IP)
36 if a.Zone != "" {
37 return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
38 }
39 return JoinHostPort(ip, itoa(a.Port))
40 }
41
42 func (a *UDPAddr) isWildcard() bool {
43 if a == nil || a.IP == nil {
44 return true
45 }
46 return a.IP.IsUnspecified()
47 }
48
49 func (a *UDPAddr) opAddr() Addr {
50 if a == nil {
51 return nil
52 }
53 return a
54 }
55
56 // ResolveUDPAddr returns an address of UDP end point.
57 //
58 // The network must be a UDP network name.
59 //
60 // If the host in the address parameter is not a literal IP address or
61 // the port is not a literal port number, ResolveUDPAddr resolves the
62 // address to an address of UDP end point.
63 // Otherwise, it parses the address as a pair of literal IP address
64 // and port number.
65 // The address parameter can use a host name, but this is not
66 // recommended, because it will return at most one of the host name's
67 // IP addresses.
68 //
69 // See func Dial for a description of the network and address
70 // parameters.
71 func ResolveUDPAddr(network, address string) (*UDPAddr, error) {
72 switch network {
73 case "udp", "udp4", "udp6":
74 case "": // a hint wildcard for Go 1.0 undocumented behavior
75 network = "udp"
76 default:
77 return nil, UnknownNetworkError(network)
78 }
79 addrs, err := DefaultResolver.internetAddrList(context.Background(), network, address)
80 if err != nil {
81 return nil, err
82 }
83 return addrs.forResolve(network, address).(*UDPAddr), nil
84 }
85
86 // UDPConn is the implementation of the Conn and PacketConn interfaces
87 // for UDP network connections.
88 type UDPConn struct {
89 conn
90 }
91
92 // SyscallConn returns a raw network connection.
93 // This implements the syscall.Conn interface.
94 func (c *UDPConn) SyscallConn() (syscall.RawConn, error) {
95 if !c.ok() {
96 return nil, syscall.EINVAL
97 }
98 return newRawConn(c.fd)
99 }
100
101 // ReadFromUDP acts like ReadFrom but returns a UDPAddr.
102 func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
103 if !c.ok() {
104 return 0, nil, syscall.EINVAL
105 }
106 n, addr, err := c.readFrom(b)
107 if err != nil {
108 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
109 }
110 return n, addr, err
111 }
112
113 // ReadFrom implements the PacketConn ReadFrom method.
114 func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
115 if !c.ok() {
116 return 0, nil, syscall.EINVAL
117 }
118 n, addr, err := c.readFrom(b)
119 if err != nil {
120 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
121 }
122 if addr == nil {
123 return n, nil, err
124 }
125 return n, addr, err
126 }
127
128 // ReadMsgUDP reads a message from c, copying the payload into b and
129 // the associated out-of-band data into oob. It returns the number of
130 // bytes copied into b, the number of bytes copied into oob, the flags
131 // that were set on the message and the source address of the message.
132 //
133 // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
134 // used to manipulate IP-level socket options in oob.
135 func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
136 if !c.ok() {
137 return 0, 0, 0, nil, syscall.EINVAL
138 }
139 n, oobn, flags, addr, err = c.readMsg(b, oob)
140 if err != nil {
141 err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
142 }
143 return
144 }
145
146 // WriteToUDP acts like WriteTo but takes a UDPAddr.
147 func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
148 if !c.ok() {
149 return 0, syscall.EINVAL
150 }
151 n, err := c.writeTo(b, addr)
152 if err != nil {
153 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
154 }
155 return n, err
156 }
157
158 // WriteTo implements the PacketConn WriteTo method.
159 func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
160 if !c.ok() {
161 return 0, syscall.EINVAL
162 }
163 a, ok := addr.(*UDPAddr)
164 if !ok {
165 return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
166 }
167 n, err := c.writeTo(b, a)
168 if err != nil {
169 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
170 }
171 return n, err
172 }
173
174 // WriteMsgUDP writes a message to addr via c if c isn't connected, or
175 // to c's remote address if c is connected (in which case addr must be
176 // nil). The payload is copied from b and the associated out-of-band
177 // data is copied from oob. It returns the number of payload and
178 // out-of-band bytes written.
179 //
180 // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
181 // used to manipulate IP-level socket options in oob.
182 func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
183 if !c.ok() {
184 return 0, 0, syscall.EINVAL
185 }
186 n, oobn, err = c.writeMsg(b, oob, addr)
187 if err != nil {
188 err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
189 }
190 return
191 }
192
193 func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
194
195 // DialUDP acts like Dial for UDP networks.
196 //
197 // The network must be a UDP network name; see func Dial for details.
198 //
199 // If laddr is nil, a local address is automatically chosen.
200 // If the IP field of raddr is nil or an unspecified IP address, the
201 // local system is assumed.
202 func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) {
203 switch network {
204 case "udp", "udp4", "udp6":
205 default:
206 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
207 }
208 if raddr == nil {
209 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
210 }
211 sd := &sysDialer{network: network, address: raddr.String()}
212 c, err := sd.dialUDP(context.Background(), laddr, raddr)
213 if err != nil {
214 return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
215 }
216 return c, nil
217 }
218
219 // ListenUDP acts like ListenPacket for UDP networks.
220 //
221 // The network must be a UDP network name; see func Dial for details.
222 //
223 // If the IP field of laddr is nil or an unspecified IP address,
224 // ListenUDP listens on all available IP addresses of the local system
225 // except multicast IP addresses.
226 // If the Port field of laddr is 0, a port number is automatically
227 // chosen.
228 func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error) {
229 switch network {
230 case "udp", "udp4", "udp6":
231 default:
232 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
233 }
234 if laddr == nil {
235 laddr = &UDPAddr{}
236 }
237 sl := &sysListener{network: network, address: laddr.String()}
238 c, err := sl.listenUDP(context.Background(), laddr)
239 if err != nil {
240 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
241 }
242 return c, nil
243 }
244
245 // ListenMulticastUDP acts like ListenPacket for UDP networks but
246 // takes a group address on a specific network interface.
247 //
248 // The network must be a UDP network name; see func Dial for details.
249 //
250 // ListenMulticastUDP listens on all available IP addresses of the
251 // local system including the group, multicast IP address.
252 // If ifi is nil, ListenMulticastUDP uses the system-assigned
253 // multicast interface, although this is not recommended because the
254 // assignment depends on platforms and sometimes it might require
255 // routing configuration.
256 // If the Port field of gaddr is 0, a port number is automatically
257 // chosen.
258 //
259 // ListenMulticastUDP is just for convenience of simple, small
260 // applications. There are golang.org/x/net/ipv4 and
261 // golang.org/x/net/ipv6 packages for general purpose uses.
262 func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
263 switch network {
264 case "udp", "udp4", "udp6":
265 default:
266 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: UnknownNetworkError(network)}
267 }
268 if gaddr == nil || gaddr.IP == nil {
269 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: errMissingAddress}
270 }
271 sl := &sysListener{network: network, address: gaddr.String()}
272 c, err := sl.listenMulticastUDP(context.Background(), ifi, gaddr)
273 if err != nil {
274 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: err}
275 }
276 return c, nil
277 }