@apocaliss92/nodelink-js 0.5.1-beta.1 → 0.5.1-beta.11
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/{DiagnosticsTools-ILDDJZL7.js → DiagnosticsTools-7BIWJDZS.js} +2 -2
- package/dist/{chunk-6ILAHQF5.js → chunk-COUH6ZJT.js} +163 -18
- package/dist/chunk-COUH6ZJT.js.map +1 -0
- package/dist/{chunk-AHY4L7JI.js → chunk-VOPEOB4H.js} +71 -2
- package/dist/chunk-VOPEOB4H.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +229 -17
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +2 -2
- package/dist/index.cjs +369 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +35 -0
- package/dist/index.js +135 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6ILAHQF5.js.map +0 -1
- package/dist/chunk-AHY4L7JI.js.map +0 -1
- /package/dist/{DiagnosticsTools-ILDDJZL7.js.map → DiagnosticsTools-7BIWJDZS.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
sampleStreams,
|
|
13
13
|
sanitizeFixtureData,
|
|
14
14
|
testChannelStreams
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VOPEOB4H.js";
|
|
16
16
|
import "./chunk-GVWJGQPT.js";
|
|
17
17
|
export {
|
|
18
18
|
captureModelFixtures,
|
|
@@ -29,4 +29,4 @@ export {
|
|
|
29
29
|
sanitizeFixtureData,
|
|
30
30
|
testChannelStreams
|
|
31
31
|
};
|
|
32
|
-
//# sourceMappingURL=DiagnosticsTools-
|
|
32
|
+
//# sourceMappingURL=DiagnosticsTools-7BIWJDZS.js.map
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
runAllDiagnosticsConsecutively,
|
|
31
31
|
runMultifocalDiagnosticsConsecutively,
|
|
32
32
|
xmlEscape
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-VOPEOB4H.js";
|
|
34
34
|
import {
|
|
35
35
|
BC_CLASS_FILE_DOWNLOAD,
|
|
36
36
|
BC_CLASS_LEGACY,
|
|
@@ -656,6 +656,10 @@ function sleep(ms) {
|
|
|
656
656
|
return new Promise((r) => setTimeout(r, ms));
|
|
657
657
|
}
|
|
658
658
|
var P2P_RELAY_HOSTNAMES = [
|
|
659
|
+
// Master anycast routers — try first.
|
|
660
|
+
"p2pm-abr.reolink.com",
|
|
661
|
+
"p2pm-ali.reolink.com",
|
|
662
|
+
// Numbered regional relays.
|
|
659
663
|
"p2p.reolink.com",
|
|
660
664
|
"p2p1.reolink.com",
|
|
661
665
|
"p2p2.reolink.com",
|
|
@@ -667,8 +671,29 @@ var P2P_RELAY_HOSTNAMES = [
|
|
|
667
671
|
"p2p8.reolink.com",
|
|
668
672
|
"p2p9.reolink.com",
|
|
669
673
|
"p2p10.reolink.com",
|
|
670
|
-
"p2p11.reolink.com"
|
|
674
|
+
"p2p11.reolink.com",
|
|
675
|
+
// China-region fallbacks (intentionally last).
|
|
676
|
+
"p2p.reolink.com.cn",
|
|
677
|
+
"p2p1.reolink.com.cn",
|
|
678
|
+
"p2p2.reolink.com.cn",
|
|
679
|
+
"p2p3.reolink.com.cn",
|
|
680
|
+
"p2p4.reolink.com.cn",
|
|
681
|
+
"p2p5.reolink.com.cn",
|
|
682
|
+
"p2p6.reolink.com.cn",
|
|
683
|
+
"p2p7.reolink.com.cn",
|
|
684
|
+
"p2p8.reolink.com.cn",
|
|
685
|
+
"p2p9.reolink.com.cn"
|
|
671
686
|
];
|
|
687
|
+
function isUnroutableForP2P(ip) {
|
|
688
|
+
if (!ip) return true;
|
|
689
|
+
if (ip === "0.0.0.0") return true;
|
|
690
|
+
if (ip.startsWith("127.")) return true;
|
|
691
|
+
if (ip.startsWith("10.")) return true;
|
|
692
|
+
if (ip.startsWith("192.168.")) return true;
|
|
693
|
+
if (/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(ip)) return true;
|
|
694
|
+
if (/^100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\./.test(ip)) return true;
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
672
697
|
var P2P_LOOKUP_PORT = 9999;
|
|
673
698
|
var P2P_MAX_WAIT_MS = 15e3;
|
|
674
699
|
var P2P_RESEND_WAIT_MS = 500;
|
|
@@ -835,19 +860,30 @@ var BcUdpStream = class extends EventEmitter {
|
|
|
835
860
|
}
|
|
836
861
|
async p2pUidLookup(sock, uid) {
|
|
837
862
|
const resolved = [];
|
|
863
|
+
const sinkholed = [];
|
|
838
864
|
for (const host of P2P_RELAY_HOSTNAMES) {
|
|
839
865
|
try {
|
|
840
866
|
const answers = await dns.lookup(host, { family: 4, all: true });
|
|
841
867
|
for (const a of answers) {
|
|
842
|
-
if (
|
|
843
|
-
|
|
868
|
+
if (!a.address) continue;
|
|
869
|
+
if (isUnroutableForP2P(a.address)) {
|
|
870
|
+
sinkholed.push({ host, ip: a.address });
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
if (!resolved.includes(a.address)) resolved.push(a.address);
|
|
844
874
|
}
|
|
845
875
|
} catch {
|
|
846
876
|
}
|
|
847
877
|
}
|
|
848
878
|
if (resolved.length === 0) {
|
|
879
|
+
if (sinkholed.length > 0) {
|
|
880
|
+
const samples = sinkholed.slice(0, 3).map((s) => `${s.host} \u2192 ${s.ip}`).join(", ");
|
|
881
|
+
throw new Error(
|
|
882
|
+
`P2P UID lookup failed: DNS resolves Reolink P2P hostnames to non-routable IPs (${samples}). This is almost certainly an /etc/hosts rewrite or a DNS filter (Pi-hole, AdGuard, NextDNS) blocking *.reolink.com. Battery cameras cannot connect without P2P \u2014 whitelist *.reolink.com (at least p2p*.reolink.com on UDP/9999) or remove the override. Verify with \`getent hosts p2p.reolink.com\` inside your container \u2014 if it differs from \`nslookup p2p.reolink.com\`, the offender is /etc/hosts.`
|
|
883
|
+
);
|
|
884
|
+
}
|
|
849
885
|
throw new Error(
|
|
850
|
-
"P2P UID lookup failed: no p2p.reolink.com addresses resolved"
|
|
886
|
+
"P2P UID lookup failed: no p2p.reolink.com addresses resolved (DNS failure)"
|
|
851
887
|
);
|
|
852
888
|
}
|
|
853
889
|
const start = Date.now();
|
|
@@ -19771,6 +19807,37 @@ ${xml}`
|
|
|
19771
19807
|
}
|
|
19772
19808
|
);
|
|
19773
19809
|
}
|
|
19810
|
+
if (!isMultiFocal) {
|
|
19811
|
+
try {
|
|
19812
|
+
const caps = await this.getDeviceCapabilities(channel);
|
|
19813
|
+
const channelNumRaw = caps.support?.channelNum;
|
|
19814
|
+
const channelNum = typeof channelNumRaw === "string" ? Number.parseInt(channelNumRaw, 10) : channelNumRaw;
|
|
19815
|
+
if (Number.isFinite(channelNum) && channelNum >= 2) {
|
|
19816
|
+
isMultiFocal = true;
|
|
19817
|
+
}
|
|
19818
|
+
if (!isMultiFocal) {
|
|
19819
|
+
const items = caps.support?.items;
|
|
19820
|
+
if (Array.isArray(items)) {
|
|
19821
|
+
for (const it of items) {
|
|
19822
|
+
const raw = it.binoCfg;
|
|
19823
|
+
const v = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : 0;
|
|
19824
|
+
if (Number.isFinite(v) && v > 0) {
|
|
19825
|
+
isMultiFocal = true;
|
|
19826
|
+
break;
|
|
19827
|
+
}
|
|
19828
|
+
}
|
|
19829
|
+
}
|
|
19830
|
+
}
|
|
19831
|
+
} catch (e) {
|
|
19832
|
+
logDebug(
|
|
19833
|
+
"[ReolinkBaichuanApi] buildVideoStreamOptions: SupportInfo dual-lens probe failed",
|
|
19834
|
+
{
|
|
19835
|
+
host: this.host,
|
|
19836
|
+
err: e instanceof Error ? e.message : String(e)
|
|
19837
|
+
}
|
|
19838
|
+
);
|
|
19839
|
+
}
|
|
19840
|
+
}
|
|
19774
19841
|
logDebug("[ReolinkBaichuanApi] buildVideoStreamOptions: inputs", {
|
|
19775
19842
|
host: this.host,
|
|
19776
19843
|
onNvr,
|
|
@@ -20165,7 +20232,7 @@ ${xml}`
|
|
|
20165
20232
|
* @returns Test results for all stream types and profiles
|
|
20166
20233
|
*/
|
|
20167
20234
|
async testChannelStreams(channel, logger) {
|
|
20168
|
-
const { testChannelStreams } = await import("./DiagnosticsTools-
|
|
20235
|
+
const { testChannelStreams } = await import("./DiagnosticsTools-7BIWJDZS.js");
|
|
20169
20236
|
return await testChannelStreams({
|
|
20170
20237
|
api: this,
|
|
20171
20238
|
channel: this.normalizeChannel(channel),
|
|
@@ -20181,7 +20248,7 @@ ${xml}`
|
|
|
20181
20248
|
* @returns Complete diagnostics for all channels and streams
|
|
20182
20249
|
*/
|
|
20183
20250
|
async collectMultifocalDiagnostics(logger) {
|
|
20184
|
-
const { collectMultifocalDiagnostics } = await import("./DiagnosticsTools-
|
|
20251
|
+
const { collectMultifocalDiagnostics } = await import("./DiagnosticsTools-7BIWJDZS.js");
|
|
20185
20252
|
return await collectMultifocalDiagnostics({
|
|
20186
20253
|
api: this,
|
|
20187
20254
|
logger
|
|
@@ -24231,19 +24298,95 @@ function isTcpFailureThatShouldFallbackToUdp(e) {
|
|
|
24231
24298
|
return message.includes("ECONNREFUSED") || message.includes("ETIMEDOUT") || message.includes("EHOSTUNREACH") || message.includes("ENETUNREACH") || message.includes("socket hang up") || message.includes("TCP connection timeout") || message.includes("Baichuan socket closed") || message.includes("timeout waiting for nonce") || message.includes("expected encryption info") || message.includes("ECONNRESET") || message.includes("EPIPE");
|
|
24232
24299
|
}
|
|
24233
24300
|
async function pingHost(host, timeoutMs = 3e3) {
|
|
24234
|
-
|
|
24301
|
+
if (!host || typeof host !== "string") return false;
|
|
24235
24302
|
const platform2 = process.platform;
|
|
24236
|
-
const
|
|
24237
|
-
|
|
24238
|
-
|
|
24239
|
-
|
|
24240
|
-
|
|
24241
|
-
|
|
24242
|
-
|
|
24303
|
+
const pingCandidates = platform2 === "win32" ? ["ping"] : platform2 === "darwin" ? ["/sbin/ping", "/usr/sbin/ping", "ping"] : ["/bin/ping", "/usr/bin/ping", "ping"];
|
|
24304
|
+
const pingArgs = (bin) => {
|
|
24305
|
+
void bin;
|
|
24306
|
+
if (platform2 === "win32") {
|
|
24307
|
+
return ["-n", "1", "-w", String(timeoutMs), host];
|
|
24308
|
+
}
|
|
24309
|
+
if (platform2 === "darwin") {
|
|
24310
|
+
return ["-c", "1", "-W", String(timeoutMs), host];
|
|
24311
|
+
}
|
|
24312
|
+
return ["-c", "1", "-W", String(Math.max(1, Math.floor(timeoutMs / 1e3))), host];
|
|
24313
|
+
};
|
|
24314
|
+
const { spawn: spawn3 } = await import("child_process");
|
|
24315
|
+
for (const bin of pingCandidates) {
|
|
24316
|
+
const ranOk = await new Promise((resolve) => {
|
|
24317
|
+
let settled = false;
|
|
24318
|
+
let child;
|
|
24319
|
+
try {
|
|
24320
|
+
child = spawn3(bin, pingArgs(bin), { stdio: "ignore" });
|
|
24321
|
+
} catch {
|
|
24322
|
+
resolve("spawn-failed");
|
|
24323
|
+
return;
|
|
24324
|
+
}
|
|
24325
|
+
const timer = setTimeout(() => {
|
|
24326
|
+
if (settled) return;
|
|
24327
|
+
settled = true;
|
|
24328
|
+
try {
|
|
24329
|
+
child?.kill("SIGKILL");
|
|
24330
|
+
} catch {
|
|
24331
|
+
}
|
|
24332
|
+
resolve(false);
|
|
24333
|
+
}, timeoutMs + 500);
|
|
24334
|
+
child.on("error", () => {
|
|
24335
|
+
if (settled) return;
|
|
24336
|
+
settled = true;
|
|
24337
|
+
clearTimeout(timer);
|
|
24338
|
+
resolve("spawn-failed");
|
|
24339
|
+
});
|
|
24340
|
+
child.on("exit", (code) => {
|
|
24341
|
+
if (settled) return;
|
|
24342
|
+
settled = true;
|
|
24343
|
+
clearTimeout(timer);
|
|
24344
|
+
resolve(code === 0);
|
|
24345
|
+
});
|
|
24346
|
+
});
|
|
24347
|
+
if (ranOk === true) return true;
|
|
24348
|
+
if (ranOk === "spawn-failed") continue;
|
|
24349
|
+
break;
|
|
24350
|
+
}
|
|
24351
|
+
for (const port of [9e3, 443, 80]) {
|
|
24352
|
+
if (await tcpReachabilityProbe(host, port, 800)) return true;
|
|
24353
|
+
}
|
|
24354
|
+
return false;
|
|
24355
|
+
}
|
|
24356
|
+
async function tcpReachabilityProbe(host, port, timeoutMs) {
|
|
24357
|
+
const net4 = await import("net");
|
|
24243
24358
|
return new Promise((resolve) => {
|
|
24244
|
-
|
|
24245
|
-
|
|
24359
|
+
let settled = false;
|
|
24360
|
+
const socket = new net4.Socket();
|
|
24361
|
+
const timer = setTimeout(() => {
|
|
24362
|
+
if (settled) return;
|
|
24363
|
+
settled = true;
|
|
24364
|
+
try {
|
|
24365
|
+
socket.destroy();
|
|
24366
|
+
} catch {
|
|
24367
|
+
}
|
|
24368
|
+
resolve(false);
|
|
24369
|
+
}, timeoutMs);
|
|
24370
|
+
const finish = (reachable) => {
|
|
24371
|
+
if (settled) return;
|
|
24372
|
+
settled = true;
|
|
24373
|
+
clearTimeout(timer);
|
|
24374
|
+
try {
|
|
24375
|
+
socket.destroy();
|
|
24376
|
+
} catch {
|
|
24377
|
+
}
|
|
24378
|
+
resolve(reachable);
|
|
24379
|
+
};
|
|
24380
|
+
socket.once("connect", () => finish(true));
|
|
24381
|
+
socket.once("error", (err) => {
|
|
24382
|
+
if (err?.code === "ECONNREFUSED") finish(true);
|
|
24383
|
+
else finish(false);
|
|
24246
24384
|
});
|
|
24385
|
+
try {
|
|
24386
|
+
socket.connect(port, host);
|
|
24387
|
+
} catch {
|
|
24388
|
+
finish(false);
|
|
24389
|
+
}
|
|
24247
24390
|
});
|
|
24248
24391
|
}
|
|
24249
24392
|
function createBaichuanApi(inputs, transport) {
|
|
@@ -24759,6 +24902,7 @@ export {
|
|
|
24759
24902
|
encodeHeader,
|
|
24760
24903
|
decodeHeader,
|
|
24761
24904
|
BaichuanFrameParser,
|
|
24905
|
+
isUnroutableForP2P,
|
|
24762
24906
|
BcUdpStream,
|
|
24763
24907
|
asLogger,
|
|
24764
24908
|
createNullLogger,
|
|
@@ -24823,6 +24967,7 @@ export {
|
|
|
24823
24967
|
normalizeUid,
|
|
24824
24968
|
maskUid,
|
|
24825
24969
|
isTcpFailureThatShouldFallbackToUdp,
|
|
24970
|
+
tcpReachabilityProbe,
|
|
24826
24971
|
autoDetectDeviceType
|
|
24827
24972
|
};
|
|
24828
|
-
//# sourceMappingURL=chunk-
|
|
24973
|
+
//# sourceMappingURL=chunk-COUH6ZJT.js.map
|