mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-10-10 12:13:10 +08:00
chore: change the brutal negotiation in shadowquic to be asynchronous
This commit is contained in:
+4
-4
@@ -1508,8 +1508,8 @@ proxies: # socks5
|
||||
# zero-rtt: false # 官方 server 的 0-RTT 路径可能在 JLS 认证完成前读取用户状态(已确认影响 v0.3.11);使用官方 server 时必须在服务端关闭 zero-rtt
|
||||
# keep-alive-interval: 10000
|
||||
# congestion-controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic"
|
||||
# up: 100 Mbps # enables brutal; client upload speed; requires mihomo ShadowQuic on both ends
|
||||
# down: 100 Mbps # enables brutal; requested client download speed, capped by listener up; requires mihomo ShadowQuic on both ends
|
||||
# up: 100 Mbps # enables brutal negotiation via a mihomo private extension; client upload speed; falls back to congestion-controller when unsupported
|
||||
# down: 100 Mbps # enables brutal negotiation via a mihomo private extension; requested client download speed, capped by listener up; falls back to congestion-controller when unsupported
|
||||
# cwnd: 10 # default: 32
|
||||
# bbr-profile: "" # Available: "standard", "conservative", "aggressive". Default: "standard"
|
||||
# max-datagram-frame-size: 1400
|
||||
@@ -2271,8 +2271,8 @@ listeners:
|
||||
# quic-versions: [v1] # 本机手动配置及探测失败时的版本;支持 v1/v2
|
||||
# zero-rtt: true
|
||||
# congestion-controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic"
|
||||
# up: 100 Mbps # enables brutal; server upload/client download speed cap; requires mihomo ShadowQuic on both ends
|
||||
# down: 100 Mbps # enables brutal; requested server download/client upload speed; requires mihomo ShadowQuic on both ends
|
||||
# up: 100 Mbps # enables brutal negotiation via a mihomo private extension; server upload/client download speed cap; falls back to congestion-controller when unsupported
|
||||
# down: 100 Mbps # enables brutal negotiation via a mihomo private extension; requested server download/client upload speed; falls back to congestion-controller when unsupported
|
||||
# ignore-client-bandwidth: false # for brutal; ignore outbound down and use listener down/auto instead
|
||||
# cwnd: 10 # default: 32
|
||||
# bbr-profile: "" # Available: "standard", "conservative", "aggressive". Default: "standard"
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
|
||||
@@ -52,43 +53,41 @@ func (c *Client) getConn(ctx context.Context) (*connState, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = c.configureCongestion(ctx, quicConn); err != nil {
|
||||
_ = quicConn.CloseWithError(0, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
SetCongestionController(quicConn, c.option.CongestionController, c.option.CWND, c.option.BBRProfile)
|
||||
c.conn = newConnState(quicConn)
|
||||
if c.brutalEnabled() {
|
||||
// Brutal is an optional upgrade; keep the connection usable while it is negotiated.
|
||||
go c.negotiateBrutal(c.conn)
|
||||
}
|
||||
return c.conn, nil
|
||||
}
|
||||
|
||||
func (c *Client) configureCongestion(ctx context.Context, quicConn *quic.Conn) error {
|
||||
if !c.brutalEnabled() {
|
||||
SetCongestionController(quicConn, c.option.CongestionController, c.option.CWND, c.option.BBRProfile)
|
||||
return nil
|
||||
}
|
||||
|
||||
stream, err := quicConn.OpenStreamSync(ctx)
|
||||
func (c *Client) negotiateBrutal(state *connState) {
|
||||
ctx, cancel := context.WithTimeout(state.ctx, brutalNegotiationTimeout)
|
||||
defer cancel()
|
||||
stream, err := state.quicConn.OpenStreamSync(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
defer stream.Close()
|
||||
_ = stream.SetDeadline(time.Now().Add(brutalNegotiationTimeout))
|
||||
|
||||
if err = WriteBrutalNegotiationRequest(stream, c.option.ReceiveBPS); err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
rx, rxAuto, err := ReadBrutalNegotiationResponse(stream)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
actualTx := rx
|
||||
if actualTx == 0 || actualTx > c.option.SendBPS {
|
||||
actualTx = c.option.SendBPS
|
||||
}
|
||||
if !rxAuto && actualTx > 0 {
|
||||
setBrutalCongestionController(quicConn, actualTx)
|
||||
setBrutalCongestionController(state.quicConn, actualTx)
|
||||
} else {
|
||||
SetCongestionController(quicConn, "bbr", c.option.CWND, c.option.BBRProfile)
|
||||
SetCongestionController(state.quicConn, "bbr", c.option.CWND, c.option.BBRProfile)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) brutalEnabled() bool {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -16,6 +17,7 @@ const (
|
||||
brutalNegotiationMaxPayloadLen = 64
|
||||
|
||||
brutalNegotiationFlagRxAuto byte = 1 << 0
|
||||
brutalNegotiationTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -49,9 +49,8 @@ func (s *Server) Serve() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !s.brutalRequired() {
|
||||
SetCongestionController(conn, s.option.CongestionController, s.option.CWND, s.option.BBRProfile)
|
||||
}
|
||||
// Application streams may arrive before Brutal negotiation completes.
|
||||
SetCongestionController(conn, s.option.CongestionController, s.option.CWND, s.option.BBRProfile)
|
||||
state := newConnState(conn)
|
||||
go s.handleConnection(state)
|
||||
}
|
||||
@@ -79,11 +78,6 @@ func (s *Server) handleStream(state *connState, stream *quic.Stream) {
|
||||
_ = conn.Close()
|
||||
return
|
||||
}
|
||||
if command != CommandExtension && s.brutalRequired() && !state.isBrutalNegotiated() {
|
||||
_ = conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
switch command {
|
||||
case CommandConnect:
|
||||
target, err := ReadRequestAddr(conn)
|
||||
@@ -122,10 +116,6 @@ func (s *Server) handleStream(state *connState, stream *quic.Stream) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) brutalRequired() bool {
|
||||
return s.option.SendBPS > 0 || s.option.ReceiveBPS > 0
|
||||
}
|
||||
|
||||
func (s *Server) handleBrutalNegotiation(state *connState, conn net.Conn) {
|
||||
rx, err := ReadBrutalNegotiationRequest(conn)
|
||||
if err != nil {
|
||||
@@ -135,7 +125,6 @@ func (s *Server) handleBrutalNegotiation(state *connState, conn net.Conn) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
state.markBrutalNegotiated()
|
||||
if err = WriteBrutalNegotiationResponse(conn, s.option.ReceiveBPS, rxAuto); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/metacubex/mihomo/transport/socks5"
|
||||
|
||||
@@ -36,8 +35,6 @@ type connState struct {
|
||||
nextID uint16
|
||||
activeSend map[uint16]struct{}
|
||||
recv map[uint16]*recvSlot
|
||||
|
||||
brutalNegotiated atomic.Bool
|
||||
}
|
||||
|
||||
type recvSlot struct {
|
||||
@@ -84,14 +81,6 @@ func (s *connState) closeWithError(code quic.ApplicationErrorCode, message strin
|
||||
return s.quicConn.CloseWithError(code, message)
|
||||
}
|
||||
|
||||
func (s *connState) markBrutalNegotiated() {
|
||||
s.brutalNegotiated.Store(true)
|
||||
}
|
||||
|
||||
func (s *connState) isBrutalNegotiated() bool {
|
||||
return s.brutalNegotiated.Load()
|
||||
}
|
||||
|
||||
func (s *connState) handleDatagrams() {
|
||||
for {
|
||||
message, err := s.quicConn.ReceiveDatagram(s.ctx)
|
||||
|
||||
Reference in New Issue
Block a user