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
78 ctxDone := ctx.Done()
79 if ctxDone != nil {
80 if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
81 fd.pfd.SetWriteDeadline(deadline)
82 defer fd.pfd.SetWriteDeadline(noDeadline)
83 }
84
85 stop := context.AfterFunc(ctx, func() {
86
87
88
89 _ = fd.pfd.SetWriteDeadline(aLongTimeAgo)
90 testHookCanceledDial()
91 })
92 defer func() {
93 if !stop() && ret == nil {
94
95
96
97
98
99
100 ret = mapErr(ctx.Err())
101
102
103 }
104 }()
105 }
106
107 for {
108
109
110
111
112
113
114
115
116 if err := fd.pfd.WaitWrite(); err != nil {
117 select {
118 case <-ctxDone:
119 return nil, mapErr(ctx.Err())
120 default:
121 }
122 return nil, err
123 }
124 nerr, err := getsockoptIntFunc(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
125 if err != nil {
126 return nil, os.NewSyscallError("getsockopt", err)
127 }
128 switch err := syscall.Errno(nerr); err {
129 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
130 case syscall.EISCONN:
131 return nil, nil
132 case syscall.Errno(0):
133
134
135
136 if rsa, err := syscall.Getpeername(fd.pfd.Sysfd); err == nil {
137 return rsa, nil
138 }
139 default:
140 return nil, os.NewSyscallError("connect", err)
141 }
142 runtime.KeepAlive(fd)
143 }
144 }
145
146 func (fd *netFD) accept() (netfd *netFD, err error) {
147 d, rsa, errcall, err := fd.pfd.Accept()
148 if err != nil {
149 if errcall != "" {
150 err = wrapSyscallError(errcall, err)
151 }
152 return nil, err
153 }
154
155 if netfd, err = newFD(d, fd.family, fd.sotype, fd.net); err != nil {
156 poll.CloseFunc(d)
157 return nil, err
158 }
159 if err = netfd.init(); err != nil {
160 netfd.Close()
161 return nil, err
162 }
163 lsa, _ := syscall.Getsockname(netfd.pfd.Sysfd)
164 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
165 return netfd, nil
166 }
167
168
169 func newUnixFile(fd int, name string) *os.File
170
171 func (fd *netFD) dup() (f *os.File, err error) {
172 ns, call, err := fd.pfd.Dup()
173 if err != nil {
174 if call != "" {
175 err = os.NewSyscallError(call, err)
176 }
177 return nil, err
178 }
179
180 return newUnixFile(ns, fd.name()), nil
181 }
182
View as plain text