Skip to content

Commit 58f342c

Browse files
committed
Initial prototype
1 parent d7c19ce commit 58f342c

5 files changed

Lines changed: 80 additions & 19 deletions

File tree

livekit-ffi/protocol/room.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,12 +310,12 @@ message RoomOptions {
310310
optional RtcConfig rtc_config = 5; // allow to setup a custom RtcConfiguration
311311
optional uint32 join_retries = 6;
312312
optional E2eeOptions encryption = 7;
313+
repeated string registered_rpc_methods = 8;
313314
}
314315

315316
//
316317
// Room
317318
//
318-
319319
enum ConnectionQuality {
320320
QUALITY_POOR = 0;
321321
QUALITY_GOOD = 1;

livekit-ffi/src/server/room.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,27 @@ struct FfiSipDtmfPacket {
114114
impl FfiRoom {
115115
pub fn connect(
116116
server: &'static FfiServer,
117-
connect: proto::ConnectRequest,
117+
mut connect: proto::ConnectRequest,
118118
) -> proto::ConnectResponse {
119119
let async_id = server.resolve_async_id(connect.request_async_id);
120120

121121
let req = connect.clone();
122+
123+
// TODO: move this conversion
124+
let rpc_handler_registry =
125+
std::mem::take(&mut connect.options.registered_rpc_methods).into_iter().fold(
126+
livekit::participant::RpcHandlerRegistry::default(),
127+
|mut registry, name| {
128+
registry.register(name, async |invocation| {
129+
// TODO: delegate to handler (probably via static), error if called early.
130+
todo!()
131+
});
132+
registry
133+
},
134+
);
135+
122136
let mut options: RoomOptions = connect.options.into();
137+
options.rpc_handlers = rpc_handler_registry;
123138

124139
{
125140
let config = server.config.lock();

livekit/src/room/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@ pub use self::{
4545
};
4646
pub use crate::rtc_engine::SimulateScenario;
4747
use crate::{
48-
participant::ConnectionQuality,
48+
participant::{ConnectionQuality, RpcHandlerRegistry},
4949
prelude::*,
5050
registered_audio_filter_plugins,
5151
rtc_engine::{
52-
EngineError, EngineEvent, EngineEvents, EngineOptions, EngineResult, RtcEngine,
53-
SessionStats, INITIAL_BUFFERED_AMOUNT_LOW_THRESHOLD,
52+
EngineError, EngineEvent, EngineEvents, EngineOptions, EngineResult, INITIAL_BUFFERED_AMOUNT_LOW_THRESHOLD, RtcEngine, SessionStats
5453
},
5554
};
5655

@@ -368,6 +367,7 @@ pub struct RoomOptions {
368367
pub rtc_config: RtcConfiguration,
369368
pub join_retries: u32,
370369
pub sdk_options: RoomSdkOptions,
370+
pub rpc_handlers: RpcHandlerRegistry
371371
}
372372

373373
impl Default for RoomOptions {
@@ -388,6 +388,7 @@ impl Default for RoomOptions {
388388
},
389389
join_retries: 3,
390390
sdk_options: RoomSdkOptions::default(),
391+
rpc_handlers: RpcHandlerRegistry::default()
391392
}
392393
}
393394
}

livekit/src/room/participant/local_participant.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,10 @@ use super::{
2727
ParticipantTrackPermission,
2828
};
2929
use crate::{
30-
data_stream::{
30+
ChatMessage, DataPacket, RoomSession, RpcAck, RpcRequest, RpcResponse, SipDTMF, Transcription, data_stream::{
3131
ByteStreamInfo, ByteStreamWriter, StreamByteOptions, StreamResult, StreamTextOptions,
3232
TextStreamInfo, TextStreamWriter,
33-
},
34-
e2ee::EncryptionType,
35-
options::{self, compute_video_encodings, video_layers_from_encodings, TrackPublishOptions},
36-
prelude::*,
37-
room::participant::rpc::{RpcError, RpcErrorCode, RpcInvocationData, MAX_PAYLOAD_BYTES},
38-
rtc_engine::{EngineError, RtcEngine},
39-
ChatMessage, DataPacket, RoomSession, RpcAck, RpcRequest, RpcResponse, SipDTMF, Transcription,
33+
}, e2ee::EncryptionType, options::{self, TrackPublishOptions, compute_video_encodings, video_layers_from_encodings}, participant::RpcHandlerRegistry, prelude::*, room::participant::rpc::{MAX_PAYLOAD_BYTES, RpcError, RpcErrorCode, RpcInvocationData}, rtc_engine::{EngineError, RtcEngine}
4034
};
4135
use chrono::Utc;
4236
use libwebrtc::{native::create_random_uuid, rtp_parameters::RtpEncodingParameters};
@@ -68,15 +62,15 @@ struct LocalEvents {
6862
struct RpcState {
6963
pending_acks: HashMap<String, oneshot::Sender<()>>,
7064
pending_responses: HashMap<String, oneshot::Sender<Result<String, RpcError>>>,
71-
handlers: HashMap<String, RpcHandler>,
65+
handlers: RpcHandlerRegistry
7266
}
7367

7468
impl RpcState {
7569
fn new() -> Self {
7670
Self {
7771
pending_acks: HashMap::new(),
7872
pending_responses: HashMap::new(),
79-
handlers: HashMap::new(),
73+
handlers: Default::default()
8074
}
8175
}
8276
}
@@ -867,11 +861,11 @@ impl LocalParticipant {
867861
+ Sync
868862
+ 'static,
869863
) {
870-
self.local.rpc_state.lock().handlers.insert(method, Arc::new(handler));
864+
self.local.rpc_state.lock().handlers.register(method, handler);
871865
}
872866

873867
pub fn unregister_rpc_method(&self, method: String) {
874-
self.local.rpc_state.lock().handlers.remove(&method);
868+
self.local.rpc_state.lock().handlers.unregister(&method);
875869
}
876870

877871
pub(crate) fn handle_incoming_rpc_ack(&self, request_id: String) {
@@ -925,7 +919,7 @@ impl LocalParticipant {
925919
let response = if version != 1 {
926920
Err(RpcError::built_in(RpcErrorCode::UnsupportedVersion, None))
927921
} else {
928-
let handler = self.local.rpc_state.lock().handlers.get(&method).cloned();
922+
let handler = self.local.rpc_state.lock().handlers.get(&method);
929923

930924
match handler {
931925
Some(handler) => {

livekit/src/room/participant/rpc.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
// limitations under the License.
1414

1515
use crate::room::participant::ParticipantIdentity;
16+
use core::fmt;
17+
use futures_util::future::BoxFuture;
1618
use livekit_protocol::RpcError as RpcError_Proto;
17-
use std::{error::Error, fmt::Display, time::Duration};
19+
use std::{
20+
collections::HashMap, error::Error, fmt::Display, future::Future, sync::Arc, time::Duration,
21+
};
1822

1923
/// Parameters for performing an RPC call
2024
#[derive(Debug, Clone)]
@@ -166,3 +170,50 @@ pub(crate) fn truncate_bytes(s: &str, max_bytes: usize) -> String {
166170
}
167171
result
168172
}
173+
174+
type RpcHandler =
175+
Arc<dyn Fn(RpcInvocationData) -> BoxFuture<'static, Result<String, RpcError>> + Send + Sync>;
176+
177+
#[derive(Default, Clone)]
178+
pub struct RpcHandlerRegistry {
179+
inner: HashMap<String, RpcHandler>,
180+
}
181+
182+
impl RpcHandlerRegistry {
183+
pub fn register<H, Fut>(&mut self, method: impl Into<String>, handler: H)
184+
where
185+
H: for<'a> Fn(RpcInvocationData) -> Fut + Send + Sync + 'static,
186+
Fut: Future<Output = Result<String, RpcError>> + Send + 'static,
187+
{
188+
self.inner.insert(
189+
method.into(),
190+
Arc::new(move |invocation| Box::pin(handler(invocation)) as BoxFuture<_>),
191+
);
192+
}
193+
194+
pub fn unregister(&mut self, method: impl Into<String>) {
195+
self.inner.remove(&method.into());
196+
}
197+
198+
pub(crate) fn get(&self, method: &str) -> Option<RpcHandler> {
199+
self.inner.get(method).cloned().into()
200+
}
201+
}
202+
203+
impl fmt::Debug for RpcHandlerRegistry {
204+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205+
let mut dbg = f.debug_struct("RpcHandlerRegistry");
206+
dbg.field("methods", &self.inner.keys().collect::<Vec<_>>());
207+
dbg.finish()
208+
}
209+
}
210+
211+
#[cfg(test)]
212+
mod tests {
213+
use super::*;
214+
215+
#[tokio::test]
216+
async fn test_register() {
217+
RpcHandlerRegistry::default().register("my_method", async |_invocation| Ok("ok".into()));
218+
}
219+
}

0 commit comments

Comments
 (0)