github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/transport/internet/sockopt_darwin.go (about) 1 package internet 2 3 import ( 4 "net" 5 6 "golang.org/x/sys/unix" 7 ) 8 9 const ( 10 // TCP_FASTOPEN_SERVER is the value to enable TCP fast open on darwin for server connections. 11 TCP_FASTOPEN_SERVER = 0x01 // nolint: revive,stylecheck 12 // TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections. 13 TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck 14 ) 15 16 func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { 17 if isTCPSocket(network) { 18 switch config.Tfo { 19 case SocketConfig_Enable: 20 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, TCP_FASTOPEN_CLIENT); err != nil { 21 return err 22 } 23 case SocketConfig_Disable: 24 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 0); err != nil { 25 return err 26 } 27 } 28 29 if config.TcpKeepAliveInterval > 0 { 30 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { 31 return newError("failed to set TCP_KEEPINTVL").Base(err) 32 } 33 } 34 if config.TcpKeepAliveIdle > 0 { 35 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveIdle)); err != nil { 36 return newError("failed to set TCP_KEEPALIVE (TCP keepalive idle time on Darwin)").Base(err) 37 } 38 } 39 40 if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 { 41 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { 42 return newError("failed to set SO_KEEPALIVE").Base(err) 43 } 44 } 45 } 46 47 if config.BindToDevice != "" { 48 iface, err := net.InterfaceByName(config.BindToDevice) 49 if err != nil { 50 return newError("failed to get interface ", config.BindToDevice).Base(err) 51 } 52 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil { 53 return newError("failed to set IP_BOUND_IF", err) 54 } 55 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil { 56 return newError("failed to set IPV6_BOUND_IF", err) 57 } 58 } 59 60 if config.TxBufSize != 0 { 61 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil { 62 return newError("failed to set SO_SNDBUF").Base(err) 63 } 64 } 65 66 if config.RxBufSize != 0 { 67 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, int(config.RxBufSize)); err != nil { 68 return newError("failed to set SO_RCVBUF").Base(err) 69 } 70 } 71 72 return nil 73 } 74 75 func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error { 76 if isTCPSocket(network) { 77 switch config.Tfo { 78 case SocketConfig_Enable: 79 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, TCP_FASTOPEN_SERVER); err != nil { 80 return err 81 } 82 case SocketConfig_Disable: 83 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 0); err != nil { 84 return err 85 } 86 } 87 if config.TcpKeepAliveInterval > 0 { 88 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil { 89 return newError("failed to set TCP_KEEPINTVL").Base(err) 90 } 91 } 92 if config.TcpKeepAliveIdle > 0 { 93 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveIdle)); err != nil { 94 return newError("failed to set TCP_KEEPALIVE (TCP keepalive idle time on Darwin)").Base(err) 95 } 96 } 97 if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 { 98 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { 99 return newError("failed to set SO_KEEPALIVE").Base(err) 100 } 101 } 102 } 103 104 if config.BindToDevice != "" { 105 iface, err := net.InterfaceByName(config.BindToDevice) 106 if err != nil { 107 return newError("failed to get interface ", config.BindToDevice).Base(err) 108 } 109 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil { 110 return newError("failed to set IP_BOUND_IF", err) 111 } 112 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil { 113 return newError("failed to set IPV6_BOUND_IF", err) 114 } 115 } 116 117 if config.TxBufSize != 0 { 118 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil { 119 return newError("failed to set SO_SNDBUF/SO_SNDBUFFORCE").Base(err) 120 } 121 } 122 123 if config.RxBufSize != 0 { 124 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, int(config.RxBufSize)); err != nil { 125 return newError("failed to set SO_RCVBUF/SO_RCVBUFFORCE").Base(err) 126 } 127 } 128 return nil 129 } 130 131 func bindAddr(fd uintptr, address []byte, port uint32) error { 132 return nil 133 } 134 135 func setReuseAddr(fd uintptr) error { 136 return nil 137 } 138 139 func setReusePort(fd uintptr) error { 140 return nil 141 }