Exemplo n.º 1
0
 public void SendUpdatesPipeMessage(string msg)
 {
     PipeHelper.WritePipeData(
         _updatesPipe,
         "remotesession_" + _remotesessionID + "_updates",
         msg,
         false);
 }
Exemplo n.º 2
0
        public void SendCommand(RemoteSessionCommand command, string args = "")
        {
            if (RemoteSession.State == RemoteSessionState.NotConnected ||
                RemoteSession.State == RemoteSessionState.Disconnected)
            {
                return;
            }

            var commandWithArgs = string.Concat((string)RemoteSessionCommandMapping.ToPrefix[command], args);

            switch (command)
            {
            // as the process command line can be displayed into the task manager / process explorer, the connection settings (including user credentials) are now passed to the host client through the inputs pipe
            // their values are set from the login page (using http(s) get or post) and shouldn't be modified at this step
            case RemoteSessionCommand.SendServerAddress:
            case RemoteSessionCommand.SendVMGuid:
            case RemoteSessionCommand.SendUserDomain:
            case RemoteSessionCommand.SendUserName:
            case RemoteSessionCommand.SendUserPassword:
            case RemoteSessionCommand.SendStartProgram:

                if (RemoteSession.State != RemoteSessionState.Connecting)
                {
                    return;
                }

                break;

            // browser resize
            case RemoteSessionCommand.SendBrowserResize:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                if (_resizeDelayed)
                {
                    if (_resizeTimeout != null)
                    {
                        _resizeTimeout.Cancel();
                        _resizeTimeout.Dispose();
                    }
                    _resizeTimeout = new CancellationTokenSource();
                    Task.Delay(500, _resizeTimeout.Token).ContinueWith(task =>
                    {
                        var resolution = args.Split(new[] { "x" }, StringSplitOptions.None);
                        var width      = int.Parse(resolution[0]);
                        var height     = int.Parse(resolution[1]);

                        RemoteSession.ClientWidth  = width < 100 ? 100 : width;
                        RemoteSession.ClientHeight = height < 100 ? 100 : height;

                        if (RemoteSession.BrowserResize == BrowserResize.Reconnect)
                        {
                            RemoteSession.Reconnect = true;
                            SendCommand(RemoteSessionCommand.CloseClient);
                        }
                        else
                        {
                            _resizeDelayed = false;
                            SendCommand(RemoteSessionCommand.SendBrowserResize, args);
                        }
                    }, TaskContinuationOptions.NotOnCanceled);
                    return;
                }
                _resizeDelayed = true;
                break;

            // browser pulse
            case RemoteSessionCommand.SendBrowserPulse:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                break;

            // keyboard, mouse
            case RemoteSessionCommand.SendKeyUnicode:
            case RemoteSessionCommand.SendMouseMove:
            case RemoteSessionCommand.SendMouseLeftButton:
            case RemoteSessionCommand.SendMouseMiddleButton:
            case RemoteSessionCommand.SendMouseRightButton:
            case RemoteSessionCommand.SendMouseWheelUp:
            case RemoteSessionCommand.SendMouseWheelDown:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                break;

            case RemoteSessionCommand.SendKeyScancode:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                var keyCodeAndState = args.Split(new[] { "-" }, StringSplitOptions.None);

                var jsKeyCode = int.Parse(keyCodeAndState[0]);
                var keyState  = keyCodeAndState[1];

                var rdpScanCode = JsKeyCodeToRdpScanCodeMapping.MapTable[jsKeyCode] as RdpScanCode;
                if (rdpScanCode != null && rdpScanCode.Value != 0)
                {
                    commandWithArgs = string.Concat((string)RemoteSessionCommandMapping.ToPrefix[command], rdpScanCode.Value + "-" + keyState + "-" + (rdpScanCode.Extend ? "1" : "0"));
                }
                break;

            // control
            case RemoteSessionCommand.SetScaleDisplay:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Display scaling {0}, remote session {1}", args != "0" ? args : "OFF", RemoteSession.Id);
                RemoteSession.BrowserResize = args != "0" ? BrowserResize.Scale : BrowserResize.None;
                break;

            case RemoteSessionCommand.SetReconnectSession:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Session reconnect {0}, remote session {1}", args == "1" ? "ON" : "OFF", RemoteSession.Id);
                RemoteSession.BrowserResize = args == "1" ? BrowserResize.Reconnect : BrowserResize.None;
                break;

            case RemoteSessionCommand.SetImageEncoding:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Image encoding {0}, remote session {1}", int.Parse(args), RemoteSession.Id);
                RemoteSession.ImageEncoding = (ImageEncoding)int.Parse(args);
                break;

            case RemoteSessionCommand.SetImageQuality:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Image quality {0}, remote session {1}", int.Parse(args), RemoteSession.Id);
                RemoteSession.ImageQuality = int.Parse(args);
                break;

            case RemoteSessionCommand.SetImageQuantity:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Image quantity {0}, remote session {1}", int.Parse(args), RemoteSession.Id);
                RemoteSession.ImageQuantity = int.Parse(args);
                break;

            case RemoteSessionCommand.SetAudioFormat:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Audio format {0}, remote session {1}", int.Parse(args), RemoteSession.Id);
                RemoteSession.AudioFormat = (AudioFormat)int.Parse(args);
                break;

            case RemoteSessionCommand.SetAudioBitrate:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                Trace.TraceInformation("Audio bitrate {0}, remote session {1}", int.Parse(args), RemoteSession.Id);
                RemoteSession.AudioBitrate = int.Parse(args);
                break;

            case RemoteSessionCommand.SetScreenshotConfig:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                var config = args.Split(new[] { "|" }, StringSplitOptions.None);
                RemoteSession.ScreenshotIntervalSecs = int.Parse(config[0]);
                RemoteSession.ScreenshotFormat       = (CaptureFormat)int.Parse(config[1]);
                RemoteSession.ScreenshotPath         = config[2];

                Trace.TraceInformation("Screenshot config {0}, remote session {1}", args, RemoteSession.Id);
                break;

            case RemoteSessionCommand.StartTakingScreenshots:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                if (_screenshotTimeout != null)
                {
                    _screenshotTimeout.Cancel();
                    _screenshotTimeout.Dispose();
                }
                _screenshotTimeout = new CancellationTokenSource();
                SendCommand(RemoteSessionCommand.TakeScreenshot);

                Trace.TraceInformation("Starting taking screenshots {0}, remote session {1}", args, RemoteSession.Id);
                break;

            case RemoteSessionCommand.StopTakingScreenshots:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                if (_screenshotTimeout != null)
                {
                    _screenshotTimeout.Cancel();
                    _screenshotTimeout.Dispose();
                }
                _screenshotTimeout = null;

                Trace.TraceInformation("Stopping taking screenshots {0}, remote session {1}", args, RemoteSession.Id);
                break;

            case RemoteSessionCommand.TakeScreenshot:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                if (_screenshotTimeout != null)
                {
                    _screenshotTimeout.Cancel();
                    _screenshotTimeout.Dispose();
                    _screenshotTimeout = new CancellationTokenSource();
                    Task.Delay(RemoteSession.ScreenshotIntervalSecs * 1000, _screenshotTimeout.Token).ContinueWith(task =>
                    {
                        SendCommand(RemoteSessionCommand.TakeScreenshot);
                    }, TaskContinuationOptions.NotOnCanceled);
                }

                FullscreenEventPending = true;

                Trace.TraceInformation("Taking screenshot {0}, remote session {1}", args, RemoteSession.Id);
                break;

            case RemoteSessionCommand.RequestFullscreenUpdate:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                FullscreenEventPending = true;

                Trace.TraceInformation("Requesting fullscreen update, all image(s) will now be discarded while waiting for it, remote session {0}", RemoteSession.Id);
                break;

            case RemoteSessionCommand.SendLocalClipboard:

                if (RemoteSession.State != RemoteSessionState.Connected)
                {
                    return;
                }

                var clipboardText = string.Empty;

                // read the clipboard text from unicode code points
                var charsCodes = args.Split(new[] { "-" }, StringSplitOptions.None);
                foreach (var charCode in charsCodes)
                {
                    clipboardText += char.ConvertFromUtf32(int.Parse(charCode));
                }

                // truncated above max length, which was normally already enforced client side; re-checking
                if (clipboardText.Length > _clipboardMaxLength)
                {
                    clipboardText = clipboardText.Substring(0, _clipboardMaxLength) + "--- TRUNCATED ---";
                }

                commandWithArgs = string.Concat((string)RemoteSessionCommandMapping.ToPrefix[command], clipboardText);

                Trace.TraceInformation("Sending local clipboard, remote session {0}", RemoteSession.Id);
                break;

            case RemoteSessionCommand.ConnectClient:

                if (RemoteSession.State != RemoteSessionState.Connecting)
                {
                    return;
                }

                Trace.TraceInformation("Connecting remote session, remote session {0}", RemoteSession.Id);
                break;

            case RemoteSessionCommand.CloseClient:

                if ((RemoteSession.State != RemoteSessionState.Connecting) &&
                    (RemoteSession.State != RemoteSessionState.Connected))
                {
                    return;
                }

                RemoteSession.State = RemoteSessionState.Disconnecting;

                Trace.TraceInformation("disconnecting remote session, remote session {0}", RemoteSession.Id);
                break;
            }

            Trace.TraceInformation("Sending command with args {0}, remote session {1}", commandWithArgs, RemoteSession.Id);

            try
            {
                PipeHelper.WritePipeData(
                    Pipes.InputsPipe,
                    "remotesession_" + RemoteSession.Id + "_inputs",
                    commandWithArgs);
            }
            catch (Exception exc)
            {
                Trace.TraceWarning("Failed to send command {0}, args {1}, remote session {2} ({3})", command, args, RemoteSession.Id, exc);

                // there is a problem with the inputs pipe, force close the remote session in order to avoid it being stuck
                // it's usually not a big deal, some inputs being sent while the pipes are being disconnected when the host client is closed (and thus before the remote session state is set to disconnected), but better take no risk...
                HostClient.StopProcess();
            }
        }