2020-04-24 17:48:22 +02:00
|
|
|
module server.server;
|
2020-04-16 15:02:34 +02:00
|
|
|
|
2020-04-16 16:35:07 +02:00
|
|
|
import utils.debugging : debugPrint;
|
|
|
|
import std.conv : to;
|
2020-04-20 18:48:06 +02:00
|
|
|
import std.socket : Socket, AddressFamily, SocketType, ProtocolType, parseAddress, SocketFlags, Address;
|
2020-04-16 17:05:56 +02:00
|
|
|
import core.thread : Thread;
|
2020-04-17 18:47:05 +02:00
|
|
|
import std.stdio : writeln, File;
|
2020-04-18 15:25:22 +02:00
|
|
|
import std.json : JSONValue, parseJSON, JSONException, JSONType, toJSON;
|
2020-04-17 14:50:12 +02:00
|
|
|
import std.string : cmp;
|
2020-04-24 17:53:07 +02:00
|
|
|
import handlers.handler;
|
2020-04-24 17:48:22 +02:00
|
|
|
import listeners.listener;
|
|
|
|
import connection.connection;
|
2020-04-30 13:30:03 +02:00
|
|
|
import handlers.response;
|
2020-04-20 17:18:40 +02:00
|
|
|
|
2020-04-24 19:19:53 +02:00
|
|
|
public final class BesterServer
|
2020-04-16 15:02:34 +02:00
|
|
|
{
|
2020-04-17 13:46:54 +02:00
|
|
|
/**
|
|
|
|
* Message handlers
|
|
|
|
*
|
|
|
|
* Associative array of `payloadType (string)`:`MessageHandler`
|
|
|
|
* TODO: Implement this
|
|
|
|
*/
|
2020-04-24 17:48:22 +02:00
|
|
|
public MessageHandler[] handlers;
|
2020-04-16 16:35:07 +02:00
|
|
|
|
2020-04-16 16:39:31 +02:00
|
|
|
/* The server's socket */
|
|
|
|
private Socket serverSocket;
|
2020-04-20 18:55:48 +02:00
|
|
|
/* TODO: The above to be replaced */
|
|
|
|
|
2020-04-20 19:23:59 +02:00
|
|
|
/* Socket listeners for incoming connections */
|
2020-04-20 18:55:48 +02:00
|
|
|
private BesterListener[] listeners;
|
2020-04-16 16:39:31 +02:00
|
|
|
|
2020-04-19 18:53:16 +02:00
|
|
|
/* Connected clients */
|
2020-04-20 18:48:06 +02:00
|
|
|
public BesterConnection[] clients;
|
2020-04-19 18:53:16 +02:00
|
|
|
|
2020-04-25 18:58:32 +02:00
|
|
|
public BesterConnection[] getClients(string[] usernames)
|
|
|
|
{
|
2020-04-25 19:36:23 +02:00
|
|
|
/* List of authenticated users matching `usernames` */
|
|
|
|
BesterConnection[] matchedUsers;
|
2020-04-25 20:30:49 +02:00
|
|
|
|
2020-04-28 17:44:28 +02:00
|
|
|
//debugPrint("All clients (ever connected): " ~ to!(string)(clients));
|
|
|
|
|
2020-04-25 22:20:12 +02:00
|
|
|
/* Search through the provided usernames */
|
|
|
|
for(ulong i = 0; i < usernames.length; i++)
|
|
|
|
{
|
2020-04-25 22:33:35 +02:00
|
|
|
for(ulong k = 0; k < clients.length; k++)
|
2020-04-25 20:30:49 +02:00
|
|
|
{
|
2020-04-25 22:20:12 +02:00
|
|
|
/* The potentially-matched user */
|
|
|
|
BesterConnection potentialMatch = clients[k];
|
|
|
|
|
|
|
|
/* Check if the user is authenticated */
|
2020-04-27 16:34:14 +02:00
|
|
|
if(potentialMatch.getType() == BesterConnection.Scope.CLIENT && cmp(potentialMatch.getCredentials()[0], usernames[i]) == 0)
|
2020-04-25 20:30:49 +02:00
|
|
|
{
|
2020-04-25 22:20:12 +02:00
|
|
|
matchedUsers ~= potentialMatch;
|
|
|
|
}
|
2020-04-25 20:30:49 +02:00
|
|
|
}
|
2020-04-25 19:36:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return matchedUsers;
|
2020-04-25 18:58:32 +02:00
|
|
|
}
|
|
|
|
|
2020-04-20 20:08:55 +02:00
|
|
|
public void addListener(BesterListener listener)
|
2020-04-16 16:35:07 +02:00
|
|
|
{
|
2020-04-20 20:08:55 +02:00
|
|
|
this.listeners ~= listener;
|
2020-04-20 19:07:29 +02:00
|
|
|
}
|
2020-04-17 20:23:22 +02:00
|
|
|
|
2020-04-20 19:07:29 +02:00
|
|
|
this(JSONValue config)
|
|
|
|
{
|
2020-04-17 20:40:02 +02:00
|
|
|
/* TODO: Bounds check and JSON type check */
|
2020-04-20 20:30:17 +02:00
|
|
|
//debugPrint("Setting up socket...");
|
|
|
|
//setupServerSocket(config["network"]);
|
2020-04-17 20:40:02 +02:00
|
|
|
|
|
|
|
/* TODO: Bounds check and JSON type check */
|
2020-04-17 18:47:05 +02:00
|
|
|
debugPrint("Setting up message handlers...");
|
2020-04-17 20:40:02 +02:00
|
|
|
setupHandlers(config["handlers"]);
|
2020-04-30 13:30:03 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the `server` field in the HandlerResponse class
|
|
|
|
* to be this server.
|
|
|
|
*/
|
|
|
|
HandlerResponse.server = this;
|
2020-04-30 14:25:12 +02:00
|
|
|
writeln("jdfjfdhhjfh", HandlerResponse.server);
|
2020-04-16 16:39:31 +02:00
|
|
|
}
|
|
|
|
|
2020-04-17 20:40:02 +02:00
|
|
|
private void setupHandlers(JSONValue handlerBlock)
|
2020-04-17 13:46:54 +02:00
|
|
|
{
|
|
|
|
/* TODO: Implement me */
|
2020-04-17 18:07:13 +02:00
|
|
|
debugPrint("Constructing message handlers...");
|
2020-04-17 22:24:08 +02:00
|
|
|
handlers = MessageHandler.constructHandlers(handlerBlock);
|
2020-04-18 16:13:31 +02:00
|
|
|
writeln(handlers[0].getPluginName());
|
2020-04-17 13:46:54 +02:00
|
|
|
}
|
|
|
|
|
2020-04-17 20:23:22 +02:00
|
|
|
/* Setup the server socket */
|
|
|
|
private void setupServerSocket(JSONValue networkBlock)
|
2020-04-16 16:39:31 +02:00
|
|
|
{
|
2020-04-17 20:23:22 +02:00
|
|
|
string bindAddress;
|
|
|
|
ushort listenPort;
|
|
|
|
|
|
|
|
JSONValue jsonAddress, jsonPort;
|
|
|
|
|
|
|
|
writeln(networkBlock);
|
|
|
|
|
|
|
|
/* TODO: Bounds check */
|
|
|
|
jsonAddress = networkBlock["address"];
|
|
|
|
jsonPort = networkBlock["port"];
|
|
|
|
|
|
|
|
bindAddress = jsonAddress.str;
|
|
|
|
listenPort = cast(ushort)jsonPort.integer;
|
|
|
|
|
|
|
|
debugPrint("Binding to address: " ~ bindAddress ~ " and port " ~ to!(string)(listenPort));
|
|
|
|
|
2020-04-16 16:39:31 +02:00
|
|
|
/* Create a socket */
|
2020-04-16 16:41:56 +02:00
|
|
|
serverSocket = new Socket(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP);
|
2020-04-16 16:43:00 +02:00
|
|
|
serverSocket.bind(parseAddress(bindAddress, listenPort));
|
2020-04-16 16:39:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Start listen loop */
|
|
|
|
public void run()
|
|
|
|
{
|
2020-04-20 20:30:17 +02:00
|
|
|
for(ulong i = 0; i < listeners.length; i++)
|
2020-04-16 17:05:56 +02:00
|
|
|
{
|
2020-04-20 20:30:17 +02:00
|
|
|
debugPrint("Starting...");
|
|
|
|
listeners[i].start();
|
2020-04-16 17:05:56 +02:00
|
|
|
}
|
2020-04-20 22:02:12 +02:00
|
|
|
|
2020-04-16 17:05:56 +02:00
|
|
|
}
|
2020-04-16 23:25:22 +02:00
|
|
|
|
|
|
|
/* Authenticate the user */
|
|
|
|
public bool authenticate(string username, string password)
|
|
|
|
{
|
|
|
|
/* TODO: Implement me */
|
2020-04-17 11:57:06 +02:00
|
|
|
debugPrint("Attempting to authenticate:\n\nUsername: " ~ username ~ "\nPassword: " ~ password);
|
2020-04-19 18:53:16 +02:00
|
|
|
|
|
|
|
/* If the authentication went through */
|
|
|
|
bool authed = true;
|
|
|
|
|
|
|
|
/* If the authentication succeeded */
|
|
|
|
if(authed)
|
|
|
|
{
|
|
|
|
/* Add the user to the list of authenticated clients */
|
|
|
|
}
|
|
|
|
|
2020-04-16 23:25:22 +02:00
|
|
|
return true;
|
|
|
|
}
|
2020-04-19 13:37:26 +02:00
|
|
|
|
2020-04-19 14:45:53 +02:00
|
|
|
/* Returns the MessageHandler object of the requested type */
|
|
|
|
public MessageHandler findHandler(string payloadType)
|
|
|
|
{
|
|
|
|
/* The found MessageHandler */
|
|
|
|
MessageHandler foundHandler;
|
|
|
|
|
|
|
|
for(uint i = 0; i < handlers.length; i++)
|
|
|
|
{
|
|
|
|
if(cmp(handlers[i].getPluginName(), payloadType) == 0)
|
|
|
|
{
|
|
|
|
foundHandler = handlers[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return foundHandler;
|
|
|
|
}
|
|
|
|
|
2020-04-19 14:31:24 +02:00
|
|
|
public static bool isBuiltInCommand(string command)
|
2020-04-19 13:37:26 +02:00
|
|
|
{
|
2020-04-19 13:44:57 +02:00
|
|
|
/* Whether or not `payloadType` is a built-in command */
|
|
|
|
bool isBuiltIn = true;
|
|
|
|
|
2020-04-19 14:31:24 +02:00
|
|
|
|
2020-04-19 13:44:57 +02:00
|
|
|
return isBuiltIn;
|
2020-04-19 13:37:26 +02:00
|
|
|
}
|
2020-04-16 17:05:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|