/// <summary> /// Register type as plugin. /// </summary> /// <param name="pluginType"></param> public void RegisterPluginType(Type pluginType) { if (pluginType == null) { throw new ArgumentNullException(nameof(pluginType)); } if (PluginTypes.FirstOrDefault(x => x.Type == pluginType) != null) { throw new ArgumentException("Unable to register plugin " + pluginType.ToString() + ", type already registered!"); } ITcpAppServerPlugin ptrPlugin = Activator.CreateInstance(pluginType) as ITcpAppServerPlugin; try { if (PluginTypes.FirstOrDefault(x => x.Name.Equals(ptrPlugin.PluginName, StringComparison.InvariantCultureIgnoreCase)) != null) { throw new ArgumentException("Unable to register plugin, name already exist!"); } if (pluginType.GetInterfaces().Contains(typeof(ITcpAppServerPlugin))) { PluginTypes.Add(new TcpAppServerPluginType() { Name = ptrPlugin.PluginName, Description = ptrPlugin.PluginDescription, Type = pluginType }); } else { throw new ArgumentException("Unable to register plugin, input type does not implement ITcpAppServerPlugin interface!"); } } finally { ptrPlugin.DisposeRequest(); } }
/// <summary> /// Add plugin object directly from TcpAppServer. /// </summary> /// <param name="plugin"></param> public void AddPlugin(ITcpAppServerPlugin plugin) { if (Plugins.FirstOrDefault(x => string.Compare(x.Alias, plugin.Alias, true) == 0) != null) { throw new ArgumentException("Unable to add object with alias '" + plugin.Alias + "'. Object already exists!"); } Plugins.Add(plugin); }
/// <summary> /// Add plugin object directly from TcpAppServer by code. /// </summary> /// <param name="plugin"></param> public void AddPlugin(ITcpAppServerPlugin plugin) { if (plugin == null) { throw new ArgumentNullException(nameof(plugin)); } if (_Plugins.FirstOrDefault(x => string.Compare(x.Alias, plugin.Alias, true) == 0) != null) { throw new ArgumentException("Unable to add object with alias '" + plugin.Alias + "'. Object already exists!"); } //Verify input object type is registered if (PluginTypes.FirstOrDefault(x => x.Type == plugin.GetType()) == null) { throw new ArgumentException("Plugin type not registered! " + plugin.GetType().ToString()); } _Plugins.Add(plugin); }
private void ShowHelp(TcpAppInputCommand sender) { string aliasName = sender.Command.Parameter("Alias").Value; List <string> lines = null; if (aliasName == "-") { //Print Help Screen - Write to sender.OutputMessage lines = new List <string> { "TCP Aplication Server Version " + Version.ToString(), " ", "==== USAGE ====", " SEND: <Command> [Param0] ... [ParamN]", " RECV: <Command> <Status> [Return Message]", " ", " Notes:", " <> = Required parameters", " [] = Optional parameters", " ", }; lines.AddRange(TcpAppCommon.PrintCommandHelpContents(Commands)); sender.OutputMessage = string.Join("\r\n", lines.ToArray()); sender.Status = TcpAppCommandStatus.OK; } else { //Get Help Content for selected object. ITcpAppServerPlugin plugin = Plugins.FirstOrDefault(x => string.Compare(x.Alias, sender.Command.Parameter("Alias").Value, true) == 0); if (plugin == null) { sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = "Object [" + aliasName + "] not exist!"; } else { plugin.ShowHelp(sender); } } }
/// <summary> /// Constructor /// </summary> /// <param name="mainForm">Main Form Handle</param> public TcpAppServer(Form mainForm) : base() { MainForm = mainForm; MessageDelimiter = Convert.ToByte(Convert.ToChar(TcpAppCommon.Delimiter)); base.ClientConnected += TcpAppServer_ClientConnected; base.ClientDisconnected += TcpAppServer_ClientDisconnected; //TcpAppServer Format: // TX: TCP: <Command> [-Param0] [-Param1] ... [-ParamN] // RX: TCP: <Command> <Status> [Return Message] // Source - [email protected]:23 // Command - Registered Command. //Register System Commands //--- INIT (Commands used by TcpAppClient) --- RegisterCommand("TcpAppInit", "Initialize TCP Application.", delegate(TcpAppInputCommand sender) { sender.OutputMessage = string.IsNullOrEmpty(WelcomeMessage) ? Application.ProductName + " " + Application.ProductVersion : WelcomeMessage; sender.Status = TcpAppCommandStatus.OK; }); RegisterCommand("TcpAppVersion?", "Get TcpAppServer Library Version", delegate(TcpAppInputCommand sender) { sender.OutputMessage = Version.ToString(); sender.Status = TcpAppCommandStatus.OK; }); RegisterCommand("FunctionList?", "Get list of registered functions.", delegate(TcpAppInputCommand sender) { foreach (TcpAppCommand x in Commands) { sender.OutputMessage += x.Keyword; sender.OutputMessage += " "; } sender.Status = TcpAppCommandStatus.OK; }); //-- APP INFO -- RegisterCommand("ApplicationName?", "Get Application Name.", delegate(TcpAppInputCommand sender) { sender.OutputMessage = Application.ProductName; sender.Status = TcpAppCommandStatus.OK; }); RegisterCommand("ApplicationVersion?", "Get Application Version.", delegate(TcpAppInputCommand sender) { sender.OutputMessage = Application.ProductVersion; sender.Status = TcpAppCommandStatus.OK; }); //--- PLUGIN --- RegisterCommand("PluginTypes?", "Get list of plugin class type. Use CreateObject command to instantiate type.", delegate(TcpAppInputCommand sender) { if (PluginTypes.Count == 0) { sender.OutputMessage = "-NONE-"; } else { sender.OutputMessage = string.Join(" ", PluginTypes.Keys.ToArray()); } sender.Status = TcpAppCommandStatus.OK; }); RegisterCommand("CreateObject", "Create an object from listed plugin types.", delegate(TcpAppInputCommand sender) { string typeName = sender.Command.Parameter("TypeName").Value; string aliasName = sender.Command.Parameter("Alias").Value; //Sanity Check - Type Name Type pluginType = PluginTypes[PluginTypes.Keys.FirstOrDefault(x => string.Compare(x, typeName, true) == 0)]; if (!PluginTypes.Keys.Contains(typeName, StringComparer.InvariantCultureIgnoreCase)) { throw new ArgumentException("Unknown plugin type: " + typeName); } //Sanity Check - Alias Name if (Plugins.FirstOrDefault(x => string.Compare(x.Alias, aliasName, true) == 0) != null) { throw new ArgumentException("Unable to create object with alias '" + aliasName + "'. Object already exists!"); } ITcpAppServerPlugin pluginInstance = Activator.CreateInstance(pluginType) as ITcpAppServerPlugin; pluginInstance.Alias = aliasName; Plugins.Add(pluginInstance); sender.OutputMessage = "Object created " + aliasName; sender.Status = TcpAppCommandStatus.OK; }, new TcpAppParameter("TypeName", "Plugin type name."), new TcpAppParameter("Alias", "Plugin object Alias Name. Alias name is case insensitive")); RegisterCommand("Objects?", "Return object list by alias name.", delegate(TcpAppInputCommand sender) { if (Plugins.Count == 0) { sender.OutputMessage = "-NONE-"; } else { sender.OutputMessage = string.Join(" ", Plugins.Select(x => x.Alias).ToArray()); } sender.Status = TcpAppCommandStatus.OK; }); RegisterCommand("Execute", "Exceute plugin's command.", delegate(TcpAppInputCommand sender) { ITcpAppServerPlugin plugin = Plugins.FirstOrDefault(x => string.Compare(x.Alias, sender.Command.Parameter("Alias").Value, true) == 0); if (plugin == null) { throw new ArgumentNullException("Plugin not exists!"); } TcpAppInputCommand pluginCommand = new TcpAppInputCommand() { Arguments = sender.Arguments }; plugin.ExecutePluginCommand(pluginCommand); sender.Status = pluginCommand.Status; sender.OutputMessage = pluginCommand.OutputMessage; }, new TcpAppParameter("Alias", "Plugin object Alias Name.")); RegisterCommand("DisposeObject", "Delete object by alias name.", delegate(TcpAppInputCommand sender) { string alias = sender.Command.Parameter("Alias").Value; ITcpAppServerPlugin item = Plugins.FirstOrDefault(x => string.Compare(x.Alias, alias, true) == 0); if (item == null) { sender.OutputMessage = "Object [" + alias + "] not found / disposed."; sender.Status = TcpAppCommandStatus.OK; return; } else { if (item.DisposeRequest() == true) { Plugins.Remove(item); sender.OutputMessage = alias + " disposed."; sender.Status = TcpAppCommandStatus.OK; } else { sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = "Unable to dispose " + alias; } } }, new TcpAppParameter("Alias", "Object alias name.")); //-- GUI Control -- string ErrMainFormNull = "Main Form not assigned!"; RegisterCommand("MaximizeWindow", "Maximize Application Window.", delegate(TcpAppInputCommand sender) { if (MainForm != null) { MainForm.WindowState = FormWindowState.Maximized; sender.Status = TcpAppCommandStatus.OK; } else { sender.OutputMessage = ErrMainFormNull; } }); RegisterCommand("MinimizeWindow", "Minimize Application Window.", delegate(TcpAppInputCommand sender) { if (MainForm != null) { MainForm.WindowState = FormWindowState.Minimized; sender.Status = TcpAppCommandStatus.OK; } else { sender.OutputMessage = ErrMainFormNull; } }); RegisterCommand("RestoreWindow", "Restore Application Window.", delegate(TcpAppInputCommand sender) { if (MainForm != null) { MainForm.WindowState = FormWindowState.Normal; sender.Status = TcpAppCommandStatus.OK; } else { sender.OutputMessage = ErrMainFormNull; } }); RegisterCommand("BringToFront", "Set Application Window as Top Most.", delegate(TcpAppInputCommand sender) { if (MainForm != null) { MainForm.BringToFront(); sender.Status = TcpAppCommandStatus.OK; } else { sender.OutputMessage = ErrMainFormNull; } }); RegisterCommand("SetWindowPosition", "Set Window Position.", delegate(TcpAppInputCommand sender) { if (MainForm != null) { MainForm.Location = new System.Drawing.Point( Convert.ToInt16(sender.Command.Parameter("X").Value), Convert.ToInt16(sender.Command.Parameter("Y").Value)); sender.Status = TcpAppCommandStatus.OK; } else { sender.OutputMessage = ErrMainFormNull; } }, new TcpAppParameter("X", "Upper left X coordinate of main form."), new TcpAppParameter("Y", "Upper left Y coordinate of main form.")); RegisterCommand("Terminate", "Terminate Application. Default Exit Code = -99", delegate(TcpAppInputCommand sender) { int exitCode = -99; try { exitCode = Convert.ToInt32(sender.Command.Parameter("ExitCode").Value); } catch { } sender.Status = TcpAppCommandStatus.OK; Environment.ExitCode = exitCode; System.Threading.Thread ptrThread = new System.Threading.Thread(TerminateApplication); ptrThread.Start(); }, new TcpAppParameter("ExitCode", "Assign Exit Code for application termination.", "-99")); //-- User Interaction -- RegisterCommand("Help", "Show help screen.", ShowHelp, new TcpAppParameter("Alias", "Object Alias Name", "-")); }
private void Client_ProcessReceivedMessage(TcpServerConnection client, string message, byte[] messageBytes) { //Parse and Execute Commands string[] cmdArg = TcpAppCommon.ParseCommand(message.Trim()); try { //Register Client Connection TcpAppServerConnection ptrClient = AppClients.FirstOrDefault(x => x.Connection == client); if (ptrClient == null) { //Reconstruct device which had already signed out ptrClient = AddClientToAppClientsList(client); } Debug.WriteLine("AppServer[" + ptrClient.Name + "]-RX: " + message); TcpAppInputCommand inputCommand = TcpAppCommon.CreateInputCommand(Commands, cmdArg); if (inputCommand != null) { inputCommand.AppClient = ptrClient; } else//Command keyword not exist { //Check if command keyword is alias name ITcpAppServerPlugin plugin = _Plugins.FirstOrDefault(x => string.Compare(x.Alias, cmdArg[0], true) == 0); if (plugin != null) { //Execute plugin command inputCommand = plugin.GetPluginCommand(cmdArg.Skip(1).ToArray()); inputCommand.AppClient = ptrClient; BeforeExecutePluginCommand?.Invoke(this, new TcpAppServerExEventArgs(ptrClient) { Plugin = plugin }); } else { //Error - Unrecognized command. inputCommand = new TcpAppInputCommand() { Status = TcpAppCommandStatus.ERR, OutputMessage = "Invalid Command " + cmdArg[0] }; WriteResultToClient(ptrClient, inputCommand); return; } } //Verify Client had signed in. if (!inputCommand.AppClient.SignedIn && !inputCommand.Command.IsSystemCommand) { throw new Exception("Client not signed in! Execute SignIn first."); } if (inputCommand.Command.UseMessageQueue && !inputCommand.Command.IsSystemCommand) { //Single thread execution, post message to message queue. lock (CommandQueue) { inputCommand.ID = inputCommand.GetHashCode(); if (ptrClient.NextQueuedCommand == null) { ptrClient.NextQueuedCommand = inputCommand; //Set pointer to next queued command. } //Add Command to Queue CommandQueue.Add(inputCommand); CommandQueueWaitSignal?.Set(); inputCommand.OutputMessage = inputCommand.ID.ToString(); inputCommand.Status = TcpAppCommandStatus.QUEUED; } } else if (inputCommand.Command.IsSystemCommand) { inputCommand.ExecuteCallback(); } else { //Execute command, wait until return if (ExecutionTimeout == 0) { inputCommand.ExecuteCallback(); } //Execute command, terminate on timeout else { ptrClient.ExecuteCommandAsync(inputCommand, ExecutionTimeout); } } WriteResultToClient(ptrClient, inputCommand); //Send result back to client. } catch (Exception ex) { WriteExceptionErrorToClient(client, ex); } }
private void ShowHelp(TcpAppInputCommand sender) { string aliasName = sender.Command.Parameter("Plugin").Value; List <string> lines = null; if (aliasName == "-") { lines = new List <string> { "[ TCP Aplication Server V" + Version.ToString() + " ]", " ", "==== USAGE ====", " Execute Tcp App Server Command:", " SEND: <Command> [Param0] ... [ParamN]", " RECV: <Status> [Return Message]", " ", " Execute plugin Command:", " SEND: <Alias> <Command> [Param0] ... [ParamN]", " RECV: <Status> [Return Message]", " ", " Notes:", " Command are not case sensitive.", " <> = Required parameters", " [] = Optional parameters", " ", }; //Insert Application Header if defined. string header = OnShowHelpGetApplicationHeader(); if (!string.IsNullOrEmpty(header)) { lines.Insert(0, header); } lines.AddRange(TcpAppCommon.PrintCommandHelpContents(Commands)); //Print registered plugins if (PluginTypes.Count > 0) { lines.Add("[ PLUGINS ]"); lines.AddRange(PluginTypes.Select(x => string.Format(" {0, -20} {1}", x.Name, x.Description)).ToArray()); lines.Add(" "); } if (_Plugins.Count > 0) { lines.Add("[ OBJECTS ]"); lines.AddRange(_Plugins.Select(x => string.Format(" {0, -20} {1}", x.Alias, "(" + PluginTypes.FirstOrDefault(n => n.Type == x.GetType())?.Name + ")")).ToArray()); } sender.OutputMessage = string.Join(TcpAppCommon.NewLine, lines.ToArray()); sender.Status = TcpAppCommandStatus.OK; } else { //Get Help Content for selected object. string pluginName = sender.Command.Parameter("Plugin").Value; ITcpAppServerPlugin plugin = null; TcpAppServerPluginType ptrType = PluginTypes.FirstOrDefault(x => x.Name.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase)); if (ptrType != null) { //Get help by type Type pluginType = ptrType.Type; plugin = _Plugins.FirstOrDefault(x => x.GetType() == pluginType); if (plugin != null) { //Show Help using existing object plugin.ShowHelp(sender); return; } //Create instance and show help, dispose after use plugin = Activator.CreateInstance(pluginType) as ITcpAppServerPlugin; plugin.ShowHelp(sender); plugin.DisposeRequest(); plugin = null; return; } else { //Get help by alias name plugin = _Plugins.FirstOrDefault(x => string.Compare(x.Alias, pluginName, true) == 0); if (plugin != null) { plugin.ShowHelp(sender); return; } } sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = "Object [" + aliasName + "] not exist!"; } }
/// <summary> /// Remove plugin by code. /// </summary> /// <param name="plugin"></param> public void DisposePlugin(ITcpAppServerPlugin plugin) { _Plugins.Remove(plugin); }
/// <summary> /// Constructor /// </summary> public TcpAppServer() : base() { MessageDelimiter = Convert.ToByte(Convert.ToChar(TcpAppCommon.Delimiter)); base.ClientConnected += TcpAppServer_ClientConnected; base.ClientDisconnected += TcpAppServer_ClientDisconnected; base.ServerStopped += TcpAppServer_ServerStopped; CommandQueueThread = new Thread(ExecuteQueuedCommandsAsync); AbortCommandQueueThread = false; CommandQueueThread.Start(); //TcpAppServer Format: // TX: TCP: <Command> [-Param0] [-Param1] ... [-ParamN] // RX: TCP: <Status> [Return Message] // Source - [email protected]:23 // Command - Registered Command. //Register System Commands //--- INIT (Commands used by TcpAppClient) --- RegisterSystemCommand("Help", "Show help screen. Include plugin type or object alias name to show commands for selected plugin.", ShowHelp, TcpAppParameter.CreateOptionalParameter("Plugin", "Plugin type or Alias", "-")); RegisterSystemCommand("SignIn", "Sign in to TcpAppServer. Server will verify connection id and return unique ID.", delegate(TcpAppInputCommand sender) { //Assign Name string machineName = sender.Command.Parameter("ConnectionID").Value?.Replace(" ", "_"); if (string.IsNullOrEmpty(machineName)) { machineName = sender.AppClient.Connection.ClientIPAddress.ToString(); } if (sender.AppClient.SignedIn) { //Client already signed in, verify connection ID. if (sender.AppClient.Name.Equals(machineName, StringComparison.InvariantCultureIgnoreCase)) { sender.OutputMessage = sender.AppClient.Name; sender.Status = TcpAppCommandStatus.OK; return; } else { sender.AppClient.SignedIn = false; } } TcpAppServerExEventArgs signInArg = new TcpAppServerExEventArgs(sender.AppClient) { Value = machineName }; ClientSigningIn?.Invoke(this, signInArg); if (signInArg.Cancel == true) { sender.OutputMessage = signInArg.Reason; if (string.IsNullOrEmpty(sender.OutputMessage)) { sender.OutputMessage = "Access Denied!"; } sender.Status = TcpAppCommandStatus.ERR; return; } string uniqueName = machineName; lock (AppClients) { //Cleanup instance with same name but already disconnected without signout if (AppClients.FirstOrDefault(x => x.Name == uniqueName) != null) { for (int x = 0; x < AppClients.Count;) { if (!AppClients[x].Connection.Connected && AppClients[x].Name.StartsWith(uniqueName)) { AppClients[x].Dispose(); AppClients.RemoveAt(x); } else { x++; } } } while (AppClients.FirstOrDefault(x => x.Name == uniqueName) != null) { uniqueName = machineName + "_" + (++Counter).ToString(); } sender.AppClient.Name = uniqueName; sender.OutputMessage = uniqueName; sender.Status = TcpAppCommandStatus.OK; sender.AppClient.SignedIn = true; ClientSignedIn?.Invoke(this, new TcpAppServerEventArgs(sender.AppClient)); //Event } }, TcpAppParameter.CreateParameter("ConnectionID", "Connection ID. If already exist, server will return an updated unique ID.")); RegisterSystemCommand("SignOut", "Signout TcpAppClient.", delegate(TcpAppInputCommand sender) { ClientSigningOut?.Invoke(this, new TcpAppServerEventArgs(sender.AppClient)); sender.AppClient.Dispose(); lock (AppClients) { AppClients.Remove(sender.AppClient); } sender.AppClient.SignedIn = false; sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("Version?", "Get TcpAppServer Library Version", delegate(TcpAppInputCommand sender) { sender.OutputMessage = Version.ToString(); sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("Terminate", "Terminate Application. Command only valid after client Signin. Default Exit Code = -99", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); int exitCode = -99; try { exitCode = Convert.ToInt32(sender.Command.Parameter("ExitCode").Value); } catch { } sender.Status = TcpAppCommandStatus.OK; Environment.ExitCode = exitCode; Thread ptrThread = new Thread(TerminateApplication); ptrThread.Start(); }, TcpAppParameter.CreateOptionalParameter("ExitCode", "Assign Exit Code for application termination.", "-99")); //--- Execution --- RegisterSystemCommand("FunctionList?", "Get list of registered functions.", delegate(TcpAppInputCommand sender) { foreach (TcpAppCommand x in Commands) { sender.OutputMessage += x.Keyword; sender.OutputMessage += " "; } sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("Execute", "Execute plugin's command. Command only valid after client Signin.", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); ITcpAppServerPlugin plugin = _Plugins.FirstOrDefault(x => string.Compare(x.Alias, sender.Command.Parameter("Alias").Value, true) == 0); if (plugin == null) { throw new ArgumentException("Plugin not exists!"); } TcpAppInputCommand pluginCommand = plugin.GetPluginCommand(sender.Arguments.Skip(1).ToArray()); TcpAppServerExEventArgs pluginExecuteEventArgs = new TcpAppServerExEventArgs(sender.AppClient) { Plugin = plugin }; BeforeExecutePluginCommand?.Invoke(this, pluginExecuteEventArgs); if (pluginExecuteEventArgs.Cancel) { //Command execution cancelled by server, return error with reason. sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = pluginExecuteEventArgs.Reason; } else { //Proceed with execution. pluginCommand.ExecuteCallback(); sender.Status = pluginCommand.Status; sender.OutputMessage = pluginCommand.OutputMessage; } }, TcpAppParameter.CreateParameter("Alias", "Plugin Alias Name.")); RegisterSystemCommand("CheckStatus", "Check execution status for queued command. RETURN: Command status if executed, else BUSY. ERR if no queued message.", delegate(TcpAppInputCommand sender) { int queueID = Convert.ToInt32(sender.Command.Parameter("QueueID").Value); if (queueID == 0) { //ID not specified, get status for next queued command. if (sender.AppClient.NextQueuedCommand == null) { sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = "No queued message!"; return; } sender.Status = sender.AppClient.NextQueuedCommand.Status; switch (sender.AppClient.NextQueuedCommand.Status) { case TcpAppCommandStatus.BUSY: case TcpAppCommandStatus.QUEUED: sender.OutputMessage = string.Empty; break; default: lock (CommandQueue) { //Return result for all queued message except executing one. TcpAppInputCommand[] results = ResultQueue.Where(x => x.AppClient == sender.AppClient).ToArray(); TcpAppInputCommand nextQueue = null; foreach (TcpAppInputCommand cmd in results) { if (cmd.Status == TcpAppCommandStatus.BUSY || cmd.Status == TcpAppCommandStatus.QUEUED) { nextQueue = cmd; break; } if (cmd.Status == TcpAppCommandStatus.ERR) { cmd.Status = sender.Status; cmd.OutputMessage += "! "; //Prefix for command with error status. } ResultQueue.Remove(cmd); sender.OutputMessage += cmd.OutputMessage + "\n"; } //Return number of remaining queued commands sender.OutputMessage += CommandQueue.Where(x => x.AppClient == sender.AppClient).Count().ToString(); sender.AppClient.NextQueuedCommand = nextQueue; } break; } } else { //Return status of specific message. TcpAppInputCommand ptrCmd = CommandQueue.FirstOrDefault(x => x.AppClient == sender.AppClient && x.ID == queueID); if (ptrCmd == null) { ptrCmd = ResultQueue.FirstOrDefault(x => x.AppClient == sender.AppClient); if (ptrCmd != null) { ResultQueue.Remove(ptrCmd); } else { sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = "Invalid ID: " + queueID.ToString(); return; } } sender.OutputMessage = ptrCmd.OutputMessage; sender.Status = ptrCmd.Status; } }, TcpAppParameter.CreateOptionalParameter("QueueID", "Get status of specific message.", "0")); RegisterSystemCommand("Abort", "Abort last queued command.", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); if (sender.AppClient.NextQueuedCommand != null) { lock (CommandQueue) { CommandQueue.Remove(sender.AppClient.NextQueuedCommand); ResultQueue.Remove(sender.AppClient.NextQueuedCommand); sender.AppClient.NextQueuedCommand = null; } } sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("FlushQueue", "Flush message queue for calling client.", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); lock (CommandQueue) { CommandQueue.RemoveAll(x => x.AppClient == sender.AppClient); ResultQueue.RemoveAll(x => x.AppClient == sender.AppClient); sender.AppClient.NextQueuedCommand = null; } sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("FlushAllQueue", "Flush message queue for all clients.", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); lock (CommandQueue) { CommandQueue.Clear(); ResultQueue.Clear(); lock (AppClients) { foreach (TcpAppServerConnection client in AppClients) { client.NextQueuedCommand = null; } } } sender.Status = TcpAppCommandStatus.OK; }); //--- PLUGIN --- RegisterSystemCommand("PluginTypes?", "Get list of plugin class type. Use CreatePlugins command to instantiate type.", delegate(TcpAppInputCommand sender) { if (PluginTypes.Count == 0) { sender.OutputMessage = "-NONE-"; } else { sender.OutputMessage = string.Join(" ", PluginTypes.Select(x => x.Name).ToArray()); } sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("CreatePlugin", "Create an plugin object from listed plugin types. Command only valid after client Signin.", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); string typeName = sender.Command.Parameter("TypeName").Value; //Sanity Check - Type Name if (PluginTypes.FirstOrDefault(x => x.Name.Equals(typeName, StringComparison.InvariantCultureIgnoreCase)) == null) { throw new ArgumentException("Unknown plugin type: " + typeName); } Type pluginType = PluginTypes.FirstOrDefault(x => x.Name.Equals(typeName, StringComparison.InvariantCultureIgnoreCase)).Type; string aliasName; sender.OutputMessage = "Plugin created:"; foreach (string value in sender.Command.Parameter("Alias").Values) { aliasName = value; if (Commands.FirstOrDefault(x => string.Compare(x.Keyword, aliasName, true) == 0) != null) { throw new ArgumentException("Unable to create plugin with alias '" + aliasName + "'. Name already registered as command!"); } //Sanity Check - Verify alias name is not plugin type name if (PluginTypes.FirstOrDefault(x => string.Compare(x.Name, aliasName, true) == 0) != null) { throw new ArgumentException("Unable to create plugin with alias '" + aliasName + "'. Name already registered plugin type!"); } //Sanity Check - Alias Name if (_Plugins.FirstOrDefault(x => string.Compare(x.Alias, aliasName, true) == 0) != null) { throw new ArgumentException("Unable to create plugin with alias '" + aliasName + "'. Plugin already exists!"); } ITcpAppServerPlugin pluginInstance = Activator.CreateInstance(pluginType) as ITcpAppServerPlugin; pluginInstance.Alias = aliasName; _Plugins.Add(pluginInstance); PluginCreated?.Invoke(this, new TcpAppServerEventArgs(sender.AppClient) { Plugin = pluginInstance }); sender.OutputMessage += " " + aliasName; } sender.Status = TcpAppCommandStatus.OK; }, TcpAppParameter.CreateParameter("TypeName", "Plugin type name."), TcpAppParameter.CreateParameterArray("Alias", "Plugin object name, case insensitive.", false)); RegisterSystemCommand("Plugins?", "Return plugins list by alias name.", delegate(TcpAppInputCommand sender) { if (_Plugins.Count == 0) { sender.OutputMessage = "-NONE-"; } else { sender.OutputMessage = string.Join(TcpAppCommon.NewLine, _Plugins.Select(x => x.Alias + "(" + PluginTypes.FirstOrDefault(n => n.Type == x.GetType())?.Name + ")").ToArray()); } sender.Status = TcpAppCommandStatus.OK; }); RegisterSystemCommand("DisposePlugin", "Delete plugin by alias name. Command only valid after client Signin.", delegate(TcpAppInputCommand sender) { VerifyUserSignedIn(sender); string alias = sender.Command.Parameter("Alias").Value; ITcpAppServerPlugin item = _Plugins.FirstOrDefault(x => string.Compare(x.Alias, alias, true) == 0); if (item == null) { sender.OutputMessage = "Plugin [" + alias + "] not found / disposed."; sender.Status = TcpAppCommandStatus.OK; return; } else { if (item.DisposeRequest() == true) { _Plugins.Remove(item); PluginDisposed?.Invoke(this, new TcpAppServerEventArgs(sender.AppClient) { Plugin = item }); sender.OutputMessage = alias + " disposed."; sender.Status = TcpAppCommandStatus.OK; } else { sender.Status = TcpAppCommandStatus.ERR; sender.OutputMessage = "Unable to dispose " + alias; } } }, TcpAppParameter.CreateParameter("Alias", "Plugin alias name.")); }