diff --git a/dialer/icmp/conn.go b/dialer/icmp/conn.go index b6797bf2..7b10598f 100644 --- a/dialer/icmp/conn.go +++ b/dialer/icmp/conn.go @@ -3,6 +3,7 @@ package quic import ( "context" "net" + "time" "github.com/quic-go/quic-go" ) @@ -12,7 +13,9 @@ type quicSession struct { } func (session *quicSession) GetConn() (*quicConn, error) { - stream, err := session.session.OpenStreamSync(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + stream, err := session.session.OpenStreamSync(ctx) if err != nil { return nil, err } diff --git a/dialer/icmp/dialer.go b/dialer/icmp/dialer.go index bd87d403..855a1623 100644 --- a/dialer/icmp/dialer.go +++ b/dialer/icmp/dialer.go @@ -75,7 +75,6 @@ func (d *icmpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO } d.sessionMutex.Lock() - defer d.sessionMutex.Unlock() session, ok := d.sessions[addr] if session != nil && session.IsClosed() { @@ -95,6 +94,7 @@ func (d *icmpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO pc, err = icmp_pkg.ListenPacket("ip4:icmp", "") } if err != nil { + d.sessionMutex.Unlock() return } @@ -109,16 +109,22 @@ func (d *icmpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO if err != nil { d.logger.Error(err) pc.Close() + d.sessionMutex.Unlock() return nil, err } d.sessions[addr] = session } + d.sessionMutex.Unlock() conn, err = session.GetConn() if err != nil { + d.sessionMutex.Lock() + if d.sessions[addr] == session { + delete(d.sessions, addr) + } session.Close() - delete(d.sessions, addr) + d.sessionMutex.Unlock() return nil, err } diff --git a/dialer/icmp/metadata.go b/dialer/icmp/metadata.go index 329abea9..0660a338 100644 --- a/dialer/icmp/metadata.go +++ b/dialer/icmp/metadata.go @@ -14,14 +14,21 @@ type metadata struct { } func (d *icmpDialer) parseMetadata(md mdata.Metadata) (err error) { - if mdutil.GetBool(md, "keepalive") { - d.md.keepAlivePeriod = mdutil.GetDuration(md, "ttl") + const ( + keepAlive = "keepAlive" + keepAlivePeriod = "ttl" + handshakeTimeout = "handshakeTimeout" + maxIdleTimeout = "maxIdleTimeout" + ) + + if md == nil || !md.IsExists(keepAlive) || mdutil.GetBool(md, keepAlive) { + d.md.keepAlivePeriod = mdutil.GetDuration(md, keepAlivePeriod) if d.md.keepAlivePeriod <= 0 { d.md.keepAlivePeriod = 10 * time.Second } } - d.md.handshakeTimeout = mdutil.GetDuration(md, "handshakeTimeout") - d.md.maxIdleTimeout = mdutil.GetDuration(md, "maxIdleTimeout") + d.md.handshakeTimeout = mdutil.GetDuration(md, handshakeTimeout) + d.md.maxIdleTimeout = mdutil.GetDuration(md, maxIdleTimeout) return } diff --git a/dialer/quic/conn.go b/dialer/quic/conn.go index b6797bf2..7b10598f 100644 --- a/dialer/quic/conn.go +++ b/dialer/quic/conn.go @@ -3,6 +3,7 @@ package quic import ( "context" "net" + "time" "github.com/quic-go/quic-go" ) @@ -12,7 +13,9 @@ type quicSession struct { } func (session *quicSession) GetConn() (*quicConn, error) { - stream, err := session.session.OpenStreamSync(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + stream, err := session.session.OpenStreamSync(ctx) if err != nil { return nil, err } diff --git a/dialer/quic/dialer.go b/dialer/quic/dialer.go index a12a1008..f1ad8898 100644 --- a/dialer/quic/dialer.go +++ b/dialer/quic/dialer.go @@ -58,7 +58,6 @@ func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO } d.sessionMutex.Lock() - defer d.sessionMutex.Unlock() session, ok := d.sessions[addr] if session != nil && session.IsClosed() { @@ -73,11 +72,13 @@ func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO c, err := options.Dialer.Dial(ctx, "udp", "") if err != nil { + d.sessionMutex.Unlock() return nil, err } pc, ok := c.(net.PacketConn) if !ok { c.Close() + d.sessionMutex.Unlock() return nil, errors.New("quic: wrong connection type") } @@ -89,16 +90,22 @@ func (d *quicDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO if err != nil { d.logger.Error(err) pc.Close() + d.sessionMutex.Unlock() return nil, err } d.sessions[addr] = session } + d.sessionMutex.Unlock() conn, err = session.GetConn() if err != nil { + d.sessionMutex.Lock() + if d.sessions[addr] == session { + delete(d.sessions, addr) + } session.Close() - delete(d.sessions, addr) + d.sessionMutex.Unlock() return nil, err }