Exemplo n.º 1
0
        private async Task <Message> RunLoop(CancellationToken ct)
        {
            TaskUtilities.AssertIsOnBackgroundThread();

            try {
                _log.EnterRLoop(_rLoopDepth++);
                while (!ct.IsCancellationRequested)
                {
                    var message = await ReceiveMessageAsync(ct);

                    if (message == null)
                    {
                        return(null);
                    }
                    else if (message.IsResponse)
                    {
                        Request request;
                        if (!_requests.TryRemove(message.RequestId, out request))
                        {
                            throw ProtocolError($"Mismatched response - no request with such ID:", message);
                        }
                        else if (message.Name != ":" + request.MessageName.Substring(1))
                        {
                            throw ProtocolError($"Mismatched response - message name does not match request '{request.MessageName}':", message);
                        }

                        request.Handle(this, message);
                        continue;
                    }

                    try {
                        switch (message.Name)
                        {
                        case "!End":
                            message.ExpectArguments(1);
                            await _callbacks.Shutdown(message.GetBoolean(0, "rdataSaved"));

                            break;

                        case "!CanceledAll":
                            CancelAll();
                            break;

                        case "?YesNoCancel":
                            ShowDialog(message, MessageButtons.YesNoCancel, CancellationTokenSource.CreateLinkedTokenSource(ct, _cancelAllCts.Token).Token)
                            .SilenceException <MessageTransportException>()
                            .DoNotWait();
                            break;

                        case "?YesNo":
                            ShowDialog(message, MessageButtons.YesNo, CancellationTokenSource.CreateLinkedTokenSource(ct, _cancelAllCts.Token).Token)
                            .SilenceException <MessageTransportException>()
                            .DoNotWait();
                            break;

                        case "?OkCancel":
                            ShowDialog(message, MessageButtons.OKCancel, CancellationTokenSource.CreateLinkedTokenSource(ct, _cancelAllCts.Token).Token)
                            .SilenceException <MessageTransportException>()
                            .DoNotWait();
                            break;

                        case "?>":
                            ReadConsole(message, CancellationTokenSource.CreateLinkedTokenSource(ct, _cancelAllCts.Token).Token)
                            .SilenceException <MessageTransportException>()
                            .DoNotWait();
                            break;

                        case "!":
                        case "!!":
                            message.ExpectArguments(1);
                            await _callbacks.WriteConsoleEx(
                                message.GetString(0, "buf", allowNull: true),
                                message.Name.Length == 1?OutputType.Output : OutputType.Error,
                                ct);

                            break;

                        case "!ShowMessage":
                            message.ExpectArguments(1);
                            await _callbacks.ShowMessage(message.GetString(0, "s", allowNull: true), ct);

                            break;

                        case "!+":
                            await _callbacks.Busy(true, ct);

                            break;

                        case "!-":
                            await _callbacks.Busy(false, ct);

                            break;

                        case "!SetWD":
                            _callbacks.DirectoryChanged();
                            break;

                        case "!Library":
                            await _callbacks.ViewLibrary(ct);

                            break;

                        case "!ShowFile":
                            message.ExpectArguments(3);
                            await _callbacks.ShowFile(
                                message.GetString(0, "file"),
                                message.GetString(1, "tabName"),
                                message.GetBoolean(2, "delete.file"));

                            break;

                        case "!View":
                            message.ExpectArguments(2);
                            _callbacks.ViewObject(message.GetString(0, "x"), message.GetString(1, "title"));
                            break;

                        case "!Plot":
                            await _callbacks.Plot(
                                new PlotMessage(
                                    Guid.Parse(message.GetString(0, "device_id")),
                                    Guid.Parse(message.GetString(1, "plot_id")),
                                    message.GetString(2, "file_path"),
                                    message.GetInt32(3, "device_num"),
                                    message.GetInt32(4, "active_plot_index"),
                                    message.GetInt32(5, "plot_count"),
                                    message.Blob),
                                ct);

                            break;

                        case "?Locator":
                            var locatorResult = await _callbacks.Locator(Guid.Parse(message.GetString(0, "device_id")), ct);

                            ct.ThrowIfCancellationRequested();
                            await RespondAsync(message, ct, locatorResult.Clicked, locatorResult.X, locatorResult.Y);

                            break;

                        case "?PlotDeviceCreate":
                            var plotDeviceResult = await _callbacks.PlotDeviceCreate(Guid.Parse(message.GetString(0, "device_id")), ct);

                            ct.ThrowIfCancellationRequested();
                            await RespondAsync(message, ct, plotDeviceResult.Width, plotDeviceResult.Height, plotDeviceResult.Resolution);

                            break;

                        case "!PlotDeviceDestroy":
                            await _callbacks.PlotDeviceDestroy(Guid.Parse(message.GetString(0, "device_id")), ct);

                            break;

                        case "!WebBrowser":
                            await _callbacks.WebBrowser(message.GetString(0, "url"), ct);

                            break;

                        case "!PackagesInstalled":
                            _callbacks.PackagesInstalled();
                            break;

                        case "!PackagesRemoved":
                            _callbacks.PackagesRemoved();
                            break;

                        case "!FetchFile":
                            var destPath = await _callbacks.SaveFileAsync(message.GetString(0, "file_path"), message.Blob);

                            await _callbacks.WriteConsoleEx(destPath, OutputType.Error, ct);

                            break;

                        default:
                            throw ProtocolError($"Unrecognized host message name:", message);
                        }
                    } catch (OperationCanceledException) when(!ct.IsCancellationRequested)
                    {
                        // Canceled via _cancelAllCts - just move onto the next message.
                    }
                }
            } finally {
                _log.ExitRLoop(--_rLoopDepth);
            }

            return(null);
        }