diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 484aff54c5..71b94c25aa 100755 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -267,15 +267,17 @@ namespace OpenRA try { NatUtility.Logger = Log.Channels["server"].Writer; - NatUtility.Verbose = true; + NatUtility.Verbose = Settings.Server.VerboseNatDiscovery; NatUtility.DeviceFound += DeviceFound; NatUtility.DeviceLost += DeviceLost; + Settings.Server.NatDeviceAvailable = false; NatUtility.StartDiscovery(); Log.Write("server", "NAT discovery started."); } catch (Exception e) { Log.Write("server", "Can't discover UPnP-enabled device: {0}", e); + Settings.Server.NatDeviceAvailable = false; Settings.Server.AllowUPnP = false; } @@ -289,6 +291,18 @@ namespace OpenRA Sound.Create(Settings.Sound.Engine); InitializeWithMods(Settings.Game.Mods); + + RunAfterDelay(Settings.Server.NatDiscoveryTimeout, () => + { + NatUtility.StopDiscovery(); + Log.Write("server", "NAT discovery stopped."); + if (natDevice == null) + { + Log.Write("server", "No NAT devices with UPnP enabled found within {0} ms deadline. Disabling automatic port forwarding.".F(Settings.Server.NatDiscoveryTimeout)); + Settings.Server.NatDeviceAvailable = false; + Settings.Server.AllowUPnP = false; + } + }); } public static void DeviceFound(object sender, DeviceEventArgs args) @@ -302,6 +316,7 @@ namespace OpenRA foreach (var mp in natDevice.GetAllMappings()) Log.Write("server", "Existing port mapping: protocol={0}, public={1}, private={2}", mp.Protocol, mp.PublicPort, mp.PrivatePort); + Settings.Server.NatDeviceAvailable = true; Settings.Server.AllowUPnP = true; } @@ -309,9 +324,10 @@ namespace OpenRA { natDevice = args.Device; - Log.Write("server", "NAT device Lost"); + Log.Write("server", "NAT device lost."); Log.Write("server", "Type: {0}", natDevice.GetType()); + Settings.Server.NatDeviceAvailable = false; Settings.Server.AllowUPnP = false; } diff --git a/OpenRA.Game/GameRules/Settings.cs b/OpenRA.Game/GameRules/Settings.cs index 527fe66866..2e2a179155 100644 --- a/OpenRA.Game/GameRules/Settings.cs +++ b/OpenRA.Game/GameRules/Settings.cs @@ -29,7 +29,10 @@ namespace OpenRA.GameRules public int ExternalPort = 1234; public bool AdvertiseOnline = true; public string MasterServer = "http://master.open-ra.org/"; - public bool AllowUPnP = true; + public bool AllowUPnP = true; // let the user disable it + public bool NatDeviceAvailable = false; // internal check if discovery succeeded + public int NatDiscoveryTimeout = 1000; // ms to search for UPnP enabled NATs + public bool VerboseNatDiscovery = false; // print very detailed logs for debugging public bool AllowCheats = false; public string Map = null; public string[] Ban = null; @@ -49,6 +52,9 @@ namespace OpenRA.GameRules AdvertiseOnline = other.AdvertiseOnline; MasterServer = other.MasterServer; AllowUPnP = other.AllowUPnP; + NatDeviceAvailable = other.NatDeviceAvailable; + NatDiscoveryTimeout = other.NatDiscoveryTimeout; + VerboseNatDiscovery = other.VerboseNatDiscovery; AllowCheats = other.AllowCheats; Map = other.Map; Ban = other.Ban; diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 20bae37b1a..5ca5dc5a4b 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -80,8 +80,6 @@ namespace OpenRA.Server { foreach (var t in ServerTraits.WithInterface()) t.GameEnded(this); - if (Settings.AllowUPnP) - RemovePortforward(); } public Server(IPEndPoint endpoint, string[] mods, ServerSettings settings, ModData modData, INatDevice natDevice) @@ -159,6 +157,8 @@ namespace OpenRA.Server if (State == ServerState.ShuttingDown) { EndGame(); + if (Settings.AllowUPnP) + RemovePortforward(); break; } } @@ -166,9 +166,6 @@ namespace OpenRA.Server foreach (var t in ServerTraits.WithInterface()) t.ServerShutdown(this); - if (Settings.AllowUPnP) - RemovePortforward(); - preConns.Clear(); conns.Clear(); try { listener.Stop(); } diff --git a/OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs index e93d00a2f4..c15dac9da7 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs @@ -69,6 +69,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic var UPnPCheckbox = panel.Get("UPNP_CHECKBOX"); UPnPCheckbox.IsChecked = () => allowUPnP; UPnPCheckbox.OnClick = () => allowUPnP ^= true; + UPnPCheckbox.IsDisabled = () => !Game.Settings.Server.NatDeviceAvailable; } void CreateAndJoin() diff --git a/mods/cnc/chrome/createserver.yaml b/mods/cnc/chrome/createserver.yaml index 839eea09f4..9f6ce6eaaf 100644 --- a/mods/cnc/chrome/createserver.yaml +++ b/mods/cnc/chrome/createserver.yaml @@ -75,7 +75,7 @@ Container@CREATESERVER_PANEL: Y:180 Width:300 Height:20 - Text:Allow UPnP port forwarding + Text:Automatic port forwarding Label@EXTERNAL_PORT_LABEL: X:15 Y:219 diff --git a/mods/ra/chrome/create-server.yaml b/mods/ra/chrome/create-server.yaml index 3a81044bd2..c8427d0fc5 100644 --- a/mods/ra/chrome/create-server.yaml +++ b/mods/ra/chrome/create-server.yaml @@ -65,7 +65,7 @@ Background@CREATESERVER_BG: Y:165 Width:300 Height:20 - Text:Allow UPnP port forwarding + Text:Automatic port forwarding Button@CREATE_BUTTON: X:130 Y:PARENT_BOTTOM - 45