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