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