base: Add Child_policy::Route

The new return value of 'resolve_session_request' allows the child
policy to define the label used as the policy selector at the server.

Because this patch introduces the distinction of the child-provided
label from the label as presented to the server along with the session
request, the latter is now handled as a dedicated 'Session_state'
argument.

Issue #2248
This commit is contained in:
Norman Feske 2017-02-14 17:38:09 +01:00 committed by Christian Helmuth
parent 2d199982eb
commit c0af463b81
8 changed files with 110 additions and 18 deletions

View File

@ -69,11 +69,38 @@ struct Genode::Child_policy
* Determine service to provide a session request * Determine service to provide a session request
* *
* \return service to be contacted for the new session * \return service to be contacted for the new session
* \deprecated
* *
* \throw Parent::Service_denied * \throw Parent::Service_denied
*/ */
virtual Service &resolve_session_request(Service::Name const &, virtual Service &resolve_session_request(Service::Name const &,
Session_state::Args const &) = 0; Session_state::Args const &)
{
throw Parent::Service_denied();
}
/**
* Routing destination of a session request
*/
struct Route
{
Service &service;
Session_label const label;
};
/**
* Determine service and server-side label for a given session request
*
* \return routing and policy-selection information for the session
*
* \throw Parent::Service_denied
*/
virtual Route resolve_session_request(Service::Name const &,
Session_label const &)
{
/* \deprecated make pure virtual once the old version is gone */
throw Parent::Service_denied();
}
/** /**
* Apply transformations to session arguments * Apply transformations to session arguments
@ -271,6 +298,9 @@ class Genode::Child : protected Rpc_object<Parent>,
typedef Session_state::Args Args; typedef Session_state::Args Args;
static Child_policy::Route _resolve_session_request(Child_policy &,
Service::Name const &,
char const *);
/* /*
* Members that are initialized not before the child's environment is * Members that are initialized not before the child's environment is
* complete. * complete.
@ -370,7 +400,7 @@ class Genode::Child : protected Rpc_object<Parent>,
Args const _args; Args const _args;
Service &_service; Child_policy::Route _route;
/* /*
* The 'Env_service' monitors session responses in order to attempt * The 'Env_service' monitors session responses in order to attempt
@ -439,8 +469,9 @@ class Genode::Child : protected Rpc_object<Parent>,
Label const &label = Label()) Label const &label = Label())
: :
_args(_construct_args(child._policy, label)), _args(_construct_args(child._policy, label)),
_service(child._policy.resolve_session_request(_service_name(), _args)), _route(child._resolve_session_request(child._policy, _service_name(),
_env_service(child, _service), _args.string())),
_env_service(child, _route.service),
_connection(_env_service, child._id_space, id, _args, _connection(_env_service, child._id_space, id, _args,
child._policy.filter_session_affinity(Affinity())) child._policy.filter_session_affinity(Affinity()))
{ } { }

View File

@ -60,8 +60,8 @@ struct Genode::Local_connection_base : Noncopyable
Args const &args, Affinity const &affinity, Args const &args, Affinity const &affinity,
size_t ram_quota) size_t ram_quota)
: :
_session_state(service, id_space, id, _init_args(args, ram_quota), _session_state(service, id_space, id, label_from_args(args.string()),
affinity) _init_args(args, ram_quota), affinity)
{ {
_session_state.service().initiate_request(_session_state); _session_state.service().initiate_request(_session_state);
} }

View File

@ -192,7 +192,7 @@ class Genode::Local_service : public Service
case Session_state::CREATE_REQUESTED: case Session_state::CREATE_REQUESTED:
try { try {
SESSION &rpc_obj = _factory.create(session.args(), SESSION &rpc_obj = _factory.create(Session_state::Server_args(session).string(),
session.affinity()); session.affinity());
session.local_ptr = &rpc_obj; session.local_ptr = &rpc_obj;
session.cap = rpc_obj.cap(); session.cap = rpc_obj.cap();
@ -272,9 +272,10 @@ class Genode::Parent_service : public Service
session.id_at_parent.construct(session.parent_client, session.id_at_parent.construct(session.parent_client,
_env.id_space()); _env.id_space());
try { try {
session.cap = _env.session(name().string(), session.cap = _env.session(name().string(),
session.id_at_parent->id(), session.id_at_parent->id(),
session.args().string(), Session_state::Server_args(session).string(),
session.affinity()); session.affinity());
session.phase = Session_state::AVAILABLE; session.phase = Session_state::AVAILABLE;

View File

@ -21,6 +21,7 @@
#include <base/id_space.h> #include <base/id_space.h>
#include <base/env.h> #include <base/env.h>
#include <base/log.h> #include <base/log.h>
#include <base/session_label.h>
namespace Genode { namespace Genode {
@ -62,8 +63,9 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
Reconstructible<Id_space<Parent::Client>::Element> _id_at_client; Reconstructible<Id_space<Parent::Client>::Element> _id_at_client;
Args _args; Session_label const _label;
Affinity _affinity; Args _args;
Affinity _affinity;
public: public:
@ -110,15 +112,22 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
* Constructor * Constructor
* *
* \param service interface that was used to create the session * \param service interface that was used to create the session
* \param label session label to be presented to the server
* \param client_id_space ID space for client-side session IDs * \param client_id_space ID space for client-side session IDs
* \param client_id session ID picked by the client * \param client_id session ID picked by the client
* \param args session arguments * \param args session arguments
* *
* \throw Id_space<Parent::Client>::Conflicting_id * \throw Id_space<Parent::Client>::Conflicting_id
*
* The client-provided (and child-name-prefixed) session label is
* contained in 'args'. In contrast, the 'label' argument is the label
* presented to the server along with the session request, which
* depends on the policy of 'Child_policy::resolve_session_request'.
*/ */
Session_state(Service &service, Session_state(Service &service,
Id_space<Parent::Client> &client_id_space, Id_space<Parent::Client> &client_id_space,
Parent::Client::Id client_id, Parent::Client::Id client_id,
Session_label const &label,
Args const &args, Args const &args,
Affinity const &affinity); Affinity const &affinity);
@ -195,6 +204,24 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
* This function has no effect for sessions not created via a 'Factory'. * This function has no effect for sessions not created via a 'Factory'.
*/ */
void destroy(); void destroy();
/**
* Utility to override the client-provided label by the label assigned
* by 'Child_policy::resolve_session_request'.
*/
struct Server_args
{
char _buf[Args::capacity()];
Server_args(Session_state const &session)
{
Genode::strncpy(_buf, session._args.string(), sizeof(_buf));
Arg_string::set_arg_string(_buf, sizeof(_buf),
"label", session._label.string());
}
char const *string() const { return _buf; }
};
}; };

View File

@ -85,8 +85,8 @@ _ZN6Genode13Registry_base7_insertERNS0_7ElementE T
_ZN6Genode13Registry_base7_removeERNS0_7ElementE T _ZN6Genode13Registry_base7_removeERNS0_7ElementE T
_ZN6Genode13Registry_base9_for_eachERNS0_15Untyped_functorE T _ZN6Genode13Registry_base9_for_eachERNS0_15Untyped_functorE T
_ZN6Genode13Session_state7destroyEv T _ZN6Genode13Session_state7destroyEv T
_ZN6Genode13Session_stateC1ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_6StringILm256EEERKNS_8AffinityE T _ZN6Genode13Session_stateC1ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_13Session_labelERKNS_6StringILm256EEERKNS_8AffinityE T
_ZN6Genode13Session_stateC2ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_6StringILm256EEERKNS_8AffinityE T _ZN6Genode13Session_stateC2ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_13Session_labelERKNS_6StringILm256EEERKNS_8AffinityE T
_ZN6Genode13Shared_objectC1ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T _ZN6Genode13Shared_objectC1ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T
_ZN6Genode13Shared_objectC2ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T _ZN6Genode13Shared_objectC2ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T
_ZN6Genode13Shared_objectD1Ev T _ZN6Genode13Shared_objectD1Ev T

View File

@ -94,7 +94,8 @@ Session_capability Core_parent::session(Parent::Client::Id id,
return; return;
Session_state &session = *new (_alloc) Session_state &session = *new (_alloc)
Session_state(service, _id_space, id, args.string(), affinity); Session_state(service, _id_space, id, label_from_args(args.string()),
args.string(), affinity);
service.initiate_request(session); service.initiate_request(session);

View File

@ -156,12 +156,13 @@ void Child::session_sigh(Signal_context_capability sigh)
*/ */
Session_state & Session_state &
create_session(Child_policy::Name const &child_name, Service &service, create_session(Child_policy::Name const &child_name, Service &service,
Session_label const &label,
Session_state::Factory &factory, Id_space<Parent::Client> &id_space, Session_state::Factory &factory, Id_space<Parent::Client> &id_space,
Parent::Client::Id id, Session_state::Args const &args, Parent::Client::Id id, Session_state::Args const &args,
Affinity const &affinity) Affinity const &affinity)
{ {
try { try {
return service.create_session(factory, id_space, id, args, affinity); return service.create_session(factory, id_space, id, label, args, affinity);
} }
catch (Allocator::Out_of_memory) { catch (Allocator::Out_of_memory) {
error("could not allocate session meta data for child ", child_name); error("could not allocate session meta data for child ", child_name);
@ -179,6 +180,34 @@ create_session(Child_policy::Name const &child_name, Service &service,
} }
/*
* \deprecated Temporary wrapper around 'Child_policy::resolve_session_request'
* that tries both overloads.
*
* \throw Parent::Service_denied
*/
Child_policy::Route Child::_resolve_session_request(Child_policy &policy,
Service::Name const &name,
char const *argbuf)
{
Session_label const label = label_from_args(argbuf);
/*
* \deprecated Try old interface, remove once all 'Child_policy'
* implementations are updated.
*/
try {
Session_state::Args args(argbuf);
return Child_policy::Route {
policy.resolve_session_request(name, args), label };
}
catch (Parent::Service_denied) { }
return policy.resolve_session_request(name, label);
}
Session_capability Child::session(Parent::Client::Id id, Session_capability Child::session(Parent::Client::Id id,
Parent::Service_name const &name, Parent::Service_name const &name,
Parent::Session_args const &args, Parent::Session_args const &args,
@ -202,10 +231,11 @@ Session_capability Child::session(Parent::Client::Id id,
Affinity const filtered_affinity = _policy.filter_session_affinity(affinity); Affinity const filtered_affinity = _policy.filter_session_affinity(affinity);
/* may throw a 'Parent::Service_denied' exception */ /* may throw a 'Parent::Service_denied' exception */
Service &service = _policy.resolve_session_request(name.string(), argbuf); Child_policy::Route route = _resolve_session_request(_policy, name.string(), argbuf);
Service &service = route.service;
Session_state &session = Session_state &session =
create_session(_policy.name(), service, *_session_factory, create_session(_policy.name(), service, route.label, *_session_factory,
_id_space, id, argbuf, filtered_affinity); _id_space, id, argbuf, filtered_affinity);
session.ready_callback = this; session.ready_callback = this;

View File

@ -40,8 +40,9 @@ void Session_state::generate_session_request(Xml_generator &xml) const
xml.node("create", [&] () { xml.node("create", [&] () {
xml.attribute("id", id_at_server->id().value); xml.attribute("id", id_at_server->id().value);
xml.attribute("service", _service.name()); xml.attribute("service", _service.name());
xml.attribute("label", _label);
xml.node("args", [&] () { xml.node("args", [&] () {
xml.append_sanitized(_args.string()); xml.append_sanitized(Server_args(*this).string());
}); });
}); });
break; break;
@ -110,11 +111,12 @@ void Session_state::destroy()
Session_state::Session_state(Service &service, Session_state::Session_state(Service &service,
Id_space<Parent::Client> &client_id_space, Id_space<Parent::Client> &client_id_space,
Parent::Client::Id client_id, Parent::Client::Id client_id,
Session_label const &label,
Args const &args, Args const &args,
Affinity const &affinity) Affinity const &affinity)
: :
_service(service), _service(service),
_donated_ram_quota(Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0)), _donated_ram_quota(Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0)),
_id_at_client(*this, client_id_space, client_id), _id_at_client(*this, client_id_space, client_id),
_args(args), _affinity(affinity) _label(label), _args(args), _affinity(affinity)
{ } { }