GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/platform/linux_dbus_api.h
Date: 2026-05-04 21:11:01
Exec Total Coverage
Lines: 0 146 0.0%
Functions: 0 6 0.0%
Branches: 0 90 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #ifndef GATE_SYSTEM_PLATFORM_LINUX_DBUS_API_H_INCLUDED
30 #define GATE_SYSTEM_PLATFORM_LINUX_DBUS_API_H_INCLUDED
31
32 #include <dbus/dbus.h>
33 #include "gate/libraries.h"
34 #include "gate/results.h"
35 #include "gate/values.h"
36
37 typedef struct gate_libdbus_class
38 {
39 void (*error_init)(DBusError* ptr_error);
40 dbus_bool_t (*error_is_set)(DBusError* ptr_error);
41 void (*error_free)(DBusError* ptr_error);
42
43 DBusConnection* (*bus_get)(DBusBusType type, DBusError* ptr_error);
44
45 DBusConnection* (*connection_open)(const char* address, DBusError* error);
46 DBusConnection* (*connection_ref)(DBusConnection* connection);
47 void (*connection_unref)(DBusConnection* connection);
48 void (*connection_close)(DBusConnection* connection);
49 DBusMessage* (*connection_send_with_reply_and_block)(DBusConnection* connection, DBusMessage* message, int timeout_milliseconds, DBusError* error);
50
51 DBusMessage* (*message_ref)(DBusMessage* message);
52 void (*message_unref)(DBusMessage* message);
53 DBusMessage* (*message_copy)(const DBusMessage* message);
54 DBusMessage* (*message_new_method_call)(const char* bus_name, const char* path, const char* iface, const char* method);
55 dbus_bool_t (*message_append_args)(DBusMessage* message, int first_arg_type, ...);
56
57 dbus_bool_t (*message_iter_init) (DBusMessage* message, DBusMessageIter* iter);
58 int (*message_iter_get_arg_type)(DBusMessageIter* iter);
59 void (*message_iter_recurse) (DBusMessageIter* iter, DBusMessageIter* sub);
60 void (*message_iter_get_basic) (DBusMessageIter* iter, void* value);
61 dbus_bool_t (*message_iter_next) (DBusMessageIter* iter);
62 void (*message_iter_init_append) (DBusMessage* message, DBusMessageIter *iter);
63 dbus_bool_t (*message_iter_append_basic) (DBusMessageIter* iter, int type, const void* value);
64 dbus_bool_t (*message_iter_open_container) (DBusMessageIter* iter, int type, const char* contained_signature, DBusMessageIter* sub);
65 dbus_bool_t (*message_iter_close_container) (DBusMessageIter* iter, DBusMessageIter* sub);
66 } gate_libdbus_t;
67
68
69 #if defined(GATE_SYSTEM_LIBDBUS_STATIC)
70
71 static gate_result_t load_libdbus_lib(void)
72 {
73 return GATE_RESULT_OK;
74 }
75
76 # define LOAD_DBUS_FUNC(funcptr, funcname) do { funcptr = funcname; } while(0)
77
78 #else
79
80 static gate_library_t global_libdbus_lib = NULL;
81
82 static gate_result_t load_libdbus_lib(void)
83 {
84 static gate_string_t const libdbus_libname = GATE_STRING_INIT_STATIC("libdbus-1.so");
85 gate_result_t ret;
86
87 if (global_libdbus_lib == NULL)
88 {
89 ret = gate_library_open(&libdbus_libname, &global_libdbus_lib, 0);
90 if (GATE_FAILED(ret))
91 {
92 global_libdbus_lib = NULL;
93 }
94 }
95 else
96 {
97 ret = GATE_RESULT_OK;
98 }
99 return ret;
100 }
101
102 static gate_result_t load_libdbus_function(void* ptr_funcptr, char const* funcname)
103 {
104 return gate_library_get_function_name(global_libdbus_lib, funcname, ptr_funcptr);
105 }
106
107 # define LOAD_DBUS_FUNC(funcptr, funcname) \
108 do { \
109 gate_result_t result = load_libdbus_function(&funcptr, #funcname); \
110 if(GATE_FAILED(result)) { return result; } \
111 } while(0)
112
113 #endif
114
115
116 static gate_result_t load_libdbus(gate_libdbus_t* dbus)
117 {
118 gate_result_t result = load_libdbus_lib();
119 if (GATE_FAILED(result))
120 {
121 return result;
122 }
123
124 LOAD_DBUS_FUNC(dbus->error_init, dbus_error_init);
125 LOAD_DBUS_FUNC(dbus->error_is_set, dbus_error_is_set);
126 LOAD_DBUS_FUNC(dbus->error_free, dbus_error_free);
127
128 LOAD_DBUS_FUNC(dbus->bus_get, dbus_bus_get);
129
130 LOAD_DBUS_FUNC(dbus->connection_open, dbus_connection_open);
131 LOAD_DBUS_FUNC(dbus->connection_ref, dbus_connection_ref);
132 LOAD_DBUS_FUNC(dbus->connection_unref, dbus_connection_unref);
133 LOAD_DBUS_FUNC(dbus->connection_close, dbus_connection_close);
134 LOAD_DBUS_FUNC(dbus->connection_send_with_reply_and_block, dbus_connection_send_with_reply_and_block);
135
136 LOAD_DBUS_FUNC(dbus->message_ref, dbus_message_ref);
137 LOAD_DBUS_FUNC(dbus->message_unref, dbus_message_unref);
138 LOAD_DBUS_FUNC(dbus->message_copy, dbus_message_copy);
139 LOAD_DBUS_FUNC(dbus->message_new_method_call, dbus_message_new_method_call);
140 LOAD_DBUS_FUNC(dbus->message_append_args, dbus_message_append_args);
141
142 LOAD_DBUS_FUNC(dbus->message_iter_init, dbus_message_iter_init);
143 LOAD_DBUS_FUNC(dbus->message_iter_get_arg_type, dbus_message_iter_get_arg_type);
144 LOAD_DBUS_FUNC(dbus->message_iter_recurse, dbus_message_iter_recurse);
145 LOAD_DBUS_FUNC(dbus->message_iter_get_basic, dbus_message_iter_get_basic);
146 LOAD_DBUS_FUNC(dbus->message_iter_next, dbus_message_iter_next);
147
148 LOAD_DBUS_FUNC(dbus->message_iter_init_append, dbus_message_iter_init_append);
149 LOAD_DBUS_FUNC(dbus->message_iter_append_basic, dbus_message_iter_append_basic);
150 LOAD_DBUS_FUNC(dbus->message_iter_open_container, dbus_message_iter_open_container);
151 LOAD_DBUS_FUNC(dbus->message_iter_close_container, dbus_message_iter_close_container);
152
153 return GATE_RESULT_OK;
154 }
155
156
157 static gate_libdbus_t* gate_load_libdbus(void)
158 {
159 static gate_libdbus_t dbus;
160 static gate_bool_t dbus_loaded = false;
161
162 if (!dbus_loaded)
163 {
164 gate_result_t result = load_libdbus(&dbus);
165 if (GATE_FAILED(result))
166 {
167 return NULL;
168 }
169 dbus_loaded = true;
170 }
171 return &dbus;
172 }
173
174
175 static gate_result_t gate_dbus_open_system_connection(gate_libdbus_t** ptr_dbus, DBusConnection** ptr_conn)
176 {
177 gate_libdbus_t* dbus = gate_load_libdbus();
178 if (dbus == NULL)
179 {
180 GATE_DEBUG_TRACE("FAILED to load libdbus");
181 return GATE_RESULT_NOTAVAILABLE;
182 }
183 else
184 {
185 DBusConnection* conn = NULL;
186 DBusError err;
187 dbus->error_init(&err);
188 conn = dbus->bus_get(DBUS_BUS_SYSTEM, &err);
189 dbus->error_free(&err);
190 if (conn == NULL)
191 {
192 GATE_DEBUG_TRACE("FAILED to access DBUS system bus");
193 *ptr_dbus = NULL;
194 *ptr_conn = NULL;
195 return GATE_RESULT_NOTAVAILABLE;
196 }
197 else
198 {
199 *ptr_dbus = dbus;
200 *ptr_conn = conn;
201 return GATE_RESULT_OK;
202 }
203 }
204 }
205
206
207 static gate_result_t gate_dbus_property_get(gate_libdbus_t* dbus, DBusConnection* conn,
208 char const* bus_name, char const* path, char const* iface, char const* prop_name, gate_value_t* ptr_out_value)
209 {
210 static char const* const DBUS_INTERFACE_PROP = "org.freedesktop.DBus.Properties";
211 static char const* const DBUS_METHOD_GET = "Get";
212 gate_result_t ret = GATE_RESULT_FAILED;
213 DBusError err;
214 DBusMessage* msg = NULL;
215 DBusMessage* reply = NULL;;
216 DBusMessageIter args_iter, value_iter;
217
218 dbus->error_init(&err);
219 do
220 {
221 dbus_bool_t succeeded;
222
223 msg = dbus->message_new_method_call(bus_name, path, DBUS_INTERFACE_PROP, DBUS_METHOD_GET);
224 if (NULL == msg)
225 {
226 GATE_DEBUG_TRACE("dbus_message_new_method_call() FAILED");
227 ret = GATE_RESULT_OUTOFMEMORY;
228 break;
229 }
230
231 succeeded = dbus->message_append_args(msg,
232 DBUS_TYPE_STRING, &iface,
233 DBUS_TYPE_STRING, &prop_name,
234 DBUS_TYPE_INVALID);
235 if (!succeeded)
236 {
237 GATE_DEBUG_TRACE("dbus_message_append_args() FAILED");
238 ret = GATE_RESULT_PREPARATIONFAILED;
239 break;
240 }
241
242 reply = dbus->connection_send_with_reply_and_block(conn, msg, -1, &err);
243 if (reply == NULL)
244 {
245 GATE_DEBUG_TRACE("dbus_connection_send_with_reply_and_block() FAILED");
246 GATE_DEBUG_TRACE(err.message);
247 ret = GATE_RESULT_FAILED;
248 break;
249 }
250 else
251 {
252 /* reply received */
253 int value_type;
254 DBusBasicValue basic_value;
255 gate_value_t* ptr_value;
256
257 if(!dbus->message_iter_init(reply, &args_iter))
258 {
259 ret = GATE_RESULT_NOTAVAILABLE;
260 break;
261 }
262 dbus->message_iter_recurse(&args_iter, &value_iter);
263
264 value_type = dbus->message_iter_get_arg_type(&value_iter);
265 dbus->message_iter_get_basic(&value_iter, &basic_value);
266
267 ret = GATE_RESULT_OK; /* expect success as default */
268 ptr_value = NULL; /* default output value is NULL */
269 switch(value_type) /* map dbus value to gate value */
270 {
271 case DBUS_TYPE_BYTE:
272 {
273 const gate_uint8_t b = basic_value.byt;
274 ptr_value = gate_value_create(GATE_TYPE_UI8, &b, ptr_out_value);
275 break;
276 }
277 case DBUS_TYPE_BOOLEAN:
278 {
279 const gate_bool_t b = basic_value.bool_val;
280 ptr_value = gate_value_create(GATE_TYPE_BOOL, &b, ptr_out_value);
281 break;
282 }
283 case DBUS_TYPE_INT16:
284 {
285 const gate_int16_t v = basic_value.i16;
286 ptr_value = gate_value_create(GATE_TYPE_I16, &v, ptr_out_value);
287 break;
288 }
289 case DBUS_TYPE_UINT16:
290 {
291 const gate_uint16_t v = basic_value.u16;
292 ptr_value = gate_value_create(GATE_TYPE_UI16, &v, ptr_out_value);
293 break;
294 }
295 case DBUS_TYPE_INT32:
296 {
297 const gate_int32_t v = basic_value.i32;
298 ptr_value = gate_value_create(GATE_TYPE_I32, &v, ptr_out_value);
299 break;
300 }
301 case DBUS_TYPE_UINT32:
302 {
303 const gate_uint32_t v = basic_value.u32;
304 ptr_value = gate_value_create(GATE_TYPE_UI32, &v, ptr_out_value);
305 break;
306 }
307 case DBUS_TYPE_INT64:
308 {
309 const gate_int64_t v = basic_value.i64;
310 ptr_value = gate_value_create(GATE_TYPE_UI64, &v, ptr_out_value);
311 break;
312 }
313 case DBUS_TYPE_UINT64:
314 {
315 const gate_uint64_t v = basic_value.i64;
316 ptr_value = gate_value_create(GATE_TYPE_UI64, &v, ptr_out_value);
317 break;
318 }
319 case DBUS_TYPE_DOUBLE:
320 {
321 const gate_real64_t v = basic_value.dbl;
322 ptr_value = gate_value_create(GATE_TYPE_R64, &v, ptr_out_value);
323 break;
324 }
325 case DBUS_TYPE_STRING:
326 case DBUS_TYPE_OBJECT_PATH:
327 case DBUS_TYPE_SIGNATURE:
328 {
329 gate_string_t str;
330 if (NULL != gate_string_create(&str, basic_value.str, gate_str_length(basic_value.str)))
331 {
332 ptr_value = gate_value_create(GATE_TYPE_STRING, &str, ptr_out_value);
333 gate_string_release(&str);
334 }
335 break;
336 }
337 case DBUS_TYPE_UNIX_FD:
338 {
339 const gate_uintptr_t v = (gate_uintptr_t)(gate_intptr_t)basic_value.fd;
340 ptr_value = gate_value_create(GATE_TYPE_ADDRESS, &v, ptr_out_value);
341 break;
342 }
343 default:
344 {
345 ret = GATE_RESULT_NOTSUPPORTED;
346 break;
347 }
348 }
349
350 if (GATE_SUCCEEDED(ret))
351 {
352 if (ptr_value == NULL)
353 {
354 /* failed to create gate_value_t */
355 ret = GATE_RESULT_OUTOFMEMORY;
356 }
357 }
358 }
359 } while (0);
360
361 if (reply) dbus->message_unref(reply);
362 if (msg) dbus->message_unref(msg);
363 dbus->error_free(&err);
364
365 return ret;
366 }
367
368
369 #endif
370