diff --git a/go.mod b/go.mod index 8ebfed6..500d5d6 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,5 @@ require ( github.com/valyala/bytebufferpool v1.0.0 github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e + golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34 ) diff --git a/go.sum b/go.sum index 863089e..d85bf3f 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,6 @@ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34 h1:u6CI7A++8r4SItZHYe2cWeAEndN4p1p+3Oum/Ft2EzM= +golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/reuseport/reuseport_test.go b/reuseport/reuseport_test.go index 76df6ee..a9b60ea 100644 --- a/reuseport/reuseport_test.go +++ b/reuseport/reuseport_test.go @@ -1,5 +1,3 @@ -// +build !windows - package reuseport import ( diff --git a/reuseport/reuseport_windows.go b/reuseport/reuseport_windows.go index 8137eb5..bf5c312 100644 --- a/reuseport/reuseport_windows.go +++ b/reuseport/reuseport_windows.go @@ -1,11 +1,23 @@ package reuseport import ( - "fmt" + "context" "net" + "syscall" + + "golang.org/x/sys/windows" ) -// Listen always returns ErrNoReusePort on Windows +var listenConfig = net.ListenConfig{ + Control: func(network, address string, c syscall.RawConn) (err error) { + return c.Control(func(fd uintptr) { + err = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1) + }) + }, +} + +// Listen returns TCP listener with SO_REUSEADDR option set, SO_REUSEPORT is not supported on Windows, so it uses +// SO_REUSEADDR as an alternative to achieve the same effect. func Listen(network, addr string) (net.Listener, error) { - return nil, &ErrNoReusePort{fmt.Errorf("Not supported on Windows")} + return listenConfig.Listen(context.Background(), network, addr) } diff --git a/reuseport/reuseport_windows_test.go b/reuseport/reuseport_windows_test.go deleted file mode 100644 index 33ac337..0000000 --- a/reuseport/reuseport_windows_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build windows - -package reuseport - -import ( - "testing" -) - -func TestListen(t *testing.T) { - _, err := Listen("tcp6", "[::1]:10082") - if err == nil { - t.Fatalf("unexpected non-error creating listener") - } - - if _, errnoreuseport := err.(*ErrNoReusePort); !errnoreuseport { - t.Fatalf("unexpected error creating listener: %s", err) - } -}