@@ -57,6 +57,7 @@ type listener struct {
57
57
// used to control the lifecycle of the listener
58
58
ctx context.Context
59
59
cancel context.CancelFunc
60
+ wg sync.WaitGroup
60
61
}
61
62
62
63
var _ tpt.Listener = & listener {}
@@ -91,30 +92,27 @@ func newListener(transport *WebRTCTransport, laddr ma.Multiaddr, socket net.Pack
91
92
}
92
93
93
94
l .ctx , l .cancel = context .WithCancel (context .Background ())
94
- mux := udpmux .NewUDPMux (socket )
95
- l .mux = mux
96
- mux .Start ()
95
+ l .mux = udpmux .NewUDPMux (socket )
96
+ l .mux .Start ()
97
97
98
- go l .listen ()
98
+ l .wg .Add (1 )
99
+ go func () {
100
+ l .wg .Done ()
101
+ l .listen ()
102
+ }()
99
103
100
104
return l , err
101
105
}
102
106
103
107
func (l * listener ) listen () {
104
- // Accepting a connection requires instantiating a peerconnection
105
- // and a noise connection which is expensive. We therefore limit
106
- // the number of in-flight connection requests. A connection
107
- // is considered to be in flight from the instant it is handled
108
- // until it is dequeued by a call to Accept, or errors out in some
109
- // way.
110
- inFlightQueueCh := make (chan struct {}, l .transport .maxInFlightConnections )
111
- for i := uint32 (0 ); i < l .transport .maxInFlightConnections ; i ++ {
112
- inFlightQueueCh <- struct {}{}
113
- }
114
-
108
+ // Accepting a connection requires instantiating a peerconnection and a noise connection
109
+ // which is expensive. We therefore limit the number of in-flight connection requests. A
110
+ // connection is considered to be in flight from the instant it is handled until it is
111
+ // dequeued by a call to Accept, or errors out in some way.
112
+ inFlightSemaphore := make (chan struct {}, l .transport .maxInFlightConnections )
115
113
for {
116
114
select {
117
- case <- inFlightQueueCh :
115
+ case inFlightSemaphore <- struct {}{} :
118
116
case <- l .ctx .Done ():
119
117
return
120
118
}
@@ -128,7 +126,7 @@ func (l *listener) listen() {
128
126
}
129
127
130
128
go func () {
131
- defer func () { inFlightQueueCh <- struct {}{} }() // free this spot once again
129
+ defer func () { <- inFlightSemaphore }()
132
130
133
131
ctx , cancel := context .WithTimeout (l .ctx , candidateSetupTimeout )
134
132
defer cancel ()
@@ -145,7 +143,7 @@ func (l *listener) listen() {
145
143
log .Warn ("could not push connection: ctx done" )
146
144
conn .Close ()
147
145
case l .acceptQueue <- conn :
148
- // acceptQueue is an unbuffered channel, so this block until the connection is accepted.
146
+ // acceptQueue is an unbuffered channel, so this blocks until the connection is accepted.
149
147
}
150
148
}()
151
149
}
@@ -307,7 +305,18 @@ func (l *listener) Close() error {
307
305
select {
308
306
case <- l .ctx .Done ():
309
307
default :
310
- l .cancel ()
308
+ }
309
+ l .cancel ()
310
+ l .mux .Close ()
311
+ l .wg .Wait ()
312
+ loop:
313
+ for {
314
+ select {
315
+ case conn := <- l .acceptQueue :
316
+ conn .Close ()
317
+ default :
318
+ break loop
319
+ }
311
320
}
312
321
return nil
313
322
}
0 commit comments