From bce4f7dc441d70068f455af00684dec1da31fb81 Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Tue, 10 Mar 2020 20:19:47 -0700 Subject: [PATCH] Added automatic reconnect for GUI clients. --- .../ViewModels/MainWindowViewModel.cs | 31 ++++++ Desktop.Win/ViewModels/MainWindowViewModel.cs | 98 ++++++++++++------- ScreenCast.Core/Capture/ScreenCasterBase.cs | 2 +- ScreenCast.Core/Communication/CasterSocket.cs | 15 +-- ScreenCast.Win/Program.cs | 2 +- 5 files changed, 104 insertions(+), 44 deletions(-) diff --git a/Desktop.Linux/ViewModels/MainWindowViewModel.cs b/Desktop.Linux/ViewModels/MainWindowViewModel.cs index b7e949a9..f00aa4fd 100644 --- a/Desktop.Linux/ViewModels/MainWindowViewModel.cs +++ b/Desktop.Linux/ViewModels/MainWindowViewModel.cs @@ -149,8 +149,31 @@ namespace Remotely.Desktop.Linux.ViewModels await PromptForHostName(); } Conductor.ProcessArgs(new string[] { "-mode", "Normal", "-host", Host }); + await Conductor.Connect(); + Conductor.CasterSocket.Connection.Closed += async (ex) => + { + await Dispatcher.UIThread.InvokeAsync(() => + { + SessionID = "Disconnected"; + }); + }; + + Conductor.CasterSocket.Connection.Reconnecting += async (ex) => + { + await Dispatcher.UIThread.InvokeAsync(() => + { + SessionID = "Reconnecting"; + }); + }; + + Conductor.CasterSocket.Connection.Reconnected += async (arg) => + { + await GetSessionID(); + }; + + await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID); await Conductor.CasterSocket.GetSessionID(); } @@ -162,6 +185,13 @@ namespace Remotely.Desktop.Linux.ViewModels } } + public async Task GetSessionID() + { + await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID); + await Conductor.CasterSocket.GetSessionID(); + } + + public async Task PromptForHostName() { var prompt = new HostNamePrompt(); @@ -205,6 +235,7 @@ namespace Remotely.Desktop.Linux.ViewModels ServiceContainer.Instance = serviceCollection.BuildServiceProvider(); } + private void ScreenCastRequested(object sender, ScreenCastRequest screenCastRequest) { Dispatcher.UIThread.InvokeAsync(async () => diff --git a/Desktop.Win/ViewModels/MainWindowViewModel.cs b/Desktop.Win/ViewModels/MainWindowViewModel.cs index 76139cfc..75873b6e 100644 --- a/Desktop.Win/ViewModels/MainWindowViewModel.cs +++ b/Desktop.Win/ViewModels/MainWindowViewModel.cs @@ -64,39 +64,6 @@ namespace Remotely.Desktop.Win.ViewModels public Conductor Conductor { get; } public CursorIconWatcher CursorIconWatcher { get; private set; } - public string Host - { - get => host; - set - { - host = value; - FirePropertyChanged("Host"); - } - } - - public bool IsAdministrator => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); - - public ICommand RemoveViewersCommand - { - get - { - return new Executor(async (param) => - { - foreach (Viewer viewer in (param as IList).ToArray()) - { - viewer.DisconnectRequested = true; - ViewerRemoved(this, viewer.ViewerConnectionID); - await Conductor.CasterSocket.SendViewerRemoved(viewer.ViewerConnectionID); - } - }, - (param) => - { - return (param as IList)?.Count > 0; - }); - } - - } - public ICommand ElevateToAdminCommand { get @@ -151,6 +118,38 @@ namespace Remotely.Desktop.Win.ViewModels } } + public string Host + { + get => host; + set + { + host = value; + FirePropertyChanged("Host"); + } + } + + public bool IsAdministrator => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); + + public ICommand RemoveViewersCommand + { + get + { + return new Executor(async (param) => + { + foreach (Viewer viewer in (param as IList).ToArray()) + { + viewer.DisconnectRequested = true; + ViewerRemoved(this, viewer.ViewerConnectionID); + await Conductor.CasterSocket.SendViewerRemoved(viewer.ViewerConnectionID); + } + }, + (param) => + { + return (param as IList)?.Count > 0; + }); + } + + } public string SessionID { get => sessionID; @@ -184,6 +183,30 @@ namespace Remotely.Desktop.Win.ViewModels try { await Conductor.Connect(); + + + Conductor.CasterSocket.Connection.Closed += async (ex) => + { + App.Current.Dispatcher.Invoke(() => + { + SessionID = "Disconnected"; + }); + }; + + Conductor.CasterSocket.Connection.Reconnecting += async (ex) => + { + App.Current.Dispatcher.Invoke(() => + { + SessionID = "Reconnecting"; + }); + }; + + Conductor.CasterSocket.Connection.Reconnected += async (arg) => + { + await GetSessionID(); + }; + + await GetSessionID(); } catch (Exception ex) { @@ -191,7 +214,10 @@ namespace Remotely.Desktop.Win.ViewModels MessageBox.Show(Application.Current.MainWindow, "Failed to connect to server.", "Connection Failed", MessageBoxButton.OK, MessageBoxImage.Warning); return; } + } + public async Task GetSessionID() + { await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID); await Conductor.CasterSocket.GetSessionID(); } @@ -235,7 +261,8 @@ namespace Remotely.Desktop.Win.ViewModels serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddTransient(provider => { + serviceCollection.AddTransient(provider => + { try { var dxCapture = new DXCapture(); @@ -259,9 +286,10 @@ namespace Remotely.Desktop.Win.ViewModels ServiceContainer.Instance = serviceCollection.BuildServiceProvider(); } + private async void CursorIconWatcher_OnChange(object sender, CursorInfo cursor) { - if (Conductor?.CasterSocket != null && Conductor?.Viewers?.Count > 0) + if (Conductor?.CasterSocket?.IsConnected == true && Conductor?.Viewers?.Count > 0) { await Conductor?.CasterSocket?.SendCursorChange(cursor, Conductor.Viewers.Keys.ToList()); } diff --git a/ScreenCast.Core/Capture/ScreenCasterBase.cs b/ScreenCast.Core/Capture/ScreenCasterBase.cs index 50d70cb3..c678312d 100644 --- a/ScreenCast.Core/Capture/ScreenCasterBase.cs +++ b/ScreenCast.Core/Capture/ScreenCasterBase.cs @@ -71,7 +71,7 @@ namespace Remotely.ScreenCast.Core.Capture await casterSocket.SendScreenSize(bounds.Width, bounds.Height, viewerID); }; - while (!viewer.DisconnectRequested) + while (!viewer.DisconnectRequested && casterSocket.IsConnected) { try { diff --git a/ScreenCast.Core/Communication/CasterSocket.cs b/ScreenCast.Core/Communication/CasterSocket.cs index 0ef59193..008c1284 100644 --- a/ScreenCast.Core/Communication/CasterSocket.cs +++ b/ScreenCast.Core/Communication/CasterSocket.cs @@ -35,16 +35,16 @@ namespace Remotely.ScreenCast.Core.Communication ClipboardService.ClipboardTextChanged += ClipboardService_ClipboardTextChanged; } + public bool IsConnected => Connection?.State == HubConnectionState.Connected; public IScreenCaster ScreenCaster { get; } private IAudioCapturer AudioCapturer { get; } private IClipboardService ClipboardService { get; } - private HubConnection Connection { get; set; } + public HubConnection Connection { get; private set; } private IKeyboardMouseInput KeyboardMouseInput { get; } - public async Task Connect(string host) { if (Connection != null) @@ -55,6 +55,7 @@ namespace Remotely.ScreenCast.Core.Communication Connection = new HubConnectionBuilder() .WithUrl($"{host}/RCDeviceHub") .AddMessagePackProtocol() + .WithAutomaticReconnect() .Build(); ApplyConnectionHandlers(); @@ -108,6 +109,11 @@ namespace Remotely.ScreenCast.Core.Communication await Connection.SendAsync("ReceiveDeviceInfo", serviceID, machineName, deviceID); } + public async Task SendIceCandidateToBrowser(string candidate, int sdpMlineIndex, string sdpMid, string viewerConnectionID) + { + await Connection.SendAsync("SendIceCandidateToBrowser", candidate, sdpMlineIndex, sdpMid, viewerConnectionID); + } + public async Task SendMachineName(string machineName, string viewerID) { await Connection.SendAsync("SendMachineName", machineName, viewerID); @@ -137,11 +143,6 @@ namespace Remotely.ScreenCast.Core.Communication { await Connection.SendAsync("SendViewerRemoved", viewerID); } - - public async Task SendIceCandidateToBrowser(string candidate, int sdpMlineIndex, string sdpMid, string viewerConnectionID) - { - await Connection.SendAsync("SendIceCandidateToBrowser", candidate, sdpMlineIndex, sdpMid, viewerConnectionID); - } private void ApplyConnectionHandlers() { var conductor = ServiceContainer.Instance.GetRequiredService(); diff --git a/ScreenCast.Win/Program.cs b/ScreenCast.Win/Program.cs index cb2da996..41ad74c7 100644 --- a/ScreenCast.Win/Program.cs +++ b/ScreenCast.Win/Program.cs @@ -27,7 +27,7 @@ namespace Remotely.ScreenCast.Win } public static async void CursorIconWatcher_OnChange(object sender, CursorInfo cursor) { - if (Conductor?.CasterSocket != null) + if (Conductor?.CasterSocket?.IsConnected == true) { await Conductor.CasterSocket.SendCursorChange(cursor, Conductor.Viewers.Keys.ToList()); }