1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "bus-message.h"
30 #include "bus-internal.h"
32 #include "bus-signature.h"
34 static int message_parse_fields(sd_bus_message *m);
35 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
37 static void reset_containers(sd_bus_message *m) {
42 for (i = 0; i < m->n_containers; i++)
43 free(m->containers[i].signature);
49 m->root_container.index = 0;
52 static void message_free(sd_bus_message *m) {
66 for (i = 0; i < m->n_fds; i++)
67 close_nointr_nofail(m->fds[i]);
70 free(m->root_container.signature);
72 free(m->peeked_signature);
76 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
84 start = ALIGN_TO((size_t) *sz, align);
88 return (uint8_t*) *p + start;
90 if (n > (size_t) ((uint32_t) -1))
97 /* Zero out padding */
99 memset((uint8_t*) k + *sz, 0, start - *sz);
104 return (uint8_t*) k + start;
107 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
113 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
117 if (o != m->fields) {
118 /* Adjust quick access pointers */
121 m->path = (const char*) m->fields + (m->path - (const char*) o);
123 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
125 m->member = (const char*) m->fields + (m->member - (const char*) o);
127 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
129 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
131 m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
134 m->free_fields = true;
139 static int message_append_field_string(
152 if (l > (size_t) (uint32_t) -1)
155 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
156 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
165 ((uint32_t*) p)[1] = l;
166 memcpy(p + 8, s, l + 1);
169 *ret = (const char*) p + 8;
174 static int message_append_field_signature(
189 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
190 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
196 p[2] = SD_BUS_TYPE_SIGNATURE;
199 memcpy(p + 5, s, l + 1);
202 *ret = (const char*) p + 5;
207 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
212 /* field id byte + signature length + signature 'u' + NUL + value */
213 p = message_extend_fields(m, 8, 4 + 4);
219 p[2] = SD_BUS_TYPE_UINT32;
222 ((uint32_t*) p)[1] = x;
227 int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret) {
229 struct bus_header *h;
230 size_t total, fs, bs;
233 assert(buffer || length <= 0);
236 if (length < sizeof(struct bus_header))
246 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
249 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
252 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
253 fs = bswap_32(h->fields_size);
254 bs = bswap_32(h->body_size);
258 total = sizeof(struct bus_header) + ALIGN_TO(fs, 8) + bs;
262 m = new0(sd_bus_message, 1);
268 m->free_header = true;
269 m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
270 m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN_TO(fs, 8);
274 m->iovec[0].iov_base = buffer;
275 m->iovec[0].iov_len = length;
277 r = message_parse_fields(m);
287 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
290 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
295 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
296 m->header->endian = SD_BUS_NATIVE_ENDIAN;
297 m->header->type = type;
298 m->header->version = bus ? bus->message_version : 1;
303 int sd_bus_message_new_signal(
306 const char *interface,
308 sd_bus_message **m) {
322 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
326 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
328 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
331 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
334 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
342 sd_bus_message_unref(t);
346 int sd_bus_message_new_method_call(
348 const char *destination,
350 const char *interface,
352 sd_bus_message **m) {
364 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
368 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
371 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
376 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
382 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
395 static int message_new_reply(
397 sd_bus_message *call,
399 sd_bus_message **m) {
406 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
411 t = message_new(bus, type);
415 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
416 t->reply_serial = BUS_MESSAGE_SERIAL(call);
418 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
423 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
428 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
438 int sd_bus_message_new_method_return(
440 sd_bus_message *call,
441 sd_bus_message **m) {
443 return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
446 int sd_bus_message_new_method_error(
448 sd_bus_message *call,
449 const sd_bus_error *e,
450 sd_bus_message **m) {
455 if (!sd_bus_error_is_set(e))
460 r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
464 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
469 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
482 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
486 assert(m->n_ref > 0);
492 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
496 assert(m->n_ref > 0);
505 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
511 *type = m->header->type;
515 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
520 if (m->header->serial == 0)
523 *serial = BUS_MESSAGE_SERIAL(m);
527 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
532 if (m->reply_serial == 0)
535 *serial = m->reply_serial;
539 int sd_bus_message_get_no_reply(sd_bus_message *m) {
543 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
546 const char *sd_bus_message_get_path(sd_bus_message *m) {
553 const char *sd_bus_message_get_interface(sd_bus_message *m) {
560 const char *sd_bus_message_get_member(sd_bus_message *m) {
566 const char *sd_bus_message_get_destination(sd_bus_message *m) {
570 return m->destination;
573 const char *sd_bus_message_get_sender(sd_bus_message *m) {
580 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
584 if (!sd_bus_error_is_set(&m->error))
590 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
600 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
610 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
620 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
630 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
634 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
637 if (interface && (!m->interface || !streq(m->interface, interface)))
640 if (member && (!m->member || !streq(m->member, member)))
646 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
650 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
653 if (interface && (!m->interface || !streq(m->interface, interface)))
656 if (member && (!m->member || !streq(m->member, member)))
662 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
666 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
669 if (name && (!m->error.name || !streq(m->error.name, name)))
675 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
680 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
684 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
686 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
691 static struct bus_container *message_get_container(sd_bus_message *m) {
694 if (m->n_containers == 0)
695 return &m->root_container;
697 assert(m->containers);
698 return m->containers + m->n_containers - 1;
701 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
704 struct bus_container *c;
710 added = m->header->body_size;
712 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
716 added = m->header->body_size - added;
718 for (c = m->containers; c < m->containers + m->n_containers; c++)
720 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
721 *c->array_size += added;
725 if (m->error.message)
726 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
734 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
735 struct bus_container *c;
745 if (!bus_type_is_basic(type))
748 c = message_get_container(m);
750 if (c->signature && c->signature[c->index]) {
751 /* Container signature is already set */
753 if (c->signature[c->index] != type)
756 /* Maybe we can append to the signature? But only if this is the top-level container*/
757 if (c->enclosing != 0)
760 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
767 case SD_BUS_TYPE_STRING:
768 case SD_BUS_TYPE_OBJECT_PATH:
770 sz = 4 + strlen(p) + 1;
773 case SD_BUS_TYPE_SIGNATURE:
775 sz = 1 + strlen(p) + 1;
778 case SD_BUS_TYPE_BOOLEAN:
781 assert_cc(sizeof(int) == sizeof(uint32_t));
788 align = bus_type_get_alignment(type);
789 sz = bus_type_get_size(type);
796 a = message_extend_body(m, align, sz);
798 /* Truncate extended signature again */
800 c->signature[c->index] = 0;
805 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
806 *(uint32_t*) a = sz - 5;
807 memcpy((uint8_t*) a + 4, p, sz - 4);
810 *stored = (const uint8_t*) a + 4;
812 } else if (type == SD_BUS_TYPE_SIGNATURE) {
813 *(uint8_t*) a = sz - 1;
814 memcpy((uint8_t*) a + 1, p, sz - 1);
817 *stored = (const uint8_t*) a + 1;
826 if (c->enclosing != SD_BUS_TYPE_ARRAY)
832 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
833 return message_append_basic(m, type, p, NULL);
836 static int bus_message_open_array(
838 struct bus_container *c,
839 const char *contents,
840 uint32_t **array_size) {
853 if (!signature_is_single(contents))
856 alignment = bus_type_get_alignment(contents[0]);
860 if (c->signature && c->signature[c->index]) {
862 /* Verify the existing signature */
864 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
867 if (!startswith(c->signature + c->index + 1, contents))
870 nindex = c->index + 1 + strlen(contents);
872 if (c->enclosing != 0)
875 /* Extend the existing signature */
877 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
881 nindex = e - c->signature;
884 saved = m->header->body_size;
885 a = message_extend_body(m, 4, 4);
887 /* Truncate extended signature again */
889 c->signature[c->index] = 0;
895 if (!message_extend_body(m, alignment, 0)) {
896 /* Add alignment between size and first element */
898 c->signature[c->index] = 0;
900 m->header->body_size = saved;
904 if (c->enclosing != SD_BUS_TYPE_ARRAY)
907 /* m->body might have changed so let's readjust a */
908 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
915 static int bus_message_open_variant(
917 struct bus_container *c,
918 const char *contents) {
928 if (!signature_is_single(contents))
931 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
934 if (c->signature && c->signature[c->index]) {
936 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
940 if (c->enclosing != 0)
943 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
948 l = strlen(contents);
949 a = message_extend_body(m, 1, 1 + l + 1);
951 /* Truncate extended signature again */
953 c->signature[c->index] = 0;
959 memcpy((uint8_t*) a + 1, contents, l + 1);
961 if (c->enclosing != SD_BUS_TYPE_ARRAY)
967 static int bus_message_open_struct(
969 struct bus_container *c,
970 const char *contents) {
979 if (!signature_is_valid(contents, false))
982 if (c->signature && c->signature[c->index]) {
985 l = strlen(contents);
987 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
988 !startswith(c->signature + c->index + 1, contents) ||
989 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
992 nindex = c->index + 1 + l + 1;
994 if (c->enclosing != 0)
997 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1001 nindex = e - c->signature;
1004 /* Align contents to 8 byte boundary */
1005 if (!message_extend_body(m, 8, 0)) {
1007 c->signature[c->index] = 0;
1012 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1018 static int bus_message_open_dict_entry(
1020 struct bus_container *c,
1021 const char *contents) {
1029 if (!signature_is_pair(contents))
1032 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1035 if (c->signature && c->signature[c->index]) {
1038 l = strlen(contents);
1040 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1041 !startswith(c->signature + c->index + 1, contents) ||
1042 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1045 nindex = c->index + 1 + l + 1;
1049 /* Align contents to 8 byte boundary */
1050 if (!message_extend_body(m, 8, 0))
1053 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1059 int sd_bus_message_open_container(
1062 const char *contents) {
1064 struct bus_container *c, *w;
1065 uint32_t *array_size = NULL;
1076 /* Make sure we have space for one more container */
1077 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1082 c = message_get_container(m);
1084 signature = strdup(contents);
1088 if (type == SD_BUS_TYPE_ARRAY)
1089 r = bus_message_open_array(m, c, contents, &array_size);
1090 else if (type == SD_BUS_TYPE_VARIANT)
1091 r = bus_message_open_variant(m, c, contents);
1092 else if (type == SD_BUS_TYPE_STRUCT)
1093 r = bus_message_open_struct(m, c, contents);
1094 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1095 r = bus_message_open_dict_entry(m, c, contents);
1104 /* OK, let's fill it in */
1105 w += m->n_containers++;
1106 w->enclosing = type;
1107 w->signature = signature;
1109 w->array_size = array_size;
1115 int sd_bus_message_close_container(sd_bus_message *m) {
1116 struct bus_container *c;
1122 if (m->n_containers <= 0)
1125 c = message_get_container(m);
1126 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1127 if (c->signature && c->signature[c->index] != 0)
1136 static int message_append_ap(
1147 for (t = types; *t; t++) {
1150 case SD_BUS_TYPE_BYTE: {
1153 x = (uint8_t) va_arg(ap, int);
1154 r = sd_bus_message_append_basic(m, *t, &x);
1158 case SD_BUS_TYPE_BOOLEAN:
1159 case SD_BUS_TYPE_INT32:
1160 case SD_BUS_TYPE_UINT32:
1161 case SD_BUS_TYPE_UNIX_FD: {
1164 /* We assume a boolean is the same as int32_t */
1165 assert_cc(sizeof(int32_t) == sizeof(int));
1167 x = va_arg(ap, uint32_t);
1168 r = sd_bus_message_append_basic(m, *t, &x);
1172 case SD_BUS_TYPE_INT16:
1173 case SD_BUS_TYPE_UINT16: {
1176 x = (uint16_t) va_arg(ap, int);
1177 r = sd_bus_message_append_basic(m, *t, &x);
1181 case SD_BUS_TYPE_INT64:
1182 case SD_BUS_TYPE_UINT64:
1183 case SD_BUS_TYPE_DOUBLE: {
1186 x = va_arg(ap, uint64_t);
1187 r = sd_bus_message_append_basic(m, *t, &x);
1191 case SD_BUS_TYPE_STRING:
1192 case SD_BUS_TYPE_OBJECT_PATH:
1193 case SD_BUS_TYPE_SIGNATURE: {
1196 x = va_arg(ap, const char*);
1197 r = sd_bus_message_append_basic(m, *t, x);
1201 case SD_BUS_TYPE_ARRAY: {
1204 r = signature_element_length(t + 1, &k);
1212 memcpy(s, t + 1, k);
1216 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1220 n = va_arg(ap, unsigned);
1221 for (i = 0; i < n; i++) {
1222 r = message_append_ap(m, s, ap);
1227 r = sd_bus_message_close_container(m);
1233 case SD_BUS_TYPE_VARIANT: {
1236 s = va_arg(ap, const char*);
1240 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1244 r = message_append_ap(m, s, ap);
1248 r = sd_bus_message_close_container(m);
1252 case SD_BUS_TYPE_STRUCT_BEGIN:
1253 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1256 r = signature_element_length(t, &k);
1263 memcpy(s, t + 1, k - 2);
1266 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1272 r = message_append_ap(m, s, ap);
1276 r = sd_bus_message_close_container(m);
1293 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1304 va_start(ap, types);
1305 r = message_append_ap(m, types, ap);
1311 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1317 start = ALIGN_TO((size_t) *rindex, align);
1323 /* Verify that padding is 0 */
1324 for (k = *rindex; k < start; k++)
1325 if (((const uint8_t*) p)[k] != 0)
1329 *r = (uint8_t*) p + start;
1336 static bool message_end_of_array(sd_bus_message *m, size_t index) {
1337 struct bus_container *c;
1341 c = message_get_container(m);
1345 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
1348 static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
1353 if (message_end_of_array(m, *rindex))
1356 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1359 static bool validate_string(const char *s, size_t l) {
1362 /* Check for NUL chars in the string */
1363 if (memchr(s, 0, l))
1366 /* Check for NUL termination */
1370 /* Check if valid UTF8 */
1371 if (!utf8_is_valid(s))
1377 static bool validate_signature(const char *s, size_t l) {
1378 /* Check for NUL chars in the signature */
1379 if (memchr(s, 0, l))
1382 /* Check for NUL termination */
1386 /* Check if valid signature */
1387 if (!signature_is_valid(s, true))
1393 int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1394 struct bus_container *c;
1402 if (!bus_type_is_basic(type))
1405 c = message_get_container(m);
1407 if (!c->signature || c->signature[c->index] == 0)
1410 if (c->signature[c->index] != type)
1415 case SD_BUS_TYPE_STRING:
1416 case SD_BUS_TYPE_OBJECT_PATH: {
1421 r = message_peek_body(m, &rindex, 4, 4, &q);
1425 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1426 r = message_peek_body(m, &rindex, 1, l+1, &q);
1432 if (!validate_string(q, l))
1436 *(const char**) p = q;
1440 case SD_BUS_TYPE_SIGNATURE: {
1445 r = message_peek_body(m, &rindex, 1, 1, &q);
1450 r = message_peek_body(m, &rindex, 1, l+1, &q);
1456 if (!validate_signature(q, l))
1460 *(const char**) p = q;
1467 align = bus_type_get_alignment(type);
1468 sz = bus_type_get_size(type);
1470 r = message_peek_body(m, &m->rindex, align, sz, &q);
1476 case SD_BUS_TYPE_BYTE:
1477 *(uint8_t*) p = *(uint8_t*) q;
1480 case SD_BUS_TYPE_BOOLEAN:
1481 *(int*) p = !!*(uint32_t*) q;
1484 case SD_BUS_TYPE_INT16:
1485 case SD_BUS_TYPE_UINT16:
1486 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1489 case SD_BUS_TYPE_INT32:
1490 case SD_BUS_TYPE_UINT32:
1491 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1494 case SD_BUS_TYPE_INT64:
1495 case SD_BUS_TYPE_UINT64:
1496 case SD_BUS_TYPE_DOUBLE:
1497 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1501 assert_not_reached("Unknown basic type...");
1508 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1514 static int bus_message_enter_array(
1516 struct bus_container *c,
1517 const char *contents,
1518 uint32_t **array_size) {
1529 if (!signature_is_single(contents))
1532 alignment = bus_type_get_alignment(contents[0]);
1536 if (!c->signature || c->signature[c->index] == 0)
1539 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1542 if (!startswith(c->signature + c->index + 1, contents))
1546 r = message_peek_body(m, &rindex, 4, 4, &q);
1550 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > 67108864)
1553 r = message_peek_body(m, &rindex, alignment, 0, NULL);
1559 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1560 c->index += 1 + strlen(contents);
1564 *array_size = (uint32_t*) q;
1569 static int bus_message_enter_variant(
1571 struct bus_container *c,
1572 const char *contents) {
1583 if (!signature_is_single(contents))
1586 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1589 if (!c->signature || c->signature[c->index] == 0)
1592 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1596 r = message_peek_body(m, &rindex, 1, 1, &q);
1601 r = message_peek_body(m, &rindex, 1, l+1, &q);
1607 if (!validate_signature(q, l))
1610 if (!streq(q, contents))
1613 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1621 static int bus_message_enter_struct(
1623 struct bus_container *c,
1624 const char *contents) {
1633 if (!signature_is_valid(contents, false))
1636 if (!c->signature || c->signature[c->index] == 0)
1639 l = strlen(contents);
1641 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1642 !startswith(c->signature + c->index + 1, contents) ||
1643 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1646 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1650 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1651 c->index += 1 + l + 1;
1656 static int bus_message_enter_dict_entry(
1658 struct bus_container *c,
1659 const char *contents) {
1668 if (!signature_is_pair(contents))
1671 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1674 if (!c->signature || c->signature[c->index] == 0)
1677 l = strlen(contents);
1679 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1680 !startswith(c->signature + c->index + 1, contents) ||
1681 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1684 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1688 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1689 c->index += 1 + l + 1;
1694 int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
1695 struct bus_container *c, *w;
1696 uint32_t *array_size = NULL;
1707 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1712 c = message_get_container(m);
1714 if (!c->signature || c->signature[c->index] == 0)
1717 signature = strdup(contents);
1721 if (type == SD_BUS_TYPE_ARRAY)
1722 r = bus_message_enter_array(m, c, contents, &array_size);
1723 else if (type == SD_BUS_TYPE_VARIANT)
1724 r = bus_message_enter_variant(m, c, contents);
1725 else if (type == SD_BUS_TYPE_STRUCT)
1726 r = bus_message_enter_struct(m, c, contents);
1727 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1728 r = bus_message_enter_dict_entry(m, c, contents);
1737 /* OK, let's fill it in */
1738 w += m->n_containers++;
1739 w->enclosing = type;
1740 w->signature = signature;
1742 w->array_size = array_size;
1743 w->begin = m->rindex;
1748 int sd_bus_message_exit_container(sd_bus_message *m) {
1749 struct bus_container *c;
1755 if (m->n_containers <= 0)
1758 c = message_get_container(m);
1759 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
1762 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
1763 if (c->begin + l != m->rindex)
1767 if (c->signature && c->signature[c->index] != 0)
1777 int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
1778 struct bus_container *c;
1786 c = message_get_container(m);
1788 if (!c->signature || c->signature[c->index] == 0)
1791 if (message_end_of_array(m, m->rindex))
1794 if (bus_type_is_basic(c->signature[c->index])) {
1798 *type = c->signature[c->index];
1802 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
1808 r = signature_element_length(c->signature+c->index+1, &l);
1814 sig = strndup(c->signature + c->index + 1, l);
1818 free(m->peeked_signature);
1819 m->peeked_signature = sig;
1825 *type = SD_BUS_TYPE_ARRAY;
1830 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
1831 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
1837 r = signature_element_length(c->signature+c->index, &l);
1842 sig = strndup(c->signature + c->index + 1, l - 2);
1846 free(m->peeked_signature);
1847 m->peeked_signature = sig;
1853 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
1858 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
1864 r = message_peek_body(m, &rindex, 1, 1, &q);
1871 r = message_peek_body(m, &rindex, 1, l+1, &q);
1877 if (!validate_signature(q, l))
1884 *type = SD_BUS_TYPE_VARIANT;
1893 *type = c->enclosing;
1899 int sd_bus_message_rewind(sd_bus_message *m, int complete) {
1900 struct bus_container *c;
1908 reset_containers(m);
1910 m->root_container.index = 0;
1912 c = message_get_container(m);
1914 c = message_get_container(m);
1917 m->rindex = c->begin;
1920 return !isempty(c->signature);
1923 static int message_read_ap(sd_bus_message *m, const char *types, va_list ap) {
1930 for (t = types; *t; t++) {
1933 case SD_BUS_TYPE_BYTE:
1934 case SD_BUS_TYPE_BOOLEAN:
1935 case SD_BUS_TYPE_INT16:
1936 case SD_BUS_TYPE_UINT16:
1937 case SD_BUS_TYPE_INT32:
1938 case SD_BUS_TYPE_UINT32:
1939 case SD_BUS_TYPE_INT64:
1940 case SD_BUS_TYPE_UINT64:
1941 case SD_BUS_TYPE_DOUBLE:
1942 case SD_BUS_TYPE_STRING:
1943 case SD_BUS_TYPE_OBJECT_PATH:
1944 case SD_BUS_TYPE_SIGNATURE: {
1947 p = va_arg(ap, void*);
1948 r = sd_bus_message_read_basic(m, *t, p);
1952 case SD_BUS_TYPE_ARRAY: {
1955 r = signature_element_length(t + 1, &k);
1963 memcpy(s, t + 1, k);
1967 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
1973 n = va_arg(ap, unsigned);
1974 for (i = 0; i < n; i++) {
1975 r = message_read_ap(m, s, ap);
1980 r = sd_bus_message_exit_container(m);
1986 case SD_BUS_TYPE_VARIANT: {
1989 s = va_arg(ap, const char *);
1993 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
1999 r = message_read_ap(m, s, ap);
2005 r = sd_bus_message_exit_container(m);
2009 case SD_BUS_TYPE_STRUCT_BEGIN:
2010 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2013 r = signature_element_length(t, &k);
2019 memcpy(s, t + 1, k - 2);
2022 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2030 r = message_read_ap(m, s, ap);
2036 r = sd_bus_message_exit_container(m);
2055 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2066 va_start(ap, types);
2067 r = message_read_ap(m, types, ap);
2073 static int message_peek_fields(
2084 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2087 static int message_peek_field_string(
2099 r = message_peek_fields(m, ri, 4, 4, &q);
2103 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2104 r = message_peek_fields(m, ri, 1, l+1, &q);
2108 if (!validate_string(q, l))
2117 static int message_peek_field_signature(
2129 r = message_peek_fields(m, ri, 1, 1, &q);
2134 r = message_peek_fields(m, ri, 1, l+1, &q);
2138 if (!validate_signature(q, l))
2147 static int message_peek_field_uint32(
2158 r = message_peek_fields(m, ri, 4, 4, &q);
2163 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2168 static int message_skip_fields(
2171 uint32_t array_size,
2172 const char **signature) {
2174 size_t original_index;
2181 original_index = *ri;
2188 if (array_size != (uint32_t) -1 &&
2189 array_size <= *ri - original_index)
2196 if (t == SD_BUS_TYPE_STRING ||
2197 t == SD_BUS_TYPE_OBJECT_PATH) {
2199 r = message_peek_field_string(m, ri, NULL);
2205 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2207 r = message_peek_field_signature(m, ri, NULL);
2213 } else if (bus_type_is_basic(t)) {
2216 align = bus_type_get_alignment(align);
2217 k = bus_type_get_size(align);
2219 r = message_peek_fields(m, ri, align, k, NULL);
2225 } else if (t == SD_BUS_TYPE_ARRAY) {
2227 r = signature_element_length(*signature+1, &l);
2237 strncpy(sig, *signature + 1, l-1);
2240 alignment = bus_type_get_alignment(sig[0]);
2244 r = message_peek_fields(m, ri, 4, 4, &q);
2248 nas = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2252 r = message_peek_fields(m, ri, alignment, 0, NULL);
2256 r = message_skip_fields(m, ri, nas, (const char**) &s);
2261 (*signature) += 1 + l;
2263 } else if (t == SD_BUS_TYPE_VARIANT) {
2266 r = message_peek_field_signature(m, ri, &s);
2270 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2276 } else if (t == SD_BUS_TYPE_STRUCT ||
2277 t == SD_BUS_TYPE_DICT_ENTRY) {
2279 r = signature_element_length(*signature, &l);
2286 strncpy(sig, *signature + 1, l-1);
2289 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2300 static int message_parse_fields(sd_bus_message *m) {
2306 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2307 const char *signature;
2310 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2314 r = message_peek_field_signature(m, &ri, &signature);
2319 case _SD_BUS_MESSAGE_HEADER_INVALID:
2322 case SD_BUS_MESSAGE_HEADER_PATH:
2323 if (!streq(signature, "o"))
2326 r = message_peek_field_string(m, &ri, &m->path);
2329 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2330 if (!streq(signature, "s"))
2333 r = message_peek_field_string(m, &ri, &m->interface);
2336 case SD_BUS_MESSAGE_HEADER_MEMBER:
2337 if (!streq(signature, "s"))
2340 r = message_peek_field_string(m, &ri, &m->member);
2343 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2344 if (!streq(signature, "s"))
2347 r = message_peek_field_string(m, &ri, &m->error.name);
2350 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2351 if (!streq(signature, "s"))
2354 r = message_peek_field_string(m, &ri, &m->destination);
2357 case SD_BUS_MESSAGE_HEADER_SENDER:
2358 if (!streq(signature, "s"))
2361 r = message_peek_field_string(m, &ri, &m->sender);
2365 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2369 if (!streq(signature, "g"))
2372 r = message_peek_field_signature(m, &ri, &s);
2380 free(m->root_container.signature);
2381 m->root_container.signature = c;
2387 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2388 if (!streq(signature, "u"))
2391 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
2395 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
2402 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
2405 switch (m->header->type) {
2407 case SD_BUS_MESSAGE_TYPE_SIGNAL:
2408 if (!m->path || !m->interface || !m->member)
2412 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
2414 if (!m->path || !m->member)
2419 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
2421 if (m->reply_serial == 0)
2425 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
2427 if (m->reply_serial == 0 || !m->error.name)
2432 /* Try to read the error message, but if we can't it's a non-issue */
2433 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
2434 sd_bus_message_read(m, "s", &m->error.message);
2439 static void setup_iovec(sd_bus_message *m) {
2445 m->iovec[m->n_iovec].iov_base = m->header;
2446 m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
2450 m->iovec[m->n_iovec].iov_base = m->fields;
2451 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
2454 if (m->header->fields_size % 8 != 0) {
2455 static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
2457 m->iovec[m->n_iovec].iov_base = (void*) padding;
2458 m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
2464 m->iovec[m->n_iovec].iov_base = m->body;
2465 m->iovec[m->n_iovec].iov_len = m->header->body_size;
2470 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2478 if (m->n_containers > 0)
2481 /* If there's a non-trivial signature set, then add it in here */
2482 if (!isempty(m->root_container.signature)) {
2483 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2489 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2494 m->header->serial = serial;
2502 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
2512 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
2515 int bus_message_dump(sd_bus_message *m) {
2521 printf("Message %p\n"
2528 "\tfields_size=%u\n"
2533 "\tdestination=%s\n"
2536 "\treply_serial=%u\n"
2538 "\terror.message=%s\n"
2546 BUS_MESSAGE_SERIAL(m),
2547 BUS_MESSAGE_FIELDS_SIZE(m),
2548 BUS_MESSAGE_BODY_SIZE(m),
2550 strna(m->interface),
2552 strna(m->destination),
2554 strna(m->root_container.signature),
2556 strna(m->error.name),
2557 strna(m->error.message),
2560 r = sd_bus_message_rewind(m, true);
2562 log_error("Failed to rewind: %s", strerror(-r));
2566 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
2569 _cleanup_free_ char *prefix = NULL;
2570 const char *contents = NULL;
2585 r = sd_bus_message_peek_type(m, &type, &contents);
2587 log_error("Failed to peek type: %s", strerror(-r));
2594 r = sd_bus_message_exit_container(m);
2596 log_error("Failed to exit container: %s", strerror(-r));
2602 prefix = strrep("\t", level);
2606 if (type == SD_BUS_TYPE_ARRAY)
2607 printf("%s} END_ARRAY \n", prefix);
2608 else if (type == SD_BUS_TYPE_VARIANT)
2609 printf("%s} END_VARIANT\n", prefix);
2610 else if (type == SD_BUS_TYPE_STRUCT)
2611 printf("%s} END_STRUCT\n", prefix);
2612 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2613 printf("%s} END_DICT_ENTRY\n", prefix);
2618 prefix = strrep("\t", level);
2622 if (bus_type_is_container(type) > 0) {
2623 r = sd_bus_message_enter_container(m, type, contents);
2625 log_error("Failed to enter container: %s", strerror(-r));
2629 if (type == SD_BUS_TYPE_ARRAY)
2630 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
2631 else if (type == SD_BUS_TYPE_VARIANT)
2632 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
2633 else if (type == SD_BUS_TYPE_STRUCT)
2634 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
2635 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2636 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
2643 r = sd_bus_message_read_basic(m, type, &basic);
2645 log_error("Failed to get basic: %s", strerror(-r));
2651 case SD_BUS_TYPE_BYTE:
2652 printf("%sBYTE: %u\n", prefix, basic.u8);
2655 case SD_BUS_TYPE_BOOLEAN:
2656 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
2659 case SD_BUS_TYPE_INT16:
2660 printf("%sINT16: %i\n", prefix, basic.s16);
2663 case SD_BUS_TYPE_UINT16:
2664 printf("%sUINT16: %u\n", prefix, basic.u16);
2667 case SD_BUS_TYPE_INT32:
2668 printf("%sINT32: %i\n", prefix, basic.s32);
2671 case SD_BUS_TYPE_UINT32:
2672 printf("%sUINT32: %u\n", prefix, basic.u32);
2675 case SD_BUS_TYPE_INT64:
2676 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
2679 case SD_BUS_TYPE_UINT64:
2680 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
2683 case SD_BUS_TYPE_DOUBLE:
2684 printf("%sDOUBLE: %g\n", prefix, basic.d64);
2687 case SD_BUS_TYPE_STRING:
2688 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
2691 case SD_BUS_TYPE_OBJECT_PATH:
2692 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
2695 case SD_BUS_TYPE_SIGNATURE:
2696 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
2699 case SD_BUS_TYPE_UNIX_FD:
2700 printf("%sUNIX_FD: %i\n", prefix, basic.i);
2704 assert_not_reached("Unknown basic type.");
2708 printf("} END_MESSAGE\n");
2712 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
2721 for (i = 0, total = 0; i < m->n_iovec; i++)
2722 total += m->iovec[i].iov_len;
2728 for (i = 0, e = p; i < m->n_iovec; i++)
2729 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
2737 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
2743 r = sd_bus_message_enter_container(m, 'a', "s");
2750 r = sd_bus_message_read_basic(m, 's', &s);
2756 r = strv_extend(l, s);
2761 r = sd_bus_message_exit_container(m);