Skip to content

Commit 633914c

Browse files
committed
Logging update, and adding a pre-connection ping.
1 parent 7dfd126 commit 633914c

12 files changed

+246
-74
lines changed

horizon-cli/Program.cs

+23-9
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,14 @@ public class Options
5454
static HorizonServer server;
5555
static HorizonClient client;
5656

57+
5758
static void Main(string[] args)
5859
{
60+
#if DEBUG
61+
Logger.Level = Logger.LoggingLevel.Debug;
62+
#endif
5963
Console.WriteLine(
60-
" |-------------------------------------------------------------------------------------| \n" +
64+
" |-------------------------------------------------------------------------------------| \n" +
6165
" | Horizon | High Performance WebSocket Tunnels | \n" +
6266
" | [To view help, execute Horizon with --help] | \n" +
6367
" | View the project at (https://github.com/encodeous/horizon) | \n" +
@@ -150,6 +154,7 @@ static void Main(string[] args)
150154
Console.WriteLine($"Unrecognized Url Scheme \"{s}\". Valid schemes are (http/s, ws/s)");
151155
return;
152156
}
157+
153158
if (o.PortMap == null)
154159
{
155160
Console.WriteLine("Horizon Client requires a port map.");
@@ -163,26 +168,35 @@ static void Main(string[] args)
163168
o.Token = "horizon";
164169
}
165170

166-
string[] k = o.PortMap.Split(":");
167-
var lep = new IPEndPoint(IPAddress.Any, int.Parse(k[0]));
171+
var k = o.PortMap.Split(":");
168172

169-
client = new HorizonClient(new Uri(o.Client), k[1], int.Parse(k[2]));
170-
if (o.BufferSize != 0)
173+
var localEp = new IPEndPoint(IPAddress.Any, int.Parse(k[0]));
174+
175+
client = new HorizonClient(new Uri(o.Client), k[1], int.Parse(k[2]), o.Username, o.Token);
176+
177+
var ping = client.Ping();
178+
179+
if (ping.Success)
171180
{
172-
client.OpenTunnel(lep, o.Username, o.Token,
173-
new HorizonOptions() {DefaultBufferSize = o.BufferSize});
181+
Console.WriteLine($"Pinged server, Latency: ({ping.Latency.TotalMilliseconds} ms).");
174182
}
175183
else
176184
{
177-
client.OpenTunnel(lep, o.Username, o.Token, new HorizonOptions());
185+
Console.WriteLine($"Could not ping server, double check the username/token or the server uri.");
186+
return;
178187
}
179188

189+
client.OpenTunnel(localEp,
190+
o.BufferSize != 0
191+
? new HorizonOptions {DefaultBufferSize = o.BufferSize}
192+
: new HorizonOptions());
180193
Console.WriteLine($"Horizon started | {o.Username}@ [{o.PortMap}] = > [{o.Client}].");
181194
Thread.Sleep(-1);
182195
}
183196
else
184197
{
185-
Console.WriteLine(" - [Press Any Key to exit...] - ");
198+
Console.WriteLine(
199+
" - [Press Any Key to exit...] - ");
186200
Console.ReadKey();
187201
}
188202
});
+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"profiles": {
33
"horizon-cli": {
4-
"commandName": "Project"
4+
"commandName": "Project",
5+
"commandLineArgs": "-c ws://localhost:1234 -m 1233:localhost:1235"
56
}
67
}
78
}

horizon.sln

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Global
1515
Release|Any CPU = Release|Any CPU
1616
EndGlobalSection
1717
GlobalSection(ProjectConfigurationPlatforms) = postSolution
18-
{20B42686-5206-4703-98A1-2D7D89E7667E}.Debug|Any CPU.ActiveCfg = Release|Any CPU
19-
{20B42686-5206-4703-98A1-2D7D89E7667E}.Debug|Any CPU.Build.0 = Release|Any CPU
18+
{20B42686-5206-4703-98A1-2D7D89E7667E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19+
{20B42686-5206-4703-98A1-2D7D89E7667E}.Debug|Any CPU.Build.0 = Debug|Any CPU
2020
{20B42686-5206-4703-98A1-2D7D89E7667E}.Release|Any CPU.ActiveCfg = Release|Any CPU
2121
{20B42686-5206-4703-98A1-2D7D89E7667E}.Release|Any CPU.Build.0 = Release|Any CPU
2222
{4708480A-08AF-44C8-A653-E7545FA34DA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

horizon/ConnectionValidator.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public HorizonResponse HandleClientRequest(HorizonRequest clientRequest)
2929
var ts = DateTime.UtcNow - clientRequest.RequestTime;
3030
if (ts >= TimeSpan.FromMinutes(2))
3131
{
32-
$"{clientRequest.UserId} has failed to connect, the access token is expired".Log();
32+
$"{clientRequest.UserId} has failed to connect, the access token is expired".Log(Logger.LoggingLevel.Info);
3333
return null;
3434
}
3535

@@ -54,7 +54,7 @@ public HorizonResponse HandleClientRequest(HorizonRequest clientRequest)
5454
}
5555
else
5656
{
57-
$"{clientRequest.UserId} has failed to connect, the access token is invalid".Log();
57+
$"{clientRequest.UserId} has failed to connect, the access token is invalid".Log(Logger.LoggingLevel.Info);
5858
return null;
5959
}
6060
}
@@ -67,7 +67,7 @@ public HorizonResponse HandleClientRequest(HorizonRequest clientRequest)
6767
}
6868

6969
}
70-
$"{clientRequest.UserId} has failed to connect, username not found".Log();
70+
$"{clientRequest.UserId} has failed to connect, username not found".Log(Logger.LoggingLevel.Info);
7171
return null;
7272
}
7373

@@ -77,7 +77,7 @@ private bool VerifyClientPermissions(UserPermission user, HorizonRequest clientR
7777
if (!user.AllowAnyPort && (!user.AllowedRemotePorts.Contains(clientRequest.RequestedPort) ||
7878
user.DisallowedRemotePorts.Contains(clientRequest.RequestedPort)))
7979
{
80-
$"{clientRequest.UserId} has failed to connect, unauthorized port [{clientRequest.RequestedHost}:{clientRequest.RequestedPort}]".Log();
80+
$"{clientRequest.UserId} has failed to connect, unauthorized port [{clientRequest.RequestedHost}:{clientRequest.RequestedPort}]".Log(Logger.LoggingLevel.Info);
8181
return false;
8282
}
8383

@@ -94,13 +94,13 @@ private bool VerifyClientPermissions(UserPermission user, HorizonRequest clientR
9494
user.DisallowedRemoteServers.Contains(domain)))
9595
{
9696

97-
$"{clientRequest.UserId} has failed to connect, unauthorized host [{clientRequest.RequestedHost}:{clientRequest.RequestedPort}]".Log();
97+
$"{clientRequest.UserId} has failed to connect, unauthorized host [{clientRequest.RequestedHost}:{clientRequest.RequestedPort}]".Log(Logger.LoggingLevel.Info);
9898
return false;
9999
}
100100
}
101101
catch
102102
{
103-
$"{clientRequest.UserId} has failed to connect, unauthorized host [{clientRequest.RequestedHost}:{clientRequest.RequestedPort}]".Log();
103+
$"{clientRequest.UserId} has failed to connect, unauthorized host [{clientRequest.RequestedHost}:{clientRequest.RequestedPort}]".Log(Logger.LoggingLevel.Info);
104104
return false;
105105
}
106106
}
@@ -171,6 +171,7 @@ public static bool VerifyServerResponse(string token, HorizonRequest clientReque
171171
}
172172
}
173173
}
174+
174175
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
175176
internal static unsafe bool FastCmp(byte[] ba, byte[] bb)
176177
{

horizon/HorizonClient.cs

+81-33
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,32 @@ namespace horizon
1212
public class HorizonClient
1313
{
1414
public IoManager ioManager;
15-
private string tunnelDestination;
16-
private int tunnelDestinationPort;
17-
private Uri horizonHost;
15+
private string _tunnelDestination;
16+
private int _tunnelDestinationPort;
17+
private Uri _horizonHost;
1818
private bool stopFlag = false;
19-
private Socket localSock;
19+
private Socket _localSock;
20+
private string _userId;
21+
private string _userToken;
2022

21-
public HorizonClient(Uri horizonHost, string destination, int port)
23+
public HorizonClient(Uri horizonHost, string destination, int port, string userId, string userToken)
2224
{
23-
this.horizonHost = horizonHost;
24-
tunnelDestination = destination;
25-
tunnelDestinationPort = port;
25+
_userId = userId;
26+
_userToken = userToken;
27+
_horizonHost = horizonHost;
28+
_tunnelDestination = destination;
29+
_tunnelDestinationPort = port;
30+
}
31+
/// <summary>
32+
/// Pings the server to check credentials and latency
33+
/// </summary>
34+
/// <returns></returns>
35+
public PingResult Ping()
36+
{
37+
WStream client = new WStream();
38+
var connection = client.Connect(_horizonHost, CancellationToken.None);
39+
var s = AuthenticatePing(connection, out var latency);
40+
return new PingResult(){Latency = latency, Success = s};
2641
}
2742

2843
/// <summary>
@@ -32,13 +47,13 @@ public HorizonClient(Uri horizonHost, string destination, int port)
3247
/// <param name="userId"></param>
3348
/// <param name="token"></param>
3449
/// <param name="ioConfig"></param>
35-
public void OpenTunnel(EndPoint localBinding, string userId, string token, HorizonOptions ioConfig)
50+
public void OpenTunnel(EndPoint localBinding, HorizonOptions ioConfig)
3651
{
3752
ioManager = new IoManager(ioConfig);
38-
localSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
39-
localSock.Bind(localBinding);
40-
localSock.Listen(1000);
41-
new Thread(() => SocketListener(userId, token)).Start();
53+
_localSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
54+
_localSock.Bind(localBinding);
55+
_localSock.Listen(1000);
56+
new Thread(SocketListener).Start();
4257
}
4358

4459
/// <summary>
@@ -49,49 +64,82 @@ public void CloseTunnel()
4964
ioManager.Stop();
5065
}
5166

52-
private void SocketListener(string userId, string token)
67+
private void SocketListener()
5368
{
5469
while (!stopFlag)
5570
{
56-
var sock = localSock.Accept();
57-
Connect(userId, token, sock);
71+
try
72+
{
73+
var sock = _localSock.Accept();
74+
Connect( sock);
75+
}
76+
catch
77+
{
78+
"Failed to accept local client".Log(Logger.LoggingLevel.Severe);
79+
}
5880
}
5981
}
6082

61-
private void Connect(string userId, string token, Socket _localSock)
83+
private void Connect(Socket localSock)
6284
{
63-
WStream client = new WStream();
64-
var connection = client.Connect(horizonHost, CancellationToken.None);
65-
if (Authenticate(userId, token, connection, out var req))
85+
try
6686
{
67-
ioManager.AddIoConnection(connection, _localSock, req);
87+
WStream client = new WStream();
88+
var connection = client.Connect(_horizonHost, CancellationToken.None);
89+
if (Authenticate(connection, out var req))
90+
{
91+
ioManager.AddIoConnection(connection, localSock, req);
92+
}
93+
else
94+
{
95+
connection.Close();
96+
localSock.Disconnect(false);
97+
}
6898
}
69-
else
99+
catch
70100
{
71-
connection.Close();
72-
_localSock.Disconnect(false);
101+
localSock.Disconnect(false);
102+
throw;
73103
}
74104
}
75105

76-
private bool Authenticate(string userId, string token, WsConnection connection, out HorizonRequest req)
106+
private bool Authenticate(WsConnection connection, out HorizonRequest req)
77107
{
78108
var request = new HorizonRequest
79109
{
80-
RequestedHost = tunnelDestination,
81-
RequestedPort = tunnelDestinationPort,
82-
UserId = userId.ToLower().Trim(),
110+
RequestedHost = _tunnelDestination,
111+
RequestedPort = _tunnelDestinationPort,
112+
UserId = _userId.ToLower().Trim(),
83113
RequestTime = DateTime.UtcNow,
84114
};
85-
if (ProtocolManager.PerformClientHandshake(connection, token, request))
115+
req = request;
116+
if (ProtocolManager.PerformClientHandshake(connection, _userToken, request))
86117
{
87-
req = request;
88118
return true;
89119
}
90-
else
120+
return false;
121+
}
122+
123+
private bool AuthenticatePing(WsConnection connection, out TimeSpan latency)
124+
{
125+
var request = new HorizonRequest
126+
{
127+
RequestedHost = _tunnelDestination,
128+
RequestedPort = _tunnelDestinationPort,
129+
UserId = _userId.ToLower().Trim(),
130+
RequestTime = DateTime.UtcNow,
131+
PingPacket = true
132+
};
133+
var response = ProtocolManager.PerformClientPing(connection, _userToken, request);
134+
135+
latency = response - request.RequestTime;
136+
137+
if (response != DateTime.MinValue)
91138
{
92-
req = request;
93-
return false;
139+
return true;
94140
}
141+
142+
return false;
95143
}
96144
}
97145
}

horizon/HorizonRequest.cs

+8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ public class HorizonRequest
2424
/// </summary>
2525
public byte[] Salt;
2626

27+
/// <summary>
28+
/// The time the request was generated
29+
/// </summary>
2730
public DateTime RequestTime;
31+
32+
/// <summary>
33+
/// Identifies as true if the packet is a ping request
34+
/// </summary>
35+
public bool PingPacket;
2836
}
2937
}

0 commit comments

Comments
 (0)