<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Nov 28, 2016 at 6:45 PM, Lennart Poettering <span dir="ltr"><<a target="_blank" href="mailto:lennart@poettering.net">lennart@poettering.net</a>></span> wrote:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><span>On Sat, 26.11.16 16:01, Stanislav Angelovič (<a target="_blank" href="mailto:angelovic.s@gmail.com">angelovic.s@gmail.com</a>) wrote:<br>
<br>
> Hi,<br>
><br>
> A quick question: Is it possible to append contents (the serialized data)<br>
> of an sd-bus message to another sd-bus message? Conversely, is it possible<br>
> to extract a part of sd-bus message contents into a separate<br>
> message?<br>
<br>
</span>There's sd_bus_message_copy() which can copy the contents (or a part<br>
of it) of a message into another message.<br>
<br>
There's currently no API that exposes the raw binary bits, and they<br>
aren't particularly useful anyway on dbus1 as they are not safe<br>
regarding alignment and you cannot copy them byte-by-byte to arbitrary<br>
memory locations. </blockquote><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<span><br>
> Details:<br>
><br>
> In the process of creating a method call message, I would like to do this:<br>
> 1. Create a temporary, empty message A.<br>
> 2. Serialize data into the message A.<br>
> 3. Create a method call message B.<br>
> 4. Serialize some user data into the message B, plus copy the data of the<br>
> message A into the message B. And send the message B.<br>
<br>
</span>sd_bus_message_copy() should work fine for that. </blockquote><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<div><div class="gmail-m_6495271554720758608h5"><br>
> Analogously, when deserializing data from the message B upon its reception<br>
> on the server side, I would like to do this:<br>
> 1. Extract user data from the message B, plus copy selected data into a<br>
> separate, empty message A.<br>
> 2. Destroy the message B.<br>
> 3. In some other context, deserialize real data from the message A.<br>
><br>
> Why am I asking is because we like sd-bus and are building a C++ binding on<br>
> top of it. We stumbled upon a problem when modelling Variant. The typical<br>
> flow in such a case is that upon e.g. deserialization, first the Variant<br>
> instances are created from the message contents, and then at some later<br>
> phase, users want to extract real data from the Variant. In this phase, our<br>
> C++ binding would perform the deserialization from that temporry message<br>
> (message A) that the Variant would hold.<br>
><br>
> For example, if the method call message carries an array of Variants, we<br>
> first deserialize the message into std::vector<Variant>, where each Variant<br>
> instance keeps the temporary sd-bus message with the variant data, and when<br>
> the user asks for a concrete data from that Variant, the deserialization<br>
> from that temporary message takes place.<br>
><br>
> This is the way it's done in e.g. dbus-c++, the C++ binding for libdbus.<br>
> libdbus API allows creating "empty" messages, and allows copying the data<br>
> among messages with the possibility of reading from them at the same time.<br>
> Is it possible to create an empty message using sd-bus? Regarding copying,<br>
> we know there's the sd_bus_message_copy function, but once we create the<br>
> copy message, we cannot read from it later because of the assertion that<br>
> the message is sealed, which in reality is not.<br>
<br>
</div></div>Hmm, so internally there's bus_message_seal() which I figure we could<br>
make publically available, so that you can create a new msg, copy the<br>
data to it, seal it, and read it back. <br></blockquote><div><br></div><div>Yes, exactly, I need to create a message copy, but also be able to read from it afterwards. If invoking  bus_message_seal() is sufficient to make the message readable after creating it, it would be so welcome to have it in the public API.<br></div><div>Additionally, we'd need a simple factory function for a message that won't have a context of a method call, a signal or an error message. Just plain message that will be used for storing some data and later, via sd_bus_message_copy(), copying the data into a 'real' message. There is message_new function in sd-bus, but it's internal. Would it be possible to make it public, just like lidbbus provides dbus_message_new()?<br></div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<span><br>
> Is there a way to solve this in sd-bus? Perhaps another way than I<br>
> described? Many thanks in advance for your response!<br>
<br>
</span>There's no nicer way right now. But I think we could add a<br>
sd_bus_message_dup() or so that duplicates a message, but does so<br>
efficiently, i.e. shares the memory for the actual payload. This way<br>
you could duplicate a message to simply get a new read ptr on the<br>
same, immutable message. I think that would suit your usecase best?<br></blockquote><div><br></div><div>sd_bus_message_dup() as you describe it could perfectly be an option, but -- similarly to sd_bus_message_copy() -- it would have to allow not only duplication of the entire message, but also a part of it. This could perhaps be handled -- consistently to sd_bus_message_copy() -- with an additional 'complete' boolean parameter. The behavior would be the same to sd_bus_message_copy, but the result would not be a real copy, but just a view/reference to (if complete==false, then a part of) the original message. So in my use case example if the message has signature "av", where the size of the array is 3, then I would like to create 3 messages out of it, each pointing to the corresponding variant data in the original message. And -- importantly -- be able to read from those 3 messages afterwards (the solution to that could be public sd_bus_message_seal(), as you proposed).<br></div><div>The first phase of reading from the original message would be done by the C++ binding (creation of 3 messages), the second phase by the user of the binding (taking data of a concrete type from these messages).<br><br></div><div>To sum up, we'd need just two simple things:<br></div><div>- be able to create a plain message, a-ka sd_bus_message *sd_bus_message_new(sd_bus *bus, uint8_t type);<br></div><div>- be able to read back from a message after we've created it (regardless of whether created by copying from another message, or anew) and appended some data into it, which now fails on the "sealed==true" expectation.<br></div><div><br></div><div>Support for efficient, shallow copy (sd_bus_message_dup()) would also be very nice to have. I like this idea.<br><br>Thanks a lot for your support!<br></div><div><br></div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<span class="gmail-m_6495271554720758608HOEnZb"><font color="#888888"><br>
Lennart<br>
<br>
--<br>
Lennart Poettering, Red Hat<br>
</font></span></blockquote></div><br></div></div>