[systemd-devel] sd-bus: Implementing Variant concept: Copying sd-bus message contents

Lennart Poettering lennart at poettering.net
Mon Nov 28 17:45:40 UTC 2016


On Sat, 26.11.16 16:01, Stanislav Angelovič (angelovic.s at gmail.com) wrote:

> Hi,
> 
> A quick question: Is it possible to append contents (the serialized data)
> of an sd-bus message to another sd-bus message? Conversely, is it possible
> to extract a part of sd-bus message contents into a separate
> message?

There's sd_bus_message_copy() which can copy the contents (or a part
of it) of a message into another message.

There's currently no API that exposes the raw binary bits, and they
aren't particularly useful anyway on dbus1 as they are not safe
regarding alignment and you cannot copy them byte-by-byte to arbitrary
memory locations.

> Details:
> 
> In the process of creating a method call message, I would like to do this:
> 1. Create a temporary, empty message A.
> 2. Serialize data into the message A.
> 3. Create a method call message B.
> 4. Serialize some user data into the message B, plus copy the data of the
> message A into the message B. And send the message B.

sd_bus_message_copy() should work fine for that.

> Analogously, when deserializing data from the message B upon its reception
> on the server side, I would like to do this:
> 1. Extract user data from the message B, plus copy selected data into a
> separate, empty message A.
> 2. Destroy the message B.
> 3. In some other context, deserialize real data from the message A.
> 
> Why am I asking is because we like sd-bus and are building a C++ binding on
> top of it. We stumbled upon a problem when modelling Variant. The typical
> flow in such a case is that upon e.g. deserialization, first the Variant
> instances are created from the message contents, and then at some later
> phase, users want to extract real data from the Variant. In this phase, our
> C++ binding would perform the deserialization from that temporry message
> (message A) that the Variant would hold.
> 
> For example, if the method call message carries an array of Variants, we
> first deserialize the message into std::vector<Variant>, where each Variant
> instance keeps the temporary sd-bus message with the variant data, and when
> the user asks for a concrete data from that Variant, the deserialization
> from that temporary message takes place.
> 
> This is the way it's done in e.g. dbus-c++, the C++ binding for libdbus.
> libdbus API allows creating "empty" messages, and allows copying the data
> among messages with the possibility of reading from them at the same time.
> Is it possible to create an empty message using sd-bus? Regarding copying,
> we know there's the sd_bus_message_copy function, but once we create the
> copy message, we cannot read from it later because of the assertion that
> the message is sealed, which in reality is not.

Hmm, so internally there's bus_message_seal() which I figure we could
make publically available, so that you can create a new msg, copy the
data to it, seal it, and read it back.

> Is there a way to solve this in sd-bus? Perhaps another way than I
> described? Many thanks in advance for your response!

There's no nicer way right now. But I think we could add a
sd_bus_message_dup() or so that duplicates a message, but does so
efficiently, i.e. shares the memory for the actual payload. This way
you could duplicate a message to simply get a new read ptr on the
same, immutable message. I think that would suit your usecase best?

Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list