Buttplug sex toy control library
1use buttplug_core::errors::ButtplugDeviceError;
2use dashmap::DashMap;
3use getset::Getters;
4use std::{
5 collections::HashMap,
6 fmt::{self, Debug},
7};
8use uuid::Uuid;
9
10use crate::{
11 BaseDeviceIdentifier,
12 ButtplugDeviceConfigError,
13 ProtocolCommunicationSpecifier,
14 ServerDeviceDefinition,
15 ServerDeviceDefinitionBuilder,
16 UserDeviceIdentifier,
17};
18
19#[derive(Default, Clone)]
20pub struct DeviceConfigurationManagerBuilder {
21 base_communication_specifiers: HashMap<String, Vec<ProtocolCommunicationSpecifier>>,
22 user_communication_specifiers: DashMap<String, Vec<ProtocolCommunicationSpecifier>>,
23 base_device_definitions: HashMap<BaseDeviceIdentifier, ServerDeviceDefinition>,
24 user_device_definitions: DashMap<UserDeviceIdentifier, ServerDeviceDefinition>,
25}
26
27impl DeviceConfigurationManagerBuilder {
28 pub fn communication_specifier(
29 &mut self,
30 protocol_name: &str,
31 specifier: &[ProtocolCommunicationSpecifier],
32 ) -> &mut Self {
33 self
34 .base_communication_specifiers
35 .entry(protocol_name.to_owned())
36 .or_default()
37 .extend(specifier.iter().cloned());
38 self
39 }
40
41 pub fn base_device_definition(
42 &mut self,
43 identifier: &BaseDeviceIdentifier,
44 features: &ServerDeviceDefinition,
45 ) -> &mut Self {
46 self
47 .base_device_definitions
48 .insert(identifier.clone(), features.clone());
49 self
50 }
51
52 pub fn user_communication_specifier(
53 &mut self,
54 protocol_name: &str,
55 specifier: &[ProtocolCommunicationSpecifier],
56 ) -> &mut Self {
57 self
58 .user_communication_specifiers
59 .entry(protocol_name.to_owned())
60 .or_default()
61 .extend(specifier.iter().cloned());
62 self
63 }
64
65 pub fn user_device_definition(
66 &mut self,
67 identifier: &UserDeviceIdentifier,
68 device_definition: &ServerDeviceDefinition,
69 ) -> Result<&mut Self, ButtplugDeviceConfigError> {
70 if self
71 .base_device_definitions
72 .iter()
73 .any(|(_, x)| x.id() == device_definition.base_id().unwrap_or_default())
74 {
75 self
76 .user_device_definitions
77 .insert(identifier.clone(), device_definition.clone());
78 Ok(self)
79 } else {
80 error!(
81 "Cannot find protocol with base id {:?} for user id {}",
82 device_definition.base_id(),
83 device_definition.id()
84 );
85 Err(ButtplugDeviceConfigError::BaseIdNotFound(
86 device_definition.id(),
87 ))
88 }
89 }
90
91 pub fn finish(&mut self) -> Result<DeviceConfigurationManager, ButtplugDeviceError> {
92 // Build and validate the protocol attributes tree.
93 let mut attribute_tree_map = HashMap::new();
94
95 // Add all the defaults first, they won't have parent attributes.
96 for (ident, attr) in &self.base_device_definitions {
97 attribute_tree_map.insert(ident.clone(), attr.clone());
98 }
99
100 let user_attribute_tree_map = DashMap::new();
101 // Finally, add in user configurations, which will have an address.
102 for kv in &self.user_device_definitions {
103 user_attribute_tree_map.insert(kv.key().clone(), kv.value().clone());
104 }
105
106 Ok(DeviceConfigurationManager {
107 base_communication_specifiers: self.base_communication_specifiers.clone(),
108 user_communication_specifiers: self.user_communication_specifiers.clone(),
109 base_device_definitions: attribute_tree_map,
110 user_device_definitions: user_attribute_tree_map,
111 //protocol_map,
112 })
113 }
114}
115
116/// Correlates information about protocols and which devices they support.
117///
118/// The [DeviceConfigurationManager] handles stores information about which device protocols the
119/// library supports, as well as which devices can use those protocols. When a
120/// [DeviceCommunicationManager](crate::server::device::communication_manager) finds a device during scanning,
121/// device information is given to the [DeviceConfigurationManager] to decide whether Buttplug
122/// should try to connect to and communicate with the device.
123///
124/// Assuming the device is supported by the library, the [DeviceConfigurationManager] also stores
125/// information about what commands can be sent to the device (Vibrate, Rotate, etc...), and the
126/// parameters for those commands (number of power levels, stroke distances, etc...).
127#[derive(Getters)]
128#[getset(get = "pub(crate)")]
129pub struct DeviceConfigurationManager {
130 /// Communication specifiers from the base device config, mapped from protocol name to vector of
131 /// specifiers. Should not change/update during a session.
132 #[getset(get = "pub")]
133 base_communication_specifiers: HashMap<String, Vec<ProtocolCommunicationSpecifier>>,
134 /// Device definitions from the base device config. Should not change/update during a session.
135 base_device_definitions: HashMap<BaseDeviceIdentifier, ServerDeviceDefinition>,
136 /// Communication specifiers provided by the user, mapped from protocol name to vector of
137 /// specifiers. Loaded at session start, may change over life of session.
138 #[getset(get = "pub")]
139 user_communication_specifiers: DashMap<String, Vec<ProtocolCommunicationSpecifier>>,
140 /// Device definitions from the user device config. Loaded at session start, may change over life
141 /// of session.
142 #[getset(get = "pub")]
143 user_device_definitions: DashMap<UserDeviceIdentifier, ServerDeviceDefinition>,
144}
145
146impl Debug for DeviceConfigurationManager {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 f.debug_struct("DeviceConfigurationManager").finish()
149 }
150}
151
152impl Default for DeviceConfigurationManager {
153 fn default() -> Self {
154 // Unwrap allowed here because we assume our built in device config will
155 // always work. System won't pass tests or possibly even build otherwise.
156 DeviceConfigurationManagerBuilder::default()
157 .finish()
158 .expect("Default creation of a DCM should always work.")
159 }
160}
161
162impl DeviceConfigurationManager {
163 pub fn add_user_communication_specifier(
164 &self,
165 protocol: &str,
166 specifier: &ProtocolCommunicationSpecifier,
167 ) -> Result<(), ButtplugDeviceError> {
168 //self.protocol_map.contains_key(protocol);
169 self
170 .user_communication_specifiers
171 .entry(protocol.to_owned())
172 .or_default()
173 .push(specifier.clone());
174 Ok(())
175 }
176
177 pub fn remove_user_communication_specifier(
178 &self,
179 protocol: &str,
180 specifier: &ProtocolCommunicationSpecifier,
181 ) {
182 if let Some(mut specifiers) = self.user_communication_specifiers.get_mut(protocol) {
183 let specifier_vec = specifiers.value_mut();
184 *specifier_vec = specifier_vec
185 .iter()
186 .filter(|s| *specifier != **s)
187 .cloned()
188 .collect();
189 }
190 }
191
192 pub fn add_user_device_definition(
193 &self,
194 identifier: &UserDeviceIdentifier,
195 definition: &ServerDeviceDefinition,
196 ) {
197 // TODO we should actually check validity of the definition we're adding here, i.e. does it have
198 // a base id, is that ID in our base selections, etc...
199 self
200 .user_device_definitions
201 .insert(identifier.clone(), definition.clone());
202 }
203
204 pub fn remove_user_device_definition(&self, identifier: &UserDeviceIdentifier) {
205 self.user_device_definitions.remove(identifier);
206 }
207
208 pub fn address_allowed(&self, address: &str) -> bool {
209 // Make sure the device isn't on the deny list
210 if self
211 .user_device_definitions
212 .iter()
213 .any(|kv| kv.key().address() == address && kv.value().deny())
214 {
215 // If device is outright denied, deny
216 info!(
217 "Device {} denied by configuration, not connecting.",
218 address
219 );
220 false
221 } else if self
222 .user_device_definitions
223 .iter()
224 .any(|kv| kv.value().allow())
225 && !self
226 .user_device_definitions
227 .iter()
228 .any(|kv| kv.key().address() == address && kv.value().allow())
229 {
230 // If device is not on allow list and allow list isn't empty, deny
231 info!(
232 "Device {} not on allow list and allow list not empty, not connecting.",
233 address
234 );
235 false
236 } else {
237 true
238 }
239 }
240
241 fn device_index(&self, identifier: &UserDeviceIdentifier) -> u32 {
242 // See if we have a reserved or reusable device index here.
243 if let Some(config) = self.user_device_definitions.get(identifier) {
244 let index = config.index();
245 debug!("Found index {index} for device {identifier:?}");
246 return index;
247 }
248
249 let current_indexes: Vec<u32> = self
250 .user_device_definitions
251 .iter()
252 .map(|x| x.index())
253 .collect();
254
255 // Someone is gonna make a max device index in their config file just to fuck with me, therefore
256 // we don't do "max + 1", we fill in holes (lol) in sequences. To whomever has 4 billion sex toys:
257 // sorry your index finding for new devices is slow and takes 16GB of allocation every time we
258 // want to search the index space.
259
260 let mut index = 0;
261 while current_indexes.contains(&index) {
262 index += 1;
263 }
264 debug!("Generating and assigning index {index:?} for device {identifier:?}");
265 index
266 }
267
268 pub fn device_definition(
269 &self,
270 identifier: &UserDeviceIdentifier,
271 ) -> Option<ServerDeviceDefinition> {
272 let features = if let Some(definition) = self.user_device_definitions.get(identifier) {
273 debug!("User device config found for {:?}", identifier);
274 definition.clone()
275 } else if let Some(definition) = self.base_device_definitions.get(&BaseDeviceIdentifier::new(
276 identifier.protocol(),
277 identifier.identifier(),
278 )) {
279 debug!(
280 "Protocol + Identifier device config found for {:?}, creating new user device from configuration",
281 identifier
282 );
283 let mut builder = ServerDeviceDefinitionBuilder::from_base(definition, Uuid::new_v4(), true);
284 builder.index(self.device_index(identifier)).finish()
285 } else if let Some(definition) = self
286 .base_device_definitions
287 .get(&BaseDeviceIdentifier::new(identifier.protocol(), &None))
288 {
289 debug!(
290 "Protocol device config found for {:?}, creating new user device from protocol defaults",
291 identifier
292 );
293 let mut builder = ServerDeviceDefinitionBuilder::from_base(definition, Uuid::new_v4(), true);
294 builder.index(self.device_index(identifier)).finish()
295 } else {
296 return None;
297 };
298
299 // If this is a new device, it needs to be added to the user device definition map.
300 //
301 // Device definitions are looked up before we fully initialize a device, mostly for algorithm
302 // preparation. There is a very small chance we may save the device config then error out when
303 // we connect to the device, but we'll assume we may connect successfully later.
304 if self.user_device_definitions.get(identifier).is_none() {
305 self
306 .user_device_definitions
307 .insert(identifier.clone(), features.clone());
308 }
309
310 Some(features)
311 }
312}