├── .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 | 
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 |
--------------------------------------------------------------------------------