Hysteria client: Remove closed instance conn (#7107)

https://github.com/XTLS/Xray-core/pull/7102#issuecomment-6054105250

Fixes https://github.com/XTLS/Xray-core/issues/7100

---------

Co-authored-by: LjhAUMEM <llnu14702@gmail.com>
This commit is contained in:
风扇滑翔翼
2026-10-10 08:08:06 +00:00
committed by GitHub
co-authored by LjhAUMEM
parent aa7aa9ad0a
commit c7dbfd5e1e
2 changed files with 39 additions and 13 deletions
+36 -12
View File
@@ -17,6 +17,7 @@ import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/finalmask"
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
@@ -28,6 +29,8 @@ import (
type client struct {
sync.Mutex
instance *core.Instance
forced bool
dest net.Destination
config *Config
tlsConfig *gotls.Config
@@ -64,11 +67,14 @@ func (c *client) close() {
}
func (c *client) dial(ctx context.Context) error {
status := c.status()
if status == StatusActive {
return nil
if c.forced {
return errors.New("client is closed")
}
if status == StatusInactive {
switch c.status() {
case StatusActive:
return nil
case StatusInactive:
c.close()
}
@@ -90,7 +96,7 @@ func (c *client) dial(ctx context.Context) error {
ChromeParrot: !quicParams.DisableChromeParrot,
EnableDatagrams: true,
MaxDatagramFrameSize: MaxDatagramFrameSize,
OmitMaxDatagramFrameSize: time.Now().After(time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC)),
OmitMaxDatagramFrameSize: true,
DisablePathManager: true,
}
if quicParams.InitStreamReceiveWindow == 0 {
@@ -256,9 +262,12 @@ func (c *client) udp(ctx context.Context) (stat.Connection, error) {
return c.udpSM.udp()
}
func (c *client) clean() {
func (c *client) clean(force bool) {
c.Lock()
if c.status() == StatusInactive {
if force {
c.forced = true
}
if status := c.status(); force && status != StatusNull || status == StatusInactive {
c.close()
}
c.Unlock()
@@ -277,11 +286,23 @@ type clientManager struct {
func (m *clientManager) clean() {
ticker := time.NewTicker(idleCleanupInterval)
for range ticker.C {
var forced []dialerConf
m.RLock()
for _, c := range m.m {
c.clean()
for k, c := range m.m {
force := c.instance != nil && !c.instance.IsRunning()
c.clean(force)
if force {
forced = append(forced, k)
}
}
m.RUnlock()
for i := range forced {
m.Lock()
delete(m.m, forced[i])
m.Unlock()
}
}
}
@@ -306,15 +327,18 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
go manager.clean()
})
dialerConfKey := dialerConf{dest, streamSettings}
manager.RLock()
c := manager.m[dialerConf{dest, streamSettings}]
c := manager.m[dialerConfKey]
manager.RUnlock()
if c == nil {
manager.Lock()
c = manager.m[dialerConf{dest, streamSettings}]
c = manager.m[dialerConfKey]
if c == nil {
c = &client{
instance: core.FromContext(ctx),
dest: dest,
config: streamSettings.ProtocolSettings.(*Config),
tlsConfig: tlsConfig.GetTLSConfig(tls.WithDestination(dest)),
@@ -322,7 +346,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
finalMask: streamSettings.FinalMask,
quicParams: streamSettings.QuicParams,
}
manager.m[dialerConf{dest, streamSettings}] = c
manager.m[dialerConfKey] = c
}
manager.Unlock()
}