Buttplug sex toy control library

fix: Fix message version changes between sessions causing errors

Completely recycle servers between connections. Only a problem in Engine.

Fixes #702

+48 -18
+1
crates/intiface_engine/src/backdoor_server.rs
··· 28 28 .name("Intiface Backdoor Server") 29 29 .finish() 30 30 .unwrap(), 31 + &None 31 32 ); 32 33 let (s_out, mut r_out) = mpsc::channel(255); 33 34 let (s_in, r_in) = mpsc::channel(255);
+33 -13
crates/intiface_engine/src/buttplug_server.rs
··· 1 1 use std::sync::Arc; 2 2 3 3 use crate::{ 4 - BackdoorServer, ButtplugRemoteServer, ButtplugServerConnectorError, EngineOptions, 5 - IntifaceEngineError, IntifaceError, 4 + remote_server::ButtplugRemoteServerEvent, BackdoorServer, ButtplugRemoteServer, ButtplugServerConnectorError, EngineOptions, IntifaceEngineError, IntifaceError 6 5 }; 7 - use buttplug_transport_websocket_tungstenite::{ 8 - ButtplugWebsocketClientTransport, 9 - ButtplugWebsocketServerTransportBuilder, 10 - }; 6 + use buttplug_server::{ 7 + ButtplugServerBuilder, 8 + connector::ButtplugRemoteServerConnector, 9 + device::{ServerDeviceManager, ServerDeviceManagerBuilder}, 10 + message::serializer::ButtplugServerJSONSerializer, 11 + }; 11 12 use buttplug_server_device_config::{DeviceConfigurationManager, load_protocol_configs}; 12 13 use buttplug_server_hwmgr_btleplug::BtlePlugCommunicationManagerBuilder; 13 14 use buttplug_server_hwmgr_lovense_connect::LovenseConnectServiceCommunicationManagerBuilder; 14 15 use buttplug_server_hwmgr_websocket::WebsocketServerDeviceCommunicationManagerBuilder; 15 - use buttplug_server::{ 16 - connector::ButtplugRemoteServerConnector, device::{ 17 - ServerDeviceManagerBuilder, 18 - }, message::serializer::ButtplugServerJSONSerializer, ButtplugServerBuilder 16 + use buttplug_transport_websocket_tungstenite::{ 17 + ButtplugWebsocketClientTransport, ButtplugWebsocketServerTransportBuilder, 19 18 }; 20 19 use once_cell::sync::OnceCell; 20 + use tokio::sync::broadcast::Sender; 21 21 // Device communication manager setup gets its own module because the includes and platform 22 22 // specifics are such a mess. 23 23 ··· 75 75 } 76 76 } 77 77 78 + pub async fn reset_buttplug_server( 79 + options: &EngineOptions, 80 + device_manager: &Arc<ServerDeviceManager>, 81 + sender: &Sender<ButtplugRemoteServerEvent> 82 + ) -> Result<ButtplugRemoteServer, IntifaceEngineError> { 83 + match ButtplugServerBuilder::with_shared_device_manager(device_manager.clone()) 84 + .name(options.server_name()) 85 + .max_ping_time(options.max_ping_time()) 86 + .finish() 87 + { 88 + Ok(server) => Ok(ButtplugRemoteServer::new(server, &Some(sender.clone()))), 89 + Err(e) => { 90 + error!("Error starting server: {:?}", e); 91 + return Err(IntifaceEngineError::ButtplugServerError(e)); 92 + } 93 + } 94 + } 95 + 78 96 pub async fn setup_buttplug_server( 79 97 options: &EngineOptions, 80 98 backdoor_server: &OnceCell<Arc<BackdoorServer>>, ··· 98 116 }; 99 117 100 118 setup_server_device_comm_managers(options, &mut dm_builder); 101 - 102 119 let mut server_builder = ButtplugServerBuilder::new( 103 120 dm_builder 104 121 .finish() 105 122 .map_err(|e| IntifaceEngineError::ButtplugServerError(e))?, 106 123 ); 124 + 107 125 server_builder 108 126 .name(options.server_name()) 109 127 .max_ping_time(options.max_ping_time()); ··· 124 142 .into(), 125 143 ) 126 144 } else { 127 - Ok(ButtplugRemoteServer::new(core_server)) 145 + Ok(ButtplugRemoteServer::new(core_server, &None)) 128 146 } 129 147 } 130 148 ··· 154 172 )) 155 173 .await 156 174 } else { 157 - panic!("Websocket port not set, cannot create transport. Please specify a websocket port in arguments."); 175 + panic!( 176 + "Websocket port not set, cannot create transport. Please specify a websocket port in arguments." 177 + ); 158 178 } 159 179 }
+5 -2
crates/intiface_engine/src/engine.rs
··· 1 1 use crate::{ 2 2 backdoor_server::BackdoorServer, 3 - buttplug_server::{run_server, setup_buttplug_server}, 3 + buttplug_server::{reset_buttplug_server, run_server, setup_buttplug_server}, 4 4 error::IntifaceEngineError, 5 5 frontend::{ 6 6 frontend_external_event_loop, frontend_server_event_loop, process_messages::EngineMessage, ··· 106 106 107 107 // Hang out until those listeners get sick of listening. 108 108 info!("Intiface CLI Setup finished, running server tasks until all joined."); 109 - let server = setup_buttplug_server(options, &self.backdoor_server, &dcm).await?; 109 + let mut server = setup_buttplug_server(options, &self.backdoor_server, &dcm).await?; 110 110 let dcm = server 111 111 .server() 112 112 .device_manager() ··· 193 193 info!("Breaking out of event loop in order to exit"); 194 194 break; 195 195 } 196 + // We're not exiting, rebuild our server. 197 + let dm = server.server().device_manager(); 198 + server = reset_buttplug_server(options, &dm, server.event_sender()).await?; 196 199 info!("Server connection dropped, restarting"); 197 200 } 198 201 info!("Shutting down server...");
+9 -3
crates/intiface_engine/src/remote_server.rs
··· 20 20 use serde::{Deserialize, Serialize}; 21 21 use std::sync::Arc; 22 22 use thiserror::Error; 23 - use tokio::sync::{broadcast, mpsc, Notify}; 23 + use tokio::sync::{broadcast::{self, Sender}, mpsc, Notify}; 24 24 25 25 // Clone derived here to satisfy tokio broadcast requirements. 26 26 #[derive(Clone, Debug, Serialize, Deserialize)] ··· 49 49 pub struct ButtplugRemoteServer { 50 50 #[getset(get = "pub")] 51 51 server: Arc<ButtplugServer>, 52 + #[getset(get = "pub")] 52 53 event_sender: broadcast::Sender<ButtplugRemoteServerEvent>, 53 54 disconnect_notifier: Arc<Notify>, 54 55 } ··· 210 211 ButtplugServerBuilder::default() 211 212 .finish() 212 213 .expect("Default is infallible"), 214 + &None 213 215 ) 214 216 } 215 217 } 216 218 217 219 impl ButtplugRemoteServer { 218 - pub fn new(server: ButtplugServer) -> Self { 219 - let (event_sender, _) = broadcast::channel(256); 220 + pub fn new(server: ButtplugServer, event_sender: &Option<Sender<ButtplugRemoteServerEvent>>) -> Self { 221 + let event_sender = if let Some(sender) = event_sender { 222 + sender.clone() 223 + } else { 224 + broadcast::channel(256).0 225 + }; 220 226 // Thanks to the existence of the backdoor server, device updates can happen for the lifetime to 221 227 // the RemoteServer instance, not just during client connect. We need to make sure these are 222 228 // emitted to the frontend.