Skip to content

Commit

Permalink
Add configurable IceServers and concurrent update count.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Apr 29, 2020
1 parent 4215d16 commit f9a0a53
Show file tree
Hide file tree
Showing 19 changed files with 126 additions and 52 deletions.
10 changes: 7 additions & 3 deletions ScreenCast.Core/Communication/CasterSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ public async Task Disconnect()
await Connection.DisposeAsync();
}

public async Task<IceServerModel[]> GetIceServers()
{
return await Connection.InvokeAsync<IceServerModel[]>("GetIceServers");
}

public async Task GetSessionID()
{
await Connection.SendAsync("GetSessionID");
}

public async Task NotifyRequesterUnattendedReady(string requesterID)
{
await Connection.SendAsync("NotifyRequesterUnattendedReady", requesterID);
Expand Down Expand Up @@ -127,9 +131,9 @@ public async Task SendMachineName(string machineName, string viewerID)
await Connection.SendAsync("SendMachineName", machineName, viewerID);
}

public async Task SendRtcOfferToBrowser(string sdp, string viewerID)
public async Task SendRtcOfferToBrowser(string sdp, string viewerID, IceServerModel[] iceServers)
{
await Connection.SendAsync("SendRtcOfferToBrowser", sdp, viewerID);
await Connection.SendAsync("SendRtcOfferToBrowser", sdp, viewerID, iceServers);
}

public async Task SendScreenCapture(byte[] captureBytes, string viewerID, int left, int top, int width, int height, int imageQuality)
Expand Down
21 changes: 14 additions & 7 deletions ScreenCast.Core/Communication/WebRtcSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public WebRtcSession(IRtcMessageHandler rtcMessageHandler)
public bool IsPeerConnected => PeerConnection?.IsConnected == true;
private DataChannel CaptureChannel { get; set; }
private PeerConnection PeerConnection { get; set; }
private IceServerModel[] IceServers { get; set; }
private IRtcMessageHandler RtcMessageHandler { get; }
public void AddIceCandidate(string sdpMid, int sdpMlineIndex, string candidate)
{
Expand All @@ -38,18 +39,24 @@ public void Dispose()
PeerConnection?.Dispose();
}

public async Task Init()
public async Task Init(IceServerModel[] iceServers)
{
Logger.Debug("Starting WebRTC connection.");

IceServers = iceServers;

PeerConnection = new PeerConnection();

var iceList = IceServers.Select(x => new IceServer()
{
Urls = { x.Url },
TurnPassword = x.TurnPassword ?? string.Empty,
TurnUserName = x.TurnUsername ?? string.Empty
}).ToList();

var config = new PeerConnectionConfiguration()
{
IceServers = new List<IceServer>
{
new IceServer{ Urls = { "stun:stun.l.google.com:19302" } },
new IceServer{ Urls = { "stun:stun4.l.google.com:19302" } }
}
IceServers = iceList
};

await PeerConnection.InitializeAsync(config);
Expand Down Expand Up @@ -139,7 +146,7 @@ private async void CaptureChannel_StateChanged()
Logger.Debug($"DataChannel state changed. New State: {CaptureChannel.State}");
if (CaptureChannel.State == DataChannel.ChannelState.Closed)
{
await Init();
await Init(IceServers);
}
}
private void DataChannel_BufferingChanged(ulong previous, ulong current, ulong limit)
Expand Down
10 changes: 5 additions & 5 deletions ScreenCast.Core/Models/Viewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@ public Viewer(CasterSocket casterSocket,
public IScreenCapturer Capturer { get; }

public bool DisconnectRequested { get; set; }

public EncoderParameters EncoderParams { get; private set; }

public bool HasControl { get; set; } = true;

public int ImageQuality
{
get
Expand Down Expand Up @@ -81,16 +78,19 @@ public async Task InitializeWebRtc()
{
try
{
var iceServers = await CasterSocket.GetIceServers();

RtcSession = WebRtcSessionFactory.GetNewSession(this);
RtcSession.LocalSdpReady += async (sender, sdp) =>
{
await CasterSocket.SendRtcOfferToBrowser(sdp, ViewerConnectionID);
await CasterSocket.SendRtcOfferToBrowser(sdp, ViewerConnectionID, iceServers);
};
RtcSession.IceCandidateReady += async (sender, args) =>
{
await CasterSocket.SendIceCandidateToBrowser(args.candidate, args.sdpMlineIndex, args.sdpMid, ViewerConnectionID);
};
await RtcSession.Init();

await RtcSession.Init(iceServers);
}
catch (Exception ex)
{
Expand Down
3 changes: 2 additions & 1 deletion ScreenCast.Core/Services/ScreenCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace Remotely.ScreenCast.Core.Services
{
public class ScreenCaster : IScreenCaster
{
public ScreenCaster(Conductor conductor, ICursorIconWatcher cursorIconWatcher)
public ScreenCaster(Conductor conductor,
ICursorIconWatcher cursorIconWatcher)
{
Conductor = conductor;
CursorIconWatcher = cursorIconWatcher;
Expand Down
13 changes: 10 additions & 3 deletions Server/API/AgentUpdateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ public class AgentUpdateController : ControllerBase
private static readonly MemoryCache downloadingAgents = new MemoryCache(new MemoryCacheOptions());


public AgentUpdateController(IWebHostEnvironment hostingEnv, DataService dataService)
public AgentUpdateController(IWebHostEnvironment hostingEnv,
DataService dataService,
ApplicationConfig appConfig)
{
this.HostEnv = hostingEnv;
HostEnv = hostingEnv;
DataService = dataService;
AppConfig = appConfig;
}

private DataService DataService { get; }
public ApplicationConfig AppConfig { get; }
private IWebHostEnvironment HostEnv { get; }


Expand Down Expand Up @@ -50,10 +54,13 @@ public async Task<ActionResult> DownloadPackage(string platform, string download
{
try
{
while (downloadingAgents.Count > 10)
var startWait = DateTimeOffset.Now;
while (downloadingAgents.Count > AppConfig.MaxConcurrentUpdates)
{
await Task.Delay(new Random().Next(100, 10000));
}
var waitTime = DateTimeOffset.Now - startWait;
DataService.WriteEvent($"Download started after wait time of {waitTime}.", Shared.Models.EventType.Debug, string.Empty);

downloadingAgents.Set(downloadId, string.Empty, TimeSpan.FromMinutes(10));

Expand Down
2 changes: 2 additions & 0 deletions Server/Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<Content Remove="wwwroot\scripts\Models\Device.ts" />
<Content Remove="wwwroot\scripts\Models\DynamicDtoType.ts" />
<Content Remove="wwwroot\scripts\Models\GenericCommandResult.ts" />
<Content Remove="wwwroot\scripts\Models\IceServerModel.ts" />
<Content Remove="wwwroot\scripts\Models\Parameter.ts" />
<Content Remove="wwwroot\scripts\Models\Point.ts" />
<Content Remove="wwwroot\scripts\RemoteControl\MessageSender.ts" />
Expand Down Expand Up @@ -157,6 +158,7 @@
<TypeScriptCompile Include="wwwroot\scripts\Models\CommandLineParameter.ts" />
<TypeScriptCompile Include="wwwroot\scripts\Models\ConsoleCommand.ts" />
<TypeScriptCompile Include="wwwroot\scripts\Enums\DynamicDtoType.ts" />
<TypeScriptCompile Include="wwwroot\scripts\Models\IceServerModel.ts" />
<TypeScriptCompile Include="wwwroot\scripts\RemoteControl\MessageSender.ts" />
<TypeScriptCompile Include="wwwroot\scripts\Models\Point.ts" />
<TypeScriptCompile Include="wwwroot\scripts\Models\UserOptions.ts" />
Expand Down
36 changes: 23 additions & 13 deletions Server/Services/ApplicationConfig.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
using Microsoft.Extensions.Configuration;
using Remotely.Shared.Models;

namespace Remotely.Server.Services
{
public class ApplicationConfig
{
private IceServerModel[] fallbackIceServers = new IceServerModel[]
{
new IceServerModel() { Url = "stun: stun.l.google.com:19302"},
new IceServerModel() { Url = "stun: stun4.l.google.com:19302"}
};

public ApplicationConfig(IConfiguration config)
{
Config = config;
}
public bool AllowApiLogin => bool.Parse(Config["ApplicationOptions:AllowApiLogin"]);
public double DataRetentionInDays => double.Parse(Config["ApplicationOptions:DataRetentionInDays"]);
public string DBProvider => Config["ApplicationOptions:DBProvider"];
public string DefaultPrompt => Config["ApplicationOptions:DefaultPrompt"];

public bool AllowApiLogin => bool.Parse(Config["ApplicationOptions:AllowApiLogin"] ?? "false");
public double DataRetentionInDays => double.Parse(Config["ApplicationOptions:DataRetentionInDays"] ?? "30");
public string DBProvider => Config["ApplicationOptions:DBProvider"] ?? "SQLite";
public string DefaultPrompt => Config["ApplicationOptions:DefaultPrompt"] ?? "~>";
public bool EnableWindowsEventLog => bool.Parse(Config["ApplicationOptions:EnableWindowsEventLog"]);
public IceServerModel[] IceServers => Config.GetSection("ApplicationOptions:IceServers").Get<IceServerModel[]>() ?? fallbackIceServers;
public string[] KnownProxies => Config.GetSection("ApplicationOptions:KnownProxies").Get<string[]>();
public int MaxOrganizationCount => int.Parse(Config["ApplicationOptions:MaxOrganizationCount"]);
public bool RecordRemoteControlSessions => bool.Parse(Config["ApplicationOptions:RecordRemoteControlSessions"]);
public bool RedirectToHttps => bool.Parse(Config["ApplicationOptions:RedirectToHttps"]);
public bool RemoteControlRequiresAuthentication => bool.Parse(Config["ApplicationOptions:RemoteControlRequiresAuthentication"]);
public double RemoteControlSessionLimit => double.Parse(Config["ApplicationOptions:RemoteControlSessionLimit"]);
public bool Require2FA => bool.Parse(Config["ApplicationOptions:Require2FA"]);
public int MaxConcurrentUpdates => int.Parse(Config["ApplicationOptions:MaxConcurrentUpdates"] ?? "10");
public int MaxOrganizationCount => int.Parse(Config["ApplicationOptions:MaxOrganizationCount"] ?? "1");
public bool RecordRemoteControlSessions => bool.Parse(Config["ApplicationOptions:RecordRemoteControlSessions"] ?? "false");
public bool RedirectToHttps => bool.Parse(Config["ApplicationOptions:RedirectToHttps"] ?? "false");
public bool RemoteControlRequiresAuthentication => bool.Parse(Config["ApplicationOptions:RemoteControlRequiresAuthentication"] ?? "true");
public double RemoteControlSessionLimit => double.Parse(Config["ApplicationOptions:RemoteControlSessionLimit"] ?? "3");
public bool Require2FA => bool.Parse(Config["ApplicationOptions:Require2FA"] ?? "false");
public string SmtpDisplayName => Config["ApplicationOptions:SmtpDisplayName"];
public string SmtpEmail => Config["ApplicationOptions:SmtpEmail"];
public bool SmtpEnableSsl => bool.Parse(Config["ApplicationOptions:SmtpEnableSsl"]);
public bool SmtpEnableSsl => bool.Parse(Config["ApplicationOptions:SmtpEnableSsl"] ?? "true");
public string SmtpHost => Config["ApplicationOptions:SmtpHost"];
public string SmtpPassword => Config["ApplicationOptions:SmtpPassword"];
public int SmtpPort => int.Parse(Config["ApplicationOptions:SmtpPort"]);
public string SmtpUserName => Config["ApplicationOptions:SmtpUserName"];
public string Theme => Config["ApplicationOptions:Theme"];
public string[] TrustedCorsOrigins => Config.GetSection("ApplicationOptions:TrustedCorsOrigins").Get<string[]>();
public bool UseHsts => bool.Parse(Config["ApplicationOptions:UseHsts"]);
public bool UseWebRtc => bool.Parse(Config["ApplicationOptions:UseWebRtc"]);
public bool UseHsts => bool.Parse(Config["ApplicationOptions:UseHsts"] ?? "false");
public bool UseWebRtc => bool.Parse(Config["ApplicationOptions:UseWebRtc"] ?? "true");
private IConfiguration Config { get; set; }
}
}
9 changes: 7 additions & 2 deletions Server/Services/RCDeviceHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ public Task CtrlAltDel()
{
return DeviceHubContext.Clients.Client(SessionInfo.ServiceID).SendAsync("CtrlAltDel");
}
public IceServerModel[] GetIceServers()
{
return AppConfig.IceServers;
}

public Task GetSessionID()
{
var random = new Random();
Expand Down Expand Up @@ -186,11 +191,11 @@ public Task SendMachineName(string machineName, string viewerID)
return RCBrowserHubContext.Clients.Client(viewerID).SendAsync("ReceiveMachineName", machineName);
}

public Task SendRtcOfferToBrowser(string sdp, string viewerID)
public Task SendRtcOfferToBrowser(string sdp, string viewerID, IceServerModel[] iceServers)
{
if (AppConfig.UseWebRtc)
{
return RCBrowserHubContext.Clients.Client(viewerID).SendAsync("ReceiveRtcOffer", sdp);
return RCBrowserHubContext.Clients.Client(viewerID).SendAsync("ReceiveRtcOffer", sdp, iceServers);
}

return Task.CompletedTask;
Expand Down
9 changes: 7 additions & 2 deletions Server/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@
},
"ApplicationOptions": {
"AllowApiLogin": false,
"MaxOrganizationCount": 1,
"DataRetentionInDays": 90,
"DBProvider": "SQLite",
"DefaultPrompt": "~>",
"EnableWindowsEventLog": false,
"IceServers": [
{ "Url": "stun: stun.l.google.com:19302" },
{ "Url": "stun: stun4.l.google.com:19302" }
],
"KnownProxies": [],
"MaxConcurrentUpdates": 10,
"MaxOrganizationCount": 1,
"RecordRemoteControlSessions": false,
"RedirectToHttps": false,
"RemoteControlSessionLimit": 1,
"RemoteControlSessionLimit": 3,
"RemoteControlRequiresAuthentication": true,
"Require2FA": false,
"SmtpHost": "",
Expand Down
3 changes: 3 additions & 0 deletions Server/wwwroot/scripts/Models/IceServerModel.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Server/wwwroot/scripts/Models/IceServerModel.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Server/wwwroot/scripts/Models/IceServerModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class IceServerModel {
Url: string;
TurnPassword: string;
TurnUsername: string;
}
4 changes: 2 additions & 2 deletions Server/wwwroot/scripts/RemoteControl/RCHubConnection.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f9a0a53

Please sign in to comment.