...

Source file src/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 aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
     6	
     7	package net
     8	
     9	import (
    10		"context"
    11		"syscall"
    12	)
    13	
    14	func sockaddrToUDP(sa syscall.Sockaddr) Addr {
    15		switch sa := sa.(type) {
    16		case *syscall.SockaddrInet4:
    17			return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
    18		case *syscall.SockaddrInet6:
    19			return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
    20		}
    21		return nil
    22	}
    23	
    24	func (a *UDPAddr) family() int {
    25		if a == nil || len(a.IP) <= IPv4len {
    26			return syscall.AF_INET
    27		}
    28		if a.IP.To4() != nil {
    29			return syscall.AF_INET
    30		}
    31		return syscall.AF_INET6
    32	}
    33	
    34	func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
    35		if a == nil {
    36			return nil, nil
    37		}
    38		return ipToSockaddr(family, a.IP, a.Port, a.Zone)
    39	}
    40	
    41	func (a *UDPAddr) toLocal(net string) sockaddr {
    42		return &UDPAddr{loopbackIP(net), a.Port, a.Zone}
    43	}
    44	
    45	func (c *UDPConn) readFrom(b []byte) (int, *UDPAddr, error) {
    46		var addr *UDPAddr
    47		n, sa, err := c.fd.readFrom(b)
    48		switch sa := sa.(type) {
    49		case *syscall.SockaddrInet4:
    50			addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
    51		case *syscall.SockaddrInet6:
    52			addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
    53		}
    54		return n, addr, err
    55	}
    56	
    57	func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
    58		var sa syscall.Sockaddr
    59		n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
    60		switch sa := sa.(type) {
    61		case *syscall.SockaddrInet4:
    62			addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
    63		case *syscall.SockaddrInet6:
    64			addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
    65		}
    66		return
    67	}
    68	
    69	func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
    70		if c.fd.isConnected {
    71			return 0, ErrWriteToConnected
    72		}
    73		if addr == nil {
    74			return 0, errMissingAddress
    75		}
    76		sa, err := addr.sockaddr(c.fd.family)
    77		if err != nil {
    78			return 0, err
    79		}
    80		return c.fd.writeTo(b, sa)
    81	}
    82	
    83	func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
    84		if c.fd.isConnected && addr != nil {
    85			return 0, 0, ErrWriteToConnected
    86		}
    87		if !c.fd.isConnected && addr == nil {
    88			return 0, 0, errMissingAddress
    89		}
    90		sa, err := addr.sockaddr(c.fd.family)
    91		if err != nil {
    92			return 0, 0, err
    93		}
    94		return c.fd.writeMsg(b, oob, sa)
    95	}
    96	
    97	func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) {
    98		fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial", sd.Dialer.Control)
    99		if err != nil {
   100			return nil, err
   101		}
   102		return newUDPConn(fd), nil
   103	}
   104	
   105	func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn, error) {
   106		fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_DGRAM, 0, "listen", sl.ListenConfig.Control)
   107		if err != nil {
   108			return nil, err
   109		}
   110		return newUDPConn(fd), nil
   111	}
   112	
   113	func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
   114		fd, err := internetSocket(ctx, sl.network, gaddr, nil, syscall.SOCK_DGRAM, 0, "listen", sl.ListenConfig.Control)
   115		if err != nil {
   116			return nil, err
   117		}
   118		c := newUDPConn(fd)
   119		if ip4 := gaddr.IP.To4(); ip4 != nil {
   120			if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
   121				c.Close()
   122				return nil, err
   123			}
   124		} else {
   125			if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
   126				c.Close()
   127				return nil, err
   128			}
   129		}
   130		return c, nil
   131	}
   132	
   133	func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
   134		if ifi != nil {
   135			if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
   136				return err
   137			}
   138		}
   139		if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
   140			return err
   141		}
   142		if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
   143			return err
   144		}
   145		return nil
   146	}
   147	
   148	func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
   149		if ifi != nil {
   150			if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
   151				return err
   152			}
   153		}
   154		if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
   155			return err
   156		}
   157		if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
   158			return err
   159		}
   160		return nil
   161	}
   162	

View as plain text