Skip to main content

intiface_engine/
backdoor_server.rs

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