Skip to content

Commit b1c6471

Browse files
SplitHTTP client: Add xmux (multiplex controller) for H3 & H2 (#3613)
#3613 (comment) Closes #3560 (comment) --------- Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
1 parent a931507 commit b1c6471

9 files changed

Lines changed: 475 additions & 64 deletions

File tree

infra/conf/transport_internet.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,14 @@ type SplitHTTPConfig struct {
231231
ScMinPostsIntervalMs *Int32Range `json:"scMinPostsIntervalMs"`
232232
NoSSEHeader bool `json:"noSSEHeader"`
233233
XPaddingBytes *Int32Range `json:"xPaddingBytes"`
234+
Xmux Xmux `json:"xmux"`
235+
}
236+
237+
type Xmux struct {
238+
maxConnections *Int32Range `json:"maxConnections"`
239+
maxConcurrency *Int32Range `json:"maxConcurrency"`
240+
cMaxReuseTimes *Int32Range `json:"cMaxReuseTimes"`
241+
cMaxLifetimeMs *Int32Range `json:"cMaxLifetimeMs"`
234242
}
235243

236244
func splithttpNewRandRangeConfig(input *Int32Range) *splithttp.RandRangeConfig {
@@ -254,6 +262,19 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
254262
} else if c.Host == "" && c.Headers["Host"] != "" {
255263
c.Host = c.Headers["Host"]
256264
}
265+
266+
if c.Xmux.maxConnections != nil && c.Xmux.maxConcurrency != nil {
267+
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
268+
}
269+
270+
// Multiplexing config
271+
muxProtobuf := splithttp.Multiplexing{
272+
MaxConnections: splithttpNewRandRangeConfig(c.Xmux.maxConnections),
273+
MaxConcurrency: splithttpNewRandRangeConfig(c.Xmux.maxConcurrency),
274+
CMaxReuseTimes: splithttpNewRandRangeConfig(c.Xmux.cMaxReuseTimes),
275+
CMaxLifetimeMs: splithttpNewRandRangeConfig(c.Xmux.cMaxLifetimeMs),
276+
}
277+
257278
config := &splithttp.Config{
258279
Path: c.Path,
259280
Host: c.Host,
@@ -263,6 +284,7 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
263284
ScMinPostsIntervalMs: splithttpNewRandRangeConfig(c.ScMinPostsIntervalMs),
264285
NoSSEHeader: c.NoSSEHeader,
265286
XPaddingBytes: splithttpNewRandRangeConfig(c.XPaddingBytes),
287+
Xmux: &muxProtobuf,
266288
}
267289
return config, nil
268290
}

transport/internet/splithttp/client.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ type DialerClient interface {
3030
// implements splithttp.DialerClient in terms of direct network connections
3131
type DefaultDialerClient struct {
3232
transportConfig *Config
33-
download *http.Client
34-
upload *http.Client
33+
client *http.Client
3534
isH2 bool
3635
isH3 bool
3736
// pool of net.Conn, created using dialUploadConn
@@ -80,7 +79,7 @@ func (c *DefaultDialerClient) OpenDownload(ctx context.Context, baseURL string)
8079

8180
req.Header = c.transportConfig.GetRequestHeader()
8281

83-
response, err := c.download.Do(req)
82+
response, err := c.client.Do(req)
8483
gotConn.Close()
8584
if err != nil {
8685
errors.LogInfoInner(ctx, err, "failed to send download http request")
@@ -138,7 +137,7 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string,
138137
req.Header = c.transportConfig.GetRequestHeader()
139138

140139
if c.isH2 || c.isH3 {
141-
resp, err := c.upload.Do(req)
140+
resp, err := c.client.Do(req)
142141
if err != nil {
143142
return err
144143
}

transport/internet/splithttp/config.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,49 @@ func (c *Config) GetNormalizedXPaddingBytes() RandRangeConfig {
105105
return *c.XPaddingBytes
106106
}
107107

108+
func (m *Multiplexing) GetNormalizedCMaxReuseTimes() RandRangeConfig {
109+
if m.CMaxReuseTimes == nil {
110+
return RandRangeConfig{
111+
From: 0,
112+
To: 0,
113+
}
114+
}
115+
116+
return *m.CMaxReuseTimes
117+
}
118+
119+
func (m *Multiplexing) GetNormalizedCMaxLifetimeMs() RandRangeConfig {
120+
if m.CMaxLifetimeMs == nil || m.CMaxLifetimeMs.To == 0 {
121+
return RandRangeConfig{
122+
From: 0,
123+
To: 0,
124+
}
125+
}
126+
return *m.CMaxLifetimeMs
127+
}
128+
129+
func (m *Multiplexing) GetNormalizedMaxConnections() RandRangeConfig {
130+
if m.MaxConnections == nil {
131+
return RandRangeConfig{
132+
From: 0,
133+
To: 0,
134+
}
135+
}
136+
137+
return *m.MaxConnections
138+
}
139+
140+
func (m *Multiplexing) GetNormalizedMaxConcurrency() RandRangeConfig {
141+
if m.MaxConcurrency == nil {
142+
return RandRangeConfig{
143+
From: 0,
144+
To: 0,
145+
}
146+
}
147+
148+
return *m.MaxConcurrency
149+
}
150+
108151
func init() {
109152
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
110153
return new(Config)

transport/internet/splithttp/config.pb.go

Lines changed: 156 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

transport/internet/splithttp/config.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ message Config {
1515
RandRangeConfig scMinPostsIntervalMs = 6;
1616
bool noSSEHeader = 7;
1717
RandRangeConfig xPaddingBytes = 8;
18+
Multiplexing xmux = 9;
1819
}
1920

2021
message RandRangeConfig {
2122
int32 from = 1;
2223
int32 to = 2;
2324
}
25+
26+
message Multiplexing {
27+
RandRangeConfig maxConnections = 1;
28+
RandRangeConfig maxConcurrency = 2;
29+
RandRangeConfig cMaxReuseTimes = 3;
30+
RandRangeConfig cMaxLifetimeMs = 4;
31+
}

0 commit comments

Comments
 (0)