1 #region Copyright & License Information 2 /* 3 * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 4 * This file is part of OpenRA, which is free software. It is made 5 * available to you under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, either version 3 of 7 * the License, or (at your option) any later version. For more 8 * information, see COPYING. 9 */ 10 #endregion 11 12 using System; 13 using System.Diagnostics; 14 using System.Net; 15 using System.Threading; 16 using System.Threading.Tasks; 17 18 using Open.Nat; 19 20 namespace OpenRA.Network 21 { 22 public enum UPnPStatus { Enabled, Disabled, NotSupported } 23 24 public class UPnP 25 { 26 static NatDevice natDevice; 27 static Mapping mapping; 28 static bool initialized; 29 30 public static IPAddress ExternalIP { get; private set; } 31 public static UPnPStatus Status 32 { 33 get 34 { 35 return initialized ? natDevice != null ? 36 UPnPStatus.Enabled : UPnPStatus.NotSupported : UPnPStatus.Disabled; 37 } 38 } 39 DiscoverNatDevices(int timeout)40 public static async Task DiscoverNatDevices(int timeout) 41 { 42 initialized = true; 43 44 NatDiscoverer.TraceSource.Switch.Level = SourceLevels.Verbose; 45 var logChannel = Log.Channel("nat"); 46 NatDiscoverer.TraceSource.Listeners.Add(new TextWriterTraceListener(logChannel.Writer)); 47 48 var natDiscoverer = new NatDiscoverer(); 49 var token = new CancellationTokenSource(timeout); 50 natDevice = await natDiscoverer.DiscoverDeviceAsync(PortMapper.Upnp, token); 51 try 52 { 53 ExternalIP = await natDevice.GetExternalIPAsync(); 54 } 55 catch (Exception e) 56 { 57 Console.WriteLine("Getting the external IP from NAT device failed: {0}", e.Message); 58 Log.Write("nat", e.StackTrace); 59 } 60 } 61 ForwardPort(int listen, int external)62 public static async Task ForwardPort(int listen, int external) 63 { 64 mapping = new Mapping(Protocol.Tcp, listen, external, "OpenRA"); 65 try 66 { 67 await natDevice.CreatePortMapAsync(mapping); 68 } 69 catch (Exception e) 70 { 71 Console.WriteLine("Port forwarding failed: {0}", e.Message); 72 Log.Write("nat", e.StackTrace); 73 } 74 } 75 RemovePortForward()76 public static async Task RemovePortForward() 77 { 78 try 79 { 80 await natDevice.DeletePortMapAsync(mapping); 81 } 82 catch (Exception e) 83 { 84 Console.WriteLine("Port removal failed: {0}", e.Message); 85 Log.Write("nat", e.StackTrace); 86 } 87 } 88 } 89 } 90