Skip to content

Commit

Permalink
Fixes issue #93 - Remote callback channel times out with SessionKeyEx…
Browse files Browse the repository at this point in the history
…piredException
  • Loading branch information
ryannewington committed Jan 9, 2018
1 parent f562c85 commit e8fec9f
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 9 deletions.
5 changes: 5 additions & 0 deletions src/Lithnet.Miiserver.AutoSync/EventService/EventClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public MAStatus GetFullUpdate(Guid managementAgentID)
return this.Channel.GetFullUpdate(managementAgentID);
}

public bool Ping(Guid managementAgentID)
{
return this.Channel.Ping(managementAgentID);
}

public static EventClient GetNamedPipesClient(InstanceContext ctx)
{
return new EventClient(ctx, EventServiceConfiguration.NetNamedPipeBinding, EventServiceConfiguration.NetNamedPipeEndpointAddress);
Expand Down
37 changes: 36 additions & 1 deletion src/Lithnet.Miiserver.AutoSync/EventService/EventService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public void Register(Guid managementAgentID)
commObj.Closed += EventService.CommObj_Closed;
}

logger.Trace($"Registered callback channel for {name}/{managementAgentID}");
logger.Trace($"Registered callback channel for {name}/{managementAgentID} on client {EventService.RemoteHost}");
}
catch (Exception ex)
{
Expand All @@ -163,6 +163,41 @@ public void Register(Guid managementAgentID)
}
}

public bool Ping(Guid managementAgentID)
{
IEventCallBack subscriber = OperationContext.Current.GetCallbackChannel<IEventCallBack>();

if (EventService.subscribers.ContainsKey(managementAgentID))
{
if (EventService.subscribers[managementAgentID].Contains(subscriber))
{
// Still registered
logger.Trace($"Client ping succeeded for {managementAgentID} at {EventService.RemoteHost}");
return true;
}
}

logger.Warn($"Client ping failed for {managementAgentID} at {EventService.RemoteHost}. Client is no longer registered.");

// Not registered
return false;
}

private static string RemoteHost
{
get
{
RemoteEndpointMessageProperty remoteEndpoint = OperationContext.Current?.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;

if (remoteEndpoint == null)
{
return null;
}

return $"{remoteEndpoint?.Address}:{remoteEndpoint?.Port}";
}
}

private static void CommObj_Closed(object sender, EventArgs e)
{
EventService.DeregisterCallbackChannel(sender);
Expand Down
3 changes: 3 additions & 0 deletions src/Lithnet.Miiserver.AutoSync/EventService/IEventService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ public interface IEventService

[OperationContract()]
MAStatus GetFullUpdate(Guid managementAgentID);

[OperationContract]
bool Ping(Guid managementAgentID);
}
}
17 changes: 12 additions & 5 deletions src/Lithnet.Miiserver.Autosync.UI/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public App()
{
AppDomain.CurrentDomain.UnhandledException += this.CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += this.TaskScheduler_UnobservedTaskException;
Application.Current.DispatcherUnhandledException += this.Dispatcher_UnhandledException;
Application.Current.DispatcherUnhandledException += this.Dispatcher_UnhandledException;

#if DEBUG
if (Debugger.IsAttached)
Expand Down Expand Up @@ -105,7 +105,7 @@ public App()

private void ShowDummyWindow()
{
Window t = new Window() {AllowsTransparency = true, ShowInTaskbar = false, WindowStyle = WindowStyle.None, Background = Brushes.Transparent};
Window t = new Window() { AllowsTransparency = true, ShowInTaskbar = false, WindowStyle = WindowStyle.None, Background = Brushes.Transparent };
t.Show();
}

Expand Down Expand Up @@ -179,10 +179,10 @@ private void HandleException(Exception e)
Environment.Exit(1);
}
}

internal static EventClient GetDefaultEventClient(InstanceContext ctx)
{
if (string.Equals(UserSettings.AutoSyncServerHost, "localhost", StringComparison.OrdinalIgnoreCase))
if (App.IsConnectedToLocalhost())
{
return EventClient.GetNamedPipesClient(ctx);
}
Expand All @@ -194,7 +194,7 @@ internal static EventClient GetDefaultEventClient(InstanceContext ctx)

public static ConfigClient GetDefaultConfigClient()
{
if (string.Equals(UserSettings.AutoSyncServerHost, "localhost", StringComparison.OrdinalIgnoreCase))
if (App.IsConnectedToLocalhost())
{
return ConfigClient.GetNamedPipesClient();
}
Expand All @@ -204,6 +204,13 @@ public static ConfigClient GetDefaultConfigClient()
}
}

public static bool IsConnectedToLocalhost()
{
return string.Equals(UserSettings.AutoSyncServerHost, "localhost", StringComparison.OrdinalIgnoreCase);
}

public static string Hostname => UserSettings.AutoSyncServerHost;

internal static BitmapImage GetImageResource(string name)
{
return new BitmapImage(new Uri($"pack://application:,,,/Resources/{name}", UriKind.Absolute));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@
using System.Windows.Media.Imaging;
using Lithnet.Common.Presentation;
using PropertyChanged;
using Timer = System.Timers.Timer;

namespace Lithnet.Miiserver.AutoSync.UI.ViewModels
{
public class ExecutionMonitorViewModel : ViewModelBase<object>, IEventCallBack
{
private EventClient client;

private Timer pingTimer;

private int faultedCount;

public ExecutionMonitorViewModel(KeyValuePair<Guid, string> ma)
: base(ma)
{
Expand Down Expand Up @@ -421,15 +426,46 @@ private void SubscribeToStateChanges()
MAStatus status = this.client.GetFullUpdate(this.ManagementAgentID);
Debug.WriteLine($"Got full update from {this.ManagementAgentName}/{this.ManagementAgentID}");

this.StartPingTimer();

if (status != null)
{
this.MAStatusChanged(status);
}
}

private void StartPingTimer()
{
if (!App.IsConnectedToLocalhost())
{
this.pingTimer = new Timer();
this.pingTimer.Interval = TimeSpan.FromSeconds(60).TotalMilliseconds;
this.pingTimer.Elapsed += this.PingTimerElapsed;
this.pingTimer.Start();
}
}

private void StopPingTimer()
{
this.pingTimer?.Stop();
}

private void PingTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (this.IsConnected)
{
if (!this.client.Ping(this.ManagementAgentID))
{
Trace.WriteLine("Server ping failed. Restarting client");
this.CleanupAndRestartClient();
}
}
}

private void InnerChannel_Faulted(object sender, EventArgs e)
{
Trace.WriteLine($"Closing faulted event channel on client side for {this.ManagementAgentName}/{this.ManagementAgentID}");
this.StopPingTimer();
this.faultedCount++;
try
{
Expand All @@ -443,6 +479,7 @@ private void InnerChannel_Faulted(object sender, EventArgs e)
private void InnerChannel_Closed(object sender, EventArgs e)
{
Trace.WriteLine($"Closing event channel on client side for {this.ManagementAgentName}/{this.ManagementAgentID}");
this.StopPingTimer();
this.IsConnected = false;
this.DisplayState = "Disconnected";
this.client.InnerChannel.Closed -= this.InnerChannel_Closed;
Expand All @@ -454,8 +491,6 @@ private void InnerChannel_Closed(object sender, EventArgs e)
}
}

private int faultedCount;

private void CleanupAndRestartClient()
{
if (this.faultedCount > 5)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal class MainWindowViewModel : ViewModelBase

public ConfigFileViewModel ConfigFile { get; set; }

public string DisplayName => "Lithnet AutoSync" + (this.IsDirty ? "*" : string.Empty);
public string DisplayName => "Lithnet AutoSync" + (App.IsConnectedToLocalhost() ? string.Empty : $" - {App.Hostname}") + (this.IsDirty ? "*" : string.Empty);

public Cursor Cursor { get; set; }

Expand Down

0 comments on commit e8fec9f

Please sign in to comment.