mirror of https://github.com/quasar/Quasar.git
Improved UPnP support #280
This commit is contained in:
parent
1b24fd8d65
commit
0251e42cd3
|
@ -74,7 +74,7 @@ protected override void OnPaint(PaintEventArgs e)
|
|||
Alignment = StringAlignment.Center
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
g.DrawString(TabPages[i].Text, new Font(Font.FontFamily, Font.Size, FontStyle.Bold),
|
||||
Brushes.Black, x2, new StringFormat
|
||||
|
@ -118,7 +118,7 @@ protected override void OnPaint(PaintEventArgs e)
|
|||
Alignment = StringAlignment.Center
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
g.DrawString(TabPages[i].Text, Font, Brushes.DimGray, x2, new StringFormat
|
||||
{
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Mono.Nat;
|
||||
|
||||
namespace xServer.Core.Helper
|
||||
{
|
||||
internal static class UPnP
|
||||
{
|
||||
public static bool IsPortForwarded { get; private set; }
|
||||
public static ushort Port { get; private set; }
|
||||
private static readonly HashSet<INatDevice> Devices = new HashSet<INatDevice>();
|
||||
private static bool _eventSub;
|
||||
private static bool _isDiscovering;
|
||||
private static readonly object _isDiscoveringLock = new object();
|
||||
|
||||
public static void ForwardPort(ushort port)
|
||||
{
|
||||
lock (_isDiscoveringLock)
|
||||
{
|
||||
if (_isDiscovering) return;
|
||||
_isDiscovering = true;
|
||||
}
|
||||
|
||||
Port = port;
|
||||
|
||||
if (!_eventSub)
|
||||
{
|
||||
NatUtility.DeviceFound += DeviceFound;
|
||||
NatUtility.DeviceLost += DeviceLost;
|
||||
_eventSub = true;
|
||||
}
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
NatUtility.StartDiscovery();
|
||||
|
||||
int trys = 0;
|
||||
while (Devices.Count == 0 && trys < 8) // wait until first device found
|
||||
{
|
||||
trys++;
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
if (Devices.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var device in Devices)
|
||||
{
|
||||
if (device.GetSpecificMapping(Protocol.Tcp, Port).PublicPort < 0) // if port is not mapped
|
||||
{
|
||||
device.CreatePortMap(new Mapping(Protocol.Tcp, Port, Port));
|
||||
IsPortForwarded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MappingException)
|
||||
{
|
||||
IsPortForwarded = false;
|
||||
}
|
||||
}
|
||||
|
||||
NatUtility.StopDiscovery();
|
||||
|
||||
lock (_isDiscoveringLock)
|
||||
{
|
||||
_isDiscovering = false;
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
private static void DeviceFound(object sender, DeviceEventArgs args)
|
||||
{
|
||||
Devices.Add(args.Device);
|
||||
}
|
||||
|
||||
private static void DeviceLost(object sender, DeviceEventArgs args)
|
||||
{
|
||||
Devices.Remove(args.Device);
|
||||
}
|
||||
|
||||
public static void RemovePort()
|
||||
{
|
||||
foreach (var device in Devices)
|
||||
{
|
||||
if (device.GetSpecificMapping(Protocol.Tcp, Port).PublicPort > 0) // if port map exists
|
||||
{
|
||||
device.DeletePortMap(new Mapping(Protocol.Tcp, Port, Port));
|
||||
IsPortForwarded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using xServer.Core.Networking.Utilities;
|
||||
using xServer.Core.Packets;
|
||||
|
||||
namespace xServer.Core.Networking
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xServer.Core.Networking
|
||||
namespace xServer.Core.Networking.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a pool of byte arrays to improve allocation performance when parsing data.
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Nat;
|
||||
|
||||
namespace xServer.Core.Networking.Utilities
|
||||
{
|
||||
internal static class UPnP
|
||||
{
|
||||
private static Dictionary<int, Mapping> _mappings;
|
||||
private static bool _discoveryComplete;
|
||||
private static INatDevice _device;
|
||||
private static int _port = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the discovery of new UPnP devices.
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
_mappings = new Dictionary<int, Mapping>();
|
||||
|
||||
try
|
||||
{
|
||||
NatUtility.DeviceFound += DeviceFound;
|
||||
NatUtility.DeviceLost += DeviceLost;
|
||||
|
||||
_discoveryComplete = false;
|
||||
|
||||
NatUtility.StartDiscovery();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the discovery of new UPnP devices
|
||||
/// and creates a port map with the given port.
|
||||
/// </summary>
|
||||
/// <param name="port">The port to map.</param>
|
||||
public static void Initialize(int port)
|
||||
{
|
||||
_port = port;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells if the class found an UPnP device.
|
||||
/// </summary>
|
||||
public static bool IsDeviceFound
|
||||
{
|
||||
get { return _device != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new port map.
|
||||
/// </summary>
|
||||
/// <param name="port">The port to map.</param>
|
||||
/// <param name="externalPort">The port which has been mapped, -1 if it failed.</param>
|
||||
/// <returns>True if successfull, else False.</returns>
|
||||
public static bool CreatePortMap(int port, out int externalPort)
|
||||
{
|
||||
if (!_discoveryComplete)
|
||||
{
|
||||
externalPort = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Mapping mapping = new Mapping(Protocol.Tcp, port, port);
|
||||
_device.CreatePortMap(mapping);
|
||||
|
||||
if (_mappings.ContainsKey(mapping.PrivatePort))
|
||||
_mappings[mapping.PrivatePort] = mapping;
|
||||
else
|
||||
_mappings.Add(mapping.PrivatePort, mapping);
|
||||
|
||||
externalPort = mapping.PublicPort;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
externalPort = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an existing port map.
|
||||
/// </summary>
|
||||
/// <param name="port">The port to delete.</param>
|
||||
public static void DeletePortMap(int port)
|
||||
{
|
||||
if (!_discoveryComplete)
|
||||
return;
|
||||
|
||||
Mapping mapping;
|
||||
if (_mappings.TryGetValue(port, out mapping))
|
||||
{
|
||||
try
|
||||
{
|
||||
_device.DeletePortMap(mapping);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeviceFound(object sender, DeviceEventArgs args)
|
||||
{
|
||||
_device = args.Device;
|
||||
|
||||
NatUtility.StopDiscovery();
|
||||
|
||||
_discoveryComplete = true;
|
||||
|
||||
if (_port > 0)
|
||||
{
|
||||
int outPort;
|
||||
CreatePortMap(_port, out outPort);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeviceLost(object sender, DeviceEventArgs args)
|
||||
{
|
||||
_device = null;
|
||||
_discoveryComplete = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
using xServer.Core.Helper;
|
||||
using xServer.Core.Misc;
|
||||
using xServer.Core.Networking;
|
||||
using xServer.Core.Networking.Utilities;
|
||||
using xServer.Settings;
|
||||
using UserStatus = xServer.Core.Commands.CommandHandler.UserStatus;
|
||||
using ShutdownAction = xServer.Core.Commands.CommandHandler.ShutdownAction;
|
||||
|
@ -109,16 +110,22 @@ private void InitializeServer()
|
|||
ConServer.ClientDisconnected += ClientDisconnected;
|
||||
}
|
||||
|
||||
private void FrmMain_Load(object sender, EventArgs e)
|
||||
private void AutostartListeningP()
|
||||
{
|
||||
InitializeServer();
|
||||
|
||||
if (XMLSettings.AutoListen)
|
||||
if (XMLSettings.AutoListen && XMLSettings.UseUPnP)
|
||||
{
|
||||
if (XMLSettings.UseUPnP)
|
||||
UPnP.ForwardPort(ushort.Parse(XMLSettings.ListenPort.ToString()));
|
||||
UPnP.Initialize(XMLSettings.ListenPort);
|
||||
ConServer.Listen(XMLSettings.ListenPort);
|
||||
}
|
||||
else if (XMLSettings.AutoListen)
|
||||
{
|
||||
UPnP.Initialize();
|
||||
ConServer.Listen(XMLSettings.ListenPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPnP.Initialize();
|
||||
}
|
||||
|
||||
if (XMLSettings.IntegrateNoIP)
|
||||
{
|
||||
|
@ -126,13 +133,16 @@ private void FrmMain_Load(object sender, EventArgs e)
|
|||
}
|
||||
}
|
||||
|
||||
private void FrmMain_Load(object sender, EventArgs e)
|
||||
{
|
||||
InitializeServer();
|
||||
AutostartListeningP();
|
||||
}
|
||||
|
||||
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
ConServer.Disconnect();
|
||||
|
||||
if (UPnP.IsPortForwarded)
|
||||
UPnP.RemovePort();
|
||||
|
||||
UPnP.DeletePortMap(XMLSettings.ListenPort);
|
||||
nIcon.Visible = false;
|
||||
nIcon.Dispose();
|
||||
Instance = null;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using xServer.Core.Helper;
|
||||
using xServer.Core.Misc;
|
||||
using xServer.Core.Networking;
|
||||
using xServer.Core.Networking.Utilities;
|
||||
using xServer.Settings;
|
||||
|
||||
namespace xServer.Forms
|
||||
|
@ -42,17 +42,49 @@ private void FrmSettings_Load(object sender, EventArgs e)
|
|||
txtNoIPPass.Text = XMLSettings.NoIPPassword;
|
||||
}
|
||||
|
||||
private ushort GetPortSafe()
|
||||
{
|
||||
var portValue = ncPort.Value.ToString(CultureInfo.InvariantCulture);
|
||||
ushort port;
|
||||
return (!ushort.TryParse(portValue, out port)) ? (ushort)0 : port;
|
||||
}
|
||||
|
||||
private void btnListen_Click(object sender, EventArgs e)
|
||||
{
|
||||
ushort port = GetPortSafe();
|
||||
|
||||
if (port == 0)
|
||||
{
|
||||
MessageBox.Show("Please enter a valid port > 0.", "Please enter a valid port", MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btnListen.Text == "Start listening" && !_listenServer.Listening)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (chkUseUpnp.Checked && !UPnP.IsPortForwarded)
|
||||
UPnP.ForwardPort(ushort.Parse(ncPort.Value.ToString(CultureInfo.InvariantCulture)));
|
||||
if (chkUseUpnp.Checked)
|
||||
{
|
||||
if (!UPnP.IsDeviceFound)
|
||||
{
|
||||
MessageBox.Show("No available UPnP device found!", "No UPnP device", MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
int outPort;
|
||||
UPnP.CreatePortMap(port, out outPort);
|
||||
if (port != outPort)
|
||||
{
|
||||
MessageBox.Show("Creating a port map with the UPnP device failed!\nPlease check if your device allows to create new port maps.", "Creating port map failed", MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(chkNoIPIntegration.Checked)
|
||||
NoIpUpdater.Start();
|
||||
_listenServer.Listen(ushort.Parse(ncPort.Value.ToString(CultureInfo.InvariantCulture)));
|
||||
_listenServer.Listen(port);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -66,8 +98,7 @@ private void btnListen_Click(object sender, EventArgs e)
|
|||
try
|
||||
{
|
||||
_listenServer.Disconnect();
|
||||
if (UPnP.IsPortForwarded)
|
||||
UPnP.RemovePort();
|
||||
UPnP.DeletePortMap(port);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -80,8 +111,17 @@ private void btnListen_Click(object sender, EventArgs e)
|
|||
|
||||
private void btnSave_Click(object sender, EventArgs e)
|
||||
{
|
||||
XMLSettings.WriteValue("ListenPort", ncPort.Value.ToString(CultureInfo.InvariantCulture));
|
||||
XMLSettings.ListenPort = ushort.Parse(ncPort.Value.ToString(CultureInfo.InvariantCulture));
|
||||
ushort port = GetPortSafe();
|
||||
|
||||
if (port == 0)
|
||||
{
|
||||
MessageBox.Show("Please enter a valid port > 0.", "Please enter a valid port", MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
XMLSettings.WriteValue("ListenPort", port.ToString());
|
||||
XMLSettings.ListenPort = port;
|
||||
|
||||
XMLSettings.WriteValue("AutoListen", chkAutoListen.Checked.ToString());
|
||||
XMLSettings.AutoListen = chkAutoListen.Checked;
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
<Compile Include="Core\Encryption\AES.cs" />
|
||||
<Compile Include="Core\Helper\FileSplit.cs" />
|
||||
<Compile Include="Core\Helper\UnsafeStreamCodec.cs" />
|
||||
<Compile Include="Core\Helper\UPnP.cs" />
|
||||
<Compile Include="Core\Networking\Utilities\UPnP.cs" />
|
||||
<Compile Include="Core\Misc\InputBox.cs" />
|
||||
<Compile Include="Core\Compression\JpgCompression.cs" />
|
||||
<Compile Include="Core\Misc\ListViewColumnSorter.cs" />
|
||||
|
@ -93,7 +93,7 @@
|
|||
<Compile Include="Core\Misc\NoIpUpdater.cs" />
|
||||
<Compile Include="Core\Misc\SavedVariables.cs" />
|
||||
<Compile Include="Core\Networking\ConnectionHandler.cs" />
|
||||
<Compile Include="Core\Networking\PooledBufferManager.cs" />
|
||||
<Compile Include="Core\Networking\Utilities\PooledBufferManager.cs" />
|
||||
<Compile Include="Core\Packets\ClientPackets\GetDesktopResponse.cs" />
|
||||
<Compile Include="Core\Packets\ClientPackets\GetDirectoryResponse.cs" />
|
||||
<Compile Include="Core\Packets\ClientPackets\DoDownloadFileResponse.cs" />
|
||||
|
|
Loading…
Reference in New Issue