/// <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); } }
/// <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); } }
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); }
/// <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); } }
/// <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); } }
/// <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); } }
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); }
/// <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); } }
/// <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); } } }
public RemoteSessionProcessClient(RemoteSessionManager remoteSessionManager, InstanceContext callbackContext) : base(callbackContext) { _remoteSessionManager = remoteSessionManager; _processStartLock = new object(); }
public RemoteSessionProcessClientCallback(RemoteSessionManager remoteSessionManager, HttpApplicationState application) { _remoteSessionManager = remoteSessionManager; _application = application; }
public RemoteSessionProcessClientCallback(RemoteSessionManager remoteSessionManager) { _remoteSessionManager = remoteSessionManager; }
public RemoteSessionProcessClient(RemoteSessionManager remoteSessionManager, InstanceContext callbackContext) : base(callbackContext) { _remoteSessionManager = remoteSessionManager; }
public HostTypeEnum HostType; // set remote host type, RDP or SSH public RemoteSession() { Manager = new RemoteSessionManager(this); }
/// <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); } }
/// <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); } }