protected virtual void ReceiveManagementLoop()
        {
            while (ManagementClient?.Connected ?? false)
            {
                Thread.Sleep(0);

                GhostNetFrame frame = new GhostNetFrame();
                try {
                    // Let's just hope that the reader always reads a full frame...
                    frame.Read(ManagementReader);
                } catch (Exception e) {
                    if (!(ManagementClient?.Connected ?? false))
                    {
                        Dispose();
                        return;
                    }

                    Logger.Log(LogLevel.Warn, "ghostnet-con", "Failed receiving management frame");
                    LogContext(LogLevel.Warn);
                    e.LogDetailed();
                    if (DisposeOnFailure)
                    {
                        Dispose();
                        return;
                    }
                }
                // Logger.Log(LogLevel.Verbose, "ghostnet-con", "Received management frame");
                ReceiveManagement(ManagementEndPoint, frame);
            }
            // Not connected - dispose.
            Dispose();
        }
        protected virtual void ReceiveUpdateLoop()
        {
            while (UpdateClient != null)
            {
                Thread.Sleep(0);

                IPEndPoint known  = UpdateEndPoint ?? ManagementEndPoint;
                IPEndPoint remote = known;
                byte[]     data   = null;
                try {
                    // Let's just hope that we always receive a full frame...
                    // Console.WriteLine("Starting receive update");
                    data = UpdateClient?.Receive(ref remote);
                    // Console.WriteLine($"Finished receive update from {remote}: {data.ToHexadecimalString()}");
                } catch (Exception e) {
                    Logger.Log(LogLevel.Warn, "ghostnet-con", "Failed receiving update frame");
                    LogContext(LogLevel.Warn);
                    e.LogDetailed();
                    if (DisposeOnFailure)
                    {
                        Dispose();
                        return;
                    }
                }
                if (known != null && !remote.Address.Equals(known.Address))
                {
                    Logger.Log(LogLevel.Warn, "ghostnet-con", $"Received update data from unknown remote {remote}: {data.ToHexadecimalString()}");
                    continue;
                }

                try {
                    using (MemoryStream bufferStream = new MemoryStream(data))
                        using (BinaryReader bufferReader = new BinaryReader(bufferStream)) {
                            GhostNetFrame frame = new GhostNetFrame();
                            frame.Read(bufferReader);
                            // Logger.Log(LogLevel.Verbose, "ghostnet-con", "Received update frame");
                            ReceiveUpdate(remote, frame);
                        }
                } catch (Exception e) {
                    Logger.Log(LogLevel.Warn, "ghostnet-con", "Failed parsing update frame");
                    LogContext(LogLevel.Warn);
                    e.LogDetailed();
                    Console.WriteLine("Data:");
                    Console.WriteLine(data.ToHexadecimalString());
                    // Don't dispose - maybe upcoming data isn't broken?
                }
            }
        }