Skip to content

Commit e7c6abf

Browse files
committed
JanusConnection, PeerConnection wrapper and PeerConnectionManager
1 parent a4c9e01 commit e7c6abf

File tree

6 files changed

+190
-25
lines changed

6 files changed

+190
-25
lines changed

Sources/PrivMXEndpointSwift/Errors/PrivMXEndpointError.swift

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public enum PrivMXEndpointError : Error{
4545
case failedDisconnecting(privmx.InternalError)
4646
/// Failed to list Contexts.
4747
case failedListingContexts(privmx.InternalError)
48-
48+
4949
/// Failed to get a list of Users from a Context.
5050
case failedGettingContextUsers(privmx.InternalError)
5151

@@ -169,7 +169,7 @@ public enum PrivMXEndpointError : Error{
169169

170170
/// Failed to emit a `CustomEvent`.
171171
case failedEmittingCustomEvent(privmx.InternalError)
172-
172+
173173
/// Failed to subscribe for Custom Events.
174174
case failedSubscribingForCustomEvents(privmx.InternalError)
175175

@@ -179,7 +179,7 @@ public enum PrivMXEndpointError : Error{
179179
/// Failed to set a User Verifier.
180180
case failedSettingUserVerifier(privmx.InternalError)
181181

182-
/// Failed to instantiate ExtKey.
182+
/// Failed to instantiate ExtKey.
183183
case failedInstantiatingExtKey(privmx.InternalError)
184184
/// Failed to derive ExtKey.
185185
case failedDerivingExtKey(privmx.InternalError)
@@ -201,7 +201,7 @@ public enum PrivMXEndpointError : Error{
201201
case failedVerifyingCompactSignature(privmx.InternalError)
202202
/// Failed to check if ExtKey is private.
203203
case failedCheckingIfExtKeyIsPrivate(privmx.InternalError)
204-
204+
205205
/// Failed to convert a PGP Asn1 key to Base58DER.
206206
case failedConvertingKeyToBase58DER(privmx.InternalError)
207207

@@ -269,7 +269,11 @@ public enum PrivMXEndpointError : Error{
269269
case failedDeletingKvdbEntries(privmx.InternalError)
270270

271271
case failedSyncingFile(privmx.InternalError)
272-
272+
273+
#if Streams
274+
case failedInitializingPeerConnection(privmx.InternalError)
275+
#endif
276+
273277
/// Gets the Message of the error.
274278
///
275279
/// - Returns: Message of the error
@@ -388,6 +392,10 @@ public enum PrivMXEndpointError : Error{
388392
.failedSyncingFile(let err),
389393
.failedGeneratingBIP39(let err):
390394
return String(err.message)
395+
#if Streams
396+
case .failedInitializingPeerConnection(let err):
397+
return String(err.message)
398+
#endif
391399
}
392400
}
393401

@@ -510,6 +518,10 @@ public enum PrivMXEndpointError : Error{
510518
.failedSyncingFile(let err),
511519
.failedGeneratingBIP39(let err):
512520
return err.code.value
521+
#if Streams
522+
case .failedInitializingPeerConnection(let err):
523+
return err.code.value
524+
#endif
513525
}
514526
}
515527

@@ -631,6 +643,10 @@ public enum PrivMXEndpointError : Error{
631643
.failedSyncingFile(let err),
632644
.failedGeneratingBIP39(let err):
633645
return String(err.name)
646+
#if Streams
647+
case .failedInitializingPeerConnection(let err):
648+
return String(err.name)
649+
#endif
634650
}
635651
}
636652

@@ -752,6 +768,10 @@ public enum PrivMXEndpointError : Error{
752768
.failedSyncingFile(let err),
753769
.failedGeneratingBIP39(let err):
754770
return String(err.description)
771+
#if Streams
772+
case .failedInitializingPeerConnection(let err):
773+
return String(err.description)
774+
#endif
755775
}
756776
}
757777

@@ -877,7 +897,14 @@ public enum PrivMXEndpointError : Error{
877897
} else {
878898
return nil
879899
}
880-
900+
#if Streams
901+
case .failedInitializingPeerConnection(let err):
902+
if let scope = err.scope.value{
903+
return String(scope)
904+
} else {
905+
return nil
906+
}
907+
#endif
881908
}
882909
}
883910
}

Sources/PrivMXEndpointSwift/Streams/JanusConnection.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,19 @@ import Foundation
1414
import WebRTC
1515
import PrivMXEndpointStreamsLow
1616

17-
class JanusConnection{
17+
public final class JanusConnection: @unchecked Sendable{
18+
var peerConnection : PeerConnection
19+
var sessionId: Int64
20+
var hasSubscriptions : Bool
1821

22+
init(
23+
peerConnection: PeerConnection,
24+
sessionId: Int64,
25+
hasSubscriptions: Bool
26+
) {
27+
self.peerConnection = peerConnection
28+
self.sessionId = sessionId
29+
self.hasSubscriptions = hasSubscriptions
30+
}
1931
}
20-
#endif
32+
#endif // Streams

Sources/PrivMXEndpointSwift/Streams/PeerConnection.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,34 @@
1212
import PrivMXEndpointSwiftNative
1313
import PrivMXEndpointStreamsLow
1414
import WebRTC
15+
import os.lock
1516

16-
public class PeerConnection{
17-
let rtcPeerConnection: RTCPeerConnection
18-
let rtcPeerConnectionObserver: PmxPeerConnectionObserver
17+
public enum ConnectionType:Sendable{
18+
case Subscriber
19+
case Publisher
20+
}
21+
22+
public class PeerConnection: @unchecked Sendable{
23+
enum State{
24+
case idle
25+
case working
26+
}
27+
var rtcPeerConnection: RTCPeerConnection
28+
var rtcPeerConnectionObserver: PmxPeerConnectionObserver
29+
var audioTracks : [String:AudioTrackInfo] = [:]
30+
var videoTracks : [String:VideoTrackInfo] = [:]
31+
var trackMutex = OSAllocatedUnfairLock<State>(initialState: State.idle)
32+
var keys : PMXKeyStore
1933

20-
init(rtcPeerConnection: RTCPeerConnection, rtcPeerConnectionObserver: PmxPeerConnectionObserver) {
34+
init(rtcPeerConnection: RTCPeerConnection,
35+
rtcPeerConnectionObserver: PmxPeerConnectionObserver,
36+
keys: PMXKeyStore
37+
) {
2138
self.rtcPeerConnection = rtcPeerConnection
2239
self.rtcPeerConnectionObserver = rtcPeerConnectionObserver
40+
self.keys = keys
2341
}
2442

2543
}
2644

27-
#endif
45+
#endif // Streams

Sources/PrivMXEndpointSwift/Streams/PeerConnectionManager.swift

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,115 @@
1212
#if Streams
1313
import Foundation
1414
import PrivMXEndpointStreamsLow
15+
import WebRTC
16+
import os.lock
1517

16-
final class PeerConnectionManager {
17-
private var _createPeerCOnnection : ((String) -> PeerConnection)?
18+
public final class PeerConnectionManager: Sendable {
19+
enum State{
20+
case reading,writing
21+
case idle
22+
}
23+
private let mutex = OSAllocatedUnfairLock(initialState: State.idle)
24+
private let _createPeerConnection : (@Sendable (String) -> PeerConnection)
25+
private let _onTrickle : (@Sendable (Int64,String) throws -> Void)
26+
nonisolated(unsafe) private var _connections : [String : [ConnectionType:JanusConnection]] = [:]
27+
nonisolated private var connections : [String : [ConnectionType:JanusConnection]]{
28+
set(val) {
29+
mutex.withLockUnchecked{
30+
state in
31+
state = .writing
32+
_connections = val
33+
state = .idle
34+
}
35+
}
36+
get {
37+
mutex.withLock{
38+
state in
39+
defer{
40+
state = .idle
41+
}
42+
state = .reading
43+
return _connections
44+
}
45+
46+
}
47+
}
1848

49+
init(
50+
_createPeerConnection: @Sendable @escaping (String) -> PeerConnection,
51+
_onTrickle: (@Sendable @escaping (Int64,String) throws -> Void)
52+
) {
53+
self._createPeerConnection = _createPeerConnection
54+
self._onTrickle = _onTrickle
55+
}
56+
57+
public func initializeConnection(
58+
in streamRoomId: String,
59+
ofType type: ConnectionType,
60+
sessionId: Int64 = -1
61+
) throws {
62+
if connections.contains(where: {$0 == streamRoomId && $1.keys.contains(type)}){
63+
throw PrivMXEndpointError.failedInitializingPeerConnection(privmx.InternalError(
64+
name: "Already Initialized",
65+
message: "JanusConnection with given parameters already initialized",
66+
description: "", code: nil, scope: nil))
67+
}
68+
if !connections.keys.contains(streamRoomId){
69+
connections[streamRoomId] = [:]
70+
}
71+
72+
let pc = _createPeerConnection(streamRoomId)
73+
74+
75+
pc.rtcPeerConnectionObserver.setIceCandidateGeneratedCallback({
76+
peerConnection,candidate in
77+
78+
let roomConnections = self.connections[streamRoomId] ?? [:]
79+
let roomConnection = roomConnections[type]
80+
if !candidate.sdp.isEmpty,let sessionId = roomConnection?.sessionId, sessionId > -1{
81+
var iceCandidate = candidate.sdp
82+
try? self._onTrickle(sessionId,iceCandidate)
83+
}
84+
})
85+
86+
connections[streamRoomId]![type] = JanusConnection(
87+
peerConnection: pc,
88+
sessionId: sessionId,
89+
hasSubscriptions: false)
90+
}
91+
92+
public func updateSessionForConnection(
93+
streamRoomId:String,
94+
connectionType: ConnectionType,
95+
sessionId: Int64
96+
) throws -> Void {
97+
if !connections.contains(where: {$0.key == streamRoomId}) || nil == connections[streamRoomId]?[connectionType] {
98+
try initializeConnection(
99+
in: streamRoomId,
100+
ofType: connectionType,
101+
sessionId: sessionId)
102+
}
103+
connections[streamRoomId]?[connectionType]?.sessionId = sessionId
104+
}
105+
106+
public func hasConnection(
107+
streamRoomId: String,
108+
connectionType: ConnectionType
109+
) throws -> Bool {
110+
return nil != connections[streamRoomId]?[connectionType]
111+
}
112+
113+
public func getConnectionWithSession(
114+
streamRoomId:String,
115+
connectionType: ConnectionType
116+
) throws -> JanusConnection {
117+
if !connections.contains(where: {$0.key == streamRoomId})
118+
|| nil == connections[streamRoomId]?[connectionType] {
119+
try initializeConnection(
120+
in: streamRoomId,
121+
ofType: connectionType)
122+
}
123+
return connections[streamRoomId]![connectionType]!
124+
}
19125
}
20-
#endif
126+
#endif // Streams

Sources/PrivMXEndpointSwift/Streams/PmxPeerConnectionObserver.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import Foundation
1414
import WebRTC
1515
import Synchronization
1616

17-
public class PmxPeerConnectionObserver:NSObject,RTCPeerConnectionDelegate, @unchecked Sendable{
17+
public final class PmxPeerConnectionObserver:NSObject,RTCPeerConnectionDelegate, @unchecked Sendable{
1818

1919

2020
private var onConnectionSignalingStateChanged: ((RTCPeerConnection,RTCSignalingState)->Void)?
@@ -26,8 +26,8 @@ public class PmxPeerConnectionObserver:NSObject,RTCPeerConnectionDelegate, @unch
2626
private var onIceCandidateErrorEvent:((RTCPeerConnection,RTCIceCandidateErrorEvent)->Void)?
2727
private var onIceConnectionStateChanged:((RTCPeerConnection,RTCIceConnectionState)->Void)?
2828
private var onIceGatheringStateChanged:((RTCPeerConnection,RTCIceGatheringState)->Void)?
29-
private var onIceCandindateGenerated:((RTCPeerConnection,RTCIceCandidate)->Void)?
30-
private var onIceCandindatesRemoved:((RTCPeerConnection,[RTCIceCandidate])->Void)?
29+
private var onIceCandidateGenerated:((RTCPeerConnection,RTCIceCandidate)->Void)?
30+
private var onIceCandidatesRemoved:((RTCPeerConnection,[RTCIceCandidate])->Void)?
3131

3232
private var onDataChannelOpened:((RTCPeerConnection,RTCDataChannel)->Void)?
3333
private var onStartedReceiving:((RTCPeerConnection,RTCRtpTransceiver)->Void)?
@@ -81,15 +81,15 @@ public class PmxPeerConnectionObserver:NSObject,RTCPeerConnectionDelegate, @unch
8181
){
8282
onIceGatheringStateChanged = cb
8383
}
84-
public func setIceCandindateGeneratedCallback(
84+
public func setIceCandidateGeneratedCallback(
8585
_ cb :(@Sendable (RTCPeerConnection,RTCIceCandidate)->Void)?
8686
){
87-
onIceCandindateGenerated = cb
87+
onIceCandidateGenerated = cb
8888
}
89-
public func setIceCandindatesRemovedCallback(
89+
public func setIceCandidatesRemovedCallback(
9090
_ cb :(@Sendable (RTCPeerConnection,[RTCIceCandidate])->Void)?
9191
){
92-
onIceCandindatesRemoved = cb
92+
onIceCandidatesRemoved = cb
9393
}
9494

9595
public func setDataChannelOpenedCallback(
@@ -171,14 +171,14 @@ public class PmxPeerConnectionObserver:NSObject,RTCPeerConnectionDelegate, @unch
171171
_ peerConnection: RTCPeerConnection,
172172
didGenerate candidate: RTCIceCandidate
173173
) {
174-
onIceCandindateGenerated?(peerConnection,candidate)
174+
onIceCandidateGenerated?(peerConnection,candidate)
175175
}
176176

177177
public func peerConnection(
178178
_ peerConnection: RTCPeerConnection,
179179
didRemove candidates: [RTCIceCandidate]
180180
) {
181-
onIceCandindatesRemoved?(peerConnection,candidates)
181+
onIceCandidatesRemoved?(peerConnection,candidates)
182182
}
183183

184184
public func peerConnection(

Sources/PrivMXEndpointSwift/Streams/TrackInfo.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// limitations under the License.
1010
//
1111

12+
#if Streams
1213
import Foundation
1314
import WebRTC
1415
import PrivMXEndpointStreamsLow
@@ -24,3 +25,4 @@ struct VideoTrackInfo{
2425
var sender: RTCRtpSender
2526
var frameCryptor: PMXFrameCryptorTransformer
2627
}
28+
#endif // Streams

0 commit comments

Comments
 (0)