From cf175f31e66ab00e577482b01c0d43fd2ed99ad9 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Tue, 20 Oct 2026 17:13:17 +0200 Subject: [PATCH 1/2] fix: allow receivers to cap the size of fragmented messages --- README.md | 2 +- messaging.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ffeac9a..312ccae 100644 --- a/README.md +++ b/README.md @@ -423,7 +423,7 @@ The concatenated `data` from all fragments yields the original message's payload - Senders SHOULD NOT fragment messages that fit in a single Noise transport message. - A sender MUST NOT use `1` as `orig_type`. -**Receiver behavior:** maintain a single reassembly buffer along with the in-flight `orig_type`. On a first fragment, read `orig_type` from byte 2 and start a new buffer with its `data`; on any other fragment, append its `data` to the buffer. When bit 0 is set, dispatch the buffer as a single message of type `orig_type` and clear it. +**Receiver behavior:** maintain a single reassembly buffer along with the in-flight `orig_type`. On a first fragment, read `orig_type` from byte 2 and start a new buffer with its `data`; on any other fragment, append its `data` to the buffer. When bit 0 is set, dispatch the buffer as a single message of type `orig_type` and clear it. A receiver MAY close the connection when the concatenated `data` received so far exceeds a limit it chooses. The limit SHOULD be large enough that no valid message it can receive exceeds it. The [ignore rules](#communication) also apply to fragmented messages. If the receiver does not implement `orig_type`, it MAY discard each fragment's `data` instead of allocating a reassembly buffer. It MUST still authenticate every Noise transport message, track the fragment sequence, and enforce the malformed-sequence rules below. The last fragment clears the sequence state. The discarded message is not dispatched. diff --git a/messaging.md b/messaging.md index a864cea..9f7c5ed 100644 --- a/messaging.md +++ b/messaging.md @@ -105,7 +105,7 @@ The concatenated `data` from all fragments yields the original message's payload - Senders SHOULD NOT fragment messages that fit in a single Noise transport message. - A sender MUST NOT use `1` as `orig_type`. -**Receiver behavior:** maintain a single reassembly buffer along with the in-flight `orig_type`. On a first fragment, read `orig_type` from byte 2 and start a new buffer with its `data`; on any other fragment, append its `data` to the buffer. When bit 0 is set, dispatch the buffer as a single message of type `orig_type` and clear it. +**Receiver behavior:** maintain a single reassembly buffer along with the in-flight `orig_type`. On a first fragment, read `orig_type` from byte 2 and start a new buffer with its `data`; on any other fragment, append its `data` to the buffer. When bit 0 is set, dispatch the buffer as a single message of type `orig_type` and clear it. A receiver MAY close the connection when the concatenated `data` received so far exceeds a limit it chooses. The limit SHOULD be large enough that no valid message it can receive exceeds it. The [ignore rules](#communication) also apply to fragmented messages. If the receiver does not implement `orig_type`, it MAY discard each fragment's `data` instead of allocating a reassembly buffer. It MUST still authenticate every Noise transport message, track the fragment sequence, and enforce the malformed-sequence rules below. The last fragment clears the sequence state. The discarded message is not dispatched. From 6d8d7c6ebf3e93e9e0df79a4490696db549d0cb1 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Wed, 21 Oct 2026 10:47:52 +0200 Subject: [PATCH 2/2] fix: allow artwork clients to discard images above a size limit --- README.md | 2 ++ roles/artwork/v1.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 312ccae..956c8c2 100644 --- a/README.md +++ b/README.md @@ -1719,6 +1719,8 @@ The fields are: The concatenated `data` of all parts is the encoded image; the transfer is complete when the received data reaches `total_size`. An announce with `total_size` `0` completes immediately, with no parts. An artwork message MUST NOT exceed 65519 bytes, so that it fits in a single Noise transport message without [fragmentation](#fragmentation). +A client MAY discard an image whose `total_size` exceeds a limit it chooses. The limit SHOULD be large enough that no valid image it can receive exceeds it. + At most one image transfer is in flight at a time across all of the role's channels: a transfer is in flight from its announce until it completes or its partly received image is discarded. The server MUST NOT announce an image, on any channel, while a transfer is in flight; to replace an image still in flight, it cancels that transfer first. The server MUST cancel an in-flight transfer before sending an artwork [`stream/end`](#server--client-streamend) or a [`stream/start`](#server--client-streamstart) that changes that transfer's channel configuration. Any other messages MAY be sent between the messages of a transfer. A server SHOULD pace a transfer's parts instead of sending them back to back. Artwork is not time critical, so spreading the parts out keeps a large image from delaying the other roles the connection carries, such as `player@v1` audio chunks. diff --git a/roles/artwork/v1.md b/roles/artwork/v1.md index a4e8d25..a09757c 100644 --- a/roles/artwork/v1.md +++ b/roles/artwork/v1.md @@ -69,6 +69,8 @@ The fields are: The concatenated `data` of all parts is the encoded image; the transfer is complete when the received data reaches `total_size`. An announce with `total_size` `0` completes immediately, with no parts. An artwork message MUST NOT exceed 65519 bytes, so that it fits in a single Noise transport message without [fragmentation](../../messaging.md#fragmentation). +A client MAY discard an image whose `total_size` exceeds a limit it chooses. The limit SHOULD be large enough that no valid image it can receive exceeds it. + At most one image transfer is in flight at a time across all of the role's channels: a transfer is in flight from its announce until it completes or its partly received image is discarded. The server MUST NOT announce an image, on any channel, while a transfer is in flight; to replace an image still in flight, it cancels that transfer first. The server MUST cancel an in-flight transfer before sending an artwork [`stream/end`](../../messaging.md#server--client-streamend) or a [`stream/start`](../../messaging.md#server--client-streamstart) that changes that transfer's channel configuration. Any other messages MAY be sent between the messages of a transfer. A server SHOULD pace a transfer's parts instead of sending them back to back. Artwork is not time critical, so spreading the parts out keeps a large image from delaying the other roles the connection carries, such as `player@v1` audio chunks.