@@ -203,9 +203,10 @@ type Swarm struct {
203
203
204
204
dialRanker network.DialRanker
205
205
206
- udpBlackHoleConfig blackHoleConfig
207
- ipv6BlackHoleConfig blackHoleConfig
208
- bhd * blackHoleDetector
206
+ udpBlackHoleConfig blackHoleConfig
207
+ ipv6BlackHoleConfig blackHoleConfig
208
+ bhd * blackHoleDetector
209
+ connectednessEventEmitter * connectednessEventEmitter
209
210
}
210
211
211
212
// NewSwarm constructs a Swarm.
@@ -238,6 +239,7 @@ func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts
238
239
s .transports .m = make (map [int ]transport.Transport )
239
240
s .notifs .m = make (map [network.Notifiee ]struct {})
240
241
s .directConnNotifs .m = make (map [peer.ID ][]chan struct {})
242
+ s .connectednessEventEmitter = newConnectednessEventEmitter (s .Connectedness , emitter )
241
243
242
244
for _ , opt := range opts {
243
245
if err := opt (s ); err != nil {
@@ -254,7 +256,6 @@ func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts
254
256
s .backf .init (s .ctx )
255
257
256
258
s .bhd = newBlackHoleDetector (s .udpBlackHoleConfig , s .ipv6BlackHoleConfig , s .metricsTracer )
257
-
258
259
return s , nil
259
260
}
260
261
@@ -271,8 +272,6 @@ func (s *Swarm) Done() <-chan struct{} {
271
272
func (s * Swarm ) close () {
272
273
s .ctxCancel ()
273
274
274
- s .emitter .Close ()
275
-
276
275
// Prevents new connections and/or listeners from being added to the swarm.
277
276
s .listeners .Lock ()
278
277
listeners := s .listeners .m
@@ -308,6 +307,8 @@ func (s *Swarm) close() {
308
307
309
308
// Wait for everything to finish.
310
309
s .refs .Wait ()
310
+ s .connectednessEventEmitter .Close ()
311
+ s .emitter .Close ()
311
312
312
313
// Now close out any transports (if necessary). Do this after closing
313
314
// all connections/listeners.
@@ -350,6 +351,7 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
350
351
}
351
352
stat .Direction = dir
352
353
stat .Opened = time .Now ()
354
+ isLimited := stat .Limited
353
355
354
356
// Wrap and register the connection.
355
357
c := & Conn {
@@ -390,21 +392,24 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
390
392
}
391
393
392
394
c .streams .m = make (map [* Stream ]struct {})
393
- isFirstConnection := len (s .conns .m [p ]) == 0
394
395
s .conns .m [p ] = append (s .conns .m [p ], c )
395
-
396
396
// Add two swarm refs:
397
397
// * One will be decremented after the close notifications fire in Conn.doClose
398
398
// * The other will be decremented when Conn.start exits.
399
399
s .refs .Add (2 )
400
-
401
400
// Take the notification lock before releasing the conns lock to block
402
401
// Disconnect notifications until after the Connect notifications done.
402
+ // This lock also ensures that swarm.refs.Wait() exits after we have
403
+ // enqueued the peer connectedness changed notification.
404
+ // TODO: Fix this fragility by taking a swarm ref for dial worker loop
403
405
c .notifyLk .Lock ()
404
406
s .conns .Unlock ()
405
407
406
- // Notify goroutines waiting for a direct connection
407
- if ! c .Stat ().Transient {
408
+ s .connectednessEventEmitter .AddConn (p )
409
+
410
+ if ! isLimited {
411
+ // Notify goroutines waiting for a direct connection
412
+ //
408
413
// Go routines interested in waiting for direct connection first acquire this lock
409
414
// and then acquire s.conns.RLock. Do not acquire this lock before conns.Unlock to
410
415
// prevent deadlock.
@@ -415,16 +420,6 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
415
420
delete (s .directConnNotifs .m , p )
416
421
s .directConnNotifs .Unlock ()
417
422
}
418
-
419
- // Emit event after releasing `s.conns` lock so that a consumer can still
420
- // use swarm methods that need the `s.conns` lock.
421
- if isFirstConnection {
422
- s .emitter .Emit (event.EvtPeerConnectednessChanged {
423
- Peer : p ,
424
- Connectedness : network .Connected ,
425
- })
426
- }
427
-
428
423
s .notifyAll (func (f network.Notifiee ) {
429
424
f .Connected (s , c )
430
425
})
@@ -455,14 +450,14 @@ func (s *Swarm) StreamHandler() network.StreamHandler {
455
450
456
451
// NewStream creates a new stream on any available connection to peer, dialing
457
452
// if necessary.
458
- // Use network.WithUseTransient to open a stream over a transient (relayed)
453
+ // Use network.WithAllowLimitedConn to open a stream over a limited (relayed)
459
454
// connection.
460
455
func (s * Swarm ) NewStream (ctx context.Context , p peer.ID ) (network.Stream , error ) {
461
456
log .Debugf ("[%s] opening stream to peer [%s]" , s .local , p )
462
457
463
458
// Algorithm:
464
459
// 1. Find the best connection, otherwise, dial.
465
- // 2. If the best connection is transient , wait for a direct conn via conn
460
+ // 2. If the best connection is limited , wait for a direct conn via conn
466
461
// reversal or hole punching.
467
462
// 3. Try opening a stream.
468
463
// 4. If the underlying connection is, in fact, closed, close the outer
@@ -491,8 +486,8 @@ func (s *Swarm) NewStream(ctx context.Context, p peer.ID) (network.Stream, error
491
486
}
492
487
}
493
488
494
- useTransient , _ := network .GetUseTransient (ctx )
495
- if ! useTransient && c .Stat ().Transient {
489
+ limitedAllowed , _ := network .GetAllowLimitedConn (ctx )
490
+ if ! limitedAllowed && c .Stat ().Limited {
496
491
var err error
497
492
c , err = s .waitForDirectConn (ctx , p )
498
493
if err != nil {
@@ -518,12 +513,12 @@ func (s *Swarm) waitForDirectConn(ctx context.Context, p peer.ID) (*Conn, error)
518
513
if c == nil {
519
514
s .directConnNotifs .Unlock ()
520
515
return nil , network .ErrNoConn
521
- } else if ! c .Stat ().Transient {
516
+ } else if ! c .Stat ().Limited {
522
517
s .directConnNotifs .Unlock ()
523
518
return c , nil
524
519
}
525
520
526
- // Wait for transient connection to upgrade to a direct connection either by
521
+ // Wait for limited connection to upgrade to a direct connection either by
527
522
// connection reversal or hole punching.
528
523
ch := make (chan struct {})
529
524
s .directConnNotifs .m [p ] = append (s .directConnNotifs .m [p ], ch )
@@ -555,8 +550,8 @@ func (s *Swarm) waitForDirectConn(ctx context.Context, p peer.ID) (*Conn, error)
555
550
if c == nil {
556
551
return nil , network .ErrNoConn
557
552
}
558
- if c .Stat ().Transient {
559
- return nil , network .ErrTransientConn
553
+ if c .Stat ().Limited {
554
+ return nil , network .ErrLimitedConn
560
555
}
561
556
return c , nil
562
557
}
@@ -577,11 +572,11 @@ func (s *Swarm) ConnsToPeer(p peer.ID) []network.Conn {
577
572
}
578
573
579
574
func isBetterConn (a , b * Conn ) bool {
580
- // If one is transient and not the other, prefer the non-transient connection.
581
- aTransient := a .Stat ().Transient
582
- bTransient := b .Stat ().Transient
583
- if aTransient != bTransient {
584
- return ! aTransient
575
+ // If one is limited and not the other, prefer the unlimited connection.
576
+ aLimited := a .Stat ().Limited
577
+ bLimited := b .Stat ().Limited
578
+ if aLimited != bLimited {
579
+ return ! aLimited
585
580
}
586
581
587
582
// If one is direct and not the other, prefer the direct connection.
@@ -632,7 +627,7 @@ func (s *Swarm) bestConnToPeer(p peer.ID) *Conn {
632
627
633
628
// bestAcceptableConnToPeer returns the best acceptable connection, considering the passed in ctx.
634
629
// If network.WithForceDirectDial is used, it only returns a direct connections, ignoring
635
- // any transient (relayed) connections to the peer.
630
+ // any limited (relayed) connections to the peer.
636
631
func (s * Swarm ) bestAcceptableConnToPeer (ctx context.Context , p peer.ID ) * Conn {
637
632
conn := s .bestConnToPeer (p )
638
633
@@ -652,8 +647,28 @@ func isDirectConn(c *Conn) bool {
652
647
// To check if we have an open connection, use `s.Connectedness(p) ==
653
648
// network.Connected`.
654
649
func (s * Swarm ) Connectedness (p peer.ID ) network.Connectedness {
655
- if s .bestConnToPeer (p ) != nil {
656
- return network .Connected
650
+ s .conns .RLock ()
651
+ defer s .conns .RUnlock ()
652
+
653
+ return s .connectednessUnlocked (p )
654
+ }
655
+
656
+ // connectednessUnlocked returns the connectedness of a peer.
657
+ func (s * Swarm ) connectednessUnlocked (p peer.ID ) network.Connectedness {
658
+ var haveLimited bool
659
+ for _ , c := range s .conns .m [p ] {
660
+ if c .IsClosed () {
661
+ // These will be garbage collected soon
662
+ continue
663
+ }
664
+ if c .Stat ().Limited {
665
+ haveLimited = true
666
+ } else {
667
+ return network .Connected
668
+ }
669
+ }
670
+ if haveLimited {
671
+ return network .Limited
657
672
}
658
673
return network .NotConnected
659
674
}
@@ -751,24 +766,7 @@ func (s *Swarm) removeConn(c *Conn) {
751
766
p := c .RemotePeer ()
752
767
753
768
s .conns .Lock ()
754
-
755
769
cs := s .conns .m [p ]
756
-
757
- if len (cs ) == 1 {
758
- delete (s .conns .m , p )
759
- s .conns .Unlock ()
760
-
761
- // Emit event after releasing `s.conns` lock so that a consumer can still
762
- // use swarm methods that need the `s.conns` lock.
763
- s .emitter .Emit (event.EvtPeerConnectednessChanged {
764
- Peer : p ,
765
- Connectedness : network .NotConnected ,
766
- })
767
- return
768
- }
769
-
770
- defer s .conns .Unlock ()
771
-
772
770
for i , ci := range cs {
773
771
if ci == c {
774
772
// NOTE: We're intentionally preserving order.
@@ -780,6 +778,10 @@ func (s *Swarm) removeConn(c *Conn) {
780
778
break
781
779
}
782
780
}
781
+ if len (s .conns .m [p ]) == 0 {
782
+ delete (s .conns .m , p )
783
+ }
784
+ s .conns .Unlock ()
783
785
}
784
786
785
787
// String returns a string representation of Network.
0 commit comments