2016-10-09 12:18:14 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2016-10-09 12:27:08 +00:00
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Sockets;
|
|
|
|
|
using System.Reflection;
|
2016-10-09 12:18:14 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace Galactic_Colors_Control_Server
|
|
|
|
|
{
|
2016-10-09 12:27:08 +00:00
|
|
|
|
internal class Program
|
|
|
|
|
{
|
|
|
|
|
private const int BUFFER_SIZE = 2048;
|
|
|
|
|
private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
public static bool _debug = false;
|
|
|
|
|
public static bool _run = true;
|
|
|
|
|
public static bool _open = true;
|
|
|
|
|
private static readonly byte[] buffer = new byte[BUFFER_SIZE];
|
|
|
|
|
public static Dictionary<Socket, Data> clients { get; private set; } = new Dictionary<Socket, Data>();
|
|
|
|
|
public static Config config = new Config();
|
|
|
|
|
|
|
|
|
|
private static void Main(string[] args)
|
|
|
|
|
{
|
|
|
|
|
Console.Title = "Galactic Colors Control Server";
|
|
|
|
|
Logger.Write("Galactic Colors Control Server " + Assembly.GetEntryAssembly().GetName().Version.ToString(), Logger.logType.fatal);
|
|
|
|
|
if (args.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
switch (args[0])
|
|
|
|
|
{
|
|
|
|
|
case "--debug":
|
|
|
|
|
_debug = true;
|
|
|
|
|
Logger.Write("SERVER IS IN DEBUG MODE !", Logger.logType.error);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
Utilities.ConsoleWrite("Use --debug or any argument");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(Type.GetType("Mono.Runtime") != null) { Logger.Write("Using Mono", Logger.logType.warm); }
|
|
|
|
|
Console.Write(">");
|
|
|
|
|
SetupServer();
|
|
|
|
|
ConsoleLoop();
|
|
|
|
|
CloseAllSockets();
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initialise server and start threads.
|
|
|
|
|
/// </summary>
|
2016-10-09 12:27:08 +00:00
|
|
|
|
private static void SetupServer()
|
|
|
|
|
{
|
|
|
|
|
config = config.Load();
|
|
|
|
|
Logger.Initialise();
|
|
|
|
|
Commands.Manager.Load();
|
|
|
|
|
Logger.Write("Setting up server on *:" + config.port, Logger.logType.warm);
|
|
|
|
|
Logger.Write("Size:" + config.size, Logger.logType.debug);
|
|
|
|
|
serverSocket.Bind(new IPEndPoint(IPAddress.Any, config.port));
|
|
|
|
|
serverSocket.Listen(0);
|
|
|
|
|
serverSocket.BeginAccept(AcceptCallback, null);
|
|
|
|
|
Logger.Write("Server setup complete", Logger.logType.info);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Wait console commands and execute them.
|
|
|
|
|
/// </summary>
|
2016-10-09 12:27:08 +00:00
|
|
|
|
private static void ConsoleLoop()
|
|
|
|
|
{
|
|
|
|
|
while (_run)
|
|
|
|
|
{
|
|
|
|
|
string ConsoleInput = Console.ReadLine();
|
|
|
|
|
Console.Write(">");
|
|
|
|
|
ExecuteMessage(ConsoleInput, null, true);
|
|
|
|
|
ConsoleInput = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// Close all connected client.
|
2016-10-09 12:27:08 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
private static void CloseAllSockets()
|
|
|
|
|
{
|
|
|
|
|
Logger.Write("Stoping server", Logger.logType.warm);
|
|
|
|
|
config.Save();
|
|
|
|
|
foreach (Socket socket in clients.Keys)
|
|
|
|
|
{
|
|
|
|
|
socket.Shutdown(SocketShutdown.Both);
|
|
|
|
|
Logger.Write("Shutdown " + Utilities.GetName(socket),Logger.logType.debug);
|
|
|
|
|
}
|
|
|
|
|
serverSocket.Close();
|
|
|
|
|
Logger.Write("Server stoped", Logger.logType.info);
|
|
|
|
|
Logger._run = false;
|
|
|
|
|
Logger.Updater.Join();
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Wait a client and check if is correct
|
|
|
|
|
/// </summary>
|
2016-10-09 12:27:08 +00:00
|
|
|
|
private static void AcceptCallback(IAsyncResult AR)
|
|
|
|
|
{
|
|
|
|
|
Socket socket;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
socket = serverSocket.EndAccept(AR);
|
|
|
|
|
}
|
|
|
|
|
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (_open)
|
|
|
|
|
{
|
2016-10-10 11:41:14 +00:00
|
|
|
|
if (clients.Count < config.size)
|
2016-10-09 12:27:08 +00:00
|
|
|
|
{
|
|
|
|
|
AddClient(socket);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Write("Client can't join from " + ((IPEndPoint)socket.LocalEndPoint).Address.ToString() + " no more space", Logger.logType.warm);
|
|
|
|
|
Utilities.Send(socket, "/kick can't_join_no_more_space", Utilities.dataType.message);
|
|
|
|
|
socket.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Write("Client can't join from " + ((IPEndPoint)socket.LocalEndPoint).Address.ToString() + " server closed", Logger.logType.info);
|
|
|
|
|
Utilities.Send(socket, "/kick can't_join_server_closed", Utilities.dataType.message);
|
|
|
|
|
socket.Close();
|
|
|
|
|
}
|
|
|
|
|
serverSocket.BeginAccept(AcceptCallback, null);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Add client and initialise receive
|
|
|
|
|
/// </summary>
|
2016-10-09 12:27:08 +00:00
|
|
|
|
private static void AddClient(Socket socket)
|
|
|
|
|
{
|
|
|
|
|
clients.Add(socket, new Data());
|
|
|
|
|
socket.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
|
|
|
|
|
Logger.Write("Client connection from " + Utilities.GetName(socket), Logger.logType.info);
|
|
|
|
|
Logger.Write("Size: " + clients.Count + "/" + config.size, Logger.logType.debug);
|
|
|
|
|
if (clients.Count >= config.size)
|
|
|
|
|
{
|
|
|
|
|
Logger.Write("Server full", Logger.logType.warm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Wait a client commands and execute them
|
|
|
|
|
/// </summary>
|
2016-10-09 12:27:08 +00:00
|
|
|
|
private static void ReceiveCallback(IAsyncResult AR)
|
|
|
|
|
{
|
|
|
|
|
Socket current = (Socket)AR.AsyncState;
|
|
|
|
|
int received;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
received = current.EndReceive(AR);
|
|
|
|
|
}
|
|
|
|
|
catch (SocketException)
|
|
|
|
|
{
|
|
|
|
|
Logger.Write("Client forcefully disconnected from " + Utilities.GetName(current), Logger.logType.info);
|
|
|
|
|
Logger.Write("Size: " + clients.Count + "/" + config.size, Logger.logType.debug);
|
|
|
|
|
current.Close(); // Don't shutdown because the socket may be disposed and its disconnected anyway.
|
|
|
|
|
clients.Remove(current);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var data = new byte[received];
|
|
|
|
|
Array.Copy(buffer, data, received);
|
|
|
|
|
|
|
|
|
|
byte[] type = new byte[4];
|
|
|
|
|
type = data.Take(4).ToArray();
|
|
|
|
|
type.Reverse();
|
|
|
|
|
Utilities.dataType dtype = (Utilities.dataType)BitConverter.ToInt32(type, 0);
|
|
|
|
|
byte[] bytes = null;
|
|
|
|
|
bytes = data.Skip(4).ToArray();
|
|
|
|
|
switch (dtype)
|
|
|
|
|
{
|
|
|
|
|
case Utilities.dataType.message:
|
|
|
|
|
string text = Encoding.ASCII.GetString(bytes);
|
|
|
|
|
ExecuteMessage(text, current);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Utilities.dataType.data:
|
|
|
|
|
Console.WriteLine("data");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
Logger.Write("Unknow type data form" + Utilities.GetName(current), Logger.logType.error);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (clients.ContainsKey(current)) { current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current); }
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 11:41:14 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Execute send command
|
|
|
|
|
/// <param name="text">Command</param>
|
|
|
|
|
/// <param name="soc">Sender socket</param>
|
|
|
|
|
/// <param name="server">Is sender server?</param>
|
|
|
|
|
/// </summary>
|
2016-10-09 12:27:08 +00:00
|
|
|
|
private static void ExecuteMessage(string text, Socket soc = null, bool server = false)
|
|
|
|
|
{
|
|
|
|
|
if (text.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (text[0] == '/')
|
|
|
|
|
{
|
|
|
|
|
text = text.Substring(1);
|
|
|
|
|
text = text.ToLower();
|
|
|
|
|
string[] array = text.Split(new char[1] { ' ' }, 4, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
if (array.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
Commands.Manager.Execute(array, soc, server);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Utilities.Return("Any command",soc , server);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!Utilities.IsConnect(soc))
|
|
|
|
|
{
|
|
|
|
|
Utilities.Send(soc, "Only identified clients can talk.", Utilities.dataType.message);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Write(Utilities.GetName(soc) + " : " + text, Logger.logType.info);
|
|
|
|
|
Utilities.Broadcast(Utilities.GetName(soc) + " : " + text, Utilities.dataType.message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|