From 9abedc9bc7fb58568e14c1843c2142755ebdff32 Mon Sep 17 00:00:00 2001 From: Bitl Date: Sun, 3 Sep 2017 09:52:14 -0700 Subject: [PATCH] UPNP --- .../RBXLegacyLauncher/MainForm.cs | 70 +++++++++++------- .../RBXLegacyLauncher.csproj | 3 + .../RBXLegacyLauncher/Resources/Mono.Nat.dll | Bin 0 -> 42496 bytes 3 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 RBXLegacyLauncher/RBXLegacyLauncher/Resources/Mono.Nat.dll diff --git a/RBXLegacyLauncher/RBXLegacyLauncher/MainForm.cs b/RBXLegacyLauncher/RBXLegacyLauncher/MainForm.cs index d8b6a5c..12fe28c 100644 --- a/RBXLegacyLauncher/RBXLegacyLauncher/MainForm.cs +++ b/RBXLegacyLauncher/RBXLegacyLauncher/MainForm.cs @@ -18,6 +18,45 @@ namespace RBXLegacyLauncher { InitializeComponent(); } + + public event EventHandler evNATdone; + + public class evNATdoneargs : EventArgs + { + public string IP; + public int port; + } + + //this class contains network connectivity stuff + public void StartUPNP() + { + Mono.Nat.NatUtility.DeviceFound += new EventHandler(NatUtility_DeviceFound); + Mono.Nat.NatUtility.DeviceLost += new EventHandler(NatUtility_DeviceLost); + Mono.Nat.NatUtility.StartDiscovery(); + } + + private void NatUtility_DeviceFound(object sender, Mono.Nat.DeviceEventArgs e) + { + //do port forwarding with UPNP + Mono.Nat.INatDevice natd = e.Device; + natd.CreatePortMap(new Mono.Nat.Mapping(Mono.Nat.Protocol.Tcp,GlobalVars.ServerPort,GlobalVars.ServerPort)); + natd.CreatePortMap(new Mono.Nat.Mapping(Mono.Nat.Protocol.Udp,GlobalVars.ServerPort,GlobalVars.ServerPort)); + ConsolePrint("Port " + GlobalVars.ServerPort.ToString() + " registered to device " + natd.GetExternalIP().ToString(), 3); + evNATdoneargs args = new evNATdoneargs(); + args.IP = natd.GetExternalIP().ToString(); + args.port = GlobalVars.ServerPort; + evNATdone(this, args); + //MessageBox.Show("NAT done! My public IP is " + IP); + } + + private void NatUtility_DeviceLost(object sender, Mono.Nat.DeviceEventArgs e) + { + //do port forwarding with UPNP + Mono.Nat.INatDevice natd = e.Device; + natd.DeletePortMap(new Mono.Nat.Mapping(Mono.Nat.Protocol.Tcp,GlobalVars.ServerPort,GlobalVars.ServerPort)); + natd.DeletePortMap(new Mono.Nat.Mapping(Mono.Nat.Protocol.Udp,GlobalVars.ServerPort,GlobalVars.ServerPort)); + } + void tabControl1_SelectedIndexChanged(object sender, EventArgs e) { if (tabControl1.SelectedTab == tabControl1.TabPages["tabPage2"]) @@ -110,7 +149,7 @@ namespace RBXLegacyLauncher { if (GlobalVars.upnp == true) { - //TODO: find good libary for UPNP + StartUPNP(); } WriteConfigValues(); StartServer(); @@ -767,14 +806,7 @@ namespace RBXLegacyLauncher try { ConsolePrint("Server Loaded.", 4); - Process server = new Process(); - server.StartInfo.FileName = rbxexe; - server.StartInfo.Arguments = args; - if (GlobalVars.upnp == true) - { - server.Exited += new EventHandler(ServerExited); - } - server.Start(); + Process.Start(rbxexe, args); } catch (Exception ex) { @@ -801,14 +833,7 @@ namespace RBXLegacyLauncher try { ConsolePrint("Server Loaded in No3D mode.", 4); - Process server = new Process(); - server.StartInfo.FileName = rbxexe; - server.StartInfo.Arguments = args; - if (GlobalVars.upnp == true) - { - server.Exited += new EventHandler(ServerExited); - } - server.Start(); + Process.Start(rbxexe, args); } catch (Exception ex) { @@ -817,11 +842,6 @@ namespace RBXLegacyLauncher } } - void ServerExited(object sender, EventArgs e) - { - //TODO: find good libary for UPNP - } - void StartStudio() { string mapfile = GlobalVars.MapsDir + @"\\" + GlobalVars.Map; @@ -864,7 +884,7 @@ namespace RBXLegacyLauncher { if (GlobalVars.upnp == true) { - //TODO: find good libary for UPNP + StartUPNP(); } StartServer(); } @@ -872,7 +892,7 @@ namespace RBXLegacyLauncher { if (GlobalVars.upnp == true) { - //TODO: find good libary for UPNP + StartUPNP(); } StartServerNo3D(); } @@ -880,7 +900,7 @@ namespace RBXLegacyLauncher { if (GlobalVars.upnp == true) { - //TODO: find good libary for UPNP + StartUPNP(); } StartServerNo3D(); } diff --git a/RBXLegacyLauncher/RBXLegacyLauncher/RBXLegacyLauncher.csproj b/RBXLegacyLauncher/RBXLegacyLauncher/RBXLegacyLauncher.csproj index 97ef50d..56a95df 100644 --- a/RBXLegacyLauncher/RBXLegacyLauncher/RBXLegacyLauncher.csproj +++ b/RBXLegacyLauncher/RBXLegacyLauncher/RBXLegacyLauncher.csproj @@ -49,6 +49,9 @@ ..\..\..\RBXLegacy\release\RBXLegacy\RBXLegacyLauncher.exe + + Resources\Mono.Nat.dll + diff --git a/RBXLegacyLauncher/RBXLegacyLauncher/Resources/Mono.Nat.dll b/RBXLegacyLauncher/RBXLegacyLauncher/Resources/Mono.Nat.dll new file mode 100644 index 0000000000000000000000000000000000000000..614b2c233228c02d6dcad894ed490c57a9efd9cd GIT binary patch literal 42496 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 VRe!gxT;7#^Y?l9_{(sj3{|C9aI;8*r literal 0 HcmV?d00001