-
Notifications
You must be signed in to change notification settings - Fork 224
Simplify enabling E2EE with Session API #1053
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| minor type="added" "Simplify enabling E2EE with Session API" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,12 +13,59 @@ | |
| // limitations under the License. | ||
|
|
||
| import '../core/room.dart'; | ||
| import '../e2ee/key_provider.dart'; | ||
|
|
||
| /// Encryption key configuration for a [Session]. | ||
| /// | ||
| /// Use one of the named constructors to specify either a shared passphrase | ||
| /// or a pre-configured [BaseKeyProvider]. | ||
| sealed class SessionEncryptionKey { | ||
| const SessionEncryptionKey(); | ||
|
|
||
| /// Use a shared passphrase string. | ||
| /// | ||
| /// A [BaseKeyProvider] is created internally using the string as a shared | ||
| /// key (recommended for maximum compatibility across SDKs). | ||
| const factory SessionEncryptionKey.sharedKey(String key) = SharedKeyEncryption; | ||
|
|
||
| /// Use a pre-configured [BaseKeyProvider] for custom key management. | ||
| const factory SessionEncryptionKey.keyProvider(BaseKeyProvider provider) = KeyProviderEncryption; | ||
| } | ||
|
|
||
| /// A shared passphrase used to derive encryption keys. | ||
| class SharedKeyEncryption extends SessionEncryptionKey { | ||
| final String sharedKey; | ||
| const SharedKeyEncryption(this.sharedKey); | ||
| } | ||
|
|
||
| /// A pre-configured [BaseKeyProvider] instance. | ||
| class KeyProviderEncryption extends SessionEncryptionKey { | ||
| final BaseKeyProvider keyProvider; | ||
| const KeyProviderEncryption(this.keyProvider); | ||
| } | ||
|
|
||
| /// Encryption configuration for a [Session]. | ||
| class SessionEncryptionOptions { | ||
| /// The encryption key, either a shared passphrase or a custom key provider. | ||
| final SessionEncryptionKey key; | ||
|
|
||
| const SessionEncryptionOptions({required this.key}); | ||
|
|
||
| /// Creates encryption options with a shared passphrase string. | ||
| SessionEncryptionOptions.sharedKey(String key) : key = SharedKeyEncryption(key); | ||
|
|
||
| /// Creates encryption options with a pre-configured [BaseKeyProvider]. | ||
| SessionEncryptionOptions.keyProvider(BaseKeyProvider provider) : key = KeyProviderEncryption(provider); | ||
| } | ||
|
|
||
| /// Options for creating a [Session]. | ||
| class SessionOptions { | ||
| /// The underlying [Room] used by the session. | ||
| final Room room; | ||
|
|
||
| /// Whether a custom [Room] was explicitly provided. | ||
| final bool isRoomProvided; | ||
|
|
||
| /// Whether to enable audio pre-connect with [PreConnectAudioBuffer]. | ||
| /// | ||
| /// If enabled, the microphone is activated before connecting to the room. | ||
|
|
@@ -30,21 +77,55 @@ class SessionOptions { | |
| /// to a failed state. | ||
| final Duration agentConnectTimeout; | ||
|
|
||
| /// Optional encryption configuration for end-to-end encryption. | ||
| /// | ||
| /// When provided, the session will configure E2EE on the room before | ||
| /// connecting. Use [Session.setEncryptionEnabled] to toggle encryption | ||
| /// after the session has started. | ||
| final SessionEncryptionOptions? encryption; | ||
|
|
||
| SessionOptions({ | ||
| Room? room, | ||
| this.preConnectAudio = true, | ||
| this.agentConnectTimeout = const Duration(seconds: 20), | ||
| }) : room = room ?? Room(); | ||
| this.encryption, | ||
| }) : isRoomProvided = room != null, | ||
| room = room ?? Room() { | ||
| _validateEncryptionConfiguration(); | ||
| } | ||
|
|
||
| SessionOptions._({ | ||
| required this.room, | ||
| required this.isRoomProvided, | ||
| required this.preConnectAudio, | ||
| required this.agentConnectTimeout, | ||
| this.encryption, | ||
| }) { | ||
| _validateEncryptionConfiguration(); | ||
| } | ||
|
Comment on lines
87
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might be a bad / nonsensical suggestion as I am not too familiar with typical flutter patterns, but would be worthwhile to get all session initialization (constructor and alternate constructor paths like the |
||
|
|
||
| SessionOptions copyWith({ | ||
| Room? room, | ||
| bool? preConnectAudio, | ||
| Duration? agentConnectTimeout, | ||
| SessionEncryptionOptions? encryption, | ||
| }) { | ||
| return SessionOptions( | ||
| return SessionOptions._( | ||
| room: room ?? this.room, | ||
| isRoomProvided: room != null ? true : isRoomProvided, | ||
| preConnectAudio: preConnectAudio ?? this.preConnectAudio, | ||
| agentConnectTimeout: agentConnectTimeout ?? this.agentConnectTimeout, | ||
| encryption: encryption ?? this.encryption, | ||
| ); | ||
| } | ||
|
|
||
| void _validateEncryptionConfiguration() { | ||
| if (isRoomProvided && encryption != null) { | ||
| throw ArgumentError.value( | ||
| encryption, | ||
| 'encryption', | ||
| 'Cannot be provided when room is also provided. Configure E2EE on the Room directly.', | ||
| ); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curiously, do we need to pass the encryption over to the room in this case ?