Buttplug sex toy control library

chore: Fix keepalive shutdown on device disconnect

Fixes #733

+33 -21
+1
crates/buttplug_server/src/device/mod.rs
··· 102 102 mod server_device_manager; 103 103 mod server_device_manager_event_loop; 104 104 105 + pub use protocol_impl::get_default_protocol_map; 105 106 pub use server_device::{ServerDevice, ServerDeviceEvent}; 106 107 pub use server_device_manager::{ServerDeviceManager, ServerDeviceManagerBuilder};
+32 -21
crates/buttplug_server/src/device/server_device.rs
··· 44 44 }; 45 45 46 46 use buttplug_core::{ 47 + ButtplugResultFuture, 47 48 errors::{ButtplugDeviceError, ButtplugError}, 48 49 message::{ 49 - self, 50 - ButtplugServerMessageV4, 51 - DeviceFeature, 52 - DeviceMessageInfoV4, 53 - InputCommandType, 54 - InputType, 55 - OutputRotateWithDirection, 56 - OutputType, 57 - OutputValue, 50 + self, ButtplugServerMessageV4, DeviceFeature, DeviceMessageInfoV4, InputCommandType, InputType, 51 + OutputRotateWithDirection, OutputType, OutputValue, 58 52 }, 59 53 util::{self, async_manager, stream::convert_broadcast_receiver_to_stream}, 60 - ButtplugResultFuture, 61 54 }; 62 55 use buttplug_server_device_config::{ 63 - DeviceConfigurationManager, 64 - DeviceDefinition, 65 - UserDeviceIdentifier, 56 + DeviceConfigurationManager, DeviceDefinition, UserDeviceIdentifier, 66 57 }; 67 58 68 59 use crate::{ 60 + ButtplugServerResultFuture, 69 61 device::{ 70 62 hardware::{Hardware, HardwareCommand, HardwareConnector, HardwareEvent}, 71 63 protocol::{ProtocolHandler, ProtocolKeepaliveStrategy, ProtocolSpecializer}, 72 64 }, 73 65 message::{ 74 - checked_input_cmd::CheckedInputCmdV4, 75 - checked_output_cmd::CheckedOutputCmdV4, 76 - server_device_attributes::ServerDeviceAttributes, 66 + ButtplugServerDeviceMessage, checked_input_cmd::CheckedInputCmdV4, 67 + checked_output_cmd::CheckedOutputCmdV4, server_device_attributes::ServerDeviceAttributes, 77 68 spec_enums::ButtplugDeviceCommandMessageUnionV4, 78 - ButtplugServerDeviceMessage, 79 69 }, 80 - ButtplugServerResultFuture, 81 70 }; 82 71 use core::hash::{Hash, Hasher}; 83 72 use dashmap::DashMap; ··· 86 75 use tokio::{ 87 76 select, 88 77 sync::{ 89 - mpsc::{channel, Sender}, 90 78 Mutex, 79 + mpsc::{Sender, channel}, 91 80 }, 92 81 time::Instant, 93 82 }; ··· 133 122 } 134 123 } 135 124 136 - impl Eq for ServerDevice { 137 - } 125 + impl Eq for ServerDevice {} 138 126 139 127 impl PartialEq for ServerDevice { 140 128 fn eq(&self, other: &Self) -> bool { ··· 259 247 None 260 248 }; 261 249 async_manager::spawn(async move { 250 + let mut hardware_events = hardware.event_stream(); 262 251 let keepalive_packet = Mutex::new(None); 263 252 // TODO This needs to throw system error messages 264 253 let send_hw_cmd = async |command| { ··· 287 276 }; 288 277 }; 289 278 select! { 279 + hw_event = hardware_events.recv() => { 280 + if let Ok(hw_event) = hw_event { 281 + if matches!(hw_event, HardwareEvent::Disconnected(_)) { 282 + info!("Hardware disconnected, shutting down keepalive"); 283 + return; 284 + } 285 + } else { 286 + info!("Hardware disconnected, shutting down keepalive"); 287 + return; 288 + } 289 + } 290 290 msg = internal_hw_msg_recv.recv() => { 291 291 if msg.is_none() { 292 292 info!("No longer receiving message from device parent, breaking"); ··· 313 313 let sleep_until = Instant::now() + *device_wait_duration.as_ref().unwrap(); 314 314 loop { 315 315 select! { 316 + hw_event = hardware_events.recv() => { 317 + if let Ok(hw_event) = hw_event { 318 + if matches!(hw_event, HardwareEvent::Disconnected(_)) { 319 + info!("Hardware disconnected, shutting down keepalive"); 320 + return; 321 + } 322 + } else { 323 + info!("Hardware disconnected, shutting down keepalive"); 324 + return; 325 + } 326 + } 316 327 msg = internal_hw_msg_recv.recv() => { 317 328 if msg.is_none() { 318 329 info!("No longer receiving message from device parent, breaking");