@ndn/lp
Version:
NDNts: NDN Link Protocol
90 lines (89 loc) • 2.88 kB
JavaScript
import { NackHeader } from "@ndn/packet";
import { Encoder, EvDecoder, NNI } from "@ndn/tlv";
import { assert } from "@ndn/util";
import { TT } from "./an_node.js";
function isCritical(tt) {
return !(tt >= 800 && tt <= 959 && tt % 4 === 0);
}
const EVD = new EvDecoder("LpPacket", TT.LpPacket)
.add(TT.LpSeqNum, (t, { nniBig }) => t.fragSeqNum = nniBig)
.add(TT.FragIndex, (t, { nni }) => t.fragIndex = nni)
.add(TT.FragCount, (t, { nni }) => t.fragCount = nni)
.add(TT.PitToken, (t, { value }) => t.pitToken = value)
.add(TT.Nack, (t, { decoder }) => t.nack = decoder.decode(NackHeader))
.add(TT.CongestionMark, (t, { nni }) => t.congestionMark = nni)
.add(TT.LpPayload, (t, { value }) => t.payload = value)
.setIsCritical(isCritical);
/** NDNLPv2 packet. */
export class LpPacket {
static decodeFrom(decoder) {
return EVD.decode(new LpPacket(), decoder);
}
fragSeqNum;
fragIndex = 0;
fragCount = 1;
/**
* L3 payload.
*
* @remarks
* This field may contain either a whole L3 packet or fragment of one.
* This is also known as *fragment* in other libraries.
*/
payload;
/**
* Extract L3 fields only.
*
* @remarks
* They may be copied to another LpPacket via `Object.assign()`.
*/
get l3() {
const t = {};
for (const k of ["pitToken", "nack", "congestionMark"]) {
t[k] = this[k];
}
return t;
}
/**
* Prepend LpPacket to encoder.
*
* @throws Error
* Thrown if fragmentation headers violate invariants:
* - `.fragIndex >= .fragCount`
* - `.fragSeqNum` is unset but `.fragCount > 1`
*/
encodeTo(encoder) {
encoder.prependTlv(TT.LpPacket, ...this.encodeFragHeaders(), ...this.encodeL3Headers(), [TT.LpPayload, Encoder.OmitEmpty, this.payload]);
}
encodeFragHeaders() {
assert(this.fragIndex < this.fragCount);
if (this.fragSeqNum === undefined) {
assert(this.fragCount === 1);
return [];
}
return [
[TT.LpSeqNum, NNI(this.fragSeqNum, { len: 8 })],
this.fragIndex > 0 && [TT.FragIndex, NNI(this.fragIndex)],
this.fragCount > 1 && [TT.FragCount, NNI(this.fragCount)],
];
}
/**
* Determine whether any L3 header is present.
* @see {@link LpL3}
*/
hasL3Headers() {
const { congestionMark = 0 } = this;
return !!this.pitToken || !!this.nack || congestionMark > 0;
}
/**
* Encode L3 headers.
* @see {@link LpL3}
*/
encodeL3Headers() {
const { congestionMark = 0 } = this;
return [
[TT.PitToken, Encoder.OmitEmpty, this.pitToken],
this.nack,
congestionMark > 0 && [TT.CongestionMark, NNI(congestionMark)],
];
}
}