├── .nuget ├── NuGet.exe ├── NuGet.Config └── NuGet.targets ├── NetroTest ├── packages.config ├── Properties │ └── AssemblyInfo.cs ├── Util │ ├── AsyncTest.cs │ └── Extensions.cs ├── NetroTestFull.cs ├── SocketPipeTest.cs ├── NetroTest.csproj ├── ReverseAsyncSocketTest.cs ├── NetroTest.cs └── AsyncSocketTest.cs ├── Netro ├── Properties │ └── AssemblyInfo.cs ├── SocketPipe.cs ├── Program.cs ├── NetroStatus.cs ├── Netro.csproj ├── Netro.cs ├── Output.cs ├── ReverseAsyncSocket.cs └── AsyncSocket.cs ├── Netro.sln └── Readme.md /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eirikb/Netro/HEAD/.nuget/NuGet.exe -------------------------------------------------------------------------------- /NetroTest/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Netro/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("Netro")] 5 | [assembly: ComVisible(false)] 6 | [assembly: Guid("64c033e8-bb86-4924-bd67-85363506b441")] 7 | [assembly: AssemblyVersion("1.0.1.0")] 8 | [assembly: AssemblyFileVersion("1.0.1.0")] -------------------------------------------------------------------------------- /NetroTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("NetroTest")] 5 | [assembly: AssemblyProduct("NetroTest")] 6 | [assembly: ComVisible(false)] 7 | [assembly: Guid("0dcfc932-87b4-43d3-82ac-f4aca1512628")] 8 | [assembly: AssemblyVersion("1.0.0.0")] 9 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Netro/SocketPipe.cs: -------------------------------------------------------------------------------- 1 | namespace Netro 2 | { 3 | public static class SocketPipe 4 | { 5 | public static void PipeSockets(AsyncSocket socketA, AsyncSocket socketB) 6 | { 7 | socketA.Read(socketB.Write); 8 | socketB.Read(socketA.Write); 9 | 10 | socketA.Disconnect(socketB.Disconnect); 11 | socketB.Disconnect(socketA.Disconnect); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /NetroTest/Util/AsyncTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using NUnit.Framework; 4 | 5 | namespace NetroTest.Util 6 | { 7 | public class AsyncTest 8 | { 9 | protected const string Host = "localhost"; 10 | private static int _port = 12111; 11 | 12 | [SetUp] 13 | public void SetUp() 14 | { 15 | _port += 5; 16 | } 17 | 18 | public void Until(Action run) 19 | { 20 | var doRun = true; 21 | run(_port, () => doRun = false); 22 | while (doRun) Thread.Sleep(100); 23 | } 24 | 25 | public void Until(Action> run) 26 | { 27 | var complete = false; 28 | run(_port, done => complete = done); 29 | while (!complete) Thread.Sleep(100); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /NetroTest/Util/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Netro; 4 | 5 | namespace NetroTest.Util 6 | { 7 | public static class AsyncSocketExtensions 8 | { 9 | public static void Write(this AsyncSocket socket, string text) 10 | { 11 | var data = Encoding.UTF8.GetBytes(text); 12 | socket.Write(data, 0, data.Length); 13 | } 14 | 15 | public static void Read(this AsyncSocket socket, Action callback) 16 | { 17 | socket.Read((buffer, read) => callback(Encoding.UTF8.GetString(buffer, 0, read))); 18 | } 19 | 20 | public static void Write(this ReverseAsyncSocket socket, int id, string text) 21 | { 22 | var data = Encoding.UTF8.GetBytes(text); 23 | socket.Write(id, Command.Data, data, 0, data.Length); 24 | } 25 | 26 | public static void ReadString(this ReverseAsyncSocket socket, Action callback) 27 | { 28 | socket.Read((id, command, data) => callback(id, command, Encoding.UTF8.GetString(data))); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Netro/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Netro 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | var netro = new Netro(); 11 | 12 | var hasListen = false; 13 | var hasClient = false; 14 | 15 | args.ToList().ForEach(arg => 16 | { 17 | int port; 18 | 19 | var split = arg.Split(':'); 20 | if (split.Length > 1) 21 | { 22 | port = int.Parse(split[1]); 23 | 24 | if (!hasClient) netro.SetClient(split[0], port); 25 | else netro.ConnectReverse(split[0], port); 26 | 27 | hasClient = true; 28 | return; 29 | } 30 | 31 | port = int.Parse(arg); 32 | 33 | if (!hasListen) netro.Listen(port); 34 | else netro.ListenReverse(port); 35 | 36 | hasListen = true; 37 | }); 38 | 39 | 40 | var netroStatus = new NetroStatus(netro); 41 | 42 | if (netroStatus.CurrentType == NetroStatus.Type.None) 43 | { 44 | Console.WriteLine("Netro not running, missing arguments?"); 45 | Console.WriteLine("Check https://github.com/eirikb/Netro for usage examples"); 46 | return; 47 | } 48 | 49 | var output = new Output(netroStatus); 50 | Console.Read(); 51 | output.Reset(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Netro.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Netro", "Netro\Netro.csproj", "{A9853783-A155-4328-B4D0-2CDFB7BD8CA7}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetroTest", "NetroTest\NetroTest.csproj", "{BE6EC95C-1A1F-41FB-A3F5-3BAACA46117F}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{33D90B52-6CE6-4B40-80C9-53517D52839A}" 9 | ProjectSection(SolutionItems) = preProject 10 | .nuget\NuGet.Config = .nuget\NuGet.Config 11 | .nuget\NuGet.exe = .nuget\NuGet.exe 12 | .nuget\NuGet.targets = .nuget\NuGet.targets 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {A9853783-A155-4328-B4D0-2CDFB7BD8CA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {A9853783-A155-4328-B4D0-2CDFB7BD8CA7}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {A9853783-A155-4328-B4D0-2CDFB7BD8CA7}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {A9853783-A155-4328-B4D0-2CDFB7BD8CA7}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {BE6EC95C-1A1F-41FB-A3F5-3BAACA46117F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {BE6EC95C-1A1F-41FB-A3F5-3BAACA46117F}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {BE6EC95C-1A1F-41FB-A3F5-3BAACA46117F}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {BE6EC95C-1A1F-41FB-A3F5-3BAACA46117F}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /NetroTest/NetroTestFull.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Netro; 3 | using NetroTest.Util; 4 | 5 | namespace NetroTest 6 | { 7 | [TestFixture] 8 | public class NetroTestFull : AsyncTest 9 | { 10 | [Test, Timeout(2000)] 11 | public void FullTest() 12 | { 13 | Until((port, done) => 14 | { 15 | var serverPortA = port + 1; 16 | var serverPortB = port + 2; 17 | 18 | var serverA = new AsyncSocket(); 19 | var serverB = new AsyncSocket(); 20 | var clientA = new AsyncSocket(); 21 | 22 | var reverseServer = new ReverseAsyncSocket(); 23 | var reverseClient = new ReverseAsyncSocket(); 24 | 25 | var netro = new Netro.Netro(); 26 | 27 | serverA.Listen(serverPortA); 28 | serverB.Listen(serverPortB); 29 | reverseServer.Listen(port); 30 | 31 | netro.ReverseServerToServer(reverseServer, serverA); 32 | netro.ReverseClientToClient(reverseClient, Host, serverPortB); 33 | 34 | reverseServer.Connect(s => 35 | { 36 | serverB.Connect(socket => socket.Read(text => 37 | { 38 | Assert.AreEqual("Hello", text); 39 | socket.Write("world!"); 40 | })); 41 | 42 | clientA.Connect(Host, serverPortA, () => 43 | { 44 | clientA.Write("Hello"); 45 | clientA.Read(text => 46 | { 47 | Assert.AreEqual("world!", text); 48 | done(); 49 | }); 50 | }); 51 | }); 52 | 53 | reverseClient.Connect(Host, port, () => { }); 54 | }); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ## Netro 2 | 3 | ![Screenshot 1.0.1](http://eirikb.github.io/Netro/1.0.1/screenshot.png) 4 | 5 | Reverse tunneling in Windows. 6 | 7 | Try it out: http://eirikb.github.io/Netro/1.0.1/Netro.exe 8 | Warning: Executable, use at your own risk! 9 | Netro works perfectly with mono for Linux / OSX. 10 | 11 | I usually fire up `ssh -R` when I need some reverse tunneling, on any platform. 12 | But sometimes I have to tunnel from Windows to Windows, and this is a bit more difficult, as I usually don't have sshd running on Windows servers. 13 | Netro, a bad play on "Metro" is here to help me and others that must do some quick, dirty and simple tunneling on Windows. 14 | 15 | 16 | Here is an example: 17 | The right side in the following figure is behind a firewall, the left side is publicly accessible. 18 | 19 | 1. Netro A listens for incoming connections, and listens for reverse tunneling. 20 | 2. Netro B connects to A for tunneling. 21 | 3. When a client connects to A the data will be transferred through the link between A and B. 22 | 4. Connection is made on B to desired host:port. 23 | 5. Data can now flow both ways. 24 | 25 | Figure: 26 | 27 | ┊ 28 | u ┆ O 29 | │ ┆ │ 30 | ┌───┴───┐ ┆ ┌───┴───┐ 31 | │ │ ┆ │ │ 32 | │ A ├───ᑕO──────┆───────────┤ B │ 33 | │ │ ┆ │ │ 34 | └───────┘ ┆ └───────┘ 35 | ┆ 36 | 37 | 38 | ### Tunneling types 39 | 40 | `Netro.exe 5000 localhost:80` 41 | Listen on port 5000, send connections/data to localhost on port 80. 42 | No reverse tunneling involved (Proxy). 43 | 44 | 45 | ┌─────┐ 46 | ᑐ───┤ ├───O 47 | └─────┘ 48 | 49 | 50 | `Netro.exe 5000 5001` 51 | Listen on port 5000 for normal connections. Listen on port 5001 for reverse tunneling connection. 52 | 53 | 54 | u 55 | │ 56 | ┌──┴──┐ 57 | ᑐ───┤ │ 58 | └─────┘ 59 | 60 | 61 | `Netro.exe example.com:5001 localhost:80` 62 | Open reverse tunneling cunnection against example.com on port 5001. 63 | On reverse connections, open connection against localhost on port 80. 64 | 65 | 66 | O 67 | │ 68 | ┌──┴──┐ 69 | │ ├───O 70 | └─────┘ 71 | 72 | ## License 73 | 74 | MIT © Eirik Brandtzæg 75 | -------------------------------------------------------------------------------- /Netro/NetroStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Netro 4 | { 5 | public class NetroStatus 6 | { 7 | public enum Type 8 | { 9 | None, 10 | ReverseServer, 11 | ReverseClient, 12 | Proxy 13 | } 14 | 15 | private readonly Netro _netro; 16 | 17 | public NetroStatus(Netro netro) 18 | { 19 | _netro = netro; 20 | } 21 | 22 | public Type CurrentType 23 | { 24 | get 25 | { 26 | if (_netro.ReverseServer != null) return Type.ReverseServer; 27 | if (_netro.ReverseClient != null) return Type.ReverseClient; 28 | return _netro.Server != null ? Type.Proxy : Type.None; 29 | } 30 | } 31 | 32 | public string From 33 | { 34 | get 35 | { 36 | switch (CurrentType) 37 | { 38 | case Type.ReverseServer: 39 | return "" + _netro.ReverseServer.Port; 40 | case Type.ReverseClient: 41 | return "" + _netro.ReverseClient.Host + ":" + _netro.ReverseClient.Port; 42 | case Type.Proxy: 43 | return "" + _netro.Server.Port; 44 | default: 45 | return ""; 46 | } 47 | } 48 | } 49 | 50 | public string To 51 | { 52 | get 53 | { 54 | switch (CurrentType) 55 | { 56 | case Type.ReverseServer: 57 | return "" + _netro.Server.Port; 58 | case Type.ReverseClient: 59 | case Type.Proxy: 60 | return _netro.Client.Key + ":" + _netro.Client.Value; 61 | default: 62 | return ""; 63 | } 64 | } 65 | } 66 | 67 | public void OnConnect(Action callback) 68 | { 69 | var reverse = _netro.ReverseServer ?? _netro.ReverseClient; 70 | var socket = _netro.Server; 71 | 72 | if (reverse != null) 73 | { 74 | reverse.Connect(s => callback(true)); 75 | reverse.Disconnect(() => callback(false)); 76 | if (reverse.Connected) callback(true); 77 | 78 | return; 79 | } 80 | 81 | if (socket == null) return; 82 | 83 | socket.Connect(s => callback(true)); 84 | socket.Disconnect(() => callback(false)); 85 | if (socket.Connected) callback(true); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /NetroTest/SocketPipeTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Netro; 3 | using NetroTest.Util; 4 | 5 | namespace NetroTest 6 | { 7 | [TestFixture] 8 | public class SocketPipeTest : AsyncTest 9 | { 10 | [Test, Timeout(2000)] 11 | public void TestPipeClients() 12 | { 13 | Until((port, done) => 14 | { 15 | var serverA = new AsyncSocket(); 16 | var serverB = new AsyncSocket(); 17 | 18 | var socketA = new AsyncSocket(); 19 | var socketB = new AsyncSocket(); 20 | 21 | serverA.Listen(port, socket => socket.Read(text => 22 | { 23 | Assert.AreEqual("Hello", text); 24 | socket.Write("world!"); 25 | })); 26 | socketA.Connect(Host, port); 27 | 28 | serverB.Listen(port + 1, socket => 29 | { 30 | socket.Read(text => 31 | { 32 | Assert.AreEqual("world!", text); 33 | done(); 34 | }); 35 | socket.Write("Hello"); 36 | }); 37 | 38 | socketB.Connect(Host, port + 1, () => { }); 39 | 40 | SocketPipe.PipeSockets(socketA, socketB); 41 | }); 42 | } 43 | 44 | [Test, Timeout(10000)] 45 | public void TestPipeServerClient() 46 | { 47 | Until((port, done) => 48 | { 49 | var server = new AsyncSocket(); 50 | 51 | var socketA = new AsyncSocket(); 52 | var socketB = new AsyncSocket(); 53 | var portA = port; 54 | var portB = portA + 1; 55 | 56 | server.Listen(portA, socket => socket.Read(text => 57 | { 58 | Assert.AreEqual("Hello", text); 59 | socket.Write("world!"); 60 | })); 61 | 62 | socketB.Listen(portB, socket => 63 | { 64 | var c = new AsyncSocket(); 65 | c.Connect(Host, portB, () => SocketPipe.PipeSockets(socket, c)); 66 | }); 67 | 68 | socketA.Read(text => 69 | { 70 | Assert.AreEqual("world!", text); 71 | done(); 72 | }); 73 | socketA.Connect(Host, portA, () => socketA.Write("Hello")); 74 | }); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Netro/Netro.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A9853783-A155-4328-B4D0-2CDFB7BD8CA7} 8 | Exe 9 | Properties 10 | Netro 11 | Netro 12 | v3.5 13 | 512 14 | 15 | 16 | ..\ 17 | true 18 | 19 | 20 | AnyCPU 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | false 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /Netro/Netro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Netro 5 | { 6 | public class Netro 7 | { 8 | internal KeyValuePair Client; 9 | internal ReverseAsyncSocket ReverseClient; 10 | internal ReverseAsyncSocket ReverseServer; 11 | internal AsyncSocket Server; 12 | 13 | public void ServerToClient(AsyncSocket server, string host, int port, Action callback = null) 14 | { 15 | server.Connect(socket => 16 | { 17 | var client = new AsyncSocket(); 18 | if (callback != null) client.Connect(callback); 19 | client.Connect(host, port, () => SocketPipe.PipeSockets(socket, client)); 20 | }); 21 | } 22 | 23 | public void ReverseServerToServer(ReverseAsyncSocket reverseServer, AsyncSocket server) 24 | { 25 | var id = 0; 26 | reverseServer.Connect(reverseSocket => server.Connect(socket => 27 | { 28 | var tid = id++; 29 | reverseSocket.Read((sid, command, buffer) => { if (sid == tid) socket.Write(buffer); }); 30 | socket.Read((buffer, count) => 31 | reverseSocket.Write(tid, Command.Data, buffer, 0, count)); 32 | })); 33 | } 34 | 35 | public void ReverseClientToClient(ReverseAsyncSocket reverseClient, string host, int port) 36 | { 37 | var clients = new Dictionary(); 38 | 39 | reverseClient.Read((id, command, buffer) => 40 | { 41 | AsyncSocket client; 42 | if (!clients.TryGetValue(id, out client)) 43 | { 44 | client = new AsyncSocket(); 45 | client.Read((cbuffer, ccount) => reverseClient.Write(id, Command.Data, cbuffer, 0, ccount)); 46 | client.Connect(host, port); 47 | 48 | clients[id] = client; 49 | 50 | client.Connect(socket => client.Write(buffer)); 51 | } 52 | else 53 | { 54 | client.Write(buffer); 55 | } 56 | }); 57 | } 58 | 59 | public void SetClient(string host, int port) 60 | { 61 | Client = new KeyValuePair(host, port); 62 | 63 | if (Server == null) return; 64 | 65 | ServerToClient(Server, host, port); 66 | } 67 | 68 | public void ConnectReverse(string host, int port) 69 | { 70 | ReverseClient = new ReverseAsyncSocket(); 71 | ReverseClientToClient(ReverseClient, Client.Key, Client.Value); 72 | ReverseClient.Connect(host, port); 73 | } 74 | 75 | public void Listen(int port) 76 | { 77 | Server = new AsyncSocket(); 78 | Server.Listen(port); 79 | } 80 | 81 | public void ListenReverse(int port) 82 | { 83 | ReverseServer = new ReverseAsyncSocket(); 84 | ReverseServerToServer(ReverseServer, Server); 85 | ReverseServer.Listen(port); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /NetroTest/NetroTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BE6EC95C-1A1F-41FB-A3F5-3BAACA46117F} 8 | Library 9 | Properties 10 | NetroTest 11 | NetroTest 12 | v4.5 13 | 512 14 | 15 | ..\ 16 | true 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | false 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | 39 | ..\packages\NUnit.2.6.2\lib\nunit.framework.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | {a9853783-a155-4328-b4d0-2cdfb7bd8ca7} 65 | Netro 66 | 67 | 68 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /Netro/Output.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace Netro 7 | { 8 | public class Output 9 | { 10 | private static readonly string[] Logo = new[] 11 | { 12 | @" _......_ ", 13 | @" .'\|_|_|_|_/'.", 14 | @"/_\/` ____ `\/_\", 15 | @"|_| [ ## ] |_|", 16 | @"|_| | )||( | |_|", 17 | @"|_| \//()\\/ |_|", 18 | @"|_| \\__// |_|", 19 | @"|_| /`/ \`\ |_|", 20 | @"|_| \:____:/ |_|", 21 | @" =//====\\=", 22 | @" =//======\\=", 23 | @" =//========\\=" 24 | }; 25 | 26 | private static readonly Dictionary TypeFormats = new Dictionary 27 | 28 | { 29 | {NetroStatus.Type.Proxy, "Proxy ({0} -> {1}"}, 30 | {NetroStatus.Type.ReverseClient, "Reverse client ({0} -> {1})"}, 31 | {NetroStatus.Type.ReverseServer, "Reverse server ({0} -> {1})"} 32 | }; 33 | 34 | private readonly NetroStatus _status; 35 | 36 | public Output(NetroStatus netroStatus) 37 | { 38 | _status = netroStatus; 39 | 40 | Console.Clear(); 41 | Console.CursorVisible = false; 42 | Console.SetCursorPosition(0, 0); 43 | Console.Write("Loading..."); 44 | 45 | DrawLogo(); 46 | SetConnectedStatus(false); 47 | SetType(); 48 | _status.OnConnect(SetConnectedStatus); 49 | } 50 | 51 | private static void DrawLogo() 52 | { 53 | var x = Console.WindowWidth - Logo.First().Length - 1; 54 | var y = 1; 55 | Console.ForegroundColor = ConsoleColor.White; 56 | Logo.ToList().ForEach(line => 57 | { 58 | Console.SetCursorPosition(x, y); 59 | Console.Write(line); 60 | y++; 61 | }); 62 | Console.SetCursorPosition(x, y); 63 | Console.Write(" Netro {0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3)); 64 | } 65 | 66 | private static void ClearRect(int x, int y, int width, int height) 67 | { 68 | Console.ResetColor(); 69 | Console.CursorSize = height; 70 | Console.SetCursorPosition(x, y); 71 | Console.Write(string.Join("", Enumerable.Range(0, width).Select(s => " ").ToArray())); 72 | Console.CursorSize = 1; 73 | } 74 | 75 | public void SetType() 76 | { 77 | var type = string.Format(TypeFormats[_status.CurrentType], _status.From, _status.To); 78 | ClearRect(0, 0, Console.WindowWidth, 1); 79 | 80 | Console.ResetColor(); 81 | Console.SetCursorPosition(1, 3); 82 | Console.WriteLine("Type: {0}", type); 83 | } 84 | 85 | public void SetConnectedStatus(bool connected) 86 | { 87 | ClearRect(1, 1, 10, 1); 88 | Console.SetCursorPosition(1, 1); 89 | Console.BackgroundColor = connected ? ConsoleColor.Green : ConsoleColor.Yellow; 90 | Console.ForegroundColor = ConsoleColor.Black; 91 | var text = connected ? "CONNECTED" : "WAITING"; 92 | Console.WriteLine(text); 93 | } 94 | 95 | public void Reset() 96 | { 97 | Console.SetCursorPosition(0, 20); 98 | Console.ResetColor(); 99 | Console.CursorVisible = true; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /NetroTest/ReverseAsyncSocketTest.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using NUnit.Framework; 3 | using Netro; 4 | using NetroTest.Util; 5 | 6 | namespace NetroTest 7 | { 8 | [TestFixture] 9 | public class ReverseAsyncSocketTest : AsyncTest 10 | { 11 | [Test, Timeout(2000)] 12 | public void TestDisconnectClient() 13 | { 14 | Until((port, done) => 15 | { 16 | var server = new ReverseAsyncSocket(); 17 | server.Listen(port, socket => socket.Disconnect()); 18 | 19 | var count = 2; 20 | var client = new ReverseAsyncSocket(); 21 | client.Read((id, command, text) => { }); 22 | client.Disconnect(() => done(--count == 0)); 23 | client.Connect(Host, port, () => client.Disconnect(() => done(--count == 0))); 24 | }); 25 | } 26 | 27 | [Test, Timeout(2000)] 28 | public void TestPingClient() 29 | { 30 | Until((port, done) => 31 | { 32 | var server = new ReverseAsyncSocket(); 33 | server.Listen(port, socket => socket.Read((id, command, data) => 34 | { 35 | var text = Encoding.UTF8.GetString(data); 36 | Assert.AreEqual(7, id); 37 | Assert.AreEqual("Hello", text); 38 | done(); 39 | })); 40 | 41 | var client = new ReverseAsyncSocket(); 42 | client.Connect(Host, port, () => client.Write(7, "Hello")); 43 | }); 44 | } 45 | 46 | [Test, Timeout(2000)] 47 | public void TestPingPong() 48 | { 49 | Until((port, done) => 50 | { 51 | var server = new ReverseAsyncSocket(); 52 | server.Listen(port, socket => socket.ReadString((id, command, text) => 53 | { 54 | Assert.GreaterOrEqual(id, 42); 55 | Assert.LessOrEqual(id, 43); 56 | Assert.AreEqual("Hello", text); 57 | 58 | var res = (new[] {"eirikb", "world!"})[43 - id]; 59 | socket.Write(id + 1, res); 60 | })); 61 | 62 | var client = new ReverseAsyncSocket(); 63 | client.ReadString((id, command, text) => 64 | { 65 | Assert.GreaterOrEqual(id, 43); 66 | Assert.LessOrEqual(id, 44); 67 | if (id != 43) return; 68 | 69 | Assert.AreEqual("world!", text); 70 | client.Write(id, "Hello"); 71 | }); 72 | 73 | client.Connect(Host, port, () => 74 | { 75 | client.ReadString((id, command, text) => 76 | { 77 | Assert.GreaterOrEqual(id, 43); 78 | Assert.LessOrEqual(id, 44); 79 | if (id != 44) return; 80 | 81 | Assert.AreEqual("eirikb", text); 82 | done(); 83 | }); 84 | 85 | client.Write(42, "Hello"); 86 | }); 87 | }); 88 | } 89 | 90 | [Test, Timeout(2000)] 91 | public void TestServerDisconnect() 92 | { 93 | Until((port, done) => 94 | { 95 | var server = new ReverseAsyncSocket(); 96 | server.Listen(port, socket => 97 | { 98 | socket.Disconnect(done); 99 | socket.Read((id, command, text) => { }); 100 | }); 101 | 102 | var client = new ReverseAsyncSocket(); 103 | client.Connect("localhost", port, client.Disconnect); 104 | }); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /Netro/ReverseAsyncSocket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Netro 5 | { 6 | public enum Command : byte 7 | { 8 | Connect = 1, 9 | Data = 2, 10 | Disconnect = 3 11 | } 12 | 13 | public class ReverseAsyncSocket 14 | { 15 | private readonly List> _callbackConnect; 16 | private readonly List> _callbackRead; 17 | private readonly AsyncSocket _socket; 18 | private Command _command; 19 | private int _currentId; 20 | private bool _reading; 21 | private int _waitingFor; 22 | 23 | public ReverseAsyncSocket() 24 | { 25 | _socket = new AsyncSocket(); 26 | _callbackRead = new List>(); 27 | _callbackConnect = new List>(); 28 | } 29 | 30 | private ReverseAsyncSocket(AsyncSocket socket) : this() 31 | { 32 | _socket = socket; 33 | } 34 | 35 | public bool Connected 36 | { 37 | get { return _socket.Connected; } 38 | } 39 | 40 | public int Port 41 | { 42 | get { return _socket.Port; } 43 | } 44 | 45 | public string Host 46 | { 47 | get { return _socket.Host; } 48 | } 49 | 50 | public void Listen(int port) 51 | { 52 | _socket.Listen(port); 53 | } 54 | 55 | public void Listen(int port, Action callback) 56 | { 57 | Connect(callback); 58 | _socket.Listen(port); 59 | } 60 | 61 | public void Connect(Action callback) 62 | { 63 | _callbackConnect.Add(callback); 64 | if (_callbackConnect.Count > 1) return; 65 | 66 | _socket.Connect(socket => 67 | { 68 | var reverseSocket = new ReverseAsyncSocket(socket); 69 | _callbackConnect.ForEach(cb => cb(reverseSocket)); 70 | }); 71 | } 72 | 73 | public void Connect(string host, int port) 74 | { 75 | _socket.Connect(host, port); 76 | } 77 | 78 | public void Connect(string host, int port, Action callback) 79 | { 80 | _socket.Connect(host, port, callback); 81 | } 82 | 83 | public void Disconnect(Action callback) 84 | { 85 | _socket.Disconnect(callback); 86 | } 87 | 88 | public void Disconnect() 89 | { 90 | _socket.Disconnect(); 91 | } 92 | 93 | 94 | public void Read(Action callback) 95 | { 96 | _callbackRead.Add(callback); 97 | 98 | if (_reading) return; 99 | _reading = true; 100 | 101 | _socket.Read((buffer, read) => 102 | { 103 | var pos = 0; 104 | while (pos < read) 105 | { 106 | if (_waitingFor == 0) 107 | { 108 | _currentId = BitConverter.ToInt32(buffer, pos); 109 | _waitingFor = BitConverter.ToInt32(buffer, pos + 4); 110 | _command = (Command) buffer[pos + 8]; 111 | pos += 9; 112 | } 113 | 114 | var count = read - pos; 115 | if (count > _waitingFor) count = _waitingFor; 116 | 117 | var data = new byte[count]; 118 | Array.Copy(buffer, pos, data, 0, count); 119 | 120 | _callbackRead.ForEach(cb => cb(_currentId, _command, data)); 121 | 122 | pos += count; 123 | _waitingFor -= count; 124 | } 125 | }); 126 | } 127 | 128 | public void Write(int id, Command command, byte[] buffer, int index, int count) 129 | { 130 | var newBuffer = new byte[count + 9]; 131 | BitConverter.GetBytes(id).CopyTo(newBuffer, 0); 132 | BitConverter.GetBytes(count).CopyTo(newBuffer, 4); 133 | newBuffer[8] = (byte) command; 134 | Array.Copy(buffer, index, newBuffer, 9, count); 135 | _socket.Write(newBuffer, 0, newBuffer.Length); 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /NetroTest/NetroTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Netro; 4 | using NetroTest.Util; 5 | 6 | namespace NetroTest 7 | { 8 | [TestFixture] 9 | public class NetroTest : AsyncTest 10 | { 11 | [Test, Timeout(2000)] 12 | public void ReverseClientToClient() 13 | { 14 | Until((port, done) => 15 | { 16 | var serverPort = port + 1; 17 | 18 | var reverseServer = new ReverseAsyncSocket(); 19 | var server = new AsyncSocket(); 20 | 21 | var reverseClient = new ReverseAsyncSocket(); 22 | var netro = new Netro.Netro(); 23 | 24 | netro.ReverseClientToClient(reverseClient, Host, serverPort); 25 | 26 | reverseServer.Listen(port); 27 | server.Listen(serverPort); 28 | 29 | reverseClient.Connect(Host, port, () => { }); 30 | 31 | server.Connect(socket => socket.Read(text => 32 | { 33 | Assert.AreEqual("Hello", text); 34 | socket.Write("world!"); 35 | })); 36 | 37 | reverseServer.Connect(socket => 38 | { 39 | socket.ReadString((id, command, text) => 40 | { 41 | Assert.AreEqual("world!", text); 42 | done(); 43 | }); 44 | socket.Write(42, "Hello"); 45 | }); 46 | }); 47 | } 48 | 49 | [Test, Timeout(2000)] 50 | public void TestReverseServerToServer() 51 | { 52 | Until((port, done) => 53 | { 54 | var reverseServer = new ReverseAsyncSocket(); 55 | var server = new AsyncSocket(); 56 | 57 | var reverseClient = new ReverseAsyncSocket(); 58 | var client = new AsyncSocket(); 59 | 60 | var netro = new Netro.Netro(); 61 | var serverPort = port + 1; 62 | 63 | reverseServer.Listen(port); 64 | server.Listen(serverPort); 65 | 66 | netro.ReverseServerToServer(reverseServer, server); 67 | 68 | reverseClient.ReadString((tid, command, text) => 69 | { 70 | Assert.AreEqual("Hello", text); 71 | reverseClient.Write(tid, "world!"); 72 | }); 73 | client.Read(text => 74 | { 75 | Assert.AreEqual("world!", text); 76 | done(); 77 | }); 78 | 79 | reverseClient.Connect(Host, port, 80 | () => 81 | { 82 | client.Connect(Host, serverPort, () => 83 | { 84 | client.Write("Hello"); 85 | }); 86 | }); 87 | }); 88 | } 89 | 90 | [Test, Timeout(2000)] 91 | public void TestServerToClient() 92 | { 93 | Until((port, done) => 94 | { 95 | var portTestServer = port; 96 | var portServer = portTestServer + 1; 97 | 98 | var testServer = new AsyncSocket(); 99 | var server = new AsyncSocket(); 100 | var client = new AsyncSocket(); 101 | var netro = new Netro.Netro(); 102 | 103 | server.Listen(portServer); 104 | netro.ServerToClient(server, Host, portTestServer); 105 | 106 | testServer.Listen(portTestServer, socket => socket.Read(text => 107 | { 108 | Assert.AreEqual("Hello", text); 109 | socket.Write("world!"); 110 | })); 111 | 112 | client.Connect(Host, portServer, () => 113 | { 114 | client.Read(text => 115 | { 116 | Assert.AreEqual("world!", text); 117 | done(); 118 | }); 119 | client.Write("Hello"); 120 | }); 121 | }); 122 | } 123 | 124 | [Test, Timeout(2000)] 125 | public void TestServerToClientDisconnect() 126 | { 127 | Until((port, done) => 128 | { 129 | var portTestServer = port; 130 | var portServer = portTestServer + 1; 131 | 132 | var testServer = new AsyncSocket(); 133 | var server = new AsyncSocket(); 134 | var client = new AsyncSocket(); 135 | var netro = new Netro.Netro(); 136 | 137 | server.Listen(portServer); 138 | netro.ServerToClient(server, Host, portTestServer); 139 | 140 | testServer.Listen(portTestServer, socket => socket.Disconnect()); 141 | 142 | client.Connect(Host, portServer, () => 143 | { 144 | client.Read(text => { }); 145 | client.Disconnect(done); 146 | }); 147 | }); 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /Netro/AsyncSocket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | 7 | namespace Netro 8 | { 9 | public class AsyncSocket 10 | { 11 | private const int BufferSize = 32768; 12 | private readonly List> _callbackConnect; 13 | private readonly List _callbackDisconnect; 14 | private readonly List> _callbackPreconnect; 15 | private readonly List> _callbackRead; 16 | private readonly Socket _socket; 17 | protected NetworkStream Stream; 18 | 19 | public AsyncSocket() 20 | { 21 | _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 22 | _callbackPreconnect = new List>(); 23 | _callbackConnect = new List>(); 24 | _callbackDisconnect = new List(); 25 | _callbackRead = new List>(); 26 | } 27 | 28 | private AsyncSocket(Socket socket) : this() 29 | { 30 | Connected = true; 31 | _socket = socket; 32 | Stream = new NetworkStream(_socket); 33 | } 34 | 35 | public int Port { get; private set; } 36 | public string Host { get; private set; } 37 | 38 | public bool Connected { get; private set; } 39 | 40 | public virtual void Connect(Action callback) 41 | { 42 | _callbackConnect.Add(callback); 43 | } 44 | 45 | public virtual void Preconnect(Func callback) 46 | { 47 | _callbackPreconnect.Add(callback); 48 | } 49 | 50 | public virtual void Connect(string host, int port, Action callback) 51 | { 52 | _callbackConnect.Add(socket => callback()); 53 | Connect(host, port); 54 | } 55 | 56 | public virtual void Connect(string host, int port) 57 | { 58 | Host = host; 59 | Port = port; 60 | 61 | _socket.BeginConnect(host, port, ar => 62 | { 63 | try 64 | { 65 | _socket.EndConnect(ar); 66 | Stream = new NetworkStream(_socket); 67 | 68 | Connected = true; 69 | if (_callbackRead.Count > 0) BeginRead(); 70 | _callbackConnect.ForEach(callback => callback(this)); 71 | } 72 | catch 73 | { 74 | _callbackDisconnect.ForEach(callback => callback()); 75 | } 76 | }, _socket); 77 | } 78 | 79 | private void BeginRead() 80 | { 81 | var buffer = new byte[BufferSize]; 82 | if (!_socket.Connected) 83 | { 84 | _callbackDisconnect.ForEach(callback => callback()); 85 | return; 86 | } 87 | 88 | Stream.BeginRead(buffer, 0, buffer.Length, ar => 89 | { 90 | try 91 | { 92 | var read = Stream.EndRead(ar); 93 | if (read == 0) _socket.Disconnect(false); 94 | else _callbackRead.ForEach(callback => callback(buffer, read)); 95 | 96 | BeginRead(); 97 | } 98 | catch 99 | { 100 | _callbackDisconnect.ForEach(callback => callback()); 101 | } 102 | }, Stream); 103 | } 104 | 105 | public virtual void Listen(int port) 106 | { 107 | Port = port; 108 | _socket.Bind(new IPEndPoint(0, port)); 109 | _socket.Listen(int.MaxValue); 110 | BeginAccept(); 111 | } 112 | 113 | public virtual void Listen(int port, Action callback) 114 | { 115 | _callbackConnect.Add(callback); 116 | Listen(port); 117 | } 118 | 119 | private void BeginAccept() 120 | { 121 | _socket.BeginAccept(ar => 122 | { 123 | try 124 | { 125 | var socket = _socket.EndAccept(ar); 126 | if (!_callbackPreconnect.All(callback => callback())) 127 | { 128 | socket.Close(); 129 | } 130 | else 131 | { 132 | var asyncSocket = new AsyncSocket(socket); 133 | _callbackConnect.ForEach(callback => callback(asyncSocket)); 134 | } 135 | BeginAccept(); 136 | } 137 | catch 138 | { 139 | _callbackDisconnect.ForEach(callback => callback()); 140 | } 141 | }, _socket); 142 | } 143 | 144 | public virtual void Read(Action callback) 145 | { 146 | _callbackRead.Add(callback); 147 | if (Connected) BeginRead(); 148 | } 149 | 150 | public virtual void Write(byte[] data) 151 | { 152 | Write(data, data.Length); 153 | } 154 | 155 | public virtual void Write(byte[] data, int count) 156 | { 157 | Write(data, 0, count); 158 | } 159 | 160 | public virtual void Write(byte[] data, int offset, int count) 161 | { 162 | Stream.BeginWrite(data, offset, count, ar => Stream.EndWrite(ar), Stream); 163 | } 164 | 165 | public void Disconnect(Action callback) 166 | { 167 | _callbackDisconnect.Add(callback); 168 | } 169 | 170 | public void Disconnect() 171 | { 172 | if (_socket != null) _socket.Close(); 173 | } 174 | } 175 | } -------------------------------------------------------------------------------- /NetroTest/AsyncSocketTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using NUnit.Framework; 5 | using Netro; 6 | using NetroTest.Util; 7 | 8 | namespace NetroTest 9 | { 10 | [TestFixture] 11 | public class AsyncSocketTest : AsyncTest 12 | { 13 | [Test, Timeout(2000000)] 14 | public void TestClientDisconnect() 15 | { 16 | Until((port, done) => 17 | { 18 | var server = new AsyncSocket(); 19 | server.Listen(port, socket => 20 | { 21 | socket.Disconnect(done); 22 | socket.Read(text => { }); 23 | }); 24 | 25 | var client = new AsyncSocket(); 26 | client.Connect(Host, port, client.Disconnect); 27 | }); 28 | } 29 | 30 | [Test, Timeout(2000)] 31 | public void TestClientPingDisconnect() 32 | { 33 | Until((port, done) => 34 | { 35 | var server = new AsyncSocket(); 36 | server.Listen(port, socket => socket.Read(text => 37 | { 38 | Assert.AreEqual("Hello, world!", text); 39 | socket.Disconnect(); 40 | })); 41 | 42 | var client = new AsyncSocket(); 43 | client.Disconnect(done); 44 | client.Connect(Host, port, () => client.Write("Hello, world!")); 45 | client.Read(text => { }); 46 | }); 47 | } 48 | 49 | [Test, Timeout(5000)] 50 | public void TestMassiveDisconnect() 51 | { 52 | Until((port, done) => 53 | { 54 | const int clientCount = 100; 55 | var count = 0; 56 | 57 | var server = new AsyncSocket(); 58 | server.Listen(port, socket => 59 | { 60 | count++; 61 | socket.Disconnect(() => count--); 62 | socket.Read(text => { }); 63 | }); 64 | 65 | var clients = Enumerable.Range(0, clientCount).Select(i => 66 | { 67 | var client = new AsyncSocket(); 68 | client.Connect(Host, port); 69 | return client; 70 | }).ToList(); 71 | 72 | while (count < clientCount) Thread.Sleep(100); 73 | 74 | Assert.AreEqual(clientCount, count); 75 | 76 | clients.ForEach(client => client.Disconnect()); 77 | while (count > 0) Thread.Sleep(100); 78 | 79 | Assert.AreEqual(0, count); 80 | done(); 81 | }); 82 | } 83 | 84 | [Test, Timeout(2000)] 85 | public void TestPing() 86 | { 87 | Until((port, done) => 88 | { 89 | var server = new AsyncSocket(); 90 | server.Listen(port, socket => socket.Read(text => 91 | { 92 | Assert.AreEqual("Hello, world!", text); 93 | done(); 94 | })); 95 | 96 | var client = new AsyncSocket(); 97 | client.Connect(Host, port, () => client.Write("Hello, world!")); 98 | }); 99 | } 100 | 101 | [Test, Timeout(2000)] 102 | public void TestPingPong() 103 | { 104 | Until((port, done) => 105 | { 106 | var server = new AsyncSocket(); 107 | server.Listen(port, socket => socket.Read(text => 108 | { 109 | Assert.AreEqual("Hello", text); 110 | socket.Write("World!"); 111 | })); 112 | 113 | var client = new AsyncSocket(); 114 | client.Connect(Host, port, () => client.Write("Hello")); 115 | Thread.Sleep(500); 116 | client.Read(text => 117 | { 118 | Assert.AreEqual("World!", text); 119 | done(); 120 | }); 121 | }); 122 | } 123 | 124 | [Test, Timeout(2000)] 125 | public void TestPreconnect() 126 | { 127 | Until((port, done) => 128 | { 129 | var count = 0; 130 | var clients = 0; 131 | var server = new AsyncSocket(); 132 | server.Listen(port); 133 | server.Preconnect(() => 134 | { 135 | count++; 136 | return count%2 == 0; 137 | }); 138 | server.Connect(socket => 139 | { 140 | clients++; 141 | if (count < 10) return; 142 | Assert.AreEqual(10, count); 143 | Assert.AreEqual(5, clients); 144 | done(); 145 | }); 146 | 147 | for (var i = 0; i < 10; i++) 148 | { 149 | var client = new AsyncSocket(); 150 | client.Connect(Host, port); 151 | } 152 | }); 153 | } 154 | 155 | [Test, Timeout(2000)] 156 | public void TestServerDisconnect() 157 | { 158 | Until((port, done) => 159 | { 160 | var server = new AsyncSocket(); 161 | server.Listen(port, socket => socket.Disconnect()); 162 | 163 | var client = new AsyncSocket(); 164 | client.Disconnect(done); 165 | client.Connect(Host, port); 166 | client.Read(text => {}); 167 | }); 168 | } 169 | 170 | [Test, Timeout(2000)] 171 | public void TestServerPongReadAfterConnect() 172 | { 173 | Until((port, done) => 174 | { 175 | var server = new AsyncSocket(); 176 | server.Listen(port, socket => socket.Write("Hello")); 177 | 178 | var client = new AsyncSocket(); 179 | client.Connect(Host, port); 180 | client.Read(text => 181 | { 182 | Assert.AreEqual("Hello", text); 183 | done(); 184 | }); 185 | }); 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(MSBuildProjectDirectory)\..\ 7 | 8 | 9 | false 10 | 11 | 12 | false 13 | 14 | 15 | true 16 | 17 | 18 | false 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 33 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 34 | 35 | 36 | 37 | 38 | $(SolutionDir).nuget 39 | packages.config 40 | 41 | 42 | 43 | 44 | $(NuGetToolsPath)\NuGet.exe 45 | @(PackageSource) 46 | 47 | "$(NuGetExePath)" 48 | mono --runtime=v4.0.30319 $(NuGetExePath) 49 | 50 | $(TargetDir.Trim('\\')) 51 | 52 | -RequireConsent 53 | -NonInteractive 54 | 55 | 56 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir) " 57 | $(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 58 | 59 | 60 | 61 | RestorePackages; 62 | $(BuildDependsOn); 63 | 64 | 65 | 66 | 67 | $(BuildDependsOn); 68 | BuildPackage; 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | 97 | 99 | 100 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 132 | 133 | 134 | 135 | --------------------------------------------------------------------------------