Buttplug sex toy control library
1use buttplug_core::{
2 connector::transport::stream::ButtplugStreamTransport,
3 message::serializer::ButtplugSerializedMessage,
4 util::stream::convert_broadcast_receiver_to_stream,
5};
6use buttplug_server::{
7 ButtplugServerBuilder, connector::ButtplugRemoteServerConnector, device::ServerDeviceManager,
8 message::serializer::ButtplugServerJSONSerializer,
9};
10use std::sync::Arc;
11use tokio::sync::{
12 broadcast,
13 mpsc::{self, Sender},
14};
15use tokio_stream::Stream;
16
17use crate::ButtplugRemoteServer;
18
19// Allows direct access to the Device Manager of a running ButtplugServer. Bypasses requirements for
20// client handshake, ping, etc...
21pub struct BackdoorServer {
22 //server: ButtplugRemoteServer,
23 sender: Sender<ButtplugSerializedMessage>,
24 broadcaster: broadcast::Sender<String>,
25}
26
27impl BackdoorServer {
28 pub fn new(device_manager: Arc<ServerDeviceManager>) -> Self {
29 let server = ButtplugRemoteServer::new(
30 ButtplugServerBuilder::with_shared_device_manager(device_manager.clone())
31 .name("Intiface Backdoor Server")
32 .finish()
33 .unwrap(),
34 &None,
35 );
36 let (s_out, mut r_out) = mpsc::channel(255);
37 let (s_in, r_in) = mpsc::channel(255);
38 let (s_stream, _) = broadcast::channel(255);
39 tokio::spawn(async move {
40 if let Err(e) = server
41 .start(ButtplugRemoteServerConnector::<
42 _,
43 ButtplugServerJSONSerializer,
44 >::new(ButtplugStreamTransport::new(s_out, r_in)))
45 .await
46 {
47 // We can't do much if the server fails, but we *can* yell into the logs!
48 error!("Backdoor server error: {:?}", e);
49 }
50 });
51 let sender_clone = s_stream.clone();
52 tokio::spawn(async move {
53 while let Some(ButtplugSerializedMessage::Text(m)) = r_out.recv().await {
54 if sender_clone.receiver_count() == 0 {
55 continue;
56 }
57 if sender_clone.send(m).is_err() {
58 break;
59 }
60 }
61 });
62 Self {
63 sender: s_in,
64 broadcaster: s_stream,
65 }
66 }
67
68 pub fn event_stream(&self) -> impl Stream<Item = String> + '_ {
69 convert_broadcast_receiver_to_stream(self.broadcaster.subscribe())
70 }
71
72 pub async fn parse_message(&self, msg: &str) {
73 self
74 .sender
75 .send(ButtplugSerializedMessage::Text(msg.to_owned()))
76 .await
77 .unwrap();
78 }
79}