@blockcast/mmt-base 0.1.0 → 0.3.0-main.288475b64b3e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/fec-block-profile.d.ts +55 -0
- package/dist/fec-block-profile.d.ts.map +1 -0
- package/dist/fec-block-profile.js +132 -0
- package/dist/fec-block-profile.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/mmtp.d.ts +77 -56
- package/dist/mmtp.d.ts.map +1 -1
- package/dist/mmtp.js +260 -216
- package/dist/mmtp.js.map +1 -1
- package/dist/net-constants.d.ts +18 -0
- package/dist/net-constants.d.ts.map +1 -0
- package/dist/net-constants.js +18 -0
- package/dist/net-constants.js.map +1 -0
- package/dist/ntp-short.d.ts +47 -0
- package/dist/ntp-short.d.ts.map +1 -0
- package/dist/ntp-short.js +54 -0
- package/dist/ntp-short.js.map +1 -0
- package/dist/serial-number.d.ts +28 -0
- package/dist/serial-number.d.ts.map +1 -0
- package/dist/serial-number.js +44 -0
- package/dist/serial-number.js.map +1 -0
- package/dist/signalling.d.ts +314 -0
- package/dist/signalling.d.ts.map +1 -0
- package/dist/signalling.js +637 -0
- package/dist/signalling.js.map +1 -0
- package/package.json +9 -4
- package/src/fec-block-profile.ts +145 -0
- package/src/index.ts +5 -0
- package/src/mmtp.ts +334 -188
- package/src/net-constants.ts +17 -0
- package/src/ntp-short.ts +67 -0
- package/src/serial-number.ts +49 -0
- package/src/signalling.ts +860 -0
- package/src/alfec.test.ts +0 -176
- package/src/mmtp.test.ts +0 -769
package/src/ntp-short.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NTP short format (RFC 5905 §6): an unsigned 32-bit, 16.16 fixed-point count
|
|
3
|
+
* of seconds. The MMTP header `timestamp` field (ISO/IEC 23008-1 §9.2.2)
|
|
4
|
+
* carries each packet's UTC sending instant in this format, so the value wraps
|
|
5
|
+
* to 0 every 2^16 s (~18.2 h).
|
|
6
|
+
*
|
|
7
|
+
* Plain numeric order on these values breaks at every wrap: a retained
|
|
8
|
+
* `Math.max` stays at the pre-wrap value and every later instant compares as
|
|
9
|
+
* older. Order send times only with {@link compareNtpShort}, which applies
|
|
10
|
+
* RFC 1982 serial-number arithmetic over the field's width.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Width in bits of the MMTP `timestamp` field (NTP short). */
|
|
14
|
+
export const NTP_SHORT_BITS = 32
|
|
15
|
+
|
|
16
|
+
/** Number of distinct NTP-short values; the field wraps to 0 here. */
|
|
17
|
+
export const NTP_SHORT_MODULUS = 2 ** NTP_SHORT_BITS
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* RFC 1982 §3.2's `2^(SERIAL_BITS - 1)`. Two values whose forward distance is
|
|
21
|
+
* below this are ordered; exactly this far apart they are not ordered at all.
|
|
22
|
+
* Two instants must be less than this far apart (2^15 s, ~9.1 h of send time)
|
|
23
|
+
* for the comparison to give their true order.
|
|
24
|
+
*/
|
|
25
|
+
export const NTP_SHORT_HALF_RANGE = 2 ** (NTP_SHORT_BITS - 1)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Serial order of one NTP-short value relative to another.
|
|
29
|
+
*
|
|
30
|
+
* `'unordered'` is RFC 1982's undefined case: the values are exactly
|
|
31
|
+
* {@link NTP_SHORT_HALF_RANGE} apart, so neither precedes the other. It is
|
|
32
|
+
* never folded into `'before'` or `'after'`; each caller decides what an
|
|
33
|
+
* unorderable pair means for it.
|
|
34
|
+
*/
|
|
35
|
+
export type NtpShortOrder = 'before' | 'equal' | 'after' | 'unordered'
|
|
36
|
+
|
|
37
|
+
/** True when `value` is an NTP-short value: an integer in [0, NTP_SHORT_MODULUS). */
|
|
38
|
+
export function isNtpShort(value: number): boolean {
|
|
39
|
+
return Number.isInteger(value) && value >= 0 && value < NTP_SHORT_MODULUS
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* RFC 1982 serial comparison of NTP-short `a` against `b`: `'after'` when `a`
|
|
44
|
+
* is the later instant, `'before'` when it is the earlier one.
|
|
45
|
+
*
|
|
46
|
+
* The answer is the true order only while the two instants are less than
|
|
47
|
+
* {@link NTP_SHORT_HALF_RANGE} apart. Past that a 32-bit field cannot tell
|
|
48
|
+
* later from earlier, and the result names whichever direction is nearer.
|
|
49
|
+
* This is not a total order (it is not transitive across the whole space), so
|
|
50
|
+
* it must never be used to sort.
|
|
51
|
+
*
|
|
52
|
+
* @throws {RangeError} if either operand is not an NTP-short value
|
|
53
|
+
*/
|
|
54
|
+
export function compareNtpShort(a: number, b: number): NtpShortOrder {
|
|
55
|
+
if (!isNtpShort(a) || !isNtpShort(b)) {
|
|
56
|
+
throw new RangeError(
|
|
57
|
+
`NTP-short values must be integers in [0, 2^${NTP_SHORT_BITS}), got ${String(a)} and ${String(b)}`,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
if (a === b) return 'equal'
|
|
61
|
+
// Forward distance from b to a, reduced into [1, NTP_SHORT_MODULUS). Both
|
|
62
|
+
// operands are below 2^32, so every step is exact in a double.
|
|
63
|
+
const forward = (a - b + NTP_SHORT_MODULUS) % NTP_SHORT_MODULUS
|
|
64
|
+
if (forward < NTP_SHORT_HALF_RANGE) return 'after'
|
|
65
|
+
if (forward > NTP_SHORT_HALF_RANGE) return 'before'
|
|
66
|
+
return 'unordered'
|
|
67
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 1982 serial-number arithmetic for the 32-bit MMTP AL-FEC symbol
|
|
3
|
+
* counters (ISO/IEC 23008-1:2023 C.5.2 SS_ID, C.5.3 SS_Start).
|
|
4
|
+
*
|
|
5
|
+
* SS_ID is a 32-bit field, so a stream that runs long enough wraps it to 0.
|
|
6
|
+
* Ordering two SS_IDs (or two blocks by their first SS_ID) with `<` reads
|
|
7
|
+
* every post-wrap value as older than every pre-wrap one. Serial order
|
|
8
|
+
* agrees with `<` whenever the two values are less than 2^31 apart, so for
|
|
9
|
+
* every stream that has not reached the wrap the result is unchanged; only
|
|
10
|
+
* the order across the wrap point differs (BLO-35597 iso:5).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** 2^SERIAL_BITS for SERIAL_BITS = 32. */
|
|
14
|
+
export const SERIAL32_SPAN = 0x1_0000_0000
|
|
15
|
+
|
|
16
|
+
/** RFC 1982 §3.2's 2^(SERIAL_BITS - 1). */
|
|
17
|
+
export const SERIAL32_HALF = 0x8000_0000
|
|
18
|
+
|
|
19
|
+
function assertUint32(value: number, name: string): void {
|
|
20
|
+
if (!Number.isInteger(value) || value < 0 || value >= SERIAL32_SPAN) {
|
|
21
|
+
throw new RangeError(`${name} must be a uint32 (got ${value})`)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* RFC 1982 §3.1 addition, extended to negative `n` for the matching
|
|
27
|
+
* subtraction: `(s + n) mod 2^32`. `n` must lie in (-2^31, 2^31).
|
|
28
|
+
*/
|
|
29
|
+
export function serial32Add(s: number, n: number): number {
|
|
30
|
+
assertUint32(s, 's')
|
|
31
|
+
if (!Number.isInteger(n) || n <= -SERIAL32_HALF || n >= SERIAL32_HALF) {
|
|
32
|
+
throw new RangeError(`serial addend must lie in (-2^31, 2^31) (got ${n})`)
|
|
33
|
+
}
|
|
34
|
+
return (s + n + SERIAL32_SPAN) % SERIAL32_SPAN
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Forward distance from `from` to `to`: `(to - from) mod 2^32`. */
|
|
38
|
+
export function serial32Distance(from: number, to: number): number {
|
|
39
|
+
return (to - from) >>> 0
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* RFC 1982 §3.2: `a` precedes `b`. Values exactly 2^31 apart are unordered
|
|
44
|
+
* (neither precedes the other).
|
|
45
|
+
*/
|
|
46
|
+
export function serial32Precedes(a: number, b: number): boolean {
|
|
47
|
+
const distance = serial32Distance(a, b)
|
|
48
|
+
return distance !== 0 && distance < SERIAL32_HALF
|
|
49
|
+
}
|