chiark / gitweb /
bus: add macro for iterating through body parts of a message
[elogind.git] / src / libsystemd-bus / bus-socket.c
index c68c7bca682791625b4adf05a50833fb75ad0f49..f43b7da05ca651fa158a07e850cf0531f4a840dc 100644 (file)
@@ -58,6 +58,61 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
         }
 }
 
+static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
+        assert(m);
+        assert(p);
+        assert(sz > 0);
+
+        m->iovec[m->n_iovec].iov_base = (void*) p;
+        m->iovec[m->n_iovec].iov_len = sz;
+        m->n_iovec++;
+
+        return 0;
+}
+
+static int bus_message_setup_iovec(sd_bus_message *m) {
+        struct bus_body_part *part;
+        unsigned n, i;
+        int r;
+
+        assert(m);
+        assert(m->sealed);
+
+        if (m->n_iovec > 0)
+                return 0;
+
+        assert(!m->iovec);
+
+        n = 1 + !!m->fields + m->n_body_parts;
+        if (n < ELEMENTSOF(m->iovec_fixed))
+                m->iovec = m->iovec_fixed;
+        else {
+                m->iovec = new(struct iovec, n);
+                if (!m->iovec)
+                        return -ENOMEM;
+        }
+
+        r = append_iovec(m, m->header, sizeof(*m->header));
+        if (r < 0)
+                return r;
+
+        if (m->fields) {
+                r = append_iovec(m, m->fields, ALIGN8(m->header->fields_size));
+                if (r < 0)
+                        return r;
+        }
+
+        MESSAGE_FOREACH_PART(part, i, m)  {
+                r = append_iovec(m, part->data, part->size);
+                if (r < 0)
+                        return r;
+        }
+
+        assert(n == m->n_iovec);
+
+        return 0;
+}
+
 bool bus_socket_auth_needs_write(sd_bus *b) {
 
         unsigned i;
@@ -723,15 +778,20 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
         ssize_t k;
         size_t n;
         unsigned j;
+        int r;
 
         assert(bus);
         assert(m);
         assert(idx);
         assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
 
-        if (*idx >= m->size)
+        if (*idx >= BUS_MESSAGE_SIZE(m))
                 return 0;
 
+        r = bus_message_setup_iovec(m);
+        if (r < 0)
+                return r;
+
         n = m->n_iovec * sizeof(struct iovec);
         iov = alloca(n);
         memcpy(iov, m->iovec, n);
@@ -877,7 +937,7 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
                             CMSG_SPACE(NAME_MAX)]; /*selinux label */
         } control;
         struct cmsghdr *cmsg;
-        bool handle_cmsg;
+        bool handle_cmsg = false;
 
         assert(bus);
         assert(m);
@@ -986,16 +1046,14 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
 int bus_socket_process_opening(sd_bus *b) {
         int error = 0;
         socklen_t slen = sizeof(error);
-        struct pollfd p;
+        struct pollfd p = {
+                .fd = b->output_fd,
+                .events = POLLOUT,
+        };
         int r;
 
-        assert(b);
         assert(b->state == BUS_OPENING);
 
-        zero(p);
-        p.fd = b->output_fd;
-        p.events = POLLOUT;
-
         r = poll(&p, 1, 0);
         if (r < 0)
                 return -errno;