Skip to main content

aria2_core/config/
option_definitions.rs

1//! Built-in option definitions for aria2-rust.
2//!
3//! This module contains the registration of all ~77 built-in configuration options,
4//! organized by category. Each category has its own registration method on
5//! [`OptionRegistry`](super::OptionRegistry) for clear separation of concerns.
6//!
7//! # Option Priority Categorization (Phase 13 / Wave D — Task D1)
8//!
9//! Options are classified by how frequently users set them from the CLI:
10//!
11//! ## P0 — Connection / Timeout / Proxy / Bandwidth (set most often)
12//!   General:   dir(d), out(o), input-file(i), quiet(q)
13//!   HttpFtp:   timeout(t), connect-timeout(T), max-tries(m), retry-wait(w),
14//!             max-connection-per-server(x), min-split-size(k), split(s),
15//!             continue(c), all-proxy(p), http-proxy(P), check-certificate(b),
16//!             allow-overwrite(O), user-agent(U), referer(R), header(H),
17//!             load-cookies(C), no-proxy(N), https-proxy(y)
18//!   Advanced:  max-concurrent-downloads(j), max-overall-download-limit(A),
19//!             max-download-limit(Q)
20//!
21//! ## P1 — BT Seeding / RPC / Logging (important but less frequently changed)
22//!   General:   log(l), log-level(L), dry-run(n), summary-interval(S)
23//!   BitTorrent: seed-ratio(g), seed-time(G), bt-max-peers(B), listen-port(h),
24//!             enable-dht(D), follow-torrent(M), bt-force-encryption(X),
25//!             bt-save-metadata, enable-peer-exchange, bt-enable-lpd
26//!   Rpc:      enable-rpc(e), rpc-listen-port(r), rpc-secret(I), rpc-user,
27//!             rpc-passwd
28//!   HttpFtp:   ca-certificate(E), save-cookies(V), ftp-proxy(F)
29//!   Advanced:  file-allocation(f), max-overall-upload-limit(W),
30//!             max-upload-limit(K), disk-cache(Z), piece-length(Y), stop(z)
31//!
32//! ## P2 — Advanced / Rare (seldom changed from CLI)
33//!   General:   conf-path, console-log-level, enable-color, save-session,
34//!             save-session-interval, auto-save-interval
35//!   HttpFtp:   auto-file-renaming, remote-time
36//!   BitTorrent: bt-request-peer-speed-limit, bt-max-open-files,
37//!             bt-seed-unverified, bt-min-crypto-level, dht-listen-port,
38//!             dht-message-path, on-bt-download-complete, on-bt-download-error
39//!   Rpc:      rpc-listen-all, rpc-listen-address, rpc-allow-origin
40//!   Advanced:  force-save
41//!
42//! # Short-Option Mapping (Phase 13 / Wave D — Task D2)
43//!
44//! | Short | Long Option            | Category | Priority |
45//! |-------|------------------------|----------|----------|
46//! | d     | dir                    | General  | P0       |
47//! | o     | out                    | General  | P0       |
48//! | i     | input-file             | General  | P0       |
49//! | q     | quiet                  | General  | P0       |
50//! | l     | log                    | General  | P1       |
51//! | L     | log-level              | General  | P1       |
52//! | n     | dry-run                | General  | P2       |
53//! | S     | summary-interval       | General  | P2       |
54//! | s     | split                  | HttpFtp  | P0       |
55//! | c     | continue               | HttpFtp  | P0       |
56//! | t     | timeout                | HttpFtp  | P0       |
57//! | T     | connect-timeout        | HttpFtp  | P0       |
58//! | m     | max-tries              | HttpFtp  | P0       |
59//! | w     | retry-wait             | HttpFtp  | P0       |
60//! | x     | max-connection-per-server | HttpFtp | P0    |
61//! | k     | min-split-size         | HttpFtp  | P0       |
62//! | p     | all-proxy              | HttpFtp  | P0       |
63//! | P     | http-proxy             | HttpFtp  | P1       |
64//! | U     | user-agent             | HttpFtp  | P0       |
65//! | R     | referer                | HttpFtp  | P1       |
66//! | H     | header                 | HttpFft  | P1       |
67//! | b     | check-certificate      | HttpFtp  | P1       |
68//! | E     | ca-certificate         | HttpFft  | P2       |
69//! | O     | allow-overwrite        | HttpFtp  | P1       |
70//! | C     | load-cookies           | HttpFtp  | P1       |
71//! | V     | save-cookies           | HttpFft  | P2       |
72//! | N     | no-proxy               | HttpFtp  | P1       |
73//! | y     | https-proxy            | HttpFft  | P1       |
74//! | F     | ftp-proxy              | HttpFft  | P2       |
75//! | j     | max-concurrent-downloads | Adv.    | P0       |
76//! | f     | file-allocation        | Adv.     | P1       |
77//! | z     | stop                   | Adv.     | P2       |
78//! | g     | seed-ratio             | BT       | P1       |
79//! | G     | seed-time              | BT       | P1       |
80//! | B     | bt-max-peers           | BT       | P1       |
81//! | h     | listen-port            | BT       | P1       |
82//! | D     | enable-dht             | BT       | P1       |
83//! | X     | bt-force-encryption    | BT       | P2       |
84//! | M     | follow-torrent         | BT       | P1       |
85//! | e     | enable-rpc             | RPC      | P1       |
86//! | r     | rpc-listen-port        | RPC      | P1       |
87//! | I     | rpc-secret             | RPC      | P1       |
88//! | A     | max-overall-download-limit | Adv. | P0       |
89//! | Q     | max-download-limit     | Adv.     | P0       |
90//! | W     | max-overall-upload-limit  | Adv.  | P1       |
91//! | K     | max-upload-limit       | Adv.     | P1       |
92//! | Z     | disk-cache             | Adv.     | P1       |
93//! | Y     | piece-length           | Adv.     | P2       |
94
95use crate::config::{OptionCategory, OptionDef, OptionType, OptionValue};
96
97/// Extension trait that adds categorized registration methods to `OptionRegistry`.
98///
99/// This trait is implemented for [`super::OptionRegistry`] and provides one method
100/// per option category, making it easy to register options in logical groups or
101/// to selectively enable/disable categories.
102#[allow(dead_code)] // Trait methods are called dynamically via impl blocks
103pub(super) trait RegisterOptions {
104    /// Register all General category options (directory, logging, UI, session).
105    fn register_general_options(&mut self);
106
107    /// Register all HTTP/FTP category options (proxies, headers, timeouts, connections).
108    fn register_http_ftp_options(&mut self);
109
110    /// Register all BitTorrent category options (seeding, DHT, PEX, peers).
111    fn register_bt_options(&mut self);
112
113    /// Register all RPC category options (JSON-RPC/XML-RPC server settings).
114    fn register_rpc_options(&mut self);
115
116    /// Register all Advanced category options (bandwidth limits, disk cache, allocation).
117    fn register_advanced_options(&mut self);
118
119    /// Convenience method that registers all categories at once.
120    fn register_all_options(&mut self) {
121        self.register_general_options();
122        self.register_http_ftp_options();
123        self.register_bt_options();
124        self.register_rpc_options();
125        self.register_advanced_options();
126    }
127}
128
129// Note: The impl block is in option.rs since OptionRegistry is defined there.
130// This file only contains the trait definition and is imported by option.rs.
131
132/// ---------------------------------------------------------------------------
133/// General Options
134/// ---------------------------------------------------------------------------
135impl super::OptionRegistry {
136    /// Register general-purpose options: directory, output, logging, UI, session management.
137    pub fn register_general_options(&mut self) {
138        // --- Directory & Output ---
139        self.register(OptionDef {
140            name: "dir".into(),
141            opt_type: OptionType::Path,
142            short_name: Some('d'),
143            default_value: OptionValue::Str(".".into()),
144            description: "Save directory".into(),
145            category: OptionCategory::General,
146            ..Default::default()
147        });
148        self.register(OptionDef {
149            name: "out".into(),
150            opt_type: OptionType::String,
151            short_name: Some('o'),
152            description: "Output filename".into(),
153            category: OptionCategory::General,
154            ..Default::default()
155        });
156
157        // --- Logging ---
158        self.register(OptionDef {
159            name: "log".into(),
160            opt_type: OptionType::Path,
161            short_name: Some('l'),
162            default_value: OptionValue::None,
163            description: "Log file path".into(),
164            category: OptionCategory::General,
165            ..Default::default()
166        });
167        self.register(OptionDef {
168            name: "log-level".into(),
169            opt_type: OptionType::Enum,
170            short_name: Some('L'),
171            default_value: OptionValue::Str("info".into()),
172            description: "Log level (debug/info/notice/warn/error)".into(),
173            category: OptionCategory::General,
174            ..Default::default()
175        });
176        self.register(OptionDef {
177            name: "console-log-level".into(),
178            opt_type: OptionType::Enum,
179            default_value: OptionValue::Str("notice".into()),
180            description: "Console log level".into(),
181            category: OptionCategory::General,
182            ..Default::default()
183        });
184        self.register(OptionDef {
185            name: "log-backup-count".into(),
186            opt_type: OptionType::Integer,
187            default_value: OptionValue::Int(5),
188            min: Some(1),
189            description: "Number of backup log files to keep".into(),
190            category: OptionCategory::General,
191            ..Default::default()
192        });
193
194        // --- Progress & Intervals ---
195        self.register(OptionDef {
196            name: "summary-interval".into(),
197            opt_type: OptionType::Integer,
198            short_name: Some('S'),
199            default_value: OptionValue::Int(60),
200            min: Some(0),
201            max: Some(3600),
202            description: "Progress summary interval in seconds".into(),
203            category: OptionCategory::General,
204            ..Default::default()
205        });
206
207        // --- Configuration Files ---
208        self.register(OptionDef {
209            name: "conf-path".into(),
210            opt_type: OptionType::Path,
211            description: "Configuration file path".into(),
212            category: OptionCategory::General,
213            ..Default::default()
214        });
215        self.register(OptionDef {
216            name: "input-file".into(),
217            opt_type: OptionType::Path,
218            short_name: Some('i'),
219            description: "URI input file".into(),
220            category: OptionCategory::General,
221            ..Default::default()
222        });
223
224        // --- Session Management ---
225        self.register(OptionDef {
226            name: "save-session".into(),
227            opt_type: OptionType::Path,
228            description: "Session save file".into(),
229            category: OptionCategory::General,
230            ..Default::default()
231        });
232        self.register(OptionDef {
233            name: "save-session-interval".into(),
234            opt_type: OptionType::Integer,
235            default_value: OptionValue::Int(0),
236            description: "Auto-save session interval (0=disabled)".into(),
237            category: OptionCategory::General,
238            ..Default::default()
239        });
240        self.register(OptionDef {
241            name: "auto-save-interval".into(),
242            opt_type: OptionType::Integer,
243            default_value: OptionValue::Int(60),
244            min: Some(0),
245            max: Some(600),
246            description: "Auto-save interval".into(),
247            category: OptionCategory::General,
248            ..Default::default()
249        });
250
251        // --- UI Behavior ---
252        self.register(OptionDef {
253            name: "enable-color".into(),
254            opt_type: OptionType::Boolean,
255            default_value: OptionValue::Bool(true),
256            description: "Enable colored output".into(),
257            category: OptionCategory::General,
258            ..Default::default()
259        });
260        self.register(OptionDef {
261            name: "quiet".into(),
262            opt_type: OptionType::Boolean,
263            short_name: Some('q'),
264            default_value: OptionValue::Bool(false),
265            description: "Quiet mode".into(),
266            category: OptionCategory::General,
267            ..Default::default()
268        });
269        self.register(OptionDef {
270            name: "dry-run".into(),
271            opt_type: OptionType::Boolean,
272            short_name: Some('n'),
273            default_value: OptionValue::Bool(false),
274            description: "Dry run (check only, no download)".into(),
275            category: OptionCategory::General,
276            ..Default::default()
277        });
278
279        // --- Daemon Mode ---
280        self.register(OptionDef {
281            name: "daemon".into(),
282            opt_type: OptionType::Boolean,
283            short_name: Some('D'),
284            default_value: OptionValue::Bool(false),
285            description: "Run as a background daemon (detached process)".into(),
286            category: OptionCategory::General,
287            ..Default::default()
288        });
289        self.register(OptionDef {
290            name: "pid-file".into(),
291            opt_type: OptionType::Path,
292            description: "Path to PID file for daemon process management".into(),
293            category: OptionCategory::General,
294            ..Default::default()
295        });
296    }
297}
298
299/// ---------------------------------------------------------------------------
300/// HTTP/FTP Options
301/// ---------------------------------------------------------------------------
302impl super::OptionRegistry {
303    /// Register HTTP/FTP download options: proxies, headers, timeouts, connection management.
304    pub fn register_http_ftp_options(&mut self) {
305        // --- Proxy Settings ---
306        self.register(OptionDef {
307            name: "all-proxy".into(),
308            opt_type: OptionType::String,
309            short_name: Some('p'),
310            description: "Global proxy URL".into(),
311            category: OptionCategory::HttpFtp,
312            ..Default::default()
313        });
314        self.register(OptionDef {
315            name: "http-proxy".into(),
316            opt_type: OptionType::String,
317            short_name: Some('P'),
318            description: "HTTP proxy URL".into(),
319            category: OptionCategory::HttpFtp,
320            ..Default::default()
321        });
322        self.register(OptionDef {
323            name: "https-proxy".into(),
324            opt_type: OptionType::String,
325            short_name: Some('y'),
326            description: "HTTPS proxy URL".into(),
327            category: OptionCategory::HttpFtp,
328            ..Default::default()
329        });
330        self.register(OptionDef {
331            name: "ftp-proxy".into(),
332            opt_type: OptionType::String,
333            short_name: Some('F'),
334            description: "FTP proxy URL".into(),
335            category: OptionCategory::HttpFtp,
336            ..Default::default()
337        });
338        self.register(OptionDef {
339            name: "no-proxy".into(),
340            opt_type: OptionType::List,
341            short_name: Some('N'),
342            description: "Proxy exclusion list (comma-separated domains)".into(),
343            category: OptionCategory::HttpFtp,
344            ..Default::default()
345        });
346
347        // --- HTTP Headers & Identity ---
348        self.register(OptionDef {
349            name: "user-agent".into(),
350            opt_type: OptionType::String,
351            short_name: Some('U'),
352            default_value: OptionValue::Str("aria2/1.37.0-Rust".into()),
353            description: "User-Agent header".into(),
354            category: OptionCategory::HttpFtp,
355            ..Default::default()
356        });
357        self.register(OptionDef {
358            name: "referer".into(),
359            opt_type: OptionType::String,
360            short_name: Some('R'),
361            description: "Referer header".into(),
362            category: OptionCategory::HttpFtp,
363            ..Default::default()
364        });
365        self.register(OptionDef {
366            name: "header".into(),
367            opt_type: OptionType::List,
368            short_name: Some('H'),
369            description: "Custom headers (Header:Value pairs)".into(),
370            category: OptionCategory::HttpFtp,
371            ..Default::default()
372        });
373
374        // --- Cookies ---
375        self.register(OptionDef {
376            name: "load-cookies".into(),
377            opt_type: OptionType::Path,
378            short_name: Some('C'),
379            description: "Cookie file to load".into(),
380            category: OptionCategory::HttpFtp,
381            ..Default::default()
382        });
383        self.register(OptionDef {
384            name: "save-cookies".into(),
385            opt_type: OptionType::Path,
386            short_name: Some('V'),
387            description: "Cookie file to save".into(),
388            category: OptionCategory::HttpFtp,
389            ..Default::default()
390        });
391
392        // --- Timeouts & Retries ---
393        self.register(OptionDef {
394            name: "connect-timeout".into(),
395            opt_type: OptionType::Integer,
396            short_name: Some('T'),
397            default_value: OptionValue::Int(60),
398            min: Some(1),
399            max: Some(600),
400            description: "Connect timeout in seconds".into(),
401            category: OptionCategory::HttpFtp,
402            ..Default::default()
403        });
404        self.register(OptionDef {
405            name: "timeout".into(),
406            opt_type: OptionType::Integer,
407            short_name: Some('t'),
408            default_value: OptionValue::Int(60),
409            min: Some(1),
410            max: Some(600),
411            description: "I/O timeout in seconds".into(),
412            category: OptionCategory::HttpFtp,
413            ..Default::default()
414        });
415        self.register(OptionDef {
416            name: "max-tries".into(),
417            opt_type: OptionType::Integer,
418            short_name: Some('m'),
419            default_value: OptionValue::Int(5),
420            min: Some(0),
421            max: Some(100),
422            description: "Max retry attempts".into(),
423            category: OptionCategory::HttpFtp,
424            ..Default::default()
425        });
426        self.register(OptionDef {
427            name: "retry-wait".into(),
428            opt_type: OptionType::Integer,
429            short_name: Some('w'),
430            default_value: OptionValue::Int(0),
431            min: Some(0),
432            max: Some(3600),
433            description: "Retry wait time in seconds".into(),
434            category: OptionCategory::HttpFtp,
435            ..Default::default()
436        });
437
438        // --- Connection Management ---
439        self.register(OptionDef {
440            name: "split".into(),
441            opt_type: OptionType::Integer,
442            short_name: Some('s'),
443            default_value: OptionValue::Int(5),
444            min: Some(1),
445            max: Some(16),
446            description: "Connections per download".into(),
447            category: OptionCategory::HttpFtp,
448            ..Default::default()
449        });
450        self.register(OptionDef {
451            name: "min-split-size".into(),
452            opt_type: OptionType::Size,
453            short_name: Some('k'),
454            default_value: OptionValue::Int((20 * 1024 * 1024) as i64),
455            description: "Min split size".into(),
456            category: OptionCategory::HttpFtp,
457            ..Default::default()
458        });
459        self.register(OptionDef {
460            name: "max-connection-per-server".into(),
461            opt_type: OptionType::Integer,
462            short_name: Some('x'),
463            default_value: OptionValue::Int(1),
464            min: Some(1),
465            max: Some(16),
466            description: "Max connections per server".into(),
467            category: OptionCategory::HttpFtp,
468            ..Default::default()
469        });
470
471        // --- SSL/TLS ---
472        self.register(OptionDef {
473            name: "check-certificate".into(),
474            opt_type: OptionType::Boolean,
475            short_name: Some('b'),
476            default_value: OptionValue::Bool(true),
477            description: "Verify SSL certificate".into(),
478            category: OptionCategory::HttpFtp,
479            ..Default::default()
480        });
481        self.register(OptionDef {
482            name: "ca-certificate".into(),
483            opt_type: OptionType::Path,
484            short_name: Some('E'),
485            description: "CA certificate file".into(),
486            category: OptionCategory::HttpFtp,
487            ..Default::default()
488        });
489
490        // --- File Handling ---
491        self.register(OptionDef {
492            name: "allow-overwrite".into(),
493            opt_type: OptionType::Boolean,
494            short_name: Some('O'),
495            default_value: OptionValue::Bool(false),
496            description: "Allow overwriting existing files".into(),
497            category: OptionCategory::HttpFtp,
498            ..Default::default()
499        });
500        self.register(OptionDef {
501            name: "auto-file-renaming".into(),
502            opt_type: OptionType::Boolean,
503            default_value: OptionValue::Bool(true),
504            description: "Auto rename conflicting files".into(),
505            category: OptionCategory::HttpFtp,
506            ..Default::default()
507        });
508        self.register(OptionDef {
509            name: "continue".into(),
510            opt_type: OptionType::Boolean,
511            short_name: Some('c'),
512            default_value: OptionValue::Bool(true),
513            description: "Resume partial downloads".into(),
514            category: OptionCategory::HttpFtp,
515            ..Default::default()
516        });
517        self.register(OptionDef {
518            name: "remote-time".into(),
519            opt_type: OptionType::Boolean,
520            default_value: OptionValue::Bool(true),
521            description: "Use remote file timestamp".into(),
522            category: OptionCategory::HttpFtp,
523            ..Default::default()
524        });
525    }
526}
527
528/// ---------------------------------------------------------------------------
529/// BitTorrent Options
530/// ---------------------------------------------------------------------------
531impl super::OptionRegistry {
532    /// Register BitTorrent-specific options: seeding, DHT, PEX, peer management.
533    pub fn register_bt_options(&mut self) {
534        // --- Seeding Settings ---
535        self.register(OptionDef {
536            name: "seed-time".into(),
537            opt_type: OptionType::Float,
538            short_name: Some('G'),
539            default_value: OptionValue::Float(0.0),
540            description: "Seeding time in minutes (0=infinite)".into(),
541            category: OptionCategory::BitTorrent,
542            ..Default::default()
543        });
544        self.register(OptionDef {
545            name: "seed-ratio".into(),
546            opt_type: OptionType::Float,
547            short_name: Some('g'),
548            default_value: OptionValue::Float(1.0),
549            description: "Share ratio threshold".into(),
550            category: OptionCategory::BitTorrent,
551            ..Default::default()
552        });
553
554        // --- Peer Management ---
555        self.register(OptionDef {
556            name: "bt-max-peers".into(),
557            opt_type: OptionType::Integer,
558            short_name: Some('B'),
559            default_value: OptionValue::Int(55),
560            min: Some(0),
561            max: Some(512),
562            description: "Max peers per torrent".into(),
563            category: OptionCategory::BitTorrent,
564            ..Default::default()
565        });
566        self.register(OptionDef {
567            name: "bt-request-peer-speed-limit".into(),
568            opt_type: OptionType::Size,
569            default_value: OptionValue::Int((50 * 1024) as i64),
570            description: "Min peer speed to stay connected".into(),
571            category: OptionCategory::BitTorrent,
572            ..Default::default()
573        });
574        self.register(OptionDef {
575            name: "bt-max-open-files".into(),
576            opt_type: OptionType::Integer,
577            default_value: OptionValue::Int(100),
578            min: Some(10),
579            max: Some(4096),
580            description: "Max open files for BT".into(),
581            category: OptionCategory::BitTorrent,
582            ..Default::default()
583        });
584
585        // --- Torrent Behavior ---
586        self.register(OptionDef {
587            name: "bt-seed-unverified".into(),
588            opt_type: OptionType::Boolean,
589            default_value: OptionValue::Bool(false),
590            description: "Seed without verifying hash".into(),
591            category: OptionCategory::BitTorrent,
592            ..Default::default()
593        });
594        self.register(OptionDef {
595            name: "bt-save-metadata".into(),
596            opt_type: OptionType::Boolean,
597            short_name: Some('M'),
598            default_value: OptionValue::Bool(false),
599            description: "Save metadata as .torrent file".into(),
600            category: OptionCategory::BitTorrent,
601            ..Default::default()
602        });
603
604        // --- Encryption ---
605        self.register(OptionDef {
606            name: "bt-force-encryption".into(),
607            opt_type: OptionType::Boolean,
608            short_name: Some('X'),
609            default_value: OptionValue::Bool(false),
610            description: "Force BT encryption".into(),
611            category: OptionCategory::BitTorrent,
612            ..Default::default()
613        });
614        self.register(OptionDef {
615            name: "bt-min-crypto-level".into(),
616            opt_type: OptionType::Enum,
617            default_value: OptionValue::Str("plain".into()),
618            description: "Min crypto level (plain/arc4)".into(),
619            category: OptionCategory::BitTorrent,
620            ..Default::default()
621        });
622
623        // --- DHT / LPD / PEX ---
624        self.register(OptionDef {
625            name: "bt-enable-lpd".into(),
626            opt_type: OptionType::Boolean,
627            default_value: OptionValue::Bool(true),
628            description: "Enable Local Peer Discovery".into(),
629            category: OptionCategory::BitTorrent,
630            ..Default::default()
631        });
632        self.register(OptionDef {
633            name: "enable-lpd".into(),
634            opt_type: OptionType::Boolean,
635            default_value: OptionValue::Bool(true),
636            description: "Enable Local Peer Discovery (alias for bt-enable-lpd)".into(),
637            category: OptionCategory::BitTorrent,
638            ..Default::default()
639        });
640        self.register(OptionDef {
641            name: "lpd-listen-port".into(),
642            opt_type: OptionType::Integer,
643            default_value: OptionValue::Int(6771),
644            min: Some(1024),
645            max: Some(65535),
646            description: "UDP port for Local Peer Discovery".into(),
647            category: OptionCategory::BitTorrent,
648            ..Default::default()
649        });
650        self.register(OptionDef {
651            name: "bt-enable-web-seed".into(),
652            opt_type: OptionType::Boolean,
653            default_value: OptionValue::Bool(true),
654            description: "Enable web seed (HTTP/FTP seeding)".into(),
655            category: OptionCategory::BitTorrent,
656            ..Default::default()
657        });
658        self.register(OptionDef {
659            name: "enable-dht".into(),
660            opt_type: OptionType::Boolean,
661            short_name: Some('D'),
662            default_value: OptionValue::Bool(true),
663            description: "Enable DHT".into(),
664            category: OptionCategory::BitTorrent,
665            ..Default::default()
666        });
667        self.register(OptionDef {
668            name: "dht-listen-port".into(),
669            opt_type: OptionType::Integer,
670            default_value: OptionValue::Int(6881),
671            min: Some(1024),
672            max: Some(65535),
673            description: "DHT listen port".into(),
674            category: OptionCategory::BitTorrent,
675            ..Default::default()
676        });
677        self.register(OptionDef {
678            name: "dht-entry-point".into(),
679            opt_type: OptionType::List,
680            description: "DHT bootstrap nodes (host:port format, comma-separated)".into(),
681            category: OptionCategory::BitTorrent,
682            ..Default::default()
683        });
684        self.register(OptionDef {
685            name: "dht-file-path".into(),
686            opt_type: OptionType::Path,
687            description: "Path to DHT routing table file for persistence".into(),
688            category: OptionCategory::BitTorrent,
689            ..Default::default()
690        });
691        self.register(OptionDef {
692            name: "dht-message-path".into(),
693            opt_type: OptionType::Path,
694            description: "DHT message cache path (deprecated, use dht-file-path instead)".into(),
695            category: OptionCategory::BitTorrent,
696            ..Default::default()
697        });
698        self.register(OptionDef {
699            name: "enable-peer-exchange".into(),
700            opt_type: OptionType::Boolean,
701            default_value: OptionValue::Bool(true),
702            description: "Enable PEX".into(),
703            category: OptionCategory::BitTorrent,
704            ..Default::default()
705        });
706
707        // --- Torrent Handling ---
708        self.register(OptionDef {
709            name: "follow-torrent".into(),
710            opt_type: OptionType::Enum,
711            short_name: Some('M'),
712            default_value: OptionValue::Str("true".into()),
713            description: "Auto-handle .torrent (true/false/mem)".into(),
714            category: OptionCategory::BitTorrent,
715            ..Default::default()
716        });
717
718        // --- Event Hooks ---
719        self.register(OptionDef {
720            name: "on-bt-download-complete".into(),
721            opt_type: OptionType::String,
722            description: "Command on BT download complete".into(),
723            category: OptionCategory::BitTorrent,
724            ..Default::default()
725        });
726        self.register(OptionDef {
727            name: "on-bt-download-error".into(),
728            opt_type: OptionType::String,
729            description: "Command on BT download error".into(),
730            category: OptionCategory::BitTorrent,
731            ..Default::default()
732        });
733
734        // --- Listening Port ---
735        self.register(OptionDef {
736            name: "listen-port".into(),
737            opt_type: OptionType::String,
738            short_name: Some('h'),
739            default_value: OptionValue::Str("6881-6999".into()),
740            description: "Listening port range".into(),
741            category: OptionCategory::BitTorrent,
742            ..Default::default()
743        });
744
745        // --- Piece Selection Priority (G2) ---
746        self.register(OptionDef {
747            name: "bt-prioritize-piece".into(),
748            opt_type: OptionType::String,
749            default_value: OptionValue::Str("rarest".into()),
750            description: "Piece selection priority mode: 'rarest' (default), 'head' (sequential from start), 'tail' (sequential from end)".into(),
751            category: OptionCategory::BitTorrent,
752            ..Default::default()
753        });
754
755        // --- uTP (UDP Transport Protocol - BEP 29) ---
756        // Note: uTP is not implemented in the original C++ aria2. This is an experimental
757        // feature in aria2-rust that implements BEP 29 (http://www.bittorrent.org/beps/bep_0029.html).
758        // uTP provides congestion control over UDP, making BitTorrent friendlier to network traffic.
759        self.register(OptionDef {
760            name: "enable-utp".into(),
761            opt_type: OptionType::Boolean,
762            default_value: OptionValue::Bool(false),
763            description: "Enable uTP (UDP Transport Protocol, BEP 29). Experimental feature not in original aria2. Default: false".into(),
764            category: OptionCategory::BitTorrent,
765            ..Default::default()
766        });
767        self.register(OptionDef {
768            name: "utp-listen-port".into(),
769            opt_type: OptionType::Integer,
770            default_value: OptionValue::Int(0),
771            min: Some(0),
772            max: Some(65535),
773            description: "UDP port for uTP connections. 0 = auto-assign. Experimental feature not in original aria2".into(),
774            category: OptionCategory::BitTorrent,
775            ..Default::default()
776        });
777    }
778}
779
780/// ---------------------------------------------------------------------------
781/// RPC Options
782/// ---------------------------------------------------------------------------
783impl super::OptionRegistry {
784    /// Register JSON-RPC/XML-RPC server options: listening, authentication, CORS.
785    pub fn register_rpc_options(&mut self) {
786        // --- Server Enable / Bind ---
787        self.register(OptionDef {
788            name: "enable-rpc".into(),
789            opt_type: OptionType::Boolean,
790            short_name: Some('e'),
791            default_value: OptionValue::Bool(false),
792            description: "Enable JSON-RPC/XML-RPC server".into(),
793            category: OptionCategory::Rpc,
794            ..Default::default()
795        });
796        self.register(OptionDef {
797            name: "rpc-listen-all".into(),
798            opt_type: OptionType::Boolean,
799            default_value: OptionValue::Bool(false),
800            description: "Listen on all network interfaces".into(),
801            category: OptionCategory::Rpc,
802            ..Default::default()
803        });
804        self.register(OptionDef {
805            name: "rpc-listen-port".into(),
806            opt_type: OptionType::Integer,
807            short_name: Some('r'),
808            default_value: OptionValue::Int(6800),
809            min: Some(1024),
810            max: Some(65535),
811            description: "RPC server port".into(),
812            category: OptionCategory::Rpc,
813            ..Default::default()
814        });
815        self.register(OptionDef {
816            name: "rpc-listen-address".into(),
817            opt_type: OptionType::String,
818            default_value: OptionValue::Str("127.0.0.1".into()),
819            description: "RPC server bind address".into(),
820            category: OptionCategory::Rpc,
821            ..Default::default()
822        });
823
824        // --- Authentication ---
825        self.register(OptionDef {
826            name: "rpc-secret".into(),
827            opt_type: OptionType::String,
828            short_name: Some('I'),
829            description: "RPC secret token for authorization".into(),
830            category: OptionCategory::Rpc,
831            ..Default::default()
832        });
833        self.register(OptionDef {
834            name: "rpc-user".into(),
835            opt_type: OptionType::String,
836            description: "RPC Basic Auth username".into(),
837            category: OptionCategory::Rpc,
838            ..Default::default()
839        });
840        self.register(OptionDef {
841            name: "rpc-passwd".into(),
842            opt_type: OptionType::String,
843            description: "RPC Basic Auth password".into(),
844            category: OptionCategory::Rpc,
845            ..Default::default()
846        });
847
848        // --- CORS ---
849        self.register(OptionDef {
850            name: "rpc-allow-origin".into(),
851            opt_type: OptionType::String,
852            description: "CORS Allow-Origin value".into(),
853            category: OptionCategory::Rpc,
854            ..Default::default()
855        });
856        self.register(OptionDef {
857            name: "rpc-cors-domain".into(),
858            opt_type: OptionType::String,
859            default_value: OptionValue::Str("*".into()),
860            description: "CORS allowed domains for RPC (comma-separated, * for all)".into(),
861            category: OptionCategory::Rpc,
862            ..Default::default()
863        });
864
865        // --- HTTPS/TLS ---
866        self.register(OptionDef {
867            name: "rpc-secure".into(),
868            opt_type: OptionType::Boolean,
869            default_value: OptionValue::Bool(false),
870            description: "Enable HTTPS for RPC server".into(),
871            category: OptionCategory::Rpc,
872            ..Default::default()
873        });
874        self.register(OptionDef {
875            name: "rpc-certificate".into(),
876            opt_type: OptionType::Path,
877            description: "Path to TLS certificate file (PEM format)".into(),
878            category: OptionCategory::Rpc,
879            ..Default::default()
880        });
881        self.register(OptionDef {
882            name: "rpc-private-key".into(),
883            opt_type: OptionType::Path,
884            description: "Path to TLS private key file (PEM format)".into(),
885            category: OptionCategory::Rpc,
886            ..Default::default()
887        });
888    }
889}
890
891/// ---------------------------------------------------------------------------
892/// Advanced Options
893/// ---------------------------------------------------------------------------
894impl super::OptionRegistry {
895    /// Register advanced/performance options: bandwidth limits, disk cache, file allocation.
896    pub fn register_advanced_options(&mut self) {
897        // --- File Allocation ---
898        self.register(OptionDef {
899            name: "file-allocation".into(),
900            opt_type: OptionType::Enum,
901            short_name: Some('f'),
902            default_value: OptionValue::Str("falloc".into()),
903            description: "File allocation method (none/prealloc/falloc/trunc/mmap)".into(),
904            category: OptionCategory::Advanced,
905            ..Default::default()
906        });
907
908        // --- Secure Falloc ---
909        // Zero-fill allocated space after fallocate on platforms that don't
910        // zero-fill (macOS F_PREALLOCATE, Windows SetFileValidData). Prevents
911        // exposure of residual disk data at a performance cost. Has no effect
912        // on Linux where fallocate(2) always returns zeroed blocks.
913        self.register(OptionDef {
914            name: "secure-falloc".into(),
915            opt_type: OptionType::Boolean,
916            default_value: OptionValue::Bool(false),
917            description: "Zero-fill allocated space after fallocate on platforms that don't zero-fill (macOS, Windows). Prevents exposure of residual disk data at a performance cost.".into(),
918            category: OptionCategory::Advanced,
919            ..Default::default()
920        });
921
922        // --- Mmap Threshold ---
923        // Files larger than this threshold use MmapDiskWriter when
924        // --file-allocation=mmap is set. Below the threshold, positioned I/O
925        // is used (avoids address space waste for small files).
926        self.register(OptionDef {
927            name: "mmap-threshold".into(),
928            opt_type: OptionType::Size,
929            default_value: OptionValue::Int(256 * 1024 * 1024), // 256 MiB
930            description:
931                "File size threshold for mmap writes when file-allocation=mmap (default 256 MiB)"
932                    .into(),
933            category: OptionCategory::Advanced,
934            ..Default::default()
935        });
936
937        // --- Concurrency ---
938        self.register(OptionDef {
939            name: "max-concurrent-downloads".into(),
940            opt_type: OptionType::Integer,
941            short_name: Some('j'),
942            default_value: OptionValue::Int(5),
943            min: Some(1),
944            max: Some(256),
945            description: "Max concurrent downloads".into(),
946            category: OptionCategory::Advanced,
947            ..Default::default()
948        });
949
950        // --- Bandwidth Limits ---
951        self.register(OptionDef {
952            name: "max-overall-download-limit".into(),
953            opt_type: OptionType::Size,
954            short_name: Some('A'),
955            default_value: OptionValue::Int(0),
956            description: "Overall download speed limit (0=unlimited)".into(),
957            category: OptionCategory::Advanced,
958            ..Default::default()
959        });
960        self.register(OptionDef {
961            name: "max-download-limit".into(),
962            opt_type: OptionType::Size,
963            short_name: Some('Q'),
964            default_value: OptionValue::Int(0),
965            description: "Per-task download limit (0=unlimited)".into(),
966            category: OptionCategory::Advanced,
967            ..Default::default()
968        });
969        self.register(OptionDef {
970            name: "max-overall-upload-limit".into(),
971            opt_type: OptionType::Size,
972            short_name: Some('W'),
973            default_value: OptionValue::Int(0),
974            description: "Overall upload speed limit (0=unlimited)".into(),
975            category: OptionCategory::Advanced,
976            ..Default::default()
977        });
978        self.register(OptionDef {
979            name: "max-upload-limit".into(),
980            opt_type: OptionType::Size,
981            short_name: Some('K'),
982            default_value: OptionValue::Int(0),
983            description: "Per-task upload limit (0=unlimited)".into(),
984            category: OptionCategory::Advanced,
985            ..Default::default()
986        });
987
988        // --- BT Piece & Disk ---
989        self.register(OptionDef {
990            name: "piece-length".into(),
991            opt_type: OptionType::Size,
992            short_name: Some('Y'),
993            default_value: OptionValue::Int((1024 * 1024) as i64),
994            description: "BT piece length".into(),
995            category: OptionCategory::Advanced,
996            ..Default::default()
997        });
998        self.register(OptionDef {
999            name: "disk-cache".into(),
1000            opt_type: OptionType::Size,
1001            short_name: Some('Z'),
1002            default_value: OptionValue::Int(0),
1003            description: "Disk cache size (0=disabled)".into(),
1004            category: OptionCategory::Advanced,
1005            ..Default::default()
1006        });
1007
1008        // --- Auto-stop & Save ---
1009        self.register(OptionDef {
1010            name: "stop".into(),
1011            opt_type: OptionType::Integer,
1012            short_name: Some('z'),
1013            default_value: OptionValue::Int(0),
1014            min: Some(0),
1015            max: Some(86400),
1016            description: "Stop after N seconds of completion (0=never)".into(),
1017            category: OptionCategory::Advanced,
1018            ..Default::default()
1019        });
1020        self.register(OptionDef {
1021            name: "force-save".into(),
1022            opt_type: OptionType::Boolean,
1023            default_value: OptionValue::Bool(false),
1024            description: "Force save state on every change".into(),
1025            category: OptionCategory::Advanced,
1026            ..Default::default()
1027        });
1028
1029        // --- Server Statistics Persistence ---
1030        self.register(OptionDef {
1031            name: "server-stat-file".into(),
1032            opt_type: OptionType::Path,
1033            description: "Path to save/load server performance statistics".into(),
1034            category: OptionCategory::Advanced,
1035            ..Default::default()
1036        });
1037        self.register(OptionDef {
1038            name: "save-server-stat-interval".into(),
1039            opt_type: OptionType::Integer,
1040            default_value: OptionValue::Int(0),
1041            min: Some(0),
1042            max: Some(86400),
1043            description: "Auto-save interval for server stats in seconds (0 = disabled)".into(),
1044            category: OptionCategory::Advanced,
1045            ..Default::default()
1046        });
1047    }
1048}