Skip to content

Commit 2823f43

Browse files
committed
version 2.7.0 (see changelog)
1 parent 3191e48 commit 2823f43

File tree

121 files changed

+3469
-1101
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+3469
-1101
lines changed

CHANGELOG

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,42 @@
1-
2019-09-23 Version 2.5.5 (patched)
1+
2019-10-30 Version 2.7.0 (stable)
22
* HOTFIX * fixed a critical issue with FreeRDP (exit code 131085) when using an RD license server configured in "per device" mode, past the 120 days of the RDS grace period
33
updated readme and documentation about the RDS role
4+
the browser "heartbeat" (used to detect if the browser window/tab was closed) is now on a different timer than the periodical fullscreen update (config.js; default 10 secs)
5+
disabled the alt key capture because it may interfere with the browser alt+key menu
6+
keys following the alt+gr modifier are now sent as scancode instead of unicode
7+
ability to configure the login url (by default the myrtille login page; web.config)
8+
updated the installer for a better display of prerequisites
9+
added the option into the installer to choose either to pass the http session ID into url or store it into the default "ASP.NET_SessionId" cookie (the former allows multiple connections/tabs or iframes)
10+
the connection API is now out of beta and installed by default (full auto-connect/start program from url syntax is still available)
11+
the scale feature now keeps the aspect ratio on browser resize
12+
fixed a display refresh issue under chrome + https if the clipboard is empty
13+
increased the image cache duration (1 sec -> 3 secs)
14+
halved the input buffer duration (based on the roundtrip duration)
15+
updated display tweaking
16+
improved cleanup on session disconnect into wfreerdp to prevent memory leaks with GDI+
17+
improved cleanup on session disconnect into Myrtille to prevent memory leaks on the application pool
18+
removed any unnecessary memory allocation and released any disposable object on the application pool
19+
the application pool is now automatically recycled when there is no active remote session (configurable into web.config)
20+
fixed an issue related to the disconnect callback (which was sometimes not received by the gateway due a WCF deadlock)
21+
scripts and styles now have computed hashes to prevent browser caching (in case content is changed); they could also be minified, as needed (see comments in BundleConfig.cs)
22+
re-enabled multiple connections/tabs (web.config, read comments about security)
23+
24+
2019-09-02 Version 2.6.0 (stable)
25+
resynced FreeRDP (2.0.0-dev5)
26+
added a REST API to disconnect a given remote session or all of them (on a gateway)
27+
fixed an issue with some network or domain configuration that could delay the start of a connection
28+
support of Connection Broker database, in High Availability mode
29+
support of RDS API
30+
configurable drain of disconnected sessions
31+
seamless clipboard synchronization, using the async clipboard API (requires Chrome and HTTPS) with fallback to standard web API (for other browsers and HTTP)
32+
now hiding iframe content on browser resize
33+
various mockup improvements
34+
get focus back on main window after a popup is closed
35+
screenshot is now returned as HttpResponseMessage, byte array content
36+
clipboard virtual channel comments and check
37+
the self-signed certificate (installed by myrtille on install) is now issued with the machine FQDN to prevent ERR_CERT_AUTHORITY_INVALID (Subject Alternative Name Missing) in recent Chrome releases
38+
now using a web worker for the periodical fullscreen updates to keep them going even if the main thread is paused (due to inactive window/tab, after focus lost for example)
39+
some refactoring
440

541
2019-06-01 Version 2.5.5 (stable)
642
added audio support (MP3 (default)/WAV, config.js)

DISCLAIMERS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,30 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
996996
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
997997
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
998998

999+
## Cassia
1000+
1001+
MIT License
1002+
1003+
Copyright (c) 2008 - 2017 Dan Ports
1004+
1005+
Permission is hereby granted, free of charge, to any person obtaining a copy
1006+
of this software and associated documentation files (the "Software"), to deal
1007+
in the Software without restriction, including without limitation the rights
1008+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1009+
copies of the Software, and to permit persons to whom the Software is
1010+
furnished to do so, subject to the following conditions:
1011+
1012+
The above copyright notice and this permission notice shall be included in all
1013+
copies or substantial portions of the Software.
1014+
1015+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1016+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1017+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1018+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1019+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1020+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1021+
SOFTWARE.
1022+
9991023
## NAudio
10001024

10011025
Microsoft Public License (Ms-PL)

DOCUMENTATION.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ See the Myrtille.Admin.Web **mockup** to see how to implement Myrtille into your
317317

318318
- in HTML4 mode, data is sent to Myrtille using xhrs; these are limited in size (depends on browser and IIS config), so sending a large block of text with the "keyboard" popup may fail in such a case
319319

320+
- the clipboard synchronization requires Chrome (or async clipboard API support) and HTTPS connection and is limited to text only and 1MB max
321+
320322
## Troubleshoot
321323
First at all, ensure the Myrtille prerequisites are met (IIS 7 or greater (preferably IIS 8+ with websocket protocol enabled) and .NET 4.5+). Note that IIS must be installed separately, before running the installer (see "Installation").
322324

@@ -349,6 +351,9 @@ Also please read notes and limitations above.
349351
- Check the gateway windows event logs, particulary regarding .NET.
350352
- Retry with debug enabled and check logs (into the "log" folder). You can change their verbosity level in config (but be warned it will affect peformance and flood the disk if set too verbose).
351353

354+
- Reconnection on browser resize (toolbar option) doesn't work
355+
- this feature requires the RDS disconnection timeout to be set and greater than 5 secs (to give FreeRDP time to reconnect)
356+
352357
- Some characters/keys are not working as expected
353358
- Keyboard is mapped to english/US layout by default. Try to add that layout to your server (and select it when connected).
354359

Myrtille.Admin.Services/MyrtilleApiHost.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public static class MyrtilleApiHost
3030

3131
public static void Start()
3232
{
33-
var url = "http://*:" + Settings.Default.WebApiPort + "/Myrtille/";
33+
var url = "http://*:" + Settings.Default.WebApiPort + "/MyrtilleAdmin/";
3434
Console.WriteLine($"{DateTime.UtcNow} - Starting Myrtille Admin API at url: " + url);
3535

3636
try

Myrtille.Admin.Services/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("2.5.5.0")]
36-
[assembly: AssemblyFileVersion("2.5.5.0")]
35+
[assembly: AssemblyVersion("2.7.0.0")]
36+
[assembly: AssemblyFileVersion("2.7.0.0")]

Myrtille.Admin.Services/Services/ConnectionService.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public Guid GetConnectionId(ConnectionInfo connectionInfo)
4949
connections.Add(connection.Id, connection);
5050
}
5151

52-
Trace.TraceInformation("new connection: {0}, domain={1}, user={2}, host={3}, vm={4}", connection.Id, connection.Info.User.Domain, connection.Info.User.UserName, connection.Info.Host.IPAddress, connection.Info.VM != null ? connection.Info.VM.Guid.ToString() : string.Empty);
52+
Trace.TraceInformation("GetConnectionId: {0}, domain={1}, user={2}, host={3}, vm={4}", connection.Id, connection.Info.User.Domain, connection.Info.User.UserName, connection.Info.Host.IPAddress, connection.Info.VM != null ? connection.Info.VM.Guid.ToString() : string.Empty);
5353

5454
return connection.Id;
5555
}
@@ -61,12 +61,12 @@ public ConnectionInfo GetConnectionInfo(Guid connectionId)
6161
{
6262
if (connection.InfoAccessed)
6363
{
64-
Trace.TraceWarning("connection: {0}, info was already accessed, access denied", connection.Id);
64+
Trace.TraceWarning("GetConnectionInfo: {0}, info was already accessed, access denied", connection.Id);
6565
return null;
6666
}
6767

6868
connection.InfoAccessed = true;
69-
Trace.TraceInformation("connection: {0}, domain={1}, user={2}, host={3}, vm={4}", connection.Id, connection.Info.User.Domain, connection.Info.User.UserName, connection.Info.Host.IPAddress, connection.Info.VM != null ? connection.Info.VM.Guid.ToString() : string.Empty);
69+
Trace.TraceInformation("GetConnectionInfo: {0}, domain={1}, user={2}, host={3}, vm={4}", connection.Id, connection.Info.User.Domain, connection.Info.User.UserName, connection.Info.Host.IPAddress, connection.Info.VM != null ? connection.Info.VM.Guid.ToString() : string.Empty);
7070
return connection.Info;
7171
}
7272
else
@@ -78,13 +78,15 @@ public ConnectionInfo GetConnectionInfo(Guid connectionId)
7878

7979
public bool IsUserAllowedToConnectHost(string domain, string userName, string hostIPAddress, Guid VMGuid)
8080
{
81+
// this method is just an empty shell
82+
// have your own implementation to allow or deny user access to a given host
8183
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(hostIPAddress))
8284
{
83-
Trace.TraceInformation("access granted: domain={0}, user={1}, host={2}, vm={3}", domain, userName, hostIPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty);
85+
Trace.TraceInformation("IsUserAllowedToConnectHost, access granted: domain={0}, user={1}, host={2}, vm={3}", domain, userName, hostIPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty);
8486
return true;
8587
}
8688

87-
Trace.TraceInformation("access denied: domain={0}, user={1}, host={2}, vm={3}", domain, userName, hostIPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty);
89+
Trace.TraceInformation("IsUserAllowedToConnectHost, access denied: domain={0}, user={1}, host={2}, vm={3}", domain, userName, hostIPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty);
8890
return false;
8991
}
9092

@@ -93,7 +95,7 @@ public bool SetConnectionState(Guid connectionId, string IPAddress, Guid VMGuid,
9395
var connection = connections[connectionId] as Connection;
9496
if (connection != null)
9597
{
96-
Trace.TraceInformation("connection: {0}, ip={1}, vm={2}, state={3}", connectionId, IPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty, state);
98+
Trace.TraceInformation("SetConnectionState: {0}, ip={1}, vm={2}, state={3}", connectionId, IPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty, state);
9799
connection.State = state;
98100
return true;
99101
}
@@ -107,7 +109,7 @@ public bool SetConnectionExitCode(Guid connectionId, string IPAddress, Guid VMGu
107109
var connection = connections[connectionId] as Connection;
108110
if (connection != null)
109111
{
110-
Trace.TraceInformation("connection: {0}, ip={1}, vm={2}, exit code={3}", connectionId, IPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty, exitCode);
112+
Trace.TraceInformation("SetConnectionExitCode: {0}, ip={1}, vm={2}, exit code={3}", connectionId, IPAddress, VMGuid != Guid.Empty ? VMGuid.ToString() : string.Empty, exitCode);
111113
connection.ExitCode = exitCode;
112114
return true;
113115
}

Myrtille.Admin.Services/ServicesInstaller.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private void InitializeComponent()
5353
this.serviceInstaller = new ServiceInstaller();
5454
this.serviceInstaller.ServiceName = "Myrtille.Admin.Services";
5555
this.serviceInstaller.Description = "Myrtille Admin API";
56-
this.serviceInstaller.StartType = ServiceStartMode.Manual;
56+
this.serviceInstaller.StartType = ServiceStartMode.Automatic;
5757

5858
this.Installers.AddRange(new Installer[] {
5959
this.serviceProcessInstaller,
@@ -156,10 +156,6 @@ public override void Uninstall(
156156

157157
private void StartService()
158158
{
159-
// the connection api wasn't requested
160-
if (string.IsNullOrEmpty(Context.Parameters["CONNECTIONAPI"]))
161-
return;
162-
163159
Context.LogMessage("Starting Myrtille.Admin.Services");
164160

165161
// try to start the service
@@ -193,10 +189,6 @@ private void StartService()
193189

194190
private void StopService()
195191
{
196-
// the connection api wasn't requested
197-
if (string.IsNullOrEmpty(Context.Parameters["CONNECTIONAPI"]))
198-
return;
199-
200192
Context.LogMessage("Stopping Myrtille.Admin.Services");
201193

202194
// if the service is running while uninstall is going on, the user is asked wether to stop it or not

Myrtille.Admin.Web/Default.aspx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,49 @@
3232
<div align="left">
3333
<input type="hidden" runat="server" id="_guestId" />
3434
<input type="hidden" runat="server" id="_allowControl" />
35-
<input type="button" runat="server" id="AddGuestButton" value="Add a guest" data-fid="myrtille_1" onclick="_allowControl.value = prompt('Grant control to guest?', 'true');" onserverclick="AddGuestButtonClick"/><br />
36-
<input type="button" runat="server" id="GetGuestsButton" value="Show guests list" data-fid="myrtille_1" onserverclick="GetGuestsButtonClick"/><br />
37-
<input type="button" runat="server" id="GetGuestButton" value="Show guest info" onclick="_guestId.value = prompt('Enter guest id', 'guid');" onserverclick="GetGuestButtonClick"/><br />
38-
<input type="button" runat="server" id="UpdateGuestButton" value="Update a guest" onclick="_guestId.value = prompt('Enter guest id', 'guid'); if (_guestId.value) { _allowControl.value = prompt('Grant control to guest?', 'true'); }" onserverclick="UpdateGuestButtonClick"/><br />
39-
<input type="button" runat="server" id="RemoveGuestButton" value="Remove a guest" onclick="_guestId.value = prompt('Enter guest id', 'guid');" onserverclick="RemoveGuestButtonClick"/><br />
35+
<input type="button" runat="server" id="AddGuestButton" value="Add a guest" data-fid="myrtille_1" onclick="_allowControl.value = prompt('Grant control to guest?', 'true');" onserverclick="AddGuestButtonClick" disabled="disabled"/><br />
36+
<input type="button" runat="server" id="GetGuestsButton" value="Show guests list" data-fid="myrtille_1" onserverclick="GetGuestsButtonClick" disabled="disabled"/><br />
37+
<input type="button" runat="server" id="GetGuestButton" value="Show guest info" data-fid="myrtille_1" onclick="_guestId.value = prompt('Enter guest id', 'guid');" onserverclick="GetGuestButtonClick" disabled="disabled"/><br />
38+
<input type="button" runat="server" id="UpdateGuestButton" value="Update a guest" data-fid="myrtille_1" onclick="_guestId.value = prompt('Enter guest id', 'guid'); if (_guestId.value) { _allowControl.value = prompt('Grant control to guest?', 'true'); }" onserverclick="UpdateGuestButtonClick" disabled="disabled"/><br />
39+
<input type="button" runat="server" id="RemoveGuestButton" value="Remove a guest" data-fid="myrtille_1" onclick="_guestId.value = prompt('Enter guest id', 'guid');" onserverclick="RemoveGuestButtonClick" disabled="disabled"/><br />
4040
</div>
4141

4242
<br />
4343

4444
<div align="left">
45-
<!-- relative iframe size: session is reconnected on browser resize (adjusting to screen) -->
46-
<iframe runat="server" id="myrtille_1" name="myrtille_1"></iframe><br />
45+
<div class="iframeOverlayOuter">
46+
<canvas id="myrtille_1_overlay" class="iframeOverlayInner" width="0" height="0"></canvas>
47+
<!-- relative iframe size: session is reconnected on browser resize (adjusting to screen) -->
48+
<iframe runat="server" id="myrtille_1" name="myrtille_1"></iframe><br />
49+
</div>
4750
<span>^ relative iframe size (resized on browser resize)</span><br />
48-
<input type="button" runat="server" id="SetScreenshotConfigButton" value="screenshot config (click first)" data-fid="myrtille_1" onserverclick="SetScreenshotConfigButtonClick"/><br />&nbsp;Screenshots will be saved into C:\path\to\screenshots on this machine<br />
49-
<input type="button" runat="server" id="StartTakingScreenshotsButton" value="start taking screenshots" data-fid="myrtille_1" onserverclick="StartTakingScreenshotsButtonClick"/><br />
50-
<input type="button" runat="server" id="StopTakingScreenshotsButton" value="stop taking screenshots" data-fid="myrtille_1" onserverclick="StopTakingScreenshotsButtonClick"/><br />
51-
<input type="button" runat="server" id="TakeScreenshotButton" value="take screenshot" data-fid="myrtille_1" onserverclick="TakeScreenshotButtonClick"/>
51+
<input type="button" runat="server" id="SetScreenshotConfigButton" value="screenshot config (click first)" data-fid="myrtille_1" onserverclick="SetScreenshotConfigButtonClick" disabled="disabled"/><br />&nbsp;Screenshots will be saved into C:\path\to\screenshots on this machine<br />
52+
<input type="button" runat="server" id="StartTakingScreenshotsButton" value="start taking screenshots" data-fid="myrtille_1" onserverclick="StartTakingScreenshotsButtonClick" disabled="disabled"/><br />
53+
<input type="button" runat="server" id="StopTakingScreenshotsButton" value="stop taking screenshots" data-fid="myrtille_1" onserverclick="StopTakingScreenshotsButtonClick" disabled="disabled"/><br />
54+
<input type="button" runat="server" id="TakeScreenshotButton" value="take screenshot" data-fid="myrtille_1" onserverclick="TakeScreenshotButtonClick" disabled="disabled"/>
55+
</div>
56+
57+
<div align="left">
58+
<input type="button" runat="server" id="myrtille_1_disconnect" value="Disconnect" data-fid="myrtille_1" onserverclick="DisconnectButtonClick" disabled="disabled"/>
5259
</div>
5360

5461
<hr/>
5562

5663
<div align="left">
57-
<!-- fixed iframe size -->
64+
<!-- fixed iframe size (no need for an overlay) -->
5865
<iframe runat="server" id="myrtille_2" name="myrtille_2"></iframe><br />
5966
<span>^ fixed iframe size</span>
6067
</div>
68+
69+
<div align="left">
70+
<input type="button" runat="server" id="myrtille_2_disconnect" value="Disconnect" data-fid="myrtille_2" onserverclick="DisconnectButtonClick" disabled="disabled"/>
71+
</div>
72+
73+
<hr/>
74+
75+
<div align="left">
76+
<input type="button" runat="server" id="Logout" value="Logout" onserverclick="LogoutButtonClick" disabled="disabled"/>
77+
</div>
6178

6279
</form>
6380

0 commit comments

Comments
 (0)