mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-05-14 05:04:12 +08:00
New feature: Happy Eyeballs (RFC 8305)
This commit is contained in:
parent
aa4134f4a6
commit
4be238a5f3
@ -699,6 +699,14 @@ type CustomSockoptConfig struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HappyEyeballsConfig struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
||||||
|
TryDelayMs uint64 `json:"tryDelayMs"`
|
||||||
|
Interleave uint32 `json:"interleave"`
|
||||||
|
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
||||||
|
}
|
||||||
|
|
||||||
type SocketConfig struct {
|
type SocketConfig struct {
|
||||||
Mark int32 `json:"mark"`
|
Mark int32 `json:"mark"`
|
||||||
TFO interface{} `json:"tcpFastOpen"`
|
TFO interface{} `json:"tcpFastOpen"`
|
||||||
@ -718,6 +726,7 @@ type SocketConfig struct {
|
|||||||
TcpMptcp bool `json:"tcpMptcp"`
|
TcpMptcp bool `json:"tcpMptcp"`
|
||||||
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
||||||
AddressPortStrategy string `json:"addressPortStrategy"`
|
AddressPortStrategy string `json:"addressPortStrategy"`
|
||||||
|
HappyEyeballsSettings *HappyEyeballsConfig `json:"happyEyeballs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
@ -809,6 +818,21 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
|
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var happyEyeballs = &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, PrioritizeIpv6: false, TryDelayMs: 250, MaxConcurrentTry: 4}
|
||||||
|
if c.HappyEyeballsSettings != nil {
|
||||||
|
happyEyeballs.Enabled = c.HappyEyeballsSettings.Enabled
|
||||||
|
happyEyeballs.PrioritizeIpv6 = c.HappyEyeballsSettings.PrioritizeIPv6
|
||||||
|
if c.HappyEyeballsSettings.Interleave > 0 {
|
||||||
|
happyEyeballs.Interleave = c.HappyEyeballsSettings.Interleave
|
||||||
|
}
|
||||||
|
if c.HappyEyeballsSettings.TryDelayMs > 0 {
|
||||||
|
happyEyeballs.TryDelayMs = c.HappyEyeballsSettings.TryDelayMs
|
||||||
|
}
|
||||||
|
if c.HappyEyeballsSettings.MaxConcurrentTry > 0 {
|
||||||
|
happyEyeballs.MaxConcurrentTry = c.HappyEyeballsSettings.MaxConcurrentTry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &internet.SocketConfig{
|
return &internet.SocketConfig{
|
||||||
Mark: c.Mark,
|
Mark: c.Mark,
|
||||||
Tfo: tfo,
|
Tfo: tfo,
|
||||||
@ -828,6 +852,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
TcpMptcp: c.TcpMptcp,
|
TcpMptcp: c.TcpMptcp,
|
||||||
CustomSockopt: customSockopts,
|
CustomSockopt: customSockopts,
|
||||||
AddressPortStrategy: addressPortStrategy,
|
AddressPortStrategy: addressPortStrategy,
|
||||||
|
HappyEyeballs: happyEyeballs,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
Tfo: 256,
|
Tfo: 256,
|
||||||
DomainStrategy: internet.DomainStrategy_USE_IP,
|
DomainStrategy: internet.DomainStrategy_USE_IP,
|
||||||
DialerProxy: "tag",
|
DialerProxy: "tag",
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -47,6 +48,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: -1,
|
Tfo: -1,
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -65,6 +67,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 65535,
|
Tfo: 65535,
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -83,6 +86,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: -65535,
|
Tfo: -65535,
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -101,6 +105,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 0,
|
Tfo: 0,
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -119,6 +124,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 0,
|
Tfo: 0,
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -135,6 +141,7 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 0,
|
Tfo: 0,
|
||||||
|
HappyEyeballs: &internet.HappyEyeballsConfig{Enabled: false, Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
|
@ -529,6 +529,7 @@ type SocketConfig struct {
|
|||||||
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
|
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
|
||||||
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
|
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
|
||||||
AddressPortStrategy AddressPortStrategy `protobuf:"varint,21,opt,name=address_port_strategy,json=addressPortStrategy,proto3,enum=xray.transport.internet.AddressPortStrategy" json:"address_port_strategy,omitempty"`
|
AddressPortStrategy AddressPortStrategy `protobuf:"varint,21,opt,name=address_port_strategy,json=addressPortStrategy,proto3,enum=xray.transport.internet.AddressPortStrategy" json:"address_port_strategy,omitempty"`
|
||||||
|
HappyEyeballs *HappyEyeballsConfig `protobuf:"bytes,22,opt,name=happy_eyeballs,json=happyEyeballs,proto3" json:"happy_eyeballs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SocketConfig) Reset() {
|
func (x *SocketConfig) Reset() {
|
||||||
@ -708,6 +709,90 @@ func (x *SocketConfig) GetAddressPortStrategy() AddressPortStrategy {
|
|||||||
return AddressPortStrategy_None
|
return AddressPortStrategy_None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SocketConfig) GetHappyEyeballs() *HappyEyeballsConfig {
|
||||||
|
if x != nil {
|
||||||
|
return x.HappyEyeballs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type HappyEyeballsConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
|
PrioritizeIpv6 bool `protobuf:"varint,2,opt,name=prioritize_ipv6,json=prioritizeIpv6,proto3" json:"prioritize_ipv6,omitempty"`
|
||||||
|
Interleave uint32 `protobuf:"varint,3,opt,name=interleave,proto3" json:"interleave,omitempty"`
|
||||||
|
TryDelayMs uint64 `protobuf:"varint,4,opt,name=try_delayMs,json=tryDelayMs,proto3" json:"try_delayMs,omitempty"`
|
||||||
|
MaxConcurrentTry uint32 `protobuf:"varint,5,opt,name=max_concurrent_try,json=maxConcurrentTry,proto3" json:"max_concurrent_try,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) Reset() {
|
||||||
|
*x = HappyEyeballsConfig{}
|
||||||
|
mi := &file_transport_internet_config_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HappyEyeballsConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_config_proto_msgTypes[5]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use HappyEyeballsConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HappyEyeballsConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_config_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) GetEnabled() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Enabled
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) GetPrioritizeIpv6() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.PrioritizeIpv6
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) GetInterleave() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Interleave
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) GetTryDelayMs() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.TryDelayMs
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HappyEyeballsConfig) GetMaxConcurrentTry() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxConcurrentTry
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_config_proto_rawDesc = []byte{
|
var file_transport_internet_config_proto_rawDesc = []byte{
|
||||||
@ -766,7 +851,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||||
0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x22, 0xfd, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43,
|
0x74, 0x79, 0x70, 0x65, 0x22, 0xd2, 0x08, 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,
|
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,
|
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,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74,
|
||||||
@ -827,37 +912,55 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65,
|
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x13,
|
0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x13,
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x65, 0x67, 0x79, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64,
|
0x65, 0x67, 0x79, 0x12, 0x53, 0x0a, 0x0e, 0x68, 0x61, 0x70, 0x70, 0x79, 0x5f, 0x65, 0x79, 0x65,
|
||||||
0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50,
|
0x62, 0x61, 0x6c, 0x6c, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65,
|
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
|
||||||
0x63, 0x74, 0x10, 0x02, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x61, 0x70, 0x70, 0x79, 0x45, 0x79, 0x65, 0x62, 0x61,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53,
|
0x6c, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x68, 0x61, 0x70, 0x70, 0x79,
|
||||||
0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b,
|
0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f,
|
||||||
0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55,
|
0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12,
|
||||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52,
|
||||||
0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x22, 0xc7, 0x01, 0x0a, 0x13, 0x48, 0x61,
|
||||||
0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
0x70, 0x70, 0x79, 0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10,
|
0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08,
|
0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x70,
|
||||||
0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09,
|
0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x02,
|
||||||
0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65,
|
||||||
0x2a, 0x97, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74,
|
0x49, 0x70, 0x76, 0x36, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65,
|
0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c,
|
||||||
0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c,
|
0x65, 0x61, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x61,
|
||||||
0x79, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x72, 0x76, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
0x79, 0x4d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, 0x72, 0x79, 0x44, 0x65,
|
||||||
0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x72, 0x76, 0x50, 0x6f,
|
0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e,
|
||||||
0x72, 0x74, 0x41, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x03, 0x12, 0x0f,
|
0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x0a, 0x0b, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x04, 0x12,
|
0x0d, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
|
||||||
0x12, 0x0a, 0x0e, 0x54, 0x78, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, 0x6c,
|
0x54, 0x72, 0x79, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
||||||
0x79, 0x10, 0x05, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x6e,
|
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10,
|
||||||
0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x06, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f,
|
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a,
|
||||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53,
|
||||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74,
|
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
||||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
||||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10,
|
||||||
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79,
|
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07,
|
||||||
0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72,
|
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12,
|
||||||
0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12,
|
||||||
|
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x2a,
|
||||||
|
0x97, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53,
|
||||||
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10,
|
||||||
|
0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79,
|
||||||
|
0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x72, 0x76, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||||
|
0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72,
|
||||||
|
0x74, 0x41, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x03, 0x12, 0x0f, 0x0a,
|
||||||
|
0x0b, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x04, 0x12, 0x12,
|
||||||
|
0x0a, 0x0e, 0x54, 0x78, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, 0x6c, 0x79,
|
||||||
|
0x10, 0x05, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x6e, 0x64,
|
||||||
|
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x06, 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 (
|
var (
|
||||||
@ -873,7 +976,7 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
||||||
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||||
var file_transport_internet_config_proto_goTypes = []any{
|
var file_transport_internet_config_proto_goTypes = []any{
|
||||||
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
||||||
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
||||||
@ -883,24 +986,26 @@ var file_transport_internet_config_proto_goTypes = []any{
|
|||||||
(*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig
|
(*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig
|
||||||
(*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
|
(*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
|
||||||
(*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
|
(*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
|
||||||
(*serial.TypedMessage)(nil), // 8: xray.common.serial.TypedMessage
|
(*HappyEyeballsConfig)(nil), // 8: xray.transport.internet.HappyEyeballsConfig
|
||||||
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
|
(*serial.TypedMessage)(nil), // 9: xray.common.serial.TypedMessage
|
||||||
|
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
|
||||||
}
|
}
|
||||||
var file_transport_internet_config_proto_depIdxs = []int32{
|
var file_transport_internet_config_proto_depIdxs = []int32{
|
||||||
8, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
9, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||||
9, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
10, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||||
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
||||||
8, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
9, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
7, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
7, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
||||||
2, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
2, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
||||||
0, // 6: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
0, // 6: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
6, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
6, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
||||||
1, // 8: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
1, // 8: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
||||||
9, // [9:9] is the sub-list for method output_type
|
8, // 9: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig
|
||||||
9, // [9:9] is the sub-list for method input_type
|
10, // [10:10] is the sub-list for method output_type
|
||||||
9, // [9:9] is the sub-list for extension type_name
|
10, // [10:10] is the sub-list for method input_type
|
||||||
9, // [9:9] is the sub-list for extension extendee
|
10, // [10:10] is the sub-list for extension type_name
|
||||||
0, // [0:9] is the sub-list for field type_name
|
10, // [10:10] is the sub-list for extension extendee
|
||||||
|
0, // [0:10] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_transport_internet_config_proto_init() }
|
func init() { file_transport_internet_config_proto_init() }
|
||||||
@ -914,7 +1019,7 @@ func file_transport_internet_config_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_transport_internet_config_proto_rawDesc,
|
RawDescriptor: file_transport_internet_config_proto_rawDesc,
|
||||||
NumEnums: 3,
|
NumEnums: 3,
|
||||||
NumMessages: 5,
|
NumMessages: 6,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@ -130,4 +130,14 @@ message SocketConfig {
|
|||||||
repeated CustomSockopt customSockopt = 20;
|
repeated CustomSockopt customSockopt = 20;
|
||||||
|
|
||||||
AddressPortStrategy address_port_strategy = 21;
|
AddressPortStrategy address_port_strategy = 21;
|
||||||
|
|
||||||
|
HappyEyeballsConfig happy_eyeballs = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HappyEyeballsConfig {
|
||||||
|
bool enabled = 1;
|
||||||
|
bool prioritize_ipv6 = 2;
|
||||||
|
uint32 interleave = 3;
|
||||||
|
uint64 try_delayMs = 4;
|
||||||
|
uint32 max_concurrent_try = 5;
|
||||||
}
|
}
|
||||||
|
@ -255,9 +255,11 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
|
|||||||
if sockopt.DomainStrategy.forceIP() {
|
if sockopt.DomainStrategy.forceIP() {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else if !sockopt.HappyEyeballs.Enabled || len(ips) < 2 || len(sockopt.DialerProxy) > 0 || dest.Network != net.Network_TCP {
|
||||||
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
||||||
|
} else {
|
||||||
|
return TcpRaceDial(ctx, src, ips, dest.Port, sockopt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
165
transport/internet/happy_eyeballs.go
Normal file
165
transport/internet/happy_eyeballs.go
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
package internet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type result struct {
|
||||||
|
err error
|
||||||
|
conn net.Conn
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func TcpRaceDial(ctx context.Context, src net.Address, ips []net.IP, port net.Port, sockopt *SocketConfig) (net.Conn, error) {
|
||||||
|
if len(ips) < 2 {
|
||||||
|
panic("at least 2 ips is required to race dial")
|
||||||
|
}
|
||||||
|
ips = sortIPs(ips, sockopt.HappyEyeballs.PrioritizeIpv6, sockopt.HappyEyeballs.Interleave)
|
||||||
|
newCtx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
var resultCh = make(chan *result, len(ips))
|
||||||
|
nextTryIndex := 0
|
||||||
|
activeNum := uint32(0)
|
||||||
|
waitTime := time.Duration(0)
|
||||||
|
var winConn net.Conn
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case r := <-resultCh:
|
||||||
|
activeNum--
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
cancel()
|
||||||
|
waitTime = 100 * time.Hour
|
||||||
|
if winConn != nil {
|
||||||
|
winConn.Close()
|
||||||
|
}
|
||||||
|
if r.conn != nil {
|
||||||
|
r.conn.Close()
|
||||||
|
}
|
||||||
|
if activeNum == 0 {
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
if r.conn != nil {
|
||||||
|
cancel()
|
||||||
|
waitTime = 100 * time.Hour
|
||||||
|
if winConn == nil {
|
||||||
|
winConn = r.conn
|
||||||
|
} else {
|
||||||
|
r.conn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if winConn != nil && activeNum == 0 {
|
||||||
|
return winConn, nil
|
||||||
|
}
|
||||||
|
if winConn != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if nextTryIndex < len(ips) {
|
||||||
|
waitTime = time.Duration(0)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if activeNum == 0 {
|
||||||
|
return nil, r.err
|
||||||
|
}
|
||||||
|
waitTime = 100 * time.Hour
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-time.After(waitTime):
|
||||||
|
if nextTryIndex == len(ips) || activeNum == sockopt.HappyEyeballs.MaxConcurrentTry {
|
||||||
|
panic("impossible situation")
|
||||||
|
}
|
||||||
|
go tcpTryDial(newCtx, src, sockopt, ips[nextTryIndex], port, nextTryIndex, resultCh)
|
||||||
|
activeNum++
|
||||||
|
nextTryIndex++
|
||||||
|
if nextTryIndex == len(ips) || activeNum == sockopt.HappyEyeballs.MaxConcurrentTry {
|
||||||
|
waitTime = 100 * time.Hour
|
||||||
|
} else {
|
||||||
|
waitTime = time.Duration(sockopt.HappyEyeballs.TryDelayMs) * time.Millisecond
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sortIPs sort IPs according to rfc 8305.
|
||||||
|
func sortIPs(ips []net.IP, priorIPv6 bool, interleave uint32) []net.IP {
|
||||||
|
if len(ips) == 0 {
|
||||||
|
return ips
|
||||||
|
}
|
||||||
|
var ip4 = make([]net.IP, 0, len(ips))
|
||||||
|
var ip6 = make([]net.IP, 0, len(ips))
|
||||||
|
for _, ip := range ips {
|
||||||
|
parsedIp := net.IPAddress(ip).IP()
|
||||||
|
if len(parsedIp) == net.IPv4len {
|
||||||
|
ip4 = append(ip4, parsedIp)
|
||||||
|
} else {
|
||||||
|
ip6 = append(ip6, parsedIp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ip4) == 0 || len(ip6) == 0 {
|
||||||
|
return ips
|
||||||
|
}
|
||||||
|
|
||||||
|
var newIPs = make([]net.IP, 0, len(ips))
|
||||||
|
consumeIP4 := 0
|
||||||
|
consumeIP6 := 0
|
||||||
|
consumeTurn := uint32(0)
|
||||||
|
ip4turn := true
|
||||||
|
if priorIPv6 {
|
||||||
|
ip4turn = false
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
if ip4turn {
|
||||||
|
newIPs = append(newIPs, ip4[consumeIP4])
|
||||||
|
consumeIP4++
|
||||||
|
if consumeIP4 == len(ip4) {
|
||||||
|
newIPs = append(newIPs, ip6[consumeIP6:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
consumeTurn++
|
||||||
|
if consumeTurn == interleave {
|
||||||
|
ip4turn = false
|
||||||
|
consumeTurn = uint32(0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newIPs = append(newIPs, ip6[consumeIP6])
|
||||||
|
consumeIP6++
|
||||||
|
if consumeIP6 == len(ip6) {
|
||||||
|
newIPs = append(newIPs, ip4[consumeIP4:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
consumeTurn++
|
||||||
|
if consumeTurn == interleave {
|
||||||
|
ip4turn = true
|
||||||
|
consumeTurn = uint32(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newIPs
|
||||||
|
}
|
||||||
|
|
||||||
|
func tcpTryDial(ctx context.Context, src net.Address, sockopt *SocketConfig, ip net.IP, port net.Port, index int, resultCh chan<- *result) {
|
||||||
|
conn, err := effectiveSystemDialer.Dial(ctx, src, net.Destination{Address: net.IPAddress(ip), Network: net.Network_TCP, Port: port}, sockopt)
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
if conn != nil {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
resultCh <- &result{err: ctx.Err(), index: index}
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
if err != nil {
|
||||||
|
resultCh <- &result{err: err, index: index}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resultCh <- &result{conn: conn, index: index}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user