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