diff --git a/src-tauri/src/games/downloads/download_agent.rs b/src-tauri/src/games/downloads/download_agent.rs index c003863..942cf4a 100644 --- a/src-tauri/src/games/downloads/download_agent.rs +++ b/src-tauri/src/games/downloads/download_agent.rs @@ -246,11 +246,17 @@ impl GameDownloadAgent { let completed_indexes = Arc::new(boxcar::Vec::new()); let completed_indexes_loop_arc = completed_indexes.clone(); + let base_url = DB.fetch_base_url(); + + + let contexts = self.contexts.lock().unwrap(); pool.scope(|scope| { - for (index, context) in self.contexts.lock().unwrap().iter().enumerate() { + let client = &reqwest::blocking::Client::new(); + for (index, context) in contexts.iter().enumerate() { + let client = client.clone(); let completed_indexes = completed_indexes_loop_arc.clone(); - let progress = self.progress.get(index); // Clone arcs + let progress = self.progress.get(index); let progress_handle = ProgressHandle::new(progress, self.progress.clone()); // If we've done this one already, skip it if self.completed_contexts.lock().unwrap().contains(&index) { @@ -258,13 +264,13 @@ impl GameDownloadAgent { continue; } - let context = context.clone(); - let control_flag = self.control_flag.clone(); // Clone arcs - let sender = self.sender.clone(); + let request = generate_request(&base_url, client, &context); + + scope.spawn(move |_| { - match download_game_chunk(context.clone(), control_flag, progress_handle) { + match download_game_chunk(context, &self.control_flag, progress_handle, request) { Ok(res) => { if res { completed_indexes.push(index); @@ -275,6 +281,7 @@ impl GameDownloadAgent { sender.send(DownloadManagerSignal::Error(e)).unwrap(); } } + info!("Completed context id {}", index); }); } }); @@ -310,6 +317,26 @@ impl GameDownloadAgent { } } +fn generate_request(base_url: &url::Url, client: reqwest::blocking::Client, context: &DropDownloadContext) -> reqwest::blocking::RequestBuilder { + let chunk_url = base_url + .join(&format!( + "/api/v1/client/chunk?id={}&version={}&name={}&chunk={}", + // Encode the parts we don't trust + context.game_id, + encode(&context.version), + encode(&context.file_name), + context.index + )) + .unwrap(); + + let header = generate_authorization_header(); + + let request = client + .get(chunk_url) + .header("Authorization", header); + request +} + impl Downloadable for GameDownloadAgent { fn download(&self, app_handle: &AppHandle) -> Result { *self.status.lock().unwrap() = DownloadStatus::Downloading; diff --git a/src-tauri/src/games/downloads/download_logic.rs b/src-tauri/src/games/downloads/download_logic.rs index 2c942c2..a14756d 100644 --- a/src-tauri/src/games/downloads/download_logic.rs +++ b/src-tauri/src/games/downloads/download_logic.rs @@ -6,15 +6,15 @@ use crate::download_manager::progress_object::ProgressHandle; use crate::games::downloads::manifest::DropDownloadContext; use crate::remote::RemoteAccessError; use crate::DB; -use http::StatusCode; use log::{info, warn}; use md5::{Context, Digest}; -use reqwest::blocking::Response; +use reqwest::blocking::{Client, Request, RequestBuilder, Response}; use std::fs::{set_permissions, Permissions}; use std::io::Read; #[cfg(unix)] use std::os::unix::fs::PermissionsExt; +use std::sync::Arc; use std::{ fs::{File, OpenOptions}, io::{self, BufWriter, Seek, SeekFrom, Write}, @@ -65,18 +65,18 @@ impl Seek for DropWriter { } } -pub struct DropDownloadPipeline { +pub struct DropDownloadPipeline<'a, R: Read, W: Write> { pub source: R, pub destination: DropWriter, - pub control_flag: DownloadThreadControl, + pub control_flag: &'a DownloadThreadControl, pub progress: ProgressHandle, pub size: usize, } -impl DropDownloadPipeline { +impl<'a> DropDownloadPipeline<'a, Response, File> { fn new( source: Response, destination: DropWriter, - control_flag: DownloadThreadControl, + control_flag: &'a DownloadThreadControl, progress: ProgressHandle, size: usize, ) -> Self { @@ -121,9 +121,10 @@ impl DropDownloadPipeline { } pub fn download_game_chunk( - ctx: DropDownloadContext, - control_flag: DownloadThreadControl, + ctx: &DropDownloadContext, + control_flag: &DownloadThreadControl, progress: ProgressHandle, + request: RequestBuilder ) -> Result { // If we're paused if control_flag.get() == DownloadThreadControlFlag::Stop { @@ -131,25 +132,7 @@ pub fn download_game_chunk( return Ok(false); } - let base_url = DB.fetch_base_url(); - - let client = reqwest::blocking::Client::new(); - let chunk_url = base_url - .join(&format!( - "/api/v1/client/chunk?id={}&version={}&name={}&chunk={}", - // Encode the parts we don't trust - ctx.game_id, - encode(&ctx.version), - encode(&ctx.file_name), - ctx.index - )) - .unwrap(); - - let header = generate_authorization_header(); - - let response = client - .get(chunk_url) - .header("Authorization", header) + let response = request .send() .map_err(|e| ApplicationDownloadError::Communication(e.into()))?; @@ -194,7 +177,7 @@ pub fn download_game_chunk( #[cfg(unix)] { let permissions = Permissions::from_mode(ctx.permissions); - set_permissions(ctx.path, permissions).unwrap(); + set_permissions(ctx.path.clone(), permissions).unwrap(); } /*