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 darwin freebsd linux netbsd openbsd
14 func newFileFD(f
*os
.File
) (*netFD
, error
) {
15 syscall
.ForkLock
.RLock()
16 fd
, err
:= syscall
.Dup(int(f
.Fd()))
18 syscall
.ForkLock
.RUnlock()
19 return nil, os
.NewSyscallError("dup", err
)
21 syscall
.CloseOnExec(fd
)
22 syscall
.ForkLock
.RUnlock()
23 if err
= syscall
.SetNonblock(fd
, true); err
!= nil {
28 sotype
, err
:= syscall
.GetsockoptInt(fd
, syscall
.SOL_SOCKET
, syscall
.SO_TYPE
)
31 return nil, os
.NewSyscallError("getsockopt", err
)
34 family
:= syscall
.AF_UNSPEC
35 toAddr
:= sockaddrToTCP
36 lsa
, _
:= syscall
.Getsockname(fd
)
40 return nil, syscall
.EINVAL
41 case *syscall
.SockaddrInet4
:
42 family
= syscall
.AF_INET
43 if sotype
== syscall
.SOCK_DGRAM
{
44 toAddr
= sockaddrToUDP
45 } else if sotype
== syscall
.SOCK_RAW
{
48 case *syscall
.SockaddrInet6
:
49 family
= syscall
.AF_INET6
50 if sotype
== syscall
.SOCK_DGRAM
{
51 toAddr
= sockaddrToUDP
52 } else if sotype
== syscall
.SOCK_RAW
{
55 case *syscall
.SockaddrUnix
:
56 family
= syscall
.AF_UNIX
57 toAddr
= sockaddrToUnix
58 if sotype
== syscall
.SOCK_DGRAM
{
59 toAddr
= sockaddrToUnixgram
60 } else if sotype
== syscall
.SOCK_SEQPACKET
{
61 toAddr
= sockaddrToUnixpacket
65 rsa
, _
:= syscall
.Getpeername(fd
)
68 netfd
, err
:= newFD(fd
, family
, sotype
, laddr
.Network())
73 netfd
.setAddr(laddr
, raddr
)
77 // FileConn returns a copy of the network connection corresponding to
78 // the open file f. It is the caller's responsibility to close f when
79 // finished. Closing c does not affect f, and closing f does not
81 func FileConn(f
*os
.File
) (c Conn
, err error
) {
82 fd
, err
:= newFileFD(f
)
86 switch fd
.laddr
.(type) {
88 return newTCPConn(fd
), nil
90 return newUDPConn(fd
), nil
92 return newIPConn(fd
), nil
94 return newUnixConn(fd
), nil
97 return nil, syscall
.EINVAL
100 // FileListener returns a copy of the network listener corresponding
101 // to the open file f. It is the caller's responsibility to close l
102 // when finished. Closing l does not affect f, and closing f does not
104 func FileListener(f
*os
.File
) (l Listener
, err error
) {
105 fd
, err
:= newFileFD(f
)
109 switch laddr
:= fd
.laddr
.(type) {
111 return &TCPListener
{fd
}, nil
113 return &UnixListener
{fd
, laddr
.Name
}, nil
116 return nil, syscall
.EINVAL
119 // FilePacketConn returns a copy of the packet network connection
120 // corresponding to the open file f. It is the caller's
121 // responsibility to close f when finished. Closing c does not affect
122 // f, and closing f does not affect c.
123 func FilePacketConn(f
*os
.File
) (c PacketConn
, err error
) {
124 fd
, err
:= newFileFD(f
)
128 switch fd
.laddr
.(type) {
130 return newUDPConn(fd
), nil
132 return newUnixConn(fd
), nil
135 return nil, syscall
.EINVAL