From 838675b682e5ab8b983e75d514e8b9a3582df9dc Mon Sep 17 00:00:00 2001 From: adel-signal Date: Mon, 6 May 2024 15:02:45 -0700 Subject: [PATCH 1/5] Update WebRTC to 6261h --- bin/fetch-artifact.py | 16 ++++++++-------- config/version.properties | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/fetch-artifact.py b/bin/fetch-artifact.py index f3878cf9..7dc526b7 100755 --- a/bin/fetch-artifact.py +++ b/bin/fetch-artifact.py @@ -18,14 +18,14 @@ UNVERIFIED_DOWNLOAD_NAME = "unverified.tmp" PREBUILD_CHECKSUMS = { - 'android': '69958caaefe350057cd2c77d001ee99afe646cb8e52a1f24873ef0db2a8f0aba', - 'ios': 'd1bd0e604f60a1799c8453b4c1f374389d5a3572547cc41d7576db1c81482c15', - 'linux-arm64': 'f67592faccf361c099b38e1de35ae2d1956e18e98160543f03f67df9d0418f7d', - 'linux-x64': '48f7259397c3fc7d811087fa4cc649f49a78d9e53f1d2b23cae8c6f1e1c1b4cd', - 'mac-arm64': 'd91539dcb73241702b7eacb4d4c4518d962432eafa2410b718af6c084ed667b4', - 'mac-x64': '461a5aee558c3f7bd43fe4e85fe929bc9b87d8ad58af23c95f2f327603a9dbef', - 'windows-arm64': '97a0190de3797c45f1b86348e139bef5ef910d1255decb4872569853bb53ec95', - 'windows-x64': 'aa1c12170acce307e9d46253f241ec7f91bbb3709939d3c59a8b43f13ae91fcd', + 'android': 'a80abd3b13be53c8a896b8780411be804d4c2da3f6149c708c6170f81e62ebb1', + 'ios': '5a6715df70085a3c5fcef034193fd817f56a21de5e214aae23cef7347d7933b4', + 'linux-arm64': 'f468545546ece82d4d1fffee90792d2ba33b7ebecace89f00684435ae685ff0e', + 'linux-x64': 'c77f61968c8458f341ec4aa921dc2f0775f6ca4ee85c98c646ac454adce87529', + 'mac-arm64': 'f46ef8b8e7f74dbf70df95fb4a83f669c4b970f500704e6d828efe8d05c1eed7', + 'mac-x64': '250045ea4808e466fc8907536863aa0cf75044cb0dd77cbe94c6edf06561d81c', + 'windows-arm64': 'de0e2e0f49982b22eb09f445970af80fe8046ceefc7c8069e1011529947328fa', + 'windows-x64': 'd2feebb8a03ed658a10001d79ef6face312ae4352baa1c2ad51b7683447aa55e', } diff --git a/config/version.properties b/config/version.properties index 7bbfbd54..47af4c89 100644 --- a/config/version.properties +++ b/config/version.properties @@ -1,4 +1,4 @@ -webrtc.version=6261g +webrtc.version=6261h ringrtc.version.major=2 ringrtc.version.minor=41 From f4427de1bb4ad3274dd6a59f0fafe08a666d0325 Mon Sep 17 00:00:00 2001 From: adel-signal Date: Tue, 7 May 2024 10:43:04 -0700 Subject: [PATCH 2/5] Add support for reporting rtc_stats to client application --- src/node/ringrtc/Service.ts | 19 +++++++++++ src/node/test/CallingClass.ts | 6 +++- src/rust/src/bin/group_call.rs | 4 +++ src/rust/src/core/call_manager.rs | 5 +++ src/rust/src/core/group_call.rs | 40 +++++++++++++++++++++-- src/rust/src/core/platform.rs | 2 ++ src/rust/src/electron.rs | 21 ++++++++++++ src/rust/src/native.rs | 12 +++++++ src/rust/src/webrtc/ffi/stats_observer.rs | 5 +++ src/rust/src/webrtc/sim/stats_observer.rs | 13 ++++++++ src/rust/src/webrtc/stats_observer.rs | 32 ++++++++++++++++-- 11 files changed, 153 insertions(+), 6 deletions(-) diff --git a/src/node/ringrtc/Service.ts b/src/node/ringrtc/Service.ts index 9aa0f20e..adc929a0 100644 --- a/src/node/ringrtc/Service.ts +++ b/src/node/ringrtc/Service.ts @@ -158,6 +158,8 @@ class NativeCallManager { Native.cm_getAudioOutputs; (NativeCallManager.prototype as any).setAudioOutput = Native.cm_setAudioOutput; (NativeCallManager.prototype as any).processEvents = Native.cm_processEvents; +(NativeCallManager.prototype as any).setRtcStatsInterval = + Native.cm_setRtcStatsInterval; type GroupId = Buffer; type GroupCallUserId = Buffer; @@ -423,6 +425,8 @@ export class RingRTCType { ) => void) | null = null; + handleRtcStatsReport: ((reportJson: string) => void) | null = null; + constructor() { this.callManager = new NativeCallManager(this) as unknown as CallManager; this._call = null; @@ -1476,6 +1480,13 @@ export class RingRTCType { }); } + // Called by Rust + handleRtcStatsReportComplete(reportJson: string): void { + if (this.handleRtcStatsReport) { + this.handleRtcStatsReport(reportJson); + } + } + // Called by Rust onLogMessage( level: number, @@ -2610,6 +2621,10 @@ export class GroupCall { this._observer.onRemoteDeviceStatesChanged(this); } } + + setRtcStatsInterval(intervalMillis: number): void { + this._callManager.setRtcStatsInterval(this._clientId, intervalMillis); + } } // Implements VideoSource for use in CanvasVideoRenderer @@ -2911,6 +2926,10 @@ export interface CallManager { maxWidth: number, maxHeight: number ): [number, number] | undefined; + setRtcStatsInterval( + clientId: GroupCallClientId, + intervalMillis: number + ): void; // Responses come back via handleCallLinkResponse readCallLink( requestId: number, diff --git a/src/node/test/CallingClass.ts b/src/node/test/CallingClass.ts index f02eb190..2b5048d5 100644 --- a/src/node/test/CallingClass.ts +++ b/src/node/test/CallingClass.ts @@ -174,6 +174,10 @@ export class CallingClass { log('handleGroupCallRingUpdate'); } + private handleRtcStatsReport(reportJson: string): void { + log('handleRtcStatsReport'); + } + //////////////////////////////////////////////////////////////////////////////// // Support @@ -235,7 +239,7 @@ export class CallingClass { this.handleSendCallMessageToGroup.bind(this); RingRTC.handleGroupCallRingUpdate = this.handleGroupCallRingUpdate.bind(this); - + RingRTC.handleRtcStatsReport = this.handleRtcStatsReport.bind(this); RingRTC.setSelfUuid(Buffer.from(uuidToBytes(this._id))); } diff --git a/src/rust/src/bin/group_call.rs b/src/rust/src/bin/group_call.rs index d26ae1ec..cb822721 100644 --- a/src/rust/src/bin/group_call.rs +++ b/src/rust/src/bin/group_call.rs @@ -145,6 +145,10 @@ impl group_call::Observer for Observer { fn handle_raised_hands(&self, _client_id: ClientId, raised_hands: Vec) { info!("Raised hands changed to {:?}", raised_hands); } + + fn handle_rtc_stats_report(&self, _report_json: String) { + // ignore + } } impl VideoSink for Observer { diff --git a/src/rust/src/core/call_manager.rs b/src/rust/src/core/call_manager.rs index 6fd2d2b3..019ff64f 100644 --- a/src/rust/src/core/call_manager.rs +++ b/src/rust/src/core/call_manager.rs @@ -2623,6 +2623,10 @@ where platform_handler!(self, handle_raised_hands, client_id, raised_hands); } + fn handle_rtc_stats_report(&self, report_json: String) { + platform_handler!(self, handle_rtc_stats_report, report_json); + } + fn handle_ended(&self, client_id: group_call::ClientId, reason: group_call::EndReason) { info!("handle_ended({:?}):", reason); platform_handler!(self, handle_ended, client_id, reason); @@ -2947,6 +2951,7 @@ where forward_group_call_api!(block_client(other_client_id: DemuxId)); forward_group_call_api!(set_group_members(members: Vec)); forward_group_call_api!(set_membership_proof(proof: Vec)); + forward_group_call_api!(set_rtc_stats_interval(interval: Duration)); } #[cfg(test)] diff --git a/src/rust/src/core/group_call.rs b/src/rust/src/core/group_call.rs index 0e0d8233..54ffd23f 100644 --- a/src/rust/src/core/group_call.rs +++ b/src/rust/src/core/group_call.rs @@ -269,6 +269,8 @@ pub trait Observer { fn handle_raised_hands(&self, client_id: ClientId, raised_hands: Vec); + fn handle_rtc_stats_report(&self, report_json: String); + // This will be the last callback. // The observer can assume the Call is completely shut down and can be deleted. fn handle_ended(&self, client_id: ClientId, reason: EndReason); @@ -980,6 +982,7 @@ struct State { // Things for getting statistics from the PeerConnection // Stats gathering happens only when joined next_stats_time: Option, + get_stats_interval: Duration, stats_observer: Box, // Things for getting audio levels from the PeerConnection @@ -1076,7 +1079,7 @@ const TICK_INTERVAL: Duration = Duration::from_millis(200); const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(1); // How often to get and log stats. -const STATS_INTERVAL: Duration = Duration::from_secs(10); +const DEFAULT_STATS_INTERVAL: Duration = Duration::from_secs(10); const STATS_INITIAL_OFFSET: Duration = Duration::from_secs(2); // How often to request an updated membership proof (24 hours). @@ -1211,7 +1214,11 @@ impl Client { next_heartbeat_time: None, next_stats_time: None, - stats_observer: create_stats_observer(call_id_for_stats, STATS_INTERVAL), + get_stats_interval: DEFAULT_STATS_INTERVAL, + stats_observer: create_stats_observer( + call_id_for_stats, + DEFAULT_STATS_INTERVAL, + ), audio_levels_interval, next_audio_levels_time: None, @@ -1321,7 +1328,10 @@ impl Client { let _ = state .peer_connection .get_stats(state.stats_observer.as_ref()); - state.next_stats_time = Some(now + STATS_INTERVAL); + state.next_stats_time = Some(now + state.get_stats_interval); + } + if let Some(report_json) = state.stats_observer.take_stats_report() { + state.observer.handle_rtc_stats_report(report_json) } } @@ -2623,6 +2633,28 @@ impl Client { }); } + pub fn set_rtc_stats_interval(&self, interval: Duration) { + info!( + "group_call::Client(outer)::set_rtc_stats_interval: {}, interval: {:?})", + self.client_id, interval + ); + + self.actor.send(move |state| { + let old_stats_interval = state.get_stats_interval; + state.get_stats_interval = if interval.is_zero() { + state.stats_observer.set_collect_raw_stats_report(false); + DEFAULT_STATS_INTERVAL + } else { + state.stats_observer.set_collect_raw_stats_report(true); + interval + }; + + state.next_stats_time = state + .next_stats_time + .map(|stats_time| stats_time - old_stats_interval + state.get_stats_interval); + }); + } + // Most of the logic moved to inner method so this can be called by both // set_peek_result() and as a callback to SfuClient::request_remote_devices. fn set_peek_result_inner(state: &mut State, result: PeekResult) { @@ -4760,6 +4792,8 @@ mod tests { fn handle_raised_hands(&self, _client_id: ClientId, _raised_hands: Vec) {} + fn handle_rtc_stats_report(&self, _report_json: String) {} + fn handle_peek_changed( &self, _client_id: ClientId, diff --git a/src/rust/src/core/platform.rs b/src/rust/src/core/platform.rs index 2984cd74..d02e841a 100644 --- a/src/rust/src/core/platform.rs +++ b/src/rust/src/core/platform.rs @@ -267,5 +267,7 @@ pub trait Platform: sfu::Delegate + fmt::Debug + fmt::Display + Send + Sized + ' fn handle_raised_hands(&self, client_id: group_call::ClientId, raised_hands: Vec); + fn handle_rtc_stats_report(&self, _report_json: String) {} + fn handle_ended(&self, client_id: group_call::ClientId, reason: group_call::EndReason); } diff --git a/src/rust/src/electron.rs b/src/rust/src/electron.rs index 3dcba719..45ca0a2d 100644 --- a/src/rust/src/electron.rs +++ b/src/rust/src/electron.rs @@ -2127,6 +2127,19 @@ fn setAudioOutput(mut cx: FunctionContext) -> JsResult { Ok(cx.undefined().upcast()) } +#[allow(non_snake_case)] +fn setRtcStatsInterval(mut cx: FunctionContext) -> JsResult { + let client_id = cx.argument::(0)?.value(&mut cx) as group_call::ClientId; + let interval = Duration::from_millis(cx.argument::(1)?.value(&mut cx) as u64); + with_call_endpoint(&mut cx, |endpoint| { + endpoint + .call_manager + .set_rtc_stats_interval(client_id, interval) + }); + + Ok(cx.undefined().upcast()) +} + #[allow(non_snake_case)] fn processEvents(mut cx: FunctionContext) -> JsResult { let this = cx.this::()?; @@ -2785,6 +2798,13 @@ fn processEvents(mut cx: FunctionContext) -> JsResult { let method = observer.get::(&mut cx, method_name)?; method.call(&mut cx, observer, args)?; } + + Event::GroupUpdate(GroupUpdate::RtcStatsReportComplete { report_json }) => { + let method_name = "handleRtcStatsReportComplete"; + let args = [cx.string(report_json).upcast()]; + let method = observer.get::(&mut cx, method_name)?; + method.call(&mut cx, observer, args)?; + } } } Ok(cx.undefined().upcast()) @@ -2945,6 +2965,7 @@ fn register(mut cx: ModuleContext) -> NeonResult<()> { cx.export_function("cm_setAudioInput", setAudioInput)?; cx.export_function("cm_getAudioOutputs", getAudioOutputs)?; cx.export_function("cm_setAudioOutput", setAudioOutput)?; + cx.export_function("cm_setRtcStatsInterval", setRtcStatsInterval)?; cx.export_function("cm_processEvents", processEvents)?; Ok(()) } diff --git a/src/rust/src/native.rs b/src/rust/src/native.rs index fdbb347b..fd2d2f36 100644 --- a/src/rust/src/native.rs +++ b/src/rust/src/native.rs @@ -252,6 +252,9 @@ pub enum GroupUpdate { }, Reactions(group_call::ClientId, Vec), RaisedHands(group_call::ClientId, Vec), + RtcStatsReportComplete { + report_json: String, + }, } impl fmt::Display for GroupUpdate { @@ -281,6 +284,7 @@ impl fmt::Display for GroupUpdate { GroupUpdate::RaisedHands(_, raised_hands) => { format!("RaisedHands({:?})", raised_hands) } + GroupUpdate::RtcStatsReportComplete { .. } => "RtcStatsReportComplete".to_string(), }; write!(f, "({})", display) } @@ -990,6 +994,14 @@ impl Platform for NativePlatform { } } + fn handle_rtc_stats_report(&self, report_json: String) { + debug!("NativePlatform::handle_rtc_stats_report"); + let result = self.send_group_update(GroupUpdate::RtcStatsReportComplete { report_json }); + if result.is_err() { + error!("{:?}", result.err()); + } + } + fn handle_ended(&self, client_id: group_call::ClientId, reason: group_call::EndReason) { info!("NativePlatform::handle_ended(): id: {}", client_id); diff --git a/src/rust/src/webrtc/ffi/stats_observer.rs b/src/rust/src/webrtc/ffi/stats_observer.rs index ec9ceab7..724108d4 100644 --- a/src/rust/src/webrtc/ffi/stats_observer.rs +++ b/src/rust/src/webrtc/ffi/stats_observer.rs @@ -24,4 +24,9 @@ extern "C" { stats_observer: webrtc::ptr::Borrowed, stats_observer_cbs: webrtc::ptr::Borrowed, ) -> webrtc::ptr::OwnedRc; + + pub fn Rust_setCollectRawStatsReport( + stats_observer: webrtc::ptr::BorrowedRc, + collect_raw_stats_report: bool, + ); } diff --git a/src/rust/src/webrtc/sim/stats_observer.rs b/src/rust/src/webrtc/sim/stats_observer.rs index 2ea40a66..08d7b0c6 100644 --- a/src/rust/src/webrtc/sim/stats_observer.rs +++ b/src/rust/src/webrtc/sim/stats_observer.rs @@ -44,10 +44,23 @@ pub unsafe fn Rust_createStatsObserver( // Hit on the onComplete() callback let callbacks = callbacks.as_ptr() as *const StatsObserverCallbacks; + let report_json = std::ffi::CString::new("{}").expect("CString::new failed"); ((*callbacks).onStatsComplete)( webrtc::ptr::Borrowed::from_ptr(stats_observer.as_ptr() as *mut StatsObserver), webrtc::ptr::Borrowed::from_ptr(&dummy), + webrtc::ptr::Borrowed::from_ptr(report_json.as_ptr()), ); webrtc::ptr::OwnedRc::from_ptr(&FAKE_STATS_OBSERVER) } + +#[allow(non_snake_case, clippy::missing_safety_doc)] +pub unsafe fn Rust_setCollectRawStatsReport( + _stats_observer: webrtc::ptr::BorrowedRc, + collect_raw_stats_report: bool, +) { + info!( + "Rust_setCollectRawStatsReport: {}", + collect_raw_stats_report + ); +} diff --git a/src/rust/src/webrtc/stats_observer.rs b/src/rust/src/webrtc/stats_observer.rs index b38160a5..d20f24d1 100644 --- a/src/rust/src/webrtc/stats_observer.rs +++ b/src/rust/src/webrtc/stats_observer.rs @@ -9,6 +9,7 @@ use std::{ borrow::Cow, collections::HashMap, slice, + sync::Mutex, time::{Duration, Instant}, }; @@ -44,6 +45,8 @@ struct Stats { video_send: HashMap, audio_recv: HashMap, video_recv: HashMap, + + report_json: Mutex, } /// Collector object for obtaining statistics. #[derive(Debug)] @@ -320,7 +323,7 @@ impl StatsObserver { } /// Invoked when statistics are received via the stats observer callback. - fn on_stats_complete(&mut self, media_statistics: &MediaStatistics) { + fn on_stats_complete(&mut self, media_statistics: &MediaStatistics, report_json: String) { let seconds_elapsed = if self.stats.timestamp_us > 0 { (media_statistics.timestamp_us - self.stats.timestamp_us) as f32 / 1_000_000.0 } else { @@ -331,6 +334,9 @@ impl StatsObserver { self.print_system(); let stats = &mut self.stats; + let mut stats_report_json = stats.report_json.lock().unwrap(); + *stats_report_json = report_json; + drop(stats_report_json); if media_statistics.audio_sender_statistics_size > 0 { let audio_senders = unsafe { @@ -453,6 +459,21 @@ impl StatsObserver { pub fn rffi(&self) -> &webrtc::Arc { &self.rffi } + + pub fn take_stats_report(&self) -> Option { + let mut stats_report_json = self.stats.report_json.lock().unwrap(); + if !stats_report_json.is_empty() { + Some(std::mem::take(&mut *stats_report_json)) + } else { + None + } + } + + pub fn set_collect_raw_stats_report(&self, collect_raw_stats_report: bool) { + unsafe { + stats::Rust_setCollectRawStatsReport(self.rffi.as_borrowed(), collect_raw_stats_report) + }; + } } #[repr(C)] @@ -573,12 +594,18 @@ pub struct MediaStatistics { extern "C" fn stats_observer_OnStatsComplete( stats_observer: webrtc::ptr::Borrowed, values: webrtc::ptr::Borrowed, + report_json: webrtc::ptr::Borrowed, ) { // Safe because the observer should still be alive (it was just passed to us) if let Some(stats_observer) = unsafe { stats_observer.as_mut() } { + let report_json = unsafe { + std::ffi::CStr::from_ptr(report_json.as_ptr()) + .to_string_lossy() + .into_owned() + }; // Safe because the values should still be alive (it was just passed to us) if let Some(values) = unsafe { values.as_ref() } { - stats_observer.on_stats_complete(values); + stats_observer.on_stats_complete(values, report_json); } else { error!("stats_observer_OnStatsComplete() with null values"); } @@ -594,6 +621,7 @@ pub struct StatsObserverCallbacks { pub onStatsComplete: extern "C" fn( stats_observer: webrtc::ptr::Borrowed, values: webrtc::ptr::Borrowed, + report_json: webrtc::ptr::Borrowed, ), } From 9b68bf150a1db8c9191da749a706c3aa464bfeab Mon Sep 17 00:00:00 2001 From: Rashad Sookram Date: Tue, 14 May 2024 16:42:05 -0400 Subject: [PATCH 3/5] Update to WebRTC 6261i --- bin/fetch-artifact.py | 16 ++++++++-------- config/version.properties | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/fetch-artifact.py b/bin/fetch-artifact.py index 7dc526b7..73a176d5 100755 --- a/bin/fetch-artifact.py +++ b/bin/fetch-artifact.py @@ -18,14 +18,14 @@ UNVERIFIED_DOWNLOAD_NAME = "unverified.tmp" PREBUILD_CHECKSUMS = { - 'android': 'a80abd3b13be53c8a896b8780411be804d4c2da3f6149c708c6170f81e62ebb1', - 'ios': '5a6715df70085a3c5fcef034193fd817f56a21de5e214aae23cef7347d7933b4', - 'linux-arm64': 'f468545546ece82d4d1fffee90792d2ba33b7ebecace89f00684435ae685ff0e', - 'linux-x64': 'c77f61968c8458f341ec4aa921dc2f0775f6ca4ee85c98c646ac454adce87529', - 'mac-arm64': 'f46ef8b8e7f74dbf70df95fb4a83f669c4b970f500704e6d828efe8d05c1eed7', - 'mac-x64': '250045ea4808e466fc8907536863aa0cf75044cb0dd77cbe94c6edf06561d81c', - 'windows-arm64': 'de0e2e0f49982b22eb09f445970af80fe8046ceefc7c8069e1011529947328fa', - 'windows-x64': 'd2feebb8a03ed658a10001d79ef6face312ae4352baa1c2ad51b7683447aa55e', + 'android': '3dd5d5f1987489aeba4f7048593914fbec6f7c726d3d75bfde9ac61a98d45575', + 'ios': '4559bab546155bd6f128d893f7fb92351d154cbff23a615813be885e56db9317', + 'linux-arm64': '21a7f0ce6947f42981876fb7cf5c3f1905ccd25b85b922468689d6c80cdc8062', + 'linux-x64': '8259927f292e950ebe9ed2e274e23ca6ff7e279a887dbd02d6f6a165026731a2', + 'mac-arm64': '7dba81c95d70562d9ce8e0968ecc352fd636596712df9cba3fab3475ee32cc70', + 'mac-x64': 'd476e6d86c5b24995e08ff4c5d3a78f428a2fac57f124ebb8b553386fffbf783', + 'windows-arm64': '30caf82f2e956f22317830fa183889bf8ddf2184c6ac32bbf901174c4ea7aa9d', + 'windows-x64': '798405d6168b603be54aea7c329943f05356cc5184d618bda3ef805bedb88e6f', } diff --git a/config/version.properties b/config/version.properties index 47af4c89..2b763334 100644 --- a/config/version.properties +++ b/config/version.properties @@ -1,4 +1,4 @@ -webrtc.version=6261h +webrtc.version=6261i ringrtc.version.major=2 ringrtc.version.minor=41 From d8df90d43563bf0d6e703e71c9c2f379b8d91958 Mon Sep 17 00:00:00 2001 From: adel-signal Date: Tue, 14 May 2024 14:54:54 -0700 Subject: [PATCH 4/5] Add prebuilt_webrtc feature, supports rust-only build on linux & mac --- .github/workflows/ringrtc.yml | 25 ++++++++++ BUILDING.md | 14 +++++- bin/fetch-artifact.py | 50 +++++++++++++------- src/rust/Cargo.toml | 1 + src/rust/build.rs | 88 +++++++++++++++++++++++++++++------ 5 files changed, 145 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ringrtc.yml b/.github/workflows/ringrtc.yml index 1bcf8eeb..4fec22cc 100644 --- a/.github/workflows/ringrtc.yml +++ b/.github/workflows/ringrtc.yml @@ -119,6 +119,31 @@ jobs: - run: ${{ matrix.test-runner }} yarn test working-directory: src/node + cargo_build_using_prebuilt: + name: RingRTC as dependency (using Prebuilt WebRTC) + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-13] + include: + - os: ubuntu-latest + install-deps: sudo apt-get update && sudo apt-get install -y protobuf-compiler + - os: macos-13 + install-deps: brew install protobuf coreutils + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash # as opposed to PowerShell + steps: + - name: Install dependencies + run: ${{ matrix.install-deps }} + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: 'src/node/.nvmrc' + - run: rustup toolchain install $(cat rust-toolchain) --profile minimal + - run: cargo build -p ringrtc --features prebuilt_webrtc + android: name: Android Build runs-on: ubuntu-latest diff --git a/BUILDING.md b/BUILDING.md index de50aad2..b3cda7b6 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -126,9 +126,19 @@ You can then add the Signal repo to sync with upstream changes: git remote add upstream https://github.com/signalapp/ringrtc.git ## Building - Important: If building the for the first time, it will take a long time to download -WebRTC dependencies and then a long time to build WebRTC and RingRTC. +WebRTC dependencies and then a long time to build WebRTC and RingRTC from scratch. + + +To quickly build RingRTC on Linux or MacOS using only the rust toolchain, you must add the `prebuilt_webrtc` feature. Note this is limited to arm64 and x86_64 architectures: + +Examples: +```sh +cargo build -p ringrtc --features prebuilt_webrtc +cargo build -p ringrtc --features prebuilt_webrtc --target aarch64-apple-darwin +cargo build -p ringrtc --features prebuilt_webrtc --target x86_64-apple-darwin +cargo build -p ringrtc --features prebuilt_webrtc --target aarch64-unknown-linux-gnu +``` ### Android diff --git a/bin/fetch-artifact.py b/bin/fetch-artifact.py index 73a176d5..b0f19ff2 100755 --- a/bin/fetch-artifact.py +++ b/bin/fetch-artifact.py @@ -29,25 +29,39 @@ } +def resolve_os(os_name: str) -> str: + if os_name in ['darwin', 'macos']: + return 'mac' + return os_name + + +def resolve_arch(arch_name: str) -> str: + if arch_name in ['x86_64', 'amd64']: + return 'x64' + if arch_name in ['arm64', 'aarch64']: + return 'arm64' + return arch_name + + def resolve_platform(platform_name: str) -> str: if platform_name in PREBUILD_CHECKSUMS: return platform_name - - if platform_name in ['windows', 'mac', 'linux']: - arch_name = platform.machine().lower() - if arch_name in ['x86_64', 'amd64']: - return resolve_platform(platform_name + '-x64') - if arch_name in ['arm64', 'aarch64']: - return resolve_platform(platform_name + '-arm64') - raise AssertionError('unsupported architecture: ' + arch_name) - if platform_name == 'desktop': - os_name = platform.system().lower() - if os_name == 'darwin': - return resolve_platform('mac') - return resolve_platform(os_name) + return resolve_platform(platform.system().lower()) + + splits = platform_name.split('-') + os_name = resolve_os(splits[0]) + if len(splits) > 2: + raise AssertionError('unsupported platform format: ' + platform_name) + elif len(splits) == 2: + arch_name = resolve_arch(splits[1]) + else: + arch_name = resolve_arch(platform.machine().lower()) - raise AssertionError('unsupported platform: ' + platform_name) + resolved_platform_name = "{}-{}".format(os_name, arch_name) + if resolved_platform_name not in PREBUILD_CHECKSUMS: + raise AssertionError('unsupported platform: ' + resolved_platform_name) + return resolved_platform_name def build_argument_parser() -> argparse.ArgumentParser: @@ -128,11 +142,11 @@ def main() -> None: if not url: if not args.webrtc_version: parser.error(message='--platform requires --webrtc-version') - platform = resolve_platform(args.platform) + platform_name = resolve_platform(args.platform) build_mode = 'debug' if args.debug else 'release' - url = "https://build-artifacts.signal.org/libraries/webrtc-{}-{}-{}.tar.bz2".format(args.webrtc_version, platform, build_mode) + url = "https://build-artifacts.signal.org/libraries/webrtc-{}-{}-{}.tar.bz2".format(args.webrtc_version, platform_name, build_mode) if not checksum: - checksum = PREBUILD_CHECKSUMS[platform] + checksum = PREBUILD_CHECKSUMS[platform_name] if not checksum: parser.error(message='missing --checksum') @@ -145,7 +159,7 @@ def main() -> None: if args.skip_extract: return - print("extracting {}...".format(archive_file), file=sys.stderr) + print("extracting {} to {}".format(archive_file, args.output_dir), file=sys.stderr) open_archive.seek(0) tarfile.open(fileobj=open_archive).extractall(path=args.output_dir) diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 94ab1976..96bd08b0 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -98,6 +98,7 @@ default = [] sim = [] electron = ["neon", "native"] native = [] +prebuilt_webrtc = ["native"] simnet = ["injectable_network"] injectable_network = [] http = ["ureq", "rustls"] diff --git a/src/rust/build.rs b/src/rust/build.rs index 7ccf0ca8..25098266 100644 --- a/src/rust/build.rs +++ b/src/rust/build.rs @@ -3,7 +3,9 @@ // SPDX-License-Identifier: AGPL-3.0-only // -use std::env; +use core::panic; +use std::env::{self, VarError}; +use std::fs; use std::process::Command; fn build_protos() { @@ -20,17 +22,47 @@ fn build_protos() { } } +// corresponds to PROJECT_DIR in bin/env.sh +fn project_dir() -> String { + format!("{}/../..", env::current_dir().unwrap().display()) +} + +// corresponds to CONFIG_DIR in bin/env.sh +fn config_dir() -> String { + format!("{}/config", project_dir()) +} + +// corresponds to default OUTPUT_DIR in bin/env.sh +fn default_output_dir() -> String { + format!("{}/out", project_dir()) +} + fn main() { let target = env::var("TARGET").unwrap(); let profile = env::var("PROFILE").unwrap(); - let out_dir = env::var("OUTPUT_DIR"); + let out_dir = env::var("OUTPUT_DIR") + .or_else(|err| match err { + VarError::NotPresent => { + let out_dir = default_output_dir(); + eprintln!("Defaulting WebRTC output directory, OUTPUT_DIR={}", out_dir); + Ok(out_dir) + } + err => Err(err), + }) + .expect("Invalid OUTPUT_DIR environment variable"); + let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + // TARGET and PROFILE are set by Cargo, but OUTPUT_DIR is external. println!("cargo:rerun-if-env-changed=OUTPUT_DIR"); let debug = profile.contains("debug"); let build_type = if debug { "debug" } else { "release" }; - eprintln!("build.rs: target: {}, profile: {}", target, profile); + eprintln!( + "build.rs: target: {}, profile: {}, os: {}, arch: {}, outdir: {}", + target, profile, target_os, target_arch, out_dir + ); // We only depend on environment variables, not any files. // Explicitly state that by depending on build.rs itself, as recommended. @@ -46,16 +78,19 @@ fn main() { } if cfg!(feature = "native") { - if let Ok(out_dir) = out_dir { - println!( - "cargo:rustc-link-search=native={}/{}/obj/", - out_dir, build_type, - ); - println!("cargo:rerun-if-changed={}/{}/obj/", out_dir, build_type,); + let webrtc_dir = if cfg!(feature = "prebuilt_webrtc") { + if let Err(e) = fs::create_dir_all(&out_dir) { + panic!("Failed to create webrtc out directory: {:?}", e); + } + fetch_webrtc_artifact(&target_os, &target_arch, &out_dir).unwrap(); + // Ignore build type since we only have release prebuilts + format!("{}/release/obj/", out_dir) } else { - println!("cargo:warning=No WebRTC output directory (OUTPUT_DIR) defined!"); - } - + format!("{}/{}/obj", out_dir, build_type) + }; + println!("cargo:rerun-if-changed={}", webrtc_dir); + println!("cargo:rerun-if-changed={}", config_dir()); + println!("cargo:rustc-link-search=native={}", webrtc_dir); println!("cargo:rustc-link-lib=webrtc"); if cfg!(target_os = "macos") { @@ -89,7 +124,7 @@ fn main() { } else { println!("cargo:rustc-link-lib=stdc++"); } - } else if env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" { + } else if target_os == "android" { // Rely on the compile invocation to provide the right search path. println!("cargo:rustc-link-lib=ringrtc_rffi"); } @@ -117,3 +152,30 @@ fn macos_link_search_path() -> Option { // Failed to determine link search path. None } + +fn fetch_webrtc_artifact( + target_os: &str, + target_arch: &str, + artifact_out_dir: &str, +) -> Result<(), String> { + let fetch_script = format!("{}/bin/fetch-artifact", project_dir()); + let platform = format!("{}-{}", target_os, target_arch); + eprintln!( + "Fetching prebuilt webrtc for {} and outputting to {}...", + platform, artifact_out_dir + ); + + let output = Command::new(fetch_script) + .current_dir(project_dir()) + .env("OUTPUT_DIR", artifact_out_dir) + .arg("--platform") + .arg(platform) + .output() + .expect("bin/fetch-artifact failed to complete"); + + if !output.status.success() { + // debug format shows captured stdout/stderr + return Err(format!("Failed to fetch artifact: {:?}", output)); + } + Ok(()) +} From 2a7c164b47177bf23ccca4ef3b5a764f15cd78e8 Mon Sep 17 00:00:00 2001 From: Rashad Sookram Date: Wed, 15 May 2024 10:33:09 -0400 Subject: [PATCH 5/5] Bump version to v2.42.0 --- CHANGELOG.md | 8 ++++++++ Cargo.lock | 2 +- SignalRingRTC.podspec | 2 +- acknowledgments/acknowledgments.html | 2 +- acknowledgments/acknowledgments.md | 2 +- acknowledgments/acknowledgments.plist | 2 +- config/version.properties | 2 +- src/node/package.json | 2 +- src/rust/Cargo.toml | 2 +- 9 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8591f30c..0577d1cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## v2.42.0 + +- Add support for reporting rtc_stats to client application + +- Update to webrtc 6261i + - Support for reporting rtc_stats + - Enable per-layer PLI for screen sharing + ## v2.41.0 - Call links: Add Call Link state to PeekInfo diff --git a/Cargo.lock b/Cargo.lock index 1bfa36ef..0385f9d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2021,7 +2021,7 @@ dependencies = [ [[package]] name = "ringrtc" -version = "2.41.0" +version = "2.42.0" dependencies = [ "aes", "aes-gcm-siv", diff --git a/SignalRingRTC.podspec b/SignalRingRTC.podspec index 961e2b55..d55eff7a 100644 --- a/SignalRingRTC.podspec +++ b/SignalRingRTC.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = "SignalRingRTC" - s.version = "2.41.0" + s.version = "2.42.0" s.summary = "A Swift & Objective-C library used by the Signal iOS app for WebRTC interactions." s.description = <<-DESC diff --git a/acknowledgments/acknowledgments.html b/acknowledgments/acknowledgments.html index 0e4ddbb7..bb0591cc 100644 --- a/acknowledgments/acknowledgments.html +++ b/acknowledgments/acknowledgments.html @@ -735,7 +735,7 @@

Used by:

  • libsignal-core 0.1.0
  • partial-default-derive 0.1.0
  • regex-aot 0.1.0
  • -
  • ringrtc 2.41.0
  • +
  • ringrtc 2.42.0
  • GNU AFFERO GENERAL PUBLIC LICENSE
     Version 3, 19 November 2007
    diff --git a/acknowledgments/acknowledgments.md b/acknowledgments/acknowledgments.md
    index bc3ca933..67c562b1 100644
    --- a/acknowledgments/acknowledgments.md
    +++ b/acknowledgments/acknowledgments.md
    @@ -669,7 +669,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
     
     ```
     
    -## libsignal-core 0.1.0, partial-default-derive 0.1.0, regex-aot 0.1.0, ringrtc 2.41.0
    +## libsignal-core 0.1.0, partial-default-derive 0.1.0, regex-aot 0.1.0, ringrtc 2.42.0
     
     ```
     GNU AFFERO GENERAL PUBLIC LICENSE
    diff --git a/acknowledgments/acknowledgments.plist b/acknowledgments/acknowledgments.plist
    index c5fa94b3..dadd8cf6 100644
    --- a/acknowledgments/acknowledgments.plist
    +++ b/acknowledgments/acknowledgments.plist
    @@ -924,7 +924,7 @@ You should also get your employer (if you work as a programmer) or school, if an
     			License
     			GNU Affero General Public License v3.0
     			Title
    -			libsignal-core 0.1.0, partial-default-derive 0.1.0, regex-aot 0.1.0, ringrtc 2.41.0
    +			libsignal-core 0.1.0, partial-default-derive 0.1.0, regex-aot 0.1.0, ringrtc 2.42.0
     			Type
     			PSGroupSpecifier
     		
    diff --git a/config/version.properties b/config/version.properties
    index 2b763334..311b9ee1 100644
    --- a/config/version.properties
    +++ b/config/version.properties
    @@ -1,5 +1,5 @@
     webrtc.version=6261i
     
     ringrtc.version.major=2
    -ringrtc.version.minor=41
    +ringrtc.version.minor=42
     ringrtc.version.revision=0
    diff --git a/src/node/package.json b/src/node/package.json
    index 90c598da..64b18209 100644
    --- a/src/node/package.json
    +++ b/src/node/package.json
    @@ -1,6 +1,6 @@
     {
       "name": "@signalapp/ringrtc",
    -  "version": "2.41.0",
    +  "version": "2.42.0",
       "description": "Signal Messenger voice and video calling library.",
       "main": "dist/index.js",
       "types": "dist/index.d.ts",
    diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
    index 96bd08b0..3541e944 100644
    --- a/src/rust/Cargo.toml
    +++ b/src/rust/Cargo.toml
    @@ -5,7 +5,7 @@
     
     [package]
     name = "ringrtc"
    -version = "2.41.0"
    +version = "2.42.0"
     authors = ["Calling Team "]
     edition = "2021"
     description = "A Rust interface for WebRTC"