preview 2
This commit is contained in:
parent
47d50ad458
commit
0d1c7cb76a
162
3DView.rbxl
162
3DView.rbxl
|
|
@ -28,18 +28,18 @@
|
|||
<Ref name="CameraSubject">null</Ref>
|
||||
<token name="CameraType">0</token>
|
||||
<CoordinateFrame name="CoordinateFrame">
|
||||
<X>2.8825047</X>
|
||||
<Y>16.8061104</Y>
|
||||
<Z>19.8420525</Z>
|
||||
<R00>0.990262866</R00>
|
||||
<R01>-0.0670645982</R01>
|
||||
<R02>0.121990994</R02>
|
||||
<R10>3.7252903e-009</R10>
|
||||
<R11>0.876308203</R11>
|
||||
<R12>0.481750816</R12>
|
||||
<R20>-0.139210135</R20>
|
||||
<R21>-0.477059931</R21>
|
||||
<R22>0.8677755</R22>
|
||||
<X>21.9769001</X>
|
||||
<Y>13.1075497</Y>
|
||||
<Z>-9.91257381</Z>
|
||||
<R00>-0.342057496</R00>
|
||||
<R01>-0.313667655</R01>
|
||||
<R02>0.885781765</R02>
|
||||
<R10>-7.45057971e-009</R10>
|
||||
<R11>0.942642868</R11>
|
||||
<R12>0.333802998</R12>
|
||||
<R20>-0.939678967</R20>
|
||||
<R21>0.114179812</R21>
|
||||
<R22>-0.322438091</R22>
|
||||
</CoordinateFrame>
|
||||
<CoordinateFrame name="Focus">
|
||||
<X>-0.167192921</X>
|
||||
|
|
@ -324,6 +324,112 @@
|
|||
end
|
||||
end
|
||||
|
||||
script.Parent.MouseButton1Down:connect(onClicked)</ProtectedString>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="TextButton" referent="RBX15">
|
||||
<Properties>
|
||||
<bool name="Active">true</bool>
|
||||
<bool name="AutoButtonColor">true</bool>
|
||||
<Color3 name="BackgroundColor3">4288914085</Color3>
|
||||
<float name="BackgroundTransparency">0.400000006</float>
|
||||
<Color3 name="BorderColor3">4279970357</Color3>
|
||||
<int name="BorderSizePixel">0</int>
|
||||
<token name="Font">0</token>
|
||||
<token name="FontSize">0</token>
|
||||
<string name="Name">BackgroundColor</string>
|
||||
<UDim2 name="Position">
|
||||
<XS>1</XS>
|
||||
<XO>-155</XO>
|
||||
<YS>1</YS>
|
||||
<YO>-75</YO>
|
||||
</UDim2>
|
||||
<bool name="Selected">false</bool>
|
||||
<UDim2 name="Size">
|
||||
<XS>0</XS>
|
||||
<XO>150</XO>
|
||||
<YS>0</YS>
|
||||
<YO>20</YO>
|
||||
</UDim2>
|
||||
<token name="SizeConstraint">0</token>
|
||||
<token name="Style">0</token>
|
||||
<string name="Text">Change Background Color</string>
|
||||
<Color3 name="TextColor3">4283256141</Color3>
|
||||
<float name="TextTransparency">0</float>
|
||||
<bool name="TextWrap">false</bool>
|
||||
<token name="TextXAlignment">2</token>
|
||||
<token name="TextYAlignment">1</token>
|
||||
<bool name="Visible">true</bool>
|
||||
<int name="ZIndex">1</int>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
<Item class="LocalScript" referent="RBX16">
|
||||
<Properties>
|
||||
<bool name="Disabled">false</bool>
|
||||
<Content name="LinkedSource"><null></null></Content>
|
||||
<string name="Name">LocalScript</string>
|
||||
<ProtectedString name="Source">function onClicked()
|
||||
if (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/blue.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/red.jpg"
|
||||
elseif (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/red.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/green.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/green.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/green.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/green.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/green.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/green.jpg"
|
||||
elseif (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/green.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/orange.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/orange.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/orange.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/orange.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/orange.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/orange.jpg"
|
||||
elseif (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/orange.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/black.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/black.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/black.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/black.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/black.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/black.jpg"
|
||||
elseif (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/black.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/white.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/white.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/white.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/white.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/white.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/white.jpg"
|
||||
elseif (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/white.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/greenscreen.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/greenscreen.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/greenscreen.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/greenscreen.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/greenscreen.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/greenscreen.jpg"
|
||||
elseif (game.Lighting.Sky.SkyboxBk == "rbxasset://Sky/greenscreen.jpg") then
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/blue.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/blue.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/blue.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/blue.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/blue.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/blue.jpg"
|
||||
else
|
||||
game.Lighting.Sky.SkyboxBk = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxDn = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxFt = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxLf = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxRt = "rbxasset://Sky/red.jpg"
|
||||
game.Lighting.Sky.SkyboxUp = "rbxasset://Sky/red.jpg"
|
||||
end
|
||||
end
|
||||
|
||||
script.Parent.MouseButton1Down:connect(onClicked)</ProtectedString>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
|
|
@ -331,7 +437,7 @@ script.Parent.MouseButton1Down:connect(onClicked)</ProtectedString>
|
|||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="SoundService" referent="RBX15">
|
||||
<Item class="SoundService" referent="RBX17">
|
||||
<Properties>
|
||||
<token name="AmbientReverb">0</token>
|
||||
<float name="DistanceFactor">10</float>
|
||||
|
|
@ -341,68 +447,68 @@ script.Parent.MouseButton1Down:connect(onClicked)</ProtectedString>
|
|||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="CollectionService" referent="RBX16">
|
||||
<Item class="CollectionService" referent="RBX18">
|
||||
<Properties>
|
||||
<string name="Name">CollectionService</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="PhysicsService" referent="RBX17">
|
||||
<Item class="PhysicsService" referent="RBX19">
|
||||
<Properties>
|
||||
<string name="Name">PhysicsService</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="BadgeService" referent="RBX18">
|
||||
<Item class="BadgeService" referent="RBX20">
|
||||
<Properties>
|
||||
<string name="Name">BadgeService</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Geometry" referent="RBX19">
|
||||
<Item class="Geometry" referent="RBX21">
|
||||
<Properties>
|
||||
<string name="Name">Geometry</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="RenderHooksService" referent="RBX20">
|
||||
<Item class="RenderHooksService" referent="RBX22">
|
||||
<Properties>
|
||||
<string name="Name">RenderHooksService</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="SocialService" referent="RBX21">
|
||||
<Item class="SocialService" referent="RBX23">
|
||||
<Properties>
|
||||
<string name="Name">SocialService</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Debris" referent="RBX22">
|
||||
<Item class="Debris" referent="RBX24">
|
||||
<Properties>
|
||||
<int name="MaxItems">1000</int>
|
||||
<string name="Name">Debris</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Timer" referent="RBX23">
|
||||
<Item class="Timer" referent="RBX25">
|
||||
<Properties>
|
||||
<string name="Name">Instance</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="ScriptInformationProvider" referent="RBX24">
|
||||
<Item class="ScriptInformationProvider" referent="RBX26">
|
||||
<Properties>
|
||||
<string name="Name">Instance</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Selection" referent="RBX25">
|
||||
<Item class="Selection" referent="RBX27">
|
||||
<Properties>
|
||||
<string name="Name">Selection</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Lighting" referent="RBX26">
|
||||
<Item class="Lighting" referent="RBX28">
|
||||
<Properties>
|
||||
<Color3 name="Ambient">4286874756</Color3>
|
||||
<float name="Brightness">1</float>
|
||||
|
|
@ -414,7 +520,7 @@ script.Parent.MouseButton1Down:connect(onClicked)</ProtectedString>
|
|||
<string name="TimeOfDay">14:00:00</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
<Item class="Sky" referent="RBX27">
|
||||
<Item class="Sky" referent="RBX29">
|
||||
<Properties>
|
||||
<bool name="CelestialBodiesShown">false</bool>
|
||||
<string name="Name">Sky</string>
|
||||
|
|
@ -429,19 +535,19 @@ script.Parent.MouseButton1Down:connect(onClicked)</ProtectedString>
|
|||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="ChangeHistoryService" referent="RBX28">
|
||||
<Item class="ChangeHistoryService" referent="RBX30">
|
||||
<Properties>
|
||||
<string name="Name">ChangeHistoryService</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="MeshContentProvider" referent="RBX29">
|
||||
<Item class="MeshContentProvider" referent="RBX31">
|
||||
<Properties>
|
||||
<string name="Name">Instance</string>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="TextureContentProvider" referent="RBX30">
|
||||
<Item class="TextureContentProvider" referent="RBX32">
|
||||
<Properties>
|
||||
<string name="Name">Instance</string>
|
||||
<bool name="archivable">true</bool>
|
||||
|
|
|
|||
BIN
Mono.Nat.dll
BIN
Mono.Nat.dll
Binary file not shown.
|
|
@ -0,0 +1,8 @@
|
|||
Open.Nat is a Mono.Nat fork
|
||||
|
||||
= Mono.Nat authors
|
||||
Alan McGovern <alan.mcgovern@gmail.com>
|
||||
Ben Motmans <ben.motmans@gmail.com>
|
||||
|
||||
= Open.Nat author
|
||||
Lucas Ontivero <lucasontivero@gmail.com>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
The MIT License
|
||||
|
||||
Copyright (C) 2006 Alan McGovern
|
||||
Copyright (C) 2007 Ben Motmans
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2013 for Windows Desktop
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Open.Nat", "Open.Nat\Open.Nat.csproj", "{F5D74163-145F-47BF-83DC-D0E07249C6CA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documents", "Documents", "{94F0AE28-727F-497A-AC20-EB5B0C5EBA9A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.gitignore = .gitignore
|
||||
AUTHORS = AUTHORS
|
||||
LICENSE = LICENSE
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F5D74163-145F-47BF-83DC-D0E07249C6CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F5D74163-145F-47BF-83DC-D0E07249C6CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F5D74163-145F-47BF-83DC-D0E07249C6CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F5D74163-145F-47BF-83DC-D0E07249C6CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(OpenDevelopProperties) = preSolution
|
||||
version = 0.1
|
||||
StartupItem = Open.Nat\Open.Nat.csproj
|
||||
name = Open.Nat
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("Open.Nat")]
|
||||
[assembly: AssemblyDescription(".NET Library for automatic network address translation")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Open.Nat")]
|
||||
[assembly: AssemblyCopyright("Copyright Alan McGovern, Ben Motmans, Lucas Ontivero © 2006-2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("c8e81e95-9f15-4eb8-8982-3d2c9cd95dee")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||
[assembly: CLSCompliant(false)]
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal interface ISearcher
|
||||
{
|
||||
void Search(CancellationToken cancellationToken);
|
||||
IEnumerable<NatDevice> Receive();
|
||||
NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// Authors:
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal abstract class Searcher
|
||||
{
|
||||
private readonly List<NatDevice> _devices = new List<NatDevice>();
|
||||
protected List<UdpClient> Sockets;
|
||||
public EventHandler<DeviceEventArgs> DeviceFound;
|
||||
internal DateTime NextSearch = DateTime.UtcNow;
|
||||
|
||||
public async Task<IEnumerable<NatDevice>> Search(CancellationToken cancelationToken)
|
||||
{
|
||||
await Task.Factory.StartNew(async _ =>
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogInfo("Searching for: {0}", GetType().Name);
|
||||
while (!cancelationToken.IsCancellationRequested)
|
||||
{
|
||||
Discover(cancelationToken);
|
||||
Receive(cancelationToken);
|
||||
}
|
||||
CloseSockets();
|
||||
}, cancelationToken);
|
||||
return _devices;
|
||||
}
|
||||
|
||||
private void Discover(CancellationToken cancelationToken)
|
||||
{
|
||||
if(DateTime.UtcNow < NextSearch) return;
|
||||
|
||||
foreach (var socket in Sockets)
|
||||
{
|
||||
try
|
||||
{
|
||||
Discover(socket, cancelationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogError("Error searching {0} - Details:", GetType().Name);
|
||||
NatDiscoverer.TraceSource.LogError(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Receive(CancellationToken cancelationToken)
|
||||
{
|
||||
foreach (var client in Sockets.Where(x=>x.Available>0))
|
||||
{
|
||||
if(cancelationToken.IsCancellationRequested) return;
|
||||
|
||||
var localHost = ((IPEndPoint)client.Client.LocalEndPoint).Address;
|
||||
var receivedFrom = new IPEndPoint(IPAddress.None, 0);
|
||||
var buffer = client.Receive(ref receivedFrom);
|
||||
var device = AnalyseReceivedResponse(localHost, buffer, receivedFrom);
|
||||
|
||||
if (device != null) RaiseDeviceFound(device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected abstract void Discover(UdpClient client, CancellationToken cancelationToken);
|
||||
|
||||
public abstract NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint);
|
||||
|
||||
public void CloseSockets()
|
||||
{
|
||||
foreach (var udpClient in Sockets)
|
||||
{
|
||||
udpClient.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void RaiseDeviceFound(NatDevice device)
|
||||
{
|
||||
_devices.Add(device);
|
||||
var handler = DeviceFound;
|
||||
if(handler!=null)
|
||||
handler(this, new DeviceEventArgs(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
/// <summary>
|
||||
/// Protocol to allow/disallow
|
||||
/// </summary>
|
||||
public enum Protocol
|
||||
{
|
||||
/// <summary>
|
||||
/// Transport Control Protocol
|
||||
/// </summary>
|
||||
Tcp,
|
||||
/// <summary>
|
||||
/// Datagram Protocol
|
||||
/// </summary>
|
||||
Udp
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class DeviceEventArgs : System.EventArgs
|
||||
{
|
||||
public DeviceEventArgs(NatDevice device)
|
||||
{
|
||||
Device = device;
|
||||
}
|
||||
|
||||
public NatDevice Device { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class MappingException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ErrorCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ErrorText { get; private set; }
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal MappingException()
|
||||
{
|
||||
}
|
||||
|
||||
internal MappingException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
internal MappingException(int errorCode, string errorText)
|
||||
: base(string.Format("Error {0}: {1}", errorCode, errorText))
|
||||
{
|
||||
ErrorCode = errorCode;
|
||||
ErrorText = errorText;
|
||||
}
|
||||
|
||||
internal MappingException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected MappingException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null) throw new ArgumentNullException("info");
|
||||
|
||||
ErrorCode = info.GetInt32("errorCode");
|
||||
ErrorText = info.GetString("errorText");
|
||||
base.GetObjectData(info, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class NatDeviceNotFoundException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public NatDeviceNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public NatDeviceNotFoundException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public NatDeviceNotFoundException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected NatDeviceNotFoundException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
namespace Open.Nat
|
||||
{
|
||||
sealed class Finalizer
|
||||
{
|
||||
~Finalizer()
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogInfo("Closing ports opened in this session");
|
||||
NatDiscoverer.RenewTimer.Dispose();
|
||||
NatDiscoverer.ReleaseSessionMappings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
enum MappingLifetime
|
||||
{
|
||||
Permanent,
|
||||
Session,
|
||||
Manual,
|
||||
ForcedSession
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a port forwarding entry in the NAT translation table.
|
||||
/// </summary>
|
||||
public class Mapping
|
||||
{
|
||||
private DateTime _expiration;
|
||||
private int _lifetime;
|
||||
internal MappingLifetime LifetimeType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mapping's description. It is the value stored in the NewPortMappingDescription parameter.
|
||||
/// The NewPortMappingDescription parameter is a human readable string that describes the connection.
|
||||
/// It is used in sorme web interfaces of routers so the user can see which program is using what port.
|
||||
/// </summary>
|
||||
public string Description { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the private ip.
|
||||
/// </summary>
|
||||
public IPAddress PrivateIP { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the protocol.
|
||||
/// </summary>
|
||||
public Protocol Protocol { get; internal set; }
|
||||
/// <summary>
|
||||
/// The PrivatePort parameter specifies the port on a client machine to which all traffic
|
||||
/// coming in on <see cref="#PublicPort">PublicPort</see> for the protocol specified by
|
||||
/// <see cref="#Protocol">Protocol</see> should be forwarded to.
|
||||
/// </summary>
|
||||
/// <see cref="Protocol">Protocol enum</see>
|
||||
public int PrivatePort { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the public ip.
|
||||
/// </summary>
|
||||
public IPAddress PublicIP { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the external (visible) port number.
|
||||
/// It is the value stored in the NewExternalPort parameter .
|
||||
/// The NewExternalPort parameter is used to specify the TCP or UDP port on the WAN side of the router which should be forwarded.
|
||||
/// </summary>
|
||||
public int PublicPort { get; internal set; }
|
||||
/// <summary>
|
||||
/// Gets the lifetime. The Lifetime parameter tells the router how long the portmapping should be active.
|
||||
/// Since most programs don't know this in advance, it is often set to 0, which means 'unlimited' or 'permanent'.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All portmappings are release automatically as part of the shutdown process when <see cref="NatDiscoverer">NatUtility</see>.<see cref="NatUtility#releaseonshutdown">ReleaseOnShutdown</see> is true.
|
||||
/// Permanent portmappings will not be released if the process ends anormally.
|
||||
/// Since most programs don't know the lifetime in advance, Open.NAT renew all the portmappings (except the permanents) before they expires. So, developers have to close explicitly those portmappings
|
||||
/// they don't want to remain open for the session.
|
||||
/// </remarks>
|
||||
public int Lifetime
|
||||
{
|
||||
get { return _lifetime; }
|
||||
internal set
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case int.MaxValue:
|
||||
LifetimeType = MappingLifetime.Session;
|
||||
_lifetime = 10 * 60; // ten minutes
|
||||
_expiration = DateTime.UtcNow.AddSeconds(_lifetime);;
|
||||
break;
|
||||
case 0:
|
||||
LifetimeType = MappingLifetime.Permanent;
|
||||
_lifetime = 0;
|
||||
_expiration = DateTime.UtcNow;
|
||||
break;
|
||||
default:
|
||||
LifetimeType = MappingLifetime.Manual;
|
||||
_lifetime = value;
|
||||
_expiration = DateTime.UtcNow.AddSeconds(_lifetime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the expiration. The property value is calculated using <see cref="#Lifetime">Lifetime</see> property.
|
||||
/// </summary>
|
||||
public DateTime Expiration
|
||||
{
|
||||
get { return _expiration; }
|
||||
internal set
|
||||
{
|
||||
_expiration = value;
|
||||
_lifetime = (int)(_expiration - DateTime.UtcNow).TotalSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
internal Mapping(Protocol protocol, IPAddress privateIP, int privatePort, int publicPort)
|
||||
: this(protocol, privateIP, privatePort, publicPort, 0, "Open.Nat")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
/// <param name="protocol">The protocol.</param>
|
||||
/// <param name="privateIP">The private ip.</param>
|
||||
/// <param name="privatePort">The private port.</param>
|
||||
/// <param name="publicPort">The public port.</param>
|
||||
/// <param name="lifetime">The lifetime.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
internal Mapping(Protocol protocol, IPAddress privateIP, int privatePort, int publicPort, int lifetime, string description)
|
||||
{
|
||||
Guard.IsInRange(privatePort, 0, ushort.MaxValue, "privatePort");
|
||||
Guard.IsInRange(publicPort, 0, ushort.MaxValue, "publicPort");
|
||||
Guard.IsInRange(lifetime, 0, int.MaxValue, "lifetime");
|
||||
Guard.IsTrue(protocol == Protocol.Tcp || protocol == Protocol.Udp, "protocol");
|
||||
|
||||
Protocol = protocol;
|
||||
PrivateIP = privateIP;
|
||||
PrivatePort = privatePort;
|
||||
PublicIP = IPAddress.None;
|
||||
PublicPort = publicPort;
|
||||
Lifetime = lifetime;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
/// <param name="protocol">The protocol.</param>
|
||||
/// <param name="privatePort">The private port.</param>
|
||||
/// <param name="publicPort">The public port.</param>
|
||||
/// <remarks>
|
||||
/// This constructor initializes a Permanent mapping. The description by deafult is "Open.NAT"
|
||||
/// </remarks>
|
||||
public Mapping(Protocol protocol, int privatePort, int publicPort)
|
||||
: this(protocol, IPAddress.None, privatePort, publicPort, 0, "Open.NAT")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
/// <param name="protocol">The protocol.</param>
|
||||
/// <param name="privatePort">The private port.</param>
|
||||
/// <param name="publicPort">The public port.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
/// <remarks>
|
||||
/// This constructor initializes a Permanent mapping.
|
||||
/// </remarks>
|
||||
public Mapping(Protocol protocol, int privatePort, int publicPort, string description)
|
||||
: this(protocol, IPAddress.None, privatePort, publicPort, int.MaxValue, description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
/// <param name="protocol">The protocol.</param>
|
||||
/// <param name="privatePort">The private port.</param>
|
||||
/// <param name="publicPort">The public port.</param>
|
||||
/// <param name="lifetime">The lifetime.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
public Mapping(Protocol protocol, int privatePort, int publicPort, int lifetime, string description)
|
||||
: this(protocol, IPAddress.None, privatePort, publicPort, lifetime, description)
|
||||
{
|
||||
}
|
||||
|
||||
internal Mapping(Mapping mapping)
|
||||
{
|
||||
PrivateIP = mapping.PrivateIP;
|
||||
PrivatePort = mapping.PrivatePort;
|
||||
Protocol = mapping.Protocol;
|
||||
PublicIP = mapping.PublicIP;
|
||||
PublicPort = mapping.PublicPort;
|
||||
LifetimeType = mapping.LifetimeType;
|
||||
Description = mapping.Description;
|
||||
_lifetime = mapping._lifetime;
|
||||
_expiration = mapping._expiration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance is expired.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanent mappings never expires.
|
||||
/// </remarks>
|
||||
public bool IsExpired ()
|
||||
{
|
||||
return LifetimeType != MappingLifetime.Permanent
|
||||
&& LifetimeType != MappingLifetime.ForcedSession
|
||||
&& Expiration < DateTime.UtcNow;
|
||||
}
|
||||
|
||||
internal bool ShoundRenew()
|
||||
{
|
||||
return LifetimeType == MappingLifetime.Session && IsExpired();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
var m = obj as Mapping;
|
||||
if (ReferenceEquals(null, m)) return false;
|
||||
return PublicPort == m.PublicPort && PrivatePort == m.PrivatePort;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = PublicPort;
|
||||
hashCode = (hashCode * 397) ^ (PrivateIP != null ? PrivateIP.GetHashCode() : 0);
|
||||
hashCode = (hashCode * 397) ^ PrivatePort;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} {1} --> {2}:{3} ({4})",
|
||||
Protocol == Protocol.Tcp ? "Tcp" : "Udp",
|
||||
PublicPort,
|
||||
PrivateIP,
|
||||
PrivatePort,
|
||||
Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a NAT device and provides access to the operation set that allows
|
||||
/// open (forward) ports, close ports and get the externa (visible) IP address.
|
||||
/// </summary>
|
||||
public abstract class NatDevice
|
||||
{
|
||||
private readonly HashSet<Mapping> _openedMapping = new HashSet<Mapping>();
|
||||
protected DateTime LastSeen { get; private set; }
|
||||
|
||||
internal void Touch()
|
||||
{
|
||||
LastSeen = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the port map asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="mapping">The <see cref="Mapping">Mapping</see> entry.</param>
|
||||
/// <example>
|
||||
/// device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1700, 1600));
|
||||
/// </example>
|
||||
/// <exception cref="MappingException">MappingException</exception>
|
||||
public abstract Task CreatePortMapAsync(Mapping mapping);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a mapped port asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="mapping">The <see cref="Mapping">Mapping</see> entry.</param>
|
||||
/// <example>
|
||||
/// device.DeletePortMapAsync(new Mapping(Protocol.Tcp, 1700, 1600));
|
||||
/// </example>
|
||||
/// <exception cref="MappingException">MappingException-class</exception>
|
||||
public abstract Task DeletePortMapAsync(Mapping mapping);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all mappings asynchronous.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The list of all forwarded ports
|
||||
/// </returns>
|
||||
/// <example>
|
||||
/// var mappings = await device.GetAllMappingsAsync();
|
||||
/// foreach(var mapping in mappings)
|
||||
/// {
|
||||
/// Console.WriteLine(mapping)
|
||||
/// }
|
||||
/// </example>
|
||||
/// <exception cref="MappingException">MappingException</exception>
|
||||
public abstract Task<IEnumerable<Mapping>> GetAllMappingsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the external (visible) IP address asynchronous. This is the NAT device IP address
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The public IP addrees
|
||||
/// </returns>
|
||||
/// <example>
|
||||
/// Console.WriteLine("My public IP is: {0}", await device.GetExternalIPAsync());
|
||||
/// </example>
|
||||
/// <exception cref="MappingException">MappingException</exception>
|
||||
public abstract Task<IPAddress> GetExternalIPAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified mapping asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="protocol">The protocol.</param>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <returns>
|
||||
/// The matching mapping
|
||||
/// </returns>
|
||||
public abstract Task<Mapping> GetSpecificMappingAsync(Protocol protocol, int port);
|
||||
|
||||
protected void RegisterMapping(Mapping mapping)
|
||||
{
|
||||
_openedMapping.Remove(mapping);
|
||||
_openedMapping.Add(mapping);
|
||||
}
|
||||
|
||||
protected void UnregisterMapping(Mapping mapping)
|
||||
{
|
||||
_openedMapping.RemoveWhere(x => x.Equals(mapping));
|
||||
}
|
||||
|
||||
|
||||
internal void ReleaseMapping(IEnumerable<Mapping> mappings)
|
||||
{
|
||||
var maparr = mappings.ToArray();
|
||||
var mapCount = maparr.Length;
|
||||
NatDiscoverer.TraceSource.LogInfo("{0} ports to close", mapCount);
|
||||
for (var i = 0; i < mapCount; i++)
|
||||
{
|
||||
var mapping = _openedMapping.ElementAt(i);
|
||||
|
||||
try
|
||||
{
|
||||
DeletePortMapAsync(mapping);
|
||||
NatDiscoverer.TraceSource.LogInfo(mapping + " port successfully closed");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogError(mapping + " port couldn't be close");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void ReleaseAll()
|
||||
{
|
||||
ReleaseMapping(_openedMapping);
|
||||
}
|
||||
|
||||
internal void ReleaseSessionMappings()
|
||||
{
|
||||
var mappings = from m in _openedMapping
|
||||
where m.LifetimeType == MappingLifetime.Session
|
||||
select m;
|
||||
|
||||
ReleaseMapping(mappings);
|
||||
}
|
||||
|
||||
internal async Task RenewMappings()
|
||||
{
|
||||
var mappings = _openedMapping.Where(x => x.ShoundRenew());
|
||||
foreach (var mapping in mappings.ToArray())
|
||||
{
|
||||
var m = mapping;
|
||||
await RenewMapping(m);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RenewMapping(Mapping mapping)
|
||||
{
|
||||
var renewMapping = new Mapping(mapping);
|
||||
try
|
||||
{
|
||||
renewMapping.Expiration = DateTime.UtcNow.AddSeconds(mapping.Lifetime);
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("Renewing mapping {0}", renewMapping);
|
||||
await CreatePortMapAsync(renewMapping);
|
||||
NatDiscoverer.TraceSource.LogInfo("Next renew scheduled at: {0}",
|
||||
renewMapping.Expiration.ToLocalTime().TimeOfDay);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogWarn("Renew {0} failed", mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class NatDiscoverer
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="http://msdn.microsoft.com/en-us/library/vstudio/system.diagnostics.tracesource">TraceSource</see> instance
|
||||
/// used for debugging and <see cref="https://github.com/lontivero/Open.Nat/wiki/Troubleshooting">Troubleshooting</see>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// NatUtility.TraceSource.Switch.Level = SourceLevels.Verbose;
|
||||
/// NatUtility.TraceSource.Listeners.Add(new ConsoleListener());
|
||||
/// </example>
|
||||
/// <remarks>
|
||||
/// At least one trace listener has to be added to the Listeners collection if a trace is required; if no listener is added
|
||||
/// there will no be tracing to analyse.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// Open.NAT only supports SourceLevels.Verbose, SourceLevels.Error, SourceLevels.Warning and SourceLevels.Information.
|
||||
/// </remarks>
|
||||
public readonly static TraceSource TraceSource = new TraceSource("Open.NAT");
|
||||
|
||||
private static readonly Dictionary<string, NatDevice> Devices = new Dictionary<string, NatDevice>();
|
||||
|
||||
// Finalizer is never used however its destructor, that releases the open ports, is invoked by the
|
||||
// process as part of the shuting down step. So, don't remove it!
|
||||
private static readonly Finalizer Finalizer = new Finalizer();
|
||||
internal static readonly Timer RenewTimer = new Timer(RenewMappings, null, 5000, 2000);
|
||||
|
||||
/// <summary>
|
||||
/// Discovers and returns an UPnp or Pmp NAT device; otherwise a <see cref="NatDeviceNotFoundException">NatDeviceNotFoundException</see>
|
||||
/// exception is thrown after 3 seconds.
|
||||
/// </summary>
|
||||
/// <returns>A NAT device</returns>
|
||||
/// <exception cref="NatDeviceNotFoundException">when no NAT found before 3 seconds.</exception>
|
||||
public async Task<NatDevice> DiscoverDeviceAsync()
|
||||
{
|
||||
var cts = new CancellationTokenSource(3 * 1000);
|
||||
return await DiscoverDeviceAsync(PortMapper.Pmp | PortMapper.Upnp, cts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers and returns a NAT device for the specified type; otherwise a <see cref="NatDeviceNotFoundException">NatDeviceNotFoundException</see>
|
||||
/// exception is thrown when it is cancelled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It allows to specify the NAT type to discover as well as the cancellation token in order.
|
||||
/// </remarks>
|
||||
/// <param name="portMapper">Port mapper protocol; Upnp, Pmp or both</param>
|
||||
/// <param name="cancellationTokenSource">Cancellation token source for cancelling the discovery process</param>
|
||||
/// <returns>A NAT device</returns>
|
||||
/// <exception cref="NatDeviceNotFoundException">when no NAT found before cancellation</exception>
|
||||
public async Task<NatDevice> DiscoverDeviceAsync(PortMapper portMapper, CancellationTokenSource cancellationTokenSource)
|
||||
{
|
||||
Guard.IsTrue(portMapper == PortMapper.Upnp || portMapper == PortMapper.Pmp, "poertMapper");
|
||||
Guard.IsNotNull(cancellationTokenSource, "cancellationTokenSource");
|
||||
|
||||
var devices = await DiscoverAsync(portMapper, true, cancellationTokenSource);
|
||||
var device = devices.FirstOrDefault();
|
||||
if(device==null)
|
||||
{
|
||||
throw new NatDeviceNotFoundException();
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers and returns all NAT devices for the specified type. If no NAT device is found it returns an empty enumerable
|
||||
/// </summary>
|
||||
/// <param name="portMapper">Port mapper protocol; Upnp, Pmp or both</param>
|
||||
/// <param name="cancellationTokenSource">Cancellation token source for cancelling the discovery process</param>
|
||||
/// <returns>All found NAT devices</returns>
|
||||
public async Task<IEnumerable<NatDevice>> DiscoverDevicesAsync(PortMapper portMapper, CancellationTokenSource cancellationTokenSource)
|
||||
{
|
||||
Guard.IsTrue(portMapper == PortMapper.Upnp || portMapper == PortMapper.Pmp, "poertMapper");
|
||||
Guard.IsNotNull(cancellationTokenSource, "cancellationTokenSource");
|
||||
|
||||
var devices = await DiscoverAsync(portMapper, false, cancellationTokenSource);
|
||||
return devices.ToArray();
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<NatDevice>> DiscoverAsync(PortMapper portMapper, bool onlyOne, CancellationTokenSource cts)
|
||||
{
|
||||
TraceSource.LogInfo("Start Discovery");
|
||||
var searcherTasks = new List<Task<IEnumerable<NatDevice>>>();
|
||||
if(portMapper.HasFlag(PortMapper.Upnp))
|
||||
{
|
||||
var upnpSearcher = new UpnpSearcher(new IPAddressesProvider());
|
||||
upnpSearcher.DeviceFound += (sender, args) => { if (onlyOne) cts.Cancel(); };
|
||||
searcherTasks.Add(upnpSearcher.Search(cts.Token));
|
||||
}
|
||||
if(portMapper.HasFlag(PortMapper.Pmp))
|
||||
{
|
||||
var pmpSearcher = new PmpSearcher(new IPAddressesProvider());
|
||||
pmpSearcher.DeviceFound += (sender, args) => { if (onlyOne) cts.Cancel(); };
|
||||
searcherTasks.Add(pmpSearcher.Search(cts.Token));
|
||||
}
|
||||
|
||||
await Task.WhenAll(searcherTasks);
|
||||
TraceSource.LogInfo("Stop Discovery");
|
||||
|
||||
var devices = searcherTasks.SelectMany(x => x.Result);
|
||||
foreach (var device in devices)
|
||||
{
|
||||
var key = device.ToString();
|
||||
NatDevice nat;
|
||||
if(Devices.TryGetValue(key, out nat))
|
||||
{
|
||||
nat.Touch();
|
||||
}
|
||||
else
|
||||
{
|
||||
Devices.Add(key, device);
|
||||
}
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release all ports opened by Open.NAT.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If ReleaseOnShutdown value is true, it release all the mappings created through the library.
|
||||
/// </remarks>
|
||||
public static void ReleaseAll()
|
||||
{
|
||||
foreach (var device in Devices.Values)
|
||||
{
|
||||
device.ReleaseAll();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ReleaseSessionMappings()
|
||||
{
|
||||
foreach (var device in Devices.Values)
|
||||
{
|
||||
device.ReleaseSessionMappings();
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenewMappings(object state)
|
||||
{
|
||||
Task.Factory.StartNew(async ()=>
|
||||
{
|
||||
foreach (var device in Devices.Values)
|
||||
{
|
||||
await device.RenewMappings();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F5D74163-145F-47BF-83DC-D0E07249C6CA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<NoStandardLibraries>false</NoStandardLibraries>
|
||||
<AssemblyName>Open.Nat</AssemblyName>
|
||||
<RootNamespace>Open.Nat</RootNamespace>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>2.0</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Open.Nat</RootNamespace>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<DocumentationFile>bin\Debug\Open.Nat.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Open.Nat</RootNamespace>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>Open.Nat.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Finalizer.cs" />
|
||||
<Compile Include="Utils\Guard.cs" />
|
||||
<Compile Include="NatDevice.cs" />
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Enums\ProtocolType.cs" />
|
||||
<Compile Include="EventArgs\DeviceEventArgs.cs" />
|
||||
<Compile Include="Exceptions\MappingException.cs" />
|
||||
<Compile Include="Discovery\ISearcher.cs" />
|
||||
<Compile Include="Mapping.cs" />
|
||||
<Compile Include="Exceptions\NatDeviceNotFoundException.cs" />
|
||||
<Compile Include="NatDiscoverer.cs" />
|
||||
<Compile Include="Pmp\PmpSearcher.cs" />
|
||||
<Compile Include="Pmp\PmpConstants.cs" />
|
||||
<Compile Include="Pmp\PmpNatDevice.cs" />
|
||||
<Compile Include="PortMapper.cs" />
|
||||
<Compile Include="Discovery\Searcher.cs" />
|
||||
<Compile Include="Upnp\UpnpSearcher.cs" />
|
||||
<Compile Include="Upnp\DiscoveryResponseMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\DiscoverDeviceMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\Requests\CreatePortMappingMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\Requests\DeletePortMappingMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\Requests\GetExternalIPAddressMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\Requests\GetGenericPortMappingEntry.cs" />
|
||||
<Compile Include="Upnp\Messages\Requests\GetSpecificPortMappingEntryMessage.cs" />
|
||||
<Compile Include="Upnp\ResponseMessageBase.cs" />
|
||||
<Compile Include="Upnp\Messages\Responses\GetExternalIPAddressResponseMessage.cs" />
|
||||
<Compile Include="Upnp\Messages\Responses\GetGenericPortMappingEntryResponseMessage.cs" />
|
||||
<Compile Include="Upnp\RequestMessageBase.cs" />
|
||||
<Compile Include="Upnp\SoapClient.cs" />
|
||||
<Compile Include="Upnp\UpnpConstants.cs" />
|
||||
<Compile Include="Upnp\UpnpNatDeviceInfo.cs" />
|
||||
<Compile Include="Upnp\UpnpNatDevice.cs" />
|
||||
<Compile Include="Utils\Extensions.cs" />
|
||||
<Compile Include="Utils\IIPAddressesProvider.cs" />
|
||||
<Compile Include="Utils\IPAddressesProvider.cs" />
|
||||
<Compile Include="Utils\WellKnownConstants.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Open.Nat.snk" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio AllowExistingFolder="true" />
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Open.NAT</id>
|
||||
<version>$version$</version>
|
||||
<title>Open.NAT</title>
|
||||
<authors>Alan McGovern, Ben Motmans, Lucas Ontivero</authors>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>https://github.com/lontivero/Open.NAT</projectUrl>
|
||||
<iconUrl>http://github.com/lontivero/Open.Nat/raw/gh-pages/images/logos/64.jpg</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>
|
||||
Open.NAT is a lightweight and easy-to-use class library to allow port forwarding in NAT devices (Network Address Translator) that support Universal Plug and Play (UPNP) and/or Port Mapping Protocol (PMP).
|
||||
</description>
|
||||
<summary>Library to allow port forwarding in NAT devices that support UPNP and/or PMP.</summary>
|
||||
<language>en-US</language>
|
||||
<copyright>Please see LICENSE for more details.</copyright>
|
||||
<tags>NAT TRANSVERSAL UPNP PMP PORT FORWARD</tags>
|
||||
<releaseNotes>
|
||||
**Version 2.0.8**
|
||||
Fixes several defects. #10, #11, #12, #13 and #14
|
||||
|
||||
**2.0.0**
|
||||
Thus version breaks backward compatibility with v1.
|
||||
Changes the event-based discovery process' nature to an asynchronous one.
|
||||
|
||||
**1.1.0**
|
||||
Fix for SSDP Location header.
|
||||
After this version Open.NAT breaks backward compatibility.
|
||||
|
||||
**1.0.19**
|
||||
Minor changes previous to v2.
|
||||
|
||||
**1.0.18**
|
||||
Discovery timeout raises an event.
|
||||
Permanent mappings are created when NAT only supports that kind of mappings.
|
||||
Protocol to use in discovery process can be specified.
|
||||
Automatic renew port mappings before expiration.
|
||||
Add operations timeout after 4 seconds.
|
||||
Add parameters validation in Mapping class.
|
||||
Fix UnhandledException event was never raised.
|
||||
|
||||
**1.0.17**
|
||||
Discovery timeout added.
|
||||
Auto release ports opened in the session.
|
||||
Fix NextSearch to use UtcNow (also performance)
|
||||
Fix LocalIP property after add a port.
|
||||
Tracing improvements
|
||||
</releaseNotes>
|
||||
</metadata>
|
||||
</package>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// Authors:
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal static class PmpConstants
|
||||
{
|
||||
public const byte Version = 0;
|
||||
|
||||
public const byte OperationExternalAddressRequest = 0;
|
||||
public const byte OperationCodeUdp = 1;
|
||||
public const byte OperationCodeTcp = 2;
|
||||
public const byte ServerNoop = 128;
|
||||
|
||||
public const int ClientPort = 5350;
|
||||
public const int ServerPort = 5351;
|
||||
|
||||
public const int RetryDelay = 250;
|
||||
public const int RetryAttempts = 9;
|
||||
|
||||
public const int RecommendedLeaseTime = 60*60;
|
||||
public const int DefaultLeaseTime = RecommendedLeaseTime;
|
||||
|
||||
public const short ResultCodeSuccess = 0; // Success
|
||||
public const short ResultCodeUnsupportedVersion = 1; // Unsupported Version
|
||||
|
||||
public const short ResultCodeNotAuthorized = 2;
|
||||
// Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)
|
||||
|
||||
public const short ResultCodeNetworkFailure = 3;
|
||||
// Network Failure (e.g. NAT box itself has not obtained a DHCP lease)
|
||||
|
||||
public const short ResultCodeOutOfResources = 4;
|
||||
// Out of resources (NAT box cannot create any more mappings at this time)
|
||||
|
||||
public const short ResultCodeUnsupportedOperationCode = 5; // Unsupported opcode
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
//
|
||||
// Authors:
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal sealed class PmpNatDevice : NatDevice
|
||||
{
|
||||
private readonly IPAddress _publicAddress;
|
||||
|
||||
internal PmpNatDevice(IPAddress localAddress, IPAddress publicAddress)
|
||||
{
|
||||
LocalAddress = localAddress;
|
||||
_publicAddress = publicAddress;
|
||||
}
|
||||
|
||||
internal IPAddress LocalAddress { get; private set; }
|
||||
|
||||
public override async Task CreatePortMapAsync(Mapping mapping)
|
||||
{
|
||||
await InternalCreatePortMapAsync(mapping, true)
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
RegisterMapping(mapping);
|
||||
}
|
||||
|
||||
public override async Task DeletePortMapAsync(Mapping mapping)
|
||||
{
|
||||
await InternalCreatePortMapAsync(mapping, false)
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
UnregisterMapping(mapping);
|
||||
}
|
||||
|
||||
public override Task<IEnumerable<Mapping>> GetAllMappingsAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override Task<IPAddress> GetExternalIPAsync()
|
||||
{
|
||||
return Task.Run(() => _publicAddress)
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
}
|
||||
|
||||
public override Task<Mapping> GetSpecificMappingAsync(Protocol protocol, int port)
|
||||
{
|
||||
throw new NotSupportedException("NAT-PMP does not specify a way to get a specific port map");
|
||||
}
|
||||
|
||||
|
||||
private async Task<Mapping> InternalCreatePortMapAsync(Mapping mapping, bool create)
|
||||
{
|
||||
var package = new List<byte>();
|
||||
|
||||
package.Add(PmpConstants.Version);
|
||||
package.Add(mapping.Protocol == Protocol.Tcp ? PmpConstants.OperationCodeTcp : PmpConstants.OperationCodeUdp);
|
||||
package.Add(0); //reserved
|
||||
package.Add(0); //reserved
|
||||
package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) mapping.PrivatePort)));
|
||||
package.AddRange(
|
||||
BitConverter.GetBytes(create ? IPAddress.HostToNetworkOrder((short) mapping.PublicPort) : (short) 0));
|
||||
package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(mapping.Lifetime)));
|
||||
|
||||
try
|
||||
{
|
||||
byte[] buffer = package.ToArray();
|
||||
int attempt = 0;
|
||||
int delay = PmpConstants.RetryDelay;
|
||||
|
||||
using (var udpClient = new UdpClient())
|
||||
{
|
||||
CreatePortMapListen(udpClient, mapping);
|
||||
|
||||
while (attempt < PmpConstants.RetryAttempts)
|
||||
{
|
||||
await
|
||||
udpClient.SendAsync(buffer, buffer.Length,
|
||||
new IPEndPoint(LocalAddress, PmpConstants.ServerPort));
|
||||
|
||||
attempt++;
|
||||
delay *= 2;
|
||||
Thread.Sleep(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string type = create ? "create" : "delete";
|
||||
string message = String.Format("Failed to {0} portmap (protocol={1}, private port={2})",
|
||||
type,
|
||||
mapping.Protocol,
|
||||
mapping.PrivatePort);
|
||||
NatDiscoverer.TraceSource.LogError(message);
|
||||
var pmpException = e as MappingException;
|
||||
throw new MappingException(message, pmpException);
|
||||
}
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private void CreatePortMapListen(UdpClient udpClient, Mapping mapping)
|
||||
{
|
||||
var endPoint = new IPEndPoint(LocalAddress, PmpConstants.ServerPort);
|
||||
|
||||
while (true)
|
||||
{
|
||||
byte[] data = udpClient.Receive(ref endPoint);
|
||||
|
||||
if (data.Length < 16)
|
||||
continue;
|
||||
|
||||
if (data[0] != PmpConstants.Version)
|
||||
continue;
|
||||
|
||||
var opCode = (byte) (data[1] & 127);
|
||||
|
||||
var protocol = Protocol.Tcp;
|
||||
if (opCode == PmpConstants.OperationCodeUdp)
|
||||
protocol = Protocol.Udp;
|
||||
|
||||
short resultCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 2));
|
||||
int epoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 4));
|
||||
|
||||
short privatePort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 8));
|
||||
short publicPort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 10));
|
||||
|
||||
var lifetime = (uint) IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 12));
|
||||
|
||||
if (privatePort < 0 || publicPort < 0 || resultCode != PmpConstants.ResultCodeSuccess)
|
||||
{
|
||||
var errors = new[]
|
||||
{
|
||||
"Success",
|
||||
"Unsupported Version",
|
||||
"Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)"
|
||||
,
|
||||
"Network Failure (e.g. NAT box itself has not obtained a DHCP lease)",
|
||||
"Out of resources (NAT box cannot create any more mappings at this time)",
|
||||
"Unsupported opcode"
|
||||
};
|
||||
throw new MappingException(resultCode, errors[resultCode]);
|
||||
}
|
||||
|
||||
if (lifetime == 0) return; //mapping was deleted
|
||||
|
||||
//mapping was created
|
||||
//TODO: verify that the private port+protocol are a match
|
||||
mapping.PublicPort = publicPort;
|
||||
mapping.Protocol = protocol;
|
||||
mapping.Expiration = DateTime.Now.AddSeconds(lifetime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("Local Address: {0}\nPublic IP: {1}\nLast Seen: {2}",
|
||||
LocalAddress, _publicAddress, LastSeen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
//
|
||||
// Authors:
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class PmpSearcher : Searcher
|
||||
{
|
||||
private readonly IIPAddressesProvider _ipprovider;
|
||||
private Dictionary<UdpClient, IEnumerable<IPEndPoint>> _gatewayLists;
|
||||
private int _timeout;
|
||||
|
||||
internal PmpSearcher(IIPAddressesProvider ipprovider)
|
||||
{
|
||||
_ipprovider = ipprovider;
|
||||
_timeout = 250;
|
||||
CreateSocketsAndAddGateways();
|
||||
}
|
||||
|
||||
private void CreateSocketsAndAddGateways()
|
||||
{
|
||||
Sockets = new List<UdpClient>();
|
||||
_gatewayLists = new Dictionary<UdpClient, IEnumerable<IPEndPoint>>();
|
||||
|
||||
try
|
||||
{
|
||||
List<IPEndPoint> gatewayList = _ipprovider.GatewayAddresses()
|
||||
.Select(ip => new IPEndPoint(ip, PmpConstants.ServerPort))
|
||||
.ToList();
|
||||
|
||||
if (!gatewayList.Any())
|
||||
{
|
||||
gatewayList.AddRange(
|
||||
_ipprovider.DnsAddresses()
|
||||
.Select(ip => new IPEndPoint(ip, PmpConstants.ServerPort)));
|
||||
}
|
||||
|
||||
if (!gatewayList.Any()) return;
|
||||
|
||||
foreach (IPAddress address in _ipprovider.UnicastAddresses())
|
||||
{
|
||||
UdpClient client;
|
||||
|
||||
try
|
||||
{
|
||||
client = new UdpClient(new IPEndPoint(address, 0));
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
continue; // Move on to the next address.
|
||||
}
|
||||
|
||||
_gatewayLists.Add(client, gatewayList);
|
||||
Sockets.Add(client);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogError("There was a problem finding gateways: " + e);
|
||||
// NAT-PMP does not use multicast, so there isn't really a good fallback.
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Discover(UdpClient client, CancellationToken cancelationToken)
|
||||
{
|
||||
// Sort out the time for the next search first. The spec says the
|
||||
// timeout should double after each attempt. Once it reaches 64 seconds
|
||||
// (and that attempt fails), assume no devices available
|
||||
NextSearch = DateTime.UtcNow.AddMilliseconds(_timeout);
|
||||
_timeout *= 2;
|
||||
|
||||
if (_timeout >= 3000)
|
||||
{
|
||||
_timeout = 250;
|
||||
NextSearch = DateTime.UtcNow.AddSeconds(10);
|
||||
return;
|
||||
}
|
||||
|
||||
// The nat-pmp search message. Must be sent to GatewayIP:53531
|
||||
var buffer = new[] {PmpConstants.Version, PmpConstants.OperationExternalAddressRequest};
|
||||
foreach (IPEndPoint gatewayEndpoint in _gatewayLists[client])
|
||||
{
|
||||
if (cancelationToken.IsCancellationRequested) return;
|
||||
|
||||
client.Send(buffer, buffer.Length, gatewayEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSearchAddress(IPAddress address)
|
||||
{
|
||||
return _gatewayLists.Values.SelectMany(x => x)
|
||||
.Any(x => x.Address.Equals(address));
|
||||
}
|
||||
|
||||
public override NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
{
|
||||
if (!IsSearchAddress(endpoint.Address)
|
||||
|| response.Length != 12
|
||||
|| response[0] != PmpConstants.Version
|
||||
|| response[1] != PmpConstants.ServerNoop)
|
||||
return null;
|
||||
|
||||
int errorcode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(response, 2));
|
||||
if (errorcode != 0)
|
||||
NatDiscoverer.TraceSource.LogError("Non zero error: {0}", errorcode);
|
||||
|
||||
var publicIp = new IPAddress(new[] {response[8], response[9], response[10], response[11]});
|
||||
//NextSearch = DateTime.Now.AddMinutes(5);
|
||||
|
||||
_timeout = 250;
|
||||
return new PmpNatDevice(endpoint.Address, publicIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
/// <summary>
|
||||
/// Protocol that should be used for searching a NAT device.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum PortMapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Use only Port Mapping Protocol
|
||||
/// </summary>
|
||||
Pmp = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Use only Universal Plug and Play
|
||||
/// </summary>
|
||||
Upnp = 2
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
class DiscoveryResponseMessage
|
||||
{
|
||||
private readonly IDictionary<string, string> _headers;
|
||||
|
||||
public DiscoveryResponseMessage(string message)
|
||||
{
|
||||
var lines = message.Split(new[]{"\r\n"}, StringSplitOptions.RemoveEmptyEntries);
|
||||
var headers = from h in lines.Skip(1)
|
||||
let c = h.Split(':')
|
||||
let key = c[0]
|
||||
let value = c.Length > 1
|
||||
? string.Join(":", c.Skip(1))
|
||||
: string.Empty
|
||||
select new {Key = key, Value = value.Trim()};
|
||||
_headers = headers.ToDictionary(x => x.Key.ToUpperInvariant(), x => x.Value);
|
||||
}
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get { return _headers[key.ToUpperInvariant()]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal static class DiscoverDeviceMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// The message sent to discover all uPnP devices on the network
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string Encode(string serviceType)
|
||||
{
|
||||
const string s = "M-SEARCH * HTTP/1.1\r\n"
|
||||
+ "HOST: 239.255.255.250:1900\r\n"
|
||||
+ "MAN: \"ssdp:discover\"\r\n"
|
||||
+ "MX: 3\r\n"
|
||||
// + "ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n\r\n";
|
||||
+ "ST: urn:schemas-upnp-org:service:{0}\r\n\r\n";
|
||||
//+ "ST:upnp:rootdevice\r\n\r\n";
|
||||
|
||||
string ss = string.Format(CultureInfo.InvariantCulture, s, serviceType);
|
||||
return ss;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class CreatePortMappingRequestMessage : RequestMessageBase
|
||||
{
|
||||
private readonly Mapping _mapping;
|
||||
|
||||
public CreatePortMappingRequestMessage(Mapping mapping)
|
||||
{
|
||||
_mapping = mapping;
|
||||
}
|
||||
|
||||
public override IDictionary<string, object> ToXml()
|
||||
{
|
||||
string remoteHost = _mapping.PublicIP.Equals(IPAddress.None)
|
||||
? string.Empty
|
||||
: _mapping.PublicIP.ToString();
|
||||
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{"NewRemoteHost", remoteHost},
|
||||
{"NewExternalPort", _mapping.PublicPort},
|
||||
{"NewProtocol", _mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP"},
|
||||
{"NewInternalPort", _mapping.PrivatePort},
|
||||
{"NewInternalClient", _mapping.PrivateIP},
|
||||
{"NewEnabled", 1},
|
||||
{"NewPortMappingDescription", _mapping.Description},
|
||||
{"NewLeaseDuration", _mapping.Lifetime}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class DeletePortMappingRequestMessage : RequestMessageBase
|
||||
{
|
||||
private readonly Mapping _mapping;
|
||||
|
||||
public DeletePortMappingRequestMessage(Mapping mapping)
|
||||
{
|
||||
_mapping = mapping;
|
||||
}
|
||||
|
||||
public override IDictionary<string, object> ToXml()
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{"NewRemoteHost", string.Empty},
|
||||
{"NewExternalPort", _mapping.PublicPort},
|
||||
{"NewProtocol", _mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP"}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class GetExternalIPAddressRequestMessage : RequestMessageBase
|
||||
{
|
||||
public override IDictionary<string, object> ToXml()
|
||||
{
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class GetGenericPortMappingEntry : RequestMessageBase
|
||||
{
|
||||
private readonly int _index;
|
||||
|
||||
public GetGenericPortMappingEntry(int index)
|
||||
{
|
||||
_index = index;
|
||||
}
|
||||
|
||||
public override IDictionary<string, object> ToXml()
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{"NewPortMappingIndex", _index}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class GetSpecificPortMappingEntryRequestMessage : RequestMessageBase
|
||||
{
|
||||
private readonly int _externalPort;
|
||||
private readonly Protocol _protocol;
|
||||
|
||||
public GetSpecificPortMappingEntryRequestMessage(Protocol protocol, int externalPort)
|
||||
{
|
||||
_protocol = protocol;
|
||||
_externalPort = externalPort;
|
||||
}
|
||||
|
||||
public override IDictionary<string, object> ToXml()
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{"NewRemoteHost", string.Empty},
|
||||
{"NewExternalPort", _externalPort},
|
||||
{"NewProtocol", _protocol == Protocol.Tcp ? "TCP" : "UDP"}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class AddPortMappingResponseMessage : ResponseMessageBase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class DeletePortMappingResponseMessage : ResponseMessageBase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class GetExternalIPAddressResponseMessage : ResponseMessageBase
|
||||
{
|
||||
public GetExternalIPAddressResponseMessage(XmlDocument response, string serviceType)
|
||||
: base(response, serviceType, "GetExternalIPAddressResponseMessage")
|
||||
{
|
||||
string ip = GetNode().GetXmlElementText("NewExternalIPAddress");
|
||||
ExternalIPAddress = IPAddress.Parse(ip);
|
||||
}
|
||||
|
||||
public IPAddress ExternalIPAddress { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class GetPortMappingEntryResponseMessage : ResponseMessageBase
|
||||
{
|
||||
internal GetPortMappingEntryResponseMessage(XmlDocument response, string serviceType, bool genericMapping)
|
||||
: base(response, serviceType, genericMapping ? "GetGenericPortMappingEntryResponseMessage" : "GetSpecificPortMappingEntryResponseMessage")
|
||||
{
|
||||
XmlNode data = GetNode();
|
||||
|
||||
RemoteHost = (genericMapping) ? data.GetXmlElementText("NewRemoteHost") : string.Empty;
|
||||
ExternalPort = (genericMapping) ? Convert.ToInt32(data.GetXmlElementText("NewExternalPort")) : ushort.MaxValue;
|
||||
if (genericMapping)
|
||||
Protocol = data.GetXmlElementText("NewProtocol").Equals("TCP", StringComparison.InvariantCultureIgnoreCase)
|
||||
? Protocol.Tcp
|
||||
: Protocol.Udp;
|
||||
else
|
||||
Protocol = Protocol.Udp;
|
||||
|
||||
InternalPort = Convert.ToInt32(data.GetXmlElementText("NewInternalPort"));
|
||||
InternalClient = data.GetXmlElementText("NewInternalClient");
|
||||
Enabled = data.GetXmlElementText("NewEnabled") == "1";
|
||||
PortMappingDescription = data.GetXmlElementText("NewPortMappingDescription");
|
||||
LeaseDuration = Convert.ToInt32(data.GetXmlElementText("NewLeaseDuration"));
|
||||
}
|
||||
|
||||
public string RemoteHost { get; private set; }
|
||||
public int ExternalPort { get; private set; }
|
||||
public Protocol Protocol { get; private set; }
|
||||
public int InternalPort { get; private set; }
|
||||
public string InternalClient { get; private set; }
|
||||
public bool Enabled { get; private set; }
|
||||
public string PortMappingDescription { get; private set; }
|
||||
public int LeaseDuration { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal abstract class RequestMessageBase
|
||||
{
|
||||
public abstract IDictionary<string, object> ToXml();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucas.ontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal abstract class ResponseMessageBase
|
||||
{
|
||||
private readonly XmlDocument _document;
|
||||
protected string ServiceType;
|
||||
private readonly string _typeName;
|
||||
|
||||
protected ResponseMessageBase(XmlDocument response, string serviceType, string typeName)
|
||||
{
|
||||
_document = response;
|
||||
ServiceType = serviceType;
|
||||
_typeName = typeName;
|
||||
}
|
||||
|
||||
protected XmlNode GetNode()
|
||||
{
|
||||
var nsm = new XmlNamespaceManager(_document.NameTable);
|
||||
nsm.AddNamespace("responseNs", ServiceType);
|
||||
|
||||
string typeName = _typeName;
|
||||
string messageName = typeName.Substring(0, typeName.Length - "Message".Length);
|
||||
XmlNode node = _document.SelectSingleNode("//responseNs:" + messageName, nsm);
|
||||
if (node == null) throw new InvalidOperationException("The response is invalid: " + messageName);
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class SoapClient
|
||||
{
|
||||
private readonly string _serviceType;
|
||||
private readonly Uri _url;
|
||||
|
||||
public SoapClient(Uri url, string serviceType)
|
||||
{
|
||||
_url = url;
|
||||
_serviceType = serviceType;
|
||||
}
|
||||
|
||||
public async Task<XmlDocument> InvokeAsync(string operationName, IDictionary<string, object> args)
|
||||
{
|
||||
NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "SOAPACTION: **{0}** url:{1}", operationName,
|
||||
_url);
|
||||
byte[] messageBody = BuildMessageBody(operationName, args);
|
||||
HttpWebRequest request = BuildHttpWebRequest(operationName, messageBody);
|
||||
|
||||
if (messageBody.Length > 0)
|
||||
{
|
||||
using (var stream = await request.GetRequestStreamAsync())
|
||||
{
|
||||
await stream.WriteAsync(messageBody, 0, messageBody.Length);
|
||||
}
|
||||
}
|
||||
|
||||
using(var response = await GetWebResponse(request))
|
||||
{
|
||||
var stream = response.GetResponseStream();
|
||||
var contentLength = response.ContentLength;
|
||||
|
||||
var reader = new StreamReader(stream, Encoding.UTF8);
|
||||
|
||||
var responseBody = contentLength != -1
|
||||
? reader.ReadAsMany((int) contentLength)
|
||||
: reader.ReadToEnd();
|
||||
|
||||
var responseXml = GetXmlDocument(responseBody);
|
||||
NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Response: \n{0}", responseXml.ToPrintableXml());
|
||||
|
||||
response.Close();
|
||||
return responseXml;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<WebResponse> GetWebResponse(WebRequest request)
|
||||
{
|
||||
WebResponse response;
|
||||
try
|
||||
{
|
||||
response = await request.GetResponseAsync();
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "WebException status: {0}", ex.Status);
|
||||
|
||||
// Even if the request "failed" we need to continue reading the response from the router
|
||||
response = ex.Response as HttpWebResponse;
|
||||
|
||||
if (response == null)
|
||||
throw;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private HttpWebRequest BuildHttpWebRequest(string operationName, byte[] messageBody)
|
||||
{
|
||||
var request = WebRequest.CreateHttp(_url);
|
||||
request.KeepAlive = false;
|
||||
request.Method = "POST";
|
||||
request.ContentType = "text/xml; charset=\"utf-8\"";
|
||||
request.Headers.Add("SOAPACTION", "\"" + _serviceType + "#" + operationName + "\"");
|
||||
request.ContentLength = messageBody.Length;
|
||||
return request;
|
||||
}
|
||||
|
||||
private byte[] BuildMessageBody(string operationName, IEnumerable<KeyValuePair<string, object>> args)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("<s:Envelope ");
|
||||
sb.AppendLine(" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
|
||||
sb.AppendLine(" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
|
||||
sb.AppendLine(" <s:Body>");
|
||||
sb.AppendLine(" <u:" + operationName + " xmlns:u=\"" + _serviceType + "\">");
|
||||
foreach (var a in args)
|
||||
{
|
||||
sb.AppendLine(" <" + a.Key + ">" + Convert.ToString(a.Value, CultureInfo.InvariantCulture) +
|
||||
"</" + a.Key + ">");
|
||||
}
|
||||
sb.AppendLine(" </u:" + operationName + ">");
|
||||
sb.AppendLine(" </s:Body>");
|
||||
sb.Append("</s:Envelope>\r\n\r\n");
|
||||
string requestBody = sb.ToString();
|
||||
|
||||
NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, requestBody);
|
||||
byte[] messageBody = Encoding.UTF8.GetBytes(requestBody);
|
||||
return messageBody;
|
||||
}
|
||||
|
||||
private XmlDocument GetXmlDocument(string response)
|
||||
{
|
||||
XmlNode node;
|
||||
var doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
|
||||
var nsm = new XmlNamespaceManager(doc.NameTable);
|
||||
|
||||
// Error messages should be found under this namespace
|
||||
nsm.AddNamespace("errorNs", "urn:schemas-upnp-org:control-1-0");
|
||||
|
||||
// Check to see if we have a fault code message.
|
||||
if ((node = doc.SelectSingleNode("//errorNs:UPnPError", nsm)) != null)
|
||||
{
|
||||
int code = Convert.ToInt32(node.GetXmlElementText("errorCode"), CultureInfo.InvariantCulture);
|
||||
string errorMessage = node.GetXmlElementText("errorDescription");
|
||||
NatDiscoverer.TraceSource.LogWarn("Server failed with error: {0} - {1}", code, errorMessage);
|
||||
throw new MappingException(code, errorMessage);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal static class UpnpConstants
|
||||
{
|
||||
public const int InvalidArguments = 402;
|
||||
public const int ActionFailed = 501;
|
||||
public const int Unathorized = 606;
|
||||
public const int SpecifiedArrayIndexInvalid = 713;
public const int NoSuchEntryInArray = 714;
|
||||
public const int WildCardNotPermittedInSourceIp = 715;
|
||||
public const int WildCardNotPermittedInExternalPort = 716;
|
||||
public const int ConflictInMappingEntry = 718;
|
||||
public const int SamePortValuesRequired = 724;
|
||||
public const int OnlyPermanentLeasesSupported = 725;
|
||||
public const int RemoteHostOnlySupportsWildcard = 726;
|
||||
public const int ExternalPortOnlySupportsWildcard = 727;
|
||||
public const int NoPortMapsAvailable = 728;
|
||||
public const int ConflictWithOtherMechanisms = 729;
|
||||
public const int WildCardNotPermittedInIntPort = 732;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
//
|
||||
// Authors:
|
||||
// Alan McGovern alan.mcgovern@gmail.com
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2006 Alan McGovern
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal sealed class UpnpNatDevice : NatDevice
|
||||
{
|
||||
internal readonly UpnpNatDeviceInfo DeviceInfo;
|
||||
private readonly SoapClient _soapClient;
|
||||
|
||||
internal UpnpNatDevice (UpnpNatDeviceInfo deviceInfo)
|
||||
{
|
||||
Touch();
|
||||
DeviceInfo = deviceInfo;
|
||||
_soapClient = new SoapClient(DeviceInfo.ServiceControlUri, DeviceInfo.ServiceType);
|
||||
}
|
||||
|
||||
public override async Task<IPAddress> GetExternalIPAsync()
|
||||
{
|
||||
var message = new GetExternalIPAddressRequestMessage();
|
||||
var responseData = await _soapClient
|
||||
.InvokeAsync("GetExternalIPAddress", message.ToXml())
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
|
||||
var response = new GetExternalIPAddressResponseMessage(responseData, DeviceInfo.ServiceType);
|
||||
return response.ExternalIPAddress;
|
||||
}
|
||||
|
||||
public override async Task CreatePortMapAsync(Mapping mapping)
|
||||
{
|
||||
Guard.IsNotNull(mapping, "mapping");
|
||||
|
||||
mapping.PrivateIP = DeviceInfo.LocalAddress;
|
||||
try
|
||||
{
|
||||
var message = new CreatePortMappingRequestMessage(mapping);
|
||||
await _soapClient
|
||||
.InvokeAsync("AddPortMapping", message.ToXml())
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
RegisterMapping(mapping);
|
||||
}
|
||||
catch(MappingException me)
|
||||
{
|
||||
switch (me.ErrorCode)
|
||||
{
|
||||
case UpnpConstants.OnlyPermanentLeasesSupported:
|
||||
NatDiscoverer.TraceSource.LogWarn("Only Permanent Leases Supported - There is no warranty it will be closed");
|
||||
mapping.Lifetime = 0;
|
||||
// We create the mapping anyway. It must be released on shutdown.
|
||||
mapping.LifetimeType = MappingLifetime.ForcedSession;
|
||||
CreatePortMapAsync(mapping);
|
||||
break;
|
||||
case UpnpConstants.SamePortValuesRequired:
|
||||
NatDiscoverer.TraceSource.LogWarn("Same Port Values Required - Using internal port {0}", mapping.PrivatePort);
|
||||
mapping.PublicPort = mapping.PrivatePort;
|
||||
CreatePortMapAsync(mapping);
|
||||
break;
|
||||
case UpnpConstants.RemoteHostOnlySupportsWildcard:
|
||||
NatDiscoverer.TraceSource.LogWarn("Remote Host Only Supports Wildcard");
|
||||
mapping.PublicIP = IPAddress.None;
|
||||
CreatePortMapAsync(mapping);
|
||||
break;
|
||||
case UpnpConstants.ExternalPortOnlySupportsWildcard:
|
||||
NatDiscoverer.TraceSource.LogWarn("External Port Only Supports Wildcard");
|
||||
throw;
|
||||
case UpnpConstants.ConflictInMappingEntry:
|
||||
NatDiscoverer.TraceSource.LogWarn("Conflict with an already existing mapping");
|
||||
throw;
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task DeletePortMapAsync(Mapping mapping)
|
||||
{
|
||||
Guard.IsNotNull(mapping, "mapping");
|
||||
|
||||
try
|
||||
{
|
||||
var message = new DeletePortMappingRequestMessage(mapping);
|
||||
await _soapClient
|
||||
.InvokeAsync("DeletePortMapping", message.ToXml())
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
UnregisterMapping(mapping);
|
||||
}
|
||||
catch (MappingException e)
|
||||
{
|
||||
if(e.ErrorCode != UpnpConstants.NoSuchEntryInArray) throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IEnumerable<Mapping>> GetAllMappingsAsync()
|
||||
{
|
||||
var index = 0;
|
||||
var mappings = new List<Mapping>();
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = new GetGenericPortMappingEntry(index);
|
||||
|
||||
var responseData = await _soapClient
|
||||
.InvokeAsync("GetGenericPortMappingEntry", message.ToXml())
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
|
||||
var responseMessage = new GetPortMappingEntryResponseMessage(responseData, DeviceInfo.ServiceType, true);
|
||||
|
||||
var mapping = new Mapping(responseMessage.Protocol
|
||||
, IPAddress.Parse(responseMessage.InternalClient)
|
||||
, responseMessage.InternalPort
|
||||
, responseMessage.ExternalPort
|
||||
, responseMessage.LeaseDuration
|
||||
, responseMessage.PortMappingDescription);
|
||||
mappings.Add(mapping);
|
||||
index++;
|
||||
}
|
||||
catch (MappingException e)
|
||||
{
|
||||
if (e.ErrorCode == UpnpConstants.SpecifiedArrayIndexInvalid) break; // there are no more mappings
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return mappings.ToArray();
|
||||
}
|
||||
|
||||
public override async Task<Mapping> GetSpecificMappingAsync (Protocol protocol, int port)
|
||||
{
|
||||
Guard.IsTrue(protocol == Protocol.Tcp || protocol == Protocol.Udp, "protocol");
|
||||
Guard.IsInRange(port, 0, ushort.MaxValue, "port");
|
||||
|
||||
try
|
||||
{
|
||||
var message = new GetSpecificPortMappingEntryRequestMessage(protocol, port);
|
||||
var responseData = await _soapClient
|
||||
.InvokeAsync("GetSpecificPortMappingEntry", message.ToXml())
|
||||
.TimeoutAfter(TimeSpan.FromSeconds(4));
|
||||
|
||||
var messageResponse = new GetPortMappingEntryResponseMessage(responseData, DeviceInfo.ServiceType, false);
|
||||
|
||||
return new Mapping(messageResponse.Protocol
|
||||
, IPAddress.Parse(messageResponse.InternalClient)
|
||||
, messageResponse.InternalPort
|
||||
, messageResponse.ExternalPort
|
||||
, messageResponse.LeaseDuration
|
||||
, messageResponse.PortMappingDescription);
|
||||
}
|
||||
catch (MappingException e)
|
||||
{
|
||||
if (e.ErrorCode != UpnpConstants.NoSuchEntryInArray) throw;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString( )
|
||||
{
|
||||
//GetExternalIP is blocking and can throw exceptions, can't use it here.
|
||||
return String.Format(
|
||||
"EndPoint: {0}\nControl Url: {1}\nService Type: {2}\nLast Seen: {3}",
|
||||
DeviceInfo.HostEndPoint, DeviceInfo.ServiceControlUri, DeviceInfo.ServiceType, LastSeen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class UpnpNatDeviceInfo
|
||||
{
|
||||
public UpnpNatDeviceInfo(IPAddress localAddress, Uri locationUri, string serviceControlUrl, string serviceType)
|
||||
{
|
||||
LocalAddress = localAddress;
|
||||
ServiceType = serviceType;
|
||||
HostEndPoint = new IPEndPoint(IPAddress.Parse(locationUri.Host), locationUri.Port);
|
||||
|
||||
if (Uri.IsWellFormedUriString(serviceControlUrl, UriKind.Absolute))
|
||||
{
|
||||
var u = new Uri(serviceControlUrl);
|
||||
IPEndPoint old = HostEndPoint;
|
||||
serviceControlUrl = serviceControlUrl.Substring(u.GetLeftPart(UriPartial.Authority).Length);
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}: Absolute URI detected. Host address is now: {1}", old,
|
||||
HostEndPoint);
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}: New control url: {1}", HostEndPoint, serviceControlUrl);
|
||||
}
|
||||
|
||||
var builder = new UriBuilder("http", locationUri.Host, locationUri.Port, serviceControlUrl);
|
||||
ServiceControlUri = builder.Uri;
|
||||
}
|
||||
|
||||
public IPEndPoint HostEndPoint { get; private set; }
|
||||
public IPAddress LocalAddress { get; private set; }
|
||||
public string ServiceType { get; private set; }
|
||||
public Uri ServiceControlUri { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
//
|
||||
// Authors:
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class UpnpSearcher : Searcher
|
||||
{
|
||||
private readonly IIPAddressesProvider _ipprovider;
|
||||
private readonly IDictionary<Uri, NatDevice> _devices;
|
||||
private readonly Dictionary<IPAddress, DateTime> _lastFetched;
|
||||
private static readonly string[] ServiceTypes = new[]{
|
||||
"WANIPConnection:2",
|
||||
"WANPPPConnection:2",
|
||||
"WANIPConnection:1",
|
||||
"WANPPPConnection:1"
|
||||
};
|
||||
|
||||
internal UpnpSearcher(IIPAddressesProvider ipprovider)
|
||||
{
|
||||
_ipprovider = ipprovider;
|
||||
Sockets = CreateSockets();
|
||||
_devices = new Dictionary<Uri, NatDevice>();
|
||||
_lastFetched = new Dictionary<IPAddress, DateTime>();
|
||||
}
|
||||
|
||||
private List<UdpClient> CreateSockets()
|
||||
{
|
||||
var clients = new List<UdpClient>();
|
||||
try
|
||||
{
|
||||
var ips = _ipprovider.UnicastAddresses();
|
||||
|
||||
foreach (var ipAddress in ips)
|
||||
{
|
||||
try
|
||||
{
|
||||
clients.Add(new UdpClient(new IPEndPoint(ipAddress, 0)));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
continue; // Move on to the next address.
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
clients.Add(new UdpClient(0));
|
||||
}
|
||||
return clients;
|
||||
}
|
||||
|
||||
protected override void Discover(UdpClient client, CancellationToken cancelationToken)
|
||||
{
|
||||
NextSearch = DateTime.UtcNow.AddSeconds(1);
|
||||
var searchEndpoint = new IPEndPoint(
|
||||
WellKnownConstants.IPv4MulticastAddress
|
||||
/*IPAddress.Broadcast*/
|
||||
, 1900);
|
||||
|
||||
foreach (var serviceType in ServiceTypes)
|
||||
{
|
||||
var datax = DiscoverDeviceMessage.Encode(serviceType);
|
||||
var data = Encoding.ASCII.GetBytes(datax);
|
||||
|
||||
// UDP is unreliable, so send 3 requests at a time (per Upnp spec, sec 1.1.2)
|
||||
// Yes, however it works perfectly well with just 1 request.
|
||||
for (var i = 0; i < 2; i++)
|
||||
{
|
||||
if (cancelationToken.IsCancellationRequested) return;
|
||||
client.Send(data, data.Length, searchEndpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
{
|
||||
// Convert it to a string for easy parsing
|
||||
string dataString = null;
|
||||
|
||||
// No matter what, this method should never throw an exception. If something goes wrong
|
||||
// we should still be in a position to handle the next reply correctly.
|
||||
try
|
||||
{
|
||||
dataString = Encoding.UTF8.GetString(response);
|
||||
var message = new DiscoveryResponseMessage(dataString);
|
||||
var serviceType = message["ST"];
|
||||
|
||||
NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "UPnP Response: {0}", dataString);
|
||||
|
||||
if (!IsValidControllerService(serviceType)) return null;
|
||||
NatDiscoverer.TraceSource.LogInfo("UPnP Response: Router advertised a '{0}' service!!!", serviceType);
|
||||
|
||||
var location = message["Location"];
|
||||
var locationUri = new Uri(location);
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("Found device at: {0}", locationUri.ToString());
|
||||
|
||||
if (_devices.ContainsKey(locationUri))
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogInfo("Already found - Ignored");
|
||||
_devices[locationUri].Touch();
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we send 3 requests at a time, ensure we only fetch the services list once
|
||||
// even if three responses are received
|
||||
if (_lastFetched.ContainsKey(endpoint.Address))
|
||||
{
|
||||
var last = _lastFetched[endpoint.Address];
|
||||
if ((DateTime.Now - last) < TimeSpan.FromSeconds(20))
|
||||
return null;
|
||||
}
|
||||
_lastFetched[endpoint.Address] = DateTime.Now;
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}:{1}: Fetching service list", locationUri.Host, locationUri.Port );
|
||||
|
||||
var deviceInfo = BuildUpnpNatDeviceInfo(localAddress, locationUri);
|
||||
|
||||
UpnpNatDevice device;
|
||||
lock (_devices)
|
||||
{
|
||||
device = new UpnpNatDevice(deviceInfo);
|
||||
if (!_devices.ContainsKey(locationUri))
|
||||
{
|
||||
_devices.Add(locationUri, device);
|
||||
}
|
||||
}
|
||||
return device;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogError("Unhandled exception when trying to decode a device's response. ");
|
||||
NatDiscoverer.TraceSource.LogError("Report the issue in https://github.com/lontivero/Open.Nat/issues");
|
||||
NatDiscoverer.TraceSource.LogError("Also copy and paste the following info:");
|
||||
NatDiscoverer.TraceSource.LogError("-- beging ---------------------------------");
|
||||
NatDiscoverer.TraceSource.LogError(ex.Message);
|
||||
NatDiscoverer.TraceSource.LogError("Data string:");
|
||||
NatDiscoverer.TraceSource.LogError(dataString ?? "No data available");
|
||||
NatDiscoverer.TraceSource.LogError("-- end ------------------------------------");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool IsValidControllerService(string serviceType)
|
||||
{
|
||||
var services = from serviceName in ServiceTypes
|
||||
let serviceUrn = string.Format("urn:schemas-upnp-org:service:{0}", serviceName)
|
||||
where serviceType.ContainsIgnoreCase(serviceUrn)
|
||||
select new {ServiceName = serviceName, ServiceUrn = serviceUrn};
|
||||
|
||||
return services.Any();
|
||||
}
|
||||
|
||||
private UpnpNatDeviceInfo BuildUpnpNatDeviceInfo(IPAddress localAddress, Uri location)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogInfo("Found device at: {0}", location.ToString());
|
||||
|
||||
var hostEndPoint = new IPEndPoint(IPAddress.Parse(location.Host), location.Port);
|
||||
|
||||
WebResponse response = null;
|
||||
try
|
||||
{
|
||||
var request = WebRequest.CreateHttp(location);
|
||||
request.Headers.Add("ACCEPT-LANGUAGE", "en");
|
||||
request.Method = "GET";
|
||||
|
||||
response = request.GetResponse();
|
||||
|
||||
var httpresponse = response as HttpWebResponse;
|
||||
|
||||
if (httpresponse != null && httpresponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
var message = string.Format("Couldn't get services list: {0} {1}", httpresponse.StatusCode, httpresponse.StatusDescription);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
var xmldoc = ReadXmlResponse(response);
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}: Parsed services list", hostEndPoint);
|
||||
|
||||
var ns = new XmlNamespaceManager(xmldoc.NameTable);
|
||||
ns.AddNamespace("ns", "urn:schemas-upnp-org:device-1-0");
|
||||
var services = xmldoc.SelectNodes("//ns:service", ns);
|
||||
|
||||
foreach (XmlNode service in services)
|
||||
{
|
||||
var serviceType = service.GetXmlElementText("serviceType");
|
||||
if (!IsValidControllerService(serviceType)) continue;
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}: Found service: {1}", hostEndPoint, serviceType);
|
||||
|
||||
var serviceControlUrl = service.GetXmlElementText("controlURL");
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}: Found upnp service at: {1}", hostEndPoint, serviceControlUrl);
|
||||
|
||||
NatDiscoverer.TraceSource.LogInfo("{0}: Handshake Complete", hostEndPoint);
|
||||
return new UpnpNatDeviceInfo(localAddress, location, serviceControlUrl, serviceType);
|
||||
}
|
||||
|
||||
throw new Exception("No valid control service was found in the service descriptor document");
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
// Just drop the connection, FIXME: Should i retry?
|
||||
NatDiscoverer.TraceSource.LogError("{0}: Device denied the connection attempt: {1}", hostEndPoint, ex);
|
||||
var inner = ex.InnerException as SocketException;
|
||||
if (inner != null)
|
||||
{
|
||||
NatDiscoverer.TraceSource.LogError("{0}: ErrorCode:{1}", hostEndPoint, inner.ErrorCode);
|
||||
NatDiscoverer.TraceSource.LogError("Go to http://msdn.microsoft.com/en-us/library/system.net.sockets.socketerror.aspx");
|
||||
NatDiscoverer.TraceSource.LogError("Usually this happens. Try resetting the device and try again. If you are in a VPN, disconnect and try again.");
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (response != null)
|
||||
response.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static XmlDocument ReadXmlResponse(WebResponse response)
|
||||
{
|
||||
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
|
||||
{
|
||||
var servicesXml = reader.ReadToEnd();
|
||||
var xmldoc = new XmlDocument();
|
||||
xmldoc.LoadXml(servicesXml);
|
||||
return xmldoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal static class StreamExtensions
|
||||
{
|
||||
internal static string ReadAsMany(this StreamReader stream, int bytesToRead)
|
||||
{
|
||||
var buffer = new char[bytesToRead];
|
||||
stream.ReadBlock(buffer, 0, bytesToRead);
|
||||
return new string(buffer);
|
||||
}
|
||||
|
||||
internal static string GetXmlElementText(this XmlNode node, string elementName)
|
||||
{
|
||||
XmlElement element = node[elementName];
|
||||
return element != null ? element.InnerText : string.Empty;
|
||||
}
|
||||
|
||||
internal static bool ContainsIgnoreCase(this string s, string pattern)
|
||||
{
|
||||
return s.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
internal static void LogInfo(this TraceSource source, string format, params object[] args)
|
||||
{
|
||||
source.TraceEvent(TraceEventType.Information, 0, format, args);
|
||||
}
|
||||
|
||||
internal static void LogWarn(this TraceSource source, string format, params object[] args)
|
||||
{
|
||||
source.TraceEvent(TraceEventType.Warning, 0, format, args);
|
||||
}
|
||||
|
||||
internal static void LogError(this TraceSource source, string format, params object[] args)
|
||||
{
|
||||
source.TraceEvent(TraceEventType.Error, 0, format, args);
|
||||
}
|
||||
|
||||
internal static string ToPrintableXml(this XmlDocument document)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
using (var writer = new XmlTextWriter(stream, Encoding.Unicode))
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.Formatting = Formatting.Indented;
|
||||
|
||||
document.WriteContentTo(writer);
|
||||
writer.Flush();
|
||||
stream.Flush();
|
||||
|
||||
// Have to rewind the MemoryStream in order to read
|
||||
// its contents.
|
||||
stream.Position = 0;
|
||||
|
||||
// Read MemoryStream contents into a StreamReader.
|
||||
var reader = new StreamReader(stream);
|
||||
|
||||
// Extract the text from the StreamReader.
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return document.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
|
||||
{
|
||||
#if DEBUG
|
||||
return await task;
|
||||
#endif
|
||||
var timeoutCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
Task completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
|
||||
if (completedTask == task)
|
||||
{
|
||||
timeoutCancellationTokenSource.Cancel();
|
||||
return await task;
|
||||
}
|
||||
throw new TimeoutException(
|
||||
"The operation has timed out. The network is broken, router has gone or is too busy.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class Guard
|
||||
{
|
||||
private Guard()
|
||||
{
|
||||
}
|
||||
|
||||
internal static void IsInRange(int paramValue, int lowerBound, int upperBound, string paramName)
|
||||
{
|
||||
if (paramValue < lowerBound || paramValue > upperBound)
|
||||
throw new ArgumentOutOfRangeException(paramName);
|
||||
}
|
||||
|
||||
internal static void IsTrue(bool exp, string paramName)
|
||||
{
|
||||
if (!exp)
|
||||
throw new ArgumentOutOfRangeException(paramName);
|
||||
}
|
||||
|
||||
internal static void IsNotNull(object obj, string paramName)
|
||||
{
|
||||
if(obj == null) throw new ArgumentNullException(paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal interface IIPAddressesProvider
|
||||
{
|
||||
IEnumerable<IPAddress> DnsAddresses();
|
||||
IEnumerable<IPAddress> GatewayAddresses();
|
||||
IEnumerable<IPAddress> UnicastAddresses();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal class IPAddressesProvider : IIPAddressesProvider
|
||||
{
|
||||
#region IIPAddressesProvider Members
|
||||
|
||||
public IEnumerable<IPAddress> UnicastAddresses()
|
||||
{
|
||||
return IPAddresses(p => p.UnicastAddresses.Select(x => x.Address));
|
||||
}
|
||||
|
||||
public IEnumerable<IPAddress> DnsAddresses()
|
||||
{
|
||||
return IPAddresses(p => p.DnsAddresses);
|
||||
}
|
||||
|
||||
public IEnumerable<IPAddress> GatewayAddresses()
|
||||
{
|
||||
return IPAddresses(p => p.GatewayAddresses.Select(x => x.Address));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static IEnumerable<IPAddress> IPAddresses(Func<IPInterfaceProperties, IEnumerable<IPAddress>> ipExtractor)
|
||||
{
|
||||
return from networkInterface in NetworkInterface.GetAllNetworkInterfaces()
|
||||
where
|
||||
networkInterface.OperationalStatus == OperationalStatus.Up ||
|
||||
networkInterface.OperationalStatus == OperationalStatus.Unknown
|
||||
let properties = networkInterface.GetIPProperties()
|
||||
from address in ipExtractor(properties)
|
||||
where address.AddressFamily == AddressFamily.InterNetwork
|
||||
select address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Authors:
|
||||
// Lucas Ontivero lucasontivero@gmail.com
|
||||
//
|
||||
// Copyright (C) 2014 Lucas Ontivero
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Open.Nat
|
||||
{
|
||||
internal static class WellKnownConstants
|
||||
{
|
||||
public static IPAddress IPv4MulticastAddress = IPAddress.Parse("239.255.255.250");
|
||||
public static IPEndPoint NatPmpEndPoint = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 5351);
|
||||
}
|
||||
}
|
||||
|
|
@ -1324,7 +1324,7 @@ namespace RBXLegacyLauncher
|
|||
this.tabPage7.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage7.Size = new System.Drawing.Size(447, 250);
|
||||
this.tabPage7.TabIndex = 6;
|
||||
this.tabPage7.Text = "GEARS";
|
||||
this.tabPage7.Text = "GEAR";
|
||||
this.tabPage7.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// button7
|
||||
|
|
|
|||
|
|
@ -112,12 +112,12 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBox5.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
|
|
@ -1273,7 +1273,7 @@
|
|||
<data name="button1308.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -1417,7 +1417,7 @@
|
|||
<data name="button1208.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -1561,7 +1561,7 @@
|
|||
<data name="button1108.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -1705,7 +1705,7 @@
|
|||
<data name="button1008.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -1849,7 +1849,7 @@
|
|||
<data name="button908.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -1993,7 +1993,7 @@
|
|||
<data name="button708.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -2137,7 +2137,7 @@
|
|||
<data name="button608.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
@ -2281,7 +2281,7 @@
|
|||
<data name="button508.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAYAAAB+TFE1AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vQAADr0BR/uQrQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
vAAADrwBlbxySQAAIEdJREFUeF7t3Qtz1EbahuHv//+w9e4mBHO0YSEH7ACOsQHb2GAb5qtbNU1NHCG1
|
||||
ZkbSK/V9VXWFeDQ6tFT9jE7d/7eQJCkAA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaS
|
||||
JCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmS
|
||||
QjCQJEkhGEiSpBAMJElSCAaSJCkEA0mSFIKBJEkKwUCSJIVgIEmSQjCQJEkhGEiSpBAMJElSCAaSJCkE
|
||||
|
|
|
|||
|
|
@ -112,9 +112,9 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
|
@ -112,10 +112,10 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="richTextBox1.Text" xml:space="preserve">
|
||||
<value>VERSION CODENAME DOCUMENTATION
|
||||
|
|
|
|||
|
|
@ -112,10 +112,10 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
|
||||
this.button11 = new System.Windows.Forms.Button();
|
||||
this.label35 = new System.Windows.Forms.Label();
|
||||
this.label42 = new System.Windows.Forms.Label();
|
||||
|
|
@ -99,10 +100,10 @@
|
|||
this.label27 = new System.Windows.Forms.Label();
|
||||
this.label28 = new System.Windows.Forms.Label();
|
||||
this.textBox5 = new System.Windows.Forms.TextBox();
|
||||
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.tabPage6.SuspendLayout();
|
||||
|
|
@ -110,7 +111,6 @@
|
|||
this.tabPage8.SuspendLayout();
|
||||
this.tabPage4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// pictureBox1
|
||||
|
|
@ -171,6 +171,25 @@
|
|||
this.tabPage1.ToolTipText = "Join a server via IP Address";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// numericUpDown1
|
||||
//
|
||||
this.numericUpDown1.Location = new System.Drawing.Point(214, 25);
|
||||
this.numericUpDown1.Maximum = new decimal(new int[] {
|
||||
99999,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDown1.Name = "numericUpDown1";
|
||||
this.numericUpDown1.Size = new System.Drawing.Size(175, 20);
|
||||
this.numericUpDown1.TabIndex = 43;
|
||||
this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.numericUpDown1.Value = new decimal(new int[] {
|
||||
53640,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDown1.ValueChanged += new System.EventHandler(this.NumericUpDown1ValueChanged);
|
||||
//
|
||||
// button11
|
||||
//
|
||||
this.button11.Location = new System.Drawing.Point(213, 47);
|
||||
|
|
@ -389,6 +408,7 @@
|
|||
this.label30.Name = "label30";
|
||||
this.label30.Size = new System.Drawing.Size(393, 2);
|
||||
this.label30.TabIndex = 23;
|
||||
this.label30.Visible = false;
|
||||
//
|
||||
// button6
|
||||
//
|
||||
|
|
@ -398,6 +418,7 @@
|
|||
this.button6.TabIndex = 6;
|
||||
this.button6.Text = "CONFIGURE CLIENT";
|
||||
this.button6.UseVisualStyleBackColor = true;
|
||||
this.button6.Visible = false;
|
||||
this.button6.Click += new System.EventHandler(this.Button6Click);
|
||||
//
|
||||
// label19
|
||||
|
|
@ -416,7 +437,7 @@
|
|||
this.textBox6.Name = "textBox6";
|
||||
this.textBox6.ReadOnly = true;
|
||||
this.textBox6.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.textBox6.Size = new System.Drawing.Size(393, 67);
|
||||
this.textBox6.Size = new System.Drawing.Size(393, 111);
|
||||
this.textBox6.TabIndex = 4;
|
||||
this.textBox6.Text = "textBox6";
|
||||
//
|
||||
|
|
@ -999,24 +1020,6 @@
|
|||
this.textBox5.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.textBox5.TextChanged += new System.EventHandler(this.TextBox5TextChanged);
|
||||
//
|
||||
// numericUpDown1
|
||||
//
|
||||
this.numericUpDown1.Location = new System.Drawing.Point(214, 25);
|
||||
this.numericUpDown1.Maximum = new decimal(new int[] {
|
||||
99999,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDown1.Name = "numericUpDown1";
|
||||
this.numericUpDown1.Size = new System.Drawing.Size(175, 20);
|
||||
this.numericUpDown1.TabIndex = 43;
|
||||
this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.numericUpDown1.Value = new decimal(new int[] {
|
||||
53640,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
|
@ -1055,6 +1058,7 @@
|
|||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.tabPage3.PerformLayout();
|
||||
|
|
@ -1063,7 +1067,6 @@
|
|||
this.tabPage8.ResumeLayout(false);
|
||||
this.tabPage4.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Reflection;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Open.Nat;
|
||||
|
||||
namespace RBXLegacyLauncher
|
||||
{
|
||||
|
|
@ -19,42 +20,61 @@ namespace RBXLegacyLauncher
|
|||
InitializeComponent();
|
||||
}
|
||||
|
||||
public event EventHandler<evNATdoneargs> evNATdone;
|
||||
|
||||
public class evNATdoneargs : EventArgs
|
||||
public async void StartUPNP()
|
||||
{
|
||||
public string IP;
|
||||
public int port;
|
||||
}
|
||||
try
|
||||
{
|
||||
var nat = new NatDiscoverer();
|
||||
|
||||
//this class contains network connectivity stuff
|
||||
public void StartUPNP()
|
||||
{
|
||||
Mono.Nat.NatUtility.DeviceFound += new EventHandler<Mono.Nat.DeviceEventArgs>(NatUtility_DeviceFound);
|
||||
Mono.Nat.NatUtility.DeviceLost += new EventHandler<Mono.Nat.DeviceEventArgs>(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);
|
||||
var cts = new CancellationTokenSource(5000);
|
||||
var device = await nat.DiscoverDeviceAsync(PortMapper.Upnp, cts);
|
||||
await device.CreatePortMapAsync(new Mapping(Protocol.Udp, GlobalVars.ServerPort, GlobalVars.ServerPort, "RBXLegacy"));
|
||||
|
||||
var ip = await device.GetExternalIPAsync();
|
||||
|
||||
ConsolePrint("Port " + GlobalVars.ServerPort.ToString() + " registered to device " + ip, 3);
|
||||
}
|
||||
catch(NatDeviceNotFoundException e)
|
||||
{
|
||||
ConsolePrint("Error: " + e.ToString(), 2);
|
||||
}
|
||||
catch(MappingException me)
|
||||
{
|
||||
switch(me.ErrorCode)
|
||||
{
|
||||
case 718:
|
||||
ConsolePrint("The external port is already in use.", 2);
|
||||
break;
|
||||
case 728:
|
||||
ConsolePrint("The router's mapping table is full.", 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void NatUtility_DeviceLost(object sender, Mono.Nat.DeviceEventArgs e)
|
||||
public async void StopUPNP()
|
||||
{
|
||||
//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));
|
||||
try
|
||||
{
|
||||
var nat = new NatDiscoverer();
|
||||
var cts = new CancellationTokenSource(5000);
|
||||
var device = await nat.DiscoverDeviceAsync(PortMapper.Upnp, cts);
|
||||
|
||||
foreach (var mapping in await device.GetAllMappingsAsync())
|
||||
{
|
||||
if(mapping.Description.Contains("RBXLegacy"))
|
||||
{
|
||||
await device.DeletePortMapAsync(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
var ip = await device.GetExternalIPAsync();
|
||||
ConsolePrint("Port " + GlobalVars.ServerPort.ToString() + " removed from device " + ip, 2);
|
||||
}
|
||||
catch(NatDeviceNotFoundException e)
|
||||
{
|
||||
ConsolePrint("Error: " + e.ToString(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
|
||||
|
|
@ -398,7 +418,7 @@ namespace RBXLegacyLauncher
|
|||
DialogResult result = MessageBox.Show("Your configuration has been saved successfully!","RBXLegacy Launcher - Configuration", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
void numericUpDown1TextChanged(object sender, EventArgs e)
|
||||
void NumericUpDown1ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
int parsedValue;
|
||||
if (int.TryParse(numericUpDown1.Text, out parsedValue))
|
||||
|
|
@ -607,6 +627,7 @@ namespace RBXLegacyLauncher
|
|||
|
||||
void ConsolePrint(string text, int type)
|
||||
{
|
||||
//1 = white text, 2 = red text, 3 = green text, 4 = aqua text, 5 = yellow text
|
||||
richTextBox1.AppendText("[" + DateTime.Now.ToShortTimeString() + "]", Color.White);
|
||||
richTextBox1.AppendText(" - ", Color.White);
|
||||
if (type == 1)
|
||||
|
|
@ -755,19 +776,19 @@ namespace RBXLegacyLauncher
|
|||
string HatIDOffline3 = GlobalVars.Custom_Hat3ID_Offline;
|
||||
if (GlobalVars.UsesPlayerName == true && GlobalVars.UsesID == true)
|
||||
{
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(" + GlobalVars.UserID + ",'" + GlobalVars.PlayerName + "','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + ") " + quote;
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(" + GlobalVars.UserID + ",'" + GlobalVars.PlayerName + "','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + "," + GlobalVars.RespawnTime + ") " + quote;
|
||||
}
|
||||
else if (GlobalVars.UsesPlayerName == false && GlobalVars.UsesID == true)
|
||||
{
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(" + GlobalVars.UserID + ",'Player','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + ") " + quote;
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(" + GlobalVars.UserID + ",'Player','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + "," + GlobalVars.RespawnTime + ") " + quote;
|
||||
}
|
||||
else if (GlobalVars.UsesPlayerName == true && GlobalVars.UsesID == false)
|
||||
{
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(0,'" + GlobalVars.PlayerName + "','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + ") " + quote;
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(0,'" + GlobalVars.PlayerName + "','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + "," + GlobalVars.RespawnTime + ") " + quote;
|
||||
}
|
||||
else if (GlobalVars.UsesPlayerName == false && GlobalVars.UsesID == false )
|
||||
{
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(0,'Player','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + ") " + quote;
|
||||
args = quote + mapfile + "\" -script \"dofile('" + GlobalVars.DefaultScript + "') _G.SetRBXLegacyVersion(" + GlobalVars.SelectedClientVersion + ") _G.CSSolo(0,'Player','" + HatIDOffline1 + "','" + HatIDOffline2 + "','" + HatIDOffline3 + "'," + GlobalVars.HeadColorID + "," + GlobalVars.TorsoColorID + "," + GlobalVars.LeftArmColorID + "," + GlobalVars.RightArmColorID + "," + GlobalVars.LeftLegColorID + "," + GlobalVars.RightLegColorID + ",'" + GlobalVars.Custom_TShirt + "','" + GlobalVars.Custom_Shirt + "','" + GlobalVars.Custom_Pants + "','" + GlobalVars.FaceID + "','" + GlobalVars.HeadID + "','" + GlobalVars.TorsoID + "','" + GlobalVars.RightArmID + "','" + GlobalVars.LeftArmID + "','" + GlobalVars.RightLegID + "','" + GlobalVars.LeftLegID + "','" + GlobalVars.Custom_Gear1 + "','" + GlobalVars.Custom_Gear2 + "','" + GlobalVars.Custom_Gear3 + "','" + GlobalVars.Custom_IconType + "'," + GlobalVars.melee.ToString().ToLower() + "," + GlobalVars.powerup.ToString().ToLower() + "," + GlobalVars.ranged.ToString().ToLower() + "," + GlobalVars.navigation.ToString().ToLower() + "," + GlobalVars.explosives.ToString().ToLower() + "," + GlobalVars.musical.ToString().ToLower() + "," + GlobalVars.social.ToString().ToLower() + "," + GlobalVars.transport.ToString().ToLower() + "," + GlobalVars.building.ToString().ToLower() + "," + GlobalVars.RespawnTime + ") " + quote;
|
||||
}
|
||||
try
|
||||
{
|
||||
|
|
@ -799,7 +820,16 @@ namespace RBXLegacyLauncher
|
|||
try
|
||||
{
|
||||
ConsolePrint("Server Loaded.", 4);
|
||||
Process.Start(rbxexe, args);
|
||||
Process server = new Process();
|
||||
server.StartInfo.FileName = rbxexe;
|
||||
server.StartInfo.Arguments = args;
|
||||
server.EnableRaisingEvents = true;
|
||||
ReadClientValues(GlobalVars.SelectedClient);
|
||||
if (GlobalVars.upnp == true)
|
||||
{
|
||||
server.Exited += new EventHandler(ServerExited);
|
||||
}
|
||||
server.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -826,7 +856,16 @@ namespace RBXLegacyLauncher
|
|||
try
|
||||
{
|
||||
ConsolePrint("Server Loaded in No3D mode.", 4);
|
||||
Process.Start(rbxexe, args);
|
||||
Process server = new Process();
|
||||
server.StartInfo.FileName = rbxexe;
|
||||
server.StartInfo.Arguments = args;
|
||||
server.EnableRaisingEvents = true;
|
||||
ReadClientValues(GlobalVars.SelectedClient);
|
||||
if (GlobalVars.upnp == true)
|
||||
{
|
||||
server.Exited += new EventHandler(ServerExited);
|
||||
}
|
||||
server.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -835,6 +874,16 @@ namespace RBXLegacyLauncher
|
|||
}
|
||||
}
|
||||
|
||||
void ServerExited(object sender, EventArgs e)
|
||||
{
|
||||
StopUPNP();
|
||||
|
||||
if (this.WindowState == FormWindowState.Minimized)
|
||||
{
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
void StartStudio()
|
||||
{
|
||||
string mapfile = GlobalVars.MapsDir + @"\\" + GlobalVars.Map;
|
||||
|
|
@ -872,8 +921,8 @@ namespace RBXLegacyLauncher
|
|||
|
||||
void ConsoleProcessCommands(string command)
|
||||
{
|
||||
string important = SecurityFuncs.Base64Decode("cmJ4bGVnYWN5IGthbnJpc2hh");
|
||||
if (command.Equals("rbxlegacy server"))
|
||||
string important = SecurityFuncs.Base64Decode("a2FucmlzaGE=");
|
||||
if (command.Equals("server"))
|
||||
{
|
||||
if (GlobalVars.upnp == true)
|
||||
{
|
||||
|
|
@ -881,7 +930,7 @@ namespace RBXLegacyLauncher
|
|||
}
|
||||
StartServer();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy server no3d"))
|
||||
else if (command.Equals("serverno3d"))
|
||||
{
|
||||
if (GlobalVars.upnp == true)
|
||||
{
|
||||
|
|
@ -889,15 +938,7 @@ namespace RBXLegacyLauncher
|
|||
}
|
||||
StartServerNo3D();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy no3d"))
|
||||
{
|
||||
if (GlobalVars.upnp == true)
|
||||
{
|
||||
StartUPNP();
|
||||
}
|
||||
StartServerNo3D();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy client"))
|
||||
else if (command.Equals("client"))
|
||||
{
|
||||
ReadClientValues(GlobalVars.SelectedClient);
|
||||
if (GlobalVars.HasRocky == true)
|
||||
|
|
@ -911,53 +952,37 @@ namespace RBXLegacyLauncher
|
|||
}
|
||||
StartClient();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy client solo"))
|
||||
else if (command.Equals("solo"))
|
||||
{
|
||||
StartSolo();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy solo"))
|
||||
{
|
||||
StartSolo();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy studio"))
|
||||
else if (command.Equals("studio"))
|
||||
{
|
||||
StartStudio();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy config save"))
|
||||
else if (command.Equals("config save"))
|
||||
{
|
||||
WriteConfigValues();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy config load"))
|
||||
else if (command.Equals("config load"))
|
||||
{
|
||||
ReadConfigValues();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy config reset"))
|
||||
else if (command.Equals("config reset"))
|
||||
{
|
||||
ResetConfigValues();
|
||||
}
|
||||
else if (command.Equals("rbxlegacy sdk"))
|
||||
{
|
||||
SDKForm sdk = new SDKForm();
|
||||
sdk.Show();
|
||||
ConsolePrint("Launched SDK.", 4);
|
||||
}
|
||||
else if (command.Equals("sdk"))
|
||||
{
|
||||
SDKForm sdk = new SDKForm();
|
||||
sdk.Show();
|
||||
ConsolePrint("Launched SDK.", 4);
|
||||
}
|
||||
else if (command.Equals("rbxlegacy help"))
|
||||
else if (command.Equals("uri"))
|
||||
{
|
||||
ConsoleRBXLegacyHelp(0);
|
||||
}
|
||||
else if (command.Equals("rbxlegacy"))
|
||||
{
|
||||
ConsoleRBXLegacyHelp(0);
|
||||
}
|
||||
else if (command.Equals("rbxlegacy config"))
|
||||
{
|
||||
ConsoleRBXLegacyHelp(1);
|
||||
Process uri = new Process();
|
||||
uri.StartInfo.FileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\RBXLegacyURI.exe";
|
||||
uri.Start();
|
||||
}
|
||||
else if (command.Equals("config"))
|
||||
{
|
||||
|
|
@ -975,7 +1000,7 @@ namespace RBXLegacyLauncher
|
|||
}
|
||||
else
|
||||
{
|
||||
ConsolePrint("ERROR 3 - Command is either not registered or valid", 2);
|
||||
ConsolePrint("ERROR 3 - Command is invalid", 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -984,32 +1009,36 @@ namespace RBXLegacyLauncher
|
|||
{
|
||||
if (page == 1)
|
||||
{
|
||||
ConsolePrint("rbxlegacy config", 2);
|
||||
ConsolePrint("-------------------------", 1);
|
||||
ConsolePrint("= save | Saves the config file", 3);
|
||||
ConsolePrint("= load | Reloads the config file", 3);
|
||||
ConsolePrint("= reset | Resets the config file", 3);
|
||||
ConsolePrint("RBXLegacy Config Command List", 2);
|
||||
ConsolePrint("-----------------------------------------", 1);
|
||||
ConsolePrint("config save | Saves the config file", 4);
|
||||
ConsolePrint("config load | Reloads the config file", 4);
|
||||
ConsolePrint("config reset | Resets the config file", 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsolePrint("rbxlegacy", 2);
|
||||
ConsolePrint("---------", 1);
|
||||
ConsolePrint("= client | Loads client with launcher settings", 3);
|
||||
ConsolePrint("-- solo | Loads client in Play Solo mode with launcher settings", 4);
|
||||
ConsolePrint("= server | Loads server with launcher settings", 3);
|
||||
ConsolePrint("-- no3d | Loads server in NoGraphics mode with launcher settings", 4);
|
||||
ConsolePrint("= studio | Loads Roblox Studio with launcher settings", 3);
|
||||
ConsolePrint("= sdk | Loads the RBXLegacy SDK", 3);
|
||||
ConsolePrint("= config", 3);
|
||||
ConsolePrint("-- save | Saves the config file", 4);
|
||||
ConsolePrint("-- load | Reloads the config file", 4);
|
||||
ConsolePrint("-- reset | Resets the config file", 4);
|
||||
ConsolePrint("RBXLegacy Console Command List", 2);
|
||||
ConsolePrint("------------------------------------------", 1);
|
||||
ConsolePrint("client | Loads client with launcher settings", 4);
|
||||
ConsolePrint("solo | Loads client in Play Solo mode with launcher settings", 4);
|
||||
ConsolePrint("server | Loads server with launcher settings", 4);
|
||||
ConsolePrint("serverno3d | Loads server in No3D mode with launcher settings", 4);
|
||||
ConsolePrint("studio | Loads Roblox Studio with launcher settings", 4);
|
||||
ConsolePrint("sdk | Loads the RBXLegacy SDK", 4);
|
||||
ConsolePrint("uri | Installs the RBXLegacy URI", 4);
|
||||
ConsolePrint("config save | Saves the config file", 4);
|
||||
ConsolePrint("config load | Reloads the config file", 4);
|
||||
ConsolePrint("config reset | Resets the config file", 4);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
base.OnFormClosing(e);
|
||||
if (GlobalVars.upnp == true)
|
||||
{
|
||||
StopUPNP();
|
||||
}
|
||||
WriteConfigValues();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,16 +112,16 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAMYAAAAhCAYAAACC2tRnAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
vgAADr4B6kKxwAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAAYO0lEQVR4Xu1c
|
||||
vAAADrwBlbxySQAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAAYO0lEQVR4Xu1c
|
||||
CXgUVba+ne5sEPYdJAKCOiqCDqPCoIgbDjow41NHEARRH47PcUNRouI2jLKKIgIiKgg+NtFRILImQJAd
|
||||
M7INARJCEsOSAFl7q+r/nXPrVqe6Ux1ah+D3vi/n+/6vqqvOPffce89/t6pqYScQ4k7CNgjXIThcWXS0
|
||||
ICYLDlEFUU9BXQ/qWXXoXozI8jtFVmWsAb+LrtM1iRBdy2/j3u8I8cqvOEJXCOc9ZHMUnb9IOoyxpP8e
|
||||
|
|
@ -235,7 +235,7 @@
|
|||
<data name="pictureBox2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAMYAAAAhCAYAAACC2tRnAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
wAAADsABataJCQAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAAYO0lEQVR4Xu1c
|
||||
vQAADr0BR/uQrQAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAAYO0lEQVR4Xu1c
|
||||
CXgUVba+ne5sEPYdJAKCOiqCDqPCoIgbDjow41NHEARRH47PcUNRouI2jLKKIgIiKgg+NtFRILImQJAd
|
||||
M7INARJCEsOSAFl7q+r/nXPrVqe6Ux1ah+D3vi/n+/6vqqvOPffce89/t6pqYScQ4k7CNgjXIThcWXS0
|
||||
ICYLDlEFUU9BXQ/qWXXoXozI8jtFVmWsAb+LrtM1iRBdy2/j3u8I8cqvOEJXCOc9ZHMUnb9IOoyxpP8e
|
||||
|
|
|
|||
|
|
@ -112,10 +112,10 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>RBXLegacyLauncher</RootNamespace>
|
||||
<AssemblyName>RBXLegacyLauncher</AssemblyName>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
|
|
@ -49,14 +49,23 @@
|
|||
<StartProgram>..\..\..\RBXLegacy\release\RBXLegacy\RBXLegacyLauncher.exe</StartProgram>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Nat">
|
||||
<HintPath>Resources\Mono.Nat.dll</HintPath>
|
||||
<Reference Include="Open.Nat">
|
||||
<HintPath>Resources\Open.Nat.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CharacterCustomization.cs" />
|
||||
|
|
@ -110,9 +119,6 @@
|
|||
<EmbeddedResource Include="DocForm.resx">
|
||||
<DependentUpon>DocForm.Designer.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>ClientSettings.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="LoaderForm.resx">
|
||||
<DependentUpon>LoaderForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -4,12 +4,14 @@ using System.Drawing;
|
|||
using System.Windows.Forms;
|
||||
|
||||
// you need this once (only), and it must be in this namespace
|
||||
/*
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class
|
||||
| AttributeTargets.Method)]
|
||||
public sealed class ExtensionAttribute : Attribute {}
|
||||
}
|
||||
*/
|
||||
|
||||
public static class RichTextBoxExtensions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@
|
|||
this.checkBox4.Name = "checkBox4";
|
||||
this.checkBox4.Size = new System.Drawing.Size(192, 20);
|
||||
this.checkBox4.TabIndex = 34;
|
||||
this.checkBox4.Text = "Use Sudppipe (RECCOMENDED)";
|
||||
this.checkBox4.Text = "Use Sudppipe (RECOMMENDED)";
|
||||
this.checkBox4.UseVisualStyleBackColor = true;
|
||||
this.checkBox4.CheckedChanged += new System.EventHandler(this.CheckBox4CheckedChanged);
|
||||
//
|
||||
|
|
|
|||
|
|
@ -112,12 +112,12 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAYAEBAAAAAAIABoBAAAZgAAACAgAAAAACAAqBAAAM4EAAAwMAAAAAAgAKglAAB2FQAAQEAAAAAA
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
|
||||
this.checkBox12 = new System.Windows.Forms.CheckBox();
|
||||
this.textBox11 = new System.Windows.Forms.TextBox();
|
||||
this.textBox12 = new System.Windows.Forms.TextBox();
|
||||
|
|
@ -55,11 +56,10 @@
|
|||
this.radioButton1 = new System.Windows.Forms.RadioButton();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox1
|
||||
|
|
@ -133,6 +133,24 @@
|
|||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
this.tabPage1.Click += new System.EventHandler(this.TabPage1Click);
|
||||
//
|
||||
// numericUpDown1
|
||||
//
|
||||
this.numericUpDown1.Location = new System.Drawing.Point(240, 80);
|
||||
this.numericUpDown1.Maximum = new decimal(new int[] {
|
||||
99999,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDown1.Name = "numericUpDown1";
|
||||
this.numericUpDown1.Size = new System.Drawing.Size(237, 20);
|
||||
this.numericUpDown1.TabIndex = 67;
|
||||
this.numericUpDown1.Value = new decimal(new int[] {
|
||||
53640,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDown1.ValueChanged += new System.EventHandler(this.NumericUpDown1ValueChanged);
|
||||
//
|
||||
// checkBox12
|
||||
//
|
||||
this.checkBox12.Location = new System.Drawing.Point(353, 6);
|
||||
|
|
@ -494,23 +512,6 @@
|
|||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.Button1Click);
|
||||
//
|
||||
// numericUpDown1
|
||||
//
|
||||
this.numericUpDown1.Location = new System.Drawing.Point(240, 80);
|
||||
this.numericUpDown1.Maximum = new decimal(new int[] {
|
||||
99999,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDown1.Name = "numericUpDown1";
|
||||
this.numericUpDown1.Size = new System.Drawing.Size(237, 20);
|
||||
this.numericUpDown1.TabIndex = 67;
|
||||
this.numericUpDown1.Value = new decimal(new int[] {
|
||||
53640,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// ServerPrefs
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
|
@ -530,9 +531,9 @@
|
|||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
private System.Windows.Forms.NumericUpDown numericUpDown1;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Open.Nat;
|
||||
|
||||
namespace RBXLegacyLauncher
|
||||
{
|
||||
|
|
@ -191,21 +194,16 @@ namespace RBXLegacyLauncher
|
|||
|
||||
string GetExternalIPAddress()
|
||||
{
|
||||
string ipAddress;
|
||||
using (WebClient wc = new WebClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
Mono.Nat.INatDevice natd = e.Device;
|
||||
ipAddress = natd.GetExternalIP().ToString();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
ipAddress = "localhost";
|
||||
}
|
||||
}
|
||||
|
||||
return ipAddress;
|
||||
string url = "http://checkip.dyndns.org";
|
||||
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
|
||||
System.Net.WebResponse resp = req.GetResponse();
|
||||
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
|
||||
string response = sr.ReadToEnd().Trim();
|
||||
string[] a = response.Split(':');
|
||||
string a2 = a[1].Substring(1);
|
||||
string[] a3 = a2.Split('<');
|
||||
string a4 = a3[0];
|
||||
return a4;
|
||||
}
|
||||
|
||||
void RadioButton1CheckedChanged(object sender, EventArgs e)
|
||||
|
|
@ -307,7 +305,7 @@ namespace RBXLegacyLauncher
|
|||
GlobalVars.building = false;
|
||||
}
|
||||
|
||||
void numericUpDown1TextChanged(object sender, EventArgs e)
|
||||
void NumericUpDown1ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
int parsedValue;
|
||||
if (int.TryParse(numericUpDown1.Text, out parsedValue))
|
||||
|
|
|
|||
|
|
@ -112,12 +112,12 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAYAEBAAAAAAIABoBAAAZgAAACAgAAAAACAAqBAAAM4EAAAwMAAAAAAgAKglAAB2FQAAQEAAAAAA
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v2.0.50727" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
@ -31,6 +31,7 @@ Name: "quicklaunchicon"; Description: "Create a icon on your Quick Start Menu";
|
|||
[Files]
|
||||
Source: "RBXLegacy\RBXLegacyLauncher.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\RBXLegacyLauncher.exe.config"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\RBXLegacyURI.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\README.TXT"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\changelog.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\info.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
|
@ -40,7 +41,7 @@ Source: "RBXLegacy\models\*"; DestDir: "{app}\models"; Flags: ignoreversion recu
|
|||
Source: "RBXLegacy\avatar\*"; DestDir: "{app}\avatar"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "RBXLegacy\scripts\*"; DestDir: "{app}\scripts"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "RBXLegacy\udppipe.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\Mono.Nat.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy\Open.Nat.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\RBXLegacy"; Filename: "{app}\RBXLegacyLauncher.exe"
|
||||
|
|
@ -50,5 +51,6 @@ Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\RBXLegacy"; Filena
|
|||
|
||||
[Run]
|
||||
Filename: "{app}\RBXLegacyLauncher.exe"; Description: "Play RBXLegacy"; Flags: nowait postinstall skipifsilent
|
||||
Filename: "{app}\RBXLegacyURI.exe"; Description: "Install the URI"; Flags: nowait postinstall skipifsilent
|
||||
Filename: "{app}\README.TXT"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent unchecked
|
||||
Filename: "{app}\changelog.txt"; Description: "View the changelog"; Flags: postinstall shellexec skipifsilent unchecked
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ Name: "quicklaunchicon"; Description: "Create a icon on your Quick Start Menu";
|
|||
[Files]
|
||||
Source: "RBXLegacy-Preview\RBXLegacyLauncher.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\RBXLegacyLauncher.exe.config"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\RBXLegacyURI.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\README.TXT"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\changelog.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\info.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
|
@ -40,7 +41,7 @@ Source: "RBXLegacy-Preview\models\*"; DestDir: "{app}\models"; Flags: ignorevers
|
|||
Source: "RBXLegacy-Preview\avatar\*"; DestDir: "{app}\avatar"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "RBXLegacy-Preview\scripts\*"; DestDir: "{app}\scripts"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "RBXLegacy-Preview\udppipe.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\Mono.Nat.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "RBXLegacy-Preview\Open.Nat.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\RBXLegacy-Preview"; Filename: "{app}\RBXLegacyLauncher.exe"
|
||||
|
|
@ -49,6 +50,7 @@ Name: "{commondesktop}\RBXLegacy-Preview"; Filename: "{app}\RBXLegacyLauncher.ex
|
|||
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\RBXLegacy-Preview"; Filename: "{app}\RBXLegacyLauncher.exe"; Tasks: quicklaunchicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\RBXLegacyLauncher.exe"; Description: "Play RBXLegacy 1.18 Preview"; Flags: nowait postinstall skipifsilent
|
||||
Filename: "{app}\RBXLegacyLauncher.exe"; Description: "Play RBXLegacy"; Flags: nowait postinstall skipifsilent
|
||||
Filename: "{app}\RBXLegacyURI.exe"; Description: "Install the URI"; Flags: nowait postinstall skipifsilent
|
||||
Filename: "{app}\README.TXT"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent unchecked
|
||||
Filename: "{app}\changelog.txt"; Description: "View the changelog"; Flags: postinstall shellexec skipifsilent unchecked
|
||||
|
|
|
|||
|
|
@ -18,15 +18,18 @@ namespace RBXLegacyURI
|
|||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Console.Title = "RBXLegacy";
|
||||
try {
|
||||
Console.Title = "RBXLegacy URI Installer";
|
||||
try
|
||||
{
|
||||
Program.registerURI("RBXLegacy", AppDomain.CurrentDomain.BaseDirectory + "RBXLegacyLauncher.exe", "");
|
||||
Program.registerURI("rbxlegacy", AppDomain.CurrentDomain.BaseDirectory + "RBXLegacyLauncher.exe", ""); // chromium
|
||||
Console.WriteLine("RBXLegacy has been installed on your computer successfully! You can now join RBXLegacy servers with URI.");
|
||||
Console.WriteLine("RBXLegacy has been installed on your computer successfully! You can now join RBXLegacy servers with URI links and via the website!");
|
||||
Console.WriteLine("Press any key to continue . . .");
|
||||
Console.ReadKey();
|
||||
} catch (Exception) {
|
||||
Console.Title = "RBXLegacy - ERROR";
|
||||
Console.WriteLine("z0mgh4x0r l0gs"); // how can they see this still??? 1337 h4x0r
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine("RBXLegacy failed to install the RBXLegacy URL protocol.");
|
||||
Console.WriteLine("Make sure you're running this application as an administrator, and that RBXLegacyLauncher.exe is in the RBXLegacy folder.");
|
||||
Console.WriteLine("Press any key to continue . . .");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<ApplicationIcon>Resources\rbxlegacyicon2.ico</ApplicationIcon>
|
||||
<NoWin32Manifest>False</NoWin32Manifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
|
|
@ -20,3 +20,11 @@ If you find any problem(s) in RBXLegacy, [feel free to submit an issue here.](ht
|
|||
If you know how to solve an (existing) issue in RBXLegacy, [you can submit a pull request for it.](https://github.com/Bitl/RBXLegacy-src/pulls)
|
||||
|
||||
And of course, we welcome everyone with new ideas. [You can post your idea in issues as well.](https://github.com/Bitl/RBXLegacy-src/issues)
|
||||
|
||||
## Licence
|
||||
|
||||
RBXLegacy is licenced under the GPL, but some components of it may use different licences.
|
||||
|
||||
Open.NAT is licened under the MIT Licence. Please look in the Open.NAT folder for more information.
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue