@@ -6,10 +6,45 @@ import (
6
6
"errors"
7
7
"io"
8
8
"syscall"
9
+ "unsafe"
9
10
10
11
"golang.org/x/sys/windows"
11
12
)
12
13
14
+ const fionbio = 0x8004667e
15
+
16
+ // updateBlocking updates the blocking mode of the file descriptor.
17
+ // It returns true if the blocking mode was changed, and false if it was already in the desired mode.
18
+ // If an error occurs, it returns the error.
19
+ func updateBlocking (fd windows.Handle , blocking bool ) (bool , error ) {
20
+ // Determine the desired mode
21
+ var desiredMode uint32
22
+ if ! blocking {
23
+ desiredMode = 1
24
+ } else {
25
+ desiredMode = 0
26
+ }
27
+
28
+ // Query the current mode
29
+ var currentMode uint32
30
+ err := windows .WSAIoctl (fd , fionbio , (* byte )(unsafe .Pointer (& currentMode )), 4 , nil , 0 , nil , nil , 0 )
31
+ if err != nil {
32
+ return false , err
33
+ }
34
+
35
+ if currentMode == desiredMode {
36
+ return false , nil
37
+ }
38
+
39
+ // Update to the desired mode
40
+ err = windows .WSAIoctl (fd , fionbio , (* byte )(unsafe .Pointer (& desiredMode )), 4 , nil , 0 , nil , nil , 0 )
41
+ if err != nil {
42
+ return false , err
43
+ }
44
+
45
+ return true , nil
46
+ }
47
+
13
48
func OSPeekConn (conn syscall.Conn ) (PeekedBytes , error ) {
14
49
s := PeekedBytes {}
15
50
@@ -18,6 +53,24 @@ func OSPeekConn(conn syscall.Conn) (PeekedBytes, error) {
18
53
return s , err
19
54
}
20
55
56
+ var updatedBlocking bool
57
+ ctlErr := rawConn .Control (func (fd uintptr ) {
58
+ updatedBlocking , err = updateBlocking (windows .Handle (fd ), true )
59
+ })
60
+ if ctlErr != nil {
61
+ return s , ctlErr
62
+ }
63
+ if err != nil {
64
+ return s , err
65
+ }
66
+ if updatedBlocking {
67
+ defer func () {
68
+ _ = rawConn .Control (func (fd uintptr ) {
69
+ _ , _ = updateBlocking (windows .Handle (fd ), false )
70
+ })
71
+ }()
72
+ }
73
+
21
74
var readErr error
22
75
var n uint32
23
76
err = rawConn .Read (func (fd uintptr ) bool {
0 commit comments