Looking for a simple tutorial.
I need to send and receive binary data through DBus (pure C).
All tutorial I found are using DBUS_TYPE_STRING, but I have a binary data blocks.
Thinking about usage like this:
void write_msg(DbusConnection *conn, void *data, size_t datasize) {
DBusMessage *msg = dbus_message_new(DBUS_TYPE_ARRAY); // Is it DBUS_TYPE_ARRAY?
// how to convert data of datasize into msg?
dbus_connection_send(conn, msg, NULL);
dbus_free(msg); // there is no dbus_message_free() function?
}
void read_msg(DbusConnection *conn, void *data, size_t datasize) {
DBusMessage *msg = dbus_connection_pop_message(conn);
// how to convert msg to data of datasize?
dbus_free(msg);
}
// And to use it as:
struct my_struct st;
write_msg(conn, &st, sizeof(st));
So how to write/read an untyped memory block into DBusMessage? To make it as easy as write/read datagrams in sockets?
dbus_message_new(DBUS_TYPE_ARRAY); // Is it DBUS_TYPE_ARRAY
No, that's the message type, not the data type. D-Bus has "method call" and "signal" as the two major message types – if you are calling a function (method) via D-Bus, you should be specifying DBUS_MESSAGE_TYPE_METHOD_CALL
, or using the dbus_message_new_method_call()
function.
So how to write/read an untyped memory block into DBusMessage?
Binary data in D-Bus is usually transferred as type ay
– "array of byte".
While I'm not very familiar with dbus-glib, I looked at wpa_supplicant's source code (hostap.git) for an example, and I think you're looking for:
Begin the array with dbus_message_iter_open_container(&val, DBUS_TYPE_ARRAY, "y", &iter)
,
Write data using dbus_message_iter_append_fixed_array()
(Alternatively, you could loop dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE, &(val[i]))
for each byte of your memory block),
Finish using dbus_message_iter_close_container(&iter)
To make it as easy as write/read datagrams in sockets?
If all you need is datagrams over a socket, D-Bus is probably not for you. You can't fully get away from its structure (the method call/return format and the object & interface system) – and if you do, then what's the point of using D-Bus?
However, do try out either GLib2 (GDBus) or systemd's "sd-bus" as an easier-to-use C library. (The dbus-glib library you're using is mostly considered deprecated in favor of GDBus via GLib; it will keep working forever but is not really maintained anymore.)
Additionally, keep in mind that D-Bus is not meant for high-volume traffic. Over a private socket it's fine but the shared system (or session) bus will have limits on what's acceptable.
If you really need a raw Unix socket, then use a socket – for example, you can create a socketpair(), pass one of the file descriptors via D-Bus call (using a h
value), then continue all communications over the socket. This is already done by some programs and is even recommended by dbus-daemon maintainers for programs that need high traffic volumes or unstructured communications.