@ndn/lp
Version:
NDNts: NDN Link Protocol
118 lines (117 loc) • 4.08 kB
JavaScript
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_node.js";
import { Fragmenter } from "./fragmenter_node.js";
import { LpPacket } from "./packet_node.js";
import { Reassembler } from "./reassembler_node.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 = {}));