GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/platform/linux_dbus_api.h
Date: 2026-06-21 00:38:37
Exec Total Coverage
Lines: 0 159 0.0%
Functions: 0 6 0.0%
Branches: 0 95 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 void (*message_iter_get_fixed_array)(DBusMessageIter* iter, void* value, int* n_elements);
62 dbus_bool_t (*message_iter_next) (DBusMessageIter* iter);
63 void (*message_iter_init_append) (DBusMessage* message, DBusMessageIter *iter);
64 dbus_bool_t (*message_iter_append_basic) (DBusMessageIter* iter, int type, const void* value);
65 dbus_bool_t (*message_iter_open_container) (DBusMessageIter* iter, int type, const char* contained_signature, DBusMessageIter* sub);
66 dbus_bool_t (*message_iter_close_container) (DBusMessageIter* iter, DBusMessageIter* sub);
67 } gate_libdbus_t;
68
69
70 #if defined(GATE_SYSTEM_LIBDBUS_STATIC)
71
72 static gate_result_t load_libdbus_lib(void)
73 {
74 return GATE_RESULT_OK;
75 }
76
77 # define LOAD_DBUS_FUNC(funcptr, funcname) do { funcptr = funcname; } while(0)
78
79 #else
80
81 static gate_library_t global_libdbus_lib = NULL;
82
83 static gate_result_t load_libdbus_lib(void)
84 {
85 static gate_string_t const libdbus_libname = GATE_STRING_INIT_STATIC("libdbus-1.so");
86 gate_result_t ret;
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_get_fixed_array, dbus_message_iter_get_fixed_array);
147 LOAD_DBUS_FUNC(dbus->message_iter_next, dbus_message_iter_next);
148
149 LOAD_DBUS_FUNC(dbus->message_iter_init_append, dbus_message_iter_init_append);
150 LOAD_DBUS_FUNC(dbus->message_iter_append_basic, dbus_message_iter_append_basic);
151 LOAD_DBUS_FUNC(dbus->message_iter_open_container, dbus_message_iter_open_container);
152 LOAD_DBUS_FUNC(dbus->message_iter_close_container, dbus_message_iter_close_container);
153
154 return GATE_RESULT_OK;
155 }
156
157
158 static gate_libdbus_t* gate_load_libdbus(void)
159 {
160 static gate_libdbus_t dbus;
161 static gate_bool_t dbus_loaded = false;
162
163 if (!dbus_loaded)
164 {
165 gate_result_t result = load_libdbus(&dbus);
166 if (GATE_FAILED(result))
167 {
168 return NULL;
169 }
170 dbus_loaded = true;
171 }
172 return &dbus;
173 }
174
175
176 static gate_result_t gate_dbus_open_system_connection(gate_libdbus_t** ptr_dbus, DBusConnection** ptr_conn)
177 {
178 gate_libdbus_t* dbus = gate_load_libdbus();
179 if (dbus == NULL)
180 {
181 GATE_DEBUG_TRACE("FAILED to load libdbus");
182 return GATE_RESULT_NOTAVAILABLE;
183 }
184 else
185 {
186 DBusConnection* conn = NULL;
187 DBusError err;
188 dbus->error_init(&err);
189 conn = dbus->bus_get(DBUS_BUS_SYSTEM, &err);
190 dbus->error_free(&err);
191 if (conn == NULL)
192 {
193 GATE_DEBUG_TRACE("FAILED to access DBUS system bus");
194 *ptr_dbus = NULL;
195 *ptr_conn = NULL;
196 return GATE_RESULT_NOTAVAILABLE;
197 }
198 else
199 {
200 *ptr_dbus = dbus;
201 *ptr_conn = conn;
202 return GATE_RESULT_OK;
203 }
204 }
205 }
206
207
208 static gate_result_t gate_dbus_property_get(gate_libdbus_t* dbus, DBusConnection* conn,
209 char const* bus_name, char const* path, char const* iface, char const* prop_name, gate_value_t* ptr_out_value)
210 {
211 static char const* const DBUS_INTERFACE_PROP = "org.freedesktop.DBus.Properties";
212 static char const* const DBUS_METHOD_GET = "Get";
213 gate_result_t ret = GATE_RESULT_FAILED;
214 DBusError err;
215 DBusMessage* msg = NULL;
216 DBusMessage* reply = NULL;;
217 DBusMessageIter args_iter, value_iter;
218
219 dbus->error_init(&err);
220 do
221 {
222 dbus_bool_t succeeded;
223
224 msg = dbus->message_new_method_call(bus_name, path, DBUS_INTERFACE_PROP, DBUS_METHOD_GET);
225 if (NULL == msg)
226 {
227 GATE_DEBUG_TRACE("dbus_message_new_method_call() FAILED");
228 ret = GATE_RESULT_OUTOFMEMORY;
229 break;
230 }
231
232 succeeded = dbus->message_append_args(msg,
233 DBUS_TYPE_STRING, &iface,
234 DBUS_TYPE_STRING, &prop_name,
235 DBUS_TYPE_INVALID);
236 if (!succeeded)
237 {
238 GATE_DEBUG_TRACE("dbus_message_append_args() FAILED");
239 ret = GATE_RESULT_PREPARATIONFAILED;
240 break;
241 }
242
243 reply = dbus->connection_send_with_reply_and_block(conn, msg, -1, &err);
244 if (reply == NULL)
245 {
246 GATE_DEBUG_TRACE("dbus_connection_send_with_reply_and_block() FAILED");
247 GATE_DEBUG_TRACE(err.message);
248 ret = GATE_RESULT_FAILED;
249 break;
250 }
251 else
252 {
253 /* reply received */
254 int value_type;
255 DBusBasicValue basic_value;
256 gate_value_t* ptr_value;
257
258 if(!dbus->message_iter_init(reply, &args_iter))
259 {
260 ret = GATE_RESULT_NOTAVAILABLE;
261 break;
262 }
263 dbus->message_iter_recurse(&args_iter, &value_iter);
264
265 ret = GATE_RESULT_OK; /* expect success as default */
266 ptr_value = NULL; /* default output value is NULL */
267
268 value_type = dbus->message_iter_get_arg_type(&value_iter);
269 switch(value_type)
270 {
271 case DBUS_TYPE_BYTE:
272 case DBUS_TYPE_BOOLEAN:
273 case DBUS_TYPE_INT16:
274 case DBUS_TYPE_UINT16:
275 case DBUS_TYPE_INT32:
276 case DBUS_TYPE_UINT32:
277 case DBUS_TYPE_INT64:
278 case DBUS_TYPE_UINT64:
279 case DBUS_TYPE_DOUBLE:
280 case DBUS_TYPE_STRING:
281 case DBUS_TYPE_OBJECT_PATH:
282 case DBUS_TYPE_SIGNATURE:
283 case DBUS_TYPE_UNIX_FD:
284 {
285 dbus->message_iter_get_basic(&value_iter, &basic_value);
286 break;
287 }
288 case DBUS_TYPE_ARRAY:
289 /* case DBUS_TYPE_VARIANT: */
290 {
291 unsigned char* ptr_data = NULL;
292 int data_len = 0;
293 gate_blob_t blob = GATE_INIT_EMPTY;
294 /* TODO error analysis */
295 /* dbus->message_iter_get_fixed_array(&value_iter, &ptr_data, &data_len); */
296 gate_blob_create(&blob, ptr_data, data_len);
297 ptr_value = gate_value_create(GATE_TYPE_BLOB, &blob, ptr_out_value);
298 break;
299 }
300 default:
301 {
302 ret = GATE_RESULT_NOTSUPPORTED;
303 break;
304 }
305 }
306
307 switch(value_type) /* map dbus value to gate value */
308 {
309 case DBUS_TYPE_BYTE:
310 {
311 const gate_uint8_t b = basic_value.byt;
312 ptr_value = gate_value_create(GATE_TYPE_UI8, &b, ptr_out_value);
313 break;
314 }
315 case DBUS_TYPE_BOOLEAN:
316 {
317 const gate_bool_t b = basic_value.bool_val;
318 ptr_value = gate_value_create(GATE_TYPE_BOOL, &b, ptr_out_value);
319 break;
320 }
321 case DBUS_TYPE_INT16:
322 {
323 const gate_int16_t v = basic_value.i16;
324 ptr_value = gate_value_create(GATE_TYPE_I16, &v, ptr_out_value);
325 break;
326 }
327 case DBUS_TYPE_UINT16:
328 {
329 const gate_uint16_t v = basic_value.u16;
330 ptr_value = gate_value_create(GATE_TYPE_UI16, &v, ptr_out_value);
331 break;
332 }
333 case DBUS_TYPE_INT32:
334 {
335 const gate_int32_t v = basic_value.i32;
336 ptr_value = gate_value_create(GATE_TYPE_I32, &v, ptr_out_value);
337 break;
338 }
339 case DBUS_TYPE_UINT32:
340 {
341 const gate_uint32_t v = basic_value.u32;
342 ptr_value = gate_value_create(GATE_TYPE_UI32, &v, ptr_out_value);
343 break;
344 }
345 case DBUS_TYPE_INT64:
346 {
347 const gate_int64_t v = basic_value.i64;
348 ptr_value = gate_value_create(GATE_TYPE_UI64, &v, ptr_out_value);
349 break;
350 }
351 case DBUS_TYPE_UINT64:
352 {
353 const gate_uint64_t v = basic_value.i64;
354 ptr_value = gate_value_create(GATE_TYPE_UI64, &v, ptr_out_value);
355 break;
356 }
357 case DBUS_TYPE_DOUBLE:
358 {
359 const gate_real64_t v = basic_value.dbl;
360 ptr_value = gate_value_create(GATE_TYPE_R64, &v, ptr_out_value);
361 break;
362 }
363 case DBUS_TYPE_STRING:
364 case DBUS_TYPE_OBJECT_PATH:
365 case DBUS_TYPE_SIGNATURE:
366 {
367 gate_string_t str;
368 if (NULL != gate_string_create(&str, basic_value.str, gate_str_length(basic_value.str)))
369 {
370 ptr_value = gate_value_create(GATE_TYPE_STRING, &str, ptr_out_value);
371 gate_string_release(&str);
372 }
373 break;
374 }
375 case DBUS_TYPE_UNIX_FD:
376 {
377 const gate_uintptr_t v = (gate_uintptr_t)(gate_intptr_t)basic_value.fd;
378 ptr_value = gate_value_create(GATE_TYPE_ADDRESS, &v, ptr_out_value);
379 break;
380 }
381 default:
382 {
383 break;
384 }
385 }
386
387 if (GATE_SUCCEEDED(ret))
388 {
389 if (ptr_value == NULL)
390 {
391 /* failed to create gate_value_t */
392 ret = GATE_RESULT_OUTOFMEMORY;
393 }
394 }
395 }
396 } while (0);
397
398 if (reply) dbus->message_unref(reply);
399 if (msg) dbus->message_unref(msg);
400 dbus->error_free(&err);
401
402 return ret;
403 }
404
405
406 #endif
407