Skip to content

Commit e522d0d

Browse files
authored
Hysteria transport: Add congestion config (""/"reno"/"bbr"/"brutal"/"force-brutal") (XTLS#5549)
Closes XTLS#5546
1 parent e245262 commit e522d0d

7 files changed

Lines changed: 112 additions & 51 deletions

File tree

infra/conf/transport_internet.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,12 @@ type UdpHop struct {
391391
}
392392

393393
type HysteriaConfig struct {
394-
Version int32 `json:"version"`
395-
Auth string `json:"auth"`
396-
Up Bandwidth `json:"up"`
397-
Down Bandwidth `json:"down"`
398-
UdpHop UdpHop `json:"udphop"`
394+
Version int32 `json:"version"`
395+
Auth string `json:"auth"`
396+
Congestion string `json:"congestion"`
397+
Up Bandwidth `json:"up"`
398+
Down Bandwidth `json:"down"`
399+
UdpHop UdpHop `json:"udphop"`
399400

400401
InitStreamReceiveWindow uint64 `json:"initStreamReceiveWindow"`
401402
MaxStreamReceiveWindow uint64 `json:"maxStreamReceiveWindow"`
@@ -410,6 +411,7 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
410411
if c.Version != 2 {
411412
return nil, errors.New("version != 2")
412413
}
414+
413415
up, err := c.Up.Bps()
414416
if err != nil {
415417
return nil, err
@@ -418,6 +420,12 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
418420
if err != nil {
419421
return nil, err
420422
}
423+
424+
c.Congestion = strings.ToLower(c.Congestion)
425+
if c.Congestion == "force-brutal" && up == 0 {
426+
return nil, errors.New("force-brutal require up")
427+
}
428+
421429
var hop *PortList
422430
if err := json.Unmarshal(c.UdpHop.PortList, &hop); err != nil {
423431
hop = &PortList{}
@@ -455,6 +463,7 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
455463
config := &hysteria.Config{}
456464
config.Version = c.Version
457465
config.Auth = c.Auth
466+
config.Congestion = c.Congestion
458467
config.Up = up
459468
config.Down = down
460469
config.Ports = hop.Build().Ports()

proxy/hysteria/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/xtls/xray-core/common/task"
1818
"github.com/xtls/xray-core/core"
1919
"github.com/xtls/xray-core/features/policy"
20+
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
2021
"github.com/xtls/xray-core/transport"
2122
"github.com/xtls/xray-core/transport/internet"
2223
"github.com/xtls/xray-core/transport/internet/hysteria"
@@ -55,6 +56,9 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
5556
ob.CanSpliceCopy = 3
5657
target := ob.Target
5758

59+
if target.Network == net.Network_UDP {
60+
hyCtx.ContextWithRequireDatagram(ctx)
61+
}
5862
conn, err := dialer.Dial(ctx, c.server.Destination)
5963
if err != nil {
6064
return errors.New("failed to find an available destination").AtWarning().Base(err)

proxy/hysteria/ctx/ctx.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ctx
2+
3+
import (
4+
"context"
5+
)
6+
7+
type key int
8+
9+
const (
10+
requireDatagram key = iota
11+
)
12+
13+
func ContextWithRequireDatagram(ctx context.Context) context.Context {
14+
return context.WithValue(ctx, requireDatagram, struct{}{})
15+
}
16+
17+
func RequireDatagramFromContext(ctx context.Context) bool {
18+
_, ok := ctx.Value(requireDatagram).(struct{})
19+
return ok
20+
}

transport/internet/hysteria/config.pb.go

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

transport/internet/hysteria/config.proto

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ option java_multiple_files = true;
99
message Config {
1010
int32 version = 1;
1111
string auth = 2;
12-
uint64 up = 3;
13-
uint64 down = 4;
14-
repeated uint32 ports = 5;
15-
int64 interval = 6;
12+
string congestion = 3;
13+
uint64 up = 4;
14+
uint64 down = 5;
15+
repeated uint32 ports = 6;
16+
int64 interval = 7;
1617

17-
uint64 init_stream_receive_window = 7;
18-
uint64 max_stream_receive_window = 8;
19-
uint64 init_conn_receive_window = 9;
20-
uint64 max_conn_receive_window = 10;
21-
int64 max_idle_timeout = 11;
22-
int64 keep_alive_period = 12;
23-
bool disable_path_mtu_discovery = 13;
18+
uint64 init_stream_receive_window = 8;
19+
uint64 max_stream_receive_window = 9;
20+
uint64 init_conn_receive_window = 10;
21+
uint64 max_conn_receive_window = 11;
22+
int64 max_idle_timeout = 12;
23+
int64 keep_alive_period = 13;
24+
bool disable_path_mtu_discovery = 14;
2425
}
2526

transport/internet/hysteria/conn.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ func (i *InterUdpConn) Read(p []byte) (int, error) {
6464
return 0, io.EOF
6565
}
6666
n := copy(p, b)
67+
if n != len(b) {
68+
return 0, io.ErrShortBuffer
69+
}
6770
return n, nil
6871
}
6972

transport/internet/hysteria/dialer.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import (
1616
"github.com/xtls/xray-core/common"
1717
"github.com/xtls/xray-core/common/errors"
1818
"github.com/xtls/xray-core/common/net"
19-
"github.com/xtls/xray-core/common/session"
2019
"github.com/xtls/xray-core/common/task"
20+
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
2121
"github.com/xtls/xray-core/transport/internet"
2222
"github.com/xtls/xray-core/transport/internet/finalmask"
2323
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
@@ -115,8 +115,8 @@ type client struct {
115115
conn *quic.Conn
116116
config *Config
117117
tlsConfig *go_tls.Config
118-
udpmaskManager *finalmask.UdpmaskManager
119118
socketConfig *internet.SocketConfig
119+
udpmaskManager *finalmask.UdpmaskManager
120120
udpSM *udpSessionManager
121121
mutex sync.Mutex
122122
}
@@ -243,10 +243,25 @@ func (c *client) dial() error {
243243
serverAuto := resp.Header.Get(CommonHeaderCCRX)
244244
serverDown, _ := strconv.ParseUint(serverAuto, 10, 64)
245245

246-
if serverAuto == "auto" || c.config.Up == 0 || serverDown == 0 {
246+
switch c.config.Congestion {
247+
case "reno":
248+
errors.LogDebug(c.ctx, "congestion reno")
249+
case "bbr":
250+
errors.LogDebug(c.ctx, "congestion bbr")
247251
congestion.UseBBR(quicConn)
248-
} else {
249-
congestion.UseBrutal(quicConn, min(c.config.Up, serverDown))
252+
case "brutal", "":
253+
if serverAuto == "auto" || c.config.Up == 0 || serverDown == 0 {
254+
errors.LogDebug(c.ctx, "congestion bbr")
255+
congestion.UseBBR(quicConn)
256+
} else {
257+
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", min(c.config.Up, serverDown))
258+
congestion.UseBrutal(quicConn, min(c.config.Up, serverDown))
259+
}
260+
case "force-brutal":
261+
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", c.config.Up)
262+
congestion.UseBrutal(quicConn, c.config.Up)
263+
default:
264+
errors.LogDebug(c.ctx, "congestion reno")
250265
}
251266

252267
c.pktConn = pktConn
@@ -363,6 +378,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
363378
return nil, errors.New("tls config is nil")
364379
}
365380

381+
requireDatagram := hyCtx.RequireDatagramFromContext(ctx)
366382
addr := dest.NetAddr()
367383
config := streamSettings.ProtocolSettings.(*Config)
368384

@@ -375,18 +391,15 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
375391
dest: dest,
376392
config: config,
377393
tlsConfig: tlsConfig.GetTLSConfig(),
378-
udpmaskManager: streamSettings.UdpmaskManager,
379394
socketConfig: streamSettings.SocketSettings,
395+
udpmaskManager: streamSettings.UdpmaskManager,
380396
}
381397
manger.m[addr] = c
382398
}
383399
c.setCtx(ctx)
384400
manger.mutex.Unlock()
385401

386-
outbounds := session.OutboundsFromContext(ctx)
387-
targetUdp := len(outbounds) > 0 && outbounds[len(outbounds)-1].Target.Network == net.Network_UDP
388-
389-
if targetUdp {
402+
if requireDatagram {
390403
return c.udp()
391404
}
392405
return c.tcp()

0 commit comments

Comments
 (0)