diff --git a/Server/Controls/DotNetBarTabControl.cs b/Server/Controls/DotNetBarTabControl.cs index 2232bd0d..e46e837d 100644 --- a/Server/Controls/DotNetBarTabControl.cs +++ b/Server/Controls/DotNetBarTabControl.cs @@ -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 { diff --git a/Server/Core/Helper/UPnP.cs b/Server/Core/Helper/UPnP.cs deleted file mode 100644 index 93983659..00000000 --- a/Server/Core/Helper/UPnP.cs +++ /dev/null @@ -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 Devices = new HashSet(); - 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; - } - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Networking/Server.cs b/Server/Core/Networking/Server.cs index 7e84dbf7..03cf53ae 100644 --- a/Server/Core/Networking/Server.cs +++ b/Server/Core/Networking/Server.cs @@ -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 diff --git a/Server/Core/Networking/PooledBufferManager.cs b/Server/Core/Networking/Utilities/PooledBufferManager.cs similarity index 99% rename from Server/Core/Networking/PooledBufferManager.cs rename to Server/Core/Networking/Utilities/PooledBufferManager.cs index ebd71adf..5025b511 100644 --- a/Server/Core/Networking/PooledBufferManager.cs +++ b/Server/Core/Networking/Utilities/PooledBufferManager.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace xServer.Core.Networking +namespace xServer.Core.Networking.Utilities { /// /// Implements a pool of byte arrays to improve allocation performance when parsing data. diff --git a/Server/Core/Networking/Utilities/UPnP.cs b/Server/Core/Networking/Utilities/UPnP.cs new file mode 100644 index 00000000..7d867269 --- /dev/null +++ b/Server/Core/Networking/Utilities/UPnP.cs @@ -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 _mappings; + private static bool _discoveryComplete; + private static INatDevice _device; + private static int _port = -1; + + /// + /// Initializes the discovery of new UPnP devices. + /// + public static void Initialize() + { + _mappings = new Dictionary(); + + try + { + NatUtility.DeviceFound += DeviceFound; + NatUtility.DeviceLost += DeviceLost; + + _discoveryComplete = false; + + NatUtility.StartDiscovery(); + } + catch (Exception) + { + } + } + + /// + /// Initializes the discovery of new UPnP devices + /// and creates a port map with the given port. + /// + /// The port to map. + public static void Initialize(int port) + { + _port = port; + Initialize(); + } + + /// + /// Tells if the class found an UPnP device. + /// + public static bool IsDeviceFound + { + get { return _device != null; } + } + + /// + /// Creates a new port map. + /// + /// The port to map. + /// The port which has been mapped, -1 if it failed. + /// True if successfull, else False. + 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; + } + } + + /// + /// Deletes an existing port map. + /// + /// The port to delete. + 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; + } + } +} \ No newline at end of file diff --git a/Server/Forms/FrmMain.cs b/Server/Forms/FrmMain.cs index dc2b0be7..de781260 100644 --- a/Server/Forms/FrmMain.cs +++ b/Server/Forms/FrmMain.cs @@ -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; diff --git a/Server/Forms/FrmSettings.cs b/Server/Forms/FrmSettings.cs index c1878c2f..b9f97bff 100644 --- a/Server/Forms/FrmSettings.cs +++ b/Server/Forms/FrmSettings.cs @@ -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; diff --git a/Server/Server.csproj b/Server/Server.csproj index 18c44634..7db7135d 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -85,7 +85,7 @@ - + @@ -93,7 +93,7 @@ - +