Files
OpenRA/OpenRA.Game/Network/Nat.cs
2021-03-27 18:36:12 +00:00

102 lines
2.3 KiB
C#

#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;
}
}
}