1
2
3
4
5 package windows
6
7 import (
8 "errors"
9 "sync"
10 "syscall"
11 "unsafe"
12 )
13
14
15 type _OSVERSIONINFOW struct {
16 osVersionInfoSize uint32
17 majorVersion uint32
18 minorVersion uint32
19 buildNumber uint32
20 platformId uint32
21 csdVersion [128]uint16
22 }
23
24
25
26
27
28
29 func version() (major, minor, build uint32) {
30 info := _OSVERSIONINFOW{}
31 info.osVersionInfoSize = uint32(unsafe.Sizeof(info))
32 rtlGetVersion(&info)
33 return info.majorVersion, info.minorVersion, info.buildNumber
34 }
35
36 var (
37 supportTCPKeepAliveIdle bool
38 supportTCPKeepAliveInterval bool
39 supportTCPKeepAliveCount bool
40 )
41
42 var initTCPKeepAlive = sync.OnceFunc(func() {
43 s, err := WSASocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP, nil, 0, WSA_FLAG_NO_HANDLE_INHERIT)
44 if err != nil {
45
46 major, _, build := version()
47 supportTCPKeepAliveIdle = major >= 10 && build >= 16299
48 supportTCPKeepAliveInterval = major >= 10 && build >= 16299
49 supportTCPKeepAliveCount = major >= 10 && build >= 15063
50 return
51 }
52 defer syscall.Closesocket(s)
53 var optSupported = func(opt int) bool {
54 err := syscall.SetsockoptInt(s, syscall.IPPROTO_TCP, opt, 1)
55 return !errors.Is(err, syscall.WSAENOPROTOOPT)
56 }
57 supportTCPKeepAliveIdle = optSupported(TCP_KEEPIDLE)
58 supportTCPKeepAliveInterval = optSupported(TCP_KEEPINTVL)
59 supportTCPKeepAliveCount = optSupported(TCP_KEEPCNT)
60 })
61
62
63
64 func SupportTCPKeepAliveIdle() bool {
65 initTCPKeepAlive()
66 return supportTCPKeepAliveIdle
67 }
68
69
70
71 func SupportTCPKeepAliveInterval() bool {
72 initTCPKeepAlive()
73 return supportTCPKeepAliveInterval
74 }
75
76
77
78
79 func SupportTCPKeepAliveCount() bool {
80 initTCPKeepAlive()
81 return supportTCPKeepAliveCount
82 }
83
84
85
86
87 var SupportTCPInitialRTONoSYNRetransmissions = sync.OnceValue(func() bool {
88 major, _, build := version()
89 return major >= 10 && build >= 16299
90 })
91
92
93
94
95 var SupportUnixSocket = sync.OnceValue(func() bool {
96 var size uint32
97
98
99 _, _ = syscall.WSAEnumProtocols(nil, nil, &size)
100 n := int32(size) / int32(unsafe.Sizeof(syscall.WSAProtocolInfo{}))
101
102 buf := make([]syscall.WSAProtocolInfo, n)
103 n, err := syscall.WSAEnumProtocols(nil, &buf[0], &size)
104 if err != nil {
105 return false
106 }
107 for i := int32(0); i < n; i++ {
108 if buf[i].AddressFamily == syscall.AF_UNIX {
109 return true
110 }
111 }
112 return false
113 })
114
View as plain text