예제 #1
0
        public void TestToErrorMessage()
        {
            var msg = new Error("test1", Error.ErrorClass.ERROR_DEVICE, 2);
            var err = ButtplugException.FromError(msg);

            err.ButtplugErrorMessage.Should().BeEquivalentTo(msg);
        }
예제 #2
0
        /// <summary>
        /// Message Received event handler. Either tries to match incoming messages as replies to
        /// messages we've sent, or fires an event related to an incoming event, like device
        /// additions/removals, log messages, etc.
        /// </summary>
        /// <param name="aSender">Object sending the open event, unused.</param>
        /// <param name="aArgs">Event parameters, including the data received.</param>
        private async void MessageReceivedHandler(object aSender, MessageReceivedEventArgs aArgs)
        {
            var msg = aArgs.Message;

            switch (msg)
            {
            case Log l:
                Log?.Invoke(this, new LogEventArgs(l));
                break;

            case DeviceAdded d:
                var dev = new ButtplugClientDevice(_bpLogManager, this, SendDeviceMessageAsync, d);
                _devices.Add(d.DeviceIndex, dev);
                DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(dev));
                break;

            case DeviceRemoved d:
                if (!_devices.ContainsKey(d.DeviceIndex))
                {
                    ErrorReceived?.Invoke(this,
                                          new ButtplugExceptionEventArgs(
                                              new ButtplugDeviceException(_bpLogger,
                                                                          "Got device removed message for unknown device.",
                                                                          msg.Id)));
                    return;
                }

                var oldDev = _devices[d.DeviceIndex];
                _devices.Remove(d.DeviceIndex);
                DeviceRemoved?.Invoke(this, new DeviceRemovedEventArgs(oldDev));
                break;

            case ScanningFinished _:
                // The scanning finished event is self explanatory and doesn't require extra arguments.
                ScanningFinished?.Invoke(this, new EventArgs());
                break;

            case Error e:
                // This will both log the error and fire it from our ErrorReceived event handler.
                ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(ButtplugException.FromError(_bpLogger, e)));

                if (e.ErrorCode == Error.ErrorClass.ERROR_PING)
                {
                    PingTimeout?.Invoke(this, EventArgs.Empty);
                    await DisconnectAsync().ConfigureAwait(false);
                }

                break;

            default:
                ErrorReceived?.Invoke(this,
                                      new ButtplugExceptionEventArgs(
                                          new ButtplugMessageException(_bpLogger,
                                                                       $"Got unhandled message: {msg}",
                                                                       msg.Id)));
                break;
            }
        }
예제 #3
0
        public void HandleErrorInvoked(object aObj, ButtplugExceptionEventArgs aEx)
        {
            if (_errorInvoked)
            {
                Assert.Fail("Multiple errors thrown without resets.");
            }

            _errorInvoked     = true;
            _currentException = aEx.Exception;
        }
예제 #4
0
 public void TestFromError()
 {
     ButtplugException.FromError(new Error("test", Error.ErrorClass.ERROR_DEVICE, ButtplugConsts.SystemMsgId))
     .Should().BeOfType <ButtplugDeviceException>();
     ButtplugException.FromError(new Error("test", Error.ErrorClass.ERROR_UNKNOWN, ButtplugConsts.SystemMsgId))
     .Should().BeOfType <ButtplugException>();
     ButtplugException.FromError(new Error("test", Error.ErrorClass.ERROR_INIT, ButtplugConsts.SystemMsgId))
     .Should().BeOfType <ButtplugHandshakeException>();
     ButtplugException.FromError(new Error("test", Error.ErrorClass.ERROR_MSG, ButtplugConsts.SystemMsgId))
     .Should().BeOfType <ButtplugMessageException>();
     ButtplugException.FromError(new Error("test", Error.ErrorClass.ERROR_PING, ButtplugConsts.SystemMsgId))
     .Should().BeOfType <ButtplugPingException>();
 }
예제 #5
0
        /// <summary>
        /// Sends a message, expecting a response of message type <see cref="Ok"/>.
        /// </summary>
        /// <param name="aMsg">Message to send.</param>
        /// <param name="aToken">Cancellation token, for cancelling action externally if it is not yet finished.</param>
        /// <returns>True if successful.</returns>
        private async Task SendMessageExpectOk(ButtplugMessage aMsg, CancellationToken aToken = default(CancellationToken))
        {
            var msg = await SendMessageAsync(aMsg, aToken).ConfigureAwait(false);

            switch (msg)
            {
            case Ok _:
                return;

            case Error err:
                throw ButtplugException.FromError(_bpLogger, err);

            default:
                throw new ButtplugMessageException(_bpLogger, $"Message type {msg.Name} not handled by SendMessageExpectOk", msg.Id);
            }
        }
        public void CheckMessage(ButtplugMessage aMsg, IButtplugLog aLog = null)
        {
            // We'll never match a system message, those are server -> client only.
            if (aMsg.Id == 0)
            {
                throw new ButtplugMessageException(aLog, "Cannot sort message with System ID", aMsg.Id);
            }

            // If we haven't gotten a system message and we're not currently waiting for the message
            // id, throw.
            if (!_waitingMsgs.TryRemove(aMsg.Id, out var queued))
            {
                throw new ButtplugMessageException(aLog, "Message with non-matching ID received.", aMsg.Id);
            }

            if (aMsg is Error errMsg)
            {
                queued.SetException(ButtplugException.FromError(errMsg));
                return;
            }

            queued.SetResult(aMsg);
        }
예제 #7
0
        // ReSharper disable once UnusedMember.Global
        public async Task ConnectAsync(CancellationToken aToken = default(CancellationToken))
        {
            if (Connected)
            {
                throw new ButtplugHandshakeException(_bpLogger, "Client already connected to a server.");
            }

            _connector.MessageReceived += MessageReceivedHandler;
            await _connector.ConnectAsync(aToken).ConfigureAwait(false);

            var res = await SendMessageAsync(new RequestServerInfo(Name), aToken).ConfigureAwait(false);

            switch (res)
            {
            case ServerInfo si:
                if (si.MaxPingTime > 0)
                {
                    _pingTimer = new Timer(OnPingTimer, null, 0,
                                           Convert.ToInt32(Math.Round(((double)si.MaxPingTime) / 2, 0)));
                }

                if (si.MessageVersion < ButtplugConsts.CurrentSpecVersion)
                {
                    await DisconnectAsync().ConfigureAwait(false);

                    throw new ButtplugHandshakeException(_bpLogger,
                                                         $"B******g Server's schema version ({si.MessageVersion}) is less than the client's ({ButtplugConsts.CurrentSpecVersion}). A newer server is required.",
                                                         res.Id);
                }

                // Get full device list and populate internal list
                var resp = await SendMessageAsync(new RequestDeviceList()).ConfigureAwait(false);

                if (!(resp is DeviceList))
                {
                    await DisconnectAsync().ConfigureAwait(false);

                    if (resp is Error errResp)
                    {
                        throw ButtplugException.FromError(_bpLogger, errResp);
                    }

                    throw new ButtplugHandshakeException(_bpLogger,
                                                         "Received unknown response to DeviceList handshake query");
                }

                foreach (var d in (resp as DeviceList).Devices)
                {
                    if (_devices.ContainsKey(d.DeviceIndex))
                    {
                        continue;
                    }

                    var device = new ButtplugClientDevice(_bpLogManager, this, SendDeviceMessageAsync, d);
                    _devices[d.DeviceIndex] = device;
                    DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(device));
                }

                break;

            case Error e:
                await DisconnectAsync().ConfigureAwait(false);

                throw ButtplugException.FromError(_bpLogger, e);

            default:
                await DisconnectAsync().ConfigureAwait(false);

                throw new ButtplugHandshakeException(_bpLogger, $"Unrecognized message {res.Name} during handshake", res.Id);
            }
        }