/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,24 +42,56 @@ |
{ |
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 disocvery type"); |
throw new ArgumentException("Unknown discovery type"); |
} |
} |
|
private async Task<bool> CreateUPnPMapping(int port) |
public async Task<bool> DeleteMapping(DiscoveryType type, 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; |
@@ -67,7 +99,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; |
@@ -74,15 +106,33 @@ |
} |
} |
|
private async Task<bool> CreatePMPPortMapping(int port) |
private async Task<bool> DeletePmpPortMapping(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; |
} |
@@ -89,7 +139,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/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,21 +28,22 @@ |
{ |
var outputStream = new MemoryStream(); |
|
using (var rijdanelManaged = new RijndaelManaged()) |
using (var aesManaged = new AesManaged()) |
{ |
// FIPS-197 / CBC |
rijdanelManaged.BlockSize = AesBlockSize; |
rijdanelManaged.Mode = AesCipherMode; |
rijdanelManaged.Padding = AesPaddingMode; |
aesManaged.BlockSize = AesBlockSize; |
aesManaged.Mode = AesCipherMode; |
aesManaged.Padding = AesPaddingMode; |
aesManaged.KeySize = AesKeySize; |
|
// Compute the salt and the IV from the key. |
var salt = new byte[AesKeySaltBytes]; |
Rng.GetBytes(salt); |
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations); |
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8); |
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8); |
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8); |
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8); |
|
using (var encryptor = rijdanelManaged.CreateEncryptor(rijdanelManaged.Key, rijdanelManaged.IV)) |
using (var encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV)) |
{ |
using (var memoryStream = new MemoryStream()) |
{ |
@@ -76,21 +77,22 @@ |
/// <returns>an encrypted byte array</returns> |
public static async Task<byte[]> Encrypt(byte[] data, string key) |
{ |
using (var rijdanelManaged = new RijndaelManaged()) |
using (var aesManaged = new AesManaged()) |
{ |
// FIPS-197 / CBC |
rijdanelManaged.BlockSize = AesBlockSize; |
rijdanelManaged.Mode = AesCipherMode; |
rijdanelManaged.Padding = AesPaddingMode; |
aesManaged.BlockSize = AesBlockSize; |
aesManaged.Mode = AesCipherMode; |
aesManaged.Padding = AesPaddingMode; |
aesManaged.KeySize = AesKeySize; |
|
// Compute the salt and the IV from the key. |
var salt = new byte[AesKeySaltBytes]; |
Rng.GetBytes(salt); |
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations); |
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8); |
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8); |
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8); |
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8); |
|
using (var encryptor = rijdanelManaged.CreateEncryptor(rijdanelManaged.Key, rijdanelManaged.IV)) |
using (var encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV)) |
{ |
using (var memoryStream = new MemoryStream()) |
{ |
@@ -133,19 +135,20 @@ |
//var salt = data.Take(AesKeySaltBytes).ToArray(); |
//var text = data.Skip(AesKeySaltBytes).ToArray(); |
|
using (var rijdanelManaged = new RijndaelManaged()) |
using (var aesManaged = new AesManaged()) |
{ |
// FIPS-197 / CBC |
rijdanelManaged.BlockSize = AesBlockSize; |
rijdanelManaged.Mode = AesCipherMode; |
rijdanelManaged.Padding = AesPaddingMode; |
aesManaged.BlockSize = AesBlockSize; |
aesManaged.Mode = AesCipherMode; |
aesManaged.Padding = AesPaddingMode; |
aesManaged.KeySize = AesKeySize; |
|
// Retrieve the key and the IV from the salt. |
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations); |
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8); |
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8); |
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8); |
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8); |
|
using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV)) |
using (var decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV)) |
{ |
using (var memoryStream = new MemoryStream(text)) |
{ |
@@ -176,19 +179,20 @@ |
var salt = data.Take(AesKeySaltBytes).ToArray(); |
var text = data.Skip(AesKeySaltBytes).ToArray(); |
|
using (var rijdanelManaged = new RijndaelManaged()) |
using (var aesManaged = new AesManaged()) |
{ |
// FIPS-197 / CBC |
rijdanelManaged.BlockSize = AesBlockSize; |
rijdanelManaged.Mode = AesCipherMode; |
rijdanelManaged.Padding = AesPaddingMode; |
aesManaged.BlockSize = AesBlockSize; |
aesManaged.Mode = AesCipherMode; |
aesManaged.Padding = AesPaddingMode; |
aesManaged.KeySize = AesKeySize; |
|
// Retrieve the key and the IV from the salt. |
var derivedKey = new Rfc2898DeriveBytes(key, salt, AesKeyIterations); |
rijdanelManaged.Key = derivedKey.GetBytes(rijdanelManaged.KeySize / 8); |
rijdanelManaged.IV = derivedKey.GetBytes(rijdanelManaged.BlockSize / 8); |
aesManaged.Key = derivedKey.GetBytes(aesManaged.KeySize / 8); |
aesManaged.IV = derivedKey.GetBytes(aesManaged.BlockSize / 8); |
|
using (var decryptor = rijdanelManaged.CreateDecryptor(rijdanelManaged.Key, rijdanelManaged.IV)) |
using (var decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV)) |
{ |
using (var memoryStream = new MemoryStream(text)) |
{ |
@@ -208,15 +212,12 @@ |
} |
} |
|
public static string ExpandKey(string password, int size = 32) |
public static string ExpandKey(string password, int length = 32) |
{ |
var sb = new StringBuilder(password); |
do |
{ |
sb.Append(password); |
} while (sb.Length < size); |
|
return sb.ToString(0, size); |
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; |
} |
} |
} |
/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.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components); |
this.WingManNotifyIcon = 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, 337); |
this.groupBox2.Size = new System.Drawing.Size(530, 332); |
this.groupBox2.TabIndex = 1; |
this.groupBox2.TabStop = false; |
this.groupBox2.Text = "Lobby"; |
@@ -245,6 +245,8 @@ |
// |
// 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"; |
@@ -430,7 +432,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, 337); |
this.tabPage2.Size = new System.Drawing.Size(530, 332); |
this.tabPage2.TabIndex = 1; |
this.tabPage2.Text = "Bindings"; |
this.tabPage2.UseVisualStyleBackColor = true; |
@@ -441,7 +443,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, 337); |
this.tabPage3.Size = new System.Drawing.Size(530, 332); |
this.tabPage3.TabIndex = 2; |
this.tabPage3.Text = "Chat"; |
this.tabPage3.UseVisualStyleBackColor = true; |
@@ -492,12 +494,12 @@ |
this.OverlayPanelLabel.TabIndex = 0; |
this.OverlayPanelLabel.Text = "Press key-combination to bind..."; |
// |
// notifyIcon1 |
// WingManNotifyIcon |
// |
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); |
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); |
// |
// WingManForm |
// |
@@ -578,7 +580,7 @@ |
private System.Windows.Forms.Label OverlayPanelLabel; |
private System.Windows.Forms.Label label6; |
private System.Windows.Forms.TextBox Password; |
private System.Windows.Forms.NotifyIcon notifyIcon1; |
private System.Windows.Forms.NotifyIcon WingManNotifyIcon; |
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,6 +45,7 @@ |
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; |
@@ -65,6 +66,7 @@ |
DataSource = LocalKeyBindings.Bindings |
}; |
LocalCheckedListBoxBindingSource.ListChanged += LocalCheckedListBoxBindingSourceOnListChanged; |
|
LocalBindingsCheckedListBox.DisplayMember = "DisplayName"; |
LocalBindingsCheckedListBox.ValueMember = "Keys"; |
LocalBindingsCheckedListBox.DataSource = LocalCheckedListBoxBindingSource; |
@@ -78,10 +80,13 @@ |
{ |
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); |
@@ -113,7 +118,7 @@ |
|
private List<string> MouseKeyCombo { get; set; } |
|
private LocalKeyBindings LocalKeyBindings { get; } |
public LocalKeyBindings LocalKeyBindings { get; set; } |
|
private RemoteKeyBindings RemoteKeyBindings { get; } |
|
@@ -133,19 +138,24 @@ |
|
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; |
@@ -281,47 +291,36 @@ |
{ |
KeyBindingsExchange.ExchangeBindings.Add(e.Bindings); |
RemoteBindingsComboBoxSource.ResetBindings(false); |
UpdateRemoteItems(); |
return; |
} |
|
// If the bindings for the nick have not changed then do not update. |
if (exchangeBindings.KeyBindings.SequenceEqual(e.Bindings.KeyBindings)) |
if (e.Bindings.KeyBindings.Count == exchangeBindings.KeyBindings.Count && |
e.Bindings.KeyBindings.All(exchangeBindings.KeyBindings.Contains)) |
{ |
RemoteBindingsComboBoxSource.ResetBindings(false); |
UpdateRemoteItems(); |
return; |
} |
|
// Update the bindings. |
exchangeBindings.KeyBindings = e.Bindings.KeyBindings; |
exchangeBindings.KeyBindings.RemoveAll(binding => !e.Bindings.KeyBindings.Contains(binding)); |
exchangeBindings.KeyBindings.AddRange( |
e.Bindings.KeyBindings.Where(binding => !exchangeBindings.KeyBindings.Contains(binding))); |
RemoteBindingsComboBoxSource.ResetBindings(false); |
UpdateRemoteItems(); |
} |
|
private void UpdateRemoteItems() |
private void UpdateRemoteBindingsListBox() |
{ |
var exchangeBindings = (List<KeyBinding>) RemoteBindingsComboBox.SelectedValue; |
if (exchangeBindings == null) |
var keyBindingExchange = (KeyBindingExchange) RemoteBindingsComboBox.SelectedItem; |
if (keyBindingExchange == 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; |
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(); |
|
replaceMouseBindings.Add(remoteBinding); |
} |
|
RemoteKeyBindings.Bindings.Clear(); |
foreach (var binding in replaceMouseBindings) RemoteKeyBindings.Bindings.Add(binding); |
|
RemoteBindingsListBox.Items.Clear(); |
RemoteBindingsListBox.DisplayMember = "Name"; |
RemoteBindingsListBox.ValueMember = "Name"; |
var bindings = exchangeBindings.Select(binding => (object) binding.Name).ToArray(); |
if (bindings.Length == 0) |
return; |
|
@@ -330,9 +329,9 @@ |
|
private void OnLobbyMessageReceived(object sender, LobbyMessageReceivedEventArgs e) |
{ |
notifyIcon1.BalloonTipTitle = Strings.Lobby_message; |
notifyIcon1.BalloonTipText = $"{e.Nick} : {e.Message}{Environment.NewLine}"; |
notifyIcon1.ShowBalloonTip(1000); |
WingManNotifyIcon.BalloonTipTitle = Strings.Lobby_message; |
WingManNotifyIcon.BalloonTipText = $"{e.Nick} : {e.Message}{Environment.NewLine}"; |
WingManNotifyIcon.ShowBalloonTip(1000); |
|
LobbyTextBox.AppendText($"{e.Nick} : {e.Message}{Environment.NewLine}"); |
} |
@@ -352,7 +351,16 @@ |
// 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. |
@@ -370,10 +378,14 @@ |
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}"); |
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); |
|
// Start the MQTT server. |
if (!await MqttCommunication |
@@ -468,7 +480,7 @@ |
return false; |
} |
|
password = AES.ExpandKey(Password.Text); |
password = Aes.ExpandKey(Password.Text); |
|
Address.BackColor = Color.Empty; |
Port.BackColor = Color.Empty; |
@@ -531,7 +543,7 @@ |
LobbySayTextBox.Text = string.Empty; |
} |
|
private void LocalAddBindingButtonClick(object sender, EventArgs e) |
private async void LocalAddBindingButtonClick(object sender, EventArgs e) |
{ |
if (string.IsNullOrEmpty(LocalNameTextBox.Text)) |
{ |
@@ -551,6 +563,10 @@ |
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>(); |
@@ -607,11 +623,11 @@ |
|
private async void LocalBindingsRemoveButtonClick(object sender, EventArgs e) |
{ |
var helmBinding = (KeyBinding) LocalBindingsCheckedListBox.SelectedItem; |
if (helmBinding == null) |
var localBinding = (KeyBinding) LocalBindingsCheckedListBox.SelectedItem; |
if (localBinding == null) |
return; |
|
LocalKeyBindings.Bindings.Remove(helmBinding); |
LocalKeyBindings.Bindings.Remove(localBinding); |
LocalCheckedListBoxBindingSource.ResetBindings(false); |
|
await SaveLocalMouseKeyBindings(); |
@@ -630,7 +646,7 @@ |
|
private void RemoteBindingsComboBoxSelectionChangeCompleted(object sender, EventArgs e) |
{ |
UpdateRemoteItems(); |
UpdateRemoteBindingsListBox(); |
} |
|
private async void WingManFormOnLoad(object sender, EventArgs e) |
@@ -762,7 +778,7 @@ |
{ |
if (e.Button != MouseButtons.Left) return; |
|
tabControlClickStartPosition = e.Location; |
TabControlClickStartPosition = e.Location; |
} |
|
private void WingManTabControlMouseMove(object sender, MouseEventArgs e) |
@@ -769,19 +785,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) |
@@ -814,7 +830,10 @@ |
Location = MousePosition, |
MaximizeBox = false, |
SizeGripStyle = SizeGripStyle.Hide, |
FormBorderStyle = FormBorderStyle.FixedSingle |
FormBorderStyle = FormBorderStyle.FixedSingle, |
Name = Name, |
Text = Text, |
Icon = Icon |
}; |
|
DetachedTabControl = new TabControl |