Skip to main content

sendmer/core/
options.rs

1//! 发送和接收选项定义。
2//!
3//! 本文件定义:SendOptions, ReceiveOptions, RelayModeOption, AddrInfoOptions。
4
5use iroh::RelayUrl;
6use std::net::{SocketAddrV4, SocketAddrV6};
7
8#[derive(Debug, Default)]
9pub struct SendOptions {
10    pub relay_mode: RelayModeOption,
11    pub ticket_type: AddrInfoOptions,
12    pub magic_ipv4_addr: Option<SocketAddrV4>,
13    pub magic_ipv6_addr: Option<SocketAddrV6>,
14}
15
16#[derive(Debug, Default)]
17pub struct ReceiveOptions {
18    pub output_dir: Option<std::path::PathBuf>,
19    pub relay_mode: RelayModeOption,
20    pub magic_ipv4_addr: Option<SocketAddrV4>,
21    pub magic_ipv6_addr: Option<SocketAddrV6>,
22}
23
24pub trait EndpointOptions: BindAddressOptions {
25    fn relay_mode(&self) -> RelayModeOption;
26}
27
28pub trait BindAddressOptions {
29    fn magic_ipv4_addr(&self) -> Option<SocketAddrV4>;
30    fn magic_ipv6_addr(&self) -> Option<SocketAddrV6>;
31}
32
33impl EndpointOptions for SendOptions {
34    fn relay_mode(&self) -> RelayModeOption {
35        self.relay_mode.clone()
36    }
37}
38
39impl BindAddressOptions for SendOptions {
40    fn magic_ipv4_addr(&self) -> Option<SocketAddrV4> {
41        self.magic_ipv4_addr
42    }
43
44    fn magic_ipv6_addr(&self) -> Option<SocketAddrV6> {
45        self.magic_ipv6_addr
46    }
47}
48
49impl EndpointOptions for ReceiveOptions {
50    fn relay_mode(&self) -> RelayModeOption {
51        self.relay_mode.clone()
52    }
53}
54
55impl BindAddressOptions for ReceiveOptions {
56    fn magic_ipv4_addr(&self) -> Option<SocketAddrV4> {
57        self.magic_ipv4_addr
58    }
59
60    fn magic_ipv6_addr(&self) -> Option<SocketAddrV6> {
61        self.magic_ipv6_addr
62    }
63}
64
65pub fn apply_bind_addrs<T: BindAddressOptions>(
66    mut builder: iroh::endpoint::Builder,
67    options: &T,
68) -> iroh::endpoint::Builder {
69    if let Some(addr) = options.magic_ipv4_addr() {
70        builder = builder.bind_addr_v4(addr);
71    }
72    if let Some(addr) = options.magic_ipv6_addr() {
73        builder = builder.bind_addr_v6(addr);
74    }
75    builder
76}
77
78#[derive(Clone, Debug, Default)]
79pub enum RelayModeOption {
80    Disabled,
81    #[default]
82    Default,
83    Custom(RelayUrl),
84}
85
86impl From<RelayModeOption> for iroh::RelayMode {
87    fn from(value: RelayModeOption) -> Self {
88        match value {
89            RelayModeOption::Disabled => Self::Disabled,
90            RelayModeOption::Default => Self::Default,
91            RelayModeOption::Custom(url) => Self::Custom(url.into()),
92        }
93    }
94}
95
96impl std::str::FromStr for RelayModeOption {
97    type Err = anyhow::Error;
98
99    fn from_str(s: &str) -> Result<Self, Self::Err> {
100        match s {
101            "disabled" => Ok(Self::Disabled),
102            "default" => Ok(Self::Default),
103            _ => Ok(Self::Custom(RelayUrl::from_str(s)?)),
104        }
105    }
106}
107
108impl std::fmt::Display for RelayModeOption {
109    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110        match self {
111            Self::Disabled => f.write_str("disabled"),
112            Self::Default => f.write_str("default"),
113            Self::Custom(url) => url.fmt(f),
114        }
115    }
116}
117
118#[derive(
119    Copy,
120    Clone,
121    PartialEq,
122    Eq,
123    Default,
124    Debug,
125    derive_more::Display,
126    derive_more::FromStr,
127    serde::Serialize,
128    serde::Deserialize,
129)]
130pub enum AddrInfoOptions {
131    #[default]
132    Id,
133    RelayAndAddresses,
134    Relay,
135    Addresses,
136}
137
138pub fn apply_options(addr: &mut iroh::EndpointAddr, opts: AddrInfoOptions) {
139    use iroh::TransportAddr;
140    match opts {
141        AddrInfoOptions::Id => {
142            addr.addrs = Default::default();
143        }
144        AddrInfoOptions::RelayAndAddresses => {
145            // nothing to do
146        }
147        AddrInfoOptions::Relay => {
148            addr.addrs = addr
149                .addrs
150                .iter()
151                .filter(|addr| matches!(addr, TransportAddr::Relay(_)))
152                .cloned()
153                .collect();
154        }
155        AddrInfoOptions::Addresses => {
156            addr.addrs = addr
157                .addrs
158                .iter()
159                .filter(|addr| matches!(addr, TransportAddr::Ip(_)))
160                .cloned()
161                .collect();
162        }
163    }
164}