...
Run Format

Source file src/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 NaCl, Plan 9 and Windows, 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	// 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 parses addr as a UDP address of the form "host:port"
    57	// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
    58	// port name on the network net, which must be "udp", "udp4" or
    59	// "udp6".  A literal address or host name for IPv6 must be enclosed
    60	// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
    61	// "[ipv6-host%zone]:80".
    62	//
    63	// Resolving a hostname is not recommended because this returns at most
    64	// one of its IP addresses.
    65	func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
    66		switch net {
    67		case "udp", "udp4", "udp6":
    68		case "": // a hint wildcard for Go 1.0 undocumented behavior
    69			net = "udp"
    70		default:
    71			return nil, UnknownNetworkError(net)
    72		}
    73		addrs, err := DefaultResolver.internetAddrList(context.Background(), net, addr)
    74		if err != nil {
    75			return nil, err
    76		}
    77		return addrs.first(isIPv4).(*UDPAddr), nil
    78	}
    79	
    80	// UDPConn is the implementation of the Conn and PacketConn interfaces
    81	// for UDP network connections.
    82	type UDPConn struct {
    83		conn
    84	}
    85	
    86	// ReadFromUDP reads a UDP packet from c, copying the payload into b.
    87	// It returns the number of bytes copied into b and the return address
    88	// that was on the packet.
    89	//
    90	// ReadFromUDP can be made to time out and return an error with
    91	// Timeout() == true after a fixed time limit; see SetDeadline and
    92	// SetReadDeadline.
    93	func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
    94		if !c.ok() {
    95			return 0, nil, syscall.EINVAL
    96		}
    97		n, addr, err := c.readFrom(b)
    98		if err != nil {
    99			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   100		}
   101		return n, addr, err
   102	}
   103	
   104	// ReadFrom implements the PacketConn ReadFrom method.
   105	func (c *UDPConn) ReadFrom(b []byte) (int, Addr, 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		if addr == nil {
   114			return n, nil, err
   115		}
   116		return n, addr, err
   117	}
   118	
   119	// ReadMsgUDP reads a packet from c, copying the payload into b and
   120	// the associated out-of-band data into oob. It returns the number
   121	// of bytes copied into b, the number of bytes copied into oob, the
   122	// flags that were set on the packet and the source address of the
   123	// packet.
   124	func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
   125		if !c.ok() {
   126			return 0, 0, 0, nil, syscall.EINVAL
   127		}
   128		n, oobn, flags, addr, err = c.readMsg(b, oob)
   129		if err != nil {
   130			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   131		}
   132		return
   133	}
   134	
   135	// WriteToUDP writes a UDP packet to addr via c, copying the payload
   136	// from b.
   137	//
   138	// WriteToUDP can be made to time out and return an error with
   139	// Timeout() == true after a fixed time limit; see SetDeadline and
   140	// SetWriteDeadline. On packet-oriented connections, write timeouts
   141	// are rare.
   142	func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
   143		if !c.ok() {
   144			return 0, syscall.EINVAL
   145		}
   146		n, err := c.writeTo(b, addr)
   147		if err != nil {
   148			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   149		}
   150		return n, err
   151	}
   152	
   153	// WriteTo implements the PacketConn WriteTo method.
   154	func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
   155		if !c.ok() {
   156			return 0, syscall.EINVAL
   157		}
   158		a, ok := addr.(*UDPAddr)
   159		if !ok {
   160			return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
   161		}
   162		n, err := c.writeTo(b, a)
   163		if err != nil {
   164			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
   165		}
   166		return n, err
   167	}
   168	
   169	// WriteMsgUDP writes a packet to addr via c if c isn't connected, or
   170	// to c's remote destination address if c is connected (in which case
   171	// addr must be nil).  The payload is copied from b and the associated
   172	// out-of-band data is copied from oob. It returns the number of
   173	// payload and out-of-band bytes written.
   174	func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
   175		if !c.ok() {
   176			return 0, 0, syscall.EINVAL
   177		}
   178		n, oobn, err = c.writeMsg(b, oob, addr)
   179		if err != nil {
   180			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   181		}
   182		return
   183	}
   184	
   185	func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
   186	
   187	// DialUDP connects to the remote address raddr on the network net,
   188	// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is
   189	// used as the local address for the connection.
   190	func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
   191		switch net {
   192		case "udp", "udp4", "udp6":
   193		default:
   194			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
   195		}
   196		if raddr == nil {
   197			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
   198		}
   199		c, err := dialUDP(context.Background(), net, laddr, raddr)
   200		if err != nil {
   201			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
   202		}
   203		return c, nil
   204	}
   205	
   206	// ListenUDP listens for incoming UDP packets addressed to the local
   207	// address laddr. Net must be "udp", "udp4", or "udp6".  If laddr has
   208	// a port of 0, ListenUDP will choose an available port.
   209	// The LocalAddr method of the returned UDPConn can be used to
   210	// discover the port. The returned connection's ReadFrom and WriteTo
   211	// methods can be used to receive and send UDP packets with per-packet
   212	// addressing.
   213	func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
   214		switch net {
   215		case "udp", "udp4", "udp6":
   216		default:
   217			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
   218		}
   219		if laddr == nil {
   220			laddr = &UDPAddr{}
   221		}
   222		c, err := listenUDP(context.Background(), net, laddr)
   223		if err != nil {
   224			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
   225		}
   226		return c, nil
   227	}
   228	
   229	// ListenMulticastUDP listens for incoming multicast UDP packets
   230	// addressed to the group address gaddr on the interface ifi.
   231	// Network must be "udp", "udp4" or "udp6".
   232	// ListenMulticastUDP uses the system-assigned multicast interface
   233	// when ifi is nil, although this is not recommended because the
   234	// assignment depends on platforms and sometimes it might require
   235	// routing configuration.
   236	//
   237	// ListenMulticastUDP is just for convenience of simple, small
   238	// applications. There are golang.org/x/net/ipv4 and
   239	// golang.org/x/net/ipv6 packages for general purpose uses.
   240	func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
   241		switch network {
   242		case "udp", "udp4", "udp6":
   243		default:
   244			return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: UnknownNetworkError(network)}
   245		}
   246		if gaddr == nil || gaddr.IP == nil {
   247			return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: errMissingAddress}
   248		}
   249		c, err := listenMulticastUDP(context.Background(), network, ifi, gaddr)
   250		if err != nil {
   251			return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: err}
   252		}
   253		return c, nil
   254	}
   255	

View as plain text