Skip to content

Commit be4141e

Browse files
update the code to adapt the style / apis like other sdk
1 parent 3a09f35 commit be4141e

File tree

6 files changed

+353
-222
lines changed

6 files changed

+353
-222
lines changed

examples/simple_room/main.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,15 @@ int main(int argc, char *argv[]) {
278278
options.dynacast = false;
279279

280280
if (enable_e2ee) {
281-
livekit::E2EEOptions e2ee;
282-
e2ee.encryption_type = livekit::EncryptionType::GCM;
281+
livekit::E2EEOptions encryption;
282+
encryption.encryption_type = livekit::EncryptionType::GCM;
283283
// Optional shared key: if empty, we enable E2EE without setting a shared
284284
// key. (Advanced use: keys can be set/ratcheted later via
285285
// E2EEManager/KeyProvider.)
286286
if (!e2ee_key.empty()) {
287-
e2ee.shared_key = toBytes(e2ee_key);
287+
encryption.key_provider_options.shared_key = toBytes(e2ee_key);
288288
}
289-
options.e2ee = e2ee;
289+
options.encryption = encryption;
290290
if (!e2ee_key.empty()) {
291291
std::cout << "[E2EE] enabled : (shared key length=" << e2ee_key.size()
292292
<< ")\n";
@@ -385,19 +385,23 @@ int main(int argc, char *argv[]) {
385385
std::this_thread::sleep_for(std::chrono::milliseconds(10));
386386
}
387387

388-
// Shutdown the audio thread.
388+
// Shutdown the audio / video capture threads.
389389
media.stopMic();
390+
media.stopCamera();
391+
392+
// Drain any queued tasks that might still try to update the renderer /
393+
// speaker
394+
MainThreadDispatcher::update();
395+
396+
// Must be cleaned up before FfiClient::instance().shutdown();
397+
room->setDelegate(nullptr);
390398

391399
// Clean up the audio track publishment
392400
room->localParticipant()->unpublishTrack(audioPub->sid());
393401

394-
media.stopCamera();
395-
396402
// Clean up the video track publishment
397403
room->localParticipant()->unpublishTrack(videoPub->sid());
398404

399-
// Must be cleaned up before FfiClient::instance().shutdown();
400-
room->setDelegate(nullptr);
401405
room.reset();
402406

403407
FfiClient::instance().shutdown();

include/livekit/e2ee.h

Lines changed: 168 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -24,143 +24,198 @@
2424

2525
namespace livekit {
2626

27-
/* Encryption algorithm type used by the underlying stack. Keep this aligned
28-
* with your proto enum. */
29-
enum class EncryptionType { NONE = 0, GCM = 1, CUSTOM = 2 };
30-
31-
/// End-to-end encryption (E2EE) configuration.
32-
///
33-
/// When enabled, media frames are encrypted before being sent and
34-
/// decrypted on receipt. Keys may be provided up-front (shared-key mode)
35-
/// or supplied by other mechanisms supported by the underlying runtime.
36-
struct E2EEOptions {
37-
bool enabled;
38-
/// Encryption algorithm to use.
39-
///
40-
/// GCM is the default and recommended option.
41-
EncryptionType encryption_type = EncryptionType::GCM;
27+
/* Encryption algorithm type used by the underlying stack.
28+
* Keep this aligned with your proto enum values. */
29+
enum class EncryptionType {
30+
NONE = 0,
31+
GCM = 1,
32+
CUSTOM = 2,
33+
};
4234

43-
/// Shared static key for shared-key E2EE.
35+
/* Defaults (match other SDKs / Python defaults). */
36+
inline constexpr const char *kDefaultRatchetSalt = "LKFrameEncryptionKey";
37+
inline constexpr int kDefaultRatchetWindowSize = 16;
38+
inline constexpr int kDefaultFailureTolerance = -1;
39+
40+
/**
41+
* Options for configuring the key provider used by E2EE.
42+
*
43+
* Notes:
44+
* - `shared_key` is optional. If omitted, the application may set keys later
45+
* (e.g. via KeyProvider::setSharedKey / per-participant keys).
46+
* - `ratchet_salt` may be empty to indicate "use implementation default".
47+
* - `ratchet_window_size` and `failure_tolerance` use SDK defaults unless
48+
* overridden.
49+
*/
50+
struct EncryptionKeyProviderOptions {
51+
/// Shared static key for "shared-key E2EE" (optional).
4452
///
45-
/// When using shared-key E2EE, this key must be provided and must be
46-
/// identical (byte-for-byte) for all participants in the room in order
47-
/// to successfully encrypt and decrypt media.
53+
/// If set, it must be identical (byte-for-byte) across all participants
54+
/// that are expected to decrypt each other’s media.
4855
///
49-
/// If this is empty while E2EE is enabled, media cannot be decrypted
50-
/// and participants will not be able to communicate (e.g. black video /
51-
/// silent audio).
52-
std::vector<std::uint8_t> shared_key;
56+
/// If not set, keys must be provided out-of-band later (e.g. via KeyProvider
57+
/// APIs).
58+
std::optional<std::vector<std::uint8_t>> shared_key;
5359

54-
/// Optional salt used when deriving ratcheted encryption keys.
60+
/// Salt used when deriving ratcheted keys.
5561
///
56-
/// If empty, a default salt is used by the underlying implementation.
57-
std::vector<std::uint8_t> ratchet_salt;
62+
/// If empty, the underlying implementation default is used.
63+
std::vector<std::uint8_t> ratchet_salt = std::vector<std::uint8_t>(
64+
kDefaultRatchetSalt, kDefaultRatchetSalt + std::char_traits<char>::length(
65+
kDefaultRatchetSalt));
5866

59-
/// Optional ratchet window size.
60-
///
6167
/// Controls how many previous keys are retained during ratcheting.
62-
/// A value of 0 indicates that the implementation default is used.
63-
int ratchet_window_size = 0;
68+
int ratchet_window_size = kDefaultRatchetWindowSize;
6469

65-
/// Optional failure tolerance for ratcheting.
66-
///
67-
/// Specifies how many consecutive ratcheting failures are tolerated
68-
/// before encryption errors are reported. A value of 0 indicates
69-
/// that the implementation default is used.
70-
int failure_tolerance = 0;
70+
/// Number of tolerated ratchet failures before reporting encryption errors.
71+
int failure_tolerance = kDefaultFailureTolerance;
72+
};
73+
74+
/**
75+
* End-to-end encryption (E2EE) configuration for a room.
76+
*
77+
* Provide this in RoomOptions to initialize E2EE support.
78+
*
79+
* IMPORTANT:
80+
* - Providing E2EEOptions means "E2EE support is configured for this room".
81+
* - Whether encryption is actively applied can still be toggled at runtime via
82+
* E2EEManager::setEnabled().
83+
* - A room can be configured for E2EE even if no shared key is provided yet.
84+
* In that case, the app must supply keys later via KeyProvider (shared-key or
85+
* per-participant).
86+
*/
87+
struct E2EEOptions {
88+
EncryptionKeyProviderOptions key_provider_options{};
89+
EncryptionType encryption_type = EncryptionType::GCM; // default & recommended
7190
};
7291

92+
/**
93+
* E2EE manager for a connected room.
94+
*
95+
* Lifetime:
96+
* - Owned by Room. Applications must not construct E2EEManager directly.
97+
*
98+
* Enablement model:
99+
* - If the Room was created with `RoomOptions.e2ee` set, the room will expose
100+
* a non-null E2EEManager via Room::E2eeManager().
101+
* - If the Room was created without E2EE options, Room::E2eeManager() may be
102+
* null.
103+
*
104+
* Key model:
105+
* - Keys are managed via KeyProvider (shared-key or per-participant).
106+
* - Providing a shared key up-front is convenient for shared-key E2EE, but is
107+
* not required by the API shape (keys may be supplied later).
108+
*/
73109
class E2EEManager {
74110
public:
75-
virtual ~E2EEManager();
76-
111+
/** If your application requires key rotation during the lifetime of a single
112+
* room or unique keys per participant (such as when implementing the MEGOLM
113+
* or MLS protocol), you' can do it via key provider and frame cryptor. refer
114+
* https://docs.livekit.io/home/client/encryption/#custom-key-provider doe
115+
* details
116+
* */
117+
class KeyProvider {
118+
public:
119+
~KeyProvider() = default;
120+
121+
KeyProvider(const KeyProvider &) = delete;
122+
KeyProvider &operator=(const KeyProvider &) = delete;
123+
KeyProvider(KeyProvider &&) noexcept = default;
124+
KeyProvider &operator=(KeyProvider &&) noexcept = default;
125+
126+
/// Returns the options used to initialize this KeyProvider.
127+
const EncryptionKeyProviderOptions &options() const;
128+
129+
/// Sets the shared key for the given key slot.
130+
void setSharedKey(const std::vector<std::uint8_t> &key, int key_index = 0);
131+
132+
/// Exports the shared key for a given key slot.
133+
std::vector<std::uint8_t> exportSharedKey(int key_index = 0) const;
134+
135+
/// Ratchets the shared key at key_index and returns the newly derived key.
136+
std::vector<std::uint8_t> ratchetSharedKey(int key_index = 0);
137+
138+
/// Sets a key for a specific participant identity.
139+
void setKey(const std::string &participant_identity,
140+
const std::vector<std::uint8_t> &key, int key_index = 0);
141+
142+
/// Exports a participant-specific key.
143+
std::vector<std::uint8_t> exportKey(const std::string &participant_identity,
144+
int key_index = 0) const;
145+
146+
/// Ratchets a participant-specific key and returns the new key.
147+
std::vector<std::uint8_t>
148+
ratchetKey(const std::string &participant_identity, int key_index = 0);
149+
150+
private:
151+
friend class E2EEManager;
152+
KeyProvider(std::uint64_t room_handle,
153+
EncryptionKeyProviderOptions options);
154+
std::uint64_t room_handle_{0};
155+
EncryptionKeyProviderOptions options_;
156+
};
157+
158+
class FrameCryptor {
159+
public:
160+
FrameCryptor(std::uint64_t room_handle, std::string participant_identity,
161+
int key_index, bool enabled);
162+
~FrameCryptor() = default;
163+
FrameCryptor(const FrameCryptor &) = delete;
164+
FrameCryptor &operator=(const FrameCryptor &) = delete;
165+
FrameCryptor(FrameCryptor &&) noexcept = default;
166+
FrameCryptor &operator=(FrameCryptor &&) noexcept = default;
167+
168+
const std::string &participantIdentity() const;
169+
int keyIndex() const;
170+
bool enabled() const;
171+
172+
/// Enables or disables frame encryption/decryption for this participant.
173+
void setEnabled(bool enabled);
174+
175+
/// Sets the active key index for this participant cryptor.
176+
void setKeyIndex(int key_index);
177+
178+
private:
179+
std::uint64_t room_handle_{0};
180+
bool enabled_{false};
181+
std::string participant_identity_;
182+
int key_index_{0};
183+
};
184+
185+
~E2EEManager() = default;
77186
E2EEManager(const E2EEManager &) = delete;
78187
E2EEManager &operator=(const E2EEManager &) = delete;
188+
E2EEManager(E2EEManager &&) noexcept = delete;
189+
E2EEManager &operator=(E2EEManager &&) noexcept = delete;
79190

80-
E2EEManager(E2EEManager &&) noexcept;
81-
E2EEManager &operator=(E2EEManager &&) noexcept;
82-
83-
/**
84-
* Returns whether end-to-end encryption (E2EE) is currently enabled.
85-
*
86-
* This reflects the runtime encryption state for media tracks
87-
* associated with the room.
88-
*/
191+
/// Returns whether E2EE is currently enabled for this room at runtime.
89192
bool enabled() const;
90193

91-
/**
92-
* Enable or disable end-to-end encryption at runtime.
93-
*
94-
* Disabling E2EE will stop encrypting outgoing media and stop
95-
* decrypting incoming media.
96-
*
97-
* NOTE:
98-
* - All participants must agree on E2EE state and keys in order
99-
* to successfully exchange media.
100-
* - Disabling E2EE while other participants still have it enabled
101-
* will result in media being undecodable.
102-
*/
194+
/// Enable or disable E2EE at runtime.
195+
///
196+
/// NOTE:
197+
/// - Enabling E2EE without having compatible keys set across participants
198+
/// will result in undecodable media (black video / silent audio).
103199
void setEnabled(bool enabled);
104200

105-
/**
106-
* Set or replace the shared encryption key at the given key index.
107-
*
108-
* This is typically used for:
109-
* - Manual key rotation
110-
*
111-
* The provided key MUST be identical across all participants
112-
* using shared-key E2EE, otherwise media decryption will fail.
113-
*
114-
* @param key Raw key bytes
115-
* @param key_index Index of the key to set (default: 0)
116-
*/
117-
void setSharedKey(const std::vector<std::uint8_t> &key, int key_index = 0);
118-
119-
/**
120-
* Export the currently active shared key at the given key index.
121-
*
122-
* This API is primarily intended for debugging, verification,
123-
* or diagnostics. Applications should avoid exporting keys
124-
* unless absolutely necessary.
125-
*
126-
* @param key_index Index of the key to export (default: 0)
127-
* @return Raw key bytes
128-
*/
129-
std::vector<std::uint8_t> exportSharedKey(int key_index = 0) const;
130-
131-
/**
132-
* Ratchet (derive) a new shared key at the given key index.
133-
*
134-
* This advances the key forward and returns the newly derived key.
135-
* All participants must ratchet keys in the same order to remain
136-
* in sync.
137-
*
138-
* @param key_index Index of the key to ratchet (default: 0)
139-
* @return Newly derived key bytes
140-
*/
141-
std::vector<std::uint8_t> ratchetSharedKey(int key_index = 0);
201+
/// Returns the key provider if E2EE was configured for the room; otherwise
202+
/// nullptr.
203+
KeyProvider *keyProvider();
204+
const KeyProvider *keyProvider() const;
205+
206+
/// Retrieves the current list of frame cryptors from the underlying runtime.
207+
std::vector<E2EEManager::FrameCryptor> frameCryptors() const;
142208

143209
protected:
144-
/*
145-
* Construct an E2EE manager for a connected room.
146-
*
147-
* This constructor are intended for internal use by room.
148-
* Applications should NOT create their own E2EEManager instances.
149-
*
150-
* After successfully connecting to a room with E2EE enabled,
151-
* obtain the E2EE manager via the Room:
152-
*
153-
* auto e2ee_manager = room->e2eeManager();
154-
*
155-
* The Room owns and manages the lifetime of the E2EEManager and ensures
156-
* it is correctly wired to the underlying room handle and track lifecycle.
157-
*/
158-
explicit E2EEManager(std::uint64_t room_handle, E2EEOptions config);
210+
/// Internal constructor used by Room when E2EEOptions are provided.
211+
explicit E2EEManager(std::uint64_t room_handle, const E2EEOptions &options);
159212
friend class Room;
160213

161214
private:
162-
struct Impl;
163-
std::unique_ptr<Impl> impl_;
215+
std::uint64_t room_handle_{0};
216+
bool enabled_{false};
217+
E2EEOptions options_;
218+
KeyProvider key_provider_;
164219
};
165220

166221
} // namespace livekit

include/livekit/room.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ struct RoomOptions {
7373
// Enable dynacast (server sends optimal layers depending on subscribers).
7474
bool dynacast = false;
7575

76-
// Optional end-to-end encryption settings.
77-
std::optional<E2EEOptions> e2ee;
78-
7976
// Optional WebRTC configuration (ICE policy, servers, etc.)
8077
std::optional<RtcConfig> rtc_config;
78+
79+
// Optional end-to-end encryption settings.
80+
std::optional<E2EEOptions> encryption;
8181
};
8282

8383
/// Represents a LiveKit room session.

0 commit comments

Comments
 (0)