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