fix: grpc transport not apply dial timeout
Some checks failed
Trigger CMFA Update / trigger-CMFA-update (push) Failing after 1s

This commit is contained in:
wwqgtxx 2025-04-04 21:05:54 +08:00
parent 24a9ff6d03
commit 190047c8c0
3 changed files with 23 additions and 14 deletions

View File

@ -22,6 +22,7 @@ import (
"github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/common/buf"
"github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/common/pool"
tlsC "github.com/metacubex/mihomo/component/tls" tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
@ -224,11 +225,9 @@ func (g *Conn) SetDeadline(t time.Time) error {
} }
func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, Fingerprint string, realityConfig *tlsC.RealityConfig) *TransportWrap { func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, Fingerprint string, realityConfig *tlsC.RealityConfig) *TransportWrap {
closed := &atomic.Bool{}
dialFunc := func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) { dialFunc := func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
if closed.Load() { ctx, cancel := context.WithTimeout(ctx, C.DefaultTLSTimeout)
return nil, errors.New("transport closed") defer cancel()
}
pconn, err := dialFn(ctx, network, addr) pconn, err := dialFn(ctx, network, addr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -291,9 +290,12 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, Fingerprint string, re
DisableCompression: true, DisableCompression: true,
PingTimeout: 0, PingTimeout: 0,
} }
ctx, cancel := context.WithCancel(context.Background())
wrap := &TransportWrap{ wrap := &TransportWrap{
Transport: transport, Transport: transport,
closed: closed, ctx: ctx,
cancel: cancel,
} }
return wrap return wrap
} }
@ -320,6 +322,7 @@ func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, er
ProtoMinor: 0, ProtoMinor: 0,
Header: defaultHeader, Header: defaultHeader,
} }
request = request.WithContext(transport.ctx)
conn := &Conn{ conn := &Conn{
initFn: func() (io.ReadCloser, netAddr, error) { initFn: func() (io.ReadCloser, netAddr, error) {

View File

@ -1,16 +1,26 @@
package gun package gun
import ( import (
"context"
"net" "net"
"sync"
"github.com/metacubex/mihomo/common/atomic"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
type TransportWrap struct { type TransportWrap struct {
*http2.Transport *http2.Transport
closed *atomic.Bool ctx context.Context
cancel context.CancelFunc
closeOnce sync.Once
}
func (tw *TransportWrap) Close() error {
tw.closeOnce.Do(func() {
tw.cancel()
closeTransport(tw.Transport)
})
return nil
} }
type netAddr struct { type netAddr struct {

View File

@ -45,11 +45,8 @@ func closeClientConn(cc *http2.ClientConn) { // like forceCloseConn() in http2.C
_ = cc.Close() _ = cc.Close()
} }
func (tw *TransportWrap) Close() error { func closeTransport(tr *http2.Transport) {
if tw.closed.Swap(true) { connPool := transportConnPool(tr)
return nil // already closed
}
connPool := transportConnPool(tw.Transport)
p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data) p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data)
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
@ -61,7 +58,6 @@ func (tw *TransportWrap) Close() error {
// cleanup // cleanup
p.conns = make(map[string][]*http2.ClientConn) p.conns = make(map[string][]*http2.ClientConn)
p.keys = make(map[*http2.ClientConn][]string) p.keys = make(map[*http2.ClientConn][]string)
return nil
} }
//go:linkname transportConnPool golang.org/x/net/http2.(*Transport).connPool //go:linkname transportConnPool golang.org/x/net/http2.(*Transport).connPool