This patch allows switching from the standard recv to recvmsg for a qemu char device. Switching allows file descriptors to be passed with SCM_RIGHTS to a qemu process. Instead of receiving a buffer of data the recvmsg call back is passed a 'struct msghdr'. The patch also adds a function to add an eventfd as qemu char device. Perhaps this should be a separate patch. This is not an elegant solution to supporting recvmsg so suggestions are especially welcome. --- qemu-char.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-char.h | 8 ++++++ 2 files changed, 80 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..c1620c2 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) s->chr_read(s->handler_opaque, buf, len); } +void qemu_chr_recvmsg(CharDriverState *s, struct msghdr *msg, int flags) +{ + s->chr_read(s->handler_opaque, msg, flags); +} + void qemu_chr_accept_input(CharDriverState *s) { if (s->chr_accept_input) @@ -1652,6 +1657,7 @@ static CharDriverState *qemu_chr_open_win_pipe(const char *filename) WinCharState *s; chr = qemu_mallocz(sizeof(CharDriverState)); + s = qemu_mallocz(sizeof(WinCharState)); chr->opaque = s; chr->chr_write = win_chr_write; @@ -1937,6 +1943,72 @@ static void tcp_chr_read(void *opaque) } } +/* this is a new function that will replace tcp_chr_read (which calls recv) + * with this one that calls recvmsg instead when we want to use recvmsg */ +static void tcp_chr_recvmsg(void *opaque) +{ + CharDriverState *chr = opaque; + TCPCharDriver *s = chr->opaque; + struct msghdr msg; + uint8_t buf[1024]; + int len, size; + char control[CMSG_SPACE(RECVMSG_MAX)]; + struct iovec iov[8]; + + printf("inside tcp_chr_recvmsg\n"); + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + msg.msg_flags = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + iov[0].iov_base = buf; + iov[0].iov_len = 1024; + + if (!s->connected || s->max_size <= 0) + return; + len = sizeof(control); + if (len > s->max_size) + len = s->max_size; +// size = recv(s->fd, buf, len, 0); + printf("calling recvmsg\n"); + size = recvmsg(s->fd, &msg, 0); + if (size == 0) { + /* connection closed */ + s->connected = 0; + if (s->listen_fd >= 0) { + qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); + } + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + closesocket(s->fd); + s->fd = -1; + } else if (size > 0) { + if (s->do_telnetopt) + tcp_chr_process_IAC_bytes(chr, s, buf, &size); + if (size > 0) + qemu_chr_recvmsg(chr, &msg, 0); + } + + +} + +void tcp_switch_to_recvmsg_handlers(void *opaque) +{ + CharDriverState *chr = opaque; + TCPCharDriver *s = chr->opaque; + + qemu_set_fd_handler2(s->fd, tcp_chr_read_poll, + tcp_chr_recvmsg, NULL, chr); +} + +CharDriverState *qemu_chr_open_eventfd(int eventfd){ + + return qemu_chr_open_fd(eventfd, eventfd); + +} + static void tcp_chr_connect(void *opaque) { CharDriverState *chr = opaque; diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..5fe6c43 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -44,6 +44,8 @@ typedef struct { #define CHR_TIOCM_DTR 0x002 #define CHR_TIOCM_RTS 0x004 +#define RECVMSG_MAX 1024 + typedef void IOEventHandler(void *opaque, int event); struct CharDriverState { @@ -84,6 +86,12 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); +/* function to change tcp_chr_read to tcp_chr_recvmsg */ +void tcp_switch_to_recvmsg_handlers(void *opaque); + +/* add an eventfd to the qemu devices that are polled */ +CharDriverState *qemu_chr_open_eventfd(int eventfd); + extern int term_escape_char; /* async I/O support */ -- 1.6.0.6 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html