dittolive_ditto/transport/transport_config.rs
1use std::{collections::HashSet, path::PathBuf, time::Duration};
2
3use serde::{Deserialize, Serialize};
4use serde_with::serde_as;
5
6pub const NO_PREFERRED_ROUTE_HINT: u32 = 0;
7
8/// A configuration object specifying which network transports Ditto should use
9/// to sync data.
10///
11/// A `Ditto` object comes with a default transport configuration where all
12/// available peer-to-peer transports are enabled. You can customize this by
13/// initializing a `TransportConfig`, adjusting its properties, and supplying it
14/// to `set_transport_config()` on `Ditto`.
15///
16/// When you initialize a `TransportConfig` yourself it starts with all
17/// transports disabled. You must enable each one directly.
18///
19/// Peer-to-peer transports will automatically discover peers in the vicinity
20/// and create connections without any configuration. These are configured
21/// inside the `peer_to_peer` property. To turn each one on, set its `enabled`
22/// property to `true`.
23///
24/// To connect to a peer at a known location, such as a Ditto Big Peer, add its
25/// address inside the `connect` configuration. These are either `host:port`
26/// strings for raw TCP sync, or a `wss://…` URL for websockets.
27///
28/// The `listen` configurations are for specific less common data sync
29/// scenarios. Please read the documentation on the Ditto website for examples.
30/// Incorrect use of `listen` can result in insecure configurations.
31#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
32pub struct TransportConfig {
33 /// Configure Bluetooth and LAN transports.
34 pub peer_to_peer: PeerToPeer,
35
36 /// Configure TCP and WebSocket outbound transports.
37 pub connect: Connect,
38
39 /// Configure TCP and HTTP inbound transports.
40 pub listen: Listen,
41
42 /// Set peer-global transport settings.
43 pub global: Global,
44}
45
46impl TransportConfig {
47 /// Create a new [`TransportConfig`] with default settings.
48 pub fn new() -> Self {
49 Self {
50 peer_to_peer: PeerToPeer {
51 bluetooth_le: BluetoothLEConfig::new(),
52 lan: LanConfig::new(),
53 },
54 connect: Connect {
55 tcp_servers: HashSet::new(),
56 websocket_urls: HashSet::new(),
57 retry_interval: Duration::from_secs(5),
58 },
59 listen: Listen {
60 tcp: TcpListenConfig::new(),
61 http: HttpListenConfig::new(),
62 },
63 global: Global {
64 sync_group: 0,
65 routing_hint: NO_PREFERRED_ROUTE_HINT,
66 },
67 }
68 }
69
70 /// Enables peer-to-peer transports in this config.
71 pub fn enable_all_peer_to_peer(&mut self) {
72 self.peer_to_peer.bluetooth_le.enabled = true;
73 self.peer_to_peer.lan.enabled = true;
74 }
75}
76
77/// Configure peer-to-peer transports such as Bluetooth and LAN.
78#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
79pub struct PeerToPeer {
80 /// Bluetooth transport configurations.
81 pub bluetooth_le: BluetoothLEConfig,
82
83 /// LAN transport configurations.
84 pub lan: LanConfig,
85}
86
87/// Configure outbound transports such as TCP and WebSocket dialing.
88#[serde_as]
89#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
90pub struct Connect {
91 /// A set of TCP servers to attempt connection to.
92 pub tcp_servers: HashSet<String>,
93
94 /// A set of websocket servers to attempt connection to.
95 pub websocket_urls: HashSet<String>,
96
97 /// The retry interval between failed connection attempts. For
98 /// cross-compatibility, this must be less than 2^32 - 1 milliseconds.
99 #[serde_as(as = "::serde_with::DurationMilliSeconds<u64>")]
100 pub retry_interval: Duration,
101}
102
103/// Configure inbound transports such as TCP and HTTP servers.
104#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
105pub struct Listen {
106 /// Configure inbound TCP transports.
107 pub tcp: TcpListenConfig,
108
109 /// Configure inbound HTTP transports.
110 pub http: HttpListenConfig,
111}
112
113/// Settings not associated with any specific type of transport.
114#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
115pub struct Global {
116 /// The sync group for this device.
117 ///
118 /// When peer-to-peer transports are enabled, all devices with the same App
119 /// ID will normally form an interconnected mesh network. In some
120 /// situations it may be desirable to have distinct groups of devices
121 /// within the same app, so that connections will only be formed within
122 /// each group. The `sync_group` parameter changes that group
123 /// membership. A device can only ever be in one sync group, which
124 /// by default is group 0. Up to 2^32 distinct group numbers can be used in
125 /// an app.
126 ///
127 /// This is an optimization, not a security control. If a connection is
128 /// created manually, such as by specifying a `connect` transport, then
129 /// devices from different sync groups will still sync as normal. If
130 /// two groups of devices are intended to have access to different data
131 /// sets, this must be enforced using Ditto's permissions system.
132 pub sync_group: u32,
133
134 /// The routing hint for this device.
135 ///
136 /// A routing hint is a performance tuning option which can improve the performance of
137 /// applications that use large collections. Ditto will make a best effort to co-locate data
138 /// for the same routing key. In most circumstances, this should substantially improve
139 /// responsiveness of the Ditto Cloud.
140 ///
141 /// The value of the routing hint is application specific - you are free to chose any value.
142 /// Devices which you expect to operate on much the same data should be configured to
143 /// use the same value.
144 ///
145 /// A routing hint does not partition data. The value of the routing hint will not affect the
146 /// data returned for a query. The routing hint only improves the efficiency of the Cloud's
147 /// ability to satisfy the query.
148 pub routing_hint: u32,
149}
150
151/// Configure inbound HTTP transports.
152#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
153pub struct HttpListenConfig {
154 /// Whether inbound HTTP is enabled.
155 pub enabled: bool,
156
157 /// The IP address on which to bind a listenting HTTP server.
158 pub interface_ip: String,
159
160 /// The port on which to bind a listening HTTP server.
161 pub port: u16,
162
163 /// An optional path to static files to make available to clients.
164 pub static_content_path: Option<PathBuf>,
165
166 /// Whether to enable Websocket sync on this transport.
167 pub websocket_sync: bool,
168
169 /// Optional path to a TLS key file.
170 pub tls_key_path: Option<PathBuf>,
171
172 /// Optional path to a TLS certificate file.
173 pub tls_certificate_path: Option<PathBuf>,
174}
175
176impl HttpListenConfig {
177 /// Create a new [`HttpListenConfig`] with default settings.
178 pub fn new() -> Self {
179 Self {
180 enabled: false,
181 interface_ip: "[::]".to_string(),
182 port: 80,
183 static_content_path: None,
184 websocket_sync: true,
185 tls_key_path: None,
186 tls_certificate_path: None,
187 }
188 }
189}
190
191/// Configure inbound TCP transports.
192#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
193pub struct TcpListenConfig {
194 /// Whether inbound TCP is enabled.
195 pub enabled: bool,
196
197 /// The address to bind a TCP listener, such as `0.0.0.0`.
198 pub interface_ip: String,
199
200 /// The port to bind the TCP listener to.
201 pub port: u16,
202}
203
204impl TcpListenConfig {
205 /// Create a new [`TcpListenConfig`] with default settings.
206 pub fn new() -> Self {
207 Self {
208 enabled: false,
209 interface_ip: "[::]".to_string(),
210 port: 4040,
211 }
212 }
213}
214
215/// Configure the Bluetooth Low-Energy transport.
216#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
217pub struct BluetoothLEConfig {
218 /// Whether to enable the Bluetooth Low-Energy transport.
219 pub enabled: bool,
220}
221
222impl BluetoothLEConfig {
223 /// Create a new [`BluetoothLEConfig`] with default settings.
224 pub fn new() -> Self {
225 Self { enabled: false }
226 }
227}
228
229/// Configure the Local Area Network (LAN) transport.
230#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
231pub struct LanConfig {
232 /// Whether to enable the LAN transport.
233 pub enabled: bool,
234
235 /// Whether to enable mDNS peer discovery.
236 pub mdns_enabled: bool,
237
238 /// Whether to enable multicast.
239 pub multicast_enabled: bool,
240}
241
242impl LanConfig {
243 /// Create a new [`LanConfig`] with default settings.
244 pub fn new() -> Self {
245 Self {
246 enabled: false,
247 mdns_enabled: true,
248 multicast_enabled: true,
249 }
250 }
251}