Skip to content

Commit ae81bf1

Browse files
LjhAUMEMExclude0122
authored andcommitted
mKCP transport: Add cwndMultiplier; Apply unaggressive strategy by default (XTLS#5890)
XTLS#4846 (comment) XTLS#5872 (comment) XTLS#5890 (comment)
1 parent 06ab137 commit ae81bf1

13 files changed

Lines changed: 150 additions & 690 deletions

File tree

infra/conf/transport_internet.go

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"syscall"
1515
"time"
1616

17+
"github.com/xtls/xray-core/common"
1718
"github.com/xtls/xray-core/common/errors"
1819
"github.com/xtls/xray-core/common/net"
1920
"github.com/xtls/xray-core/common/platform/filesystem"
@@ -54,62 +55,55 @@ var (
5455
)
5556

5657
type KCPConfig struct {
57-
Mtu *uint32 `json:"mtu"`
58-
Tti *uint32 `json:"tti"`
59-
UpCap *uint32 `json:"uplinkCapacity"`
60-
DownCap *uint32 `json:"downlinkCapacity"`
61-
Congestion *bool `json:"congestion"`
62-
ReadBufferSize *uint32 `json:"readBufferSize"`
63-
WriteBufferSize *uint32 `json:"writeBufferSize"`
64-
HeaderConfig json.RawMessage `json:"header"`
65-
Seed *string `json:"seed"`
58+
Mtu *uint32 `json:"mtu"`
59+
Tti *uint32 `json:"tti"`
60+
UpCap *uint32 `json:"uplinkCapacity"`
61+
DownCap *uint32 `json:"downlinkCapacity"`
62+
CwndMultiplier *uint32 `json:"cwndMultiplier"`
63+
MaxSendingWindow *uint32 `json:"maxSendingWindow"`
64+
65+
HeaderConfig json.RawMessage `json:"header"`
66+
Seed *string `json:"seed"`
6667
}
6768

6869
// Build implements Buildable.
6970
func (c *KCPConfig) Build() (proto.Message, error) {
70-
config := new(kcp.Config)
71+
if c.HeaderConfig != nil || c.Seed != nil {
72+
return nil, errors.PrintRemovedFeatureError("mkcp header & seed", "finalmask/udp header-* & mkcp-original & mkcp-aes128gcm")
73+
}
74+
75+
config := common.Must2(internet.CreateTransportConfig(kcp.ProtocolName)).(*kcp.Config)
7176

7277
if c.Mtu != nil {
73-
mtu := *c.Mtu
74-
// if mtu < 576 || mtu > 1460 {
75-
// return nil, errors.New("invalid mKCP MTU size: ", mtu).AtError()
76-
// }
77-
config.Mtu = &kcp.MTU{Value: mtu}
78+
config.Mtu = *c.Mtu
7879
}
7980
if c.Tti != nil {
80-
tti := *c.Tti
81-
if tti < 10 || tti > 5000 {
82-
return nil, errors.New("invalid mKCP TTI: ", tti).AtError()
83-
}
84-
config.Tti = &kcp.TTI{Value: tti}
81+
config.Tti = *c.Tti
8582
}
8683
if c.UpCap != nil {
87-
config.UplinkCapacity = &kcp.UplinkCapacity{Value: *c.UpCap}
84+
config.UplinkCapacity = *c.UpCap
8885
}
8986
if c.DownCap != nil {
90-
config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *c.DownCap}
87+
config.DownlinkCapacity = *c.DownCap
9188
}
92-
if c.Congestion != nil {
93-
config.Congestion = *c.Congestion
89+
if c.CwndMultiplier != nil {
90+
config.CwndMultiplier = *c.CwndMultiplier
9491
}
95-
if c.ReadBufferSize != nil {
96-
size := *c.ReadBufferSize
97-
if size > 0 {
98-
config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024}
99-
} else {
100-
config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024}
101-
}
92+
if c.MaxSendingWindow != nil {
93+
config.MaxSendingWindow = *c.MaxSendingWindow
10294
}
103-
if c.WriteBufferSize != nil {
104-
size := *c.WriteBufferSize
105-
if size > 0 {
106-
config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024}
107-
} else {
108-
config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024}
109-
}
95+
96+
if config.Mtu < 21 {
97+
return nil, errors.New("Mtu must be at least 21").AtError()
11098
}
111-
if c.HeaderConfig != nil || c.Seed != nil {
112-
return nil, errors.PrintRemovedFeatureError("mkcp header & seed", "finalmask/udp header-* & mkcp-original & mkcp-aes128gcm")
99+
if config.Tti < 10 || config.Tti > 1000 {
100+
return nil, errors.New("invalid mKCP TTI: ", c.Tti).AtError()
101+
}
102+
if config.CwndMultiplier < 1 {
103+
return nil, errors.New("CwndMultiplier must be at least 1").AtError()
104+
}
105+
if config.GetSendingBufferSize() == 0 {
106+
return nil, errors.New("MaxSendingWindow must be >= Mtu").AtError()
113107
}
114108

115109
return config, nil

testing/scenarios/vmess_test.go

Lines changed: 15 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"github.com/xtls/xray-core/testing/servers/tcp"
2323
"github.com/xtls/xray-core/testing/servers/udp"
2424
"github.com/xtls/xray-core/transport/internet"
25-
"github.com/xtls/xray-core/transport/internet/kcp"
2625
"golang.org/x/sync/errgroup"
2726
)
2827

@@ -94,9 +93,9 @@ func TestVMessGCM(t *testing.T) {
9493
Receiver: &protocol.ServerEndpoint{
9594
Address: net.NewIPOrDomain(net.LocalHostIP),
9695
Port: uint32(serverPort),
97-
User: &protocol.User{
96+
User: &protocol.User{
9897
Account: serial.ToTypedMessage(&vmess.Account{
99-
Id: userID.String(),
98+
Id: userID.String(),
10099
SecuritySettings: &protocol.SecurityConfig{
101100
Type: protocol.SecurityType_AES128_GCM,
102101
},
@@ -192,9 +191,9 @@ func TestVMessGCMReadv(t *testing.T) {
192191
Receiver: &protocol.ServerEndpoint{
193192
Address: net.NewIPOrDomain(net.LocalHostIP),
194193
Port: uint32(serverPort),
195-
User: &protocol.User{
194+
User: &protocol.User{
196195
Account: serial.ToTypedMessage(&vmess.Account{
197-
Id: userID.String(),
196+
Id: userID.String(),
198197
SecuritySettings: &protocol.SecurityConfig{
199198
Type: protocol.SecurityType_AES128_GCM,
200199
},
@@ -293,9 +292,9 @@ func TestVMessGCMUDP(t *testing.T) {
293292
Receiver: &protocol.ServerEndpoint{
294293
Address: net.NewIPOrDomain(net.LocalHostIP),
295294
Port: uint32(serverPort),
296-
User: &protocol.User{
295+
User: &protocol.User{
297296
Account: serial.ToTypedMessage(&vmess.Account{
298-
Id: userID.String(),
297+
Id: userID.String(),
299298
SecuritySettings: &protocol.SecurityConfig{
300299
Type: protocol.SecurityType_AES128_GCM,
301300
},
@@ -388,9 +387,9 @@ func TestVMessChacha20(t *testing.T) {
388387
Receiver: &protocol.ServerEndpoint{
389388
Address: net.NewIPOrDomain(net.LocalHostIP),
390389
Port: uint32(serverPort),
391-
User: &protocol.User{
390+
User: &protocol.User{
392391
Account: serial.ToTypedMessage(&vmess.Account{
393-
Id: userID.String(),
392+
Id: userID.String(),
394393
SecuritySettings: &protocol.SecurityConfig{
395394
Type: protocol.SecurityType_CHACHA20_POLY1305,
396395
},
@@ -484,7 +483,7 @@ func TestVMessNone(t *testing.T) {
484483
Receiver: &protocol.ServerEndpoint{
485484
Address: net.NewIPOrDomain(net.LocalHostIP),
486485
Port: uint32(serverPort),
487-
User: &protocol.User{
486+
User: &protocol.User{
488487
Account: serial.ToTypedMessage(&vmess.Account{
489488
Id: userID.String(),
490489
SecuritySettings: &protocol.SecurityConfig{
@@ -638,25 +637,6 @@ func TestVMessKCPLarge(t *testing.T) {
638637
Listen: net.NewIPOrDomain(net.LocalHostIP),
639638
StreamSettings: &internet.StreamConfig{
640639
ProtocolName: "mkcp",
641-
TransportSettings: []*internet.TransportConfig{
642-
{
643-
ProtocolName: "mkcp",
644-
Settings: serial.ToTypedMessage(&kcp.Config{
645-
ReadBuffer: &kcp.ReadBuffer{
646-
Size: 512 * 1024,
647-
},
648-
WriteBuffer: &kcp.WriteBuffer{
649-
Size: 512 * 1024,
650-
},
651-
UplinkCapacity: &kcp.UplinkCapacity{
652-
Value: 20,
653-
},
654-
DownlinkCapacity: &kcp.DownlinkCapacity{
655-
Value: 20,
656-
},
657-
}),
658-
},
659-
},
660640
},
661641
}),
662642
ProxySettings: serial.ToTypedMessage(&inbound.Config{
@@ -704,7 +684,7 @@ func TestVMessKCPLarge(t *testing.T) {
704684
Receiver: &protocol.ServerEndpoint{
705685
Address: net.NewIPOrDomain(net.LocalHostIP),
706686
Port: uint32(serverPort),
707-
User: &protocol.User{
687+
User: &protocol.User{
708688
Account: serial.ToTypedMessage(&vmess.Account{
709689
Id: userID.String(),
710690
SecuritySettings: &protocol.SecurityConfig{
@@ -717,25 +697,6 @@ func TestVMessKCPLarge(t *testing.T) {
717697
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
718698
StreamSettings: &internet.StreamConfig{
719699
ProtocolName: "mkcp",
720-
TransportSettings: []*internet.TransportConfig{
721-
{
722-
ProtocolName: "mkcp",
723-
Settings: serial.ToTypedMessage(&kcp.Config{
724-
ReadBuffer: &kcp.ReadBuffer{
725-
Size: 512 * 1024,
726-
},
727-
WriteBuffer: &kcp.WriteBuffer{
728-
Size: 512 * 1024,
729-
},
730-
UplinkCapacity: &kcp.UplinkCapacity{
731-
Value: 20,
732-
},
733-
DownlinkCapacity: &kcp.DownlinkCapacity{
734-
Value: 20,
735-
},
736-
}),
737-
},
738-
},
739700
},
740701
}),
741702
},
@@ -833,7 +794,7 @@ func TestVMessGCMMux(t *testing.T) {
833794
Receiver: &protocol.ServerEndpoint{
834795
Address: net.NewIPOrDomain(net.LocalHostIP),
835796
Port: uint32(serverPort),
836-
User: &protocol.User{
797+
User: &protocol.User{
837798
Account: serial.ToTypedMessage(&vmess.Account{
838799
Id: userID.String(),
839800
SecuritySettings: &protocol.SecurityConfig{
@@ -956,7 +917,7 @@ func TestVMessGCMMuxUDP(t *testing.T) {
956917
Receiver: &protocol.ServerEndpoint{
957918
Address: net.NewIPOrDomain(net.LocalHostIP),
958919
Port: uint32(serverPort),
959-
User: &protocol.User{
920+
User: &protocol.User{
960921
Account: serial.ToTypedMessage(&vmess.Account{
961922
Id: userID.String(),
962923
SecuritySettings: &protocol.SecurityConfig{
@@ -1059,7 +1020,7 @@ func TestVMessZero(t *testing.T) {
10591020
Receiver: &protocol.ServerEndpoint{
10601021
Address: net.NewIPOrDomain(net.LocalHostIP),
10611022
Port: uint32(serverPort),
1062-
User: &protocol.User{
1023+
User: &protocol.User{
10631024
Account: serial.ToTypedMessage(&vmess.Account{
10641025
Id: userID.String(),
10651026
SecuritySettings: &protocol.SecurityConfig{
@@ -1154,7 +1115,7 @@ func TestVMessGCMLengthAuth(t *testing.T) {
11541115
Receiver: &protocol.ServerEndpoint{
11551116
Address: net.NewIPOrDomain(net.LocalHostIP),
11561117
Port: uint32(serverPort),
1157-
User: &protocol.User{
1118+
User: &protocol.User{
11581119
Account: serial.ToTypedMessage(&vmess.Account{
11591120
Id: userID.String(),
11601121
SecuritySettings: &protocol.SecurityConfig{
@@ -1254,7 +1215,7 @@ func TestVMessGCMLengthAuthPlusNoTerminationSignal(t *testing.T) {
12541215
Receiver: &protocol.ServerEndpoint{
12551216
Address: net.NewIPOrDomain(net.LocalHostIP),
12561217
Port: uint32(serverPort),
1257-
User: &protocol.User{
1218+
User: &protocol.User{
12581219
Account: serial.ToTypedMessage(&vmess.Account{
12591220
Id: userID.String(),
12601221
SecuritySettings: &protocol.SecurityConfig{

transport/internet/hysteria/config.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ const protocolName = "hysteria"
4848

4949
func init() {
5050
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
51-
return new(Config)
51+
return &Config{
52+
UdpIdleTimeout: 60,
53+
}
5254
}))
5355
}

transport/internet/kcp/config.go

Lines changed: 12 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,35 @@ import (
55
"github.com/xtls/xray-core/transport/internet"
66
)
77

8-
// GetMTUValue returns the value of MTU settings.
9-
func (c *Config) GetMTUValue() uint32 {
10-
if c == nil || c.Mtu == nil {
11-
return 1350
12-
}
13-
return c.Mtu.Value
14-
}
15-
16-
// GetTTIValue returns the value of TTI settings.
17-
func (c *Config) GetTTIValue() uint32 {
18-
if c == nil || c.Tti == nil {
19-
return 50
20-
}
21-
return c.Tti.Value
22-
}
23-
24-
// GetUplinkCapacityValue returns the value of UplinkCapacity settings.
25-
func (c *Config) GetUplinkCapacityValue() uint32 {
26-
if c == nil || c.UplinkCapacity == nil {
27-
return 5
28-
}
29-
return c.UplinkCapacity.Value
30-
}
31-
32-
// GetDownlinkCapacityValue returns the value of DownlinkCapacity settings.
33-
func (c *Config) GetDownlinkCapacityValue() uint32 {
34-
if c == nil || c.DownlinkCapacity == nil {
35-
return 20
36-
}
37-
return c.DownlinkCapacity.Value
38-
}
39-
40-
// GetWriteBufferSize returns the size of WriterBuffer in bytes.
41-
func (c *Config) GetWriteBufferSize() uint32 {
42-
if c == nil || c.WriteBuffer == nil {
43-
return 2 * 1024 * 1024
44-
}
45-
return c.WriteBuffer.Size
46-
}
47-
48-
// GetReadBufferSize returns the size of ReadBuffer in bytes.
49-
// func (c *Config) GetReadBufferSize() uint32 {
50-
// if c == nil || c.ReadBuffer == nil {
51-
// return 2 * 1024 * 1024
52-
// }
53-
// return c.ReadBuffer.Size
54-
// }
55-
568
func (c *Config) GetSendingInFlightSize() uint32 {
57-
size := c.GetUplinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
9+
size := c.UplinkCapacity * 1024 * 1024 / c.Mtu / (1000 / c.Tti)
5810
if size < 8 {
5911
size = 8
6012
}
6113
return size
6214
}
6315

6416
func (c *Config) GetSendingBufferSize() uint32 {
65-
return c.GetWriteBufferSize() / c.GetMTUValue()
17+
return c.MaxSendingWindow / c.Mtu
6618
}
6719

6820
func (c *Config) GetReceivingInFlightSize() uint32 {
69-
size := c.GetDownlinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
21+
size := c.DownlinkCapacity * 1024 * 1024 / c.Mtu / (1000 / c.Tti)
7022
if size < 8 {
7123
size = 8
7224
}
7325
return size
7426
}
7527

76-
// func (c *Config) GetReceivingBufferSize() uint32 {
77-
// return c.GetReadBufferSize() / c.GetMTUValue()
78-
// }
79-
8028
func init() {
81-
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
82-
return new(Config)
29+
common.Must(internet.RegisterProtocolConfigCreator(ProtocolName, func() interface{} {
30+
return &Config{
31+
Mtu: 1350,
32+
Tti: 50,
33+
UplinkCapacity: 5,
34+
DownlinkCapacity: 20,
35+
CwndMultiplier: 1,
36+
MaxSendingWindow: 2 * 1024 * 1024,
37+
}
8338
}))
8439
}

0 commit comments

Comments
 (0)