@@ -24,9 +24,10 @@ use std::{
2424use fs2:: FileExt ;
2525use regex:: Regex ;
2626use reqwest:: StatusCode ;
27+ use sha2:: { Digest , Sha256 } ;
2728
2829pub const SCRATH_PATH : & str = "livekit_webrtc" ;
29- pub const WEBRTC_TAG : & str = "webrtc-b99fd2c-6 " ;
30+ pub const WEBRTC_TAG : & str = "webrtc-ed96590 " ;
3031pub const IGNORE_DEFINES : [ & str ; 2 ] = [ "CR_CLANG_REVISION" , "CR_XCODE_VERSION" ] ;
3132
3233pub fn target_os ( ) -> String {
@@ -84,23 +85,14 @@ pub fn custom_dir() -> Option<path::PathBuf> {
8485
8586/// Location of the downloaded webrtc binaries
8687pub fn prebuilt_dir ( ) -> path:: PathBuf {
87- let target_dir = PathBuf :: from ( std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ) ;
88- path:: Path :: new ( & target_dir) . join ( format ! (
88+ PathBuf :: from ( std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ) . join ( format ! (
8989 "livekit/{}-{}/{}" ,
9090 webrtc_triple( ) ,
9191 WEBRTC_TAG ,
9292 webrtc_triple( )
9393 ) )
9494}
9595
96- pub fn download_url ( ) -> String {
97- format ! (
98- "https://github.com/livekit/client-sdk-rust/releases/download/{}/{}.zip" ,
99- WEBRTC_TAG ,
100- format!( "webrtc-{}" , webrtc_triple( ) )
101- )
102- }
103-
10496/// Used location of libwebrtc depending on whether it's a custom build or not
10597pub fn webrtc_dir ( ) -> path:: PathBuf {
10698 if let Some ( path) = custom_dir ( ) {
@@ -177,31 +169,97 @@ pub fn configure_jni_symbols() -> Result<(), Box<dyn Error>> {
177169}
178170
179171pub fn download_webrtc ( ) -> Result < ( ) , Box < dyn Error > > {
180- let dir = scratch:: path ( SCRATH_PATH ) ;
181- let flock = File :: create ( dir. join ( ".lock" ) ) ?;
182- flock. lock_exclusive ( ) ?;
172+ fn inner ( ) -> Result < ( ) , Box < dyn Error > > {
173+ let dir = scratch:: path ( SCRATH_PATH ) ;
174+ let flock = File :: create ( dir. join ( ".lock" ) ) ?;
175+ flock. lock_exclusive ( ) ?;
176+
177+ let webrtc_dir = webrtc_dir ( ) ;
178+ if webrtc_dir. exists ( ) {
179+ return Ok ( ( ) ) ;
180+ }
183181
184- let webrtc_dir = webrtc_dir ( ) ;
185- if webrtc_dir. exists ( ) {
186- return Ok ( ( ) ) ;
187- }
182+ #[ derive( Debug , serde:: Deserialize ) ]
183+ struct Asset {
184+ name : String ,
185+ browser_download_url : String ,
186+ digest : Option < String > ,
187+ }
188188
189- let mut resp = reqwest :: blocking :: get ( download_url ( ) ) ? ;
190- if resp . status ( ) != StatusCode :: OK {
191- return Err ( format ! ( "failed to download webrtc: {}" , resp . status ( ) ) . into ( ) ) ;
192- }
189+ # [ derive ( Debug , serde :: Deserialize ) ]
190+ struct Release {
191+ assets : Vec < Asset > ,
192+ }
193193
194- let tmp_path = env:: var ( "OUT_DIR" ) . unwrap ( ) + "/webrtc.zip" ;
195- let tmp_path = path:: Path :: new ( & tmp_path) ;
196- let mut file = fs:: File :: options ( ) . write ( true ) . read ( true ) . create ( true ) . open ( tmp_path) ?;
197- resp. copy_to ( & mut file) ?;
194+ let tmp_path = env:: var ( "OUT_DIR" ) . unwrap ( ) + "/webrtc.zip" ;
195+ let tmp_path = path:: Path :: new ( & tmp_path) ;
196+ let mut error = None ;
198197
199- let mut archive = zip:: ZipArchive :: new ( file) ?;
200- archive. extract ( webrtc_dir. parent ( ) . unwrap ( ) ) ?;
201- drop ( archive) ;
198+ let mut attempt = 0 ;
199+ let file = loop {
200+ attempt += 1 ;
201+ if attempt > 5 {
202+ return Err ( error. unwrap_or_else ( || "failed to download webrtc" . to_owned ( ) . into ( ) ) ) ;
203+ }
202204
203- fs:: remove_file ( tmp_path) ?;
204- Ok ( ( ) )
205+ let mut file = fs:: File :: options ( )
206+ . write ( true )
207+ . read ( true )
208+ . create ( true )
209+ . truncate ( true )
210+ . open ( tmp_path) ?;
211+
212+ let client = reqwest:: blocking:: Client :: builder ( )
213+ . user_agent ( "Zed livekit-rust-sdks build script" )
214+ . build ( ) ?;
215+ let release_url = format ! (
216+ "https://api.github.com/repos/livekit/rust-sdks/releases/tags/{}" ,
217+ WEBRTC_TAG
218+ ) ;
219+ let release = client. get ( release_url) . send ( ) ?. json :: < Release > ( ) ?;
220+ let name = format ! ( "webrtc-{}.zip" , webrtc_triple( ) ) ;
221+ let asset = release. assets . iter ( ) . find ( |asset| asset. name == name) . unwrap ( ) ;
222+
223+ let mut resp = reqwest:: blocking:: get ( & asset. browser_download_url ) ?;
224+ if resp. status ( ) != StatusCode :: OK {
225+ let msg = format ! ( "failed to download webrtc: {}" , resp. status( ) ) ;
226+ println ! ( "cargo:warning={msg}" ) ;
227+ error = Some ( msg. into ( ) ) ;
228+ continue ;
229+ }
230+
231+ resp. copy_to ( & mut file) ?;
232+
233+ if let Some ( digest) =
234+ asset. digest . as_ref ( ) . and_then ( |digest| digest. strip_prefix ( "sha256:" ) )
235+ {
236+ let content = std:: fs:: read ( tmp_path) ?;
237+ let found_digest = Sha256 :: digest ( & content) ;
238+ let found_digest = base16:: encode_lower ( & found_digest) ;
239+ if found_digest != digest {
240+ let msg = "corrupted webrtc download" . to_owned ( ) ;
241+ println ! ( "cargo:warning={msg}" ) ;
242+ error = Some ( msg. into ( ) ) ;
243+ continue ;
244+ }
245+ }
246+
247+ break file;
248+ } ;
249+
250+ let mut archive = zip:: ZipArchive :: new ( file) ?;
251+ archive. extract ( webrtc_dir. parent ( ) . unwrap ( ) ) ?;
252+ drop ( archive) ;
253+
254+ fs:: remove_file ( tmp_path) ?;
255+ Ok ( ( ) )
256+ }
257+
258+ let result = inner ( ) ;
259+ if result. is_err ( ) {
260+ std:: fs:: remove_dir_all ( webrtc_dir ( ) ) . ok ( ) ;
261+ }
262+ result
205263}
206264
207265pub fn android_ndk_toolchain ( ) -> Result < path:: PathBuf , & ' static str > {
0 commit comments