UNPKG

@ndn/lp

Version:
118 lines (117 loc) 4.09 kB
import { __importDefault, __importStar } from "tslib"; import { Data, Interest, Nack, TT as l3TT } from "@ndn/packet"; import { Decoder, Encoder, printTT } from "@ndn/tlv"; import { assert, flatMapOnce, toHex } from "@ndn/util"; import _cjsDefaultImport0 from "it-keepalive"; const itKeepAlive = __importDefault(_cjsDefaultImport0).default; import { TT } from "./an_browser.js"; import { Fragmenter } from "./fragmenter_browser.js"; import { LpPacket } from "./packet_browser.js"; import { Reassembler } from "./reassembler_browser.js"; const IDLE = Encoder.encode(new LpPacket()); /** NDNLPv2 service. */ export class LpService { transport; constructor({ keepAlive = 60000, mtu = Infinity, reassemblerCapacity = 16, }, transport) { this.transport = transport; if (Number.isFinite(keepAlive) && keepAlive > 0) { this.keepAlive = Math.ceil(keepAlive); } this.mtu = mtu; this.reassembler = new Reassembler(reassemblerCapacity); } keepAlive; mtu; fragmenter = new Fragmenter(); reassembler; rx = (iterable) => flatMapOnce((tlv) => this.decode(tlv), iterable); *decode(dtlv) { const { type, decoder, tlv } = dtlv; try { if (type !== TT.LpPacket) { return yield this.decodeL3(dtlv); } const fragment = decoder.decode(LpPacket); const lpp = this.reassembler.accept(fragment); if (!lpp?.payload) { return; } const pkt = this.decodeL3(new Decoder(lpp.payload).read()); if (lpp.nack) { assert(pkt.l3 instanceof Interest, "Nack can only appear on Interest"); pkt.l3 = new Nack(pkt.l3, lpp.nack); } pkt.token = lpp.pitToken; pkt.congestionMark = lpp.congestionMark; yield pkt; } catch (err) { yield new LpService.RxError(err, tlv); } } decodeL3({ type, decoder }) { switch (type) { case l3TT.Interest: { return { l3: decoder.decode(Interest) }; } case l3TT.Data: { return { l3: decoder.decode(Data) }; } default: { throw new Error(`unrecognized TLV-TYPE ${printTT(type)} as L3Pkt`); } } } tx = (iterable) => flatMapOnce((pkt) => this.encode(pkt), this.keepAlive ? itKeepAlive(() => false, { timeout: this.keepAlive })(iterable) : iterable); *encode(pkt) { if (pkt === false) { yield IDLE; return; } const mtu = Math.min(this.mtu, this.transport.mtu); const { l3 } = pkt; const lpp = new LpPacket(); lpp.pitToken = pkt.token; lpp.congestionMark = pkt.congestionMark; try { if (l3 instanceof Nack) { lpp.nack = l3.header; lpp.payload = Encoder.encode(l3.interest); } else { lpp.payload = Encoder.encode(l3); } } catch (err) { return yield new LpService.TxError(err, l3); } if (!lpp.hasL3Headers() && lpp.payload.length <= mtu) { yield lpp.payload; } else if (Number.isFinite(mtu)) { yield* this.fragmenter.fragment(lpp, mtu).map((fragment) => Encoder.encode(fragment, mtu)); } else { yield Encoder.encode(lpp); } } } (function (LpService) { class RxError extends Error { packet; constructor(inner, packet) { super(`${inner.message} ${toHex(packet)}`); this.packet = packet; } } LpService.RxError = RxError; class TxError extends Error { packet; constructor(inner, packet) { super(`${inner.message} ${packet instanceof Nack ? packet.interest.name : packet.name}`); this.packet = packet; } } LpService.TxError = TxError; })(LpService || (LpService = {}));