diff --git a/.gitignore b/.gitignore index eedc620..dff8ceb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ target # MSVC Windows builds of rustc generate these, which store debugging information *.pdb - +*.env # Generated by cargo mutants # Contains mutation testing data **/mutants.out*/W diff --git a/Cargo.lock b/Cargo.lock index 4d75204..55de0ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,12 +16,16 @@ dependencies = [ "crossterm", "dashmap", "der", + "dotenv", "futures", "futures-util", "hex", - "http", + "http 1.3.1", "hyper", "json", + "livekit", + "livekit-api", + "log", "loom", "once_cell", "pkcs8", @@ -49,6 +53,23 @@ dependencies = [ "x509", ] +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -76,6 +97,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + [[package]] name = "async-channel" version = "1.9.0" @@ -289,7 +322,7 @@ dependencies = [ "bytes", "form_urlencoded", "futures-util", - "http", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -320,7 +353,7 @@ checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", - "http", + "http 1.3.1", "http-body", "http-body-util", "mime", @@ -358,7 +391,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -397,18 +430,54 @@ dependencies = [ "piper", ] +[[package]] +name = "bmrng" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54df9073108f1558f90ae6c5bf5ab9c917c4185f5527b280c87a993cbead0ac" +dependencies = [ + "futures-core", + "tokio", +] + [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.13+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "cc" version = "1.2.46" @@ -421,6 +490,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -446,6 +521,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.42" @@ -459,6 +540,16 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -470,6 +561,32 @@ dependencies = [ "libloading", ] +[[package]] +name = "clap" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +dependencies = [ + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + [[package]] name = "cmake" version = "0.1.54" @@ -479,6 +596,27 @@ dependencies = [ "cc", ] +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -494,6 +632,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "convert_case" version = "0.7.1" @@ -547,6 +691,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -609,6 +762,68 @@ dependencies = [ "typenum", ] +[[package]] +name = "cxx" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b788601e7e3e6944d9b37efbae0bee7ee44d9aab533838d4854f631534a1a49" +dependencies = [ + "cc", + "cxx-build", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e11d62eb0de451f6d3aa83f2cec0986af61c23bd7515f1e2d6572c6c9e53c96" +dependencies = [ + "cc", + "codespan-reporting", + "indexmap", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a368ed4a0fd83ebd3f2808613842d942a409c41cc24cd9d83f1696a00d78afe" +dependencies = [ + "clap", + "codespan-reporting", + "indexmap", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9571a7c69f236d7202f517553241496125ed56a86baa1ce346d02aa72357c74" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eba2aaae28ca1d721d3f364bb29d51811921e7194c08bb9eaf745c8ab8d81309" +dependencies = [ + "indexmap", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -639,6 +854,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_more" version = "2.0.1" @@ -668,6 +892,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -690,6 +915,12 @@ dependencies = [ "litrs", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dunce" version = "1.0.5" @@ -783,12 +1014,34 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -813,6 +1066,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -952,8 +1215,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -963,9 +1228,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -1025,7 +1292,7 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "880e524e0085f3546cfb38532b2c202c0d64741d9977a6e4aa24704bfc9f19fb" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro-crate", "proc-macro2", "quote", @@ -1082,7 +1349,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.3.1", "indexmap", "slab", "tokio", @@ -1117,7 +1384,7 @@ dependencies = [ "base64 0.22.1", "bytes", "headers-core", - "http", + "http 1.3.1", "httpdate", "mime", "sha1", @@ -1129,9 +1396,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http", + "http 1.3.1", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -1150,6 +1423,26 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.3.1" @@ -1168,7 +1461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.3.1", ] [[package]] @@ -1179,7 +1472,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", + "http 1.3.1", "http-body", "pin-project-lite", ] @@ -1207,7 +1500,7 @@ dependencies = [ "futures-channel", "futures-core", "h2", - "http", + "http 1.3.1", "http-body", "httparse", "httpdate", @@ -1225,10 +1518,11 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", + "http 1.3.1", "hyper", "hyper-util", "rustls 0.23.35", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", @@ -1262,7 +1556,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http", + "http 1.3.1", "http-body", "hyper", "ipnet", @@ -1413,6 +1707,15 @@ dependencies = [ "hashbrown 0.16.0", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -1429,6 +1732,24 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1444,6 +1765,28 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.34" @@ -1470,6 +1813,19 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64 0.22.1", + "js-sys", + "ring", + "serde", + "serde_json", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -1501,6 +1857,39 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "libwebrtc" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7cdca6ecb63fb4b32ea1ae04921e47ee448e5645e7348a904f8602fe0ddd36" +dependencies = [ + "cxx", + "jni", + "js-sys", + "lazy_static", + "livekit-protocol", + "livekit-runtime", + "log", + "parking_lot", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webrtc-sys", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82" +dependencies = [ + "cc", +] + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -1519,6 +1908,87 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "livekit" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15aee1ced6569cc3f7ff14fcb1aeb4c29fdc33804cbe773aa3bf26a7cd939aa6" +dependencies = [ + "bmrng", + "bytes", + "chrono", + "futures-util", + "lazy_static", + "libloading", + "libwebrtc", + "livekit-api", + "livekit-protocol", + "livekit-runtime", + "log", + "parking_lot", + "prost", + "semver", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "livekit-api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7942197fb744e26697aa151b08fbdeccdf07ec036109af8db664206fddc92b02" +dependencies = [ + "base64 0.21.7", + "futures-util", + "http 1.3.1", + "jsonwebtoken", + "livekit-protocol", + "livekit-runtime", + "log", + "parking_lot", + "pbjson-types", + "prost", + "rand 0.9.2", + "reqwest", + "scopeguard", + "serde", + "serde_json", + "sha2", + "thiserror 1.0.69", + "tokio", + "tokio-tungstenite 0.20.1", + "url", +] + +[[package]] +name = "livekit-protocol" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a490520ea5d66fc5c303fe99666cc42e1ff49bc60489715531d1a687b3fd37bd" +dependencies = [ + "futures-util", + "livekit-runtime", + "parking_lot", + "pbjson", + "pbjson-types", + "prost", + "serde", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "livekit-runtime" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532e84c6cdc5fe774f2b5d9912597b5f3bea561927a48296d03e24549d21c3f6" +dependencies = [ + "tokio", + "tokio-stream", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -1550,6 +2020,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "matchers" version = "0.2.0" @@ -1593,6 +2069,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" version = "1.1.0" @@ -1605,6 +2091,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + [[package]] name = "native-tls" version = "0.2.14" @@ -1650,6 +2142,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.19" @@ -1738,12 +2236,82 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pbjson" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90" +dependencies = [ + "base64 0.21.7", + "serde", +] + +[[package]] +name = "pbjson-build" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735" +dependencies = [ + "heck 0.4.1", + "itertools 0.11.0", + "prost", + "prost-types", +] + +[[package]] +name = "pbjson-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f596653ba4ac51bdecbb4ef6773bc7f56042dc13927910de1684ad3d32aa12" +dependencies = [ + "bytes", + "chrono", + "pbjson", + "pbjson-build", + "prost", + "prost-build", + "serde", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -1826,6 +2394,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1863,6 +2437,114 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.12.1", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.35", + "socket2", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls 0.23.35", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.42" @@ -2010,9 +2692,11 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", + "futures-util", "h2", - "http", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -2025,6 +2709,9 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.35", + "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -2032,6 +2719,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2138,6 +2826,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ + "web-time", "zeroize", ] @@ -2205,6 +2894,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scratch" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" + [[package]] name = "sct" version = "0.7.1" @@ -2251,6 +2946,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -2393,6 +3094,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" version = "0.4.11" @@ -2431,6 +3138,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" @@ -2521,7 +3234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c8f33736f986f16d69b6cb8b03f55ddcad5c41acc4ccc39dd88e84aa805e7f" dependencies = [ "cfg-expr", - "heck", + "heck 0.5.0", "pkg-config", "toml", "version-compare", @@ -2546,6 +3259,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -2595,6 +3317,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + [[package]] name = "tinystr" version = "0.8.2" @@ -2605,6 +3346,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.48.0" @@ -2675,6 +3431,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.20.1", +] + [[package]] name = "tokio-tungstenite" version = "0.26.2" @@ -2716,7 +3484,7 @@ dependencies = [ "serde", "tokio", "tokio-rustls", - "tokio-tungstenite", + "tokio-tungstenite 0.26.2", "tracing", "uuid", ] @@ -2797,7 +3565,7 @@ dependencies = [ "bitflags", "bytes", "futures-util", - "http", + "http 1.3.1", "http-body", "iri-string", "pin-project-lite", @@ -2886,6 +3654,25 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror 1.0.69", + "url", + "utf-8", +] + [[package]] name = "tungstenite" version = "0.26.2" @@ -2894,7 +3681,7 @@ checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.3.1", "httparse", "log", "rand 0.9.2", @@ -2911,7 +3698,7 @@ checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.3.1", "httparse", "log", "native-tls", @@ -2948,6 +3735,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "untrusted" version = "0.9.0" @@ -3048,7 +3841,7 @@ dependencies = [ "bytes", "futures-util", "headers", - "http", + "http 1.3.1", "http-body", "http-body-util", "log", @@ -3149,6 +3942,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki" version = "0.22.4" @@ -3177,6 +3980,36 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webrtc-sys" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4b26eb6cd3c89734f760c783694cb938a229301f5db0acc1e36ddc28c5335f9" +dependencies = [ + "cc", + "cxx", + "cxx-build", + "glob", + "log", + "pkg-config", + "webrtc-sys-build", +] + +[[package]] +name = "webrtc-sys-build" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0acd1d2d3b5df7badd0fb0c2aec1efbbc3a09993c7aa0821bcf43412e2ee5772" +dependencies = [ + "anyhow", + "fs2", + "regex", + "reqwest", + "scratch", + "semver", + "zip", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3377,6 +4210,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3404,6 +4246,21 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -3446,6 +4303,12 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3458,6 +4321,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3470,6 +4339,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3494,6 +4369,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3506,6 +4387,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3518,6 +4405,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3530,6 +4423,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3686,3 +4585,52 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index b6a35e3..38abf8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,3 +45,7 @@ walkdir = "2.5.0" warp = "*" x448 = { version = "*" } x509 = "*" +log = "0.4" +livekit = "0.7.25" +livekit-api = "0.4.10" +dotenv = "0.15.0" diff --git a/src/calls/call_connection.rs b/src/calls/call_connection.rs deleted file mode 100644 index 1639d88..0000000 --- a/src/calls/call_connection.rs +++ /dev/null @@ -1,283 +0,0 @@ -use async_tungstenite::{WebSocketReceiver, WebSocketSender, tungstenite::Message}; -use std::{any::Any, sync::Arc}; -use tokio::sync::{ - RwLock, - mpsc::{UnboundedSender, unbounded_channel}, -}; -use tokio_util::compat::Compat; -use tungstenite::Utf8Bytes; -use uuid::Uuid; - -use crate::{ - calls::call_manager, - data::communication::{CommunicationType, CommunicationValue, DataTypes}, - util::print::{PrintType, line, line_err}, -}; -use json::JsonValue; - -pub struct CallConnection { - pub sender: Arc>>>, - pub receiver: Arc>>>, - pub tx: UnboundedSender, - pub user_id: Arc>>, - pub call_id: Arc>>, -} - -impl CallConnection { - pub async fn new( - sender: WebSocketSender>, - receiver: WebSocketReceiver>, - ) -> Arc { - let (tx, mut rx) = unbounded_channel::(); - - let conn = Arc::new(Self { - sender: Arc::new(RwLock::new(sender)), - receiver: Arc::new(RwLock::new(receiver)), - tx, - user_id: Arc::new(RwLock::new(None)), - call_id: Arc::new(RwLock::new(None)), - }); - - // Spawn sender task to forward tx → session - let sender_clone = Arc::clone(&conn.sender); - tokio::spawn(async move { - while let Some(msg) = rx.recv().await { - let mut sess = sender_clone.write().await; - let _ = sess.send(Message::Text(msg)).await; - } - }); - - conn - } - - /// Handle a single incoming message - pub async fn handle_message(self: Arc, msg: Utf8Bytes) { - let mut cv = CommunicationValue::from_json(&msg); - if let Some(sender) = *self.user_id.read().await { - cv = cv.with_sender(sender); - } - - if cv.is_type(CommunicationType::webrtc_sdp) - | cv.is_type(CommunicationType::webrtc_ice) - | cv.is_type(CommunicationType::watch_stream) - { - line( - PrintType::CallIn, - &format!( - "{:?} : {} -> {} ", - &cv.type_id(), - &cv.get_sender(), - &cv.get_data(DataTypes::receiver_id).unwrap() - ), - ); - } else if !cv.is_type(CommunicationType::ping) { - line(PrintType::CallIn, &cv.to_json().to_string()); - } - - match cv.comm_type { - CommunicationType::identification => self.handle_identification(cv).await, - CommunicationType::ping => self.handle_ping(cv).await, - CommunicationType::client_changed => self.handle_client_changed(cv).await, - CommunicationType::start_stream | CommunicationType::end_stream => { - self.handle_stream_toggle(cv).await - } - CommunicationType::webrtc_sdp - | CommunicationType::webrtc_ice - | CommunicationType::watch_stream => self.handle_direct_relay(cv).await, - _ => {} - } - } - - async fn handle_identification(&self, cv: CommunicationValue) { - let user_str = cv - .get_data(DataTypes::user_id) - .and_then(|v| v.as_str()) - .unwrap_or(""); - let call_str = cv - .get_data(DataTypes::call_id) - .and_then(|v| v.as_str()) - .unwrap_or(""); - let secret_sha = cv - .get_data(DataTypes::call_secret_sha) - .and_then(|v| v.as_str()) - .unwrap_or(""); - - let (Ok(uid), Ok(cid)) = (Uuid::parse_str(user_str), Uuid::parse_str(call_str)) else { - return; - }; - - { - *self.user_id.write().await = Some(uid); - *self.call_id.write().await = Some(cid); - } - - let group = call_manager::get_or_create_group(cid, secret_sha).await; - if let None = group { - self.send_message(&CommunicationValue::new( - CommunicationType::error_invalid_secret, - )) - .await; - return; - } - let group = group.unwrap(); - - // Build broadcast - let broadcast = CommunicationValue::new(CommunicationType::client_connected) - .with_id(cv.get_id().clone()) - .add_data_str(DataTypes::user_id, uid.to_string()) - .add_data_str(DataTypes::call_state, "muted".to_string()); - { - group - .lock() - .await - .broadcast(&broadcast.to_json().to_string()) - .await; - } - - { - group.lock().await.add_member(uid, self.tx.clone()); - } - - // Build response - let mut response = CommunicationValue::new(CommunicationType::identification_response) - .with_id(cv.get_id().clone()); - - let mut users = JsonValue::new_object(); - { - for caller in group.lock().await.callers.values() { - let mut user_info = JsonValue::new_object(); - let _ = user_info.insert("state", JsonValue::from("muted")); - let _ = user_info.insert("streaming", JsonValue::from(false)); - let _ = users.insert(&caller.user_id.read().await.to_string(), user_info); - } - } - response = response.add_data(DataTypes::about, users); - self.send_message(&response).await; - } - - async fn handle_ping(&self, cv: CommunicationValue) { - let resp = CommunicationValue::new(CommunicationType::pong).with_id(cv.get_id().clone()); - self.send_message(&resp).await; - } - - async fn handle_client_changed(&self, cv: CommunicationValue) { - let uid = match *self.user_id.read().await { - Some(id) => id, - None => return, - }; - - let cid = match *self.call_id.read().await { - Some(id) => id, - None => return, - }; - - if let Some(JsonValue::String(_state_str)) = cv.get_data(DataTypes::call_state) { - let Some(group_lock) = call_manager::get_group(cid).await else { - return; - }; - let mut group = group_lock.lock().await; - if let Some(_caller) = group.caller_state_mut(&uid) { - // caller_state_change(caller, &state_str); - } - - let mut bc = cv.clone(); - bc = bc.add_data(DataTypes::sender_id, JsonValue::String(uid.to_string())); - group.broadcast(&bc.to_json().to_string()).await; - } - } - - async fn handle_stream_toggle(&self, cv: CommunicationValue) { - let uid = match *self.user_id.read().await { - Some(id) => id, - None => return, - }; - - let cid = match *self.call_id.read().await { - Some(id) => id, - None => return, - }; - - if let Some(group_lock) = call_manager::get_group(cid).await { - let group = group_lock.lock().await; - let _streaming = cv.comm_type == CommunicationType::start_stream; - let mut bc = cv.clone(); - bc = bc.add_data(DataTypes::sender_id, JsonValue::String(uid.to_string())); - group.broadcast(&bc.to_json().to_string()).await; - } - } - - async fn handle_direct_relay(&self, cv: CommunicationValue) { - let uid = match *self.user_id.read().await { - Some(id) => id, - None => return, - }; - let cid = match *self.call_id.read().await { - Some(id) => id, - None => return, - }; - if let Some(JsonValue::String(receiver_str)) = cv.get_data(DataTypes::receiver_id) { - if let Ok(receiver_id) = Uuid::parse_str(&receiver_str) { - if let Some(group) = call_manager::get_group(cid).await { - let mut bc = cv.clone(); - bc = bc.add_data(DataTypes::sender_id, JsonValue::String(uid.to_string())); - group - .lock() - .await - .send_to(&receiver_id, &bc.to_json().to_string()) - .await; - line( - PrintType::CallOut, - &format!("Forwarded WebRTC message to receiver: {}", receiver_str), - ); - } else { - line_err(PrintType::CallOut, "Failed to find the group for the call."); - } - } else { - line_err(PrintType::CallOut, "Invalid receiver_id in WebRTC message."); - } - } else { - line_err(PrintType::CallOut, "Missing receiver_id in WebRTC message."); - } - } - pub async fn send_message(&self, cv: &CommunicationValue) { - if !cv.is_type(CommunicationType::pong) { - line(PrintType::CallOut, &cv.to_json().to_string()); - } - let mut session = self.sender.write().await; - if let Err(e) = session - .send(Message::Text(Utf8Bytes::from(cv.to_json().to_string()))) - .await - { - line_err( - PrintType::CallOut, - &format!("Failed to send message to client: {}", e), - ); - } - } - - pub async fn close(&self) { - let (uid, cid) = { (*self.user_id.read().await, *self.call_id.read().await) }; - if let (Some(uid), Some(cid)) = (uid, cid) { - if let Some(group) = call_manager::get_group(cid).await { - group - .lock() - .await - .broadcast( - &CommunicationValue::new(CommunicationType::client_disconnected) - .add_data_str(DataTypes::user_id, uid.to_string()) - .to_json() - .to_string(), - ) - .await; - group.lock().await.disconnect_member(uid).await; - } - call_manager::remove_inactive().await; - } - - let mut session = self.sender.write().await; - let _ = session.close(None).await; - } - pub async fn handle_close(&self) { - self.close().await; - } -} diff --git a/src/calls/call_group.rs b/src/calls/call_group.rs index f2d54b6..d597a50 100644 --- a/src/calls/call_group.rs +++ b/src/calls/call_group.rs @@ -1,60 +1,27 @@ -use crate::calls::caller::Caller; -use std::{collections::HashMap, sync::Arc}; -use tokio::sync::mpsc::UnboundedSender; -use tungstenite::Utf8Bytes; +use std::sync::Arc; + +use tokio::sync::RwLock; use uuid::Uuid; +use crate::calls::caller::Caller; + pub struct CallGroup { - pub callers: HashMap>, - pub secret_hash: String, + pub call_id: Uuid, + pub members: RwLock>>, } impl CallGroup { - pub fn new(secret_hash: String) -> Self { - Self { - callers: HashMap::new(), - secret_hash: secret_hash, + pub fn new(call_id: Uuid, user: Arc) -> Self { + CallGroup { + call_id, + members: RwLock::new(vec![user]), } } - pub fn add_member(&mut self, user_id: Uuid, tx: UnboundedSender) { - self.callers - .insert(user_id, Arc::new(Caller::new(user_id, tx))); - } - pub fn remove_member(&mut self, user_id: Uuid) { - self.callers.remove(&user_id); - } - pub fn get_member(&self, user_id: &Uuid) -> Option<&Arc> { - self.callers.get(user_id) - } - pub async fn disconnect_member(&mut self, user_id: Uuid) { - if let Some(caller) = self.callers.get(&user_id) { - caller.disconnect().await; - } - } - - pub async fn is_empty(&self) -> bool { - for caller in self.callers.values() { - if caller.is_connected().await { - return false; - } - } - true - } - - pub async fn send_to(&self, user_id: &Uuid, message: &str) { - if let Some(caller) = self.callers.get(user_id) { - caller.send(Utf8Bytes::from(message.to_string())).await; - } - } - - pub async fn broadcast(&self, message: &str) { - for caller in self.callers.values() { - caller.send(Utf8Bytes::from(message.to_string())).await; - } - } - - pub fn caller_state_mut(&mut self, user_id: &Uuid) -> Option<&Arc> { - self.callers.get(user_id) + pub async fn add_member(self: Arc, member: Uuid, inviter: Uuid) { + self.members + .write() + .await + .push(Arc::new(Caller::new(member, inviter, self.call_id))); } } diff --git a/src/calls/call_manager.rs b/src/calls/call_manager.rs index 60b1a95..04a5d40 100644 --- a/src/calls/call_manager.rs +++ b/src/calls/call_manager.rs @@ -1,87 +1,81 @@ -use crate::calls::call_group::CallGroup; -use futures::lock::Mutex; // Used only to protect CallGroup contents -use once_cell::sync::Lazy; -use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::RwLock; // Used to protect the global HashMap + +use once_cell::sync::Lazy; +use tokio::sync::RwLock; use uuid::Uuid; -// FIX 1: Simplify the global state. Only use RwLock to protect the HashMap. -// The inner Arc> protects the contents of each group. -pub static CALL_GROUPS: Lazy>>>> = - Lazy::new(|| RwLock::new(HashMap::new())); +use crate::calls::{call_group::CallGroup, caller::Caller}; -/// Retrieves a CallGroup by ID, if it exists. -pub async fn get_group(call_id: Uuid) -> Option>> { - // Acquire read lock (very fast, non-blocking for other readers) - CALL_GROUPS - .read() - .await - .get(&call_id) // Use get(), as we only need to clone the Arc - .cloned() -} +static CALL_GROUPS: Lazy>>> = Lazy::new(|| RwLock::new(Vec::new())); -/// Retrieves an existing group or creates a new one, performing a secret check. -pub async fn get_or_create_group(call_id: Uuid, secret: &str) -> Option>> { - // Phase 1: Check existence under a READ lock. - { - let groups = CALL_GROUPS.read().await; - if let Some(group_arc) = groups.get(&call_id) { - // Found it. Release the global READ lock and check the secret. - // This await on the group's lock only blocks access to that *specific* group. - let group_lock = group_arc.lock().await; - if group_lock.secret_hash.eq(secret) { - return Some(group_arc.clone()); - } else { - return None; // Secret mismatch +pub async fn get_call_invites(user_id: Uuid) -> Vec> { + let mut callers = Vec::new(); + for cg in CALL_GROUPS.read().await.iter() { + for member in cg.members.read().await.iter() { + if member.user_id == user_id { + callers.push(member.clone()); } } - } // READ lock automatically released here. + } + callers +} - // Phase 2: Not found, acquire a WRITE lock to create (only held for insertion). - let mut groups = CALL_GROUPS.write().await; +pub async fn get_call_groups(user_id: Uuid) -> Vec> { + let mut call_groups = Vec::new(); + for cg in CALL_GROUPS.read().await.iter() { + for member in cg.members.read().await.iter() { + if member.user_id == user_id { + call_groups.push(cg.clone()); + } + } + } + call_groups +} - // FIX 2: Double-check (race condition prevention) - A group might have been created - // between the read lock release and the write lock acquisition. - if let Some(group_arc) = groups.get(&call_id) { - // Already created by another task, check secret again. - let group_lock = group_arc.lock().await; - if group_lock.secret_hash.eq(secret) { - return Some(group_arc.clone()); - } else { +pub async fn get_call_token(user_id: Uuid, call_id: Uuid) -> Option { + let call_groups = CALL_GROUPS.read().await; + for cg in call_groups.iter() { + if cg.call_id == call_id { + for member in cg.members.read().await.iter() { + if member.user_id == user_id { + return Some(member.create_token()); + } + } return None; } } - - // Still not found, proceed with creation. - let new_group = Arc::new(Mutex::new(CallGroup::new(secret.to_string()))); - groups.insert(call_id, new_group.clone()); - - // WRITE lock automatically released here. - Some(new_group) + let caller = Arc::new(Caller::new(user_id, user_id, call_id)); + let call_group = CallGroup::new(call_id, caller.clone()); + { + CALL_GROUPS.write().await.push(Arc::new(call_group)); + } + Some(caller.create_token()) } -/// Removes inactive groups. -pub async fn remove_inactive() { - // Collect keys to remove under a read lock first. - let groups_to_check: Vec = CALL_GROUPS.read().await.keys().cloned().collect(); +pub async fn add_invite(call_id: Uuid, inviter_id: Uuid, invitee_id: Uuid) -> bool { + let call_groups = CALL_GROUPS.read().await; + for cg in call_groups.iter() { + if cg.call_id == call_id { + for member in cg.members.read().await.iter() { + if member.user_id == inviter_id { + cg.clone().add_member(inviter_id, invitee_id).await; + return true; + } + } + return false; + } + } + false +} - let mut rem = Vec::new(); - for call_id in groups_to_check { - // Retrieve the group Arc outside the global lock - if let Some(group_arc) = get_group(call_id).await { - // FIX 3: Check for emptiness outside the global lock - if group_arc.lock().await.is_empty().await { - rem.push(call_id); +pub async fn get_call_group_by_user(user_id: Uuid) -> Option> { + let call_groups = CALL_GROUPS.read().await; + for cg in call_groups.iter() { + for member in cg.members.read().await.iter() { + if member.user_id == user_id { + return Some(cg.clone()); } } } - - // Acquire write lock only to perform the removals. - if !rem.is_empty() { - let mut groups = CALL_GROUPS.write().await; - for call_id in rem { - groups.remove(&call_id); - } - } + None } diff --git a/src/calls/call_util.rs b/src/calls/call_util.rs new file mode 100644 index 0000000..f913216 --- /dev/null +++ b/src/calls/call_util.rs @@ -0,0 +1,21 @@ +use livekit_api::access_token; +use std::env; +use uuid::Uuid; + +pub fn create_token( + user_id: Uuid, + call_id: Uuid, +) -> Result { + let api_key = env::var("LIVEKIT_API_KEY").expect("LIVEKIT_API_KEY is not set"); + let api_secret = env::var("LIVEKIT_API_SECRET").expect("LIVEKIT_API_SECRET is not set"); + + let token = access_token::AccessToken::with_api_key(&api_key, &api_secret) + .with_identity(&user_id.to_string()) + .with_grants(access_token::VideoGrants { + room_join: true, + room: call_id.to_string(), + ..Default::default() + }) + .to_jwt(); + return token; +} diff --git a/src/calls/caller.rs b/src/calls/caller.rs index 645ad4d..da41876 100644 --- a/src/calls/caller.rs +++ b/src/calls/caller.rs @@ -1,49 +1,26 @@ -use std::sync::Arc; - -use futures::lock::Mutex; -use tokio::sync::{RwLock, mpsc::UnboundedSender}; -use tungstenite::Utf8Bytes; use uuid::Uuid; +use crate::calls::call_util; + pub struct Caller { - pub user_id: RwLock, - pub tx: Mutex>>, - pub user_state: RwLock, - pub streaming: RwLock, -} -#[derive(Clone)] -pub enum CallUserState { - Active, - Muted, - Deafed, - Disconnected, + pub user_id: Uuid, + pub call_id: Uuid, + pub inviters: Vec, } + impl Caller { - pub fn new(user_id: Uuid, tx: UnboundedSender) -> Self { - Self { - user_id: RwLock::new(user_id), - tx: Mutex::new(Some(tx)), - user_state: RwLock::new(CallUserState::Active), - streaming: RwLock::new(false), + pub fn new(user_id: Uuid, call_id: Uuid, inviter_id: Uuid) -> Self { + Caller { + user_id, + call_id, + inviters: vec![inviter_id], } } - - pub async fn send(&self, msg: impl Into) { - if let Some(tx) = &*self.tx.lock().await { - let _ = tx.send(msg.into()); - } - } - - pub async fn disconnect(self: &Arc) { - *self.user_state.write().await = CallUserState::Disconnected; - *self.tx.lock().await = None; - } - - pub async fn is_connected(&self) -> bool { - if let CallUserState::Disconnected = *self.user_state.read().await { - false + pub fn create_token(&self) -> String { + if let Ok(token) = call_util::create_token(self.user_id, self.call_id) { + token } else { - true + String::new() } } } diff --git a/src/calls/mod.rs b/src/calls/mod.rs index 98613e7..8413354 100644 --- a/src/calls/mod.rs +++ b/src/calls/mod.rs @@ -1,4 +1,4 @@ -pub mod call_connection; pub mod call_group; pub mod call_manager; +pub mod call_util; pub mod caller; diff --git a/src/data/communication.rs b/src/data/communication.rs index 42f0fee..d96e20b 100644 --- a/src/data/communication.rs +++ b/src/data/communication.rs @@ -20,7 +20,6 @@ pub enum DataTypes { user_state, user_states, user_pings, - call_state, screen_share, private_key_hash, accepted, @@ -36,10 +35,7 @@ pub enum DataTypes { shared_secret_sign, shared_secret, call_id, - call_name, - call_secret_sha, - call_secret, - shared_call_secret, + call_token, start_date, end_date, receiver_id, @@ -96,7 +92,6 @@ impl DataTypes { "userstate" => DataTypes::user_state, "userstates" => DataTypes::user_states, "userpings" => DataTypes::user_pings, - "callstate" => DataTypes::call_state, "screenshare" => DataTypes::screen_share, "privatekeyhash" => DataTypes::private_key_hash, "accepted" => DataTypes::accepted, @@ -112,10 +107,7 @@ impl DataTypes { "sharedsecretsign" => DataTypes::shared_secret_sign, "sharedsecret" => DataTypes::shared_secret, "callid" => DataTypes::call_id, - "callname" => DataTypes::call_name, - "callsecretsha" => DataTypes::call_secret_sha, - "callsecret" => DataTypes::call_secret, - "sharedcallsecret" => DataTypes::shared_call_secret, + "calltoken" => DataTypes::call_token, "startdate" => DataTypes::start_date, "enddate" => DataTypes::end_date, "receiverid" => DataTypes::receiver_id, @@ -209,10 +201,8 @@ pub enum CommunicationType { start_stream, end_stream, watch_stream, - get_call, - new_call, + call_get, call_invite, - end_call, function, update, } @@ -263,10 +253,8 @@ impl CommunicationType { "startstream" => CommunicationType::start_stream, "endstream" => CommunicationType::end_stream, "watchstream" => CommunicationType::watch_stream, - "getcall" => CommunicationType::get_call, - "newcall" => CommunicationType::new_call, + "callget" => CommunicationType::call_get, "callinvite" => CommunicationType::call_invite, - "endcall" => CommunicationType::end_call, "function" => CommunicationType::function, "update" => CommunicationType::update, _ => CommunicationType::error, diff --git a/src/main.rs b/src/main.rs index c7abfc1..87e3f33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,23 +7,24 @@ mod util; use async_tungstenite::accept_hdr_async; use futures::StreamExt; +use livekit_api::services::room::{CreateRoomOptions, RoomClient}; use std::sync::Arc; use tokio::net::TcpListener; use tokio_util::compat::TokioAsyncReadCompatExt; use tungstenite::handshake::server::{Request, Response}; use crate::{ - calls::call_connection::CallConnection, + calls::call_util, omega::omega_connection::OmegaConnection, rho::{client_connection::ClientConnection, iota_connection::IotaConnection}, - util::config_util::CONFIG, - util::print::{PrintType, line, line_err, print_start_message}, + util::{ + config_util::CONFIG, + print::{PrintType, line, line_err}, + }, }; #[tokio::main] async fn main() { - print_start_message(); - tokio::spawn(async move { OmegaConnection::new().connect().await; }); @@ -121,39 +122,6 @@ async fn main() { } } } - } else if path == "/ws/call/" { - line(PrintType::CallIn, "New Call connection"); - let call_conn: Arc = - Arc::from(CallConnection::new(sender, receiver).await); - loop { - let msg_result = { - let mut session_lock = call_conn.receiver.write().await; - session_lock.next().await - }; - - match msg_result { - Some(Ok(msg)) => { - if msg.is_text() { - let text = msg.into_text().unwrap(); - call_conn.clone().handle_message(text).await; - } else if msg.is_close() { - line(PrintType::CallIn, "Call disconnected"); - call_conn.handle_close().await; - return; - } - } - Some(Err(e)) => { - line_err(PrintType::CallIn, &format!("WebSocket error: {}", e)); - call_conn.handle_close().await; - return; - } - None => { - line(PrintType::CallIn, "Call stream ended"); - call_conn.handle_close().await; - return; - } - } - } } }); } diff --git a/src/rho/client_connection.rs b/src/rho/client_connection.rs index 00afeb1..a9e3008 100644 --- a/src/rho/client_connection.rs +++ b/src/rho/client_connection.rs @@ -141,7 +141,7 @@ impl ClientConnection { } // Handle get call requests - if cv.is_type(CommunicationType::get_call) { + if cv.is_type(CommunicationType::call_get) { self.handle_get_call(cv).await; return; } @@ -303,13 +303,14 @@ impl ClientConnection { } }; - // Get call group - placeholder implementation - // let call_group = CallManager::get_call_group(call_id, &call_secret_sha.unwrap(), true).await; - // if call_group.is_none() { - // self.send_error_response(&cv.get_id(), CommunicationType::error) - // .await; - // return; - // } + let invited = + call_manager::add_invite(call_id, self.user_id.read().await.unwrap(), receiver_id) + .await; + if invited { + self.send_error_response(&cv.get_id(), CommunicationType::error) + .await; + return; + } // Find target RhoConnection let target_rho = match rho_manager::get_rho_con_for_user(receiver_id).await { @@ -328,20 +329,16 @@ impl ClientConnection { }; // Create and send call distribution message - let distribute = CommunicationValue::new(CommunicationType::new_call) + let forward = CommunicationValue::new(CommunicationType::call_invite) .with_receiver(receiver_id) .with_sender(sender_id) .add_data_str(DataTypes::call_id, call_id.to_string()) .add_data_str(DataTypes::receiver_id, receiver_id.to_string()) .add_data_str(DataTypes::sender_id, sender_id.to_string()); - target_rho.message_to_client(distribute).await; + target_rho.message_to_client(forward).await; - // Handle call group invitation logic here - // This would require implementing CallGroup::Caller and related functionality - - // Send success response - let response = CommunicationValue::new(CommunicationType::call_invite).with_id(cv.get_id()); + let response = CommunicationValue::new(CommunicationType::success).with_id(cv.get_id()); self.send_message(&response).await; } @@ -368,26 +365,17 @@ impl ClientConnection { } }; - // Get call group - let mut response = CommunicationValue::new(CommunicationType::get_call) - .with_id(cv.get_id()) - .with_receiver(user_id); - - if let Some(_call_group) = call_manager::get_group(call_id).await { - /*response = response - .add_data_str(DataTypes::call_state, call_group.call_state.to_string()) - .add_data_str(DataTypes::start_date, call_group.started_at.to_string()); - - if call_group.lock(). != 0 { - response = - response.add_data_str(DataTypes::end_date, call_group.ended_at.to_string()); - } - */ + if let Some(token) = call_manager::get_call_token(user_id, call_id).await { + let response = CommunicationValue::new(CommunicationType::call_get) + .with_id(cv.get_id()) + .with_receiver(user_id) + .add_data_str(DataTypes::call_token, token); + self.send_message(&response).await; } else { - response = response.add_data_str(DataTypes::call_state, "DESTROYED".to_string()); + self.send_error_response(&cv.get_id(), CommunicationType::error) + .await; + return; } - - self.send_message(&response).await; } /// Forward message to Iota diff --git a/src/rho/iota_connection.rs b/src/rho/iota_connection.rs index 0260d59..b7eb7fb 100644 --- a/src/rho/iota_connection.rs +++ b/src/rho/iota_connection.rs @@ -1,3 +1,5 @@ +use crate::calls::call_group::CallGroup; +use crate::calls::call_manager; use crate::util::print::PrintType; use crate::util::print::line; use crate::util::print::line_err; @@ -5,12 +7,14 @@ use async_tungstenite::WebSocketReceiver; use async_tungstenite::WebSocketSender; use async_tungstenite::tungstenite::Message; use json::JsonValue; +use json::parse; use std::{ collections::HashMap, sync::{Arc, Weak}, }; use tokio::sync::RwLock; use tokio_util::compat::Compat; +use tower::retry::backoff::InvalidBackoff; use tungstenite::Utf8Bytes; use uuid::Uuid; @@ -278,22 +282,44 @@ impl IotaConnection { /// Handle GET_CHATS message async fn handle_get_chats(&self, cv: CommunicationValue) { let receiver_id = cv.get_receiver(); - let interested_ids: Vec = Vec::new(); + let mut interested_ids: Vec = Vec::new(); + + let calls: Vec> = call_manager::get_call_groups(receiver_id).await; + let mut invites: HashMap> = HashMap::new(); + + for call in calls { + for inviter in call.members.read().await.iter() { + let inviter_id = inviter.user_id; + if let Some(call_ids) = invites.get_mut(&inviter_id) { + call_ids.push(call.call_id); + } else { + invites.insert(inviter_id, vec![call.call_id]); + } + } + } // Process contacts and add call information + // Enriched Contacts data: + // [{"user_id": "uuid", "calls": ["call_id"]}, {"user_id": "uuid"}] + let mut enriched_contacts = JsonValue::new_array(); + // Contacts data: + // [{"user_id": "uuid"}, {"user_id": "uuid"}] if let Some(contacts_data) = cv.get_data(DataTypes::user_ids) { - /*let contacts: Vec<(Uuid, String)> = parse_contacts(contacts_data); - for contact in &contacts { - interested_ids.push(contact.user_id); + if let JsonValue::Array(user_ids) = contacts_data { + for user_id in user_ids { + if let JsonValue::String(user_id_str) = user_id { + if let Ok(user_id) = Uuid::parse_str(user_id_str) { + interested_ids.push(user_id); + let mut enriched_contact = JsonValue::new_object(); + let _ = enriched_contact.insert("user_id", user_id.to_string()); + let _ = enriched_contact.insert("calls", JsonValue::new_array()); + let _ = enriched_contacts.push(enriched_contact); + } + } + } + } else { + enriched_contacts = contacts_data.clone(); } - - // Get call invites for receiver - let invites = CallManager::get_call_invites(receiver_id).await; - - // Enrich contacts with call information - let enriched_contacts = enrich_with_calls(contacts, invites); - - cv = cv.add_data(DataTypes::user_ids, enriched_contacts.into());*/ } // Notify OmegaConnection about user states @@ -305,7 +331,8 @@ impl IotaConnection { } // Forward to client - self.forward_to_client(cv).await; + self.forward_to_client(cv.add_data(DataTypes::user_ids, enriched_contacts)) + .await; } /// Forward message to client