diff --git a/repos/os/src/init/child.cc b/repos/os/src/init/child.cc index d436b5706..29d7b7332 100644 --- a/repos/os/src/init/child.cc +++ b/repos/os/src/init/child.cc @@ -463,21 +463,14 @@ Init::Child::Route Init::Child::resolve_session_request(Service::Name const &ser Session::Diag const target_diag { target.attribute_value("diag", false) }; + auto no_filter = [] (Service &) -> bool { return false; }; + if (target.has_type("parent")) { - Parent_service *service = nullptr; - - if ((service = find_service(_parent_services, service_name))) - return Route { *service, target_label, target_diag }; - - if (service && service->abandoned()) - throw Service_denied(); - - if (!service_wildcard) { - warning(name(), ": service lookup for " - "\"", service_name, "\" at parent failed"); - throw Service_denied(); - } + try { + return Route { find_service(_parent_services, service_name, no_filter), + target_label, target_diag }; + } catch (Service_denied) { } } if (target.has_type("child")) { @@ -486,24 +479,14 @@ Init::Child::Route Init::Child::resolve_session_request(Service::Name const &ser Name server_name = target.attribute_value("name", Name()); server_name = _name_registry.deref_alias(server_name); - Routed_service *service = nullptr; + auto filter_server_name = [&] (Routed_service &s) -> bool { + return s.child_name() != server_name; }; - _child_services.for_each([&] (Routed_service &s) { - if (s.name() == Service::Name(service_name) - && s.child_name() == server_name) - service = &s; }); + try { + return Route { find_service(_child_services, service_name, filter_server_name), + target_label, target_diag }; - if (service && service->abandoned()) - throw Service_denied(); - - if (service) - return Route { *service, target_label, target_diag }; - - if (!service_wildcard) { - warning(name(), ": lookup to child " - "server \"", server_name, "\" failed"); - throw Service_denied(); - } + } catch (Service_denied) { } } if (target.has_type("any-child")) { @@ -513,17 +496,16 @@ Init::Child::Route Init::Child::resolve_session_request(Service::Name const &ser "service \"", service_name, "\""); throw Service_denied(); } + try { + return Route { find_service(_child_services, service_name, no_filter), + target_label, target_diag }; - Routed_service *service = nullptr; + } catch (Service_denied) { } + } - if ((service = find_service(_child_services, service_name))) - return Route { *service, target_label, target_diag }; - - if (!service_wildcard) { - warning(name(), ": lookup for service " - "\"", service_name, "\" failed"); - throw Service_denied(); - } + if (!service_wildcard) { + warning(name(), ": lookup for service \"", service_name, "\" failed"); + throw Service_denied(); } if (target.last()) diff --git a/repos/os/src/init/utils.h b/repos/os/src/init/utils.h index 7468b9803..e86a4e624 100644 --- a/repos/os/src/init/utils.h +++ b/repos/os/src/init/utils.h @@ -122,15 +122,36 @@ namespace Init { return cnt > 1; } - - template - inline T *find_service(Registry &services, Service::Name const &name) + /** + * Find service with certain values in given registry + * + * \param services service registry + * \param name name of wanted service + * \param filter_fn function that applies additional filters + * + * \throw Service_denied + */ + template + inline T &find_service(Registry &services, + Service::Name const &name, + FILTER_FN const &filter_fn) { T *service = nullptr; services.for_each([&] (T &s) { - if (!service && (s.name() == name)) - service = &s; }); - return service; + + if (service || s.name() != name || filter_fn(s)) + return; + + service = &s; + }); + + if (!service) + throw Service_denied(); + + if (service->abandoned()) + throw Service_denied(); + + return *service; }