From 9a85f68d3a4a80255c0a6f97fb7aaf252fda7f04 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sat, 26 Jul 2025 19:56:38 +1000 Subject: [PATCH] chore: commit changes, still bad --- src-tauri/Cargo.lock | 1 - src-tauri/Cargo.toml | 2 +- src-tauri/src/client/cleanup.rs | 7 +-- src-tauri/src/client/commands.rs | 6 +- src-tauri/src/download_manager/commands.rs | 12 ++-- .../download_manager_builder.rs | 62 +++++++++++++------ .../download_manager_frontend.rs | 4 +- src-tauri/src/games/commands.rs | 15 ++--- src-tauri/src/games/downloads/commands.rs | 17 +++-- .../src/games/downloads/download_agent.rs | 46 +++++++------- .../src/games/downloads/download_logic.rs | 10 ++- src-tauri/src/games/library.rs | 13 ++-- src-tauri/src/lib.rs | 31 ++++++---- src-tauri/src/main.rs | 11 +++- src-tauri/src/process/commands.rs | 10 ++- src-tauri/src/process/process_manager.rs | 11 ++-- src-tauri/src/remote/auth.rs | 35 ++++++----- src-tauri/src/remote/commands.rs | 9 ++- src-tauri/src/remote/server_proto.rs | 5 +- src-tauri/src/remote/utils.rs | 14 ++--- 20 files changed, 173 insertions(+), 148 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b02f6fe..5f4c87a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4337,7 +4337,6 @@ checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" dependencies = [ "base64 0.22.1", "bytes", - "futures-channel", "futures-core", "futures-util", "h2 0.4.11", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 01f4852..ef23650 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -105,7 +105,7 @@ features = ["other_errors"] # You can also use "yaml_enc" [dependencies.reqwest] version = "0.12" default-features = false -features = ["json", "http2", "blocking", "rustls-tls-webpki-roots", "stream"] +features = ["json", "http2", "rustls-tls-webpki-roots", "stream"] [dependencies.serde] version = "1" diff --git a/src-tauri/src/client/cleanup.rs b/src-tauri/src/client/cleanup.rs index c3322e4..b01ccd8 100644 --- a/src-tauri/src/client/cleanup.rs +++ b/src-tauri/src/client/cleanup.rs @@ -1,11 +1,10 @@ use log::{debug, error}; use tauri::AppHandle; -use tokio::sync::Mutex; -use crate::AppState; +use crate::DropFunctionState; #[tauri::command] -pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, Mutex>>) -> Result<(), ()> { +pub async fn quit<>(app: tauri::AppHandle, state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> { cleanup_and_exit(&app, &state).await; Ok(()) @@ -13,7 +12,7 @@ pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, Mutex>>, + state: &tauri::State<'_, DropFunctionState<'_>>, ) { debug!("cleaning up and exiting application"); let download_manager = state.lock().await.download_manager.clone(); diff --git a/src-tauri/src/client/commands.rs b/src-tauri/src/client/commands.rs index 635233d..a782cfb 100644 --- a/src-tauri/src/client/commands.rs +++ b/src-tauri/src/client/commands.rs @@ -1,10 +1,8 @@ -use tokio::sync::Mutex; - -use crate::AppState; +use crate::DropFunctionState; #[tauri::command] pub async fn fetch_state( - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result { let guard = state.lock().await; let cloned_state = serde_json::to_string(&guard.clone()).map_err(|e| e.to_string())?; diff --git a/src-tauri/src/download_manager/commands.rs b/src-tauri/src/download_manager/commands.rs index 8bcb350..26f3215 100644 --- a/src-tauri/src/download_manager/commands.rs +++ b/src-tauri/src/download_manager/commands.rs @@ -1,22 +1,20 @@ -use tokio::sync::Mutex; - -use crate::{database::models::data::DownloadableMetadata, AppState}; +use crate::{database::models::data::DownloadableMetadata, DropFunctionState}; #[tauri::command] -pub async fn pause_downloads(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { +pub async fn pause_downloads(state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> { state.lock().await.download_manager.pause_downloads(); Ok(()) } #[tauri::command] -pub async fn resume_downloads(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { +pub async fn resume_downloads(state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> { state.lock().await.download_manager.resume_downloads(); Ok(()) } #[tauri::command] pub async fn move_download_in_queue( - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, old_index: usize, new_index: usize, ) -> Result<(), ()> { @@ -29,7 +27,7 @@ pub async fn move_download_in_queue( } #[tauri::command] -pub async fn cancel_game(state: tauri::State<'_, Mutex>>, meta: DownloadableMetadata) -> Result<(), ()> { +pub async fn cancel_game(state: tauri::State<'_, DropFunctionState<'_>>, meta: DownloadableMetadata) -> Result<(), ()> { state.lock().await.download_manager.cancel(meta); Ok(()) } diff --git a/src-tauri/src/download_manager/download_manager_builder.rs b/src-tauri/src/download_manager/download_manager_builder.rs index 2f915e5..d2c7f40 100644 --- a/src-tauri/src/download_manager/download_manager_builder.rs +++ b/src-tauri/src/download_manager/download_manager_builder.rs @@ -9,7 +9,7 @@ use std::{ use ::futures::future::join_all; use log::{debug, error, info, warn}; use tauri::{AppHandle, Emitter}; -use tokio::{spawn, sync::Mutex, task::JoinHandle}; +use tokio::{runtime::Runtime, sync::Mutex}; use crate::{ database::models::data::DownloadableMetadata, @@ -75,9 +75,10 @@ pub struct DownloadManagerBuilder { progress: CurrentProgressObject, status: Arc>, app_handle: AppHandle, + runtime: Runtime, current_download_agent: Option, // Should be the only download agent in the map with the "Go" flag - current_download_thread: Mutex>>, + current_download_thread: Mutex>>, active_control_flag: Option, } impl DownloadManagerBuilder { @@ -95,13 +96,24 @@ impl DownloadManagerBuilder { sender: command_sender.clone(), progress: active_progress.clone(), app_handle, + runtime: tokio::runtime::Builder::new_multi_thread() + .worker_threads(1) + .enable_all() + .build() + .unwrap(), current_download_agent: None, current_download_thread: Mutex::new(None), active_control_flag: None, }; - let terminator = spawn(async{ manager.manage_queue().await }); + let terminator = tauri::async_runtime::spawn(async { + if let Err(_err) = manager.manage_queue().await { + panic!("download manager exited with error"); + } else { + Ok(()) + } + }); DownloadManager::new(terminator, queue, active_progress, command_sender) } @@ -110,7 +122,10 @@ impl DownloadManagerBuilder { *self.status.lock().await = status; } - async fn remove_and_cleanup_front_download(&mut self, meta: &DownloadableMetadata) -> DownloadAgent { + async fn remove_and_cleanup_front_download( + &mut self, + meta: &DownloadableMetadata, + ) -> DownloadAgent { self.download_queue.pop_front(); let download_agent = self.download_agent_registry.remove(meta).unwrap(); self.cleanup_current_download().await; @@ -126,7 +141,6 @@ impl DownloadManagerBuilder { let mut download_thread_lock = self.current_download_thread.lock().await; *download_thread_lock = None; - drop(download_thread_lock); } async fn stop_and_wait_current_download(&self) { @@ -237,12 +251,20 @@ impl DownloadManagerBuilder { self.active_control_flag = Some(download_agent.control_flag().await); self.current_download_agent = Some(download_agent.clone()); + info!("fetched control flag"); + let sender = self.sender.clone(); + info!("cloned sender"); + let mut download_thread_lock = self.current_download_thread.lock().await; + info!("acquired download thread lock"); let app_handle = self.app_handle.clone(); - *download_thread_lock = Some(spawn(async move { + info!("starting download agent thread"); + + *download_thread_lock = Some(self.runtime.spawn(async move { + info!("started download agent thread"); match download_agent.download(&app_handle).await { // Ok(true) is for completed and exited properly Ok(true) => { @@ -285,6 +307,8 @@ impl DownloadManagerBuilder { self.set_status(DownloadManagerStatus::Downloading).await; let active_control_flag = self.active_control_flag.clone().unwrap(); active_control_flag.set(DownloadThreadControlFlag::Go); + + // download_thread_lock.take().unwrap().await; } async fn manage_stop_signal(&mut self) { debug!("got signal Stop"); @@ -311,7 +335,8 @@ impl DownloadManagerBuilder { current_agent.on_error(&self.app_handle, &error).await; self.stop_and_wait_current_download().await; - self.remove_and_cleanup_front_download(¤t_agent.metadata()).await; + self.remove_and_cleanup_front_download(¤t_agent.metadata()) + .await; } self.set_status(DownloadManagerStatus::Error).await; } @@ -365,18 +390,17 @@ impl DownloadManagerBuilder { } async fn push_ui_queue_update(&self) { let queue = &self.download_queue.read(); - let queue_objs = join_all(queue - .iter() - .map(async |key| { - let val = self.download_agent_registry.get(key).unwrap(); - QueueUpdateEventQueueData { - meta: DownloadableMetadata::clone(key), - status: val.status().await, - progress: val.progress().await.get_progress(), - current: val.progress().await.sum(), - max: val.progress().await.get_max(), - } - })).await; + let queue_objs = join_all(queue.iter().map(async |key| { + let val = self.download_agent_registry.get(key).unwrap(); + QueueUpdateEventQueueData { + meta: DownloadableMetadata::clone(key), + status: val.status().await, + progress: val.progress().await.get_progress(), + current: val.progress().await.sum(), + max: val.progress().await.get_max(), + } + })) + .await; let event_data = QueueUpdateEvent { queue: queue_objs }; self.app_handle.emit("update_queue", event_data).unwrap(); diff --git a/src-tauri/src/download_manager/download_manager_frontend.rs b/src-tauri/src/download_manager/download_manager_frontend.rs index 3783d99..77176bb 100644 --- a/src-tauri/src/download_manager/download_manager_frontend.rs +++ b/src-tauri/src/download_manager/download_manager_frontend.rs @@ -9,7 +9,7 @@ use std::{ use log::{debug, info}; use serde::Serialize; -use tokio::task::{JoinError, JoinHandle}; +use tauri::async_runtime::JoinHandle; use crate::{ database::models::data::DownloadableMetadata, @@ -170,7 +170,7 @@ impl DownloadManager { pub fn resume_downloads(&self) { self.command_sender.send(DownloadManagerSignal::Go).unwrap(); } - pub async fn ensure_terminated(&self) -> Result, JoinError> { + pub async fn ensure_terminated(&self) -> Result, tauri::Error> { self.command_sender .send(DownloadManagerSignal::Finish) .unwrap(); diff --git a/src-tauri/src/games/commands.rs b/src-tauri/src/games/commands.rs index d19c1e6..211a7cf 100644 --- a/src-tauri/src/games/commands.rs +++ b/src-tauri/src/games/commands.rs @@ -1,16 +1,11 @@ use serde::Deserialize; use tauri::AppHandle; -use tokio::sync::Mutex; use crate::{ - AppState, - database::{db::borrow_db_mut_checked, models::data::GameVersion}, - error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, - games::library::{ + database::{db::borrow_db_mut_checked, models::data::GameVersion}, error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, games::library::{ fetch_game_logic_offline, fetch_library_logic_offline, get_current_meta, uninstall_game_logic, - }, - offline, + }, offline, DropFunctionState }; use super::{ @@ -23,7 +18,7 @@ use super::{ #[tauri::command] pub async fn fetch_library( - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result, RemoteAccessError> { offline!( state, @@ -37,7 +32,7 @@ pub async fn fetch_library( #[tauri::command] pub async fn fetch_game( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result { offline!( state, @@ -68,7 +63,7 @@ pub async fn uninstall_game(game_id: String, app_handle: AppHandle) -> Result<() #[tauri::command] pub async fn fetch_game_verion_options( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result, RemoteAccessError> { fetch_game_verion_options_logic(game_id, state).await } diff --git a/src-tauri/src/games/downloads/commands.rs b/src-tauri/src/games/downloads/commands.rs index 2115ab0..70ba8a0 100644 --- a/src-tauri/src/games/downloads/commands.rs +++ b/src-tauri/src/games/downloads/commands.rs @@ -1,6 +1,6 @@ use std::{ path::PathBuf, - sync::{Arc, Mutex}, + sync::Arc, }; use crate::{ @@ -8,8 +8,7 @@ use crate::{ download_manager::{ download_manager_frontend::DownloadManagerSignal, downloadable::Downloadable, }, - error::download_manager_error::DownloadManagerError, - AppState, + error::download_manager_error::DownloadManagerError, DropFunctionState, }; use super::download_agent::GameDownloadAgent; @@ -19,9 +18,9 @@ pub async fn download_game( game_id: String, game_version: String, install_dir: usize, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), DownloadManagerError> { - let sender = state.lock().unwrap().download_manager.get_sender(); + let sender = state.lock().await.download_manager.get_sender(); let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new_from_index( game_id, game_version, @@ -30,7 +29,7 @@ pub async fn download_game( ).await) as Box); Ok(state .lock() - .unwrap() + .await .download_manager .queue_download(game_download_agent)?) } @@ -38,7 +37,7 @@ pub async fn download_game( #[tauri::command] pub async fn resume_download( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), DownloadManagerError> { let s = borrow_db_checked().await .applications @@ -56,7 +55,7 @@ pub async fn resume_download( install_dir, } => (version_name, install_dir), }; - let sender = state.lock().unwrap().download_manager.get_sender(); + let sender = state.lock().await.download_manager.get_sender(); let parent_dir: PathBuf = install_dir.into(); let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new( game_id, @@ -66,7 +65,7 @@ pub async fn resume_download( )) as Box); Ok(state .lock() - .unwrap() + .await .download_manager .queue_download(game_download_agent)?) } diff --git a/src-tauri/src/games/downloads/download_agent.rs b/src-tauri/src/games/downloads/download_agent.rs index 4d5fa80..5399aa7 100644 --- a/src-tauri/src/games/downloads/download_agent.rs +++ b/src-tauri/src/games/downloads/download_agent.rs @@ -1,5 +1,6 @@ +use crate::DB; use crate::auth::generate_authorization_header; -use crate::database::db::{borrow_db_checked, borrow_db_mut_checked}; +use crate::database::db::{DatabaseImpls, borrow_db_checked, borrow_db_mut_checked}; use crate::database::models::data::{ ApplicationTransientStatus, DownloadType, DownloadableMetadata, }; @@ -105,6 +106,7 @@ impl GameDownloadAgent { // Blocking pub async fn download(&self, app_handle: &AppHandle) -> Result { + debug!("starting download"); self.setup_download().await?; self.set_progress_object_params(); let timer = Instant::now(); @@ -268,11 +270,19 @@ impl GameDownloadAgent { self.id, max_download_threads ); - let client = &reqwest::Client::new(); + let base_url = DB + .fetch_base_url() + .await + .join("/api/v1/client/chunk") + .unwrap(); + let client = reqwest::Client::new(); + let client_ref = unsafe { extend_lifetime(&client) }; let rt = tokio::runtime::Builder::new_multi_thread() .worker_threads(max_download_threads) .thread_name("drop-download-thread") + .enable_io() + .enable_time() .build() .map_err(|e| { warn!("failed to create download scheduler: {e}"); @@ -288,8 +298,6 @@ impl GameDownloadAgent { let context_map = self.context_map.lock().unwrap(); for (index, context) in contexts.iter().enumerate() { - let client = client.clone(); - let progress = self.progress.get(index); let progress_handle = ProgressHandle::new(progress, self.progress.clone()); @@ -308,30 +316,22 @@ impl GameDownloadAgent { */ let context = unsafe { extend_lifetime(context) }; let self_static = unsafe { extend_lifetime(self) }; + let mut base_url = base_url.clone(); rt.spawn(async move { - let request = match make_request( - &client, - &["/api/v1/client/chunk"], - &[ + { + let mut query = base_url.query_pairs_mut(); + let query_params = [ ("id", &context.game_id), ("version", &context.version), ("name", &context.file_name), ("chunk", &context.index.to_string()), - ], - async |r| r, - ) - .await - { - Ok(request) => request, - Err(e) => { - sender - .send(DownloadManagerSignal::Error( - ApplicationDownloadError::Communication(e), - )) - .unwrap(); - return; + ]; + for (param, val) in query_params { + query.append_pair(param.as_ref(), val.as_ref()); } - }; + } + + let request = client_ref.get(base_url); match download_game_chunk( context, @@ -356,7 +356,6 @@ impl GameDownloadAgent { let mut newly_completed = Vec::new(); while let Some(completed_checksum) = rx.recv().await { - println!("completed checksum {}", completed_checksum); newly_completed.push(completed_checksum); } @@ -409,6 +408,7 @@ impl Downloadable for GameDownloadAgent { } async fn download(&self, app_handle: &AppHandle) -> Result { + debug!("starting download from downloadable trait"); *self.status.lock().unwrap() = DownloadStatus::Downloading; self.download(app_handle).await } diff --git a/src-tauri/src/games/downloads/download_logic.rs b/src-tauri/src/games/downloads/download_logic.rs index c870ce4..7a6e4fe 100644 --- a/src-tauri/src/games/downloads/download_logic.rs +++ b/src-tauri/src/games/downloads/download_logic.rs @@ -6,9 +6,9 @@ use crate::error::application_download_error::ApplicationDownloadError; use crate::error::drop_server_error::DropServerError; use crate::error::remote_access_error::RemoteAccessError; use crate::games::downloads::manifest::DropDownloadContext; -use crate::remote::auth::generate_authorization_header; +use crate::remote::auth::{generate_authorization_header, generate_authorization_header_part}; use futures::TryStreamExt; -use log::{debug, warn}; +use log::{debug, info, warn}; use md5::{Context, Digest}; use reqwest::RequestBuilder; use tokio::fs::{File, OpenOptions}; @@ -97,6 +97,7 @@ where } let mut bytes_read = self.source.read(&mut copy_buf).await?; + info!("read {}", bytes_read); current_size += bytes_read; if current_size > self.size { @@ -139,8 +140,11 @@ pub async fn download_game_chunk( progress.set(0); return Ok(false); } + + let header_generator = generate_authorization_header_part().await; + let response = request - .header("Authorization", generate_authorization_header().await) + .header("Authorization", header_generator()) .send() .await .map_err(|e| ApplicationDownloadError::Communication(e.into()))?; diff --git a/src-tauri/src/games/library.rs b/src-tauri/src/games/library.rs index 2cbcf68..74d642c 100644 --- a/src-tauri/src/games/library.rs +++ b/src-tauri/src/games/library.rs @@ -5,9 +5,7 @@ use serde::{Deserialize, Serialize}; use tauri::AppHandle; use tauri::Emitter; use tokio::spawn; -use tokio::sync::Mutex; -use crate::AppState; use crate::database::db::{borrow_db_checked, borrow_db_mut_checked}; use crate::database::models::data::{ ApplicationTransientStatus, DownloadableMetadata, GameDownloadStatus, GameVersion, @@ -18,6 +16,7 @@ use crate::games::state::{GameStatusManager, GameStatusWithTransient}; use crate::remote::auth::generate_authorization_header; use crate::remote::cache::{cache_object, get_cached_object, get_cached_object_db}; use crate::remote::requests::make_request; +use crate::DropFunctionState; use bitcode::{Decode, Encode}; #[derive(Serialize, Deserialize, Debug)] @@ -73,7 +72,7 @@ pub struct StatsUpdateEvent { } pub async fn fetch_library_logic( - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result, RemoteAccessError> { let header = generate_authorization_header().await; @@ -125,7 +124,7 @@ pub async fn fetch_library_logic( Ok(games) } pub async fn fetch_library_logic_offline( - _state: tauri::State<'_, Mutex>>, + _state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result, RemoteAccessError> { let mut games: Vec = get_cached_object("library").await?; @@ -142,7 +141,7 @@ pub async fn fetch_library_logic_offline( } pub async fn fetch_game_logic( id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result { let mut state_handle = state.lock().await; @@ -222,7 +221,7 @@ pub async fn fetch_game_logic( pub async fn fetch_game_logic_offline( id: String, - _state: tauri::State<'_, Mutex>>, + _state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result { let handle = borrow_db_checked().await; let metadata_option = handle.applications.installed_game_version.get(&id); @@ -253,7 +252,7 @@ pub async fn fetch_game_logic_offline( pub async fn fetch_game_verion_options_logic( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result, RemoteAccessError> { let client = reqwest::Client::new(); diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a7223e5..894c52c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -72,7 +72,6 @@ use tauri::tray::TrayIconBuilder; use tauri::{AppHandle, Manager, RunEvent, WindowEvent}; use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_dialog::DialogExt; -use tokio::runtime::Handle; use tokio::sync::Mutex; #[derive(Clone, Copy, Serialize, Eq, PartialEq)] @@ -220,6 +219,7 @@ async fn setup(handle: AppHandle) -> AppState<'static> { } pub static DB: OnceCellDatabase = OnceCellDatabase::new(); +pub type DropFunctionState<'a> = Mutex>; pub fn custom_panic_handler(e: &PanicHookInfo) -> Option<()> { let crash_file = DATA_ROOT_DIR.join(format!( @@ -238,15 +238,12 @@ pub fn custom_panic_handler(e: &PanicHookInfo) -> Option<()> { } #[cfg_attr(mobile, tauri::mobile_entry_point)] -pub async fn run() { +pub fn run() { panic::set_hook(Box::new(|e| { let _ = custom_panic_handler(e); println!("{e}"); })); - DB.init(async { DatabaseInterface::set_up_database().await }) - .await; - let mut builder = tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_os::init()) @@ -318,9 +315,11 @@ pub async fn run() { )) .setup(|app| { let app = app.handle().clone(); - let runtime = Handle::current(); - runtime.spawn(async move { + tauri::async_runtime::spawn(async move { + DB.init(async { DatabaseInterface::set_up_database().await }) + .await; + let state = setup(app.clone()).await; info!("initialized drop client"); if !app.manage(Mutex::new(state)) { @@ -363,18 +362,24 @@ pub async fn run() { ) .unwrap(); - run_on_tray(|| { + let tray_app_handle = app.clone(); + run_on_tray(move || { TrayIconBuilder::new() - .icon(app.default_window_icon().unwrap().clone()) + .icon(tray_app_handle.default_window_icon().unwrap().clone()) .menu(&menu) .on_menu_event(|app, event| { + let tray_app_handle = app.clone(); tauri::async_runtime::block_on(async move { match event.id.as_ref() { "open" => { app.webview_windows().get("main").unwrap().show().unwrap(); } "quit" => { - cleanup_and_exit(app, &app.state()).await; + cleanup_and_exit( + &tray_app_handle, + &tray_app_handle.state(), + ) + .await; } _ => { @@ -383,7 +388,7 @@ pub async fn run() { } }) }) - .build(&app) + .build(&tray_app_handle) .expect("error while setting up tray menu"); }); @@ -422,7 +427,7 @@ pub async fn run() { }) .register_asynchronous_uri_scheme_protocol("object", move |ctx, request, responder| { tauri::async_runtime::block_on(async move { - let state: tauri::State<'_, Mutex> = ctx.app_handle().state(); + let state = ctx.app_handle().state::>(); offline!( state, fetch_object, @@ -435,7 +440,7 @@ pub async fn run() { }) .register_asynchronous_uri_scheme_protocol("server", move |ctx, request, responder| { tauri::async_runtime::block_on(async move { - let state: tauri::State<'_, Mutex> = ctx.app_handle().state(); + let state = ctx.app_handle().state::>(); offline!( state, handle_server_proto, diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 6f28672..8dd7b81 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,7 +1,12 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -#[tokio::main] -async fn main() { - drop_app_lib::run().await +fn main() { + let global_runtime = tokio::runtime::Builder::new_multi_thread() + .worker_threads(32) + .enable_all() + .build() + .unwrap(); + tauri::async_runtime::set(global_runtime.handle().clone()); + drop_app_lib::run() } diff --git a/src-tauri/src/process/commands.rs b/src-tauri/src/process/commands.rs index a9ef333..b62ef64 100644 --- a/src-tauri/src/process/commands.rs +++ b/src-tauri/src/process/commands.rs @@ -1,11 +1,9 @@ -use tokio::sync::Mutex; - -use crate::{AppState, error::process_error::ProcessError}; +use crate::{error::process_error::ProcessError, DropFunctionState}; #[tauri::command] pub async fn launch_game( id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), ProcessError> { let state_lock = state.lock().await; let mut process_manager_lock = state_lock.process_manager.lock().await; @@ -30,7 +28,7 @@ pub async fn launch_game( #[tauri::command] pub async fn kill_game( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), ProcessError> { let state_lock = state.lock().await; let mut process_manager_lock = state_lock.process_manager.lock().await; @@ -42,7 +40,7 @@ pub async fn kill_game( #[tauri::command] pub async fn open_process_logs( game_id: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), ProcessError> { let state_lock = state.lock().await; let mut process_manager_lock = state_lock.process_manager.lock().await; diff --git a/src-tauri/src/process/process_manager.rs b/src-tauri/src/process/process_manager.rs index 0e58493..d4271cd 100644 --- a/src-tauri/src/process/process_manager.rs +++ b/src-tauri/src/process/process_manager.rs @@ -16,19 +16,16 @@ use serde::{Deserialize, Serialize}; use shared_child::SharedChild; use tauri::{AppHandle, Emitter, Manager}; use tauri_plugin_opener::OpenerExt; -use tokio::{spawn, sync::Mutex}; +use tokio::spawn; use crate::{ - AppState, DB, database::{ - db::{DATA_ROOT_DIR, borrow_db_mut_checked}, + db::{borrow_db_mut_checked, DATA_ROOT_DIR}, models::data::{ ApplicationTransientStatus, DownloadType, DownloadableMetadata, GameDownloadStatus, GameVersion, }, - }, - error::process_error::ProcessError, - games::{library::push_game_update, state::GameStatusManager}, + }, error::process_error::ProcessError, games::{library::push_game_update, state::GameStatusManager}, DropFunctionState, DB }; pub struct RunningProcess { @@ -337,7 +334,7 @@ impl ProcessManager<'_> { spawn(async move { let result: Result = launch_process_handle.wait(); - let app_state = wait_thread_apphandle.state::>(); + let app_state = wait_thread_apphandle.state::>>(); let app_state_handle = app_state.lock().await; let mut process_manager_handle = app_state_handle.process_manager.lock().await; diff --git a/src-tauri/src/remote/auth.rs b/src-tauri/src/remote/auth.rs index 51e2488..4930d37 100644 --- a/src-tauri/src/remote/auth.rs +++ b/src-tauri/src/remote/auth.rs @@ -1,15 +1,15 @@ -use std::{collections::HashMap, env, sync::Mutex}; +use std::{collections::HashMap, env}; use chrono::Utc; use droplet_rs::ssl::sign_nonce; use gethostname::gethostname; -use log::{debug, error, warn}; +use log::{debug, error, info, warn}; use serde::{Deserialize, Serialize}; use tauri::{AppHandle, Emitter, Manager}; use url::Url; use crate::{ - AppState, AppStatus, User, + AppStatus, DropFunctionState, User, database::{ db::{borrow_db_checked, borrow_db_mut_checked}, models::data::DatabaseAuth, @@ -50,16 +50,23 @@ struct HandshakeResponse { } pub async fn generate_authorization_header() -> String { + let func = generate_authorization_header_part().await; + func() +} + +pub async fn generate_authorization_header_part() -> Box String> { let certs = { let db = borrow_db_checked().await; db.auth.clone().unwrap() }; - let nonce = Utc::now().timestamp_millis().to_string(); + Box::new(move || { + let nonce = Utc::now().timestamp_millis().to_string(); - let signature = sign_nonce(certs.private, nonce.clone()).unwrap(); + let signature = sign_nonce(certs.private, nonce.clone()).unwrap(); - format!("Nonce {} {} {}", certs.client_id, nonce, signature) + format!("Nonce {} {} {}", certs.client_id, nonce, signature) + }) } pub async fn fetch_user() -> Result { @@ -156,11 +163,11 @@ pub async fn recieve_handshake(app: AppHandle, path: String) { return; } - let app_state = app.state::>(); + let app_state = app.state::>(); let (app_status, user) = setup().await; - - let mut state_lock = app_state.lock().unwrap(); + + let mut state_lock = app_state.lock().await; state_lock.status = app_status; state_lock.user = user; @@ -185,20 +192,20 @@ pub async fn auth_initiate_logic() -> Result<(), RemoteAccessError> { ]), }; - let client = reqwest::blocking::Client::new(); - let response = client.post(endpoint.to_string()).json(&body).send()?; + let client = reqwest::Client::new(); + let response = client.post(endpoint.to_string()).json(&body).send().await?; if response.status() != 200 { - let data: DropServerError = response.json()?; + let data: DropServerError = response.json().await?; error!("could not start handshake: {}", data.status_message); return Err(RemoteAccessError::HandshakeFailed(data.status_message)); } - let redir_url = response.text()?; + let redir_url = response.text().await?; let complete_redir_url = base_url.join(&redir_url)?; - debug!("opening web browser to continue authentication"); + info!("opening web browser to continue authentication: {}", complete_redir_url); webbrowser::open(complete_redir_url.as_ref()).unwrap(); Ok(()) diff --git a/src-tauri/src/remote/commands.rs b/src-tauri/src/remote/commands.rs index 28bde66..60b6eee 100644 --- a/src-tauri/src/remote/commands.rs +++ b/src-tauri/src/remote/commands.rs @@ -1,11 +1,10 @@ use log::debug; use reqwest::Client; use tauri::{AppHandle, Emitter, Manager}; -use tokio::sync::Mutex; use url::Url; use crate::{ - AppState, AppStatus, + AppStatus, DropFunctionState, database::db::{borrow_db_checked, borrow_db_mut_checked}, error::remote_access_error::RemoteAccessError, remote::{auth::generate_authorization_header, requests::make_request}, @@ -20,7 +19,7 @@ use super::{ #[tauri::command] pub async fn use_remote( url: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), RemoteAccessError> { use_remote_logic(url, state).await } @@ -70,7 +69,7 @@ pub async fn sign_out(app: AppHandle) { // Update app state { - let app_state = app.state::>(); + let app_state = app.state::>(); let mut app_state_handle = app_state.lock().await; app_state_handle.status = AppStatus::SignedOut; app_state_handle.user = None; @@ -81,7 +80,7 @@ pub async fn sign_out(app: AppHandle) { } #[tauri::command] -pub async fn retry_connect(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { +pub async fn retry_connect(state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> { let (app_status, user) = setup().await; let mut guard = state.lock().await; diff --git a/src-tauri/src/remote/server_proto.rs b/src-tauri/src/remote/server_proto.rs index 854aa40..21bad4f 100644 --- a/src-tauri/src/remote/server_proto.rs +++ b/src-tauri/src/remote/server_proto.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri}; -use reqwest::blocking::Client; +use reqwest::Client; use tauri::UriSchemeResponder; use crate::database::db::borrow_db_checked; @@ -44,10 +44,11 @@ pub async fn handle_server_proto(request: Request>, responder: UriScheme .header("Authorization", format!("Bearer {web_token}")) .headers(request.headers().clone()) .send() + .await .unwrap(); let response_status = response.status(); - let response_body = response.bytes().unwrap(); + let response_body = response.bytes().await.unwrap(); let http_response = Response::builder() .status(response_status) diff --git a/src-tauri/src/remote/utils.rs b/src-tauri/src/remote/utils.rs index aa0acf2..339da8c 100644 --- a/src-tauri/src/remote/utils.rs +++ b/src-tauri/src/remote/utils.rs @@ -1,11 +1,9 @@ -use log::{debug, warn}; +use log::{debug, info, warn}; use serde::Deserialize; -use tokio::sync::Mutex; use url::Url; use crate::{ - AppState, AppStatus, database::db::borrow_db_mut_checked, - error::remote_access_error::RemoteAccessError, + database::db::borrow_db_mut_checked, error::remote_access_error::RemoteAccessError, AppStatus, DropFunctionState }; #[derive(Deserialize)] @@ -16,16 +14,16 @@ struct DropHealthcheck { pub async fn use_remote_logic( url: String, - state: tauri::State<'_, Mutex>>, + state: tauri::State<'_, DropFunctionState<'_>>, ) -> Result<(), RemoteAccessError> { - debug!("connecting to url {url}"); + info!("connecting to url {url}"); let base_url = Url::parse(&url)?; // Test Drop url let test_endpoint = base_url.join("/api/v1")?; - let response = reqwest::blocking::get(test_endpoint.to_string())?; + let response = reqwest::get(test_endpoint.to_string()).await?; - let result: DropHealthcheck = response.json()?; + let result: DropHealthcheck = response.json().await?; if result.app_name != "Drop" { warn!("user entered drop endpoint that connected, but wasn't identified as Drop");