@ndn/node-transport
Advanced tools
Comparing version 0.0.20240113 to 0.0.20240630
export * from "./hostport_browser.js"; | ||
export * from "./tcp-transport_browser.js"; | ||
export * from "./unix-transport_browser.js"; | ||
import * as udp_helper from "./udp-helper_browser.js"; export { udp_helper }; | ||
export * from "./udp-transport_browser.js"; | ||
export * from "./unix-transport_browser.js"; |
export * from "./hostport_node.js"; | ||
export * from "./tcp-transport_node.js"; | ||
export * from "./unix-transport_node.js"; | ||
import * as udp_helper from "./udp-helper_node.js"; export { udp_helper }; | ||
export * from "./udp-transport_node.js"; | ||
export * from "./unix-transport_node.js"; |
export * from "./hostport.js"; | ||
export * from "./tcp-transport.js"; | ||
export * from "./unix-transport.js"; | ||
import * as udp_helper from "./udp-helper.js"; export { udp_helper }; | ||
export * from "./udp-transport.js"; | ||
export * from "./unix-transport.js"; |
@@ -1,8 +0,23 @@ | ||
import * as net from "net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import { joinHostPort } from "./hostport_browser.js"; | ||
const DEFAULT_PORT = 6363; | ||
import { connectAndWaitConnected } from "./impl-net-connect_browser.js"; | ||
/** TCP socket transport. */ | ||
export class TcpTransport extends StreamTransport { | ||
connectOpts; | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param host - Remote host (default is localhost) or endpoint address (with other options). | ||
* @param port - Remote port. Default is 6363. | ||
* @param opts - Other options. | ||
* @see {@link TcpTransport.createFace} | ||
*/ | ||
static async connect(host, port = 6363, opts = {}) { | ||
const combined = { | ||
port, | ||
noDelay: true, | ||
...(typeof host === "string" ? { host } : host), | ||
...opts, | ||
}; | ||
return new TcpTransport(await connectAndWaitConnected(combined), combined); | ||
} | ||
constructor(sock, connectOpts) { | ||
@@ -15,2 +30,3 @@ super(sock, { | ||
} | ||
/** Reopen the transport by making a new connection with the same options. */ | ||
reopen() { | ||
@@ -21,35 +37,4 @@ return TcpTransport.connect(this.connectOpts); | ||
(function (TcpTransport) { | ||
function connect(arg1, port, opts) { | ||
return connectImpl(arg1, port, opts); | ||
} | ||
TcpTransport.connect = connect; | ||
function connectImpl(arg1, port = DEFAULT_PORT, opts = {}) { | ||
const connectOpts = arg1 === undefined ? { port } : | ||
typeof arg1 === "string" ? { host: arg1, port } : | ||
{ host: arg1.host, port: arg1.port ?? DEFAULT_PORT, family: arg1.family }; | ||
const { connectTimeout = 10000, signal, } = typeof arg1 === "object" ? arg1 : opts; | ||
return new Promise((resolve, reject) => { | ||
const sock = net.connect(connectOpts); | ||
sock.setNoDelay(true); | ||
let timeout; // eslint-disable-line prefer-const | ||
const fail = (err) => { | ||
clearTimeout(timeout); | ||
sock.destroy(); | ||
reject(err); | ||
}; | ||
timeout = setTimeout(() => fail(new Error("connectTimeout")), connectTimeout); | ||
const onabort = () => fail(new Error("abort")); | ||
signal?.addEventListener("abort", onabort); | ||
sock.on("error", () => undefined); | ||
sock.once("error", fail); | ||
sock.once("connect", () => { | ||
clearTimeout(timeout); | ||
sock.off("error", fail); | ||
signal?.removeEventListener("abort", onabort); | ||
resolve(new TcpTransport(sock, connectOpts)); | ||
}); | ||
}); | ||
} | ||
/** Create a transport and add to forwarder. */ | ||
TcpTransport.createFace = L3Face.makeCreateFace(connectImpl); | ||
TcpTransport.createFace = L3Face.makeCreateFace(TcpTransport.connect); | ||
})(TcpTransport || (TcpTransport = {})); |
@@ -1,8 +0,23 @@ | ||
import * as net from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import { joinHostPort } from "./hostport_node.js"; | ||
const DEFAULT_PORT = 6363; | ||
import { connectAndWaitConnected } from "./impl-net-connect_node.js"; | ||
/** TCP socket transport. */ | ||
export class TcpTransport extends StreamTransport { | ||
connectOpts; | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param host - Remote host (default is localhost) or endpoint address (with other options). | ||
* @param port - Remote port. Default is 6363. | ||
* @param opts - Other options. | ||
* @see {@link TcpTransport.createFace} | ||
*/ | ||
static async connect(host, port = 6363, opts = {}) { | ||
const combined = { | ||
port, | ||
noDelay: true, | ||
...(typeof host === "string" ? { host } : host), | ||
...opts, | ||
}; | ||
return new TcpTransport(await connectAndWaitConnected(combined), combined); | ||
} | ||
constructor(sock, connectOpts) { | ||
@@ -15,2 +30,3 @@ super(sock, { | ||
} | ||
/** Reopen the transport by making a new connection with the same options. */ | ||
reopen() { | ||
@@ -21,35 +37,4 @@ return TcpTransport.connect(this.connectOpts); | ||
(function (TcpTransport) { | ||
function connect(arg1, port, opts) { | ||
return connectImpl(arg1, port, opts); | ||
} | ||
TcpTransport.connect = connect; | ||
function connectImpl(arg1, port = DEFAULT_PORT, opts = {}) { | ||
const connectOpts = arg1 === undefined ? { port } : | ||
typeof arg1 === "string" ? { host: arg1, port } : | ||
{ host: arg1.host, port: arg1.port ?? DEFAULT_PORT, family: arg1.family }; | ||
const { connectTimeout = 10000, signal, } = typeof arg1 === "object" ? arg1 : opts; | ||
return new Promise((resolve, reject) => { | ||
const sock = net.connect(connectOpts); | ||
sock.setNoDelay(true); | ||
let timeout; // eslint-disable-line prefer-const | ||
const fail = (err) => { | ||
clearTimeout(timeout); | ||
sock.destroy(); | ||
reject(err); | ||
}; | ||
timeout = setTimeout(() => fail(new Error("connectTimeout")), connectTimeout); | ||
const onabort = () => fail(new Error("abort")); | ||
signal?.addEventListener("abort", onabort); | ||
sock.on("error", () => undefined); | ||
sock.once("error", fail); | ||
sock.once("connect", () => { | ||
clearTimeout(timeout); | ||
sock.off("error", fail); | ||
signal?.removeEventListener("abort", onabort); | ||
resolve(new TcpTransport(sock, connectOpts)); | ||
}); | ||
}); | ||
} | ||
/** Create a transport and add to forwarder. */ | ||
TcpTransport.createFace = L3Face.makeCreateFace(connectImpl); | ||
TcpTransport.createFace = L3Face.makeCreateFace(TcpTransport.connect); | ||
})(TcpTransport || (TcpTransport = {})); |
@@ -1,34 +0,30 @@ | ||
/// <reference types="node" /> | ||
import * as net from "node:net"; | ||
import type { Socket, TcpSocketConnectOpts } from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import type { Except } from "type-fest"; | ||
import type { SetOptional } from "type-fest"; | ||
/** TCP socket transport. */ | ||
export declare class TcpTransport extends StreamTransport { | ||
export declare class TcpTransport extends StreamTransport<Socket> { | ||
private readonly connectOpts; | ||
constructor(sock: net.Socket, connectOpts: net.TcpNetConnectOpts); | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param host - Remote host (default is localhost) or endpoint address (with other options). | ||
* @param port - Remote port. Default is 6363. | ||
* @param opts - Other options. | ||
* @see {@link TcpTransport.createFace} | ||
*/ | ||
static connect(host?: string | (SetOptional<TcpSocketConnectOpts, "port"> & TcpTransport.Options), port?: number, opts?: TcpTransport.Options): Promise<TcpTransport>; | ||
private constructor(); | ||
/** Reopen the transport by making a new connection with the same options. */ | ||
reopen(): Promise<TcpTransport>; | ||
} | ||
export declare namespace TcpTransport { | ||
type NetConnectOpts = Except<net.TcpNetConnectOpts, "port"> & Partial<Pick<net.TcpNetConnectOpts, "port">>; | ||
/** {@link TcpTransport.connect} options. */ | ||
interface Options { | ||
/** Connect timeout (in milliseconds). */ | ||
/** | ||
* Connect timeout (in milliseconds). | ||
* @defaultValue 10000 | ||
*/ | ||
connectTimeout?: number; | ||
/** AbortSignal that allows canceling connection attempt via AbortController. */ | ||
signal?: AbortSignal; | ||
} | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param host remote host, default is "localhost". | ||
* @param port remote port, default is 6363. | ||
* @param opts other options. | ||
*/ | ||
function connect(host?: string, port?: number, opts?: Options): Promise<TcpTransport>; | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param opts remote endpoint and other options. | ||
*/ | ||
function connect(opts: NetConnectOpts & Options): Promise<TcpTransport>; | ||
/** Create a transport and add to forwarder. */ | ||
const createFace: L3Face.CreateFaceFunc<TcpTransport, [arg1?: string | ({ | ||
timeout?: number | undefined; | ||
const createFace: L3Face.CreateFaceFunc<[host?: string | ({ | ||
host?: string | undefined; | ||
@@ -39,3 +35,3 @@ localAddress?: string | undefined; | ||
family?: number | undefined; | ||
lookup?: net.LookupFunction | undefined; | ||
lookup?: import("net").LookupFunction | undefined; | ||
noDelay?: boolean | undefined; | ||
@@ -46,9 +42,5 @@ keepAlive?: boolean | undefined; | ||
autoSelectFamilyAttemptTimeout?: number | undefined; | ||
onread?: net.OnReadOpts | undefined; | ||
fd?: number | undefined; | ||
allowHalfOpen?: boolean | undefined; | ||
readable?: boolean | undefined; | ||
writable?: boolean | undefined; | ||
signal?: AbortSignal | undefined; | ||
} & Partial<Pick<net.TcpNetConnectOpts, "port">> & Options) | undefined, port?: number | undefined, opts?: Options | undefined]>; | ||
onread?: import("net").OnReadOpts | undefined; | ||
port?: number | undefined; | ||
} & Options) | undefined, port?: number | undefined, opts?: Options | undefined]>; | ||
} |
@@ -1,8 +0,8 @@ | ||
import * as dgram from "dgram"; | ||
import dgram from "dgram"; | ||
import { once } from "events"; | ||
import * as os from "os"; | ||
export const DEFAULT_MTU = 65000; | ||
import os from "os"; | ||
const DEFAULT_UNICAST_PORT = 6363; | ||
const DEFAULT_MULTICAST_GROUP = "224.0.23.170"; | ||
const DEFAULT_MULTICAST_PORT = 56363; | ||
/** Create a UDP socket and start listening on local endpoint. */ | ||
export async function openSocket({ family, recvBufferSize, sendBufferSize, bind = {}, }) { | ||
@@ -26,2 +26,3 @@ family ??= bind.address?.includes(":") ? 6 : 4; | ||
} | ||
/** Connect a UDP socket to remote endpoint. */ | ||
export async function connect(sock, { host, port = DEFAULT_UNICAST_PORT, }) { | ||
@@ -38,2 +39,3 @@ try { | ||
} | ||
/** Create a UDP socket and connect to remote endpoint. */ | ||
export async function openUnicast(opts) { | ||
@@ -60,2 +62,3 @@ if (!opts.family && opts.host.includes(":")) { | ||
} | ||
/** Create a UDP socket and prepare for receiving multicast datagrams. */ | ||
export async function openMulticastRx(opts) { | ||
@@ -78,2 +81,3 @@ const { intf, group = DEFAULT_MULTICAST_GROUP, port = DEFAULT_MULTICAST_PORT, multicastLoopback = false, } = opts; | ||
} | ||
/** Create a UDP socket and prepare for transmitting multicast datagrams. */ | ||
export async function openMulticastTx(opts) { | ||
@@ -80,0 +84,0 @@ const { intf, group = DEFAULT_MULTICAST_GROUP, port = DEFAULT_MULTICAST_PORT, multicastTtl = 1, } = opts; |
@@ -1,8 +0,8 @@ | ||
import * as dgram from "node:dgram"; | ||
import dgram from "node:dgram"; | ||
import { once } from "node:events"; | ||
import * as os from "node:os"; | ||
export const DEFAULT_MTU = 65000; | ||
import os from "node:os"; | ||
const DEFAULT_UNICAST_PORT = 6363; | ||
const DEFAULT_MULTICAST_GROUP = "224.0.23.170"; | ||
const DEFAULT_MULTICAST_PORT = 56363; | ||
/** Create a UDP socket and start listening on local endpoint. */ | ||
export async function openSocket({ family, recvBufferSize, sendBufferSize, bind = {}, }) { | ||
@@ -26,2 +26,3 @@ family ??= bind.address?.includes(":") ? 6 : 4; | ||
} | ||
/** Connect a UDP socket to remote endpoint. */ | ||
export async function connect(sock, { host, port = DEFAULT_UNICAST_PORT, }) { | ||
@@ -38,2 +39,3 @@ try { | ||
} | ||
/** Create a UDP socket and connect to remote endpoint. */ | ||
export async function openUnicast(opts) { | ||
@@ -60,2 +62,3 @@ if (!opts.family && opts.host.includes(":")) { | ||
} | ||
/** Create a UDP socket and prepare for receiving multicast datagrams. */ | ||
export async function openMulticastRx(opts) { | ||
@@ -78,2 +81,3 @@ const { intf, group = DEFAULT_MULTICAST_GROUP, port = DEFAULT_MULTICAST_PORT, multicastLoopback = false, } = opts; | ||
} | ||
/** Create a UDP socket and prepare for transmitting multicast datagrams. */ | ||
export async function openMulticastTx(opts) { | ||
@@ -80,0 +84,0 @@ const { intf, group = DEFAULT_MULTICAST_GROUP, port = DEFAULT_MULTICAST_PORT, multicastTtl = 1, } = opts; |
@@ -1,11 +0,10 @@ | ||
/// <reference types="node" /> | ||
import * as dgram from "node:dgram"; | ||
export declare const DEFAULT_MTU = 65000; | ||
export type Socket = dgram.Socket; | ||
import dgram from "node:dgram"; | ||
export type SocketBufferOptions = Pick<dgram.SocketOptions, "recvBufferSize" | "sendBufferSize">; | ||
export type AddressFamily = 4 | 6; | ||
/** {@link openSocket} options. */ | ||
export interface OpenSocketOptions extends SocketBufferOptions { | ||
/** | ||
* IPv4 or IPv6. | ||
* Default is IPv4, unless hostname is an IPv6 address (contains a colon). | ||
* @defaultValue | ||
* IPv4, unless hostname is a literal IPv6 address. | ||
*/ | ||
@@ -16,3 +15,5 @@ family?: AddressFamily; | ||
} | ||
export declare function openSocket({ family, recvBufferSize, sendBufferSize, bind, }: OpenSocketOptions): Promise<Socket>; | ||
/** Create a UDP socket and start listening on local endpoint. */ | ||
export declare function openSocket({ family, recvBufferSize, sendBufferSize, bind, }: OpenSocketOptions): Promise<dgram.Socket>; | ||
/** {@link connect} options. */ | ||
export interface ConnectOptions { | ||
@@ -24,6 +25,9 @@ /** Remote address. */ | ||
} | ||
export declare function connect(sock: Socket, { host, port, }: ConnectOptions): Promise<Socket>; | ||
/** Connect a UDP socket to remote endpoint. */ | ||
export declare function connect(sock: dgram.Socket, { host, port, }: ConnectOptions): Promise<dgram.Socket>; | ||
/** {@link openUnicast} options. */ | ||
export interface UnicastOptions extends OpenSocketOptions, ConnectOptions { | ||
} | ||
export declare function openUnicast(opts: UnicastOptions): Promise<Socket>; | ||
/** Create a UDP socket and connect to remote endpoint. */ | ||
export declare function openUnicast(opts: UnicastOptions): Promise<dgram.Socket>; | ||
/** | ||
@@ -34,15 +38,36 @@ * List network interfaces capable of IPv4 multicast. | ||
export declare function listMulticastIntfs(): string[]; | ||
/** {@link openMulticastRx} and {@link openMulticastTx} options. */ | ||
export interface MulticastOptions extends SocketBufferOptions { | ||
/** IPv4 address of local network interface. */ | ||
intf: string; | ||
/** Multicast group address. */ | ||
/** | ||
* Multicast group address. | ||
* @defaultValue 224.0.23.170 | ||
*/ | ||
group?: string; | ||
/** Local and group port. */ | ||
/** | ||
* Local and group port. | ||
* @defaultValue 56363 | ||
*/ | ||
port?: number; | ||
/** Multicast TTL (for unit testing). */ | ||
/** | ||
* Multicast TTL. | ||
* @defaultValue 1 | ||
* | ||
* @remarks | ||
* Changing this option is inadvisable except for unit testing. | ||
*/ | ||
multicastTtl?: number; | ||
/** MulticastLoopback flag (for unit testing). */ | ||
/** | ||
* MulticastLoopback flag. | ||
* @defaultValue false | ||
* | ||
* @remarks | ||
* Changing this option is inadvisable except for unit testing. | ||
*/ | ||
multicastLoopback?: boolean; | ||
} | ||
export declare function openMulticastRx(opts: MulticastOptions): Promise<Socket>; | ||
export declare function openMulticastTx(opts: MulticastOptions): Promise<Socket>; | ||
/** Create a UDP socket and prepare for receiving multicast datagrams. */ | ||
export declare function openMulticastRx(opts: MulticastOptions): Promise<dgram.Socket>; | ||
/** Create a UDP socket and prepare for transmitting multicast datagrams. */ | ||
export declare function openMulticastTx(opts: MulticastOptions): Promise<dgram.Socket>; |
import { __importDefault, __importStar } from "tslib"; | ||
import dgram from "dgram"; | ||
import { L3Face, rxFromPacketIterable, Transport } from "@ndn/l3face"; | ||
@@ -8,8 +9,32 @@ import _cjsDefaultImport0 from "event-iterator"; const EventIterator = __importDefault(_cjsDefaultImport0).default; | ||
export class UdpTransport extends Transport { | ||
rx; | ||
isMulticast; | ||
laddr; | ||
raddr; | ||
rxSock; | ||
txSock; | ||
/** | ||
* Create a unicast transport. | ||
* @param host - Remote host or endpoint address (with other options) or existing socket. | ||
* @param port - Remote port. Default is 6363. | ||
* @see {@link UdpTransport.createFace} | ||
*/ | ||
static async connect(host, port) { | ||
if (typeof host === "string") { | ||
host = { host }; | ||
} | ||
const sock = host instanceof dgram.Socket ? host : await udp.openUnicast({ port, ...host }); | ||
return new UdpTransport(sock); | ||
} | ||
/** | ||
* Create a multicast transport. | ||
* @param opts - Network interface and other options. | ||
* @see {@link UdpTransport.createMulticastFace} | ||
*/ | ||
static async multicast(opts) { | ||
const tx = await udp.openMulticastTx(opts); | ||
let rx; | ||
try { | ||
rx = await udp.openMulticastRx(opts); | ||
} | ||
catch (err) { | ||
tx.close(); | ||
throw err; | ||
} | ||
return new UdpTransport(tx, rx); | ||
} | ||
constructor(txSock, rxSock) { | ||
@@ -22,3 +47,2 @@ const [scheme, { address, port }] = rxSock ? ["UDPm", txSock.address()] : ["UDP", txSock.remoteAddress()]; | ||
if (rxSock) { | ||
this.isMulticast = true; | ||
this.rxSock = rxSock; | ||
@@ -31,3 +55,2 @@ this.txSock = txSock; | ||
else { | ||
this.isMulticast = false; | ||
this.rxSock = txSock; | ||
@@ -50,3 +73,26 @@ this.txSock = txSock; | ||
} | ||
get mtu() { return udp.DEFAULT_MTU; } | ||
/** Local endpoint address. */ | ||
laddr; | ||
/** Remote endpoint or multicast group address. */ | ||
raddr; | ||
rxSock; | ||
txSock; | ||
/** | ||
* Report MTU as 65487. | ||
* @see {@link https://superuser.com/a/1697822} | ||
*/ | ||
// https://github.com/typescript-eslint/typescript-eslint/issues/3602 | ||
// eslint-disable-next-line @typescript-eslint/class-literal-property-style | ||
get mtu() { return 65487; } | ||
rx; | ||
async tx(iterable) { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
} | ||
close() { | ||
@@ -61,45 +107,12 @@ try { | ||
} | ||
tx = async (iterable) => { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
}; | ||
} | ||
(function (UdpTransport) { | ||
function connect(arg1, port) { | ||
return connectImpl(arg1, port); | ||
} | ||
UdpTransport.connect = connect; | ||
async function connectImpl(arg1, port) { | ||
const opts = typeof arg1 === "string" ? { host: arg1, port } : arg1; | ||
const sock = await udp.openUnicast(opts); | ||
return new UdpTransport(sock); | ||
} | ||
/** Create a unicast transport and add to forwarder. */ | ||
UdpTransport.createFace = L3Face.makeCreateFace(connectImpl); | ||
/** Create a multicast transport. */ | ||
async function multicast(opts) { | ||
const tx = await udp.openMulticastTx(opts); | ||
let rx; | ||
try { | ||
rx = await udp.openMulticastRx(opts); | ||
} | ||
catch (err) { | ||
tx.close(); | ||
throw err; | ||
} | ||
return new UdpTransport(tx, rx); | ||
} | ||
UdpTransport.multicast = multicast; | ||
UdpTransport.createFace = L3Face.makeCreateFace(UdpTransport.connect); | ||
/** Create a multicast transport and add to forwarder. */ | ||
UdpTransport.createMulticastFace = L3Face.makeCreateFace(multicast); | ||
/** Create multicast transports on every interface. */ | ||
UdpTransport.createMulticastFace = L3Face.makeCreateFace(UdpTransport.multicast); | ||
/** Create multicast transports on every multicast-capable netif. */ | ||
async function multicasts(opts = {}) { | ||
const intfs = udp.listMulticastIntfs(); | ||
return (await Promise.allSettled(intfs.map((intf) => multicast({ ...opts, intf })))) | ||
return (await Promise.allSettled(intfs.map((intf) => UdpTransport.multicast({ ...opts, intf })))) | ||
.filter((res) => res.status === "fulfilled") | ||
@@ -109,4 +122,4 @@ .map(({ value }) => value); | ||
UdpTransport.multicasts = multicasts; | ||
/** Create multicast transports on every interface. */ | ||
/** Create multicast transports on every multicast-capable netif and add to forwarder. */ | ||
UdpTransport.createMulticastFaces = L3Face.makeCreateFace(multicasts); | ||
})(UdpTransport || (UdpTransport = {})); |
import { __importDefault, __importStar } from "tslib"; | ||
import dgram from "node:dgram"; | ||
import { L3Face, rxFromPacketIterable, Transport } from "@ndn/l3face"; | ||
@@ -8,8 +9,32 @@ import _cjsDefaultImport0 from "event-iterator"; const EventIterator = __importDefault(_cjsDefaultImport0).default; | ||
export class UdpTransport extends Transport { | ||
rx; | ||
isMulticast; | ||
laddr; | ||
raddr; | ||
rxSock; | ||
txSock; | ||
/** | ||
* Create a unicast transport. | ||
* @param host - Remote host or endpoint address (with other options) or existing socket. | ||
* @param port - Remote port. Default is 6363. | ||
* @see {@link UdpTransport.createFace} | ||
*/ | ||
static async connect(host, port) { | ||
if (typeof host === "string") { | ||
host = { host }; | ||
} | ||
const sock = host instanceof dgram.Socket ? host : await udp.openUnicast({ port, ...host }); | ||
return new UdpTransport(sock); | ||
} | ||
/** | ||
* Create a multicast transport. | ||
* @param opts - Network interface and other options. | ||
* @see {@link UdpTransport.createMulticastFace} | ||
*/ | ||
static async multicast(opts) { | ||
const tx = await udp.openMulticastTx(opts); | ||
let rx; | ||
try { | ||
rx = await udp.openMulticastRx(opts); | ||
} | ||
catch (err) { | ||
tx.close(); | ||
throw err; | ||
} | ||
return new UdpTransport(tx, rx); | ||
} | ||
constructor(txSock, rxSock) { | ||
@@ -22,3 +47,2 @@ const [scheme, { address, port }] = rxSock ? ["UDPm", txSock.address()] : ["UDP", txSock.remoteAddress()]; | ||
if (rxSock) { | ||
this.isMulticast = true; | ||
this.rxSock = rxSock; | ||
@@ -31,3 +55,2 @@ this.txSock = txSock; | ||
else { | ||
this.isMulticast = false; | ||
this.rxSock = txSock; | ||
@@ -50,3 +73,26 @@ this.txSock = txSock; | ||
} | ||
get mtu() { return udp.DEFAULT_MTU; } | ||
/** Local endpoint address. */ | ||
laddr; | ||
/** Remote endpoint or multicast group address. */ | ||
raddr; | ||
rxSock; | ||
txSock; | ||
/** | ||
* Report MTU as 65487. | ||
* @see {@link https://superuser.com/a/1697822} | ||
*/ | ||
// https://github.com/typescript-eslint/typescript-eslint/issues/3602 | ||
// eslint-disable-next-line @typescript-eslint/class-literal-property-style | ||
get mtu() { return 65487; } | ||
rx; | ||
async tx(iterable) { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
} | ||
close() { | ||
@@ -61,45 +107,12 @@ try { | ||
} | ||
tx = async (iterable) => { | ||
try { | ||
for await (const pkt of iterable) { | ||
this.txSock.send(pkt); | ||
} | ||
} | ||
finally { | ||
this.close(); | ||
} | ||
}; | ||
} | ||
(function (UdpTransport) { | ||
function connect(arg1, port) { | ||
return connectImpl(arg1, port); | ||
} | ||
UdpTransport.connect = connect; | ||
async function connectImpl(arg1, port) { | ||
const opts = typeof arg1 === "string" ? { host: arg1, port } : arg1; | ||
const sock = await udp.openUnicast(opts); | ||
return new UdpTransport(sock); | ||
} | ||
/** Create a unicast transport and add to forwarder. */ | ||
UdpTransport.createFace = L3Face.makeCreateFace(connectImpl); | ||
/** Create a multicast transport. */ | ||
async function multicast(opts) { | ||
const tx = await udp.openMulticastTx(opts); | ||
let rx; | ||
try { | ||
rx = await udp.openMulticastRx(opts); | ||
} | ||
catch (err) { | ||
tx.close(); | ||
throw err; | ||
} | ||
return new UdpTransport(tx, rx); | ||
} | ||
UdpTransport.multicast = multicast; | ||
UdpTransport.createFace = L3Face.makeCreateFace(UdpTransport.connect); | ||
/** Create a multicast transport and add to forwarder. */ | ||
UdpTransport.createMulticastFace = L3Face.makeCreateFace(multicast); | ||
/** Create multicast transports on every interface. */ | ||
UdpTransport.createMulticastFace = L3Face.makeCreateFace(UdpTransport.multicast); | ||
/** Create multicast transports on every multicast-capable netif. */ | ||
async function multicasts(opts = {}) { | ||
const intfs = udp.listMulticastIntfs(); | ||
return (await Promise.allSettled(intfs.map((intf) => multicast({ ...opts, intf })))) | ||
return (await Promise.allSettled(intfs.map((intf) => UdpTransport.multicast({ ...opts, intf })))) | ||
.filter((res) => res.status === "fulfilled") | ||
@@ -109,4 +122,4 @@ .map(({ value }) => value); | ||
UdpTransport.multicasts = multicasts; | ||
/** Create multicast transports on every interface. */ | ||
/** Create multicast transports on every multicast-capable netif and add to forwarder. */ | ||
UdpTransport.createMulticastFaces = L3Face.makeCreateFace(multicasts); | ||
})(UdpTransport || (UdpTransport = {})); |
@@ -1,2 +0,2 @@ | ||
/// <reference types="node" /> | ||
import dgram from "node:dgram"; | ||
import type { AddressInfo } from "node:net"; | ||
@@ -8,37 +8,45 @@ import { L3Face, Transport } from "@ndn/l3face"; | ||
export declare class UdpTransport extends Transport { | ||
readonly rx: Transport.Rx; | ||
readonly isMulticast: boolean; | ||
/** | ||
* Create a unicast transport. | ||
* @param host - Remote host or endpoint address (with other options) or existing socket. | ||
* @param port - Remote port. Default is 6363. | ||
* @see {@link UdpTransport.createFace} | ||
*/ | ||
static connect(host: string | udp.UnicastOptions | dgram.Socket, port?: number): Promise<UdpTransport>; | ||
/** | ||
* Create a multicast transport. | ||
* @param opts - Network interface and other options. | ||
* @see {@link UdpTransport.createMulticastFace} | ||
*/ | ||
static multicast(opts: udp.MulticastOptions): Promise<UdpTransport>; | ||
private constructor(); | ||
private constructor(); | ||
/** Local endpoint address. */ | ||
readonly laddr: AddressInfo; | ||
/** Remote endpoint or multicast group address. */ | ||
readonly raddr: AddressInfo; | ||
private readonly rxSock; | ||
private readonly txSock; | ||
constructor(unicast: udp.Socket); | ||
constructor(multicastTx: udp.Socket, multicastRx: udp.Socket); | ||
/** | ||
* Report MTU as 65487. | ||
* @see {@link https://superuser.com/a/1697822} | ||
*/ | ||
get mtu(): number; | ||
readonly rx: Transport.RxIterable; | ||
tx(iterable: Transport.TxIterable): Promise<void>; | ||
close(): void; | ||
readonly tx: (iterable: AsyncIterable<Uint8Array>) => Promise<void>; | ||
} | ||
export declare namespace UdpTransport { | ||
/** | ||
* Create a unicast transport. | ||
* @param host remote host. | ||
* @param port remote port, default is 6363. | ||
*/ | ||
function connect(host: string, port?: number): Promise<UdpTransport>; | ||
/** Create a unicast transport. */ | ||
function connect(opts: udp.UnicastOptions): Promise<UdpTransport>; | ||
/** Create a unicast transport and add to forwarder. */ | ||
const createFace: L3Face.CreateFaceFunc<UdpTransport, [arg1: string | udp.UnicastOptions, port?: number | undefined]>; | ||
/** Create a multicast transport. */ | ||
function multicast(opts: udp.MulticastOptions): Promise<UdpTransport>; | ||
const createFace: L3Face.CreateFaceFunc<[host: string | dgram.Socket | udp.UnicastOptions, port?: number | undefined]>; | ||
/** Create a multicast transport and add to forwarder. */ | ||
const createMulticastFace: L3Face.CreateFaceFunc<UdpTransport, [opts: udp.MulticastOptions]>; | ||
/** Create multicast transports on every interface. */ | ||
const createMulticastFace: L3Face.CreateFaceFunc<[opts: udp.MulticastOptions]>; | ||
/** Create multicast transports on every multicast-capable netif. */ | ||
function multicasts(opts?: Except<udp.MulticastOptions, "intf">): Promise<UdpTransport[]>; | ||
/** Create multicast transports on every interface. */ | ||
const createMulticastFaces: L3Face.CreateFaceFunc<UdpTransport[], [opts?: { | ||
group?: string | undefined; | ||
port?: number | undefined; | ||
multicastTtl?: number | undefined; | ||
multicastLoopback?: boolean | undefined; | ||
/** Create multicast transports on every multicast-capable netif and add to forwarder. */ | ||
const createMulticastFaces: L3Face.CreateFacesFunc<[opts?: { | ||
group?: string; | ||
port?: number; | ||
multicastTtl?: number; | ||
multicastLoopback?: boolean; | ||
recvBufferSize?: number | undefined; | ||
@@ -45,0 +53,0 @@ sendBufferSize?: number | undefined; |
@@ -1,6 +0,15 @@ | ||
import * as net from "net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import { connectAndWaitConnected } from "./impl-net-connect_browser.js"; | ||
/** Unix socket transport. */ | ||
export class UnixTransport extends StreamTransport { | ||
connectOpts; | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param path - Unix socket path or IPC options. | ||
* @see {@link UnixTransport.createFace} | ||
*/ | ||
static async connect(path) { | ||
const connectOpts = typeof path === "string" ? { path } : path; | ||
return new UnixTransport(await connectAndWaitConnected(connectOpts), connectOpts); | ||
} | ||
constructor(sock, connectOpts) { | ||
@@ -13,2 +22,3 @@ super(sock, { | ||
} | ||
/** Reopen the transport by making a new connection with the same options. */ | ||
reopen() { | ||
@@ -19,23 +29,4 @@ return UnixTransport.connect(this.connectOpts); | ||
(function (UnixTransport) { | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param pathOrOpts Unix socket path. | ||
*/ | ||
function connect(pathOrOpts) { | ||
const connectOpts = typeof pathOrOpts === "string" ? { path: pathOrOpts } : | ||
pathOrOpts; | ||
return new Promise((resolve, reject) => { | ||
const sock = net.connect(connectOpts); | ||
sock.setNoDelay(true); | ||
sock.on("error", () => undefined); | ||
sock.once("error", reject); | ||
sock.once("connect", () => { | ||
sock.off("error", reject); | ||
resolve(new UnixTransport(sock, connectOpts)); | ||
}); | ||
}); | ||
} | ||
UnixTransport.connect = connect; | ||
/** Create a transport and add to forwarder. */ | ||
UnixTransport.createFace = L3Face.makeCreateFace(UnixTransport.connect); | ||
})(UnixTransport || (UnixTransport = {})); |
@@ -1,6 +0,15 @@ | ||
import * as net from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
import { connectAndWaitConnected } from "./impl-net-connect_node.js"; | ||
/** Unix socket transport. */ | ||
export class UnixTransport extends StreamTransport { | ||
connectOpts; | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param path - Unix socket path or IPC options. | ||
* @see {@link UnixTransport.createFace} | ||
*/ | ||
static async connect(path) { | ||
const connectOpts = typeof path === "string" ? { path } : path; | ||
return new UnixTransport(await connectAndWaitConnected(connectOpts), connectOpts); | ||
} | ||
constructor(sock, connectOpts) { | ||
@@ -13,2 +22,3 @@ super(sock, { | ||
} | ||
/** Reopen the transport by making a new connection with the same options. */ | ||
reopen() { | ||
@@ -19,23 +29,4 @@ return UnixTransport.connect(this.connectOpts); | ||
(function (UnixTransport) { | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param pathOrOpts Unix socket path. | ||
*/ | ||
function connect(pathOrOpts) { | ||
const connectOpts = typeof pathOrOpts === "string" ? { path: pathOrOpts } : | ||
pathOrOpts; | ||
return new Promise((resolve, reject) => { | ||
const sock = net.connect(connectOpts); | ||
sock.setNoDelay(true); | ||
sock.on("error", () => undefined); | ||
sock.once("error", reject); | ||
sock.once("connect", () => { | ||
sock.off("error", reject); | ||
resolve(new UnixTransport(sock, connectOpts)); | ||
}); | ||
}); | ||
} | ||
UnixTransport.connect = connect; | ||
/** Create a transport and add to forwarder. */ | ||
UnixTransport.createFace = L3Face.makeCreateFace(UnixTransport.connect); | ||
})(UnixTransport || (UnixTransport = {})); |
@@ -1,18 +0,19 @@ | ||
/// <reference types="node" /> | ||
import * as net from "node:net"; | ||
import type { IpcSocketConnectOpts, Socket } from "node:net"; | ||
import { L3Face, StreamTransport } from "@ndn/l3face"; | ||
/** Unix socket transport. */ | ||
export declare class UnixTransport extends StreamTransport { | ||
export declare class UnixTransport extends StreamTransport<Socket> { | ||
private readonly connectOpts; | ||
constructor(sock: net.Socket, connectOpts: net.IpcNetConnectOpts); | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param path - Unix socket path or IPC options. | ||
* @see {@link UnixTransport.createFace} | ||
*/ | ||
static connect(path: string | IpcSocketConnectOpts): Promise<UnixTransport>; | ||
private constructor(); | ||
/** Reopen the transport by making a new connection with the same options. */ | ||
reopen(): Promise<UnixTransport>; | ||
} | ||
export declare namespace UnixTransport { | ||
/** | ||
* Create a transport and connect to remote endpoint. | ||
* @param pathOrOpts Unix socket path. | ||
*/ | ||
function connect(pathOrOpts: string | net.IpcNetConnectOpts): Promise<UnixTransport>; | ||
/** Create a transport and add to forwarder. */ | ||
const createFace: L3Face.CreateFaceFunc<UnixTransport, [pathOrOpts: string | net.IpcNetConnectOpts]>; | ||
const createFace: L3Face.CreateFaceFunc<[path: string | IpcSocketConnectOpts]>; | ||
} |
{ | ||
"name": "@ndn/node-transport", | ||
"version": "0.0.20240113", | ||
"version": "0.0.20240630", | ||
"description": "NDNts: Low-Level Transports for Node.js", | ||
@@ -20,9 +20,10 @@ "keywords": [ | ||
"url": "https://github.com/yoursunny/NDNts.git", | ||
"directory": "packages/node-transport" | ||
"directory": "pkg/node-transport" | ||
}, | ||
"dependencies": { | ||
"@ndn/l3face": "0.0.20240113", | ||
"@ndn/l3face": "0.0.20240630", | ||
"event-iterator": "^2.0.0", | ||
"tslib": "^2.6.2", | ||
"type-fest": "^4.9.0", | ||
"p-event": "^6.0.1", | ||
"tslib": "^2.6.3", | ||
"type-fest": "^4.20.1", | ||
"url-format-lax": "^2.0.0", | ||
@@ -29,0 +30,0 @@ "url-parse-lax": "^5.0.0" |
@@ -11,2 +11,4 @@ import { TcpTransport, UdpTransport, UnixTransport } from "@ndn/node-transport"; | ||
// NOTICE: ndnts-demo-*.ndn.today hostnames are not intended for general application use. | ||
// UnixTransport.connect() establishes a UNIX socket connection. | ||
@@ -24,3 +26,3 @@ // It accepts a Unix socket path. | ||
try { | ||
const tcp4 = await TcpTransport.connect("suns.cs.ucla.edu", 6363); | ||
const tcp4 = await TcpTransport.connect("wundngw.wustl.edu", 6363); | ||
await useInL3Face(tcp4); | ||
@@ -33,3 +35,3 @@ } catch (err: unknown) { // router unavailable | ||
try { | ||
const tcp6 = await TcpTransport.connect({ host: "ndnhub.ipv6.lip6.fr", family: 6 }); | ||
const tcp6 = await TcpTransport.connect({ host: "ndnts-demo-tcp6.ndn.today", family: 6 }); | ||
await useInL3Face(tcp6); | ||
@@ -42,3 +44,3 @@ } catch (err: unknown) { // router unavailable | ||
try { | ||
const udp4 = await UdpTransport.connect("suns.cs.ucla.edu"); | ||
const udp4 = await UdpTransport.connect("wundngw.wustl.edu"); | ||
await useInL3Face(udp4); | ||
@@ -51,3 +53,3 @@ } catch (err: unknown) { // router unavailable | ||
try { | ||
const udp6 = await UdpTransport.connect({ host: "ndnhub.ipv6.lip6.fr", family: 6 }); | ||
const udp6 = await UdpTransport.connect({ host: "ndnts-demo-udp6.ndn.today", family: 6 }); | ||
await useInL3Face(udp6); | ||
@@ -70,3 +72,3 @@ } catch (err: unknown) { // router unavailable | ||
// It returns a FwFace instance (from @ndn/fw package). | ||
const face = await UdpTransport.createFace({}, "suns.cs.ucla.edu"); | ||
const face = await UdpTransport.createFace({}, "wundngw.wustl.edu"); | ||
face.close(); | ||
@@ -97,3 +99,3 @@ // TcpTransport.createFace() and UnixTransport.createFace() behave similarly. | ||
await delay(50); | ||
const interest = new Interest(`/ndn/edu/ucla/ping/NDNts/${seq++}`); | ||
const interest = new Interest(`/ndn/edu/memphis/ping/NDNts/${seq++}`); | ||
console.log(`${transport} <I ${interest.name}`); | ||
@@ -100,0 +102,0 @@ yield FwPacket.create(interest); |
Sorry, the diff of this file is not supported yet
41544
25
934
7
+ Addedp-event@^6.0.1
+ Added@ndn/fw@0.0.20240630(transitive)
+ Added@ndn/l3face@0.0.20240630(transitive)
+ Added@ndn/lp@0.0.20240630(transitive)
+ Added@ndn/packet@0.0.20240630(transitive)
+ Added@ndn/tlv@0.0.20240630(transitive)
+ Added@ndn/util@0.0.20240630(transitive)
+ Added@shigen/polyfill-symbol-dispose@1.0.1(transitive)
+ Addedtiny-invariant@1.3.3(transitive)
+ Addedwait-your-turn@1.0.1(transitive)
- Removed@ndn/fw@0.0.20240113(transitive)
- Removed@ndn/l3face@0.0.20240113(transitive)
- Removed@ndn/lp@0.0.20240113(transitive)
- Removed@ndn/packet@0.0.20240113(transitive)
- Removed@ndn/tlv@0.0.20240113(transitive)
- Removed@ndn/util@0.0.20240113(transitive)
- Removed@types/minimalistic-assert@1.0.3(transitive)
- Removedit-pushable@3.2.3(transitive)
- Removedminimalistic-assert@1.0.1(transitive)
- Removedp-defer@4.0.1(transitive)
Updated@ndn/l3face@0.0.20240630
Updatedtslib@^2.6.3
Updatedtype-fest@^4.20.1