mirror of
https://github.com/golang/go
synced 2024-11-16 18:04:39 -07:00
internal/syscall/windows: implement SupportUnixSocket by enumerating protocols
windows.SupportUnixSocket is currently implemented using a Windows version check. This approach is not reliable, see #27943 and #28061. Also, it uses the undocumented RtlGetNtVersionNumbers API, which we should try to avoid. This PR implements SupportUnixSocket by enumerating the available protocols and checking for AF_UNIX support. Cq-Include-Trybots: luci.golang.try:gotip-windows-arm64 Change-Id: I76cd635067309f09571ad0eac4a5699450a2709a Reviewed-on: https://go-review.googlesource.com/c/go/+/570075 Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Reviewed-by: Bryan Mills <bcmills@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
293fadffe7
commit
34d28ba932
@ -201,7 +201,9 @@ const (
|
||||
WSA_FLAG_OVERLAPPED = 0x01
|
||||
WSA_FLAG_NO_HANDLE_INHERIT = 0x80
|
||||
|
||||
WSAEINVAL syscall.Errno = 10022
|
||||
WSAEMSGSIZE syscall.Errno = 10040
|
||||
WSAEAFNOSUPPORT syscall.Errno = 10047
|
||||
|
||||
MSG_PEEK = 0x2
|
||||
MSG_TRUNC = 0x0100
|
||||
|
@ -6,7 +6,8 @@ package windows
|
||||
|
||||
import (
|
||||
"sync"
|
||||
_ "unsafe" // for linkname
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// version retrieves the major, minor, and build version numbers
|
||||
@ -42,6 +43,21 @@ var SupportTCPInitialRTONoSYNRetransmissions = sync.OnceValue(func() bool {
|
||||
// Unix Domain Sockets.
|
||||
// The minimal requirement is Windows 10.0.17063.
|
||||
var SupportUnixSocket = sync.OnceValue(func() bool {
|
||||
major, _, build := version()
|
||||
return major >= 10 && build >= 17063
|
||||
var size uint32
|
||||
// First call to get the required buffer size in bytes.
|
||||
// Ignore the error, it will always fail.
|
||||
_, _ = syscall.WSAEnumProtocols(nil, nil, &size)
|
||||
n := int32(size) / int32(unsafe.Sizeof(syscall.WSAProtocolInfo{}))
|
||||
// Second call to get the actual protocols.
|
||||
buf := make([]syscall.WSAProtocolInfo, n)
|
||||
n, err := syscall.WSAEnumProtocols(nil, &buf[0], &size)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for i := int32(0); i < n; i++ {
|
||||
if buf[i].AddressFamily == syscall.AF_UNIX {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
31
src/internal/syscall/windows/version_windows_test.go
Normal file
31
src/internal/syscall/windows/version_windows_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package windows_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"internal/syscall/windows"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSupportUnixSocket(t *testing.T) {
|
||||
var d syscall.WSAData
|
||||
if err := syscall.WSAStartup(uint32(0x202), &d); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer syscall.WSACleanup()
|
||||
|
||||
// Test that SupportUnixSocket returns true if WSASocket succeeds with AF_UNIX.
|
||||
got := windows.SupportUnixSocket()
|
||||
s, err := windows.WSASocket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0, nil, 0, windows.WSA_FLAG_NO_HANDLE_INHERIT)
|
||||
if err == nil {
|
||||
syscall.Closesocket(s)
|
||||
}
|
||||
want := !errors.Is(err, windows.WSAEAFNOSUPPORT) && !errors.Is(err, windows.WSAEINVAL)
|
||||
if want != got {
|
||||
t.Errorf("SupportUnixSocket = %v; want %v", got, want)
|
||||
}
|
||||
}
|
@ -10,26 +10,13 @@ import (
|
||||
"internal/syscall/windows"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func skipIfUnixSocketNotSupported(t *testing.T) {
|
||||
// TODO: the windows.SupportUnixSocket check should be enough, investigate why 386 and arm
|
||||
// can't run these tests on newer Windows.
|
||||
switch runtime.GOARCH {
|
||||
case "386":
|
||||
t.Skip("not supported on windows/386, see golang.org/issue/27943")
|
||||
case "arm":
|
||||
t.Skip("not supported on windows/arm, see golang.org/issue/28061")
|
||||
}
|
||||
func TestUnixConnLocalWindows(t *testing.T) {
|
||||
if !windows.SupportUnixSocket() {
|
||||
t.Skip("unix test")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnixConnLocalWindows(t *testing.T) {
|
||||
skipIfUnixSocketNotSupported(t)
|
||||
handler := func(ls *localServer, ln Listener) {}
|
||||
for _, laddr := range []string{"", testUnixAddr(t)} {
|
||||
laddr := laddr
|
||||
@ -83,7 +70,10 @@ func TestUnixConnLocalWindows(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModeSocket(t *testing.T) {
|
||||
skipIfUnixSocketNotSupported(t)
|
||||
if !windows.SupportUnixSocket() {
|
||||
t.Skip("unix test")
|
||||
}
|
||||
|
||||
addr := testUnixAddr(t)
|
||||
|
||||
l, err := Listen("unix", addr)
|
||||
|
Loading…
Reference in New Issue
Block a user