1 module handlers.handler; 2 3 import std.stdio : writeln; 4 import std.socket : Socket, AddressFamily, parseAddress, SocketType, SocketOSException, UnixAddress; 5 import std.json : JSONValue, JSONType; 6 import utils.debugging : debugPrint; 7 8 public final class MessageHandler 9 { 10 /* The path to the message handler executable */ 11 private string executablePath; 12 13 /* The UNIX domain socket */ 14 private Socket domainSocket; 15 16 /* The pluginName/type */ 17 private string pluginName; 18 19 /* The UNIX domain socket path */ 20 public string socketPath; 21 22 public Socket getSocket() 23 { 24 return domainSocket; 25 } 26 27 this(string executablePath, string socketPath, string pluginName) 28 { 29 /* Set the plugin name */ 30 this.pluginName = pluginName; 31 32 /* Initialize the socket */ 33 //initializeUNIXSocket(socketPath); 34 35 /* Set the socket path */ 36 this.socketPath = socketPath; 37 } 38 39 public string getPluginName() 40 { 41 return pluginName; 42 } 43 44 public Socket getNewSocket() 45 { 46 /* Create the UNIX domain socket */ 47 Socket domainSocket = new Socket(AddressFamily.UNIX, SocketType.STREAM); 48 49 /* Connect to the socket at the socket path */ 50 domainSocket.connect(new UnixAddress(socketPath)); 51 52 return domainSocket; 53 } 54 55 private void initializeUNIXSocket(string socketPath) 56 { 57 /* Create the UNIX domain socket */ 58 domainSocket = new Socket(AddressFamily.UNIX, SocketType.STREAM); 59 60 /* Bind it to the socket path */ 61 domainSocket.connect(new UnixAddress(socketPath)); 62 } 63 64 private static string[] getAvailableTypes(JSONValue handlerBlock) 65 { 66 /* Available types as strings */ 67 string[] availableTypesStrings; 68 69 /* Get the available handlers */ 70 JSONValue availableTypes; 71 72 /* TODO: Bounds check */ 73 availableTypes = handlerBlock["availableTypes"]; 74 75 /* Make sure it is an array */ 76 if(availableTypes.type == JSONType.array) 77 { 78 /* Get the array of available types */ 79 JSONValue[] availableTypesArray = availableTypes.array; 80 81 for(uint i = 0; i < availableTypesArray.length; i++) 82 { 83 /* Make sure that it is a string */ 84 if(availableTypesArray[i].type == JSONType..string) 85 { 86 /* Add the type handler to the list of available types */ 87 availableTypesStrings ~= availableTypesArray[i].str; 88 debugPrint("Module wanted: " ~ availableTypesArray[i].str); 89 } 90 else 91 { 92 /* TODO: Error handling here */ 93 debugPrint("Available type not of type JSON string"); 94 } 95 } 96 } 97 else 98 { 99 /* TODO: Error handling */ 100 } 101 102 return availableTypesStrings; 103 } 104 105 private static string[2] getConfigurationArray(string pluginName, JSONValue typeMapBlock) 106 { 107 /* The configuration string */ 108 string[2] configurationString; 109 110 /* The module block */ 111 JSONValue moduleBlock; 112 113 /* TODO: Bounds check */ 114 moduleBlock = typeMapBlock[pluginName]; 115 116 /* Module block mst be of tpe JSON object */ 117 if(moduleBlock.type == JSONType.object) 118 { 119 /* TODO: Set the executable path */ 120 configurationString[0] = moduleBlock["handlerBinary"].str; 121 122 /* TODO: Set the UNIX domain socket path */ 123 configurationString[1] = moduleBlock["unixDomainSocketPath"].str; 124 } 125 else 126 { 127 /* TODO: Error handling */ 128 } 129 130 return configurationString; 131 } 132 133 /* TODO: Implement me */ 134 public static MessageHandler[] constructHandlers(JSONValue handlerBlock) 135 { 136 /* List of loaded message handlers */ 137 MessageHandler[] handlers; 138 139 /* TODO: Throwing error from inside this function */ 140 string[] availableTypes = getAvailableTypes(handlerBlock); 141 142 for(uint i = 0; i < availableTypes.length; i++) 143 { 144 /* Load module */ 145 string pluginName = availableTypes[i]; 146 debugPrint("Loading module \"" ~ pluginName ~ "\"..."); 147 148 try 149 { 150 JSONValue typeMap; 151 152 /* TODO: Bounds check */ 153 typeMap = handlerBlock["typeMap"]; 154 155 string[2] configuration = getConfigurationArray(pluginName, typeMap); 156 debugPrint("Module executable at: \"" ~ configuration[0] ~ "\""); 157 debugPrint("Module socket path at: \"" ~ configuration[1] ~ "\""); 158 MessageHandler constructedMessageHandler = new MessageHandler(configuration[0], configuration[1], pluginName); 159 handlers ~= constructedMessageHandler; 160 debugPrint("Module \"" ~ pluginName ~ "\" loaded"); 161 } 162 catch(SocketOSException exception) 163 { 164 debugPrint("Error whilst loading module \"" ~ pluginName ~ "\": " ~ exception.toString()); 165 } 166 } 167 168 return handlers; 169 } 170 }