1 // Copyright 2011 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.
5 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
15 func dupSocket(f
*os
.File
) (int, error
) {
16 s
, call
, err
:= poll
.DupCloseOnExec(int(f
.Fd()))
19 err
= os
.NewSyscallError(call
, err
)
23 if err
:= syscall
.SetNonblock(s
, true); err
!= nil {
25 return -1, os
.NewSyscallError("setnonblock", err
)
30 func newFileFD(f
*os
.File
) (*netFD
, error
) {
31 s
, err
:= dupSocket(f
)
35 family
:= syscall
.AF_UNSPEC
36 sotype
, err
:= syscall
.GetsockoptInt(s
, syscall
.SOL_SOCKET
, syscall
.SO_TYPE
)
39 return nil, os
.NewSyscallError("getsockopt", err
)
41 lsa
, _
:= syscall
.Getsockname(s
)
42 rsa
, _
:= syscall
.Getpeername(s
)
44 case *syscall
.SockaddrInet4
:
45 family
= syscall
.AF_INET
46 case *syscall
.SockaddrInet6
:
47 family
= syscall
.AF_INET6
48 case *syscall
.SockaddrUnix
:
49 family
= syscall
.AF_UNIX
52 return nil, syscall
.EPROTONOSUPPORT
54 fd
, err
:= newFD(s
, family
, sotype
, "")
59 laddr
:= fd
.addrFunc()(lsa
)
60 raddr
:= fd
.addrFunc()(rsa
)
61 fd
.net
= laddr
.Network()
62 if err
:= fd
.init(); err
!= nil {
66 fd
.setAddr(laddr
, raddr
)
70 func fileConn(f
*os
.File
) (Conn
, error
) {
71 fd
, err
:= newFileFD(f
)
75 switch fd
.laddr
.(type) {
77 return newTCPConn(fd
), nil
79 return newUDPConn(fd
), nil
81 return newIPConn(fd
), nil
83 return newUnixConn(fd
), nil
86 return nil, syscall
.EINVAL
89 func fileListener(f
*os
.File
) (Listener
, error
) {
90 fd
, err
:= newFileFD(f
)
94 switch laddr
:= fd
.laddr
.(type) {
96 return &TCPListener
{fd
}, nil
98 return &UnixListener
{fd
: fd
, path
: laddr
.Name
, unlink
: false}, nil
101 return nil, syscall
.EINVAL
104 func filePacketConn(f
*os
.File
) (PacketConn
, error
) {
105 fd
, err
:= newFileFD(f
)
109 switch fd
.laddr
.(type) {
111 return newUDPConn(fd
), nil
113 return newIPConn(fd
), nil
115 return newUnixConn(fd
), nil
118 return nil, syscall
.EINVAL