diodejs 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -65
- package/clientManager.js +1657 -78
- package/networkDiscoveryClient.js +89 -0
- package/package.json +4 -3
- package/scripts/benchmark-relay-selection.js +476 -0
- package/test/clientManager.relaySelection.test.js +1376 -0
- package/test/fixtures/dio-network-snapshot.json +82 -0
package/README.md
CHANGED
|
@@ -38,22 +38,40 @@ DIODE_TICKET_BYTES_THRESHOLD=512000
|
|
|
38
38
|
DIODE_TICKET_UPDATE_INTERVAL=30000
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
These settings can also be configured programmatically
|
|
41
|
+
These settings can also be configured programmatically on the relay connections managed by `DiodeClientManager`:
|
|
42
42
|
```javascript
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
const { DiodeClientManager } = require('diodejs');
|
|
44
|
+
|
|
45
|
+
async function main() {
|
|
46
|
+
const client = new DiodeClientManager({ keyLocation: './db/keys.json' });
|
|
47
|
+
await client.connect();
|
|
48
|
+
|
|
49
|
+
for (const connection of client.getConnections()) {
|
|
50
|
+
connection.setReconnectOptions({
|
|
51
|
+
maxRetries: 10,
|
|
52
|
+
retryDelay: 2000,
|
|
53
|
+
maxRetryDelay: 20000,
|
|
54
|
+
autoReconnect: true
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
connection.setTicketBatchingOptions({
|
|
58
|
+
threshold: 512000,
|
|
59
|
+
interval: 30000
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
main();
|
|
51
65
|
```
|
|
52
66
|
|
|
53
67
|
### Multi-Relay Connections (Recommended)
|
|
54
68
|
|
|
55
69
|
You can connect to multiple Diode relays and automatically route binds to the relay where the target device is connected.
|
|
56
70
|
|
|
71
|
+
`DiodeClientManager` now ranks relays by observed latency. On startup it probes the required candidate set, persists relay scores to disk, and prefers the lowest-latency connected relay for control-plane RPC calls. It does not ping the full network at startup.
|
|
72
|
+
|
|
73
|
+
When neither `host` nor `hosts` is specified, the manager starts from the default seed pool, any discovery-provider candidates, built-in `dio_network` candidates, and previously successful non-provider relays saved in `relay-scores.json`. Without live network discovery it probes all default seeds once. When live network discovery returns usable relays, startup resolves from a region-diverse seed bootstrap subset plus the bounded discovery sample, then continues measuring the remaining seeds in the background while keeping region diversity in the warm set. If you pass `host` or `hosts`, startup stays constrained to those configured relays unless you explicitly opt into using the discovery provider alongside them.
|
|
74
|
+
|
|
57
75
|
```javascript
|
|
58
76
|
const { DiodeClientManager, BindPort } = require('diodejs');
|
|
59
77
|
|
|
@@ -69,6 +87,66 @@ async function main() {
|
|
|
69
87
|
}
|
|
70
88
|
```
|
|
71
89
|
|
|
90
|
+
You can tune relay selection if needed:
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
const client = new DiodeClientManager({
|
|
94
|
+
keyLocation: './db/keys.json',
|
|
95
|
+
relaySelection: {
|
|
96
|
+
startupConcurrency: 2,
|
|
97
|
+
minReadyConnections: 2,
|
|
98
|
+
probeTimeoutMs: 1200,
|
|
99
|
+
warmConnectionBudget: 3,
|
|
100
|
+
probeAllInitialCandidates: true,
|
|
101
|
+
continueProbingUntestedSeeds: true,
|
|
102
|
+
regionDiverseSeedOrdering: true,
|
|
103
|
+
discoveryProviderTimeoutMs: 1500,
|
|
104
|
+
backgroundProbeIntervalMs: 300000,
|
|
105
|
+
slowRelayThresholdMs: 250,
|
|
106
|
+
slowDeviceRetryTtlMs: 5000,
|
|
107
|
+
scoreCachePath: './db/relay-scores.json'
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Routing note: the initiating client can prefer a better local relay, but it cannot override the relay encoded in the remote device ticket. Best results come when both clients use the manager's relay ranking so each side reconnects toward a closer relay over time.
|
|
113
|
+
|
|
114
|
+
Discovery note: startup discovery sources are now `configured/seed`, `discoveryProvider`, built-in live `dio_network` discovery, cached non-provider/non-network relays, and target-on-demand relay resolution from `getNode(serverId)`. Provider and network membership are not cached independently; only RTT/history is persisted in `relay-scores.json`.
|
|
115
|
+
|
|
116
|
+
Example discovery provider:
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const fs = require('fs/promises');
|
|
120
|
+
|
|
121
|
+
const client = new DiodeClientManager({
|
|
122
|
+
keyLocation: './db/keys.json',
|
|
123
|
+
relaySelection: {
|
|
124
|
+
discoveryProvider: async () => {
|
|
125
|
+
const data = JSON.parse(await fs.readFile('./relays.json', 'utf8'));
|
|
126
|
+
return data;
|
|
127
|
+
},
|
|
128
|
+
networkDiscovery: {
|
|
129
|
+
endpoint: 'wss://prenet.diode.io:8443/ws',
|
|
130
|
+
startupProbeCount: 2,
|
|
131
|
+
backgroundBatchSize: 12
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`discoveryProvider(context)` may return either relay strings such as `'relay.example.com:41046'` or objects like `{ host, port, priority, region, metadata }`. The callback receives a read-only `context` object with:
|
|
138
|
+
|
|
139
|
+
- `defaultPort`
|
|
140
|
+
- `keyLocation`
|
|
141
|
+
- `explicitHost`
|
|
142
|
+
- `explicitHosts`
|
|
143
|
+
- `initialHosts`
|
|
144
|
+
- `knownRelayScores`
|
|
145
|
+
|
|
146
|
+
`knownRelayScores` contains the manager's current score snapshot for previously seen relays. Provider membership itself is not cached across runs; only relay score history is persisted.
|
|
147
|
+
|
|
148
|
+
Built-in network discovery uses the Diode JSON-RPC websocket endpoint and requests `dio_network`. It is enabled by default only when neither `host` nor `hosts` is set. Only connected `server` nodes are considered, and private/unroutable addresses are filtered unless `includePrivateAddresses` is enabled. When discovery succeeds, startup keeps the seed safety baseline by probing one seed per region before adding the configured discovery sample, instead of blocking on every seed before ready.
|
|
149
|
+
|
|
72
150
|
If you provide a host, only that relay is used initially (similar to `-diodeaddrs`):
|
|
73
151
|
|
|
74
152
|
```javascript
|
|
@@ -85,25 +163,35 @@ await client.connect();
|
|
|
85
163
|
Here's a quick example to get you started with RPC functions using `DiodeRPC` Class
|
|
86
164
|
|
|
87
165
|
```javascript
|
|
88
|
-
const {
|
|
166
|
+
const { DiodeClientManager, DiodeRPC, makeReadable } = require('diodejs');
|
|
89
167
|
|
|
90
168
|
async function main() {
|
|
91
169
|
const host = 'eu2.prenet.diode.io';
|
|
92
170
|
const port = 41046;
|
|
93
171
|
const keyLocation = './db/keys.json'; // Optional, defaults to './db/keys.json'
|
|
94
172
|
|
|
95
|
-
const
|
|
96
|
-
|
|
173
|
+
const client = new DiodeClientManager({ host, port, keyLocation });
|
|
174
|
+
await client.connect();
|
|
175
|
+
|
|
176
|
+
const connection = client.getConnections()[0];
|
|
177
|
+
if (!connection) {
|
|
178
|
+
throw new Error('No relay connection available');
|
|
179
|
+
}
|
|
180
|
+
|
|
97
181
|
// Configure reconnection (optional - overrides environment variables)
|
|
98
182
|
connection.setReconnectOptions({
|
|
99
183
|
maxRetries: Infinity, // Unlimited reconnection attempts
|
|
100
184
|
retryDelay: 1000, // Initial delay of 1 second
|
|
101
185
|
maxRetryDelay: 30000, // Maximum delay of 30 seconds
|
|
102
|
-
autoReconnect: true
|
|
103
|
-
ticketBytesThreshold: 512000, // Bytes threshold for ticket updates
|
|
104
|
-
ticketUpdateInterval: 30000 // Time interval for ticket updates
|
|
186
|
+
autoReconnect: true // Automatically reconnect on disconnection
|
|
105
187
|
});
|
|
106
|
-
|
|
188
|
+
|
|
189
|
+
// Configure ticket batching (optional - overrides environment variables)
|
|
190
|
+
connection.setTicketBatchingOptions({
|
|
191
|
+
threshold: 512000, // Bytes threshold for ticket updates
|
|
192
|
+
interval: 30000 // Time interval for ticket updates
|
|
193
|
+
});
|
|
194
|
+
|
|
107
195
|
// Listen for reconnection events (optional)
|
|
108
196
|
connection.on('reconnecting', (info) => {
|
|
109
197
|
console.log(`Reconnecting... Attempt #${info.attempt} in ${info.delay}ms`);
|
|
@@ -114,8 +202,6 @@ async function main() {
|
|
|
114
202
|
connection.on('reconnect_failed', () => {
|
|
115
203
|
console.log('Failed to reconnect after maximum attempts');
|
|
116
204
|
});
|
|
117
|
-
|
|
118
|
-
await connection.connect();
|
|
119
205
|
|
|
120
206
|
const rpc = new DiodeRPC(connection);
|
|
121
207
|
|
|
@@ -130,7 +216,7 @@ async function main() {
|
|
|
130
216
|
} catch (error) {
|
|
131
217
|
console.error('RPC Error:', error);
|
|
132
218
|
} finally {
|
|
133
|
-
|
|
219
|
+
client.close();
|
|
134
220
|
}
|
|
135
221
|
}
|
|
136
222
|
|
|
@@ -143,15 +229,15 @@ Here's a quick example to get you started with port forwarding using the `BindPo
|
|
|
143
229
|
|
|
144
230
|
#### Port Binding
|
|
145
231
|
```javascript
|
|
146
|
-
const {
|
|
232
|
+
const { DiodeClientManager, BindPort } = require('diodejs');
|
|
147
233
|
|
|
148
234
|
async function main() {
|
|
149
235
|
const host = 'eu2.prenet.diode.io';
|
|
150
236
|
const port = 41046;
|
|
151
237
|
const keyLocation = './db/keys.json';
|
|
152
238
|
|
|
153
|
-
const
|
|
154
|
-
await
|
|
239
|
+
const client = new DiodeClientManager({ host, port, keyLocation });
|
|
240
|
+
await client.connect();
|
|
155
241
|
|
|
156
242
|
// Multiple or single port binding with configuration object
|
|
157
243
|
const portsConfig = {
|
|
@@ -168,7 +254,7 @@ async function main() {
|
|
|
168
254
|
}
|
|
169
255
|
};
|
|
170
256
|
|
|
171
|
-
const portForward = new BindPort(
|
|
257
|
+
const portForward = new BindPort(client, portsConfig);
|
|
172
258
|
portForward.bind();
|
|
173
259
|
|
|
174
260
|
// You can also dynamically add ports with protocol specification
|
|
@@ -181,18 +267,18 @@ main();
|
|
|
181
267
|
|
|
182
268
|
#### Single Port Binding (Legacy)
|
|
183
269
|
```javascript
|
|
184
|
-
const {
|
|
270
|
+
const { DiodeClientManager, BindPort } = require('diodejs');
|
|
185
271
|
|
|
186
272
|
async function main() {
|
|
187
273
|
const host = 'eu2.prenet.diode.io';
|
|
188
274
|
const port = 41046;
|
|
189
275
|
const keyLocation = './db/keys.json';
|
|
190
276
|
|
|
191
|
-
const
|
|
192
|
-
await
|
|
277
|
+
const client = new DiodeClientManager({ host, port, keyLocation });
|
|
278
|
+
await client.connect();
|
|
193
279
|
|
|
194
280
|
// Legacy method - single port binding (defaults to TLS protocol)
|
|
195
|
-
const portForward = new BindPort(
|
|
281
|
+
const portForward = new BindPort(client, 3002, 80, "5365baf29cb7ab58de588dfc448913cb609283e2");
|
|
196
282
|
portForward.bind();
|
|
197
283
|
}
|
|
198
284
|
|
|
@@ -204,15 +290,15 @@ main();
|
|
|
204
290
|
Here's a quick example to get you started with publishing ports using the `PublishPort` class:
|
|
205
291
|
|
|
206
292
|
```javascript
|
|
207
|
-
const {
|
|
293
|
+
const { DiodeClientManager, PublishPort } = require('diodejs');
|
|
208
294
|
|
|
209
295
|
async function main() {
|
|
210
296
|
const host = 'us2.prenet.diode.io';
|
|
211
297
|
const port = 41046;
|
|
212
298
|
const keyLocation = './db/keys.json';
|
|
213
299
|
|
|
214
|
-
const
|
|
215
|
-
await
|
|
300
|
+
const client = new DiodeClientManager({ host, port, keyLocation });
|
|
301
|
+
await client.connect();
|
|
216
302
|
|
|
217
303
|
// Option 1: Simple array of ports (all public)
|
|
218
304
|
const publishedPorts = [8080, 3000];
|
|
@@ -227,7 +313,7 @@ async function main() {
|
|
|
227
313
|
};
|
|
228
314
|
|
|
229
315
|
// certPath parameter is maintained for backward compatibility but not required
|
|
230
|
-
const publishPort = new PublishPort(
|
|
316
|
+
const publishPort = new PublishPort(client, publishedPortsWithConfig);
|
|
231
317
|
}
|
|
232
318
|
|
|
233
319
|
main();
|
|
@@ -237,35 +323,6 @@ main();
|
|
|
237
323
|
|
|
238
324
|
### Classes and Methods
|
|
239
325
|
|
|
240
|
-
#### `DiodeConnection`
|
|
241
|
-
|
|
242
|
-
- **Constructor**: `new DiodeConnection(host, port, keyLocation)`
|
|
243
|
-
- `host` (string): The host address of the Diode server.
|
|
244
|
-
- `port` (number): The port number of the Diode server.
|
|
245
|
-
- `keyLocation` (string)(default: './db/keys.json'): The path to the key storage file. If the file doesn't exist, keys are generated automatically.
|
|
246
|
-
|
|
247
|
-
- **Methods**:
|
|
248
|
-
- `connect()`: Connects to the Diode server. Returns a promise.
|
|
249
|
-
- `sendCommand(commandArray)`: Sends a command to the Diode server. Returns a promise.
|
|
250
|
-
- `sendCommandWithSessionId(commandArray, sessionId)`: Sends a command with a session ID. Returns a promise.
|
|
251
|
-
- `getEthereumAddress()`: Returns the Ethereum address derived from the device keys.
|
|
252
|
-
- `getServerEthereumAddress()`: Returns the Ethereum address of the server.
|
|
253
|
-
- `createTicketCommand()`: Creates a ticket command for authentication. Returns a promise.
|
|
254
|
-
- `close()`: Closes the connection to the Diode server.
|
|
255
|
-
- `getDeviceCertificate()`: Returns the generated certificate PEM.
|
|
256
|
-
- `setReconnectOptions(options)`: Configures reconnection behavior with the following options:
|
|
257
|
-
- `maxRetries` (number): Maximum reconnection attempts (default: Infinity)
|
|
258
|
-
- `retryDelay` (number): Initial delay between retries in ms (default: 1000)
|
|
259
|
-
- `maxRetryDelay` (number): Maximum delay between retries in ms (default: 30000)
|
|
260
|
-
- `autoReconnect` (boolean): Whether to automatically reconnect on disconnection (default: true)
|
|
261
|
-
- `ticketBytesThreshold` (number): Bytes threshold for ticket updates (default: 512000)
|
|
262
|
-
- `ticketUpdateInterval` (number): Time interval for ticket updates in ms (default: 30000)
|
|
263
|
-
|
|
264
|
-
- **Events**:
|
|
265
|
-
- `reconnecting`: Emitted when a reconnection attempt is about to start, with `attempt` and `delay` information
|
|
266
|
-
- `reconnected`: Emitted when reconnection is successful
|
|
267
|
-
- `reconnect_failed`: Emitted when all reconnection attempts have failed
|
|
268
|
-
|
|
269
326
|
#### `DiodeClientManager`
|
|
270
327
|
|
|
271
328
|
- **Constructor**: `new DiodeClientManager(options)`
|
|
@@ -274,17 +331,51 @@ main();
|
|
|
274
331
|
- `options.hosts` (string[] or comma-separated string, optional): Explicit relay list.
|
|
275
332
|
- `options.keyLocation` (string, optional): Key storage path (default: `./db/keys.json`).
|
|
276
333
|
- `options.deviceCacheTtlMs` (number, optional): Cache TTL for device relay resolution (default: `30000`).
|
|
334
|
+
- `options.relaySelection` (object, optional): Relay ranking and probing options.
|
|
335
|
+
- `enabled` (boolean, optional): Enables smart relay ranking. Defaults to `true`.
|
|
336
|
+
- `startupConcurrency` (number, optional): Parallel startup probe limit. Defaults to `2`.
|
|
337
|
+
- `minReadyConnections` (number, optional): Minimum target connection count for the startup probe set. Defaults to `2`.
|
|
338
|
+
- `probeTimeoutMs` (number, optional): Ping timeout for relay probes. Defaults to `1200`.
|
|
339
|
+
- `warmConnectionBudget` (number, optional): Maximum number of idle control relays to keep after startup coverage completes. Defaults to `3`.
|
|
340
|
+
- `probeAllInitialCandidates` (boolean, optional): Probes all initial configured/default candidates once before final startup ranking is trusted. Defaults to `true`.
|
|
341
|
+
- `continueProbingUntestedSeeds` (boolean, optional): Continues probing untested candidates after startup coverage completes. Defaults to `true`.
|
|
342
|
+
- `regionDiverseSeedOrdering` (boolean, optional): Interleaves seed regions during first-pass probing and warm retention. Defaults to `true`.
|
|
343
|
+
- `discoveryProvider` (function, optional): Async or sync callback that returns extra relay candidates as strings or `{ host, port, priority, region, metadata }` objects. The callback receives `{ defaultPort, keyLocation, explicitHost, explicitHosts, initialHosts, knownRelayScores }`.
|
|
344
|
+
- `discoveryProviderTimeoutMs` (number, optional): Timeout for `discoveryProvider` results. Defaults to `1500`.
|
|
345
|
+
- `useProviderWithExplicitHost` (boolean, optional): Allows provider candidates when `options.host` is set. Defaults to `false`.
|
|
346
|
+
- `useProviderWithExplicitHosts` (boolean, optional): Allows provider candidates when `options.hosts` is set. Defaults to `false`.
|
|
347
|
+
- `networkDiscovery` (object, optional): Built-in live directory discovery via the JSON-RPC websocket endpoint.
|
|
348
|
+
- `enabled` (boolean, optional): Enables live network discovery when no explicit `host` or `hosts` is configured. Defaults to `true` in default mode.
|
|
349
|
+
- `endpoint` (string, optional): Directory endpoint. Defaults to `wss://prenet.diode.io:8443/ws`.
|
|
350
|
+
- `method` (string, optional): JSON-RPC method name. Defaults to `dio_network`.
|
|
351
|
+
- `timeoutMs` (number, optional): Timeout for the discovery websocket request. Defaults to `1500`.
|
|
352
|
+
- `startupProbeCount` (number, optional): Number of discovered network relays added to the startup coverage probe set. Defaults to `2`.
|
|
353
|
+
- `backgroundBatchSize` (number, optional): Number of additional discovered relays measured in the background queue per run. Defaults to `12`.
|
|
354
|
+
- `includePrivateAddresses` (boolean, optional): Allows private or unroutable discovery results to be used. Defaults to `false`.
|
|
355
|
+
- `backgroundProbeIntervalMs` (number, optional): Minimum interval before background refresh probes are retried for a relay. Defaults to `300000`.
|
|
356
|
+
- `slowRelayThresholdMs` (number, optional): RTT threshold used to shorten target relay cache entries. Defaults to `250`.
|
|
357
|
+
- `slowDeviceRetryTtlMs` (number, optional): TTL used for slow target relays. Defaults to `5000`.
|
|
358
|
+
- `deviceRelayReconciliation` (object, optional): Bounded fallback that re-resolves a device through alternate connected control relays when the initially resolved target relay is much slower than the current control relay baseline.
|
|
359
|
+
- `enabled` (boolean, optional): Enables reconciliation. Defaults to `true`.
|
|
360
|
+
- `maxControlRelays` (number, optional): Maximum number of alternate connected control relays queried per reconciliation attempt. Defaults to `2`.
|
|
361
|
+
- `timeoutMs` (number, optional): Per-control-relay timeout for reconciliation lookups. Defaults to `probeTimeoutMs`.
|
|
362
|
+
- `minLatencyDeltaMs` (number, optional): Minimum RTT gap between the target relay and the control relay baseline before reconciliation triggers. Defaults to `150`.
|
|
363
|
+
- `slowdownFactor` (number, optional): Minimum multiple by which the target relay RTT must exceed the control relay baseline before reconciliation triggers. Defaults to `4`.
|
|
364
|
+
- `scoreCachePath` (string|null, optional): Relay score cache file. Defaults to `./db/relay-scores.json` next to `keyLocation`. Set to `null` to disable persistence.
|
|
277
365
|
|
|
278
366
|
- **Methods**:
|
|
279
|
-
- `connect()`:
|
|
367
|
+
- `connect()`: Probes the required initial relays, merges provider and optional `dio_network` candidates, ranks the successful relays by latency, trims the warm relay set, and returns a promise. In live network discovery mode this starts from a region-diverse seed bootstrap subset plus the bounded discovery sample, then continues probing the remaining seeds in the background.
|
|
368
|
+
- `getNearestConnection()`: Returns the preferred connected relay. With relay selection enabled, this is the lowest-latency scored relay.
|
|
280
369
|
- `getConnectionForDevice(deviceId)`: Resolves and returns a relay connection for the device. Returns a promise.
|
|
281
370
|
- `getConnections()`: Returns a list of active connections.
|
|
282
371
|
- `close()`: Closes all managed connections.
|
|
283
372
|
|
|
373
|
+
Connections returned by `getConnections()` or `getConnectionForDevice()` emit `reconnecting`, `reconnected`, and `reconnect_failed` events, and support `setReconnectOptions(...)` and `setTicketBatchingOptions({ threshold, interval })`.
|
|
374
|
+
|
|
284
375
|
#### `DiodeRPC`
|
|
285
376
|
|
|
286
377
|
- **Constructor**: `new DiodeRPC(connection)`
|
|
287
|
-
- `connection` (
|
|
378
|
+
- `connection` (object): A relay connection from `DiodeClientManager.getConnections()` or `DiodeClientManager.getConnectionForDevice()`.
|
|
288
379
|
|
|
289
380
|
- **Methods**:
|
|
290
381
|
- `getBlockPeak()`: Retrieves the current block peak. Returns a promise.
|
|
@@ -308,14 +399,14 @@ main();
|
|
|
308
399
|
|
|
309
400
|
Legacy Constructor:
|
|
310
401
|
- `new BindPort(connection, localPort, targetPort, deviceIdHex)`
|
|
311
|
-
- `connection` (
|
|
402
|
+
- `connection` (DiodeClientManager): An instance of `DiodeClientManager`.
|
|
312
403
|
- `localPort` (number): The local port to bind.
|
|
313
404
|
- `targetPort` (number): The target port on the device.
|
|
314
405
|
- `deviceIdHex` (string): The device ID in hexadecimal format (with or without '0x' prefix).
|
|
315
406
|
|
|
316
407
|
New Constructor:
|
|
317
408
|
- `new BindPort(connection, portsConfig)`
|
|
318
|
-
- `connection` (
|
|
409
|
+
- `connection` (DiodeClientManager): An instance of `DiodeClientManager`.
|
|
319
410
|
- `portsConfig` (object): A configuration object where keys are local ports and values are objects with:
|
|
320
411
|
- `targetPort` (number): The target port on the device.
|
|
321
412
|
- `deviceIdHex` (string): The device ID in hexadecimal format (with or without '0x' prefix).
|
|
@@ -334,7 +425,7 @@ main();
|
|
|
334
425
|
#### `PublishPort`
|
|
335
426
|
|
|
336
427
|
- **Constructor**: `new PublishPort(connection, publishedPorts, _certPath)`
|
|
337
|
-
- `connection` (
|
|
428
|
+
- `connection` (DiodeClientManager): An instance of `DiodeClientManager`.
|
|
338
429
|
- `publishedPorts` (array|object): Either:
|
|
339
430
|
- An array of ports to publish (all public mode)
|
|
340
431
|
- An object mapping ports to their configuration: `{ port: { mode: 'public'|'private', whitelist: ['0x123...'] } }`
|