2011-03-25 12:42:25 -06:00
|
|
|
// Copyright 2011 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: add build comments to core packages
The go/build package already recognizes
system-specific file names like
mycode_darwin.go
mycode_darwin_386.go
mycode_386.s
However, it is also common to write files that
apply to multiple architectures, so a recent CL added
to go/build the ability to process comments
listing a set of conditions for building. For example:
// +build darwin freebsd openbsd/386
says that this file should be compiled only on
OS X, FreeBSD, or 32-bit x86 OpenBSD systems.
These conventions are not yet documented
(hence this long CL description).
This CL adds build comments to the multi-system
files in the core library, a step toward making it
possible to use go/build to build them.
With this change go/build can handle crypto/rand,
exec, net, path/filepath, os/user, and time.
os and syscall need additional adjustments.
R=golang-dev, r, gri, r, gustavo
CC=golang-dev
https://golang.org/cl/5011046
2011-09-15 14:48:57 -06:00
|
|
|
// +build darwin freebsd linux openbsd
|
|
|
|
|
2011-03-25 12:42:25 -06:00
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
2011-11-01 20:05:34 -06:00
|
|
|
func newFileFD(f *os.File) (nfd *netFD, err error) {
|
2011-03-25 12:42:25 -06:00
|
|
|
fd, errno := syscall.Dup(f.Fd())
|
2011-11-13 20:44:52 -07:00
|
|
|
if errno != nil {
|
2011-03-25 12:42:25 -06:00
|
|
|
return nil, os.NewSyscallError("dup", errno)
|
|
|
|
}
|
|
|
|
|
|
|
|
proto, errno := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
|
2011-11-13 20:44:52 -07:00
|
|
|
if errno != nil {
|
2011-03-25 12:42:25 -06:00
|
|
|
return nil, os.NewSyscallError("getsockopt", errno)
|
|
|
|
}
|
|
|
|
|
2011-10-12 11:36:45 -06:00
|
|
|
family := syscall.AF_UNSPEC
|
2011-03-25 12:42:25 -06:00
|
|
|
toAddr := sockaddrToTCP
|
|
|
|
sa, _ := syscall.Getsockname(fd)
|
|
|
|
switch sa.(type) {
|
|
|
|
default:
|
|
|
|
closesocket(fd)
|
|
|
|
return nil, os.EINVAL
|
|
|
|
case *syscall.SockaddrInet4:
|
2011-10-12 11:36:45 -06:00
|
|
|
family = syscall.AF_INET
|
2011-03-25 12:42:25 -06:00
|
|
|
if proto == syscall.SOCK_DGRAM {
|
|
|
|
toAddr = sockaddrToUDP
|
|
|
|
} else if proto == syscall.SOCK_RAW {
|
|
|
|
toAddr = sockaddrToIP
|
|
|
|
}
|
|
|
|
case *syscall.SockaddrInet6:
|
2011-10-12 11:36:45 -06:00
|
|
|
family = syscall.AF_INET6
|
2011-03-25 12:42:25 -06:00
|
|
|
if proto == syscall.SOCK_DGRAM {
|
|
|
|
toAddr = sockaddrToUDP
|
|
|
|
} else if proto == syscall.SOCK_RAW {
|
|
|
|
toAddr = sockaddrToIP
|
|
|
|
}
|
|
|
|
case *syscall.SockaddrUnix:
|
2011-10-12 11:36:45 -06:00
|
|
|
family = syscall.AF_UNIX
|
2011-03-25 12:42:25 -06:00
|
|
|
toAddr = sockaddrToUnix
|
|
|
|
if proto == syscall.SOCK_DGRAM {
|
|
|
|
toAddr = sockaddrToUnixgram
|
|
|
|
} else if proto == syscall.SOCK_SEQPACKET {
|
|
|
|
toAddr = sockaddrToUnixpacket
|
|
|
|
}
|
|
|
|
}
|
|
|
|
laddr := toAddr(sa)
|
|
|
|
sa, _ = syscall.Getpeername(fd)
|
|
|
|
raddr := toAddr(sa)
|
|
|
|
|
2011-10-12 11:36:45 -06:00
|
|
|
if nfd, err = newFD(fd, family, proto, laddr.Network()); err != nil {
|
2011-03-28 21:40:01 -06:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
nfd.setAddr(laddr, raddr)
|
|
|
|
return nfd, nil
|
2011-03-25 12:42:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// FileConn returns a copy of the network connection corresponding to
|
|
|
|
// the open file f. It is the caller's responsibility to close f when
|
|
|
|
// finished. Closing c does not affect f, and closing f does not
|
|
|
|
// affect c.
|
2011-11-01 20:05:34 -06:00
|
|
|
func FileConn(f *os.File) (c Conn, err error) {
|
2011-03-25 12:42:25 -06:00
|
|
|
fd, err := newFileFD(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
switch fd.laddr.(type) {
|
|
|
|
case *TCPAddr:
|
|
|
|
return newTCPConn(fd), nil
|
|
|
|
case *UDPAddr:
|
|
|
|
return newUDPConn(fd), nil
|
|
|
|
case *UnixAddr:
|
|
|
|
return newUnixConn(fd), nil
|
|
|
|
case *IPAddr:
|
|
|
|
return newIPConn(fd), nil
|
|
|
|
}
|
|
|
|
fd.Close()
|
|
|
|
return nil, os.EINVAL
|
|
|
|
}
|
|
|
|
|
|
|
|
// FileListener returns a copy of the network listener corresponding
|
|
|
|
// to the open file f. It is the caller's responsibility to close l
|
|
|
|
// when finished. Closing c does not affect l, and closing l does not
|
|
|
|
// affect c.
|
2011-11-01 20:05:34 -06:00
|
|
|
func FileListener(f *os.File) (l Listener, err error) {
|
2011-03-25 12:42:25 -06:00
|
|
|
fd, err := newFileFD(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
switch laddr := fd.laddr.(type) {
|
|
|
|
case *TCPAddr:
|
|
|
|
return &TCPListener{fd}, nil
|
|
|
|
case *UnixAddr:
|
|
|
|
return &UnixListener{fd, laddr.Name}, nil
|
|
|
|
}
|
|
|
|
fd.Close()
|
|
|
|
return nil, os.EINVAL
|
|
|
|
}
|
|
|
|
|
|
|
|
// FilePacketConn returns a copy of the packet network connection
|
|
|
|
// corresponding to the open file f. It is the caller's
|
|
|
|
// responsibility to close f when finished. Closing c does not affect
|
|
|
|
// f, and closing f does not affect c.
|
2011-11-01 20:05:34 -06:00
|
|
|
func FilePacketConn(f *os.File) (c PacketConn, err error) {
|
2011-03-25 12:42:25 -06:00
|
|
|
fd, err := newFileFD(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
switch fd.laddr.(type) {
|
|
|
|
case *UDPAddr:
|
|
|
|
return newUDPConn(fd), nil
|
|
|
|
case *UnixAddr:
|
|
|
|
return newUnixConn(fd), nil
|
|
|
|
}
|
|
|
|
fd.Close()
|
|
|
|
return nil, os.EINVAL
|
|
|
|
}
|