mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-04 18:50:29 +08:00
f8d9fa9e80
This upgrades all of libgo other than the runtime package to the Go 1.4 release. In Go 1.4 much of the runtime was rewritten into Go. Merging that code will take more time and will not change the API, so I'm putting it off for now. There are a few runtime changes anyhow, to accomodate other packages that rely on minor modifications to the runtime support. The compiler changes slightly to add a one-bit flag to each type descriptor kind that is stored directly in an interface, which for gccgo is currently only pointer types. Another one-bit flag (gcprog) is reserved because it is used by the gc compiler, but gccgo does not currently use it. There is another error check in the compiler since I ran across it during testing. gotools/: * Makefile.am (go_cmd_go_files): Sort entries. Add generate.go. * Makefile.in: Rebuild. From-SVN: r219627
217 lines
5.7 KiB
Go
217 lines
5.7 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
|
|
|
|
netaddr
|
|
|
|
// 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) (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 {
|
|
closesocket(s)
|
|
return nil, err
|
|
}
|
|
if fd, err = newFD(s, family, sotype, net); err != nil {
|
|
closesocket(s)
|
|
return nil, err
|
|
}
|
|
|
|
// This function makes a network file descriptor for the
|
|
// following applications:
|
|
//
|
|
// - An endpoint holder that opens a passive stream
|
|
// connenction, 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); 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) 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); 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 := syscall.Listen(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
|
|
}
|