#pragma once #include "remote.hpp" #include #include namespace saw { namespace rmt { struct Loopback {}; } template<> class remote_address { private: data addr_id_; public: remote_address(data addr_id__): addr_id_{addr_id__} {} const data& get_address_id() const { return addr_id_; } }; template<> class remote { private: struct key_t { std::array data; template static key_t create(const remote_address& addr){ key_t k; k.data = std::array{addr.get_address_id().get(), schema_hash::apply(), schema_hash::apply()}; return k; } bool operator<(const key_t& rhs) const { for(uint64_t i = 0u; i < 3; ++i){ if(data[i] != rhs.data[i]){ return data[i] < rhs.data[i]; } } return false; } }; std::map>> registered_data_servers_; std::map>> registered_rpc_servers_; template error_or find_data_servers_ele(typename rpc_server::DataServers& ret_val){ if } template error_or::DataServers> find_data_servers(){ typename rpc_server::DataServers ret_val; { auto eov = find_data_servers_ele(ret_val); if(eov.is_error()){ return std::move(eov.get_error()); } } return ret_val; } public: /** * Resolves an address for the remote */ error_or>> parse_address(data id){ return heap>(id); } /** * Connect to a remote */ template conveyor> rpc_connect(const remote_address& addr); /** * Start listening */ template error_or>> rpc_listen(remote_address& addr, typename rpc_server::InterfaceT iface){ auto eo_dat_srvs = find_data_servers(); if(eo_dat_srvs.is_error()){ return std::move(eo_dat_srvs.get_error()); } auto& dat_srvs = eo_dat_srvs.get_value(); return heap>(*this, addr, std::move(iface), dat_srvs); } /** * Start data server */ template error_or>> data_listen(const remote_address& addr){ auto key_v = key_t::template create(addr); auto find = registered_data_servers_.find(key_v); if(find != registered_data_servers_.end()){ return make_error("Server already bound to this address"); } auto dat_srv = heap>(*this, addr); return dat_srv; } /** * Connect to a data server */ template conveyor> data_connect(const remote_address& addr){ constexpr auto class_id = data_server::class_id; key_t key; key.data = std::array{addr.get_address_id().get(), class_id.first, class_id.second}; auto find = registered_data_servers_.find(key); if(find == registered_data_servers_.end()){ return make_error("Server not found"); } auto eo_dat_srv = find->second().template cast_to>(); if(eo_dat_srv.is_error()){ auto& err = eo_dat_srv.get_error(); return std::move(err); } auto dat_srv = eo_dat_srv.get_value(); return data_client{dat_srv}; } /** * Internal function */ error_or register_data_server(const remote_address& addr, i_data_server& srv){ auto class_id = srv.get_class_id(); key_t key; key.data = std::array{addr.get_address_id().get(), class_id.first, class_id.second}; auto insert = registered_data_servers_.emplace(std::make_pair(key, ptr>{srv})); if(insert.second){ return make_error("Server already bound to this address"); } return make_void(); } error_or deregister_data_server(const remote_address& addr, i_data_server& srv){ auto class_id = srv.get_class_id(); key_t key; key.data = std::array{addr.get_address_id().get(), class_id.first, class_id.second}; auto erase = registered_data_servers_.erase(key); if(erase == 0u){ return make_error("Server not found"); } return make_void(); } }; }