bus: remarshal messages when necessary before sending
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
#include "bus-type.h"
|
||||
#include "bus-signature.h"
|
||||
#include "bus-gvariant.h"
|
||||
#include "bus-util.h"
|
||||
|
||||
static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
|
||||
|
||||
@@ -5407,3 +5408,87 @@ _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
|
||||
|
||||
return m->bus;
|
||||
}
|
||||
|
||||
int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
|
||||
_cleanup_bus_message_unref_ sd_bus_message *n = NULL;
|
||||
usec_t timeout;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(m);
|
||||
assert(*m);
|
||||
|
||||
switch ((*m)->header->type) {
|
||||
|
||||
case SD_BUS_MESSAGE_SIGNAL:
|
||||
r = sd_bus_message_new_signal(bus, (*m)->path, (*m)->interface, (*m)->member, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case SD_BUS_MESSAGE_METHOD_CALL:
|
||||
r = sd_bus_message_new_method_call(bus, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case SD_BUS_MESSAGE_METHOD_RETURN:
|
||||
case SD_BUS_MESSAGE_METHOD_ERROR:
|
||||
|
||||
n = message_new(bus, (*m)->header->type);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
n->reply_serial = (*m)->reply_serial;
|
||||
r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_serial);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
|
||||
r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n->error._need_free = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((*m)->destination && !n->destination) {
|
||||
r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if ((*m)->sender && !n->sender) {
|
||||
r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
|
||||
|
||||
r = sd_bus_message_copy(n, *m, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
timeout = (*m)->timeout;
|
||||
if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
|
||||
timeout = BUS_DEFAULT_TIMEOUT;
|
||||
|
||||
r = bus_message_seal(n, (*m)->header->serial, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sd_bus_message_unref(*m);
|
||||
*m = n;
|
||||
n = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -231,3 +231,5 @@ void bus_body_part_unmap(struct bus_body_part *part);
|
||||
int bus_message_to_errno(sd_bus_message *m);
|
||||
|
||||
int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m);
|
||||
|
||||
int bus_message_remarshal(sd_bus *bus, sd_bus_message **m);
|
||||
|
||||
+32
-11
@@ -1319,14 +1319,6 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
|
||||
assert(b);
|
||||
assert(m);
|
||||
|
||||
if (b->message_version != 0 &&
|
||||
m->header->version != b->message_version)
|
||||
return -EPERM;
|
||||
|
||||
if (b->message_endian != 0 &&
|
||||
m->header->endian != b->message_endian)
|
||||
return -EPERM;
|
||||
|
||||
if (m->sealed) {
|
||||
/* If we copy the same message to multiple
|
||||
* destinations, avoid using the same serial
|
||||
@@ -1341,6 +1333,18 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
|
||||
return bus_message_seal(m, ++b->serial, timeout);
|
||||
}
|
||||
|
||||
static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
|
||||
assert(b);
|
||||
|
||||
/* Do packet version and endianess already match? */
|
||||
if ((b->message_version == 0 || b->message_version == (*m)->header->version) &&
|
||||
(b->message_endian == 0 || b->message_endian == (*m)->header->endian))
|
||||
return 0;
|
||||
|
||||
/* No? Then remarshal! */
|
||||
return bus_message_remarshal(b, m);
|
||||
}
|
||||
|
||||
int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
|
||||
assert(b);
|
||||
assert(m);
|
||||
@@ -1452,7 +1456,8 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
|
||||
}
|
||||
}
|
||||
|
||||
_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
|
||||
_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *serial) {
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
@@ -1477,6 +1482,12 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Remarshall if we have to. This will possible unref the
|
||||
* message and place a replacement in m */
|
||||
r = bus_remarshal_message(bus, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* If this is a reply and no reply was requested, then let's
|
||||
* suppress this, if we can */
|
||||
if (m->dont_send && !serial)
|
||||
@@ -1567,12 +1578,13 @@ static int timeout_compare(const void *a, const void *b) {
|
||||
|
||||
_public_ int sd_bus_call_async(
|
||||
sd_bus *bus,
|
||||
sd_bus_message *m,
|
||||
sd_bus_message *_m,
|
||||
sd_bus_message_handler_t callback,
|
||||
void *userdata,
|
||||
uint64_t usec,
|
||||
uint64_t *serial) {
|
||||
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
|
||||
struct reply_callback *c;
|
||||
int r;
|
||||
|
||||
@@ -1596,6 +1608,10 @@ _public_ int sd_bus_call_async(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_remarshal_message(bus, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c = new0(struct reply_callback, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
@@ -1674,11 +1690,12 @@ int bus_ensure_running(sd_bus *bus) {
|
||||
|
||||
_public_ int sd_bus_call(
|
||||
sd_bus *bus,
|
||||
sd_bus_message *m,
|
||||
sd_bus_message *_m,
|
||||
uint64_t usec,
|
||||
sd_bus_error *error,
|
||||
sd_bus_message **reply) {
|
||||
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
|
||||
usec_t timeout;
|
||||
uint64_t serial;
|
||||
unsigned i;
|
||||
@@ -1702,6 +1719,10 @@ _public_ int sd_bus_call(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_remarshal_message(bus, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_send(bus, m, &serial);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Reference in New Issue
Block a user