...
Run Format

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	// +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	}
   218	

View as plain text