Source file
src/net/fd_unix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "internal/poll"
12 "os"
13 "runtime"
14 "syscall"
15 )
16
17 const (
18 readSyscallName = "read"
19 readFromSyscallName = "recvfrom"
20 readMsgSyscallName = "recvmsg"
21 writeSyscallName = "write"
22 writeToSyscallName = "sendto"
23 writeMsgSyscallName = "sendmsg"
24 )
25
26 func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
27 ret := &netFD{
28 pfd: poll.FD{
29 Sysfd: sysfd,
30 IsStream: sotype == syscall.SOCK_STREAM,
31 ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
32 },
33 family: family,
34 sotype: sotype,
35 net: net,
36 }
37 return ret, nil
38 }
39
40 func (fd *netFD) init() error {
41 return fd.pfd.Init(fd.net, true)
42 }
43
44 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa syscall.Sockaddr, ret error) {
45
46
47
48 switch err := connectFunc(fd.pfd.Sysfd, ra); err {
49 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
50 case nil, syscall.EISCONN:
51 select {
52 case <-ctx.Done():
53 return nil, mapErr(ctx.Err())
54 default:
55 }
56 if err := fd.pfd.Init(fd.net, true); err != nil {
57 return nil, err
58 }
59 runtime.KeepAlive(fd)
60 return nil, nil
61 case syscall.EINVAL:
62
63
64
65
66
67 if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" {
68 return nil, nil
69 }
70 fallthrough
71 default:
72 return nil, os.NewSyscallError("connect", err)
73 }
74 if err := fd.pfd.Init(fd.net, true); err != nil {
75 return nil, err
76 }
77 if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
78 fd.pfd.SetWriteDeadline(deadline)
79 defer fd.pfd.SetWriteDeadline(noDeadline)
80 }
81
82
83
84
85
86
87 ctxDone := ctx.Done()
88 if ctxDone != nil {
89
90
91 done := make(chan struct{})
92 interruptRes := make(chan error)
93 defer func() {
94 close(done)
95 if ctxErr := <-interruptRes; ctxErr != nil && ret == nil {
96
97
98
99
100
101
102 ret = mapErr(ctxErr)
103 fd.Close()
104 }
105 }()
106 go func() {
107 select {
108 case <-ctxDone:
109
110
111
112 fd.pfd.SetWriteDeadline(aLongTimeAgo)
113 testHookCanceledDial()
114 interruptRes <- ctx.Err()
115 case <-done:
116 interruptRes <- nil
117 }
118 }()
119 }
120
121 for {
122
123
124
125
126
127
128
129
130 if err := fd.pfd.WaitWrite(); err != nil {
131 select {
132 case <-ctxDone:
133 return nil, mapErr(ctx.Err())
134 default:
135 }
136 return nil, err
137 }
138 nerr, err := getsockoptIntFunc(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
139 if err != nil {
140 return nil, os.NewSyscallError("getsockopt", err)
141 }
142 switch err := syscall.Errno(nerr); err {
143 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
144 case syscall.EISCONN:
145 return nil, nil
146 case syscall.Errno(0):
147
148
149
150 if rsa, err := syscall.Getpeername(fd.pfd.Sysfd); err == nil {
151 return rsa, nil
152 }
153 default:
154 return nil, os.NewSyscallError("connect", err)
155 }
156 runtime.KeepAlive(fd)
157 }
158 }
159
160 func (fd *netFD) accept() (netfd *netFD, err error) {
161 d, rsa, errcall, err := fd.pfd.Accept()
162 if err != nil {
163 if errcall != "" {
164 err = wrapSyscallError(errcall, err)
165 }
166 return nil, err
167 }
168
169 if netfd, err = newFD(d, fd.family, fd.sotype, fd.net); err != nil {
170 poll.CloseFunc(d)
171 return nil, err
172 }
173 if err = netfd.init(); err != nil {
174 netfd.Close()
175 return nil, err
176 }
177 lsa, _ := syscall.Getsockname(netfd.pfd.Sysfd)
178 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
179 return netfd, nil
180 }
181
182
183 func newUnixFile(fd int, name string) *os.File
184
185 func (fd *netFD) dup() (f *os.File, err error) {
186 ns, call, err := fd.pfd.Dup()
187 if err != nil {
188 if call != "" {
189 err = os.NewSyscallError(call, err)
190 }
191 return nil, err
192 }
193
194 return newUnixFile(ns, fd.name()), nil
195 }
196
View as plain text