diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-06-16 18:36:39 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-10-28 18:35:54 +0000 |
commit | 1e3328b3183aa5ba02c0153e1c3d6e49e218f7d9 (patch) | |
tree | 4035e34161847707097a2969e628cb0f3d24346b | |
parent | 76fa00b37a1a19f6546c741b27061a49f59e4edf (diff) |
qemu-char: Add a chr_del_client method to char backends
Add a chr_del_client method to char backends. This makes sense
mostly for TCP, where it means "close the current connection and
then go back to listening for a new one"; the semantics are
as if the remote end had closed the connection.
This could for completeness be supported for other backends
(eg pipe, fd, tty), but this patch only supports it in TCP.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | include/sysemu/char.h | 11 | ||||
-rw-r--r-- | qemu-char.c | 19 |
2 files changed, 26 insertions, 4 deletions
diff --git a/include/sysemu/char.h b/include/sysemu/char.h index 832b7fead4..b6b2785853 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -65,6 +65,7 @@ struct CharDriverState { int (*get_msgfds)(struct CharDriverState *s, int* fds, int num); int (*set_msgfds)(struct CharDriverState *s, int *fds, int num); int (*chr_add_client)(struct CharDriverState *chr, int fd); + int (*chr_del_client)(struct CharDriverState *chr); IOEventHandler *chr_event; IOCanReadHandler *chr_can_read; IOReadHandler *chr_read; @@ -339,6 +340,16 @@ void qemu_chr_add_handlers(CharDriverState *s, void qemu_chr_be_generic_open(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); int qemu_chr_add_client(CharDriverState *s, int fd); + +/** + * @qemu_chr_del_client: + * + * Delete (disconnect) the current client from the char backend, + * as if the remote end had closed itself. This is most useful for TCP + * listening sockets, where it means that we will close the connection to + * the current client but remain listening for new ones. + */ +int qemu_chr_del_client(CharDriverState *s); CharDriverState *qemu_chr_find(const char *name); bool chr_is_ringbuf(const CharDriverState *chr); diff --git a/qemu-char.c b/qemu-char.c index 8623c70964..6f8bb7abd1 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -235,6 +235,11 @@ int qemu_chr_add_client(CharDriverState *s, int fd) return s->chr_add_client ? s->chr_add_client(s, fd) : -1; } +int qemu_chr_del_client(CharDriverState *s) +{ + return s->chr_del_client ? s->chr_del_client(s) : -1; +} + void qemu_chr_accept_input(CharDriverState *s) { if (s->chr_accept_input) @@ -2676,10 +2681,14 @@ static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond) return g_io_create_watch(s->chan, cond); } -static void tcp_chr_disconnect(CharDriverState *chr) +static int tcp_chr_del_client(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; + if (!s->connected) { + return -1; + } + s->connected = 0; if (s->listen_chan) { s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, @@ -2691,6 +2700,7 @@ static void tcp_chr_disconnect(CharDriverState *chr) closesocket(s->fd); s->fd = -1; qemu_chr_be_event(chr, CHR_EVENT_CLOSED); + return 0; } static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) @@ -2702,7 +2712,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) if (cond & G_IO_HUP) { /* connection closed */ - tcp_chr_disconnect(chr); + tcp_chr_del_client(chr); return TRUE; } @@ -2715,7 +2725,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) size = tcp_chr_recv(chr, (void *)buf, len); if (size == 0) { /* connection closed */ - tcp_chr_disconnect(chr); + tcp_chr_del_client(chr); } else if (size > 0) { if (s->do_telnetopt) tcp_chr_process_IAC_bytes(chr, s, buf, &size); @@ -2738,7 +2748,7 @@ static int tcp_chr_sync_read(CharDriverState *chr, const uint8_t *buf, int len) size = tcp_chr_recv(chr, (void *) buf, len); if (size == 0) { /* connection closed */ - tcp_chr_disconnect(chr); + tcp_chr_del_client(chr); } return size; @@ -2950,6 +2960,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay, chr->get_msgfds = tcp_get_msgfds; chr->set_msgfds = tcp_set_msgfds; chr->chr_add_client = tcp_chr_add_client; + chr->chr_del_client = tcp_chr_del_client; chr->chr_add_watch = tcp_chr_add_watch; chr->chr_update_read_handler = tcp_chr_update_read_handler; /* be isn't opened until we get a connection */ |