From 510013d4fac192cd02d89302909955164afb741a Mon Sep 17 00:00:00 2001 From: DecDuck Date: Wed, 3 Dec 2025 11:54:20 +1100 Subject: [PATCH] feat: torrential setup --- src-tauri/download_manager/src/error.rs | 2 +- .../games/src/downloads/download_agent.rs | 7 ++-- .../games/src/downloads/download_logic.rs | 35 ++++++++++++------- src-tauri/games/src/downloads/manifest.rs | 1 + src-tauri/games/src/downloads/validate.rs | 3 +- src-tauri/games/src/library.rs | 4 +-- src-tauri/remote/src/requests.rs | 10 +++--- src-tauri/remote/src/utils.rs | 3 +- 8 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src-tauri/download_manager/src/error.rs b/src-tauri/download_manager/src/error.rs index 21201e8..93ece25 100644 --- a/src-tauri/download_manager/src/error.rs +++ b/src-tauri/download_manager/src/error.rs @@ -57,7 +57,7 @@ impl Display for ApplicationDownloadError { format_size(*required, BINARY), format_size(*available, BINARY), ), - ApplicationDownloadError::Communication(error) => write!(f, "{error}"), + ApplicationDownloadError::Communication(error) => write!(f, "{error:?}"), ApplicationDownloadError::Lock => write!( f, "failed to acquire lock. Something has gone very wrong internally. Please restart the application" diff --git a/src-tauri/games/src/downloads/download_agent.rs b/src-tauri/games/src/downloads/download_agent.rs index 1d54ca0..26b2acd 100644 --- a/src-tauri/games/src/downloads/download_agent.rs +++ b/src-tauri/games/src/downloads/download_agent.rs @@ -36,13 +36,13 @@ use crate::downloads::validate::validate_game_chunk; use crate::library::{on_game_complete, push_game_update, set_partially_installed}; use crate::state::GameStatusManager; -use super::download_logic::download_game_bucket; +use super::download_logic::download_game_chunk; use super::drop_data::DropData; static RETRY_COUNT: usize = 3; const TARGET_BUCKET_SIZE: usize = 63 * 1000 * 1000; -const MAX_FILES_PER_BUCKET: usize = (1024 / 4) - 1; +const MAX_FILES_PER_BUCKET: usize = 1; // (1024 / 4) - 1; pub struct GameDownloadAgent { pub id: String, @@ -283,6 +283,7 @@ impl GameDownloadAgent { for (index, length) in chunk.lengths.iter().enumerate() { let drop = DownloadDrop { filename: raw_path.to_string(), + id: chunk.ids[index].clone(), start: file_running_offset, length: *length, checksum: chunk.checksums[index].clone(), @@ -465,7 +466,7 @@ impl GameDownloadAgent { // 3 attempts for i in 0..RETRY_COUNT { let loop_progress_handle = progress_handle.clone(); - match download_game_bucket( + match download_game_chunk( &bucket, download_context, &self.control_flag, diff --git a/src-tauri/games/src/downloads/download_logic.rs b/src-tauri/games/src/downloads/download_logic.rs index d5d650b..040097a 100644 --- a/src-tauri/games/src/downloads/download_logic.rs +++ b/src-tauri/games/src/downloads/download_logic.rs @@ -3,7 +3,7 @@ use std::io::Read; #[cfg(unix)] use std::os::unix::fs::PermissionsExt; use std::sync::Arc; -use std::time::Instant; +use std::time::{Duration, Instant}; use std::{ fs::{File, OpenOptions}, io::{self, BufWriter, Seek, SeekFrom, Write}, @@ -105,7 +105,8 @@ impl<'a> DropDownloadPipeline<'a, Response, File> { }) } - fn copy(&mut self) -> Result { + fn copy(&mut self) -> Result<(bool, usize), io::Error> { + let mut total_copied = 0; let mut copy_buffer = [0u8; MAX_PACKET_LENGTH]; for (index, drop) in self.drops.iter().enumerate() { let destination = self @@ -127,13 +128,14 @@ impl<'a> DropDownloadPipeline<'a, Response, File> { })?; remaining -= size; last_bump += size; + // total_copied += size; destination.write_all(©_buffer[0..size])?; if last_bump > BUMP_SIZE { last_bump -= BUMP_SIZE; if self.control_flag.get() == DownloadThreadControlFlag::Stop { - return Ok(false); + return Ok((false, 0)); } } @@ -143,11 +145,11 @@ impl<'a> DropDownloadPipeline<'a, Response, File> { } if self.control_flag.get() == DownloadThreadControlFlag::Stop { - return Ok(false); + return Ok((false, 0)); } } - Ok(true) + Ok((true, total_copied)) } #[allow(dead_code)] @@ -167,7 +169,7 @@ impl<'a> DropDownloadPipeline<'a, Response, File> { } } -pub fn download_game_bucket( +pub fn download_game_chunk( bucket: &DownloadBucket, ctx: &DownloadContext, control_flag: &DownloadThreadControl, @@ -183,14 +185,20 @@ pub fn download_game_bucket( let header = generate_authorization_header(); - let url = generate_url(&["/api/v2/client/chunk"], &[]) - .map_err(ApplicationDownloadError::Communication)?; + if bucket.drops.len() > 1 { + panic!("lol"); + } - let body = ChunkBody::create(ctx, &bucket.drops); + let drop = bucket.drops.first().unwrap(); + + let bits = ["/api/v1/depot/", &bucket.game_id, &bucket.version, &drop.id]; + let url = generate_url(&bits, &[]).unwrap(); + + // let body = ChunkBody::create(ctx, &bucket.drops); let response = DROP_CLIENT_SYNC - .post(url) - .json(&body) + .get(url) + //.json(&body) .header("Authorization", header) .send() .map_err(|e| ApplicationDownloadError::Communication(e.into()))?; @@ -210,7 +218,7 @@ pub fn download_game_bucket( RemoteAccessError::UnparseableResponse(raw_res), )); } - + /* let lengths = response .headers() .get("Content-Lengths") @@ -255,6 +263,7 @@ pub fn download_game_bucket( )); } } + */ let timestep = start.elapsed().as_millis(); @@ -264,7 +273,7 @@ pub fn download_game_bucket( DropDownloadPipeline::new(response, bucket.drops.clone(), control_flag, progress) .map_err(|e| ApplicationDownloadError::IoError(Arc::new(e)))?; - let completed = pipeline + let (completed, _) = pipeline .copy() .map_err(|e| ApplicationDownloadError::IoError(Arc::new(e)))?; if !completed { diff --git a/src-tauri/games/src/downloads/manifest.rs b/src-tauri/games/src/downloads/manifest.rs index b1b4baa..659da80 100644 --- a/src-tauri/games/src/downloads/manifest.rs +++ b/src-tauri/games/src/downloads/manifest.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; // Drops go in buckets pub struct DownloadDrop { pub index: usize, + pub id: String, pub filename: String, pub path: PathBuf, pub start: usize, diff --git a/src-tauri/games/src/downloads/validate.rs b/src-tauri/games/src/downloads/validate.rs index 0c709f7..c5c5f15 100644 --- a/src-tauri/games/src/downloads/validate.rs +++ b/src-tauri/games/src/downloads/validate.rs @@ -10,7 +10,7 @@ use download_manager::{ progress_object::ProgressHandle, }, }; -use log::debug; +use log::{debug, info}; use md5::Context; use crate::downloads::manifest::DropValidateContext; @@ -52,6 +52,7 @@ pub fn validate_game_chunk( let res = hex::encode(hasher.finalize().0); if res != ctx.checksum { + info!("{} doesn't match", ctx.path.display()); return Ok(false); } diff --git a/src-tauri/games/src/library.rs b/src-tauri/games/src/library.rs index c58d3c0..fb40bbf 100644 --- a/src-tauri/games/src/library.rs +++ b/src-tauri/games/src/library.rs @@ -9,7 +9,7 @@ use remote::{ utils::DROP_CLIENT_SYNC, }; use serde::{Deserialize, Serialize}; -use std::fs::remove_dir_all; +use std::fs::{exists, remove_dir_all}; use std::thread::spawn; use tauri::AppHandle; use utils::app_emit; @@ -154,7 +154,7 @@ pub fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) let app_handle = app_handle.clone(); spawn(move || { - if let Err(e) = remove_dir_all(install_dir) { + if exists(install_dir.clone()).unwrap_or(false) && let Err(e) = remove_dir_all(install_dir) { error!("{e}"); } else { let mut db_handle = borrow_db_mut_checked(); diff --git a/src-tauri/remote/src/requests.rs b/src-tauri/remote/src/requests.rs index df74269..7f9d035 100644 --- a/src-tauri/remote/src/requests.rs +++ b/src-tauri/remote/src/requests.rs @@ -1,4 +1,6 @@ + use database::{DB, interface::DatabaseImpls}; +use log::info; use url::Url; use crate::{ @@ -9,10 +11,10 @@ pub fn generate_url>( path_components: &[T], query: &[(T, T)], ) -> Result { - let mut base_url = DB.fetch_base_url(); - for endpoint in path_components { - base_url = base_url.join(endpoint.as_ref())?; - } + let components = path_components.iter().map(|v| v.as_ref()).map(|v| v.trim_matches('/')).collect::>(); + let mut base_url = DB + .fetch_base_url() + .join(&components.join("/"))?; { let mut queries = base_url.query_pairs_mut(); for (param, val) in query { diff --git a/src-tauri/remote/src/utils.rs b/src-tauri/remote/src/utils.rs index 6ca4e0b..0646ae2 100644 --- a/src-tauri/remote/src/utils.rs +++ b/src-tauri/remote/src/utils.rs @@ -1,7 +1,7 @@ use std::{ fs::{self, File}, io::Read, - sync::LazyLock, + sync::LazyLock, time::Duration, }; use database::db::DATA_ROOT_DIR; @@ -91,6 +91,7 @@ pub fn get_client_sync() -> reqwest::blocking::Client { } client .use_rustls_tls() + .connect_timeout(Duration::from_millis(1500)) .build() .expect("Failed to build synchronous client") }