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>
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),
"<undefined>");
}
char const *string() const { return _buf; }
char buf[String::capacity()];
Arg_string::find_arg(args, "label").string(buf, sizeof(buf),
"<undefined>");
*static_cast<String *>(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("<none/>");
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 <size_t N>
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_ */

View File

@ -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;