static async Task ConnectWebsocket()
 {
     // Creating a Websocket Connector is as easy as using the right
     // options object.
     var connector = new ButtplugWebsocketConnectorOptions(
         new Uri("ws://localhost:12345/b******g"));
     var client = new ButtplugClient("Example Client");
     await client.ConnectAsync(connector);
 }
Esempio n. 2
0
        private async void Connect()
        {
            connecting = true;
            var connector = new ButtplugWebsocketConnectorOptions(new Uri(IntifaceAddress));

            try
            {
                await client.ConnectAsync(connector);

                await client.StartScanningAsync();
            }
            catch (ButtplugConnectorException e)
            {
                Logger.Error(e, "Failed to connect to B******g :(");
            }
            finally
            {
                connecting = false;
            }

            connecting = false;
        }
        public async Task ConnectTask(string aAddress)
        {
            var client = new ButtplugClient("VaMSync");

            client.DeviceAdded      += OnDeviceAdded;
            client.DeviceRemoved    += OnDeviceRemoved;
            client.ServerDisconnect += OnDisconnect;
            client.ScanningFinished += OnScanningFinished;
            try
            {
                if (aAddress == null)
                {
                    await client.ConnectAsync(new ButtplugEmbeddedConnectorOptions());
                }
                else
                {
                    var connector = new ButtplugWebsocketConnectorOptions(new Uri(aAddress));
                    await client.ConnectAsync(connector);
                }

                _client = client;

                await Dispatcher.Invoke(async() =>
                {
                    ConnectedHandler?.Invoke(this, new EventArgs());
                    _connectStatus.Text = $"Connected{(aAddress == null ? ", restart VaMSync to disconnect." : " to Remote B******g Server")}";
                    OnScanningClick(null, null);
                    _scanningButton.IsEnabled = true;
                    _connectButton.Visibility = Visibility.Collapsed;
                    if (aAddress != null)
                    {
                        _disconnectButton.Visibility = Visibility.Visible;
                    }
                });
            }
            catch (ButtplugConnectorException ex)
            {
                Debug.WriteLine("Connection failed.");
                // If the exception was thrown after connect, make sure we disconnect.
                if (_client != null && _client.Connected)
                {
                    await _client.DisconnectAsync();

                    _client = null;
                }
                Dispatcher.Invoke(() =>
                {
                    _connectStatus.Text = $"Connection failed, please try again.";
                });
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Did something else fail? {ex})");
                // If the exception was thrown after connect, make sure we disconnect.
                if (_client != null && _client.Connected)
                {
                    await _client.DisconnectAsync();

                    _client = null;
                }
                Dispatcher.Invoke(() =>
                {
                    _connectStatus.Text = $"Connection failed, please try again.";
                });
            }
            finally
            {
                if (_client == null)
                {
                    Dispatcher.Invoke(() =>
                    {
                        _connectButton.IsEnabled = true;
                        _radioEmbedded.IsEnabled = true;
                        _radioRemote.IsEnabled   = true;
                    });
                }
            }
        }
        private async void Connect_Click(object sender, RoutedEventArgs e)
        {
            Connect.IsEnabled = false;

            if (_client != null)
            {
                try
                {
                    await _client.StopScanningAsync();
                }
                catch (Exception)
                {
                    // no-op: ignore failures, just stop if possible
                }

                await _client.DisconnectAsync();

                _client = null;

                var devs = Devices.Keys;
                foreach (var dev in devs)
                {
                    Devices.Remove(dev);
                }

                ButtplugConnType.IsEnabled = true;
                ButtplugConnType_SelectionChanged(this, null);
                Connect.Content   = "Connect";
                Connect.IsEnabled = true;
                Scan_Click(this, null);
                return;
            }

            try
            {
                switch (((ComboBoxItem)ButtplugConnType.SelectedValue).Content)
                {
                case "WebSocket":
                {
                    ButtplugTarget.IsEnabled   = false;
                    ButtplugConnType.IsEnabled = false;

                    ButtplugWebsocketConnectorOptions conn;
                    try
                    {
                        conn = new ButtplugWebsocketConnectorOptions(new Uri(ButtplugTarget.Text));
                    }
                    catch (UriFormatException e1)
                    {
                        MessageBox.Show($"Uri Error: {e1.Message}", "B******g Error", MessageBoxButton.OK,
                                        MessageBoxImage.Error);
                        Connect.IsEnabled        = true;
                        ButtplugTarget.IsEnabled = true;
                        ButtplugConnType_SelectionChanged(this, null);
                        return;
                    }

                    _client                   = new ButtplugClient("NogasmChart");
                    _client.DeviceAdded      += ClientOnDeviceAdded;
                    _client.DeviceRemoved    += ClientOnDeviceRemoved;
                    _client.ServerDisconnect += ClientOnServerDisconnect;
                    _client.ErrorReceived    += ClientOnErrorReceived;
                    _client.ScanningFinished += ClientOnScanFinished;
                    await _client.ConnectAsync(conn);

                    break;
                }

                case "Embedded":
                {
                    ButtplugTarget.IsEnabled   = false;
                    ButtplugConnType.IsEnabled = false;

                    ButtplugEmbeddedConnectorOptions conn = new ButtplugEmbeddedConnectorOptions();
                    conn.ServerName = "NogasmChart";

                    _client                   = new ButtplugClient("NogasmChart");
                    _client.DeviceAdded      += ClientOnDeviceAdded;
                    _client.DeviceRemoved    += ClientOnDeviceRemoved;
                    _client.ServerDisconnect += ClientOnServerDisconnect;
                    _client.ErrorReceived    += ClientOnErrorReceived;
                    _client.ScanningFinished += ClientOnScanFinished;
                    await _client.ConnectAsync(conn);

                    break;
                }

                default:
                    MessageBox.Show("Invalid Connection type!", "B******g Error", MessageBoxButton.OK,
                                    MessageBoxImage.Error);
                    Connect.IsEnabled = true;
                    return;
                }
            }
            catch (Exception e1)
            {
                MessageBox.Show($"Something went wrong: {e1.Message}", "B******g Error", MessageBoxButton.OK,
                                MessageBoxImage.Error);
                try
                {
                    if (_client != null)
                    {
                        await _client.DisconnectAsync();
                    }
                }
                catch (Exception)
                {
                    // no-op: cleanup only
                }

                _client = null;

                ButtplugConnType.IsEnabled = true;
                ButtplugConnType_SelectionChanged(this, null);
                Connect.Content   = "Connect";
                Connect.IsEnabled = true;
                Scan_Click(this, null);
                return;
            }

            Connect.Content   = "Disconnect";
            Connect.IsEnabled = true;

            try
            {
                Scan.IsEnabled = false;
                await _client.StartScanningAsync();

                Scan.Content   = "Stop Scanning";
                Scan.IsEnabled = true;
            }
            catch (Exception e1)
            {
                MessageBox.Show($"Something went wrong: {e1.Message}", "B******g Error", MessageBoxButton.OK,
                                MessageBoxImage.Warning);
            }
        }
Esempio n. 5
0
        static async Task AwaitExample()
        {
            // In CSharp, anything that will block is awaited. For instance, if
            // we're going to connect to a remote server, that might take some
            // time due to the network connection quality, or other issues. To
            // deal with that, we use async/await.
            //
            // For now, you can ignore the API calls here, since we're just
            // talking about how our API works in general. Setting up a
            // connection is discussed more in the Connecting section of this
            // document.
            var connector =
                new ButtplugWebsocketConnectorOptions(
                    new Uri("ws://localhost:12345/b******g"));
            var client =
                new ButtplugClient("Example Client");

            // As an example of events, we'll assume the server might send the
            // client notifications about new devices that it has found. The
            // client will let us know about this via events.
            client.DeviceAdded += OnDeviceAdded;

            // As an example response/reply messages, we'll use our Connect API.
            // Connecting to a server requires the client and server to send
            // information back and forth, so we'll await that while those
            // transfers happen. It is possible for these to be slow, depending
            // on if network is being used and other factors)
            //
            // If something goes wrong, we throw, which breaks out of the await.
            try
            {
                await client.ConnectAsync(connector);
            }
            catch (ButtplugConnectorException ex)
            {
                Console.WriteLine(
                    "Can't connect to B******g Server, exiting!" +
                    $"Message: {ex.InnerException.Message}");
            }
            catch (ButtplugHandshakeException ex)
            {
                Console.WriteLine(
                    "Handshake with B******g Server, exiting!" +
                    $"Message: {ex.InnerException.Message}");
            }

            // There's also no requirement that the tasks returned from these
            // methods be run immediately. Each method returns a task which will
            // not run until awaited, so we can store it off and run it later,
            // run it on the scheduler, etc...
            //
            // As a rule, if you don't want to worry about all of the async task
            // scheduling and what not, you can just use "await" on methods when
            // you call them and they'll block until return. This is the easiest
            // way to work sometimes.
            var startScanningTask = client.StartScanningAsync();

            try
            {
                await startScanningTask;
            }
            catch (ButtplugException ex)
            {
                Console.WriteLine(
                    $"Scanning failed: {ex.InnerException.Message}");
            }
        }
Esempio n. 6
0
        // Given a set of Client/Server options, creates a client that either
        // connects to a server process also started by us, or else to an external
        // server like Intiface Desktop.
        //
        // Throws if server is already running, or if server process fails to start
        // up, or if client fails to connect for some reason.
        public static async Task StartProcessAndCreateClient(ButtplugUnityClient client, ButtplugUnityOptions options)
        {
            if (options.OutputDebugMessages)
            {
                outputDebugMessages = true;
            }

            ButtplugUnityHelper.MaybeDebugLog($"Using connection type {options.ConnectorType}.");

            ButtplugUnityHelper.MaybeDebugLog("Bringing up B******g Server/Client");
            // If the server is already up, we can't start it again, but we also can't
            // hand back a client. Throw.
            if (ButtplugUnityHelper.serverProcess != null)
            {
                ButtplugUnityHelper.MaybeDebugLog("Server already running, throwing");
                throw new InvalidOperationException("Server already running.");
            }

            var websocketPort = options.WebsocketPort;

            // We want to start the CLI process without a window, and capture output
            // from stdout at the moment just to see if it's alive. Crude, but it
            // does the job of making sure we don't try to connect before the
            // process spins up. This will change to using the Intiface Protobuf
            // system in the future.
            if (options.ConnectorType == ButtplugUnityConnectorType.WebsocketServerProcess)
            {
                // If we aren't given a port to use, generate a random one.
                if (websocketPort == 0)
                {
                    var rand = new System.Random();
                    websocketPort = (ushort)rand.Next(10000, 60000);
                }
                ButtplugUnityHelper.MaybeDebugLog($"Setting websocket port to {websocketPort}");

                var processPath = Path.Combine(Application.streamingAssetsPath, "B******g", "IntifaceCLI.exe");
                var arguments   = $"--wsinsecureport {websocketPort} --pingtime {options.ServerPingTime}";
                if (options.AllowRawMessages)
                {
                    arguments += " --allowraw";
                }
                try
                {
                    // Create a new task that will resolve when the server comes up.
                    ButtplugUnityHelper.serverBringupTask = new TaskCompletionSource <bool>();

                    var serverProcess = new Process();
                    serverProcess.StartInfo.FileName = processPath;
                    // Don't open a window on starting, and make sure stdout is redirected
                    // so we can catch it for bringup status.
                    serverProcess.StartInfo.CreateNoWindow         = true;
                    serverProcess.StartInfo.RedirectStandardOutput = true;
                    serverProcess.StartInfo.UseShellExecute        = false;
                    serverProcess.StartInfo.Arguments = arguments;

                    ButtplugUnityHelper.MaybeDebugLog($"Starting task with arguments: {serverProcess.StartInfo.Arguments}");
                    serverProcess.Exited             += ButtplugUnityHelper.OnServerExit;
                    serverProcess.OutputDataReceived += ButtplugUnityHelper.OnServerStart;

                    ButtplugUnityHelper.serverProcess = serverProcess;
                    serverProcess.Start();
                    serverProcess.BeginOutputReadLine();
                    ButtplugUnityHelper.MaybeDebugLog("Waiting for task output");
                    // Wait to get something from the process
                    await ButtplugUnityHelper.serverBringupTask.Task;
                    ButtplugUnityHelper.MaybeDebugLog("Task output received, continuing");
                    // Reset our bringup task to null now that the process is either up or dead.
                    ButtplugUnityHelper.serverBringupTask = null;
                    if (ButtplugUnityHelper.serverProcess == null)
                    {
                        ButtplugUnityHelper.MaybeDebugLog("Process died before bringup finished.");
                        throw new ApplicationException("ButtplugUnityHelper: Intiface process exited or crashed while coming up.");
                    }
                }
                catch (Win32Exception processException)
                {
                    ButtplugUnityHelper.MaybeDebugLog("Got process exception. If this is IL2CPP, this is expected and Ok. Printing exception and retrying using kernel32 P/Invoke methods.");
                    ButtplugUnityHelper.MaybeDebugLog(processException.ToString());
                    // This might be a IL2CPP issue, in which case, try to launch the process using those bindings.
                    //
                    // The option here is to hide the window, so we'll flip the context from our option.
                    StartExternalProcess.Start(processPath + " " + arguments, ".", !options.OpenIL2CPPConsoleWindow);
                }
            }

            // For some reason, in Unity 2018/2019 IL2CPP, awaiting our connect call
            // causes copies internally that end up dropping our sorter, meaning we'll
            // never get our connection confirmation back. This work everywhere in
            // Mono, and is fixed in IL2CPP in Unity 2020.
            //
            // Why am I doing this work for free.
            //
            // Logic tests for "202", meaning this should work back through 2018/2019,
            // but will futureproof us until Unity 2030 (or until they change their
            // major versioning scheme again).

            ButtplugUnityHelper.MaybeDebugLog("Connecting client");
            if (options.ConnectorType == ButtplugUnityConnectorType.ExternalWebsocketServer || options.ConnectorType == ButtplugUnityConnectorType.WebsocketServerProcess)
            {
                var connector_options = new ButtplugWebsocketConnectorOptions(new Uri($"ws://{options.WebsocketAddress}:{websocketPort}/b******g"));
                if (Application.unityVersion.Contains("202"))
                {
                    await client.ConnectAsync(connector_options);
                }
                else
                {
                    client.ConnectAsync(connector_options);
                    await Task.Delay(3000);
                }
            }
            else
            {
                var connector_options = new ButtplugEmbeddedConnectorOptions();
                connector_options.AllowRawMessages = options.AllowRawMessages;
                connector_options.MaxPingTime      = options.ServerPingTime;
                if (Application.unityVersion.Contains("202"))
                {
                    await client.ConnectAsync(connector_options);
                }
                else
                {
                    client.ConnectAsync(connector_options);
                    await Task.Delay(3000);
                }
            }
            ButtplugUnityHelper.MaybeDebugLog("Connected client");
        }