github.com/sagernet/tfo-go@v0.0.0-20231209031829-7b5343ac1dc6/tfo_listen_generic.go (about)

     1  //go:build freebsd || linux || windows
     2  
     3  package tfo
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"net"
     9  	"os"
    10  	"syscall"
    11  )
    12  
    13  // defaultBacklog is Go std's listen(2) backlog.
    14  // We use this as the default TFO backlog.
    15  const defaultBacklog = 4096
    16  
    17  func (lc *ListenConfig) listenTFO(ctx context.Context, network, address string) (net.Listener, error) {
    18  	ctrlFn := lc.Control
    19  	backlog := lc.Backlog
    20  	if backlog == 0 {
    21  		backlog = defaultBacklog
    22  	}
    23  	llc := *lc
    24  	llc.Control = func(network, address string, c syscall.RawConn) (err error) {
    25  		if ctrlFn != nil {
    26  			if err = ctrlFn(network, address, c); err != nil {
    27  				return err
    28  			}
    29  		}
    30  
    31  		if cerr := c.Control(func(fd uintptr) {
    32  			err = setTFOListenerWithBacklog(fd, backlog)
    33  		}); cerr != nil {
    34  			return cerr
    35  		}
    36  
    37  		if err != nil {
    38  			if !lc.Fallback || !errors.Is(err, os.ErrInvalid) {
    39  				return wrapSyscallError("setsockopt(TCP_FASTOPEN)", err)
    40  			}
    41  			runtimeListenNoTFO.Store(true)
    42  		}
    43  		return nil
    44  	}
    45  	return llc.ListenConfig.Listen(ctx, network, address)
    46  }