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 {
27 return &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 }
38
39 func (fd *netFD) init() error {
40 return fd.pfd.Init(fd.net, true)
41 }
42
43 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa syscall.Sockaddr, ret error) {
44
45
46
47 switch err := connectFunc(fd.pfd.Sysfd, ra); err {
48 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
49 case nil, syscall.EISCONN:
50 select {
51 case <-ctx.Done():
52 return nil, mapErr(ctx.Err())
53 default:
54 }
55 if err := fd.pfd.Init(fd.net, true); err != nil {
56 return nil, err
57 }
58 runtime.KeepAlive(fd)
59 return nil, nil
60 case syscall.EINVAL:
61
62
63
64
65
66 if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" {
67 return nil, nil
68 }
69 fallthrough
70 default:
71 return nil, os.NewSyscallError("connect", err)
72 }
73 if err := fd.pfd.Init(fd.net, true); err != nil {
74 return nil, err
75 }
76
77 ctxDone := ctx.Done()
78 if ctxDone != nil {
79 if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
80 fd.pfd.SetWriteDeadline(deadline)
81 defer fd.pfd.SetWriteDeadline(noDeadline)
82 }
83
84
85
86 testHookCanceledDial := testHookCanceledDial
87 stop := context.AfterFunc(ctx, func() {
88
89
90
91 _ = fd.pfd.SetWriteDeadline(aLongTimeAgo)
92 testHookCanceledDial()
93 })
94 defer func() {
95 if !stop() && ret == nil {
96
97
98
99
100
101
102 ret = mapErr(ctx.Err())
103
104
105 }
106 }()
107 }
108
109 for {
110
111
112
113
114
115
116
117
118 if err := fd.pfd.WaitWrite(); err != nil {
119 select {
120 case <-ctxDone:
121 return nil, mapErr(ctx.Err())
122 default:
123 }
124 return nil, err
125 }
126 nerr, err := getsockoptIntFunc(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
127 if err != nil {
128 return nil, os.NewSyscallError("getsockopt", err)
129 }
130 switch err := syscall.Errno(nerr); err {
131 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
132 case syscall.EISCONN:
133 return nil, nil
134 case syscall.Errno(0):
135
136
137
138 if rsa, err := syscall.Getpeername(fd.pfd.Sysfd); err == nil {
139 return rsa, nil
140 }
141 default:
142 return nil, os.NewSyscallError("connect", err)
143 }
144 runtime.KeepAlive(fd)
145 }
146 }
147
148 func (fd *netFD) accept() (netfd *netFD, err error) {
149 d, rsa, errcall, err := fd.pfd.Accept()
150 if err != nil {
151 if errcall != "" {
152 err = wrapSyscallError(errcall, err)
153 }
154 return nil, err
155 }
156
157 netfd = newFD(d, fd.family, fd.sotype, fd.net)
158 if err = netfd.init(); err != nil {
159 netfd.Close()
160 return nil, err
161 }
162 lsa, _ := syscall.Getsockname(netfd.pfd.Sysfd)
163 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
164 return netfd, nil
165 }
166
167
168 func newUnixFile(fd int, name string) *os.File
169
170 func (fd *netFD) dup() (f *os.File, err error) {
171 ns, call, err := fd.pfd.Dup()
172 if err != nil {
173 if call != "" {
174 err = os.NewSyscallError(call, err)
175 }
176 return nil, err
177 }
178
179 return newUnixFile(ns, fd.name()), nil
180 }
181
View as plain text