Browse Source

fixed ReadV issue for windows

sync https://github.com/v2fly/v2ray-core/commit/847b289798eca6ec90b3733288a27887c7427522
Kslr 6 years ago
parent
commit
c6f3ab48ee
3 changed files with 52 additions and 1 deletions
  1. 6 1
      common/buf/io.go
  2. 9 0
      common/buf/readv_constraint_other.go
  3. 37 0
      common/buf/readv_constraint_windows.go

+ 6 - 1
common/buf/io.go

@@ -63,7 +63,12 @@ func NewReader(reader io.Reader) Reader {
 			if err != nil {
 				newError("failed to get sysconn").Base(err).WriteToLog()
 			} else {
-				return NewReadVReader(reader, rawConn)
+				/* Check if ReadVReader Can be used on this reader first
+				Fix https://github.com/v2ray/v2ray-core/issues/1666
+				*/
+				if ok, _ := checkReadVConstraint(rawConn); ok {
+					return NewReadVReader(reader, rawConn)
+				}
 			}
 		}
 	}

+ 9 - 0
common/buf/readv_constraint_other.go

@@ -0,0 +1,9 @@
+// +build !windows
+
+package buf
+
+import "syscall"
+
+func checkReadVConstraint(conn syscall.RawConn) (bool, error) {
+	return true, nil
+}

+ 37 - 0
common/buf/readv_constraint_windows.go

@@ -0,0 +1,37 @@
+// +build windows
+package buf
+
+import (
+	"syscall"
+)
+
+func checkReadVConstraint(conn syscall.RawConn) (bool, error) {
+	var isSocketReady = false
+	var reason error
+	/*
+		In Windows, WSARecv system call only support socket connection.
+
+		It it required to check if the given fd is of a socket type
+
+		Fix https://github.com/v2ray/v2ray-core/issues/1666
+
+		Additional Information:
+		https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsarecv
+		https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-getsockopt
+		https://docs.microsoft.com/en-us/windows/desktop/WinSock/sol-socket-socket-options
+
+	*/
+	err := conn.Control(func(fd uintptr) {
+		var val [4]byte
+		var le = int32(len(val))
+		err := syscall.Getsockopt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, &val[0], &le)
+		if err != nil {
+			isSocketReady = false
+		} else {
+			isSocketReady = true
+		}
+		reason = err
+	})
+
+	return isSocketReady, err
+}