Skip to content

Commit

Permalink
see changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
cedrozor committed Jul 23, 2021
1 parent 43f1125 commit b996715
Show file tree
Hide file tree
Showing 25 changed files with 548 additions and 506 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
2021-03-07 Version 2.9.2
2021-07-22 Version 2.9.3
pre-requisites PLEASE READ! Myrtille requires a Windows Server edition (2012 R2 or greater) for itself (remote servers can be whatever OS with RDP enabled). Windows client editions (7, 8, 10 - whatever the version: pro, enterprise, ultimate, etc.) are not suitable for Myrtille due to the limitation to a maximum of 10 simultaneous connections on IIS!
a client is now identified by an unique id instead of a cookie based key; this fixes a problem of sharing a session by url within the same browser
disabled the share session by url feature (web.config), because it bypasses the share session by guest logic and make it difficult to track the active clients
redesigned the adaptive display tweaking logic, based on bandwidth usage

2021-03-07 Version 2.9.2
FreeRDP is now built as a dll instead of an executable for better modularity and to reduce the risk of false positive detection of wfreerdp.exe by some antiviruses (mostly cloud based)
embedded interact.js and simple-keyboard (nodejs modules) into myrtille in order to remove dependencies on external CDNs (ans thus allow myrtille to be used standalone and not subject to external changes)
fixed a problem with the creation of the self-signed certificate that prevented Myrtille from installing correctly on Windows Server 2012 R2 (thanks camjcorley)
Expand Down
6 changes: 1 addition & 5 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,14 @@ I hope you will enjoy Myrtille! :)
Special thanks to Catalin Trifanescu for its support.

## Installation
Starting from version 2.8.0, the Myrtille requirements change: Windows 8.1 or Windows Server 2012 R2 or greater. This is partly because of the automated installation of the roles and features required by myrtille (which requires a modern powershell) and partly to deliver the best user experience possible (fast display and audio support), as HTML5 websockets (supported by all browsers nowadays) are only available in IIS 8.0+ (Windows 8.1 or Windows Server 2012 R2 or greater).

That said, Myrtille will continue to fallback to HTML4 (xhr and long-polling) if websockets are not enabled into IIS (it's optional) or if the websocket traffic is blocked by any network equipment.
Windows Server OS (2012 R2 or greater, with IIS 8.0+, .NET 4.5+ and WCF/HTTP activation enabled). CAUTION! IIS on Windows client OSes (7, 8, 10 - all versions) is limited to 10 simultaneous connections only - across all http sessions - and will hang after that!

The .NET 4.5+ framework can be installed automatically by the myrtille installer, enabled as a feature of IIS (Web Server role > Applications Development > ASP.NET 4.5 on Windows Server 2012) or installed separately (https://www.microsoft.com/en-us/download/details.aspx?id=30653).

Into the roles and features management, ensure you have enabled **HTTP Activation** under ".NET Framework 4.5+ Features" > "WCF Services" (required by the Myrtille services and REST API).

The installer does install myrtille under the IIS default website and creates a custom application pool ("MyrtilleAppPool"). If you want to use another website or application pool, you can change it manually afterward (with the IIS manager).

CAUTION! IIS on Windows client OSes (7, 8, 10) is limited to 10 simultaneous connections only - across all http sessions - and will hang after that! (https://forums.asp.net/t/2062118.aspx?+limit+of+10+simultaneous+connections+imposed+). Use Windows Server editions for production environments.

All releases here: https://github.com/cedrozor/myrtille/releases

## Docker
Expand Down
8 changes: 2 additions & 6 deletions Myrtille.Web/SendInputs.aspx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ protected void Page_Load(
// retrieve the remote session for the current http session
remoteSession = (RemoteSession)Session[HttpSessionStateVariables.RemoteSession.ToString()];

var clientId = Session.SessionID;
if (Request.Cookies[HttpRequestCookies.ClientKey.ToString()] != null)
{
clientId = Request.Cookies[HttpRequestCookies.ClientKey.ToString()].Value;
}
var clientId = Request.QueryString["clientId"];

if (!remoteSession.Manager.Clients.ContainsKey(clientId))
{
Expand Down Expand Up @@ -131,7 +127,7 @@ protected void Page_Load(
// process input(s)
if (!string.IsNullOrEmpty(data))
{
remoteSession.Manager.ProcessInputs(Session, data);
remoteSession.Manager.ProcessInputs(Session, clientId, data);
}

client.ImgIdx = imgIdx;
Expand Down
5 changes: 2 additions & 3 deletions Myrtille.Web/Web.Base.config
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,12 @@
<!-- allow audio plaback -->
<add key="AllowAudioPlayback" value="true"/>
<!-- share a session by url, with owner rights. set to false to disable and provide a session url spoofing protection. requires cookieless="UseUri" session state (system.web/sessionState section above) -->
<!-- if a session is shared by url between different clients, each client is identified by a unique key instead of the http session id -->
<add key="AllowShareSessionUrl" value="true"/>
<add key="AllowShareSessionUrl" value="false"/>
<!-- client ip protection -->
<add key="ClientIPTracking" value="false"/>
<!-- if the browser window/tab of the remote session owner is closed without disconnecting first, or if the connection is lost, delay (ms) before the remote session is disconnected by the gateway. value must be greater than "browserPulseInterval" defined into config.js (default 10 secs). 0 to disable -->
<!-- this comes in addition but does not replace the session idle timeout, defined at the RDS level, which will disconnect the session after no user inputs are received for a given time, independently of Myrtille -->
<add key="ClientIdleTimeout" value="0"/>
<add key="OwnerIdleTimeout" value="0"/>
<!-- audio buffer. improves the audio quality at the expense of a slight latency -->
<add key="AudioBuffering" value="true"/>
<!-- show or hide the toolbar (you can hide it if using your own UI) -->
Expand Down
3 changes: 2 additions & 1 deletion Myrtille.Web/handlers/AudioSocketHandler.ashx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public void ProcessRequest(HttpContext context)
context.AcceptWebSocketRequest(
new RemoteSessionAudioSocketHandler(
context,
string.IsNullOrEmpty(context.Request["binary"]) ? true : context.Request["binary"] == "true"));
string.IsNullOrEmpty(context.Request["binary"]) ? true : context.Request["binary"] == "true",
context.Request["clientId"]));
}
}

Expand Down
5 changes: 4 additions & 1 deletion Myrtille.Web/handlers/EventSourceHandler.ashx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public class EventSourceHandler : IHttpHandler, IReadOnlySessionState
{
public void ProcessRequest(HttpContext context)
{
var handler = new RemoteSessionEventSourceHandler(context);
// retrieve params
var clientId = context.Request.QueryString["clientId"];

var handler = new RemoteSessionEventSourceHandler(context, clientId);

try
{
Expand Down
3 changes: 2 additions & 1 deletion Myrtille.Web/handlers/LongPollingHandler.ashx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class LongPollingHandler : IHttpHandler, IReadOnlySessionState
public void ProcessRequest(HttpContext context)
{
// retrieve params
var clientId = context.Request.QueryString["clientId"];
var longPollingDuration = int.Parse(context.Request.QueryString["longPollingDuration"]);
var imgIdx = int.Parse(context.Request.QueryString["imgIdx"]); // if needed

Expand All @@ -36,7 +37,7 @@ public void ProcessRequest(HttpContext context)
var startTime = DateTime.Now;
var remainingTime = longPollingDuration;

var handler = new RemoteSessionLongPollingHandler(context);
var handler = new RemoteSessionLongPollingHandler(context, clientId);

try
{
Expand Down
1 change: 1 addition & 0 deletions Myrtille.Web/handlers/SocketHandler.ashx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public void ProcessRequest(HttpContext context)
new RemoteSessionSocketHandler(
context,
string.IsNullOrEmpty(context.Request["binary"]) ? true : context.Request["binary"] == "true",
context.Request["clientId"],
direction));
}
}
Expand Down
2 changes: 1 addition & 1 deletion Myrtille.Web/js/audio/audiowebsocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function AudioWebsocket(base, config, dialog, display, network)
config.setAudioBitrate(320);
}

var wsUrl = config.getHttpServerUrl().replace('http', 'ws') + 'handlers/AudioSocketHandler.ashx?binary=true';
var wsUrl = config.getHttpServerUrl().replace('http', 'ws') + 'handlers/AudioSocketHandler.ashx?binary=true&clientId=' + network.getClientId();

//dialog.showDebug('audio websocket server url: ' + wsUrl);

Expand Down
10 changes: 4 additions & 6 deletions Myrtille.Web/js/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ function Config(
var imageEncoding = imageEncodingEnum.JPEG; // image encoding
var imageQuality = 75; // image quality (%) higher = better; not applicable for PNG (lossless); tweaked dynamically to fit the available bandwidth if using JPEG, AUTO or WEBP encoding.
var imageQuantity = 100; // image quantity (%) less images = lower cpu and bandwidth usage / faster; more = smoother display (skipping images may result in some display inconsistencies). tweaked dynamically to fit the available bandwidth; possible values: 5, 10, 20, 25, 50, 100 (lower = higher consolidation rate)
var imageTweakBandwidthLowerThreshold = 50; // tweak the image quality & quantity depending on the available bandwidth (%): lower threshold. see network.js
var imageTweakBandwidthHigherThreshold = 75; // tweak the image quality & quantity depending on the available bandwidth (%): higher threshold. see network.js
var imageTweakBandwidthThreshold = 50; // tweak the image quality depending on the available bandwidth (%): threshold. see network.js
var imageCountOk = 100; // reasonable number of images to display at once; for HTML4 (divs), used to clean the DOM (by requesting a fullscreen update) as too many divs may slow down the browser; not applicable for HTML5 (canvas)
var imageCountMax = 300; // maximal number of images to display at once; for HTML4 (divs), used to clean the DOM (by reloading the page) as too many divs may slow down the browser; not applicable for HTML5 (canvas)
var imageMode = imageModeEnum.AUTO; // image mode
Expand All @@ -145,15 +144,15 @@ function Config(
var roundtripDurationMax = 0; // roundtrip duration (ms) above which the connection is considered having issues, displaying a warning message to the user. 0 to disable
var bandwidthCheckInterval = 300000; // periodical bandwidth check; used to tweak down the images (quality & quantity) if the available bandwidth gets too low. it relies on a 5MB dummy file download, so this param shouldn't be set on a too short timer (or it will eat the bandwidth it's supposed to test...)
var networkMode = networkModeEnum.AUTO; // network mode
var websocketCount = 5; // number of concurrent websockets to send the user inputs and receive the display updates (RDP host only, max 100). splitting the load across multiple websockets can help to mitigate network lag. 1 for duplex websocket. CAUTION! IIS on Windows client OSes (7, 8, 10) is limited to 10 simultaneous connections only - across all http sessions - and will hang after that! use Windows Server editions for production environments
var websocketCount = 2; // number of concurrent websockets to send the user inputs and receive the display updates (RDP host only, max 100). splitting the load across multiple websockets can help to mitigate network lag. 1 for duplex websocket. CAUTION! IIS on Windows client OSes (7, 8, 10) is limited to 10 simultaneous connections only - across all http sessions - and will hang after that! use Windows Server editions for production environments
var httpSessionKeepAliveInterval = 30000; // periodical dummy xhr calls (ms) when using websocket, in order to keep the http session alive
var xmlHttpTimeout = 3000; // xmlhttp requests (xhr) timeout (ms)
var longPollingDuration = 60000; // long-polling requests duration (ms)
var bufferEnabled = true; // buffer for user inputs; adjusted dynamically to fit the latency
var bufferDelayBase = 0; // minimal buffering duration (ms)
var bufferDelayEmpty = 10; // buffering duration (ms) when sending empty buffer
var bufferSize = 128; // max number of buffered items (not size in bytes)
var browserPulseInterval = 10000; // periodical browser pulse (ms); used server side to detect if the browser window/tab was closed (and possibly disconnect the remote session before the RDS idle timeout occurs; see "ClientIdleTimeout" into web.config)
var browserPulseInterval = 10000; // periodical browser pulse (ms); used server side to detect if the browser window/tab was closed (and possibly disconnect the remote session before the RDS idle timeout occurs; see "OwnerIdleTimeout" into web.config)

// user
var mouseMoveSamplingRate = 100; // sampling the mouse moves (%) may help to reduce the server load in applications that trigger a lot of updates (i.e.: imaging applications); possible values: 5, 10, 20, 25, 50, 100 (lower = higher drop rate)
Expand Down Expand Up @@ -204,8 +203,7 @@ function Config(
this.setImageQuality = function(quality) { imageQuality = quality; };
this.getImageQuantity = function() { return imageQuantity; };
this.setImageQuantity = function(quantity) { imageQuantity = quantity; };
this.getImageTweakBandwidthLowerThreshold = function() { return imageTweakBandwidthLowerThreshold; };
this.getImageTweakBandwidthHigherThreshold = function() { return imageTweakBandwidthHigherThreshold; };
this.getImageTweakBandwidthThreshold = function() { return imageTweakBandwidthThreshold; };
this.getImageCountOk = function() { return imageCountOk; };
this.getImageCountMax = function() { return imageCountMax; };
this.getImageModeEnum = function() { return imageModeEnum; };
Expand Down
2 changes: 2 additions & 0 deletions Myrtille.Web/js/myrtille.js
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,8 @@ function changeImageQuality(quality)
// display settings are applied by the network.js "tweakDisplay" function
network.setOriginalImageEncoding(config.getImageEncodingEnum().JPEG);
network.setOriginalImageQuality(quality <= 90 ? quality : 90);
network.tweakDisplay(true);
network.setImageTweak(false);
}
catch (exc)
{
Expand Down
Loading

0 comments on commit b996715

Please sign in to comment.