diff --git a/transport/internet/hysteria/dialer.go b/transport/internet/hysteria/dialer.go index 6ff19c237..c652b40aa 100644 --- a/transport/internet/hysteria/dialer.go +++ b/transport/internet/hysteria/dialer.go @@ -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),