github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/net/sock_posix.go (about)

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