From 4ffce73b8f2bd17305e65e95210d604fc2d5c68b Mon Sep 17 00:00:00 2001 From: arlo-phoenix Date: Sat, 18 Nov 2023 15:18:15 +0100 Subject: [PATCH] Add DBusClient node --- project/demo/dbus_client_example.gd | 10 +- project/demo/dbus_client_node_example.gd | 10 ++ project/demo/dbus_client_util.gd | 12 ++ project/demo/dbus_client_util.tscn | 10 ++ project/demo/dbus_server_example.gd | 20 +-- project/demo/server_client_example.tscn | 15 +- src/dbus_client.cpp | 65 +++----- src/dbus_client.h | 16 +- src/dbus_client_node.cpp | 196 +++++++++++++++++++++++ src/dbus_client_node.h | 84 ++++++++++ src/dbus_privilege.h | 7 + src/dbus_response.cpp | 54 +++---- src/dbus_response.h | 8 +- src/dbus_server_node.cpp | 41 ++--- src/register_types.cpp | 4 +- 15 files changed, 422 insertions(+), 130 deletions(-) create mode 100644 project/demo/dbus_client_node_example.gd create mode 100644 project/demo/dbus_client_util.gd create mode 100644 project/demo/dbus_client_util.tscn create mode 100644 src/dbus_client_node.cpp create mode 100644 src/dbus_client_node.h create mode 100644 src/dbus_privilege.h diff --git a/project/demo/dbus_client_example.gd b/project/demo/dbus_client_example.gd index 49994b9..fe1fb36 100644 --- a/project/demo/dbus_client_example.gd +++ b/project/demo/dbus_client_example.gd @@ -11,14 +11,14 @@ var num2=0 func test_request(): var client=DBusClient.new() - client.destination="net.poettering.Calculator" - client.path="/net/poettering/Calculator" - client.interface="net.poettering.Calculator" - + var destination="net.poettering.Calculator" + var path="/net/poettering/Calculator" + var interface="net.poettering.Calculator" var member="Multiply" + client.open() - var request_message=client.create_request(member) + var request_message=client.create_request(destination, path, interface, member) request_message.append(num1) request_message.append(num2) var response_message=client.send_request(request_message) diff --git a/project/demo/dbus_client_node_example.gd b/project/demo/dbus_client_node_example.gd new file mode 100644 index 0000000..1c8980d --- /dev/null +++ b/project/demo/dbus_client_node_example.gd @@ -0,0 +1,10 @@ +extends DBusClientNode + + +func _on_request_finished(response: DBusMessage): + assert(response) + print(response.read_single(TYPE_FLOAT)) + +func _on_timer_timeout(): + open() + var err=request("Divide", _on_request_finished, 50, 10) diff --git a/project/demo/dbus_client_util.gd b/project/demo/dbus_client_util.gd new file mode 100644 index 0000000..2d92bba --- /dev/null +++ b/project/demo/dbus_client_util.gd @@ -0,0 +1,12 @@ +extends DBusClientNode + +func _ready(): + open() + #godots XMLParser is horrible so if you want to display this use some C++ library or plugin + print(introspect()) + + # if you have a parser would need to call this down the tree + # to replicate busctl tree + print(introspect_path("/org")) + + close() diff --git a/project/demo/dbus_client_util.tscn b/project/demo/dbus_client_util.tscn new file mode 100644 index 0000000..fbe2568 --- /dev/null +++ b/project/demo/dbus_client_util.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=2 format=3 uid="uid://c670mp7v4rfln"] + +[ext_resource type="Script" path="res://demo/dbus_client_util.gd" id="1_lk0kj"] + +[node name="DBusClientUtil" type="DBusClientNode"] +destination = "org.freedesktop.portal.Desktop" +path = "/org/freedesktop/portal/desktop" +interface = "org.freedesktop.portal.Desktop" +autostart = false +script = ExtResource("1_lk0kj") diff --git a/project/demo/dbus_server_example.gd b/project/demo/dbus_server_example.gd index 6a7720e..a380f61 100644 --- a/project/demo/dbus_server_example.gd +++ b/project/demo/dbus_server_example.gd @@ -2,30 +2,30 @@ extends DBusServerNode @onready var client=$"../DBusClient" -func _multiply(message: DBusResponse) -> int: - var message_signature=message.read() +func _multiply(request: DBusRequest) -> int: + var message_signature=request.read() var response=Array() response.append(message_signature[0] * message_signature[1]) - message.reply(response) + request.reply(response) return 0 -func _empty(message: DBusResponse) -> int: +func _empty(request: DBusRequest) -> int: var response=Array() - print("do shit") + print("do sth") response.append(true) - message.reply(response) + request.reply(response) return 0 -func _divide(message: DBusResponse) -> int: - var message_signature=message.read() +func _divide(request: DBusRequest) -> int: + var message_signature=request.read() var num1:float=message_signature[0] var num2:float=message_signature[1] if num2==0: - message.set_error("net.poettering.DivisionByZero", "Division by zero not allowed") + request.set_error("net.poettering.DivisionByZero", "Division by zero not allowed") return -ERR_INVALID_PARAMETER var response=Array() response.append(num1/num2) - message.reply(response) + request.reply(response) return 0 func _ready() -> void: diff --git a/project/demo/server_client_example.tscn b/project/demo/server_client_example.tscn index c69a002..8be1cb4 100644 --- a/project/demo/server_client_example.tscn +++ b/project/demo/server_client_example.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=13 format=3 uid="uid://c7u64tpv6byvb"] +[gd_scene load_steps=14 format=3 uid="uid://c7u64tpv6byvb"] [ext_resource type="Script" path="res://demo/dbus_server_example.gd" id="1_jyovi"] [ext_resource type="Script" path="res://demo/dbus_client_example.gd" id="2_ik254"] +[ext_resource type="Script" path="res://demo/dbus_client_node_example.gd" id="3_pfkpg"] [sub_resource type="DBusMethodArgument" id="DBusMethodArgument_7xm51"] @@ -39,13 +40,23 @@ result = Array[DBusMethodArgument]([SubResource("DBusMethodArgument_rishs")]) object_path = "/net/poettering/Calculator" interface_name = "net.poettering.Calculator" methods = [SubResource("DBusMethod_pftgm"), SubResource("DBusMethod_1nn3q"), SubResource("DBusMethod_02o38")] +autostart = true script = ExtResource("1_jyovi") [node name="DBusClient" type="Node" parent="."] script = ExtResource("2_ik254") [node name="Timer" type="Timer" parent="."] -wait_time = 2.0 +one_shot = true autostart = true +[node name="DBusClientNode" type="DBusClientNode" parent="."] +destination = "net.poettering.Calculator" +path = "/net/poettering/Calculator" +interface = "net.poettering.Calculator" +autostart = false +use_threads = true +script = ExtResource("3_pfkpg") + [connection signal="timeout" from="Timer" to="DBusClient" method="_on_timer_timeout"] +[connection signal="timeout" from="Timer" to="DBusClientNode" method="_on_timer_timeout"] diff --git a/src/dbus_client.cpp b/src/dbus_client.cpp index c881e54..617d9c2 100644 --- a/src/dbus_client.cpp +++ b/src/dbus_client.cpp @@ -1,4 +1,4 @@ -#include "dbus_client.h" + /* Code mostly just copied and packed from https://www.freedesktop.org/software/systemd/man/latest/sd_bus_call_method.html# @@ -7,6 +7,9 @@ licensed under: SPDX-License-Identifier: MIT-0 */ +#include "dbus_client.h" +#include "dbus_privilege.h" + #define ERR_BUS_FAIL(msg) \ ERR_FAIL_COND_MSG(r < 0, String(msg) + ": " + strerror(-r)) @@ -14,23 +17,11 @@ SPDX-License-Identifier: MIT-0 ERR_FAIL_COND_V_MSG(r < 0, ret, String(msg) + ": " + strerror(-r)) void DBusClient::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_destination", "p_destination"), &DBusClient::set_destination); - ClassDB::bind_method(D_METHOD("get_destination"), &DBusClient::get_destination); - - ClassDB::bind_method(D_METHOD("set_path", "p_path"), &DBusClient::set_path); - ClassDB::bind_method(D_METHOD("get_path"), &DBusClient::get_path); - - ClassDB::bind_method(D_METHOD("set_interface", "p_interface"), &DBusClient::set_interface); - ClassDB::bind_method(D_METHOD("get_interface"), &DBusClient::get_interface); - - ClassDB::bind_method(D_METHOD("create_request", "member"), &DBusClient::create_request); + ClassDB::bind_method(D_METHOD("create_request", "destination", "path", "interface", "member"), &DBusClient::create_request); ClassDB::bind_method(D_METHOD("send_request", "request"), &DBusClient::send_request); ClassDB::bind_method(D_METHOD("open"), &DBusClient::open); ClassDB::bind_method(D_METHOD("close"), &DBusClient::close); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "destination"), "set_destination", "get_destination"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "path"), "set_path", "get_path"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "interface"), "set_interface", "get_interface"); + ClassDB::bind_method(D_METHOD("is_open"), &DBusClient::is_open); } DBusClient::DBusClient() { @@ -42,32 +33,8 @@ DBusClient::~DBusClient() { } } -void DBusClient::set_destination(const String &p_destination) { - _destination = p_destination; -} - -String DBusClient::get_destination() const { - return _destination; -} - -void DBusClient::set_path(const String &p_path) { - _path = p_path; -} - -String DBusClient::get_path() const { - return _path; -} - -void DBusClient::set_interface(const String &p_interface) { - _interface = p_interface; -} - -String DBusClient::get_interface() const { - return _interface; -} - void DBusClient::open() { - int r = sd_bus_open_user(&_bus); + int r = D_BUS_OPEN(&_bus); ERR_BUS_FAIL("Failed to acquire bus"); _open = true; } @@ -78,16 +45,20 @@ void DBusClient::close() { _open = false; } -Ref DBusClient::create_request(const String &p_member) { +bool DBusClient::is_open() const { + return _open; +} + +Ref DBusClient::create_request(const String &p_destination, const String &p_path, const String &p_interface, const String &p_member) { ERR_FAIL_COND_V(!_open, nullptr); - sd_bus_message *msg = nullptr; - int r = sd_bus_message_new_method_call(_bus, &msg, - _destination.utf8(), - _path.utf8(), - _interface.utf8(), + sd_bus_message *reply = nullptr; + int r = sd_bus_message_new_method_call(_bus, &reply, + p_destination.utf8(), + p_path.utf8(), + p_interface.utf8(), p_member.utf8()); ERR_BUS_FAIL_V(String("Failed to created request: ") + _error.message, nullptr); - return DBusMessage::from_internal(msg, true); + return DBusMessage::from_internal(reply, true); } Ref DBusClient::send_request(const Ref &p_request) { diff --git a/src/dbus_client.h b/src/dbus_client.h index b8cbff4..2f08876 100644 --- a/src/dbus_client.h +++ b/src/dbus_client.h @@ -13,10 +13,6 @@ class DBusClient : public RefCounted { sd_bus *_bus = nullptr; sd_bus_error _error = SD_BUS_ERROR_NULL; - String _destination; - String _path; - String _interface; - bool _open = false; protected: @@ -26,18 +22,10 @@ class DBusClient : public RefCounted { DBusClient(); ~DBusClient(); - void set_destination(const String &p_destination); - String get_destination() const; - - void set_path(const String &p_path); - String get_path() const; - - void set_interface(const String &p_interface); - String get_interface() const; - void open(); void close(); + bool is_open() const; - Ref create_request(const String &p_member); + Ref create_request(const String &p_destination, const String &p_path, const String &p_interface, const String &p_member); Ref send_request(const Ref &p_request); }; \ No newline at end of file diff --git a/src/dbus_client_node.cpp b/src/dbus_client_node.cpp new file mode 100644 index 0000000..e92aa71 --- /dev/null +++ b/src/dbus_client_node.cpp @@ -0,0 +1,196 @@ +#include "dbus_client_node.h" +#include + +void DBusClientNode::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_destination", "destination"), &DBusClientNode::set_destination); + ClassDB::bind_method(D_METHOD("get_destination"), &DBusClientNode::get_destination); + + ClassDB::bind_method(D_METHOD("set_path", "path"), &DBusClientNode::set_path); + ClassDB::bind_method(D_METHOD("get_path"), &DBusClientNode::get_path); + + ClassDB::bind_method(D_METHOD("set_interface", "interface"), &DBusClientNode::set_interface); + ClassDB::bind_method(D_METHOD("get_interface"), &DBusClientNode::get_interface); + + ClassDB::bind_method(D_METHOD("open"), &DBusClientNode::open); + ClassDB::bind_method(D_METHOD("close"), &DBusClientNode::close); + ClassDB::bind_method(D_METHOD("is_open"), &DBusClientNode::is_open); + + ClassDB::bind_method(D_METHOD("set_autostart", "autostart"), &DBusClientNode::set_autostart); + ClassDB::bind_method(D_METHOD("get_autostart"), &DBusClientNode::get_autostart); + + ClassDB::bind_method(D_METHOD("set_use_threads", "use_threads"), &DBusClientNode::set_use_threads); + ClassDB::bind_method(D_METHOD("get_use_threads"), &DBusClientNode::get_use_threads); + + { + MethodInfo mi; + mi.arguments.push_back(PropertyInfo(Variant::STRING, "member")); + mi.arguments.push_back(PropertyInfo(Variant::CALLABLE, "callback")); + mi.name = "request"; + ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "request", &DBusClientNode::request, mi); + } + ClassDB::bind_method(D_METHOD("_request", "request_message", "callback"), &DBusClientNode::_request); + + //start util + ClassDB::bind_method(D_METHOD("introspect"), &DBusClientNode::introspect); + ClassDB::bind_method(D_METHOD("introspect_path", "object_path"), &DBusClientNode::introspect_path); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "destination"), "set_destination", "get_destination"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "path"), "set_path", "get_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "interface"), "set_interface", "get_interface"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "get_autostart"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "get_use_threads"); +} + +DBusClientNode::DBusClientNode() { + _client.instantiate(); +} + +DBusClientNode::~DBusClientNode() { + if (is_open()) { + close(); + } +} + +void DBusClientNode::_notification(int p_what) { + if (p_what == NOTIFICATION_READY) { + if (Engine::get_singleton()->is_editor_hint()) { + return; + } + + if (_autostart) { + open(); + } + } +} + +void DBusClientNode::set_destination(const String &p_destination) { + _destination = p_destination; +} + +String DBusClientNode::get_destination() const { + return _destination; +} + +void DBusClientNode::set_path(const String &p_path) { + _path = p_path; +} + +String DBusClientNode::get_path() const { + return _path; +} + +void DBusClientNode::set_interface(const String &p_interface) { + _interface = p_interface; +} + +String DBusClientNode::get_interface() const { + return _interface; +} + +void DBusClientNode::open() { + _client->open(); +} + +void DBusClientNode::close() { + if (_thread.is_started()) { + _thread.wait_to_finish(); + } + + _client->close(); +} + +bool DBusClientNode::is_open() const { + return _client->is_open(); +} + +void DBusClientNode::set_autostart(const bool p_autostart) { + _autostart = p_autostart; +} + +bool DBusClientNode::get_autostart() const { + return _autostart; +} + +void DBusClientNode::set_use_threads(const bool p_use_threads) { + _use_threads = p_use_threads; +} + +bool DBusClientNode::get_use_threads() const { + return _use_threads; +} + +Error DBusClientNode::request(const Variant **p_args, GDExtensionInt p_arg_count, GDExtensionCallError &error) { + if (p_arg_count < 2) { + error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; + error.expected = 2; + return ERR_INVALID_PARAMETER; + } + + Variant::Type type = p_args[0]->get_type(); + if (type != Variant::STRING && type != Variant::STRING_NAME) { + error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT; + error.argument = 0; + error.expected = Variant::STRING; + return ERR_INVALID_PARAMETER; + } + const String member = *p_args[0]; + + type = p_args[1]->get_type(); + if (type != Variant::CALLABLE) { + error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT; + error.argument = 1; + error.expected = Variant::CALLABLE; + return ERR_INVALID_PARAMETER; + } + const Callable callback = *p_args[1]; + + if (_use_threads && _thread.is_alive()) { + _thread.wait_to_finish(); + } + + Ref request_message = _client->create_request(_destination, + _path, + _interface, + member); + + for (int i = 2; i < p_arg_count; i++) { + request_message->append(*p_args[i]); + } + + if (_use_threads) { + Callable async_request = Callable(this, "_request"); + async_request = async_request.bind(request_message, callback); + _thread.start(async_request); + } else { + _request(request_message, callback); + } + + return OK; +} + +String DBusClientNode::introspect() { + ERR_FAIL_COND_V(!is_open(), String()); + Ref request_message = _client->create_request(get_destination(), get_path(), "org.freedesktop.DBus.Introspectable", "Introspect"); + ERR_FAIL_COND_V(request_message.is_null(), String()); + Ref response = _client->send_request(request_message); + ERR_FAIL_COND_V(response.is_null(), String()); + return response->read_single(Variant::Type::STRING); +} + +String DBusClientNode::introspect_path(const String &object_path) { + ERR_FAIL_COND_V(!is_open(), String()); + Ref request_message = _client->create_request(get_destination(), object_path, "org.freedesktop.DBus.Introspectable", "Introspect"); + ERR_FAIL_COND_V(request_message.is_null(), String()); + Ref response = _client->send_request(request_message); + ERR_FAIL_COND_V(response.is_null(), String()); + return response->read_single(Variant::Type::STRING); +} + +void DBusClientNode::_request(const Ref &p_request, Callable callback) { + Ref response = _client->send_request(p_request); + if (_use_threads) { + callback.call(response); + } else { + callback.call(response); + } +} diff --git a/src/dbus_client_node.h b/src/dbus_client_node.h new file mode 100644 index 0000000..d30d89c --- /dev/null +++ b/src/dbus_client_node.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include + +using namespace godot; + +/** + * @brief Just pasted properties from DBusClient and async callback implementation + * + */ +class DBusClientNode : public Node { + GDCLASS(DBusClientNode, Node) +private: + Ref _client; + String _destination; + String _path; + String _interface; + + /** + * @brief internal request which sends and waits for a response, threaded if _use_threads is set + * + * @param p_request + * @param callback + */ + void _request(const Ref &p_request, Callable callback); + Thread _thread; + bool _autostart = true; + bool _use_threads = false; + +protected: + static void _bind_methods(); + +public: + DBusClientNode(); + ~DBusClientNode(); + + void _notification(int p_what); + + void set_destination(const String &p_destination); + String get_destination() const; + + void set_path(const String &p_path); + String get_path() const; + + void set_interface(const String &p_interface); + String get_interface() const; + + void open(); + void close(); + bool is_open() const; + + void set_autostart(const bool p_autostart); + bool get_autostart() const; + + void set_use_threads(const bool p_use_threads); + bool get_use_threads() const; + + /** + * @brief Request member, callback, arg1, arg2,... (member and callback are necessary) + * + * @param p_args + * @param p_arg_count + * @param error + * @return Error + */ + Error request(const Variant **p_args, GDExtensionInt p_arg_count, GDExtensionCallError &error); + + //start utility + /** + * @brief busctl introspect the service + * + * @return String + */ + String introspect(); + /** + * @brief useful to replicate tree call + * + * @return String + * + */ + String introspect_path(const String &object_path); +}; \ No newline at end of file diff --git a/src/dbus_privilege.h b/src/dbus_privilege.h new file mode 100644 index 0000000..43fee84 --- /dev/null +++ b/src/dbus_privilege.h @@ -0,0 +1,7 @@ +#pragma once + +#ifdef GODOT_DBUS_SYSTEM_LEVEL +#define D_BUS_OPEN sd_bus_open_system +#else +#define D_BUS_OPEN sd_bus_open_user +#endif \ No newline at end of file diff --git a/src/dbus_response.cpp b/src/dbus_response.cpp index 2850ecf..2993ae7 100644 --- a/src/dbus_response.cpp +++ b/src/dbus_response.cpp @@ -1,25 +1,25 @@ #include "dbus_response.h" #include "dbus_method.h" -void DBusResponse::_bind_methods() { - ClassDB::bind_method(D_METHOD("read_all"), &DBusResponse::read_all); - ClassDB::bind_method(D_METHOD("reply", "args"), &DBusResponse::reply); - ClassDB::bind_method(D_METHOD("set_error", "name", "message"), &DBusResponse::set_error); +void DBusRequest::_bind_methods() { + ClassDB::bind_method(D_METHOD("read_all"), &DBusRequest::read_all); + ClassDB::bind_method(D_METHOD("reply", "args"), &DBusRequest::reply); + ClassDB::bind_method(D_METHOD("set_error", "name", "message"), &DBusRequest::set_error); - ClassDB::bind_method(D_METHOD("set_response_code", "response_code"), &DBusResponse::set_response_code); - ClassDB::bind_method(D_METHOD("get_response_code"), &DBusResponse::get_response_code); - ClassDB::bind_method(D_METHOD("is_valid"), &DBusResponse::is_valid); + ClassDB::bind_method(D_METHOD("set_response_code", "response_code"), &DBusRequest::set_response_code); + ClassDB::bind_method(D_METHOD("get_response_code"), &DBusRequest::get_response_code); + ClassDB::bind_method(D_METHOD("is_valid"), &DBusRequest::is_valid); - ClassDB::bind_method(D_METHOD("get_message"), &DBusResponse::get_message); - ClassDB::bind_method(D_METHOD("read"), &DBusResponse::read_all); - ClassDB::bind_method(D_METHOD("read_single", "type"), &DBusResponse::read_single); + ClassDB::bind_method(D_METHOD("get_message"), &DBusRequest::get_message); + ClassDB::bind_method(D_METHOD("read"), &DBusRequest::read_all); + ClassDB::bind_method(D_METHOD("read_single", "type"), &DBusRequest::read_single); ADD_PROPERTY(PropertyInfo(Variant::INT, "response_code"), "set_response_code", "get_response_code"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "message"), "", "get_message"); } -Ref DBusResponse::from_internal(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - Ref message; +Ref DBusRequest::from_internal(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + Ref message; message.instantiate(); message->set_internal_message(m); message->set_userdata(userdata); @@ -28,31 +28,31 @@ Ref DBusResponse::from_internal(sd_bus_message *m, void *userdata, return message; } -DBusResponse::DBusResponse() : +DBusRequest::DBusRequest() : _message(nullptr), _userdata(nullptr), _ret_error(nullptr), _response_code(0) { } -void DBusResponse::set_internal_message(sd_bus_message *p_message) { +void DBusRequest::set_internal_message(sd_bus_message *p_message) { _message = DBusMessage::from_internal(p_message); } -void DBusResponse::set_userdata(void *p_userdata) { +void DBusRequest::set_userdata(void *p_userdata) { _userdata = p_userdata; } -void DBusResponse::set_bus_error(sd_bus_error *p_ret_error) { +void DBusRequest::set_bus_error(sd_bus_error *p_ret_error) { _ret_error = p_ret_error; } -void DBusResponse::set_signature(const Array &p_signature) { +void DBusRequest::set_signature(const Array &p_signature) { _signature = p_signature; } -void DBusResponse::set_result(const Array &p_result) { +void DBusRequest::set_result(const Array &p_result) { _result = p_result; } -Array DBusResponse::read_all() { +Array DBusRequest::read_all() { Array input_arguments; input_arguments.resize(_signature.size()); @@ -63,11 +63,11 @@ Array DBusResponse::read_all() { return input_arguments; } -Variant DBusResponse::read_single(const Variant::Type p_type) { +Variant DBusRequest::read_single(const Variant::Type p_type) { return _message->read_single(p_type); } -void DBusResponse::reply(const Array &args) { +void DBusRequest::reply(const Array &args) { ERR_FAIL_COND(args.size() != _result.size()); InternalDBusMessageContainer reply; @@ -87,26 +87,26 @@ void DBusResponse::reply(const Array &args) { ERR_FAIL_COND_MSG(_response_code < 0, "Failed to send message"); } -void DBusResponse::set_error(const String &p_name, const String &p_message) { +void DBusRequest::set_error(const String &p_name, const String &p_message) { sd_bus_error_set_const(_ret_error, p_name.utf8().get_data(), p_message.utf8().get_data()); } -int DBusResponse::get_response_code() const { +int DBusRequest::get_response_code() const { return _response_code; } -void DBusResponse::set_response_code(const int p_response_code) { +void DBusRequest::set_response_code(const int p_response_code) { _response_code = p_response_code; } -Ref DBusResponse::get_message() const { +Ref DBusRequest::get_message() const { return _message; } -bool DBusResponse::is_valid() const { +bool DBusRequest::is_valid() const { return _response_code >= 0; } -String DBusResponse::get_member() const { +String DBusRequest::get_member() const { return _message->get_member(); } diff --git a/src/dbus_response.h b/src/dbus_response.h index 543998f..861159a 100644 --- a/src/dbus_response.h +++ b/src/dbus_response.h @@ -8,8 +8,8 @@ using namespace godot; #include "dbus_method.h" #include "systemd/sd-bus.h" -class DBusResponse : public RefCounted { - GDCLASS(DBusResponse, RefCounted) +class DBusRequest : public RefCounted { + GDCLASS(DBusRequest, RefCounted) private: Ref _message; void *_userdata; @@ -34,8 +34,8 @@ class DBusResponse : public RefCounted { * @param p_result Array * @return Ref */ - static Ref from_internal(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); - DBusResponse(); + static Ref from_internal(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); + DBusRequest(); void set_internal_message(sd_bus_message *p_message); void set_userdata(void *p_userdata); void set_bus_error(sd_bus_error *p_ret_error); diff --git a/src/dbus_server_node.cpp b/src/dbus_server_node.cpp index a10ca29..86fa399 100644 --- a/src/dbus_server_node.cpp +++ b/src/dbus_server_node.cpp @@ -1,5 +1,5 @@ #include "dbus_server_node.h" - +#include "dbus_privilege.h" #include "dbus_response.h" #include @@ -48,22 +48,6 @@ DBusServerNode::~DBusServerNode() { } } -void DBusServerNode::stop() { - ERR_FAIL_COND_MSG(!_running, "Already stopped"); - _set_running(false); - if (_thread.is_alive()) { - _thread.wait_to_finish(); - } - sd_bus_slot_unref(_slot); - sd_bus_unref(_bus); - _slot = nullptr; - _bus = nullptr; - - delete[] v_table; - v_table = nullptr; - _v_table_size = 0; -} - void DBusServerNode::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { if (Engine::get_singleton()->is_editor_hint()) { @@ -155,6 +139,7 @@ bool DBusServerNode::is_running() { void DBusServerNode::start() { //since start and end + 2 + ERR_FAIL_COND_MSG(_running, "Already running"); _v_table_size = _methods.size() + 2; v_table = new sd_bus_vtable[_v_table_size]; v_table[0] = SD_BUS_VTABLE_START(0); @@ -168,7 +153,7 @@ void DBusServerNode::start() { v_table[_v_table_size - 1] = SD_BUS_VTABLE_END; int r; - r = sd_bus_open_user(&_bus); + r = D_BUS_OPEN(&_bus); ERR_BUS_FAIL("Failed to connect system bus"); r = sd_bus_add_object_vtable(_bus, @@ -188,6 +173,22 @@ void DBusServerNode::start() { _running = true; } +void DBusServerNode::stop() { + ERR_FAIL_COND_MSG(!_running, "Already stopped"); + _set_running(false); + if (_thread.is_alive()) { + _thread.wait_to_finish(); + } + sd_bus_slot_unref(_slot); + sd_bus_unref(_bus); + _slot = nullptr; + _bus = nullptr; + + delete[] v_table; + v_table = nullptr; + _v_table_size = 0; +} + int DBusServerNode::_server_callback_wrapper(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { DBusServerNode *server = static_cast(userdata); //callback is static so use userdata pointer to call object callback @@ -195,8 +196,8 @@ int DBusServerNode::_server_callback_wrapper(sd_bus_message *m, void *userdata, } int DBusServerNode::_server_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - Ref message = DBusResponse::from_internal(m, userdata, ret_error); - //call callback, DBusResponse contains all required data to read/respond + Ref message = DBusRequest::from_internal(m, userdata, ret_error); + //call callback, DBusRequest contains all required data to read/respond if (!_method_map.has(message->get_member())) { return 0; } diff --git a/src/register_types.cpp b/src/register_types.cpp index e952c88..9c3dd75 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -7,6 +7,7 @@ #include #include "dbus_client.h" +#include "dbus_client_node.h" #include "dbus_message.h" #include "dbus_method.h" #include "dbus_response.h" @@ -17,11 +18,12 @@ using namespace godot; void gdextension_initialize(ModuleInitializationLevel p_level) { if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) { ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); } }