Просмотр исходного кода

Fix: net.FilePacketConn not supported on Windows

Rod Hynes 7 лет назад
Родитель
Сommit
7c9832b9c6
4 измененных файлов с 112 добавлено и 29 удалено
  1. 1 2
      psiphon/LookupIP_nobind.go
  2. 2 27
      psiphon/UDPConn.go
  3. 64 0
      psiphon/UDPConn_bind.go
  4. 45 0
      psiphon/UDPConn_nobind.go

+ 1 - 2
psiphon/LookupIP_nobind.go

@@ -29,8 +29,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 )
 
-// LookupIP resolves a hostname. When BindToDevice is not required, it
-// simply uses net.LookupIP.
+// LookupIP resolves a hostname.
 func LookupIP(ctx context.Context, host string, config *DialConfig) ([]net.IP, error) {
 
 	if config.DeviceBinder != nil {

+ 2 - 27
psiphon/UDPConn.go

@@ -25,7 +25,6 @@ import (
 	"fmt"
 	"math/rand"
 	"net"
-	"os"
 	"strconv"
 	"syscall"
 
@@ -44,8 +43,6 @@ import (
 func NewUDPConn(
 	ctx context.Context, addr string, config *DialConfig) (net.PacketConn, *net.UDPAddr, error) {
 
-	// TODO: refactor code in common with tcpDial.
-
 	host, strPort, err := net.SplitHostPort(addr)
 	if err != nil {
 		return nil, nil, common.ContextError(err)
@@ -64,6 +61,7 @@ func NewUDPConn(
 	}
 
 	ipAddr := ipAddrs[rand.Intn(len(ipAddrs))]
+
 	if config.IPv6Synthesizer != nil {
 		if ipAddr.To4() != nil {
 			synthesizedIPAddress := config.IPv6Synthesizer.IPv6Synthesize(ipAddr.String())
@@ -85,30 +83,7 @@ func NewUDPConn(
 		return nil, nil, common.ContextError(fmt.Errorf("invalid IP address: %s", ipAddr.String()))
 	}
 
-	socketFD, err := syscall.Socket(domain, syscall.SOCK_DGRAM, 0)
-	if err != nil {
-		return nil, nil, common.ContextError(err)
-	}
-
-	syscall.CloseOnExec(socketFD)
-
-	setAdditionalSocketOptions(socketFD)
-
-	if config.DeviceBinder != nil {
-		err := bindToDeviceCallWrapper(config.DeviceBinder, socketFD)
-		if err != nil {
-			syscall.Close(socketFD)
-			return nil, nil, common.ContextError(fmt.Errorf("BindToDevice failed: %s", err))
-		}
-	}
-
-	// Convert the socket fd to a net.PacketConn
-	// This code block is from:
-	// https://github.com/golang/go/issues/6966
-
-	file := os.NewFile(uintptr(socketFD), "")
-	conn, err := net.FilePacketConn(file) // net.FilePackateConn() dups socketFD
-	file.Close()                          // file.Close() closes socketFD
+	conn, err := newUDPConn(domain, config)
 	if err != nil {
 		return nil, nil, common.ContextError(err)
 	}

+ 64 - 0
psiphon/UDPConn_bind.go

@@ -0,0 +1,64 @@
+// +build !windows
+
+/*
+ * Copyright (c) 2018, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package psiphon
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"syscall"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+)
+
+func newUDPConn(domain int, config *DialConfig) (net.PacketConn, error) {
+
+	socketFD, err := syscall.Socket(domain, syscall.SOCK_DGRAM, 0)
+	if err != nil {
+		return nil, common.ContextError(err)
+	}
+
+	syscall.CloseOnExec(socketFD)
+
+	setAdditionalSocketOptions(socketFD)
+
+	if config.DeviceBinder != nil {
+		err := bindToDeviceCallWrapper(config.DeviceBinder, socketFD)
+		if err != nil {
+			syscall.Close(socketFD)
+			return nil, common.ContextError(fmt.Errorf("BindToDevice failed: %s", err))
+		}
+	}
+
+	// Convert the socket fd to a net.PacketConn
+	// This code block is from:
+	// https://github.com/golang/go/issues/6966
+
+	file := os.NewFile(uintptr(socketFD), "")
+	conn, err := net.FilePacketConn(file) // net.FilePackateConn() dups socketFD
+	file.Close()                          // file.Close() closes socketFD
+	if err != nil {
+		return nil, common.ContextError(err)
+	}
+
+	return conn, nil
+}

+ 45 - 0
psiphon/UDPConn_nobind.go

@@ -0,0 +1,45 @@
+// +build windows
+
+/*
+ * Copyright (c) 2018, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package psiphon
+
+import (
+	"errors"
+	"net"
+	"syscall"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
+)
+
+func newUDPConn(domain int, config *DialConfig) (net.PacketConn, error) {
+
+	if config.DeviceBinder != nil {
+		return nil, common.ContextError(errors.New("newUDPConn with DeviceBinder not supported on this platform"))
+	}
+
+	network := "udp4"
+
+	if domain == syscall.AF_INET6 {
+		network = "udp6"
+	}
+
+	return net.ListenUDP(network, nil)
+}