diff --git a/Cargo.lock b/Cargo.lock index dc34d0d..057fef9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "0.7.19" @@ -114,6 +120,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -124,6 +139,36 @@ dependencies = [ "typenum", ] +[[package]] +name = "curl" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi", +] + +[[package]] +name = "curl-sys" +version = "0.4.59+curl-7.86.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", +] + [[package]] name = "cxx" version = "1.0.78" @@ -206,12 +251,34 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.42.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -462,12 +529,27 @@ checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" name = "libwebrtc-sys" version = "0.1.0" dependencies = [ + "curl", "cxx", "cxx-build", "env_logger", + "flate2", "glob", "log", "regex", + "tar", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] @@ -555,6 +637,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.4" @@ -564,7 +655,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -672,7 +763,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -864,7 +955,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -989,6 +1080,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -1270,39 +1372,105 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] diff --git a/crates/livekit-core/src/rtc_engine/rtc_events.rs b/crates/livekit-core/src/rtc_engine/rtc_events.rs index 6ccd0ed..dca1af6 100644 --- a/crates/livekit-core/src/rtc_engine/rtc_events.rs +++ b/crates/livekit-core/src/rtc_engine/rtc_events.rs @@ -2,11 +2,12 @@ use livekit_webrtc::data_channel::{DataChannel, OnMessageHandler}; use livekit_webrtc::jsep::{IceCandidate, SessionDescription}; use livekit_webrtc::media_stream::MediaStream; use livekit_webrtc::peer_connection::{ - OnAddTrackHandler, OnConnectionChangeHandler, OnDataChannelHandler, OnIceCandidateHandler, - PeerConnectionState, + OnAddTrackHandler, OnConnectionChangeHandler, OnDataChannelHandler, OnIceCandidateErrorHandler, + OnIceCandidateHandler, PeerConnectionState, }; use livekit_webrtc::rtp_receiver::RtpReceiver; use tokio::sync::mpsc; +use tracing::error; use crate::proto::SignalTarget; use crate::rtc_engine::pc_transport::OnOfferHandler; @@ -93,6 +94,18 @@ fn on_add_track(target: SignalTarget, emitter: RTCEmitter) -> OnAddTrackHandler }) } +fn on_ice_candidate_error( + target: SignalTarget, + _emitter: RTCEmitter, +) -> OnIceCandidateErrorHandler { + Box::new(move |address, port, url, error_code, error_text| { + error!( + "ICE candidate error ({:?}): address: {} - port: {} - url: {} - error_code: {} - error_text: {}", + target, address, port, url, error_code, error_text + ); + }) +} + pub fn forward_pc_events(transport: &mut PCTransport, rtc_emitter: RTCEmitter) { let signal_target = transport.signal_target(); transport @@ -111,6 +124,10 @@ pub fn forward_pc_events(transport: &mut PCTransport, rtc_emitter: RTCEmitter) { .peer_connection() .on_connection_change(on_connection_change(signal_target, rtc_emitter.clone())); + transport + .peer_connection() + .on_ice_candidate_error(on_ice_candidate_error(signal_target, rtc_emitter.clone())); + transport.on_offer(on_offer(transport.signal_target(), rtc_emitter.clone())); } diff --git a/crates/livekit-core/src/rtc_engine/rtc_session.rs b/crates/livekit-core/src/rtc_engine/rtc_session.rs index bde216f..14865ac 100644 --- a/crates/livekit-core/src/rtc_engine/rtc_session.rs +++ b/crates/livekit-core/src/rtc_engine/rtc_session.rs @@ -132,7 +132,6 @@ struct SessionInner { emitter: SessionEmitter, } - /// This struct holds a WebRTC session /// The session changes at every reconnection /// diff --git a/crates/livekit-webrtc/libwebrtc-sys/Cargo.toml b/crates/livekit-webrtc/libwebrtc-sys/Cargo.toml index cb2bc5b..d250c82 100644 --- a/crates/livekit-webrtc/libwebrtc-sys/Cargo.toml +++ b/crates/livekit-webrtc/libwebrtc-sys/Cargo.toml @@ -9,6 +9,9 @@ cxx = "1.0" log = "0.4" [build-dependencies] +curl = "0.4" +tar = "0.4" +flate2 = "1.0" cxx-build = "1.0" glob = "0.3.0" regex = "1.0" diff --git a/crates/livekit-webrtc/libwebrtc-sys/build.rs b/crates/livekit-webrtc/libwebrtc-sys/build.rs index fb00e3d..8424e2c 100644 --- a/crates/livekit-webrtc/libwebrtc-sys/build.rs +++ b/crates/livekit-webrtc/libwebrtc-sys/build.rs @@ -1,72 +1,93 @@ +use curl::easy::Easy; +use flate2::read::GzDecoder; use regex::Regex; use std::env; use std::fs; -use std::io::Write; +use std::io::{self, Write}; use std::path; use std::process::Command; +use tar::Archive; -const MAC_SDKS: &str = - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"; +const WEBRTC_TAG: &str = "m104.5112.06"; -fn get_mac_sysroot() -> String { - let mut sdks: Vec = vec![]; - let files = fs::read_dir(MAC_SDKS).unwrap(); - for entry in files { - let entry = entry.unwrap(); - let filename = entry.file_name().to_str().unwrap().to_owned(); - sdks.push(filename); +fn download_prebuilt( + target_os: &str, + target_arch: &str, + out_path: std::path::PathBuf, +) -> Result> { + let target_arch = match target_arch { + "aarch64" => "arm64", + _ => target_arch, + }; + + let file_name = format!("webrtc.{}_{}.tar.gz", target_os, target_arch); + let file_url = format!( + "https://github.com/webrtc-sdk/webrtc-build/releases/download/{}/{}", + WEBRTC_TAG, file_name + ); + let file_path = out_path.join(&file_name); + + if !out_path.exists() { + fs::create_dir(&out_path)?; } - sdks = sdks - .iter() - .filter(|value| value.contains("MacOSX1")) - .map(|original| original.to_owned()) - .collect(); + // Download the release archive + if !file_path.exists() { + let file = fs::File::create(&file_path)?; + { + let mut writer = io::BufWriter::new(file); + let mut handle = Easy::new(); + handle.url(&file_url)?; + handle.follow_location(true)?; + handle.write_function(move |data| Ok(writer.write(data).unwrap()))?; + handle.perform()?; - let last = sdks.last().unwrap(); - - format!("{}/{}", MAC_SDKS, &last) -} - -fn macos_link_search_path() -> Option { - let output = Command::new("clang") - .arg("--print-search-dirs") - .output() - .ok()?; - if !output.status.success() { - // Failed to run 'clang --print-search-dirs'. - return None; - } - - let stdout = String::from_utf8_lossy(&output.stdout); - for line in stdout.lines() { - if line.contains("libraries: =") { - let path = line.split('=').nth(1)?; - return Some(format!("{}/lib/darwin", path)); + let response_code = handle.response_code()?; + if response_code != 200 { + fs::remove_file(&file_path)?; + Err(format!( + "Failed to download WebRTC-SDK (Status: {}) {}", + response_code, file_url + ))? + } } + + // Extract the archive + let file = fs::File::open(&file_path)?; + let unzipped = GzDecoder::new(file); + let mut a = Archive::new(unzipped); + a.unpack(&out_path)?; } - // Failed to determine link search path. - None + Ok(out_path.join("webrtc")) } fn main() { - // TODO Download precompiled binaries of WebRTC for the target_os - let target_os = "windows"; - //let target_arch = "arm64"; + // Download the prebuilt WebRTC library. + let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + let install_directory = env::var("OUT_DIR").unwrap() + "/webrtc-sdk"; - let libwebrtc_dir = path::PathBuf::from("libwebrtc/src"); + let webrtc_dir = download_prebuilt( + &target_os, + &target_arch, + path::PathBuf::from(install_directory), + ) + .unwrap(); + + let webrtc_include = webrtc_dir.join("include"); + let webrtc_lib = webrtc_dir.join("lib"); // Just required for the bridge build to succeed. let includes = &[ path::PathBuf::from("./include"), - libwebrtc_dir.clone(), - libwebrtc_dir.join("third_party/abseil-cpp/"), - libwebrtc_dir.join("third_party/libyuv/include/"), - libwebrtc_dir.join("third_party/libc++/"), + webrtc_include.clone(), + webrtc_include.join("third_party/abseil-cpp/"), + webrtc_include.join("third_party/libyuv/include/"), + webrtc_include.join("third_party/libc++/"), // For mac & ios - libwebrtc_dir.join("sdk/objc"), - libwebrtc_dir.join("sdk/objc/base"), + webrtc_include.join("sdk/objc"), + webrtc_include.join("sdk/objc/base"), ]; let mut builder = cxx_build::bridges(&[ @@ -102,15 +123,10 @@ fn main() { println!( "cargo:rustc-link-search=native={}", - libwebrtc_dir - .join("out/Default/obj") - .canonicalize() - .unwrap() - .to_str() - .unwrap() + webrtc_lib.canonicalize().unwrap().to_str().unwrap() ); - match target_os { + match &target_os as &str { "windows" => { println!("cargo:rustc-link-lib=dylib=msdmo"); println!("cargo:rustc-link-lib=dylib=wmcodecdspuuid"); @@ -135,7 +151,6 @@ fn main() { .define("NOMINMAX", None); } "macos" => { - println!("cargo:rustc-link-lib=dylib=c++"); println!("cargo:rustc-link-lib=framework=Foundation"); println!("cargo:rustc-link-lib=framework=AVFoundation"); println!("cargo:rustc-link-lib=framework=CoreAudio"); @@ -151,19 +166,30 @@ fn main() { println!("cargo:rustc-link-lib=framework=IOKit"); println!("cargo:rustc-link-lib=framework=IOSurface"); println!("cargo:rustc-link-lib=static=webrtc"); + println!("cargo:rustc-link-lib=dylib=c++"); + println!("cargo:rustc-link-lib=clang_rt.osx"); + + let output = Command::new("clang") + .arg("--print-search-dirs") + .output() + .ok() + .unwrap(); + + let stdout = String::from_utf8_lossy(&output.stdout); + for line in stdout.lines() { + if line.contains("libraries: =") { + let path = line.split('=').nth(1).unwrap(); + let path = format!("{}/lib/darwin", path); + println!("cargo:rustc-link-search={}", path); + } + } builder .flag("-stdlib=libc++") .flag("-std=c++17") - .flag(format!("-isysroot{}", get_mac_sysroot()).as_str()) .define("WEBRTC_ENABLE_OBJC_SYMBOL_EXPORT", None) .define("WEBRTC_POSIX", None) .define("WEBRTC_MAC", None); - - if let Some(path) = macos_link_search_path() { - println!("cargo:rustc-link-lib=clang_rt.osx"); - println!("cargo:rustc-link-search={}", path); - } } "ios" => { builder @@ -205,7 +231,7 @@ fn main() { // Find JNI symbols let readelf_output = std::process::Command::new(toolchain.join("bin/llvm-readelf")) .arg("-Ws") - .arg(libwebrtc_dir.join("libwebrtc.a")) + .arg(webrtc_lib.join("/libwebrtc.a")) .output() .expect("failed to run llvm-readelf"); diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 4cfaa19..f810cc4 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -425,6 +425,36 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +[[package]] +name = "curl" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi", +] + +[[package]] +name = "curl-sys" +version = "0.4.59+curl-7.86.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", +] + [[package]] name = "cxx" version = "1.0.83" @@ -665,6 +695,18 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.42.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1112,11 +1154,26 @@ dependencies = [ name = "libwebrtc-sys" version = "0.1.0" dependencies = [ + "curl", "cxx", "cxx-build", + "flate2", "glob", "log", "regex", + "tar", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] @@ -2138,6 +2195,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -2975,6 +3043,15 @@ dependencies = [ "nix 0.24.3", ] +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] + [[package]] name = "xcursor" version = "0.3.4"