quick_file_transfer/config/transfer/
send.rs

1use std::time::Duration;
2
3use crate::{config::util::*, util::IANA_RECOMMEND_DYNAMIC_PORT_RANGE_START};
4
5#[cfg(feature = "mdns")]
6pub mod mdns;
7
8/// Holds the Send subcommands
9#[derive(Debug, Args)]
10#[command(arg_required_else_help = true)]
11pub struct SendArgs {
12    #[command(subcommand)]
13    pub subcmd: SendCommand,
14
15    /// Supply a file for I/O (if none: use stdio)
16    #[arg(
17        short,
18        long,
19        global(true),
20        value_name("FILE"),
21        group("io-content"),
22        name("INPUT_FILE")
23    )]
24    pub file: Vec<PathBuf>,
25
26    /// Disables that client sends the size of files to the server allowing the server to preallocate for the expected size
27    #[arg(long,action = ArgAction::SetTrue, requires = "INPUT_FILE", global(true))]
28    pub no_prealloc: bool,
29
30    /// Use memory mapping mode
31    #[arg(long, action = ArgAction::SetTrue, requires = "INPUT_FILE", global(true))]
32    pub mmap: bool,
33
34    /// Poll the server with a specified interval (ms) until a connection is established.
35    #[arg(
36        long("poll"),
37        global(true),
38        value_name("INTERVAL_MS"),
39        default_value_t = 100
40    )]
41    pub poll: u32,
42
43    /// Disable polling, exit immediately if the first attempt at establishing a connection to the server fails
44    #[arg(
45        long("one-shot"),
46        visible_alias("disable-poll"),
47        default_value_t = false
48    )]
49    pub one_shot: bool,
50
51    /// Maxiumum time to attempt to establish a TCP connection to remote.
52    #[arg(long, default_value = Some("5000"), group("tcp_about_condition"))]
53    pub tcp_timeout_ms: Option<u32>,
54
55    /// Maximum attempts to establish a TCP connection to remote.
56    #[arg(long, group("tcp_about_condition"))]
57    pub tcp_max_attempts: Option<u32>,
58}
59
60impl SendArgs {
61    /// Returns the configured mode for making Tcp connections
62    pub fn tcp_connect_mode(&self) -> TcpConnectMode {
63        if self.one_shot {
64            TcpConnectMode::OneShot
65        } else {
66            let abort_cond = if let Some(attempts) = self.tcp_max_attempts {
67                PollAbortCondition::Attempts(attempts)
68            } else {
69                PollAbortCondition::Timeout(Duration::from_millis(
70                    self.tcp_timeout_ms.unwrap().into(),
71                ))
72            };
73            TcpConnectMode::poll_from_ms(self.poll, abort_cond)
74        }
75    }
76
77    pub fn prealloc(&self) -> bool {
78        if self.file.is_empty() {
79            false
80        } else {
81            !self.no_prealloc
82        }
83    }
84}
85
86#[allow(clippy::large_enum_variant)] // This lint should be revised when command-line args are fairly stabilized
87#[derive(Subcommand, Debug)]
88pub enum SendCommand {
89    /// Send to target by specifying IP e.g. `192.1.1.1`
90    Ip(SendIpArgs),
91
92    /// Send to target by specifying mDNS hostname e.g. `foo.local`
93    #[cfg(feature = "mdns")]
94    Mdns(mdns::SendMdnsArgs),
95}
96
97#[derive(Debug, Args, Clone)]
98#[command(flatten_help = true)]
99pub struct SendIpArgs {
100    /// IP to send to e.g. `192.0.0.1`
101    pub ip: String,
102    /// e.g. 49152. IANA recommends: 49152-65535 for dynamic use.
103    #[arg(short, long, default_value_t = IANA_RECOMMEND_DYNAMIC_PORT_RANGE_START, value_parser = clap::value_parser!(u16).range(1..))]
104    pub port: u16,
105    /// Compression format
106    #[command(subcommand)]
107    pub compression: Option<Compression>,
108}