From c0af463b81aad13f78cac1a31c1ef4c930ef8518 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 14 Feb 2017 17:38:09 +0100 Subject: [PATCH] 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 --- repos/base/include/base/child.h | 39 +++++++++++++++++++--- repos/base/include/base/local_connection.h | 4 +-- repos/base/include/base/service.h | 5 +-- repos/base/include/base/session_state.h | 31 +++++++++++++++-- repos/base/lib/symbols/ld | 4 +-- repos/base/src/core/main.cc | 3 +- repos/base/src/lib/base/child.cc | 36 ++++++++++++++++++-- repos/base/src/lib/base/session_state.cc | 6 ++-- 8 files changed, 110 insertions(+), 18 deletions(-) diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index f72ff75df..4f8be206a 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -69,11 +69,38 @@ struct Genode::Child_policy * Determine service to provide a session request * * \return service to be contacted for the new session + * \deprecated * * \throw Parent::Service_denied */ 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 @@ -271,6 +298,9 @@ class Genode::Child : protected Rpc_object, 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 * complete. @@ -370,7 +400,7 @@ class Genode::Child : protected Rpc_object, Args const _args; - Service &_service; + Child_policy::Route _route; /* * The 'Env_service' monitors session responses in order to attempt @@ -439,8 +469,9 @@ class Genode::Child : protected Rpc_object, Label const &label = Label()) : _args(_construct_args(child._policy, label)), - _service(child._policy.resolve_session_request(_service_name(), _args)), - _env_service(child, _service), + _route(child._resolve_session_request(child._policy, _service_name(), + _args.string())), + _env_service(child, _route.service), _connection(_env_service, child._id_space, id, _args, child._policy.filter_session_affinity(Affinity())) { } diff --git a/repos/base/include/base/local_connection.h b/repos/base/include/base/local_connection.h index cf79d3c00..c45b917cc 100644 --- a/repos/base/include/base/local_connection.h +++ b/repos/base/include/base/local_connection.h @@ -60,8 +60,8 @@ struct Genode::Local_connection_base : Noncopyable Args const &args, Affinity const &affinity, size_t ram_quota) : - _session_state(service, id_space, id, _init_args(args, ram_quota), - affinity) + _session_state(service, id_space, id, label_from_args(args.string()), + _init_args(args, ram_quota), affinity) { _session_state.service().initiate_request(_session_state); } diff --git a/repos/base/include/base/service.h b/repos/base/include/base/service.h index 4e9fd3663..e9207e3dd 100644 --- a/repos/base/include/base/service.h +++ b/repos/base/include/base/service.h @@ -192,7 +192,7 @@ class Genode::Local_service : public Service case Session_state::CREATE_REQUESTED: try { - SESSION &rpc_obj = _factory.create(session.args(), + SESSION &rpc_obj = _factory.create(Session_state::Server_args(session).string(), session.affinity()); session.local_ptr = &rpc_obj; session.cap = rpc_obj.cap(); @@ -272,9 +272,10 @@ class Genode::Parent_service : public Service session.id_at_parent.construct(session.parent_client, _env.id_space()); try { + session.cap = _env.session(name().string(), session.id_at_parent->id(), - session.args().string(), + Session_state::Server_args(session).string(), session.affinity()); session.phase = Session_state::AVAILABLE; diff --git a/repos/base/include/base/session_state.h b/repos/base/include/base/session_state.h index 859d140a5..b4d55b526 100644 --- a/repos/base/include/base/session_state.h +++ b/repos/base/include/base/session_state.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace Genode { @@ -62,8 +63,9 @@ class Genode::Session_state : public Parent::Client, public Parent::Server, Reconstructible::Element> _id_at_client; - Args _args; - Affinity _affinity; + Session_label const _label; + Args _args; + Affinity _affinity; public: @@ -110,15 +112,22 @@ class Genode::Session_state : public Parent::Client, public Parent::Server, * Constructor * * \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 session ID picked by the client * \param args session arguments * * \throw Id_space::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, Id_space &client_id_space, Parent::Client::Id client_id, + Session_label const &label, Args const &args, 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'. */ 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; } + }; }; diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 0344baca3..048ab5ee5 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -85,8 +85,8 @@ _ZN6Genode13Registry_base7_insertERNS0_7ElementE T _ZN6Genode13Registry_base7_removeERNS0_7ElementE T _ZN6Genode13Registry_base9_for_eachERNS0_15Untyped_functorE T _ZN6Genode13Session_state7destroyEv T -_ZN6Genode13Session_stateC1ERNS_7ServiceERNS_8Id_spaceINS_6Parent6ClientEEENS6_2IdERKNS_6StringILm256EEERKNS_8AffinityE T -_ZN6Genode13Session_stateC2ERNS_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_13Session_labelERKNS_6StringILm256EEERKNS_8AffinityE T _ZN6Genode13Shared_objectC1ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T _ZN6Genode13Shared_objectC2ERNS_3EnvERNS_9AllocatorEPKcNS0_4BindENS0_4KeepE T _ZN6Genode13Shared_objectD1Ev T diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 5747f874d..1ba2580ed 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -94,7 +94,8 @@ Session_capability Core_parent::session(Parent::Client::Id id, return; 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); diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 05406687c..606f15c95 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -156,12 +156,13 @@ void Child::session_sigh(Signal_context_capability sigh) */ Session_state & create_session(Child_policy::Name const &child_name, Service &service, + Session_label const &label, Session_state::Factory &factory, Id_space &id_space, Parent::Client::Id id, Session_state::Args const &args, Affinity const &affinity) { 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) { 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, Parent::Service_name const &name, 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); /* 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 = - create_session(_policy.name(), service, *_session_factory, + create_session(_policy.name(), service, route.label, *_session_factory, _id_space, id, argbuf, filtered_affinity); session.ready_callback = this; diff --git a/repos/base/src/lib/base/session_state.cc b/repos/base/src/lib/base/session_state.cc index 3ad564cc1..52f993732 100644 --- a/repos/base/src/lib/base/session_state.cc +++ b/repos/base/src/lib/base/session_state.cc @@ -40,8 +40,9 @@ void Session_state::generate_session_request(Xml_generator &xml) const xml.node("create", [&] () { xml.attribute("id", id_at_server->id().value); xml.attribute("service", _service.name()); + xml.attribute("label", _label); xml.node("args", [&] () { - xml.append_sanitized(_args.string()); + xml.append_sanitized(Server_args(*this).string()); }); }); break; @@ -110,11 +111,12 @@ void Session_state::destroy() Session_state::Session_state(Service &service, Id_space &client_id_space, Parent::Client::Id client_id, + Session_label const &label, Args const &args, Affinity const &affinity) : _service(service), _donated_ram_quota(Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0)), _id_at_client(*this, client_id_space, client_id), - _args(args), _affinity(affinity) + _label(label), _args(args), _affinity(affinity) { }