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 dragonfly freebsd linux nacl netbsd openbsd solaris
14 func newFileFD(f
*os
.File
) (*netFD
, error
) {
15 fd
, err
:= dupCloseOnExec(int(f
.Fd()))
17 return nil, os
.NewSyscallError("dup", err
)
20 if err
= syscall
.SetNonblock(fd
, true); err
!= nil {
25 sotype
, err
:= syscall
.GetsockoptInt(fd
, syscall
.SOL_SOCKET
, syscall
.SO_TYPE
)
28 return nil, os
.NewSyscallError("getsockopt", err
)
31 family
:= syscall
.AF_UNSPEC
32 toAddr
:= sockaddrToTCP
33 lsa
, _
:= syscall
.Getsockname(fd
)
37 return nil, syscall
.EINVAL
38 case *syscall
.SockaddrInet4
:
39 family
= syscall
.AF_INET
40 if sotype
== syscall
.SOCK_DGRAM
{
41 toAddr
= sockaddrToUDP
42 } else if sotype
== syscall
.SOCK_RAW
{
45 case *syscall
.SockaddrInet6
:
46 family
= syscall
.AF_INET6
47 if sotype
== syscall
.SOCK_DGRAM
{
48 toAddr
= sockaddrToUDP
49 } else if sotype
== syscall
.SOCK_RAW
{
52 case *syscall
.SockaddrUnix
:
53 family
= syscall
.AF_UNIX
54 toAddr
= sockaddrToUnix
55 if sotype
== syscall
.SOCK_DGRAM
{
56 toAddr
= sockaddrToUnixgram
57 } else if sotype
== syscall
.SOCK_SEQPACKET
{
58 toAddr
= sockaddrToUnixpacket
62 rsa
, _
:= syscall
.Getpeername(fd
)
65 netfd
, err
:= newFD(fd
, family
, sotype
, laddr
.Network())
70 if err
:= netfd
.init(); err
!= nil {
74 netfd
.setAddr(laddr
, raddr
)
78 // FileConn returns a copy of the network connection corresponding to
79 // the open file f. It is the caller's responsibility to close f when
80 // finished. Closing c does not affect f, and closing f does not
82 func FileConn(f
*os
.File
) (c Conn
, err error
) {
83 fd
, err
:= newFileFD(f
)
87 switch fd
.laddr
.(type) {
89 return newTCPConn(fd
), nil
91 return newUDPConn(fd
), nil
93 return newIPConn(fd
), nil
95 return newUnixConn(fd
), nil
98 return nil, syscall
.EINVAL
101 // FileListener returns a copy of the network listener corresponding
102 // to the open file f. It is the caller's responsibility to close l
103 // when finished. Closing l does not affect f, and closing f does not
105 func FileListener(f
*os
.File
) (l Listener
, err error
) {
106 fd
, err
:= newFileFD(f
)
110 switch laddr
:= fd
.laddr
.(type) {
112 return &TCPListener
{fd
}, nil
114 return &UnixListener
{fd
, laddr
.Name
}, nil
117 return nil, syscall
.EINVAL
120 // FilePacketConn returns a copy of the packet network connection
121 // corresponding to the open file f. It is the caller's
122 // responsibility to close f when finished. Closing c does not affect
123 // f, and closing f does not affect c.
124 func FilePacketConn(f
*os
.File
) (c PacketConn
, err error
) {
125 fd
, err
:= newFileFD(f
)
129 switch fd
.laddr
.(type) {
131 return newUDPConn(fd
), nil
133 return newIPConn(fd
), nil
135 return newUnixConn(fd
), nil
138 return nil, syscall
.EINVAL