Buttplug sex toy control library
1use std::sync::Arc;
2
3use crate::{
4 BackdoorServer, ButtplugRemoteServer, ButtplugServerConnectorError, EngineOptions,
5 IntifaceEngineError, IntifaceError, remote_server::ButtplugRemoteServerEvent,
6};
7use buttplug_server::{
8 ButtplugServer, ButtplugServerBuilder,
9 connector::ButtplugRemoteServerConnector,
10 device::{ServerDeviceManager, ServerDeviceManagerBuilder},
11 message::serializer::ButtplugServerJSONSerializer,
12};
13use buttplug_server_device_config::{DeviceConfigurationManager, load_protocol_configs};
14use buttplug_server_hwmgr_btleplug::BtlePlugCommunicationManagerBuilder;
15use buttplug_server_hwmgr_lovense_connect::LovenseConnectServiceCommunicationManagerBuilder;
16use buttplug_server_hwmgr_websocket::WebsocketServerDeviceCommunicationManagerBuilder;
17use buttplug_transport_websocket_tungstenite::{
18 ButtplugWebsocketClientTransport, ButtplugWebsocketServerTransportBuilder,
19};
20use once_cell::sync::OnceCell;
21use tokio::sync::broadcast::Sender;
22// Device communication manager setup gets its own module because the includes and platform
23// specifics are such a mess.
24
25pub fn setup_server_device_comm_managers(
26 args: &EngineOptions,
27 server_builder: &mut ServerDeviceManagerBuilder,
28) {
29 if args.use_bluetooth_le() {
30 info!("Including Bluetooth LE (btleplug) Device Comm Manager Support");
31 let mut command_manager_builder = BtlePlugCommunicationManagerBuilder::default();
32 #[cfg(target_os = "ios")]
33 command_manager_builder.requires_keepalive(true);
34 #[cfg(not(target_os = "ios"))]
35 command_manager_builder.requires_keepalive(false);
36 server_builder.comm_manager(command_manager_builder);
37 }
38 if args.use_lovense_connect() {
39 info!("Including Lovense Connect App Support");
40 server_builder.comm_manager(LovenseConnectServiceCommunicationManagerBuilder::default());
41 }
42 #[cfg(not(any(target_os = "android", target_os = "ios")))]
43 {
44 use buttplug_server_hwmgr_hid::HidCommunicationManagerBuilder;
45 use buttplug_server_hwmgr_lovense_dongle::LovenseHIDDongleCommunicationManagerBuilder;
46 use buttplug_server_hwmgr_serial::SerialPortCommunicationManagerBuilder;
47 if args.use_lovense_dongle_hid() {
48 info!("Including Lovense HID Dongle Support");
49 server_builder.comm_manager(LovenseHIDDongleCommunicationManagerBuilder::default());
50 }
51 if args.use_serial_port() {
52 info!("Including Serial Port Support");
53 server_builder.comm_manager(SerialPortCommunicationManagerBuilder::default());
54 }
55 if args.use_hid() {
56 info!("Including Hid Support");
57 server_builder.comm_manager(HidCommunicationManagerBuilder::default());
58 }
59 #[cfg(target_os = "windows")]
60 {
61 use buttplug_server_hwmgr_xinput::XInputDeviceCommunicationManagerBuilder;
62 if args.use_xinput() {
63 info!("Including XInput Gamepad Support");
64 server_builder.comm_manager(XInputDeviceCommunicationManagerBuilder::default());
65 }
66 }
67 }
68 if args.use_device_websocket_server() {
69 info!("Including Websocket Server Device Support");
70 let mut builder =
71 WebsocketServerDeviceCommunicationManagerBuilder::default().listen_on_all_interfaces(true);
72 if let Some(port) = args.device_websocket_server_port() {
73 builder = builder.server_port(port);
74 }
75 server_builder.comm_manager(builder);
76 }
77}
78
79pub async fn reset_buttplug_server(
80 options: &EngineOptions,
81 device_manager: &Arc<ServerDeviceManager>,
82 sender: &Sender<ButtplugRemoteServerEvent>,
83) -> Result<ButtplugRemoteServer, IntifaceEngineError> {
84 match ButtplugServerBuilder::with_shared_device_manager(device_manager.clone())
85 .name(options.server_name())
86 .max_ping_time(options.max_ping_time())
87 .finish()
88 {
89 Ok(server) => Ok(ButtplugRemoteServer::new(server, &Some(sender.clone()))),
90 Err(e) => {
91 error!("Error starting server: {:?}", e);
92 Err(IntifaceEngineError::ButtplugServerError(e))
93 }
94 }
95}
96
97pub async fn setup_buttplug_server(
98 options: &EngineOptions,
99 backdoor_server: &OnceCell<Arc<BackdoorServer>>,
100 dcm: &Option<Arc<DeviceConfigurationManager>>,
101) -> Result<ButtplugServer, IntifaceEngineError> {
102 let mut dm_builder = if let Some(dcm) = dcm {
103 ServerDeviceManagerBuilder::new_with_arc(dcm.clone())
104 } else {
105 let mut dcm_builder = load_protocol_configs(
106 options.device_config_json(),
107 options.user_device_config_json(),
108 false,
109 )
110 .map_err(|e| IntifaceEngineError::ButtplugError(e.into()))?;
111
112 ServerDeviceManagerBuilder::new(
113 dcm_builder
114 .finish()
115 .map_err(|e| IntifaceEngineError::ButtplugError(e.into()))?,
116 )
117 };
118
119 setup_server_device_comm_managers(options, &mut dm_builder);
120 let mut server_builder = ButtplugServerBuilder::new(
121 dm_builder
122 .finish()
123 .map_err(IntifaceEngineError::ButtplugServerError)?,
124 );
125
126 server_builder
127 .name(options.server_name())
128 .max_ping_time(options.max_ping_time());
129
130 let core_server = match server_builder.finish() {
131 Ok(server) => server,
132 Err(e) => {
133 error!("Error starting server: {:?}", e);
134 return Err(IntifaceEngineError::ButtplugServerError(e));
135 }
136 };
137 if backdoor_server
138 .set(Arc::new(BackdoorServer::new(core_server.device_manager())))
139 .is_err()
140 {
141 Err(
142 IntifaceError::new("BackdoorServer already initialized somehow! This should never happen!")
143 .into(),
144 )
145 } else {
146 Ok(core_server)
147 }
148}
149
150pub async fn run_server(
151 server: &ButtplugRemoteServer,
152 options: &EngineOptions,
153) -> Result<(), ButtplugServerConnectorError> {
154 if let Some(port) = options.websocket_port() {
155 server
156 .start(ButtplugRemoteServerConnector::<
157 _,
158 ButtplugServerJSONSerializer,
159 >::new(
160 ButtplugWebsocketServerTransportBuilder::default()
161 .port(port)
162 .listen_on_all_interfaces(options.websocket_use_all_interfaces())
163 .finish(),
164 ))
165 .await
166 } else if let Some(addr) = options.websocket_client_address() {
167 server
168 .start(ButtplugRemoteServerConnector::<
169 _,
170 ButtplugServerJSONSerializer,
171 >::new(
172 ButtplugWebsocketClientTransport::new_insecure_connector(addr),
173 ))
174 .await
175 } else {
176 panic!(
177 "Websocket port not set, cannot create transport. Please specify a websocket port in arguments."
178 );
179 }
180}