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