[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames
From: |
Brandon Carpenter |
Subject: |
[Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames |
Date: |
Fri, 8 Sep 2017 10:38:01 -0700 |
Add an immediate ping reply (pong) to the outgoing stream when a ping
is received. Unsolicited pongs are ignored.
Signed-off-by: Brandon Carpenter <address@hidden>
---
io/channel-websock.c | 50 ++++++++++++++++++++++++++++++++------------------
1 file changed, 32 insertions(+), 18 deletions(-)
diff --git a/io/channel-websock.c b/io/channel-websock.c
index 50387050d5..175f17ce6b 100644
--- a/io/channel-websock.c
+++ b/io/channel-websock.c
@@ -479,7 +479,8 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel
*ioc,
}
-static void qio_channel_websock_encode(QIOChannelWebsock *ioc)
+static void qio_channel_websock_encode_buffer(QIOChannelWebsock *ioc,
+ uint8_t opcode, Buffer *buffer)
{
size_t header_size;
union {
@@ -487,33 +488,37 @@ static void qio_channel_websock_encode(QIOChannelWebsock
*ioc)
QIOChannelWebsockHeader ws;
} header;
- if (!ioc->rawoutput.offset) {
- return;
- }
-
header.ws.b0 = QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN |
- (QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME &
- QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE);
- if (ioc->rawoutput.offset <
+ (opcode & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE);
+ if (buffer->offset <
QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT) {
- header.ws.b1 = (uint8_t)ioc->rawoutput.offset;
+ header.ws.b1 = (uint8_t)buffer->offset;
header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT;
- } else if (ioc->rawoutput.offset <
+ } else if (buffer->offset <
QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT) {
header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT;
- header.ws.u.s16.l16 = cpu_to_be16((uint16_t)ioc->rawoutput.offset);
+ header.ws.u.s16.l16 = cpu_to_be16((uint16_t)buffer->offset);
header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT;
} else {
header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT;
- header.ws.u.s64.l64 = cpu_to_be64(ioc->rawoutput.offset);
+ header.ws.u.s64.l64 = cpu_to_be64(buffer->offset);
header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT;
}
header_size -= QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK;
- buffer_reserve(&ioc->encoutput, header_size + ioc->rawoutput.offset);
+ buffer_reserve(&ioc->encoutput, header_size + buffer->offset);
buffer_append(&ioc->encoutput, header.buf, header_size);
- buffer_append(&ioc->encoutput, ioc->rawoutput.buffer,
- ioc->rawoutput.offset);
+ buffer_append(&ioc->encoutput, buffer->buffer, buffer->offset);
+}
+
+
+static void qio_channel_websock_encode(QIOChannelWebsock *ioc)
+{
+ if (!ioc->rawoutput.offset) {
+ return;
+ }
+ qio_channel_websock_encode_buffer(ioc,
+ QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME, &ioc->rawoutput);
buffer_reset(&ioc->rawoutput);
}
@@ -558,7 +563,7 @@ static int
qio_channel_websock_decode_header(QIOChannelWebsock *ioc,
/* Websocket frame sanity check:
* * Fragmentation is only supported for binary frames.
* * All frames sent by a client MUST be masked.
- * * Only binary encoding is supported.
+ * * Only binary and ping/pong encoding is supported.
*/
if (!fin) {
if (opcode != QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) {
@@ -619,6 +624,11 @@ static int
qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
* for purpose of unmasking, except at end of payload
*/
if (ioc->encinput.offset < ioc->payload_remain) {
+ /* Wait for the entire payload before processing control frames
+ * because the payload will most likely be echoed back. */
+ if (ioc->opcode & QIO_CHANNEL_WEBSOCK_CONTROL_OPCODE_MASK) {
+ return QIO_CHANNEL_ERR_BLOCK;
+ }
payload_len = ioc->encinput.offset - (ioc->encinput.offset % 4);
} else {
payload_len = ioc->payload_remain;
@@ -641,13 +651,17 @@ static int
qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
}
}
- /* Drop the payload of ping/pong packets */
if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) {
if (payload_len) {
+ /* binary frames are passed on */
buffer_reserve(&ioc->rawinput, payload_len);
buffer_append(&ioc->rawinput, ioc->encinput.buffer, payload_len);
}
- }
+ } else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_PING) {
+ /* ping frames produce an immediate pong reply */
+ qio_channel_websock_encode_buffer(ioc,
+ QIO_CHANNEL_WEBSOCK_OPCODE_PONG, &ioc->encinput);
+ } /* pong frames are ignored */
if (payload_len) {
buffer_advance(&ioc->encinput, payload_len);
--
2.14.1
--
CONFIDENTIALITY NOTICE: This e-mail message, including any attachments, is
for the sole use of the intended recipient(s) and may contain proprietary,
confidential or privileged information or otherwise be protected by law.
Any unauthorized review, use, disclosure or distribution is prohibited. If
you are not the intended recipient, please notify the sender and destroy
all copies and the original message.
- [Qemu-devel] [PATCH v2 0/6] Update websocket code to more fully support the RFC, Brandon Carpenter, 2017/09/08
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames,
Brandon Carpenter <=
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Daniel P. Berrange, 2017/09/11
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Brandon Carpenter, 2017/09/11
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Daniel P. Berrange, 2017/09/11
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Brandon Carpenter, 2017/09/11
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Daniel P. Berrange, 2017/09/12
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Daniel P. Berrange, 2017/09/11
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Brandon Carpenter, 2017/09/11
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Daniel P. Berrange, 2017/09/12
- Re: [Qemu-devel] [PATCH v2 6/6] io: Reply to ping frames, Brandon Carpenter, 2017/09/12
Re: [Qemu-devel] [PATCH v2 0/6] Update websocket code to more fully support the RFC, Eric Blake, 2017/09/08