1
2
3 package sysfs
4
5 import (
6 "net"
7 "syscall"
8 "unsafe"
9
10 "github.com/tetratelabs/wazero/experimental/sys"
11 "github.com/tetratelabs/wazero/internal/fsapi"
12 socketapi "github.com/tetratelabs/wazero/internal/sock"
13 )
14
15 const (
16
17
18 MSG_PEEK = 0x2
19
20 _FIONBIO = 0x8004667e
21 )
22
23 var (
24
25 modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
26
27 procrecvfrom = modws2_32.NewProc("recvfrom")
28
29 procioctlsocket = modws2_32.NewProc("ioctlsocket")
30 )
31
32
33
34
35
36
37
38 func recvfrom(s syscall.Handle, buf []byte, flags int32) (n int, errno sys.Errno) {
39 var _p0 *byte
40 if len(buf) > 0 {
41 _p0 = &buf[0]
42 }
43 r0, _, e1 := syscall.SyscallN(
44 procrecvfrom.Addr(),
45 uintptr(s),
46 uintptr(unsafe.Pointer(_p0)),
47 uintptr(len(buf)),
48 uintptr(flags),
49 0,
50 0)
51 return int(r0), sys.UnwrapOSError(e1)
52 }
53
54 func setNonblockSocket(fd syscall.Handle, enabled bool) sys.Errno {
55 opt := uint64(0)
56 if enabled {
57 opt = 1
58 }
59
60 _, _, errno := syscall.SyscallN(
61 procioctlsocket.Addr(),
62 uintptr(fd),
63 uintptr(_FIONBIO),
64 uintptr(unsafe.Pointer(&opt)))
65 return sys.UnwrapOSError(errno)
66 }
67
68
69
70
71
72
73
74 func syscallConnControl(conn syscall.Conn, fn func(fd uintptr) (int, sys.Errno)) (n int, errno sys.Errno) {
75 syscallConn, err := conn.SyscallConn()
76 if err != nil {
77 return 0, sys.UnwrapOSError(err)
78 }
79
80 if controlErr := syscallConn.Control(func(fd uintptr) {
81 n, errno = fn(fd)
82 }); errno == 0 {
83 errno = sys.UnwrapOSError(controlErr)
84 }
85 return
86 }
87
88 func _pollSock(conn syscall.Conn, flag fsapi.Pflag, timeoutMillis int32) (bool, sys.Errno) {
89 if flag != fsapi.POLLIN {
90 return false, sys.ENOTSUP
91 }
92 n, errno := syscallConnControl(conn, func(fd uintptr) (int, sys.Errno) {
93 return _poll([]pollFd{newPollFd(fd, _POLLIN, 0)}, timeoutMillis)
94 })
95 return n > 0, errno
96 }
97
98
99
100
101
102
103
104
105
106 func newTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock {
107 return &winTcpListenerFile{tl: tl}
108 }
109
110 var _ socketapi.TCPSock = (*winTcpListenerFile)(nil)
111
112 type winTcpListenerFile struct {
113 baseSockFile
114
115 tl *net.TCPListener
116 closed bool
117 nonblock bool
118 }
119
120
121 func (f *winTcpListenerFile) Accept() (socketapi.TCPConn, sys.Errno) {
122
123 if f.nonblock {
124 if ready, errno := _pollSock(f.tl, fsapi.POLLIN, 0); !ready || errno != 0 {
125 return nil, sys.EAGAIN
126 }
127 }
128
129
130
131
132 if conn, err := f.tl.Accept(); err != nil {
133 return nil, sys.UnwrapOSError(err)
134 } else {
135 return newTcpConn(conn.(*net.TCPConn)), 0
136 }
137 }
138
139
140 func (f *winTcpListenerFile) Close() sys.Errno {
141 if !f.closed {
142 return sys.UnwrapOSError(f.tl.Close())
143 }
144 return 0
145 }
146
147
148 func (f *winTcpListenerFile) Addr() *net.TCPAddr {
149 return f.tl.Addr().(*net.TCPAddr)
150 }
151
152
153 func (f *winTcpListenerFile) IsNonblock() bool {
154 return f.nonblock
155 }
156
157
158 func (f *winTcpListenerFile) SetNonblock(enabled bool) sys.Errno {
159 f.nonblock = enabled
160 _, errno := syscallConnControl(f.tl, func(fd uintptr) (int, sys.Errno) {
161 return 0, setNonblockSocket(syscall.Handle(fd), enabled)
162 })
163 return errno
164 }
165
166
167 func (f *winTcpListenerFile) Poll(fsapi.Pflag, int32) (ready bool, errno sys.Errno) {
168 return false, sys.ENOSYS
169 }
170
171 var _ socketapi.TCPConn = (*winTcpConnFile)(nil)
172
173
174
175
176 type winTcpConnFile struct {
177 baseSockFile
178
179 tc *net.TCPConn
180
181
182
183 nonblock bool
184
185 closed bool
186 }
187
188 func newTcpConn(tc *net.TCPConn) socketapi.TCPConn {
189 return &winTcpConnFile{tc: tc}
190 }
191
192
193 func (f *winTcpConnFile) Read(buf []byte) (n int, errno sys.Errno) {
194 if len(buf) == 0 {
195 return 0, 0
196 }
197 if nonBlockingFileReadSupported && f.IsNonblock() {
198 n, errno = syscallConnControl(f.tc, func(fd uintptr) (int, sys.Errno) {
199 return readSocket(syscall.Handle(fd), buf)
200 })
201 } else {
202 n, errno = read(f.tc, buf)
203 }
204 if errno != 0 {
205
206 errno = fileError(f, f.closed, errno)
207 }
208 return
209 }
210
211
212 func (f *winTcpConnFile) Write(buf []byte) (n int, errno sys.Errno) {
213 if nonBlockingFileWriteSupported && f.IsNonblock() {
214 return syscallConnControl(f.tc, func(fd uintptr) (int, sys.Errno) {
215 return writeSocket(fd, buf)
216 })
217 } else {
218 n, errno = write(f.tc, buf)
219 }
220 if errno != 0 {
221
222 errno = fileError(f, f.closed, errno)
223 }
224 return
225 }
226
227
228 func (f *winTcpConnFile) Recvfrom(p []byte, flags int) (n int, errno sys.Errno) {
229 if flags != MSG_PEEK {
230 errno = sys.EINVAL
231 return
232 }
233 return syscallConnControl(f.tc, func(fd uintptr) (int, sys.Errno) {
234 return recvfrom(syscall.Handle(fd), p, MSG_PEEK)
235 })
236 }
237
238
239 func (f *winTcpConnFile) Shutdown(how int) sys.Errno {
240
241 var err error
242 switch how {
243 case syscall.SHUT_RD:
244 err = f.tc.CloseRead()
245 case syscall.SHUT_WR:
246 err = f.tc.CloseWrite()
247 case syscall.SHUT_RDWR:
248 return f.close()
249 default:
250 return sys.EINVAL
251 }
252 return sys.UnwrapOSError(err)
253 }
254
255
256 func (f *winTcpConnFile) Close() sys.Errno {
257 return f.close()
258 }
259
260 func (f *winTcpConnFile) close() sys.Errno {
261 if f.closed {
262 return 0
263 }
264 f.closed = true
265 return f.Shutdown(syscall.SHUT_RDWR)
266 }
267
268
269 func (f *winTcpConnFile) IsNonblock() bool {
270 return f.nonblock
271 }
272
273
274 func (f *winTcpConnFile) SetNonblock(enabled bool) (errno sys.Errno) {
275 f.nonblock = true
276 _, errno = syscallConnControl(f.tc, func(fd uintptr) (int, sys.Errno) {
277 return 0, sys.UnwrapOSError(setNonblockSocket(syscall.Handle(fd), enabled))
278 })
279 return
280 }
281
282
283 func (f *winTcpConnFile) Poll(fsapi.Pflag, int32) (ready bool, errno sys.Errno) {
284 return false, sys.ENOSYS
285 }
286
View as plain text