mirror of
https://github.com/OpenBluetoothToolbox/SimpleBLE
synced 2025-10-14 02:08:22 +08:00
Checkpoint for pass 3 of Peripheral integration.
This commit is contained in:
@@ -6,11 +6,14 @@
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
#include "simpleble/Config.h"
|
||||
#include "simpleble/SimpleBLE.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
int main() {
|
||||
SimpleBLE::Config::SimpleBluez::use_legacy_bluez_backend = false;
|
||||
|
||||
auto adapter_optional = Utils::getAdapter();
|
||||
|
||||
if (!adapter_optional.has_value()) {
|
||||
|
@@ -5,6 +5,8 @@
|
||||
#include <simplebluez/Device.h>
|
||||
#include <simplebluez/interfaces/Adapter1.h>
|
||||
|
||||
#include <simpledbus/advanced/ProxyRegistry.h>
|
||||
|
||||
#include <kvn/kvn_safe_callback.hpp>
|
||||
|
||||
#include <functional>
|
||||
@@ -41,6 +43,8 @@ class Adapter : public SimpleDBus::Proxy {
|
||||
std::shared_ptr<Adapter1> adapter1();
|
||||
|
||||
kvn::safe_callback<void(std::shared_ptr<Device> device)> _on_device_updated;
|
||||
|
||||
static const SimpleDBus::AutoRegisterProxy<Adapter> registry;
|
||||
};
|
||||
|
||||
} // namespace SimpleBluez
|
||||
|
@@ -6,6 +6,8 @@
|
||||
#include <simplebluez/Types.h>
|
||||
#include <simplebluez/interfaces/GattCharacteristic1.h>
|
||||
|
||||
#include <simpledbus/advanced/ProxyRegistry.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace SimpleBluez {
|
||||
@@ -41,6 +43,8 @@ class Characteristic : public SimpleDBus::Proxy {
|
||||
std::shared_ptr<SimpleDBus::Proxy> path_create(const std::string& path) override;
|
||||
|
||||
std::shared_ptr<GattCharacteristic1> gattcharacteristic1();
|
||||
|
||||
static const SimpleDBus::AutoRegisterProxy<Characteristic> registry;
|
||||
};
|
||||
|
||||
} // namespace SimpleBluez
|
||||
|
@@ -5,6 +5,8 @@
|
||||
#include <simplebluez/Types.h>
|
||||
#include <simplebluez/interfaces/GattDescriptor1.h>
|
||||
|
||||
#include <simpledbus/advanced/ProxyRegistry.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace SimpleBluez {
|
||||
@@ -28,6 +30,8 @@ class Descriptor : public SimpleDBus::Proxy {
|
||||
|
||||
private:
|
||||
std::shared_ptr<GattDescriptor1> gattdescriptor1();
|
||||
|
||||
static const SimpleDBus::AutoRegisterProxy<Descriptor> registry;
|
||||
};
|
||||
|
||||
} // namespace SimpleBluez
|
||||
|
@@ -7,6 +7,8 @@
|
||||
#include <simplebluez/interfaces/Battery1.h>
|
||||
#include <simplebluez/interfaces/Device1.h>
|
||||
|
||||
#include <simpledbus/advanced/ProxyRegistry.h>
|
||||
|
||||
namespace SimpleBluez {
|
||||
|
||||
class Device : public SimpleDBus::Proxy {
|
||||
@@ -59,6 +61,8 @@ class Device : public SimpleDBus::Proxy {
|
||||
|
||||
std::shared_ptr<Device1> device1();
|
||||
std::shared_ptr<Battery1> battery1();
|
||||
|
||||
static const SimpleDBus::AutoRegisterProxy<Device> registry;
|
||||
};
|
||||
|
||||
} // namespace SimpleBluez
|
||||
|
@@ -5,6 +5,8 @@
|
||||
#include <simplebluez/Characteristic.h>
|
||||
#include <simplebluez/interfaces/GattService1.h>
|
||||
|
||||
#include <simpledbus/advanced/ProxyRegistry.h>
|
||||
|
||||
namespace SimpleBluez {
|
||||
|
||||
class Service : public SimpleDBus::Proxy {
|
||||
@@ -22,6 +24,8 @@ class Service : public SimpleDBus::Proxy {
|
||||
private:
|
||||
std::shared_ptr<SimpleDBus::Proxy> path_create(const std::string& path) override;
|
||||
std::shared_ptr<GattService1> gattservice1();
|
||||
|
||||
static const SimpleDBus::AutoRegisterProxy<Service> registry;
|
||||
};
|
||||
|
||||
} // namespace SimpleBluez
|
||||
|
@@ -5,6 +5,13 @@
|
||||
|
||||
using namespace SimpleBluez;
|
||||
|
||||
const SimpleDBus::AutoRegisterProxy<Adapter> Adapter::registry{
|
||||
"hci",
|
||||
[](std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path) -> std::shared_ptr<SimpleDBus::Proxy> {
|
||||
return std::static_pointer_cast<SimpleDBus::Proxy>(std::make_shared<Adapter>(conn, bus_name, path));
|
||||
}
|
||||
};
|
||||
|
||||
Adapter::Adapter(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {}
|
||||
|
||||
|
@@ -6,8 +6,13 @@ using namespace SimpleBluez;
|
||||
|
||||
Agent::Agent(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {
|
||||
_interfaces.emplace(std::make_pair(
|
||||
"org.bluez.Agent1", std::static_pointer_cast<SimpleDBus::Interface>(std::make_shared<Agent1>(_conn, _path))));
|
||||
|
||||
{
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[SimpleDBus::Path(_path)];
|
||||
path_interfaces.emplace(std::make_pair(
|
||||
"org.bluez.Agent1", std::static_pointer_cast<SimpleDBus::Interface>(std::make_shared<Agent1>(_conn, _path))));
|
||||
}
|
||||
}
|
||||
|
||||
std::string Agent::capabilities() const {
|
||||
|
@@ -7,7 +7,10 @@ using namespace SimpleBluez;
|
||||
BluezRoot::BluezRoot(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {
|
||||
|
||||
_interfaces.emplace(std::make_pair("org.freedesktop.DBus.ObjectManager", std::make_shared<SimpleDBus::ObjectManager>(conn, _bus_name, _path)));
|
||||
{
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
_global_interfaces[SimpleDBus::Path(_path)].emplace(std::make_pair("org.freedesktop.DBus.ObjectManager", std::make_shared<SimpleDBus::ObjectManager>(conn, _bus_name, _path)));
|
||||
}
|
||||
|
||||
object_manager()->InterfacesAdded = [&](std::string path, SimpleDBus::Holder options) { path_add(path, options); };
|
||||
object_manager()->InterfacesRemoved = [&](std::string path, SimpleDBus::Holder options) {
|
||||
|
@@ -4,6 +4,13 @@
|
||||
|
||||
using namespace SimpleBluez;
|
||||
|
||||
const SimpleDBus::AutoRegisterProxy<Characteristic> Characteristic::registry{
|
||||
"char",
|
||||
[](std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path) -> std::shared_ptr<SimpleDBus::Proxy> {
|
||||
return std::static_pointer_cast<SimpleDBus::Proxy>(std::make_shared<Characteristic>(conn, bus_name, path));
|
||||
}
|
||||
};
|
||||
|
||||
Characteristic::Characteristic(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name,
|
||||
const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {}
|
||||
|
@@ -2,6 +2,13 @@
|
||||
|
||||
using namespace SimpleBluez;
|
||||
|
||||
const SimpleDBus::AutoRegisterProxy<Descriptor> Descriptor::registry{
|
||||
"descriptor",
|
||||
[](std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path) -> std::shared_ptr<SimpleDBus::Proxy> {
|
||||
return std::static_pointer_cast<SimpleDBus::Proxy>(std::make_shared<Descriptor>(conn, bus_name, path));
|
||||
}
|
||||
};
|
||||
|
||||
Descriptor::Descriptor(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name,
|
||||
const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {}
|
||||
|
@@ -6,6 +6,13 @@
|
||||
|
||||
using namespace SimpleBluez;
|
||||
|
||||
const SimpleDBus::AutoRegisterProxy<Device> Device::registry{
|
||||
"dev",
|
||||
[](std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path) -> std::shared_ptr<SimpleDBus::Proxy> {
|
||||
return std::static_pointer_cast<SimpleDBus::Proxy>(std::make_shared<Device>(conn, bus_name, path));
|
||||
}
|
||||
};
|
||||
|
||||
Device::Device(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {}
|
||||
|
||||
|
@@ -4,6 +4,13 @@
|
||||
|
||||
using namespace SimpleBluez;
|
||||
|
||||
const SimpleDBus::AutoRegisterProxy<Service> Service::registry{
|
||||
"service",
|
||||
[](std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path) -> std::shared_ptr<SimpleDBus::Proxy> {
|
||||
return std::static_pointer_cast<SimpleDBus::Proxy>(std::make_shared<Service>(conn, bus_name, path));
|
||||
}
|
||||
};
|
||||
|
||||
Service::Service(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path)
|
||||
: Proxy(conn, bus_name, path) {}
|
||||
|
||||
|
@@ -44,7 +44,8 @@ class InterfaceRegistry {
|
||||
iface->load(options);
|
||||
return iface;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
return std::make_shared<Interface>(conn, bus_name, path, key);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -99,6 +99,17 @@ class Proxy {
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: This method is used only for testing purposes.
|
||||
static void purge_global_interfaces() {
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
_global_interfaces.clear();
|
||||
}
|
||||
|
||||
static void purge_global_proxies() {
|
||||
std::scoped_lock lock(_global_proxies_mutex);
|
||||
_global_proxies.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _valid;
|
||||
bool _registered;
|
||||
@@ -107,11 +118,16 @@ class Proxy {
|
||||
|
||||
std::shared_ptr<Connection> _conn;
|
||||
|
||||
std::map<std::string, std::shared_ptr<Interface>> _interfaces;
|
||||
std::map<std::string, std::shared_ptr<Proxy>> _children;
|
||||
|
||||
std::recursive_mutex _interface_access_mutex;
|
||||
std::recursive_mutex _child_access_mutex;
|
||||
|
||||
std::map<std::string, std::shared_ptr<Proxy>> children() const;
|
||||
|
||||
static std::map<Path, std::unordered_map<std::string, std::shared_ptr<Interface>>> _global_interfaces;
|
||||
static std::recursive_mutex _global_interfaces_mutex;
|
||||
|
||||
static std::map<Path, std::shared_ptr<Proxy>> _global_proxies;
|
||||
static std::recursive_mutex _global_proxies_mutex;
|
||||
};
|
||||
|
||||
} // namespace SimpleDBus
|
||||
|
60
simpledbus/include/simpledbus/advanced/ProxyRegistry.h
Normal file
60
simpledbus/include/simpledbus/advanced/ProxyRegistry.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
|
||||
#include <simpledbus/base/Connection.h>
|
||||
#include <simpledbus/base/Holder.h>
|
||||
#include <simpledbus/base/Logging.h>
|
||||
|
||||
namespace SimpleDBus {
|
||||
|
||||
class Proxy;
|
||||
|
||||
using ProxyCreatorFunction = std::shared_ptr<Proxy> (*)(std::shared_ptr<Connection>, const std::string&, const std::string&);
|
||||
|
||||
class ProxyRegistry {
|
||||
public:
|
||||
static ProxyRegistry& getInstance() {
|
||||
static ProxyRegistry instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void registerClass(const std::string& prefix, ProxyCreatorFunction creator) {
|
||||
static_assert(std::is_base_of<Proxy, T>::value, "T must inherit from Proxy");
|
||||
creators[prefix] = creator;
|
||||
}
|
||||
|
||||
bool isRegistered(const std::string& prefix) const {
|
||||
return creators.find(prefix) != creators.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<Proxy> create(const std::string& prefix, std::shared_ptr<Connection> conn, const std::string& bus_name, const std::string& path) const {
|
||||
auto it = creators.find(prefix);
|
||||
if (it != creators.end()) {
|
||||
auto proxy = it->second(conn, bus_name, path);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return std::make_shared<Proxy>(conn, bus_name, path);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, ProxyCreatorFunction> creators;
|
||||
ProxyRegistry() = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct AutoRegisterProxy {
|
||||
AutoRegisterProxy(const std::string& prefix, ProxyCreatorFunction creator) {
|
||||
static_assert(std::is_base_of<Proxy, T>::value, "T must inherit from Proxy");
|
||||
ProxyRegistry::getInstance().registerClass<T>(prefix, creator);
|
||||
LOG_DEBUG("Registered class with prefix {}", prefix);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace SimpleDBus
|
@@ -6,10 +6,18 @@
|
||||
#include <simpledbus/base/Path.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
// #include <simpledbus/interfaces/Properties.h>
|
||||
|
||||
using namespace SimpleDBus;
|
||||
|
||||
std::map<Path, std::unordered_map<std::string, std::shared_ptr<Interface>>> Proxy::_global_interfaces;
|
||||
std::recursive_mutex Proxy::_global_interfaces_mutex;
|
||||
|
||||
std::map<Path, std::shared_ptr<Proxy>> Proxy::_global_proxies;
|
||||
std::recursive_mutex Proxy::_global_proxies_mutex;
|
||||
|
||||
Proxy::Proxy(std::shared_ptr<Connection> conn, const std::string& bus_name, const std::string& path)
|
||||
: _conn(conn), _bus_name(bus_name), _path(path), _valid(true), _registered(false) {
|
||||
// TODO: UNCOMMENT THIS WHEN MIGRATING TO NEW PROXY FORWARDING LOGIC
|
||||
@@ -42,9 +50,34 @@ std::string Proxy::path() const { return _path; }
|
||||
|
||||
std::string Proxy::bus_name() const { return _bus_name; }
|
||||
|
||||
const std::map<std::string, std::shared_ptr<Proxy>>& Proxy::children() { return _children; }
|
||||
std::map<std::string, std::shared_ptr<Proxy>> Proxy::children() const {
|
||||
std::map<std::string, std::shared_ptr<Proxy>> direct_children;
|
||||
std::scoped_lock lock(_global_proxies_mutex);
|
||||
|
||||
const std::map<std::string, std::shared_ptr<Interface>>& Proxy::interfaces() { return _interfaces; }
|
||||
// Find the first potential child path (current path + "/")
|
||||
std::string child_prefix = _path + "/";
|
||||
auto it = _global_proxies.lower_bound(Path(child_prefix));
|
||||
|
||||
// Iterate through potential children
|
||||
while (it != _global_proxies.end()) {
|
||||
const std::string& path_str = static_cast<std::string>(it->first);
|
||||
|
||||
// If we've moved beyond children of this path, stop
|
||||
if (path_str.find(child_prefix) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if this is a direct child (not a grandchild)
|
||||
if (PathUtils::is_child(_path, path_str)) {
|
||||
std::string child_path_name = PathUtils::next_child_strip(_path, path_str);
|
||||
direct_children.emplace(child_path_name, it->second);
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
return direct_children;
|
||||
}
|
||||
|
||||
// ----- PATH HANDLING -----
|
||||
|
||||
@@ -72,22 +105,27 @@ std::string Proxy::introspect() {
|
||||
// ----- INTERFACE HANDLING -----
|
||||
|
||||
bool Proxy::interface_exists(const std::string& name) {
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
return _interfaces.find(name) != _interfaces.end();
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
return _global_interfaces[Path(_path)].find(name) != _global_interfaces[Path(_path)].end();
|
||||
}
|
||||
|
||||
std::shared_ptr<Interface> Proxy::interface_get(const std::string& name) {
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
if (!interface_exists(name)) {
|
||||
throw Exception::InterfaceNotFoundException(_path, name);
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[Path(_path)];
|
||||
|
||||
auto iface_it = path_interfaces.find(name);
|
||||
if (iface_it != path_interfaces.end()) {
|
||||
return iface_it->second;
|
||||
}
|
||||
return _interfaces[name];
|
||||
throw Exception::InterfaceNotFoundException(_path, name);
|
||||
}
|
||||
|
||||
size_t Proxy::interfaces_count() {
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[Path(_path)];
|
||||
|
||||
size_t count = 0;
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
for (auto& [iface_name, interface] : _interfaces) {
|
||||
for (auto& [iface_name, interface] : path_interfaces) {
|
||||
if (interface->is_loaded()) {
|
||||
count++;
|
||||
}
|
||||
@@ -98,25 +136,30 @@ size_t Proxy::interfaces_count() {
|
||||
void Proxy::interfaces_load(Holder managed_interfaces) {
|
||||
auto managed_interface = managed_interfaces.get_dict_string();
|
||||
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[Path(_path)];
|
||||
|
||||
for (auto& [iface_name, options] : managed_interface) {
|
||||
// If the interface has not been loaded, load it
|
||||
if (!interface_exists(iface_name)) {
|
||||
auto iface_it = path_interfaces.find(iface_name);
|
||||
if (iface_it == path_interfaces.end()) {
|
||||
// Interface doesn't exist, create it
|
||||
if (InterfaceRegistry::getInstance().isRegistered(iface_name)) {
|
||||
_interfaces.emplace(std::make_pair(
|
||||
iface_name, InterfaceRegistry::getInstance().create(iface_name, _conn, _bus_name, _path, options)));
|
||||
auto interface = InterfaceRegistry::getInstance().create(iface_name, _conn, _bus_name, _path, options);
|
||||
path_interfaces[iface_name] = interface;
|
||||
} else {
|
||||
LOG_WARN("Interface {} not registered within SimpleDBus", iface_name);
|
||||
}
|
||||
} else {
|
||||
_interfaces[iface_name]->load(options);
|
||||
// Interface exists, reload it
|
||||
iface_it->second->load(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Proxy::interfaces_reload(Holder managed_interfaces) {
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
for (auto& [iface_name, interface] : _interfaces) {
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[Path(_path)];
|
||||
for (auto& [iface_name, interface] : path_interfaces) {
|
||||
interface->unload();
|
||||
}
|
||||
|
||||
@@ -124,18 +167,22 @@ void Proxy::interfaces_reload(Holder managed_interfaces) {
|
||||
}
|
||||
|
||||
void Proxy::interfaces_unload(SimpleDBus::Holder removed_interfaces) {
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[Path(_path)];
|
||||
for (auto& option : removed_interfaces.get_array()) {
|
||||
std::string iface_name = option.get_string();
|
||||
if (interface_exists(iface_name)) {
|
||||
_interfaces[iface_name]->unload();
|
||||
auto iface_it = path_interfaces.find(iface_name);
|
||||
if (iface_it != path_interfaces.end()) {
|
||||
iface_it->second->unload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Proxy::interfaces_loaded() {
|
||||
std::scoped_lock lock(_interface_access_mutex);
|
||||
for (auto& [iface_name, interface] : _interfaces) {
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto& path_interfaces = _global_interfaces[Path(_path)];
|
||||
|
||||
for (auto& [iface_name, interface] : path_interfaces) {
|
||||
if (interface->is_loaded()) {
|
||||
return true;
|
||||
}
|
||||
@@ -146,16 +193,17 @@ bool Proxy::interfaces_loaded() {
|
||||
// ----- CHILD HANDLING -----
|
||||
|
||||
bool Proxy::path_exists(const std::string& path) {
|
||||
std::scoped_lock lock(_child_access_mutex);
|
||||
return _children.find(path) != _children.end();
|
||||
std::scoped_lock lock(_global_proxies_mutex);
|
||||
return _global_proxies.find(Path(path)) != _global_proxies.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<Proxy> Proxy::path_get(const std::string& path) {
|
||||
std::scoped_lock lock(_child_access_mutex);
|
||||
if (!path_exists(path)) {
|
||||
std::scoped_lock lock(_global_proxies_mutex);
|
||||
auto it = _global_proxies.find(Path(path));
|
||||
if (it == _global_proxies.end()) {
|
||||
throw Exception::PathNotFoundException(_path, path);
|
||||
}
|
||||
return _children[path];
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Proxy::path_add(const std::string& path, SimpleDBus::Holder managed_interfaces) {
|
||||
@@ -203,12 +251,12 @@ void Proxy::path_add(const std::string& path, SimpleDBus::Holder managed_interfa
|
||||
}
|
||||
}
|
||||
|
||||
bool Proxy::path_remove(const std::string& path, SimpleDBus::Holder options) {
|
||||
bool Proxy::path_remove(const std::string& path, SimpleDBus::Holder removed_interfaces) {
|
||||
// `options` contains an array of strings of the interfaces that need to be removed.
|
||||
|
||||
if (path == _path) {
|
||||
invalidate();
|
||||
interfaces_unload(options);
|
||||
interfaces_unload(removed_interfaces);
|
||||
return path_prune();
|
||||
}
|
||||
|
||||
@@ -223,7 +271,7 @@ bool Proxy::path_remove(const std::string& path, SimpleDBus::Holder options) {
|
||||
// If the path is a direct child of the proxy path, forward the request to the child proxy.
|
||||
std::string child_path = PathUtils::next_child(_path, path);
|
||||
if (path_exists(child_path)) {
|
||||
bool must_erase = _children.at(child_path)->path_remove(path, options);
|
||||
bool must_erase = _children.at(child_path)->path_remove(path, removed_interfaces);
|
||||
|
||||
// if the child proxy is no longer needed and there is only one active instance of the child proxy,
|
||||
// then remove it.
|
||||
@@ -253,6 +301,10 @@ bool Proxy::path_prune() {
|
||||
// For self to be pruned, the following conditions must be met:
|
||||
// 1. The proxy has no children
|
||||
// 2. The proxy has no interfaces or all interfaces are disabled.
|
||||
|
||||
fmt::print("Prune: {} children, {} interfaces\n", _children.size(), interfaces_count());
|
||||
fmt::print("Interfaces: {}\n", interfaces_loaded());
|
||||
|
||||
if (_children.empty() && !interfaces_loaded()) {
|
||||
return true;
|
||||
}
|
||||
@@ -264,9 +316,14 @@ Holder Proxy::path_collect() {
|
||||
SimpleDBus::Holder result = SimpleDBus::Holder::create_dict();
|
||||
SimpleDBus::Holder interfaces = SimpleDBus::Holder::create_dict();
|
||||
|
||||
for (const auto& [interface_name, interface_ptr] : _interfaces) {
|
||||
SimpleDBus::Holder properties = interface_ptr->property_collect();
|
||||
interfaces.dict_append(SimpleDBus::Holder::Type::STRING, interface_name, std::move(properties));
|
||||
// Use global interfaces instead of local _interfaces
|
||||
std::scoped_lock lock(_global_interfaces_mutex);
|
||||
auto path_it = _global_interfaces.find(Path(_path));
|
||||
if (path_it != _global_interfaces.end()) {
|
||||
for (const auto& [interface_name, interface_ptr] : path_it->second) {
|
||||
SimpleDBus::Holder properties = interface_ptr->property_collect();
|
||||
interfaces.dict_append(SimpleDBus::Holder::Type::STRING, interface_name, std::move(properties));
|
||||
}
|
||||
}
|
||||
|
||||
if (!interfaces.get_dict_string().empty()) {
|
||||
@@ -373,3 +430,5 @@ void Proxy::message_handle(Message& msg) {
|
||||
LOG_ERROR("Unhandled message: {}", msg.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -5,6 +5,9 @@
|
||||
using namespace SimpleDBus;
|
||||
|
||||
TEST(ProxyChildren, AppendChild) {
|
||||
Proxy::purge_global_interfaces();
|
||||
Proxy::purge_global_proxies();
|
||||
|
||||
Proxy p = Proxy(nullptr, "", "/a/b");
|
||||
|
||||
p.path_add("/a/b/c", Holder());
|
||||
@@ -14,6 +17,9 @@ TEST(ProxyChildren, AppendChild) {
|
||||
}
|
||||
|
||||
TEST(ProxyChildren, AppendRepeatedChild) {
|
||||
Proxy::purge_global_interfaces();
|
||||
Proxy::purge_global_proxies();
|
||||
|
||||
Proxy p = Proxy(nullptr, "", "/a/b");
|
||||
p.path_add("/a/b/c", Holder());
|
||||
|
||||
@@ -23,6 +29,9 @@ TEST(ProxyChildren, AppendRepeatedChild) {
|
||||
}
|
||||
|
||||
TEST(ProxyChildren, AppendExtendedChild) {
|
||||
Proxy::purge_global_interfaces();
|
||||
Proxy::purge_global_proxies();
|
||||
|
||||
Proxy p = Proxy(nullptr, "", "/");
|
||||
p.path_add("/a/b/c/d", Holder());
|
||||
|
||||
@@ -43,6 +52,9 @@ TEST(ProxyChildren, AppendExtendedChild) {
|
||||
}
|
||||
|
||||
TEST(ProxyChildren, RemoveSelf) {
|
||||
Proxy::purge_global_interfaces();
|
||||
Proxy::purge_global_proxies();
|
||||
|
||||
Proxy p = Proxy(nullptr, "", "/");
|
||||
|
||||
// Should notify that the proxy can be safely deleted, as nothing worth keeping is left
|
||||
@@ -65,6 +77,9 @@ TEST(ProxyChildren, RemoveSelf) {
|
||||
}
|
||||
|
||||
TEST(ProxyChildren, RemoveChildNoInterfaces) {
|
||||
Proxy::purge_global_interfaces();
|
||||
Proxy::purge_global_proxies();
|
||||
|
||||
Proxy p = Proxy(nullptr, "", "/");
|
||||
p.path_add("/a", Holder());
|
||||
|
||||
@@ -82,6 +97,9 @@ TEST(ProxyChildren, RemoveChildNoInterfaces) {
|
||||
}
|
||||
|
||||
TEST(ProxyChildren, RemoveChildWithInterfaces) {
|
||||
Proxy::purge_global_interfaces();
|
||||
Proxy::purge_global_proxies();
|
||||
|
||||
Proxy p = Proxy(nullptr, "", "/");
|
||||
|
||||
Holder managed_interfaces = Holder::create_dict();
|
||||
@@ -98,7 +116,6 @@ TEST(ProxyChildren, RemoveChildWithInterfaces) {
|
||||
{
|
||||
std::shared_ptr<Proxy> p_a = std::dynamic_pointer_cast<Proxy>(p.children().at("/a"));
|
||||
ASSERT_EQ(1, p_a->interfaces_count());
|
||||
ASSERT_EQ(1, p_a->interfaces().count("i.1"));
|
||||
}
|
||||
|
||||
// Remove the second interface
|
||||
|
@@ -44,8 +44,8 @@ TEST(ProxyInterfaces, LoadInterfaces) {
|
||||
h.interfaces_load(managed_interfaces);
|
||||
|
||||
EXPECT_TRUE(h.interfaces_loaded());
|
||||
EXPECT_EQ(1, h.interfaces().size());
|
||||
EXPECT_EQ(1, h.interfaces().count("i.1"));
|
||||
EXPECT_EQ(1, h.interfaces_count());
|
||||
EXPECT_TRUE(h.interface_exists("i.1"));
|
||||
}
|
||||
|
||||
TEST(ProxyInterfaces, UnloadInterfaces) {
|
||||
@@ -64,7 +64,7 @@ TEST(ProxyInterfaces, UnloadInterfaces) {
|
||||
|
||||
EXPECT_EQ(2, h.interfaces_count());
|
||||
EXPECT_TRUE(h.interfaces_loaded());
|
||||
EXPECT_FALSE(h.interfaces().at("i.3")->is_loaded());
|
||||
EXPECT_FALSE(h.interface_get("i.3")->is_loaded());
|
||||
|
||||
removed_interfaces = Holder::create_array();
|
||||
removed_interfaces.array_append(Holder::create_string("i.2"));
|
||||
@@ -72,7 +72,7 @@ TEST(ProxyInterfaces, UnloadInterfaces) {
|
||||
|
||||
EXPECT_EQ(1, h.interfaces_count());
|
||||
EXPECT_TRUE(h.interfaces_loaded());
|
||||
EXPECT_FALSE(h.interfaces().at("i.2")->is_loaded());
|
||||
EXPECT_FALSE(h.interface_get("i.2")->is_loaded());
|
||||
|
||||
removed_interfaces = Holder::create_array();
|
||||
removed_interfaces.array_append(Holder::create_string("i.1"));
|
||||
@@ -80,7 +80,7 @@ TEST(ProxyInterfaces, UnloadInterfaces) {
|
||||
|
||||
EXPECT_EQ(0, h.interfaces_count());
|
||||
EXPECT_FALSE(h.interfaces_loaded());
|
||||
EXPECT_FALSE(h.interfaces().at("i.1")->is_loaded());
|
||||
EXPECT_FALSE(h.interface_get("i.1")->is_loaded());
|
||||
}
|
||||
|
||||
TEST(ProxyInterfaces, ReloadInterfaces) {
|
||||
|
Reference in New Issue
Block a user