Beispiel #1
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;
            }
        }
Beispiel #2
0
        private DeadPeerDetectorEntry CreateEntry(PeerDescriptor descriptor)
        {
            var entry = new DeadPeerDetectorEntry(descriptor, _configuration, _bus, TaskScheduler);

            entry.PeerTimeoutDetected    += OnPeerTimeout;
            entry.PeerRespondingDetected += OnPeerResponding;
            entry.PingTimeout            += (detectorEntry, time) => PingTimeout?.Invoke(detectorEntry.Descriptor.PeerId, time);

            return(entry);
        }
Beispiel #3
0
        public void OnTimeout(PingTimeout timeout)
        {
            ConsoleDisplay.Timeout(timeout.SequenceNumber);

            if (Attributes.BeepMode == 1)
            {
                try { Console.Beep(); }
                catch (Exception) { }
            }
        }
Beispiel #4
0
 public static void SaveSetting()
 {
     reader.SetNodeText("PingTimeout", PingTimeout.ToString());
     reader.SetNodeText("RequestTimeout", RequestTimeout.ToString());
     reader.SetNodeText("TcpPort", TcpPort.ToString());
     reader.SetNodeText("UdpPort", UdpPort.ToString());
     reader.SetNodeText("ClientPort", ClientPort.ToString());
     reader.SetNodeText("Adapter", Adapter);
     reader.SetNodeText("PlayerID", PlayerID);
     reader.SetNodeText("DataMode", dataMode);
     reader.SetNodeText("SyncMode", syncMode);
     reader.Save("setting.xml");
 }
Beispiel #5
0
        private async void PingTimeoutHandler([NotNull] object aObj)
        {
            // Stop the timer by specifying an infinite due period (See: https://msdn.microsoft.com/en-us/library/yz1c7148(v=vs.110).aspx)
            _pingTimer?.Change(Timeout.Infinite, (int)_maxPingTime);

            // Since this happens in an event handler, output a message, not an exception
            // TODO Once server has ErrorReceived event handlers, change this to throwing an exception through that.
            MessageReceived?.Invoke(this, new MessageReceivedEventArgs(new Error("Ping timed out.",
                                                                                 Error.ErrorClass.ERROR_PING, ButtplugConsts.SystemMsgId)));
            await SendMessageAsync(new StopAllDevices()).ConfigureAwait(false);

            _pingTimedOut = true;
            PingTimeout?.Invoke(this, new EventArgs());
            _clientName = null;
        }
Beispiel #6
0
 protected bool Equals(RequestData other) =>
 RequestTimeout.Equals(other.RequestTimeout) &&
 PingTimeout.Equals(other.PingTimeout) &&
 KeepAliveTime == other.KeepAliveTime &&
 KeepAliveInterval == other.KeepAliveInterval &&
 Pipelined == other.Pipelined &&
 HttpCompression == other.HttpCompression &&
 Equals(Headers, other.Headers) &&
 string.Equals(ProxyAddress, other.ProxyAddress) &&
 string.Equals(ProxyUsername, other.ProxyUsername) &&
 string.Equals(ProxyPassword, other.ProxyPassword) &&
 DisableAutomaticProxyDetection == other.DisableAutomaticProxyDetection &&
 Equals(BasicAuthorizationCredentials, other.BasicAuthorizationCredentials) &&
 Equals(ConnectionSettings, other.ConnectionSettings) &&
 Equals(MemoryStreamFactory, other.MemoryStreamFactory);
Beispiel #7
0
        public void Ping(DateTime timestampUtc)
        {
            lock (_lock)
            {
                if (_oldestUnansweredPingTimeUtc == null)
                {
                    _oldestUnansweredPingTimeUtc = timestampUtc;
                }
                var elapsedTimeSinceFirstPing = SystemDateTime.UtcNow - _oldestUnansweredPingTimeUtc;
                if (elapsedTimeSinceFirstPing > _configuration.PeerPingInterval)
                {
                    PingTimeout?.Invoke(this, timestampUtc);
                }
            }

            SendPingCommand(timestampUtc);
        }
Beispiel #8
0
 public override int GetHashCode()
 {
     unchecked
     {
         var hashCode = RequestTimeout.GetHashCode();
         hashCode = (hashCode * 397) ^ PingTimeout.GetHashCode();
         hashCode = (hashCode * 397) ^ KeepAliveTime;
         hashCode = (hashCode * 397) ^ KeepAliveInterval;
         hashCode = (hashCode * 397) ^ Pipelined.GetHashCode();
         hashCode = (hashCode * 397) ^ HttpCompression.GetHashCode();
         hashCode = (hashCode * 397) ^ (Headers?.GetHashCode() ?? 0);
         hashCode = (hashCode * 397) ^ (ProxyAddress?.GetHashCode() ?? 0);
         hashCode = (hashCode * 397) ^ (ProxyUsername?.GetHashCode() ?? 0);
         hashCode = (hashCode * 397) ^ (ProxyPassword?.GetHashCode() ?? 0);
         hashCode = (hashCode * 397) ^ DisableAutomaticProxyDetection.GetHashCode();
         hashCode = (hashCode * 397) ^ (BasicAuthorizationCredentials?.GetHashCode() ?? 0);
         hashCode = (hashCode * 397) ^ (ConnectionSettings?.GetHashCode() ?? 0);
         hashCode = (hashCode * 397) ^ (MemoryStreamFactory?.GetHashCode() ?? 0);
         return(hashCode);
     }
 }
Beispiel #9
0
        public void SorterCallback(UIntPtr buf, int buf_length)
        {
            Span <byte> byteArray;

            unsafe
            {
                byteArray = new Span <byte>(buf.ToPointer(), buf_length);
            }
            var server_message = ButtplugFFIServerMessage.Parser.ParseFrom(byteArray.ToArray());

            if (server_message.Id > 0)
            {
                _messageSorter.CheckMessage(server_message);
            }
            else if (server_message.Message.MsgCase == ButtplugFFIServerMessage.Types.FFIMessage.MsgOneofCase.ServerMessage)
            {
                if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceAdded)
                {
                    var device_added_message = server_message.Message.ServerMessage.DeviceAdded;
                    var device_handle        = ButtplugFFI.SendCreateDevice(_clientHandle, device_added_message.Index);
                    var attribute_dict       = new Dictionary <ServerMessage.Types.MessageAttributeType, ButtplugMessageAttributes>();
                    for (var i = 0; i < device_added_message.MessageAttributes.Count; ++i)
                    {
                        var attributes = device_added_message.MessageAttributes[i];
                        var device_message_attributes = new ButtplugMessageAttributes(attributes.FeatureCount, attributes.StepCount.ToArray(),
                                                                                      attributes.Endpoints.ToArray(), attributes.MaxDuration.ToArray(), null, null);
                        attribute_dict.Add(attributes.MessageType, device_message_attributes);
                    }
                    var device = new ButtplugClientDevice(_messageSorter, device_handle, device_added_message.Index, device_added_message.Name, attribute_dict);
                    _devices.Add(device_added_message.Index, device);
                    DeviceAdded.Invoke(this, new DeviceAddedEventArgs(device));
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceRemoved)
                {
                    var device_removed_message = server_message.Message.ServerMessage.DeviceRemoved;
                    var device = _devices[device_removed_message.Index];
                    _devices.Remove(device_removed_message.Index);
                    DeviceRemoved.Invoke(this, new DeviceRemovedEventArgs(device));
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Disconnect)
                {
                    Connected = false;
                    ServerDisconnect?.Invoke(this, null);
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Error)
                {
                    var errorMsg = server_message.Message.ServerMessage.Error;
                    var error    = ButtplugException.FromError(errorMsg);
                    if (error is ButtplugPingException)
                    {
                        PingTimeout?.Invoke(this, null);
                    }
                    ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(error));
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.ScanningFinished)
                {
                    ScanningFinished?.Invoke(this, null);
                }
                else
                {
                    // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
                }
            }
            else
            {
                // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
            }
        }
        protected void SorterCallbackHandler(IntPtr buf, int buf_length)
        {
            // Process the data BEFORE we throw to the C# executor, otherwise
            // Rust will clean up the memory and we'll have nothing to read
            // from, meaning a null message at best and a crash at worst.
            Span <byte> byteArray;

            unsafe
            {
                byteArray = new Span <byte>(buf.ToPointer(), buf_length);
            }
            var server_message = ButtplugFFIServerMessage.Parser.ParseFrom(byteArray.ToArray());

            // Run the response in the context of the C# executor, not the Rust
            // thread. This means that if something goes wrong we at least
            // aren't blocking a rust executor thread.
            Task.Run(() =>
            {
                if (server_message.Id > 0)
                {
                    _messageSorter.CheckMessage(server_message);
                }
                else if (server_message.Message.MsgCase == ButtplugFFIServerMessage.Types.FFIMessage.MsgOneofCase.ServerMessage)
                {
                    if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceAdded)
                    {
                        var device_added_message = server_message.Message.ServerMessage.DeviceAdded;
                        if (_devices.ContainsKey(device_added_message.Index))
                        {
                            ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugDeviceException("A duplicate device index was received. This is most likely a bug, please file at https://github.com/buttplugio/b******g-rs-ffi")));
                            return;
                        }
                        var device_handle  = ButtplugFFI.SendCreateDevice(_clientHandle, device_added_message.Index);
                        var attribute_dict = new Dictionary <ServerMessage.Types.MessageAttributeType, ButtplugMessageAttributes>();
                        for (var i = 0; i < device_added_message.MessageAttributes.Count; ++i)
                        {
                            var attributes = device_added_message.MessageAttributes[i];
                            var device_message_attributes = new ButtplugMessageAttributes(attributes.FeatureCount, attributes.StepCount.ToArray(),
                                                                                          attributes.Endpoints.ToArray(), attributes.MaxDuration.ToArray(), null, null);
                            attribute_dict.Add(attributes.MessageType, device_message_attributes);
                        }
                        var device = new ButtplugClientDevice(_messageSorter, device_handle, device_added_message.Index, device_added_message.Name, attribute_dict, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
                        _devices.Add(device_added_message.Index, device);
                        DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(device));
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceRemoved)
                    {
                        var device_removed_message = server_message.Message.ServerMessage.DeviceRemoved;
                        if (!_devices.ContainsKey(device_removed_message.Index))
                        {
                            // Device was removed from our dict before we could remove it ourselves.
                            return;
                        }
                        try
                        {
                            var device = _devices[device_removed_message.Index];
                            _devices.Remove(device_removed_message.Index);
                            DeviceRemoved?.Invoke(this, new DeviceRemovedEventArgs(device));
                        }
                        catch (KeyNotFoundException)
                        {
                            ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugDeviceException($"Cannot remove device index {device_removed_message.Index}, device not found.")));
                        }
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Disconnect)
                    {
                        Connected = false;
                        _devices.Clear();
                        ServerDisconnect?.Invoke(this, null);
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Error)
                    {
                        var errorMsg = server_message.Message.ServerMessage.Error;
                        var error    = ButtplugException.FromError(errorMsg);
                        if (error is ButtplugPingException)
                        {
                            PingTimeout?.Invoke(this, null);
                        }
                        ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(error));
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.ScanningFinished)
                    {
                        IsScanning = false;
                        ScanningFinished?.Invoke(this, null);
                    }
                    else
                    {
                        // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
                    }
                }
                else
                {
                    // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
                }
            });
        }