From 73e0d4a666dd80e63b15f9194b91fb0ecfc6c6d1 Mon Sep 17 00:00:00 2001 From: RPRX <63339210+RPRX@users.noreply.github.com> Date: Sun, 15 Dec 2024 05:43:10 +0000 Subject: [PATCH] XHTTP XMUX: Add `hMaxRequestTimes` and `hKeepAlivePeriod` (#4163) Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11492833 --- infra/conf/transport_internet.go | 47 +- .../internet/splithttp/browser_client.go | 4 + transport/internet/splithttp/client.go | 22 +- transport/internet/splithttp/config.go | 47 +- transport/internet/splithttp/config.pb.go | 499 +++++++++--------- transport/internet/splithttp/config.proto | 37 +- transport/internet/splithttp/dialer.go | 73 ++- transport/internet/splithttp/mux.go | 148 +++--- transport/internet/splithttp/mux_test.go | 66 +-- .../internet/splithttp/splithttp_test.go | 2 +- 10 files changed, 515 insertions(+), 430 deletions(-) diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 7669c016..08f5768e 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -228,22 +228,23 @@ type SplitHTTPConfig struct { NoSSEHeader bool `json:"noSSEHeader"` ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"` ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"` - ScMaxBufferedPosts int64 `json:"scMaxConcurrentPosts"` - KeepAlivePeriod int64 `json:"keepAlivePeriod"` - Xmux Xmux `json:"xmux"` + ScMaxBufferedPosts int64 `json:"scMaxBufferedPosts"` + Xmux XmuxConfig `json:"xmux"` DownloadSettings *StreamConfig `json:"downloadSettings"` Extra json.RawMessage `json:"extra"` } -type Xmux struct { - MaxConcurrency Int32Range `json:"maxConcurrency"` - MaxConnections Int32Range `json:"maxConnections"` - CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"` - CMaxLifetimeMs Int32Range `json:"cMaxLifetimeMs"` +type XmuxConfig struct { + MaxConcurrency Int32Range `json:"maxConcurrency"` + MaxConnections Int32Range `json:"maxConnections"` + CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"` + CMaxLifetimeMs Int32Range `json:"cMaxLifetimeMs"` + HMaxRequestTimes Int32Range `json:"hMaxRequestTimes"` + HKeepAlivePeriod int64 `json:"hKeepAlivePeriod"` } -func splithttpNewRandRangeConfig(input Int32Range) *splithttp.RandRangeConfig { - return &splithttp.RandRangeConfig{ +func newRangeConfig(input Int32Range) *splithttp.RangeConfig { + return &splithttp.RangeConfig{ From: input.From, To: input.To, } @@ -281,14 +282,13 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) { if c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency.To > 0 { return nil, errors.New("maxConnections cannot be specified together with maxConcurrency") } - if c.Xmux.MaxConcurrency.To == 0 && - c.Xmux.MaxConnections.To == 0 && - c.Xmux.CMaxReuseTimes.To == 0 && - c.Xmux.CMaxLifetimeMs.To == 0 { + if c.Xmux == (XmuxConfig{}) { c.Xmux.MaxConcurrency.From = 16 c.Xmux.MaxConcurrency.To = 32 c.Xmux.CMaxReuseTimes.From = 64 c.Xmux.CMaxReuseTimes.To = 128 + c.Xmux.HMaxRequestTimes.From = 800 + c.Xmux.HMaxRequestTimes.To = 900 } config := &splithttp.Config{ @@ -296,18 +296,19 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) { Path: c.Path, Mode: c.Mode, Headers: c.Headers, - XPaddingBytes: splithttpNewRandRangeConfig(c.XPaddingBytes), + XPaddingBytes: newRangeConfig(c.XPaddingBytes), NoGRPCHeader: c.NoGRPCHeader, NoSSEHeader: c.NoSSEHeader, - ScMaxEachPostBytes: splithttpNewRandRangeConfig(c.ScMaxEachPostBytes), - ScMinPostsIntervalMs: splithttpNewRandRangeConfig(c.ScMinPostsIntervalMs), + ScMaxEachPostBytes: newRangeConfig(c.ScMaxEachPostBytes), + ScMinPostsIntervalMs: newRangeConfig(c.ScMinPostsIntervalMs), ScMaxBufferedPosts: c.ScMaxBufferedPosts, - KeepAlivePeriod: c.KeepAlivePeriod, - Xmux: &splithttp.Multiplexing{ - MaxConcurrency: splithttpNewRandRangeConfig(c.Xmux.MaxConcurrency), - MaxConnections: splithttpNewRandRangeConfig(c.Xmux.MaxConnections), - CMaxReuseTimes: splithttpNewRandRangeConfig(c.Xmux.CMaxReuseTimes), - CMaxLifetimeMs: splithttpNewRandRangeConfig(c.Xmux.CMaxLifetimeMs), + Xmux: &splithttp.XmuxConfig{ + MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency), + MaxConnections: newRangeConfig(c.Xmux.MaxConnections), + CMaxReuseTimes: newRangeConfig(c.Xmux.CMaxReuseTimes), + CMaxLifetimeMs: newRangeConfig(c.Xmux.CMaxLifetimeMs), + HMaxRequestTimes: newRangeConfig(c.Xmux.HMaxRequestTimes), + HKeepAlivePeriod: c.Xmux.HKeepAlivePeriod, }, } diff --git a/transport/internet/splithttp/browser_client.go b/transport/internet/splithttp/browser_client.go index 427ed470..1b5f6d6b 100644 --- a/transport/internet/splithttp/browser_client.go +++ b/transport/internet/splithttp/browser_client.go @@ -13,6 +13,10 @@ import ( // has no fields because everything is global state :O) type BrowserDialerClient struct{} +func (c *BrowserDialerClient) IsClosed() bool { + panic("not implemented yet") +} + func (c *BrowserDialerClient) Open(ctx context.Context, pureURL string) (io.WriteCloser, io.ReadCloser) { panic("not implemented yet") } diff --git a/transport/internet/splithttp/client.go b/transport/internet/splithttp/client.go index 925d3b0d..3baea6f0 100644 --- a/transport/internet/splithttp/client.go +++ b/transport/internet/splithttp/client.go @@ -18,6 +18,8 @@ import ( // interface to abstract between use of browser dialer, vs net/http type DialerClient interface { + IsClosed() bool + // (ctx, baseURL, payload) -> err // baseURL already contains sessionId and seq SendUploadRequest(context.Context, string, io.ReadWriteCloser, int64) error @@ -39,12 +41,17 @@ type DialerClient interface { type DefaultDialerClient struct { transportConfig *Config client *http.Client + closed bool httpVersion string // pool of net.Conn, created using dialUploadConn uploadRawPool *sync.Pool dialUploadConn func(ctxInner context.Context) (net.Conn, error) } +func (c *DefaultDialerClient) IsClosed() bool { + return c.closed +} + func (c *DefaultDialerClient) Open(ctx context.Context, pureURL string) (io.WriteCloser, io.ReadCloser) { reader, writer := io.Pipe() req, _ := http.NewRequestWithContext(ctx, "POST", pureURL, reader) @@ -59,6 +66,8 @@ func (c *DefaultDialerClient) Open(ctx context.Context, pureURL string) (io.Writ if err != nil { errors.LogInfoInner(ctx, err, "failed to open ", pureURL) } else { + // c.closed = true + response.Body.Close() errors.LogInfo(ctx, "unexpected status ", response.StatusCode) } wrc.Close() @@ -76,7 +85,14 @@ func (c *DefaultDialerClient) OpenUpload(ctx context.Context, baseURL string) io if !c.transportConfig.NoGRPCHeader { req.Header.Set("Content-Type", "application/grpc") } - go c.client.Do(req) + go func() { + if resp, err := c.client.Do(req); err == nil { + if resp.StatusCode != 200 { + // c.closed = true + } + resp.Body.Close() + } + }() return writer } @@ -130,6 +146,7 @@ func (c *DefaultDialerClient) OpenDownload(ctx context.Context, baseURL string) } if response.StatusCode != 200 { + // c.closed = true response.Body.Close() errors.LogInfo(ctx, "invalid status code on download:", response.Status) gotDownResponse.Close() @@ -180,6 +197,7 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string, defer resp.Body.Close() if resp.StatusCode != 200 { + // c.closed = true return errors.New("bad status code:", resp.Status) } } else { @@ -214,6 +232,8 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string, return fmt.Errorf("error while reading response: %s", err.Error()) } if resp.StatusCode != 200 { + // c.closed = true + // resp.Body.Close() // I'm not sure return fmt.Errorf("got non-200 error response code: %d", resp.StatusCode) } } diff --git a/transport/internet/splithttp/config.go b/transport/internet/splithttp/config.go index ca3f25af..804bbd7e 100644 --- a/transport/internet/splithttp/config.go +++ b/transport/internet/splithttp/config.go @@ -37,7 +37,7 @@ func (c *Config) GetNormalizedQuery() string { query += "&" } - paddingLen := c.GetNormalizedXPaddingBytes().roll() + paddingLen := c.GetNormalizedXPaddingBytes().rand() if paddingLen > 0 { query += "x_padding=" + strings.Repeat("0", int(paddingLen)) } @@ -58,7 +58,7 @@ func (c *Config) WriteResponseHeader(writer http.ResponseWriter) { // CORS headers for the browser dialer writer.Header().Set("Access-Control-Allow-Origin", "*") writer.Header().Set("Access-Control-Allow-Methods", "GET, POST") - paddingLen := c.GetNormalizedXPaddingBytes().roll() + paddingLen := c.GetNormalizedXPaddingBytes().rand() if paddingLen > 0 { writer.Header().Set("X-Padding", strings.Repeat("0", int(paddingLen))) } @@ -72,9 +72,9 @@ func (c *Config) GetNormalizedScMaxBufferedPosts() int { return int(c.ScMaxBufferedPosts) } -func (c *Config) GetNormalizedScMaxEachPostBytes() RandRangeConfig { +func (c *Config) GetNormalizedScMaxEachPostBytes() RangeConfig { if c.ScMaxEachPostBytes == nil || c.ScMaxEachPostBytes.To == 0 { - return RandRangeConfig{ + return RangeConfig{ From: 1000000, To: 1000000, } @@ -83,9 +83,9 @@ func (c *Config) GetNormalizedScMaxEachPostBytes() RandRangeConfig { return *c.ScMaxEachPostBytes } -func (c *Config) GetNormalizedScMinPostsIntervalMs() RandRangeConfig { +func (c *Config) GetNormalizedScMinPostsIntervalMs() RangeConfig { if c.ScMinPostsIntervalMs == nil || c.ScMinPostsIntervalMs.To == 0 { - return RandRangeConfig{ + return RangeConfig{ From: 30, To: 30, } @@ -94,9 +94,9 @@ func (c *Config) GetNormalizedScMinPostsIntervalMs() RandRangeConfig { return *c.ScMinPostsIntervalMs } -func (c *Config) GetNormalizedXPaddingBytes() RandRangeConfig { +func (c *Config) GetNormalizedXPaddingBytes() RangeConfig { if c.XPaddingBytes == nil || c.XPaddingBytes.To == 0 { - return RandRangeConfig{ + return RangeConfig{ From: 100, To: 1000, } @@ -105,9 +105,20 @@ func (c *Config) GetNormalizedXPaddingBytes() RandRangeConfig { return *c.XPaddingBytes } -func (m *Multiplexing) GetNormalizedCMaxReuseTimes() RandRangeConfig { +func (m *XmuxConfig) GetNormalizedCMaxRequestTimes() RangeConfig { + if m.HMaxRequestTimes == nil { + return RangeConfig{ + From: 0, + To: 0, + } + } + + return *m.HMaxRequestTimes +} + +func (m *XmuxConfig) GetNormalizedCMaxReuseTimes() RangeConfig { if m.CMaxReuseTimes == nil { - return RandRangeConfig{ + return RangeConfig{ From: 0, To: 0, } @@ -116,9 +127,9 @@ func (m *Multiplexing) GetNormalizedCMaxReuseTimes() RandRangeConfig { return *m.CMaxReuseTimes } -func (m *Multiplexing) GetNormalizedCMaxLifetimeMs() RandRangeConfig { - if m.CMaxLifetimeMs == nil || m.CMaxLifetimeMs.To == 0 { - return RandRangeConfig{ +func (m *XmuxConfig) GetNormalizedCMaxLifetimeMs() RangeConfig { + if m.CMaxLifetimeMs == nil { + return RangeConfig{ From: 0, To: 0, } @@ -126,9 +137,9 @@ func (m *Multiplexing) GetNormalizedCMaxLifetimeMs() RandRangeConfig { return *m.CMaxLifetimeMs } -func (m *Multiplexing) GetNormalizedMaxConnections() RandRangeConfig { +func (m *XmuxConfig) GetNormalizedMaxConnections() RangeConfig { if m.MaxConnections == nil { - return RandRangeConfig{ + return RangeConfig{ From: 0, To: 0, } @@ -137,9 +148,9 @@ func (m *Multiplexing) GetNormalizedMaxConnections() RandRangeConfig { return *m.MaxConnections } -func (m *Multiplexing) GetNormalizedMaxConcurrency() RandRangeConfig { +func (m *XmuxConfig) GetNormalizedMaxConcurrency() RangeConfig { if m.MaxConcurrency == nil { - return RandRangeConfig{ + return RangeConfig{ From: 0, To: 0, } @@ -154,7 +165,7 @@ func init() { })) } -func (c RandRangeConfig) roll() int32 { +func (c RangeConfig) rand() int32 { if c.From == c.To { return c.From } diff --git a/transport/internet/splithttp/config.pb.go b/transport/internet/splithttp/config.pb.go index 7d745d53..2dd953d0 100644 --- a/transport/internet/splithttp/config.pb.go +++ b/transport/internet/splithttp/config.pb.go @@ -21,6 +21,144 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type RangeConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + From int32 `protobuf:"varint,1,opt,name=from,proto3" json:"from,omitempty"` + To int32 `protobuf:"varint,2,opt,name=to,proto3" json:"to,omitempty"` +} + +func (x *RangeConfig) Reset() { + *x = RangeConfig{} + mi := &file_transport_internet_splithttp_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RangeConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RangeConfig) ProtoMessage() {} + +func (x *RangeConfig) ProtoReflect() protoreflect.Message { + mi := &file_transport_internet_splithttp_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 RangeConfig.ProtoReflect.Descriptor instead. +func (*RangeConfig) Descriptor() ([]byte, []int) { + return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{0} +} + +func (x *RangeConfig) GetFrom() int32 { + if x != nil { + return x.From + } + return 0 +} + +func (x *RangeConfig) GetTo() int32 { + if x != nil { + return x.To + } + return 0 +} + +type XmuxConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MaxConcurrency *RangeConfig `protobuf:"bytes,1,opt,name=maxConcurrency,proto3" json:"maxConcurrency,omitempty"` + MaxConnections *RangeConfig `protobuf:"bytes,2,opt,name=maxConnections,proto3" json:"maxConnections,omitempty"` + CMaxReuseTimes *RangeConfig `protobuf:"bytes,3,opt,name=cMaxReuseTimes,proto3" json:"cMaxReuseTimes,omitempty"` + CMaxLifetimeMs *RangeConfig `protobuf:"bytes,4,opt,name=cMaxLifetimeMs,proto3" json:"cMaxLifetimeMs,omitempty"` + HMaxRequestTimes *RangeConfig `protobuf:"bytes,5,opt,name=hMaxRequestTimes,proto3" json:"hMaxRequestTimes,omitempty"` + HKeepAlivePeriod int64 `protobuf:"varint,6,opt,name=hKeepAlivePeriod,proto3" json:"hKeepAlivePeriod,omitempty"` +} + +func (x *XmuxConfig) Reset() { + *x = XmuxConfig{} + mi := &file_transport_internet_splithttp_config_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *XmuxConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*XmuxConfig) ProtoMessage() {} + +func (x *XmuxConfig) ProtoReflect() protoreflect.Message { + mi := &file_transport_internet_splithttp_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 XmuxConfig.ProtoReflect.Descriptor instead. +func (*XmuxConfig) Descriptor() ([]byte, []int) { + return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{1} +} + +func (x *XmuxConfig) GetMaxConcurrency() *RangeConfig { + if x != nil { + return x.MaxConcurrency + } + return nil +} + +func (x *XmuxConfig) GetMaxConnections() *RangeConfig { + if x != nil { + return x.MaxConnections + } + return nil +} + +func (x *XmuxConfig) GetCMaxReuseTimes() *RangeConfig { + if x != nil { + return x.CMaxReuseTimes + } + return nil +} + +func (x *XmuxConfig) GetCMaxLifetimeMs() *RangeConfig { + if x != nil { + return x.CMaxLifetimeMs + } + return nil +} + +func (x *XmuxConfig) GetHMaxRequestTimes() *RangeConfig { + if x != nil { + return x.HMaxRequestTimes + } + return nil +} + +func (x *XmuxConfig) GetHKeepAlivePeriod() int64 { + if x != nil { + return x.HKeepAlivePeriod + } + return 0 +} + type Config struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -30,20 +168,19 @@ type Config struct { Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` Mode string `protobuf:"bytes,3,opt,name=mode,proto3" json:"mode,omitempty"` Headers map[string]string `protobuf:"bytes,4,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XPaddingBytes *RandRangeConfig `protobuf:"bytes,5,opt,name=xPaddingBytes,proto3" json:"xPaddingBytes,omitempty"` + XPaddingBytes *RangeConfig `protobuf:"bytes,5,opt,name=xPaddingBytes,proto3" json:"xPaddingBytes,omitempty"` NoGRPCHeader bool `protobuf:"varint,6,opt,name=noGRPCHeader,proto3" json:"noGRPCHeader,omitempty"` NoSSEHeader bool `protobuf:"varint,7,opt,name=noSSEHeader,proto3" json:"noSSEHeader,omitempty"` - ScMaxEachPostBytes *RandRangeConfig `protobuf:"bytes,8,opt,name=scMaxEachPostBytes,proto3" json:"scMaxEachPostBytes,omitempty"` - ScMinPostsIntervalMs *RandRangeConfig `protobuf:"bytes,9,opt,name=scMinPostsIntervalMs,proto3" json:"scMinPostsIntervalMs,omitempty"` + ScMaxEachPostBytes *RangeConfig `protobuf:"bytes,8,opt,name=scMaxEachPostBytes,proto3" json:"scMaxEachPostBytes,omitempty"` + ScMinPostsIntervalMs *RangeConfig `protobuf:"bytes,9,opt,name=scMinPostsIntervalMs,proto3" json:"scMinPostsIntervalMs,omitempty"` ScMaxBufferedPosts int64 `protobuf:"varint,10,opt,name=scMaxBufferedPosts,proto3" json:"scMaxBufferedPosts,omitempty"` - KeepAlivePeriod int64 `protobuf:"varint,11,opt,name=keepAlivePeriod,proto3" json:"keepAlivePeriod,omitempty"` - Xmux *Multiplexing `protobuf:"bytes,12,opt,name=xmux,proto3" json:"xmux,omitempty"` - DownloadSettings *internet.StreamConfig `protobuf:"bytes,13,opt,name=downloadSettings,proto3" json:"downloadSettings,omitempty"` + Xmux *XmuxConfig `protobuf:"bytes,11,opt,name=xmux,proto3" json:"xmux,omitempty"` + DownloadSettings *internet.StreamConfig `protobuf:"bytes,12,opt,name=downloadSettings,proto3" json:"downloadSettings,omitempty"` } func (x *Config) Reset() { *x = Config{} - mi := &file_transport_internet_splithttp_config_proto_msgTypes[0] + mi := &file_transport_internet_splithttp_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -55,7 +192,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_transport_internet_splithttp_config_proto_msgTypes[0] + mi := &file_transport_internet_splithttp_config_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -68,7 +205,7 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{0} + return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{2} } func (x *Config) GetHost() string { @@ -99,7 +236,7 @@ func (x *Config) GetHeaders() map[string]string { return nil } -func (x *Config) GetXPaddingBytes() *RandRangeConfig { +func (x *Config) GetXPaddingBytes() *RangeConfig { if x != nil { return x.XPaddingBytes } @@ -120,14 +257,14 @@ func (x *Config) GetNoSSEHeader() bool { return false } -func (x *Config) GetScMaxEachPostBytes() *RandRangeConfig { +func (x *Config) GetScMaxEachPostBytes() *RangeConfig { if x != nil { return x.ScMaxEachPostBytes } return nil } -func (x *Config) GetScMinPostsIntervalMs() *RandRangeConfig { +func (x *Config) GetScMinPostsIntervalMs() *RangeConfig { if x != nil { return x.ScMinPostsIntervalMs } @@ -141,14 +278,7 @@ func (x *Config) GetScMaxBufferedPosts() int64 { return 0 } -func (x *Config) GetKeepAlivePeriod() int64 { - if x != nil { - return x.KeepAlivePeriod - } - return 0 -} - -func (x *Config) GetXmux() *Multiplexing { +func (x *Config) GetXmux() *XmuxConfig { if x != nil { return x.Xmux } @@ -162,128 +292,6 @@ func (x *Config) GetDownloadSettings() *internet.StreamConfig { return nil } -type RandRangeConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - From int32 `protobuf:"varint,1,opt,name=from,proto3" json:"from,omitempty"` - To int32 `protobuf:"varint,2,opt,name=to,proto3" json:"to,omitempty"` -} - -func (x *RandRangeConfig) Reset() { - *x = RandRangeConfig{} - mi := &file_transport_internet_splithttp_config_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RandRangeConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RandRangeConfig) ProtoMessage() {} - -func (x *RandRangeConfig) ProtoReflect() protoreflect.Message { - mi := &file_transport_internet_splithttp_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 RandRangeConfig.ProtoReflect.Descriptor instead. -func (*RandRangeConfig) Descriptor() ([]byte, []int) { - return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{1} -} - -func (x *RandRangeConfig) GetFrom() int32 { - if x != nil { - return x.From - } - return 0 -} - -func (x *RandRangeConfig) GetTo() int32 { - if x != nil { - return x.To - } - return 0 -} - -type Multiplexing struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MaxConcurrency *RandRangeConfig `protobuf:"bytes,1,opt,name=maxConcurrency,proto3" json:"maxConcurrency,omitempty"` - MaxConnections *RandRangeConfig `protobuf:"bytes,2,opt,name=maxConnections,proto3" json:"maxConnections,omitempty"` - CMaxReuseTimes *RandRangeConfig `protobuf:"bytes,3,opt,name=cMaxReuseTimes,proto3" json:"cMaxReuseTimes,omitempty"` - CMaxLifetimeMs *RandRangeConfig `protobuf:"bytes,4,opt,name=cMaxLifetimeMs,proto3" json:"cMaxLifetimeMs,omitempty"` -} - -func (x *Multiplexing) Reset() { - *x = Multiplexing{} - mi := &file_transport_internet_splithttp_config_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Multiplexing) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Multiplexing) ProtoMessage() {} - -func (x *Multiplexing) ProtoReflect() protoreflect.Message { - mi := &file_transport_internet_splithttp_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 Multiplexing.ProtoReflect.Descriptor instead. -func (*Multiplexing) Descriptor() ([]byte, []int) { - return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{2} -} - -func (x *Multiplexing) GetMaxConcurrency() *RandRangeConfig { - if x != nil { - return x.MaxConcurrency - } - return nil -} - -func (x *Multiplexing) GetMaxConnections() *RandRangeConfig { - if x != nil { - return x.MaxConnections - } - return nil -} - -func (x *Multiplexing) GetCMaxReuseTimes() *RandRangeConfig { - if x != nil { - return x.CMaxReuseTimes - } - return nil -} - -func (x *Multiplexing) GetCMaxLifetimeMs() *RandRangeConfig { - if x != nil { - return x.CMaxLifetimeMs - } - return nil -} - var File_transport_internet_splithttp_config_proto protoreflect.FileDescriptor var file_transport_internet_splithttp_config_proto_rawDesc = []byte{ @@ -294,94 +302,98 @@ var file_transport_internet_splithttp_config_proto_rawDesc = []byte{ 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x1a, 0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xb0, 0x06, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, - 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x50, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0d, 0x78, 0x50, 0x61, 0x64, - 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x32, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, - 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x0d, 0x78, 0x50, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x47, 0x52, 0x50, 0x43, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x47, 0x52, 0x50, 0x43, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x53, 0x53, 0x45, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x53, - 0x53, 0x45, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x62, 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61, - 0x78, 0x45, 0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x73, - 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x45, - 0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x66, 0x0a, 0x14, - 0x73, 0x63, 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x4d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x72, 0x61, + 0x31, 0x0a, 0x0b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, + 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x66, 0x72, + 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, + 0x74, 0x6f, 0x22, 0xf4, 0x03, 0x0a, 0x0a, 0x58, 0x6d, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x56, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, + 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x56, 0x0a, 0x0e, 0x6d, 0x61, 0x78, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, + 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x56, 0x0a, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x75, 0x73, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x52, + 0x65, 0x75, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x0e, 0x63, 0x4d, 0x61, + 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, + 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, + 0x73, 0x12, 0x5a, 0x0a, 0x10, 0x68, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x68, 0x4d, 0x61, + 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a, + 0x10, 0x68, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x68, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, + 0x69, 0x76, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x22, 0xf8, 0x05, 0x0a, 0x06, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, + 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, + 0x12, 0x50, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x36, 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, 0x73, 0x70, 0x6c, 0x69, + 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x12, 0x54, 0x0a, 0x0d, 0x78, 0x50, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x78, 0x50, 0x61, 0x64, 0x64, + 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x47, 0x52, + 0x50, 0x43, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, + 0x6e, 0x6f, 0x47, 0x52, 0x50, 0x43, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, + 0x6e, 0x6f, 0x53, 0x53, 0x45, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x53, 0x53, 0x45, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5e, + 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x45, 0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, - 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, - 0x73, 0x63, 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x65, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x50, - 0x6f, 0x73, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, - 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6b, - 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x43, - 0x0a, 0x04, 0x78, 0x6d, 0x75, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x78, + 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x73, 0x63, 0x4d, 0x61, + 0x78, 0x45, 0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x62, + 0x0a, 0x14, 0x73, 0x63, 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, - 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x52, 0x04, 0x78, - 0x6d, 0x75, 0x78, 0x12, 0x51, 0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 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, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x35, 0x0a, 0x0f, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x74, 0x6f, 0x22, 0xfe, 0x02, 0x0a, 0x0c, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x12, 0x5a, 0x0a, 0x0e, 0x6d, 0x61, - 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x32, 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, 0x73, 0x70, 0x6c, - 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x5a, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, - 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x75, 0x73, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, - 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, - 0x63, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x75, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x5a, - 0x0a, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x63, 0x4d, 0x61, 0x78, - 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x42, 0x85, 0x01, 0x0a, 0x25, 0x63, - 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, + 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x73, 0x63, + 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65, + 0x72, 0x65, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, + 0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x50, 0x6f, 0x73, + 0x74, 0x73, 0x12, 0x41, 0x0a, 0x04, 0x78, 0x6d, 0x75, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, - 0x68, 0x74, 0x74, 0x70, 0x50, 0x01, 0x5a, 0x36, 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, 0x2f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02, - 0x21, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x74, - 0x74, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x68, 0x74, 0x74, 0x70, 0x2e, 0x58, 0x6d, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x04, 0x78, 0x6d, 0x75, 0x78, 0x12, 0x51, 0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 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, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x42, 0x85, 0x01, 0x0a, 0x25, 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, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x50, 0x01, + 0x5a, 0x36, 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, 0x2f, 0x73, + 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02, 0x21, 0x58, 0x72, 0x61, 0x79, 0x2e, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x74, 0x74, 0x70, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -398,28 +410,29 @@ func file_transport_internet_splithttp_config_proto_rawDescGZIP() []byte { var file_transport_internet_splithttp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_transport_internet_splithttp_config_proto_goTypes = []any{ - (*Config)(nil), // 0: xray.transport.internet.splithttp.Config - (*RandRangeConfig)(nil), // 1: xray.transport.internet.splithttp.RandRangeConfig - (*Multiplexing)(nil), // 2: xray.transport.internet.splithttp.Multiplexing + (*RangeConfig)(nil), // 0: xray.transport.internet.splithttp.RangeConfig + (*XmuxConfig)(nil), // 1: xray.transport.internet.splithttp.XmuxConfig + (*Config)(nil), // 2: xray.transport.internet.splithttp.Config nil, // 3: xray.transport.internet.splithttp.Config.HeadersEntry (*internet.StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig } var file_transport_internet_splithttp_config_proto_depIdxs = []int32{ - 3, // 0: xray.transport.internet.splithttp.Config.headers:type_name -> xray.transport.internet.splithttp.Config.HeadersEntry - 1, // 1: xray.transport.internet.splithttp.Config.xPaddingBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 1, // 2: xray.transport.internet.splithttp.Config.scMaxEachPostBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 1, // 3: xray.transport.internet.splithttp.Config.scMinPostsIntervalMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 2, // 4: xray.transport.internet.splithttp.Config.xmux:type_name -> xray.transport.internet.splithttp.Multiplexing - 4, // 5: xray.transport.internet.splithttp.Config.downloadSettings:type_name -> xray.transport.internet.StreamConfig - 1, // 6: xray.transport.internet.splithttp.Multiplexing.maxConcurrency:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 1, // 7: xray.transport.internet.splithttp.Multiplexing.maxConnections:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 1, // 8: xray.transport.internet.splithttp.Multiplexing.cMaxReuseTimes:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 1, // 9: xray.transport.internet.splithttp.Multiplexing.cMaxLifetimeMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig - 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 + 0, // 0: xray.transport.internet.splithttp.XmuxConfig.maxConcurrency:type_name -> xray.transport.internet.splithttp.RangeConfig + 0, // 1: xray.transport.internet.splithttp.XmuxConfig.maxConnections:type_name -> xray.transport.internet.splithttp.RangeConfig + 0, // 2: xray.transport.internet.splithttp.XmuxConfig.cMaxReuseTimes:type_name -> xray.transport.internet.splithttp.RangeConfig + 0, // 3: xray.transport.internet.splithttp.XmuxConfig.cMaxLifetimeMs:type_name -> xray.transport.internet.splithttp.RangeConfig + 0, // 4: xray.transport.internet.splithttp.XmuxConfig.hMaxRequestTimes:type_name -> xray.transport.internet.splithttp.RangeConfig + 3, // 5: xray.transport.internet.splithttp.Config.headers:type_name -> xray.transport.internet.splithttp.Config.HeadersEntry + 0, // 6: xray.transport.internet.splithttp.Config.xPaddingBytes:type_name -> xray.transport.internet.splithttp.RangeConfig + 0, // 7: xray.transport.internet.splithttp.Config.scMaxEachPostBytes:type_name -> xray.transport.internet.splithttp.RangeConfig + 0, // 8: xray.transport.internet.splithttp.Config.scMinPostsIntervalMs:type_name -> xray.transport.internet.splithttp.RangeConfig + 1, // 9: xray.transport.internet.splithttp.Config.xmux:type_name -> xray.transport.internet.splithttp.XmuxConfig + 4, // 10: xray.transport.internet.splithttp.Config.downloadSettings:type_name -> xray.transport.internet.StreamConfig + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_transport_internet_splithttp_config_proto_init() } diff --git a/transport/internet/splithttp/config.proto b/transport/internet/splithttp/config.proto index 655fdf3f..08677266 100644 --- a/transport/internet/splithttp/config.proto +++ b/transport/internet/splithttp/config.proto @@ -8,30 +8,31 @@ option java_multiple_files = true; import "transport/internet/config.proto"; +message RangeConfig { + int32 from = 1; + int32 to = 2; +} + +message XmuxConfig { + RangeConfig maxConcurrency = 1; + RangeConfig maxConnections = 2; + RangeConfig cMaxReuseTimes = 3; + RangeConfig cMaxLifetimeMs = 4; + RangeConfig hMaxRequestTimes = 5; + int64 hKeepAlivePeriod = 6; +} + message Config { string host = 1; string path = 2; string mode = 3; map headers = 4; - RandRangeConfig xPaddingBytes = 5; + RangeConfig xPaddingBytes = 5; bool noGRPCHeader = 6; bool noSSEHeader = 7; - RandRangeConfig scMaxEachPostBytes = 8; - RandRangeConfig scMinPostsIntervalMs = 9; + RangeConfig scMaxEachPostBytes = 8; + RangeConfig scMinPostsIntervalMs = 9; int64 scMaxBufferedPosts = 10; - int64 keepAlivePeriod = 11; - Multiplexing xmux = 12; - xray.transport.internet.StreamConfig downloadSettings = 13; -} - -message RandRangeConfig { - int32 from = 1; - int32 to = 2; -} - -message Multiplexing { - RandRangeConfig maxConcurrency = 1; - RandRangeConfig maxConnections = 2; - RandRangeConfig cMaxReuseTimes = 3; - RandRangeConfig cMaxLifetimeMs = 4; + XmuxConfig xmux = 11; + xray.transport.internet.StreamConfig downloadSettings = 12; } diff --git a/transport/internet/splithttp/dialer.go b/transport/internet/splithttp/dialer.go index cd0abc85..973b8a9c 100644 --- a/transport/internet/splithttp/dialer.go +++ b/transport/internet/splithttp/dialer.go @@ -10,6 +10,7 @@ import ( "net/url" "strconv" "sync" + "sync/atomic" "time" "github.com/quic-go/quic-go" @@ -45,11 +46,11 @@ type dialerConf struct { } var ( - globalDialerMap map[dialerConf]*muxManager + globalDialerMap map[dialerConf]*XmuxManager globalDialerAccess sync.Mutex ) -func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (DialerClient, *muxResource) { +func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (DialerClient, *XmuxClient) { realityConfig := reality.ConfigFromStreamSettings(streamSettings) if browser_dialer.HasBrowserDialer() && realityConfig != nil { @@ -60,28 +61,28 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in defer globalDialerAccess.Unlock() if globalDialerMap == nil { - globalDialerMap = make(map[dialerConf]*muxManager) + globalDialerMap = make(map[dialerConf]*XmuxManager) } key := dialerConf{dest, streamSettings} - muxManager, found := globalDialerMap[key] + xmuxManager, found := globalDialerMap[key] if !found { transportConfig := streamSettings.ProtocolSettings.(*Config) - var mux Multiplexing + var xmuxConfig XmuxConfig if transportConfig.Xmux != nil { - mux = *transportConfig.Xmux + xmuxConfig = *transportConfig.Xmux } - muxManager = NewMuxManager(mux, func() interface{} { + xmuxManager = NewXmuxManager(xmuxConfig, func() XmuxConn { return createHTTPClient(dest, streamSettings) }) - globalDialerMap[key] = muxManager + globalDialerMap[key] = xmuxManager } - res := muxManager.GetResource(ctx) - return res.Resource.(DialerClient), res + xmuxClient := xmuxManager.GetXmuxClient(ctx) + return xmuxClient.XmuxConn.(DialerClient), xmuxClient } func decideHTTPVersion(tlsConfig *tls.Config, realityConfig *reality.Config) string { @@ -144,7 +145,10 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea return conn, nil } - keepAlivePeriod := time.Duration(streamSettings.ProtocolSettings.(*Config).KeepAlivePeriod) * time.Second + var keepAlivePeriod time.Duration + if streamSettings.ProtocolSettings.(*Config).Xmux != nil { + keepAlivePeriod = time.Duration(streamSettings.ProtocolSettings.(*Config).Xmux.HKeepAlivePeriod) * time.Second + } var transport http.RoundTripper @@ -282,7 +286,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me requestURL.Path = transportConfiguration.GetNormalizedPath() + sessionIdUuid.String() requestURL.RawQuery = transportConfiguration.GetNormalizedQuery() - httpClient, muxRes := getHTTPClient(ctx, dest, streamSettings) + httpClient, xmuxClient := getHTTPClient(ctx, dest, streamSettings) mode := transportConfiguration.Mode if mode == "" || mode == "auto" { @@ -299,7 +303,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me requestURL2 := requestURL httpClient2 := httpClient - var muxRes2 *muxResource + xmuxClient2 := xmuxClient if transportConfiguration.DownloadSettings != nil { globalDialerAccess.Lock() if streamSettings.DownloadSettings == nil { @@ -332,7 +336,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me } requestURL2.Path = config2.GetNormalizedPath() + sessionIdUuid.String() requestURL2.RawQuery = config2.GetNormalizedQuery() - httpClient2, muxRes2 = getHTTPClient(ctx, dest2, memory2) + httpClient2, xmuxClient2 = getHTTPClient(ctx, dest2, memory2) errors.LogInfo(ctx, fmt.Sprintf("XHTTP is downloading from %s, mode %s, HTTP version %s, host %s", dest2, "stream-down", httpVersion2, requestURL2.Host)) } @@ -343,23 +347,29 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me if mode == "stream-one" { requestURL.Path = transportConfiguration.GetNormalizedPath() + if xmuxClient != nil { + xmuxClient.LeftRequests.Add(-1) + } writer, reader = httpClient.Open(context.WithoutCancel(ctx), requestURL.String()) remoteAddr = &net.TCPAddr{} localAddr = &net.TCPAddr{} } else { + if xmuxClient2 != nil { + xmuxClient2.LeftRequests.Add(-1) + } reader, remoteAddr, localAddr, err = httpClient2.OpenDownload(context.WithoutCancel(ctx), requestURL2.String()) if err != nil { return nil, err } } - if muxRes != nil { - muxRes.OpenRequests.Add(1) + if xmuxClient != nil { + xmuxClient.OpenUsage.Add(1) } - if muxRes2 != nil { - muxRes2.OpenRequests.Add(1) + if xmuxClient2 != nil && xmuxClient2 != xmuxClient { + xmuxClient2.OpenUsage.Add(1) } - closed := false + var once atomic.Int32 conn := splitConn{ writer: writer, @@ -367,23 +377,28 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me remoteAddr: remoteAddr, localAddr: localAddr, onClose: func() { - if closed { + if once.Add(-1) < 0 { return } - closed = true - if muxRes != nil { - muxRes.OpenRequests.Add(-1) + if xmuxClient != nil { + xmuxClient.OpenUsage.Add(-1) } - if muxRes2 != nil { - muxRes2.OpenRequests.Add(-1) + if xmuxClient2 != nil && xmuxClient2 != xmuxClient { + xmuxClient2.OpenUsage.Add(-1) } }, } if mode == "stream-one" { + if xmuxClient != nil { + xmuxClient.LeftRequests.Add(-1) + } return stat.Connection(&conn), nil } if mode == "stream-up" { + if xmuxClient != nil { + xmuxClient.LeftRequests.Add(-1) + } conn.writer = httpClient.OpenUpload(ctx, requestURL.String()) return stat.Connection(&conn), nil } @@ -391,7 +406,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me scMaxEachPostBytes := transportConfiguration.GetNormalizedScMaxEachPostBytes() scMinPostsIntervalMs := transportConfiguration.GetNormalizedScMinPostsIntervalMs() - maxUploadSize := scMaxEachPostBytes.roll() + maxUploadSize := scMaxEachPostBytes.rand() // WithSizeLimit(0) will still allow single bytes to pass, and a lot of // code relies on this behavior. Subtract 1 so that together with // uploadWriter wrapper, exact size limits can be enforced @@ -426,7 +441,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me seq += 1 if scMinPostsIntervalMs.From > 0 { - time.Sleep(time.Duration(scMinPostsIntervalMs.roll())*time.Millisecond - time.Since(lastWrite)) + time.Sleep(time.Duration(scMinPostsIntervalMs.rand())*time.Millisecond - time.Since(lastWrite)) } // by offloading the uploads into a buffered pipe, multiple conn.Write @@ -439,6 +454,10 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me lastWrite = time.Now() + if xmuxClient != nil && xmuxClient.LeftRequests.Add(-1) <= 0 { + httpClient, xmuxClient = getHTTPClient(ctx, dest, streamSettings) + } + go func() { err := httpClient.SendUploadRequest( context.WithoutCancel(ctx), diff --git a/transport/internet/splithttp/mux.go b/transport/internet/splithttp/mux.go index 83ab25b0..e658c006 100644 --- a/transport/internet/splithttp/mux.go +++ b/transport/internet/splithttp/mux.go @@ -2,101 +2,113 @@ package splithttp import ( "context" - "math/rand" + "crypto/rand" + "math" + "math/big" "sync/atomic" "time" "github.com/xtls/xray-core/common/errors" ) -type muxResource struct { - Resource interface{} - OpenRequests atomic.Int32 +type XmuxConn interface { + IsClosed() bool +} + +type XmuxClient struct { + XmuxConn XmuxConn + OpenUsage atomic.Int32 leftUsage int32 expirationTime time.Time + LeftRequests atomic.Int32 } -type muxManager struct { - newResourceFn func() interface{} - config Multiplexing - concurrency int32 - connections int32 - instances []*muxResource +type XmuxManager struct { + xmuxConfig XmuxConfig + concurrency int32 + connections int32 + newConnFunc func() XmuxConn + xmuxClients []*XmuxClient } -func NewMuxManager(config Multiplexing, newResource func() interface{}) *muxManager { - return &muxManager{ - config: config, - concurrency: config.GetNormalizedMaxConcurrency().roll(), - connections: config.GetNormalizedMaxConnections().roll(), - newResourceFn: newResource, - instances: make([]*muxResource, 0), +func NewXmuxManager(xmuxConfig XmuxConfig, newConnFunc func() XmuxConn) *XmuxManager { + return &XmuxManager{ + xmuxConfig: xmuxConfig, + concurrency: xmuxConfig.GetNormalizedMaxConcurrency().rand(), + connections: xmuxConfig.GetNormalizedMaxConnections().rand(), + newConnFunc: newConnFunc, + xmuxClients: make([]*XmuxClient, 0), } } -func (m *muxManager) GetResource(ctx context.Context) *muxResource { - m.removeExpiredConnections(ctx) +func (m *XmuxManager) newXmuxClient() *XmuxClient { + xmuxClient := &XmuxClient{ + XmuxConn: m.newConnFunc(), + leftUsage: -1, + expirationTime: time.UnixMilli(0), + } + if x := m.xmuxConfig.GetNormalizedCMaxReuseTimes().rand(); x > 0 { + xmuxClient.leftUsage = x - 1 + } + if x := m.xmuxConfig.GetNormalizedCMaxLifetimeMs().rand(); x > 0 { + xmuxClient.expirationTime = time.Now().Add(time.Duration(x) * time.Millisecond) + } + xmuxClient.LeftRequests.Store(math.MaxInt32) + if x := m.xmuxConfig.GetNormalizedCMaxRequestTimes().rand(); x > 0 { + xmuxClient.LeftRequests.Store(x) + } + m.xmuxClients = append(m.xmuxClients, xmuxClient) + return xmuxClient +} - if m.connections > 0 && len(m.instances) < int(m.connections) { - errors.LogDebug(ctx, "xmux: creating client, connections=", len(m.instances)) - return m.newResource() +func (m *XmuxManager) GetXmuxClient(ctx context.Context) *XmuxClient { // when locking + for i := 0; i < len(m.xmuxClients); { + xmuxClient := m.xmuxClients[i] + if xmuxClient.XmuxConn.IsClosed() || + xmuxClient.leftUsage == 0 || + (xmuxClient.expirationTime != time.UnixMilli(0) && time.Now().After(xmuxClient.expirationTime)) || + xmuxClient.LeftRequests.Load() <= 0 { + errors.LogDebug(ctx, "XMUX: removing xmuxClient, IsClosed() = ", xmuxClient.XmuxConn.IsClosed(), + ", OpenUsage = ", xmuxClient.OpenUsage.Load(), + ", leftUsage = ", xmuxClient.leftUsage, + ", expirationTime = ", xmuxClient.expirationTime, + ", LeftRequests = ", xmuxClient.LeftRequests.Load()) + m.xmuxClients = append(m.xmuxClients[:i], m.xmuxClients[i+1:]...) + } else { + i++ + } } - if len(m.instances) == 0 { - errors.LogDebug(ctx, "xmux: creating client because instances is empty, connections=", len(m.instances)) - return m.newResource() + if len(m.xmuxClients) == 0 { + errors.LogDebug(ctx, "XMUX: creating xmuxClient because xmuxClients is empty") + return m.newXmuxClient() } - clients := make([]*muxResource, 0) + if m.connections > 0 && len(m.xmuxClients) < int(m.connections) { + errors.LogDebug(ctx, "XMUX: creating xmuxClient because maxConnections was not hit, xmuxClients = ", len(m.xmuxClients)) + return m.newXmuxClient() + } + + xmuxClients := make([]*XmuxClient, 0) if m.concurrency > 0 { - for _, client := range m.instances { - openRequests := client.OpenRequests.Load() - if openRequests < m.concurrency { - clients = append(clients, client) + for _, xmuxClient := range m.xmuxClients { + if xmuxClient.OpenUsage.Load() < m.concurrency { + xmuxClients = append(xmuxClients, xmuxClient) } } } else { - clients = m.instances + xmuxClients = m.xmuxClients } - if len(clients) == 0 { - errors.LogDebug(ctx, "xmux: creating client because concurrency was hit, total clients=", len(m.instances)) - return m.newResource() + if len(xmuxClients) == 0 { + errors.LogDebug(ctx, "XMUX: creating xmuxClient because maxConcurrency was hit, xmuxClients = ", len(m.xmuxClients)) + return m.newXmuxClient() } - client := clients[rand.Intn(len(clients))] - if client.leftUsage > 0 { - client.leftUsage -= 1 - } - return client -} - -func (m *muxManager) newResource() *muxResource { - leftUsage := int32(-1) - if x := m.config.GetNormalizedCMaxReuseTimes().roll(); x > 0 { - leftUsage = x - 1 - } - expirationTime := time.UnixMilli(0) - if x := m.config.GetNormalizedCMaxLifetimeMs().roll(); x > 0 { - expirationTime = time.Now().Add(time.Duration(x) * time.Millisecond) - } - - client := &muxResource{ - Resource: m.newResourceFn(), - leftUsage: leftUsage, - expirationTime: expirationTime, - } - m.instances = append(m.instances, client) - return client -} - -func (m *muxManager) removeExpiredConnections(ctx context.Context) { - for i := 0; i < len(m.instances); i++ { - client := m.instances[i] - if client.leftUsage == 0 || (client.expirationTime != time.UnixMilli(0) && time.Now().After(client.expirationTime)) { - errors.LogDebug(ctx, "xmux: removing client, leftUsage = ", client.leftUsage, ", expirationTime = ", client.expirationTime) - m.instances = append(m.instances[:i], m.instances[i+1:]...) - i-- - } + i, _ := rand.Int(rand.Reader, big.NewInt(int64(len(xmuxClients)))) + xmuxClient := xmuxClients[i.Int64()] + if xmuxClient.leftUsage > 0 { + xmuxClient.leftUsage -= 1 } + return xmuxClient } diff --git a/transport/internet/splithttp/mux_test.go b/transport/internet/splithttp/mux_test.go index e59eff0e..835d07f0 100644 --- a/transport/internet/splithttp/mux_test.go +++ b/transport/internet/splithttp/mux_test.go @@ -9,80 +9,84 @@ import ( type fakeRoundTripper struct{} +func (f *fakeRoundTripper) IsClosed() bool { + return false +} + func TestMaxConnections(t *testing.T) { - config := Multiplexing{ - MaxConnections: &RandRangeConfig{From: 4, To: 4}, + xmuxConfig := XmuxConfig{ + MaxConnections: &RangeConfig{From: 4, To: 4}, } - mux := NewMuxManager(config, func() interface{} { + xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn { return &fakeRoundTripper{} }) - clients := make(map[interface{}]struct{}) + xmuxClients := make(map[interface{}]struct{}) for i := 0; i < 8; i++ { - clients[mux.GetResource(context.Background())] = struct{}{} + xmuxClients[xmuxManager.GetXmuxClient(context.Background())] = struct{}{} } - if len(clients) != 4 { - t.Error("did not get 4 distinct clients, got ", len(clients)) + if len(xmuxClients) != 4 { + t.Error("did not get 4 distinct clients, got ", len(xmuxClients)) } } func TestCMaxReuseTimes(t *testing.T) { - config := Multiplexing{ - CMaxReuseTimes: &RandRangeConfig{From: 2, To: 2}, + xmuxConfig := XmuxConfig{ + CMaxReuseTimes: &RangeConfig{From: 2, To: 2}, } - mux := NewMuxManager(config, func() interface{} { + xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn { return &fakeRoundTripper{} }) - clients := make(map[interface{}]struct{}) + xmuxClients := make(map[interface{}]struct{}) for i := 0; i < 64; i++ { - clients[mux.GetResource(context.Background())] = struct{}{} + xmuxClients[xmuxManager.GetXmuxClient(context.Background())] = struct{}{} } - if len(clients) != 32 { - t.Error("did not get 32 distinct clients, got ", len(clients)) + if len(xmuxClients) != 32 { + t.Error("did not get 32 distinct clients, got ", len(xmuxClients)) } } func TestMaxConcurrency(t *testing.T) { - config := Multiplexing{ - MaxConcurrency: &RandRangeConfig{From: 2, To: 2}, + xmuxConfig := XmuxConfig{ + MaxConcurrency: &RangeConfig{From: 2, To: 2}, } - mux := NewMuxManager(config, func() interface{} { + xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn { return &fakeRoundTripper{} }) - clients := make(map[interface{}]struct{}) + xmuxClients := make(map[interface{}]struct{}) for i := 0; i < 64; i++ { - client := mux.GetResource(context.Background()) - client.OpenRequests.Add(1) - clients[client] = struct{}{} + xmuxClient := xmuxManager.GetXmuxClient(context.Background()) + xmuxClient.OpenUsage.Add(1) + xmuxClients[xmuxClient] = struct{}{} } - if len(clients) != 32 { - t.Error("did not get 32 distinct clients, got ", len(clients)) + if len(xmuxClients) != 32 { + t.Error("did not get 32 distinct clients, got ", len(xmuxClients)) } } func TestDefault(t *testing.T) { - config := Multiplexing{} + xmuxConfig := XmuxConfig{} - mux := NewMuxManager(config, func() interface{} { + xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn { return &fakeRoundTripper{} }) - clients := make(map[interface{}]struct{}) + xmuxClients := make(map[interface{}]struct{}) for i := 0; i < 64; i++ { - client := mux.GetResource(context.Background()) - client.OpenRequests.Add(1) - clients[client] = struct{}{} + xmuxClient := xmuxManager.GetXmuxClient(context.Background()) + xmuxClient.OpenUsage.Add(1) + xmuxClients[xmuxClient] = struct{}{} } - if len(clients) != 1 { - t.Error("did not get 1 distinct clients, got ", len(clients)) + if len(xmuxClients) != 1 { + t.Error("did not get 1 distinct clients, got ", len(xmuxClients)) } } diff --git a/transport/internet/splithttp/splithttp_test.go b/transport/internet/splithttp/splithttp_test.go index 8f32f7d3..20043b4a 100644 --- a/transport/internet/splithttp/splithttp_test.go +++ b/transport/internet/splithttp/splithttp_test.go @@ -423,7 +423,7 @@ func Test_maxUpload(t *testing.T) { ProtocolName: "splithttp", ProtocolSettings: &Config{ Path: "/sh", - ScMaxEachPostBytes: &RandRangeConfig{ + ScMaxEachPostBytes: &RangeConfig{ From: 10000, To: 10000, },