mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
mKCP transport: Add cwndMultiplier; Apply unaggressive strategy by default (#5890)
https://github.com/XTLS/Xray-core/issues/4846#issuecomment-4150329444 https://github.com/XTLS/Xray-core/pull/5872#issuecomment-4184774915 https://github.com/XTLS/Xray-core/pull/5890#issuecomment-4240052251
This commit is contained in:
@@ -48,6 +48,8 @@ const protocolName = "hysteria"
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
||||
return new(Config)
|
||||
return &Config{
|
||||
UdpIdleTimeout: 60,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -5,56 +5,8 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
// GetMTUValue returns the value of MTU settings.
|
||||
func (c *Config) GetMTUValue() uint32 {
|
||||
if c == nil || c.Mtu == nil {
|
||||
return 1350
|
||||
}
|
||||
return c.Mtu.Value
|
||||
}
|
||||
|
||||
// GetTTIValue returns the value of TTI settings.
|
||||
func (c *Config) GetTTIValue() uint32 {
|
||||
if c == nil || c.Tti == nil {
|
||||
return 50
|
||||
}
|
||||
return c.Tti.Value
|
||||
}
|
||||
|
||||
// GetUplinkCapacityValue returns the value of UplinkCapacity settings.
|
||||
func (c *Config) GetUplinkCapacityValue() uint32 {
|
||||
if c == nil || c.UplinkCapacity == nil {
|
||||
return 5
|
||||
}
|
||||
return c.UplinkCapacity.Value
|
||||
}
|
||||
|
||||
// GetDownlinkCapacityValue returns the value of DownlinkCapacity settings.
|
||||
func (c *Config) GetDownlinkCapacityValue() uint32 {
|
||||
if c == nil || c.DownlinkCapacity == nil {
|
||||
return 20
|
||||
}
|
||||
return c.DownlinkCapacity.Value
|
||||
}
|
||||
|
||||
// GetWriteBufferSize returns the size of WriterBuffer in bytes.
|
||||
func (c *Config) GetWriteBufferSize() uint32 {
|
||||
if c == nil || c.WriteBuffer == nil {
|
||||
return 2 * 1024 * 1024
|
||||
}
|
||||
return c.WriteBuffer.Size
|
||||
}
|
||||
|
||||
// GetReadBufferSize returns the size of ReadBuffer in bytes.
|
||||
// func (c *Config) GetReadBufferSize() uint32 {
|
||||
// if c == nil || c.ReadBuffer == nil {
|
||||
// return 2 * 1024 * 1024
|
||||
// }
|
||||
// return c.ReadBuffer.Size
|
||||
// }
|
||||
|
||||
func (c *Config) GetSendingInFlightSize() uint32 {
|
||||
size := c.GetUplinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
|
||||
size := c.UplinkCapacity * 1024 * 1024 / c.Mtu / (1000 / c.Tti)
|
||||
if size < 8 {
|
||||
size = 8
|
||||
}
|
||||
@@ -62,23 +14,26 @@ func (c *Config) GetSendingInFlightSize() uint32 {
|
||||
}
|
||||
|
||||
func (c *Config) GetSendingBufferSize() uint32 {
|
||||
return c.GetWriteBufferSize() / c.GetMTUValue()
|
||||
return c.MaxSendingWindow / c.Mtu
|
||||
}
|
||||
|
||||
func (c *Config) GetReceivingInFlightSize() uint32 {
|
||||
size := c.GetDownlinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
|
||||
size := c.DownlinkCapacity * 1024 * 1024 / c.Mtu / (1000 / c.Tti)
|
||||
if size < 8 {
|
||||
size = 8
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// func (c *Config) GetReceivingBufferSize() uint32 {
|
||||
// return c.GetReadBufferSize() / c.GetMTUValue()
|
||||
// }
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
||||
return new(Config)
|
||||
common.Must(internet.RegisterProtocolConfigCreator(ProtocolName, func() interface{} {
|
||||
return &Config{
|
||||
Mtu: 1350,
|
||||
Tti: 50,
|
||||
UplinkCapacity: 5,
|
||||
DownlinkCapacity: 20,
|
||||
CwndMultiplier: 1,
|
||||
MaxSendingWindow: 2 * 1024 * 1024,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package kcp
|
||||
|
||||
import (
|
||||
serial "github.com/xtls/xray-core/common/serial"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@@ -22,385 +21,21 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// Maximum Transmission Unit, in bytes.
|
||||
type MTU struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *MTU) Reset() {
|
||||
*x = MTU{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *MTU) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MTU) ProtoMessage() {}
|
||||
|
||||
func (x *MTU) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[0]
|
||||
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 MTU.ProtoReflect.Descriptor instead.
|
||||
func (*MTU) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *MTU) GetValue() uint32 {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Transmission Time Interview, in milli-sec.
|
||||
type TTI struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *TTI) Reset() {
|
||||
*x = TTI{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *TTI) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*TTI) ProtoMessage() {}
|
||||
|
||||
func (x *TTI) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[1]
|
||||
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 TTI.ProtoReflect.Descriptor instead.
|
||||
func (*TTI) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *TTI) GetValue() uint32 {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uplink capacity, in MB.
|
||||
type UplinkCapacity struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *UplinkCapacity) Reset() {
|
||||
*x = UplinkCapacity{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UplinkCapacity) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UplinkCapacity) ProtoMessage() {}
|
||||
|
||||
func (x *UplinkCapacity) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[2]
|
||||
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 UplinkCapacity.ProtoReflect.Descriptor instead.
|
||||
func (*UplinkCapacity) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *UplinkCapacity) GetValue() uint32 {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Downlink capacity, in MB.
|
||||
type DownlinkCapacity struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DownlinkCapacity) Reset() {
|
||||
*x = DownlinkCapacity{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DownlinkCapacity) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DownlinkCapacity) ProtoMessage() {}
|
||||
|
||||
func (x *DownlinkCapacity) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[3]
|
||||
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 DownlinkCapacity.ProtoReflect.Descriptor instead.
|
||||
func (*DownlinkCapacity) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *DownlinkCapacity) GetValue() uint32 {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type WriteBuffer struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Buffer size in bytes.
|
||||
Size uint32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *WriteBuffer) Reset() {
|
||||
*x = WriteBuffer{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *WriteBuffer) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WriteBuffer) ProtoMessage() {}
|
||||
|
||||
func (x *WriteBuffer) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[4]
|
||||
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 WriteBuffer.ProtoReflect.Descriptor instead.
|
||||
func (*WriteBuffer) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *WriteBuffer) GetSize() uint32 {
|
||||
if x != nil {
|
||||
return x.Size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ReadBuffer struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Buffer size in bytes.
|
||||
Size uint32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ReadBuffer) Reset() {
|
||||
*x = ReadBuffer{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ReadBuffer) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ReadBuffer) ProtoMessage() {}
|
||||
|
||||
func (x *ReadBuffer) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_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 ReadBuffer.ProtoReflect.Descriptor instead.
|
||||
func (*ReadBuffer) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *ReadBuffer) GetSize() uint32 {
|
||||
if x != nil {
|
||||
return x.Size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ConnectionReuse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ConnectionReuse) Reset() {
|
||||
*x = ConnectionReuse{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ConnectionReuse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConnectionReuse) ProtoMessage() {}
|
||||
|
||||
func (x *ConnectionReuse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[6]
|
||||
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 ConnectionReuse.ProtoReflect.Descriptor instead.
|
||||
func (*ConnectionReuse) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *ConnectionReuse) GetEnable() bool {
|
||||
if x != nil {
|
||||
return x.Enable
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Pre-shared secret between client and server. It is used for traffic obfuscation.
|
||||
// Note that if seed is absent in the config, the traffic will still be obfuscated,
|
||||
// but by a predefined algorithm.
|
||||
type EncryptionSeed struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Seed string `protobuf:"bytes,1,opt,name=seed,proto3" json:"seed,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *EncryptionSeed) Reset() {
|
||||
*x = EncryptionSeed{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *EncryptionSeed) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*EncryptionSeed) ProtoMessage() {}
|
||||
|
||||
func (x *EncryptionSeed) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[7]
|
||||
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 EncryptionSeed.ProtoReflect.Descriptor instead.
|
||||
func (*EncryptionSeed) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *EncryptionSeed) GetSeed() string {
|
||||
if x != nil {
|
||||
return x.Seed
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Mtu *MTU `protobuf:"bytes,1,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
||||
Tti *TTI `protobuf:"bytes,2,opt,name=tti,proto3" json:"tti,omitempty"`
|
||||
UplinkCapacity *UplinkCapacity `protobuf:"bytes,3,opt,name=uplink_capacity,json=uplinkCapacity,proto3" json:"uplink_capacity,omitempty"`
|
||||
DownlinkCapacity *DownlinkCapacity `protobuf:"bytes,4,opt,name=downlink_capacity,json=downlinkCapacity,proto3" json:"downlink_capacity,omitempty"`
|
||||
Congestion bool `protobuf:"varint,5,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||
WriteBuffer *WriteBuffer `protobuf:"bytes,6,opt,name=write_buffer,json=writeBuffer,proto3" json:"write_buffer,omitempty"`
|
||||
ReadBuffer *ReadBuffer `protobuf:"bytes,7,opt,name=read_buffer,json=readBuffer,proto3" json:"read_buffer,omitempty"`
|
||||
HeaderConfig *serial.TypedMessage `protobuf:"bytes,8,opt,name=header_config,json=headerConfig,proto3" json:"header_config,omitempty"`
|
||||
Seed *EncryptionSeed `protobuf:"bytes,10,opt,name=seed,proto3" json:"seed,omitempty"`
|
||||
Mtu uint32 `protobuf:"varint,1,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
||||
Tti uint32 `protobuf:"varint,2,opt,name=tti,proto3" json:"tti,omitempty"`
|
||||
UplinkCapacity uint32 `protobuf:"varint,3,opt,name=uplink_capacity,json=uplinkCapacity,proto3" json:"uplink_capacity,omitempty"`
|
||||
DownlinkCapacity uint32 `protobuf:"varint,4,opt,name=downlink_capacity,json=downlinkCapacity,proto3" json:"downlink_capacity,omitempty"`
|
||||
CwndMultiplier uint32 `protobuf:"varint,5,opt,name=cwnd_multiplier,json=cwndMultiplier,proto3" json:"cwnd_multiplier,omitempty"`
|
||||
MaxSendingWindow uint32 `protobuf:"varint,6,opt,name=max_sending_window,json=maxSendingWindow,proto3" json:"max_sending_window,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*x = Config{}
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[8]
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -412,7 +47,7 @@ func (x *Config) String() string {
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[8]
|
||||
mi := &file_transport_internet_kcp_config_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -425,109 +60,63 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{8}
|
||||
return file_transport_internet_kcp_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Config) GetMtu() *MTU {
|
||||
func (x *Config) GetMtu() uint32 {
|
||||
if x != nil {
|
||||
return x.Mtu
|
||||
}
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetTti() *TTI {
|
||||
func (x *Config) GetTti() uint32 {
|
||||
if x != nil {
|
||||
return x.Tti
|
||||
}
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetUplinkCapacity() *UplinkCapacity {
|
||||
func (x *Config) GetUplinkCapacity() uint32 {
|
||||
if x != nil {
|
||||
return x.UplinkCapacity
|
||||
}
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetDownlinkCapacity() *DownlinkCapacity {
|
||||
func (x *Config) GetDownlinkCapacity() uint32 {
|
||||
if x != nil {
|
||||
return x.DownlinkCapacity
|
||||
}
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetCongestion() bool {
|
||||
func (x *Config) GetCwndMultiplier() uint32 {
|
||||
if x != nil {
|
||||
return x.Congestion
|
||||
return x.CwndMultiplier
|
||||
}
|
||||
return false
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetWriteBuffer() *WriteBuffer {
|
||||
func (x *Config) GetMaxSendingWindow() uint32 {
|
||||
if x != nil {
|
||||
return x.WriteBuffer
|
||||
return x.MaxSendingWindow
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetReadBuffer() *ReadBuffer {
|
||||
if x != nil {
|
||||
return x.ReadBuffer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetHeaderConfig() *serial.TypedMessage {
|
||||
if x != nil {
|
||||
return x.HeaderConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetSeed() *EncryptionSeed {
|
||||
if x != nil {
|
||||
return x.Seed
|
||||
}
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_transport_internet_kcp_config_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_transport_internet_kcp_config_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"#transport/internet/kcp/config.proto\x12\x1bxray.transport.internet.kcp\x1a!common/serial/typed_message.proto\"\x1b\n" +
|
||||
"\x03MTU\x12\x14\n" +
|
||||
"\x05value\x18\x01 \x01(\rR\x05value\"\x1b\n" +
|
||||
"\x03TTI\x12\x14\n" +
|
||||
"\x05value\x18\x01 \x01(\rR\x05value\"&\n" +
|
||||
"\x0eUplinkCapacity\x12\x14\n" +
|
||||
"\x05value\x18\x01 \x01(\rR\x05value\"(\n" +
|
||||
"\x10DownlinkCapacity\x12\x14\n" +
|
||||
"\x05value\x18\x01 \x01(\rR\x05value\"!\n" +
|
||||
"\vWriteBuffer\x12\x12\n" +
|
||||
"\x04size\x18\x01 \x01(\rR\x04size\" \n" +
|
||||
"\n" +
|
||||
"ReadBuffer\x12\x12\n" +
|
||||
"\x04size\x18\x01 \x01(\rR\x04size\")\n" +
|
||||
"\x0fConnectionReuse\x12\x16\n" +
|
||||
"\x06enable\x18\x01 \x01(\bR\x06enable\"$\n" +
|
||||
"\x0eEncryptionSeed\x12\x12\n" +
|
||||
"\x04seed\x18\x01 \x01(\tR\x04seed\"\xe7\x04\n" +
|
||||
"\x06Config\x122\n" +
|
||||
"\x03mtu\x18\x01 \x01(\v2 .xray.transport.internet.kcp.MTUR\x03mtu\x122\n" +
|
||||
"\x03tti\x18\x02 \x01(\v2 .xray.transport.internet.kcp.TTIR\x03tti\x12T\n" +
|
||||
"\x0fuplink_capacity\x18\x03 \x01(\v2+.xray.transport.internet.kcp.UplinkCapacityR\x0euplinkCapacity\x12Z\n" +
|
||||
"\x11downlink_capacity\x18\x04 \x01(\v2-.xray.transport.internet.kcp.DownlinkCapacityR\x10downlinkCapacity\x12\x1e\n" +
|
||||
"\n" +
|
||||
"congestion\x18\x05 \x01(\bR\n" +
|
||||
"congestion\x12K\n" +
|
||||
"\fwrite_buffer\x18\x06 \x01(\v2(.xray.transport.internet.kcp.WriteBufferR\vwriteBuffer\x12H\n" +
|
||||
"\vread_buffer\x18\a \x01(\v2'.xray.transport.internet.kcp.ReadBufferR\n" +
|
||||
"readBuffer\x12E\n" +
|
||||
"\rheader_config\x18\b \x01(\v2 .xray.common.serial.TypedMessageR\fheaderConfig\x12?\n" +
|
||||
"\x04seed\x18\n" +
|
||||
" \x01(\v2+.xray.transport.internet.kcp.EncryptionSeedR\x04seedJ\x04\b\t\x10\n" +
|
||||
"Bs\n" +
|
||||
"#transport/internet/kcp/config.proto\x12\x1bxray.transport.internet.kcp\"\xd9\x01\n" +
|
||||
"\x06Config\x12\x10\n" +
|
||||
"\x03mtu\x18\x01 \x01(\rR\x03mtu\x12\x10\n" +
|
||||
"\x03tti\x18\x02 \x01(\rR\x03tti\x12'\n" +
|
||||
"\x0fuplink_capacity\x18\x03 \x01(\rR\x0euplinkCapacity\x12+\n" +
|
||||
"\x11downlink_capacity\x18\x04 \x01(\rR\x10downlinkCapacity\x12'\n" +
|
||||
"\x0fcwnd_multiplier\x18\x05 \x01(\rR\x0ecwndMultiplier\x12,\n" +
|
||||
"\x12max_sending_window\x18\x06 \x01(\rR\x10maxSendingWindowBs\n" +
|
||||
"\x1fcom.xray.transport.internet.kcpP\x01Z0github.com/xtls/xray-core/transport/internet/kcp\xaa\x02\x1bXray.Transport.Internet.Kcpb\x06proto3"
|
||||
|
||||
var (
|
||||
@@ -542,33 +131,16 @@ func file_transport_internet_kcp_config_proto_rawDescGZIP() []byte {
|
||||
return file_transport_internet_kcp_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_internet_kcp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_transport_internet_kcp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_transport_internet_kcp_config_proto_goTypes = []any{
|
||||
(*MTU)(nil), // 0: xray.transport.internet.kcp.MTU
|
||||
(*TTI)(nil), // 1: xray.transport.internet.kcp.TTI
|
||||
(*UplinkCapacity)(nil), // 2: xray.transport.internet.kcp.UplinkCapacity
|
||||
(*DownlinkCapacity)(nil), // 3: xray.transport.internet.kcp.DownlinkCapacity
|
||||
(*WriteBuffer)(nil), // 4: xray.transport.internet.kcp.WriteBuffer
|
||||
(*ReadBuffer)(nil), // 5: xray.transport.internet.kcp.ReadBuffer
|
||||
(*ConnectionReuse)(nil), // 6: xray.transport.internet.kcp.ConnectionReuse
|
||||
(*EncryptionSeed)(nil), // 7: xray.transport.internet.kcp.EncryptionSeed
|
||||
(*Config)(nil), // 8: xray.transport.internet.kcp.Config
|
||||
(*serial.TypedMessage)(nil), // 9: xray.common.serial.TypedMessage
|
||||
(*Config)(nil), // 0: xray.transport.internet.kcp.Config
|
||||
}
|
||||
var file_transport_internet_kcp_config_proto_depIdxs = []int32{
|
||||
0, // 0: xray.transport.internet.kcp.Config.mtu:type_name -> xray.transport.internet.kcp.MTU
|
||||
1, // 1: xray.transport.internet.kcp.Config.tti:type_name -> xray.transport.internet.kcp.TTI
|
||||
2, // 2: xray.transport.internet.kcp.Config.uplink_capacity:type_name -> xray.transport.internet.kcp.UplinkCapacity
|
||||
3, // 3: xray.transport.internet.kcp.Config.downlink_capacity:type_name -> xray.transport.internet.kcp.DownlinkCapacity
|
||||
4, // 4: xray.transport.internet.kcp.Config.write_buffer:type_name -> xray.transport.internet.kcp.WriteBuffer
|
||||
5, // 5: xray.transport.internet.kcp.Config.read_buffer:type_name -> xray.transport.internet.kcp.ReadBuffer
|
||||
9, // 6: xray.transport.internet.kcp.Config.header_config:type_name -> xray.common.serial.TypedMessage
|
||||
7, // 7: xray.transport.internet.kcp.Config.seed:type_name -> xray.transport.internet.kcp.EncryptionSeed
|
||||
8, // [8:8] is the sub-list for method output_type
|
||||
8, // [8:8] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_internet_kcp_config_proto_init() }
|
||||
@@ -582,7 +154,7 @@ func file_transport_internet_kcp_config_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_kcp_config_proto_rawDesc), len(file_transport_internet_kcp_config_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 9,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -6,58 +6,11 @@ option go_package = "github.com/xtls/xray-core/transport/internet/kcp";
|
||||
option java_package = "com.xray.transport.internet.kcp";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/serial/typed_message.proto";
|
||||
|
||||
// Maximum Transmission Unit, in bytes.
|
||||
message MTU {
|
||||
uint32 value = 1;
|
||||
}
|
||||
|
||||
// Transmission Time Interview, in milli-sec.
|
||||
message TTI {
|
||||
uint32 value = 1;
|
||||
}
|
||||
|
||||
// Uplink capacity, in MB.
|
||||
message UplinkCapacity {
|
||||
uint32 value = 1;
|
||||
}
|
||||
|
||||
// Downlink capacity, in MB.
|
||||
message DownlinkCapacity {
|
||||
uint32 value = 1;
|
||||
}
|
||||
|
||||
message WriteBuffer {
|
||||
// Buffer size in bytes.
|
||||
uint32 size = 1;
|
||||
}
|
||||
|
||||
message ReadBuffer {
|
||||
// Buffer size in bytes.
|
||||
uint32 size = 1;
|
||||
}
|
||||
|
||||
message ConnectionReuse {
|
||||
bool enable = 1;
|
||||
}
|
||||
|
||||
// Pre-shared secret between client and server. It is used for traffic obfuscation.
|
||||
// Note that if seed is absent in the config, the traffic will still be obfuscated,
|
||||
// but by a predefined algorithm.
|
||||
message EncryptionSeed {
|
||||
string seed = 1;
|
||||
}
|
||||
|
||||
message Config {
|
||||
MTU mtu = 1;
|
||||
TTI tti = 2;
|
||||
UplinkCapacity uplink_capacity = 3;
|
||||
DownlinkCapacity downlink_capacity = 4;
|
||||
bool congestion = 5;
|
||||
WriteBuffer write_buffer = 6;
|
||||
ReadBuffer read_buffer = 7;
|
||||
xray.common.serial.TypedMessage header_config = 8;
|
||||
reserved 9;
|
||||
EncryptionSeed seed = 10;
|
||||
}
|
||||
uint32 mtu = 1;
|
||||
uint32 tti = 2;
|
||||
uint32 uplink_capacity = 3;
|
||||
uint32 downlink_capacity = 4;
|
||||
uint32 cwnd_multiplier = 5;
|
||||
uint32 max_sending_window = 6;
|
||||
}
|
||||
@@ -215,10 +215,10 @@ func NewConnection(meta ConnMetadata, writer io.Writer, closer io.Closer, config
|
||||
dataOutput: signal.NewNotifier(),
|
||||
Config: config,
|
||||
output: NewRetryableWriter(NewSegmentWriter(writer)),
|
||||
mss: config.GetMTUValue() - DataSegmentOverhead,
|
||||
mss: config.Mtu - DataSegmentOverhead,
|
||||
roundTrip: &RoundTripInfo{
|
||||
rto: 100,
|
||||
minRtt: config.GetTTIValue(),
|
||||
minRtt: config.Tti,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ func NewConnection(meta ConnMetadata, writer io.Writer, closer io.Closer, config
|
||||
return conn.State() == StateTerminated
|
||||
}
|
||||
conn.dataUpdater = NewUpdater(
|
||||
config.GetTTIValue(),
|
||||
config.Tti,
|
||||
func() bool {
|
||||
return !isTerminating() && (conn.sendingWorker.UpdateNecessary() || conn.receivingWorker.UpdateNecessary())
|
||||
},
|
||||
|
||||
@@ -16,7 +16,14 @@ func (NoOpCloser) Close() error {
|
||||
}
|
||||
|
||||
func TestConnectionReadTimeout(t *testing.T) {
|
||||
conn := NewConnection(ConnMetadata{Conversation: 1}, buf.DiscardBytes, NoOpCloser(0), &Config{})
|
||||
conn := NewConnection(ConnMetadata{Conversation: 1}, buf.DiscardBytes, NoOpCloser(0), &Config{
|
||||
Mtu: 1350,
|
||||
Tti: 50,
|
||||
UplinkCapacity: 5,
|
||||
DownlinkCapacity: 20,
|
||||
CwndMultiplier: 20,
|
||||
MaxSendingWindow: 2 * 1024 * 1024,
|
||||
})
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second))
|
||||
|
||||
b := make([]byte, 1024)
|
||||
|
||||
@@ -118,5 +118,5 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportDialer(protocolName, DialKCP))
|
||||
common.Must(internet.RegisterTransportDialer(ProtocolName, DialKCP))
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
// xtaci@github for translating to Golang
|
||||
package kcp
|
||||
|
||||
const protocolName = "mkcp"
|
||||
const ProtocolName = "mkcp"
|
||||
|
||||
@@ -19,8 +19,15 @@ import (
|
||||
|
||||
func TestDialAndListen(t *testing.T) {
|
||||
listerner, err := NewListener(context.Background(), net.LocalHostIP, net.Port(0), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "mkcp",
|
||||
ProtocolSettings: &Config{},
|
||||
ProtocolName: "mkcp",
|
||||
ProtocolSettings: &Config{
|
||||
Mtu: 1350,
|
||||
Tti: 50,
|
||||
UplinkCapacity: 5,
|
||||
DownlinkCapacity: 20,
|
||||
CwndMultiplier: 20,
|
||||
MaxSendingWindow: 2 * 1024 * 1024,
|
||||
},
|
||||
}, func(conn stat.Connection) {
|
||||
go func(c stat.Connection) {
|
||||
payload := make([]byte, 4096)
|
||||
@@ -46,8 +53,15 @@ func TestDialAndListen(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
errg.Go(func() error {
|
||||
clientConn, err := DialKCP(context.Background(), net.UDPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "mkcp",
|
||||
ProtocolSettings: &Config{},
|
||||
ProtocolName: "mkcp",
|
||||
ProtocolSettings: &Config{
|
||||
Mtu: 1350,
|
||||
Tti: 50,
|
||||
UplinkCapacity: 5,
|
||||
DownlinkCapacity: 20,
|
||||
CwndMultiplier: 20,
|
||||
MaxSendingWindow: 2 * 1024 * 1024,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -174,5 +174,5 @@ func ListenKCP(ctx context.Context, address net.Address, port net.Port, streamSe
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportListener(protocolName, ListenKCP))
|
||||
common.Must(internet.RegisterTransportListener(ProtocolName, ListenKCP))
|
||||
}
|
||||
|
||||
@@ -288,20 +288,22 @@ func (w *SendingWorker) Write(seg Segment) error {
|
||||
}
|
||||
|
||||
func (w *SendingWorker) OnPacketLoss(lossRate uint32) {
|
||||
if !w.conn.Config.Congestion || w.conn.roundTrip.Timeout() == 0 {
|
||||
if w.conn.roundTrip.Timeout() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if lossRate >= 15 {
|
||||
w.controlWindow = 3 * w.controlWindow / 4
|
||||
} else if lossRate <= 5 {
|
||||
}
|
||||
if lossRate <= 5 {
|
||||
w.controlWindow += w.controlWindow / 4
|
||||
}
|
||||
if w.controlWindow < 16 {
|
||||
w.controlWindow = 16
|
||||
}
|
||||
if w.controlWindow > 2*w.conn.Config.GetSendingInFlightSize() {
|
||||
w.controlWindow = 2 * w.conn.Config.GetSendingInFlightSize()
|
||||
cwnd := w.conn.Config.GetSendingInFlightSize()
|
||||
if w.controlWindow > cwnd {
|
||||
w.controlWindow = cwnd
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,11 +319,11 @@ func (w *SendingWorker) Flush(current uint32) {
|
||||
if cwnd > w.remoteNextNumber-w.firstUnacknowledged {
|
||||
cwnd = w.remoteNextNumber - w.firstUnacknowledged
|
||||
}
|
||||
if w.conn.Config.Congestion && cwnd > w.controlWindow {
|
||||
if cwnd > w.controlWindow {
|
||||
cwnd = w.controlWindow
|
||||
}
|
||||
|
||||
cwnd *= 20 // magic
|
||||
cwnd *= w.conn.Config.CwndMultiplier
|
||||
|
||||
if !w.window.IsEmpty() {
|
||||
w.window.Flush(current, w.conn.roundTrip.Timeout(), cwnd)
|
||||
|
||||
Reference in New Issue
Block a user