@ndn/node-transport
Advanced tools
Comparing version 0.0.20220501 to 0.0.20230121
@@ -1,5 +0,5 @@ | ||
export * from "./hostport"; | ||
export * from "./tcp-transport"; | ||
export * from "./unix-transport"; | ||
export * as udp_helper from "./udp-helper"; | ||
export * from "./udp-transport"; | ||
export * from "./hostport.js"; | ||
export * from "./tcp-transport.js"; | ||
export * from "./unix-transport.js"; | ||
export * as udp_helper from "./udp-helper.js"; | ||
export * from "./udp-transport.js"; |
@@ -0,3 +1,3 @@ | ||
import * as net from "net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import * as net from "net"; | ||
import { joinHostPort } from "./hostport_browser.js"; | ||
@@ -7,2 +7,3 @@ const DEFAULT_PORT = 6363; | ||
export class TcpTransport extends StreamTransport { | ||
connectOpts; | ||
constructor(sock, connectOpts) { | ||
@@ -32,7 +33,9 @@ super(sock, { | ||
sock.setNoDelay(true); | ||
let timeout; // eslint-disable-line prefer-const | ||
const fail = (err) => { | ||
clearTimeout(timeout); | ||
sock.destroy(); | ||
reject(err); | ||
}; | ||
const timeout = setTimeout(() => fail(new Error("connectTimeout")), connectTimeout); | ||
timeout = setTimeout(() => fail(new Error("connectTimeout")), connectTimeout); | ||
const onabort = () => fail(new Error("abort")); | ||
@@ -39,0 +42,0 @@ signal?.addEventListener("abort", onabort); |
@@ -0,3 +1,3 @@ | ||
import * as net from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import * as net from "node:net"; | ||
import { joinHostPort } from "./hostport_node.js"; | ||
@@ -7,2 +7,3 @@ const DEFAULT_PORT = 6363; | ||
export class TcpTransport extends StreamTransport { | ||
connectOpts; | ||
constructor(sock, connectOpts) { | ||
@@ -32,7 +33,9 @@ super(sock, { | ||
sock.setNoDelay(true); | ||
let timeout; // eslint-disable-line prefer-const | ||
const fail = (err) => { | ||
clearTimeout(timeout); | ||
sock.destroy(); | ||
reject(err); | ||
}; | ||
const timeout = setTimeout(() => fail(new Error("connectTimeout")), connectTimeout); | ||
timeout = setTimeout(() => fail(new Error("connectTimeout")), connectTimeout); | ||
const onabort = () => fail(new Error("abort")); | ||
@@ -39,0 +42,0 @@ signal?.addEventListener("abort", onabort); |
/// <reference types="node" /> | ||
import * as net from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import * as net from "node:net"; | ||
/** TCP socket transport. */ | ||
@@ -5,0 +5,0 @@ export declare class TcpTransport extends StreamTransport { |
import * as dgram from "dgram"; | ||
import { once } from "events"; | ||
import * as os from "os"; | ||
import { pEvent } from "p-event"; | ||
export const DEFAULT_MTU = 65000; | ||
@@ -8,2 +8,8 @@ const DEFAULT_UNICAST_PORT = 6363; | ||
const DEFAULT_MULTICAST_PORT = 56363; | ||
export function intfHasAddressFamily(want, { family }) { | ||
// https://github.com/nodejs/node/issues/42787 | ||
// Node.js 16.x: NetworkInterfaceInfo.family is either "IPv4" or "IPv6" | ||
// Node.js 18.x: NetworkInterfaceInfo.family is either 4 or 6 | ||
return family === want || family === `IPv${want}`; | ||
} | ||
export async function openSocket({ family, recvBufferSize, sendBufferSize, bind = {}, }) { | ||
@@ -19,3 +25,3 @@ family ??= bind.address?.includes(":") ? 6 : 4; | ||
sock.bind(bind); | ||
await pEvent(sock, "listening"); | ||
await once(sock, "listening"); | ||
} | ||
@@ -31,3 +37,3 @@ catch (err) { | ||
sock.connect(port, host); | ||
await pEvent(sock, "connect"); | ||
await once(sock, "connect"); | ||
} | ||
@@ -47,11 +53,10 @@ catch (err) { | ||
} | ||
/** | ||
* List network interfaces capable of IPv4 multicast. | ||
* @returns IPv4 address of each network interface. | ||
*/ | ||
export function listMulticastIntfs() { | ||
return Object.values(os.networkInterfaces()) | ||
.flatMap((addrs) => { | ||
if (!addrs) { | ||
return []; | ||
} | ||
return addrs.filter(({ family, internal }) => family === "IPv4" && !internal) | ||
.map(({ address }) => address).slice(0, 1); | ||
}); | ||
.flatMap((addrs = []) => addrs.filter((a) => intfHasAddressFamily(4, a) && !a.internal) | ||
.map(({ address }) => address).slice(0, 1)); | ||
} | ||
@@ -85,3 +90,3 @@ export async function openMulticastRx(opts) { | ||
sock.connect(port, group); | ||
await pEvent(sock, "connect"); | ||
await once(sock, "connect"); | ||
} | ||
@@ -88,0 +93,0 @@ catch (err) { |
import * as dgram from "node:dgram"; | ||
import { once } from "node:events"; | ||
import * as os from "node:os"; | ||
import { pEvent } from "p-event"; | ||
export const DEFAULT_MTU = 65000; | ||
@@ -8,2 +8,8 @@ const DEFAULT_UNICAST_PORT = 6363; | ||
const DEFAULT_MULTICAST_PORT = 56363; | ||
export function intfHasAddressFamily(want, { family }) { | ||
// https://github.com/nodejs/node/issues/42787 | ||
// Node.js 16.x: NetworkInterfaceInfo.family is either "IPv4" or "IPv6" | ||
// Node.js 18.x: NetworkInterfaceInfo.family is either 4 or 6 | ||
return family === want || family === `IPv${want}`; | ||
} | ||
export async function openSocket({ family, recvBufferSize, sendBufferSize, bind = {}, }) { | ||
@@ -19,3 +25,3 @@ family ??= bind.address?.includes(":") ? 6 : 4; | ||
sock.bind(bind); | ||
await pEvent(sock, "listening"); | ||
await once(sock, "listening"); | ||
} | ||
@@ -31,3 +37,3 @@ catch (err) { | ||
sock.connect(port, host); | ||
await pEvent(sock, "connect"); | ||
await once(sock, "connect"); | ||
} | ||
@@ -47,11 +53,10 @@ catch (err) { | ||
} | ||
/** | ||
* List network interfaces capable of IPv4 multicast. | ||
* @returns IPv4 address of each network interface. | ||
*/ | ||
export function listMulticastIntfs() { | ||
return Object.values(os.networkInterfaces()) | ||
.flatMap((addrs) => { | ||
if (!addrs) { | ||
return []; | ||
} | ||
return addrs.filter(({ family, internal }) => family === "IPv4" && !internal) | ||
.map(({ address }) => address).slice(0, 1); | ||
}); | ||
.flatMap((addrs = []) => addrs.filter((a) => intfHasAddressFamily(4, a) && !a.internal) | ||
.map(({ address }) => address).slice(0, 1)); | ||
} | ||
@@ -85,3 +90,3 @@ export async function openMulticastRx(opts) { | ||
sock.connect(port, group); | ||
await pEvent(sock, "connect"); | ||
await once(sock, "connect"); | ||
} | ||
@@ -88,0 +93,0 @@ catch (err) { |
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import * as dgram from "node:dgram"; | ||
import * as os from "node:os"; | ||
export declare const DEFAULT_MTU = 65000; | ||
export declare type Socket = dgram.Socket; | ||
export type Socket = dgram.Socket; | ||
export interface SocketBufferOption { | ||
@@ -9,3 +11,4 @@ recvBufferSize?: number; | ||
} | ||
export declare type AddressFamily = 4 | 6; | ||
export type AddressFamily = 4 | 6; | ||
export declare function intfHasAddressFamily(want: AddressFamily, { family }: os.NetworkInterfaceInfo): boolean; | ||
export interface AddressFamilyOption { | ||
@@ -33,2 +36,6 @@ /** | ||
export declare function openUnicast(opts: UnicastOptions): Promise<Socket>; | ||
/** | ||
* List network interfaces capable of IPv4 multicast. | ||
* @returns IPv4 address of each network interface. | ||
*/ | ||
export declare function listMulticastIntfs(): string[]; | ||
@@ -35,0 +42,0 @@ export interface MulticastOptions extends SocketBufferOption { |
@@ -0,3 +1,4 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
import { L3Face, rxFromPacketIterable, Transport } from "@ndn/l3face"; | ||
import { pEventIterator } from "p-event"; | ||
import _cjsDefaultImport0 from "event-iterator"; const EventIterator = __importDefault(_cjsDefaultImport0).default; | ||
import { joinHostPort } from "./hostport_browser.js"; | ||
@@ -7,20 +8,14 @@ import * as udp from "./udp-helper_browser.js"; | ||
export class UdpTransport extends Transport { | ||
rx; | ||
isMulticast; | ||
laddr; | ||
raddr; | ||
rxSock; | ||
txSock; | ||
constructor(txSock, rxSock) { | ||
const [scheme, { address, port }] = rxSock ? ["UDPm", txSock.address()] : ["UDP", txSock.remoteAddress()]; | ||
super({ | ||
describe: (() => { | ||
const [scheme, { address, port }] = rxSock ? ["UDPm", txSock.address()] : ["UDP", txSock.remoteAddress()]; | ||
return `${scheme}(${joinHostPort(address, port)})`; | ||
})(), | ||
describe: `${scheme}(${joinHostPort(address, port)})`, | ||
multicast: !!rxSock, | ||
}); | ||
this.tx = async (iterable) => { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
}; | ||
if (rxSock) { | ||
@@ -41,4 +36,12 @@ this.isMulticast = true; | ||
} | ||
this.rx = rxFromPacketIterable(pEventIterator(this.rxSock, "message", { | ||
resolutionEvents: ["close"], | ||
this.rx = rxFromPacketIterable(new EventIterator(({ push, stop, fail }) => { | ||
const handleMessage = (msg) => push(msg); | ||
this.rxSock.on("message", handleMessage); | ||
this.rxSock.on("close", stop); | ||
this.rxSock.on("error", fail); | ||
return () => { | ||
this.rxSock.off("message", handleMessage); | ||
this.rxSock.off("close", stop); | ||
this.rxSock.off("error", fail); | ||
}; | ||
})); | ||
@@ -56,2 +59,12 @@ } | ||
} | ||
tx = async (iterable) => { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
}; | ||
} | ||
@@ -58,0 +71,0 @@ (function (UdpTransport) { |
@@ -0,3 +1,4 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
import { L3Face, rxFromPacketIterable, Transport } from "@ndn/l3face"; | ||
import { pEventIterator } from "p-event"; | ||
import _cjsDefaultImport0 from "event-iterator"; const EventIterator = __importDefault(_cjsDefaultImport0).default; | ||
import { joinHostPort } from "./hostport_node.js"; | ||
@@ -7,20 +8,14 @@ import * as udp from "./udp-helper_node.js"; | ||
export class UdpTransport extends Transport { | ||
rx; | ||
isMulticast; | ||
laddr; | ||
raddr; | ||
rxSock; | ||
txSock; | ||
constructor(txSock, rxSock) { | ||
const [scheme, { address, port }] = rxSock ? ["UDPm", txSock.address()] : ["UDP", txSock.remoteAddress()]; | ||
super({ | ||
describe: (() => { | ||
const [scheme, { address, port }] = rxSock ? ["UDPm", txSock.address()] : ["UDP", txSock.remoteAddress()]; | ||
return `${scheme}(${joinHostPort(address, port)})`; | ||
})(), | ||
describe: `${scheme}(${joinHostPort(address, port)})`, | ||
multicast: !!rxSock, | ||
}); | ||
this.tx = async (iterable) => { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
}; | ||
if (rxSock) { | ||
@@ -41,4 +36,12 @@ this.isMulticast = true; | ||
} | ||
this.rx = rxFromPacketIterable(pEventIterator(this.rxSock, "message", { | ||
resolutionEvents: ["close"], | ||
this.rx = rxFromPacketIterable(new EventIterator(({ push, stop, fail }) => { | ||
const handleMessage = (msg) => push(msg); | ||
this.rxSock.on("message", handleMessage); | ||
this.rxSock.on("close", stop); | ||
this.rxSock.on("error", fail); | ||
return () => { | ||
this.rxSock.off("message", handleMessage); | ||
this.rxSock.off("close", stop); | ||
this.rxSock.off("error", fail); | ||
}; | ||
})); | ||
@@ -56,2 +59,12 @@ } | ||
} | ||
tx = async (iterable) => { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
}; | ||
} | ||
@@ -58,0 +71,0 @@ (function (UdpTransport) { |
/// <reference types="node" /> | ||
import type { AddressInfo } from "node:net"; | ||
import { L3Face, Transport } from "@ndn/l3face"; | ||
import type { AddressInfo } from "node:net"; | ||
import * as udp from "./udp-helper"; | ||
import * as udp from "./udp-helper.js"; | ||
/** UDP socket transport. */ | ||
@@ -6,0 +6,0 @@ export declare class UdpTransport extends Transport { |
@@ -0,5 +1,6 @@ | ||
import * as net from "net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import * as net from "net"; | ||
/** Unix socket transport. */ | ||
export class UnixTransport extends StreamTransport { | ||
connectOpts; | ||
constructor(sock, connectOpts) { | ||
@@ -6,0 +7,0 @@ super(sock, { |
@@ -0,5 +1,6 @@ | ||
import * as net from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import * as net from "node:net"; | ||
/** Unix socket transport. */ | ||
export class UnixTransport extends StreamTransport { | ||
connectOpts; | ||
constructor(sock, connectOpts) { | ||
@@ -6,0 +7,0 @@ super(sock, { |
/// <reference types="node" /> | ||
import * as net from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import * as net from "node:net"; | ||
/** Unix socket transport. */ | ||
@@ -5,0 +5,0 @@ export declare class UnixTransport extends StreamTransport { |
{ | ||
"name": "@ndn/node-transport", | ||
"version": "0.0.20220501", | ||
"version": "0.0.20230121", | ||
"description": "NDNts: Low-Level Transports for Node.js", | ||
@@ -23,10 +23,9 @@ "keywords": [ | ||
"dependencies": { | ||
"@ndn/l3face": "0.0.20220501", | ||
"p-event": "^5.0.1", | ||
"tslib": "^2.4.0", | ||
"@ndn/l3face": "0.0.20230121", | ||
"event-iterator": "^2.0.0", | ||
"tslib": "^2.4.1", | ||
"url-format-lax": "^2.0.0", | ||
"url-parse-lax": "^5.0.0" | ||
}, | ||
"types": "lib/mod.d.ts", | ||
"readme": "# @ndn/node-transport\n\nThis package is part of [NDNts](https://yoursunny.com/p/NDNts/), Named Data Networking libraries for the modern web.\n\nThis package implements socket transports for Node.js environment.\n\n```ts\nimport { TcpTransport, UdpTransport, UnixTransport } from \"@ndn/node-transport\";\n\n// other imports for examples\nimport { FwPacket } from \"@ndn/fw\";\nimport { L3Face, Transport } from \"@ndn/l3face\";\nimport { Data, Interest } from \"@ndn/packet\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nif (process.env.CI) { process.exit(0); }\n```\n\n## Transport Types\n\nThere are three transport types:\n\n* UnixTransport: Unix socket or Windows named pipe.\n* TcpTransport: TCP tunnel (IPv4 or IPv6).\n* UdpTransport: UDP unicast tunnel (IPv4 or IPv6) or UDP multicast group (IPv4 only).\n\nThe `connect()` function of each transport creates a transport.\n\n```ts\n// UnixTransport.connect() establishes a UNIX socket connection.\n// It accepts a Unix socket path.\ntry {\n const unix = await UnixTransport.connect(process.env.DEMO_NFD_UNIX ?? \"/run/nfd.sock\");\n await useInL3Face(unix);\n} catch (err: unknown) { // NFD is not running\n console.warn(\"unix\", err);\n}\n\n// TcpTransport.connect() establishes a TCP tunnel.\n// It accepts either host+port or an options object for net.connect().\ntry {\n const tcp4 = await TcpTransport.connect(\"hobo.cs.arizona.edu\", 6363);\n await useInL3Face(tcp4);\n} catch (err: unknown) { // router unavailable\n console.warn(\"tcp4\", err);\n}\n\n// Select IPv4 with `family: 4` or select IPv6 with `family: 6`. Default is both.\ntry {\n const tcp6 = await TcpTransport.connect({ host: \"ndnhub.ipv6.lip6.fr\", family: 6 });\n await useInL3Face(tcp6);\n} catch (err: unknown) { // router unavailable\n console.warn(\"tcp6\", err);\n}\n\n// UdpTransport.connect() establishes a UDP tunnel.\ntry {\n const udp4 = await UdpTransport.connect(\"hobo.cs.arizona.edu\");\n await useInL3Face(udp4);\n} catch (err: unknown) { // router unavailable\n console.warn(\"udp4\", err);\n}\n\n// Select IPv6 with `type: \"udp6\"`. Default is IPv4 only.\ntry {\n const udp6 = await UdpTransport.connect({ host: \"ndnhub.ipv6.lip6.fr\", family: 6 });\n await useInL3Face(udp6);\n} catch (err: unknown) { // router unavailable\n console.warn(\"udp6\", err);\n}\n```\n\nTo use UDP multicast, each network interface needs to have a separate transport.\nIt's easiest to let NDNts automatically create transports on every network interface.\n\n```ts\n// UdpTransport.multicasts() attempts to create UDP multicast transports on every\n// network interface, skipping network interfaces where socket creation fails.\nconst multicasts = await UdpTransport.multicasts();\nfor (const transport of multicasts) {\n await useInL3Face(transport);\n}\n```\n\n## How to Use a Transport\n\nTransports are normally used to construct **L3Face** objects (from `@ndn/l3face` package), which are in turned add to the **Forwarder** (from `@ndn/fw` package).\nEach transport provides a `createFace` convenience function to construct a transport and add it to the forwarder.\n\nSee `@ndn/ws-transport` package documentation for a complete example of `createFace` function.\n\n```ts\n// UdpTransport.createFace() constructs a UDP unicast transport, and adds it to a forwarder.\n// First parameters allows setting L3Face attributes and NDNLP service options, or attaching\n// the face to a non-default Forwarder instance. This argument is required.\n// Subsequent parameters are same as the corresponding connect() function.\n// It returns a FwFace instance (from @ndn/fw package).\nconst face = await UdpTransport.createFace({}, \"ndnhub.ipv6.lip6.fr\");\nface.close();\n// TcpTransport.createFace() and UnixTransport.createFace() behave similarly.\n\n// UdpTransport.createMulticastFaces() constructs UDP multicast transports on every network\n// interface and adds them to a forwarder.\nconst faces = await UdpTransport.createMulticastFaces({});\nfor (const face of faces) {\n face.close();\n}\n```\n\n## L3Face Low-Level Details\n\nL3Face allows sending and receiving layer-3 packets on a transport.\nL3Face does not provide Interest-Data matching logic, timeout scheduler, etc.\nIt is more like a forwarder's face.\n\nThis section presents the low-level details of how to use a \"raw\" transport with `L3Face` class.\n\n```ts\nasync function useInL3Face(transport: Transport) {\n\n // Transports are normally used in a network layer face.\n const face = new L3Face(transport);\n\n // We want to know if something goes wrong.\n face.on(\"rxerror\", (err) => console.warn(err));\n face.on(\"txerror\", (err) => console.warn(err));\n\n await Promise.all([\n face.tx({ async *[Symbol.asyncIterator]() {\n // Send five Interests.\n let seq = Math.trunc(Math.random() * 1e8);\n for (let i = 0; i < 5; ++i) {\n await delay(50);\n const interest = new Interest(`/ndn/edu/arizona/ping/NDNts/${seq++}`);\n console.log(`${transport} <I ${interest.name}`);\n yield FwPacket.create(interest);\n }\n await delay(500);\n } }),\n (async () => {\n let nData = 0;\n for await (const { l3 } of face.rx) {\n if (!(l3 instanceof Data)) {\n continue;\n }\n // Print incoming Data name.\n console.log(`${transport} >D ${l3.name}`);\n if (++nData >= 5) {\n return;\n }\n }\n })(),\n ]);\n\n // L3Face and Transport are automatically closed when TX iterable is exhausted.\n}\n```\n" | ||
"types": "lib/mod.d.ts" | ||
} |
@@ -12,5 +12,5 @@ # @ndn/node-transport | ||
import { FwPacket } from "@ndn/fw"; | ||
import { L3Face, Transport } from "@ndn/l3face"; | ||
import { type Transport, L3Face } from "@ndn/l3face"; | ||
import { Data, Interest } from "@ndn/packet"; | ||
import { setTimeout as delay } from "node:timers/promises"; | ||
import { delay } from "@ndn/util"; | ||
@@ -17,0 +17,0 @@ if (process.env.CI) { process.exit(0); } |
@@ -5,5 +5,5 @@ import { TcpTransport, UdpTransport, UnixTransport } from "@ndn/node-transport"; | ||
import { FwPacket } from "@ndn/fw"; | ||
import { L3Face, Transport } from "@ndn/l3face"; | ||
import { type Transport, L3Face } from "@ndn/l3face"; | ||
import { Data, Interest } from "@ndn/packet"; | ||
import { setTimeout as delay } from "node:timers/promises"; | ||
import { delay } from "@ndn/util"; | ||
@@ -10,0 +10,0 @@ if (process.env.CI) { process.exit(0); } |
Sorry, the diff of this file is not supported yet
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
871
39253
+ Addedevent-iterator@^2.0.0
+ Added@ndn/fw@0.0.20230121(transitive)
+ Added@ndn/l3face@0.0.20230121(transitive)
+ Added@ndn/lp@0.0.20230121(transitive)
+ Added@ndn/packet@0.0.20230121(transitive)
+ Added@ndn/tlv@0.0.20230121(transitive)
+ Added@ndn/util@0.0.20230121(transitive)
+ Addedevent-iterator@2.0.0(transitive)
+ Addedhirestime@7.0.4(transitive)
+ Addedit-pushable@3.2.3(transitive)
+ Addedp-defer@4.0.1(transitive)
- Removedp-event@^5.0.1
- Removed@ndn/fw@0.0.20220501(transitive)
- Removed@ndn/l3face@0.0.20220501(transitive)
- Removed@ndn/lp@0.0.20220501(transitive)
- Removed@ndn/packet@0.0.20220501(transitive)
- Removed@ndn/tlv@0.0.20220501(transitive)
- Removed@ndn/util@0.0.20220501(transitive)
- Removedhirestime@6.1.0(transitive)
- Removedit-pushable@2.0.2(transitive)
Updated@ndn/l3face@0.0.20230121
Updatedtslib@^2.4.1