Hysteria client: Honor cancellation during dialing (#7119)

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

---------

Co-authored-by: LjhAUMEM <llnu14702@gmail.com>
This commit is contained in:
SVLAVR
2026-10-12 05:01:23 +00:00
committed by RPRX
co-authored by LjhAUMEM
parent 1dd2a0bd3c
commit 7c2e05dc47
+25 -10
View File
@@ -27,8 +27,7 @@ import (
)
type client struct {
sync.Mutex
lock chan struct{}
instance *core.Instance
forced bool
dest net.Destination
@@ -177,8 +176,9 @@ func (c *client) dial(ctx context.Context) error {
CommonHeaderPadding: []string{AuthRequestPadding.String()},
},
}
resp, err := rt.RoundTrip(req)
resp, err := rt.RoundTrip(req.WithContext(ctx))
if err != nil {
_ = rt.Close()
if conn != nil {
_ = conn.CloseWithError(closeErrCodeProtocolError, "")
}
@@ -186,13 +186,15 @@ func (c *client) dial(ctx context.Context) error {
_ = pktConn.Close()
return err
}
_ = resp.Body.Close()
if resp.StatusCode != StatusAuthOK {
_ = rt.Close()
_ = conn.CloseWithError(closeErrCodeProtocolError, "")
_ = tr.Close()
_ = pktConn.Close()
return errors.New("auth failed code ", resp.StatusCode)
}
_ = resp.Body.Close()
// udp, _ := strconv.ParseBool(resp.Header.Get(ResponseHeaderUDPEnabled))
down, _ := strconv.ParseUint(resp.Header.Get(CommonHeaderCCRX), 10, 64)
@@ -227,9 +229,17 @@ func (c *client) dial(ctx context.Context) error {
return nil
}
func (c *client) unlock() {
<-c.lock
}
func (c *client) tcp(ctx context.Context) (stat.Connection, error) {
c.Lock()
defer c.Unlock()
select {
case <-ctx.Done():
return nil, ctx.Err()
case c.lock <- struct{}{}:
defer c.unlock()
}
err := c.dial(ctx)
if err != nil {
@@ -251,8 +261,12 @@ func (c *client) tcp(ctx context.Context) (stat.Connection, error) {
}
func (c *client) udp(ctx context.Context) (stat.Connection, error) {
c.Lock()
defer c.Unlock()
select {
case <-ctx.Done():
return nil, ctx.Err()
case c.lock <- struct{}{}:
defer c.unlock()
}
err := c.dial(ctx)
if err != nil {
@@ -263,14 +277,14 @@ func (c *client) udp(ctx context.Context) (stat.Connection, error) {
}
func (c *client) clean(force bool) {
c.Lock()
c.lock <- struct{}{}
if force {
c.forced = true
}
if status := c.status(); force && status != StatusNull || status == StatusInactive {
c.close()
}
c.Unlock()
c.unlock()
}
type dialerConf struct {
@@ -338,6 +352,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
c = manager.m[dialerConfKey]
if c == nil {
c = &client{
lock: make(chan struct{}, 1),
instance: core.FromContext(ctx),
dest: dest,
config: streamSettings.ProtocolSettings.(*Config),