@@ -144,9 +144,7 @@ type Swarm struct {
144
144
// down before continuing.
145
145
refs sync.WaitGroup
146
146
147
- emitter event.Emitter
148
- connectednessEventCh chan struct {}
149
- connectednessEmitterDone chan struct {}
147
+ emitter event.Emitter
150
148
151
149
rcmgr network.ResourceManager
152
150
@@ -158,8 +156,7 @@ type Swarm struct {
158
156
159
157
conns struct {
160
158
sync.RWMutex
161
- m map [peer.ID ][]* Conn
162
- connectednessEvents chan peer.ID
159
+ m map [peer.ID ][]* Conn
163
160
}
164
161
165
162
listeners struct {
@@ -206,9 +203,10 @@ type Swarm struct {
206
203
207
204
dialRanker network.DialRanker
208
205
209
- udpBlackHoleConfig blackHoleConfig
210
- ipv6BlackHoleConfig blackHoleConfig
211
- bhd * blackHoleDetector
206
+ udpBlackHoleConfig blackHoleConfig
207
+ ipv6BlackHoleConfig blackHoleConfig
208
+ bhd * blackHoleDetector
209
+ connectednessEventEmitter * connectednessEventEmitter
212
210
}
213
211
214
212
// NewSwarm constructs a Swarm.
@@ -219,17 +217,15 @@ func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts
219
217
}
220
218
ctx , cancel := context .WithCancel (context .Background ())
221
219
s := & Swarm {
222
- local : local ,
223
- peers : peers ,
224
- emitter : emitter ,
225
- connectednessEventCh : make (chan struct {}, 1 ),
226
- connectednessEmitterDone : make (chan struct {}),
227
- ctx : ctx ,
228
- ctxCancel : cancel ,
229
- dialTimeout : defaultDialTimeout ,
230
- dialTimeoutLocal : defaultDialTimeoutLocal ,
231
- maResolver : madns .DefaultResolver ,
232
- dialRanker : DefaultDialRanker ,
220
+ local : local ,
221
+ peers : peers ,
222
+ emitter : emitter ,
223
+ ctx : ctx ,
224
+ ctxCancel : cancel ,
225
+ dialTimeout : defaultDialTimeout ,
226
+ dialTimeoutLocal : defaultDialTimeoutLocal ,
227
+ maResolver : madns .DefaultResolver ,
228
+ dialRanker : DefaultDialRanker ,
233
229
234
230
// A black hole is a binary property. On a network if UDP dials are blocked or there is
235
231
// no IPv6 connectivity, all dials will fail. So a low success rate of 5 out 100 dials
@@ -239,11 +235,11 @@ func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts
239
235
}
240
236
241
237
s .conns .m = make (map [peer.ID ][]* Conn )
242
- s .conns .connectednessEvents = make (chan peer.ID , 32 )
243
238
s .listeners .m = make (map [transport.Listener ]struct {})
244
239
s .transports .m = make (map [int ]transport.Transport )
245
240
s .notifs .m = make (map [network.Notifiee ]struct {})
246
241
s .directConnNotifs .m = make (map [peer.ID ][]chan struct {})
242
+ s .connectednessEventEmitter = newConnectednessEventEmitter (s .Connectedness , emitter )
247
243
248
244
for _ , opt := range opts {
249
245
if err := opt (s ); err != nil {
@@ -260,7 +256,6 @@ func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts
260
256
s .backf .init (s .ctx )
261
257
262
258
s .bhd = newBlackHoleDetector (s .udpBlackHoleConfig , s .ipv6BlackHoleConfig , s .metricsTracer )
263
- go s .connectednessEventEmitter ()
264
259
return s , nil
265
260
}
266
261
@@ -306,8 +301,7 @@ func (s *Swarm) close() {
306
301
307
302
// Wait for everything to finish.
308
303
s .refs .Wait ()
309
- close (s .conns .connectednessEvents )
310
- <- s .connectednessEmitterDone
304
+ s .connectednessEventEmitter .Close ()
311
305
s .emitter .Close ()
312
306
313
307
// Now close out any transports (if necessary). Do this after closing
@@ -338,7 +332,7 @@ func (s *Swarm) close() {
338
332
wg .Wait ()
339
333
}
340
334
341
- func (s * Swarm ) addConn (tc transport.CapableConn , dir network.Direction ) (* Conn , error ) {
335
+ func (s * Swarm ) addConn (ctx context. Context , tc transport.CapableConn , dir network.Direction ) (* Conn , error ) {
342
336
var (
343
337
p = tc .RemotePeer ()
344
338
addr = tc .RemoteMultiaddr ()
@@ -403,12 +397,17 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
403
397
c .notifyLk .Lock ()
404
398
s .conns .Unlock ()
405
399
406
- // Block this goroutine till this request is enqueued.
407
- // This ensures that there are only a finite number of goroutines that are waiting to send
408
- // the connectedness event on the disconnection side in swarm.removeConn.
409
- // This is so because the goroutine to enqueue disconnection event can only be started
410
- // from either a subscriber or a notifier or after calling c.start
411
- s .conns .connectednessEvents <- p
400
+ err := s .connectednessEventEmitter .AddConn (ctx , p )
401
+ if err != nil {
402
+ // Either the subscriber is busy or the swarm is closed
403
+ c .Close ()
404
+ s .removeConn (c )
405
+ c .notifyLk .Unlock ()
406
+ // Remove both the references we aren't going to send any notifications
407
+ // or start this connection
408
+ s .refs .Add (- 2 )
409
+ return nil , fmt .Errorf ("failed to send connectedness event: %w" , err )
410
+ }
412
411
413
412
if ! isLimited {
414
413
// Notify goroutines waiting for a direct connection
@@ -427,6 +426,7 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
427
426
s .notifyAll (func (f network.Notifiee ) {
428
427
f .Connected (s , c )
429
428
})
429
+ c .notified = true
430
430
c .notifyLk .Unlock ()
431
431
432
432
c .start ()
@@ -787,36 +787,6 @@ func (s *Swarm) removeConn(c *Conn) {
787
787
}
788
788
}
789
789
s .conns .Unlock ()
790
- // Do this in a separate go routine to not block the caller.
791
- // This ensures that if a event subscriber closes the connection from the subscription goroutine
792
- // this doesn't deadlock
793
- s .refs .Add (1 )
794
- go func () {
795
- defer s .refs .Done ()
796
- s .conns .connectednessEvents <- p
797
- }()
798
- }
799
-
800
- func (s * Swarm ) connectednessEventEmitter () {
801
- defer close (s .connectednessEmitterDone )
802
- lastConnectednessEvents := make (map [peer.ID ]network.Connectedness )
803
- for p := range s .conns .connectednessEvents {
804
- s .conns .Lock ()
805
- oldState := lastConnectednessEvents [p ]
806
- newState := s .connectednessUnlocked (p )
807
- if newState != network .NotConnected {
808
- lastConnectednessEvents [p ] = newState
809
- } else {
810
- delete (lastConnectednessEvents , p )
811
- }
812
- s .conns .Unlock ()
813
- if newState != oldState {
814
- s .emitter .Emit (event.EvtPeerConnectednessChanged {
815
- Peer : p ,
816
- Connectedness : newState ,
817
- })
818
- }
819
- }
820
790
}
821
791
822
792
// String returns a string representation of Network.
0 commit comments