From 8b5f6bcaf46319367696623ea7d3954ad9eff0d5 Mon Sep 17 00:00:00 2001 From: Alan Frindell Date: Thu, 8 May 2025 18:37:10 +0200 Subject: [PATCH 01/13] New Varint Encoding Fixes: #548 Fixes: #549 --- draft-ietf-moq-transport.md | 71 ++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 8ff259c08..fa5cbb605 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -243,11 +243,6 @@ x (L): : Indicates that x is L bits long -x (i): - -: Indicates that x holds an integer value using the variable-length - encoding as described in ({{?RFC9000, Section 16}}) - x (..): : Indicates that x can be any length including zero bits long. Values @@ -262,6 +257,13 @@ x (L) ...: : Indicates that x is repeated zero or more times and that each instance has a length of L +This document redfines the following RFC9000 syntax: + +x (i): + +: Indicates that x holds an integer value using the variable-length + encoding as described in {{variable-length-integers}}. + This document extends the RFC9000 syntax and with the additional field types: x (b): @@ -276,10 +278,44 @@ x (tuple): as described in ({{?RFC9000, Section 16}}), followed by that many variable length tuple fields, each of which are encoded as (b) above. + +### Variable-Length Integers + +RFC9000 variable-length integers use a two-bit length prefix in the first byte +to determine the encoded length. This limits the number of encodings to 4, +reduces the value range of 1-byte encodings to 0-63, and prevents encoding full +64-bit numbers. This encoding is not suitable for MoQT. + +The variable-length integer encoding reserves the most one to four significant +bits of the first byte to encode the length of the integer encoding in +bytes. The integer value is encoded on the remaining bits, in network byte +order. + +Integers are encoded in 1, 2, 4, 8, or 9 bytes and can encode 7-, 14-, 29-, 60-, +or 64-bit values, respectively. The following table summarizes the encoding +properties. + +|--------------|----------------|-------------|---------------| +| Leading Bits | Length (bytes) | Usable Bits | Range | +|--------------|----------------|-------------|---------------| +| 0 | 1 | 7 | 0-127 | +|--------------|----------------|-------------|---------------| +| 10 | 2 | 14 | 0-16,383 | +|--------------|----------------|-------------|---------------| +| 110 | 4 | 29 | 0-536,870,911 | +|--------------|----------------|-------------|---------------| +| 1110 | 8 | 60 | 0-2^60-1 | +|--------------|----------------|-------------|---------------| +| 1111XXXX | 9 | 64 | 0-2^64-1 | +|--------------|----------------|-------------|---------------| +{: format title="Summary of Integer Encodings"} + To reduce unnecessary use of bandwidth, variable length integers SHOULD be encoded using the least number of bytes possible to represent the required value. +A sample decoding algorithm is in {{sample-decoding}}. + ### Location Structure Location identifies a particular Object in a Group within a Track. @@ -3443,6 +3479,31 @@ document: --- back +# Sample Variable-Length Integer Decoding {#sample-decoding} + +The function ReadVarint takes a single argument -- a sequence of bytes, which +can be read in network byte order. + +~~~ +ReadVarint(data): + lengths = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 8, 9 ] + masks = [ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x00 ] + // The length of variable-length integers is encoded in the + // first one to four bits of the first byte. + v = data.next_byte() + prefix = v >> 4 + length = lengths[prefix] + mask = masks[prefix] + + // Once the length is known, remove these bits and read any + // remaining bytes. + v = v & mask + repeat length-1 times: + v = (v << 8) + data.next_byte() + return v +~~~ + # Change Log RFC Editor's Note: Please remove this section prior to publication of a final version of this document. From 2a2f16dc64623930dfc4a1863c5520cd51eaa1e2 Mon Sep 17 00:00:00 2001 From: afrind Date: Fri, 9 May 2025 10:24:41 -0700 Subject: [PATCH 02/13] Apply suggestions from code review --- draft-ietf-moq-transport.md | 40 ++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index fa5cbb605..9e4015ce0 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -281,10 +281,11 @@ x (tuple): ### Variable-Length Integers -RFC9000 variable-length integers use a two-bit length prefix in the first byte -to determine the encoded length. This limits the number of encodings to 4, -reduces the value range of 1-byte encodings to 0-63, and prevents encoding full -64-bit numbers. This encoding is not suitable for MoQT. +MoQT requires a variable-length integer encoding with the following properties: + +1. The encoded length can be determined from the first encoded byte. +2. The range of 1 byte values is as large as possible. +3. All 64 bit numbers can be encoded. The variable-length integer encoding reserves the most one to four significant bits of the first byte to encode the length of the integer encoding in @@ -314,7 +315,7 @@ To reduce unnecessary use of bandwidth, variable length integers SHOULD be encoded using the least number of bytes possible to represent the required value. -A sample decoding algorithm is in {{sample-decoding}}. +A sample encoding and decoding algorithm is in {{sample-varint}}. ### Location Structure @@ -3479,12 +3480,31 @@ document: --- back -# Sample Variable-Length Integer Decoding {#sample-decoding} +# Sample Variable-Length Integer Encoding and Decoding {#sample-varint} + +The WriteVarint function takes two parameters, a 64 bit integer and an +output buffer with an append operation. + +~~~pseudocode +Function WriteVarint(value, output): + if value <= 127: + output.append(value, 1) + else if value <= 16383: + output.append(networkByteOrder(uint16_t(value | 0x8000)), 2) + else if value <= 536870911: + output.append(networkByteOrder(uint32_t(value | 0xC0000000)), 4) + else if value <= 1152921504606846975: + output.append(networkByteOrder(uint64_t(value | 0xE000000000000000)), 8) + else: + output.append(0xF0, 1) + output.append(networkByteOrder(value), 8) +~~~ + The function ReadVarint takes a single argument -- a sequence of bytes, which can be read in network byte order. -~~~ +~~~pseudocode ReadVarint(data): lengths = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 8, 9 ] masks = [ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, @@ -3503,6 +3523,12 @@ ReadVarint(data): v = (v << 8) + data.next_byte() return v ~~~ +For example, the nine-byte sequence 0xf0ffffffffffffffff decodes to the decimal +value 18,446,744,073,709,551,615; the eight-byte sequence 0xe2197c5eff14e88c +decodes to the decimal value 151,288,809,941,952,652; the four-byte sequence +0xdd7f3e7d decodes to 494,878,333; the two-byte sequence 0xbbbd decodes to +15,293; and the single byte 0x25 decodes to 37 (as does the two-byte sequence +0x8025). # Change Log From ae23d210a6f275cf7935149f2bbaf59836f10e39 Mon Sep 17 00:00:00 2001 From: afrind Date: Fri, 9 May 2025 10:40:01 -0700 Subject: [PATCH 03/13] Update stream count maximum Since it's only peer uni streams, the max count is 2^60 --- draft-ietf-moq-transport.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 9e4015ce0..4e3a5ad6b 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -2097,18 +2097,18 @@ SUBSCRIBE_DONE Message { * Status Code: An integer status code indicating why the subscription ended. * Stream Count: An integer indicating the number of data streams the publisher -opened for this subscription. This helps the subscriber know if it has received -all of the data published in this subscription by comparing the number of -streams received. The subscriber can immediately remove all subscription state -once the same number of streams have been processed. If the track had -Forwarding Preference = Datagram, the publisher MUST set Stream Count to 0. If -the publisher is unable to set Stream Count to the exact number of streams -opened for the subscription, it MUST set Stream Count to 2^62 - 1. Subscribers -SHOULD use a timeout or other mechanism to remove subscription state in case -the publisher set an incorrect value, reset a stream before the SUBGROUP_HEADER, -or set the maximum value. If a subscriber receives more streams for a -subscription than specified in Stream Count, it MAY close the session with a -Protocol Violation. + opened for this subscription. This helps the subscriber know if it has + received all of the data published in this subscription by comparing the + number of streams received. The subscriber can immediately remove all + subscription state once the same number of streams have been processed. If + the track had Forwarding Preference = Datagram, the publisher MUST set Stream + Count to 0. If the publisher is unable to set Stream Count to the exact + number of streams opened for the subscription, it MUST set Stream Count to a + value greater than or equal to 2^60. Subscribers SHOULD use a timeout or other + mechanism to remove subscription state in case the publisher set an incorrect + value, reset a stream before the SUBGROUP_HEADER, or set the maximum value. If + a subscriber receives more streams for a subscription than specified in Stream + Count, it MAY close the session with a Protocol Violation. * Error Reason: Provides the reason for subscription error. See {{reason-phrase}}. From eac15575507fdc374f8cd144c576ee261a280242 Mon Sep 17 00:00:00 2001 From: Alan Frindell Date: Fri, 9 May 2025 10:41:56 -0700 Subject: [PATCH 04/13] lint --- draft-ietf-moq-transport.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 4e3a5ad6b..e94e14139 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -3492,14 +3492,16 @@ Function WriteVarint(value, output): else if value <= 16383: output.append(networkByteOrder(uint16_t(value | 0x8000)), 2) else if value <= 536870911: - output.append(networkByteOrder(uint32_t(value | 0xC0000000)), 4) + output.append(networkByteOrder( + uint32_t(value | 0xC0000000)), 4) else if value <= 1152921504606846975: - output.append(networkByteOrder(uint64_t(value | 0xE000000000000000)), 8) + output.append(networkByteOrder( + uint64_t(value | 0xE000000000000000)), 8) else: output.append(0xF0, 1) output.append(networkByteOrder(value), 8) ~~~ - + The function ReadVarint takes a single argument -- a sequence of bytes, which can be read in network byte order. From cb4af37d32b542ac25529f51168b6721869ca3f9 Mon Sep 17 00:00:00 2001 From: afrind Date: Sun, 11 May 2025 10:43:50 -0700 Subject: [PATCH 05/13] Update draft-ietf-moq-transport.md Co-authored-by: Suhas Nandakumar --- draft-ietf-moq-transport.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index e94e14139..420660580 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -287,10 +287,9 @@ MoQT requires a variable-length integer encoding with the following properties: 2. The range of 1 byte values is as large as possible. 3. All 64 bit numbers can be encoded. -The variable-length integer encoding reserves the most one to four significant -bits of the first byte to encode the length of the integer encoding in -bytes. The integer value is encoded on the remaining bits, in network byte -order. +The variable-length integer encoding uses the most significant one to four +bits of the first byte to indicate the length of the encoding in bytes. The +remaining bits represent the integer value, encoded in network byte order. Integers are encoded in 1, 2, 4, 8, or 9 bytes and can encode 7-, 14-, 29-, 60-, or 64-bit values, respectively. The following table summarizes the encoding From 4527fc9a3ade227aa3cade07e483da1f451f6ad5 Mon Sep 17 00:00:00 2001 From: afrind Date: Mon, 12 May 2025 09:17:48 -0700 Subject: [PATCH 06/13] Apply suggestions from code review --- draft-ietf-moq-transport.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 420660580..28d91ed2e 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -287,7 +287,7 @@ MoQT requires a variable-length integer encoding with the following properties: 2. The range of 1 byte values is as large as possible. 3. All 64 bit numbers can be encoded. -The variable-length integer encoding uses the most significant one to four +The variable-length integer encoding uses the most significant one to four bits of the first byte to indicate the length of the encoding in bytes. The remaining bits represent the integer value, encoded in network byte order. @@ -310,6 +310,9 @@ properties. |--------------|----------------|-------------|---------------| {: format title="Summary of Integer Encodings"} +The four least significant bits of the first byte are reserved in 9-byte +encodings. + To reduce unnecessary use of bandwidth, variable length integers SHOULD be encoded using the least number of bytes possible to represent the required value. From 654a77c87ed4551afa0cff9ec43f570484b619e1 Mon Sep 17 00:00:00 2001 From: afrind Date: Tue, 13 May 2025 12:33:57 -0700 Subject: [PATCH 07/13] Update draft-ietf-moq-transport.md Co-authored-by: ianswett --- draft-ietf-moq-transport.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 28d91ed2e..9427416d8 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -257,7 +257,7 @@ x (L) ...: : Indicates that x is repeated zero or more times and that each instance has a length of L -This document redfines the following RFC9000 syntax: +This document redefines the following RFC9000 syntax: x (i): From a22a95254957338702f2db70622b3da43c1647f8 Mon Sep 17 00:00:00 2001 From: afrind Date: Sat, 31 May 2025 07:54:12 -0700 Subject: [PATCH 08/13] Review feedback --- draft-ietf-moq-transport.md | 248 ++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 124 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 9427416d8..c01f5204d 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -259,7 +259,7 @@ x (L) ...: This document redefines the following RFC9000 syntax: -x (i): +x (vi64): : Indicates that x holds an integer value using the variable-length encoding as described in {{variable-length-integers}}. @@ -310,8 +310,8 @@ properties. |--------------|----------------|-------------|---------------| {: format title="Summary of Integer Encodings"} -The four least significant bits of the first byte are reserved in 9-byte -encodings. +The four least significant bits of the first byte are ignored in 9-byte +encodings. Senders SHOULD set these bits to 0000. To reduce unnecessary use of bandwidth, variable length integers SHOULD be encoded using the least number of bytes possible to represent the @@ -325,8 +325,8 @@ Location identifies a particular Object in a Group within a Track. ~~~ Location { - Group (i), - Object (i) + Group (vi64), + Object (vi64) } ~~~ {: #moq-location format title="Location structure"} @@ -347,8 +347,8 @@ is optimized for use in the data plane. ~~~ Key-Value-Pair { - Type (i), - [Length (i),] + Type (vi64), + [Length (vi64),] Value (..) } ~~~ @@ -375,7 +375,7 @@ information about the error condition, where appropriate. ~~~ Reason Phrase { - Reason Phrase Length (i), + Reason Phrase Length (vi64), Reason Phrase Value (..) } ~~~ @@ -1247,7 +1247,7 @@ formatted as follows: ~~~ MOQT Control Message { - Message Type (i), + Message Type (vi64), Message Length (16), Message Payload (..), } @@ -1385,9 +1385,9 @@ in future messages. The TOKEN value is serialized as follows: ~~~ TOKEN { - Alias Type (i), - [Token Alias (i),] - [Token Type (i),] + Alias Type (vi64), + [Token Alias (vi64),] + [Token Type (vi64),] [Token Value (..)] } ~~~ @@ -1529,19 +1529,19 @@ The wire format of the Setup messages are as follows: ~~~ CLIENT_SETUP Message { - Type (i) = 0x20, + Type (vi64) = 0x20, Length (16), - Number of Supported Versions (i), - Supported Versions (i) ..., - Number of Parameters (i), + Number of Supported Versions (vi64), + Supported Versions (vi64) ..., + Number of Parameters (vi64), Setup Parameters (..) ..., } SERVER_SETUP Message { - Type (i) = 0x21, + Type (vi64) = 0x21, Length (16), - Selected Version (i), - Number of Parameters (i), + Selected Version (vi64), + Number of Parameters (vi64), Setup Parameters (..) ..., } ~~~ @@ -1625,9 +1625,9 @@ The endpoint MUST terminate the session with a Protocol Violation ~~~ GOAWAY Message { - Type (i) = 0x10, + Type (vi64) = 0x10, Length (16), - New Session URI Length (i), + New Session URI Length (vi64), New Session URI (..), } ~~~ @@ -1655,9 +1655,9 @@ value is a 'Protocol Violation'. ~~~ MAX_REQUEST_ID Message { - Type (i) = 0x15, + Type (vi64) = 0x15, Length (16), - Request ID (i), + Request ID (vi64), } ~~~ {: #moq-transport-max-request-id format title="MOQT MAX_REQUEST_ID Message"} @@ -1687,9 +1687,9 @@ sending REQUESTS_BLOCKED is not required. ~~~ REQUESTS_BLOCKED Message { - Type (i) = 0x1A, + Type (vi64) = 0x1A, Length (16), - Maximum Request ID (i), + Maximum Request ID (vi64), } ~~~ {: #moq-transport-requests-blocked format title="MOQT REQUESTS_BLOCKED Message"} @@ -1768,20 +1768,20 @@ The format of SUBSCRIBE is as follows: ~~~ SUBSCRIBE Message { - Type (i) = 0x3, + Type (vi64) = 0x3, Length (16), - Request ID (i), - Track Alias (i), + Request ID (vi64), + Track Alias (vi64), Track Namespace (tuple), - Track Name Length (i), + Track Name Length (vi64), Track Name (..), Subscriber Priority (8), Group Order (8), Forward (8), - Filter Type (i), + Filter Type (vi64), [Start Location (Location)], - [End Group (i)], - Number of Parameters (i), + [End Group (vi64)], + Number of Parameters (vi64), Subscribe Parameters (..) ... } ~~~ @@ -1840,14 +1840,14 @@ subscriptions. ~~~ SUBSCRIBE_OK Message { - Type (i) = 0x4, + Type (vi64) = 0x4, Length (16), - Request ID (i), - Expires (i), + Request ID (vi64), + Expires (vi64), Group Order (8), Content Exists (8), [Largest Location (Location)], - Number of Parameters (i), + Number of Parameters (vi64), Subscribe Parameters (..) ... } ~~~ @@ -1882,12 +1882,12 @@ failed SUBSCRIBE. ~~~ SUBSCRIBE_ERROR Message { - Type (i) = 0x5, + Type (vi64) = 0x5, Length (16), - Request ID (i), - Error Code (i), + Request ID (vi64), + Error Code (vi64), Error Reason (Reason Phrase), - Track Alias (i), + Track Alias (vi64), } ~~~ {: #moq-transport-subscribe-error format title="MOQT SUBSCRIBE_ERROR Message"} @@ -1991,14 +1991,14 @@ The format of SUBSCRIBE_UPDATE is as follows: ~~~ SUBSCRIBE_UPDATE Message { - Type (i) = 0x2, + Type (vi64) = 0x2, Length (16), - Request ID (i), + Request ID (vi64), Start Location (Location), - End Group (i), + End Group (vi64), Subscriber Priority (8), Forward (8), - Number of Parameters (i), + Number of Parameters (vi64), Subscribe Parameters (..) ... } ~~~ @@ -2033,9 +2033,9 @@ The format of `UNSUBSCRIBE` is as follows: ~~~ UNSUBSCRIBE Message { - Type (i) = 0xA, + Type (vi64) = 0xA, Length (16), - Request ID (i) + Request ID (vi64) } ~~~ {: #moq-transport-unsubscribe-format title="MOQT UNSUBSCRIBE Message"} @@ -2083,11 +2083,11 @@ The format of `SUBSCRIBE_DONE` is as follows: ~~~ SUBSCRIBE_DONE Message { - Type (i) = 0xB, + Type (vi64) = 0xB, Length (16), - Request ID (i), - Status Code (i), - Stream Count (i), + Request ID (vi64), + Status Code (vi64), + Stream Count (vi64), Error Reason (Reason Phrase) } ~~~ @@ -2217,22 +2217,22 @@ The format of FETCH is as follows: ~~~ FETCH Message { - Type (i) = 0x16, + Type (vi64) = 0x16, Length (16), - Request ID (i), + Request ID (vi64), Subscriber Priority (8), Group Order (8), - Fetch Type (i), + Fetch Type (vi64), [Track Namespace (tuple), - Track Name Length (i), + Track Name Length (vi64), Track Name (..), - Start Group (i), - Start Object (i), - End Group (i), - End Object (i),] - [Joining Subscribe ID (i), - Joining Start (i),] - Number of Parameters (i), + Start Group (vi64), + Start Object (vi64), + End Group (vi64), + End Object (vi64),] + [Joining Subscribe ID (vi64), + Joining Start (vi64),] + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2335,13 +2335,13 @@ but the FETCH_OK MUST NOT be sent until the end group and object are known. ~~~ FETCH_OK Message { - Type (i) = 0x18, + Type (vi64) = 0x18, Length (16), - Request ID (i), + Request ID (vi64), Group Order (8), End Of Track (8), End Location (Location), - Number of Parameters (i), + Number of Parameters (vi64), Subscribe Parameters (..) ... } ~~~ @@ -2375,10 +2375,10 @@ failed FETCH. ~~~ FETCH_ERROR Message { - Type (i) = 0x19, + Type (vi64) = 0x19, Length (16), - Request ID (i), - Error Code (i), + Request ID (vi64), + Error Code (vi64), Error Reason (Reason Phrase) } ~~~ @@ -2462,9 +2462,9 @@ The format of `FETCH_CANCEL` is as follows: ~~~ FETCH_CANCEL Message { - Type (i) = 0x17, + Type (vi64) = 0x17, Length (16), - Request ID (i) + Request ID (vi64) } ~~~ {: #moq-transport-fetch-cancel title="MOQT FETCH_CANCEL Message"} @@ -2481,13 +2481,13 @@ A TRACK_STATUS message MUST be sent in response to each TRACK_STATUS_REQUEST. ~~~ TRACK_STATUS_REQUEST Message { - Type (i) = 0xD, + Type (vi64) = 0xD, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace (tuple), - Track Name Length (i), + Track Name Length (vi64), Track Name (..), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ..., } ~~~ @@ -2509,12 +2509,12 @@ to a TRACK_STATUS_REQUEST message. ~~~ TRACK_STATUS Message { - Type (i) = 0xE, + Type (vi64) = 0xE, Length (16), - Request ID (i), - Status Code (i), + Request ID (vi64), + Status Code (vi64), Largest Location (Location), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ..., } ~~~ @@ -2562,11 +2562,11 @@ publisher is authorized to publish tracks under this namespace. ~~~ ANNOUNCE Message { - Type (i) = 0x6, + Type (vi64) = 0x6, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace (tuple), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ..., } ~~~ @@ -2586,9 +2586,9 @@ successful authorization and acceptance of an ANNOUNCE message. ~~~ ANNOUNCE_OK Message { - Type (i) = 0x7, + Type (vi64) = 0x7, Length (16), - Request ID (i) + Request ID (vi64) } ~~~ {: #moq-transport-announce-ok format title="MOQT ANNOUNCE_OK Message"} @@ -2603,10 +2603,10 @@ failed authorization. ~~~ ANNOUNCE_ERROR Message { - Type (i) = 0x8, + Type (vi64) = 0x8, Length (16), - Request ID (i), - Error Code (i), + Request ID (vi64), + Error Code (vi64), Error Reason (Reason Phrase) } ~~~ @@ -2671,7 +2671,7 @@ within the provided Track Namespace. ~~~ UNANNOUNCE Message { - Type (i) = 0x9, + Type (vi64) = 0x9, Length (16), Track Namespace (tuple), } @@ -2689,10 +2689,10 @@ within the provided Track Namespace. ~~~ ANNOUNCE_CANCEL Message { - Type (i) = 0xC, + Type (vi64) = 0xC, Length (16), Track Namespace (tuple), - Error Code (i), + Error Code (vi64), Error Reason (Reason Phrase), } ~~~ @@ -2715,11 +2715,11 @@ to the set. ~~~ SUBSCRIBE_ANNOUNCES Message { - Type (i) = 0x11, + Type (vi64) = 0x11, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace Prefix (tuple), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ..., } ~~~ @@ -2765,9 +2765,9 @@ namespace subscriptions. ~~~ SUBSCRIBE_ANNOUNCES_OK Message { - Type (i) = 0x12, + Type (vi64) = 0x12, Length (16), - Request ID (i), + Request ID (vi64), } ~~~ {: #moq-transport-sub-ann-ok format title="MOQT SUBSCRIBE_ANNOUNCES_OK @@ -2783,10 +2783,10 @@ a failed SUBSCRIBE_ANNOUNCES. ~~~ SUBSCRIBE_ANNOUNCES_ERROR Message { - Type (i) = 0x13, + Type (vi64) = 0x13, Length (16), - Request ID (i), - Error Code (i), + Request ID (vi64), + Error Code (vi64), Error Reason (Reason Phrase) } ~~~ @@ -2862,7 +2862,7 @@ The format of `UNSUBSCRIBE_ANNOUNCES` is as follows: ~~~ UNSUBSCRIBE_ANNOUNCES Message { - Type (i) = 0x14, + Type (vi64) = 0x14, Length (16), Track Namespace Prefix (tuple) } @@ -3031,12 +3031,12 @@ will be dropped. ~~~ OBJECT_DATAGRAM { - Type (i), - Track Alias (i), - Group ID (i), - Object ID (i), + Type (vi64), + Track Alias (vi64), + Group ID (vi64), + Object ID (vi64), Publisher Priority (8), - [Extension Headers Length (i), + [Extension Headers Length (vi64), Extension headers (...)], Object Payload (..), } @@ -3059,14 +3059,14 @@ conveys an Object Status and has no payload. ~~~ OBJECT_DATAGRAM_STATUS { - Type (i), - Track Alias (i), - Group ID (i), - Object ID (i), + Type (vi64), + Track Alias (vi64), + Group ID (vi64), + Object ID (vi64), Publisher Priority (8), - [Extension Headers Length (i), + [Extension Headers Length (vi64), Extension headers (...)], - Object Status (i), + Object Status (vi64), } ~~~ {: #object-datagram-status-format title="MOQT OBJECT_DATAGRAM_STATUS"} @@ -3102,10 +3102,10 @@ and the subgroup indicated by 'Group ID' and `Subgroup ID`. ~~~ SUBGROUP_HEADER { - Type (i) = 0x8..0xD, - Track Alias (i), - Group ID (i), - [Subgroup ID (i),] + Type (vi64) = 0x8..0xD, + Track Alias (vi64), + Group ID (vi64), + [Subgroup ID (vi64),] Publisher Priority (8), } ~~~ @@ -3152,11 +3152,11 @@ The Object Status field is only sent if the Object Payload Length is zero. ~~~ { - Object ID (i), - [Extension Headers Length (i), + Object ID (vi64), + [Extension Headers Length (vi64), Extension headers (...)], - Object Payload Length (i), - [Object Status (i)], + Object Payload Length (vi64), + [Object Status (vi64)], Object Payload (..), } ~~~ @@ -3292,8 +3292,8 @@ track requested in the Fetch message identified by `Request ID`. ~~~ FETCH_HEADER { - Type (i) = 0x5, - Request ID (i), + Type (vi64) = 0x5, + Request ID (vi64), } ~~~ {: #fetch-header-format title="MOQT FETCH_HEADER"} @@ -3303,14 +3303,14 @@ Each object sent on a fetch stream after the FETCH_HEADER has the following form ~~~ { - Group ID (i), - Subgroup ID (i), - Object ID (i), + Group ID (vi64), + Subgroup ID (vi64), + Object ID (vi64), Publisher Priority (8), - Extension Headers Length (i), + Extension Headers Length (vi64), [Extension headers (...)], - Object Payload Length (i), - [Object Status (i)], + Object Payload Length (vi64), + [Object Status (vi64)], Object Payload (..), } ~~~ From 7150fd243d47b2ae4556457a9c74a7410f5ce992 Mon Sep 17 00:00:00 2001 From: afrind Date: Thu, 25 Sep 2025 19:51:57 -0400 Subject: [PATCH 09/13] More i -> vi64 --- draft-ietf-moq-transport.md | 122 ++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 2563c8a89..1bd6a028b 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -519,7 +519,7 @@ encoded as follows: ~~~ Track Namespace { - Number of Track Namespace Fields (i), + Number of Track Namespace Fields (vi64), Track Namespace Field (..) ... } ~~~ @@ -531,7 +531,7 @@ Each Track Namespace Field is encoded as follows: ~~~ Track Namespace Field { - Track Namespace Field Length (i), + Track Namespace Field Length (vi64), Track Namespace Field Value (..) } ~~~ @@ -1624,9 +1624,9 @@ follows: ~~~ Token { - Alias Type (i), - [Token Alias (i),] - [Token Type (i),] + Alias Type (vi64), + [Token Alias (vi64),] + [Token Type (vi64),] [Token Value (..)] } ~~~ @@ -1956,7 +1956,7 @@ value is a `PROTOCOL_VIOLATION`. MAX_REQUEST_ID Message { Type (vi64) = 0x15, Length (16), - Max Request ID (i), + Max Request ID (vi64), } ~~~ {: #moq-transport-max-request-id format title="MOQT MAX_REQUEST_ID Message"} @@ -2005,10 +2005,10 @@ request. ~~~ REQUEST_ERROR Message { - Type (i) = 0x5, + Type (vi64) = 0x5, Length (16), - Request ID (i), - Error Code (i), + Request ID (vi64), + Error Code (vi64), Error Reason (Reason Phrase), } ~~~ @@ -2099,17 +2099,17 @@ The format of SUBSCRIBE is as follows: SUBSCRIBE Message { Type (vi64) = 0x3, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace (..), - Track Name Length (i), + Track Name Length (vi64), Track Name (..), Subscriber Priority (8), Group Order (8), Forward (8), - Filter Type (i), + Filter Type (vi64), [Start Location (Location),] - [End Group (i),] - Number of Parameters (i), + [End Group (vi64),] + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2168,13 +2168,13 @@ subscriptions. SUBSCRIBE_OK Message { Type (vi64) = 0x4, Length (16), - Request ID (i), - Track Alias (i), - Expires (i), + Request ID (vi64), + Track Alias (vi64), + Expires (vi64), Group Order (8), Content Exists (8), [Largest Location (Location),] - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2242,12 +2242,12 @@ SUBSCRIBE_UPDATE Message { Type (vi64) = 0x2, Length (16), Request ID (vi64), - Subscription Request ID (i), + Subscription Request ID (vi64), Start Location (Location), End Group (vi64), Subscriber Priority (8), Forward (8), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2302,18 +2302,18 @@ track. The receiver verifies the publisher is authorized to publish this track. ~~~ PUBLISH Message { - Type (i) = 0x1D, + Type (vi64) = 0x1D, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace (..), - Track Name Length (i), + Track Name Length (vi64), Track Name (..), - Track Alias (i), + Track Alias (vi64), Group Order (8), Content Exists (8), [Largest Location (Location),] Forward (8), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2361,16 +2361,16 @@ authorization and acceptance of a PUBLISH message, and establish a subscription. ~~~ PUBLISH_OK Message { - Type (i) = 0x1E, + Type (vi64) = 0x1E, Length (16), - Request ID (i), + Request ID (vi64), Forward (8), Subscriber Priority (8), Group Order (8), - Filter Type (i), + Filter Type (vi64), [Start Location (Location),] - [End Group (i),] - Number of Parameters (i), + [End Group (vi64),] + Number of Parameters (vi64), Parameters (..) ..., } ~~~ @@ -2432,7 +2432,7 @@ The format of `PUBLISH_DONE` is as follows: ~~~ PUBLISH_DONE Message { - Type (i) = 0xB, + Type (vi64) = 0xB, Length (16), Request ID (vi64), Status Code (vi64), @@ -2516,7 +2516,7 @@ A Standalone Fetch includes this structure: ~~~ Standalone Fetch { Track Namespace (..), - Track Name Length (i), + Track Name Length (vi64), Track Name (..), Start Location (Location), End Location (Location) @@ -2558,8 +2558,8 @@ A Joining Fetch includes this structure: ~~~ Joining Fetch { - Joining Request ID (i), - Joining Start (i) + Joining Request ID (vi64), + Joining Start (vi64) } ~~~ @@ -2602,10 +2602,10 @@ FETCH Message { Request ID (vi64), Subscriber Priority (8), Group Order (8), - Fetch Type (i), + Fetch Type (vi64), [Standalone (Standalone Fetch),] [Joining (Joining Fetch),] - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2693,7 +2693,7 @@ FETCH_OK Message { Group Order (8), End Of Track (8), End Location (Location), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2787,11 +2787,11 @@ publisher is authorized to publish tracks under this namespace. ~~~ PUBLISH_NAMESPACE Message { - Type (i) = 0x6, + Type (vi64) = 0x6, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace (..), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -2848,10 +2848,10 @@ within the provided Track Namespace. ~~~ PUBLISH_NAMESPACE_CANCEL Message { - Type (i) = 0xC, + Type (vi64) = 0xC, Length (16), Track Namespace (..), - Error Code (i), + Error Code (vi64), Error Reason (Reason Phrase) } ~~~ @@ -2875,11 +2875,11 @@ subscriptions, as well as future updates to the set. ~~~ SUBSCRIBE_NAMESPACE Message { - Type (i) = 0x11, + Type (vi64) = 0x11, Length (16), - Request ID (i), + Request ID (vi64), Track Namespace Prefix (..), - Number of Parameters (i), + Number of Parameters (vi64), Parameters (..) ... } ~~~ @@ -3112,7 +3112,7 @@ Key-Value-Pairs, in bytes. ~~~ Extensions { - Extension Headers Length (i), + Extension Headers Length (vi64), Extension headers (..), } ~~~ @@ -3149,13 +3149,13 @@ An `OBJECT_DATAGRAM` carries a single object in a datagram. ~~~ OBJECT_DATAGRAM { - Type (i) = 0x0-0x7,0x20-21,0x24-25 - Track Alias (i), - Group ID (i), - [Object ID (i),] + Type (vi64) = 0x0-0x7,0x20-21,0x24-25 + Track Alias (vi64), + Group ID (vi64), + [Object ID (vi64),] [Publisher Priority (8),] [Extensions (..),] - [Object Status (i),] + [Object Status (vi64),] [Object Payload (..),] } ~~~ @@ -3255,10 +3255,10 @@ flow control, while the sender waits for flow control to send the message. ~~~ SUBGROUP_HEADER { - Type (i) = 0x10..0x1D, - Track Alias (i), - Group ID (i), - [Subgroup ID (i),] + Type (vi64) = 0x10..0x1D, + Track Alias (vi64), + Group ID (vi64), + [Subgroup ID (vi64),] [Publisher Priority (8),] } ~~~ @@ -3360,10 +3360,10 @@ unless there is an Prior Object ID Gap extesnion header (see ~~~ { - Object ID Delta (i), + Object ID Delta (vi64), [Extensions (..),] - Object Payload Length (i), - [Object Status (i),] + Object Payload Length (vi64), + [Object Status (vi64),] [Object Payload (..),] } ~~~ @@ -3497,8 +3497,8 @@ Each object sent on a fetch stream after the FETCH_HEADER has the following form Object ID (vi64), Publisher Priority (8), Extensions (..), - Object Payload Length (i), - [Object Status (i),] + Object Payload Length (vi64), + [Object Status (vi64),] [Object Payload (..),] } ~~~ @@ -3612,7 +3612,7 @@ Headers of the Object. ~~~ Immutable Extensions { Type (0xB), - Length (i), + Length (vi64), Key-Value-Pair (..) ... } ~~~ From b950764e6cf3276b6248e8332e7bef1e09069220 Mon Sep 17 00:00:00 2001 From: afrind Date: Thu, 25 Sep 2025 19:57:42 -0400 Subject: [PATCH 10/13] delete pseudocode, reserve bits for future extension --- draft-ietf-moq-transport.md | 75 +++++++------------------------------ 1 file changed, 14 insertions(+), 61 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 1bd6a028b..29d5f784c 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -271,8 +271,7 @@ This document redefines the following RFC9000 syntax: x (vi64): : Indicates that x holds an integer value using the variable-length - encoding as described in {{variable-length-integers}}. - + encoding as described below. ### Variable-Length Integers @@ -301,18 +300,24 @@ properties. |--------------|----------------|-------------|---------------| | 1110 | 8 | 60 | 0-2^60-1 | |--------------|----------------|-------------|---------------| -| 1111XXXX | 9 | 64 | 0-2^64-1 | +| 11110000 | 9 | 64 | 0-2^64-1 | |--------------|----------------|-------------|---------------| {: format title="Summary of Integer Encodings"} -The four least significant bits of the first byte are ignored in 9-byte -encodings. Senders SHOULD set these bits to 0000. +For example, the nine-byte sequence 0xf0ffffffffffffffff decodes to the decimal +value 18,446,744,073,709,551,615; the eight-byte sequence 0xe2197c5eff14e88c +decodes to the decimal value 151,288,809,941,952,652; the four-byte sequence +0xdd7f3e7d decodes to 494,878,333; the two-byte sequence 0xbbbd decodes to +15,293; and the single byte 0x25 decodes to 37 (as does the two-byte sequence +0x8025). -To reduce unnecessary use of bandwidth, variable length integers SHOULD -be encoded using the least number of bytes possible to represent the -required value. +The four least significant bits of the first byte in 9-byte encodings MUST be +set to 0000. An endpoint that receives any other value MUST close the session +with a `PROTOCOL_VIOLATION`. -A sample encoding and decoding algorithm is in {{sample-varint}}. +To reduce unnecessary use of bandwidth, variable length integers SHOULD be +encoded using the least number of bytes possible to represent the required +value. ### Location Structure @@ -3851,58 +3856,6 @@ document: --- back -# Sample Variable-Length Integer Encoding and Decoding {#sample-varint} - -The WriteVarint function takes two parameters, a 64 bit integer and an -output buffer with an append operation. - -~~~pseudocode -Function WriteVarint(value, output): - if value <= 127: - output.append(value, 1) - else if value <= 16383: - output.append(networkByteOrder(uint16_t(value | 0x8000)), 2) - else if value <= 536870911: - output.append(networkByteOrder( - uint32_t(value | 0xC0000000)), 4) - else if value <= 1152921504606846975: - output.append(networkByteOrder( - uint64_t(value | 0xE000000000000000)), 8) - else: - output.append(0xF0, 1) - output.append(networkByteOrder(value), 8) -~~~ - - -The function ReadVarint takes a single argument -- a sequence of bytes, which -can be read in network byte order. - -~~~pseudocode -ReadVarint(data): - lengths = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 8, 9 ] - masks = [ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x00 ] - // The length of variable-length integers is encoded in the - // first one to four bits of the first byte. - v = data.next_byte() - prefix = v >> 4 - length = lengths[prefix] - mask = masks[prefix] - - // Once the length is known, remove these bits and read any - // remaining bytes. - v = v & mask - repeat length-1 times: - v = (v << 8) + data.next_byte() - return v -~~~ -For example, the nine-byte sequence 0xf0ffffffffffffffff decodes to the decimal -value 18,446,744,073,709,551,615; the eight-byte sequence 0xe2197c5eff14e88c -decodes to the decimal value 151,288,809,941,952,652; the four-byte sequence -0xdd7f3e7d decodes to 494,878,333; the two-byte sequence 0xbbbd decodes to -15,293; and the single byte 0x25 decodes to 37 (as does the two-byte sequence -0x8025). - # Change Log RFC Editor's Note: Please remove this section prior to publication of a final version of this document. From 211018d47cadcabe262378eb7467d6765108c0ed Mon Sep 17 00:00:00 2001 From: afrind Date: Thu, 25 Sep 2025 19:58:41 -0400 Subject: [PATCH 11/13] no longer redefines i --- draft-ietf-moq-transport.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 29d5f784c..ee2ab0b21 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -266,8 +266,6 @@ x (L) ...: : Indicates that x is repeated zero or more times and that each instance has a length of L -This document redefines the following RFC9000 syntax: - x (vi64): : Indicates that x holds an integer value using the variable-length From 086de2c125d2494e5865aa30ddee2f42ef57b81c Mon Sep 17 00:00:00 2001 From: afrind Date: Thu, 25 Sep 2025 19:59:05 -0400 Subject: [PATCH 12/13] Update draft-ietf-moq-transport.md --- draft-ietf-moq-transport.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index ee2ab0b21..3d2752352 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -264,7 +264,7 @@ x (..): x (L) ...: : Indicates that x is repeated zero or more times and that each instance - has a length of L + has a length of L. x (vi64): From ca87191c32b89cc9bb1b84e9a3929abcdf183579 Mon Sep 17 00:00:00 2001 From: afrind Date: Tue, 30 Sep 2025 13:55:19 -0700 Subject: [PATCH 13/13] Make ranges exact with no commas --- draft-ietf-moq-transport.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/draft-ietf-moq-transport.md b/draft-ietf-moq-transport.md index 3d2752352..8c1e2f1f2 100644 --- a/draft-ietf-moq-transport.md +++ b/draft-ietf-moq-transport.md @@ -287,19 +287,19 @@ Integers are encoded in 1, 2, 4, 8, or 9 bytes and can encode 7-, 14-, 29-, 60-, or 64-bit values, respectively. The following table summarizes the encoding properties. -|--------------|----------------|-------------|---------------| -| Leading Bits | Length (bytes) | Usable Bits | Range | -|--------------|----------------|-------------|---------------| -| 0 | 1 | 7 | 0-127 | -|--------------|----------------|-------------|---------------| -| 10 | 2 | 14 | 0-16,383 | -|--------------|----------------|-------------|---------------| -| 110 | 4 | 29 | 0-536,870,911 | -|--------------|----------------|-------------|---------------| -| 1110 | 8 | 60 | 0-2^60-1 | -|--------------|----------------|-------------|---------------| -| 11110000 | 9 | 64 | 0-2^64-1 | -|--------------|----------------|-------------|---------------| +|--------------|----------------|-------------|------------------------| +| Leading Bits | Length (bytes) | Usable Bits | Range | +|--------------|----------------|-------------|------------------------| +| 0 | 1 | 7 | 0-127 | +|--------------|----------------|-------------|------------------------| +| 10 | 2 | 14 | 0-16383 | +|--------------|----------------|-------------|------------------------| +| 110 | 4 | 29 | 0-536870911 | +|--------------|----------------|-------------|------------------------| +| 1110 | 8 | 60 | 0-1152921504606846975 | +|--------------|----------------|-------------|------------------------| +| 11110000 | 9 | 64 | 0-18446744073709551615 | +|--------------|----------------|-------------|------------------------| {: format title="Summary of Integer Encodings"} For example, the nine-byte sequence 0xf0ffffffffffffffff decodes to the decimal