Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ndn/fw

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ndn/fw - npm Package Compare versions

Comparing version 0.0.20210203 to 0.0.20210930

75

lib/face_browser.js
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.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc