Comparing version 0.0.20210930 to 0.0.20220501
@@ -5,8 +5,7 @@ import { Encoder } from "@ndn/tlv"; | ||
constructor() { | ||
this.current = (BigInt(Math.floor(Math.random() * 0x100000000)) << 32n) | | ||
BigInt(Math.floor(Math.random() * 0x100000000)); | ||
this.current = (BigInt(Math.trunc(Math.random() * 0x100000000)) << 32n) | | ||
BigInt(Math.trunc(Math.random() * 0x100000000)); | ||
} | ||
next() { | ||
++this.current; | ||
this.current = BigInt.asUintN(64, this.current); | ||
this.current = BigInt.asUintN(64, this.current + 1n); | ||
return this.current; | ||
@@ -24,15 +23,14 @@ } | ||
export class Fragmenter { | ||
constructor(mtu) { | ||
this.mtu = mtu; | ||
constructor() { | ||
this.seqNumGen = new SeqNumGen(); | ||
this.fragmentRoom = mtu - OVERHEAD; | ||
} | ||
/** | ||
* Fragment a packet. | ||
* @returns a sequence of fragment, or empty array if fragmentation fails. | ||
* @returns a sequence of fragments, or empty array if fragmentation fails. | ||
*/ | ||
fragment(full) { | ||
fragment(full, mtu) { | ||
const fragmentRoom = mtu - OVERHEAD; | ||
const sizeofL3Headers = Encoder.encode(full.encodeL3Headers()).length; | ||
const sizeofPayload = full.payload?.byteLength ?? 0; | ||
const sizeofFirstFragment = Math.min(sizeofPayload, this.fragmentRoom - sizeofL3Headers); | ||
const sizeofFirstFragment = Math.min(sizeofPayload, fragmentRoom - sizeofL3Headers); | ||
if (sizeofFirstFragment === sizeofPayload) { // no fragmentation necessary | ||
@@ -50,7 +48,7 @@ return [full]; | ||
fragments.push(first); | ||
for (let offset = sizeofFirstFragment; offset < sizeofPayload; offset += this.fragmentRoom) { | ||
for (let offset = sizeofFirstFragment; offset < sizeofPayload; offset += fragmentRoom) { | ||
const fragment = new LpPacket(); | ||
fragment.fragSeqNum = this.seqNumGen.next(); | ||
fragment.fragIndex = fragments.length; | ||
fragment.payload = full.payload.subarray(offset, offset + this.fragmentRoom); | ||
fragment.payload = full.payload.subarray(offset, offset + fragmentRoom); | ||
fragments.push(fragment); | ||
@@ -57,0 +55,0 @@ } |
@@ -5,8 +5,7 @@ import { Encoder } from "@ndn/tlv"; | ||
constructor() { | ||
this.current = (BigInt(Math.floor(Math.random() * 0x100000000)) << 32n) | | ||
BigInt(Math.floor(Math.random() * 0x100000000)); | ||
this.current = (BigInt(Math.trunc(Math.random() * 0x100000000)) << 32n) | | ||
BigInt(Math.trunc(Math.random() * 0x100000000)); | ||
} | ||
next() { | ||
++this.current; | ||
this.current = BigInt.asUintN(64, this.current); | ||
this.current = BigInt.asUintN(64, this.current + 1n); | ||
return this.current; | ||
@@ -24,15 +23,14 @@ } | ||
export class Fragmenter { | ||
constructor(mtu) { | ||
this.mtu = mtu; | ||
constructor() { | ||
this.seqNumGen = new SeqNumGen(); | ||
this.fragmentRoom = mtu - OVERHEAD; | ||
} | ||
/** | ||
* Fragment a packet. | ||
* @returns a sequence of fragment, or empty array if fragmentation fails. | ||
* @returns a sequence of fragments, or empty array if fragmentation fails. | ||
*/ | ||
fragment(full) { | ||
fragment(full, mtu) { | ||
const fragmentRoom = mtu - OVERHEAD; | ||
const sizeofL3Headers = Encoder.encode(full.encodeL3Headers()).length; | ||
const sizeofPayload = full.payload?.byteLength ?? 0; | ||
const sizeofFirstFragment = Math.min(sizeofPayload, this.fragmentRoom - sizeofL3Headers); | ||
const sizeofFirstFragment = Math.min(sizeofPayload, fragmentRoom - sizeofL3Headers); | ||
if (sizeofFirstFragment === sizeofPayload) { // no fragmentation necessary | ||
@@ -50,7 +48,7 @@ return [full]; | ||
fragments.push(first); | ||
for (let offset = sizeofFirstFragment; offset < sizeofPayload; offset += this.fragmentRoom) { | ||
for (let offset = sizeofFirstFragment; offset < sizeofPayload; offset += fragmentRoom) { | ||
const fragment = new LpPacket(); | ||
fragment.fragSeqNum = this.seqNumGen.next(); | ||
fragment.fragIndex = fragments.length; | ||
fragment.payload = full.payload.subarray(offset, offset + this.fragmentRoom); | ||
fragment.payload = full.payload.subarray(offset, offset + fragmentRoom); | ||
fragments.push(fragment); | ||
@@ -57,0 +55,0 @@ } |
import { LpPacket } from "./packet"; | ||
/** NDNLPv2 fragmenter. */ | ||
export declare class Fragmenter { | ||
readonly mtu: number; | ||
constructor(mtu: number); | ||
private readonly seqNumGen; | ||
private readonly fragmentRoom; | ||
/** | ||
* Fragment a packet. | ||
* @returns a sequence of fragment, or empty array if fragmentation fails. | ||
* @returns a sequence of fragments, or empty array if fragmentation fails. | ||
*/ | ||
fragment(full: LpPacket): LpPacket[]; | ||
fragment(full: LpPacket, mtu: number): LpPacket[]; | ||
} |
import { NackHeader } from "@ndn/packet"; | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { asDataView } from "@ndn/util"; | ||
import { TT } from "./an_browser.js"; | ||
@@ -9,3 +10,3 @@ function isCritical(tt) { | ||
.setIsCritical(isCritical) | ||
.add(TT.LpSeqNum, (t, { value }) => t.fragSeqNum = Encoder.getBigUint64(Encoder.asDataView(value), 0)) | ||
.add(TT.LpSeqNum, (t, { value }) => t.fragSeqNum = asDataView(value).getBigUint64(0)) | ||
.add(TT.FragIndex, (t, { nni }) => t.fragIndex = nni) | ||
@@ -12,0 +13,0 @@ .add(TT.FragCount, (t, { nni }) => t.fragCount = nni) |
import { NackHeader } from "@ndn/packet"; | ||
import { Encoder, EvDecoder, NNI } from "@ndn/tlv"; | ||
import { asDataView } from "@ndn/util"; | ||
import { TT } from "./an_node.js"; | ||
@@ -9,3 +10,3 @@ function isCritical(tt) { | ||
.setIsCritical(isCritical) | ||
.add(TT.LpSeqNum, (t, { value }) => t.fragSeqNum = Encoder.getBigUint64(Encoder.asDataView(value), 0)) | ||
.add(TT.LpSeqNum, (t, { value }) => t.fragSeqNum = asDataView(value).getBigUint64(0)) | ||
.add(TT.FragIndex, (t, { nni }) => t.fragIndex = nni) | ||
@@ -12,0 +13,0 @@ .add(TT.FragCount, (t, { nni }) => t.fragCount = nni) |
import { NackHeader } from "@ndn/packet"; | ||
import { Decoder, Encodable, Encoder } from "@ndn/tlv"; | ||
import { type Decoder, type Encodable, Encoder } from "@ndn/tlv"; | ||
/** NDNLPv2 packet. */ | ||
@@ -4,0 +4,0 @@ export declare class LpPacket { |
import { __importDefault, __importStar } from "tslib"; | ||
import { Data, Interest, Nack, TT as l3TT } from "@ndn/packet"; | ||
import { Decoder, Encoder, printTT, toHex } from "@ndn/tlv"; | ||
import { Decoder, Encoder, printTT } from "@ndn/tlv"; | ||
import { assert, flatMapOnce, toHex } from "@ndn/util"; | ||
import _cjsDefaultImport0 from "it-keepalive"; const itKeepAlive = __importDefault(_cjsDefaultImport0).default; | ||
import _cjsDefaultImport1 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport1).default; | ||
import { TT } from "./an_browser.js"; | ||
@@ -10,17 +10,10 @@ import { Fragmenter } from "./fragmenter_browser.js"; | ||
import { Reassembler } from "./reassembler_browser.js"; | ||
/** | ||
* Map and flatten, but only do it once. | ||
* This differs from flatMap from streaming-iterables that recursively flattens the result. | ||
*/ | ||
async function* flatMap1(f, iterable) { | ||
for await (const item of iterable) { | ||
yield* f(item); | ||
} | ||
} | ||
const IDLE = Encoder.encode(new LpPacket()); | ||
/** NDNLPv2 service. */ | ||
export class LpService { | ||
constructor({ keepAlive = 60000, mtu = Infinity, reassemblerCapacity = 16, } = {}) { | ||
this.mtu = Infinity; | ||
this.rx = (iterable) => flatMap1((tlv) => this.decode(tlv), iterable); | ||
this.tx = (iterable) => flatMap1((pkt) => this.encode(pkt), this.keepAlive ? | ||
constructor({ keepAlive = 60000, mtu = Infinity, reassemblerCapacity = 16, }, transport) { | ||
this.transport = transport; | ||
this.fragmenter = new Fragmenter(); | ||
this.rx = (iterable) => flatMapOnce((tlv) => this.decode(tlv), iterable); | ||
this.tx = (iterable) => flatMapOnce((pkt) => this.encode(pkt), this.keepAlive ? | ||
itKeepAlive(() => false, { timeout: this.keepAlive })(iterable) : | ||
@@ -31,6 +24,3 @@ iterable); | ||
} | ||
if (Number.isFinite(mtu)) { | ||
this.mtu = mtu; | ||
this.fragmenter = new Fragmenter(mtu); | ||
} | ||
this.mtu = mtu; | ||
this.reassembler = new Reassembler(reassemblerCapacity); | ||
@@ -81,2 +71,3 @@ } | ||
} | ||
const mtu = Math.min(this.mtu, this.transport.mtu); | ||
const { l3, token } = pkt; | ||
@@ -88,3 +79,3 @@ const lpp = new LpPacket(); | ||
const payload = Encoder.encode(l3); | ||
if (!token && payload.length <= this.mtu) { | ||
if (!token && payload.length <= mtu) { | ||
return yield payload; | ||
@@ -103,4 +94,4 @@ } | ||
} | ||
if (this.fragmenter) { | ||
yield* this.fragmenter.fragment(lpp).map((fragment) => Encoder.encode(fragment, this.mtu)); | ||
if (Number.isFinite(mtu)) { | ||
yield* this.fragmenter.fragment(lpp, mtu).map((fragment) => Encoder.encode(fragment, mtu)); | ||
} | ||
@@ -107,0 +98,0 @@ else { |
import { __importDefault, __importStar } from "tslib"; | ||
import { Data, Interest, Nack, TT as l3TT } from "@ndn/packet"; | ||
import { Decoder, Encoder, printTT, toHex } from "@ndn/tlv"; | ||
import { Decoder, Encoder, printTT } from "@ndn/tlv"; | ||
import { assert, flatMapOnce, toHex } from "@ndn/util"; | ||
import _cjsDefaultImport0 from "it-keepalive"; const itKeepAlive = __importDefault(_cjsDefaultImport0).default; | ||
import _cjsDefaultImport1 from "minimalistic-assert"; const assert = __importDefault(_cjsDefaultImport1).default; | ||
import { TT } from "./an_node.js"; | ||
@@ -10,17 +10,10 @@ import { Fragmenter } from "./fragmenter_node.js"; | ||
import { Reassembler } from "./reassembler_node.js"; | ||
/** | ||
* Map and flatten, but only do it once. | ||
* This differs from flatMap from streaming-iterables that recursively flattens the result. | ||
*/ | ||
async function* flatMap1(f, iterable) { | ||
for await (const item of iterable) { | ||
yield* f(item); | ||
} | ||
} | ||
const IDLE = Encoder.encode(new LpPacket()); | ||
/** NDNLPv2 service. */ | ||
export class LpService { | ||
constructor({ keepAlive = 60000, mtu = Infinity, reassemblerCapacity = 16, } = {}) { | ||
this.mtu = Infinity; | ||
this.rx = (iterable) => flatMap1((tlv) => this.decode(tlv), iterable); | ||
this.tx = (iterable) => flatMap1((pkt) => this.encode(pkt), this.keepAlive ? | ||
constructor({ keepAlive = 60000, mtu = Infinity, reassemblerCapacity = 16, }, transport) { | ||
this.transport = transport; | ||
this.fragmenter = new Fragmenter(); | ||
this.rx = (iterable) => flatMapOnce((tlv) => this.decode(tlv), iterable); | ||
this.tx = (iterable) => flatMapOnce((pkt) => this.encode(pkt), this.keepAlive ? | ||
itKeepAlive(() => false, { timeout: this.keepAlive })(iterable) : | ||
@@ -31,6 +24,3 @@ iterable); | ||
} | ||
if (Number.isFinite(mtu)) { | ||
this.mtu = mtu; | ||
this.fragmenter = new Fragmenter(mtu); | ||
} | ||
this.mtu = mtu; | ||
this.reassembler = new Reassembler(reassemblerCapacity); | ||
@@ -81,2 +71,3 @@ } | ||
} | ||
const mtu = Math.min(this.mtu, this.transport.mtu); | ||
const { l3, token } = pkt; | ||
@@ -88,3 +79,3 @@ const lpp = new LpPacket(); | ||
const payload = Encoder.encode(l3); | ||
if (!token && payload.length <= this.mtu) { | ||
if (!token && payload.length <= mtu) { | ||
return yield payload; | ||
@@ -103,4 +94,4 @@ } | ||
} | ||
if (this.fragmenter) { | ||
yield* this.fragmenter.fragment(lpp).map((fragment) => Encoder.encode(fragment, this.mtu)); | ||
if (Number.isFinite(mtu)) { | ||
yield* this.fragmenter.fragment(lpp, mtu).map((fragment) => Encoder.encode(fragment, mtu)); | ||
} | ||
@@ -107,0 +98,0 @@ else { |
import { Data, Interest, Nack } from "@ndn/packet"; | ||
import { Decoder } from "@ndn/tlv"; | ||
/** NDNLPv2 service. */ | ||
export declare class LpService { | ||
constructor({ keepAlive, mtu, reassemblerCapacity, }?: LpService.Options); | ||
private readonly transport; | ||
constructor({ keepAlive, mtu, reassemblerCapacity, }: LpService.Options, transport: LpService.Transport); | ||
private readonly keepAlive?; | ||
private readonly mtu; | ||
private readonly fragmenter?; | ||
private readonly fragmenter; | ||
private readonly reassembler; | ||
@@ -16,2 +18,9 @@ rx: (iterable: AsyncIterable<Decoder.Tlv>) => AsyncIterable<LpService.Packet | LpService.RxError>; | ||
export declare namespace LpService { | ||
/** An object to report transport MTU. */ | ||
export interface Transport { | ||
/** | ||
* Return current transport MTU. | ||
*/ | ||
readonly mtu: number; | ||
} | ||
export interface Options { | ||
@@ -25,4 +34,4 @@ /** | ||
/** | ||
* MTU for fragmentation. | ||
* Set Infinity to disable fragmentation. | ||
* Administrative MTU. | ||
* The lesser of this MTU and the transport's reported MTU is used for fragmentation. | ||
* @default Infinity | ||
@@ -29,0 +38,0 @@ */ |
{ | ||
"name": "@ndn/lp", | ||
"version": "0.0.20210930", | ||
"version": "0.0.20220501", | ||
"description": "NDNts: NDNLP", | ||
@@ -25,9 +25,10 @@ "keywords": [ | ||
"dependencies": { | ||
"@ndn/packet": "0.0.20210930", | ||
"@ndn/tlv": "0.0.20210930", | ||
"minimalistic-assert": "^1.0.1", | ||
"@ndn/packet": "0.0.20220501", | ||
"@ndn/tlv": "0.0.20220501", | ||
"@ndn/util": "0.0.20220501", | ||
"it-keepalive": "^1.2.0", | ||
"tslib": "^2.3.1" | ||
"tslib": "^2.4.0" | ||
}, | ||
"types": "lib/mod.d.ts" | ||
"types": "lib/mod.d.ts", | ||
"readme": "# @ndn/lp\n\nThis package is part of [NDNts](https://yoursunny.com/p/NDNts/), Named Data Networking libraries for the modern web.\n\nThis package implements [NDNLPv2](https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2) link protocol.\nCurrently, this is a minimal implementation that understands:\n\n* Fragmentation and reassembly.\n* Nack.\n* PIT token.\n" | ||
} |
28251
21
755
+ Added@ndn/util@0.0.20220501
+ Added@ndn/packet@0.0.20220501(transitive)
+ Added@ndn/tlv@0.0.20220501(transitive)
+ Added@ndn/util@0.0.20220501(transitive)
+ Added@types/minimalistic-assert@1.0.3(transitive)
+ Addedmnemonist@0.39.8(transitive)
- Removedminimalistic-assert@^1.0.1
- Removed@ndn/packet@0.0.20210930(transitive)
- Removed@ndn/tlv@0.0.20210930(transitive)
- Removedmnemonist@0.38.5(transitive)
Updated@ndn/packet@0.0.20220501
Updated@ndn/tlv@0.0.20220501
Updatedtslib@^2.4.0