aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/io/channel-websock.h2
-rw-r--r--io/channel-websock.c28
2 files changed, 16 insertions, 14 deletions
diff --git a/include/io/channel-websock.h b/include/io/channel-websock.h
index ff32d8651b..3762707b9c 100644
--- a/include/io/channel-websock.h
+++ b/include/io/channel-websock.h
@@ -60,8 +60,8 @@ struct QIOChannelWebsock {
Buffer encoutput;
Buffer rawinput;
Buffer rawoutput;
- Buffer ping_reply;
size_t payload_remain;
+ size_t pong_remain;
QIOChannelWebsockMask mask;
guint io_tag;
Error *io_err;
diff --git a/io/channel-websock.c b/io/channel-websock.c
index 04bcc059cd..6083f74c9b 100644
--- a/io/channel-websock.c
+++ b/io/channel-websock.c
@@ -825,11 +825,14 @@ static int qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
}
return -1;
} else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_PING) {
- /* ping frames produce an immediate reply */
- buffer_reset(&ioc->ping_reply);
- qio_channel_websock_encode_buffer(
- ioc, &ioc->ping_reply, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
- &ioc->encinput);
+ /* ping frames produce an immediate reply, as long as we've not still
+ * got a previous pong queued, in which case we drop the new pong */
+ if (ioc->pong_remain == 0) {
+ qio_channel_websock_encode_buffer(
+ ioc, &ioc->encoutput, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
+ &ioc->encinput);
+ ioc->pong_remain = ioc->encoutput.offset;
+ }
} /* pong frames are ignored */
if (payload_len) {
@@ -888,7 +891,6 @@ static void qio_channel_websock_finalize(Object *obj)
buffer_free(&ioc->encoutput);
buffer_free(&ioc->rawinput);
buffer_free(&ioc->rawoutput);
- buffer_free(&ioc->ping_reply);
object_unref(OBJECT(ioc->master));
if (ioc->io_tag) {
g_source_remove(ioc->io_tag);
@@ -946,12 +948,7 @@ static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc,
ssize_t ret;
ssize_t done = 0;
- /* ping replies take priority over binary data */
- if (!ioc->ping_reply.offset) {
- qio_channel_websock_encode(ioc);
- } else if (!ioc->encoutput.offset) {
- buffer_move_empty(&ioc->encoutput, &ioc->ping_reply);
- }
+ qio_channel_websock_encode(ioc);
while (ioc->encoutput.offset > 0) {
ret = qio_channel_write(ioc->master,
@@ -968,6 +965,11 @@ static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc,
}
buffer_advance(&ioc->encoutput, ret);
done += ret;
+ if (ioc->pong_remain < ret) {
+ ioc->pong_remain = 0;
+ } else {
+ ioc->pong_remain -= ret;
+ }
}
return done;
}
@@ -1026,7 +1028,7 @@ static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc)
return;
}
- if (ioc->encoutput.offset || ioc->ping_reply.offset) {
+ if (ioc->encoutput.offset) {
cond |= G_IO_OUT;
}
if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER &&