- r = bus_message_from_malloc(bus->rbuffer, size,
- bus->fds, bus->n_fds,
- bus->ucred_valid ? &bus->ucred : NULL,
- bus->label[0] ? bus->label : NULL,
- &t);
- if (r < 0) {
- free(b);
- return r;
- }
-
- bus->rbuffer = b;
- bus->rbuffer_size -= size;
-
- bus->fds = NULL;
- bus->n_fds = 0;
-
- *m = t;
- return 1;
-}
-
-static int message_read(sd_bus *bus, sd_bus_message **m) {
- struct msghdr mh;
- struct iovec iov;
- ssize_t k;
- size_t need;
- int r;
- void *b;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) +
- CMSG_SPACE(sizeof(struct ucred)) +
- CMSG_SPACE(NAME_MAX)]; /*selinux label */
- } control;
- struct cmsghdr *cmsg;
-
- assert(bus);
- assert(m);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- r = message_read_need(bus, &need);
- if (r < 0)
- return r;
-
- if (bus->rbuffer_size >= need)
- return message_make(bus, need, m);
-
- b = realloc(bus->rbuffer, need);
- if (!b)
- return -ENOMEM;
-
- bus->rbuffer = b;
-
- zero(iov);
- iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
- iov.iov_len = need - bus->rbuffer_size;
-
- zero(mh);
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_control = &control;
- mh.msg_controllen = sizeof(control);
-
- k = recvmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
- if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
- if (k == 0)
- return -ECONNRESET;
-
- bus->rbuffer_size += k;
-
- for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- int n, *f;
-
- n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
-
- f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
- if (!f) {
- close_many((int*) CMSG_DATA(cmsg), n);
- return -ENOMEM;
- }
-
- memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
- bus->fds = f;
- bus->n_fds += n;
- } else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_CREDENTIALS &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
-
- memcpy(&bus->ucred, CMSG_DATA(cmsg), sizeof(struct ucred));
- bus->ucred_valid = true;
-
- } else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_SECURITY) {
-
- size_t l;
- l = cmsg->cmsg_len - CMSG_LEN(0);
- memcpy(&bus->label, CMSG_DATA(cmsg), l);
- bus->label[l] = 0;
- }
- }
-
- r = message_read_need(bus, &need);
- if (r < 0)
- return r;
-
- if (bus->rbuffer_size >= need)
- return message_make(bus, need, m);
-
- return 1;
-}
-
-static int dispatch_wqueue(sd_bus *bus) {
- int r, ret = 0;
-
- assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- if (bus->fd < 0)
- return -ENOTCONN;
-
- while (bus->wqueue_size > 0) {
-
- r = message_write(bus, bus->wqueue[0], &bus->windex);
- if (r < 0) {
- sd_bus_close(bus);
- return r;
- } else if (r == 0)
- /* Didn't do anything this time */
- return ret;
- else if (bus->windex >= bus->wqueue[0]->size) {
- /* Fully written. Let's drop the entry from
- * the queue.
- *
- * This isn't particularly optimized, but
- * well, this is supposed to be our worst-case
- * buffer only, and the socket buffer is
- * supposed to be our primary buffer, and if
- * it got full, then all bets are off
- * anyway. */
-
- sd_bus_message_unref(bus->wqueue[0]);
- bus->wqueue_size --;
- memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
- bus->windex = 0;
-
- ret = 1;
- }
- }
-
- return ret;