mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-05-13 20:44:12 +08:00
Merge 4ca6302ad4032c5386bb73cc4e29327d915f9201 into 72170d8b6be0d83af1624f6d31b81cf73f1a189c
This commit is contained in:
commit
546c105692
@ -699,6 +699,30 @@ type CustomSockoptConfig struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type HappyEyeballsConfig struct {
|
||||
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
||||
TryDelayMs uint64 `json:"tryDelayMs"`
|
||||
Interleave uint32 `json:"interleave"`
|
||||
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
||||
}
|
||||
|
||||
func (h *HappyEyeballsConfig) UnmarshalJSON(data []byte) error {
|
||||
var innerHappyEyeballsConfig = struct {
|
||||
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
||||
TryDelayMs uint64 `json:"tryDelayMs"`
|
||||
Interleave uint32 `json:"interleave"`
|
||||
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
||||
}{PrioritizeIPv6: false, Interleave: 1, TryDelayMs: 250, MaxConcurrentTry: 4}
|
||||
if err := json.Unmarshal(data, &innerHappyEyeballsConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
h.PrioritizeIPv6 = innerHappyEyeballsConfig.PrioritizeIPv6
|
||||
h.TryDelayMs = innerHappyEyeballsConfig.TryDelayMs
|
||||
h.Interleave = innerHappyEyeballsConfig.Interleave
|
||||
h.MaxConcurrentTry = innerHappyEyeballsConfig.MaxConcurrentTry
|
||||
return nil
|
||||
}
|
||||
|
||||
type SocketConfig struct {
|
||||
Mark int32 `json:"mark"`
|
||||
TFO interface{} `json:"tcpFastOpen"`
|
||||
@ -718,6 +742,7 @@ type SocketConfig struct {
|
||||
TcpMptcp bool `json:"tcpMptcp"`
|
||||
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
||||
AddressPortStrategy string `json:"addressPortStrategy"`
|
||||
HappyEyeballsSettings *HappyEyeballsConfig `json:"happyEyeballs"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@ -809,6 +834,14 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
|
||||
}
|
||||
|
||||
var happyEyeballs = &internet.HappyEyeballsConfig{Interleave: 1, PrioritizeIpv6: false, TryDelayMs: 250, MaxConcurrentTry: 4}
|
||||
if c.HappyEyeballsSettings != nil {
|
||||
happyEyeballs.PrioritizeIpv6 = c.HappyEyeballsSettings.PrioritizeIPv6
|
||||
happyEyeballs.Interleave = c.HappyEyeballsSettings.Interleave
|
||||
happyEyeballs.TryDelayMs = c.HappyEyeballsSettings.TryDelayMs
|
||||
happyEyeballs.MaxConcurrentTry = c.HappyEyeballsSettings.MaxConcurrentTry
|
||||
}
|
||||
|
||||
return &internet.SocketConfig{
|
||||
Mark: c.Mark,
|
||||
Tfo: tfo,
|
||||
@ -828,6 +861,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
TcpMptcp: c.TcpMptcp,
|
||||
CustomSockopt: customSockopts,
|
||||
AddressPortStrategy: addressPortStrategy,
|
||||
HappyEyeballs: happyEyeballs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
Tfo: 256,
|
||||
DomainStrategy: internet.DomainStrategy_USE_IP,
|
||||
DialerProxy: "tag",
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
@ -47,6 +48,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
expectedOutput = &internet.SocketConfig{
|
||||
Mark: 0,
|
||||
Tfo: -1,
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
@ -65,6 +67,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
expectedOutput = &internet.SocketConfig{
|
||||
Mark: 0,
|
||||
Tfo: 65535,
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
@ -83,6 +86,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
expectedOutput = &internet.SocketConfig{
|
||||
Mark: 0,
|
||||
Tfo: -65535,
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
@ -101,6 +105,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
expectedOutput = &internet.SocketConfig{
|
||||
Mark: 0,
|
||||
Tfo: 0,
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
@ -119,6 +124,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
expectedOutput = &internet.SocketConfig{
|
||||
Mark: 0,
|
||||
Tfo: 0,
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
@ -135,6 +141,7 @@ func TestSocketConfig(t *testing.T) {
|
||||
expectedOutput = &internet.SocketConfig{
|
||||
Mark: 0,
|
||||
Tfo: 0,
|
||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 250, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
||||
}
|
||||
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"`
|
||||
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"`
|
||||
HappyEyeballs *HappyEyeballsConfig `protobuf:"bytes,22,opt,name=happy_eyeballs,json=happyEyeballs,proto3" json:"happy_eyeballs,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SocketConfig) Reset() {
|
||||
@ -708,6 +709,82 @@ func (x *SocketConfig) GetAddressPortStrategy() AddressPortStrategy {
|
||||
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
|
||||
|
||||
PrioritizeIpv6 bool `protobuf:"varint,1,opt,name=prioritize_ipv6,json=prioritizeIpv6,proto3" json:"prioritize_ipv6,omitempty"`
|
||||
Interleave uint32 `protobuf:"varint,2,opt,name=interleave,proto3" json:"interleave,omitempty"`
|
||||
TryDelayMs uint64 `protobuf:"varint,3,opt,name=try_delayMs,json=tryDelayMs,proto3" json:"try_delayMs,omitempty"`
|
||||
MaxConcurrentTry uint32 `protobuf:"varint,4,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) 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_rawDesc = []byte{
|
||||
@ -766,7 +843,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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
@ -827,37 +904,53 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
||||
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,
|
||||
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, 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, 0xa9, 0x01, 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, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10,
|
||||
0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08,
|
||||
0x12, 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,
|
||||
0x65, 0x67, 0x79, 0x12, 0x53, 0x0a, 0x0e, 0x68, 0x61, 0x70, 0x70, 0x79, 0x5f, 0x65, 0x79, 0x65,
|
||||
0x62, 0x61, 0x6c, 0x6c, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x61, 0x70, 0x70, 0x79, 0x45, 0x79, 0x65, 0x62, 0x61,
|
||||
0x6c, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x68, 0x61, 0x70, 0x70, 0x79,
|
||||
0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x73, 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, 0x22, 0xad, 0x01, 0x0a, 0x13, 0x48, 0x61,
|
||||
0x70, 0x70, 0x79, 0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x5f,
|
||||
0x69, 0x70, 0x76, 0x36, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x69, 0x6f,
|
||||
0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x49, 0x70, 0x76, 0x36, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72,
|
||||
0x79, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x0a, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6d,
|
||||
0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x72,
|
||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63,
|
||||
0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x79, 0x2a, 0xa9, 0x01, 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, 0x12, 0x0c, 0x0a,
|
||||
0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55,
|
||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52,
|
||||
0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45,
|
||||
0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 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 (
|
||||
@ -873,7 +966,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_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_transport_internet_config_proto_goTypes = []any{
|
||||
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
||||
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
||||
@ -883,24 +976,26 @@ var file_transport_internet_config_proto_goTypes = []any{
|
||||
(*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig
|
||||
(*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
|
||||
(*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
|
||||
(*serial.TypedMessage)(nil), // 8: xray.common.serial.TypedMessage
|
||||
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
|
||||
(*HappyEyeballsConfig)(nil), // 8: xray.transport.internet.HappyEyeballsConfig
|
||||
(*serial.TypedMessage)(nil), // 9: xray.common.serial.TypedMessage
|
||||
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
|
||||
}
|
||||
var file_transport_internet_config_proto_depIdxs = []int32{
|
||||
8, // 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
|
||||
9, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
9, // [9:9] is the sub-list for method output_type
|
||||
9, // [9:9] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
8, // 9: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig
|
||||
10, // [10:10] is the sub-list for method output_type
|
||||
10, // [10:10] is the sub-list for method input_type
|
||||
10, // [10:10] is the sub-list for extension 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() }
|
||||
@ -914,7 +1009,7 @@ func file_transport_internet_config_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_internet_config_proto_rawDesc,
|
||||
NumEnums: 3,
|
||||
NumMessages: 5,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
@ -130,4 +130,13 @@ message SocketConfig {
|
||||
repeated CustomSockopt customSockopt = 20;
|
||||
|
||||
AddressPortStrategy address_port_strategy = 21;
|
||||
|
||||
HappyEyeballsConfig happy_eyeballs = 22;
|
||||
}
|
||||
|
||||
message HappyEyeballsConfig {
|
||||
bool prioritize_ipv6 = 1;
|
||||
uint32 interleave = 2;
|
||||
uint64 try_delayMs = 3;
|
||||
uint32 max_concurrent_try = 4;
|
||||
}
|
||||
|
@ -255,9 +255,11 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
|
||||
if sockopt.DomainStrategy.forceIP() {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
} else if (sockopt.HappyEyeballs != nil && (sockopt.HappyEyeballs.TryDelayMs == 0 || sockopt.HappyEyeballs.MaxConcurrentTry == 0)) || len(ips) < 2 || len(sockopt.DialerProxy) > 0 || dest.Network != net.Network_TCP {
|
||||
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
||||
} else {
|
||||
return TcpRaceDial(ctx, src, ips, dest.Port, sockopt)
|
||||
}
|
||||
}
|
||||
|
||||
|
177
transport/internet/happy_eyeballs.go
Normal file
177
transport/internet/happy_eyeballs.go
Normal file
@ -0,0 +1,177 @@
|
||||
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")
|
||||
}
|
||||
|
||||
prioritizeIPv6 := false
|
||||
interleave := uint32(1)
|
||||
tryDelayMs := 250 * time.Millisecond
|
||||
maxConcurrentTry := uint32(4)
|
||||
if sockopt.HappyEyeballs != nil {
|
||||
prioritizeIPv6 = sockopt.HappyEyeballs.PrioritizeIpv6
|
||||
interleave = sockopt.HappyEyeballs.Interleave
|
||||
tryDelayMs = time.Duration(sockopt.HappyEyeballs.TryDelayMs) * time.Millisecond
|
||||
maxConcurrentTry = sockopt.HappyEyeballs.MaxConcurrentTry
|
||||
}
|
||||
|
||||
ips = sortIPs(ips, prioritizeIPv6, interleave)
|
||||
newCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
var resultCh = make(chan *result, len(ips))
|
||||
nextTryIndex := 0
|
||||
activeNum := uint32(0)
|
||||
timer := time.NewTimer(0)
|
||||
var winConn net.Conn
|
||||
for {
|
||||
select {
|
||||
case r := <-resultCh:
|
||||
activeNum--
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
cancel()
|
||||
timer.Stop()
|
||||
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()
|
||||
timer.Stop()
|
||||
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) {
|
||||
timer.Reset(0)
|
||||
continue
|
||||
}
|
||||
if activeNum == 0 {
|
||||
return nil, r.err
|
||||
}
|
||||
timer.Stop()
|
||||
continue
|
||||
}
|
||||
|
||||
case <-timer.C:
|
||||
if nextTryIndex == len(ips) || activeNum == maxConcurrentTry {
|
||||
panic("impossible situation")
|
||||
}
|
||||
go tcpTryDial(newCtx, src, sockopt, ips[nextTryIndex], port, nextTryIndex, resultCh)
|
||||
activeNum++
|
||||
nextTryIndex++
|
||||
if nextTryIndex == len(ips) || activeNum == maxConcurrentTry {
|
||||
timer.Stop()
|
||||
} else {
|
||||
timer.Reset(tryDelayMs)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sortIPs sort IPs according to rfc 8305.
|
||||
func sortIPs(ips []net.IP, prioritizeIPv6 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 prioritizeIPv6 {
|
||||
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