1
0
Fork 0
mirror of https://github.com/besterprotocol/besterd synced 2023-12-13 21:00:32 +01:00
besterd/source/server/server.d

198 lines
4.6 KiB
D
Raw Normal View History

2020-04-24 17:48:22 +02:00
module server.server;
2020-04-16 15:02:34 +02:00
import utils.debugging : debugPrint;
import std.conv : to;
2020-05-01 09:55:50 +02:00
import std.socket : Socket, AddressFamily, SocketType, ProtocolType, parseAddress;
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;
import std.string : cmp, strip;
2020-05-01 09:55:50 +02:00
import handlers.handler : MessageHandler;
import listeners.listener : BesterListener;
import connection.connection : BesterConnection;
2020-05-04 15:17:31 +02:00
import server.informer : BesterInformer;
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: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 */
public BesterConnection[] clients;
2020-04-19 18:53:16 +02:00
2020-05-04 15:17:31 +02:00
/* The informer server */
private BesterInformer informer;
2020-05-02 22:43:05 +02:00
/**
* Returns a list of BesterConnection objects that
* match the usernames provided.
*
* @param usernames Array of strings of usernames to match to
*/
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
//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++)
{
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-20 20:08:55 +02:00
this.listeners ~= listener;
2020-04-20 19:07:29 +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-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-30 15:55:40 +02:00
handlers = MessageHandler.constructHandlers(this, handlerBlock);
2020-04-17 13:46:54 +02:00
}
/* Setup the server socket */
private void setupServerSocket(JSONValue networkBlock)
2020-04-16 16:39:31 +02:00
{
string bindAddress;
ushort listenPort;
JSONValue jsonAddress, jsonPort;
2020-05-01 09:45:44 +02:00
debugPrint(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
}
2020-05-04 15:17:31 +02:00
private void startListeners()
2020-04-16 16:39:31 +02:00
{
2020-04-20 20:30:17 +02:00
for(ulong i = 0; i < listeners.length; i++)
2020-04-16 17:05:56 +02:00
{
debugPrint("Starting listener \"" ~ listeners[i].toString() ~ "\"...");
2020-04-20 20:30:17 +02:00
listeners[i].start();
2020-04-16 17:05:56 +02:00
}
2020-05-04 15:17:31 +02:00
}
/**
* Starts the BesterInformer.
*/
private void startInformer()
{
2020-05-04 15:17:53 +02:00
informer = new BesterInformer(this);
2020-05-04 15:17:31 +02:00
informer.start();
}
/* Start listen loop */
public void run()
{
/* Start the listeners */
startListeners();
/* Start the informer */
startInformer();
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;
/* Strip the username of whitespace (TODO: Should we?) */
username = strip(username);
/* Make sure username and password are not empty */
if(cmp(username, "") != 0 && cmp(password, "") != 0)
2020-04-19 18:53:16 +02:00
{
2020-04-19 18:53:16 +02:00
}
else
{
authed = false;
}
return authed;
2020-04-16 23:25:22 +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: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-16 17:05:56 +02:00
}