1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
// 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
import (
"errors"
"sync"
"syscall"
"unsafe"
)
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw
type _OSVERSIONINFOEXW struct {
osVersionInfoSize uint32
majorVersion uint32
minorVersion uint32
buildNumber uint32
platformId uint32
csdVersion [128]uint16
servicePackMajor uint16
servicePackMinor uint16
suiteMask uint16
productType byte
reserved byte
}
// According to documentation, RtlGetVersion function always succeeds.
//sys rtlGetVersion(info *_OSVERSIONINFOEXW) = ntdll.RtlGetVersion
// Retrieves version information of the current Windows OS
// from the RtlGetVersion API.
func getVersionInfo() *_OSVERSIONINFOEXW {
info := _OSVERSIONINFOEXW{}
info.osVersionInfoSize = uint32(unsafe.Sizeof(info))
rtlGetVersion(&info)
return &info
}
// Version retrieves the major, minor, and build version numbers
// of the current Windows OS from the RtlGetVersion API.
func Version() (major, minor, build uint32) {
info := getVersionInfo()
return info.majorVersion, info.minorVersion, info.buildNumber
}
// SupportUnlimitedTransmitFile indicates whether the current
// Windows version's TransmitFile function imposes any
// concurrent operation limits.
// Workstation and client versions of Windows limit the number
// of concurrent TransmitFile operations allowed on the system
// to a maximum of two. Please see:
// https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
// https://golang.org/issue/73746
var SupportUnlimitedTransmitFile = sync.OnceValue(func() bool {
info := getVersionInfo()
return info.productType != VER_NT_WORKSTATION
})
var (
supportTCPKeepAliveIdle bool
supportTCPKeepAliveInterval bool
supportTCPKeepAliveCount bool
)
var initTCPKeepAlive = sync.OnceFunc(func() {
s, err := WSASocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP, nil, 0, WSA_FLAG_NO_HANDLE_INHERIT)
if err != nil {
// Fallback to checking the Windows version.
major, _, build := Version()
supportTCPKeepAliveIdle = major >= 10 && build >= 16299
supportTCPKeepAliveInterval = major >= 10 && build >= 16299
supportTCPKeepAliveCount = major >= 10 && build >= 15063
return
}
defer syscall.Closesocket(s)
var optSupported = func(opt int) bool {
err := syscall.SetsockoptInt(s, syscall.IPPROTO_TCP, opt, 1)
return !errors.Is(err, syscall.WSAENOPROTOOPT)
}
supportTCPKeepAliveIdle = optSupported(TCP_KEEPIDLE)
supportTCPKeepAliveInterval = optSupported(TCP_KEEPINTVL)
supportTCPKeepAliveCount = optSupported(TCP_KEEPCNT)
})
// SupportTCPKeepAliveIdle indicates whether TCP_KEEPIDLE is supported.
// The minimal requirement is Windows 10.0.16299.
func SupportTCPKeepAliveIdle() bool {
initTCPKeepAlive()
return supportTCPKeepAliveIdle
}
// SupportTCPKeepAliveInterval indicates whether TCP_KEEPINTVL is supported.
// The minimal requirement is Windows 10.0.16299.
func SupportTCPKeepAliveInterval() bool {
initTCPKeepAlive()
return supportTCPKeepAliveInterval
}
// SupportTCPKeepAliveCount indicates whether TCP_KEEPCNT is supported.
// supports TCP_KEEPCNT.
// The minimal requirement is Windows 10.0.15063.
func SupportTCPKeepAliveCount() bool {
initTCPKeepAlive()
return supportTCPKeepAliveCount
}
// SupportTCPInitialRTONoSYNRetransmissions indicates whether the current
// Windows version supports the TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS.
// The minimal requirement is Windows 10.0.16299.
var SupportTCPInitialRTONoSYNRetransmissions = sync.OnceValue(func() bool {
major, _, build := Version()
return major >= 10 && build >= 16299
})
// SupportUnixSocket indicates whether the current Windows version supports
// Unix Domain Sockets.
// The minimal requirement is Windows 10.0.17063.
var SupportUnixSocket = sync.OnceValue(func() bool {
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
})
|