1 module server.server; 2 3 import utils.debugging : debugPrint; 4 import std.conv : to; 5 import std.socket : Socket, AddressFamily, SocketType, ProtocolType, parseAddress, SocketFlags, Address; 6 import core.thread : Thread; 7 import std.stdio : writeln, File; 8 import std.json : JSONValue, parseJSON, JSONException, JSONType, toJSON; 9 import std.string : cmp; 10 import handlers.handler; 11 import listeners.listener; 12 import connection.connection; 13 14 public final class BesterServer 15 { 16 /** 17 * Message handlers 18 * 19 * Associative array of `payloadType (string)`:`MessageHandler` 20 * TODO: Implement this 21 */ 22 public MessageHandler[] handlers; 23 24 /* The server's socket */ 25 private Socket serverSocket; 26 /* TODO: The above to be replaced */ 27 28 /* Socket listeners for incoming connections */ 29 private BesterListener[] listeners; 30 31 /* Connected clients */ 32 public BesterConnection[] clients; 33 34 public BesterConnection[] getClients(string[] usernames) 35 { 36 /* List of authenticated users matching `usernames` */ 37 BesterConnection[] matchedUsers; 38 39 /* Search through the provided usernames */ 40 for(ulong i = 0; i < usernames.length; i++) 41 { 42 for(ulong k = 0; k < clients.length; k++) 43 { 44 /* The potentially-matched user */ 45 BesterConnection potentialMatch = clients[k]; 46 47 /* Check if the user is authenticated */ 48 if(potentialMatch.getType() == BesterConnection.Scope.CLIENT && cmp(potentialMatch.getCredentials()[0], usernames[i])) 49 { 50 matchedUsers ~= potentialMatch; 51 } 52 } 53 } 54 55 return matchedUsers; 56 } 57 58 public void addListener(BesterListener listener) 59 { 60 this.listeners ~= listener; 61 } 62 63 this(JSONValue config) 64 { 65 /* TODO: Bounds check and JSON type check */ 66 //debugPrint("Setting up socket..."); 67 //setupServerSocket(config["network"]); 68 69 /* TODO: Bounds check and JSON type check */ 70 debugPrint("Setting up message handlers..."); 71 setupHandlers(config["handlers"]); 72 } 73 74 private void setupHandlers(JSONValue handlerBlock) 75 { 76 /* TODO: Implement me */ 77 debugPrint("Constructing message handlers..."); 78 handlers = MessageHandler.constructHandlers(handlerBlock); 79 writeln(handlers[0].getPluginName()); 80 } 81 82 /* Setup the server socket */ 83 private void setupServerSocket(JSONValue networkBlock) 84 { 85 string bindAddress; 86 ushort listenPort; 87 88 JSONValue jsonAddress, jsonPort; 89 90 writeln(networkBlock); 91 92 /* TODO: Bounds check */ 93 jsonAddress = networkBlock["address"]; 94 jsonPort = networkBlock["port"]; 95 96 bindAddress = jsonAddress.str; 97 listenPort = cast(ushort)jsonPort.integer; 98 99 debugPrint("Binding to address: " ~ bindAddress ~ " and port " ~ to!(string)(listenPort)); 100 101 /* Create a socket */ 102 serverSocket = new Socket(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP); 103 serverSocket.bind(parseAddress(bindAddress, listenPort)); 104 } 105 106 /* Start listen loop */ 107 public void run() 108 { 109 for(ulong i = 0; i < listeners.length; i++) 110 { 111 debugPrint("Starting..."); 112 listeners[i].start(); 113 } 114 115 } 116 117 /* Authenticate the user */ 118 public bool authenticate(string username, string password) 119 { 120 /* TODO: Implement me */ 121 debugPrint("Attempting to authenticate:\n\nUsername: " ~ username ~ "\nPassword: " ~ password); 122 123 /* If the authentication went through */ 124 bool authed = true; 125 126 /* If the authentication succeeded */ 127 if(authed) 128 { 129 /* Add the user to the list of authenticated clients */ 130 } 131 132 return true; 133 } 134 135 /* Returns the MessageHandler object of the requested type */ 136 public MessageHandler findHandler(string payloadType) 137 { 138 /* The found MessageHandler */ 139 MessageHandler foundHandler; 140 141 for(uint i = 0; i < handlers.length; i++) 142 { 143 if(cmp(handlers[i].getPluginName(), payloadType) == 0) 144 { 145 foundHandler = handlers[i]; 146 break; 147 } 148 } 149 return foundHandler; 150 } 151 152 public static bool isBuiltInCommand(string command) 153 { 154 /* Whether or not `payloadType` is a built-in command */ 155 bool isBuiltIn = true; 156 157 158 return isBuiltIn; 159 } 160 } 161 162