Port back to Mono.Nat and make discovery async.
This commit is contained in:
committed by
Paul Chote
parent
3f510b6d93
commit
d15e7f76fc
101
OpenRA.Game/Network/Nat.cs
Normal file
101
OpenRA.Game/Network/Nat.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Mono.Nat;
|
||||
|
||||
namespace OpenRA.Network
|
||||
{
|
||||
public enum NatStatus { Enabled, Disabled, NotSupported }
|
||||
|
||||
public class Nat
|
||||
{
|
||||
public static NatStatus Status => NatUtility.IsSearching ? natDevice != null ? NatStatus.Enabled : NatStatus.NotSupported : NatStatus.Disabled;
|
||||
|
||||
static Mapping mapping;
|
||||
static INatDevice natDevice;
|
||||
static bool initialized;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
if (Game.Settings.Server.DiscoverNatDevices)
|
||||
{
|
||||
NatUtility.DeviceFound += DeviceFound;
|
||||
NatUtility.StartDiscovery();
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
static readonly SemaphoreSlim Locker = new SemaphoreSlim(1, 1);
|
||||
|
||||
static async void DeviceFound(object sender, DeviceEventArgs args)
|
||||
{
|
||||
await Locker.WaitAsync();
|
||||
try
|
||||
{
|
||||
// Only interact with one at a time. Some support both UPnP and NAT-PMP.
|
||||
natDevice = args.Device;
|
||||
|
||||
Log.Write("nat", "Device found: {0}", natDevice.DeviceEndpoint);
|
||||
Log.Write("nat", "Type: {0}", natDevice.NatProtocol);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Locker.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryForwardPort(int listen, int external)
|
||||
{
|
||||
if (natDevice == null)
|
||||
return false;
|
||||
|
||||
var lifetime = Game.Settings.Server.NatPortMappingLifetime;
|
||||
mapping = new Mapping(Protocol.Tcp, listen, external, lifetime, "OpenRA");
|
||||
try
|
||||
{
|
||||
natDevice.CreatePortMap(mapping);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Port forwarding failed: {0}", e.Message);
|
||||
Log.Write("nat", e.StackTrace);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryRemovePortForward()
|
||||
{
|
||||
if (natDevice == null)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
natDevice.DeletePortMap(mapping);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Port removal failed: {0}", e.Message);
|
||||
Log.Write("nat", e.StackTrace);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Open.Nat;
|
||||
|
||||
namespace OpenRA.Network
|
||||
{
|
||||
public enum UPnPStatus { Enabled, Disabled, NotSupported }
|
||||
|
||||
public class UPnP
|
||||
{
|
||||
static NatDevice natDevice;
|
||||
static Mapping mapping;
|
||||
static bool initialized;
|
||||
|
||||
public static IPAddress ExternalIP { get; private set; }
|
||||
public static UPnPStatus Status =>
|
||||
initialized ? natDevice != null ?
|
||||
UPnPStatus.Enabled : UPnPStatus.NotSupported : UPnPStatus.Disabled;
|
||||
|
||||
public static async Task DiscoverNatDevices(int timeout)
|
||||
{
|
||||
initialized = true;
|
||||
|
||||
NatDiscoverer.TraceSource.Switch.Level = SourceLevels.Verbose;
|
||||
var logChannel = Log.Channel("nat");
|
||||
NatDiscoverer.TraceSource.Listeners.Add(new TextWriterTraceListener(logChannel.Writer));
|
||||
|
||||
var natDiscoverer = new NatDiscoverer();
|
||||
var token = new CancellationTokenSource(timeout);
|
||||
natDevice = await natDiscoverer.DiscoverDeviceAsync(PortMapper.Upnp, token);
|
||||
try
|
||||
{
|
||||
ExternalIP = await natDevice.GetExternalIPAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Getting the external IP from NAT device failed: {0}", e.Message);
|
||||
Log.Write("nat", e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ForwardPort(int listen, int external)
|
||||
{
|
||||
mapping = new Mapping(Protocol.Tcp, listen, external, "OpenRA");
|
||||
try
|
||||
{
|
||||
await natDevice.CreatePortMapAsync(mapping);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Port forwarding failed: {0}", e.Message);
|
||||
Log.Write("nat", e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task RemovePortForward()
|
||||
{
|
||||
try
|
||||
{
|
||||
await natDevice.DeletePortMapAsync(mapping);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Port removal failed: {0}", e.Message);
|
||||
Log.Write("nat", e.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user