Mercurial > irccd
changeset 127:77f950caab35
Irccd: implement RuleService, #498
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 11 May 2016 13:27:39 +0200 |
parents | 49572a69c41d |
children | 2d8343b86e2e |
files | irccd/main.cpp lib/irccd/CMakeSources.cmake lib/irccd/config.cpp lib/irccd/irccd.cpp lib/irccd/irccd.hpp lib/irccd/rule.cpp lib/irccd/rule.hpp lib/irccd/server-event.cpp lib/irccd/service-rule.cpp lib/irccd/service-rule.hpp lib/irccd/service-transport.cpp tests/js-timer/main.cpp tests/rules/main.cpp |
diffstat | 13 files changed, 225 insertions(+), 139 deletions(-) [+] |
line wrap: on
line diff
--- a/irccd/main.cpp Wed May 11 13:00:40 2016 +0200 +++ b/irccd/main.cpp Wed May 11 13:27:39 2016 +0200 @@ -37,6 +37,7 @@ #include <irccd/logger.hpp> #include <irccd/options.hpp> #include <irccd/path.hpp> +#include <irccd/service-rule.hpp> #include <irccd/service-server.hpp> #include <irccd/service-transport.hpp> #include <irccd/system.hpp> @@ -239,7 +240,7 @@ // [rule] section. for (const auto &rule : config.loadRules()) { - instance->addRule(rule); + instance->ruleService().add(rule); } // [plugin] section.
--- a/lib/irccd/CMakeSources.cmake Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/CMakeSources.cmake Wed May 11 13:27:39 2016 +0200 @@ -64,6 +64,7 @@ ${CMAKE_CURRENT_LIST_DIR}/server-state-disconnected.hpp ${CMAKE_CURRENT_LIST_DIR}/service.hpp ${CMAKE_CURRENT_LIST_DIR}/service-interrupt.hpp + ${CMAKE_CURRENT_LIST_DIR}/service-rule.hpp ${CMAKE_CURRENT_LIST_DIR}/service-server.hpp ${CMAKE_CURRENT_LIST_DIR}/service-transport.hpp ${CMAKE_CURRENT_LIST_DIR}/sockets.hpp @@ -134,6 +135,7 @@ ${CMAKE_CURRENT_LIST_DIR}/server-state-connecting.cpp ${CMAKE_CURRENT_LIST_DIR}/server-state-disconnected.cpp ${CMAKE_CURRENT_LIST_DIR}/service-interrupt.cpp + ${CMAKE_CURRENT_LIST_DIR}/service-rule.cpp ${CMAKE_CURRENT_LIST_DIR}/service-server.cpp ${CMAKE_CURRENT_LIST_DIR}/service-transport.cpp ${CMAKE_CURRENT_LIST_DIR}/sockets.cpp
--- a/lib/irccd/config.cpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/config.cpp Wed May 11 13:27:39 2016 +0200 @@ -23,6 +23,7 @@ #include "config.hpp" #include "fs.hpp" #include "irccd.hpp" +#include "logger.hpp" #include "path.hpp" #include "rule.hpp" #include "server.hpp"
--- a/lib/irccd/irccd.cpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/irccd.cpp Wed May 11 13:27:39 2016 +0200 @@ -26,6 +26,7 @@ #include "logger.hpp" #include "path.hpp" #include "service-interrupt.hpp" +#include "service-rule.hpp" #include "service-server.hpp" #include "service-transport.hpp" #include "util.hpp" @@ -42,6 +43,7 @@ : 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>()) { m_services.push_back(m_interruptService); m_services.push_back(m_serverService);
--- a/lib/irccd/irccd.hpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/irccd.hpp Wed May 11 13:27:39 2016 +0200 @@ -26,8 +26,6 @@ #include <algorithm> #include <atomic> -#include <cassert> -#include <condition_variable> #include <functional> #include <memory> #include <mutex> @@ -40,14 +38,13 @@ #endif #include "application.hpp" -#include "logger.hpp" -#include "rule.hpp" namespace irccd { class InterruptService; class Irccd; class Plugin; +class RuleService; class ServerService; class Service; class TransportService; @@ -68,13 +65,11 @@ std::vector<std::shared_ptr<Plugin>> m_plugins; #endif - // Rules. - std::vector<Rule> m_rules; - // Services. std::shared_ptr<InterruptService> m_interruptService; std::shared_ptr<ServerService> m_serverService; std::shared_ptr<TransportService> m_transportService; + std::shared_ptr<RuleService> m_ruleService; std::vector<std::shared_ptr<Service>> m_services; /* @@ -133,6 +128,16 @@ } /** + * Access the rule service. + * + * \return the service + */ + inline RuleService &ruleService() noexcept + { + return *m_ruleService; + } + + /** * Add an event to the queue. This will immediately signals the event loop to interrupt itself to dispatch * the pending events. * @@ -227,60 +232,6 @@ #endif // !WITH_JS - /* - * Rule management - * ---------------------------------------------------------- - * - * Functions for adding, creating new rules that are used to filter IRC events before being processed - * by JavaScript plugins. - */ - - /** - * Append a rule. - * - * \param rule the rule to append - */ - inline void addRule(Rule rule) - { - m_rules.push_back(std::move(rule)); - } - - /** - * Insert a new rule at the specified position. - * - * \param rule the rule - * \param position the position - */ - inline void insertRule(Rule rule, unsigned position) - { - assert(position <= m_rules.size()); - - m_rules.insert(m_rules.begin() + position, std::move(rule)); - } - - /** - * Get the list of rules. - * - * \return the list of rules - */ - inline const std::vector<Rule> &rules() const noexcept - { - return m_rules; - } - - /** - * Remove a new rule from the specified position. - * - * \pre position must be valid - * \param position the position - */ - inline void removeRule(unsigned position) - { - assert(position < m_rules.size()); - - m_rules.erase(m_rules.begin() + position); - } - /** * Loop forever by calling poll() and dispatch() indefinitely. */
--- a/lib/irccd/rule.cpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/rule.cpp Wed May 11 13:27:39 2016 +0200 @@ -50,40 +50,6 @@ namespace irccd { -bool Rule::solve(const std::vector<Rule> &rules, - const std::string &server, - const std::string &channel, - const std::string &origin, - const std::string &plugin, - const std::string &event) noexcept -{ - bool result = true; - - log::debug() << "rule: solving for:\n" - << " server: " << server << "\n" - << " channel: " << channel << "\n" - << " origin: " << origin << "\n" - << " plugin: " << plugin << "\n" - << " event: " << event << std::endl; - - int i = 0; - for (const Rule &rule : rules) { - log::debug() << " candidate " << i++ << ":\n" - << " servers: " << util::join(rule.m_servers.begin(), rule.m_servers.end()) << "\n" - << " channels: " << util::join(rule.m_channels.begin(), rule.m_channels.end()) << "\n" - << " origins: " << util::join(rule.m_origins.begin(), rule.m_origins.end()) << "\n" - << " plugins: " << util::join(rule.m_plugins.begin(), rule.m_plugins.end()) << "\n" - << " events: " << util::join(rule.m_events.begin(), rule.m_events.end()) << "\n" - << " action: " << ((rule.m_action == RuleAction::Accept) ? "accept" : "drop") << std::endl; - - if (rule.match(server, channel, origin, plugin, event)) { - result = rule.action() == RuleAction::Accept; - } - } - - return result; -} - bool Rule::matchMap(const RuleSet &map, const std::string &value) const noexcept { return value.empty() || map.empty() || map.count(value) == 1;
--- a/lib/irccd/rule.hpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/rule.hpp Wed May 11 13:27:39 2016 +0200 @@ -50,7 +50,7 @@ * \class Rule * \brief Manage rule to activate or deactive events. */ -class Rule final { +class Rule { private: RuleSet m_servers; RuleSet m_channels; @@ -67,24 +67,6 @@ public: /** - * Resolve the action to execute with the specified list of rules. - * - * \param rules the list of rules - * \param server the server name - * \param channel the channel name - * \param origin the origin - * \param plugin the plugin name - * \param event the event name (e.g onKick) - * \return true if the plugin must be called - */ - static bool solve(const std::vector<Rule> &rules, - const std::string &server, - const std::string &channel, - const std::string &origin, - const std::string &plugin, - const std::string &event) noexcept; - - /** * Rule constructor. * * \param servers the server list
--- a/lib/irccd/server-event.cpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/server-event.cpp Wed May 11 13:27:39 2016 +0200 @@ -17,8 +17,9 @@ */ #include "irccd.hpp" +#include "logger.hpp" #include "server-event.hpp" -#include "rule.hpp" +#include "service-rule.hpp" namespace irccd { @@ -39,7 +40,7 @@ { for (auto &plugin : irccd.plugins()) { auto eventname = m_plugin_function_name(*plugin); - auto allowed = Rule::solve(irccd.rules(), m_server, m_target, m_origin, plugin->name(), eventname); + auto allowed = irccd.ruleService().solve(m_server, m_target, m_origin, plugin->name(), eventname); if (!allowed) { log::debug() << "rule: event skipped on match" << std::endl;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/irccd/service-rule.cpp Wed May 11 13:27:39 2016 +0200 @@ -0,0 +1,79 @@ +/* + * service-rule.cpp -- store and solve rules + * + * 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 <cassert> + +#include <format.h> + +#include "logger.hpp" +#include "service-rule.hpp" +#include "util.hpp" + +using namespace fmt::literals; + +namespace irccd { + +void RuleService::add(Rule rule) +{ + m_rules.push_back(std::move(rule)); +} + +void RuleService::insert(Rule rule, unsigned position) +{ + assert(position <= m_rules.size()); + + m_rules.insert(m_rules.begin() + position, std::move(rule)); +} + +void RuleService::remove(unsigned position) +{ + assert(position < m_rules.size()); + + m_rules.erase(m_rules.begin() + position); +} + +bool RuleService::solve(const std::string &server, + const std::string &channel, + const std::string &origin, + const std::string &plugin, + const std::string &event) noexcept +{ + bool result = true; + + log::debug("rule: solving for server={}, channel={}, origin={}, plugin={}, event={}"_format(server, channel, + origin, plugin, event)); + + int i = 0; + for (const Rule &rule : m_rules) { + log::debug() << " candidate " << i++ << ":\n" + << " servers: " << util::join(rule.servers().begin(), rule.servers().end()) << "\n" + << " channels: " << util::join(rule.channels().begin(), rule.channels().end()) << "\n" + << " origins: " << util::join(rule.origins().begin(), rule.origins().end()) << "\n" + << " plugins: " << util::join(rule.plugins().begin(), rule.plugins().end()) << "\n" + << " events: " << util::join(rule.events().begin(), rule.events().end()) << "\n" + << " action: " << ((rule.action() == RuleAction::Accept) ? "accept" : "drop") << std::endl; + + if (rule.match(server, channel, origin, plugin, event)) { + result = rule.action() == RuleAction::Accept; + } + } + + return result; +} + +} // !irccd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/irccd/service-rule.hpp Wed May 11 13:27:39 2016 +0200 @@ -0,0 +1,103 @@ +/* + * service-rule.hpp -- store and solve rules + * + * 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_RULE_HPP +#define IRCCD_SERVICE_RULE_HPP + +/** + * \file service-rule.hpp + * \brief Store and solve rules. + */ + +#include <vector> + +#include "rule.hpp" + +namespace irccd { + +/** + * \brief Store and solve rules. + */ +class RuleService { +private: + std::vector<Rule> m_rules; + +public: + /** + * Get the list of rules. + * + * \return the list of rules + */ + inline const std::vector<Rule> &rules() const noexcept + { + return m_rules; + } + + /** + * Get the number of rules. + * + * \return the number of rules + */ + inline unsigned length() const noexcept + { + return m_rules.size(); + } + + /** + * Append a rule. + * + * \param rule the rule to append + */ + void add(Rule rule); + + /** + * Insert a new rule at the specified position. + * + * \param rule the rule + * \param position the position + */ + void insert(Rule rule, unsigned position); + + /** + * Remove a new rule from the specified position. + * + * \pre position must be valid + * \param position the position + */ + void remove(unsigned position); + + /** + * Resolve the action to execute with the specified list of rules. + * + * \param server the server name + * \param channel the channel name + * \param origin the origin + * \param plugin the plugin name + * \param event the event name (e.g onKick) + * \return true if the plugin must be called + */ + bool solve(const std::string &server, + const std::string &channel, + const std::string &origin, + const std::string &plugin, + const std::string &event) noexcept; +}; + +} // !irccd + +#endif // !IRCCD_SERVICE_RULE_HPP
--- a/lib/irccd/service-transport.cpp Wed May 11 13:00:40 2016 +0200 +++ b/lib/irccd/service-transport.cpp Wed May 11 13:27:39 2016 +0200 @@ -17,6 +17,7 @@ */ #include "irccd.hpp" +#include "logger.hpp" #include "service-transport.hpp" #include "transport-client.hpp" #include "transport-server.hpp" @@ -178,4 +179,4 @@ } } -} // !irccd \ No newline at end of file +} // !irccd
--- a/tests/js-timer/main.cpp Wed May 11 13:00:40 2016 +0200 +++ b/tests/js-timer/main.cpp Wed May 11 13:27:39 2016 +0200 @@ -20,6 +20,7 @@ #include <irccd/elapsed-timer.hpp> #include <irccd/irccd.hpp> +#include <irccd/logger.hpp> #include <irccd/system.hpp> using namespace irccd;
--- a/tests/rules/main.cpp Wed May 11 13:00:40 2016 +0200 +++ b/tests/rules/main.cpp Wed May 11 13:27:39 2016 +0200 @@ -19,6 +19,7 @@ #include <gtest/gtest.h> #include <irccd/rule.hpp> +#include <irccd/service-rule.hpp> namespace irccd { @@ -64,13 +65,13 @@ */ class RulesTest : public testing::Test { protected: - std::vector<Rule> m_rules; + RuleService m_rules; RulesTest() { // #1 { - m_rules.push_back({ + m_rules.add({ RuleSet{ }, // Servers RuleSet{ "#staff" }, // Channels RuleSet{ }, // Origins @@ -82,7 +83,7 @@ // #2 { - m_rules.push_back({ + m_rules.add({ RuleSet{ "unsafe" }, RuleSet{ "#staff" }, RuleSet{ }, @@ -94,7 +95,7 @@ // #3-1 { - m_rules.push_back({ + m_rules.add({ RuleSet{}, RuleSet{}, RuleSet{}, @@ -106,7 +107,7 @@ // #3-2 { - m_rules.push_back({ + m_rules.add({ RuleSet{ "malikania", "localhost" }, RuleSet{ "#games" }, RuleSet{ }, @@ -116,11 +117,6 @@ }); } } - - ~RulesTest() - { - m_rules.clear(); - } }; TEST_F(RulesTest, basicMatch1) @@ -196,40 +192,40 @@ TEST_F(RulesTest, basicSolve) { /* Allowed */ - ASSERT_TRUE(Rule::solve(m_rules, "malikania", "#staff", "", "a", "onMessage")); + ASSERT_TRUE(m_rules.solve("malikania", "#staff", "", "a", "onMessage")); /* Allowed */ - ASSERT_TRUE(Rule::solve(m_rules, "freenode", "#staff", "", "b", "onTopic")); + ASSERT_TRUE(m_rules.solve("freenode", "#staff", "", "b", "onTopic")); /* Not allowed */ - ASSERT_FALSE(Rule::solve(m_rules, "malikania", "#staff", "", "", "onCommand")); + ASSERT_FALSE(m_rules.solve("malikania", "#staff", "", "", "onCommand")); /* Not allowed */ - ASSERT_FALSE(Rule::solve(m_rules, "freenode", "#staff", "", "c", "onCommand")); + ASSERT_FALSE(m_rules.solve("freenode", "#staff", "", "c", "onCommand")); /* Allowed */ - ASSERT_TRUE(Rule::solve(m_rules, "unsafe", "#staff", "", "c", "onCommand")); + ASSERT_TRUE(m_rules.solve("unsafe", "#staff", "", "c", "onCommand")); } TEST_F(RulesTest, gamesSolve) { /* Allowed */ - ASSERT_TRUE(Rule::solve(m_rules, "malikania", "#games", "", "game", "onMessage")); + ASSERT_TRUE(m_rules.solve("malikania", "#games", "", "game", "onMessage")); /* Allowed */ - ASSERT_TRUE(Rule::solve(m_rules, "localhost", "#games", "", "game", "onMessage")); + ASSERT_TRUE(m_rules.solve("localhost", "#games", "", "game", "onMessage")); /* Allowed */ - ASSERT_TRUE(Rule::solve(m_rules, "malikania", "#games", "", "game", "onCommand")); + ASSERT_TRUE(m_rules.solve("malikania", "#games", "", "game", "onCommand")); /* Not allowed */ - ASSERT_FALSE(Rule::solve(m_rules, "malikania", "#games", "", "game", "onQuery")); + ASSERT_FALSE(m_rules.solve("malikania", "#games", "", "game", "onQuery")); /* Not allowed */ - ASSERT_FALSE(Rule::solve(m_rules, "freenode", "#no", "", "game", "onMessage")); + ASSERT_FALSE(m_rules.solve("freenode", "#no", "", "game", "onMessage")); /* Not allowed */ - ASSERT_FALSE(Rule::solve(m_rules, "malikania", "#test", "", "game", "onMessage")); + ASSERT_FALSE(m_rules.solve("malikania", "#test", "", "game", "onMessage")); } } // !irccd