@@ -398,17 +398,17 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
398398 s .conns .Unlock ()
399399
400400 // Notify goroutines waiting for a direct connection
401-
402- // Go routines interested in waiting for direct connection first acquire this lock and then
403- // acquire conns.RLock. Do not acquire this lock before conns.Unlock to prevent deadlock.
404- s .directConnNotifs .Lock ()
405401 if ! c .Stat ().Transient {
402+ // Go routines interested in waiting for direct connection first acquire this lock
403+ // and then acquire s.conns.RLock. Do not acquire this lock before conns.Unlock to
404+ // prevent deadlock.
405+ s .directConnNotifs .Lock ()
406406 for _ , ch := range s .directConnNotifs .m [p ] {
407407 close (ch )
408408 }
409409 delete (s .directConnNotifs .m , p )
410+ s .directConnNotifs .Unlock ()
410411 }
411- s .directConnNotifs .Unlock ()
412412
413413 // Emit event after releasing `s.conns` lock so that a consumer can still
414414 // use swarm methods that need the `s.conns` lock.
@@ -466,15 +466,15 @@ func (s *Swarm) NewStream(ctx context.Context, p peer.ID) (network.Stream, error
466466 //
467467 // TODO: Try all connections even if we get an error opening a stream on
468468 // a non-closed connection.
469- dialed := false
470- for i := 0 ; i < 1 ; i ++ {
469+ numDials := 0
470+ for {
471471 c := s .bestConnToPeer (p )
472472 if c == nil {
473473 if nodial , _ := network .GetNoDial (ctx ); ! nodial {
474- if dialed {
474+ numDials ++
475+ if numDials > DialAttempts {
475476 return nil , errors .New ("max dial attempts exceeded" )
476477 }
477- dialed = true
478478 var err error
479479 c , err = s .dialPeer (ctx , p )
480480 if err != nil {
@@ -503,7 +503,6 @@ func (s *Swarm) NewStream(ctx context.Context, p peer.ID) (network.Stream, error
503503 }
504504 return str , nil
505505 }
506- return nil , network .ErrNoConn
507506}
508507
509508// waitForDirectConn waits for a direct connection established through hole punching or connection reversal.
@@ -524,30 +523,33 @@ func (s *Swarm) waitForDirectConn(ctx context.Context, p peer.ID) (*Conn, error)
524523 s .directConnNotifs .m [p ] = append (s .directConnNotifs .m [p ], ch )
525524 s .directConnNotifs .Unlock ()
526525
527- // Wait for notification.
528- // There's no point waiting for more than a minute here.
529- ctx , cancel := context .WithTimeout (ctx , time .Minute )
526+ // apply the DialPeer timeout
527+ ctx , cancel := context .WithTimeout (ctx , network .GetDialPeerTimeout (ctx ))
530528 defer cancel ()
529+
530+ // Wait for notification.
531531 select {
532532 case <- ctx .Done ():
533533 // Remove ourselves from the notification list
534534 s .directConnNotifs .Lock ()
535+ defer s .directConnNotifs .Unlock ()
536+
535537 s .directConnNotifs .m [p ] = slices .DeleteFunc (
536538 s .directConnNotifs .m [p ],
537539 func (c chan struct {}) bool { return c == ch },
538540 )
539541 if len (s .directConnNotifs .m [p ]) == 0 {
540542 delete (s .directConnNotifs .m , p )
541543 }
542- s .directConnNotifs .Unlock ()
543544 return nil , ctx .Err ()
544545 case <- ch :
545546 // We do not need to remove ourselves from the list here as the notifier
546- // clears the map
547+ // clears the map entry
547548 c := s .bestConnToPeer (p )
548549 if c == nil {
549550 return nil , network .ErrNoConn
550- } else if c .Stat ().Transient {
551+ }
552+ if c .Stat ().Transient {
551553 return nil , network .ErrTransientConn
552554 }
553555 return c , nil
0 commit comments