diff options
author | nicm <nicm> | 2015-11-14 09:41:06 +0000 |
---|---|---|
committer | nicm <nicm> | 2015-11-14 09:41:06 +0000 |
commit | c56b81a2ce815f6d289232f20bb6e07cfd0e36ec (patch) | |
tree | 7a018a8f9d4354684ad5748e4d218fd8d3273fc5 /server-client.c | |
parent | 908e6bb68f127f2bdf0c15ac25dde9ccc06e9104 (diff) | |
download | rtmux-c56b81a2ce815f6d289232f20bb6e07cfd0e36ec.tar.gz rtmux-c56b81a2ce815f6d289232f20bb6e07cfd0e36ec.tar.bz2 rtmux-c56b81a2ce815f6d289232f20bb6e07cfd0e36ec.zip |
Push stdout and stderr to clients more aggressively, and add an event to
continue if the send fails.
Diffstat (limited to 'server-client.c')
-rw-r--r-- | server-client.c | 90 |
1 files changed, 87 insertions, 3 deletions
diff --git a/server-client.c b/server-client.c index fedc93bd..645492d1 100644 --- a/server-client.c +++ b/server-client.c @@ -1035,9 +1035,6 @@ server_client_dispatch(struct imsg *imsg, void *arg) server_client_dispatch_shell(c); break; } - - server_push_stdout(c); - server_push_stderr(c); } /* Handle command message. */ @@ -1214,3 +1211,90 @@ server_client_dispatch_shell(struct client *c) proc_kill_peer(c->peer); } + +/* Event callback to push more stdout data if any left. */ +static void +server_client_stdout_cb(unused int fd, unused short events, void *arg) +{ + struct client *c = arg; + + if (~c->flags & CLIENT_DEAD) + server_client_push_stdout(c); + server_client_unref(c); +} + +/* Push stdout to client if possible. */ +void +server_client_push_stdout(struct client *c) +{ + struct msg_stdout_data data; + size_t sent, left; + + left = EVBUFFER_LENGTH(c->stdout_data); + while (left != 0) { + sent = left; + if (sent > sizeof data.data) + sent = sizeof data.data; + memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent); + data.size = sent; + + if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0) + break; + evbuffer_drain(c->stdout_data, sent); + + left = EVBUFFER_LENGTH(c->stdout_data); + log_debug("%s: client %p, sent %zu, left %zu", __func__, c, + sent, left); + } + if (left != 0) { + c->references++; + event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL); + log_debug("%s: client %p, queued", __func__, c); + } +} + +/* Event callback to push more stderr data if any left. */ +static void +server_client_stderr_cb(unused int fd, unused short events, void *arg) +{ + struct client *c = arg; + + if (~c->flags & CLIENT_DEAD) + server_client_push_stderr(c); + server_client_unref(c); +} + +/* Push stderr to client if possible. */ +void +server_client_push_stderr(struct client *c) +{ + struct msg_stderr_data data; + size_t sent, left; + + if (c->stderr_data == c->stdout_data) { + server_client_push_stdout(c); + return; + } + + left = EVBUFFER_LENGTH(c->stderr_data); + while (left != 0) { + sent = left; + if (sent > sizeof data.data) + sent = sizeof data.data; + memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent); + data.size = sent; + + if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0) + break; + evbuffer_drain(c->stderr_data, sent); + + left = EVBUFFER_LENGTH(c->stderr_data); + log_debug("%s: client %p, sent %zu, left %zu", __func__, c, + sent, left); + } + if (left != 0) { + c->references++; + event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL); + log_debug("%s: client %p, queued", __func__, c); + } +} |