]> Cypherpunks repositories - gostls13.git/commitdiff
net: do not call syscall.Bind twice on windows
authorAlex Brainman <alex.brainman@gmail.com>
Wed, 1 May 2013 00:47:39 +0000 (17:47 -0700)
committerRob Pike <r@golang.org>
Wed, 1 May 2013 00:47:39 +0000 (17:47 -0700)
Fixes #5355.

R=golang-dev, mikioh.mikioh, bradfitz, r
CC=golang-dev
https://golang.org/cl/8966046

src/pkg/net/dial_test.go
src/pkg/net/fd_unix.go
src/pkg/net/fd_windows.go
src/pkg/net/sock_posix.go

index 41821e4adb10637cd0575da528ade68f6215a65f..e24fecc8d45f6281aed78c8e989eb617c97ee3e6 100644 (file)
@@ -372,3 +372,38 @@ func TestDialFailPDLeak(t *testing.T) {
                }
        }
 }
+
+func TestDialer(t *testing.T) {
+       ln, err := Listen("tcp4", "127.0.0.1:0")
+       if err != nil {
+               t.Fatalf("Listen failed: %v", err)
+       }
+       defer ln.Close()
+       ch := make(chan error, 1)
+       go func() {
+               var err error
+               c, err := ln.Accept()
+               if err != nil {
+                       ch <- fmt.Errorf("Accept failed: %v", err)
+                       return
+               }
+               defer c.Close()
+               ch <- nil
+       }()
+
+       laddr, err := ResolveTCPAddr("tcp4", "127.0.0.1:0")
+       if err != nil {
+               t.Fatalf("ResolveTCPAddr failed: %v", err)
+       }
+       d := &Dialer{LocalAddr: laddr}
+       c, err := d.Dial("tcp4", ln.Addr().String())
+       if err != nil {
+               t.Fatalf("Dial failed: %v", err)
+       }
+       defer c.Close()
+       c.Read(make([]byte, 1))
+       err = <-ch
+       if err != nil {
+               t.Error(err)
+       }
+}
index c160faeceb0922ed56943f82b2ebf45681f71ab7..8c59bff989cb01b3d6263cc28ded90a8b95838e1 100644 (file)
@@ -79,7 +79,7 @@ func (fd *netFD) name() string {
        return fd.net + ":" + ls + "->" + rs
 }
 
-func (fd *netFD) connect(ra syscall.Sockaddr) error {
+func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
        fd.wio.Lock()
        defer fd.wio.Unlock()
        if err := fd.pd.PrepareWrite(); err != nil {
index 3a16d8ae7b866e9aadbb9f986c2e238ef30627c9..fefd174bafa0b7fd7083bc523ec784dd963083bb 100644 (file)
@@ -364,22 +364,23 @@ func (o *connectOp) Name() string {
        return "ConnectEx"
 }
 
-func (fd *netFD) connect(ra syscall.Sockaddr) error {
+func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
        if !canUseConnectEx(fd.net) {
                return syscall.Connect(fd.sysfd, ra)
        }
        // ConnectEx windows API requires an unconnected, previously bound socket.
-       var la syscall.Sockaddr
-       switch ra.(type) {
-       case *syscall.SockaddrInet4:
-               la = &syscall.SockaddrInet4{}
-       case *syscall.SockaddrInet6:
-               la = &syscall.SockaddrInet6{}
-       default:
-               panic("unexpected type in connect")
-       }
-       if err := syscall.Bind(fd.sysfd, la); err != nil {
-               return err
+       if la == nil {
+               switch ra.(type) {
+               case *syscall.SockaddrInet4:
+                       la = &syscall.SockaddrInet4{}
+               case *syscall.SockaddrInet6:
+                       la = &syscall.SockaddrInet6{}
+               default:
+                       panic("unexpected type in connect")
+               }
+               if err := syscall.Bind(fd.sysfd, la); err != nil {
+                       return err
+               }
        }
        // Call ConnectEx API.
        var o connectOp
index 7e6a2c073dd52e8fe73a0b7e3b02ef910f74b25c..be89c26db2a38480383965b4008b5ba13a6d52e5 100644 (file)
@@ -57,7 +57,7 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
                if !deadline.IsZero() {
                        setWriteDeadline(fd, deadline)
                }
-               if err = fd.connect(ursa); err != nil {
+               if err = fd.connect(ulsa, ursa); err != nil {
                        fd.Close()
                        return nil, err
                }