WingMan

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 31  →  ?path2? @ 32
/trunk/WingMan/AutoCompletion/AutoCompletion.cs
@@ -165,4 +165,4 @@
}
}
}
}
}
/trunk/WingMan/AutoCompletion/AutoCompletionFailedEventArgs.cs
@@ -15,4 +15,4 @@
public Exception Exception { get; set; }
public string Name { get; set; }
}
}
}
/trunk/WingMan/AutoCompletion/AutoCompletionFailedType.cs
@@ -5,4 +5,4 @@
Load,
Save
}
}
}
/trunk/WingMan/Bindings/ExecuteKeyBinding.cs
@@ -20,4 +20,4 @@
public string Nick { get; set; }
public string Name { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBinding.cs
@@ -47,4 +47,4 @@
}
}
}
}
}
/trunk/WingMan/Bindings/KeyBindingExchange.cs
@@ -22,4 +22,4 @@
 
public List<KeyBinding> KeyBindings { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBindingExecutingEventArgs.cs
@@ -13,4 +13,4 @@
public string Nick { get; set; }
public string Name { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBindingMatchedEventArgs.cs
@@ -16,4 +16,4 @@
public string Name { get; set; }
public List<string> KeyCombo { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBindingsExchange.cs
@@ -6,4 +6,4 @@
{
public List<KeyBindingExchange> ExchangeBindings { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBindingsSynchronizer.cs
@@ -100,4 +100,4 @@
} while (!CancellationToken.IsCancellationRequested);
}
}
}
}
/trunk/WingMan/Bindings/KeyBindingsSynchronizerEventArgs.cs
@@ -11,4 +11,4 @@
 
public KeyBindingExchange Bindings { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyInterceptor.cs
@@ -157,4 +157,4 @@
ProcessPipe = false;
}
}
}
}
/trunk/WingMan/Bindings/KeySimulator.cs
@@ -100,4 +100,4 @@
}
}
}
}
}
/trunk/WingMan/Bindings/LocalKeyBindings.cs
@@ -18,4 +18,4 @@
 
public List<KeyBinding> Bindings { get; set; }
}
}
}
/trunk/WingMan/Bindings/RemoteKeyBinding.cs
@@ -21,4 +21,4 @@
 
public List<string> Keys { get; set; }
}
}
}
/trunk/WingMan/Bindings/RemoteKeyBindings.cs
@@ -19,4 +19,4 @@
 
public ObservableCollection<RemoteKeyBinding> Bindings { get; set; }
}
}
}
/trunk/WingMan/Communication/MqttAuthenticationFailureEventArgs.cs
@@ -14,4 +14,4 @@
public MqttApplicationMessageReceivedEventArgs Args { get; set; }
public Exception Exception { get; set; }
}
}
}
/trunk/WingMan/Communication/MqttCommunicationType.cs
@@ -5,4 +5,4 @@
Server,
Client
}
}
}
/trunk/WingMan/Discovery/Discovery.cs
@@ -0,0 +1,99 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Open.Nat;
 
namespace WingMan.Discovery
{
public class Discovery : IDisposable
{
public delegate void PortMapFailed(object sender, DiscoveryFailedEventArgs args);
 
public Discovery()
{
NatDiscoverer = new NatDiscoverer();
}
 
public Discovery(CancellationTokenSource cancellationTokenSource, TaskScheduler taskScheduler) : this()
{
CancellationTokenSource = cancellationTokenSource;
TaskScheduler = taskScheduler;
}
 
private static CancellationTokenSource CancellationTokenSource { get; set; }
private static NatDiscoverer NatDiscoverer { get; set; }
private static TaskScheduler TaskScheduler { get; set; }
 
private static CancellationTokenSource UPnPCancellationTokenSource { get; set; }
private static CancellationTokenSource PMPCancellationTokenSource { get; set; }
 
public void Dispose()
{
PMPCancellationTokenSource?.Dispose();
PMPCancellationTokenSource = null;
 
PMPCancellationTokenSource?.Dispose();
PMPCancellationTokenSource = null;
}
 
public event PortMapFailed OnPortMapFailed;
 
public async Task<bool> CreateMapping(DiscoveryType type, int port)
{
switch (type)
{
case DiscoveryType.UPnP:
return await CreateUPnPMapping(port);
case DiscoveryType.PMP:
return await CreatePMPPortMapping(port);
default:
throw new ArgumentException("Unknown disocvery type");
}
}
 
private async Task<bool> CreateUPnPMapping(int port)
{
try
{
UPnPCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(UPnPCancellationTokenSource.Token,
CancellationTokenSource.Token);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Upnp, linkedCancellationTokenSource);
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port, "WingMan Host"));
 
return true;
}
catch (Exception ex)
{
await Task.Delay(0, CancellationTokenSource.Token).ContinueWith(_ =>
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.UPnP, ex)),
CancellationTokenSource.Token, TaskContinuationOptions.None, TaskScheduler);
 
return false;
}
}
 
private async Task<bool> CreatePMPPortMapping(int port)
{
try
{
PMPCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
PMPCancellationTokenSource.Token,
CancellationTokenSource.Token);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Pmp, linkedCancellationTokenSource);
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port, "WingMan Host"));
return true;
}
catch (Exception ex)
{
await Task.Delay(0, CancellationTokenSource.Token).ContinueWith(_ =>
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.PMP, ex)),
CancellationTokenSource.Token, TaskContinuationOptions.None, TaskScheduler);
 
return false;
}
}
}
}
/trunk/WingMan/Discovery/DiscoveryFailedEventArgs.cs
@@ -0,0 +1,16 @@
using System;
 
namespace WingMan.Discovery
{
public class DiscoveryFailedEventArgs : EventArgs
{
public DiscoveryFailedEventArgs(DiscoveryType type, Exception ex)
{
Type = type;
Exception = ex;
}
 
public DiscoveryType Type { get; set; }
public Exception Exception { get; set; }
}
}
/trunk/WingMan/Discovery/DiscoveryType.cs
@@ -0,0 +1,8 @@
namespace WingMan.Discovery
{
public enum DiscoveryType
{
UPnP,
PMP
}
}
/trunk/WingMan/Lobby/LobbyMessage.cs
@@ -8,4 +8,4 @@
public string Message { get; set; }
public string Nick { get; set; }
}
}
}
/trunk/WingMan/Lobby/LobbyMessageReceivedEventArgs.cs
@@ -14,4 +14,4 @@
 
public string Message { get; set; }
}
}
}
/trunk/WingMan/Lobby/LobbyMessageSynchronizer.cs
@@ -67,4 +67,4 @@
}
}
}
}
}
/trunk/WingMan/Properties/AssemblyInfo.cs
@@ -31,4 +31,4 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
/trunk/WingMan/Properties/Strings.Designer.cs
@@ -151,6 +151,16 @@
}
/// <summary>
/// Looks up a localized string similar to Failed creating automatic port mapping, please ensure that the port is routed through the firewall properly.
/// </summary>
internal static string Failed_creating_automatic_port_mapping_please_make_sure_the_port_is_routed_properly {
get {
return ResourceManager.GetString("Failed_creating_automatic_port_mapping_please_make_sure_the_port_is_routed_proper" +
"ly", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed loading autocomplete source.
/// </summary>
internal static string Failed_loading_autocomplete_source {
@@ -241,6 +251,24 @@
}
/// <summary>
/// Looks up a localized string similar to Failed to create PMP port mapping.
/// </summary>
internal static string Failed_to_create_PMP_port_mapping {
get {
return ResourceManager.GetString("Failed_to_create_PMP_port_mapping", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed to create UPnp port mapping.
/// </summary>
internal static string Failed_to_create_UPnP_port_mapping {
get {
return ResourceManager.GetString("Failed_to_create_UPnP_port_mapping", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lobby message.
/// </summary>
internal static string Lobby_message {
/trunk/WingMan/Properties/Strings.resx
@@ -147,6 +147,9 @@
<data name="Executing_binding_from_remote_client" xml:space="preserve">
<value>Executing binding from remote client</value>
</data>
<data name="Failed_creating_automatic_port_mapping_please_make_sure_the_port_is_routed_properly" xml:space="preserve">
<value>Failed creating automatic port mapping, please ensure that the port is routed through the firewall properly</value>
</data>
<data name="Failed_loading_autocomplete_source" xml:space="preserve">
<value>Failed loading autocomplete source</value>
</data>
@@ -177,6 +180,12 @@
<data name="Failed_to_authenticate_with_server" xml:space="preserve">
<value>Failed to authenticate with server</value>
</data>
<data name="Failed_to_create_PMP_port_mapping" xml:space="preserve">
<value>Failed to create PMP port mapping</value>
</data>
<data name="Failed_to_create_UPnP_port_mapping" xml:space="preserve">
<value>Failed to create UPnp port mapping</value>
</data>
<data name="Lobby_message" xml:space="preserve">
<value>Lobby message</value>
</data>
/trunk/WingMan/Utilities/AES.cs
@@ -123,4 +123,4 @@
return sb.ToString(0, size);
}
}
}
}
/trunk/WingMan/Utilities/Extensions.cs
@@ -41,4 +41,4 @@
return !a.OrderBy(s => s).SequenceExcept(b.OrderBy(s => s)).Any();
}
}
}
}
/trunk/WingMan/Utilities/KeyConversion.cs
@@ -356,4 +356,4 @@
{254, "OemClear"}
};
}
}
}
/trunk/WingMan/WingMan.csproj
@@ -84,6 +84,9 @@
<Compile Include="AutoCompletion\AutoCompletionFailedEventArgs.cs" />
<Compile Include="AutoCompletion\AutoCompletionFailedType.cs" />
<Compile Include="Communication\MqttAuthenticationFailureEventArgs.cs" />
<Compile Include="Discovery\Discovery.cs" />
<Compile Include="Discovery\DiscoveryFailedEventArgs.cs" />
<Compile Include="Discovery\DiscoveryType.cs" />
<Compile Include="Lobby\LobbyMessageReceivedEventArgs.cs" />
<Compile Include="Lobby\LobbyMessageSynchronizer.cs" />
<Compile Include="Bindings\ExecuteKeyBinding.cs" />
/trunk/WingMan/WingManForm.cs
@@ -15,6 +15,7 @@
using WingMan.AutoCompletion;
using WingMan.Bindings;
using WingMan.Communication;
using WingMan.Discovery;
using WingMan.Lobby;
using WingMan.Properties;
using WingMan.Utilities;
@@ -30,6 +31,10 @@
FormTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
FormCancellationTokenSource = new CancellationTokenSource();
 
// Set up discovery.
Discovery = new Discovery.Discovery(FormCancellationTokenSource, FormTaskScheduler);
Discovery.OnPortMapFailed += OnDiscoveryPortMapFailed;
 
// Set up autocompletion.
AutoCompletion = new AutoCompletion.AutoCompletion(FormTaskScheduler, FormCancellationTokenSource.Token);
AutoCompletion.OnSaveFailed += AutoCompletionOnSaveFailed;
@@ -96,6 +101,7 @@
KeySimulator.OnMouseKeyBindingExecuting += OnMouseKeyBindingExecuting;
}
 
private static Discovery.Discovery Discovery { get; set; }
private static AutoCompletion.AutoCompletion AutoCompletion { get; set; }
private static CancellationTokenSource FormCancellationTokenSource { get; set; }
 
@@ -125,6 +131,21 @@
 
public KeySimulator KeySimulator { get; set; }
 
public void OnDiscoveryPortMapFailed(object sender, DiscoveryFailedEventArgs args)
{
switch (args.Type)
{
case DiscoveryType.UPnP:
ActivityTextBox.AppendText(
$"{Strings.Failed_to_create_UPnP_port_mapping}{Environment.NewLine}");
break;
case DiscoveryType.PMP:
ActivityTextBox.AppendText(
$"{Strings.Failed_to_create_PMP_port_mapping}{Environment.NewLine}");
break;
}
}
 
private void LocalCheckedListBoxBindingSourceOnListChanged(object sender, ListChangedEventArgs e)
{
// Check items
@@ -342,6 +363,12 @@
 
StoreConnectionAutocomplete();
 
// Try to reserve port: try UPnP followed by PMP.
if (!await Discovery.CreateMapping(DiscoveryType.UPnP, port) &&
!await Discovery.CreateMapping(DiscoveryType.PMP, port))
ActivityTextBox.AppendText(
$"{Strings.Failed_creating_automatic_port_mapping_please_make_sure_the_port_is_routed_properly}{Environment.NewLine}");
 
// Start the MQTT server.
if (!await MqttCommunication
.Start(MqttCommunicationType.Server, ipAddress, port, nick, password))