UNPKG

@ndn/lp

Version:
90 lines (89 loc) 2.88 kB
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)], ]; } }