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/>.
26 #include "bus-message.h"
28 #include "bus-internal.h"
30 #include "bus-signature.h"
32 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
34 static void message_free(sd_bus_message *m) {
48 for (i = 0; i < m->n_fds; i++)
49 close_nointr_nofail(m->fds[i]);
51 for (i = 0; i < m->n_containers; i++)
52 free(m->sub_containers[i].signature);
54 free(m->sub_containers);
58 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
66 start = ALIGN_TO((size_t) *sz, align);
70 return (uint8_t*) *p + start;
72 if (n > (size_t) ((uint32_t) -1))
79 /* Zero out padding */
81 memset((uint8_t*) k + *sz, 0, start - *sz);
86 return (uint8_t*) k + start;
89 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
95 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
100 /* Adjust quick access pointers */
103 m->path = (const char*) m->fields + (m->path - (const char*) o);
105 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
107 m->member = (const char*) m->fields + (m->member - (const char*) o);
109 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
111 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
113 m->signature = (const char*) m->fields + (m->signature - (const char*) o);
115 m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
118 m->free_fields = true;
123 static int message_append_field_string(
136 if (l > (size_t) (uint32_t) -1)
139 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
140 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
149 ((uint32_t*) p)[1] = l;
150 memcpy(p + 8, s, l + 1);
153 *ret = (const char*) p + 8;
158 static int message_append_field_signature(
173 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
174 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
180 p[2] = SD_BUS_TYPE_SIGNATURE;
183 memcpy(p + 5, s, l + 1);
186 *ret = (const char*) p + 5;
191 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
196 /* field id byte + signature length + signature 'u' + NUL + value */
197 p = message_extend_fields(m, 8, 4 + 4);
203 p[2] = SD_BUS_TYPE_UINT32;
206 ((uint32_t*) p)[1] = x;
211 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
214 m = malloc0(ALIGN(sizeof(struct sd_bus_message)) + sizeof(struct bus_header));
219 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
221 #if __BYTE_ORDER == __BIG_ENDIAN
222 m->header->endian = SD_BUS_BIG_ENDIAN;
224 m->header->endian = SD_BUS_LITTLE_ENDIAN;
226 m->header->type = type;
227 m->header->version = bus ? bus->message_version : 1;
232 int sd_bus_message_new_signal(
235 const char *interface,
237 sd_bus_message **m) {
249 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
253 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
256 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
259 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
267 sd_bus_message_unref(t);
271 int sd_bus_message_new_method_call(
273 const char *destination,
275 const char *interface,
277 sd_bus_message **m) {
287 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
291 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
294 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
299 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
305 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
318 int sd_bus_message_new_method_return(
320 sd_bus_message *call,
321 sd_bus_message **m) {
328 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
331 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_RETURN);
335 t->reply_serial = BUS_MESSAGE_SERIAL(call);
336 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
341 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
354 int sd_bus_message_new_method_error(
356 sd_bus_message *call,
357 const sd_bus_error *e,
358 sd_bus_message **m) {
365 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
372 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_ERROR);
376 t->reply_serial = BUS_MESSAGE_SERIAL(call);
377 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
382 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
387 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
392 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
405 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
409 assert(m->n_ref > 0);
415 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
419 assert(m->n_ref > 0);
428 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
434 *type = m->header->type;
438 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
443 if (m->header->serial == 0)
446 *serial = BUS_MESSAGE_SERIAL(m);
450 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
455 if (m->reply_serial == 0)
458 *serial = m->reply_serial;
462 int sd_bus_message_get_no_reply(sd_bus_message *m) {
466 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
469 const char *sd_bus_message_get_path(sd_bus_message *m) {
476 const char *sd_bus_message_get_interface(sd_bus_message *m) {
483 const char *sd_bus_message_get_member(sd_bus_message *m) {
489 const char *sd_bus_message_get_destination(sd_bus_message *m) {
493 return m->destination;
496 const char *sd_bus_message_get_sender(sd_bus_message *m) {
503 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
507 if (!sd_bus_error_is_set(&m->error))
513 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
523 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
533 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
543 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
553 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
557 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
560 if (interface && (!m->interface || !streq(m->interface, interface)))
563 if (member && (!m->member || !streq(m->member, member)))
569 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
573 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
576 if (interface && (!m->interface || !streq(m->interface, interface)))
579 if (member && (!m->member || !streq(m->member, member)))
585 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
589 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
592 if (name && (!m->error.name || !streq(m->error.name, name)))
598 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
603 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
607 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
609 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
614 static struct bus_container *message_get_container(sd_bus_message *m) {
617 if (m->n_containers == 0)
618 return &m->root_container;
620 assert(m->sub_containers);
621 return m->sub_containers + m->n_containers - 1;
624 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
627 struct bus_container *c;
632 added = m->header->body_size;
634 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
638 added = m->header->body_size - added;
640 for (c = m->sub_containers; c < m->sub_containers + m->n_containers; c++)
642 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
643 *c->array_size += added;
647 if (m->error.message)
648 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
656 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
657 struct bus_container *c;
658 size_t sz, align, nindex;
667 if (!bus_type_is_basic(type))
670 c = message_get_container(m);
672 if (c->signature && c->signature[c->index]) {
673 /* Container signature is already set */
675 if (c->signature[c->index] != type)
678 /* Maybe we can append to the signature? But only if this is the top-level container*/
679 if (c->enclosing != 0)
682 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
687 nindex = c->index + 1;
691 case SD_BUS_TYPE_STRING:
692 case SD_BUS_TYPE_OBJECT_PATH:
694 sz = 4 + strlen(p) + 1;
697 case SD_BUS_TYPE_SIGNATURE:
699 sz = 1 + strlen(p) + 1;
702 case SD_BUS_TYPE_BOOLEAN:
705 assert_cc(sizeof(int) == sizeof(uint32_t));
712 align = bus_type_get_alignment(type);
713 sz = bus_type_get_size(type);
720 a = message_extend_body(m, align, sz);
722 /* Truncate extended signature again */
724 c->signature[c->index] = 0;
729 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
730 *(uint32_t*) a = sz - 5;
731 memcpy((uint8_t*) a + 4, p, sz - 4);
734 *stored = (const uint8_t*) a + 4;
736 } else if (type == SD_BUS_TYPE_SIGNATURE) {
737 *(uint8_t*) a = sz - 1;
738 memcpy((uint8_t*) a + 1, p, sz - 1);
741 *stored = (const uint8_t*) a + 1;
750 if (c->enclosing != SD_BUS_TYPE_ARRAY)
756 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
757 return message_append_basic(m, type, p, NULL);
760 static int bus_message_open_array(
762 struct bus_container *c,
763 const char *contents,
764 uint32_t **array_size) {
777 if (!signature_is_single(contents))
780 alignment = bus_type_get_alignment(contents[0]);
784 if (c->signature && c->signature[c->index]) {
786 /* Verify the existing signature */
788 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
791 if (!startswith(c->signature + c->index + 1, contents))
794 nindex = c->index + 1 + strlen(contents);
796 if (c->enclosing != 0)
799 /* Extend the existing signature */
801 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
805 nindex = e - c->signature;
808 saved = m->header->body_size;
809 a = message_extend_body(m, 4, 4);
811 /* Truncate extended signature again */
813 c->signature[c->index] = 0;
819 if (!message_extend_body(m, alignment, 0)) {
820 /* Add alignment between size and first element */
822 c->signature[c->index] = 0;
824 m->header->body_size = saved;
828 if (c->enclosing != SD_BUS_TYPE_ARRAY)
831 /* m->body might have changed so let's readjust a */
832 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
839 static int bus_message_open_variant(
841 struct bus_container *c,
842 const char *contents) {
852 if (!signature_is_single(contents))
855 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
858 if (c->signature && c->signature[c->index]) {
860 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
864 if (c->enclosing != 0)
867 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
872 nindex = c->index + 1;
874 l = strlen(contents);
875 a = message_extend_body(m, 1, 1 + l + 1);
877 /* Truncate extended signature again */
879 c->signature[c->index] = 0;
885 memcpy((uint8_t*) a + 1, contents, l + 1);
887 if (c->enclosing != SD_BUS_TYPE_ARRAY)
893 static int bus_message_open_struct(
895 struct bus_container *c,
896 const char *contents) {
905 if (!signature_is_valid(contents, false))
908 if (c->signature && c->signature[c->index]) {
911 l = strlen(contents);
913 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
914 !startswith(c->signature + c->index + 1, contents) ||
915 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
918 nindex = c->index + 1 + l + 1;
920 if (c->enclosing != 0)
923 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
927 nindex = e - c->signature;
930 /* Align contents to 8 byte boundary */
931 if (!message_extend_body(m, 8, 0)) {
933 c->signature[c->index] = 0;
938 if (c->enclosing != SD_BUS_TYPE_ARRAY)
944 static int bus_message_open_dict_entry(
946 struct bus_container *c,
947 const char *contents) {
955 if (!signature_is_pair(contents))
958 if (c->enclosing != SD_BUS_TYPE_ARRAY)
961 if (c->signature && c->signature[c->index]) {
964 l = strlen(contents);
966 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
967 !startswith(c->signature + c->index + 1, contents) ||
968 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
971 nindex = c->index + 1 + l + 1;
975 /* Align contents to 8 byte boundary */
976 if (!message_extend_body(m, 8, 0))
979 if (c->enclosing != SD_BUS_TYPE_ARRAY)
985 int sd_bus_message_open_container(
988 const char *contents) {
990 struct bus_container *c, *sub;
992 uint32_t *array_size = NULL;
1002 /* Make sure we have space for one more container */
1003 sub = realloc(m->sub_containers, sizeof(struct bus_container) * (m->n_containers + 1));
1007 m->sub_containers = sub;
1009 c = message_get_container(m);
1011 signature = strdup(contents);
1015 if (type == SD_BUS_TYPE_ARRAY)
1016 r = bus_message_open_array(m, c, contents, &array_size);
1017 else if (type == SD_BUS_TYPE_VARIANT)
1018 r = bus_message_open_variant(m, c, contents);
1019 else if (type == SD_BUS_TYPE_STRUCT)
1020 r = bus_message_open_struct(m, c, contents);
1021 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1022 r = bus_message_open_dict_entry(m, c, contents);
1031 /* OK, let's fill it in */
1032 sub += m->n_containers++;
1034 sub->enclosing = type;
1035 sub->signature = signature;
1037 sub->array_size = array_size;
1042 int sd_bus_message_close_container(sd_bus_message *m) {
1043 struct bus_container *c;
1049 if (m->n_containers <= 0)
1052 c = message_get_container(m);
1057 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1058 if (c->signature[c->index] != 0)
1067 static int message_append_ap(
1078 for (t = types; *t; t++) {
1081 case SD_BUS_TYPE_BYTE: {
1084 x = (uint8_t) va_arg(ap, int);
1085 r = sd_bus_message_append_basic(m, *t, &x);
1089 case SD_BUS_TYPE_BOOLEAN:
1090 case SD_BUS_TYPE_INT32:
1091 case SD_BUS_TYPE_UINT32: {
1094 x = va_arg(ap, uint32_t);
1095 r = sd_bus_message_append_basic(m, *t, &x);
1099 case SD_BUS_TYPE_INT16:
1100 case SD_BUS_TYPE_UINT16: {
1103 x = (uint16_t) va_arg(ap, int);
1104 r = sd_bus_message_append_basic(m, *t, &x);
1108 case SD_BUS_TYPE_INT64:
1109 case SD_BUS_TYPE_UINT64:
1110 case SD_BUS_TYPE_DOUBLE: {
1113 x = va_arg(ap, uint64_t);
1114 r = sd_bus_message_append_basic(m, *t, &x);
1118 case SD_BUS_TYPE_STRING:
1119 case SD_BUS_TYPE_OBJECT_PATH:
1120 case SD_BUS_TYPE_SIGNATURE: {
1123 x = va_arg(ap, const char*);
1124 r = sd_bus_message_append_basic(m, *t, x);
1128 case SD_BUS_TYPE_UNIX_FD: {
1131 x = va_arg(ap, int);
1132 r = sd_bus_message_append_basic(m, *t, &x);
1136 case SD_BUS_TYPE_ARRAY: {
1140 r = signature_element_length(t + 1, &k);
1147 memcpy(s, t + 1, k);
1151 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1155 n = va_arg(ap, unsigned);
1157 for (i = 0; i < n; i++) {
1158 r = message_append_ap(m, s, ap);
1163 r = sd_bus_message_close_container(m);
1169 case SD_BUS_TYPE_VARIANT: {
1172 s = va_arg(ap, const char*);
1176 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1180 r = message_append_ap(m, s, ap);
1184 r = sd_bus_message_close_container(m);
1188 case SD_BUS_TYPE_STRUCT_BEGIN:
1189 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1192 r = signature_element_length(t, &k);
1199 memcpy(s, t + 1, k - 2);
1202 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1208 r = message_append_ap(m, s, ap);
1212 r = sd_bus_message_close_container(m);
1229 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1240 va_start(ap, types);
1241 r = message_append_ap(m, types, ap);
1247 int sd_bus_message_read_type(sd_bus_message *m, char *type, char *element, size_t *length) {
1251 int sd_bus_message_read_basic(sd_bus_message *m, char type, char element, const void **p, size_t *length) {
1255 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
1259 int message_parse(sd_bus_message *m) {
1262 if (m->header->version != 1)
1265 if (m->header->endian != SD_BUS_BIG_ENDIAN &&
1266 m->header->endian != SD_BUS_LITTLE_ENDIAN)
1272 static void setup_iovec(sd_bus_message *m) {
1278 m->iovec[m->n_iovec].iov_base = m->header;
1279 m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
1283 m->iovec[m->n_iovec].iov_base = m->fields;
1284 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
1287 if (m->header->fields_size % 8 != 0) {
1288 static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
1290 m->iovec[m->n_iovec].iov_base = (void*) padding;
1291 m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
1297 m->iovec[m->n_iovec].iov_base = m->body;
1298 m->iovec[m->n_iovec].iov_len = m->header->body_size;
1303 int message_seal(sd_bus_message *m, uint64_t serial) {
1311 if (m->n_containers > 0)
1314 /* If there's a non-trivial signature set, then add it in here */
1315 if (!isempty(m->root_container.signature)) {
1316 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, &m->signature);
1322 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
1327 m->header->serial = serial;
1335 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
1345 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
1348 void message_dump(sd_bus_message *m) {
1350 log_info("Message %p\n"
1357 "\tfields_size=%u\n"
1362 "\tdestination=%s\n"
1365 "\treply_serial=%u\n"
1367 "\terror.message=%s\n"
1375 BUS_MESSAGE_SERIAL(m),
1376 BUS_MESSAGE_FIELDS_SIZE(m),
1377 BUS_MESSAGE_BODY_SIZE(m),
1379 strna(m->interface),
1381 strna(m->destination),
1383 strna(m->signature),
1385 strna(m->error.name),
1386 strna(m->error.message),
1390 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
1399 for (i = 0, total = 0; i < m->n_iovec; i++)
1400 total += m->iovec[i].iov_len;
1406 for (i = 0, e = p; i < m->n_iovec; i++)
1407 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);