Reconnect once if hysteria request fails

This allows graceful recovery when network isn't good enough.

[Original hysteria source
code](13d46da998/core/cs/client.go (L182))
has similar mechanism.
This commit is contained in:
shadow750d6 2023-06-11 22:20:55 +08:00 committed by 世界
parent 3c2c9cf317
commit 597248130f
No known key found for this signature in database
GPG key ID: CD109927C34A63C4

View file

@ -150,6 +150,7 @@ func (h *Hysteria) offer(ctx context.Context) (quic.Connection, error) {
if conn != nil && !common.Done(conn.Context()) {
return conn, nil
}
common.Close(h.rawConn)
conn, err := h.offerNew(ctx)
if err != nil {
return nil, err
@ -260,14 +261,18 @@ func (h *Hysteria) Close() error {
return nil
}
func (h *Hysteria) open(ctx context.Context) (quic.Connection, quic.Stream, error) {
func (h *Hysteria) open(ctx context.Context, reconnect bool) (quic.Connection, quic.Stream, error) {
conn, err := h.offer(ctx)
if err != nil {
return nil, nil, err
if nErr, ok := err.(net.Error); ok && !nErr.Temporary() && reconnect {
return h.open(ctx, false)
}
}
stream, err := conn.OpenStream()
if err != nil {
return nil, nil, err
if nErr, ok := err.(net.Error); ok && !nErr.Temporary() && reconnect {
return h.open(ctx, false)
}
}
return conn, &hysteria.StreamWrapper{Stream: stream}, nil
}
@ -276,7 +281,7 @@ func (h *Hysteria) DialContext(ctx context.Context, network string, destination
switch N.NetworkName(network) {
case N.NetworkTCP:
h.logger.InfoContext(ctx, "outbound connection to ", destination)
_, stream, err := h.open(ctx)
_, stream, err := h.open(ctx, true)
if err != nil {
return nil, err
}
@ -302,7 +307,7 @@ func (h *Hysteria) DialContext(ctx context.Context, network string, destination
func (h *Hysteria) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
conn, stream, err := h.open(ctx)
conn, stream, err := h.open(ctx, true)
if err != nil {
return nil, err
}