changeset 161:49095643ae67

Irccd: store commands in a dedicated CommandService, #508
author David Demelier <markand@malikania.fr>
date Tue, 24 May 2016 13:56:35 +0200
parents c1acfacc46bd
children a24e2de22565
files lib/irccd/CMakeSources.cmake lib/irccd/application.cpp lib/irccd/application.hpp lib/irccd/cmd-help.cpp lib/irccd/irccd.cpp lib/irccd/irccd.hpp lib/irccd/irccdctl.cpp lib/irccd/irccdctl.hpp lib/irccd/service-command.cpp lib/irccd/service-command.hpp lib/irccd/service-server.cpp lib/irccd/service-transport.cpp
diffstat 12 files changed, 213 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/lib/irccd/CMakeSources.cmake	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/CMakeSources.cmake	Tue May 24 13:56:35 2016 +0200
@@ -1,7 +1,6 @@
 set(
 	HEADERS
 	${CMAKE_CURRENT_LIST_DIR}/alias.hpp
-	${CMAKE_CURRENT_LIST_DIR}/application.hpp
 	${CMAKE_CURRENT_LIST_DIR}/connection.hpp
 	${CMAKE_CURRENT_LIST_DIR}/cmd-help.hpp
 	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-info.hpp
@@ -63,6 +62,7 @@
 	${CMAKE_CURRENT_LIST_DIR}/server-state-connecting.hpp
 	${CMAKE_CURRENT_LIST_DIR}/server-state-disconnected.hpp
 	${CMAKE_CURRENT_LIST_DIR}/service.hpp
+	${CMAKE_CURRENT_LIST_DIR}/service-command.hpp
 	${CMAKE_CURRENT_LIST_DIR}/service-interrupt.hpp
 	${CMAKE_CURRENT_LIST_DIR}/service-module.hpp
 	${CMAKE_CURRENT_LIST_DIR}/service-plugin.hpp
@@ -81,7 +81,6 @@
 set(
 	SOURCES
 	${CMAKE_CURRENT_LIST_DIR}/alias.cpp
-	${CMAKE_CURRENT_LIST_DIR}/application.cpp
 	${CMAKE_CURRENT_LIST_DIR}/connection.cpp
 	${CMAKE_CURRENT_LIST_DIR}/config.cpp
 	${CMAKE_CURRENT_LIST_DIR}/cmd-help.cpp
@@ -137,6 +136,7 @@
 	${CMAKE_CURRENT_LIST_DIR}/server-state-connected.cpp
 	${CMAKE_CURRENT_LIST_DIR}/server-state-connecting.cpp
 	${CMAKE_CURRENT_LIST_DIR}/server-state-disconnected.cpp
+	${CMAKE_CURRENT_LIST_DIR}/service-command.cpp
 	${CMAKE_CURRENT_LIST_DIR}/service-interrupt.cpp
 	${CMAKE_CURRENT_LIST_DIR}/service-module.cpp
 	${CMAKE_CURRENT_LIST_DIR}/service-plugin.cpp
--- a/lib/irccd/application.cpp	Tue May 24 13:00:35 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * application.cpp -- super base class to create irccd front ends
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "application.hpp"
-#include "cmd-help.hpp"
-#include "cmd-plugin-info.hpp"
-#include "cmd-plugin-list.hpp"
-#include "cmd-plugin-load.hpp"
-#include "cmd-plugin-reload.hpp"
-#include "cmd-plugin-unload.hpp"
-#include "cmd-server-cmode.hpp"
-#include "cmd-server-cnotice.hpp"
-#include "cmd-server-connect.hpp"
-#include "cmd-server-disconnect.hpp"
-#include "cmd-server-info.hpp"
-#include "cmd-server-invite.hpp"
-#include "cmd-server-join.hpp"
-#include "cmd-server-kick.hpp"
-#include "cmd-server-list.hpp"
-#include "cmd-server-me.hpp"
-#include "cmd-server-message.hpp"
-#include "cmd-server-mode.hpp"
-#include "cmd-server-nick.hpp"
-#include "cmd-server-notice.hpp"
-#include "cmd-server-part.hpp"
-#include "cmd-server-reconnect.hpp"
-#include "cmd-server-topic.hpp"
-#include "cmd-watch.hpp"
-
-namespace irccd {
-
-Application::Application()
-{
-	// Register all commands.
-	addCommand(std::make_unique<command::Help>());
-	addCommand(std::make_unique<command::PluginInfo>());
-	addCommand(std::make_unique<command::PluginList>());
-	addCommand(std::make_unique<command::PluginLoad>());
-	addCommand(std::make_unique<command::PluginReload>());
-	addCommand(std::make_unique<command::PluginUnload>());
-	addCommand(std::make_unique<command::ServerChannelMode>());
-	addCommand(std::make_unique<command::ServerChannelNotice>());
-	addCommand(std::make_unique<command::ServerConnect>());
-	addCommand(std::make_unique<command::ServerDisconnect>());
-	addCommand(std::make_unique<command::ServerInfo>());
-	addCommand(std::make_unique<command::ServerInvite>());
-	addCommand(std::make_unique<command::ServerJoin>());
-	addCommand(std::make_unique<command::ServerKick>());
-	addCommand(std::make_unique<command::ServerList>());
-	addCommand(std::make_unique<command::ServerMe>());
-	addCommand(std::make_unique<command::ServerMessage>());
-	addCommand(std::make_unique<command::ServerMode>());
-	addCommand(std::make_unique<command::ServerNick>());
-	addCommand(std::make_unique<command::ServerNotice>());
-	addCommand(std::make_unique<command::ServerPart>());
-	addCommand(std::make_unique<command::ServerReconnect>());
-	addCommand(std::make_unique<command::ServerTopic>());
-	addCommand(std::make_unique<command::Watch>());
-}
-
-} // !irccd
--- a/lib/irccd/application.hpp	Tue May 24 13:00:35 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * application.hpp -- super base class to create irccd front ends
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_APPLICATION_HPP
-#define IRCCD_APPLICATION_HPP
-
-/**
- * \file application.hpp
- * \brief Base class for irccd and irccdctl.
- */
-
-#include <cassert>
-#include <memory>
-#include <unordered_map>
-
-#include "command.hpp"
-#include "sysconfig.hpp"
-
-namespace irccd {
-
-/**
- * Map of commands.
- */
-using RemoteCommands = std::unordered_map<std::string, std::unique_ptr<RemoteCommand>>;
-
-/**
- * \brief Base class for creating irccd front ends.
- */
-class Application {
-protected:
-	/**
-	 * Map of commands.
-	 */
-	RemoteCommands m_commands;
-
-public:
-	/**
-	 * Create the application and fill the commands with predefined commands.
-	 */
-	IRCCD_EXPORT Application();
-
-	/**
-	 * Access the remote commands.
-	 *
-	 * \return the commands
-	 */
-	inline const RemoteCommands &commands() const noexcept
-	{
-		return m_commands;
-	}
-
-	/**
-	 * Add a new command.
-	 *
-	 * \pre command must not be null
-	 * \pre the command must not exist
-	 * \param command the command
-	 */
-	inline void addCommand(std::unique_ptr<RemoteCommand> command)
-	{
-		assert(command);
-		assert(m_commands.count(command->name()) == 0);
-
-		m_commands.emplace(command->name(), std::move(command));
-	}
-};
-
-} // !irccd
-
-#endif // !_IRCCD_APPLICATION_HPP_
--- a/lib/irccd/cmd-help.cpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/cmd-help.cpp	Tue May 24 13:56:35 2016 +0200
@@ -41,12 +41,12 @@
 
 json::Value Help::request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const
 {
-	auto it = irccdctl.commands().find(args.arg(0U));
+	auto it = irccdctl.commandService().find(args.arg(0U));
 
-	if (it == irccdctl.commands().end())
+	if (!it)
 		log::warning() << "there is no command named: " << args.arg(0U) << std::endl;
 	else
-		log::warning() << it->second->usage() << std::flush;
+		log::warning() << it->usage() << std::flush;
 
 	return nullptr;
 }
--- a/lib/irccd/irccd.cpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/irccd.cpp	Tue May 24 13:56:35 2016 +0200
@@ -18,6 +18,7 @@
 
 #include "irccd.hpp"
 #include "logger.hpp"
+#include "service-command.hpp"
 #include "service-interrupt.hpp"
 #include "service-module.hpp"
 #include "service-plugin.hpp"
@@ -33,7 +34,8 @@
 namespace irccd {
 
 Irccd::Irccd()
-	: m_interruptService(std::make_shared<InterruptService>())
+	: m_commandService(std::make_shared<CommandService>())
+	, m_interruptService(std::make_shared<InterruptService>())
 	, m_serverService(std::make_shared<ServerService>(*this))
 	, m_transportService(std::make_shared<TransportService>(*this))
 	, m_ruleService(std::make_shared<RuleService>())
--- a/lib/irccd/irccd.hpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/irccd.hpp	Tue May 24 13:56:35 2016 +0200
@@ -31,13 +31,12 @@
 #include <mutex>
 #include <vector>
 
-#include "application.hpp"
 #include "sysconfig.hpp"
 
 namespace irccd {
 
+class CommandService;
 class InterruptService;
-class Irccd;
 class ModuleService;
 class PluginService;
 class RuleService;
@@ -49,7 +48,7 @@
  * \class Irccd
  * \brief Irccd main instance.
  */
-class Irccd : public Application {
+class Irccd {
 private:
 	// Main loop stuff.
 	std::atomic<bool> m_running{true};
@@ -57,6 +56,7 @@
 	std::vector<std::function<void (Irccd &)>> m_events;
 
 	// Services.
+	std::shared_ptr<CommandService> m_commandService;
 	std::shared_ptr<InterruptService> m_interruptService;
 	std::shared_ptr<ServerService> m_serverService;
 	std::shared_ptr<TransportService> m_transportService;
@@ -89,6 +89,16 @@
 	}
 
 	/**
+	 * Access the command service.
+	 *
+	 * \return the service
+	 */
+	inline CommandService &commandService() noexcept
+	{
+		return *m_commandService;
+	}
+
+	/**
 	 * Access the server service.
 	 *
 	 * \return the service
--- a/lib/irccd/irccdctl.cpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/irccdctl.cpp	Tue May 24 13:56:35 2016 +0200
@@ -25,6 +25,7 @@
 
 #include <format.h>
 
+#include "command.hpp"
 #include "elapsed-timer.hpp"
 #include "fs.hpp"
 #include "ini.hpp"
@@ -205,7 +206,7 @@
 		// This is the alias name.
 		Alias alias(option.key());
 
-		if (m_commands.count(option.key()) > 0)
+		if (m_commandService.contains(option.key()))
 			throw std::invalid_argument("there is already a command named " + option.key());
 
 		// Iterate over the list of commands to execute for this alias.
@@ -450,10 +451,10 @@
 	if (alias != m_aliases.end())
 		exec(alias->second, args);
 	else {
-		auto cmd = m_commands.find(name);
+		auto cmd = m_commandService.find(name);
 
-		if (cmd != m_commands.end())
-			exec(*cmd->second, args);
+		if (cmd)
+			exec(*cmd, args);
 		else
 			throw std::invalid_argument("no alias or command named " + name);
 	}
--- a/lib/irccd/irccdctl.hpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/irccdctl.hpp	Tue May 24 13:56:35 2016 +0200
@@ -30,9 +30,9 @@
 #include <string>
 
 #include "alias.hpp"
-#include "application.hpp"
 #include "connection.hpp"
 #include "options.hpp"
+#include "service-command.hpp"
 
 namespace irccd {
 
@@ -47,7 +47,7 @@
 /**
  * \brief Main irccdctl class.
  */
-class Irccdctl : public Application {
+class Irccdctl {
 private:
 	// Irccd's information.
 	unsigned short m_major{0};
@@ -58,6 +58,9 @@
 	bool m_javascript{true};
 	bool m_ssl{true};
 
+	// Commands.
+	CommandService m_commandService;
+
 	std::unique_ptr<Connection> m_connection;
 	std::unordered_map<std::string, Alias> m_aliases;
 
@@ -79,6 +82,16 @@
 
 public:
 	/**
+	 * Get the command service.
+	 *
+	 * \return the command service
+	 */
+	inline CommandService &commandService() noexcept
+	{
+		return m_commandService;
+	}
+
+	/**
 	 * Execute the given command and wait for its result.
 	 *
 	 * \param cmd the command
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/service-command.cpp	Tue May 24 13:56:35 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ * service-command.cpp -- store remote commands
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <algorithm>
+
+#include "cmd-help.hpp"
+#include "cmd-plugin-info.hpp"
+#include "cmd-plugin-list.hpp"
+#include "cmd-plugin-load.hpp"
+#include "cmd-plugin-reload.hpp"
+#include "cmd-plugin-unload.hpp"
+#include "cmd-server-cmode.hpp"
+#include "cmd-server-cnotice.hpp"
+#include "cmd-server-connect.hpp"
+#include "cmd-server-disconnect.hpp"
+#include "cmd-server-info.hpp"
+#include "cmd-server-invite.hpp"
+#include "cmd-server-join.hpp"
+#include "cmd-server-kick.hpp"
+#include "cmd-server-list.hpp"
+#include "cmd-server-me.hpp"
+#include "cmd-server-message.hpp"
+#include "cmd-server-mode.hpp"
+#include "cmd-server-nick.hpp"
+#include "cmd-server-notice.hpp"
+#include "cmd-server-part.hpp"
+#include "cmd-server-reconnect.hpp"
+#include "cmd-server-topic.hpp"
+#include "cmd-watch.hpp"
+#include "service-command.hpp"
+
+namespace irccd {
+
+CommandService::CommandService()
+	: m_commands{
+		std::make_shared<command::Help>(),
+		std::make_shared<command::PluginInfo>(),
+		std::make_shared<command::PluginList>(),
+		std::make_shared<command::PluginLoad>(),
+		std::make_shared<command::PluginReload>(),
+		std::make_shared<command::PluginUnload>(),
+		std::make_shared<command::ServerChannelMode>(),
+		std::make_shared<command::ServerChannelNotice>(),
+		std::make_shared<command::ServerConnect>(),
+		std::make_shared<command::ServerDisconnect>(),
+		std::make_shared<command::ServerInfo>(),
+		std::make_shared<command::ServerInvite>(),
+		std::make_shared<command::ServerJoin>(),
+		std::make_shared<command::ServerKick>(),
+		std::make_shared<command::ServerList>(),
+		std::make_shared<command::ServerMe>(),
+		std::make_shared<command::ServerMessage>(),
+		std::make_shared<command::ServerMode>(),
+		std::make_shared<command::ServerNick>(),
+		std::make_shared<command::ServerNotice>(),
+		std::make_shared<command::ServerPart>(),
+		std::make_shared<command::ServerReconnect>(),
+		std::make_shared<command::ServerTopic>(),
+		std::make_shared<command::Watch>(),
+	}
+{
+}
+
+bool CommandService::contains(const std::string &name) const noexcept
+{
+	return find(name) != nullptr;
+}
+
+std::shared_ptr<RemoteCommand> CommandService::find(const std::string &name) const noexcept
+{
+	auto it = std::find_if(m_commands.begin(), m_commands.end(), [&] (const auto &cmd) {
+		return cmd->name() == name;
+	});
+
+	return it == m_commands.end() ? nullptr : *it;
+}
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/service-command.hpp	Tue May 24 13:56:35 2016 +0200
@@ -0,0 +1,70 @@
+/*
+ * service-command.hpp -- store remote commands
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SERVICE_COMMAND_HPP
+#define IRCCD_SERVICE_COMMAND_HPP
+
+/**
+ * \file service-command.hpp
+ * \brief Store remote commands.
+ */
+
+#include <memory>
+#include <vector>
+
+#include "sysconfig.hpp"
+
+namespace irccd {
+
+class RemoteCommand;
+
+/**
+ * \brief Store remote commands.
+ */
+class CommandService {
+private:
+	std::vector<std::shared_ptr<RemoteCommand>> m_commands;
+
+public:
+	/**
+	 * Default constructor.
+	 *
+	 * Populate the commands with predefined ones.
+	 */
+	IRCCD_EXPORT CommandService();
+
+	/**
+	 * Tells if a command exists.
+	 *
+	 * \param name the command name
+	 * \return true if the command exists
+	 */
+	IRCCD_EXPORT bool contains(const std::string &name) const noexcept;
+
+	/**
+	 * Find a command by name.
+	 *
+	 * \param name the command name
+	 * \return the command or empty one if not found
+	 */
+	IRCCD_EXPORT std::shared_ptr<RemoteCommand> find(const std::string &name) const noexcept;
+};
+
+} // !irccd
+
+#endif // !IRCCD_SERVICE_COMMAND_HPP
--- a/lib/irccd/service-server.cpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/service-server.cpp	Tue May 24 13:56:35 2016 +0200
@@ -21,6 +21,7 @@
 #include <format.h>
 
 #include "irccd.hpp"
+#include "json.hpp"
 #include "logger.hpp"
 #include "plugin.hpp"
 #include "server.hpp"
--- a/lib/irccd/service-transport.cpp	Tue May 24 13:00:35 2016 +0200
+++ b/lib/irccd/service-transport.cpp	Tue May 24 13:56:35 2016 +0200
@@ -16,8 +16,11 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "command.hpp"
 #include "irccd.hpp"
+#include "json.hpp"
 #include "logger.hpp"
+#include "service-command.hpp"
 #include "service-transport.hpp"
 #include "transport-client.hpp"
 #include "transport-server.hpp"
@@ -44,9 +47,9 @@
 		}
 
 		// 2. Search for a command
-		auto it = m_irccd.commands().find(name->toString());
+		auto cmd = m_irccd.commandService().find(name->toString());
 
-		if (it == m_irccd.commands().end()) {
+		if (!cmd) {
 			// TODO: send error again
 			log::warning("command does not exists");
 			return;
@@ -56,12 +59,11 @@
 		json::Value response = json::object({});
 
 		try {
-			response = it->second->exec(m_irccd, object);
+			response = cmd->exec(m_irccd, object);
 
 			// Adjust if command has returned something else.
-			if (!response.isObject()) {
+			if (!response.isObject())
 				response = json::object({});
-			}
 
 			response.insert("status", true);
 		} catch (const std::exception &ex) {
@@ -70,7 +72,7 @@
 		}
 
 		// 4. Store the command name result.
-		response.insert("response", it->first);
+		response.insert("response", name->toString());
 
 		// 5. Send the result.
 		tc->send(response.toJson(0));