1
0
mirror of https://github.com/golang/go synced 2024-10-05 07:11:22 -06:00
go/src/net/sock_posix.go
Brad Fitzpatrick 519474451a all: make copyright headers consistent with one space after period
This is a subset of https://golang.org/cl/20022 with only the copyright
header lines, so the next CL will be smaller and more reviewable.

Go policy has been single space after periods in comments for some time.

The copyright header template at:

    https://golang.org/doc/contribute.html#copyright

also uses a single space.

Make them all consistent.

Change-Id: Icc26c6b8495c3820da6b171ca96a74701b4a01b0
Reviewed-on: https://go-review.googlesource.com/20111
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-01 23:34:33 +00:00

215 lines
5.8 KiB
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net
import (
"os"
"syscall"
"time"
)
// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
// address that can be converted into a syscall.Sockaddr.
type sockaddr interface {
Addr
// family returns the platform-dependent address family
// identifier.
family() int
// isWildcard reports whether the address is a wildcard
// address.
isWildcard() bool
// sockaddr returns the address converted into a syscall
// sockaddr type that implements syscall.Sockaddr
// interface. It returns a nil interface when the address is
// nil.
sockaddr(family int) (syscall.Sockaddr, error)
}
// socket returns a network file descriptor that is ready for
// asynchronous I/O using the network poller.
func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time, cancel <-chan struct{}) (fd *netFD, err error) {
s, err := sysSocket(family, sotype, proto)
if err != nil {
return nil, err
}
if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
closeFunc(s)
return nil, err
}
if fd, err = newFD(s, family, sotype, net); err != nil {
closeFunc(s)
return nil, err
}
// This function makes a network file descriptor for the
// following applications:
//
// - An endpoint holder that opens a passive stream
// connection, known as a stream listener
//
// - An endpoint holder that opens a destination-unspecific
// datagram connection, known as a datagram listener
//
// - An endpoint holder that opens an active stream or a
// destination-specific datagram connection, known as a
// dialer
//
// - An endpoint holder that opens the other connection, such
// as talking to the protocol stack inside the kernel
//
// For stream and datagram listeners, they will only require
// named sockets, so we can assume that it's just a request
// from stream or datagram listeners when laddr is not nil but
// raddr is nil. Otherwise we assume it's just for dialers or
// the other connection holders.
if laddr != nil && raddr == nil {
switch sotype {
case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
if err := fd.listenStream(laddr, listenerBacklog); err != nil {
fd.Close()
return nil, err
}
return fd, nil
case syscall.SOCK_DGRAM:
if err := fd.listenDatagram(laddr); err != nil {
fd.Close()
return nil, err
}
return fd, nil
}
}
if err := fd.dial(laddr, raddr, deadline, cancel); err != nil {
fd.Close()
return nil, err
}
return fd, nil
}
func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
switch fd.family {
case syscall.AF_INET, syscall.AF_INET6:
switch fd.sotype {
case syscall.SOCK_STREAM:
return sockaddrToTCP
case syscall.SOCK_DGRAM:
return sockaddrToUDP
case syscall.SOCK_RAW:
return sockaddrToIP
}
case syscall.AF_UNIX:
switch fd.sotype {
case syscall.SOCK_STREAM:
return sockaddrToUnix
case syscall.SOCK_DGRAM:
return sockaddrToUnixgram
case syscall.SOCK_SEQPACKET:
return sockaddrToUnixpacket
}
}
return func(syscall.Sockaddr) Addr { return nil }
}
func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, cancel <-chan struct{}) error {
var err error
var lsa syscall.Sockaddr
if laddr != nil {
if lsa, err = laddr.sockaddr(fd.family); err != nil {
return err
} else if lsa != nil {
if err := syscall.Bind(fd.sysfd, lsa); err != nil {
return os.NewSyscallError("bind", err)
}
}
}
var rsa syscall.Sockaddr
if raddr != nil {
if rsa, err = raddr.sockaddr(fd.family); err != nil {
return err
}
if err := fd.connect(lsa, rsa, deadline, cancel); err != nil {
return err
}
fd.isConnected = true
} else {
if err := fd.init(); err != nil {
return err
}
}
lsa, _ = syscall.Getsockname(fd.sysfd)
if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil {
fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
} else {
fd.setAddr(fd.addrFunc()(lsa), raddr)
}
return nil
}
func (fd *netFD) listenStream(laddr sockaddr, backlog int) error {
if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
return err
}
if lsa, err := laddr.sockaddr(fd.family); err != nil {
return err
} else if lsa != nil {
if err := syscall.Bind(fd.sysfd, lsa); err != nil {
return os.NewSyscallError("bind", err)
}
}
if err := listenFunc(fd.sysfd, backlog); err != nil {
return os.NewSyscallError("listen", err)
}
if err := fd.init(); err != nil {
return err
}
lsa, _ := syscall.Getsockname(fd.sysfd)
fd.setAddr(fd.addrFunc()(lsa), nil)
return nil
}
func (fd *netFD) listenDatagram(laddr sockaddr) error {
switch addr := laddr.(type) {
case *UDPAddr:
// We provide a socket that listens to a wildcard
// address with reusable UDP port when the given laddr
// is an appropriate UDP multicast address prefix.
// This makes it possible for a single UDP listener to
// join multiple different group addresses, for
// multiple UDP listeners that listen on the same UDP
// port to join the same group address.
if addr.IP != nil && addr.IP.IsMulticast() {
if err := setDefaultMulticastSockopts(fd.sysfd); err != nil {
return err
}
addr := *addr
switch fd.family {
case syscall.AF_INET:
addr.IP = IPv4zero
case syscall.AF_INET6:
addr.IP = IPv6unspecified
}
laddr = &addr
}
}
if lsa, err := laddr.sockaddr(fd.family); err != nil {
return err
} else if lsa != nil {
if err := syscall.Bind(fd.sysfd, lsa); err != nil {
return os.NewSyscallError("bind", err)
}
}
if err := fd.init(); err != nil {
return err
}
lsa, _ := syscall.Getsockname(fd.sysfd)
fd.setAddr(fd.addrFunc()(lsa), nil)
return nil
}