Comparing version 0.0.20210203 to 0.0.20210930
import { __importDefault, __importStar } from "tslib"; | ||
import { Data, Interest, Nack } from "@ndn/packet"; | ||
import { toHex } from "@ndn/tlv"; | ||
import _cjsDefaultImport0 from "mnemonist/multi-set.js"; const MultiSet = __importDefault(_cjsDefaultImport0).default; | ||
import { EventEmitter } from "events"; | ||
import _cjsDefaultImport0 from "mnemonist/multi-set.js"; const MultiSet = __importDefault(_cjsDefaultImport0).default; | ||
import _cjsDefaultImport1 from "p-defer"; const pDefer = __importDefault(_cjsDefaultImport1).default; | ||
import _cjsDefaultImport2 from "p-fifo"; const Fifo = __importDefault(_cjsDefaultImport2).default; | ||
import _cjsDefaultImport1 from "p-fifo"; const Fifo = __importDefault(_cjsDefaultImport1).default; | ||
import { buffer, filter, pipeline, tap } from "streaming-iterables"; | ||
const STOP = Symbol("FaceImpl.Stop"); | ||
function duplexFromRxTx(rxtx) { | ||
return (iterable) => { | ||
const rxtxD = rxtx; | ||
if (typeof rxtxD.duplex === "function") { | ||
return rxtxD.duplex(iterable); | ||
} | ||
const rxtxS = rxtx; | ||
rxtxS.tx(iterable); | ||
return rxtxS.rx; | ||
}; | ||
} | ||
function computeAnnouncement(name, announcement) { | ||
@@ -23,8 +32,14 @@ switch (typeof announcement) { | ||
this.fw = fw; | ||
this.rxtx = rxtx; | ||
this.routes = new MultiSet(); | ||
this.announcements = new MultiSet(); | ||
this.stopping = pDefer(); | ||
this.running = true; | ||
this.txQueue = new Fifo(); | ||
this.txQueueLength = 0; | ||
this.handleLowerUp = () => { | ||
this.emit("up"); | ||
}; | ||
this.handleLowerDown = () => { | ||
this.emit("down"); | ||
}; | ||
this.rxLoop = async (input) => { | ||
@@ -52,2 +67,3 @@ for await (const pkt of filter(() => this.running, input)) { | ||
advertiseFrom: true, | ||
routeCapture: true, | ||
...rxtx.attributes, | ||
@@ -58,14 +74,6 @@ ...attributes, | ||
fw.faces.add(this); | ||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
pipeline(() => this.txLoop(), buffer(this.fw.options.faceTxBuffer), tap((pkt) => fw.emit("pkttx", this, pkt)), (iterable) => { | ||
const rxtxT = rxtx; | ||
if (typeof rxtxT.transform === "function") { | ||
return rxtxT.transform(iterable); | ||
} | ||
const rxtxS = rxtx; | ||
rxtxS.tx(iterable); | ||
return rxtxS.rx; | ||
}, tap((pkt) => fw.emit("pktrx", this, pkt)), buffer(this.fw.options.faceRxBuffer), this.rxLoop); | ||
void pipeline(() => this.txLoop(), buffer(this.fw.options.faceTxBuffer), tap((pkt) => fw.emit("pkttx", this, pkt)), duplexFromRxTx(rxtx), tap((pkt) => fw.emit("pktrx", this, pkt)), buffer(this.fw.options.faceRxBuffer), this.rxLoop); | ||
rxtx.on?.("up", this.handleLowerUp); | ||
rxtx.on?.("down", this.handleLowerDown); | ||
} | ||
/** Shutdown the face. */ | ||
close() { | ||
@@ -76,2 +84,4 @@ if (!this.running) { | ||
this.running = false; | ||
this.rxtx.off?.("up", this.handleLowerUp); | ||
this.rxtx.off?.("down", this.handleLowerDown); | ||
this.fw.faces.delete(this); | ||
@@ -84,3 +94,3 @@ for (const nameHex of this.routes.keys()) { | ||
} | ||
this.stopping.resolve(STOP); | ||
void this.txQueue.push(false); | ||
this.emit("close"); | ||
@@ -90,10 +100,7 @@ this.fw.emit("facerm", this); | ||
toString() { | ||
var _a; | ||
return (_a = this.attributes.describe) !== null && _a !== void 0 ? _a : "FwFace"; | ||
return this.attributes.describe ?? "FwFace"; | ||
} | ||
/** Determine if a route is present on the face. */ | ||
hasRoute(name) { | ||
return this.routes.has(toHex(name.value)); | ||
} | ||
/** Add a route toward the face. */ | ||
addRoute(name, announcement = true) { | ||
@@ -104,3 +111,3 @@ this.fw.emit("prefixadd", this, name); | ||
if (this.routes.count(nameHex) === 1) { | ||
this.fw.fib.insert(this, nameHex); | ||
this.fw.fib.insert(this, nameHex, this.attributes.routeCapture); | ||
} | ||
@@ -112,3 +119,2 @@ const ann = computeAnnouncement(name, announcement); | ||
} | ||
/** Remove a route toward the face. */ | ||
removeRoute(name, announcement = true) { | ||
@@ -126,3 +132,2 @@ const ann = computeAnnouncement(name, announcement); | ||
} | ||
/** Add a prefix announcement associated with the face. */ | ||
addAnnouncement(name) { | ||
@@ -138,3 +143,2 @@ if (!this.attributes.advertiseFrom) { | ||
} | ||
/** Remove a prefix announcement associated with the face. */ | ||
removeAnnouncement(name) { | ||
@@ -152,3 +156,6 @@ if (!this.attributes.advertiseFrom) { | ||
send(pkt) { | ||
(async () => { | ||
if (!this.running) { | ||
return; | ||
} | ||
void (async () => { | ||
++this.txQueueLength; | ||
@@ -161,7 +168,4 @@ await this.txQueue.push(pkt); | ||
while (true) { | ||
const pkt = await Promise.race([ | ||
this.stopping.promise, | ||
this.txQueue.shift(), | ||
]); | ||
if (pkt === STOP) { | ||
const pkt = await this.txQueue.shift(); | ||
if (!this.running || pkt === false) { | ||
break; | ||
@@ -171,10 +175,7 @@ } | ||
} | ||
while (!this.txQueue.isEmpty()) { | ||
void this.txQueue.shift(); | ||
} | ||
this.close(); | ||
} | ||
} | ||
(function (FaceImpl) { | ||
FaceImpl.DefaultOptions = { | ||
faceRxBuffer: 16, | ||
faceTxBuffer: 16, | ||
}; | ||
})(FaceImpl || (FaceImpl = {})); |
import { __importDefault, __importStar } from "tslib"; | ||
import { Data, Interest, Nack } from "@ndn/packet"; | ||
import { toHex } from "@ndn/tlv"; | ||
import { EventEmitter } from "events"; | ||
import _cjsDefaultImport0 from "mnemonist/multi-set.js"; const MultiSet = __importDefault(_cjsDefaultImport0).default; | ||
import _cjsDefaultImport1 from "p-defer"; const pDefer = __importDefault(_cjsDefaultImport1).default; | ||
import _cjsDefaultImport2 from "p-fifo"; const Fifo = __importDefault(_cjsDefaultImport2).default; | ||
import { EventEmitter } from "node:events"; | ||
import _cjsDefaultImport1 from "p-fifo"; const Fifo = __importDefault(_cjsDefaultImport1).default; | ||
import { buffer, filter, pipeline, tap } from "streaming-iterables"; | ||
const STOP = Symbol("FaceImpl.Stop"); | ||
function duplexFromRxTx(rxtx) { | ||
return (iterable) => { | ||
const rxtxD = rxtx; | ||
if (typeof rxtxD.duplex === "function") { | ||
return rxtxD.duplex(iterable); | ||
} | ||
const rxtxS = rxtx; | ||
rxtxS.tx(iterable); | ||
return rxtxS.rx; | ||
}; | ||
} | ||
function computeAnnouncement(name, announcement) { | ||
@@ -23,8 +32,14 @@ switch (typeof announcement) { | ||
this.fw = fw; | ||
this.rxtx = rxtx; | ||
this.routes = new MultiSet(); | ||
this.announcements = new MultiSet(); | ||
this.stopping = pDefer(); | ||
this.running = true; | ||
this.txQueue = new Fifo(); | ||
this.txQueueLength = 0; | ||
this.handleLowerUp = () => { | ||
this.emit("up"); | ||
}; | ||
this.handleLowerDown = () => { | ||
this.emit("down"); | ||
}; | ||
this.rxLoop = async (input) => { | ||
@@ -52,2 +67,3 @@ for await (const pkt of filter(() => this.running, input)) { | ||
advertiseFrom: true, | ||
routeCapture: true, | ||
...rxtx.attributes, | ||
@@ -58,14 +74,6 @@ ...attributes, | ||
fw.faces.add(this); | ||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
pipeline(() => this.txLoop(), buffer(this.fw.options.faceTxBuffer), tap((pkt) => fw.emit("pkttx", this, pkt)), (iterable) => { | ||
const rxtxT = rxtx; | ||
if (typeof rxtxT.transform === "function") { | ||
return rxtxT.transform(iterable); | ||
} | ||
const rxtxS = rxtx; | ||
rxtxS.tx(iterable); | ||
return rxtxS.rx; | ||
}, tap((pkt) => fw.emit("pktrx", this, pkt)), buffer(this.fw.options.faceRxBuffer), this.rxLoop); | ||
void pipeline(() => this.txLoop(), buffer(this.fw.options.faceTxBuffer), tap((pkt) => fw.emit("pkttx", this, pkt)), duplexFromRxTx(rxtx), tap((pkt) => fw.emit("pktrx", this, pkt)), buffer(this.fw.options.faceRxBuffer), this.rxLoop); | ||
rxtx.on?.("up", this.handleLowerUp); | ||
rxtx.on?.("down", this.handleLowerDown); | ||
} | ||
/** Shutdown the face. */ | ||
close() { | ||
@@ -76,2 +84,4 @@ if (!this.running) { | ||
this.running = false; | ||
this.rxtx.off?.("up", this.handleLowerUp); | ||
this.rxtx.off?.("down", this.handleLowerDown); | ||
this.fw.faces.delete(this); | ||
@@ -84,3 +94,3 @@ for (const nameHex of this.routes.keys()) { | ||
} | ||
this.stopping.resolve(STOP); | ||
void this.txQueue.push(false); | ||
this.emit("close"); | ||
@@ -90,10 +100,7 @@ this.fw.emit("facerm", this); | ||
toString() { | ||
var _a; | ||
return (_a = this.attributes.describe) !== null && _a !== void 0 ? _a : "FwFace"; | ||
return this.attributes.describe ?? "FwFace"; | ||
} | ||
/** Determine if a route is present on the face. */ | ||
hasRoute(name) { | ||
return this.routes.has(toHex(name.value)); | ||
} | ||
/** Add a route toward the face. */ | ||
addRoute(name, announcement = true) { | ||
@@ -104,3 +111,3 @@ this.fw.emit("prefixadd", this, name); | ||
if (this.routes.count(nameHex) === 1) { | ||
this.fw.fib.insert(this, nameHex); | ||
this.fw.fib.insert(this, nameHex, this.attributes.routeCapture); | ||
} | ||
@@ -112,3 +119,2 @@ const ann = computeAnnouncement(name, announcement); | ||
} | ||
/** Remove a route toward the face. */ | ||
removeRoute(name, announcement = true) { | ||
@@ -126,3 +132,2 @@ const ann = computeAnnouncement(name, announcement); | ||
} | ||
/** Add a prefix announcement associated with the face. */ | ||
addAnnouncement(name) { | ||
@@ -138,3 +143,2 @@ if (!this.attributes.advertiseFrom) { | ||
} | ||
/** Remove a prefix announcement associated with the face. */ | ||
removeAnnouncement(name) { | ||
@@ -152,3 +156,6 @@ if (!this.attributes.advertiseFrom) { | ||
send(pkt) { | ||
(async () => { | ||
if (!this.running) { | ||
return; | ||
} | ||
void (async () => { | ||
++this.txQueueLength; | ||
@@ -161,7 +168,4 @@ await this.txQueue.push(pkt); | ||
while (true) { | ||
const pkt = await Promise.race([ | ||
this.stopping.promise, | ||
this.txQueue.shift(), | ||
]); | ||
if (pkt === STOP) { | ||
const pkt = await this.txQueue.shift(); | ||
if (!this.running || pkt === false) { | ||
break; | ||
@@ -171,10 +175,7 @@ } | ||
} | ||
while (!this.txQueue.isEmpty()) { | ||
void this.txQueue.shift(); | ||
} | ||
this.close(); | ||
} | ||
} | ||
(function (FaceImpl) { | ||
FaceImpl.DefaultOptions = { | ||
faceRxBuffer: 16, | ||
faceTxBuffer: 16, | ||
}; | ||
})(FaceImpl || (FaceImpl = {})); |
@@ -6,16 +6,15 @@ import { Name } from "@ndn/packet"; | ||
interface Events { | ||
/** Emitted upon face closing. */ | ||
/** Emitted upon face is up as reported by lower layer. */ | ||
up: () => void; | ||
/** Emitted upon face is down as reported by lower layer. */ | ||
down: () => void; | ||
/** Emitted upon face is closed. */ | ||
close: () => void; | ||
} | ||
declare const FaceImpl_base: new () => TypedEmitter<Events>; | ||
export declare class FaceImpl extends FaceImpl_base { | ||
readonly fw: ForwarderImpl; | ||
/** A socket or network interface associated with forwarding plane. */ | ||
export interface FwFace extends TypedEmitter<Events> { | ||
readonly fw: Forwarder; | ||
readonly attributes: FwFace.Attributes; | ||
private readonly routes; | ||
private readonly announcements; | ||
private readonly stopping; | ||
running: boolean; | ||
private readonly txQueue; | ||
txQueueLength: number; | ||
constructor(fw: ForwarderImpl, rxtx: FwFace.RxTx | FwFace.RxTxTransform, attributes: FwFace.Attributes); | ||
readonly running: boolean; | ||
readonly txQueueLength: number; | ||
/** Shutdown the face. */ | ||
@@ -34,22 +33,5 @@ close(): void; | ||
removeAnnouncement(name: Name): void; | ||
/** Transmit a packet on the face. */ | ||
send(pkt: FwPacket): void; | ||
private rxLoop; | ||
private txLoop; | ||
} | ||
export declare namespace FaceImpl { | ||
interface Options { | ||
faceRxBuffer: number; | ||
faceTxBuffer: number; | ||
} | ||
const DefaultOptions: Options; | ||
} | ||
/** A socket or network interface associated with forwarding plane. */ | ||
export interface FwFace extends Pick<FaceImpl, "attributes" | "close" | "toString" | "hasRoute" | "addRoute" | "removeRoute" | "addAnnouncement" | "removeAnnouncement" | Exclude<keyof TypedEmitter<Events>, "emit">> { | ||
readonly fw: Forwarder; | ||
readonly running: boolean; | ||
readonly txQueueLength: number; | ||
} | ||
export declare namespace FwFace { | ||
export interface Attributes extends Record<string, any> { | ||
interface Attributes extends Record<string, any> { | ||
/** Short string to identify the face. */ | ||
@@ -61,12 +43,22 @@ describe?: string; | ||
advertiseFrom?: boolean; | ||
/** | ||
* Whether routes registered on this face would cause FIB to stop matching onto shorter prefixes. | ||
* Default is true. | ||
* More explanation in @ndn/endpoint package ProducerOptions type. | ||
*/ | ||
routeCapture?: boolean; | ||
} | ||
export type RouteAnnouncement = boolean | number | Name; | ||
interface RxTxBase { | ||
type RouteAnnouncement = boolean | number | Name; | ||
interface RxTxEvents { | ||
up: () => void; | ||
down: () => void; | ||
} | ||
interface RxTxBase extends Partial<TypedEmitter<RxTxEvents>> { | ||
readonly attributes?: Attributes; | ||
} | ||
export interface RxTx extends RxTxBase { | ||
interface RxTx extends RxTxBase { | ||
rx: AsyncIterable<FwPacket>; | ||
tx: (iterable: AsyncIterable<FwPacket>) => void; | ||
} | ||
export interface RxTxTransform extends RxTxBase { | ||
interface RxTxDuplex extends RxTxBase { | ||
/** | ||
@@ -76,6 +68,30 @@ * The transform function takes an iterable of packets sent by the forwarder, | ||
*/ | ||
transform: (iterable: AsyncIterable<FwPacket>) => AsyncIterable<FwPacket>; | ||
duplex: (iterable: AsyncIterable<FwPacket>) => AsyncIterable<FwPacket>; | ||
} | ||
export {}; | ||
} | ||
declare const FaceImpl_base: new () => TypedEmitter<Events>; | ||
export declare class FaceImpl extends FaceImpl_base implements FwFace { | ||
readonly fw: ForwarderImpl; | ||
private readonly rxtx; | ||
readonly attributes: FwFace.Attributes; | ||
private readonly routes; | ||
private readonly announcements; | ||
running: boolean; | ||
private readonly txQueue; | ||
txQueueLength: number; | ||
constructor(fw: ForwarderImpl, rxtx: FwFace.RxTx | FwFace.RxTxDuplex, attributes: FwFace.Attributes); | ||
close(): void; | ||
toString(): string; | ||
hasRoute(name: Name): boolean; | ||
addRoute(name: Name, announcement?: FwFace.RouteAnnouncement): void; | ||
removeRoute(name: Name, announcement?: FwFace.RouteAnnouncement): void; | ||
addAnnouncement(name: Name): void; | ||
removeAnnouncement(name: Name): void; | ||
/** Transmit a packet on the face. */ | ||
send(pkt: FwPacket): void; | ||
private readonly handleLowerUp; | ||
private readonly handleLowerDown; | ||
private readonly rxLoop; | ||
private txLoop; | ||
} | ||
export {}; |
@@ -7,3 +7,3 @@ import { __importDefault, __importStar } from "tslib"; | ||
constructor() { | ||
this.nexthops = new Set(); | ||
this.nexthops = new Map(); // face=>capture | ||
} | ||
@@ -15,5 +15,6 @@ } | ||
} | ||
insert(face, nameHex) { | ||
insert(face, nameHex, capture) { | ||
const entry = this.table.get(nameHex); | ||
entry.nexthops.add(face); | ||
assert(!entry.nexthops.has(face)); | ||
entry.nexthops.set(face, capture); | ||
} | ||
@@ -28,9 +29,16 @@ delete(face, nameHex) { | ||
} | ||
lpm(name) { | ||
const entry = lpm(name, (prefixHex) => this.table.peek(prefixHex)); | ||
if (entry) { | ||
assert(entry.nexthops.size > 0); | ||
lookup(name) { | ||
const result = new Set(); | ||
for (const entry of lpm(name, (prefixHex) => this.table.peek(prefixHex))) { | ||
let capture = false; | ||
for (const [nh, c] of entry.nexthops) { | ||
result.add(nh); | ||
capture || (capture = c); | ||
} | ||
if (capture) { | ||
break; | ||
} | ||
} | ||
return entry; | ||
return result; | ||
} | ||
} |
@@ -7,3 +7,3 @@ import { __importDefault, __importStar } from "tslib"; | ||
constructor() { | ||
this.nexthops = new Set(); | ||
this.nexthops = new Map(); // face=>capture | ||
} | ||
@@ -15,5 +15,6 @@ } | ||
} | ||
insert(face, nameHex) { | ||
insert(face, nameHex, capture) { | ||
const entry = this.table.get(nameHex); | ||
entry.nexthops.add(face); | ||
assert(!entry.nexthops.has(face)); | ||
entry.nexthops.set(face, capture); | ||
} | ||
@@ -28,9 +29,16 @@ delete(face, nameHex) { | ||
} | ||
lpm(name) { | ||
const entry = lpm(name, (prefixHex) => this.table.peek(prefixHex)); | ||
if (entry) { | ||
assert(entry.nexthops.size > 0); | ||
lookup(name) { | ||
const result = new Set(); | ||
for (const entry of lpm(name, (prefixHex) => this.table.peek(prefixHex))) { | ||
let capture = false; | ||
for (const [nh, c] of entry.nexthops) { | ||
result.add(nh); | ||
capture || (capture = c); | ||
} | ||
if (capture) { | ||
break; | ||
} | ||
} | ||
return entry; | ||
return result; | ||
} | ||
} |
import { Name } from "@ndn/packet"; | ||
import DefaultMap from "mnemonist/default-map.js"; | ||
import type { FaceImpl } from "./face"; | ||
declare class FibEntry { | ||
readonly nexthops: Set<FaceImpl>; | ||
} | ||
export declare class Fib { | ||
readonly table: DefaultMap<string, FibEntry>; | ||
insert(face: FaceImpl, nameHex: string): void; | ||
private readonly table; | ||
insert(face: FaceImpl, nameHex: string, capture: boolean): void; | ||
delete(face: FaceImpl, nameHex: string): void; | ||
lpm(name: Name): FibEntry | undefined; | ||
lookup(name: Name): Set<FaceImpl>; | ||
} | ||
export {}; |
@@ -6,2 +6,38 @@ import { EventEmitter } from "events"; | ||
import { Readvertise } from "./readvertise_browser.js"; | ||
export var Forwarder; | ||
(function (Forwarder) { | ||
Forwarder.DefaultOptions = { | ||
faceRxBuffer: 16, | ||
faceTxBuffer: 16, | ||
dataNoTokenMatch: true, | ||
}; | ||
/** Create a new forwarding plane. */ | ||
function create(options) { | ||
return new ForwarderImpl({ ...Forwarder.DefaultOptions, ...options }); | ||
} | ||
Forwarder.create = create; | ||
let defaultInstance; | ||
/** Access the default forwarding plane instance. */ | ||
function getDefault() { | ||
if (!defaultInstance) { | ||
defaultInstance = Forwarder.create(); | ||
} | ||
return defaultInstance; | ||
} | ||
Forwarder.getDefault = getDefault; | ||
/** Replace the default forwarding plane instance. */ | ||
function replaceDefault(fw) { | ||
defaultInstance = fw; | ||
} | ||
Forwarder.replaceDefault = replaceDefault; | ||
/** Delete default instance (mainly for unit testing). */ | ||
function deleteDefault() { | ||
if (!defaultInstance) { | ||
return; | ||
} | ||
defaultInstance.close(); | ||
defaultInstance = undefined; | ||
} | ||
Forwarder.deleteDefault = deleteDefault; | ||
})(Forwarder || (Forwarder = {})); | ||
export class ForwarderImpl extends EventEmitter { | ||
@@ -11,11 +47,18 @@ constructor(options) { | ||
this.options = options; | ||
this.nodeNames = []; | ||
this.faces = new Set(); | ||
this.fib = new Fib(); | ||
this.pit = new Pit(); | ||
this.readvertise = new Readvertise(this); | ||
this.pit = new Pit(options.dataNoTokenMatch); | ||
} | ||
/** Add a face to the forwarding plane. */ | ||
addFace(face, attributes = {}) { | ||
return new FaceImpl(this, face, attributes); | ||
} | ||
pickInterestForwardingName(interest) { | ||
const fhName = interest.fwHint?.delegations[0]?.name; | ||
if (fhName && this.nodeNames.every((nodeName) => !fhName.isPrefixOf(nodeName))) { | ||
return fhName; | ||
} | ||
return interest.name; | ||
} | ||
/** Process incoming Interest. */ | ||
@@ -25,7 +68,4 @@ processInterest(face, pkt) { | ||
pi.receiveInterest(face, pkt); | ||
const fibEntry = this.fib.lpm(pkt.l3.name); | ||
if (!fibEntry) { | ||
return; | ||
} | ||
for (const nh of fibEntry.nexthops) { | ||
const fwName = this.pickInterestForwardingName(pkt.l3); | ||
for (const nh of this.fib.lookup(fwName)) { | ||
if (nh !== face) { | ||
@@ -39,8 +79,7 @@ pi.forwardInterest(nh); | ||
const pi = this.pit.lookup(pkt, false); | ||
pi === null || pi === void 0 ? void 0 : pi.cancelInterest(face); | ||
pi?.cancelInterest(face); | ||
} | ||
/** Process incoming Data. */ | ||
processData(face, pkt) { | ||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
this.pit.satisfy(face, pkt); | ||
void this.pit.satisfy(face, pkt); | ||
} | ||
@@ -50,26 +89,9 @@ /** Process incoming Nack. */ | ||
// ignore Nack | ||
void face; | ||
void nack; | ||
} | ||
close() { | ||
this.pit.close(); | ||
this.readvertise.close(); | ||
} | ||
} | ||
export var Forwarder; | ||
(function (Forwarder) { | ||
const DefaultOptions = { ...FaceImpl.DefaultOptions }; | ||
/** Create a new forwarding plane. */ | ||
function create(options) { | ||
return new ForwarderImpl({ ...DefaultOptions, ...options }); | ||
} | ||
Forwarder.create = create; | ||
let defaultInstance; | ||
/** Access the default forwarding plane instance. */ | ||
function getDefault() { | ||
if (!defaultInstance) { | ||
defaultInstance = Forwarder.create(); | ||
} | ||
return defaultInstance; | ||
} | ||
Forwarder.getDefault = getDefault; | ||
/** Delete default instance (mainly for unit testing). */ | ||
function deleteDefault() { | ||
defaultInstance = undefined; | ||
} | ||
Forwarder.deleteDefault = deleteDefault; | ||
})(Forwarder || (Forwarder = {})); |
@@ -1,2 +0,2 @@ | ||
import { EventEmitter } from "events"; | ||
import { EventEmitter } from "node:events"; | ||
import { FaceImpl } from "./face_node.js"; | ||
@@ -6,2 +6,38 @@ import { Fib } from "./fib_node.js"; | ||
import { Readvertise } from "./readvertise_node.js"; | ||
export var Forwarder; | ||
(function (Forwarder) { | ||
Forwarder.DefaultOptions = { | ||
faceRxBuffer: 16, | ||
faceTxBuffer: 16, | ||
dataNoTokenMatch: true, | ||
}; | ||
/** Create a new forwarding plane. */ | ||
function create(options) { | ||
return new ForwarderImpl({ ...Forwarder.DefaultOptions, ...options }); | ||
} | ||
Forwarder.create = create; | ||
let defaultInstance; | ||
/** Access the default forwarding plane instance. */ | ||
function getDefault() { | ||
if (!defaultInstance) { | ||
defaultInstance = Forwarder.create(); | ||
} | ||
return defaultInstance; | ||
} | ||
Forwarder.getDefault = getDefault; | ||
/** Replace the default forwarding plane instance. */ | ||
function replaceDefault(fw) { | ||
defaultInstance = fw; | ||
} | ||
Forwarder.replaceDefault = replaceDefault; | ||
/** Delete default instance (mainly for unit testing). */ | ||
function deleteDefault() { | ||
if (!defaultInstance) { | ||
return; | ||
} | ||
defaultInstance.close(); | ||
defaultInstance = undefined; | ||
} | ||
Forwarder.deleteDefault = deleteDefault; | ||
})(Forwarder || (Forwarder = {})); | ||
export class ForwarderImpl extends EventEmitter { | ||
@@ -11,11 +47,18 @@ constructor(options) { | ||
this.options = options; | ||
this.nodeNames = []; | ||
this.faces = new Set(); | ||
this.fib = new Fib(); | ||
this.pit = new Pit(); | ||
this.readvertise = new Readvertise(this); | ||
this.pit = new Pit(options.dataNoTokenMatch); | ||
} | ||
/** Add a face to the forwarding plane. */ | ||
addFace(face, attributes = {}) { | ||
return new FaceImpl(this, face, attributes); | ||
} | ||
pickInterestForwardingName(interest) { | ||
const fhName = interest.fwHint?.delegations[0]?.name; | ||
if (fhName && this.nodeNames.every((nodeName) => !fhName.isPrefixOf(nodeName))) { | ||
return fhName; | ||
} | ||
return interest.name; | ||
} | ||
/** Process incoming Interest. */ | ||
@@ -25,7 +68,4 @@ processInterest(face, pkt) { | ||
pi.receiveInterest(face, pkt); | ||
const fibEntry = this.fib.lpm(pkt.l3.name); | ||
if (!fibEntry) { | ||
return; | ||
} | ||
for (const nh of fibEntry.nexthops) { | ||
const fwName = this.pickInterestForwardingName(pkt.l3); | ||
for (const nh of this.fib.lookup(fwName)) { | ||
if (nh !== face) { | ||
@@ -39,8 +79,7 @@ pi.forwardInterest(nh); | ||
const pi = this.pit.lookup(pkt, false); | ||
pi === null || pi === void 0 ? void 0 : pi.cancelInterest(face); | ||
pi?.cancelInterest(face); | ||
} | ||
/** Process incoming Data. */ | ||
processData(face, pkt) { | ||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
this.pit.satisfy(face, pkt); | ||
void this.pit.satisfy(face, pkt); | ||
} | ||
@@ -50,26 +89,9 @@ /** Process incoming Nack. */ | ||
// ignore Nack | ||
void face; | ||
void nack; | ||
} | ||
close() { | ||
this.pit.close(); | ||
this.readvertise.close(); | ||
} | ||
} | ||
export var Forwarder; | ||
(function (Forwarder) { | ||
const DefaultOptions = { ...FaceImpl.DefaultOptions }; | ||
/** Create a new forwarding plane. */ | ||
function create(options) { | ||
return new ForwarderImpl({ ...DefaultOptions, ...options }); | ||
} | ||
Forwarder.create = create; | ||
let defaultInstance; | ||
/** Access the default forwarding plane instance. */ | ||
function getDefault() { | ||
if (!defaultInstance) { | ||
defaultInstance = Forwarder.create(); | ||
} | ||
return defaultInstance; | ||
} | ||
Forwarder.getDefault = getDefault; | ||
/** Delete default instance (mainly for unit testing). */ | ||
function deleteDefault() { | ||
defaultInstance = undefined; | ||
} | ||
Forwarder.deleteDefault = deleteDefault; | ||
})(Forwarder || (Forwarder = {})); |
@@ -26,5 +26,39 @@ import { Data, Interest, Nack, Name } from "@ndn/packet"; | ||
} | ||
/** Forwarding plane. */ | ||
export interface Forwarder extends TypedEmitter<Events> { | ||
/** Node names, used in forwarding hint processing. */ | ||
readonly nodeNames: Name[]; | ||
/** Logical faces. */ | ||
readonly faces: Set<FwFace>; | ||
/** Add a logical face to the forwarding plane. */ | ||
addFace(face: FwFace.RxTx | FwFace.RxTxDuplex, attributes?: FwFace.Attributes): FwFace; | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close(): void; | ||
} | ||
export declare namespace Forwarder { | ||
interface Options { | ||
/** Per-face RX buffer length. */ | ||
faceRxBuffer?: number; | ||
/** Per-face TX buffer length. */ | ||
faceTxBuffer?: number; | ||
/** Whether to try matching Data without PIT token. */ | ||
dataNoTokenMatch?: boolean; | ||
} | ||
const DefaultOptions: Required<Options>; | ||
/** Create a new forwarding plane. */ | ||
function create(options?: Options): Forwarder; | ||
/** Access the default forwarding plane instance. */ | ||
function getDefault(): Forwarder; | ||
/** Replace the default forwarding plane instance. */ | ||
function replaceDefault(fw?: Forwarder): void; | ||
/** Delete default instance (mainly for unit testing). */ | ||
function deleteDefault(): void; | ||
} | ||
declare const ForwarderImpl_base: new () => TypedEmitter<Events>; | ||
export declare class ForwarderImpl extends ForwarderImpl_base { | ||
readonly options: Forwarder.Options; | ||
export declare class ForwarderImpl extends ForwarderImpl_base implements Forwarder { | ||
readonly options: Required<Forwarder.Options>; | ||
readonly nodeNames: Name[]; | ||
readonly faces: Set<FaceImpl>; | ||
@@ -34,5 +68,5 @@ readonly fib: Fib; | ||
readonly readvertise: Readvertise; | ||
constructor(options: Forwarder.Options); | ||
/** Add a face to the forwarding plane. */ | ||
addFace(face: FwFace.RxTx | FwFace.RxTxTransform, attributes?: FwFace.Attributes): FwFace; | ||
constructor(options: Required<Forwarder.Options>); | ||
addFace(face: FwFace.RxTx | FwFace.RxTxDuplex, attributes?: FwFace.Attributes): FwFace; | ||
private pickInterestForwardingName; | ||
/** Process incoming Interest. */ | ||
@@ -46,17 +80,4 @@ processInterest(face: FaceImpl, pkt: FwPacket<Interest>): void; | ||
processNack(face: FaceImpl, nack: FwPacket<Nack>): void; | ||
close(): void; | ||
} | ||
/** Forwarding plane. */ | ||
export interface Forwarder extends Pick<ForwarderImpl, "addFace" | Exclude<keyof TypedEmitter<Events>, "emit">> { | ||
readonly faces: Set<FwFace>; | ||
readonly pit: Pick<Pit, "dataNoTokenMatch">; | ||
} | ||
export declare namespace Forwarder { | ||
type Options = FaceImpl.Options; | ||
/** Create a new forwarding plane. */ | ||
function create(options?: Options): Forwarder; | ||
/** Access the default forwarding plane instance. */ | ||
function getDefault(): Forwarder; | ||
/** Delete default instance (mainly for unit testing). */ | ||
function deleteDefault(): void; | ||
} | ||
export {}; |
@@ -0,0 +0,0 @@ export * from "./packet"; |
@@ -0,0 +0,0 @@ import type { Data, Interest, Nack } from "@ndn/packet"; |
@@ -20,4 +20,4 @@ import { __importDefault, __importStar } from "tslib"; | ||
this.pit.eraseEntry(this); | ||
for (const [face, dnR] of this.dnRecords) { | ||
face.send(new RejectInterest("expire", this.interest, dnR.token)); | ||
for (const [face, { token }] of this.dnRecords) { | ||
face.send(new RejectInterest("expire", this.interest, token)); | ||
} | ||
@@ -29,6 +29,5 @@ }; | ||
receiveInterest(face, { l3: interest, token }) { | ||
var _a; | ||
const now = getNow(); | ||
const expire = now + interest.lifetime; | ||
const nonce = (_a = interest.nonce) !== null && _a !== void 0 ? _a : Interest.generateNonce(); | ||
const nonce = interest.nonce ?? Interest.generateNonce(); | ||
const dnR = this.dnRecords.get(face); | ||
@@ -95,14 +94,7 @@ ++dnR.nRx; | ||
export class Pit { | ||
constructor() { | ||
constructor(dataNoTokenMatch) { | ||
this.dataNoTokenMatch = dataNoTokenMatch; | ||
this.byName = new Map(); | ||
this.byToken = new Map(); | ||
this.lastToken = 0; | ||
/** | ||
* true: try to match Data without token. | ||
* false: Data without token. | ||
* callback function: invoked when Data without token matches PIT entry. | ||
* return true: deliver matched PIT entry. | ||
* return false: drop Data. | ||
*/ | ||
this.dataNoTokenMatch = true; | ||
} | ||
@@ -119,5 +111,4 @@ generateToken() { | ||
insertEntry(entry) { | ||
var _a; | ||
this.byName.set(entry.key, entry); | ||
(_a = entry.token) !== null && _a !== void 0 ? _a : (entry.token = this.generateToken()); | ||
entry.token ?? (entry.token = this.generateToken()); | ||
this.byToken.set(entry.token, entry); | ||
@@ -129,2 +120,11 @@ } | ||
} | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close() { | ||
for (const entry of this.byName.values()) { | ||
clearTimeout(entry.expireTimer); | ||
} | ||
} | ||
lookup({ l3: interest }, canInsert = true) { | ||
@@ -140,3 +140,3 @@ const key = `${toHex(interest.name.value)} ${interest.canBePrefix ? "+" : "-"}${interest.mustBeFresh ? "+" : "-"}`; | ||
* Satisfy pending Interests with incoming Data. | ||
* @returns true if Data satisfies any pending Interest, or false if Data is unsolicited. | ||
* @returns true if Data satisfies any pending Interest; false if Data is unsolicited. | ||
*/ | ||
@@ -155,20 +155,17 @@ async satisfy(face, { l3: data, token }) { | ||
} | ||
if (this.dataNoTokenMatch === false) { | ||
if (!this.dataNoTokenMatch) { | ||
return; | ||
} | ||
for (let [prefix, exact] = [data.name, true]; prefix.length > 0; [prefix, exact] = [prefix.getPrefix(-1), false]) { | ||
let keySuffixes = [" ++", " +-", " -+", " --"]; | ||
for (let prefix = data.name; prefix.length > 0; prefix = prefix.getPrefix(-1)) { | ||
const prefixHex = toHex(prefix.value); | ||
for (const keySuffix of (exact ? [" ++", " +-", " -+", " --"] : [" ++", " +-"])) { | ||
const key = prefixHex + keySuffix; | ||
const entry = this.byName.get(key); | ||
for (const keySuffix of keySuffixes) { | ||
const entry = this.byName.get(prefixHex + keySuffix); | ||
if (entry) { | ||
if (typeof this.dataNoTokenMatch === "function" && | ||
!this.dataNoTokenMatch(data, key)) { | ||
return; | ||
} | ||
yield entry; | ||
} | ||
} | ||
keySuffixes = [" ++", " +-"]; | ||
} | ||
} | ||
} |
@@ -20,4 +20,4 @@ import { __importDefault, __importStar } from "tslib"; | ||
this.pit.eraseEntry(this); | ||
for (const [face, dnR] of this.dnRecords) { | ||
face.send(new RejectInterest("expire", this.interest, dnR.token)); | ||
for (const [face, { token }] of this.dnRecords) { | ||
face.send(new RejectInterest("expire", this.interest, token)); | ||
} | ||
@@ -29,6 +29,5 @@ }; | ||
receiveInterest(face, { l3: interest, token }) { | ||
var _a; | ||
const now = getNow(); | ||
const expire = now + interest.lifetime; | ||
const nonce = (_a = interest.nonce) !== null && _a !== void 0 ? _a : Interest.generateNonce(); | ||
const nonce = interest.nonce ?? Interest.generateNonce(); | ||
const dnR = this.dnRecords.get(face); | ||
@@ -95,14 +94,7 @@ ++dnR.nRx; | ||
export class Pit { | ||
constructor() { | ||
constructor(dataNoTokenMatch) { | ||
this.dataNoTokenMatch = dataNoTokenMatch; | ||
this.byName = new Map(); | ||
this.byToken = new Map(); | ||
this.lastToken = 0; | ||
/** | ||
* true: try to match Data without token. | ||
* false: Data without token. | ||
* callback function: invoked when Data without token matches PIT entry. | ||
* return true: deliver matched PIT entry. | ||
* return false: drop Data. | ||
*/ | ||
this.dataNoTokenMatch = true; | ||
} | ||
@@ -119,5 +111,4 @@ generateToken() { | ||
insertEntry(entry) { | ||
var _a; | ||
this.byName.set(entry.key, entry); | ||
(_a = entry.token) !== null && _a !== void 0 ? _a : (entry.token = this.generateToken()); | ||
entry.token ?? (entry.token = this.generateToken()); | ||
this.byToken.set(entry.token, entry); | ||
@@ -129,2 +120,11 @@ } | ||
} | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close() { | ||
for (const entry of this.byName.values()) { | ||
clearTimeout(entry.expireTimer); | ||
} | ||
} | ||
lookup({ l3: interest }, canInsert = true) { | ||
@@ -140,3 +140,3 @@ const key = `${toHex(interest.name.value)} ${interest.canBePrefix ? "+" : "-"}${interest.mustBeFresh ? "+" : "-"}`; | ||
* Satisfy pending Interests with incoming Data. | ||
* @returns true if Data satisfies any pending Interest, or false if Data is unsolicited. | ||
* @returns true if Data satisfies any pending Interest; false if Data is unsolicited. | ||
*/ | ||
@@ -155,20 +155,17 @@ async satisfy(face, { l3: data, token }) { | ||
} | ||
if (this.dataNoTokenMatch === false) { | ||
if (!this.dataNoTokenMatch) { | ||
return; | ||
} | ||
for (let [prefix, exact] = [data.name, true]; prefix.length > 0; [prefix, exact] = [prefix.getPrefix(-1), false]) { | ||
let keySuffixes = [" ++", " +-", " -+", " --"]; | ||
for (let prefix = data.name; prefix.length > 0; prefix = prefix.getPrefix(-1)) { | ||
const prefixHex = toHex(prefix.value); | ||
for (const keySuffix of (exact ? [" ++", " +-", " -+", " --"] : [" ++", " +-"])) { | ||
const key = prefixHex + keySuffix; | ||
const entry = this.byName.get(key); | ||
for (const keySuffix of keySuffixes) { | ||
const entry = this.byName.get(prefixHex + keySuffix); | ||
if (entry) { | ||
if (typeof this.dataNoTokenMatch === "function" && | ||
!this.dataNoTokenMatch(data, key)) { | ||
return; | ||
} | ||
yield entry; | ||
} | ||
} | ||
keySuffixes = [" ++", " +-"]; | ||
} | ||
} | ||
} |
@@ -14,3 +14,3 @@ /// <reference types="node" /> | ||
nonce: number; | ||
/** Last InterestToken from this downstream. */ | ||
/** Last PIT token from this downstream. */ | ||
token: unknown; | ||
@@ -49,16 +49,15 @@ } | ||
export declare class Pit { | ||
readonly byName: Map<string, PitEntry>; | ||
readonly byToken: Map<number, PitEntry>; | ||
readonly dataNoTokenMatch: boolean; | ||
constructor(dataNoTokenMatch: boolean); | ||
private readonly byName; | ||
private readonly byToken; | ||
private lastToken; | ||
/** | ||
* true: try to match Data without token. | ||
* false: Data without token. | ||
* callback function: invoked when Data without token matches PIT entry. | ||
* return true: deliver matched PIT entry. | ||
* return false: drop Data. | ||
*/ | ||
dataNoTokenMatch: boolean | ((data: Data, key: string) => boolean); | ||
private generateToken; | ||
insertEntry(entry: PitEntry): void; | ||
eraseEntry(entry: PitEntry): void; | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close(): void; | ||
/** Find or insert entry. */ | ||
@@ -70,3 +69,3 @@ lookup(interest: FwPacket<Interest>): PitEntry; | ||
* Satisfy pending Interests with incoming Data. | ||
* @returns true if Data satisfies any pending Interest, or false if Data is unsolicited. | ||
* @returns true if Data satisfies any pending Interest; false if Data is unsolicited. | ||
*/ | ||
@@ -73,0 +72,0 @@ satisfy(face: FaceImpl, { l3: data, token }: FwPacket<Data>): Promise<boolean>; |
@@ -35,3 +35,3 @@ import { __importDefault, __importStar } from "tslib"; | ||
} | ||
name !== null && name !== void 0 ? name : (name = new Name(fromHex(nameHex))); | ||
name ?? (name = new Name(fromHex(nameHex))); | ||
this.fw.emit("annrm", name); | ||
@@ -42,2 +42,11 @@ for (const dest of this.destinations) { | ||
} | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close() { | ||
for (const dest of this.destinations) { | ||
dest.disable(); | ||
} | ||
} | ||
} | ||
@@ -48,3 +57,3 @@ /** | ||
* Generally, a prefix advertised to a destination would cause Interests matching the prefix | ||
* to come to the forwarder. aka prefix registration. | ||
* to come to the forwarder, aka prefix registration. | ||
*/ | ||
@@ -70,3 +79,3 @@ export class ReadvertiseDestination { | ||
} | ||
this.process(); // eslint-disable-line @typescript-eslint/no-floating-promises | ||
void this.process(); | ||
} | ||
@@ -79,4 +88,3 @@ /** | ||
disable() { | ||
var _a; | ||
(_a = this.readvertise) === null || _a === void 0 ? void 0 : _a.destinations.delete(this); | ||
this.readvertise?.destinations.delete(this); | ||
this.readvertise = undefined; | ||
@@ -106,2 +114,3 @@ for (const [nameHex, record] of this.table) { | ||
withdraw(name, nameHex) { | ||
void name; | ||
const record = this.table.get(nameHex); | ||
@@ -115,4 +124,3 @@ if (!record) { | ||
restart(nameHex, record) { | ||
var _a; | ||
(_a = record.retry) === null || _a === void 0 ? void 0 : _a.stop(); | ||
record.retry?.stop(); | ||
record.retry = retry.operation(this.retryOptions); | ||
@@ -166,2 +174,4 @@ record.retry.attempt(() => { | ||
makeState(name, nameHex) { | ||
void name; | ||
void nameHex; | ||
return {}; | ||
@@ -168,0 +178,0 @@ } |
@@ -35,3 +35,3 @@ import { __importDefault, __importStar } from "tslib"; | ||
} | ||
name !== null && name !== void 0 ? name : (name = new Name(fromHex(nameHex))); | ||
name ?? (name = new Name(fromHex(nameHex))); | ||
this.fw.emit("annrm", name); | ||
@@ -42,2 +42,11 @@ for (const dest of this.destinations) { | ||
} | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close() { | ||
for (const dest of this.destinations) { | ||
dest.disable(); | ||
} | ||
} | ||
} | ||
@@ -48,3 +57,3 @@ /** | ||
* Generally, a prefix advertised to a destination would cause Interests matching the prefix | ||
* to come to the forwarder. aka prefix registration. | ||
* to come to the forwarder, aka prefix registration. | ||
*/ | ||
@@ -70,3 +79,3 @@ export class ReadvertiseDestination { | ||
} | ||
this.process(); // eslint-disable-line @typescript-eslint/no-floating-promises | ||
void this.process(); | ||
} | ||
@@ -79,4 +88,3 @@ /** | ||
disable() { | ||
var _a; | ||
(_a = this.readvertise) === null || _a === void 0 ? void 0 : _a.destinations.delete(this); | ||
this.readvertise?.destinations.delete(this); | ||
this.readvertise = undefined; | ||
@@ -106,2 +114,3 @@ for (const [nameHex, record] of this.table) { | ||
withdraw(name, nameHex) { | ||
void name; | ||
const record = this.table.get(nameHex); | ||
@@ -115,4 +124,3 @@ if (!record) { | ||
restart(nameHex, record) { | ||
var _a; | ||
(_a = record.retry) === null || _a === void 0 ? void 0 : _a.stop(); | ||
record.retry?.stop(); | ||
record.retry = retry.operation(this.retryOptions); | ||
@@ -166,2 +174,4 @@ record.retry.attempt(() => { | ||
makeState(name, nameHex) { | ||
void name; | ||
void nameHex; | ||
return {}; | ||
@@ -168,0 +178,0 @@ } |
import { Name } from "@ndn/packet"; | ||
import pushable from "it-pushable"; | ||
import MultiMap from "mnemonist/multi-map.js"; | ||
@@ -20,2 +21,7 @@ import * as retry from "retry"; | ||
removeAnnouncement(face: FaceImpl, name: Name | undefined, nameHex: string): void; | ||
/** | ||
* Cancel timers and other I/O resources. | ||
* This instance should not be used after this operation. | ||
*/ | ||
close(): void; | ||
} | ||
@@ -26,3 +32,3 @@ /** | ||
* Generally, a prefix advertised to a destination would cause Interests matching the prefix | ||
* to come to the forwarder. aka prefix registration. | ||
* to come to the forwarder, aka prefix registration. | ||
*/ | ||
@@ -33,3 +39,3 @@ export declare abstract class ReadvertiseDestination<State extends {} = {}> { | ||
protected readonly table: Map<string, ReadvertiseDestination.Record<State>>; | ||
protected readonly queue: import("it-pushable").Pushable<string>; | ||
protected readonly queue: pushable.Pushable<string>; | ||
protected closed: boolean; | ||
@@ -49,3 +55,3 @@ constructor(retryOptions?: ReadvertiseDestination.RetryOptions); | ||
withdraw(name: Name, nameHex: string): void; | ||
private restart; | ||
protected restart(nameHex: string, record: ReadvertiseDestination.Record<State>): void; | ||
private process; | ||
@@ -52,0 +58,0 @@ /** Create per-prefix state. */ |
@@ -0,1 +1,2 @@ | ||
import pushable from "it-pushable"; | ||
import { FwFace } from "./face"; | ||
@@ -17,4 +18,5 @@ import type { FwPacket } from "./packet"; | ||
advertiseFrom?: boolean | undefined; | ||
routeCapture?: boolean | undefined; | ||
}; | ||
readonly rx: import("it-pushable").Pushable<FwPacket<import("@ndn/packet").Interest | import("@ndn/packet").Data | import("@ndn/packet").Nack>>; | ||
readonly rx: pushable.Pushable<FwPacket<import("@ndn/packet").Interest | import("@ndn/packet").Data | import("@ndn/packet").Nack>>; | ||
private readonly ctrl; | ||
@@ -21,0 +23,0 @@ constructor(face: FwFace); |
import type { Tracer } from "./tracer"; | ||
export declare function makeTracerOutput(): Tracer.Output; |
import type { Tracer } from "./tracer"; | ||
export declare function makeTracerOutput(): Tracer.Output; |
@@ -0,0 +0,0 @@ import { Forwarder } from "./forwarder"; |
{ | ||
"name": "@ndn/fw", | ||
"version": "0.0.20210203", | ||
"version": "0.0.20210930", | ||
"description": "NDNts: Forwarding Plane", | ||
@@ -25,14 +25,13 @@ "keywords": [ | ||
"dependencies": { | ||
"@types/retry": "^0.12.0", | ||
"@ndn/packet": "0.0.20210203", | ||
"@ndn/tlv": "0.0.20210203", | ||
"@types/retry": "^0.12.1", | ||
"@ndn/packet": "0.0.20210930", | ||
"@ndn/tlv": "0.0.20210930", | ||
"hirestime": "^6.1.0", | ||
"it-pushable": "1.4.0", | ||
"it-pushable": "^1.4.2", | ||
"minimalistic-assert": "^1.0.1", | ||
"mnemonist": "^0.38.1", | ||
"p-defer": "^3.0.0", | ||
"mnemonist": "^0.38.4", | ||
"p-fifo": "^1.0.0", | ||
"retry": "^0.12.0", | ||
"streaming-iterables": "^5.0.4", | ||
"tslib": "^2.1.0", | ||
"retry": "^0.13.1", | ||
"streaming-iterables": "^6.0.0", | ||
"tslib": "^2.3.1", | ||
"typed-emitter": "^1.3.1" | ||
@@ -39,0 +38,0 @@ }, |
@@ -33,6 +33,9 @@ # @ndn/fw | ||
* No Content Store (CS). | ||
If your application needs data packet caching, use `@ndn/repo` package. | ||
* No forwarding hint processing. | ||
* If your application needs data packet caching, use `@ndn/repo` package. | ||
* No Nack generation or processing. | ||
* Limited forwarding hint processing: | ||
* Only the first delegation name is considered. Others are ignored. | ||
* If the first delegation name is a prefix of one of the configured node names, FIB lookup uses the Interest name; otherwise, FIB lookup uses the first delegation name. | ||
* Forwarding hint is not stripped even if it matches a configured node name. | ||
These are subject to change. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79939
12
2170
41
+ Added@ndn/packet@0.0.20210930(transitive)
+ Added@ndn/tlv@0.0.20210930(transitive)
+ Addedit-pushable@1.4.2(transitive)
+ Addedretry@0.13.1(transitive)
+ Addedstreaming-iterables@6.2.0(transitive)
- Removedp-defer@^3.0.0
- Removed@ndn/packet@0.0.20210203(transitive)
- Removed@ndn/tlv@0.0.20210203(transitive)
- Removedit-pushable@1.4.0(transitive)
- Removedretry@0.12.0(transitive)
- Removedstreaming-iterables@5.0.4(transitive)
Updated@ndn/packet@0.0.20210930
Updated@ndn/tlv@0.0.20210930
Updated@types/retry@^0.12.1
Updatedit-pushable@^1.4.2
Updatedmnemonist@^0.38.4
Updatedretry@^0.13.1
Updatedstreaming-iterables@^6.0.0
Updatedtslib@^2.3.1