|
|
4a2fec |
From d467ff7abd1aa30dca064883071bdd74d238567e Mon Sep 17 00:00:00 2001
|
|
|
4a2fec |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
4a2fec |
Date: Wed, 20 Dec 2017 17:56:55 +0100
|
|
|
4a2fec |
Subject: [PATCH 15/42] io: simplify websocket ping reply handling
|
|
|
4a2fec |
|
|
|
4a2fec |
RH-Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
4a2fec |
Message-id: <20171220175702.29663-14-berrange@redhat.com>
|
|
|
4a2fec |
Patchwork-id: 78465
|
|
|
4a2fec |
O-Subject: [RHV-7.5 qemu-kvm-rhev PATCH v2 13/20] io: simplify websocket ping reply handling
|
|
|
4a2fec |
Bugzilla: 1518649
|
|
|
4a2fec |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
4a2fec |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
4a2fec |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
4a2fec |
|
|
|
4a2fec |
We must ensure we don't get flooded with ping replies if the outbound
|
|
|
4a2fec |
channel is slow. Currently we do this by keeping the ping reply in a
|
|
|
4a2fec |
separate temporary buffer and only writing it if the encoutput buffer
|
|
|
4a2fec |
is completely empty. This is overly pessimistic, as it is reasonable
|
|
|
4a2fec |
to add a ping reply to the encoutput buffer even if it has previous
|
|
|
4a2fec |
data in it, as long as that previous data doesn't include a ping
|
|
|
4a2fec |
reply.
|
|
|
4a2fec |
|
|
|
4a2fec |
To track this better, put the ping reply directly into the encoutput
|
|
|
4a2fec |
buffer, and then record the size of encoutput at this time in
|
|
|
4a2fec |
pong_remain. As we write encoutput to the underlying channel, we
|
|
|
4a2fec |
can decrement the pong_remain counter. Once it hits zero, we can
|
|
|
4a2fec |
accept further ping replies for transmission.
|
|
|
4a2fec |
|
|
|
4a2fec |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
4a2fec |
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
|
|
4a2fec |
(cherry picked from commit 57b0cdf152b7266e68bfa3e84635d4bdb64ef2cd)
|
|
|
4a2fec |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
4a2fec |
---
|
|
|
4a2fec |
include/io/channel-websock.h | 2 +-
|
|
|
4a2fec |
io/channel-websock.c | 28 +++++++++++++++-------------
|
|
|
4a2fec |
2 files changed, 16 insertions(+), 14 deletions(-)
|
|
|
4a2fec |
|
|
|
4a2fec |
diff --git a/include/io/channel-websock.h b/include/io/channel-websock.h
|
|
|
4a2fec |
index ff32d86..3762707 100644
|
|
|
4a2fec |
--- a/include/io/channel-websock.h
|
|
|
4a2fec |
+++ b/include/io/channel-websock.h
|
|
|
4a2fec |
@@ -60,8 +60,8 @@ struct QIOChannelWebsock {
|
|
|
4a2fec |
Buffer encoutput;
|
|
|
4a2fec |
Buffer rawinput;
|
|
|
4a2fec |
Buffer rawoutput;
|
|
|
4a2fec |
- Buffer ping_reply;
|
|
|
4a2fec |
size_t payload_remain;
|
|
|
4a2fec |
+ size_t pong_remain;
|
|
|
4a2fec |
QIOChannelWebsockMask mask;
|
|
|
4a2fec |
guint io_tag;
|
|
|
4a2fec |
Error *io_err;
|
|
|
4a2fec |
diff --git a/io/channel-websock.c b/io/channel-websock.c
|
|
|
4a2fec |
index 04bcc05..6083f74 100644
|
|
|
4a2fec |
--- a/io/channel-websock.c
|
|
|
4a2fec |
+++ b/io/channel-websock.c
|
|
|
4a2fec |
@@ -825,11 +825,14 @@ static int qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
|
|
|
4a2fec |
}
|
|
|
4a2fec |
return -1;
|
|
|
4a2fec |
} else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_PING) {
|
|
|
4a2fec |
- /* ping frames produce an immediate reply */
|
|
|
4a2fec |
- buffer_reset(&ioc->ping_reply);
|
|
|
4a2fec |
- qio_channel_websock_encode_buffer(
|
|
|
4a2fec |
- ioc, &ioc->ping_reply, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
|
|
|
4a2fec |
- &ioc->encinput);
|
|
|
4a2fec |
+ /* ping frames produce an immediate reply, as long as we've not still
|
|
|
4a2fec |
+ * got a previous pong queued, in which case we drop the new pong */
|
|
|
4a2fec |
+ if (ioc->pong_remain == 0) {
|
|
|
4a2fec |
+ qio_channel_websock_encode_buffer(
|
|
|
4a2fec |
+ ioc, &ioc->encoutput, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
|
|
|
4a2fec |
+ &ioc->encinput);
|
|
|
4a2fec |
+ ioc->pong_remain = ioc->encoutput.offset;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
} /* pong frames are ignored */
|
|
|
4a2fec |
|
|
|
4a2fec |
if (payload_len) {
|
|
|
4a2fec |
@@ -888,7 +891,6 @@ static void qio_channel_websock_finalize(Object *obj)
|
|
|
4a2fec |
buffer_free(&ioc->encoutput);
|
|
|
4a2fec |
buffer_free(&ioc->rawinput);
|
|
|
4a2fec |
buffer_free(&ioc->rawoutput);
|
|
|
4a2fec |
- buffer_free(&ioc->ping_reply);
|
|
|
4a2fec |
object_unref(OBJECT(ioc->master));
|
|
|
4a2fec |
if (ioc->io_tag) {
|
|
|
4a2fec |
g_source_remove(ioc->io_tag);
|
|
|
4a2fec |
@@ -946,12 +948,7 @@ static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc,
|
|
|
4a2fec |
ssize_t ret;
|
|
|
4a2fec |
ssize_t done = 0;
|
|
|
4a2fec |
|
|
|
4a2fec |
- /* ping replies take priority over binary data */
|
|
|
4a2fec |
- if (!ioc->ping_reply.offset) {
|
|
|
4a2fec |
- qio_channel_websock_encode(ioc);
|
|
|
4a2fec |
- } else if (!ioc->encoutput.offset) {
|
|
|
4a2fec |
- buffer_move_empty(&ioc->encoutput, &ioc->ping_reply);
|
|
|
4a2fec |
- }
|
|
|
4a2fec |
+ qio_channel_websock_encode(ioc);
|
|
|
4a2fec |
|
|
|
4a2fec |
while (ioc->encoutput.offset > 0) {
|
|
|
4a2fec |
ret = qio_channel_write(ioc->master,
|
|
|
4a2fec |
@@ -968,6 +965,11 @@ static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc,
|
|
|
4a2fec |
}
|
|
|
4a2fec |
buffer_advance(&ioc->encoutput, ret);
|
|
|
4a2fec |
done += ret;
|
|
|
4a2fec |
+ if (ioc->pong_remain < ret) {
|
|
|
4a2fec |
+ ioc->pong_remain = 0;
|
|
|
4a2fec |
+ } else {
|
|
|
4a2fec |
+ ioc->pong_remain -= ret;
|
|
|
4a2fec |
+ }
|
|
|
4a2fec |
}
|
|
|
4a2fec |
return done;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
@@ -1026,7 +1028,7 @@ static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc)
|
|
|
4a2fec |
return;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
|
|
|
4a2fec |
- if (ioc->encoutput.offset || ioc->ping_reply.offset) {
|
|
|
4a2fec |
+ if (ioc->encoutput.offset) {
|
|
|
4a2fec |
cond |= G_IO_OUT;
|
|
|
4a2fec |
}
|
|
|
4a2fec |
if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER &&
|
|
|
4a2fec |
--
|
|
|
4a2fec |
1.8.3.1
|
|
|
4a2fec |
|