using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace BeIT_APS_Socket_Server
{
/// <summary>
/// The standard Module that handles any standard commands between the server and client.
/// </summary>
class StandardModule : Zone
{
private Int64 _baseLatency;
/// <summary>
/// The latency in 100 nanosecond intervals (supposedly) thus a readable latency
/// would be: latency*100 / 1,000,000 = milliseconds </summary>
public Int64 latency { get { return _baseLatency; } set { _baseLatency = value; } }
private Boolean _isAdmin;
/// <summary>
/// Is the user an authenticated admin?
/// </summary>
public Boolean isAdmin { get { return _isAdmin; } set { _isAdmin = value; } }
private Boolean _isLoggedIn;
/// <summary>
/// Is the user Logged In ?
/// </summary>
public Boolean isLoggedIn { get { return _isLoggedIn; } set { _isLoggedIn = value; } }
private List<Zone> _zones;
/// <summary>
/// The accessor for all of the zones.
/// </summary>
public List<Zone> registeredZones { get { return _zones; } set { _zones = value; } }
/// <summary>
/// The Module Constructor. Assigns the netHandler </summary>
/// <param name="client">Takes a TcpClient from the TcpListener Server in
/// netHandler.cs</param>
public StandardModule(netHandlerClientIO clientIO)
{
setIOHandler(clientIO);
isAdmin = false;
isLoggedIn = false;
}
/// <summary>
/// Analyses the client reply, then runs the appropriate command. Virtual to be overidden
/// by custom Modules.</summary>
/// <param name="cmd">Expects a String with the command name as the first word in caps
/// then follows the commands params. "eg: LOGIN "Matthew Lloyd" "12345""</param>
/// <remarks>It requires an Object input since the ParameterizedThreadStart() needs a method
/// that accepts only objects as its input.</remarks>
public override void runCommand(Object cmd)
{
String[] command = ((String) cmd).Trim().Split(new Char[] { ' ' });
switch (command[0])
{
case "LOGIN":
handleLogin(command);
break;
case "PING?":
ReplypingPong((String) cmd);
break;
case "PONG!":
ReplypingPong((String) cmd);
break;
}
}
/// <summary>
/// Login to the socket server.
/// </summary>
/// <param name="command">The parsed command line with the Login parameters.</param>
public void handleLogin(String[] command)
{
ServerSettings svrSettings = new ServerSettings();
if (command[2] == svrSettings.LoginPassword)
{
isAdmin = true;
socketInOut.sendData("LOGIN TRUE TRUE \"Welcome " + command[1] + " to the Admin System\"");
}
else
{
isAdmin = false;
socketInOut.sendData("LOGIN TRUE FALSE \"Welcome " + command[1] + " to the User System\"");
}
isLoggedIn = true;
}
/// <summary>
/// Replys to a PING? request. Updates Latency, and outputs to Standard Output</summary>
/// <param name="input">Expects a string similar to "PING? 12345" where the first command
/// param is the number of seconds since 1970.</param>
private void ReplypingPong(String input)
{
String[] PingSplit = input.Split(new char[] { ' ' });
updateLatency(Convert.ToInt64(PingSplit[1], 10));
Console.WriteLine("Client Latency: {0}", showLatency());
String output = pingPong(input);
socketInOut.sendData(output);
}
/// <summary>
/// Gives a Reply to a PING or PONG request</summary>
/// <param name="input">Only expects either "PING? " or "PONG! "</param>
/// <returns>Either PING? 12345, PONG! 12345 or "*" depending on input</returns>
private String pingPong(String input)
{
DateTime now = DateTime.Now;
if (input == "")
return "PING? " + now.Ticks.ToString();
else if (input.StartsWith("PING?"))
return "PONG! " + now.Ticks.ToString();
return "*";
}
/// <summary>
/// Gives a Reply to a PING or PONG request</summary>
/// <returns>Either PING? 12345, PONG! 12345 or "*" depending on input</returns>
public String pingPong()
{
return pingPong("");
}
/// <summary>
/// Updates latency between the Server and the Client
/// </summary>
/// <param name="milliSec">The number of milliseconds since midnight January 1, 1970</param>
private void updateLatency(Int64 milliSec)
{
DateTime now = DateTime.UtcNow;
DateTime then = new DateTime(milliSec * 10000);
DateTime yearCutout = new DateTime(now.Year, 1, 1, 0, 0, 0, 0);
DateTime secondYearCutout = new DateTime(then.Year, 1, 1, 0, 0, 0, 0);
TimeSpan nowWithoutYear = now.Subtract(yearCutout);
TimeSpan thenWithoutYear = then.Subtract(secondYearCutout);
latency = nowWithoutYear.Ticks - thenWithoutYear.Ticks;
}
/// <summary>
/// Returns the latency in milliseconds with the units added on.
/// </summary>
/// <returns>The converted Server-Client Latency from nanoseconds to Milliseconds with the units added on</returns>
public String showLatency()
{
return (((Double)latency) * 0.00001).ToString() + " ms";
}
}
}