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

@ndn/endpoint

Package Overview
Dependencies
Maintainers
0
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ndn/endpoint - npm Package Compare versions

Comparing version 0.0.20240113 to 0.0.20240630

lib/common_browser.js

25

lib/consumer_browser.js

@@ -1,6 +0,14 @@

import { CancelInterest, FwPacket } from "@ndn/fw";
import { CancelInterest, Forwarder, FwPacket } from "@ndn/fw";
import { Data, Interest } from "@ndn/packet";
import { pushable } from "it-pushable";
import { pushable } from "@ndn/util";
import { exactOptions } from "./common_browser.js";
import { makeRetxGenerator } from "./retx_browser.js";
export function makeConsumer(fw, interest, { describe = `consume(${interest.name})`, signal, modifyInterest, retx, verifier, }) {
export var ConsumerOptions;
(function (ConsumerOptions) {
function exact(opts = {}) {
return exactOptions(opts, ["modifyInterest", "retx", "verifier"]);
}
ConsumerOptions.exact = exact;
})(ConsumerOptions || (ConsumerOptions = {}));
function makeConsumer(interest, { fw = Forwarder.getDefault(), describe = `consume(${interest.name})`, signal, modifyInterest, retx, verifier, }) {
Interest.makeModifyFunc(modifyInterest)(interest);

@@ -10,3 +18,3 @@ let nRetx = -1;

const promise = new Promise((resolve, reject) => {
const rx = pushable({ objectMode: true });
const rx = pushable();
let timer;

@@ -53,3 +61,3 @@ const cancelRetx = () => {

signal?.removeEventListener("abort", onAbort);
rx.end();
rx.stop();
},

@@ -67,1 +75,8 @@ }, {

}
/**
* Retrieve a single piece of Data.
* @param interest - Interest or Interest name.
*/
export function consume(interest, opts = {}) {
return makeConsumer(interest instanceof Interest ? interest : new Interest(interest), opts);
}

@@ -1,6 +0,14 @@

import { CancelInterest, FwPacket } from "@ndn/fw";
import { CancelInterest, Forwarder, FwPacket } from "@ndn/fw";
import { Data, Interest } from "@ndn/packet";
import { pushable } from "it-pushable";
import { pushable } from "@ndn/util";
import { exactOptions } from "./common_node.js";
import { makeRetxGenerator } from "./retx_node.js";
export function makeConsumer(fw, interest, { describe = `consume(${interest.name})`, signal, modifyInterest, retx, verifier, }) {
export var ConsumerOptions;
(function (ConsumerOptions) {
function exact(opts = {}) {
return exactOptions(opts, ["modifyInterest", "retx", "verifier"]);
}
ConsumerOptions.exact = exact;
})(ConsumerOptions || (ConsumerOptions = {}));
function makeConsumer(interest, { fw = Forwarder.getDefault(), describe = `consume(${interest.name})`, signal, modifyInterest, retx, verifier, }) {
Interest.makeModifyFunc(modifyInterest)(interest);

@@ -10,3 +18,3 @@ let nRetx = -1;

const promise = new Promise((resolve, reject) => {
const rx = pushable({ objectMode: true });
const rx = pushable();
let timer;

@@ -53,3 +61,3 @@ const cancelRetx = () => {

signal?.removeEventListener("abort", onAbort);
rx.end();
rx.stop();
},

@@ -67,1 +75,8 @@ }, {

}
/**
* Retrieve a single piece of Data.
* @param interest - Interest or Interest name.
*/
export function consume(interest, opts = {}) {
return makeConsumer(interest instanceof Interest ? interest : new Interest(interest), opts);
}

30

lib/consumer.d.ts

@@ -1,12 +0,10 @@

import { type Forwarder } from "@ndn/fw";
import { Data, Interest, type Verifier } from "@ndn/packet";
import { Data, Interest, type NameLike, type Verifier } from "@ndn/packet";
import { type CommonOptions } from "./common.js";
import { type RetxPolicy } from "./retx.js";
export interface ConsumerOptions {
/** Description for debugging purpose. */
describe?: string;
/** AbortSignal that allows canceling the Interest via AbortController. */
signal?: AbortSignal;
/** {@link consume} options. */
export interface ConsumerOptions extends CommonOptions {
/**
* Modify Interest according to specified options.
* Default is no modification.
* @defaultValue
* `undefined`, no modification.
*/

@@ -16,3 +14,4 @@ modifyInterest?: Interest.Modify;

* Retransmission policy.
* Default is disabling retransmission.
* @defaultValue
* `undefined`, no retransmission.
*/

@@ -22,9 +21,14 @@ retx?: RetxPolicy;

* Data verifier.
* Default is no verification.
* @defaultValue
* `undefined`, no verification.
*/
verifier?: Verifier;
}
export declare namespace ConsumerOptions {
function exact(opts?: ConsumerOptions): ConsumerOptions;
}
/**
* Progress of Data retrieval.
*
* @remarks
* This is a Promise that resolves with the retrieved Data and rejects upon timeout,

@@ -37,2 +41,6 @@ * annotated with the Interest and some counters.

}
export declare function makeConsumer(fw: Forwarder, interest: Interest, { describe, signal, modifyInterest, retx, verifier, }: ConsumerOptions): ConsumerContext;
/**
* Retrieve a single piece of Data.
* @param interest - Interest or Interest name.
*/
export declare function consume(interest: Interest | NameLike, opts?: ConsumerOptions): ConsumerContext;

@@ -0,14 +1,23 @@

import { Signer } from "@ndn/packet";
import { assert } from "@ndn/util";
import { signUnsignedData } from "./producer_browser.js";
// We declare an interface here instead of importing DataStore, in order to reduce bundle size for
// webapps that do not use DataBuffer. The trade-off is that, applications wanting to use
// DataBuffer would have to import memdown and @ndn/repo themselves.
/**
* DataBuffer implementation based on DataStore from @ndn/repo package.
*
* @example
* new DataStoreBuffer(new DataStore(memdown()))
*/
/** DataBuffer implementation based on `@ndn/repo`. */
export class DataStoreBuffer {
store;
/* eslint-disable tsdoc/syntax -- tsdoc-missing-reference */
/**
* Constructor.
* @param store - {@link \@ndn/repo!DataStore} instance.
*
* @example
* ```ts
* new DataStoreBuffer(await makeInMemoryDataStore())
* ```
*
* @remarks
* `DataStore` is declared as an interface instead of importing, in order to reduce bundle size
* for webapps that do not use DataBuffer. The trade-off is that, applications wanting to use
* DataBuffer would have to import `@ndn/repo` themselves.
* Note: {@link \@ndn/repo-api!DataArray} is insufficient because it lacks `expireTime` option.
*/
/* eslint-enable tsdoc/syntax */
constructor(store, { ttl = 60000, dataSigner, } = {}) {

@@ -18,3 +27,3 @@ this.store = store;

this.ttl = ttl;
this.dataSigner = dataSigner;
this.dataSigner = dataSigner && Signer.onlyIfUnsigned(dataSigner);
}

@@ -29,3 +38,3 @@ ttl;

if (this.dataSigner) {
await Promise.all(pkts.map((data) => signUnsignedData(data, this.dataSigner)));
await Promise.all(pkts.map((data) => this.dataSigner.sign(data)));
}

@@ -32,0 +41,0 @@ return this.store.insert({ expireTime }, ...pkts);

@@ -0,14 +1,23 @@

import { Signer } from "@ndn/packet";
import { assert } from "@ndn/util";
import { signUnsignedData } from "./producer_node.js";
// We declare an interface here instead of importing DataStore, in order to reduce bundle size for
// webapps that do not use DataBuffer. The trade-off is that, applications wanting to use
// DataBuffer would have to import memdown and @ndn/repo themselves.
/**
* DataBuffer implementation based on DataStore from @ndn/repo package.
*
* @example
* new DataStoreBuffer(new DataStore(memdown()))
*/
/** DataBuffer implementation based on `@ndn/repo`. */
export class DataStoreBuffer {
store;
/* eslint-disable tsdoc/syntax -- tsdoc-missing-reference */
/**
* Constructor.
* @param store - {@link \@ndn/repo!DataStore} instance.
*
* @example
* ```ts
* new DataStoreBuffer(await makeInMemoryDataStore())
* ```
*
* @remarks
* `DataStore` is declared as an interface instead of importing, in order to reduce bundle size
* for webapps that do not use DataBuffer. The trade-off is that, applications wanting to use
* DataBuffer would have to import `@ndn/repo` themselves.
* Note: {@link \@ndn/repo-api!DataArray} is insufficient because it lacks `expireTime` option.
*/
/* eslint-enable tsdoc/syntax */
constructor(store, { ttl = 60000, dataSigner, } = {}) {

@@ -18,3 +27,3 @@ this.store = store;

this.ttl = ttl;
this.dataSigner = dataSigner;
this.dataSigner = dataSigner && Signer.onlyIfUnsigned(dataSigner);
}

@@ -29,3 +38,3 @@ ttl;

if (this.dataSigner) {
await Promise.all(pkts.map((data) => signUnsignedData(data, this.dataSigner)));
await Promise.all(pkts.map((data) => this.dataSigner.sign(data)));
}

@@ -32,0 +41,0 @@ return this.store.insert({ expireTime }, ...pkts);

@@ -1,8 +0,7 @@

import type { Data, Interest, Signer } from "@ndn/packet";
import { type Data, type Interest, Signer } from "@ndn/packet";
/** Outgoing Data buffer for producer. */
export interface DataBuffer {
find: (interest: Interest) => Promise<Data | undefined>;
insert: (...pkts: Data[]) => Promise<void>;
insert: (...pkts: readonly Data[]) => Promise<void>;
}
/** Prototype of DataStore from @ndn/repo package. */
interface DataStore {

@@ -12,12 +11,22 @@ find: (interest: Interest) => Promise<Data | undefined>;

expireTime?: number;
}, ...pkts: Data[]) => Promise<void>;
}, ...pkts: readonly Data[]) => Promise<void>;
}
/**
* DataBuffer implementation based on DataStore from @ndn/repo package.
*
* @example
* new DataStoreBuffer(new DataStore(memdown()))
*/
/** DataBuffer implementation based on `@ndn/repo`. */
export declare class DataStoreBuffer implements DataBuffer {
readonly store: DataStore;
/**
* Constructor.
* @param store - {@link \@ndn/repo!DataStore} instance.
*
* @example
* ```ts
* new DataStoreBuffer(await makeInMemoryDataStore())
* ```
*
* @remarks
* `DataStore` is declared as an interface instead of importing, in order to reduce bundle size
* for webapps that do not use DataBuffer. The trade-off is that, applications wanting to use
* DataBuffer would have to import `@ndn/repo` themselves.
* Note: {@link \@ndn/repo-api!DataArray} is insufficient because it lacks `expireTime` option.
*/
constructor(store: DataStore, { ttl, dataSigner, }?: DataStoreBuffer.Options);

@@ -30,6 +39,14 @@ private readonly ttl;

export declare namespace DataStoreBuffer {
/** {@link DataStoreBuffer} constructor options. */
interface Options {
/** Data expiration time. Default is 60000ms. 0 means infinity. */
/**
* Data expiration time in milliseconds.
* 0 means infinity.
* @defaultValue 60000
*/
ttl?: number;
/** If specified, automatically sign Data packets unless already signed. */
/**
* If specified, automatically sign Data packets unless already signed.
* @see {@link ProducerOptions.dataSigner}
*/
dataSigner?: Signer;

@@ -36,0 +53,0 @@ }

@@ -0,2 +1,3 @@

export { ConsumerOptions, consume } from "./consumer_browser.js";
export { DataStoreBuffer } from "./data-buffer_browser.js";
export * from "./endpoint_browser.js";
export { ProducerOptions, produce } from "./producer_browser.js";

@@ -0,2 +1,3 @@

export { ConsumerOptions, consume } from "./consumer_node.js";
export { DataStoreBuffer } from "./data-buffer_node.js";
export * from "./endpoint_node.js";
export { ProducerOptions, produce } from "./producer_node.js";

@@ -1,5 +0,4 @@

export type { RetxOptions, RetxPolicy } from "./retx.js";
export type { ConsumerContext, ConsumerOptions } from "./consumer.js";
export { type ConsumerContext, ConsumerOptions, consume } from "./consumer.js";
export { type DataBuffer, DataStoreBuffer } from "./data-buffer.js";
export type { ProducerHandler, ProducerOptions, Producer } from "./producer.js";
export * from "./endpoint.js";
export { type ProducerHandler, ProducerOptions, type Producer, produce } from "./producer.js";
export type { RetxOptions, RetxGenerator, RetxPolicy } from "./retx.js";

@@ -1,12 +0,20 @@

import { FwPacket } from "@ndn/fw";
import { Data, Interest, SigType } from "@ndn/packet";
import { Forwarder, FwPacket } from "@ndn/fw";
import { Data, Interest, Name, Signer } from "@ndn/packet";
import { flatTransform } from "streaming-iterables";
export class ProducerImpl {
import { exactOptions } from "./common_browser.js";
export var ProducerOptions;
(function (ProducerOptions) {
function exact(opts = {}) {
return exactOptions(opts, ["routeCapture", "announcement", "concurrency", "dataSigner", "dataBuffer", "autoBuffer"]);
}
ProducerOptions.exact = exact;
})(ProducerOptions || (ProducerOptions = {}));
class ProducerImpl {
prefix;
handler;
constructor(fw, prefix, handler, { describe = `produce(${prefix})`, signal, routeCapture = true, announcement, concurrency = 1, dataSigner, dataBuffer, autoBuffer = true, }) {
constructor(prefix, handler, { fw = Forwarder.getDefault(), describe = `produce(${prefix})`, signal, routeCapture = true, announcement, concurrency = 1, dataSigner, dataBuffer, autoBuffer = true, }) {
this.prefix = prefix;
this.handler = handler;
this.signal = signal;
this.dataSigner = dataSigner;
this.dataSigner = dataSigner && Signer.onlyIfUnsigned(dataSigner);
this.dataBuffer = dataBuffer;

@@ -25,3 +33,3 @@ this.face = fw.addFace({

this.processBuffered.bind(this, autoBuffer) :
this.processUnbuffered.bind(this);
this.processUnbuffered;
signal?.addEventListener("abort", this.close);

@@ -43,3 +51,3 @@ }

processInterest;
async processUnbuffered(interest) {
processUnbuffered = async (interest) => {
const data = await this.handler(interest, this);

@@ -49,3 +57,3 @@ if (!(data instanceof Data)) {

}
await signUnsignedData(data, this.dataSigner);
await this.dataSigner?.sign(data);
if (!await data.canSatisfy(interest)) { // isCacheLookup=false because the buffer is not considered a cache

@@ -55,3 +63,3 @@ return undefined;

return data;
}
};
async processBuffered(autoBuffer, interest) {

@@ -75,7 +83,13 @@ let found = await this.dataBuffer.find(interest);

};
}
export async function signUnsignedData(data, dataSigner) {
if (dataSigner && data.sigInfo.type === SigType.Null) {
await dataSigner.sign(data);
[Symbol.dispose]() {
this.close();
}
}
/**
* Start a producer.
* @param prefix - Prefix registration; if `undefined`, prefixes may be added later.
* @param handler - Function to handle incoming Interest.
*/
export function produce(prefix, handler, opts = {}) {
return new ProducerImpl(prefix === undefined ? undefined : Name.from(prefix), handler, opts);
}

@@ -1,12 +0,20 @@

import { FwPacket } from "@ndn/fw";
import { Data, Interest, SigType } from "@ndn/packet";
import { Forwarder, FwPacket } from "@ndn/fw";
import { Data, Interest, Name, Signer } from "@ndn/packet";
import { flatTransform } from "streaming-iterables";
export class ProducerImpl {
import { exactOptions } from "./common_node.js";
export var ProducerOptions;
(function (ProducerOptions) {
function exact(opts = {}) {
return exactOptions(opts, ["routeCapture", "announcement", "concurrency", "dataSigner", "dataBuffer", "autoBuffer"]);
}
ProducerOptions.exact = exact;
})(ProducerOptions || (ProducerOptions = {}));
class ProducerImpl {
prefix;
handler;
constructor(fw, prefix, handler, { describe = `produce(${prefix})`, signal, routeCapture = true, announcement, concurrency = 1, dataSigner, dataBuffer, autoBuffer = true, }) {
constructor(prefix, handler, { fw = Forwarder.getDefault(), describe = `produce(${prefix})`, signal, routeCapture = true, announcement, concurrency = 1, dataSigner, dataBuffer, autoBuffer = true, }) {
this.prefix = prefix;
this.handler = handler;
this.signal = signal;
this.dataSigner = dataSigner;
this.dataSigner = dataSigner && Signer.onlyIfUnsigned(dataSigner);
this.dataBuffer = dataBuffer;

@@ -25,3 +33,3 @@ this.face = fw.addFace({

this.processBuffered.bind(this, autoBuffer) :
this.processUnbuffered.bind(this);
this.processUnbuffered;
signal?.addEventListener("abort", this.close);

@@ -43,3 +51,3 @@ }

processInterest;
async processUnbuffered(interest) {
processUnbuffered = async (interest) => {
const data = await this.handler(interest, this);

@@ -49,3 +57,3 @@ if (!(data instanceof Data)) {

}
await signUnsignedData(data, this.dataSigner);
await this.dataSigner?.sign(data);
if (!await data.canSatisfy(interest)) { // isCacheLookup=false because the buffer is not considered a cache

@@ -55,3 +63,3 @@ return undefined;

return data;
}
};
async processBuffered(autoBuffer, interest) {

@@ -75,7 +83,13 @@ let found = await this.dataBuffer.find(interest);

};
}
export async function signUnsignedData(data, dataSigner) {
if (dataSigner && data.sigInfo.type === SigType.Null) {
await dataSigner.sign(data);
[Symbol.dispose]() {
this.close();
}
}
/**
* Start a producer.
* @param prefix - Prefix registration; if `undefined`, prefixes may be added later.
* @param handler - Function to handle incoming Interest.
*/
export function produce(prefix, handler, opts = {}) {
return new ProducerImpl(prefix === undefined ? undefined : Name.from(prefix), handler, opts);
}

@@ -1,27 +0,31 @@

import { type Forwarder, type FwFace } from "@ndn/fw";
import { Data, Interest, type Name, type Signer } from "@ndn/packet";
import { type FwFace } from "@ndn/fw";
import { Data, Interest, Name, type NameLike, Signer } from "@ndn/packet";
import { type CommonOptions } from "./common.js";
import type { DataBuffer } from "./data-buffer.js";
/**
* Producer handler function.
* @param interest - Incoming Interest.
* @param producer - Producer context.
*
* The handler can return a Data to respond to the Interest, or return `undefined` to cause a timeout.
*
* If Options.dataBuffer is provided, the handler can access the DataBuffer via producer.dataBuffer .
* The handler can return a Data to respond to the Interest, which is also inserted to the DataBuffer
* unless Options.autoBuffer is set to false. If the handler returns `undefined`, the Interest is used
* to query the DataBuffer, and any matching Data may be sent.
* @remarks
* The handler may be invoked concurrently up to {@link ProducerOptions.concurrency} instances.
* The handler should return a Promise that resolves to:
* - Data satisfying the Interest: send Data to consumer(s).
* - If Data is not signed, it is signed with {@link ProducerOptions.dataSigner}.
* - Data that does not satisfy the Interest or `undefined`:
* - {@link ProducerOptions.dataBuffer} is unset: cause a timeout.
* - {@link ProducerOptions.dataBuffer} is provided: query the DataBuffer.
*/
export type ProducerHandler = (interest: Interest, producer: Producer) => Promise<Data | undefined>;
export interface ProducerOptions {
/** Description for debugging purpose. */
describe?: string;
/** AbortSignal that allows closing the producer via AbortController. */
signal?: AbortSignal;
/** {@link produce} options. */
export interface ProducerOptions extends CommonOptions {
/**
* Whether routes registered by producer would cause @ndn/fw internal FIB to stop matching toward
* shorter prefixes. Default is true.
* Whether routes registered by producer would cause `@ndn/fw` internal FIB to stop matching
* toward shorter prefixes.
* @defaultValue `true`
*
* @remarks
* If all nexthops of a FIB entry are set to non-capture, FIB lookup may continue onto nexthops
* on FIB entries with shorter prefixes. One use case is in @ndn/sync package, where both local
* and remote sync participants want to receive each other's Interests.
* on FIB entries with shorter prefixes. One use case is in dataset synchronization protocols,
* where both local and remote sync participants want to receive each other's Interests.
*/

@@ -31,8 +35,8 @@ routeCapture?: boolean;

* What name to be readvertised.
* Ignored if prefix is undefined.
* Ignored if prefix is `undefined`.
*/
announcement?: FwFace.RouteAnnouncement;
announcement?: ProducerOptions.RouteAnnouncement;
/**
* How many Interests to process in parallel.
* @default 1
* @defaultValue 1
*/

@@ -42,18 +46,53 @@ concurrency?: number;

* If specified, automatically sign Data packets that are not yet signed.
* This does not apply to Data packets manually inserted to the dataBuffer.
*
* @remarks
* If the {@link ProducerHandler} returns a Data packet that is not signed (its SigType is
* *Null*), it is automatically signed with this signer.
*
* This option does not apply to Data packets manually inserted into `.dataBuffer`. To auto-sign
* those packet, specify {@link DataStoreBuffer.Options.dataSigner} in addition.
*/
dataSigner?: Signer;
/** Outgoing Data buffer. */
/**
* Outgoing Data buffer.
*
* @remarks
* Providing an outgoing Data buffer allows the {@link ProducerHandler} to prepare multiple Data
* packets in response to one Interest, in which one Data satisfies the current Interest and
* additional Data satisfy upcoming Interests. This is useful for a producer that generates a
* multi-segment response triggered by a single Interest, such as a
* {@link https://redmine.named-data.net/projects/nfd/wiki/StatusDataset | StatusDataset}
* producer in NFD Management protocol.
*
* The producer handler can prepare the Data packets and insert them to the DataBuffer. Either it
* can return `undefined`, so that the DataBuffer is queried with the current Interest and the
* first matching Data is sent. Or it can return a specific Data packet for satisfying the
* current Interest.
*/
dataBuffer?: DataBuffer;
/**
* Whether to add handler return value to buffer.
* Ignored when dataBuffer is not specified.
* @default true
* Whether to add handler return value to `.dataBuffer`.
* @defaultValue `true`
*
* @remarks
* This is only relevant when `.dataBuffer` is set. If `true`, when the {@link ProducerHandler}
* returns a Data packet, it is automatically inserted to the DataBuffer.
*/
autoBuffer?: boolean;
}
export declare namespace ProducerOptions {
/** Describe how to derive route announcement from name prefix in {@link produce}. */
type RouteAnnouncement = FwFace.RouteAnnouncement;
function exact(opts?: ProducerOptions): ProducerOptions;
}
/** A running producer. */
export interface Producer {
export interface Producer extends Disposable {
/**
* Prefix specified in {@link produce} call.
* Additional prefixes can be added via `.face.addRoute()`.
*/
readonly prefix: Name | undefined;
/** Logical forwarder face for this producer. */
readonly face: FwFace;
/** Outgoing Data buffer. */
readonly dataBuffer?: DataBuffer;

@@ -63,2 +102,3 @@ /**

*
* @remarks
* Use case of this function:

@@ -73,16 +113,7 @@ * 1. Producer A dynamically creates producer B upon receiving an Interest.

}
export declare class ProducerImpl implements Producer {
readonly prefix: Name | undefined;
private readonly handler;
constructor(fw: Forwarder, prefix: Name | undefined, handler: ProducerHandler, { describe, signal, routeCapture, announcement, concurrency, dataSigner, dataBuffer, autoBuffer, }: ProducerOptions);
readonly face: FwFace;
private readonly signal?;
private readonly dataSigner?;
readonly dataBuffer?: DataBuffer;
private faceDuplex;
readonly processInterest: (interest: Interest) => Promise<Data | undefined>;
private processUnbuffered;
private processBuffered;
close: () => void;
}
export declare function signUnsignedData(data: Data, dataSigner: Signer | undefined): Promise<void>;
/**
* Start a producer.
* @param prefix - Prefix registration; if `undefined`, prefixes may be added later.
* @param handler - Function to handle incoming Interest.
*/
export declare function produce(prefix: NameLike | undefined, handler: ProducerHandler, opts?: ProducerOptions): Producer;
import { randomJitter } from "@ndn/util";
/** Construct RetxGenerator from RetxPolicy. */
export function makeRetxGenerator(policy) {
if (!policy) {
if (!policy) { // applies to both `undefined` and zero
return () => [];
}
if (typeof policy === "number") {
return makeRetxGenerator({ limit: policy });
}
if (typeof policy === "function") {
return policy;
}
if (typeof policy === "number") {
policy = { limit: policy };
}
return function* (interestLifetime) {

@@ -14,0 +14,0 @@ const { limit = 0, interval = interestLifetime * 0.5, randomize = 0.1, backoff = 1, max = interestLifetime * 0.9, } = policy;

import { randomJitter } from "@ndn/util";
/** Construct RetxGenerator from RetxPolicy. */
export function makeRetxGenerator(policy) {
if (!policy) {
if (!policy) { // applies to both `undefined` and zero
return () => [];
}
if (typeof policy === "number") {
return makeRetxGenerator({ limit: policy });
}
if (typeof policy === "function") {
return policy;
}
if (typeof policy === "number") {
policy = { limit: policy };
}
return function* (interestLifetime) {

@@ -14,0 +14,0 @@ const { limit = 0, interval = interestLifetime * 0.5, randomize = 0.1, backoff = 1, max = interestLifetime * 0.9, } = policy;

@@ -5,10 +5,10 @@ /** Interest retransmission policy options. */

* Maximum number of retransmissions, excluding initial Interest.
*
* Default is 0, which disables retransmissions.
* @defaultValue
* `0`, which disables retransmissions
*/
limit?: number;
/**
* Initial retx interval
*
* Default is 50% of InterestLifetime.
* Initial retx interval.
* @defaultValue
* 50% of InterestLifetime
*/

@@ -18,5 +18,6 @@ interval?: number;

* Randomize retx interval within [1-randomize, 1+randomize].
* @defaultValue `0.1`
*
* Suppose this is set to 0.1, an interval of 100ms would become [90ms, 110ms].
* Default is 0.1.
* @remarks
* Suppose this is set to `0.1`, an interval of 100ms would become `[90ms,110ms]`.
*/

@@ -26,5 +27,6 @@ randomize?: number;

* Multiply retx interval by backoff factor after each retx.
* @defaultValue `1.0`
*
* This number should be in range [1.0, 2.0].
* Default is 1.0.
* @remarks
* Valid range is `[1.0, 2.0]`.
*/

@@ -34,8 +36,15 @@ backoff?: number;

* Maximum retx interval.
*
* Default is 90% of InterestLifetime.
* @defaultValue
* 90% of InterestLifetime
*/
max?: number;
}
/** A function to generate retx intervals. */
/**
* Function to generate retransmission intervals.
*
* @remarks
* The generator function is invoked once for each Interest. It should generate successive retx
* intervals for the given Interest, based on the policy it represents. When the generator ends
* (no more values from the returned iterable), no more retx is allowed.
*/
export type RetxGenerator = (interestLifetime: number) => Iterable<number>;

@@ -45,4 +54,5 @@ /**

*
* A number is interpreted as the limit.
* Set 0 to disable retransmissions.
* @remarks
* A number is interpreted as {@link RetxOptions.limit} with other options at their defaults.
* Set `0` to disable retransmissions.
*/

@@ -49,0 +59,0 @@ export type RetxPolicy = RetxOptions | RetxGenerator | number;

{
"name": "@ndn/endpoint",
"version": "0.0.20240113",
"version": "0.0.20240630",
"description": "NDNts: Client Endpoint",

@@ -22,13 +22,12 @@ "keywords": [

"url": "https://github.com/yoursunny/NDNts.git",
"directory": "packages/endpoint"
"directory": "pkg/endpoint"
},
"dependencies": {
"@ndn/fw": "0.0.20240113",
"@ndn/packet": "0.0.20240113",
"@ndn/util": "0.0.20240113",
"it-pushable": "^3.2.3",
"@ndn/fw": "0.0.20240630",
"@ndn/packet": "0.0.20240630",
"@ndn/util": "0.0.20240630",
"streaming-iterables": "^8.0.1",
"tslib": "^2.6.2"
"tslib": "^2.6.3"
},
"types": "lib/mod.d.ts"
}

@@ -5,5 +5,6 @@ # @ndn/endpoint

This package implements **Endpoint** type, which is the basic abstraction through which an application can communicate with the NDN network.
This package implements the *endpoint* concept, consisting of `consume` and `produce` functions.
These are the basic abstractions through which an application can communicate with the NDN network.
An endpoint is similar to a "client face" in other NDN libraries, with the enhancement that it handles these details automatically:
The endpoint concept is similar to a "client face" in other NDN libraries, with the enhancement that it handles these details automatically:

@@ -14,3 +15,78 @@ * [X] Outgoing packets are signed and incoming packets are verified, if trust schema is provided.

Data will be sent automatically upon Interest arrival.
* [X] The underlying transport is reconnected upon failure, if transport failure policy is specified (implemented in `@ndn/l3face` package).
* [ ] Prefix registrations are refreshed periodically or upon transport reconnection.
* [X] The underlying transport is reconnected upon failure, if transport failure policy is specified (implemented in `@ndn/l3face` package).
* [X] Prefix registrations are refreshed periodically or upon transport reconnection (implemented in `@ndn/nfdmgmt` package).
```ts
import { consume, produce } from "@ndn/endpoint";
// other imports for examples
import { generateSigningKey } from "@ndn/keychain";
import { Data, digestSigning } from "@ndn/packet";
import { fromUtf8, toUtf8 } from "@ndn/util";
// Generate a key pair for the demo.
const [signer, verifier] = await generateSigningKey("/identity");
```
## Producer
The `produce()` standalone function creates a producer.
It accepts three parameters:
1. A name prefix that the producer should listen on.
2. A handler function that produces the Data in reply to an Interest.
3. Additional options.
```ts
using producer = produce("/P", async (interest) => {
console.log(`Producer is handling Interest ${interest.name}`);
return new Data(interest.name, toUtf8("served by NDNts"));
}, {
concurrency: 16, // allow concurrent calls to the handler function
dataSigner: signer, // enable automatic signing
});
```
The return value of `produce()` function is an object that implements **Producer** interface.
This interface contains accessors and methods for observing and controlling the producer.
The object implements [Disposable](https://github.com/tc39/proposal-explicit-resource-management) interface.
With `using` keyword (TypeScript only), the producer is closed when the variable goes out of scope.
Alternatively, you can invoke `producer[Symbol.dispose]()` explicitly.
## Consumer
The `consume()` standalone function creates a consumer to receive a single Data packet.
It accepts two parameters:
1. An Interest or Interest name.
2. Additional options.
```ts
const consumer1 = consume("/P/1", {
retx: 2, // enable retransmission
verifier, // enable automatic verification
});
try {
const data1 = await consumer1;
console.log(`Consumer receives Data ${data1.name} with content "${
fromUtf8(data1.content)}" after ${consumer1.nRetx} retransmissions`);
} catch (err: unknown) {
console.log("Consumer error", err);
}
```
The return value of `consume()` function is an object that implements **ConsumerContext** interface.
This interface contains accessors and methods for observing and controlling the consumer.
Most importantly, the return value is a Promise that resolves to the retrieved Data or rejects upon error (including timeout).
Thus, you can simply `await consume(..)` to obtain the Data.
```ts
try {
const data2 = await consume("/P/2", { retx: 2, verifier });
console.log(`Consumer receives Data ${data2.name}`);
} catch (err: unknown) {
console.log("Consumer error", err);
}
```

Sorry, the diff of this file is not supported yet

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