...

Source file src/net/sock_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 || linux || netbsd || openbsd || solaris || windows
		 6  // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
		 7  
		 8  package net
		 9  
		10  import (
		11  	"context"
		12  	"internal/poll"
		13  	"os"
		14  	"syscall"
		15  )
		16  
		17  // socket returns a network file descriptor that is ready for
		18  // asynchronous I/O using the network poller.
		19  func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) (fd *netFD, err error) {
		20  	s, err := sysSocket(family, sotype, proto)
		21  	if err != nil {
		22  		return nil, err
		23  	}
		24  	if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
		25  		poll.CloseFunc(s)
		26  		return nil, err
		27  	}
		28  	if fd, err = newFD(s, family, sotype, net); err != nil {
		29  		poll.CloseFunc(s)
		30  		return nil, err
		31  	}
		32  
		33  	// This function makes a network file descriptor for the
		34  	// following applications:
		35  	//
		36  	// - An endpoint holder that opens a passive stream
		37  	//	 connection, known as a stream listener
		38  	//
		39  	// - An endpoint holder that opens a destination-unspecific
		40  	//	 datagram connection, known as a datagram listener
		41  	//
		42  	// - An endpoint holder that opens an active stream or a
		43  	//	 destination-specific datagram connection, known as a
		44  	//	 dialer
		45  	//
		46  	// - An endpoint holder that opens the other connection, such
		47  	//	 as talking to the protocol stack inside the kernel
		48  	//
		49  	// For stream and datagram listeners, they will only require
		50  	// named sockets, so we can assume that it's just a request
		51  	// from stream or datagram listeners when laddr is not nil but
		52  	// raddr is nil. Otherwise we assume it's just for dialers or
		53  	// the other connection holders.
		54  
		55  	if laddr != nil && raddr == nil {
		56  		switch sotype {
		57  		case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
		58  			if err := fd.listenStream(laddr, listenerBacklog(), ctrlFn); err != nil {
		59  				fd.Close()
		60  				return nil, err
		61  			}
		62  			return fd, nil
		63  		case syscall.SOCK_DGRAM:
		64  			if err := fd.listenDatagram(laddr, ctrlFn); err != nil {
		65  				fd.Close()
		66  				return nil, err
		67  			}
		68  			return fd, nil
		69  		}
		70  	}
		71  	if err := fd.dial(ctx, laddr, raddr, ctrlFn); err != nil {
		72  		fd.Close()
		73  		return nil, err
		74  	}
		75  	return fd, nil
		76  }
		77  
		78  func (fd *netFD) ctrlNetwork() string {
		79  	switch fd.net {
		80  	case "unix", "unixgram", "unixpacket":
		81  		return fd.net
		82  	}
		83  	switch fd.net[len(fd.net)-1] {
		84  	case '4', '6':
		85  		return fd.net
		86  	}
		87  	if fd.family == syscall.AF_INET {
		88  		return fd.net + "4"
		89  	}
		90  	return fd.net + "6"
		91  }
		92  
		93  func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
		94  	switch fd.family {
		95  	case syscall.AF_INET, syscall.AF_INET6:
		96  		switch fd.sotype {
		97  		case syscall.SOCK_STREAM:
		98  			return sockaddrToTCP
		99  		case syscall.SOCK_DGRAM:
	 100  			return sockaddrToUDP
	 101  		case syscall.SOCK_RAW:
	 102  			return sockaddrToIP
	 103  		}
	 104  	case syscall.AF_UNIX:
	 105  		switch fd.sotype {
	 106  		case syscall.SOCK_STREAM:
	 107  			return sockaddrToUnix
	 108  		case syscall.SOCK_DGRAM:
	 109  			return sockaddrToUnixgram
	 110  		case syscall.SOCK_SEQPACKET:
	 111  			return sockaddrToUnixpacket
	 112  		}
	 113  	}
	 114  	return func(syscall.Sockaddr) Addr { return nil }
	 115  }
	 116  
	 117  func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) error {
	 118  	if ctrlFn != nil {
	 119  		c, err := newRawConn(fd)
	 120  		if err != nil {
	 121  			return err
	 122  		}
	 123  		var ctrlAddr string
	 124  		if raddr != nil {
	 125  			ctrlAddr = raddr.String()
	 126  		} else if laddr != nil {
	 127  			ctrlAddr = laddr.String()
	 128  		}
	 129  		if err := ctrlFn(fd.ctrlNetwork(), ctrlAddr, c); err != nil {
	 130  			return err
	 131  		}
	 132  	}
	 133  	var err error
	 134  	var lsa syscall.Sockaddr
	 135  	if laddr != nil {
	 136  		if lsa, err = laddr.sockaddr(fd.family); err != nil {
	 137  			return err
	 138  		} else if lsa != nil {
	 139  			if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
	 140  				return os.NewSyscallError("bind", err)
	 141  			}
	 142  		}
	 143  	}
	 144  	var rsa syscall.Sockaddr	// remote address from the user
	 145  	var crsa syscall.Sockaddr // remote address we actually connected to
	 146  	if raddr != nil {
	 147  		if rsa, err = raddr.sockaddr(fd.family); err != nil {
	 148  			return err
	 149  		}
	 150  		if crsa, err = fd.connect(ctx, lsa, rsa); err != nil {
	 151  			return err
	 152  		}
	 153  		fd.isConnected = true
	 154  	} else {
	 155  		if err := fd.init(); err != nil {
	 156  			return err
	 157  		}
	 158  	}
	 159  	// Record the local and remote addresses from the actual socket.
	 160  	// Get the local address by calling Getsockname.
	 161  	// For the remote address, use
	 162  	// 1) the one returned by the connect method, if any; or
	 163  	// 2) the one from Getpeername, if it succeeds; or
	 164  	// 3) the one passed to us as the raddr parameter.
	 165  	lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
	 166  	if crsa != nil {
	 167  		fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa))
	 168  	} else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
	 169  		fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
	 170  	} else {
	 171  		fd.setAddr(fd.addrFunc()(lsa), raddr)
	 172  	}
	 173  	return nil
	 174  }
	 175  
	 176  func (fd *netFD) listenStream(laddr sockaddr, backlog int, ctrlFn func(string, string, syscall.RawConn) error) error {
	 177  	var err error
	 178  	if err = setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil {
	 179  		return err
	 180  	}
	 181  	var lsa syscall.Sockaddr
	 182  	if lsa, err = laddr.sockaddr(fd.family); err != nil {
	 183  		return err
	 184  	}
	 185  	if ctrlFn != nil {
	 186  		c, err := newRawConn(fd)
	 187  		if err != nil {
	 188  			return err
	 189  		}
	 190  		if err := ctrlFn(fd.ctrlNetwork(), laddr.String(), c); err != nil {
	 191  			return err
	 192  		}
	 193  	}
	 194  	if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
	 195  		return os.NewSyscallError("bind", err)
	 196  	}
	 197  	if err = listenFunc(fd.pfd.Sysfd, backlog); err != nil {
	 198  		return os.NewSyscallError("listen", err)
	 199  	}
	 200  	if err = fd.init(); err != nil {
	 201  		return err
	 202  	}
	 203  	lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
	 204  	fd.setAddr(fd.addrFunc()(lsa), nil)
	 205  	return nil
	 206  }
	 207  
	 208  func (fd *netFD) listenDatagram(laddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) error {
	 209  	switch addr := laddr.(type) {
	 210  	case *UDPAddr:
	 211  		// We provide a socket that listens to a wildcard
	 212  		// address with reusable UDP port when the given laddr
	 213  		// is an appropriate UDP multicast address prefix.
	 214  		// This makes it possible for a single UDP listener to
	 215  		// join multiple different group addresses, for
	 216  		// multiple UDP listeners that listen on the same UDP
	 217  		// port to join the same group address.
	 218  		if addr.IP != nil && addr.IP.IsMulticast() {
	 219  			if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil {
	 220  				return err
	 221  			}
	 222  			addr := *addr
	 223  			switch fd.family {
	 224  			case syscall.AF_INET:
	 225  				addr.IP = IPv4zero
	 226  			case syscall.AF_INET6:
	 227  				addr.IP = IPv6unspecified
	 228  			}
	 229  			laddr = &addr
	 230  		}
	 231  	}
	 232  	var err error
	 233  	var lsa syscall.Sockaddr
	 234  	if lsa, err = laddr.sockaddr(fd.family); err != nil {
	 235  		return err
	 236  	}
	 237  	if ctrlFn != nil {
	 238  		c, err := newRawConn(fd)
	 239  		if err != nil {
	 240  			return err
	 241  		}
	 242  		if err := ctrlFn(fd.ctrlNetwork(), laddr.String(), c); err != nil {
	 243  			return err
	 244  		}
	 245  	}
	 246  	if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
	 247  		return os.NewSyscallError("bind", err)
	 248  	}
	 249  	if err = fd.init(); err != nil {
	 250  		return err
	 251  	}
	 252  	lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
	 253  	fd.setAddr(fd.addrFunc()(lsa), nil)
	 254  	return nil
	 255  }
	 256  

View as plain text