WingMan

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 36  →  ?path2? @ 35
/trunk/WingMan/AutoCompletion/AutoCompletion.cs
@@ -124,29 +124,7 @@
new SqliteConnection($"URI=file:{"Autocomplete.db"}"))
{
await sqliteConnection.OpenAsync(CancellationToken);
 
// Create table if it does not exist.
using (var sqliteCommand =
new SqliteCommand($"CREATE TABLE IF NOT EXISTS {name} (data text UNIQUE NOT NULL)",
sqliteConnection))
{
using (var dbtransaction = sqliteConnection.BeginTransaction())
{
try
{
await sqliteCommand.ExecuteReaderAsync(CancellationToken);
 
dbtransaction.Commit();
}
catch
{
dbtransaction.Rollback();
throw;
}
}
}
 
using (var sqliteCommand =
new SqliteCommand($"SELECT data FROM {name}", sqliteConnection))
{
using (var dbtransaction = sqliteConnection.BeginTransaction())
@@ -187,4 +165,4 @@
}
}
}
}
}
/trunk/WingMan/Bindings/ExecuteKeyBinding.cs
@@ -1,22 +1,23 @@
using ProtoBuf;
using System.Xml.Serialization;
 
namespace WingMan.Bindings
{
[ProtoContract]
public class ExecuteKeyBinding
{
[XmlIgnore] public static readonly XmlSerializer XmlSerializer =
new XmlSerializer(typeof(ExecuteKeyBinding));
 
public ExecuteKeyBinding()
{
}
 
public ExecuteKeyBinding(string nick, string name) : this()
public ExecuteKeyBinding(string nick, string name)
{
Nick = nick;
Name = name;
}
 
[ProtoMember(1)] public string Nick { get; set; }
 
[ProtoMember(2)] public string Name { get; set; }
public string Nick { get; set; }
public string Name { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBindingExchange.cs
@@ -1,30 +1,25 @@
using System.Collections.Generic;
using ProtoBuf;
using System.Xml.Serialization;
 
namespace WingMan.Bindings
{
[ProtoContract]
public class KeyBindingExchange
{
private readonly List<string> _keyBindings = new List<string>();
[XmlIgnore] public static readonly XmlSerializer XmlSerializer =
new XmlSerializer(typeof(KeyBindingExchange));
 
public KeyBindingExchange()
{
}
 
public KeyBindingExchange(string nick, List<string> keyBindings) : this()
public KeyBindingExchange(string nick, List<KeyBinding> keyBindings)
{
Nick = nick;
KeyBindings = keyBindings;
}
 
[ProtoMember(1)] public string Nick { get; set; }
public string Nick { get; set; }
 
[ProtoMember(2)]
public List<string> KeyBindings
{
get => _keyBindings;
set => _keyBindings.AddRange(value);
}
public List<KeyBinding> KeyBindings { get; set; }
}
}
}
/trunk/WingMan/Bindings/KeyBindingsSynchronizer.cs
@@ -5,7 +5,6 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ProtoBuf;
using WingMan.Communication;
 
namespace WingMan.Bindings
@@ -22,7 +21,7 @@
CancellationToken = cancellationToken;
TaskScheduler = taskScheduler;
 
SynchronizedMouseKeyBindings = new ConcurrentDictionary<string, List<string>>();
SynchronizedMouseKeyBindings = new ConcurrentDictionary<string, List<KeyBinding>>();
 
MqttCommunication.OnMessageReceived += MqttCommunicationOnMessageReceived;
 
@@ -31,7 +30,7 @@
 
private LocalKeyBindings LocalKeyBindings { get; }
 
private ConcurrentDictionary<string, List<string>> SynchronizedMouseKeyBindings { get; }
private ConcurrentDictionary<string, List<KeyBinding>> SynchronizedMouseKeyBindings { get; }
 
private MqttCommunication MqttCommunication { get; }
 
@@ -58,7 +57,7 @@
memoryStream.Position = 0L;
 
var mouseKeyBindingsExchange =
Serializer.Deserialize<KeyBindingExchange>(memoryStream);
(KeyBindingExchange) KeyBindingExchange.XmlSerializer.Deserialize(memoryStream);
 
// Do not add own bindings.
if (string.Equals(mouseKeyBindingsExchange.Nick, MqttCommunication.Nick))
@@ -92,9 +91,8 @@
 
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream,
new KeyBindingExchange(MqttCommunication.Nick,
LocalKeyBindings.Bindings.Select(binding => binding.Name).ToList()));
KeyBindingExchange.XmlSerializer.Serialize(memoryStream,
new KeyBindingExchange(MqttCommunication.Nick, LocalKeyBindings.Bindings));
 
memoryStream.Position = 0L;
 
/trunk/WingMan/Bindings/KeyInterceptor.cs
@@ -7,7 +7,6 @@
using System.Threading.Tasks.Dataflow;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using ProtoBuf;
using WingMan.Communication;
using WingMan.Utilities;
 
@@ -17,7 +16,7 @@
{
public delegate void MouseKeyBindingMatched(object sender, KeyBindingMatchedEventArgs args);
 
private volatile bool _processPipe;
private volatile bool ProcessPipe;
 
public KeyInterceptor(RemoteKeyBindings remoteKeyBindings, MqttCommunication mqttCommunication,
TaskScheduler taskScheduler, CancellationToken cancellationToken)
@@ -99,7 +98,7 @@
 
try
{
if (!_processPipe)
if (!ProcessPipe)
return;
 
foreach (var binding in RemoteKeyBindings.Bindings)
@@ -117,7 +116,7 @@
 
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream,
ExecuteKeyBinding.XmlSerializer.Serialize(memoryStream,
new ExecuteKeyBinding(binding.Nick, binding.Name));
 
memoryStream.Position = 0L;
@@ -136,7 +135,7 @@
 
private async void MouseKeyGloalHookOnKeyDown(object sender, KeyEventArgs e)
{
_processPipe = true;
ProcessPipe = true;
 
if (!KeyConversion.KeysToString.TryGetValue((byte) e.KeyCode, out var key))
return;
@@ -155,7 +154,7 @@
 
private void MouseKeyGloalHookOnKeyUp(object sender, KeyEventArgs e)
{
_processPipe = false;
ProcessPipe = false;
}
}
}
}
/trunk/WingMan/Bindings/KeySimulator.cs
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using WindowsInput;
using WindowsInput.Native;
using ProtoBuf;
using WingMan.Communication;
using WingMan.Utilities;
 
@@ -53,7 +52,7 @@
memoryStream.Position = 0L;
 
var executeMouseKeyBinding =
Serializer.Deserialize<ExecuteKeyBinding>(memoryStream);
(ExecuteKeyBinding) ExecuteKeyBinding.XmlSerializer.Deserialize(memoryStream);
 
// Do not process own mouse key bindings.
if (!string.Equals(executeMouseKeyBinding.Nick, MqttCommunication.Nick, StringComparison.Ordinal))
/trunk/WingMan/Communication/MqttCommunication.cs
@@ -63,7 +63,7 @@
 
private IPAddress IpAddress { get; set; }
 
public int Port { get; set; }
private int Port { get; set; }
 
private string Password { get; set; }
 
@@ -159,9 +159,9 @@
 
private async Task StopClient()
{
UnbindClientHandlers();
 
await Client.StopAsync();
 
UnbindClientHandlers();
}
 
public void BindClientHandlers()
@@ -186,7 +186,7 @@
{
using (var inputStream = new MemoryStream(e.ApplicationMessage.Payload))
{
using (var decryptedStream = await Aes.Decrypt(inputStream, Password))
using (var decryptedStream = await AES.Decrypt(inputStream, Password))
{
using (var lz4Decompress = new LZ4Stream(decryptedStream, CompressionMode.Decompress))
{
@@ -254,9 +254,9 @@
 
private async Task StopServer()
{
UnbindServerHandlers();
 
await Server.StopAsync();
 
UnbindServerHandlers();
}
 
private void BindServerHandlers()
@@ -287,7 +287,7 @@
{
using (var inputStream = new MemoryStream(e.ApplicationMessage.Payload))
{
using (var decryptedStream = await Aes.Decrypt(inputStream, Password))
using (var decryptedStream = await AES.Decrypt(inputStream, Password))
{
using (var lz4Decompress = new LZ4Stream(decryptedStream, CompressionMode.Decompress))
{
@@ -383,7 +383,7 @@
 
compressStream.Position = 0L;
 
using (var outputStream = await Aes.Encrypt(compressStream, Password))
using (var outputStream = await AES.Encrypt(compressStream, Password))
{
var data = outputStream.ToArray();
switch (Type)
/trunk/WingMan/Discovery/Discovery.cs
@@ -24,16 +24,16 @@
private static NatDiscoverer NatDiscoverer { get; set; }
private static TaskScheduler TaskScheduler { get; set; }
 
private static CancellationTokenSource UpnPCancellationTokenSource { get; set; }
private static CancellationTokenSource PmpCancellationTokenSource { 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;
 
PmpCancellationTokenSource?.Dispose();
PmpCancellationTokenSource = null;
PMPCancellationTokenSource?.Dispose();
PMPCancellationTokenSource = null;
}
 
public event PortMapFailed OnPortMapFailed;
@@ -42,56 +42,24 @@
{
switch (type)
{
case DiscoveryType.Upnp:
return await CreateUpnPMapping(port);
case DiscoveryType.Pmp:
return await CreatePmpPortMapping(port);
case DiscoveryType.UPnP:
return await CreateUPnPMapping(port);
case DiscoveryType.PMP:
return await CreatePMPPortMapping(port);
default:
throw new ArgumentException("Unknown discovery type");
throw new ArgumentException("Unknown disocvery type");
}
}
 
public async Task<bool> DeleteMapping(DiscoveryType type, int port)
private async Task<bool> CreateUPnPMapping(int port)
{
switch (type)
{
case DiscoveryType.Upnp:
return await DeleteUpnPMapping(port);
case DiscoveryType.Pmp:
return await DeletePmpPortMapping(port);
default:
throw new ArgumentException("Unknown discovery type");
}
}
 
private async Task<bool> DeleteUpnPMapping(int port)
{
try
{
UpnPCancellationTokenSource = new CancellationTokenSource();
UPnPCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(UpnPCancellationTokenSource.Token,
CancellationTokenSource.CreateLinkedTokenSource(UPnPCancellationTokenSource.Token,
CancellationTokenSource.Token);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Upnp, linkedCancellationTokenSource);
await device.DeletePortMapAsync(new Mapping(Protocol.Tcp, port, port, "WingMan Host"));
 
return true;
}
catch
{
return false;
}
}
 
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;
@@ -99,7 +67,7 @@
catch (Exception ex)
{
await Task.Delay(0, CancellationTokenSource.Token).ContinueWith(_ =>
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.Upnp, ex)),
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.UPnP, ex)),
CancellationTokenSource.Token, TaskContinuationOptions.None, TaskScheduler);
 
return false;
@@ -106,33 +74,15 @@
}
}
 
private async Task<bool> DeletePmpPortMapping(int port)
private async Task<bool> CreatePMPPortMapping(int port)
{
try
{
PmpCancellationTokenSource = new CancellationTokenSource();
PMPCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
PmpCancellationTokenSource.Token,
PMPCancellationTokenSource.Token,
CancellationTokenSource.Token);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Pmp, linkedCancellationTokenSource);
await device.DeletePortMapAsync(new Mapping(Protocol.Tcp, port, port, "WingMan Host"));
return true;
}
catch
{
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;
}
@@ -139,7 +89,7 @@
catch (Exception ex)
{
await Task.Delay(0, CancellationTokenSource.Token).ContinueWith(_ =>
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.Pmp, ex)),
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.PMP, ex)),
CancellationTokenSource.Token, TaskContinuationOptions.None, TaskScheduler);
 
return false;
/trunk/WingMan/Discovery/DiscoveryType.cs
@@ -2,7 +2,7 @@
{
public enum DiscoveryType
{
Upnp,
Pmp
UPnP,
PMP
}
}
/trunk/WingMan/Lobby/LobbyMessage.cs
@@ -1,22 +1,11 @@
using ProtoBuf;
using System.Xml.Serialization;
 
namespace WingMan.Lobby
{
[ProtoContract]
public class LobbyMessage
{
public LobbyMessage()
{
}
 
public LobbyMessage(string nick, string message) : this()
{
Nick = nick;
Message = message;
}
 
[ProtoMember(1)] public string Message { get; set; }
 
[ProtoMember(2)] public string Nick { get; set; }
[XmlIgnore] public static XmlSerializer XmlSerializer = new XmlSerializer(typeof(LobbyMessage));
public string Message { get; set; }
public string Nick { get; set; }
}
}
}
/trunk/WingMan/Lobby/LobbyMessageSynchronizer.cs
@@ -2,7 +2,6 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ProtoBuf;
using WingMan.Communication;
 
namespace WingMan.Lobby
@@ -45,7 +44,7 @@
 
memoryStream.Position = 0L;
 
var lobbyMessage = Serializer.Deserialize<LobbyMessage>(memoryStream);
var lobbyMessage = (LobbyMessage) LobbyMessage.XmlSerializer.Deserialize(memoryStream);
 
await Task.Delay(0)
.ContinueWith(
@@ -59,7 +58,11 @@
{
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream, new LobbyMessage(MqttCommunication.Nick, message));
LobbyMessage.XmlSerializer.Serialize(memoryStream, new LobbyMessage
{
Nick = MqttCommunication.Nick,
Message = message
});
 
memoryStream.Position = 0L;
 
/trunk/WingMan/Utilities/AES.cs
@@ -1,13 +1,13 @@
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
 
namespace WingMan.Utilities
{
public static class Aes
public static class AES
{
private const int AesKeySize = 256;
private const int AesKeyIterations = 4096;
private const int AesBlockSize = 128;
private const CipherMode AesCipherMode = CipherMode.CBC;
@@ -28,22 +28,21 @@
{
var outputStream = new MemoryStream();
 
using (var aesManaged = new AesManaged())
using (var rijdanelManaged = new RijndaelManaged())
{
// FIPS-197 / CBC
aesManaged.BlockSize = AesBlockSize;
aesManaged.Mode = AesCipherMode;
aesManaged.Padding = AesPaddingMode;
aesManaged.KeySize = AesKeySize;
rijdanelManaged.BlockSize = AesBlockSize;
rijdanelManaged.Mode = AesCipherMode;
rijdanelManaged.Padding = AesPaddingMode;
 
// Compute the salt and the IV from the key.
var salt = new byte[AesKeySaltBytes];
Rng.GetBytes(salt);
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8);
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8);
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
 
using (var encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (var encryptor = rijdanelManaged.CreateEncryptor(rijdanelManaged.Key, rijdanelManaged.IV))
{
using (var memoryStream = new MemoryStream())
{
@@ -77,22 +76,21 @@
/// <returns>an encrypted byte array</returns>
public static async Task<byte[]> Encrypt(byte[] data, string key)
{
using (var aesManaged = new AesManaged())
using (var rijdanelManaged = new RijndaelManaged())
{
// FIPS-197 / CBC
aesManaged.BlockSize = AesBlockSize;
aesManaged.Mode = AesCipherMode;
aesManaged.Padding = AesPaddingMode;
aesManaged.KeySize = AesKeySize;
rijdanelManaged.BlockSize = AesBlockSize;
rijdanelManaged.Mode = AesCipherMode;
rijdanelManaged.Padding = AesPaddingMode;
 
// Compute the salt and the IV from the key.
var salt = new byte[AesKeySaltBytes];
Rng.GetBytes(salt);
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8);
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8);
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
 
using (var encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (var encryptor = rijdanelManaged.CreateEncryptor(rijdanelManaged.Key, rijdanelManaged.IV))
{
using (var memoryStream = new MemoryStream())
{
@@ -135,20 +133,19 @@
//var salt = data.Take(AesKeySaltBytes).ToArray();
//var text = data.Skip(AesKeySaltBytes).ToArray();
 
using (var aesManaged = new AesManaged())
using (var rijdanelManaged = new RijndaelManaged())
{
// FIPS-197 / CBC
aesManaged.BlockSize = AesBlockSize;
aesManaged.Mode = AesCipherMode;
aesManaged.Padding = AesPaddingMode;
aesManaged.KeySize = AesKeySize;
rijdanelManaged.BlockSize = AesBlockSize;
rijdanelManaged.Mode = AesCipherMode;
rijdanelManaged.Padding = AesPaddingMode;
 
// Retrieve the key and the IV from the salt.
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8);
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8);
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
 
using (var decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV))
using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV))
{
using (var memoryStream = new MemoryStream(text))
{
@@ -179,20 +176,19 @@
var salt = data.Take(AesKeySaltBytes).ToArray();
var text = data.Skip(AesKeySaltBytes).ToArray();
 
using (var aesManaged = new AesManaged())
using (var rijdanelManaged = new RijndaelManaged())
{
// FIPS-197 / CBC
aesManaged.BlockSize = AesBlockSize;
aesManaged.Mode = AesCipherMode;
aesManaged.Padding = AesPaddingMode;
aesManaged.KeySize = AesKeySize;
rijdanelManaged.BlockSize = AesBlockSize;
rijdanelManaged.Mode = AesCipherMode;
rijdanelManaged.Padding = AesPaddingMode;
 
// Retrieve the key and the IV from the salt.
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations);
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8);
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8);
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8);
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8);
 
using (var decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV))
using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV))
{
using (var memoryStream = new MemoryStream(text))
{
@@ -212,12 +208,15 @@
}
}
 
public static string ExpandKey(string password, int length = 32)
public static string ExpandKey(string password, int size = 32)
{
if (length <= password.Length) return password.Substring(0, length);
while (password.Length * 2 <= length) password += password;
if (password.Length < length) password += password.Substring(0, length - password.Length);
return password;
var sb = new StringBuilder(password);
do
{
sb.Append(password);
} while (sb.Length < size);
 
return sb.ToString(0, size);
}
}
}
/trunk/WingMan/WingMan.csproj
@@ -57,17 +57,11 @@
<Reference Include="Open.Nat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f22a6a4582336c76, processorArchitecture=MSIL">
<HintPath>..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll</HintPath>
</Reference>
<Reference Include="protobuf-net, Version=2.4.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
<HintPath>..\packages\protobuf-net.2.4.0\lib\net40\protobuf-net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Portable, Version=4.0.0.0, Culture=neutral, PublicKeyToken=59e704a76bc4613a, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\System.Data.Portable.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Threading.Tasks.Dataflow, Version=4.5.24.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Tpl.Dataflow.4.5.24\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll</HintPath>
</Reference>
/trunk/WingMan/WingManForm.Designer.cs
@@ -55,7 +55,7 @@
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.OverlayPanel = new System.Windows.Forms.Panel();
this.OverlayPanelLabel = new System.Windows.Forms.Label();
this.WingManNotifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
@@ -153,7 +153,7 @@
this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBox2.Location = new System.Drawing.Point(0, 0);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(530, 332);
this.groupBox2.Size = new System.Drawing.Size(530, 337);
this.groupBox2.TabIndex = 1;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Lobby";
@@ -245,8 +245,6 @@
//
// LocalNameTextBox
//
this.LocalNameTextBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
this.LocalNameTextBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
this.LocalNameTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.LocalNameTextBox.Location = new System.Drawing.Point(72, 256);
this.LocalNameTextBox.Name = "LocalNameTextBox";
@@ -432,7 +430,7 @@
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(530, 332);
this.tabPage2.Size = new System.Drawing.Size(530, 337);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Bindings";
this.tabPage2.UseVisualStyleBackColor = true;
@@ -443,7 +441,7 @@
this.tabPage3.Cursor = System.Windows.Forms.Cursors.Arrow;
this.tabPage3.Location = new System.Drawing.Point(4, 22);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Size = new System.Drawing.Size(530, 332);
this.tabPage3.Size = new System.Drawing.Size(530, 337);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "Chat";
this.tabPage3.UseVisualStyleBackColor = true;
@@ -494,12 +492,12 @@
this.OverlayPanelLabel.TabIndex = 0;
this.OverlayPanelLabel.Text = "Press key-combination to bind...";
//
// WingManNotifyIcon
// notifyIcon1
//
this.WingManNotifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("WingManNotifyIcon.Icon")));
this.WingManNotifyIcon.Text = "WingMan";
this.WingManNotifyIcon.Visible = true;
this.WingManNotifyIcon.DoubleClick += new System.EventHandler(this.NotifyIconDoubleClick);
this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));
this.notifyIcon1.Text = "notifyIcon1";
this.notifyIcon1.Visible = true;
this.notifyIcon1.DoubleClick += new System.EventHandler(this.NotifyIconDoubleClick);
//
// WingManForm
//
@@ -580,7 +578,7 @@
private System.Windows.Forms.Label OverlayPanelLabel;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox Password;
private System.Windows.Forms.NotifyIcon WingManNotifyIcon;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.CheckedListBox LocalBindingsCheckedListBox;
}
}
/trunk/WingMan/WingManForm.cs
@@ -24,7 +24,7 @@
{
public partial class WingManForm : Form
{
private const int TabControlDetachPixelOffset = 20;
private const int tabControlDetachPixelOffset = 20;
 
public WingManForm()
{
@@ -45,7 +45,6 @@
Task.Run(() => AutoCompletion.Load(Address.Name, Address.AutoCompleteCustomSource));
Task.Run(() => AutoCompletion.Load(Port.Name, Address.AutoCompleteCustomSource));
Task.Run(() => AutoCompletion.Load(Nick.Name, Nick.AutoCompleteCustomSource));
Task.Run(() => AutoCompletion.Load(LocalNameTextBox.Name, LocalNameTextBox.AutoCompleteCustomSource));
 
MqttCommunication = new MqttCommunication(FormTaskScheduler, FormCancellationTokenSource.Token);
MqttCommunication.OnClientAuthenticationFailed += OnMqttClientAuthenticationFailed;
@@ -66,7 +65,6 @@
DataSource = LocalKeyBindings.Bindings
};
LocalCheckedListBoxBindingSource.ListChanged += LocalCheckedListBoxBindingSourceOnListChanged;
 
LocalBindingsCheckedListBox.DisplayMember = "DisplayName";
LocalBindingsCheckedListBox.ValueMember = "Keys";
LocalBindingsCheckedListBox.DataSource = LocalCheckedListBoxBindingSource;
@@ -80,13 +78,10 @@
{
DataSource = KeyBindingsExchange.ExchangeBindings
};
RemoteBindingsComboBoxSource.ListChanged += RemoteBindingsComboBoxSourceOnListChanged;
 
RemoteBindingsComboBox.DisplayMember = "Nick";
RemoteBindingsComboBox.ValueMember = "KeyBindings";
RemoteBindingsComboBox.DataSource = RemoteBindingsComboBoxSource;
 
 
// Start lobby message synchronizer.
LobbyMessageSynchronizer = new LobbyMessageSynchronizer(MqttCommunication, FormTaskScheduler,
FormCancellationTokenSource.Token);
@@ -118,7 +113,7 @@
 
private List<string> MouseKeyCombo { get; set; }
 
public LocalKeyBindings LocalKeyBindings { get; set; }
private LocalKeyBindings LocalKeyBindings { get; }
 
private RemoteKeyBindings RemoteKeyBindings { get; }
 
@@ -138,24 +133,19 @@
 
public KeySimulator KeySimulator { get; set; }
 
private static Point TabControlClickStartPosition { get; set; }
private static Point tabControlClickStartPosition { get; set; }
private static TabControl DetachedTabControl { get; set; }
private static Form DetachedForm { get; set; }
 
private void RemoteBindingsComboBoxSourceOnListChanged(object sender, ListChangedEventArgs e)
{
UpdateRemoteBindingsListBox();
}
 
public void OnDiscoveryPortMapFailed(object sender, DiscoveryFailedEventArgs args)
{
switch (args.Type)
{
case DiscoveryType.Upnp:
case DiscoveryType.UPnP:
ActivityTextBox.AppendText(
$"{Strings.Failed_to_create_UPnP_port_mapping}{Environment.NewLine}");
break;
case DiscoveryType.Pmp:
case DiscoveryType.PMP:
ActivityTextBox.AppendText(
$"{Strings.Failed_to_create_PMP_port_mapping}{Environment.NewLine}");
break;
@@ -291,36 +281,47 @@
{
KeyBindingsExchange.ExchangeBindings.Add(e.Bindings);
RemoteBindingsComboBoxSource.ResetBindings(false);
UpdateRemoteItems();
return;
}
 
// If the bindings for the nick have not changed then do not update.
if (e.Bindings.KeyBindings.Count == exchangeBindings.KeyBindings.Count &&
e.Bindings.KeyBindings.All(exchangeBindings.KeyBindings.Contains))
if (exchangeBindings.KeyBindings.SequenceEqual(e.Bindings.KeyBindings))
{
RemoteBindingsComboBoxSource.ResetBindings(false);
UpdateRemoteItems();
return;
}
 
// Update the bindings.
exchangeBindings.KeyBindings.RemoveAll(binding => !e.Bindings.KeyBindings.Contains(binding));
exchangeBindings.KeyBindings.AddRange(
e.Bindings.KeyBindings.Where(binding => !exchangeBindings.KeyBindings.Contains(binding)));
exchangeBindings.KeyBindings = e.Bindings.KeyBindings;
RemoteBindingsComboBoxSource.ResetBindings(false);
UpdateRemoteItems();
}
 
private void UpdateRemoteBindingsListBox()
private void UpdateRemoteItems()
{
var keyBindingExchange = (KeyBindingExchange) RemoteBindingsComboBox.SelectedItem;
if (keyBindingExchange == null)
var exchangeBindings = (List<KeyBinding>) RemoteBindingsComboBox.SelectedValue;
if (exchangeBindings == null)
return;
 
var replaceMouseBindings = new ObservableCollection<RemoteKeyBinding>();
foreach (var remoteBinding in RemoteKeyBindings.Bindings)
{
if (!exchangeBindings.Any(binding =>
string.Equals(binding.Name, remoteBinding.Name, StringComparison.Ordinal)))
continue;
 
replaceMouseBindings.Add(remoteBinding);
}
 
RemoteKeyBindings.Bindings.Clear();
foreach (var binding in replaceMouseBindings) RemoteKeyBindings.Bindings.Add(binding);
 
RemoteBindingsListBox.Items.Clear();
var bindings = KeyBindingsExchange.ExchangeBindings
.Where(binding => binding.Nick == keyBindingExchange.Nick)
.SelectMany(binding => binding.KeyBindings.Select(keyBinding => keyBinding))
.Select(binding => (object) binding).ToArray();
 
RemoteBindingsListBox.DisplayMember = "Name";
RemoteBindingsListBox.ValueMember = "Name";
var bindings = exchangeBindings.Select(binding => (object) binding.Name).ToArray();
if (bindings.Length == 0)
return;
 
@@ -329,9 +330,9 @@
 
private void OnLobbyMessageReceived(object sender, LobbyMessageReceivedEventArgs e)
{
WingManNotifyIcon.BalloonTipTitle = Strings.Lobby_message;
WingManNotifyIcon.BalloonTipText = $"{e.Nick} : {e.Message}{Environment.NewLine}";
WingManNotifyIcon.ShowBalloonTip(1000);
notifyIcon1.BalloonTipTitle = Strings.Lobby_message;
notifyIcon1.BalloonTipText = $"{e.Nick} : {e.Message}{Environment.NewLine}";
notifyIcon1.ShowBalloonTip(1000);
 
LobbyTextBox.AppendText($"{e.Nick} : {e.Message}{Environment.NewLine}");
}
@@ -351,16 +352,7 @@
// Stop the MQTT server if it is running.
if (MqttCommunication.Running)
{
// Remote UPnP and Pmp mappings.
await Task.Delay(0, FormCancellationTokenSource.Token).ContinueWith(async _ =>
{
await Discovery.DeleteMapping(DiscoveryType.Upnp, MqttCommunication.Port);
await Discovery.DeleteMapping(DiscoveryType.Pmp, MqttCommunication.Port);
},
FormCancellationTokenSource.Token, TaskContinuationOptions.LongRunning, FormTaskScheduler);
 
await MqttCommunication.Stop();
 
HostButton.BackColor = Color.Empty;
 
// Enable controls.
@@ -378,14 +370,10 @@
StoreConnectionAutocomplete();
 
// Try to reserve port: try UPnP followed by PMP.
await Task.Delay(0, FormCancellationTokenSource.Token).ContinueWith(async _ =>
{
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}");
},
FormCancellationTokenSource.Token, TaskContinuationOptions.LongRunning, FormTaskScheduler);
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
@@ -480,7 +468,7 @@
return false;
}
 
password = Aes.ExpandKey(Password.Text);
password = AES.ExpandKey(Password.Text);
 
Address.BackColor = Color.Empty;
Port.BackColor = Color.Empty;
@@ -543,7 +531,7 @@
LobbySayTextBox.Text = string.Empty;
}
 
private async void LocalAddBindingButtonClick(object sender, EventArgs e)
private void LocalAddBindingButtonClick(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(LocalNameTextBox.Text))
{
@@ -563,10 +551,6 @@
LocalNameTextBox.BackColor = Color.Empty;
LocalBindingsCheckedListBox.BackColor = Color.Empty;
 
LocalNameTextBox.AutoCompleteCustomSource.Add(LocalNameTextBox.Text);
 
await AutoCompletion.Save(LocalNameTextBox.Name, LocalNameTextBox.AutoCompleteCustomSource);
 
ShowOverlayPanel();
 
MouseKeyCombo = new List<string>();
@@ -623,11 +607,11 @@
 
private async void LocalBindingsRemoveButtonClick(object sender, EventArgs e)
{
var localBinding = (KeyBinding) LocalBindingsCheckedListBox.SelectedItem;
if (localBinding == null)
var helmBinding = (KeyBinding) LocalBindingsCheckedListBox.SelectedItem;
if (helmBinding == null)
return;
 
LocalKeyBindings.Bindings.Remove(localBinding);
LocalKeyBindings.Bindings.Remove(helmBinding);
LocalCheckedListBoxBindingSource.ResetBindings(false);
 
await SaveLocalMouseKeyBindings();
@@ -646,7 +630,7 @@
 
private void RemoteBindingsComboBoxSelectionChangeCompleted(object sender, EventArgs e)
{
UpdateRemoteBindingsListBox();
UpdateRemoteItems();
}
 
private async void WingManFormOnLoad(object sender, EventArgs e)
@@ -778,7 +762,7 @@
{
if (e.Button != MouseButtons.Left) return;
 
TabControlClickStartPosition = e.Location;
tabControlClickStartPosition = e.Location;
}
 
private void WingManTabControlMouseMove(object sender, MouseEventArgs e)
@@ -785,19 +769,19 @@
{
if (e.Button == MouseButtons.Left)
{
var mouseOffsetX = TabControlClickStartPosition.X - e.X;
var mouseOffsetY = TabControlClickStartPosition.Y - e.Y;
var mouseOffsetX = tabControlClickStartPosition.X - e.X;
var mouseOffsetY = tabControlClickStartPosition.Y - e.Y;
 
if (mouseOffsetX <= TabControlDetachPixelOffset && mouseOffsetY <= TabControlDetachPixelOffset)
if (mouseOffsetX <= tabControlDetachPixelOffset && mouseOffsetY <= tabControlDetachPixelOffset)
return;
 
tabControl1.DoDragDrop(tabControl1.SelectedTab, DragDropEffects.Move);
TabControlClickStartPosition = new Point();
tabControlClickStartPosition = new Point();
 
return;
}
 
TabControlClickStartPosition = new Point();
tabControlClickStartPosition = new Point();
}
 
private void WingManTabControlGiveFeedback(object sender, GiveFeedbackEventArgs e)
@@ -830,10 +814,7 @@
Location = MousePosition,
MaximizeBox = false,
SizeGripStyle = SizeGripStyle.Hide,
FormBorderStyle = FormBorderStyle.FixedSingle,
Name = Name,
Text = Text,
Icon = Icon
FormBorderStyle = FormBorderStyle.FixedSingle
};
 
DetachedTabControl = new TabControl
/trunk/WingMan/WingManForm.resx
@@ -960,10 +960,10 @@
SUVORK5CYII=
</value>
</data>
<metadata name="WingManNotifyIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="notifyIcon1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="WingManNotifyIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<data name="notifyIcon1.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAkAEBAAAAEAIABoBAAAlgAAABgYAAABACAAiAkAAP4EAAAgIAAAAQAgAKgQAACGDgAAMDAAAAEA
IACoJQAALh8AAEBAAAABACAAKEIAANZEAABgYAAAAQAgAKiUAAD+hgAAgIAAAAEAIAAoCAEAphsBAMDA
/trunk/WingMan/packages.config
@@ -9,6 +9,5 @@
<package id="MQTTnet" version="2.8.4" targetFramework="net452" />
<package id="MQTTnet.Extensions.ManagedClient" version="2.8.4" targetFramework="net452" />
<package id="Open.NAT" version="2.1.0.0" targetFramework="net452" />
<package id="protobuf-net" version="2.4.0" targetFramework="net452" />
<package id="SQLite.Native" version="3.12.3" targetFramework="net452" />
</packages>