Skip to content

Commit 06ea581

Browse files
CriveratechSean-Der
authored andcommitted
Fix WHIP reconnect logic
Old WHIP sessions would incorrectly cause new ones to get deleted. This adds ID to WHIP sessions so we can properly identify them when cleaning up. Resolves #296
1 parent 7cb35c7 commit 06ea581

6 files changed

Lines changed: 153 additions & 27 deletions

File tree

go.mod

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,34 @@ require (
77
github.com/joho/godotenv v1.5.1
88
github.com/pion/dtls/v3 v3.0.6
99
github.com/pion/ice/v3 v3.0.16
10-
github.com/pion/interceptor v0.1.37
10+
github.com/pion/interceptor v0.1.40
1111
github.com/pion/rtcp v1.2.15
12-
github.com/pion/rtp v1.8.17
12+
github.com/pion/rtp v1.8.18
1313
github.com/pion/sdp/v3 v3.0.13
14-
github.com/pion/webrtc/v4 v4.1.1
14+
github.com/pion/webrtc/v4 v4.1.2
15+
github.com/stretchr/testify v1.10.0
1516
)
1617

1718
require (
19+
github.com/davecgh/go-spew v1.1.1 // indirect
1820
github.com/pion/datachannel v1.5.10 // indirect
1921
github.com/pion/dtls/v2 v2.2.12 // indirect
2022
github.com/pion/ice/v4 v4.0.10 // indirect
2123
github.com/pion/logging v0.2.3 // indirect
2224
github.com/pion/mdns/v2 v2.0.7 // indirect
2325
github.com/pion/randutil v0.1.0 // indirect
2426
github.com/pion/sctp v1.8.39 // indirect
25-
github.com/pion/srtp/v3 v3.0.4 // indirect
27+
github.com/pion/srtp/v3 v3.0.5 // indirect
2628
github.com/pion/stun/v2 v2.0.0 // indirect
2729
github.com/pion/stun/v3 v3.0.0 // indirect
2830
github.com/pion/transport/v2 v2.2.10 // indirect
2931
github.com/pion/transport/v3 v3.0.7 // indirect
3032
github.com/pion/turn/v3 v3.0.3 // indirect
3133
github.com/pion/turn/v4 v4.0.0 // indirect
34+
github.com/pmezard/go-difflib v1.0.0 // indirect
3235
github.com/wlynxg/anet v0.0.5 // indirect
3336
golang.org/x/crypto v0.33.0 // indirect
3437
golang.org/x/net v0.35.0 // indirect
3538
golang.org/x/sys v0.30.0 // indirect
39+
gopkg.in/yaml.v3 v3.0.1 // indirect
3640
)

go.sum

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
55
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
66
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
77
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
8+
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
9+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
810
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
911
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
1012
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
@@ -16,8 +18,8 @@ github.com/pion/ice/v3 v3.0.16 h1:YoPlNg3jU1UT/DDTa9v/g1vH6A2/pAzehevI1o66H8E=
1618
github.com/pion/ice/v3 v3.0.16/go.mod h1:SdmubtIsCcvdb1ZInrTUz7Iaqi90/rYd1pzbzlMxsZg=
1719
github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4=
1820
github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
19-
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
20-
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
21+
github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4=
22+
github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic=
2123
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
2224
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
2325
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
@@ -27,14 +29,14 @@ github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
2729
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
2830
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
2931
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
30-
github.com/pion/rtp v1.8.17 h1:CFhaPN8Ikt9Sk7B3pic0kfwVia2dUMEtPSL34Gvihjw=
31-
github.com/pion/rtp v1.8.17/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
32+
github.com/pion/rtp v1.8.18 h1:yEAb4+4a8nkPCecWzQB6V/uEU18X1lQCGAQCjP+pyvU=
33+
github.com/pion/rtp v1.8.18/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
3234
github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE=
3335
github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
3436
github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4=
3537
github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
36-
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
37-
github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
38+
github.com/pion/srtp/v3 v3.0.5 h1:8XLB6Dt3QXkMkRFpoqC3314BemkpMQK2mZeJc4pUKqo=
39+
github.com/pion/srtp/v3 v3.0.5/go.mod h1:r1G7y5r1scZRLe2QJI/is+/O83W2d+JoEsuIexpw+uM=
3840
github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=
3941
github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ=
4042
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
@@ -50,8 +52,8 @@ github.com/pion/turn/v3 v3.0.3 h1:1e3GVk8gHZLPBA5LqadWYV60lmaKUaHCkm9DX9CkGcE=
5052
github.com/pion/turn/v3 v3.0.3/go.mod h1:vw0Dz420q7VYAF3J4wJKzReLHIo2LGp4ev8nXQexYsc=
5153
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
5254
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
53-
github.com/pion/webrtc/v4 v4.1.1 h1:PMFPtLg1kpD2pVtun+LGUzA3k54JdFl87WO0Z1+HKug=
54-
github.com/pion/webrtc/v4 v4.1.1/go.mod h1:cgEGkcpxGkT6Di2ClBYO5lP9mFXbCfEOrkYUpjjCQO4=
55+
github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54=
56+
github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U=
5557
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
5658
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5759
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -62,6 +64,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
6264
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
6365
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
6466
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
67+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
6568
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
6669
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
6770
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
@@ -120,6 +123,7 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
120123
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
121124
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
122125
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
126+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
123127
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
124128
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
125129
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/webrtc/webrtc.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net"
1010
"net/http"
1111
"os"
12+
"slices"
1213
"strconv"
1314
"strings"
1415
"sync"
@@ -36,6 +37,7 @@ type (
3637
// Does this stream have a publisher?
3738
// If stream was created by a WHEP request hasWHIPClient == false
3839
hasWHIPClient atomic.Bool
40+
sessionId string
3941

4042
firstSeenEpoch uint64
4143

@@ -54,6 +56,7 @@ type (
5456
}
5557

5658
videoTrack struct {
59+
sessionId string
5760
rid string
5861
packetsReceived atomic.Uint64
5962
lastKeyFrameSeen atomic.Value
@@ -89,7 +92,7 @@ func getVideoTrackCodec(in string) videoTrackCodec {
8992
return 0
9093
}
9194

92-
func getStream(streamKey string, forWHIP bool) (*stream, error) {
95+
func getStream(streamKey string, whipSessionId string) (*stream, error) {
9396
foundStream, ok := streamMap[streamKey]
9497
if !ok {
9598
audioTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus}, "audio", "pion")
@@ -110,14 +113,15 @@ func getStream(streamKey string, forWHIP bool) (*stream, error) {
110113
streamMap[streamKey] = foundStream
111114
}
112115

113-
if forWHIP {
116+
if whipSessionId != "" {
114117
foundStream.hasWHIPClient.Store(true)
118+
foundStream.sessionId = whipSessionId
115119
}
116120

117121
return foundStream, nil
118122
}
119123

120-
func peerConnectionDisconnected(streamKey string, whepSessionId string) {
124+
func peerConnectionDisconnected(forWHIP bool, streamKey string, sessionId string) {
121125
streamMapLock.Lock()
122126
defer streamMapLock.Unlock()
123127

@@ -129,11 +133,20 @@ func peerConnectionDisconnected(streamKey string, whepSessionId string) {
129133
stream.whepSessionsLock.Lock()
130134
defer stream.whepSessionsLock.Unlock()
131135

132-
if whepSessionId != "" {
133-
delete(stream.whepSessions, whepSessionId)
136+
if !forWHIP {
137+
delete(stream.whepSessions, sessionId)
134138
} else {
139+
stream.videoTracks = slices.DeleteFunc(stream.videoTracks, func(v *videoTrack) bool {
140+
return v.sessionId == sessionId
141+
})
142+
143+
// A PeerConnection for a old WHIP session has gone to disconnected
144+
// closed. Cleanup the state associated with that session, but
145+
// don't modify the current session
146+
if stream.sessionId != sessionId {
147+
return
148+
}
135149
stream.hasWHIPClient.Store(false)
136-
stream.videoTracks = nil
137150
}
138151

139152
// Only delete stream if all WHEP Sessions are gone and have no WHIP Client
@@ -145,7 +158,7 @@ func peerConnectionDisconnected(streamKey string, whepSessionId string) {
145158
delete(streamMap, streamKey)
146159
}
147160

148-
func addTrack(stream *stream, rid string) (*videoTrack, error) {
161+
func addTrack(stream *stream, rid, sessionId string) (*videoTrack, error) {
149162
streamMapLock.Lock()
150163
defer streamMapLock.Unlock()
151164

@@ -155,7 +168,7 @@ func addTrack(stream *stream, rid string) (*videoTrack, error) {
155168
}
156169
}
157170

158-
t := &videoTrack{rid: rid}
171+
t := &videoTrack{rid: rid, sessionId: sessionId}
159172
t.lastKeyFrameSeen.Store(time.Time{})
160173
stream.videoTracks = append(stream.videoTracks, t)
161174
return t, nil

internal/webrtc/whep.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func WHEP(offer, streamKey string) (string, string, error) {
7878

7979
streamMapLock.Lock()
8080
defer streamMapLock.Unlock()
81-
stream, err := getStream(streamKey, false)
81+
stream, err := getStream(streamKey, "")
8282
if err != nil {
8383
return "", "", err
8484
}
@@ -98,7 +98,7 @@ func WHEP(offer, streamKey string) (string, string, error) {
9898
log.Println(err)
9999
}
100100

101-
peerConnectionDisconnected(streamKey, whepSessionId)
101+
peerConnectionDisconnected(false, streamKey, whepSessionId)
102102
}
103103
})
104104

internal/webrtc/whip.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"time"
1010

11+
"github.com/google/uuid"
1112
"github.com/pion/rtcp"
1213
"github.com/pion/rtp"
1314
"github.com/pion/rtp/codecs"
@@ -34,13 +35,13 @@ func audioWriter(remoteTrack *webrtc.TrackRemote, stream *stream) {
3435
}
3536
}
3637

37-
func videoWriter(remoteTrack *webrtc.TrackRemote, stream *stream, peerConnection *webrtc.PeerConnection, s *stream) {
38+
func videoWriter(remoteTrack *webrtc.TrackRemote, stream *stream, peerConnection *webrtc.PeerConnection, s *stream, sessionId string) {
3839
id := remoteTrack.RID()
3940
if id == "" {
4041
id = videoTrackLabelDefault
4142
}
4243

43-
videoTrack, err := addTrack(s, id)
44+
videoTrack, err := addTrack(s, id, sessionId)
4445
if err != nil {
4546
log.Println(err)
4647
return
@@ -142,14 +143,16 @@ func videoWriter(remoteTrack *webrtc.TrackRemote, stream *stream, peerConnection
142143
func WHIP(offer, streamKey string) (string, error) {
143144
maybePrintOfferAnswer(offer, true)
144145

146+
whipSessionId := uuid.New().String()
147+
145148
peerConnection, err := newPeerConnection(apiWhip)
146149
if err != nil {
147150
return "", err
148151
}
149152

150153
streamMapLock.Lock()
151154
defer streamMapLock.Unlock()
152-
stream, err := getStream(streamKey, true)
155+
stream, err := getStream(streamKey, whipSessionId)
153156
if err != nil {
154157
return "", err
155158
}
@@ -158,7 +161,7 @@ func WHIP(offer, streamKey string) (string, error) {
158161
if strings.HasPrefix(remoteTrack.Codec().MimeType, "audio") {
159162
audioWriter(remoteTrack, stream)
160163
} else {
161-
videoWriter(remoteTrack, stream, peerConnection, stream)
164+
videoWriter(remoteTrack, stream, peerConnection, stream, whipSessionId)
162165

163166
}
164167
})
@@ -168,7 +171,7 @@ func WHIP(offer, streamKey string) (string, error) {
168171
if err := peerConnection.Close(); err != nil {
169172
log.Println(err)
170173
}
171-
peerConnectionDisconnected(streamKey, "")
174+
peerConnectionDisconnected(true, streamKey, whipSessionId)
172175
}
173176
})
174177

internal/webrtc/whip_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package webrtc
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/pion/webrtc/v4"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
const testStreamKey = "test"
13+
14+
func doesWHIPSessionExist() (ok bool) {
15+
streamMapLock.Lock()
16+
defer streamMapLock.Unlock()
17+
18+
_, ok = streamMap[testStreamKey]
19+
return
20+
}
21+
22+
// Asserts that a old PeerConnection doesn't destroy the new one
23+
// when it disconnects
24+
func TestReconnect(t *testing.T) {
25+
Configure()
26+
localTrack, err := webrtc.NewTrackLocalStaticSample(
27+
webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeH264}, "video", "pion",
28+
)
29+
require.NoError(t, err)
30+
31+
// Create the first WHIP Session
32+
firstPublisherConnected, firstPublisherConnectedDone := context.WithCancel(context.TODO())
33+
34+
firstPublisher, err := webrtc.NewPeerConnection(webrtc.Configuration{})
35+
require.NoError(t, err)
36+
37+
firstPublisher.OnConnectionStateChange(func(c webrtc.PeerConnectionState) {
38+
if c == webrtc.PeerConnectionStateConnected {
39+
firstPublisherConnectedDone()
40+
41+
}
42+
})
43+
44+
_, err = firstPublisher.AddTrack(localTrack)
45+
require.NoError(t, err)
46+
47+
offer, err := firstPublisher.CreateOffer(nil)
48+
require.NoError(t, err)
49+
require.NoError(t, firstPublisher.SetLocalDescription(offer))
50+
51+
answer, err := WHIP(offer.SDP, testStreamKey)
52+
require.NoError(t, err)
53+
54+
firstPublisher.SetRemoteDescription(webrtc.SessionDescription{
55+
Type: webrtc.SDPTypeAnswer,
56+
SDP: answer,
57+
})
58+
59+
require.True(t, doesWHIPSessionExist())
60+
<-firstPublisherConnected.Done()
61+
62+
// Create the second WHIP Session
63+
secondPublisherConnected, secondPublisherConnectedDone := context.WithCancel(context.TODO())
64+
65+
secondPublisher, err := webrtc.NewPeerConnection(webrtc.Configuration{})
66+
require.NoError(t, err)
67+
68+
secondPublisher.OnConnectionStateChange(func(c webrtc.PeerConnectionState) {
69+
if c == webrtc.PeerConnectionStateConnected {
70+
secondPublisherConnectedDone()
71+
72+
}
73+
})
74+
75+
_, err = secondPublisher.AddTrack(localTrack)
76+
require.NoError(t, err)
77+
78+
offer, err = secondPublisher.CreateOffer(nil)
79+
require.NoError(t, err)
80+
require.NoError(t, secondPublisher.SetLocalDescription(offer))
81+
82+
answer, err = WHIP(offer.SDP, testStreamKey)
83+
require.NoError(t, err)
84+
85+
secondPublisher.SetRemoteDescription(webrtc.SessionDescription{
86+
Type: webrtc.SDPTypeAnswer,
87+
SDP: answer,
88+
})
89+
90+
require.True(t, doesWHIPSessionExist())
91+
<-secondPublisherConnected.Done()
92+
93+
// Close the first WHIP Session, the session must still exist
94+
require.NoError(t, firstPublisher.Close())
95+
time.Sleep(time.Second)
96+
require.True(t, doesWHIPSessionExist())
97+
98+
// Close the second WHIP Session, the session must be gone
99+
require.NoError(t, secondPublisher.Close())
100+
time.Sleep(time.Second)
101+
require.False(t, doesWHIPSessionExist())
102+
}

0 commit comments

Comments
 (0)