@push.rocks/smartnetwork 4.1.2 → 4.3.0
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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/smartnetwork.classes.publicip.d.ts +39 -0
- package/dist_ts/smartnetwork.classes.publicip.js +136 -0
- package/dist_ts/smartnetwork.classes.smartnetwork.d.ts +10 -2
- package/dist_ts/smartnetwork.classes.smartnetwork.js +55 -20
- package/dist_ts/smartnetwork.plugins.d.ts +3 -3
- package/dist_ts/smartnetwork.plugins.js +4 -5
- package/package.json +6 -7
- package/readme.md +180 -96
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +1 -0
- package/ts/smartnetwork.classes.publicip.ts +163 -0
- package/ts/smartnetwork.classes.smartnetwork.ts +70 -20
- package/ts/smartnetwork.plugins.ts +3 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './smartnetwork.plugins.js';
|
|
2
2
|
import { CloudflareSpeed } from './smartnetwork.classes.cloudflarespeed.js';
|
|
3
|
+
import { PublicIp } from './smartnetwork.classes.publicip.js';
|
|
3
4
|
import { getLogger } from './logging.js';
|
|
4
5
|
import { NetworkError } from './errors.js';
|
|
5
6
|
import * as stats from './helpers/stats.js';
|
|
@@ -23,6 +24,15 @@ export interface Hop {
|
|
|
23
24
|
ip: string;
|
|
24
25
|
rtt: number | null;
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Options for the findFreePort method
|
|
30
|
+
*/
|
|
31
|
+
export interface IFindFreePortOptions {
|
|
32
|
+
/** If true, selects a random available port within the range instead of the first one */
|
|
33
|
+
randomize?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
export class SmartNetwork {
|
|
27
37
|
/** Static registry for external plugins */
|
|
28
38
|
public static pluginsRegistry: Map<string, any> = new Map();
|
|
@@ -147,9 +157,10 @@ export class SmartNetwork {
|
|
|
147
157
|
* Find the first available port within a given range
|
|
148
158
|
* @param startPort The start of the port range (inclusive)
|
|
149
159
|
* @param endPort The end of the port range (inclusive)
|
|
150
|
-
* @
|
|
160
|
+
* @param options Optional configuration for port selection behavior
|
|
161
|
+
* @returns The first available port number (or random if options.randomize is true), or null if no ports are available
|
|
151
162
|
*/
|
|
152
|
-
public async findFreePort(startPort: number, endPort: number): Promise<number | null> {
|
|
163
|
+
public async findFreePort(startPort: number, endPort: number, options?: IFindFreePortOptions): Promise<number | null> {
|
|
153
164
|
// Validate port range
|
|
154
165
|
if (startPort < 1 || startPort > 65535 || endPort < 1 || endPort > 65535) {
|
|
155
166
|
throw new NetworkError('Port numbers must be between 1 and 65535', 'EINVAL');
|
|
@@ -158,16 +169,38 @@ export class SmartNetwork {
|
|
|
158
169
|
throw new NetworkError('Start port must be less than or equal to end port', 'EINVAL');
|
|
159
170
|
}
|
|
160
171
|
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
// If randomize option is true, collect all available ports and select randomly
|
|
173
|
+
if (options?.randomize) {
|
|
174
|
+
const availablePorts: number[] = [];
|
|
175
|
+
|
|
176
|
+
// Scan the range to find all available ports
|
|
177
|
+
for (let port = startPort; port <= endPort; port++) {
|
|
178
|
+
const isUnused = await this.isLocalPortUnused(port);
|
|
179
|
+
if (isUnused) {
|
|
180
|
+
availablePorts.push(port);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// If there are available ports, select one randomly
|
|
185
|
+
if (availablePorts.length > 0) {
|
|
186
|
+
const randomIndex = Math.floor(Math.random() * availablePorts.length);
|
|
187
|
+
return availablePorts[randomIndex];
|
|
166
188
|
}
|
|
189
|
+
|
|
190
|
+
// No free port found in the range
|
|
191
|
+
return null;
|
|
192
|
+
} else {
|
|
193
|
+
// Default behavior: return the first available port (sequential search)
|
|
194
|
+
for (let port = startPort; port <= endPort; port++) {
|
|
195
|
+
const isUnused = await this.isLocalPortUnused(port);
|
|
196
|
+
if (isUnused) {
|
|
197
|
+
return port;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// No free port found in the range
|
|
202
|
+
return null;
|
|
167
203
|
}
|
|
168
|
-
|
|
169
|
-
// No free port found in the range
|
|
170
|
-
return null;
|
|
171
204
|
}
|
|
172
205
|
|
|
173
206
|
/**
|
|
@@ -259,10 +292,10 @@ export class SmartNetwork {
|
|
|
259
292
|
* Lookup public IPv4 and IPv6
|
|
260
293
|
*/
|
|
261
294
|
public async getPublicIps(): Promise<{ v4: string | null; v6: string | null }> {
|
|
262
|
-
const fetcher = async () =>
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
295
|
+
const fetcher = async () => {
|
|
296
|
+
const publicIp = new PublicIp({ timeout: 1000 });
|
|
297
|
+
return publicIp.getPublicIps();
|
|
298
|
+
};
|
|
266
299
|
if (this.options.cacheTtl && this.options.cacheTtl > 0) {
|
|
267
300
|
return this.getCached('publicIps', fetcher);
|
|
268
301
|
}
|
|
@@ -276,13 +309,30 @@ export class SmartNetwork {
|
|
|
276
309
|
host: string,
|
|
277
310
|
): Promise<{ A: string[]; AAAA: string[]; MX: { exchange: string; priority: number }[] }> {
|
|
278
311
|
try {
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
312
|
+
const dnsClient = new plugins.smartdns.dnsClientMod.Smartdns({
|
|
313
|
+
strategy: 'prefer-system', // Try system resolver first (handles localhost), fallback to DoH
|
|
314
|
+
allowDohFallback: true,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const [aRecords, aaaaRecords, mxRecords] = await Promise.all([
|
|
318
|
+
dnsClient.getRecordsA(host).catch((): any[] => []),
|
|
319
|
+
dnsClient.getRecordsAAAA(host).catch((): any[] => []),
|
|
320
|
+
dnsClient.getRecords(host, 'MX').catch((): any[] => []),
|
|
285
321
|
]);
|
|
322
|
+
|
|
323
|
+
// Extract values from the record objects
|
|
324
|
+
const A = aRecords.map((record: any) => record.value);
|
|
325
|
+
const AAAA = aaaaRecords.map((record: any) => record.value);
|
|
326
|
+
|
|
327
|
+
// Parse MX records - the value contains "priority exchange"
|
|
328
|
+
const MX = mxRecords.map((record: any) => {
|
|
329
|
+
const parts = record.value.split(' ');
|
|
330
|
+
return {
|
|
331
|
+
priority: parseInt(parts[0], 10),
|
|
332
|
+
exchange: parts[1] || '',
|
|
333
|
+
};
|
|
334
|
+
});
|
|
335
|
+
|
|
286
336
|
return { A, AAAA, MX };
|
|
287
337
|
} catch (err: any) {
|
|
288
338
|
throw new NetworkError(err.message, err.code);
|
|
@@ -6,17 +6,16 @@ import * as perfHooks from 'perf_hooks';
|
|
|
6
6
|
export { os, https, perfHooks };
|
|
7
7
|
|
|
8
8
|
// @pushrocks scope
|
|
9
|
+
import * as smartdns from '@push.rocks/smartdns';
|
|
9
10
|
import * as smartping from '@push.rocks/smartping';
|
|
10
11
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
11
12
|
import * as smartstring from '@push.rocks/smartstring';
|
|
12
13
|
|
|
13
|
-
export { smartpromise, smartping, smartstring };
|
|
14
|
+
export { smartdns, smartpromise, smartping, smartstring };
|
|
14
15
|
|
|
15
16
|
// @third party scope
|
|
16
17
|
// @ts-ignore
|
|
17
18
|
import isopen from 'isopen';
|
|
18
|
-
// @ts-ignore
|
|
19
|
-
import * as publicIp from 'public-ip';
|
|
20
19
|
import * as systeminformation from 'systeminformation';
|
|
21
20
|
|
|
22
|
-
export { isopen,
|
|
21
|
+
export { isopen, systeminformation };
|