1SD_BUS_ADD_OBJECT(3) sd_bus_add_object SD_BUS_ADD_OBJECT(3)
2
3
4
6 sd_bus_add_object, sd_bus_add_fallback, sd_bus_add_object_vtable,
7 sd_bus_add_fallback_vtable, sd_bus_add_filter, SD_BUS_VTABLE_START,
8 SD_BUS_VTABLE_END, SD_BUS_METHOD_WITH_NAMES_OFFSET,
9 SD_BUS_METHOD_WITH_NAMES, SD_BUS_METHOD_WITH_OFFSET, SD_BUS_METHOD,
10 SD_BUS_SIGNAL_WITH_NAMES, SD_BUS_SIGNAL, SD_BUS_WRITABLE_PROPERTY,
11 SD_BUS_PROPERTY, SD_BUS_PARAM - Declare properties and methods for a
12 D-Bus path
13
15 #include <systemd/sd-bus-vtable.h>
16
17
18 typedef int (*sd_bus_message_handler_t)(sd_bus_message *m,
19 void *userdata,
20 sd_bus_error *ret_error);
21
22 typedef int (*sd_bus_property_get_t)(sd_bus *bus, const char *path,
23 const char *interface,
24 const char *property,
25 sd_bus_message *reply,
26 void *userdata,
27 sd_bus_error *ret_error);
28
29 typedef int (*sd_bus_property_set_t)(sd_bus *bus, const char *path,
30 const char *interface,
31 const char *property,
32 sd_bus_message *value,
33 void *userdata,
34 sd_bus_error *ret_error);
35
36 typedef int (*sd_bus_object_find_t)(const char *path,
37 const char *interface,
38 void *userdata, void **ret_found,
39 sd_bus_error *ret_error);
40
41 int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot,
42 const char *path,
43 sd_bus_message_handler_t callback,
44 void *userdata);
45
46 int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot,
47 const char *path,
48 sd_bus_message_handler_t callback,
49 void *userdata);
50
51 int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot,
52 const char *path, const char *interface,
53 const sd_bus_vtable *vtable,
54 void *userdata);
55
56 int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot,
57 const char *prefix,
58 const char *interface,
59 const sd_bus_vtable *vtable,
60 sd_bus_object_find_t find,
61 void *userdata);
62
63 int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot,
64 sd_bus_message_handler_t callback,
65 void *userdata);
66
67 SD_BUS_VTABLE_START(flags)
68
69 SD_BUS_VTABLE_END
70
71 SD_BUS_METHOD_WITH_ARGS_OFFSET( member, args, result, handler, offset,
72 flags)
73
74 SD_BUS_METHOD_WITH_ARGS( member, args, result, handler, flags)
75
76 SD_BUS_METHOD_WITH_NAMES_OFFSET( member, signature, in_names, result,
77 out_names, handler, offset, flags)
78
79 SD_BUS_METHOD_WITH_NAMES( member, signature, in_names, result,
80 out_names, handler, flags)
81
82 SD_BUS_METHOD_WITH_OFFSET( member, signature, result, handler, offset,
83 flags)
84
85 SD_BUS_METHOD( member, signature, result, handler, flags)
86
87 SD_BUS_SIGNAL_WITH_ARGS( member, args, flags)
88
89 SD_BUS_SIGNAL_WITH_NAMES( member, signature, names, flags)
90
91 SD_BUS_SIGNAL( member, signature, flags)
92
93 SD_BUS_WRITABLE_PROPERTY( member, signature, get, set, offset, flags)
94
95 SD_BUS_PROPERTY( member, signature, get, offset, flags)
96
97 SD_BUS_PARAM(name) SD_BUS_ARGS(...) SD_BUS_RESULT(...) SD_BUS_NO_ARGS
98 SD_BUS_NO_RESULT
99
101 sd_bus_add_object_vtable() is used to declare attributes for the object
102 path path connected to the bus connection bus under the interface
103 interface. The table vtable may contain property declarations using
104 SD_BUS_PROPERTY() or SD_BUS_WRITABLE_PROPERTY(), method declarations
105 using SD_BUS_METHOD(), SD_BUS_METHOD_WITH_NAMES(),
106 SD_BUS_METHOD_WITH_OFFSET(), or SD_BUS_METHOD_WITH_NAMES_OFFSET(), and
107 signal declarations using SD_BUS_SIGNAL_WITH_NAMES() or
108 SD_BUS_SIGNAL(), see below. The userdata parameter contains a pointer
109 that will be passed to various callback functions. It may be specified
110 as NULL if no value is necessary. An interface can have any number of
111 vtables attached to it.
112
113 sd_bus_add_fallback_vtable() is similar to sd_bus_add_object_vtable(),
114 but is used to register "fallback" attributes. When looking for an
115 attribute declaration, bus object paths registered with
116 sd_bus_add_object_vtable() are checked first. If no match is found, the
117 fallback vtables are checked for each prefix of the bus object path,
118 i.e. with the last slash-separated components successively removed.
119 This allows the vtable to be used for an arbitrary number of
120 dynamically created objects.
121
122 Parameter find is a function which is used to locate the target object
123 based on the bus object path path. It must return 1 and set the
124 ret_found output parameter if the object is found, return 0 if the
125 object was not found, and return a negative errno-style error code or
126 initialize the error structure ret_error on error. The pointer passed
127 in ret_found will be used as the userdata parameter for the callback
128 functions (offset by the offset offsets as specified in the vtable
129 entries).
130
131 sd_bus_add_object() attaches a callback directly to the object path
132 path. An object path can have any number of callbacks attached to it.
133 Each callback is prepended to the list of callbacks which are always
134 called in order. sd_bus_add_fallback() is similar to
135 sd_bus_add_object() but applies to fallback paths instead.
136
137 sd_bus_add_filter() installs a callback that is invoked for each
138 incoming D-Bus message. Filters can be used to handle logic common to
139 all messages received by a service (e.g. authentication or
140 authorization).
141
142 When a request is received, any associated callbacks are called
143 sequentially until a callback returns a non-zero integer. Return zero
144 from a callback to give other callbacks the chance to process the
145 request. Callbacks are called in the following order: first, global
146 callbacks installed with sd_bus_add_filter() are called. Second,
147 callbacks attached directly to the request object path are called,
148 followed by any D-Bus method callbacks attached to the request object
149 path, interface and member. Finally, the property callbacks attached to
150 the request object path, interface and member are called. If the final
151 callback returns zero, an error reply is sent back to the caller
152 indicating no matching object for the request was found.
153
154 Note that you can return a positive integer from a method callback
155 without immediately sending a reply. This informs sd-bus this callback
156 will take responsibility for replying to the request without forcing
157 the callback to produce a reply immediately. This allows a callback to
158 perform any number of asynchronous operations required to construct a
159 reply. However, if producing a reply takes too long, the method call
160 will time out at the caller. This is only available to methods and not
161 properties.
162
163 If a callback was invoked to handle a request that expects a reply and
164 the callback returns a negative value, the value is interpreted as a
165 negative errno-style error code and sent back to the caller as a D-Bus
166 error as if sd_bus_reply_method_errno(3) was called. Additionally, all
167 callbacks take a sd_bus_error output parameter that can be used to
168 provide more detailed error information. If ret_error is set when the
169 callback finishes, the corresponding D-Bus error is sent back to the
170 caller as if sd_bus_reply_method_error(3) was called. Any error stored
171 in ret_error takes priority over any negative values returned by the
172 same callback when determining which error to send back to the caller.
173 Use sd_bus_error_set(3) or one of its variants to set ret_error and
174 return a negative integer from a callback with a single function call.
175 To send an error reply after a callback has already finished, use
176 sd_bus_reply_method_errno(3) or one of its variants.
177
178 For all functions, a match slot is created internally. If the output
179 parameter slot is NULL, a "floating" slot object is created, see
180 sd_bus_slot_set_floating(3). Otherwise, a pointer to the slot object is
181 returned. In that case, the reference to the slot object should be
182 dropped when the vtable is not needed anymore, see
183 sd_bus_slot_unref(3).
184
185 The sd_bus_vtable array
186 The array consists of the structures of type sd_bus_vtable, but it
187 should never be filled in manually, but through one of the following
188 macros:
189
190 SD_BUS_VTABLE_START(), SD_BUS_VTABLE_END
191 Those must always be the first and last element.
192
193 SD_BUS_METHOD_WITH_ARGS_OFFSET(), SD_BUS_METHOD_WITH_ARGS()
194 Declare a D-Bus method with the name member, arguments args and
195 result result. args expects a sequence of argument type/name pairs
196 wrapped in the SD_BUS_ARGS() macro. The elements at even indices in
197 this list describe the types of the method's arguments. The
198 method's parameter signature is the concatenation of all the string
199 literals at even indices in args. If a method has no parameters,
200 pass SD_BUS_NO_ARGS to args. The elements at uneven indices
201 describe the names of the method's arguments. result expects a
202 sequence of type/name pairs wrapped in the SD_BUS_RESULT() macro in
203 the same format as SD_BUS_ARGS(). The method's result signature is
204 the concatenation of all the string literals at even indices in
205 result. If a method has no result, pass SD_BUS_NO_RESULT to result.
206 Note that argument types are expected to be quoted string literals
207 and argument names are expected to be unquoted string literals. See
208 below for a complete example.
209
210 The handler function handler must be of type
211 sd_bus_message_handler_t. It will be called to handle the incoming
212 messages that call this method. It receives a pointer that is the
213 userdata parameter passed to the registration function offset by
214 offset bytes. This may be used to pass pointers to different fields
215 in the same data structure to different methods in the same vtable.
216 To send a reply from handler, call sd_bus_reply_method_return(3)
217 with the message the callback was invoked with. Parameter flags is
218 a combination of flags, see below.
219
220 SD_BUS_METHOD_WITH_ARGS() is a shorthand for calling
221 SD_BUS_METHOD_WITH_ARGS_OFFSET() with an offset of zero.
222
223 SD_BUS_METHOD_WITH_NAMES_OFFSET(), SD_BUS_METHOD_WITH_NAMES(),
224 SD_BUS_METHOD_WITH_OFFSET(), SD_BUS_METHOD()
225 Declare a D-Bus method with the name member, parameter signature
226 signature, result signature result. Parameters in_names and
227 out_names specify the argument names of the input and output
228 arguments in the function signature. in_names and out_names should
229 be created using the SD_BUS_PARAM() macro, see below. In all other
230 regards, this macro behaves exactly the same as
231 SD_BUS_METHOD_WITH_ARGS_OFFSET().
232
233 SD_BUS_METHOD_WITH_NAMES(), SD_BUS_METHOD_WITH_OFFSET(), and
234 SD_BUS_METHOD() are variants which specify zero offset (userdata
235 parameter is passed with no change), leave the names unset (i.e. no
236 parameter names), or both.
237
238 Prefer using SD_BUS_METHOD_WITH_ARGS_OFFSET() and
239 SD_BUS_METHOD_WITH_ARGS() over these macros as they allow
240 specifying argument types and names next to each other which is
241 less error-prone than first specifying all argument types followed
242 by specifying all argument names.
243
244 SD_BUS_SIGNAL_WITH_ARGS()
245 Declare a D-Bus signal with the name member and arguments args.
246 args expects a sequence of argument type/name pairs wrapped in the
247 SD_BUS_ARGS() macro. The elements at even indices in this list
248 describe the types of the signal's arguments. The signal's
249 parameter signature is the concatenation of all the string literals
250 at even indices in args. If a signal has no parameters, pass
251 SD_BUS_NO_ARGS to args. The elements at uneven indices describe the
252 names of the signal's arguments. Parameter flags is a combination
253 of flags. See below for a complete example.
254
255 SD_BUS_SIGNAL_WITH_NAMES(), SD_BUS_SIGNAL()
256 Declare a D-Bus signal with the name member, parameter signature
257 signature, and argument names names. names should be created using
258 the SD_BUS_PARAM() macro, see below. Parameter flags is a
259 combination of flags, see below.
260
261 SD_BUS_SIGNAL() is equivalent to SD_BUS_SIGNAL_WITH_NAMES() with
262 the names parameter unset (i.e. no parameter names).
263
264 Prefer using SD_BUS_SIGNAL_WITH_ARGS() over these macros as it
265 allows specifying argument types and names next to each other which
266 is less error-prone than first specifying all argument types
267 followed by specifying all argument names.
268
269 SD_BUS_WRITABLE_PROPERTY(), SD_BUS_PROPERTY()
270 Declare a D-Bus property with the name member and value signature
271 signature. Parameters get and set are the getter and setter
272 methods. They are called with a pointer that is the userdata
273 parameter passed to the registration function offset by offset
274 bytes. This may be used pass pointers to different fields in the
275 same data structure to different setters and getters in the same
276 vtable. Parameter flags is a combination of flags, see below.
277
278 The setter and getter methods may be omitted (specified as NULL),
279 if the property is one of the basic types or "as" in case of
280 read-only properties. In those cases, the userdata and offset
281 parameters must together point to a valid variable of the
282 corresponding type. A default setter and getter will be provided,
283 which simply copy the argument between this variable and the
284 message.
285
286 SD_BUS_PROPERTY() is used to define a read-only property.
287
288 SD_BUS_PARAM()
289 Parameter names should be wrapped in this macro, see the example
290 below.
291
292 Flags
293 The flags parameter is used to specify a combination of D-Bus
294 annotations[1].
295
296 SD_BUS_VTABLE_DEPRECATED
297 Mark this vtable entry as deprecated using the
298 org.freedesktop.DBus.Deprecated annotation in introspection data.
299 If specified for SD_BUS_VTABLE_START(), the annotation is applied
300 to the enclosing interface.
301
302 SD_BUS_VTABLE_HIDDEN
303 Make this vtable entry hidden. It will not be shown in
304 introspection data. If specified for SD_BUS_VTABLE_START(), all
305 entries in the array are hidden.
306
307 SD_BUS_VTABLE_UNPRIVILEGED
308 Mark this vtable entry as unprivileged. If not specified, the
309 org.freedesktop.systemd1.Privileged annotation with value "true"
310 will be shown in introspection data.
311
312 SD_BUS_VTABLE_METHOD_NO_REPLY
313 Mark this vtable entry as a method that will not return a reply
314 using the org.freedesktop.DBus.Method.NoReply annotation in
315 introspection data.
316
317 SD_BUS_VTABLE_PROPERTY_CONST, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE,
318 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
319 Those three flags correspond to different values of the
320 org.freedesktop.DBus.Property.EmitsChangedSignal annotation, which
321 specifies whether the
322 org.freedesktop.DBus.Properties.PropertiesChanged signal is emitted
323 whenever the property changes. SD_BUS_VTABLE_PROPERTY_CONST
324 corresponds to const and means that the property never changes
325 during the lifetime of the object it belongs to, so no signal needs
326 to be emitted. SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE corresponds to
327 true and means that the signal is emitted.
328 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION corresponds to
329 invalidates and means that the signal is emitted, but the value is
330 not included in the signal.
331
332 SD_BUS_VTABLE_PROPERTY_EXPLICIT
333 Mark this vtable property entry as requiring explicit request to
334 for the value to be shown (generally because the value is large or
335 slow to calculate). This entry cannot be combined with
336 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, and will not be shown in
337 property listings by default (e.g. busctl introspect). This
338 corresponds to the org.freedesktop.systemd1.Explicit annotation in
339 introspection data.
340
341 SD_BUS_VTABLE_SENSITIVE
342 Mark this vtable method entry as processing sensitive data. When
343 set, incoming method call messages and their outgoing reply
344 messages are marked as sensitive using sd_bus_message_sensitive(3),
345 so that they are erased from memory when freed.
346
347 SD_BUS_VTABLE_ABSOLUTE_OFFSET
348 Mark this vtable method or property entry so that the user data
349 pointer passed to its associated handler functions is determined
350 slightly differently: instead of adding the offset parameter of the
351 entry to the user data pointer specified during vtable
352 registration, the offset is passed directly, converted to a
353 pointer, without taking the user data pointer specified during
354 vtable registration into account.
355
357 Example 1. Create a simple listener on the bus
358
359 #include <errno.h>
360 #include <stdbool.h>
361 #include <stddef.h>
362 #include <stdlib.h>
363 #include <stdio.h>
364 #include <systemd/sd-bus.h>
365
366 #define _cleanup_(f) __attribute__((cleanup(f)))
367
368 typedef struct object {
369 char *name;
370 uint32_t number;
371 } object;
372
373 static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
374 printf("Got called with userdata=%p\n", userdata);
375 return 1;
376 }
377
378 static const sd_bus_vtable vtable[] = {
379 SD_BUS_VTABLE_START(0),
380 SD_BUS_METHOD(
381 "Method1", "s", "s", method, 0),
382 SD_BUS_METHOD_WITH_NAMES_OFFSET(
383 "Method2",
384 "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
385 "s", SD_BUS_PARAM(returnstring),
386 method, offsetof(object, number),
387 SD_BUS_VTABLE_DEPRECATED),
388 SD_BUS_METHOD_WITH_ARGS_OFFSET(
389 "Method3",
390 SD_BUS_ARGS("s", string, "o", path),
391 SD_BUS_RESULT("s", returnstring),
392 method, offsetof(object, number),
393 SD_BUS_VTABLE_UNPRIVILEGED),
394 SD_BUS_METHOD_WITH_ARGS(
395 "Method4",
396 SD_BUS_NO_ARGS,
397 SD_BUS_NO_RESULT,
398 method,
399 SD_BUS_VTABLE_UNPRIVILEGED),
400 SD_BUS_SIGNAL(
401 "Signal1",
402 "so",
403 0),
404 SD_BUS_SIGNAL_WITH_NAMES(
405 "Signal2",
406 "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
407 0),
408 SD_BUS_SIGNAL_WITH_ARGS(
409 "Signal3",
410 SD_BUS_ARGS("s", string, "o", path),
411 0),
412 SD_BUS_WRITABLE_PROPERTY(
413 "AutomaticStringProperty", "s", NULL, NULL,
414 offsetof(object, name),
415 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
416 SD_BUS_WRITABLE_PROPERTY(
417 "AutomaticIntegerProperty", "u", NULL, NULL,
418 offsetof(object, number),
419 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
420 SD_BUS_VTABLE_END
421 };
422
423 #define check(x) ({ \
424 int r = x; \
425 errno = r < 0 ? -r : 0; \
426 printf(#x ": %m\n"); \
427 if (r < 0) \
428 return EXIT_FAILURE; \
429 })
430
431 int main(int argc, char **argv) {
432 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
433
434 sd_bus_default(&bus);
435
436 object object = { .number = 666 };
437 check((object.name = strdup("name")) != NULL);
438
439 check(sd_bus_add_object_vtable(bus, NULL, "/object",
440 "org.freedesktop.systemd.VtableExample",
441 vtable,
442 &object));
443
444 for (;;) {
445 check(sd_bus_wait(bus, UINT64_MAX));
446 check(sd_bus_process(bus, NULL));
447 }
448
449 free(object.name);
450
451 return 0;
452 }
453
454 This creates a simple client on the bus (the user bus, when run as
455 normal user). We may use the D-Bus
456 org.freedesktop.DBus.Introspectable.Introspect call to acquire the XML
457 description of the interface:
458
459 <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
460 "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
461 <node>
462 <interface name="org.freedesktop.DBus.Peer">
463 <method name="Ping"/>
464 <method name="GetMachineId">
465 <arg type="s" name="machine_uuid" direction="out"/>
466 </method>
467 </interface>
468 <interface name="org.freedesktop.DBus.Introspectable">
469 <method name="Introspect">
470 <arg name="data" type="s" direction="out"/>
471 </method>
472 </interface>
473 <interface name="org.freedesktop.DBus.Properties">
474 <method name="Get">
475 <arg name="interface" direction="in" type="s"/>
476 <arg name="property" direction="in" type="s"/>
477 <arg name="value" direction="out" type="v"/>
478 </method>
479 <method name="GetAll">
480 <arg name="interface" direction="in" type="s"/>
481 <arg name="properties" direction="out" type="a{sv}"/>
482 </method>
483 <method name="Set">
484 <arg name="interface" direction="in" type="s"/>
485 <arg name="property" direction="in" type="s"/>
486 <arg name="value" direction="in" type="v"/>
487 </method>
488 <signal name="PropertiesChanged">
489 <arg type="s" name="interface"/>
490 <arg type="a{sv}" name="changed_properties"/>
491 <arg type="as" name="invalidated_properties"/>
492 </signal>
493 </interface>
494 <interface name="org.freedesktop.systemd.VtableExample">
495 <method name="Method1">
496 <arg type="s" direction="in"/>
497 <arg type="s" direction="out"/>
498 </method>
499 <method name="Method2">
500 <arg type="s" name="string" direction="in"/>
501 <arg type="o" name="path" direction="in"/>
502 <arg type="s" name="returnstring" direction="out"/>
503 <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
504 </method>
505 <property name="AutomaticStringProperty" type="s" access="readwrite">
506 </property>
507 <property name="AutomaticIntegerProperty" type="u" access="readwrite">
508 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/>
509 </property>
510 </interface>
511 </node>
512
513
515 On success, sd_bus_add_object_vtable() and sd_bus_add_fallback_vtable()
516 return a non-negative integer. On failure, they return a negative
517 errno-style error code.
518
519 Errors
520 Returned errors may indicate the following problems:
521
522 -EINVAL
523 One of the required parameters is NULL or invalid. A reserved D-Bus
524 interface was passed as the interface parameter.
525
526 -ENOPKG
527 The bus cannot be resolved.
528
529 -ECHILD
530 The bus was created in a different process.
531
532 -ENOMEM
533 Memory allocation failed.
534
535 -EPROTOTYPE
536 sd_bus_add_object_vtable() and sd_bus_add_fallback_vtable() have
537 been both called for the same bus object path, which is not
538 allowed.
539
540 -EEXIST
541 This vtable has already been registered for this interface and
542 path.
543
545 These APIs are implemented as a shared library, which can be compiled
546 and linked to with the libsystemd pkg-config(1) file.
547
549 sd-bus(3), busctl(1), sd_bus_emit_properties_changed(3),
550 sd_bus_emit_object_added(3)
551
553 1. D-Bus annotations
554 https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
555
556
557
558systemd 249 SD_BUS_ADD_OBJECT(3)