WIP: start on live_kit_server

Antonio Scandurra created

Change summary

.gitmodules                                   |  3 
Cargo.lock                                    | 16 ++++
crates/capture/src/main.rs                    |  4 
crates/live_kit_server/Cargo.toml             |  8 +
crates/live_kit_server/build.rs               |  5 +
crates/live_kit_server/protocol               |  1 
crates/live_kit_server/src/api.rs             | 36 ++++++++++
crates/live_kit_server/src/live_kit_server.rs | 74 --------------------
crates/live_kit_server/src/proto.rs           |  1 
crates/live_kit_server/src/token.rs           | 71 ++++++++++++++++++++
10 files changed, 144 insertions(+), 75 deletions(-)

Detailed changes

.gitmodules 🔗

@@ -0,0 +1,3 @@
+[submodule "crates/live_kit_server/protocol"]
+	path = crates/live_kit_server/protocol
+	url = https://github.com/livekit/protocol

Cargo.lock 🔗

@@ -3203,7 +3203,11 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "hmac 0.12.1",
+ "hyper",
  "jwt",
+ "prost 0.8.0",
+ "prost-build",
+ "prost-types 0.8.0",
  "serde",
  "sha2 0.10.6",
 ]
@@ -4363,7 +4367,7 @@ dependencies = [
  "multimap",
  "petgraph",
  "prost 0.9.0",
- "prost-types",
+ "prost-types 0.9.0",
  "regex",
  "tempfile",
  "which",
@@ -4395,6 +4399,16 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "prost-types"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
+dependencies = [
+ "bytes 1.2.1",
+ "prost 0.8.0",
+]
+
 [[package]]
 name = "prost-types"
 version = "0.9.0"

crates/capture/src/main.rs 🔗

@@ -36,7 +36,7 @@ fn main() {
         let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap();
 
         cx.spawn(|mut cx| async move {
-            let user1_token = live_kit_server::create_token(
+            let user1_token = live_kit_server::token::create(
                 &live_kit_key,
                 &live_kit_secret,
                 "test-room",
@@ -46,7 +46,7 @@ fn main() {
             let room1 = Room::new();
             room1.connect(&live_kit_url, &user1_token).await.unwrap();
 
-            let user2_token = live_kit_server::create_token(
+            let user2_token = live_kit_server::token::create(
                 &live_kit_key,
                 &live_kit_secret,
                 "test-room",

crates/live_kit_server/Cargo.toml 🔗

@@ -12,5 +12,11 @@ doctest = false
 anyhow = "1.0.38"
 hmac = "0.12"
 jwt = "0.16"
+hyper = "0.14"
+prost = "0.8"
+prost-types = "0.8"
 serde = { version = "1.0", features = ["derive", "rc"] }
-sha2 = "0.10"
+sha2 = "0.10"
+
+[build-dependencies]
+prost-build = "0.9"

crates/live_kit_server/build.rs 🔗

@@ -0,0 +1,5 @@
+fn main() {
+    prost_build::Config::new()
+        .compile_protos(&["protocol/livekit_room.proto"], &["protocol"])
+        .unwrap();
+}

crates/live_kit_server/src/api.rs 🔗

@@ -0,0 +1,36 @@
+use crate::token;
+use hyper::{client::HttpConnector, Request, Uri};
+
+pub struct Client {
+    http: hyper::Client<HttpConnector>,
+    uri: Uri,
+    key: String,
+    secret: String,
+}
+
+impl Client {
+    pub fn new(uri: Uri, key: String, secret: String) -> Self {
+        assert!(uri.scheme().is_some(), "base uri must have a scheme");
+        assert!(uri.authority().is_some(), "base uri must have an authority");
+        Self {
+            http: hyper::Client::new(),
+            uri: uri,
+            key,
+            secret,
+        }
+    }
+
+    pub fn create_room(&self) {
+        // let mut uri = url.clone();
+        // uri.set_path_and_query()
+
+        let uri = Uri::builder()
+            .scheme(self.uri.scheme().unwrap().clone())
+            .authority(self.uri.authority().unwrap().clone())
+            .path_and_query("twirp/livekit.RoomService/CreateRoom")
+            .build();
+
+        // token::create(api_key, secret_key, room_name, participant_name)
+        self.http.request(req)
+    }
+}

crates/live_kit_server/src/live_kit_server.rs 🔗

@@ -1,71 +1,3 @@
-use anyhow::Result;
-use hmac::{Hmac, Mac};
-use jwt::SignWithKey;
-use serde::Serialize;
-use sha2::Sha256;
-use std::{
-    ops::Add,
-    time::{Duration, SystemTime, UNIX_EPOCH},
-};
-
-static DEFAULT_TTL: Duration = Duration::from_secs(6 * 60 * 60); // 6 hours
-
-#[derive(Default, Serialize)]
-#[serde(rename_all = "camelCase")]
-struct ClaimGrants<'a> {
-    iss: &'a str,
-    sub: &'a str,
-    iat: u64,
-    exp: u64,
-    nbf: u64,
-    jwtid: &'a str,
-    video: VideoGrant<'a>,
-}
-
-#[derive(Default, Serialize)]
-#[serde(rename_all = "camelCase")]
-struct VideoGrant<'a> {
-    room_create: Option<bool>,
-    room_join: Option<bool>,
-    room_list: Option<bool>,
-    room_record: Option<bool>,
-    room_admin: Option<bool>,
-    room: Option<&'a str>,
-    can_publish: Option<bool>,
-    can_subscribe: Option<bool>,
-    can_publish_data: Option<bool>,
-    hidden: Option<bool>,
-    recorder: Option<bool>,
-}
-
-pub fn create_token(
-    api_key: &str,
-    secret_key: &str,
-    room_name: &str,
-    participant_name: &str,
-) -> Result<String> {
-    let secret_key: Hmac<Sha256> = Hmac::new_from_slice(secret_key.as_bytes())?;
-
-    let now = SystemTime::now();
-
-    let claims = ClaimGrants {
-        iss: api_key,
-        sub: participant_name,
-        iat: now.duration_since(UNIX_EPOCH).unwrap().as_secs(),
-        exp: now
-            .add(DEFAULT_TTL)
-            .duration_since(UNIX_EPOCH)
-            .unwrap()
-            .as_secs(),
-        nbf: 0,
-        jwtid: participant_name,
-        video: VideoGrant {
-            room: Some(room_name),
-            room_join: Some(true),
-            can_publish: Some(true),
-            can_subscribe: Some(true),
-            ..Default::default()
-        },
-    };
-    Ok(claims.sign_with_key(&secret_key)?)
-}
+mod api;
+mod proto;
+mod token;

crates/live_kit_server/src/token.rs 🔗

@@ -0,0 +1,71 @@
+use anyhow::Result;
+use hmac::{Hmac, Mac};
+use jwt::SignWithKey;
+use serde::Serialize;
+use sha2::Sha256;
+use std::{
+    ops::Add,
+    time::{Duration, SystemTime, UNIX_EPOCH},
+};
+
+static DEFAULT_TTL: Duration = Duration::from_secs(6 * 60 * 60); // 6 hours
+
+#[derive(Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct ClaimGrants<'a> {
+    iss: &'a str,
+    sub: &'a str,
+    iat: u64,
+    exp: u64,
+    nbf: u64,
+    jwtid: &'a str,
+    video: VideoGrant<'a>,
+}
+
+#[derive(Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct VideoGrant<'a> {
+    room_create: Option<bool>,
+    room_join: Option<bool>,
+    room_list: Option<bool>,
+    room_record: Option<bool>,
+    room_admin: Option<bool>,
+    room: Option<&'a str>,
+    can_publish: Option<bool>,
+    can_subscribe: Option<bool>,
+    can_publish_data: Option<bool>,
+    hidden: Option<bool>,
+    recorder: Option<bool>,
+}
+
+pub fn create(
+    api_key: &str,
+    secret_key: &str,
+    room_name: &str,
+    participant_name: &str,
+) -> Result<String> {
+    let secret_key: Hmac<Sha256> = Hmac::new_from_slice(secret_key.as_bytes())?;
+
+    let now = SystemTime::now();
+
+    let claims = ClaimGrants {
+        iss: api_key,
+        sub: participant_name,
+        iat: now.duration_since(UNIX_EPOCH).unwrap().as_secs(),
+        exp: now
+            .add(DEFAULT_TTL)
+            .duration_since(UNIX_EPOCH)
+            .unwrap()
+            .as_secs(),
+        nbf: 0,
+        jwtid: participant_name,
+        video: VideoGrant {
+            room: Some(room_name),
+            room_join: Some(true),
+            can_publish: Some(true),
+            can_subscribe: Some(true),
+            ..Default::default()
+        },
+    };
+    Ok(claims.sign_with_key(&secret_key)?)
+}