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/>.
28 #include "bus-message.h"
29 #include "bus-internal.h"
31 #include "bus-signature.h"
33 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
35 static void reset_containers(sd_bus_message *m) {
40 for (i = 0; i < m->n_containers; i++)
41 free(m->containers[i].signature);
47 m->root_container.index = 0;
50 static void message_free(sd_bus_message *m) {
64 for (i = 0; i < m->n_fds; i++)
65 close_nointr_nofail(m->fds[i]);
68 free(m->root_container.signature);
70 free(m->peeked_signature);
74 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
82 start = ALIGN_TO((size_t) *sz, align);
86 return (uint8_t*) *p + start;
88 if (n > (size_t) ((uint32_t) -1))
95 /* Zero out padding */
97 memset((uint8_t*) k + *sz, 0, start - *sz);
102 return (uint8_t*) k + start;
105 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
111 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
115 if (o != m->fields) {
116 /* Adjust quick access pointers */
119 m->path = (const char*) m->fields + (m->path - (const char*) o);
121 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
123 m->member = (const char*) m->fields + (m->member - (const char*) o);
125 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
127 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
129 m->signature = (const char*) m->fields + (m->signature - (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 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
230 m = malloc0(ALIGN(sizeof(struct sd_bus_message)) + sizeof(struct bus_header));
235 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
237 #if __BYTE_ORDER == __BIG_ENDIAN
238 m->header->endian = SD_BUS_BIG_ENDIAN;
240 m->header->endian = SD_BUS_LITTLE_ENDIAN;
242 m->header->type = type;
243 m->header->version = bus ? bus->message_version : 1;
248 int sd_bus_message_new_signal(
251 const char *interface,
253 sd_bus_message **m) {
267 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
271 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
274 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
277 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
285 sd_bus_message_unref(t);
289 int sd_bus_message_new_method_call(
291 const char *destination,
293 const char *interface,
295 sd_bus_message **m) {
307 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
311 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
314 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
319 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
325 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
338 static int message_new_reply(
340 sd_bus_message *call,
342 sd_bus_message **m) {
349 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
354 t = message_new(bus, type);
358 t->reply_serial = BUS_MESSAGE_SERIAL(call);
360 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
365 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
370 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
379 int sd_bus_message_new_method_return(
381 sd_bus_message *call,
382 sd_bus_message **m) {
384 return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
387 int sd_bus_message_new_method_error(
389 sd_bus_message *call,
390 const sd_bus_error *e,
391 sd_bus_message **m) {
403 r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
407 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
412 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
425 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
429 assert(m->n_ref > 0);
435 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
439 assert(m->n_ref > 0);
448 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
454 *type = m->header->type;
458 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
463 if (m->header->serial == 0)
466 *serial = BUS_MESSAGE_SERIAL(m);
470 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
475 if (m->reply_serial == 0)
478 *serial = m->reply_serial;
482 int sd_bus_message_get_no_reply(sd_bus_message *m) {
486 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
489 const char *sd_bus_message_get_path(sd_bus_message *m) {
496 const char *sd_bus_message_get_interface(sd_bus_message *m) {
503 const char *sd_bus_message_get_member(sd_bus_message *m) {
509 const char *sd_bus_message_get_destination(sd_bus_message *m) {
513 return m->destination;
516 const char *sd_bus_message_get_sender(sd_bus_message *m) {
523 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
527 if (!sd_bus_error_is_set(&m->error))
533 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
543 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
553 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
563 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
573 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
577 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
580 if (interface && (!m->interface || !streq(m->interface, interface)))
583 if (member && (!m->member || !streq(m->member, member)))
589 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
593 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
596 if (interface && (!m->interface || !streq(m->interface, interface)))
599 if (member && (!m->member || !streq(m->member, member)))
605 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
609 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
612 if (name && (!m->error.name || !streq(m->error.name, name)))
618 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
623 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
627 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
629 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
634 static struct bus_container *message_get_container(sd_bus_message *m) {
637 if (m->n_containers == 0)
638 return &m->root_container;
640 assert(m->containers);
641 return m->containers + m->n_containers - 1;
644 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
647 struct bus_container *c;
653 added = m->header->body_size;
655 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
659 added = m->header->body_size - added;
661 for (c = m->containers; c < m->containers + m->n_containers; c++)
663 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
664 *c->array_size += added;
668 if (m->error.message)
669 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
677 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
678 struct bus_container *c;
688 if (!bus_type_is_basic(type))
691 c = message_get_container(m);
693 if (c->signature && c->signature[c->index]) {
694 /* Container signature is already set */
696 if (c->signature[c->index] != type)
699 /* Maybe we can append to the signature? But only if this is the top-level container*/
700 if (c->enclosing != 0)
703 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
710 case SD_BUS_TYPE_STRING:
711 case SD_BUS_TYPE_OBJECT_PATH:
713 sz = 4 + strlen(p) + 1;
716 case SD_BUS_TYPE_SIGNATURE:
718 sz = 1 + strlen(p) + 1;
721 case SD_BUS_TYPE_BOOLEAN:
724 assert_cc(sizeof(int) == sizeof(uint32_t));
731 align = bus_type_get_alignment(type);
732 sz = bus_type_get_size(type);
739 a = message_extend_body(m, align, sz);
741 /* Truncate extended signature again */
743 c->signature[c->index] = 0;
748 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
749 *(uint32_t*) a = sz - 5;
750 memcpy((uint8_t*) a + 4, p, sz - 4);
753 *stored = (const uint8_t*) a + 4;
755 } else if (type == SD_BUS_TYPE_SIGNATURE) {
756 *(uint8_t*) a = sz - 1;
757 memcpy((uint8_t*) a + 1, p, sz - 1);
760 *stored = (const uint8_t*) a + 1;
769 if (c->enclosing != SD_BUS_TYPE_ARRAY)
775 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
776 return message_append_basic(m, type, p, NULL);
779 static int bus_message_open_array(
781 struct bus_container *c,
782 const char *contents,
783 uint32_t **array_size) {
796 if (!signature_is_single(contents))
799 alignment = bus_type_get_alignment(contents[0]);
803 if (c->signature && c->signature[c->index]) {
805 /* Verify the existing signature */
807 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
810 if (!startswith(c->signature + c->index + 1, contents))
813 nindex = c->index + 1 + strlen(contents);
815 if (c->enclosing != 0)
818 /* Extend the existing signature */
820 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
824 nindex = e - c->signature;
827 saved = m->header->body_size;
828 a = message_extend_body(m, 4, 4);
830 /* Truncate extended signature again */
832 c->signature[c->index] = 0;
838 if (!message_extend_body(m, alignment, 0)) {
839 /* Add alignment between size and first element */
841 c->signature[c->index] = 0;
843 m->header->body_size = saved;
847 if (c->enclosing != SD_BUS_TYPE_ARRAY)
850 /* m->body might have changed so let's readjust a */
851 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
858 static int bus_message_open_variant(
860 struct bus_container *c,
861 const char *contents) {
871 if (!signature_is_single(contents))
874 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
877 if (c->signature && c->signature[c->index]) {
879 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
883 if (c->enclosing != 0)
886 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
891 l = strlen(contents);
892 a = message_extend_body(m, 1, 1 + l + 1);
894 /* Truncate extended signature again */
896 c->signature[c->index] = 0;
902 memcpy((uint8_t*) a + 1, contents, l + 1);
904 if (c->enclosing != SD_BUS_TYPE_ARRAY)
910 static int bus_message_open_struct(
912 struct bus_container *c,
913 const char *contents) {
922 if (!signature_is_valid(contents, false))
925 if (c->signature && c->signature[c->index]) {
928 l = strlen(contents);
930 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
931 !startswith(c->signature + c->index + 1, contents) ||
932 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
935 nindex = c->index + 1 + l + 1;
937 if (c->enclosing != 0)
940 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
944 nindex = e - c->signature;
947 /* Align contents to 8 byte boundary */
948 if (!message_extend_body(m, 8, 0)) {
950 c->signature[c->index] = 0;
955 if (c->enclosing != SD_BUS_TYPE_ARRAY)
961 static int bus_message_open_dict_entry(
963 struct bus_container *c,
964 const char *contents) {
972 if (!signature_is_pair(contents))
975 if (c->enclosing != SD_BUS_TYPE_ARRAY)
978 if (c->signature && c->signature[c->index]) {
981 l = strlen(contents);
983 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
984 !startswith(c->signature + c->index + 1, contents) ||
985 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
988 nindex = c->index + 1 + l + 1;
992 /* Align contents to 8 byte boundary */
993 if (!message_extend_body(m, 8, 0))
996 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1002 int sd_bus_message_open_container(
1005 const char *contents) {
1007 struct bus_container *c, *w;
1008 uint32_t *array_size = NULL;
1019 /* Make sure we have space for one more container */
1020 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1025 c = message_get_container(m);
1027 signature = strdup(contents);
1031 if (type == SD_BUS_TYPE_ARRAY)
1032 r = bus_message_open_array(m, c, contents, &array_size);
1033 else if (type == SD_BUS_TYPE_VARIANT)
1034 r = bus_message_open_variant(m, c, contents);
1035 else if (type == SD_BUS_TYPE_STRUCT)
1036 r = bus_message_open_struct(m, c, contents);
1037 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1038 r = bus_message_open_dict_entry(m, c, contents);
1047 /* OK, let's fill it in */
1048 w += m->n_containers++;
1049 w->enclosing = type;
1050 w->signature = signature;
1052 w->array_size = array_size;
1058 int sd_bus_message_close_container(sd_bus_message *m) {
1059 struct bus_container *c;
1065 if (m->n_containers <= 0)
1068 c = message_get_container(m);
1069 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1070 if (c->signature && c->signature[c->index] != 0)
1079 static int message_append_ap(
1090 for (t = types; *t; t++) {
1093 case SD_BUS_TYPE_BYTE: {
1096 x = (uint8_t) va_arg(ap, int);
1097 r = sd_bus_message_append_basic(m, *t, &x);
1101 case SD_BUS_TYPE_BOOLEAN:
1102 case SD_BUS_TYPE_INT32:
1103 case SD_BUS_TYPE_UINT32:
1104 case SD_BUS_TYPE_UNIX_FD: {
1107 /* We assume a boolean is the same as int32_t */
1108 assert_cc(sizeof(int32_t) == sizeof(int));
1110 x = va_arg(ap, uint32_t);
1111 r = sd_bus_message_append_basic(m, *t, &x);
1115 case SD_BUS_TYPE_INT16:
1116 case SD_BUS_TYPE_UINT16: {
1119 x = (uint16_t) va_arg(ap, int);
1120 r = sd_bus_message_append_basic(m, *t, &x);
1124 case SD_BUS_TYPE_INT64:
1125 case SD_BUS_TYPE_UINT64:
1126 case SD_BUS_TYPE_DOUBLE: {
1129 x = va_arg(ap, uint64_t);
1130 r = sd_bus_message_append_basic(m, *t, &x);
1134 case SD_BUS_TYPE_STRING:
1135 case SD_BUS_TYPE_OBJECT_PATH:
1136 case SD_BUS_TYPE_SIGNATURE: {
1139 x = va_arg(ap, const char*);
1140 r = sd_bus_message_append_basic(m, *t, x);
1144 case SD_BUS_TYPE_ARRAY: {
1147 r = signature_element_length(t + 1, &k);
1155 memcpy(s, t + 1, k);
1159 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1163 n = va_arg(ap, unsigned);
1164 for (i = 0; i < n; i++) {
1165 r = message_append_ap(m, s, ap);
1170 r = sd_bus_message_close_container(m);
1176 case SD_BUS_TYPE_VARIANT: {
1179 s = va_arg(ap, const char*);
1183 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1187 r = message_append_ap(m, s, ap);
1191 r = sd_bus_message_close_container(m);
1195 case SD_BUS_TYPE_STRUCT_BEGIN:
1196 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1199 r = signature_element_length(t, &k);
1206 memcpy(s, t + 1, k - 2);
1209 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1215 r = message_append_ap(m, s, ap);
1219 r = sd_bus_message_close_container(m);
1236 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1247 va_start(ap, types);
1248 r = message_append_ap(m, types, ap);
1254 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1260 start = ALIGN_TO((size_t) *rindex, align);
1266 /* Verify that padding is 0 */
1267 for (k = *rindex; k < start; k++)
1268 if (((const uint8_t*) p)[k] != 0)
1272 *r = (uint8_t*) p + start;
1279 static bool message_end_of_array(sd_bus_message *m, size_t index) {
1280 struct bus_container *c;
1284 c = message_get_container(m);
1288 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
1291 static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
1296 if (message_end_of_array(m, *rindex))
1299 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1302 static bool validate_string(const char *s, size_t l) {
1305 /* Check for NUL chars in the string */
1306 if (memchr(s, 0, l))
1309 /* Check for NUL termination */
1313 /* Check if valid UTF8 */
1314 if (!utf8_is_valid(s))
1320 static bool validate_signature(const char *s, size_t l) {
1321 /* Check for NUL chars in the signature */
1322 if (memchr(s, 0, l))
1325 /* Check for NUL termination */
1329 /* Check if valid signature */
1330 if (!signature_is_valid(s, true))
1336 int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1337 struct bus_container *c;
1345 if (!bus_type_is_basic(type))
1348 c = message_get_container(m);
1350 if (!c->signature || c->signature[c->index] == 0)
1353 if (c->signature[c->index] != type)
1358 case SD_BUS_TYPE_STRING:
1359 case SD_BUS_TYPE_OBJECT_PATH: {
1364 r = message_peek_body(m, &rindex, 4, 4, &q);
1368 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1369 r = message_peek_body(m, &rindex, 1, l+1, &q);
1375 if (!validate_string(q, l))
1379 *(const char**) p = q;
1383 case SD_BUS_TYPE_SIGNATURE: {
1388 r = message_peek_body(m, &rindex, 1, 1, &q);
1393 r = message_peek_body(m, &rindex, 1, l+1, &q);
1399 if (!validate_signature(q, l))
1403 *(const char**) p = q;
1410 align = bus_type_get_alignment(type);
1411 sz = bus_type_get_size(type);
1413 r = message_peek_body(m, &m->rindex, align, sz, &q);
1419 case SD_BUS_TYPE_BYTE:
1420 *(uint8_t*) p = *(uint8_t*) q;
1423 case SD_BUS_TYPE_BOOLEAN:
1424 *(int*) p = !!*(uint32_t*) q;
1427 case SD_BUS_TYPE_INT16:
1428 case SD_BUS_TYPE_UINT16:
1429 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1432 case SD_BUS_TYPE_INT32:
1433 case SD_BUS_TYPE_UINT32:
1434 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1437 case SD_BUS_TYPE_INT64:
1438 case SD_BUS_TYPE_UINT64:
1439 case SD_BUS_TYPE_DOUBLE:
1440 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1444 assert_not_reached("Unknown basic type...");
1451 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1457 static int bus_message_enter_array(
1459 struct bus_container *c,
1460 const char *contents,
1461 uint32_t **array_size) {
1472 if (!signature_is_single(contents))
1475 alignment = bus_type_get_alignment(contents[0]);
1479 if (!c->signature || c->signature[c->index] == 0)
1482 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1485 if (!startswith(c->signature + c->index + 1, contents))
1489 r = message_peek_body(m, &rindex, 4, 4, &q);
1493 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > 67108864)
1496 r = message_peek_body(m, &rindex, alignment, 0, NULL);
1502 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1503 c->index += 1 + strlen(contents);
1507 *array_size = (uint32_t*) q;
1512 static int bus_message_enter_variant(
1514 struct bus_container *c,
1515 const char *contents) {
1526 if (!signature_is_single(contents))
1529 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1532 if (!c->signature || c->signature[c->index] == 0)
1535 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1539 r = message_peek_body(m, &rindex, 1, 1, &q);
1544 r = message_peek_body(m, &rindex, 1, l+1, &q);
1550 if (!validate_signature(q, l))
1553 if (!streq(q, contents))
1556 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1564 static int bus_message_enter_struct(
1566 struct bus_container *c,
1567 const char *contents) {
1576 if (!signature_is_valid(contents, false))
1579 if (!c->signature || c->signature[c->index] == 0)
1582 l = strlen(contents);
1584 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1585 !startswith(c->signature + c->index + 1, contents) ||
1586 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1589 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1593 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1594 c->index += 1 + l + 1;
1599 static int bus_message_enter_dict_entry(
1601 struct bus_container *c,
1602 const char *contents) {
1611 if (!signature_is_pair(contents))
1614 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1617 if (!c->signature || c->signature[c->index] == 0)
1620 l = strlen(contents);
1622 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1623 !startswith(c->signature + c->index + 1, contents) ||
1624 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1627 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1631 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1632 c->index += 1 + l + 1;
1637 int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
1638 struct bus_container *c, *w;
1639 uint32_t *array_size = NULL;
1650 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1655 c = message_get_container(m);
1657 if (!c->signature || c->signature[c->index] == 0)
1660 signature = strdup(contents);
1664 if (type == SD_BUS_TYPE_ARRAY)
1665 r = bus_message_enter_array(m, c, contents, &array_size);
1666 else if (type == SD_BUS_TYPE_VARIANT)
1667 r = bus_message_enter_variant(m, c, contents);
1668 else if (type == SD_BUS_TYPE_STRUCT)
1669 r = bus_message_enter_struct(m, c, contents);
1670 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1671 r = bus_message_enter_dict_entry(m, c, contents);
1680 /* OK, let's fill it in */
1681 w += m->n_containers++;
1682 w->enclosing = type;
1683 w->signature = signature;
1685 w->array_size = array_size;
1686 w->begin = m->rindex;
1691 int sd_bus_message_exit_container(sd_bus_message *m) {
1692 struct bus_container *c;
1698 if (m->n_containers <= 0)
1701 c = message_get_container(m);
1702 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
1705 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
1706 if (c->begin + l != m->rindex)
1710 if (c->signature && c->signature[c->index] != 0)
1720 int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
1721 struct bus_container *c;
1729 c = message_get_container(m);
1731 if (!c->signature || c->signature[c->index] == 0)
1734 if (message_end_of_array(m, m->rindex))
1737 if (bus_type_is_basic(c->signature[c->index])) {
1741 *type = c->signature[c->index];
1745 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
1751 r = signature_element_length(c->signature+c->index+1, &l);
1755 sig = strndup(c->signature + c->index + 1, l);
1759 free(m->peeked_signature);
1760 m->peeked_signature = sig;
1766 *type = SD_BUS_TYPE_ARRAY;
1771 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
1772 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
1778 r = signature_element_length(c->signature+c->index, &l);
1783 sig = strndup(c->signature + c->index + 1, l - 2);
1787 free(m->peeked_signature);
1788 m->peeked_signature = sig;
1794 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
1799 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
1805 r = message_peek_body(m, &rindex, 1, 1, &q);
1812 r = message_peek_body(m, &rindex, 1, l+1, &q);
1818 if (!validate_signature(q, l))
1825 *type = SD_BUS_TYPE_VARIANT;
1834 *type = c->enclosing;
1840 int sd_bus_message_rewind(sd_bus_message *m, bool complete) {
1841 struct bus_container *c;
1849 reset_containers(m);
1851 m->root_container.index = 0;
1853 c = message_get_container(m);
1855 c = message_get_container(m);
1858 m->rindex = c->begin;
1861 return !isempty(c->signature);
1864 static int message_read_ap(sd_bus_message *m, const char *types, va_list ap) {
1871 for (t = types; *t; t++) {
1874 case SD_BUS_TYPE_BYTE:
1875 case SD_BUS_TYPE_BOOLEAN:
1876 case SD_BUS_TYPE_INT16:
1877 case SD_BUS_TYPE_UINT16:
1878 case SD_BUS_TYPE_INT32:
1879 case SD_BUS_TYPE_UINT32:
1880 case SD_BUS_TYPE_INT64:
1881 case SD_BUS_TYPE_UINT64:
1882 case SD_BUS_TYPE_DOUBLE:
1883 case SD_BUS_TYPE_STRING:
1884 case SD_BUS_TYPE_OBJECT_PATH:
1885 case SD_BUS_TYPE_SIGNATURE: {
1888 p = va_arg(ap, void*);
1889 r = sd_bus_message_read_basic(m, *t, p);
1893 case SD_BUS_TYPE_ARRAY: {
1896 r = signature_element_length(t + 1, &k);
1904 memcpy(s, t + 1, k);
1908 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
1914 n = va_arg(ap, unsigned);
1915 for (i = 0; i < n; i++) {
1916 r = message_read_ap(m, s, ap);
1921 r = sd_bus_message_exit_container(m);
1927 case SD_BUS_TYPE_VARIANT: {
1930 s = va_arg(ap, const char *);
1934 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
1940 r = message_read_ap(m, s, ap);
1946 r = sd_bus_message_exit_container(m);
1950 case SD_BUS_TYPE_STRUCT_BEGIN:
1951 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1954 r = signature_element_length(t, &k);
1960 memcpy(s, t + 1, k - 2);
1963 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1971 r = message_read_ap(m, s, ap);
1977 r = sd_bus_message_exit_container(m);
1996 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2007 va_start(ap, types);
2008 r = message_read_ap(m, types, ap);
2014 int bus_message_parse(sd_bus_message *m) {
2017 if (m->header->version != 1)
2020 if (m->header->endian != SD_BUS_BIG_ENDIAN &&
2021 m->header->endian != SD_BUS_LITTLE_ENDIAN)
2027 static void setup_iovec(sd_bus_message *m) {
2033 m->iovec[m->n_iovec].iov_base = m->header;
2034 m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
2038 m->iovec[m->n_iovec].iov_base = m->fields;
2039 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
2042 if (m->header->fields_size % 8 != 0) {
2043 static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
2045 m->iovec[m->n_iovec].iov_base = (void*) padding;
2046 m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
2052 m->iovec[m->n_iovec].iov_base = m->body;
2053 m->iovec[m->n_iovec].iov_len = m->header->body_size;
2058 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2066 if (m->n_containers > 0)
2069 /* If there's a non-trivial signature set, then add it in here */
2070 if (!isempty(m->root_container.signature)) {
2071 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, &m->signature);
2077 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2082 m->header->serial = serial;
2090 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
2100 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
2103 int bus_message_dump(sd_bus_message *m) {
2109 printf("Message %p\n"
2116 "\tfields_size=%u\n"
2121 "\tdestination=%s\n"
2124 "\treply_serial=%u\n"
2126 "\terror.message=%s\n"
2134 BUS_MESSAGE_SERIAL(m),
2135 BUS_MESSAGE_FIELDS_SIZE(m),
2136 BUS_MESSAGE_BODY_SIZE(m),
2138 strna(m->interface),
2140 strna(m->destination),
2142 strna(m->signature),
2144 strna(m->error.name),
2145 strna(m->error.message),
2148 r = sd_bus_message_rewind(m, true);
2150 log_error("Failed to rewind: %s", strerror(-r));
2154 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->signature));
2157 _cleanup_free_ char *prefix = NULL;
2158 const char *contents = NULL;
2173 r = sd_bus_message_peek_type(m, &type, &contents);
2175 log_error("Failed to peek type: %s", strerror(-r));
2182 r = sd_bus_message_exit_container(m);
2184 log_error("Failed to exit container: %s", strerror(-r));
2190 prefix = strrep("\t", level);
2194 if (type == SD_BUS_TYPE_ARRAY)
2195 printf("%s} END_ARRAY \n", prefix);
2196 else if (type == SD_BUS_TYPE_VARIANT)
2197 printf("%s} END_VARIANT\n", prefix);
2198 else if (type == SD_BUS_TYPE_STRUCT)
2199 printf("%s} END_STRUCT\n", prefix);
2200 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2201 printf("%s} END_DICT_ENTRY\n", prefix);
2206 prefix = strrep("\t", level);
2210 if (bus_type_is_container(type) > 0) {
2211 r = sd_bus_message_enter_container(m, type, contents);
2213 log_error("Failed to enter container: %s", strerror(-r));
2217 if (type == SD_BUS_TYPE_ARRAY)
2218 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
2219 else if (type == SD_BUS_TYPE_VARIANT)
2220 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
2221 else if (type == SD_BUS_TYPE_STRUCT)
2222 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
2223 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2224 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
2231 r = sd_bus_message_read_basic(m, type, &basic);
2233 log_error("Failed to get basic: %s", strerror(-r));
2239 case SD_BUS_TYPE_BYTE:
2240 printf("%sBYTE: %u\n", prefix, basic.u8);
2243 case SD_BUS_TYPE_BOOLEAN:
2244 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
2247 case SD_BUS_TYPE_INT16:
2248 printf("%sINT16: %i\n", prefix, basic.s16);
2251 case SD_BUS_TYPE_UINT16:
2252 printf("%sUINT16: %u\n", prefix, basic.u16);
2255 case SD_BUS_TYPE_INT32:
2256 printf("%sINT32: %i\n", prefix, basic.s32);
2259 case SD_BUS_TYPE_UINT32:
2260 printf("%sUINT32: %u\n", prefix, basic.u32);
2263 case SD_BUS_TYPE_INT64:
2264 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
2267 case SD_BUS_TYPE_UINT64:
2268 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
2271 case SD_BUS_TYPE_DOUBLE:
2272 printf("%sDOUBLE: %g\n", prefix, basic.d64);
2275 case SD_BUS_TYPE_STRING:
2276 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
2279 case SD_BUS_TYPE_OBJECT_PATH:
2280 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
2283 case SD_BUS_TYPE_SIGNATURE:
2284 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
2287 case SD_BUS_TYPE_UNIX_FD:
2288 printf("%sUNIX_FD: %i\n", prefix, basic.i);
2292 assert_not_reached("Unknown basic type.");
2296 printf("} END_MESSAGE\n");
2300 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
2309 for (i = 0, total = 0; i < m->n_iovec; i++)
2310 total += m->iovec[i].iov_len;
2316 for (i = 0, e = p; i < m->n_iovec; i++)
2317 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);