diff --git a/repos/os/src/server/nic_router/avl_string_tree.h b/repos/os/src/server/nic_router/avl_string_tree.h index 31a4e956b8..eb20010532 100644 --- a/repos/os/src/server/nic_router/avl_string_tree.h +++ b/repos/os/src/server/nic_router/avl_string_tree.h @@ -33,29 +33,65 @@ class Net::Avl_string_tree : public Genode::Avl_tree using Node = Genode::Avl_string_base; using Tree = Genode::Avl_tree; - OBJECT &_find_by_name(char const *name) + template + + void _node_find_by_name(Node &node, + char const *name_ptr, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) { - if (!first()) { - throw No_match(); } + int const name_diff { + Genode::strcmp(name_ptr, node.name()) }; - Node *node = first()->find_by_name(name); - if (!node) { - throw No_match(); } + if (name_diff != 0) { - return *static_cast(node); + Node *child_ptr { node.child(name_diff > 0) }; + + if (child_ptr != nullptr) { + + _node_find_by_name( + *child_ptr, name_ptr, handle_match, handle_no_match); + + } else { + + handle_no_match(); + } + } else { + + handle_match(*static_cast(&node)); + } + } + + template + + void _find_by_name(char const *name_ptr, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) + { + if (first() != nullptr) { + + _node_find_by_name( + *first(), name_ptr, handle_match, handle_no_match); + + } else { + + handle_no_match(); + } } public: - struct No_match : Genode::Exception { }; - struct Name_not_unique : Genode::Exception + template + + void find_by_name(NAME const &name, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) { - OBJECT &object; - - Name_not_unique(OBJECT &object) : object(object) { } - }; - - OBJECT &find_by_name(NAME const &name) { return _find_by_name(name.string()); } + _find_by_name(name.string(), handle_match, handle_no_match); + } template void for_each(FUNCTOR && functor) const { @@ -81,10 +117,19 @@ class Net::Avl_string_tree : public Genode::Avl_tree } } - void insert(OBJECT &object) + template + + void insert(OBJECT &obj, + HANDLE_NAME_NOT_UNIQUE_FN && handle_name_not_unique) { - try { throw Name_not_unique(_find_by_name(static_cast(&object)->name())); } - catch (No_match) { Tree::insert(&object); } + _find_by_name( + static_cast(&obj)->name(), + [&] /* handle_match */ (OBJECT &other_obj) + { + handle_name_not_unique(other_obj); + }, + [&] /* handle_no_match */ () { Tree::insert(&obj); } + ); } void remove(OBJECT &object) { Tree::remove(&object); } diff --git a/repos/os/src/server/nic_router/configuration.cc b/repos/os/src/server/nic_router/configuration.cc index 09efbbf57d..7bc6c80bb7 100644 --- a/repos/os/src/server/nic_router/configuration.cc +++ b/repos/os/src/server/nic_router/configuration.cc @@ -131,11 +131,14 @@ Configuration::Configuration(Env &env, node.for_each_sub_node("domain", [&] (Xml_node const node) { try { Domain &domain = *new (_alloc) Domain(*this, node, _alloc); - try { _domains.insert(domain); } - catch (Domain_tree::Name_not_unique exception) { - _invalid_domain(domain, "name not unique"); - _invalid_domain(exception.object, "name not unique"); - } + _domains.insert( + domain, + [&] /* handle_name_not_unique */ (Domain &other_domain) + { + _invalid_domain(domain, "name not unique"); + _invalid_domain(other_domain, "name not unique"); + } + ); } catch (Domain::Invalid) { } }); @@ -200,11 +203,14 @@ Configuration::Configuration(Env &env, Nic_client { node, alloc, old_config._nic_clients, env, timer, interfaces, *this }; - try { _nic_clients.insert(nic_client); } - catch (Nic_client_tree::Name_not_unique exception) { - _invalid_nic_client(nic_client, "label not unique"); - _invalid_nic_client(exception.object, "label not unique"); - } + _nic_clients.insert( + nic_client, + [&] /* handle_name_not_unique */ (Nic_client &other_nic_client) + { + _invalid_nic_client(nic_client, "label not unique"); + _invalid_nic_client(other_nic_client, "label not unique"); + } + ); } catch (Nic_client::Invalid) { } }); diff --git a/repos/os/src/server/nic_router/dhcp_server.cc b/repos/os/src/server/nic_router/dhcp_server.cc index 1637a7655f..698e7f4759 100644 --- a/repos/os/src/server/nic_router/dhcp_server.cc +++ b/repos/os/src/server/nic_router/dhcp_server.cc @@ -206,8 +206,7 @@ Pointer Dhcp_server::_init_dns_config_from(Genode::Xml_node const node, if (dns_config_from == Domain_name()) { return Pointer(); } - try { return domains.find_by_name(dns_config_from); } - catch (Domain_tree::No_match) { throw Invalid(); } + return domains.deprecated_find_by_name(dns_config_from); } diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h index f92e6d7d9d..376fd582ee 100644 --- a/repos/os/src/server/nic_router/domain.h +++ b/repos/os/src/server/nic_router/domain.h @@ -71,7 +71,31 @@ struct Net::Domain_link_stats : Domain_object_stats }; -class Net::Domain_tree : public Avl_string_tree { }; +class Net::Domain_tree : public Avl_string_tree +{ + public: + + template + Domain &deprecated_find_by_name(Domain_name const &name) + { + Domain *dom_ptr { nullptr }; + find_by_name( + name, + [&] /* handle_match */ (Domain &dom) { dom_ptr = &dom; }, + [&] /* handle_no_match */ () { throw NO_MATCH_EXCEPTION { }; } + ); + return *dom_ptr; + } + + template + Domain &deprecated_find_by_domain_attr(Genode::Xml_node const &node) + { + Domain_name const name { + node.attribute_value("domain", Domain_name { }) }; + + return deprecated_find_by_name(name); + } +}; class Net::Domain_base diff --git a/repos/os/src/server/nic_router/forward_rule.cc b/repos/os/src/server/nic_router/forward_rule.cc index 4759a1fd88..eb6c77713f 100644 --- a/repos/os/src/server/nic_router/forward_rule.cc +++ b/repos/os/src/server/nic_router/forward_rule.cc @@ -26,18 +26,6 @@ using namespace Genode; ** Forward_rule ** ******************/ - -Domain &Forward_rule::_find_domain(Domain_tree &domains, - Xml_node const node) -{ - try { - Domain_name const domain_name = node.attribute_value("domain", Domain_name()); - return domains.find_by_name(domain_name); - } - catch (Domain_tree::No_match) { throw Invalid(); } -} - - void Forward_rule::print(Output &output) const { Genode::print(output, "port ", _port, " domain ", _domain, " to ip ", @@ -50,7 +38,7 @@ Forward_rule::Forward_rule(Domain_tree &domains, Xml_node const node) _port { node.attribute_value("port", Port(0)) }, _to_ip { node.attribute_value("to", Ipv4_address()) }, _to_port { node.attribute_value("to_port", Port(0)) }, - _domain { _find_domain(domains, node) } + _domain { domains.deprecated_find_by_domain_attr(node) } { if (_port == Port(0) || !_to_ip.valid() || dynamic_port(_port)) { throw Invalid(); } diff --git a/repos/os/src/server/nic_router/forward_rule.h b/repos/os/src/server/nic_router/forward_rule.h index b560b87ba7..3552ab8ef1 100644 --- a/repos/os/src/server/nic_router/forward_rule.h +++ b/repos/os/src/server/nic_router/forward_rule.h @@ -45,9 +45,6 @@ class Net::Forward_rule : public Genode::Avl_node Port const _to_port; Domain &_domain; - static Domain &_find_domain(Domain_tree &domains, - Genode::Xml_node const node); - public: struct Invalid : Genode::Exception { }; diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 4e989fc922..f80ce1a97c 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -390,19 +390,20 @@ void Interface::_update_domain_object(Domain &new_domain) { void Interface::attach_to_domain() { - try { - Domain &domain = - _config().domains().find_by_name(_policy.determine_domain_name()); + _config().domains().find_by_name( + _policy.determine_domain_name(), + [&] /* handle_match */ (Domain &domain) + { + _attach_to_domain_raw(domain); - _attach_to_domain_raw(domain); - - /* construct DHCP client if the new domain needs it */ - if (domain.ip_config_dynamic()) { - _dhcp_client.construct(_timer, *this); - } - attach_to_domain_finish(); - } - catch (Domain_tree::No_match) { } + /* construct DHCP client if the new domain needs it */ + if (domain.ip_config_dynamic()) { + _dhcp_client.construct(_timer, *this); + } + attach_to_domain_finish(); + }, + [&] /* handle_no_match */ () { } + ); } @@ -2056,34 +2057,37 @@ void Interface::_update_dhcp_allocations(Domain &old_domain, void Interface::_update_own_arp_waiters(Domain &domain) { - bool const verbose = _config().verbose(); - _own_arp_waiters.for_each([&] (Arp_waiter_list_element &le) { - Arp_waiter &arp_waiter = *le.object(); - try { - Domain &dst = _config().domains().find_by_name(arp_waiter.dst().name()); - if (dst.ip_config() != arp_waiter.dst().ip_config()) { - if (verbose) { - log("[", domain, "] dismiss ARP waiter: ", arp_waiter, - " (IP config changed)"); + bool const verbose { _config().verbose() }; + _own_arp_waiters.for_each([&] (Arp_waiter_list_element &le) + { + Arp_waiter &arp_waiter { *le.object() }; + bool dismiss_arp_waiter { true }; + _config().domains().find_by_name( + arp_waiter.dst().name(), + [&] /* handle_match */ (Domain &dst) + { + /* dismiss ARP waiter if IP config of target domain changed */ + if (dst.ip_config() != arp_waiter.dst().ip_config()) { + return; } - throw Dismiss_arp_waiter(); + /* keep ARP waiter */ + arp_waiter.handle_config(dst); + if (verbose) { + log("[", domain, "] update ARP waiter: ", arp_waiter); + } + dismiss_arp_waiter = false; + }, + [&] /* handle_no_match */ () + { + /* dismiss ARP waiter as the target domain disappeared */ } - /* keep ARP waiter */ - arp_waiter.handle_config(dst); + ); + if (dismiss_arp_waiter) { if (verbose) { - log("[", domain, "] update ARP waiter: ", arp_waiter); + log("[", domain, "] dismiss ARP waiter: ", arp_waiter); } - return; + cancel_arp_waiting(*_own_arp_waiters.first()->object()); } - /* dismiss ARP waiter */ - catch (Domain_tree::No_match) { - if (verbose) { - log("[", domain, "] dismiss ARP waiter: ", arp_waiter, - " (domain disappeared)"); - } - } - catch (Dismiss_arp_waiter) { } - cancel_arp_waiting(*_own_arp_waiters.first()->object()); }); } @@ -2107,11 +2111,15 @@ void Interface::handle_config_1(Configuration &config) return; } /* interface stays with its domain, so, try to reuse IP config */ - Domain &new_domain = config.domains().find_by_name(new_domain_name); - new_domain.try_reuse_ip_config(old_domain); - return; + config.domains().find_by_name( + new_domain_name, + [&] /* handle_match */ (Domain &new_domain) + { + new_domain.try_reuse_ip_config(old_domain); + }, + [&] /* handle_no_match */ () { } + ); } - catch (Domain_tree::No_match) { } catch (Pointer::Invalid) { } } @@ -2135,66 +2143,70 @@ void Interface::handle_config_2() Domain_name const &new_domain_name = _policy.determine_domain_name(); try { Domain &old_domain = domain(); - try { - Domain &new_domain = _config().domains().find_by_name(new_domain_name); + _config().domains().find_by_name( + new_domain_name, + [&] /* handle_match */ (Domain &new_domain) + { + /* if the domains differ, detach completely from the domain */ + if (old_domain.name() != new_domain_name) { - /* if the domains differ, detach completely from the domain */ - if (old_domain.name() != new_domain_name) { + _detach_from_domain(); + _attach_to_domain_raw(new_domain); + /* destruct and construct DHCP client if required */ + if (old_domain.ip_config_dynamic()) { + _dhcp_client.destruct(); + } + if (new_domain.ip_config_dynamic()) { + _dhcp_client.construct(_timer, *this); + } + return; + } + _update_domain_object(new_domain); + + /* destruct or construct DHCP client if IP-config type changes */ + if (old_domain.ip_config_dynamic() && + !new_domain.ip_config_dynamic()) + { + _dhcp_client.destruct(); + } + if (!old_domain.ip_config_dynamic() && + new_domain.ip_config_dynamic()) + { + _dhcp_client.construct(_timer, *this); + } + + /* remember that the interface stays attached to the same domain */ + _update_domain.construct(old_domain, new_domain); + }, + [&] /* handle_no_match */ () + { + /* the interface no longer has a domain */ _detach_from_domain(); - _attach_to_domain_raw(new_domain); - /* destruct and construct DHCP client if required */ + /* destruct DHCP client if it was constructed */ if (old_domain.ip_config_dynamic()) { _dhcp_client.destruct(); } - if (new_domain.ip_config_dynamic()) { - _dhcp_client.construct(_timer, *this); - } - return; } - _update_domain_object(new_domain); - - /* destruct or construct DHCP client if IP-config type changes */ - if (old_domain.ip_config_dynamic() && - !new_domain.ip_config_dynamic()) - { - _dhcp_client.destruct(); - } - if (!old_domain.ip_config_dynamic() && - new_domain.ip_config_dynamic()) - { - _dhcp_client.construct(_timer, *this); - } - - /* remember that the interface stays attached to the same domain */ - _update_domain.construct(old_domain, new_domain); - return; - } - catch (Domain_tree::No_match) { - - /* the interface no longer has a domain */ - _detach_from_domain(); - - /* destruct DHCP client if it was constructed */ - if (old_domain.ip_config_dynamic()) { - _dhcp_client.destruct(); - } - } + ); } catch (Pointer::Invalid) { /* the interface had no domain but now it may get one */ - try { - Domain &new_domain = _config().domains().find_by_name(new_domain_name); - _attach_to_domain_raw(new_domain); + _config().domains().find_by_name( + new_domain_name, + [&] /* handle_match */ (Domain &new_domain) + { + _attach_to_domain_raw(new_domain); - /* construct DHCP client if the new domain needs it */ - if (new_domain.ip_config_dynamic()) { - _dhcp_client.construct(_timer, *this); - } - } - catch (Domain_tree::No_match) { } + /* construct DHCP client if the new domain needs it */ + if (new_domain.ip_config_dynamic()) { + _dhcp_client.construct(_timer, *this); + } + }, + [&] /* handle_no_match */ () { } + ); } } diff --git a/repos/os/src/server/nic_router/ip_rule.cc b/repos/os/src/server/nic_router/ip_rule.cc index dc39199a67..efcaea257a 100644 --- a/repos/os/src/server/nic_router/ip_rule.cc +++ b/repos/os/src/server/nic_router/ip_rule.cc @@ -19,19 +19,8 @@ using namespace Net; using namespace Genode; -Domain &Ip_rule::_find_domain(Domain_tree &domains, - Xml_node const node) -{ - try { - return domains.find_by_name( - node.attribute_value("domain", Domain_name())); - } - catch (Domain_tree::No_match) { throw Invalid(); } -} - - Ip_rule::Ip_rule(Domain_tree &domains, Xml_node const node) : - Direct_rule(node), - _domain(_find_domain(domains, node)) + Direct_rule { node }, + _domain { domains.deprecated_find_by_domain_attr(node) } { } diff --git a/repos/os/src/server/nic_router/ip_rule.h b/repos/os/src/server/nic_router/ip_rule.h index ca8de1886d..15258dcb76 100644 --- a/repos/os/src/server/nic_router/ip_rule.h +++ b/repos/os/src/server/nic_router/ip_rule.h @@ -33,9 +33,6 @@ class Net::Ip_rule : public Direct_rule Domain &_domain; - static Domain &_find_domain(Domain_tree &domains, - Genode::Xml_node const node); - public: Ip_rule(Domain_tree &domains, Genode::Xml_node const node); diff --git a/repos/os/src/server/nic_router/nat_rule.cc b/repos/os/src/server/nic_router/nat_rule.cc index 3395f60196..501a150478 100644 --- a/repos/os/src/server/nic_router/nat_rule.cc +++ b/repos/os/src/server/nic_router/nat_rule.cc @@ -26,17 +26,6 @@ using namespace Net; using namespace Genode; -Domain &Nat_rule::_find_domain(Domain_tree &domains, - Xml_node const node) -{ - try { - return domains.find_by_name( - node.attribute_value("domain", Domain_name())); - } - catch (Domain_tree::No_match) { throw Invalid(); } -} - - bool Nat_rule::higher(Nat_rule *rule) { return (addr_t)&rule->domain() > (addr_t)&_domain; @@ -50,10 +39,10 @@ Nat_rule::Nat_rule(Domain_tree &domains, Xml_node const node, bool const verbose) : - _domain(_find_domain(domains, node)), - _tcp_port_alloc (tcp_port_alloc, node.attribute_value("tcp-ports", 0UL), verbose), - _udp_port_alloc (udp_port_alloc, node.attribute_value("udp-ports", 0UL), verbose), - _icmp_port_alloc(icmp_port_alloc, node.attribute_value("icmp-ids", 0UL), verbose) + _domain { domains.deprecated_find_by_domain_attr(node) }, + _tcp_port_alloc { tcp_port_alloc, node.attribute_value("tcp-ports", 0U), verbose }, + _udp_port_alloc { udp_port_alloc, node.attribute_value("udp-ports", 0U), verbose }, + _icmp_port_alloc { icmp_port_alloc, node.attribute_value("icmp-ids", 0U), verbose } { } diff --git a/repos/os/src/server/nic_router/nat_rule.h b/repos/os/src/server/nic_router/nat_rule.h index 4f6853ce3a..ffbacf1ef5 100644 --- a/repos/os/src/server/nic_router/nat_rule.h +++ b/repos/os/src/server/nic_router/nat_rule.h @@ -43,9 +43,6 @@ class Net::Nat_rule : public Genode::Avl_node Port_allocator_guard _udp_port_alloc; Port_allocator_guard _icmp_port_alloc; - static Domain &_find_domain(Domain_tree &domains, - Genode::Xml_node const node); - public: struct Invalid : Genode::Exception { }; diff --git a/repos/os/src/server/nic_router/nic_client.cc b/repos/os/src/server/nic_router/nic_client.cc index f3fad8b0fe..28645c42d4 100644 --- a/repos/os/src/server/nic_router/nic_client.cc +++ b/repos/os/src/server/nic_router/nic_client.cc @@ -59,28 +59,33 @@ Net::Nic_client::Nic_client(Xml_node const &node, _alloc { alloc }, _config { config } { - /* if an interface with this label already exists, reuse it */ - try { - Nic_client &old_nic_client = old_nic_clients.find_by_name(label()); - Nic_client_interface &interface = old_nic_client._interface(); - old_nic_client._interface = Pointer(); - interface.domain_name(domain()); - _interface = interface; - } - /* if not, create a new one */ - catch (Nic_client_tree::No_match) { - if (config.verbose()) { - log("[", domain(), "] create NIC client: ", *this); } + old_nic_clients.find_by_name( + label(), + [&] /* handle_match */ (Nic_client &old_nic_client) + { + /* reuse existing interface */ + Nic_client_interface &interface = old_nic_client._interface(); + old_nic_client._interface = Pointer(); + interface.domain_name(domain()); + _interface = interface; + }, + [&] /* handle_no_match */ () + { + /* create a new interface */ + if (config.verbose()) { + log("[", domain(), "] create NIC client: ", *this); } - try { - _interface = *new (_alloc) - Nic_client_interface { env, timer, alloc, interfaces, config, - domain(), label() }; + try { + _interface = *new (_alloc) + Nic_client_interface { + env, timer, alloc, interfaces, config, domain(), + label() }; + } + catch (Insufficient_ram_quota) { _invalid("NIC session RAM quota"); } + catch (Insufficient_cap_quota) { _invalid("NIC session CAP quota"); } + catch (Service_denied) { _invalid("NIC session denied"); } } - catch (Insufficient_ram_quota) { _invalid("NIC session RAM quota"); } - catch (Insufficient_cap_quota) { _invalid("NIC session CAP quota"); } - catch (Service_denied) { _invalid("NIC session denied"); } - } + ); } diff --git a/repos/os/src/server/nic_router/permit_rule.cc b/repos/os/src/server/nic_router/permit_rule.cc index dadba1db9b..acf5edc0cb 100644 --- a/repos/os/src/server/nic_router/permit_rule.cc +++ b/repos/os/src/server/nic_router/permit_rule.cc @@ -26,17 +26,6 @@ using namespace Genode; ** Permit_any_rule ** *********************/ -Domain &Permit_any_rule::_find_domain(Domain_tree &domains, - Xml_node const node) -{ - try { - return domains.find_by_name( - node.attribute_value("domain", Domain_name())); - } - catch (Domain_tree::No_match) { throw Invalid(); } -} - - void Permit_any_rule::print(Output &output) const { Genode::print(output, "domain ", domain()); @@ -45,7 +34,7 @@ void Permit_any_rule::print(Output &output) const Permit_any_rule::Permit_any_rule(Domain_tree &domains, Xml_node const node) : - Permit_rule(_find_domain(domains, node)) + Permit_rule { domains.deprecated_find_by_domain_attr(node) } { } @@ -53,16 +42,6 @@ Permit_any_rule::Permit_any_rule(Domain_tree &domains, Xml_node const node) ** Permit_single_rule ** ************************/ -Domain &Permit_single_rule::_find_domain(Domain_tree &domains, - Xml_node const node) -{ - try { - return domains.find_by_name( - node.attribute_value("domain", Domain_name())); - } - catch (Domain_tree::No_match) { throw Invalid(); } -} - bool Permit_single_rule::higher(Permit_single_rule *rule) { @@ -79,8 +58,8 @@ void Permit_single_rule::print(Output &output) const Permit_single_rule::Permit_single_rule(Domain_tree &domains, Xml_node const node) : - Permit_rule(_find_domain(domains, node)), - _port(node.attribute_value("port", Port(0))) + Permit_rule { domains.deprecated_find_by_domain_attr(node) }, + _port { node.attribute_value("port", Port(0)) } { if (_port == Port(0) || dynamic_port(_port)) { throw Invalid(); } diff --git a/repos/os/src/server/nic_router/permit_rule.h b/repos/os/src/server/nic_router/permit_rule.h index 594a0c64c3..aaeee27948 100644 --- a/repos/os/src/server/nic_router/permit_rule.h +++ b/repos/os/src/server/nic_router/permit_rule.h @@ -70,11 +70,6 @@ struct Net::Permit_rule : public Genode::Interface struct Net::Permit_any_rule : Permit_rule { - private: - - static Domain &_find_domain(Domain_tree &domains, - Genode::Xml_node const node); - public: struct Invalid : Genode::Exception { }; @@ -102,9 +97,6 @@ class Net::Permit_single_rule : public Permit_rule, Port const _port; - static Domain &_find_domain(Domain_tree &domains, - Genode::Xml_node const node); - public: struct Invalid : Genode::Exception { };