static void ubus_msg_dequeue(struct ubus_client *cl) { struct ubus_msg_buf *ub = ubus_msg_head(cl); if (!ub) return; ubus_msg_free(ub); cl->txq_ofs = 0; cl->tx_queue[cl->txq_cur] = NULL; cl->txq_cur = (cl->txq_cur + 1) % ARRAY_SIZE(cl->tx_queue); }
/* takes the msgbuf reference */ void ubus_msg_send(struct ubus_client *cl, struct ubus_msg_buf *ub, bool free) { int written; if (!cl->tx_queue[cl->txq_cur]) { written = ubus_msg_writev(cl->sock.fd, ub, 0); if (written >= ub->len + sizeof(ub->hdr)) goto out; if (written < 0) written = 0; cl->txq_ofs = written; /* get an event once we can write to the socket again */ uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER); } ubus_msg_enqueue(cl, ub); out: if (free) ubus_msg_free(ub); }
static int ubus_msg_writev(int fd, struct ubus_msg_buf *ub, int offset) { static struct iovec iov[2]; static struct { struct cmsghdr h; int fd; } fd_buf = { .h = { .cmsg_len = sizeof(fd_buf), .cmsg_level = SOL_SOCKET, .cmsg_type = SCM_RIGHTS, }, }; struct msghdr msghdr = { .msg_iov = iov, .msg_iovlen = ARRAY_SIZE(iov), .msg_control = &fd_buf, .msg_controllen = sizeof(fd_buf), }; fd_buf.fd = ub->fd; if (ub->fd < 0) { msghdr.msg_control = NULL; msghdr.msg_controllen = 0; } if (offset < sizeof(ub->hdr)) { iov[0].iov_base = ((char *) &ub->hdr) + offset; iov[0].iov_len = sizeof(ub->hdr) - offset; iov[1].iov_base = (char *) ub->data; iov[1].iov_len = ub->len; return sendmsg(fd, &msghdr, 0); } else { offset -= sizeof(ub->hdr); return write(fd, ((char *) ub->data) + offset, ub->len - offset); } } static void ubus_msg_enqueue(struct ubus_client *cl, struct ubus_msg_buf *ub) { if (cl->tx_queue[cl->txq_tail]) return; cl->tx_queue[cl->txq_tail] = ubus_msg_ref(ub); cl->txq_tail = (cl->txq_tail + 1) % ARRAY_SIZE(cl->tx_queue); } /* takes the msgbuf reference */ void ubus_msg_send(struct ubus_client *cl, struct ubus_msg_buf *ub, bool free) { int written; if (!cl->tx_queue[cl->txq_cur]) { written = ubus_msg_writev(cl->sock.fd, ub, 0); if (written >= ub->len + sizeof(ub->hdr)) goto out; if (written < 0) written = 0; cl->txq_ofs = written; /* get an event once we can write to the socket again */ uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER); } ubus_msg_enqueue(cl, ub); out: if (free) ubus_msg_free(ub); }