1use 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 }
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}