diff --git a/android/build.gradle b/android/build.gradle index 9c5e6c3ea..38d28c544 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,6 +31,6 @@ android { dependencies { implementation "com.facebook.react:react-android:+" - api 'io.github.webrtc-sdk:android:137.7151.01' + api 'io.github.webrtc-sdk:android:137.7151.04' implementation "androidx.core:core:1.7.0" } diff --git a/android/src/main/java/com/oney/WebRTCModule/DataPacketCryptorManager.java b/android/src/main/java/com/oney/WebRTCModule/DataPacketCryptorManager.java new file mode 100644 index 000000000..1252f7a9d --- /dev/null +++ b/android/src/main/java/com/oney/WebRTCModule/DataPacketCryptorManager.java @@ -0,0 +1,63 @@ +package com.oney.WebRTCModule; + +import android.util.Log; + +import org.webrtc.DataPacketCryptor; +import org.webrtc.DataPacketCryptorFactory; +import org.webrtc.FrameCryptorAlgorithm; +import org.webrtc.FrameCryptorKeyProvider; + +import javax.annotation.Nullable; + +public class DataPacketCryptorManager { + private static final String TAG = DataPacketCryptorManager.class.getSimpleName(); + private final DataPacketCryptor dataPacketCryptor; + private boolean isDisposed = false; + + public DataPacketCryptorManager(FrameCryptorAlgorithm algorithm, FrameCryptorKeyProvider keyProvider) { + dataPacketCryptor = + DataPacketCryptorFactory.createDataPacketCryptor(FrameCryptorAlgorithm.AES_GCM, keyProvider); + } + + @Nullable + public synchronized DataPacketCryptor.EncryptedPacket encrypt(String participantId, int keyIndex, byte[] payload) { + if (isDisposed) { + return null; + } + + DataPacketCryptor.EncryptedPacket packet = dataPacketCryptor.encrypt(participantId, keyIndex, payload); + + if (packet == null) { + Log.i(TAG, "Error encrypting packet: null packet"); + return null; + } + + if (packet.payload == null) { + Log.i(TAG, "Error encrypting packet: null payload"); + return null; + } + if (packet.iv == null) { + Log.i(TAG, "Error encrypting packet: null iv returned"); + return null; + } + + return packet; + } + + @Nullable + public synchronized byte[] decrypt(String participantId, DataPacketCryptor.EncryptedPacket packet) { + if (isDisposed) { + return null; + } + + return dataPacketCryptor.decrypt(participantId, packet); + } + + public synchronized void dispose() { + if (isDisposed) { + return; + } + isDisposed = true; + dataPacketCryptor.dispose(); + } +} \ No newline at end of file diff --git a/android/src/main/java/com/oney/WebRTCModule/RTCFrameCryptor.java b/android/src/main/java/com/oney/WebRTCModule/RTCCryptoManager.java similarity index 78% rename from android/src/main/java/com/oney/WebRTCModule/RTCFrameCryptor.java rename to android/src/main/java/com/oney/WebRTCModule/RTCCryptoManager.java index 9293e2eb9..e6318da01 100644 --- a/android/src/main/java/com/oney/WebRTCModule/RTCFrameCryptor.java +++ b/android/src/main/java/com/oney/WebRTCModule/RTCCryptoManager.java @@ -11,6 +11,7 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; +import org.webrtc.DataPacketCryptor; import org.webrtc.FrameCryptor; import org.webrtc.FrameCryptorAlgorithm; import org.webrtc.FrameCryptorFactory; @@ -24,14 +25,15 @@ import java.util.Objects; import java.util.UUID; -public class RTCFrameCryptor { +public class RTCCryptoManager { private static final String TAG = "RTCFrameCryptor"; private final Map frameCryptos = new HashMap<>(); private final Map frameCryptoObservers = new HashMap<>(); private final Map keyProviders = new HashMap<>(); + private final Map dataPacketCryptors = new HashMap<>(); private final WebRTCModule webRTCModule; - public RTCFrameCryptor(WebRTCModule webRTCModule) { + public RTCCryptoManager(WebRTCModule webRTCModule) { this.webRTCModule = webRTCModule; } @@ -275,7 +277,7 @@ public void keyProviderRatchetSharedKey(ReadableMap params, @NonNull Promise res byte[] newKey = keyProvider.ratchetSharedKey(keyIndex); WritableMap paramsResult = Arguments.createMap(); - paramsResult.putString("result", Base64.encodeToString(newKey, Base64.DEFAULT)); + paramsResult.putString("result", Base64.encodeToString(newKey, Base64.NO_WRAP)); result.resolve(paramsResult); } @@ -291,7 +293,7 @@ public void keyProviderExportSharedKey(ReadableMap params, @NonNull Promise resu byte[] key = keyProvider.exportSharedKey(keyIndex); WritableMap paramsResult = Arguments.createMap(); - paramsResult.putString("result", Base64.encodeToString(key, Base64.DEFAULT)); + paramsResult.putString("result", Base64.encodeToString(key, Base64.NO_WRAP)); result.resolve(paramsResult); } @@ -325,7 +327,7 @@ public void keyProviderRatchetKey(ReadableMap params, @NonNull Promise result) { byte[] newKey = keyProvider.ratchetKey(participantId, keyIndex); WritableMap paramsResult = Arguments.createMap(); - paramsResult.putString("result", Base64.encodeToString(newKey, Base64.DEFAULT)); + paramsResult.putString("result", Base64.encodeToString(newKey, Base64.NO_WRAP)); result.resolve(paramsResult); } @@ -342,7 +344,7 @@ public void keyProviderExportKey(ReadableMap params, @NonNull Promise result) { byte[] key = keyProvider.exportKey(participantId, keyIndex); WritableMap paramsResult = Arguments.createMap(); - paramsResult.putString("result", Base64.encodeToString(key, Base64.DEFAULT)); + paramsResult.putString("result", Base64.encodeToString(key, Base64.NO_WRAP)); result.resolve(paramsResult); } @@ -353,7 +355,7 @@ public void keyProviderSetSifTrailer(ReadableMap params, @NonNull Promise result result.reject("keyProviderSetSifTrailerFailed", "keyProvider not found", (Throwable) null); return; } - byte[] sifTrailer = Base64.decode(params.getString("sifTrailer"), Base64.DEFAULT); + byte[] sifTrailer = Base64.decode(params.getString("sifTrailer"), Base64.NO_WRAP); keyProvider.setSifTrailer(sifTrailer); WritableMap paramsResult = Arguments.createMap(); @@ -375,8 +377,110 @@ public void keyProviderDispose(ReadableMap params, @NonNull Promise result) { result.resolve(paramsResult); } - private byte[] getBytesFromMap(ReadableMap map, String key, String isBase64Key) { - boolean isBase64 = map.getBoolean(isBase64Key); + public void dataPacketCryptorFactoryCreateDataPacketCryptor(ReadableMap params, @NonNull Promise result) { + int algorithm = params.getInt("algorithm"); + String keyProviderId = params.getString("keyProviderId"); + + FrameCryptorKeyProvider keyProvider = keyProviders.get(keyProviderId); + if (keyProvider == null) { + result.reject( + "dataPacketCryptorFactoryCreateDataPacketCryptorFailed", "keyProvider not found", (Throwable) null); + return; + } + + DataPacketCryptorManager cryptor = + new DataPacketCryptorManager(frameCryptorAlgorithmFromInt(algorithm), keyProvider); + + String dataPacketCryptorId = UUID.randomUUID().toString(); + dataPacketCryptors.put(dataPacketCryptorId, cryptor); + + WritableMap paramsResult = Arguments.createMap(); + paramsResult.putString("dataPacketCryptorId", dataPacketCryptorId); + result.resolve(paramsResult); + } + + public void dataPacketCryptorEncrypt(ReadableMap params, @NonNull Promise result) { + String dataPacketCryptorId = params.getString("dataPacketCryptorId"); + String participantId = params.getString("participantId"); + int keyIndex = params.getInt("keyIndex"); + byte[] data = getBytesFromMap(params, "data", null); + + DataPacketCryptorManager cryptor = dataPacketCryptors.get(dataPacketCryptorId); + + if (cryptor == null) { + result.reject("dataPacketCryptorEncryptFailed", "data packet cryptor not found", (Throwable) null); + return; + } + + DataPacketCryptor.EncryptedPacket packet = cryptor.encrypt(participantId, keyIndex, data); + + if (packet == null) { + result.reject("dataPacketCryptorEncryptFailed", "null packet", (Throwable) null); + return; + } + + WritableMap paramsResult = Arguments.createMap(); + paramsResult.putString("payload", Base64.encodeToString(packet.payload, Base64.NO_WRAP)); + paramsResult.putString("iv", Base64.encodeToString(packet.iv, Base64.NO_WRAP)); + paramsResult.putInt("keyIndex", packet.keyIndex); + result.resolve(paramsResult); + } + + public void dataPacketCryptorDecrypt(ReadableMap params, @NonNull Promise result) { + String dataPacketCryptorId = params.getString("dataPacketCryptorId"); + String participantId = params.getString("participantId"); + int keyIndex = params.getInt("keyIndex"); + byte[] payload = getBytesFromMap(params, "payload", null); + byte[] iv = getBytesFromMap(params, "iv", null); + + DataPacketCryptorManager cryptor = dataPacketCryptors.get(dataPacketCryptorId); + + if (cryptor == null) { + result.reject("dataPacketCryptorDecryptFailed", "data packet cryptor not found", (Throwable) null); + return; + } + + DataPacketCryptor.EncryptedPacket packet = new DataPacketCryptor.EncryptedPacket(payload, iv, keyIndex); + + byte[] decryptedData = cryptor.decrypt(participantId, packet); + + if (decryptedData == null) { + result.reject("dataPacketCryptorDecryptFailed", "null decrypted data", (Throwable) null); + return; + } + + WritableMap paramsResult = Arguments.createMap(); + paramsResult.putString("data", Base64.encodeToString(decryptedData, Base64.NO_WRAP)); + result.resolve(paramsResult); + } + + public void dataPacketCryptorDispose(ReadableMap params, @NonNull Promise result) { + String dataPacketCryptorId = params.getString("dataPacketCryptorId"); + + DataPacketCryptorManager cryptor = dataPacketCryptors.get(dataPacketCryptorId); + + if (cryptor == null) { + result.reject("dataPacketCryptorDisposeFailed", "data packet cryptor not found", (Throwable) null); + return; + } + + cryptor.dispose(); + dataPacketCryptors.remove(dataPacketCryptorId); + WritableMap paramsResult = Arguments.createMap(); + paramsResult.putString("result", "success"); + + result.resolve(paramsResult); + } + + private byte[] getBytesFromMap(ReadableMap map, String key, @Nullable String isBase64Key) { + boolean isBase64; + + if (isBase64Key != null) { + isBase64 = map.getBoolean(isBase64Key); + } else { + isBase64 = true; + } + byte[] bytes; if (isBase64) { diff --git a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java index e9337be1c..001fbee8b 100644 --- a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +++ b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java @@ -1461,7 +1461,7 @@ public void dataChannelSend(int peerConnectionId, String reactTag, String data, // Frame Cryptor methods //////////////////////////////// - RTCFrameCryptor frameCryptor = new RTCFrameCryptor(this); + RTCCryptoManager frameCryptor = new RTCCryptoManager(this); @ReactMethod(isBlockingSynchronousMethod = true) public String frameCryptorFactoryCreateFrameCryptor(ReadableMap config) { @@ -1538,6 +1538,26 @@ public void keyProviderDispose(ReadableMap config, Promise promise) { frameCryptor.keyProviderDispose(config, promise); } + @ReactMethod + public void dataPacketCryptorFactoryCreateDataPacketCryptor(ReadableMap params, @NonNull Promise result) { + frameCryptor.dataPacketCryptorFactoryCreateDataPacketCryptor(params, result); + } + + @ReactMethod + public void dataPacketCryptorEncrypt(ReadableMap params, @NonNull Promise result) { + frameCryptor.dataPacketCryptorEncrypt(params, result); + } + + @ReactMethod + public void dataPacketCryptorDecrypt(ReadableMap params, @NonNull Promise result) { + frameCryptor.dataPacketCryptorDecrypt(params, result); + } + + @ReactMethod + public void dataPacketCryptorDispose(ReadableMap params, @NonNull Promise result) { + frameCryptor.dataPacketCryptorDispose(params, result); + } + @ReactMethod public void addListener(String eventName) { // Keep: Required for RN built in Event Emitter Calls. diff --git a/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m b/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m index befb031ff..dd3ce112e 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCFrameCryptor.m @@ -26,8 +26,12 @@ - (RTCCryptorAlgorithm)getAlgorithm:(NSNumber *)algorithm { } } -- (NSData *)bytesFromMap:(NSDictionary *)map key:(NSString *)key isBase64Key:(NSString *)isBase64Key { - BOOL isBase64 = [map[isBase64Key] boolValue]; +- (NSData *)bytesFromMap:(NSDictionary *)map key:(NSString *)key isBase64Key:(nullable NSString *)isBase64Key { + BOOL isBase64 = YES; + if (isBase64Key) { + isBase64 = [map[isBase64Key] boolValue]; + } + if (isBase64) { return [[NSData alloc] initWithBase64EncodedString:map[key] options:0]; } else { @@ -325,7 +329,7 @@ - (nullable RTCFrameCryptorKeyProvider *)getKeyProviderForId:(NSString *)keyProv } NSData *newKey = [keyProvider ratchetSharedKey:[keyIndex intValue]]; - resolve(@{@"result" : newKey}); + resolve(@{@"result" : [newKey base64EncodedStringWithOptions:0]}); } RCT_EXPORT_METHOD(keyProviderExportSharedKey @@ -344,7 +348,7 @@ - (nullable RTCFrameCryptorKeyProvider *)getKeyProviderForId:(NSString *)keyProv } NSData *key = [keyProvider exportSharedKey:[keyIndex intValue]]; - resolve(@{@"result" : key}); + resolve(@{@"result" : [key base64EncodedStringWithOptions:0]}); } RCT_EXPORT_METHOD(keyProviderSetKey @@ -400,7 +404,7 @@ - (nullable RTCFrameCryptorKeyProvider *)getKeyProviderForId:(NSString *)keyProv } NSData *newKey = [keyProvider ratchetKey:participantId withIndex:[keyIndex intValue]]; - resolve(@{@"result" : newKey}); + resolve(@{@"result" : [newKey base64EncodedStringWithOptions:0]}); } RCT_EXPORT_METHOD(keyProviderExportKey @@ -425,7 +429,7 @@ - (nullable RTCFrameCryptorKeyProvider *)getKeyProviderForId:(NSString *)keyProv } NSData *key = [keyProvider exportKey:participantId withIndex:[keyIndex intValue]]; - resolve(@{@"result" : key}); + resolve(@{@"result" : [key base64EncodedStringWithOptions:0]}); } RCT_EXPORT_METHOD(keyProviderSetSifTrailer @@ -481,6 +485,108 @@ - (NSString *)stringFromState:(RTCFrameCryptorState)state { } } +RCT_EXPORT_METHOD(dataPacketCryptorFactoryCreateDataPacketCryptor + : (nonnull NSDictionary *)constraints resolver + : (RCTPromiseResolveBlock)resolve rejecter + : (RCTPromiseRejectBlock)reject) { + NSNumber *algorithm = constraints[@"algorithm"]; + NSString *keyProviderId = constraints[@"keyProviderId"]; + if (keyProviderId == nil) { + reject(@"dataPacketCryptorFactoryCreateDataPacketCryptorFailed", @"Invalid keyProviderId", nil); + return; + } + + RTCFrameCryptorKeyProvider *keyProvider = self.keyProviders[keyProviderId]; + if (keyProvider == nil) { + reject(@"getKeyProviderForIdFailed", @"Invalid keyProviderId", nil); + return; + } + + RTCDataPacketCryptor *cryptor = [[RTCDataPacketCryptor alloc] initWithAlgorithm:[self getAlgorithm:algorithm] + keyProvider:keyProvider]; + NSString *cryptorId = [[NSUUID UUID] UUIDString]; + + self.dataPacketCryptors[cryptorId] = cryptor; + + resolve(@{@"dataPacketCryptorId" : cryptorId}); +} + +RCT_EXPORT_METHOD(dataPacketCryptorEncrypt + : (nonnull NSDictionary *)constraints resolver + : (RCTPromiseResolveBlock)resolve rejecter + : (RCTPromiseRejectBlock)reject) { + NSString *cryptorId = constraints[@"dataPacketCryptorId"]; + NSString *participantId = constraints[@"participantId"]; + NSNumber *keyIndex = constraints[@"keyIndex"]; + NSData *data = [self bytesFromMap:constraints key:@"data" isBase64Key:nil]; + + RTCDataPacketCryptor *cryptor = self.dataPacketCryptors[cryptorId]; + + if (cryptor == nil) { + reject(@"dataPacketCryptorEncryptFailed", @"data packet cryptor not found", nil); + return; + } + + RTCEncryptedPacket *packet = [cryptor encrypt:participantId keyIndex:[keyIndex unsignedIntValue] data:data]; + + if (packet == nil) { + reject(@"dataPacketCryptorEncryptFailed", @"packet encryption failed", nil); + return; + } + + resolve(@{ + @"payload" : [packet.data base64EncodedStringWithOptions:0], + @"iv" : [packet.iv base64EncodedStringWithOptions:0], + @"keyIndex" : [NSNumber numberWithUnsignedInt:packet.keyIndex] + }); +} + +RCT_EXPORT_METHOD(dataPacketCryptorDecrypt + : (nonnull NSDictionary *)constraints resolver + : (RCTPromiseResolveBlock)resolve rejecter + : (RCTPromiseRejectBlock)reject) { + NSString *cryptorId = constraints[@"dataPacketCryptorId"]; + NSString *participantId = constraints[@"participantId"]; + NSNumber *keyIndex = constraints[@"keyIndex"]; + NSData *payload = [self bytesFromMap:constraints key:@"payload" isBase64Key:nil]; + NSData *iv = [self bytesFromMap:constraints key:@"iv" isBase64Key:nil]; + + RTCDataPacketCryptor *cryptor = self.dataPacketCryptors[cryptorId]; + + if (cryptor == nil) { + reject(@"dataPacketCryptorDecryptFailed", @"data packet cryptor not found", nil); + return; + } + + RTCEncryptedPacket *packet = [[RTCEncryptedPacket alloc] initWithData:payload + iv:iv + keyIndex:[keyIndex unsignedIntValue]]; + NSData *decryptedData = [cryptor decrypt:participantId encryptedPacket:packet]; + + if (decryptedData == nil) { + reject(@"dataPacketCryptorDecryptFailed", @"packet decryption failed", nil); + return; + } + + resolve(@{@"data" : [decryptedData base64EncodedStringWithOptions:0]}); +} +RCT_EXPORT_METHOD(dataPacketCryptorDispose + : (nonnull NSDictionary *)constraints resolver + : (RCTPromiseResolveBlock)resolve rejecter + : (RCTPromiseRejectBlock)reject) { + NSString *cryptorId = constraints[@"dataPacketCryptorId"]; + + RTCDataPacketCryptor *cryptor = self.dataPacketCryptors[cryptorId]; + + if (cryptor == nil) { + reject(@"dataPacketCryptorDisposeFailed", @"data packet cryptor not found", nil); + return; + } + + [self.dataPacketCryptors removeObjectForKey:cryptorId]; + resolve(@{@"result" : @"success"}); +} + #pragma mark - RTCFrameCryptorDelegate methods - (void)frameCryptor:(RTC_OBJC_TYPE(RTCFrameCryptor) *)frameCryptor diff --git a/ios/RCTWebRTC/WebRTCModule.h b/ios/RCTWebRTC/WebRTCModule.h index 5b41ec598..4e0767743 100644 --- a/ios/RCTWebRTC/WebRTCModule.h +++ b/ios/RCTWebRTC/WebRTCModule.h @@ -37,6 +37,7 @@ static NSString *const kEventFrameCryptionStateChanged = @"frameCryptionStateCha @property(nonatomic, strong) NSMutableDictionary *frameCryptors; @property(nonatomic, strong) NSMutableDictionary *keyProviders; +@property(nonatomic, strong) NSMutableDictionary *dataPacketCryptors; - (RTCMediaStream *)streamForReactTag:(NSString *)reactTag; diff --git a/ios/RCTWebRTC/WebRTCModule.m b/ios/RCTWebRTC/WebRTCModule.m index 27fa77fd0..51397a17b 100644 --- a/ios/RCTWebRTC/WebRTCModule.m +++ b/ios/RCTWebRTC/WebRTCModule.m @@ -95,6 +95,7 @@ - (instancetype)init { _frameCryptors = [NSMutableDictionary new]; _keyProviders = [NSMutableDictionary new]; + _dataPacketCryptors = [NSMutableDictionary new]; dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, -1); diff --git a/livekit-react-native-webrtc.podspec b/livekit-react-native-webrtc.podspec index 0f05889ae..c2839735d 100644 --- a/livekit-react-native-webrtc.podspec +++ b/livekit-react-native-webrtc.podspec @@ -19,7 +19,7 @@ Pod::Spec.new do |s| s.libraries = 'c', 'sqlite3', 'stdc++' s.framework = 'AudioToolbox','AVFoundation', 'CoreAudio', 'CoreGraphics', 'CoreVideo', 'GLKit', 'VideoToolbox' s.dependency 'React-Core' - s.dependency 'WebRTC-SDK', '=137.7151.02' + s.dependency 'WebRTC-SDK', '=137.7151.04' # Swift/Objective-C compatibility s.pod_target_xcconfig = { diff --git a/src/RTCDataPacketCryptor.ts b/src/RTCDataPacketCryptor.ts new file mode 100644 index 000000000..c70b67f8d --- /dev/null +++ b/src/RTCDataPacketCryptor.ts @@ -0,0 +1,90 @@ +import * as base64 from 'base64-js'; +import { NativeModules } from 'react-native'; + +import Logger from './Logger'; +const { WebRTCModule } = NativeModules; +const log = new Logger('pc'); + +export interface RTCEncryptedPacket { + payload: Uint8Array, + iv: Uint8Array, + keyIndex: number, +} + +export default class RTCDataPacketCryptor { + _id: string; + + constructor(dataPacketCryptorId: string) { + this._id = dataPacketCryptorId; + } + + async encrypt(participantId: string, keyIndex: number, data: Uint8Array): Promise { + const params = { + dataPacketCryptorId: this._id, + participantId, + keyIndex, + data: base64.fromByteArray(data) + }; + + const result = await WebRTCModule.dataPacketCryptorEncrypt(params); + + if (!result) { + log.info('encrypt: result null'); + + return null; + } + + if (result.payload === undefined) { + log.info('encrypt: payload null'); + + return null; + } + + if (result.iv === undefined) { + log.info('encrypt: iv null'); + + return null; + } + + if (result.keyIndex === undefined) { + log.info('encrypt: keyIndex null'); + + return null; + } + + return { + payload: base64.toByteArray(result.payload), + iv: base64.toByteArray(result.iv), + keyIndex: result.keyIndex + }; + } + + async decrypt(participantId: string, packet: RTCEncryptedPacket): Promise { + const params = { + dataPacketCryptorId: this._id, + participantId, + payload: base64.fromByteArray(packet.payload), + iv: base64.fromByteArray(packet.iv), + keyIndex: packet.keyIndex, + }; + + const result = await WebRTCModule.dataPacketCryptorDecrypt(params); + + if (!result) { + log.info('decrypt: result null'); + + return null; + } + + return base64.toByteArray(result.data); + } + + + async dispose() { + const params = { + dataPacketCryptorId: this._id, + }; + + await WebRTCModule.dataPacketCryptorDispose(params); + } +} diff --git a/src/RTCDataPacketCryptorFactory.ts b/src/RTCDataPacketCryptorFactory.ts new file mode 100644 index 000000000..84798227a --- /dev/null +++ b/src/RTCDataPacketCryptorFactory.ts @@ -0,0 +1,25 @@ +import { NativeModules } from 'react-native'; + +import RTCDataPacketCryptor from './RTCDataPacketCryptor'; +import RTCFrameCryptorAlgorithm from './RTCFrameCryptorFactory'; +import RTCKeyProvider from './RTCKeyProvider'; +const { WebRTCModule } = NativeModules; + +export default class RTCDataPacketCryptorFactory { + static async createDataPacketCryptor( + algorithm: RTCFrameCryptorAlgorithm, + keyProvider: RTCKeyProvider + ): Promise { + const params = { + 'algorithm': algorithm, + 'keyProviderId': keyProvider._id + }; + const result = await WebRTCModule.dataPacketCryptorFactoryCreateDataPacketCryptor(params); + + if (!result) { + throw new Error('Error when creating data packet cryptor for sender'); + } + + return new RTCDataPacketCryptor(result.dataPacketCryptorId); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index fc8908959..eaedc773e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,8 @@ import MediaStreamTrack, { type MediaTrackSettings } from './MediaStreamTrack'; import MediaStreamTrackEvent from './MediaStreamTrackEvent'; import permissions from './Permissions'; import RTCAudioSession from './RTCAudioSession'; +import RTCDataPacketCryptor, { RTCEncryptedPacket } from './RTCDataPacketCryptor'; +import RTCDataPacketCryptorFactory from './RTCDataPacketCryptorFactory'; import RTCErrorEvent from './RTCErrorEvent'; import RTCFrameCryptor, { RTCFrameCryptorState } from './RTCFrameCryptor'; import RTCFrameCryptorFactory, { RTCFrameCryptorAlgorithm, RTCKeyProviderOptions } from './RTCFrameCryptorFactory'; @@ -47,6 +49,9 @@ export { RTCRtpSender, RTCErrorEvent, RTCAudioSession, + RTCDataPacketCryptor, + RTCDataPacketCryptorFactory, + RTCEncryptedPacket, RTCFrameCryptor, RTCFrameCryptorAlgorithm, RTCFrameCryptorState,