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

View as plain text