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.
This commit is contained in:
Norman Feske 2015-09-17 16:59:09 +02:00 committed by Christian Helmuth
parent 1f941d1c87
commit dce6e14e3e
2 changed files with 67 additions and 65 deletions

View File

@ -18,38 +18,33 @@
#include <os/config.h> #include <os/config.h>
namespace Genode { namespace Genode {
class Session_label; struct Session_label;
class Session_policy; 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[String::capacity()];
Arg_string::find_arg(args, "label").string(buf, sizeof(buf),
char _buf[MAX_LEN]; "<undefined>");
*static_cast<String *>(this) = String(buf);
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),
"<undefined>");
}
char const *string() const { return _buf; }
}; };
@ -71,41 +66,43 @@ class Genode::Session_policy : public Xml_node
* Returns true if the start of the label matches the specified * Returns true if the start of the label matches the specified
* match string * match string
*/ */
static bool _label_matches(Session_label const &label, char const *match) { static bool _label_matches(char const *label, char const *match) {
return strcmp(label.string(), match, strlen(match)) == 0; } return strcmp(label, match, strlen(match)) == 0; }
/** /**
* Query session policy from session label * 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; * Find policy node that matches best
try { */
unsigned label_len = 0; Xml_node best_match("<none/>");
Xml_node policy = config()->xml_node().sub_node();
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 */ /* label attribute from policy node */
char policy_label[Session_label::MAX_LEN]; char policy_label[Session_label::capacity()];
policy.attribute("label").value(policy_label, policy.attribute("label").value(policy_label,
sizeof(policy_label)); sizeof(policy_label));
if (!_label_matches(label, policy_label) if (!_label_matches(label, policy_label)
|| strlen(policy_label) < label_len) || strlen(policy_label) < label_len)
continue; return;
label_len = strlen(policy_label); label_len = strlen(policy_label);
best_match = i; best_match = policy;
} };
} catch (...) { }
if (best_match != -1) config.for_each_sub_node("policy", lambda);
return config()->xml_node().sub_node(best_match);
if (!best_match.has_type("none"))
return best_match;
throw No_policy_defined(); throw No_policy_defined();
} }
@ -115,23 +112,28 @@ class Genode::Session_policy : public Xml_node
/** /**
* Constructor * 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 * \throw No_policy_defined the server configuration has no
* policy defined for the session * policy defined for the specified label
* request
* *
* On construction, the 'Session_policy' looks up the 'policy' XML * On construction, the 'Session_policy' looks up the 'policy' XML node
* node that matches the label provided as argument. The * that matches the label provided as argument. The server-side
* server-side policies are defined in one or more policy subnodes * policies are defined in one or more policy subnodes of the server's
* of the server's 'config' node. Each policy node has a label * 'config' node. Each policy node has a label attribute. If the policy
* attribute. If the policy label matches the first part of the * label matches the first part of the label as delivered as session
* label delivered as session argument, the policy matches. If * argument, the policy matches. If multiple policies match, the one
* multiple policies match, the one with the largest label is * with the longest label is selected.
* selected.
*/ */
explicit Session_policy(Session_label const &label) template <size_t N>
: Xml_node(_query_policy(label)) { } explicit Session_policy(String<N> const &label,
Xml_node config = Genode::config()->xml_node())
:
Xml_node(_query_policy(label.string(), config))
{ }
}; };
#endif /* _INCLUDE__OS__SESSION_POLICY_H_ */ #endif /* _INCLUDE__OS__SESSION_POLICY_H_ */

View File

@ -69,7 +69,7 @@ class Session : public Session_list::Element
* Append label separator to match selectors with a trailing * Append label separator to match selectors with a trailing
* separator. * separator.
*/ */
char label[Genode::Session_label::MAX_LEN + 4]; char label[Genode::Session_label::capacity() + 4];
Genode::snprintf(label, sizeof(label), "%s ->", _label.string()); Genode::snprintf(label, sizeof(label), "%s ->", _label.string());
return Genode::strcmp(label, selector, return Genode::strcmp(label, selector,
Genode::strlen(selector)) == 0; Genode::strlen(selector)) == 0;