Skip to content

Commit

Permalink
Added asynchronous ServerTester class, updated network code
Browse files Browse the repository at this point in the history
  • Loading branch information
ewrogers committed Apr 19, 2015
1 parent 1048abd commit 76de368
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 134 deletions.
88 changes: 0 additions & 88 deletions Spark/Models/BasicVersionTester.cs

This file was deleted.

16 changes: 0 additions & 16 deletions Spark/Models/IVersionTester.cs

This file was deleted.

8 changes: 8 additions & 0 deletions Spark/Net/NetworkPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class NetworkPacket : INetworkPacket
public virtual IReadOnlyList<byte> Data { get; protected set; }
#endregion

#region Constructors
public NetworkPacket(byte signature, short size, byte command, IEnumerable<byte> data = null)
{
this.Signature = signature;
Expand All @@ -38,6 +39,13 @@ public NetworkPacket(byte signature, short size, byte command, byte[] data, int
this.Data = new ArraySegment<byte>(data, offset, count).ToList();
}

public NetworkPacket(params byte[] packet)
: this(packet, 0, packet.Length) { }

public NetworkPacket(byte[] packet, int offset, int count)
: this(packet[offset], IntegerExtender.MakeWord(packet[offset + 2], packet[offset + 1]), packet[offset + 3], packet, HeaderSize, count - HeaderSize) { }
#endregion

public override string ToString()
{
// Returns a hex string of the packet ("AA 00 03 FF ...")
Expand Down
3 changes: 2 additions & 1 deletion Spark/Net/NetworkPacketBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace Spark.Net
{
// This class buffers data bytes to create network packets that can be dequeued
public sealed class NetworkPacketBuffer
{
static readonly int BufferSize = 4096; // 4KB
Expand Down Expand Up @@ -55,7 +56,7 @@ void ProcessPacketBuffer()
{
// Get the expected size of the packet
var size = IntegerExtender.MakeWord(buffer[2], buffer[1]);
var packetSize = size + 2;
var packetSize = size + 3;

// If the entire packet has not been buffered, stop processing until more data arrives
if (packetSize > buffer.Count)
Expand Down
60 changes: 55 additions & 5 deletions Spark/Net/ServerTester.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
Expand All @@ -12,18 +14,23 @@ namespace Spark.Net
public class ServerTester : IServerTester
{
static readonly int BufferSize = 4096; // 4KB
static readonly string ServerWelcomeMessage = "CONNECTED SERVER\n";

bool isDisposed;

protected Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
protected Socket socket;
protected NetworkPacketBuffer packetBuffer = new NetworkPacketBuffer();
protected byte[] receiveBuffer = new byte[BufferSize];
protected byte[] sendBuffer = new byte[BufferSize];

public ServerTester() { }
public ServerTester()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.ReceiveTimeout = 1000;
}

#region IServerTester Methods
public virtual Task ConnectToServerAsync(IPAddress ipAddress, int port)
public virtual async Task ConnectToServerAsync(IPAddress ipAddress, int port)
{
if (ipAddress == null)
throw new ArgumentNullException("ipAddress");
Expand All @@ -32,7 +39,28 @@ public virtual Task ConnectToServerAsync(IPAddress ipAddress, int port)
throw new ArgumentOutOfRangeException("Port must be greater than zero");

CheckIfDisposed();
return socket.ConnectAsync(ipAddress, port);

// Connect to the server
await socket.ConnectAsync(ipAddress, port);

// Receive the initial welcome message packet
var welcomePacket = await ReceiveNextPacket();
Debug.WriteLine(string.Format("ReceivedPacket: {0}", welcomePacket));

// Get the welcome message ASCII bytes, skipping the first ESC control character (0x1B)
var welcomeString = Encoding.ASCII.GetString(welcomePacket.Data.Skip(1).ToArray());

// Check that the welcome message equals the expected string value
if (!string.Equals(welcomeString, ServerWelcomeMessage, StringComparison.Ordinal))
throw new Exception("A service was running at the specified location, but it doesn't appear to be a Darkages server.");

// Create a response packet
var responsePacket = new NetworkPacket(0xAA, 0x00, 0x0A, 0x62, 0x00, 0x34, 0x00, 0x0A, 0x88, 0x6E, 0x59, 0x59, 0x75);
var responsePacketData = responsePacket.ToArray();

// Send the response data to the server
await socket.SendAsync(responsePacketData, 0, responsePacketData.Length);
Debug.WriteLine(string.Format("SentPacket: {0}", responsePacket));
}

public virtual async Task<bool> CheckClientVersionCodeAsync(int versionCode)
Expand All @@ -42,8 +70,30 @@ public virtual async Task<bool> CheckClientVersionCodeAsync(int versionCode)

CheckIfDisposed();

var packet = await ReceiveNextPacket();
// Create a client version packet
var version = (short)versionCode;
var versionPacket = new NetworkPacket(0xAA, 0x00, 0x06, 0x00, version.HiByte(), version.LoByte(), 0x4C, 0x4B, 0x00);
var versionPacketData = versionPacket.ToArray();

// Send the version packet to the server
await socket.SendAsync(versionPacketData, 0, versionPacketData.Length);
Debug.WriteLine(string.Format("SentPacket: {0}", versionPacket));

// Receive the response from the server
var responsePacket = await ReceiveNextPacket();
Debug.WriteLine(string.Format("ReceivedPacket: {0}", responsePacket));

// Get the status code from the response
var statusCode = responsePacket.Data[0];

if (statusCode > 0)
{
// Get the required version and raise an exception
var requiredVersion = IntegerExtender.MakeWord(responsePacket.Data[2], responsePacket.Data[1]);
throw new Exception(string.Format("The server requires client version {0} or higher.", requiredVersion));
}

// Version was accepted by the server
return true;
}
#endregion
Expand Down
2 changes: 0 additions & 2 deletions Spark/Spark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@
<Compile Include="Input\AsyncDelegateCommand.cs" />
<Compile Include="Input\DelegateCommand.cs" />
<Compile Include="Input\InputMasking.cs" />
<Compile Include="Models\BasicVersionTester.cs" />
<Compile Include="Models\ClientVersion.cs" />
<Compile Include="Models\IVersionTester.cs" />
<Compile Include="Models\Serializers\ClientVersionSerializer.cs" />
<Compile Include="Models\Serializers\UserSettingsSerializer.cs" />
<Compile Include="Models\UserSettings.cs" />
Expand Down
40 changes: 18 additions & 22 deletions Spark/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Spark.Input;
using Spark.Interop;
using Spark.Models;
using Spark.Net;
using Spark.Runtime;
using Spark.Security;

Expand Down Expand Up @@ -137,14 +138,12 @@ void OnTestConnection()
Debug.WriteLine("OnTestConnection");
Debug.WriteLine(string.Format("ServerHostname = {0}, ServerPort = {1}", this.UserSettings.ServerHostname, this.UserSettings.ServerPort));

int version;
ClientVersion clientVersion;

#region Get Version Number
#region Get Client Version
try
{
clientVersion = DetectClientVersion(userSettings, clientVersions);
version = clientVersion.VersionCode;
}
catch (Exception ex)
{
Expand All @@ -166,10 +165,11 @@ void OnTestConnection()

return;
}
version = clientVersion.VersionCode;
#endregion

TestConnectionToServer(userSettings.ServerHostname, userSettings.ServerPort, version);
Debug.WriteLine(string.Format("ClientVersion = {0} ({1})", clientVersion.Name, clientVersion.VersionCode));

TestConnectionToServer(userSettings.ServerHostname, userSettings.ServerPort, clientVersion.VersionCode);
}

void OnLaunchClient()
Expand Down Expand Up @@ -317,7 +317,7 @@ void LaunchClientWithSettings(UserSettings settings, IEnumerable<ClientVersion>
#endregion
}

void TestConnectionToServer(string serverHostname, int serverPort, int versionNumber)
async void TestConnectionToServer(string serverHostname, int serverPort, int versionCode)
{
IPAddress serverIPAddress = null;

Expand Down Expand Up @@ -355,32 +355,28 @@ void TestConnectionToServer(string serverHostname, int serverPort, int versionNu

try
{
using (IVersionTester versionTester = new BasicVersionTester())
using (var serverTester = new ServerTester())
{
versionTester.ConnectToServer(serverIPAddress, serverPort);
int reqVersionNumber;
if (versionTester.TestVersionNumber(versionNumber, out reqVersionNumber))
await serverTester.ConnectToServerAsync(serverIPAddress, serverPort);

if (await serverTester.CheckClientVersionCodeAsync(versionCode))
{
this.DialogService.ShowOKDialog("Connection Successful",
"The server appears to be up and running.",
string.Format("Connected to {0}:{1} successfully.", serverIPAddress, serverPort));
}
else
{
string extraInfo;
// Known required version number?
if (reqVersionNumber >= 0)
{
extraInfo = string.Format("Required Version: {0}. Detected Version: {1}.", reqVersionNumber, versionNumber);
}
else
{
extraInfo = string.Format("Detected Version: {0}. Please check what versions the server you are connecting to supports.", versionNumber);
}
//string extraInfo;
//// Known required version number?
//if (reqVersionNumber >= 0)
// extraInfo = string.Format("Required Version: {0}. Detected Version: {1}.", reqVersionNumber, versionNumber);
//else
// extraInfo = string.Format("Detected Version: {0}. Please check what versions the server you are connecting to supports.", versionNumber);

this.DialogService.ShowOKDialog("Connection Failed",
"The server appears to be running, but requires a different version of the client.",
extraInfo);
null);
}
}
}
Expand All @@ -397,7 +393,7 @@ void TestConnectionToServer(string serverHostname, int serverPort, int versionNu

// Retry the connection
if (result.HasValue && result.Value)
TestConnectionToServer(serverHostname, serverPort, versionNumber);
TestConnectionToServer(serverHostname, serverPort, versionCode);
}
}

Expand Down

0 comments on commit 76de368

Please sign in to comment.