Skip to main content

Connecting to a Buttplug Server

Once you've created a connector, it's time to connect to a server!

As all connector setup was done via the Connector setup, this is now just down to dealing with whether the connection process actually worked or not.

Network connections for websockets can fail due to usual connection issues (wrong address, server not up, network not on, etc...). There is also a chance that the client and server could have a version mismatch. We'll cover this in the next section.

use buttplug::{
client::{ButtplugClient, ButtplugClientError},
core::{
connector::{ButtplugRemoteClientConnector, ButtplugWebsocketClientTransport, new_json_ws_client_connector},
errors::ButtplugError,
message::serializer::ButtplugClientJSONSerializer,
},
};
use tokio::io::{self, AsyncBufReadExt, BufReader};

async fn wait_for_input() {
BufReader::new(io::stdin())
.lines()
.next_line()
.await
.unwrap();
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
// After you've created a connector, the connection looks the same no
// matter what, though the errors thrown may be different.
let connector = new_json_ws_client_connector("ws://127.0.0.1:12345");

// Now we connect. If anything goes wrong here, we'll get an Err with either
//
// - A ButtplugClientConnectionError if there's a problem with
// the Connector, like the network address being wrong, server not
// being up, etc.
// - A ButtplugHandshakeError if there is a client/server version
// mismatch.
let client = ButtplugClient::new("Example Client");
if let Err(e) = client.connect(connector).await {
match e {
ButtplugClientError::ButtplugConnectorError(error) => {
// If our connection failed, because the server wasn't turned on,
// SSL/TLS wasn't turned off, etc, we'll just print and exit
// here.
println!("Can't connect, exiting! Message: {}", error);
wait_for_input().await;
return Ok(());
}
ButtplugClientError::ButtplugError(error) => match error {
ButtplugError::ButtplugHandshakeError(error) => {
// This means our client is newer than our server, and we need to
// upgrade the server we're connecting to.
println!("Handshake issue, exiting! Message: {}", error);
wait_for_input().await;
return Ok(());
}
error => {
println!("Unexpected error type! {}", error);
wait_for_input().await;
return Ok(());
}
},
}
};

// We're connected, yay!
println!("Connected! Check Server for Client Name.");

wait_for_input().await;

// And now we disconnect as usual
client.disconnect().await?;

Ok(())
}

Client/Server Compatibility

tl;dr As long as the server API version is equal to or greater (newer) than the client API version, things should be fine.

To see the full explanation and rules on API versioning, see the protocol portion of the architecture section.

What to Expect on Successful Connect

In most cases, connectors are only used for the initial connection setup, then you can pretty much forget about them after that. Everything will look the same across all connector types from here on out.

Now that you know how to get a Buttplug session running, you're ready to enumerate and control devices!