// Returns true if processing was successful
        protected virtual bool ProcessSinglePacket(ControlCommand.Command? requiredCommand = null)
        {
            // Alias EncryptedStream as ns for cleaner code
                Stream ns = EncryptedStream;

                byte[] commandBuffer = new byte[1];
                int commandBytesRead = 0;

                // Try reading the command byte
                try
                {
                    commandBytesRead = ns.Read(commandBuffer, 0, 1);
                } catch (Exception) {
                    return false;
                }

                // If we read a command byte
                if (commandBytesRead == 1)
                {
                    ControlCommand.Command packetCommand = (ControlCommand.Command)commandBuffer[0];
                    CommandResult cr = null;

                    // Handle incoming commands
                    switch (packetCommand)
                    {
                        case ControlCommand.Command.AvailableSettingsRequest:
                            cr = AvailableSettingsRequestCommand.Instance.HandleCommand(ns);

                            Dictionary<string, object> availableResponseParameters = new Dictionary<string, object>();
                            availableResponseParameters["availableSettings"] = OverlaySettings.GetValidOverlaySettings();
                            bool responseSent = AvailableSettingsResponseCommand.Instance.SendCommand(ns, availableResponseParameters);

                            break;

                        case ControlCommand.Command.AvailableSettingsResponse:
                            cr = AvailableSettingsResponseCommand.Instance.HandleCommand(ns);

                            if (cr.Success)
                                AvailableRemoteSettings = (List<AvailableOverlaySetting>) cr.Data["remoteSettings"];

                            break;

                        case ControlCommand.Command.DownloadSettingRequest:
                            cr = DownloadSettingRequestCommand.Instance.HandleCommand(ns);

                            if (cr.Success)
                            {
                                string settingPath = (string)cr.Data["settingPath"];

                                FileInfo overlaySettingFile = new FileInfo(Path.Combine(OverlaySettings.OverlaysBasePath.FullName, settingPath));
                                DirectoryInfo overlaySettingFolder = overlaySettingFile.Directory;

                                Dictionary<string, object> downloadResponseParameters = new Dictionary<string, object>();
                                downloadResponseParameters["fromDirectory"] = overlaySettingFolder;

                                DownloadSettingResponseCommand.Instance.SendCommand(ns, downloadResponseParameters);
                            }

                            break;

                        case ControlCommand.Command.DownloadSettingResponse:
                            cr = DownloadSettingResponseCommand.Instance.HandleCommand(ns);

                            if (cr.Success)
                            {
                                RaiseSettingsDownloaded((DirectoryInfo)cr.Data["savedDirectory"]);
                            }

                            break;

                        case ControlCommand.Command.OverlaySettingSelect:
                            cr = OverlaySettingSelectCommand.Instance.HandleCommand(ns);

                            if (cr.Success)
                            {
                                if ((bool) cr.Data["remote"])
                                {
                                    Dictionary<string, object> downloadParameters = new Dictionary<string, object>();
                                    downloadParameters["settingPath"] = cr.Data["selectedPath"];

                                    // Open when download completes
                                    SettingsDownloaded += new SettingsDownloadedHandler(SettingsDownloaded_OpenOnComplete);
                                    remoteSettingToDownload = new AvailableOverlaySetting() { Path = (string)cr.Data["selectedPath"], Local = !((bool)cr.Data["remote"]) };
                                    DownloadSettingRequestCommand.Instance.SendCommand(ns, downloadParameters);

                                } else {
                                    try
                                    {
                                        OverlaySettings.Instance.Load(new FileInfo(Path.Combine(OverlaySettings.OverlaysBasePath.FullName, (string)cr.Data["selectedPath"])));
                                    } catch (OverlayLoadingException ole) {
                                        MessageBox.Show(ole.Message);
                                        return false;
                                    }
                                    OverlaySettingLoadedCommand.Instance.SendCommand(ns);
                                }

                            }

                            break;

                        case ControlCommand.Command.OverlaySettingLoaded:
                            cr = OverlaySettingLoadedCommand.Instance.HandleCommand(ns);
                            break;

                        case ControlCommand.Command.UpdateVariable:

                            cr = UpdateVariableCommand.Instance.HandleCommand(ns);
                            if (cr.Success)
                            {
                                string variableName = (string)cr.Data["variableName"];
                                string variableValue = (string)cr.Data["variableValue"];

                                // Update our dictionary's value of variableName with variableValue
                                OverlaySettings.Instance.UpdateVariableFromNetwork(variableName, variableValue);
                            }

                            break;

                        case ControlCommand.Command.Close:

                            cr = CloseCommand.Instance.HandleCommand(ns);
                            if (cr.Success)
                                return false;

                            break;

                        // Unknown command
                        default:
                            return false;
                    }

                    if (!cr.Success)
                        return false;

                    // Mark packet processed if mutex is valid
                    if (ProcessedCommands.ContainsKey(packetCommand) && ProcessedCommands[packetCommand] != null)
                        ProcessedCommands[packetCommand].Set();

                    // If we processed a command that wasn't required, fail
                    if (requiredCommand.HasValue && ((ControlCommand.Command)commandBuffer[0]) != requiredCommand.Value)
                        return false;
                }

                return true;
        }
        protected void WaitForProcessedTracking(ControlCommand.Command c)
        {
            EventWaitHandle commandWaitHandle = ProcessedCommands[c];
                commandWaitHandle.WaitOne();
                commandWaitHandle.Close();

                ProcessedCommands.Remove(c);
        }
 protected void MarkForProcessedTracking(ControlCommand.Command c)
 {
     ProcessedCommands[c] = new ManualResetEvent(false);
 }