/* Called with chr_write_lock held. */ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) { SocketChardev *s = SOCKET_CHARDEV(chr); if (s->connected) { int ret = io_channel_send_full(s->ioc, buf, len, s->write_msgfds, s->write_msgfds_num); /* free the written msgfds, no matter what */ if (s->write_msgfds_num) { g_free(s->write_msgfds); s->write_msgfds = 0; s->write_msgfds_num = 0; } if (ret < 0 && errno != EAGAIN) { if (tcp_chr_read_poll(chr) <= 0) { tcp_chr_disconnect(chr); return len; } /* else let the read handler finish it properly */ } return ret; } else { /* XXX: indicate an error ? */ return len; } }
/* Called with chr_write_lock held. */ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) { SocketChardev *s = SOCKET_CHARDEV(chr); if (s->connected) { int ret = io_channel_send_full(s->ioc, buf, len, s->write_msgfds, s->write_msgfds_num); /* free the written msgfds, no matter what */ if (s->write_msgfds_num) { g_free(s->write_msgfds); s->write_msgfds = 0; s->write_msgfds_num = 0; } return ret; } else { /* XXX: indicate an error ? */ return len; } }
int io_channel_send_full(QIOChannel *ioc, const void *buf, size_t len, int *fds, size_t nfds) { size_t offset = 0; while (offset < len) { ssize_t ret = 0; struct iovec iov = { .iov_base = (char *)buf + offset, .iov_len = len - offset }; ret = qio_channel_writev_full( ioc, &iov, 1, fds, nfds, NULL); if (ret == QIO_CHANNEL_ERR_BLOCK) { if (offset) { return offset; } errno = EAGAIN; return -1; } else if (ret < 0) { errno = EINVAL; return -1; } offset += ret; } return offset; } int io_channel_send(QIOChannel *ioc, const void *buf, size_t len) { return io_channel_send_full(ioc, buf, len, NULL, 0); }