...

Source file src/net/udpsock_posix.go

Documentation: net

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

View as plain text