Source file src/pkg/net/udpsock_posix.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 // +build darwin freebsd linux netbsd openbsd windows 6 7 // UDP sockets 8 9 package net 10 11 import ( 12 "errors" 13 "os" 14 "syscall" 15 "time" 16 ) 17 18 var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP") 19 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} 26 } 27 return nil 28 } 29 30 func (a *UDPAddr) family() int { 31 if a == nil || len(a.IP) <= IPv4len { 32 return syscall.AF_INET 33 } 34 if a.IP.To4() != nil { 35 return syscall.AF_INET 36 } 37 return syscall.AF_INET6 38 } 39 40 func (a *UDPAddr) isWildcard() bool { 41 if a == nil || a.IP == nil { 42 return true 43 } 44 return a.IP.IsUnspecified() 45 } 46 47 func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) { 48 return ipToSockaddr(family, a.IP, a.Port) 49 } 50 51 func (a *UDPAddr) toAddr() sockaddr { 52 if a == nil { // nil *UDPAddr 53 return nil // nil interface 54 } 55 return a 56 } 57 58 // UDPConn is the implementation of the Conn and PacketConn 59 // interfaces for UDP network connections. 60 type UDPConn struct { 61 fd *netFD 62 } 63 64 func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{fd} } 65 66 func (c *UDPConn) ok() bool { return c != nil && c.fd != nil } 67 68 // Implementation of the Conn interface - see Conn for documentation. 69 70 // Read implements the Conn Read method. 71 func (c *UDPConn) Read(b []byte) (int, error) { 72 if !c.ok() { 73 return 0, syscall.EINVAL 74 } 75 return c.fd.Read(b) 76 } 77 78 // Write implements the Conn Write method. 79 func (c *UDPConn) Write(b []byte) (int, error) { 80 if !c.ok() { 81 return 0, syscall.EINVAL 82 } 83 return c.fd.Write(b) 84 } 85 86 // Close closes the UDP connection. 87 func (c *UDPConn) Close() error { 88 if !c.ok() { 89 return syscall.EINVAL 90 } 91 return c.fd.Close() 92 } 93 94 // LocalAddr returns the local network address. 95 func (c *UDPConn) LocalAddr() Addr { 96 if !c.ok() { 97 return nil 98 } 99 return c.fd.laddr 100 } 101 102 // RemoteAddr returns the remote network address, a *UDPAddr. 103 func (c *UDPConn) RemoteAddr() Addr { 104 if !c.ok() { 105 return nil 106 } 107 return c.fd.raddr 108 } 109 110 // SetDeadline implements the Conn SetDeadline method. 111 func (c *UDPConn) SetDeadline(t time.Time) error { 112 if !c.ok() { 113 return syscall.EINVAL 114 } 115 return setDeadline(c.fd, t) 116 } 117 118 // SetReadDeadline implements the Conn SetReadDeadline method. 119 func (c *UDPConn) SetReadDeadline(t time.Time) error { 120 if !c.ok() { 121 return syscall.EINVAL 122 } 123 return setReadDeadline(c.fd, t) 124 } 125 126 // SetWriteDeadline implements the Conn SetWriteDeadline method. 127 func (c *UDPConn) SetWriteDeadline(t time.Time) error { 128 if !c.ok() { 129 return syscall.EINVAL 130 } 131 return setWriteDeadline(c.fd, t) 132 } 133 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 { 137 if !c.ok() { 138 return syscall.EINVAL 139 } 140 return setReadBuffer(c.fd, bytes) 141 } 142 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 { 146 if !c.ok() { 147 return syscall.EINVAL 148 } 149 return setWriteBuffer(c.fd, bytes) 150 } 151 152 // UDP-specific methods. 153 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. 157 // 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) { 161 if !c.ok() { 162 return 0, nil, syscall.EINVAL 163 } 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} 170 } 171 return 172 } 173 174 // ReadFrom implements the PacketConn ReadFrom method. 175 func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { 176 if !c.ok() { 177 return 0, nil, syscall.EINVAL 178 } 179 n, uaddr, err := c.ReadFromUDP(b) 180 return n, uaddr.toAddr(), err 181 } 182 183 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b. 184 // 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) { 190 if !c.ok() { 191 return 0, syscall.EINVAL 192 } 193 if c.fd.isConnected { 194 return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected} 195 } 196 sa, err := addr.sockaddr(c.fd.family) 197 if err != nil { 198 return 0, &OpError{"write", c.fd.net, addr, err} 199 } 200 return c.fd.WriteTo(b, sa) 201 } 202 203 // WriteTo implements the PacketConn WriteTo method. 204 func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { 205 if !c.ok() { 206 return 0, syscall.EINVAL 207 } 208 a, ok := addr.(*UDPAddr) 209 if !ok { 210 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL} 211 } 212 return c.WriteToUDP(b, a) 213 } 214 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() } 219 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) { 224 switch net { 225 case "udp", "udp4", "udp6": 226 default: 227 return nil, UnknownNetworkError(net) 228 } 229 if raddr == nil { 230 return nil, &OpError{"dial", net, nil, errMissingAddress} 231 } 232 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) 233 if err != nil { 234 return nil, err 235 } 236 return newUDPConn(fd), nil 237 } 238 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) { 244 switch net { 245 case "udp", "udp4", "udp6": 246 default: 247 return nil, UnknownNetworkError(net) 248 } 249 if laddr == nil { 250 return nil, &OpError{"listen", net, nil, errMissingAddress} 251 } 252 fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP) 253 if err != nil { 254 return nil, err 255 } 256 return newUDPConn(fd), nil 257 } 258 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) { 264 switch net { 265 case "udp", "udp4", "udp6": 266 default: 267 return nil, UnknownNetworkError(net) 268 } 269 if gaddr == nil || gaddr.IP == nil { 270 return nil, &OpError{"listenmulticast", net, nil, errMissingAddress} 271 } 272 fd, err := internetSocket(net, gaddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP) 273 if err != nil { 274 return nil, err 275 } 276 c := newUDPConn(fd) 277 ip4 := gaddr.IP.To4() 278 if ip4 != nil { 279 err := listenIPv4MulticastUDP(c, ifi, ip4) 280 if err != nil { 281 c.Close() 282 return nil, err 283 } 284 } else { 285 err := listenIPv6MulticastUDP(c, ifi, gaddr.IP) 286 if err != nil { 287 c.Close() 288 return nil, err 289 } 290 } 291 return c, nil 292 } 293 294 func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error { 295 if ifi != nil { 296 err := setIPv4MulticastInterface(c.fd, ifi) 297 if err != nil { 298 return err 299 } 300 } 301 err := setIPv4MulticastLoopback(c.fd, false) 302 if err != nil { 303 return err 304 } 305 err = joinIPv4GroupUDP(c, ifi, ip) 306 if err != nil { 307 return err 308 } 309 return nil 310 } 311 312 func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error { 313 if ifi != nil { 314 err := setIPv6MulticastInterface(c.fd, ifi) 315 if err != nil { 316 return err 317 } 318 } 319 err := setIPv6MulticastLoopback(c.fd, false) 320 if err != nil { 321 return err 322 } 323 err = joinIPv6GroupUDP(c, ifi, ip) 324 if err != nil { 325 return err 326 } 327 return nil 328 } 329 330 func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error { 331 err := joinIPv4Group(c.fd, ifi, ip) 332 if err != nil { 333 return &OpError{"joinipv4group", c.fd.net, &IPAddr{ip}, err} 334 } 335 return nil 336 } 337 338 func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error { 339 err := leaveIPv4Group(c.fd, ifi, ip) 340 if err != nil { 341 return &OpError{"leaveipv4group", c.fd.net, &IPAddr{ip}, err} 342 } 343 return nil 344 } 345 346 func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error { 347 err := joinIPv6Group(c.fd, ifi, ip) 348 if err != nil { 349 return &OpError{"joinipv6group", c.fd.net, &IPAddr{ip}, err} 350 } 351 return nil 352 } 353 354 func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error { 355 err := leaveIPv6Group(c.fd, ifi, ip) 356 if err != nil { 357 return &OpError{"leaveipv6group", c.fd.net, &IPAddr{ip}, err} 358 } 359 return nil 360 }