chore: using NewClientConn directly instead of the built-in connection pool for masque h2 mode

This commit is contained in:
wwqgtxx
2026-04-10 17:34:12 +08:00
parent fa081fb16c
commit b0ea75bd21
2 changed files with 30 additions and 18 deletions
+5 -10
View File
@@ -17,7 +17,6 @@ import (
"github.com/metacubex/mihomo/common/atomic"
"github.com/metacubex/mihomo/common/contextutils"
"github.com/metacubex/mihomo/common/httputils"
"github.com/metacubex/mihomo/common/pool"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/resolver"
@@ -171,6 +170,7 @@ func NewMasque(option MasqueOption) (*Masque, error) {
}
return tls.Client(c, tlsConfig), nil
},
ReadIdleTimeout: 30 * time.Second,
}
}
@@ -248,11 +248,11 @@ func (w *Masque) run(ctx context.Context) error {
}
var pc net.PacketConn
var tr io.Closer
var closer io.Closer
var ipConn masque.IpConn
var err error
if w.h2Transport != nil {
ipConn, err = masque.ConnectTunnelH2(ctx, &http.Client{Transport: w.h2Transport}, w.uri)
closer, ipConn, err = masque.ConnectTunnelH2(ctx, w.h2Transport, w.uri)
if err != nil {
return err
}
@@ -276,7 +276,7 @@ func (w *Masque) run(ctx context.Context) error {
common.SetCongestionController(quicConn, w.option.CongestionController, w.option.CWND)
tr, ipConn, err = masque.ConnectTunnel(ctx, quicConn, w.uri)
closer, ipConn, err = masque.ConnectTunnel(ctx, quicConn, w.uri)
if err != nil {
_ = pc.Close()
return err
@@ -289,9 +289,7 @@ func (w *Masque) run(ctx context.Context) error {
contextutils.AfterFunc(runCtx, func() {
w.running.Store(false)
_ = ipConn.Close()
if tr != nil {
_ = tr.Close()
}
_ = closer.Close()
if pc != nil {
_ = pc.Close()
}
@@ -357,9 +355,6 @@ func (w *Masque) Close() error {
if w.tunDevice != nil {
w.tunDevice.Close()
}
if w.h2Transport != nil {
httputils.CloseTransport(w.h2Transport)
}
return nil
}
+25 -8
View File
@@ -28,7 +28,7 @@ const (
ipv6HeaderLen = 40
)
func ConnectTunnelH2(ctx context.Context, h2Client *http.Client, connectUri string) (IpConn, error) {
func ConnectTunnelH2(ctx context.Context, h2Transport *http.Http2Transport, connectUri string) (*http.Http2ClientConn, IpConn, error) {
additionalHeaders := http.Header{
"User-Agent": []string{""},
}
@@ -39,26 +39,43 @@ func ConnectTunnelH2(ctx context.Context, h2Client *http.Client, connectUri stri
// TODO: support PQC
h2Headers.Set("pq-enabled", "false")
ipConn, rsp, err := dialH2(ctx, h2Client, template, h2Headers)
conn, err := h2Transport.DialTLSContext(ctx, "tcp", ":0", nil)
if err != nil {
return nil, nil, fmt.Errorf("connect-ip: failed to dial: %w", err)
}
cc, err := h2Transport.NewClientConn(conn)
if err != nil {
return nil, nil, fmt.Errorf("connect-ip: failed to create client connection: %w", err)
}
if !cc.ReserveNewRequest() {
_ = cc.Close()
return nil, nil, fmt.Errorf("connect-ip: failed to reserve client connection: %w", err)
}
ipConn, rsp, err := dialH2(ctx, cc, template, h2Headers)
if err != nil {
_ = cc.Close()
if strings.Contains(err.Error(), "tls: access denied") {
return nil, errors.New("login failed! Please double-check if your tls key and cert is enrolled in the Cloudflare Access service")
return nil, nil, errors.New("login failed! Please double-check if your tls key and cert is enrolled in the Cloudflare Access service")
}
return nil, fmt.Errorf("failed to dial connect-ip over HTTP/2: %w", err)
return nil, nil, fmt.Errorf("failed to dial connect-ip over HTTP/2: %w", err)
}
if rsp.StatusCode != http.StatusOK {
_ = ipConn.Close()
return nil, fmt.Errorf("failed to dial connect-ip: %v", rsp.Status)
_ = cc.Close()
return nil, nil, fmt.Errorf("failed to dial connect-ip: %v", rsp.Status)
}
return ipConn, nil
return cc, ipConn, nil
}
// dialH2 dials a proxied connection over HTTP/2 CONNECT-IP.
//
// This transport carries proxied packets inside HTTP capsule DATAGRAM frames.
func dialH2(ctx context.Context, client *http.Client, template *uritemplate.Template, additionalHeaders http.Header) (*h2IpConn, *http.Response, error) {
func dialH2(ctx context.Context, rt http.RoundTripper, template *uritemplate.Template, additionalHeaders http.Header) (*h2IpConn, *http.Response, error) {
if len(template.Varnames()) > 0 {
return nil, nil, errors.New("connect-ip: IP flow forwarding not supported")
}
@@ -86,7 +103,7 @@ func dialH2(ctx context.Context, client *http.Client, template *uritemplate.Temp
}
stop := contextutils.AfterFunc(ctx, cancel) // temporarily connect ctx with reqCtx when client.Do
rsp, err := client.Do(req)
rsp, err := rt.RoundTrip(req)
stop() // disconnect ctx with reqCtx after client.Do
if err != nil {
cancel()