sock_windows.go

 1//go:build windows
 2
 3package sysfs
 4
 5import (
 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
15const (
16	// MSG_PEEK is the flag PEEK for syscall.Recvfrom on Windows.
17	// This constant is not exported on this platform.
18	MSG_PEEK = 0x2
19	// _FIONBIO is the flag to set the O_NONBLOCK flag on socket handles using ioctlsocket.
20	_FIONBIO = 0x8004667e
21)
22
23var (
24	// modws2_32 is WinSock.
25	modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
26	// procrecvfrom exposes recvfrom from WinSock.
27	procrecvfrom = modws2_32.NewProc("recvfrom")
28	// procioctlsocket exposes ioctlsocket from WinSock.
29	procioctlsocket = modws2_32.NewProc("ioctlsocket")
30)
31
32func newTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock {
33	return newDefaultTCPListenerFile(tl)
34}
35
36// recvfrom exposes the underlying syscall in Windows.
37//
38// Note: since we are only using this to expose MSG_PEEK,
39// we do not need really need all the parameters that are actually
40// allowed in WinSock.
41// We ignore `from *sockaddr` and `fromlen *int`.
42func recvfrom(s uintptr, buf []byte, flags int32) (n int, errno sys.Errno) {
43	var _p0 *byte
44	if len(buf) > 0 {
45		_p0 = &buf[0]
46	}
47	r0, _, e1 := syscall.SyscallN(
48		procrecvfrom.Addr(),
49		s,
50		uintptr(unsafe.Pointer(_p0)),
51		uintptr(len(buf)),
52		uintptr(flags),
53		0, // from *sockaddr (optional)
54		0) // fromlen *int (optional)
55	return int(r0), sys.UnwrapOSError(e1)
56}
57
58func setNonblockSocket(fd uintptr, enabled bool) sys.Errno {
59	opt := uint64(0)
60	if enabled {
61		opt = 1
62	}
63	// ioctlsocket(fd, FIONBIO, &opt)
64	_, _, errno := syscall.SyscallN(
65		procioctlsocket.Addr(),
66		uintptr(fd),
67		uintptr(_FIONBIO),
68		uintptr(unsafe.Pointer(&opt)))
69	return sys.UnwrapOSError(errno)
70}
71
72func _pollSock(conn syscall.Conn, flag fsapi.Pflag, timeoutMillis int32) (bool, sys.Errno) {
73	if flag != fsapi.POLLIN {
74		return false, sys.ENOTSUP
75	}
76	n, errno := syscallConnControl(conn, func(fd uintptr) (int, sys.Errno) {
77		return _poll([]pollFd{newPollFd(fd, _POLLIN, 0)}, timeoutMillis)
78	})
79	return n > 0, errno
80}