LjhAUMEM
2026-04-14 06:41:38 +08:00
committed by GitHub
parent d342361c89
commit 7094f8dc07
13 changed files with 160 additions and 700 deletions

View File

@@ -48,6 +48,8 @@ const protocolName = "hysteria"
func init() {
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
return new(Config)
return &Config{
UdpIdleTimeout: 60,
}
}))
}

View File

@@ -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,
}
}))
}

View File

@@ -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,
},

View File

@@ -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;
}

View File

@@ -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())
},

View File

@@ -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)

View File

@@ -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))
}

View File

@@ -6,4 +6,4 @@
// xtaci@github for translating to Golang
package kcp
const protocolName = "mkcp"
const ProtocolName = "mkcp"

View File

@@ -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

View File

@@ -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))
}

View File

@@ -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)