mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-12-22 13:39:50 +00:00
XHTTP XMUX: Add hMaxRequestTimes
and hKeepAlivePeriod
(#4163)
Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11492833
This commit is contained in:
parent
7463561856
commit
73e0d4a666
@ -228,22 +228,23 @@ type SplitHTTPConfig struct {
|
|||||||
NoSSEHeader bool `json:"noSSEHeader"`
|
NoSSEHeader bool `json:"noSSEHeader"`
|
||||||
ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"`
|
ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"`
|
||||||
ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"`
|
ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"`
|
||||||
ScMaxBufferedPosts int64 `json:"scMaxConcurrentPosts"`
|
ScMaxBufferedPosts int64 `json:"scMaxBufferedPosts"`
|
||||||
KeepAlivePeriod int64 `json:"keepAlivePeriod"`
|
Xmux XmuxConfig `json:"xmux"`
|
||||||
Xmux Xmux `json:"xmux"`
|
|
||||||
DownloadSettings *StreamConfig `json:"downloadSettings"`
|
DownloadSettings *StreamConfig `json:"downloadSettings"`
|
||||||
Extra json.RawMessage `json:"extra"`
|
Extra json.RawMessage `json:"extra"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Xmux struct {
|
type XmuxConfig struct {
|
||||||
MaxConcurrency Int32Range `json:"maxConcurrency"`
|
MaxConcurrency Int32Range `json:"maxConcurrency"`
|
||||||
MaxConnections Int32Range `json:"maxConnections"`
|
MaxConnections Int32Range `json:"maxConnections"`
|
||||||
CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"`
|
CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"`
|
||||||
CMaxLifetimeMs Int32Range `json:"cMaxLifetimeMs"`
|
CMaxLifetimeMs Int32Range `json:"cMaxLifetimeMs"`
|
||||||
|
HMaxRequestTimes Int32Range `json:"hMaxRequestTimes"`
|
||||||
|
HKeepAlivePeriod int64 `json:"hKeepAlivePeriod"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func splithttpNewRandRangeConfig(input Int32Range) *splithttp.RandRangeConfig {
|
func newRangeConfig(input Int32Range) *splithttp.RangeConfig {
|
||||||
return &splithttp.RandRangeConfig{
|
return &splithttp.RangeConfig{
|
||||||
From: input.From,
|
From: input.From,
|
||||||
To: input.To,
|
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 {
|
if c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency.To > 0 {
|
||||||
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
|
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
|
||||||
}
|
}
|
||||||
if c.Xmux.MaxConcurrency.To == 0 &&
|
if c.Xmux == (XmuxConfig{}) {
|
||||||
c.Xmux.MaxConnections.To == 0 &&
|
|
||||||
c.Xmux.CMaxReuseTimes.To == 0 &&
|
|
||||||
c.Xmux.CMaxLifetimeMs.To == 0 {
|
|
||||||
c.Xmux.MaxConcurrency.From = 16
|
c.Xmux.MaxConcurrency.From = 16
|
||||||
c.Xmux.MaxConcurrency.To = 32
|
c.Xmux.MaxConcurrency.To = 32
|
||||||
c.Xmux.CMaxReuseTimes.From = 64
|
c.Xmux.CMaxReuseTimes.From = 64
|
||||||
c.Xmux.CMaxReuseTimes.To = 128
|
c.Xmux.CMaxReuseTimes.To = 128
|
||||||
|
c.Xmux.HMaxRequestTimes.From = 800
|
||||||
|
c.Xmux.HMaxRequestTimes.To = 900
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &splithttp.Config{
|
config := &splithttp.Config{
|
||||||
@ -296,18 +296,19 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
|||||||
Path: c.Path,
|
Path: c.Path,
|
||||||
Mode: c.Mode,
|
Mode: c.Mode,
|
||||||
Headers: c.Headers,
|
Headers: c.Headers,
|
||||||
XPaddingBytes: splithttpNewRandRangeConfig(c.XPaddingBytes),
|
XPaddingBytes: newRangeConfig(c.XPaddingBytes),
|
||||||
NoGRPCHeader: c.NoGRPCHeader,
|
NoGRPCHeader: c.NoGRPCHeader,
|
||||||
NoSSEHeader: c.NoSSEHeader,
|
NoSSEHeader: c.NoSSEHeader,
|
||||||
ScMaxEachPostBytes: splithttpNewRandRangeConfig(c.ScMaxEachPostBytes),
|
ScMaxEachPostBytes: newRangeConfig(c.ScMaxEachPostBytes),
|
||||||
ScMinPostsIntervalMs: splithttpNewRandRangeConfig(c.ScMinPostsIntervalMs),
|
ScMinPostsIntervalMs: newRangeConfig(c.ScMinPostsIntervalMs),
|
||||||
ScMaxBufferedPosts: c.ScMaxBufferedPosts,
|
ScMaxBufferedPosts: c.ScMaxBufferedPosts,
|
||||||
KeepAlivePeriod: c.KeepAlivePeriod,
|
Xmux: &splithttp.XmuxConfig{
|
||||||
Xmux: &splithttp.Multiplexing{
|
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
|
||||||
MaxConcurrency: splithttpNewRandRangeConfig(c.Xmux.MaxConcurrency),
|
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
|
||||||
MaxConnections: splithttpNewRandRangeConfig(c.Xmux.MaxConnections),
|
CMaxReuseTimes: newRangeConfig(c.Xmux.CMaxReuseTimes),
|
||||||
CMaxReuseTimes: splithttpNewRandRangeConfig(c.Xmux.CMaxReuseTimes),
|
CMaxLifetimeMs: newRangeConfig(c.Xmux.CMaxLifetimeMs),
|
||||||
CMaxLifetimeMs: splithttpNewRandRangeConfig(c.Xmux.CMaxLifetimeMs),
|
HMaxRequestTimes: newRangeConfig(c.Xmux.HMaxRequestTimes),
|
||||||
|
HKeepAlivePeriod: c.Xmux.HKeepAlivePeriod,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ import (
|
|||||||
// has no fields because everything is global state :O)
|
// has no fields because everything is global state :O)
|
||||||
type BrowserDialerClient struct{}
|
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) {
|
func (c *BrowserDialerClient) Open(ctx context.Context, pureURL string) (io.WriteCloser, io.ReadCloser) {
|
||||||
panic("not implemented yet")
|
panic("not implemented yet")
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ import (
|
|||||||
|
|
||||||
// interface to abstract between use of browser dialer, vs net/http
|
// interface to abstract between use of browser dialer, vs net/http
|
||||||
type DialerClient interface {
|
type DialerClient interface {
|
||||||
|
IsClosed() bool
|
||||||
|
|
||||||
// (ctx, baseURL, payload) -> err
|
// (ctx, baseURL, payload) -> err
|
||||||
// baseURL already contains sessionId and seq
|
// baseURL already contains sessionId and seq
|
||||||
SendUploadRequest(context.Context, string, io.ReadWriteCloser, int64) error
|
SendUploadRequest(context.Context, string, io.ReadWriteCloser, int64) error
|
||||||
@ -39,12 +41,17 @@ type DialerClient interface {
|
|||||||
type DefaultDialerClient struct {
|
type DefaultDialerClient struct {
|
||||||
transportConfig *Config
|
transportConfig *Config
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
closed bool
|
||||||
httpVersion string
|
httpVersion string
|
||||||
// pool of net.Conn, created using dialUploadConn
|
// pool of net.Conn, created using dialUploadConn
|
||||||
uploadRawPool *sync.Pool
|
uploadRawPool *sync.Pool
|
||||||
dialUploadConn func(ctxInner context.Context) (net.Conn, error)
|
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) {
|
func (c *DefaultDialerClient) Open(ctx context.Context, pureURL string) (io.WriteCloser, io.ReadCloser) {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
req, _ := http.NewRequestWithContext(ctx, "POST", pureURL, reader)
|
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 {
|
if err != nil {
|
||||||
errors.LogInfoInner(ctx, err, "failed to open ", pureURL)
|
errors.LogInfoInner(ctx, err, "failed to open ", pureURL)
|
||||||
} else {
|
} else {
|
||||||
|
// c.closed = true
|
||||||
|
response.Body.Close()
|
||||||
errors.LogInfo(ctx, "unexpected status ", response.StatusCode)
|
errors.LogInfo(ctx, "unexpected status ", response.StatusCode)
|
||||||
}
|
}
|
||||||
wrc.Close()
|
wrc.Close()
|
||||||
@ -76,7 +85,14 @@ func (c *DefaultDialerClient) OpenUpload(ctx context.Context, baseURL string) io
|
|||||||
if !c.transportConfig.NoGRPCHeader {
|
if !c.transportConfig.NoGRPCHeader {
|
||||||
req.Header.Set("Content-Type", "application/grpc")
|
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
|
return writer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +146,7 @@ func (c *DefaultDialerClient) OpenDownload(ctx context.Context, baseURL string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if response.StatusCode != 200 {
|
if response.StatusCode != 200 {
|
||||||
|
// c.closed = true
|
||||||
response.Body.Close()
|
response.Body.Close()
|
||||||
errors.LogInfo(ctx, "invalid status code on download:", response.Status)
|
errors.LogInfo(ctx, "invalid status code on download:", response.Status)
|
||||||
gotDownResponse.Close()
|
gotDownResponse.Close()
|
||||||
@ -180,6 +197,7 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string,
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
|
// c.closed = true
|
||||||
return errors.New("bad status code:", resp.Status)
|
return errors.New("bad status code:", resp.Status)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -214,6 +232,8 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string,
|
|||||||
return fmt.Errorf("error while reading response: %s", err.Error())
|
return fmt.Errorf("error while reading response: %s", err.Error())
|
||||||
}
|
}
|
||||||
if resp.StatusCode != 200 {
|
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)
|
return fmt.Errorf("got non-200 error response code: %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func (c *Config) GetNormalizedQuery() string {
|
|||||||
query += "&"
|
query += "&"
|
||||||
}
|
}
|
||||||
|
|
||||||
paddingLen := c.GetNormalizedXPaddingBytes().roll()
|
paddingLen := c.GetNormalizedXPaddingBytes().rand()
|
||||||
if paddingLen > 0 {
|
if paddingLen > 0 {
|
||||||
query += "x_padding=" + strings.Repeat("0", int(paddingLen))
|
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
|
// CORS headers for the browser dialer
|
||||||
writer.Header().Set("Access-Control-Allow-Origin", "*")
|
writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
writer.Header().Set("Access-Control-Allow-Methods", "GET, POST")
|
writer.Header().Set("Access-Control-Allow-Methods", "GET, POST")
|
||||||
paddingLen := c.GetNormalizedXPaddingBytes().roll()
|
paddingLen := c.GetNormalizedXPaddingBytes().rand()
|
||||||
if paddingLen > 0 {
|
if paddingLen > 0 {
|
||||||
writer.Header().Set("X-Padding", strings.Repeat("0", int(paddingLen)))
|
writer.Header().Set("X-Padding", strings.Repeat("0", int(paddingLen)))
|
||||||
}
|
}
|
||||||
@ -72,9 +72,9 @@ func (c *Config) GetNormalizedScMaxBufferedPosts() int {
|
|||||||
return int(c.ScMaxBufferedPosts)
|
return int(c.ScMaxBufferedPosts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetNormalizedScMaxEachPostBytes() RandRangeConfig {
|
func (c *Config) GetNormalizedScMaxEachPostBytes() RangeConfig {
|
||||||
if c.ScMaxEachPostBytes == nil || c.ScMaxEachPostBytes.To == 0 {
|
if c.ScMaxEachPostBytes == nil || c.ScMaxEachPostBytes.To == 0 {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 1000000,
|
From: 1000000,
|
||||||
To: 1000000,
|
To: 1000000,
|
||||||
}
|
}
|
||||||
@ -83,9 +83,9 @@ func (c *Config) GetNormalizedScMaxEachPostBytes() RandRangeConfig {
|
|||||||
return *c.ScMaxEachPostBytes
|
return *c.ScMaxEachPostBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetNormalizedScMinPostsIntervalMs() RandRangeConfig {
|
func (c *Config) GetNormalizedScMinPostsIntervalMs() RangeConfig {
|
||||||
if c.ScMinPostsIntervalMs == nil || c.ScMinPostsIntervalMs.To == 0 {
|
if c.ScMinPostsIntervalMs == nil || c.ScMinPostsIntervalMs.To == 0 {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 30,
|
From: 30,
|
||||||
To: 30,
|
To: 30,
|
||||||
}
|
}
|
||||||
@ -94,9 +94,9 @@ func (c *Config) GetNormalizedScMinPostsIntervalMs() RandRangeConfig {
|
|||||||
return *c.ScMinPostsIntervalMs
|
return *c.ScMinPostsIntervalMs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetNormalizedXPaddingBytes() RandRangeConfig {
|
func (c *Config) GetNormalizedXPaddingBytes() RangeConfig {
|
||||||
if c.XPaddingBytes == nil || c.XPaddingBytes.To == 0 {
|
if c.XPaddingBytes == nil || c.XPaddingBytes.To == 0 {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 100,
|
From: 100,
|
||||||
To: 1000,
|
To: 1000,
|
||||||
}
|
}
|
||||||
@ -105,9 +105,20 @@ func (c *Config) GetNormalizedXPaddingBytes() RandRangeConfig {
|
|||||||
return *c.XPaddingBytes
|
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 {
|
if m.CMaxReuseTimes == nil {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 0,
|
To: 0,
|
||||||
}
|
}
|
||||||
@ -116,9 +127,9 @@ func (m *Multiplexing) GetNormalizedCMaxReuseTimes() RandRangeConfig {
|
|||||||
return *m.CMaxReuseTimes
|
return *m.CMaxReuseTimes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Multiplexing) GetNormalizedCMaxLifetimeMs() RandRangeConfig {
|
func (m *XmuxConfig) GetNormalizedCMaxLifetimeMs() RangeConfig {
|
||||||
if m.CMaxLifetimeMs == nil || m.CMaxLifetimeMs.To == 0 {
|
if m.CMaxLifetimeMs == nil {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 0,
|
To: 0,
|
||||||
}
|
}
|
||||||
@ -126,9 +137,9 @@ func (m *Multiplexing) GetNormalizedCMaxLifetimeMs() RandRangeConfig {
|
|||||||
return *m.CMaxLifetimeMs
|
return *m.CMaxLifetimeMs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Multiplexing) GetNormalizedMaxConnections() RandRangeConfig {
|
func (m *XmuxConfig) GetNormalizedMaxConnections() RangeConfig {
|
||||||
if m.MaxConnections == nil {
|
if m.MaxConnections == nil {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 0,
|
To: 0,
|
||||||
}
|
}
|
||||||
@ -137,9 +148,9 @@ func (m *Multiplexing) GetNormalizedMaxConnections() RandRangeConfig {
|
|||||||
return *m.MaxConnections
|
return *m.MaxConnections
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Multiplexing) GetNormalizedMaxConcurrency() RandRangeConfig {
|
func (m *XmuxConfig) GetNormalizedMaxConcurrency() RangeConfig {
|
||||||
if m.MaxConcurrency == nil {
|
if m.MaxConcurrency == nil {
|
||||||
return RandRangeConfig{
|
return RangeConfig{
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 0,
|
To: 0,
|
||||||
}
|
}
|
||||||
@ -154,7 +165,7 @@ func init() {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c RandRangeConfig) roll() int32 {
|
func (c RangeConfig) rand() int32 {
|
||||||
if c.From == c.To {
|
if c.From == c.To {
|
||||||
return c.From
|
return c.From
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,144 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = 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 {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -30,20 +168,19 @@ type Config struct {
|
|||||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||||
Mode string `protobuf:"bytes,3,opt,name=mode,proto3" json:"mode,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"`
|
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"`
|
NoGRPCHeader bool `protobuf:"varint,6,opt,name=noGRPCHeader,proto3" json:"noGRPCHeader,omitempty"`
|
||||||
NoSSEHeader bool `protobuf:"varint,7,opt,name=noSSEHeader,proto3" json:"noSSEHeader,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"`
|
ScMaxEachPostBytes *RangeConfig `protobuf:"bytes,8,opt,name=scMaxEachPostBytes,proto3" json:"scMaxEachPostBytes,omitempty"`
|
||||||
ScMinPostsIntervalMs *RandRangeConfig `protobuf:"bytes,9,opt,name=scMinPostsIntervalMs,proto3" json:"scMinPostsIntervalMs,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"`
|
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 *XmuxConfig `protobuf:"bytes,11,opt,name=xmux,proto3" json:"xmux,omitempty"`
|
||||||
Xmux *Multiplexing `protobuf:"bytes,12,opt,name=xmux,proto3" json:"xmux,omitempty"`
|
DownloadSettings *internet.StreamConfig `protobuf:"bytes,12,opt,name=downloadSettings,proto3" json:"downloadSettings,omitempty"`
|
||||||
DownloadSettings *internet.StreamConfig `protobuf:"bytes,13,opt,name=downloadSettings,proto3" json:"downloadSettings,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
*x = Config{}
|
*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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -55,7 +192,7 @@ func (x *Config) String() string {
|
|||||||
func (*Config) ProtoMessage() {}
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
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 {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -68,7 +205,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
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 {
|
func (x *Config) GetHost() string {
|
||||||
@ -99,7 +236,7 @@ func (x *Config) GetHeaders() map[string]string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetXPaddingBytes() *RandRangeConfig {
|
func (x *Config) GetXPaddingBytes() *RangeConfig {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.XPaddingBytes
|
return x.XPaddingBytes
|
||||||
}
|
}
|
||||||
@ -120,14 +257,14 @@ func (x *Config) GetNoSSEHeader() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetScMaxEachPostBytes() *RandRangeConfig {
|
func (x *Config) GetScMaxEachPostBytes() *RangeConfig {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ScMaxEachPostBytes
|
return x.ScMaxEachPostBytes
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetScMinPostsIntervalMs() *RandRangeConfig {
|
func (x *Config) GetScMinPostsIntervalMs() *RangeConfig {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ScMinPostsIntervalMs
|
return x.ScMinPostsIntervalMs
|
||||||
}
|
}
|
||||||
@ -141,14 +278,7 @@ func (x *Config) GetScMaxBufferedPosts() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetKeepAlivePeriod() int64 {
|
func (x *Config) GetXmux() *XmuxConfig {
|
||||||
if x != nil {
|
|
||||||
return x.KeepAlivePeriod
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetXmux() *Multiplexing {
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Xmux
|
return x.Xmux
|
||||||
}
|
}
|
||||||
@ -162,128 +292,6 @@ func (x *Config) GetDownloadSettings() *internet.StreamConfig {
|
|||||||
return nil
|
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 protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_splithttp_config_proto_rawDesc = []byte{
|
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,
|
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,
|
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,
|
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,
|
0x31, 0x0a, 0x0b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12,
|
||||||
0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12,
|
0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x66, 0x72,
|
||||||
0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61,
|
0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02,
|
||||||
0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
0x74, 0x6f, 0x22, 0xf4, 0x03, 0x0a, 0x0a, 0x58, 0x6d, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x50, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
|
0x67, 0x12, 0x56, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65,
|
||||||
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66,
|
0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61,
|
||||||
0x69, 0x67, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f,
|
||||||
0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0d, 0x78, 0x50, 0x61, 0x64,
|
0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x56, 0x0a, 0x0e, 0x6d, 0x61, 0x78,
|
||||||
0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x32, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68,
|
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69,
|
||||||
0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e,
|
0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x66, 0x69, 0x67, 0x52, 0x0d, 0x78, 0x50, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74,
|
0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x47, 0x52, 0x50, 0x43, 0x48, 0x65, 0x61, 0x64,
|
0x73, 0x12, 0x56, 0x0a, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x75, 0x73, 0x65, 0x54, 0x69,
|
||||||
0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x47, 0x52, 0x50, 0x43,
|
0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x53, 0x53, 0x45, 0x48,
|
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x53,
|
0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61,
|
||||||
0x53, 0x45, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x62, 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61,
|
0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x52,
|
||||||
0x78, 0x45, 0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08,
|
0x65, 0x75, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x0e, 0x63, 0x4d, 0x61,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73,
|
0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||||
0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e,
|
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69,
|
||||||
0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x45,
|
0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x66, 0x0a, 0x14,
|
0x67, 0x52, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d,
|
||||||
0x73, 0x63, 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76,
|
0x73, 0x12, 0x5a, 0x0a, 0x10, 0x68, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x61, 0x6c, 0x4d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x72, 0x61,
|
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,
|
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,
|
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,
|
0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x73, 0x63, 0x4d, 0x61,
|
||||||
0x73, 0x63, 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76,
|
0x78, 0x45, 0x61, 0x63, 0x68, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x62,
|
||||||
0x61, 0x6c, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66,
|
0x0a, 0x14, 0x73, 0x63, 0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65,
|
||||||
0x66, 0x65, 0x72, 0x65, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03,
|
0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78,
|
||||||
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,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
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,
|
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,
|
0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x73, 0x63,
|
||||||
0x6d, 0x75, 0x78, 0x12, 0x51, 0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53,
|
0x4d, 0x69, 0x6e, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
|
0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
0x72, 0x65, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12,
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f,
|
0x73, 0x63, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x50, 0x6f, 0x73,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65,
|
0x74, 0x73, 0x12, 0x41, 0x0a, 0x04, 0x78, 0x6d, 0x75, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
|
0x32, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 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,
|
|
||||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74,
|
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,
|
0x68, 0x74, 0x74, 0x70, 0x2e, 0x58, 0x6d, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
|
||||||
0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72,
|
0x04, 0x78, 0x6d, 0x75, 0x78, 0x12, 0x51, 0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
|
||||||
0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02,
|
0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x21, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e,
|
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||||
0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x74,
|
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
|
||||||
0x74, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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 (
|
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_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||||
var file_transport_internet_splithttp_config_proto_goTypes = []any{
|
var file_transport_internet_splithttp_config_proto_goTypes = []any{
|
||||||
(*Config)(nil), // 0: xray.transport.internet.splithttp.Config
|
(*RangeConfig)(nil), // 0: xray.transport.internet.splithttp.RangeConfig
|
||||||
(*RandRangeConfig)(nil), // 1: xray.transport.internet.splithttp.RandRangeConfig
|
(*XmuxConfig)(nil), // 1: xray.transport.internet.splithttp.XmuxConfig
|
||||||
(*Multiplexing)(nil), // 2: xray.transport.internet.splithttp.Multiplexing
|
(*Config)(nil), // 2: xray.transport.internet.splithttp.Config
|
||||||
nil, // 3: xray.transport.internet.splithttp.Config.HeadersEntry
|
nil, // 3: xray.transport.internet.splithttp.Config.HeadersEntry
|
||||||
(*internet.StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig
|
(*internet.StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig
|
||||||
}
|
}
|
||||||
var file_transport_internet_splithttp_config_proto_depIdxs = []int32{
|
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
|
0, // 0: xray.transport.internet.splithttp.XmuxConfig.maxConcurrency:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
1, // 1: xray.transport.internet.splithttp.Config.xPaddingBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
0, // 1: xray.transport.internet.splithttp.XmuxConfig.maxConnections:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
1, // 2: xray.transport.internet.splithttp.Config.scMaxEachPostBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
0, // 2: xray.transport.internet.splithttp.XmuxConfig.cMaxReuseTimes:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
1, // 3: xray.transport.internet.splithttp.Config.scMinPostsIntervalMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
0, // 3: xray.transport.internet.splithttp.XmuxConfig.cMaxLifetimeMs:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
2, // 4: xray.transport.internet.splithttp.Config.xmux:type_name -> xray.transport.internet.splithttp.Multiplexing
|
0, // 4: xray.transport.internet.splithttp.XmuxConfig.hMaxRequestTimes:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
4, // 5: xray.transport.internet.splithttp.Config.downloadSettings:type_name -> xray.transport.internet.StreamConfig
|
3, // 5: xray.transport.internet.splithttp.Config.headers:type_name -> xray.transport.internet.splithttp.Config.HeadersEntry
|
||||||
1, // 6: xray.transport.internet.splithttp.Multiplexing.maxConcurrency:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
0, // 6: xray.transport.internet.splithttp.Config.xPaddingBytes:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
1, // 7: xray.transport.internet.splithttp.Multiplexing.maxConnections:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
0, // 7: xray.transport.internet.splithttp.Config.scMaxEachPostBytes:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
1, // 8: xray.transport.internet.splithttp.Multiplexing.cMaxReuseTimes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
0, // 8: xray.transport.internet.splithttp.Config.scMinPostsIntervalMs:type_name -> xray.transport.internet.splithttp.RangeConfig
|
||||||
1, // 9: xray.transport.internet.splithttp.Multiplexing.cMaxLifetimeMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
1, // 9: xray.transport.internet.splithttp.Config.xmux:type_name -> xray.transport.internet.splithttp.XmuxConfig
|
||||||
10, // [10:10] is the sub-list for method output_type
|
4, // 10: xray.transport.internet.splithttp.Config.downloadSettings:type_name -> xray.transport.internet.StreamConfig
|
||||||
10, // [10:10] is the sub-list for method input_type
|
11, // [11:11] is the sub-list for method output_type
|
||||||
10, // [10:10] is the sub-list for extension type_name
|
11, // [11:11] is the sub-list for method input_type
|
||||||
10, // [10:10] is the sub-list for extension extendee
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
0, // [0:10] is the sub-list for field 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() }
|
func init() { file_transport_internet_splithttp_config_proto_init() }
|
||||||
|
@ -8,30 +8,31 @@ option java_multiple_files = true;
|
|||||||
|
|
||||||
import "transport/internet/config.proto";
|
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 {
|
message Config {
|
||||||
string host = 1;
|
string host = 1;
|
||||||
string path = 2;
|
string path = 2;
|
||||||
string mode = 3;
|
string mode = 3;
|
||||||
map<string, string> headers = 4;
|
map<string, string> headers = 4;
|
||||||
RandRangeConfig xPaddingBytes = 5;
|
RangeConfig xPaddingBytes = 5;
|
||||||
bool noGRPCHeader = 6;
|
bool noGRPCHeader = 6;
|
||||||
bool noSSEHeader = 7;
|
bool noSSEHeader = 7;
|
||||||
RandRangeConfig scMaxEachPostBytes = 8;
|
RangeConfig scMaxEachPostBytes = 8;
|
||||||
RandRangeConfig scMinPostsIntervalMs = 9;
|
RangeConfig scMinPostsIntervalMs = 9;
|
||||||
int64 scMaxBufferedPosts = 10;
|
int64 scMaxBufferedPosts = 10;
|
||||||
int64 keepAlivePeriod = 11;
|
XmuxConfig xmux = 11;
|
||||||
Multiplexing xmux = 12;
|
xray.transport.internet.StreamConfig downloadSettings = 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;
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
"github.com/quic-go/quic-go"
|
||||||
@ -45,11 +46,11 @@ type dialerConf struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
globalDialerMap map[dialerConf]*muxManager
|
globalDialerMap map[dialerConf]*XmuxManager
|
||||||
globalDialerAccess sync.Mutex
|
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)
|
realityConfig := reality.ConfigFromStreamSettings(streamSettings)
|
||||||
|
|
||||||
if browser_dialer.HasBrowserDialer() && realityConfig != nil {
|
if browser_dialer.HasBrowserDialer() && realityConfig != nil {
|
||||||
@ -60,28 +61,28 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
defer globalDialerAccess.Unlock()
|
defer globalDialerAccess.Unlock()
|
||||||
|
|
||||||
if globalDialerMap == nil {
|
if globalDialerMap == nil {
|
||||||
globalDialerMap = make(map[dialerConf]*muxManager)
|
globalDialerMap = make(map[dialerConf]*XmuxManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
key := dialerConf{dest, streamSettings}
|
key := dialerConf{dest, streamSettings}
|
||||||
|
|
||||||
muxManager, found := globalDialerMap[key]
|
xmuxManager, found := globalDialerMap[key]
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
||||||
var mux Multiplexing
|
var xmuxConfig XmuxConfig
|
||||||
if transportConfig.Xmux != nil {
|
if transportConfig.Xmux != nil {
|
||||||
mux = *transportConfig.Xmux
|
xmuxConfig = *transportConfig.Xmux
|
||||||
}
|
}
|
||||||
|
|
||||||
muxManager = NewMuxManager(mux, func() interface{} {
|
xmuxManager = NewXmuxManager(xmuxConfig, func() XmuxConn {
|
||||||
return createHTTPClient(dest, streamSettings)
|
return createHTTPClient(dest, streamSettings)
|
||||||
})
|
})
|
||||||
globalDialerMap[key] = muxManager
|
globalDialerMap[key] = xmuxManager
|
||||||
}
|
}
|
||||||
|
|
||||||
res := muxManager.GetResource(ctx)
|
xmuxClient := xmuxManager.GetXmuxClient(ctx)
|
||||||
return res.Resource.(DialerClient), res
|
return xmuxClient.XmuxConn.(DialerClient), xmuxClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func decideHTTPVersion(tlsConfig *tls.Config, realityConfig *reality.Config) string {
|
func decideHTTPVersion(tlsConfig *tls.Config, realityConfig *reality.Config) string {
|
||||||
@ -144,7 +145,10 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
return conn, nil
|
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
|
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.Path = transportConfiguration.GetNormalizedPath() + sessionIdUuid.String()
|
||||||
requestURL.RawQuery = transportConfiguration.GetNormalizedQuery()
|
requestURL.RawQuery = transportConfiguration.GetNormalizedQuery()
|
||||||
|
|
||||||
httpClient, muxRes := getHTTPClient(ctx, dest, streamSettings)
|
httpClient, xmuxClient := getHTTPClient(ctx, dest, streamSettings)
|
||||||
|
|
||||||
mode := transportConfiguration.Mode
|
mode := transportConfiguration.Mode
|
||||||
if mode == "" || mode == "auto" {
|
if mode == "" || mode == "auto" {
|
||||||
@ -299,7 +303,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
|
|
||||||
requestURL2 := requestURL
|
requestURL2 := requestURL
|
||||||
httpClient2 := httpClient
|
httpClient2 := httpClient
|
||||||
var muxRes2 *muxResource
|
xmuxClient2 := xmuxClient
|
||||||
if transportConfiguration.DownloadSettings != nil {
|
if transportConfiguration.DownloadSettings != nil {
|
||||||
globalDialerAccess.Lock()
|
globalDialerAccess.Lock()
|
||||||
if streamSettings.DownloadSettings == nil {
|
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.Path = config2.GetNormalizedPath() + sessionIdUuid.String()
|
||||||
requestURL2.RawQuery = config2.GetNormalizedQuery()
|
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))
|
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" {
|
if mode == "stream-one" {
|
||||||
requestURL.Path = transportConfiguration.GetNormalizedPath()
|
requestURL.Path = transportConfiguration.GetNormalizedPath()
|
||||||
|
if xmuxClient != nil {
|
||||||
|
xmuxClient.LeftRequests.Add(-1)
|
||||||
|
}
|
||||||
writer, reader = httpClient.Open(context.WithoutCancel(ctx), requestURL.String())
|
writer, reader = httpClient.Open(context.WithoutCancel(ctx), requestURL.String())
|
||||||
remoteAddr = &net.TCPAddr{}
|
remoteAddr = &net.TCPAddr{}
|
||||||
localAddr = &net.TCPAddr{}
|
localAddr = &net.TCPAddr{}
|
||||||
} else {
|
} else {
|
||||||
|
if xmuxClient2 != nil {
|
||||||
|
xmuxClient2.LeftRequests.Add(-1)
|
||||||
|
}
|
||||||
reader, remoteAddr, localAddr, err = httpClient2.OpenDownload(context.WithoutCancel(ctx), requestURL2.String())
|
reader, remoteAddr, localAddr, err = httpClient2.OpenDownload(context.WithoutCancel(ctx), requestURL2.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if muxRes != nil {
|
if xmuxClient != nil {
|
||||||
muxRes.OpenRequests.Add(1)
|
xmuxClient.OpenUsage.Add(1)
|
||||||
}
|
}
|
||||||
if muxRes2 != nil {
|
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
|
||||||
muxRes2.OpenRequests.Add(1)
|
xmuxClient2.OpenUsage.Add(1)
|
||||||
}
|
}
|
||||||
closed := false
|
var once atomic.Int32
|
||||||
|
|
||||||
conn := splitConn{
|
conn := splitConn{
|
||||||
writer: writer,
|
writer: writer,
|
||||||
@ -367,23 +377,28 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
remoteAddr: remoteAddr,
|
remoteAddr: remoteAddr,
|
||||||
localAddr: localAddr,
|
localAddr: localAddr,
|
||||||
onClose: func() {
|
onClose: func() {
|
||||||
if closed {
|
if once.Add(-1) < 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
closed = true
|
if xmuxClient != nil {
|
||||||
if muxRes != nil {
|
xmuxClient.OpenUsage.Add(-1)
|
||||||
muxRes.OpenRequests.Add(-1)
|
|
||||||
}
|
}
|
||||||
if muxRes2 != nil {
|
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
|
||||||
muxRes2.OpenRequests.Add(-1)
|
xmuxClient2.OpenUsage.Add(-1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == "stream-one" {
|
if mode == "stream-one" {
|
||||||
|
if xmuxClient != nil {
|
||||||
|
xmuxClient.LeftRequests.Add(-1)
|
||||||
|
}
|
||||||
return stat.Connection(&conn), nil
|
return stat.Connection(&conn), nil
|
||||||
}
|
}
|
||||||
if mode == "stream-up" {
|
if mode == "stream-up" {
|
||||||
|
if xmuxClient != nil {
|
||||||
|
xmuxClient.LeftRequests.Add(-1)
|
||||||
|
}
|
||||||
conn.writer = httpClient.OpenUpload(ctx, requestURL.String())
|
conn.writer = httpClient.OpenUpload(ctx, requestURL.String())
|
||||||
return stat.Connection(&conn), nil
|
return stat.Connection(&conn), nil
|
||||||
}
|
}
|
||||||
@ -391,7 +406,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
scMaxEachPostBytes := transportConfiguration.GetNormalizedScMaxEachPostBytes()
|
scMaxEachPostBytes := transportConfiguration.GetNormalizedScMaxEachPostBytes()
|
||||||
scMinPostsIntervalMs := transportConfiguration.GetNormalizedScMinPostsIntervalMs()
|
scMinPostsIntervalMs := transportConfiguration.GetNormalizedScMinPostsIntervalMs()
|
||||||
|
|
||||||
maxUploadSize := scMaxEachPostBytes.roll()
|
maxUploadSize := scMaxEachPostBytes.rand()
|
||||||
// WithSizeLimit(0) will still allow single bytes to pass, and a lot of
|
// WithSizeLimit(0) will still allow single bytes to pass, and a lot of
|
||||||
// code relies on this behavior. Subtract 1 so that together with
|
// code relies on this behavior. Subtract 1 so that together with
|
||||||
// uploadWriter wrapper, exact size limits can be enforced
|
// 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
|
seq += 1
|
||||||
|
|
||||||
if scMinPostsIntervalMs.From > 0 {
|
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
|
// 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()
|
lastWrite = time.Now()
|
||||||
|
|
||||||
|
if xmuxClient != nil && xmuxClient.LeftRequests.Add(-1) <= 0 {
|
||||||
|
httpClient, xmuxClient = getHTTPClient(ctx, dest, streamSettings)
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := httpClient.SendUploadRequest(
|
err := httpClient.SendUploadRequest(
|
||||||
context.WithoutCancel(ctx),
|
context.WithoutCancel(ctx),
|
||||||
|
@ -2,101 +2,113 @@ package splithttp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/rand"
|
"crypto/rand"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type muxResource struct {
|
type XmuxConn interface {
|
||||||
Resource interface{}
|
IsClosed() bool
|
||||||
OpenRequests atomic.Int32
|
}
|
||||||
|
|
||||||
|
type XmuxClient struct {
|
||||||
|
XmuxConn XmuxConn
|
||||||
|
OpenUsage atomic.Int32
|
||||||
leftUsage int32
|
leftUsage int32
|
||||||
expirationTime time.Time
|
expirationTime time.Time
|
||||||
|
LeftRequests atomic.Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
type muxManager struct {
|
type XmuxManager struct {
|
||||||
newResourceFn func() interface{}
|
xmuxConfig XmuxConfig
|
||||||
config Multiplexing
|
concurrency int32
|
||||||
concurrency int32
|
connections int32
|
||||||
connections int32
|
newConnFunc func() XmuxConn
|
||||||
instances []*muxResource
|
xmuxClients []*XmuxClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMuxManager(config Multiplexing, newResource func() interface{}) *muxManager {
|
func NewXmuxManager(xmuxConfig XmuxConfig, newConnFunc func() XmuxConn) *XmuxManager {
|
||||||
return &muxManager{
|
return &XmuxManager{
|
||||||
config: config,
|
xmuxConfig: xmuxConfig,
|
||||||
concurrency: config.GetNormalizedMaxConcurrency().roll(),
|
concurrency: xmuxConfig.GetNormalizedMaxConcurrency().rand(),
|
||||||
connections: config.GetNormalizedMaxConnections().roll(),
|
connections: xmuxConfig.GetNormalizedMaxConnections().rand(),
|
||||||
newResourceFn: newResource,
|
newConnFunc: newConnFunc,
|
||||||
instances: make([]*muxResource, 0),
|
xmuxClients: make([]*XmuxClient, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *muxManager) GetResource(ctx context.Context) *muxResource {
|
func (m *XmuxManager) newXmuxClient() *XmuxClient {
|
||||||
m.removeExpiredConnections(ctx)
|
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) {
|
func (m *XmuxManager) GetXmuxClient(ctx context.Context) *XmuxClient { // when locking
|
||||||
errors.LogDebug(ctx, "xmux: creating client, connections=", len(m.instances))
|
for i := 0; i < len(m.xmuxClients); {
|
||||||
return m.newResource()
|
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 {
|
if len(m.xmuxClients) == 0 {
|
||||||
errors.LogDebug(ctx, "xmux: creating client because instances is empty, connections=", len(m.instances))
|
errors.LogDebug(ctx, "XMUX: creating xmuxClient because xmuxClients is empty")
|
||||||
return m.newResource()
|
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 {
|
if m.concurrency > 0 {
|
||||||
for _, client := range m.instances {
|
for _, xmuxClient := range m.xmuxClients {
|
||||||
openRequests := client.OpenRequests.Load()
|
if xmuxClient.OpenUsage.Load() < m.concurrency {
|
||||||
if openRequests < m.concurrency {
|
xmuxClients = append(xmuxClients, xmuxClient)
|
||||||
clients = append(clients, client)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clients = m.instances
|
xmuxClients = m.xmuxClients
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) == 0 {
|
if len(xmuxClients) == 0 {
|
||||||
errors.LogDebug(ctx, "xmux: creating client because concurrency was hit, total clients=", len(m.instances))
|
errors.LogDebug(ctx, "XMUX: creating xmuxClient because maxConcurrency was hit, xmuxClients = ", len(m.xmuxClients))
|
||||||
return m.newResource()
|
return m.newXmuxClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
client := clients[rand.Intn(len(clients))]
|
i, _ := rand.Int(rand.Reader, big.NewInt(int64(len(xmuxClients))))
|
||||||
if client.leftUsage > 0 {
|
xmuxClient := xmuxClients[i.Int64()]
|
||||||
client.leftUsage -= 1
|
if xmuxClient.leftUsage > 0 {
|
||||||
}
|
xmuxClient.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--
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return xmuxClient
|
||||||
}
|
}
|
||||||
|
@ -9,80 +9,84 @@ import (
|
|||||||
|
|
||||||
type fakeRoundTripper struct{}
|
type fakeRoundTripper struct{}
|
||||||
|
|
||||||
|
func (f *fakeRoundTripper) IsClosed() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func TestMaxConnections(t *testing.T) {
|
func TestMaxConnections(t *testing.T) {
|
||||||
config := Multiplexing{
|
xmuxConfig := XmuxConfig{
|
||||||
MaxConnections: &RandRangeConfig{From: 4, To: 4},
|
MaxConnections: &RangeConfig{From: 4, To: 4},
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := NewMuxManager(config, func() interface{} {
|
xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn {
|
||||||
return &fakeRoundTripper{}
|
return &fakeRoundTripper{}
|
||||||
})
|
})
|
||||||
|
|
||||||
clients := make(map[interface{}]struct{})
|
xmuxClients := make(map[interface{}]struct{})
|
||||||
for i := 0; i < 8; i++ {
|
for i := 0; i < 8; i++ {
|
||||||
clients[mux.GetResource(context.Background())] = struct{}{}
|
xmuxClients[xmuxManager.GetXmuxClient(context.Background())] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) != 4 {
|
if len(xmuxClients) != 4 {
|
||||||
t.Error("did not get 4 distinct clients, got ", len(clients))
|
t.Error("did not get 4 distinct clients, got ", len(xmuxClients))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCMaxReuseTimes(t *testing.T) {
|
func TestCMaxReuseTimes(t *testing.T) {
|
||||||
config := Multiplexing{
|
xmuxConfig := XmuxConfig{
|
||||||
CMaxReuseTimes: &RandRangeConfig{From: 2, To: 2},
|
CMaxReuseTimes: &RangeConfig{From: 2, To: 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := NewMuxManager(config, func() interface{} {
|
xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn {
|
||||||
return &fakeRoundTripper{}
|
return &fakeRoundTripper{}
|
||||||
})
|
})
|
||||||
|
|
||||||
clients := make(map[interface{}]struct{})
|
xmuxClients := make(map[interface{}]struct{})
|
||||||
for i := 0; i < 64; i++ {
|
for i := 0; i < 64; i++ {
|
||||||
clients[mux.GetResource(context.Background())] = struct{}{}
|
xmuxClients[xmuxManager.GetXmuxClient(context.Background())] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) != 32 {
|
if len(xmuxClients) != 32 {
|
||||||
t.Error("did not get 32 distinct clients, got ", len(clients))
|
t.Error("did not get 32 distinct clients, got ", len(xmuxClients))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxConcurrency(t *testing.T) {
|
func TestMaxConcurrency(t *testing.T) {
|
||||||
config := Multiplexing{
|
xmuxConfig := XmuxConfig{
|
||||||
MaxConcurrency: &RandRangeConfig{From: 2, To: 2},
|
MaxConcurrency: &RangeConfig{From: 2, To: 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := NewMuxManager(config, func() interface{} {
|
xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn {
|
||||||
return &fakeRoundTripper{}
|
return &fakeRoundTripper{}
|
||||||
})
|
})
|
||||||
|
|
||||||
clients := make(map[interface{}]struct{})
|
xmuxClients := make(map[interface{}]struct{})
|
||||||
for i := 0; i < 64; i++ {
|
for i := 0; i < 64; i++ {
|
||||||
client := mux.GetResource(context.Background())
|
xmuxClient := xmuxManager.GetXmuxClient(context.Background())
|
||||||
client.OpenRequests.Add(1)
|
xmuxClient.OpenUsage.Add(1)
|
||||||
clients[client] = struct{}{}
|
xmuxClients[xmuxClient] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) != 32 {
|
if len(xmuxClients) != 32 {
|
||||||
t.Error("did not get 32 distinct clients, got ", len(clients))
|
t.Error("did not get 32 distinct clients, got ", len(xmuxClients))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefault(t *testing.T) {
|
func TestDefault(t *testing.T) {
|
||||||
config := Multiplexing{}
|
xmuxConfig := XmuxConfig{}
|
||||||
|
|
||||||
mux := NewMuxManager(config, func() interface{} {
|
xmuxManager := NewXmuxManager(xmuxConfig, func() XmuxConn {
|
||||||
return &fakeRoundTripper{}
|
return &fakeRoundTripper{}
|
||||||
})
|
})
|
||||||
|
|
||||||
clients := make(map[interface{}]struct{})
|
xmuxClients := make(map[interface{}]struct{})
|
||||||
for i := 0; i < 64; i++ {
|
for i := 0; i < 64; i++ {
|
||||||
client := mux.GetResource(context.Background())
|
xmuxClient := xmuxManager.GetXmuxClient(context.Background())
|
||||||
client.OpenRequests.Add(1)
|
xmuxClient.OpenUsage.Add(1)
|
||||||
clients[client] = struct{}{}
|
xmuxClients[xmuxClient] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) != 1 {
|
if len(xmuxClients) != 1 {
|
||||||
t.Error("did not get 1 distinct clients, got ", len(clients))
|
t.Error("did not get 1 distinct clients, got ", len(xmuxClients))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ func Test_maxUpload(t *testing.T) {
|
|||||||
ProtocolName: "splithttp",
|
ProtocolName: "splithttp",
|
||||||
ProtocolSettings: &Config{
|
ProtocolSettings: &Config{
|
||||||
Path: "/sh",
|
Path: "/sh",
|
||||||
ScMaxEachPostBytes: &RandRangeConfig{
|
ScMaxEachPostBytes: &RangeConfig{
|
||||||
From: 10000,
|
From: 10000,
|
||||||
To: 10000,
|
To: 10000,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user