From dce6e14e3eb349e14c708f01aa67208b17fce697 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 17 Sep 2015 16:59:09 +0200 Subject: [PATCH] os: generalize Session_label, Session_policy The utilities in os/session_policy.h used to be tailored for the matching of session arguments against a server-side policy configuration. However, the policy-matching part is useful in other situations, too. This patch removes the tight coupling with the session-argument parsing (via Arg_string) and the hard-wired use of 'Genode::config()'. To make the utilities more versatile, the 'Session_label' has become a 'Genode::String' (at the time when we originally introduced the 'Session_label', there was no 'Genode::String'). The parsing of the session arguments happens in the constructor of this special 'String'. The constructor of 'Session_policy' now takes a 'Genode::String' as argument. So it can be used with the 'Session_label' but also with other 'String' types. Furthermore, the implicit use of 'Genode::config()' can be overridden by explicitly specifying the config node as an argument. --- repos/os/include/os/session_policy.h | 130 ++++++++++++------------ repos/os/src/server/nitpicker/session.h | 2 +- 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/repos/os/include/os/session_policy.h b/repos/os/include/os/session_policy.h index b5cc46721..664a12a2c 100644 --- a/repos/os/include/os/session_policy.h +++ b/repos/os/include/os/session_policy.h @@ -18,38 +18,33 @@ #include namespace Genode { - - class Session_label; - class Session_policy; + + struct Session_label; + class Session_policy; } -class Genode::Session_label +struct Genode::Session_label : String<128> { - public: + Session_label() { } - enum { MAX_LEN = 128 }; + /** + * Constructor + * + * \param args session arguments as null-terminated string + * + * The constructor extracts the label from the supplied session-argument + * string. + */ + explicit Session_label(char const *args) + { + typedef String<128> String; - private: - - char _buf[MAX_LEN]; - - public: - - Session_label() { _buf[0] = 0; } - - /** - * Constructor - * - * \param args session arguments as null-terminated string - */ - explicit Session_label(char const *args) - { - Arg_string::find_arg(args, "label").string(_buf, sizeof(_buf), - ""); - } - - char const *string() const { return _buf; } + char buf[String::capacity()]; + Arg_string::find_arg(args, "label").string(buf, sizeof(buf), + ""); + *static_cast(this) = String(buf); + } }; @@ -71,41 +66,43 @@ class Genode::Session_policy : public Xml_node * Returns true if the start of the label matches the specified * match string */ - static bool _label_matches(Session_label const &label, char const *match) { - return strcmp(label.string(), match, strlen(match)) == 0; } + static bool _label_matches(char const *label, char const *match) { + return strcmp(label, match, strlen(match)) == 0; } /** * Query session policy from session label */ - static Xml_node _query_policy(Session_label const &label) + static Xml_node _query_policy(char const *label, Xml_node config) { - /* find index of policy node that matches best */ - int best_match = -1; - try { - unsigned label_len = 0; - Xml_node policy = config()->xml_node().sub_node(); + /* + * Find policy node that matches best + */ + Xml_node best_match(""); - for (int i = 0;; i++, policy = policy.next()) { + unsigned label_len = 0; - if (!policy.has_type("policy")) - continue; + /* + * Functor to be applied to each policy node + */ + auto lambda = [&] (Xml_node policy) { - /* label attribute from policy node */ - char policy_label[Session_label::MAX_LEN]; - policy.attribute("label").value(policy_label, - sizeof(policy_label)); + /* label attribute from policy node */ + char policy_label[Session_label::capacity()]; + policy.attribute("label").value(policy_label, + sizeof(policy_label)); - if (!_label_matches(label, policy_label) - || strlen(policy_label) < label_len) - continue; + if (!_label_matches(label, policy_label) + || strlen(policy_label) < label_len) + return; - label_len = strlen(policy_label); - best_match = i; - } - } catch (...) { } + label_len = strlen(policy_label); + best_match = policy; + }; - if (best_match != -1) - return config()->xml_node().sub_node(best_match); + config.for_each_sub_node("policy", lambda); + + if (!best_match.has_type("none")) + return best_match; throw No_policy_defined(); } @@ -115,23 +112,28 @@ class Genode::Session_policy : public Xml_node /** * Constructor * - * \param args session arguments + * \param label label used as the selector of a policy + * \param config XML node that contains the policies as sub nodes, + * using the component's top-level config node by + * default * - * \throw No_policy_defined if the server configuration has no - * policy defined for the session - * request + * \throw No_policy_defined the server configuration has no + * policy defined for the specified label * - * On construction, the 'Session_policy' looks up the 'policy' XML - * node that matches the label provided as argument. The - * server-side policies are defined in one or more policy subnodes - * of the server's 'config' node. Each policy node has a label - * attribute. If the policy label matches the first part of the - * label delivered as session argument, the policy matches. If - * multiple policies match, the one with the largest label is - * selected. + * On construction, the 'Session_policy' looks up the 'policy' XML node + * that matches the label provided as argument. The server-side + * policies are defined in one or more policy subnodes of the server's + * 'config' node. Each policy node has a label attribute. If the policy + * label matches the first part of the label as delivered as session + * argument, the policy matches. If multiple policies match, the one + * with the longest label is selected. */ - explicit Session_policy(Session_label const &label) - : Xml_node(_query_policy(label)) { } + template + explicit Session_policy(String const &label, + Xml_node config = Genode::config()->xml_node()) + : + Xml_node(_query_policy(label.string(), config)) + { } }; #endif /* _INCLUDE__OS__SESSION_POLICY_H_ */ diff --git a/repos/os/src/server/nitpicker/session.h b/repos/os/src/server/nitpicker/session.h index 4a901cb75..8b79a27e1 100644 --- a/repos/os/src/server/nitpicker/session.h +++ b/repos/os/src/server/nitpicker/session.h @@ -69,7 +69,7 @@ class Session : public Session_list::Element * Append label separator to match selectors with a trailing * separator. */ - char label[Genode::Session_label::MAX_LEN + 4]; + char label[Genode::Session_label::capacity() + 4]; Genode::snprintf(label, sizeof(label), "%s ->", _label.string()); return Genode::strcmp(label, selector, Genode::strlen(selector)) == 0;