e4d6829971
Implements tryEnableFastOpen by creating a localhost socket and enabling the TCP_FASTOPEN socket option. On builds where TCP_FASTOPEN isn't available, setting the socket option fails and tryEnableFastOpen returns false. This was verified on a supporting build (latest Windows 10) and an unsupporting build (Windows 8.1, couldn't find an ISO for an older Windows 10 build). Change-Id: I497117dc2f04acdd2b0cc836e20d12d69076b939
48 lines
1.3 KiB
Go
48 lines
1.3 KiB
Go
// Copyright (C) 2023 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package server
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"sync"
|
|
"syscall"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
const tcpFastOpen = 15 // Corresponds to TCP_FASTOPEN from MS SDK
|
|
|
|
func setTCPFastOpen(fd uintptr, queue int) error {
|
|
return syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_TCP, tcpFastOpen, 1)
|
|
}
|
|
|
|
var tryInitFastOpenOnce sync.Once
|
|
var initFastOpenPossiblyEnabled bool
|
|
|
|
// tryInitFastOpen returns true if fastopen support is possibly enabled.
|
|
func tryInitFastOpen(*zap.Logger) bool {
|
|
tryInitFastOpenOnce.Do(func() {
|
|
// TCP-FASTOPEN is supported as of Windows 10 build 1607, but is
|
|
// enabled per socket. If the socket option isn't supported then the
|
|
// call to opt-in will fail. So as long as we can set up a listening
|
|
// socket with the right socket option set, we should be good.
|
|
if listener, err := (&net.ListenConfig{
|
|
Control: func(network, addr string, c syscall.RawConn) error {
|
|
var sockOptErr error
|
|
if controlErr := c.Control(func(fd uintptr) {
|
|
sockOptErr = setTCPFastOpen(fd, 0) // queue is unused
|
|
}); controlErr != nil {
|
|
return controlErr
|
|
}
|
|
return sockOptErr
|
|
},
|
|
}).Listen(context.Background(), "tcp", "127.0.0.1:0"); err == nil {
|
|
listener.Close()
|
|
initFastOpenPossiblyEnabled = true
|
|
}
|
|
})
|
|
return initFastOpenPossiblyEnabled
|
|
}
|