github.com/sagernet/tfo-go@v0.0.0-20231209031829-7b5343ac1dc6/tfo_darwin.go (about) 1 package tfo 2 3 import ( 4 "context" 5 "errors" 6 "net" 7 "os" 8 "syscall" 9 10 "golang.org/x/sys/unix" 11 ) 12 13 func (lc *ListenConfig) listenTFO(ctx context.Context, network, address string) (net.Listener, error) { 14 // When setting TCP_FASTOPEN_FORCE_ENABLE, the socket must be in the TCPS_CLOSED state. 15 // This means setting it before listen(). 16 // 17 // However, setting TCP_FASTOPEN requires being in the TCPS_LISTEN state, 18 // which means setting it after listen(). 19 20 ctrlFn := lc.Control 21 llc := *lc 22 llc.Control = func(network, address string, c syscall.RawConn) (err error) { 23 if ctrlFn != nil { 24 if err = ctrlFn(network, address, c); err != nil { 25 return err 26 } 27 } 28 29 if cerr := c.Control(func(fd uintptr) { 30 err = setTFOForceEnable(fd) 31 }); cerr != nil { 32 return cerr 33 } 34 35 if err != nil { 36 if !lc.Fallback || !errors.Is(err, os.ErrInvalid) { 37 return wrapSyscallError("setsockopt(TCP_FASTOPEN_FORCE_ENABLE)", err) 38 } 39 runtimeListenNoTFO.Store(true) 40 } 41 return nil 42 } 43 44 ln, err := llc.ListenConfig.Listen(ctx, network, address) 45 if err != nil { 46 return nil, err 47 } 48 49 rawConn, err := ln.(*net.TCPListener).SyscallConn() 50 if err != nil { 51 ln.Close() 52 return nil, err 53 } 54 55 if cerr := rawConn.Control(func(fd uintptr) { 56 err = setTFOListener(fd) 57 }); cerr != nil { 58 ln.Close() 59 return nil, cerr 60 } 61 62 if err != nil { 63 ln.Close() 64 if !lc.Fallback || !errors.Is(err, os.ErrInvalid) { 65 return nil, wrapSyscallError("setsockopt(TCP_FASTOPEN)", err) 66 } 67 runtimeListenNoTFO.Store(true) 68 } 69 70 return ln, nil 71 } 72 73 const AF_MULTIPATH = 39 74 75 func (d *Dialer) socket(domain int) (fd int, err error) { 76 if DialerMultipathTCP(&d.Dialer) { 77 domain = AF_MULTIPATH 78 } 79 fd, err = unix.Socket(domain, unix.SOCK_STREAM, unix.IPPROTO_TCP) 80 if err != nil { 81 return 82 } 83 unix.CloseOnExec(fd) 84 err = unix.SetNonblock(fd, true) 85 if err != nil { 86 unix.Close(fd) 87 fd = 0 88 } 89 return 90 } 91 92 func (d *Dialer) setIPv6Only(fd int, family int, ipv6only bool) error { 93 if DialerMultipathTCP(&d.Dialer) { 94 return nil 95 } 96 return setIPv6Only(fd, family, ipv6only) 97 } 98 99 const setTFODialerFromSocketSockoptName = "TCP_FASTOPEN_FORCE_ENABLE" 100 101 const connectSyscallName = "connectx" 102 103 func doConnect(fd uintptr, rsa syscall.Sockaddr, b []byte) (int, error) { 104 n, err := Connectx(int(fd), 0, nil, rsa, b) 105 return int(n), err 106 }