mihomo/transport/gun/transport_close.go
2025-12-17 16:13:12 +08:00

64 lines
1.5 KiB
Go

package gun
import (
"net"
"sync"
"time"
"unsafe"
"github.com/metacubex/http"
)
type clientConnPool struct {
t *http.Http2Transport
mu sync.Mutex
conns map[string][]*http.Http2ClientConn // key is host:port
dialing map[string]unsafe.Pointer // currently in-flight dials
keys map[*http.Http2ClientConn][]string
addConnCalls map[string]unsafe.Pointer // in-flight addConnIfNeeded calls
}
type clientConn struct {
t *http.Transport
tconn net.Conn // usually *tls.Conn, except specialized impls
}
type efaceWords struct {
typ unsafe.Pointer
data unsafe.Pointer
}
type tlsConn interface {
net.Conn
NetConn() net.Conn
}
func closeClientConn(cc *http.Http2ClientConn) { // like forceCloseConn() in http.Http2ClientConn but also apply for tls-like conn
if conn, ok := (*clientConn)(unsafe.Pointer(cc)).tconn.(tlsConn); ok {
t := time.AfterFunc(time.Second, func() {
_ = conn.NetConn().Close()
})
defer t.Stop()
}
_ = cc.Close()
}
func closeTransport(tr *http.Http2Transport) {
connPool := transportConnPool(tr)
p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data)
p.mu.Lock()
defer p.mu.Unlock()
for _, vv := range p.conns {
for _, cc := range vv {
closeClientConn(cc)
}
}
// cleanup
p.conns = make(map[string][]*http.Http2ClientConn)
p.keys = make(map[*http.Http2ClientConn][]string)
}
//go:linkname transportConnPool github.com/metacubex/http.(*http2Transport).connPool
func transportConnPool(t *http.Http2Transport) http.Http2ClientConnPool