@@ -29,6 +29,9 @@ final class StreamRTCPeerConnection: StreamRTCPeerConnectionProtocol, @unchecked
2929
3030 /// A dispatch queue for handling peer connection operations.
3131 let dispatchQueue = DispatchQueue ( label: " io.getstream.peerconnection " )
32+
33+ /// A dispatch queue for safely accessing `source`. RTCPeerConnection is not thread-safe.
34+ private let connectionQueue = DispatchQueue ( label: " io.getstream.peerconnection.connection " )
3235
3336 /// A publisher for RTCPeerConnectionEvents.
3437 lazy var publisher : AnyPublisher < RTCPeerConnectionEvent , Never > = delegatePublisher
@@ -83,11 +86,14 @@ final class StreamRTCPeerConnection: StreamRTCPeerConnectionProtocol, @unchecked
8386 return
8487 }
8588
86- source. setLocalDescription ( sessionDescription) { error in
87- if let error = error {
88- continuation. resume ( throwing: error)
89- } else {
90- continuation. resume ( returning: ( ) )
89+ connectionQueue. async { [ weak self] in
90+ guard let self else { return }
91+ source. setLocalDescription ( sessionDescription) { error in
92+ if let error = error {
93+ continuation. resume ( throwing: error)
94+ } else {
95+ continuation. resume ( returning: ( ) )
96+ }
9197 }
9298 }
9399 } as ( )
@@ -108,12 +114,15 @@ final class StreamRTCPeerConnection: StreamRTCPeerConnectionProtocol, @unchecked
108114 return
109115 }
110116
111- source. setRemoteDescription ( sessionDescription) { error in
112- if let error = error {
113- continuation. resume ( throwing: error)
114- } else {
115- self . subject. send ( HasRemoteDescription ( sessionDescription: sessionDescription) )
116- continuation. resume ( returning: ( ) )
117+ connectionQueue. async { [ weak self] in
118+ guard let self else { return }
119+ source. setRemoteDescription ( sessionDescription) { error in
120+ if let error = error {
121+ continuation. resume ( throwing: error)
122+ } else {
123+ self . subject. send ( HasRemoteDescription ( sessionDescription: sessionDescription) )
124+ continuation. resume ( returning: ( ) )
125+ }
117126 }
118127 }
119128 } as ( )
@@ -162,8 +171,13 @@ final class StreamRTCPeerConnection: StreamRTCPeerConnectionProtocol, @unchecked
162171 with track: RTCMediaStreamTrack ,
163172 init transceiverInit: RTCRtpTransceiverInit
164173 ) -> RTCRtpTransceiver ? {
165- let result = source. addTransceiver ( with: track, init: transceiverInit)
166- storeTransceiver ( result, trackType: trackType)
174+ var result : RTCRtpTransceiver ?
175+ connectionQueue. sync {
176+ result = source. addTransceiver ( with: track, init: transceiverInit)
177+ }
178+ if let result {
179+ storeTransceiver ( result, trackType: trackType)
180+ }
167181 return result
168182 }
169183
@@ -195,18 +209,25 @@ final class StreamRTCPeerConnection: StreamRTCPeerConnectionProtocol, @unchecked
195209
196210 /// Restarts the ICE gathering process.
197211 func restartIce( ) {
198- source. restartIce ( )
212+ connectionQueue. async { [ weak self] in
213+ guard let self else { return }
214+ self . source. restartIce ( )
215+ }
199216 }
200217
201218 /// Closes the peer connection.
202219 func close( ) async {
203- Task { @MainActor in
204- /// It's very important to close any transceivers **before** we close the connection, to make
205- /// sure that access to `RTCVideoTrack` properties, will be handled correctly. Otherwise
206- /// if we try to access any property/method on a `RTCVideoTrack` instance whose
207- /// peerConnection has closed, we will get blocked on the Main Thread.
208- source. transceivers. forEach { $0. stopInternal ( ) }
209- source. close ( )
220+ await withCheckedContinuation { continuation in
221+ connectionQueue. async { [ weak self] in
222+ guard let self else { return }
223+ /// It's very important to close any transceivers **before** we close the connection, to make
224+ /// sure that access to `RTCVideoTrack` properties, will be handled correctly. Otherwise
225+ /// if we try to access any property/method on a `RTCVideoTrack` instance whose
226+ /// peerConnection has closed, we will get blocked on the Main Thread.
227+ self . source. transceivers. forEach { $0. stopInternal ( ) }
228+ self . source. close ( )
229+ continuation. resume ( )
230+ }
210231 }
211232 }
212233
0 commit comments