Ejemplo n.º 1
0
        /// <summary>
        /// retrieve the remote session clipboard
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(
            object sender,
            EventArgs e)
        {
            // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url
            // in both cases, the given http session is automatically bound to the current http context

            RemoteSessionManager remoteSessionManager = null;

            try
            {
                // retrieve the remote session manager for the current http session
                remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session manager for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc);
                return;
            }

            try
            {
                System.Diagnostics.Trace.TraceInformation("Requesting remote clipboard, remote session {0}", remoteSessionManager.RemoteSession.Id);
                remoteSessionManager.SendCommand(RemoteSessionCommand.RequestRemoteClipboard);
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to retrieve remote clipboard, remote session {0} ({1})", remoteSessionManager.RemoteSession.Id, exc);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// initialization
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(
            object sender,
            EventArgs e)
        {
            try
            {
                // retrieve the active remote session, if any
                if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()] != null)
                {
                    try
                    {
                        RemoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
                    }
                    catch (Exception exc)
                    {
                        System.Diagnostics.Trace.TraceError("Failed to retrieve remote session manager ({0})", exc);
                    }
                }

                // update controls
                UpateControls();

                // disable the browser cache; in addition to a "noCache" dummy param, with current time, on long-polling and xhr requests
                Response.Cache.SetCacheability(HttpCacheability.NoCache);
                Response.Cache.SetNoStore();
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to load myrtille ({0})", exc);
            }
        }
Ejemplo n.º 3
0
        public string ClipboardText;                    // clipboard text

        public RemoteSession(
            Guid id,
            string hostName,
            HostType hostType,
            SecurityProtocol securityProtocol,
            string serverAddress,
            string vmGuid,
            string vmAddress,
            bool vmEnhancedMode,
            string userDomain,
            string userName,
            string userPassword,
            int clientWidth,
            int clientHeight,
            string startProgram,
            bool allowRemoteClipboard,
            bool allowFileTransfer,
            bool allowPrintDownload,
            bool allowSessionSharing,
            bool allowAudioPlayback,
            int maxActiveGuests,
            string ownerSessionID,
            string ownerClientKey,
            bool connectionService)
        {
            Id                   = id;
            State                = RemoteSessionState.NotConnected;
            HostName             = hostName;
            HostType             = hostType;
            SecurityProtocol     = securityProtocol;
            ServerAddress        = serverAddress;
            VMGuid               = vmGuid;
            VMAddress            = vmAddress;
            VMEnhancedMode       = vmEnhancedMode;
            UserDomain           = userDomain;
            UserName             = userName;
            UserPassword         = userPassword;
            ClientWidth          = clientWidth < 100 ? 100 : clientWidth;
            ClientHeight         = clientHeight < 100 ? 100 : clientHeight;
            StartProgram         = startProgram;
            AllowRemoteClipboard = allowRemoteClipboard;
            AllowFileTransfer    = allowFileTransfer;
            AllowPrintDownload   = allowPrintDownload;
            AllowSessionSharing  = allowSessionSharing;
            AllowAudioPlayback   = allowAudioPlayback;
            ActiveGuests         = 0;
            MaxActiveGuests      = maxActiveGuests;
            OwnerSessionID       = ownerSessionID;
            OwnerClientKey       = ownerClientKey;
            ConnectionService    = connectionService;

            // default capture API config
            ScreenshotIntervalSecs = 60;
            ScreenshotFormat       = CaptureFormat.PNG;
            ScreenshotPath         = string.Empty;

            Manager = new RemoteSessionManager(this);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// retrieve the mouse cursor from the rdp session and send it to the browser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(
            object sender,
            EventArgs e)
        {
            // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url
            // in both cases, the given http session is automatically bound to the current http context

            RemoteSessionManager remoteSessionManager = null;

            try
            {
                // retrieve the remote session manager for the current http session
                remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session manager for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc);
                return;
            }

            try
            {
                // retrieve params
                var imgIdx = int.Parse(HttpContext.Current.Request.QueryString["imgIdx"]);

                // retrieve image data
                var img     = remoteSessionManager.GetCachedUpdate(imgIdx);
                var imgData = img != null?Convert.FromBase64String(img.Base64Data) : null;

                if (imgData != null && imgData.Length > 0)
                {
                    var imgStream = new MemoryStream(imgData);
                    var bitmap    = new Bitmap(imgStream);

                    //var cursor = CreateCursor(bitmap, img.PosX, img.PosY);
                    // TODO: find a way to save a cursor as .cur file? using .ico instead...

                    var icon = Icon.FromHandle(bitmap.GetHicon());

                    // TODO: IE
                    // IE does support .ico files for cursors, but an icon doesn't have an hotspot and there is no way to define it in IE...
                    // problem is, the user thinks clicking a specific spot and, in fact, isn't...
                    // also, the cursor blinks when it changes, and stays invisible as long as the user doesn't move the mouse...
                    // for these reasons, IE won't display custom cursors...

                    var iconStream = new MemoryStream();
                    icon.Save(iconStream);
                    var iconData = iconStream.ToArray();

                    // write the output
                    HttpContext.Current.Response.OutputStream.Write(iconData, 0, iconData.Length);
                }
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to get mouse cursor, remote session {0} ({1})", remoteSessionManager.RemoteSession.Id, exc);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// initialization
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Init(
            object sender,
            EventArgs e)
        {
            try
            {
                // retrieve the active remote session, if any
                if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()] != null)
                {
                    try
                    {
                        _remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
                    }
                    catch (Exception exc)
                    {
                        System.Diagnostics.Trace.TraceError("Failed to retrieve remote session manager ({0})", exc);
                    }
                }

                // ensure there is an active remote session
                // if a domain is specified, the roaming user profile is loaded from the Active Directory
                // file storage is synchronized with the user "My documents" folder (will use folder redirection if defined)
                // user credentials will be checked prior to any file operation
                // if possible, use SSL to communicate with the service
                if (_remoteSessionManager != null && (_remoteSessionManager.RemoteSession.State == RemoteSessionState.Connecting || _remoteSessionManager.RemoteSession.State == RemoteSessionState.Connected) &&
                    (_remoteSessionManager.RemoteSession.ServerAddress.ToLower() == "localhost" || _remoteSessionManager.RemoteSession.ServerAddress == "127.0.0.1" || _remoteSessionManager.RemoteSession.ServerAddress == HttpContext.Current.Request.Url.Host || !string.IsNullOrEmpty(_remoteSessionManager.RemoteSession.UserDomain)) &&
                    !string.IsNullOrEmpty(_remoteSessionManager.RemoteSession.UserName) && !string.IsNullOrEmpty(_remoteSessionManager.RemoteSession.UserPassword))
                {
                    _fileStorageClient = new FileStorageClient();

                    var files = _fileStorageClient.GetUserDocumentsFolderFiles(
                        _remoteSessionManager.RemoteSession.UserDomain,
                        _remoteSessionManager.RemoteSession.UserName,
                        _remoteSessionManager.RemoteSession.UserPassword);

                    if (files.Count > 0)
                    {
                        fileToDownloadSelect.DataSource = files;
                        fileToDownloadSelect.DataBind();
                        downloadFileButton.Disabled = false;
                    }
                }
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to init file storage ({0})", exc);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// initialization
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Init(
            object sender,
            EventArgs e)
        {
            try
            {
                // retrieve the active remote session, if any
                if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()] != null)
                {
                    try
                    {
                        _remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
                    }
                    catch (Exception exc)
                    {
                        System.Diagnostics.Trace.TraceError("Failed to retrieve remote session manager ({0})", exc);
                    }
                }

                // ensure there is an active remote session, localhost connection
                // as it's a local file storage only, it excludes domain users
                // user credentials will be checked against the local machine prior to any file operation
                // if possible, use SSL to communicate with the service
                if (_remoteSessionManager != null && (_remoteSessionManager.RemoteSession.State == RemoteSessionState.Connecting || _remoteSessionManager.RemoteSession.State == RemoteSessionState.Connected) &&
                    (_remoteSessionManager.RemoteSession.ServerAddress.ToLower() == "localhost" || _remoteSessionManager.RemoteSession.ServerAddress == "127.0.0.1" || _remoteSessionManager.RemoteSession.ServerAddress == HttpContext.Current.Request.Url.Host) &&
                    string.IsNullOrEmpty(_remoteSessionManager.RemoteSession.UserDomain) && !string.IsNullOrEmpty(_remoteSessionManager.RemoteSession.UserName) && !string.IsNullOrEmpty(_remoteSessionManager.RemoteSession.UserPassword))
                {
                    _localFileStorageClient = new LocalFileStorageClient();

                    var files = _localFileStorageClient.GetLocalUserDocumentsFolderFiles(
                        _remoteSessionManager.RemoteSession.UserName,
                        _remoteSessionManager.RemoteSession.UserPassword);

                    if (files.Count > 0)
                    {
                        fileToDownloadSelect.DataSource = files;
                        fileToDownloadSelect.DataBind();
                        downloadFileButton.Disabled = false;
                    }
                }
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to init file storage ({0})", exc);
            }
        }
Ejemplo n.º 7
0
        public RemoteSession(
            Guid id,
            RemoteSessionState state,
            string hostName,
            HostTypeEnum hostType,
            SecurityProtocolEnum securityProtocol,
            string serverAddress,
            string vmGuid,
            bool vmEnhancedMode,
            string userDomain,
            string userName,
            string userPassword,
            int clientWidth,
            int clientHeight,
            string startProgram,
            bool allowRemoteClipboard,
            bool allowFileTransfer,
            bool allowPrintDownload,
            bool allowSessionSharing,
            string ownerSessionID)
        {
            Id                   = id;
            State                = state;
            HostName             = hostName;
            HostType             = hostType;
            SecurityProtocol     = securityProtocol;
            ServerAddress        = serverAddress;
            VMGuid               = vmGuid;
            VMEnhancedMode       = vmEnhancedMode;
            UserDomain           = userDomain;
            UserName             = userName;
            UserPassword         = userPassword;
            ClientWidth          = clientWidth;
            ClientHeight         = clientHeight;
            StartProgram         = startProgram;
            AllowRemoteClipboard = allowRemoteClipboard;
            AllowFileTransfer    = allowFileTransfer;
            AllowPrintDownload   = allowPrintDownload;
            AllowSessionSharing  = allowSessionSharing;
            OwnerSessionID       = ownerSessionID;

            Manager = new RemoteSessionManager(this);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// retrieve an image update (region or fullscreen) from the rdp session and send it to the browser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(
            object sender,
            EventArgs e)
        {
            // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url
            // in both cases, the given http session is automatically bound to the current http context

            RemoteSessionManager remoteSessionManager = null;

            try
            {
                // retrieve the remote session manager for the current http session
                remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session manager for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc);
                return;
            }

            try
            {
                // retrieve params
                var imgIdx = int.Parse(HttpContext.Current.Request.QueryString["imgIdx"]);

                // retrieve image data
                var img     = remoteSessionManager.GetCachedUpdate(imgIdx);
                var imgData = img != null?Convert.FromBase64String(img.Base64Data) : null;

                if (imgData != null && imgData.Length > 0)
                {
                    // write the output
                    HttpContext.Current.Response.OutputStream.Write(imgData, 0, imgData.Length);
                }
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to get display update, remote session {0} ({1})", remoteSessionManager.RemoteSession.Id, exc);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// start the rdp session
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void ConnectButtonClick(
            object sender,
            EventArgs e)
        {
            // remove a previously disconnected remote session
            if (RemoteSessionManager != null && RemoteSessionManager.RemoteSession.State == RemoteSessionState.Disconnected)
            {
                try
                {
                    HttpContext.Current.Application.Lock();

                    // unset the remote session manager for the current http session
                    HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()] = null;

                    // unregister it at application level; used when there is no http context (i.e.: websockets)
                    var remoteSessionsManagers = (Dictionary <string, RemoteSessionManager>)HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsManagers.ToString()];
                    if (remoteSessionsManagers.ContainsKey(HttpContext.Current.Session.SessionID))
                    {
                        remoteSessionsManagers.Remove(HttpContext.Current.Session.SessionID);
                    }
                }
                catch (Exception exc)
                {
                    System.Diagnostics.Trace.TraceError("Failed to remove remote session ({0})", exc);
                }
                finally
                {
                    RemoteSessionManager = null;
                    HttpContext.Current.Application.UnLock();
                }
            }

            // create a new remote session, if none active
            if (RemoteSessionManager == null)
            {
                try
                {
                    HttpContext.Current.Application.Lock();

                    // auto-increment the remote sessions counter
                    // note that it doesn't really count the active remote sessions... it's just an auto-increment for the remote session id, ensuring it's unique...
                    // the active remote sessions are registered in HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsManagers.ToString()]; count can be retrieved from there
                    var remoteSessionsCounter = (int)HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsCounter.ToString()];
                    remoteSessionsCounter++;

                    // create the remote session manager
                    RemoteSessionManager = new RemoteSessionManager(
                        new RemoteSession
                    {
                        Id            = remoteSessionsCounter,
                        State         = RemoteSessionState.NotConnected,
                        ServerAddress = serverText.Value,
                        UserDomain    = domainText.Value,
                        UserName      = userText.Value,
                        UserPassword  = passwordText.Value,
                        ClientWidth   = width.Value,
                        ClientHeight  = height.Value,
                        DebugMode     = debugSelect.Value == "Debug enabled"
                    }
                        );

                    // set the remote session manager for the current http session
                    HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()] = RemoteSessionManager;

                    // register it at application level; used when there is no http context (i.e.: websockets)
                    var remoteSessionsManagers = (Dictionary <string, RemoteSessionManager>)HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsManagers.ToString()];
                    remoteSessionsManagers[HttpContext.Current.Session.SessionID] = RemoteSessionManager;

                    // update the remote sessions auto-increment counter
                    HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsCounter.ToString()] = remoteSessionsCounter;
                }
                catch (Exception exc)
                {
                    System.Diagnostics.Trace.TraceError("Failed to create remote session ({0})", exc);
                    RemoteSessionManager = null;
                }
                finally
                {
                    HttpContext.Current.Application.UnLock();
                }
            }

            // connect it
            if (RemoteSessionManager != null && RemoteSessionManager.RemoteSession.State != RemoteSessionState.Connecting && RemoteSessionManager.RemoteSession.State != RemoteSessionState.Connected)
            {
                try
                {
                    // update the remote session state
                    RemoteSessionManager.RemoteSession.State = RemoteSessionState.Connecting;

                    // create pipes for this web gateway and the rdp client to talk
                    RemoteSessionManager.Pipes.CreatePipes();

                    // the rdp client does connect the pipes when it starts; when it stops (either because it was closed, crashed or because the rdp session had ended), pipes are released
                    // use http://technet.microsoft.com/en-us/sysinternals/dd581625 to track the existing pipes
                    RemoteSessionManager.Client.StartProcess(
                        RemoteSessionManager.RemoteSession.Id,
                        RemoteSessionManager.RemoteSession.ServerAddress,
                        RemoteSessionManager.RemoteSession.UserDomain,
                        RemoteSessionManager.RemoteSession.UserName,
                        RemoteSessionManager.RemoteSession.UserPassword,
                        RemoteSessionManager.RemoteSession.ClientWidth,
                        RemoteSessionManager.RemoteSession.ClientHeight,
                        RemoteSessionManager.RemoteSession.DebugMode);

                    // update controls
                    UpateControls();
                }
                catch (Exception exc)
                {
                    System.Diagnostics.Trace.TraceError("Failed to connect remote session {0} ({1})", RemoteSessionManager.RemoteSession.Id, exc);
                }
            }
        }
Ejemplo n.º 10
0
 public RemoteSessionProcessClient(RemoteSessionManager remoteSessionManager, InstanceContext callbackContext)
     : base(callbackContext)
 {
     _remoteSessionManager = remoteSessionManager;
     _processStartLock     = new object();
 }
Ejemplo n.º 11
0
 public RemoteSessionProcessClientCallback(RemoteSessionManager remoteSessionManager, HttpApplicationState application)
 {
     _remoteSessionManager = remoteSessionManager;
     _application          = application;
 }
Ejemplo n.º 12
0
 public RemoteSessionProcessClientCallback(RemoteSessionManager remoteSessionManager)
 {
     _remoteSessionManager = remoteSessionManager;
 }
Ejemplo n.º 13
0
 public RemoteSessionProcessClient(RemoteSessionManager remoteSessionManager, InstanceContext callbackContext)
     : base(callbackContext)
 {
     _remoteSessionManager = remoteSessionManager;
 }
Ejemplo n.º 14
0
        public HostTypeEnum HostType;                   // set remote host type, RDP or SSH

        public RemoteSession()
        {
            Manager = new RemoteSessionManager(this);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// push image(s) updates(s) (region(s) or fullscreen(s)) from the rdp session to the browser
        /// this is done through a long-polling request (also known as reverse ajax or ajax comet) issued by a zero sized iframe
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(
            object sender,
            EventArgs e)
        {
            // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url
            // in both cases, the given http session is automatically bound to the current http context

            RemoteSessionManager remoteSessionManager = null;

            try
            {
                // retrieve the remote session manager for the current http session
                remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session manager for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc);
                return;
            }

            try
            {
                // retrieve params
                var longPollingDuration = int.Parse(HttpContext.Current.Request.QueryString["longPollingDuration"]);
                var imgIdx = int.Parse(HttpContext.Current.Request.QueryString["imgIdx"]);

                // if a websocket is set at this step, the client had probably changed the rendering mode (html5 -> html4) or configuration while the remote session is active, then reloaded the page (F5)
                // close the websocket (a new one will be set if the client change back to html5 again...)
                if (remoteSessionManager.WebSocket != null)
                {
                    System.Diagnostics.Trace.TraceInformation("Removing no longer used websocket (the client had probably changed the rendering mode from HTML5 to HTML4 then reloaded the page (F5)), remote session {0}", remoteSessionManager.RemoteSession.Id);
                    remoteSessionManager.WebSocket.Close();
                    remoteSessionManager.WebSocket = null;
                }

                // stream image(s) data within the response for the given duration
                // the connection will be automatically reseted by the client when the request ends
                var startTime     = DateTime.Now;
                var remainingTime = longPollingDuration;
                var currentImgIdx = imgIdx;

                while (remainingTime > 0)
                {
                    // ensure the remote session is still connected
                    if (remoteSessionManager.RemoteSession.State == RemoteSessionState.Disconnected)
                    {
                        // the remote session is disconnected, back to home page
                        HttpContext.Current.Response.Write("<script>parent.location.href = parent.getConfig().getHttpServerUrl();</script>");
                        HttpContext.Current.Response.Flush();
                        break;
                    }
                    // the remote clipboard content was requested
                    else if (remoteSessionManager.ClipboardRequested)
                    {
                        HttpContext.Current.Response.Write(string.Format("<script>parent.showDialogPopup('showDialogPopup', 'ShowDialog.aspx', 'Ctrl+C to copy to local clipboard (Cmd-C on Mac)', '{0}', true);</script>", remoteSessionManager.ClipboardText));
                        HttpContext.Current.Response.Flush();
                        remoteSessionManager.ClipboardRequested = false;
                    }

                    // retrieve the next update, if available; otherwise, wait it for the remaining time
                    var image = remoteSessionManager.GetNextUpdate(currentImgIdx, remainingTime);
                    if (image != null)
                    {
                        System.Diagnostics.Trace.TraceInformation("Pushing image {0} ({1}), remote session {2}", image.Idx, (image.Fullscreen ? "screen" : "region"), remoteSessionManager.RemoteSession.Id);

                        var imgData =
                            image.Idx + "," +
                            image.PosX + "," +
                            image.PosY + "," +
                            image.Width + "," +
                            image.Height + "," +
                            "'" + image.Format.ToString().ToLower() + "'," +
                            image.Quality + "," +
                            "'" + image.Base64Data + "'," +
                            image.Fullscreen.ToString().ToLower();

                        imgData = "<script>parent.pushImage(" + imgData + ");</script>";

                        // write the output
                        HttpContext.Current.Response.Write(imgData);
                        HttpContext.Current.Response.Flush();

                        currentImgIdx = image.Idx;
                    }

                    remainingTime = longPollingDuration - Convert.ToInt32((DateTime.Now - startTime).TotalMilliseconds);
                }
            }
            catch (HttpException)
            {
                // this occurs if the user reloads the page while the long-polling request is going on...
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to push display update(s), remote session {0} ({1})", remoteSessionManager.RemoteSession.Id, exc);
            }
        }
        private static void ProcessMessage(IWebSocketConnection socket, string message)
        {
            if (string.IsNullOrEmpty(message))
            {
                Trace.TraceWarning("Received null or empty websocket message");
                return;
            }

            var msgParams = message.Split(new[] { "|" }, StringSplitOptions.None);

            if (msgParams.Length >= 2)
            {
                var httpSessionId = msgParams[1];

                RemoteSessionManager remoteSessionManager = null;

                try
                {
                    // retrieve the remote session manager for the given http session (the http session id is passed as parameter as the ws protocol doesn't pass it automatically)
                    var remoteSessionsManagers = (IDictionary <string, RemoteSessionManager>)_global.Application[HttpApplicationStateVariables.RemoteSessionsManagers.ToString()];
                    remoteSessionManager = remoteSessionsManagers[httpSessionId];
                }
                catch (Exception exc)
                {
                    Trace.TraceError("Failed to retrieve the remote session manager for the http session {0}, ({1})", httpSessionId, exc);
                    return;
                }

                try
                {
                    switch (msgParams[0])
                    {
                    // user input (mouse, keyboard)
                    case "input":

                        var data           = msgParams[2];
                        var fsu            = int.Parse(msgParams[3]) == 1;
                        var imgIdx         = int.Parse(msgParams[4]);
                        var imgEncoding    = msgParams[5];
                        var imgQuality     = int.Parse(msgParams[6]);
                        var bandwidthRatio = int.Parse(msgParams[7]);
                        var newSocket      = int.Parse(msgParams[8]) == 1;
                        var timestamp      = long.Parse(msgParams[9]);

                        // if the socket is new, bind it to the remote session manager
                        // close the old one, if any
                        if (newSocket)
                        {
                            // ensure the remote session is still connected
                            if (remoteSessionManager.RemoteSession.State == RemoteSessionState.Disconnected)
                            {
                                if (socket.IsAvailable)
                                {
                                    socket.Send("disconnected");
                                }
                                return;
                            }

                            if (remoteSessionManager.WebSocket != null)
                            {
                                remoteSessionManager.WebSocket.Close();
                            }

                            remoteSessionManager.WebSocket = socket;
                        }

                        // image encoding
                        var encoding = ImageEncoding.JPEG;
                        Enum.TryParse(imgEncoding, true, out encoding);
                        remoteSessionManager.ImageEncoding = encoding;

                        // throttle the image quality depending on the bandwidth usage ratio
                        if (bandwidthRatio >= (int)ImageQualityTweakBandwidthRatio.HigherBound)
                        {
                            remoteSessionManager.ImageQuality = imgQuality / 4;
                        }
                        else if (bandwidthRatio >= (int)ImageQualityTweakBandwidthRatio.LowerBound && bandwidthRatio < (int)ImageQualityTweakBandwidthRatio.HigherBound)
                        {
                            remoteSessionManager.ImageQuality = imgQuality / 2;
                        }
                        else
                        {
                            remoteSessionManager.ImageQuality = imgQuality;
                        }

                        // if defined, send the user input(s) through the rdp session
                        if (!string.IsNullOrEmpty(data))
                        {
                            remoteSessionManager.SendUserEvent(data);
                        }

                        // if requested, ask for a fullscreen update
                        if (fsu)
                        {
                            Trace.TraceInformation("Requesting fullscreen update, remote session {0}", remoteSessionManager.RemoteSession.Id);
                            remoteSessionManager.SendCommand(RemoteSessionCommand.SendFullscreenUpdate);
                        }

                        // acknowledge the message processing with the given timestamp; it will be used by the client to compute the roundtrip delay
                        socket.Send("ack," + timestamp);

                        break;

                    // remote session has been disconnected; close the websocket
                    case "close":

                        if (remoteSessionManager.WebSocket != null)
                        {
                            remoteSessionManager.WebSocket.Close();
                            remoteSessionManager.WebSocket = null;
                        }

                        break;
                    }
                }
                catch (Exception exc)
                {
                    Trace.TraceError("Failed to process websocket message, remote session {0} ({1})", remoteSessionManager.RemoteSession.Id, exc);
                }
            }
            else
            {
                Trace.TraceError("Failed to parse websocket message {0}", message);
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// send user input(s) (mouse, keyboard) to the rdp session
        /// if long-polling is disabled (xhr only), also returns image data within the response
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(
            object sender,
            EventArgs e)
        {
            // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url
            // in both cases, the given http session is automatically bound to the current http context

            RemoteSessionManager remoteSessionManager = null;

            try
            {
                // retrieve the remote session manager for the current http session
                remoteSessionManager = (RemoteSessionManager)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSessionManager.ToString()];
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session manager for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc);
                return;
            }

            try
            {
                // retrieve params
                var data           = HttpContext.Current.Request.QueryString["data"];
                var fsu            = int.Parse(HttpContext.Current.Request.QueryString["fsu"]) == 1;
                var imgIdx         = int.Parse(HttpContext.Current.Request.QueryString["imgIdx"]);
                var imgEncoding    = HttpContext.Current.Request.QueryString["imgEncoding"];
                var imgQuality     = int.Parse(HttpContext.Current.Request.QueryString["imgQuality"]);
                var imgReturn      = int.Parse(HttpContext.Current.Request.QueryString["imgReturn"]) == 1;
                var bandwidthRatio = int.Parse(HttpContext.Current.Request.QueryString["bandwidthRatio"]);

                // image encoding
                var encoding = ImageEncoding.JPEG;
                Enum.TryParse(imgEncoding, true, out encoding);
                remoteSessionManager.ImageEncoding = encoding;

                // throttle the image quality depending on the bandwidth usage ratio
                if (bandwidthRatio >= (int)ImageQualityTweakBandwidthRatio.HigherBound)
                {
                    remoteSessionManager.ImageQuality = imgQuality / 4;
                }
                else if (bandwidthRatio >= (int)ImageQualityTweakBandwidthRatio.LowerBound && bandwidthRatio < (int)ImageQualityTweakBandwidthRatio.HigherBound)
                {
                    remoteSessionManager.ImageQuality = imgQuality / 2;
                }
                else
                {
                    remoteSessionManager.ImageQuality = imgQuality;
                }

                // if defined, send the user input(s) through the rdp session
                // also, a websocket triggers periodical dummy xhr calls, without data, in order to keep the http session alive; such calls musn't close the websocket!
                if (!string.IsNullOrEmpty(data))
                {
                    remoteSessionManager.SendUserEvent(data);

                    // if a websocket is set at this step, the client had probably changed the rendering mode (html5 -> html4) or configuration while the remote session is active, then reloaded the page (F5)
                    // close the websocket (a new one will be set if the client change back to html5 again...)
                    if (remoteSessionManager.WebSocket != null)
                    {
                        System.Diagnostics.Trace.TraceInformation("Removing no longer used websocket (the client had probably changed the rendering mode from HTML5 to HTML4 then reloaded the page (F5)), remote session {0}", remoteSessionManager.RemoteSession.Id);
                        remoteSessionManager.WebSocket.Close();
                        remoteSessionManager.WebSocket = null;
                    }
                }

                // if requested, ask for a fullscreen update
                if (fsu)
                {
                    System.Diagnostics.Trace.TraceInformation("Requesting fullscreen update, remote session {0}", remoteSessionManager.RemoteSession.Id);
                    remoteSessionManager.SendCommand(RemoteSessionCommand.SendFullscreenUpdate);
                }

                // xhr only
                if (imgReturn)
                {
                    var image = remoteSessionManager.GetNextUpdate(imgIdx);
                    if (image != null)
                    {
                        System.Diagnostics.Trace.TraceInformation("Returning image {0} ({1}), remote session {2}", image.Idx, (image.Fullscreen ? "screen" : "region"), remoteSessionManager.RemoteSession.Id);

                        var imgData =
                            image.Idx + "," +
                            image.PosX + "," +
                            image.PosY + "," +
                            image.Width + "," +
                            image.Height + "," +
                            image.Format.ToString().ToLower() + "," +
                            image.Quality + "," +
                            image.Base64Data + "," +
                            image.Fullscreen.ToString().ToLower();

                        // write the output
                        HttpContext.Current.Response.Write(imgData);
                    }
                    // ensure the remote session is still connected
                    else if (remoteSessionManager.RemoteSession.State == RemoteSessionState.Disconnected)
                    {
                        HttpContext.Current.Response.Write("disconnected");
                    }
                    // the remote clipboard content was requested
                    else if (remoteSessionManager.ClipboardRequested)
                    {
                        HttpContext.Current.Response.Write(string.Format("clipboard|{0}", remoteSessionManager.ClipboardText));
                        remoteSessionManager.ClipboardRequested = false;
                    }
                }
            }
            catch (Exception exc)
            {
                System.Diagnostics.Trace.TraceError("Failed to send user input(s), remote session {0} ({1})", remoteSessionManager.RemoteSession.Id, exc);
            }
        }