2020-04-24 17:56:57 +02:00
|
|
|
module handlers.response;
|
|
|
|
|
2020-04-27 15:18:53 +02:00
|
|
|
import std.json : JSONValue, JSONException, parseJSON;
|
2020-04-24 18:30:02 +02:00
|
|
|
import std.conv : to;
|
|
|
|
import utils.debugging : debugPrint;
|
|
|
|
import std.string : cmp;
|
|
|
|
import std.stdio : writeln;
|
2020-04-24 18:41:25 +02:00
|
|
|
import connection.connection;
|
2020-04-26 22:16:07 +02:00
|
|
|
import base.types;
|
2020-04-28 17:44:28 +02:00
|
|
|
import std.socket : Socket,SocketOSException;
|
2020-04-27 15:18:53 +02:00
|
|
|
import connection.message;
|
2020-04-28 22:41:14 +02:00
|
|
|
import handlers.handler;
|
2020-04-24 17:56:57 +02:00
|
|
|
|
2020-04-24 18:55:19 +02:00
|
|
|
/* The type of the command the message handler wants us to run */
|
|
|
|
private enum CommandType
|
|
|
|
{
|
2020-04-24 19:10:57 +02:00
|
|
|
SEND_CLIENTS, SEND_SERVERS, SEND_HANDLER
|
2020-04-24 18:55:19 +02:00
|
|
|
}
|
|
|
|
|
2020-04-24 19:19:53 +02:00
|
|
|
public final class HandlerResponse
|
2020-04-24 17:56:57 +02:00
|
|
|
{
|
2020-04-24 18:30:02 +02:00
|
|
|
/* The message-handler's response */
|
|
|
|
private JSONValue messageResponse;
|
|
|
|
|
2020-04-24 18:55:19 +02:00
|
|
|
/* The command to be executed */
|
|
|
|
private CommandType commandType;
|
|
|
|
|
2020-04-28 22:41:14 +02:00
|
|
|
/* The handler that caused such a response to be illicited */
|
|
|
|
private MessageHandler handler;
|
|
|
|
|
|
|
|
this(MessageHandler handler, JSONValue messageResponse)
|
2020-04-24 17:56:57 +02:00
|
|
|
{
|
2020-04-24 18:30:02 +02:00
|
|
|
/* Set the message-handler's response message */
|
|
|
|
this.messageResponse = messageResponse;
|
|
|
|
|
2020-04-28 22:41:14 +02:00
|
|
|
/* Set the handler who caused this reponse to occur */
|
|
|
|
this.handler = handler;
|
|
|
|
|
2020-04-24 18:30:02 +02:00
|
|
|
/* Attempt parsing the message and error checking it */
|
|
|
|
parse(messageResponse);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void parse(JSONValue handlerResponse)
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Handles the response sent back to the server from the
|
|
|
|
* message handler.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Get the status */
|
|
|
|
ulong statusCode;
|
|
|
|
|
|
|
|
/* Error? */
|
|
|
|
bool error;
|
|
|
|
|
2020-04-27 13:00:16 +02:00
|
|
|
/* TODO: Bounds checking, type checking */
|
|
|
|
try
|
|
|
|
{
|
|
|
|
/* Get the header block */
|
|
|
|
JSONValue headerBlock = handlerResponse["header"];
|
2020-04-24 18:30:02 +02:00
|
|
|
|
2020-04-27 13:00:16 +02:00
|
|
|
/* Get the status */
|
|
|
|
statusCode = to!(ulong)(headerBlock["status"].str());
|
|
|
|
debugPrint("Status code: " ~ to!(string)(statusCode));
|
2020-04-24 17:56:57 +02:00
|
|
|
|
2020-04-27 13:00:16 +02:00
|
|
|
/* If the status is 0, then it is all fine */
|
|
|
|
if(statusCode == 0)
|
|
|
|
{
|
|
|
|
debugPrint("Status is fine, the handler ran correctly");
|
2020-04-24 18:30:02 +02:00
|
|
|
|
2020-04-27 13:00:16 +02:00
|
|
|
/* The command block */
|
|
|
|
JSONValue commandBlock = headerBlock["command"];
|
2020-04-24 18:30:02 +02:00
|
|
|
|
2020-04-27 13:00:16 +02:00
|
|
|
/**
|
|
|
|
* Get the command that the message handler wants the
|
|
|
|
* server to run.
|
|
|
|
*/
|
|
|
|
string serverCommand = commandBlock["type"].str;
|
|
|
|
debugPrint("Handler->Server command: \"" ~ serverCommand ~ "\"");
|
2020-04-24 18:30:02 +02:00
|
|
|
|
2020-04-27 13:00:16 +02:00
|
|
|
/* Check the command to be run */
|
|
|
|
if(cmp(serverCommand, "sendClients") == 0)
|
|
|
|
{
|
|
|
|
/* Set the command type to SEND_CLIENTS */
|
|
|
|
commandType = CommandType.SEND_CLIENTS;
|
|
|
|
|
|
|
|
/* TODO: Error check and do accesses JSON that would be done in `.execute` */
|
2020-04-24 18:30:02 +02:00
|
|
|
}
|
2020-04-27 13:00:16 +02:00
|
|
|
else if(cmp(serverCommand, "sendServers") == 0)
|
2020-04-24 18:30:02 +02:00
|
|
|
{
|
2020-04-27 13:00:16 +02:00
|
|
|
/* Set the command type to SEND_SERVERS */
|
|
|
|
commandType = CommandType.SEND_SERVERS;
|
|
|
|
|
|
|
|
/* TODO: Error check and do accesses JSON that would be done in `.execute` */
|
2020-04-24 18:30:02 +02:00
|
|
|
}
|
2020-04-27 13:00:16 +02:00
|
|
|
else if(cmp(serverCommand, "sendHandler") == 0)
|
|
|
|
{
|
|
|
|
/* Set the command type to SEND_HAANDLER */
|
|
|
|
commandType = CommandType.SEND_HANDLER;
|
|
|
|
|
|
|
|
/* TODO: Error check and do accesses JSON that would be done in `.execute` */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* TODO: Error handling */
|
|
|
|
debugPrint("The message handler is using an invalid command");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the message handler returned a response in error */
|
|
|
|
debugPrint("Message handler returned an error code: " ~ to!(string)(statusCode));
|
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(JSONException exception)
|
|
|
|
{
|
|
|
|
debugPrint("<<< There was an error handling the response message >>>\n\n" ~ exception.toString());
|
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If an error was envountered anyway down the processing of the
|
|
|
|
* message-handler then raise a `ResponseError` exception.
|
|
|
|
*/
|
2020-04-24 18:30:02 +02:00
|
|
|
if(error)
|
|
|
|
{
|
|
|
|
throw new ResponseError(messageResponse, statusCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 18:41:25 +02:00
|
|
|
public void execute(BesterConnection originalRequester)
|
|
|
|
{
|
|
|
|
/* TODO: Implement me */
|
2020-04-24 18:55:19 +02:00
|
|
|
|
|
|
|
/* If the command is SEND_CLIENTS */
|
2020-04-24 19:10:57 +02:00
|
|
|
if(commandType == CommandType.SEND_CLIENTS)
|
2020-04-24 18:55:19 +02:00
|
|
|
{
|
|
|
|
/* Get the list of clients to send to */
|
|
|
|
string[] clients;
|
2020-04-24 19:12:26 +02:00
|
|
|
JSONValue[] clientList = messageResponse["header"]["command"]["data"].array();
|
2020-04-24 18:55:19 +02:00
|
|
|
for(ulong i = 0; i < clientList.length; i++)
|
|
|
|
{
|
|
|
|
clients ~= clientList[i].str();
|
|
|
|
}
|
2020-04-25 22:33:35 +02:00
|
|
|
|
2020-04-27 17:04:10 +02:00
|
|
|
debugPrint("Users wanting to send to: " ~ to!(string)(clients));
|
2020-04-25 22:33:35 +02:00
|
|
|
|
|
|
|
/* Find the users that are wanting to be sent to */
|
|
|
|
BesterConnection[] connectionList = originalRequester.server.getClients(clients);
|
2020-04-28 22:41:14 +02:00
|
|
|
//debugPrint("Users matched online on server: " ~ to!(string)(connectionList));
|
2020-04-27 15:18:53 +02:00
|
|
|
|
2020-04-28 22:41:14 +02:00
|
|
|
/* The fully response message to send back */
|
2020-04-28 18:19:27 +02:00
|
|
|
JSONValue clientPayload;
|
|
|
|
|
2020-04-28 22:41:14 +02:00
|
|
|
/* Set the `handlerName` field of the header block */
|
|
|
|
JSONValue handlerName;
|
|
|
|
handlerName["handlerName"] = handler.getPluginName();
|
|
|
|
|
|
|
|
/* Set the header of the response */
|
2020-04-28 18:19:27 +02:00
|
|
|
JSONValue headerBlock;
|
2020-04-28 22:41:14 +02:00
|
|
|
clientPayload["header"] = handlerName;
|
|
|
|
|
|
|
|
/* Set the payload of the response */
|
|
|
|
clientPayload["data"] = messageResponse["data"];
|
2020-04-27 15:18:53 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Loop through each BesterConnection in connectionList and
|
|
|
|
* send the message-handler payload response message to each
|
|
|
|
* of them.
|
|
|
|
*/
|
|
|
|
for(ulong i = 0; i < connectionList.length; i++)
|
|
|
|
{
|
2020-04-28 17:44:28 +02:00
|
|
|
/* Get the conneciton */
|
|
|
|
BesterConnection clientConnection = connectionList[i];
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
/* Get the client's socket */
|
|
|
|
Socket clientSocket = clientConnection.getSocket();
|
|
|
|
//debugPrint("IsAlive?: " ~ to!(string)(clientSocket.isAlive()));
|
|
|
|
|
|
|
|
/* Send the message to the client */
|
|
|
|
debugPrint("Sending handler's response to client \"" ~ clientConnection.toString() ~ "\"...");
|
|
|
|
|
|
|
|
sendMessage(clientSocket, clientPayload);
|
|
|
|
debugPrint("Sending handler's response to client \"" ~ clientConnection.toString() ~ "\"... [sent]");
|
|
|
|
}
|
|
|
|
catch(SocketOSException exception)
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* If there was an error sending to the client, this can happen
|
|
|
|
* if the client has disconnected but hasn't yet been removed from
|
|
|
|
* the connections array and hence we try to send on a dead socket
|
|
|
|
* or get the remoteAddress on a dead socket, which causes a
|
|
|
|
* SocketOSException to be called.
|
|
|
|
*/
|
|
|
|
debugPrint("Attempted interacting with dead socket");
|
|
|
|
}
|
2020-04-27 15:18:53 +02:00
|
|
|
}
|
2020-04-28 17:44:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
debugPrint("SEND_CLIENTS: Completed run");
|
2020-04-24 18:55:19 +02:00
|
|
|
}
|
2020-04-24 19:10:57 +02:00
|
|
|
else if (commandType == CommandType.SEND_SERVERS)
|
|
|
|
{
|
|
|
|
/* Get the list of servers to send to */
|
|
|
|
string[] servers;
|
2020-04-24 19:12:26 +02:00
|
|
|
JSONValue[] serverList = messageResponse["header"]["command"]["data"].array();
|
2020-04-24 19:10:57 +02:00
|
|
|
for(ulong i = 0; i < serverList.length; i++)
|
|
|
|
{
|
|
|
|
servers ~= serverList[i].str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Implement me */
|
|
|
|
writeln("Servers wanting to send to ", servers);
|
|
|
|
}
|
2020-04-24 19:19:53 +02:00
|
|
|
else if (commandType == CommandType.SEND_HANDLER)
|
|
|
|
{
|
2020-04-25 18:58:32 +02:00
|
|
|
/* Name of the handler to send the message to */
|
|
|
|
string handler = messageResponse["header"]["command"]["data"]["handler"].str();
|
|
|
|
debugPrint("Handler to forward to: " ~ handler);
|
|
|
|
|
2020-04-24 19:19:53 +02:00
|
|
|
/* TODO: Add me */
|
|
|
|
}
|
2020-04-24 18:41:25 +02:00
|
|
|
}
|
|
|
|
|
2020-04-24 18:30:02 +02:00
|
|
|
override public string toString()
|
|
|
|
{
|
|
|
|
return messageResponse.toPrettyString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-26 22:16:07 +02:00
|
|
|
public final class ResponseError : BesterException
|
2020-04-24 18:30:02 +02:00
|
|
|
{
|
2020-04-27 13:00:16 +02:00
|
|
|
|
|
|
|
/* */
|
|
|
|
|
|
|
|
/* The status code that resulted in the response handling error */
|
|
|
|
private ulong statusCode;
|
|
|
|
|
2020-04-24 18:30:02 +02:00
|
|
|
this(JSONValue messageResponse, ulong statusCode)
|
|
|
|
{
|
|
|
|
/* TODO: Set message afterwards again */
|
2020-04-27 22:19:14 +02:00
|
|
|
super("");
|
2020-04-24 17:56:57 +02:00
|
|
|
}
|
|
|
|
}
|