Skip to content

Commit 08bbb8f

Browse files
committed
feat: Add bandwidth control feature
1 parent ac22e25 commit 08bbb8f

File tree

12 files changed

+739
-219
lines changed

12 files changed

+739
-219
lines changed

AGENTS.md

Lines changed: 340 additions & 162 deletions
Large diffs are not rendered by default.

src-tauri/Cargo.lock

Lines changed: 106 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ async-trait = "0.1"
6060
# UUID for RPC request IDs
6161
uuid = { version = "1", features = ["v4"] }
6262

63+
dirs = "5"
64+
6365

src-tauri/src/aria2/api.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,24 @@ use std::sync::Mutex;
66
use std::time::Duration;
77

88
const DEFAULT_RPC_URL: &str = "http://localhost:6800/jsonrpc";
9-
const ARIA2_STARTUP_TIMEOUT: Duration = Duration::from_secs(5);
9+
const ARIA2_START_UP_TIMEOUT: Duration = Duration::from_secs(5);
1010

1111
pub struct Aria2Client {
1212
client: Client,
1313
rpc_url: String,
1414
aria2_process: Mutex<Option<Child>>,
15+
max_overall_download_limit_kb_per_sec: Mutex<u64>,
16+
max_download_limit_kb_per_sec: Mutex<u64>,
1517
}
1618

1719
impl Default for Aria2Client {
1820
fn default() -> Self {
19-
Self::new(DEFAULT_RPC_URL)
21+
Self::new(DEFAULT_RPC_URL, 0, 0)
2022
}
2123
}
2224

2325
impl Aria2Client {
24-
pub fn new(rpc_url: &str) -> Self {
26+
pub fn new(rpc_url: &str, max_overall_limit_kb_per_sec: u64, max_download_limit_kb_per_sec: u64) -> Self {
2527
let client = Client::builder()
2628
.timeout(Duration::from_secs(30))
2729
.build()
@@ -31,9 +33,22 @@ impl Aria2Client {
3133
client,
3234
rpc_url: rpc_url.to_string(),
3335
aria2_process: Mutex::new(None),
36+
max_overall_download_limit_kb_per_sec: Mutex::new(max_overall_limit_kb_per_sec),
37+
max_download_limit_kb_per_sec: Mutex::new(max_download_limit_kb_per_sec),
3438
}
3539
}
3640

41+
pub fn set_bandwidth_limit(&self, max_overall_limit_kb_per_sec: u64, max_download_limit_kb_per_sec: u64) {
42+
*self.max_overall_download_limit_kb_per_sec.lock().unwrap() = max_overall_limit_kb_per_sec;
43+
*self.max_download_limit_kb_per_sec.lock().unwrap() = max_download_limit_kb_per_sec;
44+
}
45+
46+
pub fn get_bandwidth_limit(&self) -> (u64, u64) {
47+
let overall = *self.max_overall_download_limit_kb_per_sec.lock().unwrap();
48+
let per_download = *self.max_download_limit_kb_per_sec.lock().unwrap();
49+
(overall, per_download)
50+
}
51+
3752
fn get_aria2_path() -> Option<PathBuf> {
3853
let possible_paths = [
3954
PathBuf::from("aria2/aria2c.exe"),
@@ -64,6 +79,12 @@ impl Aria2Client {
6479

6580
let aria2_path = Self::get_aria2_path().ok_or("aria2c not found")?;
6681

82+
let overall_limit = *self.max_overall_download_limit_kb_per_sec.lock().unwrap();
83+
let download_limit = *self.max_download_limit_kb_per_sec.lock().unwrap();
84+
85+
let overall_limit_arg = format!("{}K", overall_limit);
86+
let download_limit_arg = format!("{}K", download_limit);
87+
6788
let args = [
6889
"--enable-rpc",
6990
"--rpc-listen-all=false",
@@ -72,8 +93,8 @@ impl Aria2Client {
7293
"--max-connection-per-server=16",
7394
"--split=16",
7495
"--min-split-size=1M",
75-
"--max-overall-download-limit=0",
76-
"--max-download-limit=0",
96+
&format!("--max-overall-download-limit={}", overall_limit_arg),
97+
&format!("--max-download-limit={}", download_limit_arg),
7798
"--file-allocation=none",
7899
"--continue=true",
79100
"--auto-file-renaming=true",
@@ -97,7 +118,7 @@ impl Aria2Client {
97118
*self.aria2_process.lock().unwrap() = Some(child);
98119

99120
let start = std::time::Instant::now();
100-
while start.elapsed() < ARIA2_STARTUP_TIMEOUT {
121+
while start.elapsed() < ARIA2_START_UP_TIMEOUT {
101122
if self.is_running().await {
102123
return Ok(());
103124
}
@@ -263,6 +284,23 @@ impl Aria2Client {
263284
self.call("shutdown", vec![]).await
264285
}
265286

287+
pub async fn change_global_option(&self, key: &str, value: &str) -> Result<String, String> {
288+
self.call(
289+
"changeGlobalOption",
290+
vec![
291+
serde_json::json!({ key: value }),
292+
],
293+
).await
294+
}
295+
296+
pub async fn get_global_option(&self, key: &str) -> Result<String, String> {
297+
let result: serde_json::Value = self.call("getGlobalOption", vec![]).await?;
298+
result.get(key)
299+
.and_then(|v| v.as_str())
300+
.map(|s| s.to_string())
301+
.ok_or(format!("Option {} not found", key))
302+
}
303+
266304
pub async fn get_all_downloads(&self) -> Result<Vec<DownloadInfo>, String> {
267305
let mut all_downloads = Vec::new();
268306

0 commit comments

Comments
 (0)