Exemple #1
0
 public async Task <ButtplugMessage> SendMsg(ButtplugMessage aMsg)
 {
     return(await SendMessage(aMsg));
 }
 protected async Task <bool> SendMessageExpectOk(ButtplugMessage aMsg)
 {
     return(await SendMessage(aMsg) is Ok);
 }
        public string Serialize(ButtplugMessage aMsg)
        {
            ButtplugUtils.ArgumentNotNull(aMsg, nameof(aMsg));

            return(_parser.Serialize(aMsg, _clientSpecVersion));
        }
Exemple #4
0
 public async Task <ButtplugMessage> SendAsync(ButtplugMessage aMsg, CancellationToken aToken = default(CancellationToken))
 {
     return(await Server.SendMessageAsync(aMsg).ConfigureAwait(false));
 }
Exemple #5
0
        public async Task <ButtplugMessage> SendMessage(ButtplugMessage aMsg)
        {
            var id = aMsg.Id;

            switch (aMsg)
            {
            case StartScanning _:
                _bpLogger.Debug("Got StartScanning Message");
                StartScanning();
                return(new Ok(id));

            case StopScanning _:
                _bpLogger.Debug("Got StopScanning Message");
                StopScanning();
                return(new Ok(id));

            case StopAllDevices _:
                _bpLogger.Debug("Got StopAllDevices Message");
                var isOk     = true;
                var errorMsg = string.Empty;
                foreach (var d in _devices.ToList())
                {
                    if (!d.Value.IsConnected)
                    {
                        continue;
                    }

                    var r = await d.Value.ParseMessage(new StopDeviceCmd(d.Key, aMsg.Id));

                    if (r is Ok)
                    {
                        continue;
                    }

                    isOk      = false;
                    errorMsg += $"{(r as Error).ErrorMessage}; ";
                }

                if (isOk)
                {
                    return(new Ok(aMsg.Id));
                }

                return(new Error(errorMsg, Error.ErrorClass.ERROR_DEVICE, aMsg.Id));

            case RequestDeviceList _:
                _bpLogger.Debug("Got RequestDeviceList Message");
                var msgDevices = _devices.Where(aDevice => aDevice.Value.IsConnected)
                                 .Select(aDevice => new DeviceMessageInfo(
                                             aDevice.Key,
                                             aDevice.Value.Name,
                                             GetAllowedMessageTypesAsDictionary(aDevice.Value))).ToList();
                return(new DeviceList(msgDevices.ToArray(), id));

            // If it's a device message, it's most likely not ours.
            case ButtplugDeviceMessage m:
                _bpLogger.Trace($"Sending {aMsg.GetType().Name} to device index {m.DeviceIndex}");
                if (_devices.ContainsKey(m.DeviceIndex))
                {
                    return(await _devices[m.DeviceIndex].ParseMessage(m));
                }

                return(_bpLogger.LogErrorMsg(id, Error.ErrorClass.ERROR_DEVICE, $"Dropping message for unknown device index {m.DeviceIndex}"));
            }

            return(_bpLogger.LogErrorMsg(id, Error.ErrorClass.ERROR_MSG, $"Message type {aMsg.GetType().Name} unhandled by this server."));
        }
        public async Task <ButtplugMessage> SendMessageAsync([NotNull] ButtplugMessage aMsg, CancellationToken aToken = default(CancellationToken))
        {
            var combinedToken = CancellationTokenSource.CreateLinkedTokenSource(_internalToken.Token, aToken);

            _bpLogger.Trace($"Got Message {aMsg.Id} of type {aMsg.GetType().Name} to send");
            var id = aMsg.Id;

            ButtplugUtils.ArgumentNotNull(aMsg, nameof(aMsg));

            if (id == ButtplugConsts.SystemMsgId)
            {
                throw new ButtplugMessageException(_bpLogger, "Message Id 0 is reserved for outgoing system messages. Please use another Id.", id);
            }

            if (aMsg is IButtplugMessageOutgoingOnly)
            {
                throw new ButtplugMessageException(_bpLogger, $"Message of type {aMsg.GetType().Name} cannot be sent to server", id);
            }

            if (_pingTimedOut)
            {
                throw new ButtplugPingException(_bpLogger, "Ping timed out.", id);
            }

            // If we get a message that's not RequestServerInfo first, return an error.
            if (!_receivedRequestServerInfo && !(aMsg is RequestServerInfo))
            {
                throw new ButtplugHandshakeException(_bpLogger, "RequestServerInfo must be first message received by server!", id);
            }

            _bpLogger.Debug($"Got {aMsg.Name} message.");

            switch (aMsg)
            {
            case RequestLog m:
                BpLogManager.AddLogListener(m.LogLevel, LogMessageReceivedHandler);
                return(new Ok(id));

            case Ping _:
                // Start the timer
                _pingTimer?.Change((int)_maxPingTime, (int)_maxPingTime);

                return(new Ok(id));

            case RequestServerInfo rsi:
                if (_receivedRequestServerInfo)
                {
                    throw new ButtplugHandshakeException(_bpLogger, "Already received RequestServerInfo, cannot be sent twice.", id);
                }

                _receivedRequestServerInfo = true;
                _clientSpecVersion         = rsi.MessageVersion;
                _deviceManager.SpecVersion = _clientSpecVersion;

                // Start the timer
                _pingTimer?.Change((int)_maxPingTime, (int)_maxPingTime);
                _clientName = rsi.ClientName;
                ClientConnected?.Invoke(this, EventArgs.Empty);
                return(new ServerInfo(_serverName, ButtplugConsts.CurrentSpecVersion, _maxPingTime, id));

            case Core.Messages.Test m:
                return(new Core.Messages.Test(m.TestString, id));
            }

            return(await _deviceManager.SendMessageAsync(aMsg, combinedToken.Token).ConfigureAwait(false));
        }
 /// <summary>
 /// Converts a single <see cref="ButtplugMessage"/> into a JSON string.
 /// </summary>
 /// <param name="aMsg">Message to convert.</param>
 /// <returns>The JSON string representation of the message.</returns>
 public string Serialize(ButtplugMessage aMsg)
 {
     return(_parser.Serialize(aMsg, ButtplugConsts.CurrentSpecVersion));
 }
Exemple #8
0
        public async Task <ButtplugMessage> SendMessageAsync(ButtplugMessage aMsg, CancellationToken aToken = default(CancellationToken))
        {
            ButtplugUtils.ArgumentNotNull(aMsg, nameof(aMsg));
            var id = aMsg.Id;

            switch (aMsg)
            {
            case StartScanning _:
                _bpLogger.Debug("Got StartScanning Message");
                try
                {
                    await StartScanning();
                }
                catch (ButtplugDeviceException aEx)
                {
                    // Catch and rethrow here, adding the message Id onto the exception
                    throw new ButtplugDeviceException(_bpLogger, aEx.Message, id);
                }

                return(new Ok(id));

            case StopScanning _:
                _bpLogger.Debug("Got StopScanning Message");
                StopScanning();
                return(new Ok(id));

            case StopAllDevices _:
                _bpLogger.Debug("Got StopAllDevices Message");
                var isOk     = true;
                var errorMsg = string.Empty;
                foreach (var d in Devices.ToList())
                {
                    if (!d.Value.Connected)
                    {
                        continue;
                    }

                    try
                    {
                        await d.Value.ParseMessageAsync(new StopDeviceCmd(d.Key, aMsg.Id), aToken).ConfigureAwait(false);
                    }
                    catch (ButtplugDeviceException e)
                    {
                        isOk      = false;
                        errorMsg += $"{e.Message}; ";
                    }
                }

                if (isOk)
                {
                    return(new Ok(aMsg.Id));
                }

                throw new ButtplugDeviceException(_bpLogger, errorMsg, aMsg.Id);

            case RequestDeviceList _:
                _bpLogger.Debug("Got RequestDeviceList Message");
                var msgDevices = Devices.Where(aDevice => aDevice.Value.Connected)
                                 .Select(aDevice => new DeviceMessageInfo(
                                             aDevice.Key,
                                             aDevice.Value.Name,
                                             GetAllowedMessageTypesAsDictionary(aDevice.Value, SpecVersion))).ToList();
                return(new DeviceList(msgDevices.ToArray(), id));

            // If it's a device message, it's most likely not ours.
            case ButtplugDeviceMessage m:
                _bpLogger.Trace($"Sending {aMsg.GetType().Name} to device index {m.DeviceIndex}");
                if (!Devices.ContainsKey(m.DeviceIndex))
                {
                    throw new ButtplugDeviceException(_bpLogger,
                                                      $"Dropping message for unknown device index {m.DeviceIndex}", id);
                }

                return(await Devices[m.DeviceIndex].ParseMessageAsync(m, aToken).ConfigureAwait(false));
            }

            throw new ButtplugMessageException(_bpLogger, $"Message type {aMsg.GetType().Name} unhandled by this server.", id);
        }
Exemple #9
0
 public void SetMessageResponse <T>(ButtplugMessage aMsg)
     where T : ButtplugMessage
 {
     _messageResponse.Remove(typeof(T));
     _messageResponse.Add(typeof(T), aMsg);
 }
Exemple #10
0
 public void SendServerMessage(ButtplugMessage aMsg)
 {
     MessageReceived?.Invoke(this, new MessageReceivedEventArgs(aMsg));
 }
 public string Serialize(ButtplugMessage aMsg)
 {
     return(_parser.Serialize(aMsg));
 }
        private async Task ConnectionAccepter(string aPipeName, CancellationToken aToken)
        {
            while (!aToken.IsCancellationRequested)
            {
                var pipeServer = new NamedPipeServerStream(aPipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
                await pipeServer.WaitForConnectionAsync(aToken).ConfigureAwait(false);

                if (!pipeServer.IsConnected)
                {
                    continue;
                }

                var server = pipeServer;

                var buttplugServer = _serverFactory();

                void MsgReceived(object aObject, MessageReceivedEventArgs aEvent)
                {
                    var msg = buttplugServer.Serialize(aEvent.Message);

                    if (msg == null)
                    {
                        return;
                    }

                    try
                    {
                        if (server != null && server.IsConnected)
                        {
                            var output = Encoding.UTF8.GetBytes(msg);
                            server.WriteAsync(output, 0, output.Length, aToken);
                        }

                        var error = aEvent.Message as Error;
                        if (error != null && error.ErrorCode == Error.ErrorClass.ERROR_PING && server != null && server.IsConnected)
                        {
                            server.Close();
                        }
                    }
                    catch (WebSocketException e)
                    {
                        // Probably means we're replying to a message we received just before shutdown.
                        _logger.Error(e.Message, true);
                    }
                }

                buttplugServer.MessageReceived += MsgReceived;

                void ClientConnected(object aObject, EventArgs aUnused)
                {
                    ConnectionAccepted?.Invoke(this, new IPCConnectionEventArgs(buttplugServer.ClientName));
                }

                buttplugServer.ClientConnected += ClientConnected;

                try
                {
                    _connections.Enqueue(server);
                    while (!aToken.IsCancellationRequested && server.IsConnected)
                    {
                        var buffer = new byte[4096];
                        var msg    = string.Empty;
                        var len    = -1;
                        while (len < 0 || (len == buffer.Length && buffer[4095] != '\0'))
                        {
                            try
                            {
                                len = await server.ReadAsync(buffer, 0, buffer.Length, aToken).ConfigureAwait(false);

                                if (len > 0)
                                {
                                    msg += Encoding.UTF8.GetString(buffer, 0, len);
                                }
                            }
                            catch
                            {
                                // no-op?
                            }
                        }

                        if (msg.Length > 0)
                        {
                            ButtplugMessage[] respMsgs;
                            try
                            {
                                respMsgs = await buttplugServer.SendMessageAsync(msg).ConfigureAwait(false);
                            }
                            catch (ButtplugException e)
                            {
                                respMsgs = new ButtplugMessage[] { e.ButtplugErrorMessage };
                            }

                            var respMsg = buttplugServer.Serialize(respMsgs);
                            if (respMsg == null)
                            {
                                continue;
                            }

                            var output = Encoding.UTF8.GetBytes(respMsg);
                            await server.WriteAsync(output, 0, output.Length, aToken).ConfigureAwait(false);

                            foreach (var m in respMsgs)
                            {
                                if (m is Error && (m as Error).ErrorCode == Error.ErrorClass.ERROR_PING && server.IsConnected)
                                {
                                    server.Close();
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    _logger.Error(e.Message, true);
                    try
                    {
                        server.Close();
                    }
                    catch
                    {
                        // noop
                    }
                }
                finally
                {
                    buttplugServer.MessageReceived -= MsgReceived;
                    await buttplugServer.ShutdownAsync().ConfigureAwait(false);

                    buttplugServer = null;
                    _connections.TryDequeue(out var stashed);
                    while (stashed != server && _connections.Any())
                    {
                        _connections.Enqueue(stashed);
                        _connections.TryDequeue(out stashed);
                    }

                    server.Close();
                    server.Dispose();
                    server = null;
                    ConnectionClosed?.Invoke(this, new IPCConnectionEventArgs());
                }
            }
        }
Exemple #13
0
 protected string Serialize(ButtplugMessage aMsg)
 {
     return(_parser.Serialize(aMsg, ButtplugMessage.CurrentSchemaVersion));
 }
 protected string Serialize(ButtplugMessage aMsg)
 {
     return(_parser.Serialize(aMsg));
 }
Exemple #15
0
        public async Task RunServerSession()
        {
            try
            {
                var readTask  = _ws.ReadStringAsync(_linkedCancelSource.Token);
                var writeTask = _outgoingMessages.OutputAvailableAsync(_linkedCancelSource.Token);
                while (_ws.IsConnected && !_linkedCancelSource.IsCancellationRequested)
                {
                    var msgTasks = new Task[]
                    {
                        readTask,
                        writeTask,
                    };

                    var completedTaskIndex = Task.WaitAny(msgTasks);

                    if (completedTaskIndex == 0)
                    {
                        var incomingMsg = await((Task <string>)msgTasks[0]).ConfigureAwait(false);
                        if (incomingMsg != null)
                        {
                            ButtplugMessage[] msg;
                            try
                            {
                                msg = await _server.SendMessageAsync(incomingMsg).ConfigureAwait(false);
                            }
                            catch (ButtplugException ex)
                            {
                                msg = new ButtplugMessage[] { ex.ButtplugErrorMessage };
                            }
                            await QueueMessage(msg).ConfigureAwait(false);
                        }

                        readTask = _ws.ReadStringAsync(_linkedCancelSource.Token);
                    }
                    else
                    {
                        try
                        {
                            _outgoingMessages.TryReceiveAll(out var msgs);
                            var outMsgs = msgs.Aggregate(string.Empty, (current, msg) => current + msg);
                            if (_ws != null && _ws.IsConnected)
                            {
                                await _ws.WriteStringAsync(outMsgs, _linkedCancelSource.Token).ConfigureAwait(false);
                            }

                            writeTask = _outgoingMessages.OutputAvailableAsync(_linkedCancelSource.Token);
                        }
                        catch (WebSocketException e)
                        {
                            // Probably means we're replying to a message we received just before shutdown.
                            _logger.Error(e.Message, true);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                _logger.Error(e.Message, true);
            }
            finally
            {
                await ShutdownSession().ConfigureAwait(false);
            }
        }
Exemple #16
0
 public abstract void SetResult(ButtplugMessage result);
Exemple #17
0
 private void CheckValidTestMessage([NotNull] ButtplugMessage aMsg)
 {
     aMsg.Should().BeOfType <Messages.Test>();
     (aMsg as Messages.Test).TestString.Should().Be("Test");
 }