mirror of https://github.com/XTLS/Xray-core
				
				
				
			Add TCPKeepAliveIdle in Sockopt option (#1166)
* Add TCP keep alive idle setting * Add TCP keep alive idle setting: auto generated * Add TCP keep alive support in Linux * Add TCP keep alive support in MacOS, FreeBSD * Add TCP keep alive support in Windows * fix bug introduced in adding tcp keep alive adjustment * embed macOS const to avoid platform inconsistency * embed macOS const to avoid platform inconsistency(again) * add TCP Keep Alive support in config * use sys/unix instead of syscall Suggestion from: https://github.com/v2fly/v2ray-core/pull/1395#issuecomment-974761647 * use sys/unix instead of syscall Suggestion from: https://github.com/v2fly/v2ray-core/pull/1395#issuecomment-974761647 * Separate TcpKeepAliveIdle and TcpKeepAliveInterval check logic * Disable tcp keepAlive when TcpKeepAliveIdle < 0 and TcpKeepAliveInterval <= 0 Co-authored-by: xqzr <34030394+xqzr@users.noreply.github.com> Co-authored-by: ValdikSS <iam@valdikss.org.ru> Co-authored-by: Shelikhoo <xiaokangwang@outlook.com> Co-authored-by: xqzr <34030394+xqzr@users.noreply.github.com>pull/1175/head
							parent
							
								
									50b5ea5a54
								
							
						
					
					
						commit
						340234166b
					
				| 
						 | 
				
			
			@ -532,6 +532,7 @@ type SocketConfig struct {
 | 
			
		|||
	DomainStrategy       string      `json:"domainStrategy"`
 | 
			
		||||
	DialerProxy          string      `json:"dialerProxy"`
 | 
			
		||||
	TCPKeepAliveInterval int32       `json:"tcpKeepAliveInterval"`
 | 
			
		||||
	TCPKeepAliveIdle     int32       `json:"tcpKeepAliveIdle"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Build implements Buildable.
 | 
			
		||||
| 
						 | 
				
			
			@ -579,6 +580,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
 | 
			
		|||
		AcceptProxyProtocol:  c.AcceptProxyProtocol,
 | 
			
		||||
		DialerProxy:          c.DialerProxy,
 | 
			
		||||
		TcpKeepAliveInterval: c.TCPKeepAliveInterval,
 | 
			
		||||
		TcpKeepAliveIdle:     c.TCPKeepAliveIdle,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
			
		||||
// versions:
 | 
			
		||||
// 	protoc-gen-go v1.27.1
 | 
			
		||||
// 	protoc-gen-go v1.28.1
 | 
			
		||||
// 	protoc        v3.18.0
 | 
			
		||||
// source: transport/internet/config.proto
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -423,6 +423,7 @@ type SocketConfig struct {
 | 
			
		|||
	DomainStrategy             DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
 | 
			
		||||
	DialerProxy                string         `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"`
 | 
			
		||||
	TcpKeepAliveInterval       int32          `protobuf:"varint,10,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"`
 | 
			
		||||
	TcpKeepAliveIdle           int32          `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *SocketConfig) Reset() {
 | 
			
		||||
| 
						 | 
				
			
			@ -527,6 +528,13 @@ func (x *SocketConfig) GetTcpKeepAliveInterval() int32 {
 | 
			
		|||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *SocketConfig) GetTcpKeepAliveIdle() int32 {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.TcpKeepAliveIdle
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var File_transport_internet_config_proto protoreflect.FileDescriptor
 | 
			
		||||
 | 
			
		||||
var file_transport_internet_config_proto_rawDesc = []byte{
 | 
			
		||||
| 
						 | 
				
			
			@ -579,7 +587,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
 | 
			
		|||
	0x12, 0x30, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79,
 | 
			
		||||
	0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74,
 | 
			
		||||
	0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f,
 | 
			
		||||
	0x78, 0x79, 0x22, 0x92, 0x04, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e,
 | 
			
		||||
	0x78, 0x79, 0x22, 0xc1, 0x04, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e,
 | 
			
		||||
	0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
 | 
			
		||||
	0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02,
 | 
			
		||||
	0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72,
 | 
			
		||||
| 
						 | 
				
			
			@ -609,27 +617,30 @@ var file_transport_internet_config_proto_rawDesc = []byte{
 | 
			
		|||
	0x35, 0x0a, 0x17, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x6c, 0x69, 0x76,
 | 
			
		||||
	0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05,
 | 
			
		||||
	0x52, 0x14, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x49, 0x6e,
 | 
			
		||||
	0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79,
 | 
			
		||||
	0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a,
 | 
			
		||||
	0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64,
 | 
			
		||||
	0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73,
 | 
			
		||||
	0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03,
 | 
			
		||||
	0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08,
 | 
			
		||||
	0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53,
 | 
			
		||||
	0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10,
 | 
			
		||||
	0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65,
 | 
			
		||||
	0x74, 0x10, 0x05, 0x2a, 0x41, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
 | 
			
		||||
	0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00,
 | 
			
		||||
	0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07,
 | 
			
		||||
	0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45,
 | 
			
		||||
	0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
 | 
			
		||||
	0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
 | 
			
		||||
	0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
 | 
			
		||||
	0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
 | 
			
		||||
	0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74,
 | 
			
		||||
	0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61,
 | 
			
		||||
	0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62,
 | 
			
		||||
	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
			
		||||
	0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d, 0x0a, 0x13, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65,
 | 
			
		||||
	0x65, 0x70, 0x5f, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x64, 0x6c, 0x65, 0x18, 0x0b, 0x20,
 | 
			
		||||
	0x01, 0x28, 0x05, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76,
 | 
			
		||||
	0x65, 0x49, 0x64, 0x6c, 0x65, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d,
 | 
			
		||||
	0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06,
 | 
			
		||||
	0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69,
 | 
			
		||||
	0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70,
 | 
			
		||||
	0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54,
 | 
			
		||||
	0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a,
 | 
			
		||||
	0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f,
 | 
			
		||||
	0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04,
 | 
			
		||||
	0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74,
 | 
			
		||||
	0x10, 0x05, 0x2a, 0x41, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
 | 
			
		||||
	0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12,
 | 
			
		||||
	0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55,
 | 
			
		||||
	0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f,
 | 
			
		||||
	0x49, 0x50, 0x36, 0x10, 0x03, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
 | 
			
		||||
	0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65,
 | 
			
		||||
	0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
 | 
			
		||||
	0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72,
 | 
			
		||||
	0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
 | 
			
		||||
	0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e,
 | 
			
		||||
	0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06,
 | 
			
		||||
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,4 +94,6 @@ message SocketConfig {
 | 
			
		|||
  string dialer_proxy = 9;
 | 
			
		||||
 | 
			
		||||
  int32 tcp_keep_alive_interval = 10;
 | 
			
		||||
 | 
			
		||||
  int32 tcp_keep_alive_idle = 11;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,16 @@
 | 
			
		|||
package internet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// TCP_FASTOPEN is the socket option on darwin for TCP fast open.
 | 
			
		||||
	TCP_FASTOPEN = 0x105
 | 
			
		||||
	// TCP_FASTOPEN_SERVER is the value to enable TCP fast open on darwin for server connections.
 | 
			
		||||
	TCP_FASTOPEN_SERVER = 0x01
 | 
			
		||||
	// TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections.
 | 
			
		||||
	TCP_FASTOPEN_CLIENT = 0x02
 | 
			
		||||
	TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck
 | 
			
		||||
	// syscall.TCP_KEEPINTVL is missing on some darwin architectures.
 | 
			
		||||
	sysTCP_KEEPINTVL = 0x101 // nolint: revive,stylecheck
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,10 +20,30 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
 | 
			
		|||
			tfo = TCP_FASTOPEN_CLIENT
 | 
			
		||||
		}
 | 
			
		||||
		if tfo >= 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
 | 
			
		||||
			if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, tfo); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
			if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
				if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
				if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, sysTCP_KEEPINTVL, int(config.TcpKeepAliveIdle)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPIDLE", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
| 
						 | 
				
			
			@ -36,10 +56,29 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
 | 
			
		|||
			tfo = TCP_FASTOPEN_SERVER
 | 
			
		||||
		}
 | 
			
		||||
		if tfo >= 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
 | 
			
		||||
			if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, tfo); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
			if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
				if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
				if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, sysTCP_KEEPINTVL, int(config.TcpKeepAliveIdle)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPIDLE", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,6 +140,25 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
 | 
			
		|||
				return newError("failed to set TCP_FASTOPEN_CONNECT=", tfo).Base(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
			if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPIDLE", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if config.Tproxy.IsEnabled() {
 | 
			
		||||
| 
						 | 
				
			
			@ -170,6 +189,25 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
 | 
			
		|||
				return newError("failed to set TCP_FASTOPEN=", tfo).Base(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
			if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPIDLE", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if config.Tproxy.IsEnabled() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,9 +58,23 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if config.TcpKeepAliveInterval != 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
				return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
		if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
			if config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPIDLE", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -88,9 +102,23 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if config.TcpKeepAliveInterval != 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
				return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
		if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
			if config.TcpKeepAliveInterval > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPINTVL", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
 | 
			
		||||
					return newError("failed to set TCP_KEEPIDLE", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,15 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
 | 
			
		|||
		if err := setTFO(syscall.Handle(fd), config.ParseTFOValue()); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +44,15 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
 | 
			
		|||
		if err := setTFO(syscall.Handle(fd), config.ParseTFOValue()); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if config.TcpKeepAliveIdle > 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
 | 
			
		||||
				return newError("failed to set SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if config.TcpKeepAliveIdle < 0 {
 | 
			
		||||
			if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
 | 
			
		||||
				return newError("failed to unset SO_KEEPALIVE", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,10 +69,14 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
 | 
			
		|||
			Dest: destAddr,
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	goStdKeepAlive := time.Duration(0)
 | 
			
		||||
	if sockopt != nil && sockopt.TcpKeepAliveIdle != 0 {
 | 
			
		||||
		goStdKeepAlive = time.Duration(-1)
 | 
			
		||||
	}
 | 
			
		||||
	dialer := &net.Dialer{
 | 
			
		||||
		Timeout:   time.Second * 16,
 | 
			
		||||
		LocalAddr: resolveSrcAddr(dest.Network, src),
 | 
			
		||||
		KeepAlive: goStdKeepAlive,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if sockopt != nil || len(d.controllers) > 0 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/pires/go-proxyproto"
 | 
			
		||||
	"github.com/xtls/xray-core/common/net"
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,9 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
 | 
			
		|||
		network = addr.Network()
 | 
			
		||||
		address = addr.String()
 | 
			
		||||
		lc.Control = getControlFunc(ctx, sockopt, dl.controllers)
 | 
			
		||||
		if sockopt != nil && sockopt.TcpKeepAliveIdle != 0 {
 | 
			
		||||
			lc.KeepAlive = time.Duration(-1)
 | 
			
		||||
		}
 | 
			
		||||
	case *net.UnixAddr:
 | 
			
		||||
		lc.Control = nil
 | 
			
		||||
		network = addr.Network()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue