@ndn/lp
Version:
NDNts: NDN Link Protocol
90 lines (89 loc) • 2.71 kB
JavaScript
import { concatBuffers, evict } from "@ndn/util";
import { LpPacket } from "./packet_node.js";
class PartialPacket {
seqNumBase;
constructor(seqNumBase) {
this.seqNumBase = seqNumBase;
}
buffer = [];
accepted = 0;
payloadLength = 0;
accept(fragment) {
if (this.accepted === 0) { // first
this.buffer.length = fragment.fragCount;
this.acceptOne(fragment);
return undefined;
}
if (fragment.fragCount !== this.buffer.length) { // mismatch
return false;
}
if (this.buffer[fragment.fragIndex]) { // duplicate
return undefined;
}
this.acceptOne(fragment);
if (this.accepted === this.buffer.length) {
return this.reassemble();
}
return undefined;
}
acceptOne(fragment) {
this.buffer[fragment.fragIndex] = fragment;
++this.accepted;
this.payloadLength += fragment.payload?.length ?? 0;
}
reassemble() {
const full = Object.assign(new LpPacket(), this.buffer[0].l3);
const parts = [];
for (const fragment of this.buffer) {
const part = fragment.payload;
if (part) {
parts.push(part);
}
}
full.payload = concatBuffers(parts, this.payloadLength);
return full;
}
}
/** NDNLPv2 reassembler. */
export class Reassembler {
capacity;
constructor(capacity) {
this.capacity = capacity;
}
partials = new Map();
/**
* Process a fragment.
* @returns Fully reassembled packet, or undefined if packet is not yet complete.
*/
accept(fragment) {
if (fragment.fragCount === 1) { // not fragmented
return fragment;
}
if (fragment.fragSeqNum === undefined ||
fragment.fragIndex >= fragment.fragCount) { // bad fragment
return undefined;
}
const seqNumBase = BigInt.asUintN(64, fragment.fragSeqNum - BigInt(fragment.fragIndex));
const partial = this.getPartial(seqNumBase);
const result = partial.accept(fragment);
if (result) {
return result;
}
if (result !== false) {
this.putPartial(partial);
}
return undefined;
}
getPartial(seqNumBase) {
const partial = this.partials.get(seqNumBase);
if (partial) {
this.partials.delete(seqNumBase);
return partial;
}
return new PartialPacket(seqNumBase);
}
putPartial(partial) {
this.partials.set(partial.seqNumBase, partial);
evict(this.capacity, this.partials);
}
}