@apocaliss92/nodelink-js 0.6.0 → 0.6.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/dist/{chunk-7HSTETZR.js → chunk-EAHRVNEX.js} +61 -11
- package/dist/chunk-EAHRVNEX.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +60 -10
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +1 -1
- package/dist/index.cjs +60 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-7HSTETZR.js.map +0 -1
package/dist/cli/rtsp-server.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -9047,12 +9047,28 @@ async function getServerBinding(uid, options = {}) {
|
|
|
9047
9047
|
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
9048
9048
|
const logger = options.logger;
|
|
9049
9049
|
if (typeof fetchImpl !== "function") {
|
|
9050
|
-
logger?.
|
|
9050
|
+
logger?.log?.(
|
|
9051
9051
|
`[server-binding] global fetch unavailable; skipping cloud lookup`
|
|
9052
9052
|
);
|
|
9053
9053
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
9054
9054
|
return void 0;
|
|
9055
9055
|
}
|
|
9056
|
+
try {
|
|
9057
|
+
const apiHostname = new URL(baseUrl).hostname;
|
|
9058
|
+
const dns2 = await import("dns/promises");
|
|
9059
|
+
const answers = await dns2.lookup(apiHostname, { family: 4, all: true });
|
|
9060
|
+
const sinkholed = answers.find(
|
|
9061
|
+
(a) => a.address?.startsWith("127.") || a.address === "0.0.0.0" || a.address?.startsWith("10.") || a.address?.startsWith("192.168.") || /^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(a.address ?? "")
|
|
9062
|
+
);
|
|
9063
|
+
if (sinkholed) {
|
|
9064
|
+
logger?.log?.(
|
|
9065
|
+
`[server-binding] ${uid}: DNS for ${apiHostname} resolves to ${sinkholed.address} (sinkhole / /etc/hosts override). Cloud directory unreachable \u2014 falling back to the 22-hostname P2P sweep. Whitelist ${apiHostname} to enable.`
|
|
9066
|
+
);
|
|
9067
|
+
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
9068
|
+
return void 0;
|
|
9069
|
+
}
|
|
9070
|
+
} catch {
|
|
9071
|
+
}
|
|
9056
9072
|
const url = `${baseUrl}/devices/${encodeURIComponent(uid)}/server-binding?language=${encodeURIComponent(language)}`;
|
|
9057
9073
|
const controller = new AbortController();
|
|
9058
9074
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -9063,8 +9079,8 @@ async function getServerBinding(uid, options = {}) {
|
|
|
9063
9079
|
headers: { Accept: "application/json" }
|
|
9064
9080
|
});
|
|
9065
9081
|
if (!res.ok) {
|
|
9066
|
-
logger?.
|
|
9067
|
-
`[server-binding] ${uid}: HTTP ${res.status} ${res.statusText}`
|
|
9082
|
+
logger?.log?.(
|
|
9083
|
+
`[server-binding] ${uid}: HTTP ${res.status} ${res.statusText} from ${url}`
|
|
9068
9084
|
);
|
|
9069
9085
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
9070
9086
|
return void 0;
|
|
@@ -9072,8 +9088,15 @@ async function getServerBinding(uid, options = {}) {
|
|
|
9072
9088
|
const json = await res.json();
|
|
9073
9089
|
const parsed = parseServerBindingResponse(json);
|
|
9074
9090
|
if (!parsed) {
|
|
9075
|
-
logger?.
|
|
9076
|
-
`[server-binding] ${uid}: response shape did not match expectations`
|
|
9091
|
+
logger?.log?.(
|
|
9092
|
+
`[server-binding] ${uid}: response shape did not match expectations (Reolink schema change?)`
|
|
9093
|
+
);
|
|
9094
|
+
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
9095
|
+
return void 0;
|
|
9096
|
+
}
|
|
9097
|
+
if (parsed.availableZones.length === 0) {
|
|
9098
|
+
logger?.log?.(
|
|
9099
|
+
`[server-binding] ${uid}: cloud returned 0 zones \u2014 UID not registered with Reolink cloud (or wrong region)`
|
|
9077
9100
|
);
|
|
9078
9101
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
9079
9102
|
return void 0;
|
|
@@ -9092,9 +9115,23 @@ async function getServerBinding(uid, options = {}) {
|
|
|
9092
9115
|
);
|
|
9093
9116
|
return parsed;
|
|
9094
9117
|
} catch (e) {
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
)
|
|
9118
|
+
const msg = e?.message ?? String(e);
|
|
9119
|
+
const errName = e?.name;
|
|
9120
|
+
if (errName === "AbortError" || msg.includes("aborted")) {
|
|
9121
|
+
logger?.log?.(
|
|
9122
|
+
`[server-binding] ${uid}: timed out after ${timeoutMs}ms (cloud unreachable)`
|
|
9123
|
+
);
|
|
9124
|
+
} else if (msg.includes("ENOTFOUND") || msg.includes("EAI_AGAIN")) {
|
|
9125
|
+
logger?.log?.(
|
|
9126
|
+
`[server-binding] ${uid}: DNS failed (${msg}) \u2014 apis.reolink.com may be blocked at resolver`
|
|
9127
|
+
);
|
|
9128
|
+
} else if (msg.includes("ECONNREFUSED") || msg.includes("EHOSTUNREACH") || msg.includes("ENETUNREACH")) {
|
|
9129
|
+
logger?.log?.(
|
|
9130
|
+
`[server-binding] ${uid}: network unreachable (${msg}) \u2014 cloud port blocked`
|
|
9131
|
+
);
|
|
9132
|
+
} else {
|
|
9133
|
+
logger?.log?.(`[server-binding] ${uid}: fetch failed \u2014 ${msg}`);
|
|
9134
|
+
}
|
|
9098
9135
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
9099
9136
|
return void 0;
|
|
9100
9137
|
} finally {
|
|
@@ -9530,12 +9567,19 @@ var BcUdpStream = class extends import_node_events.EventEmitter {
|
|
|
9530
9567
|
const tid = (Math.floor(Math.random() * 2147483647) | 0) >>> 0;
|
|
9531
9568
|
const xml = buildC2mQ({ uid });
|
|
9532
9569
|
const pkt = encodeDiscoveryPacket(tid, xml);
|
|
9570
|
+
const counters = { sentBytes: 0, rxBytes: 0 };
|
|
9533
9571
|
return await new Promise((resolve, reject) => {
|
|
9534
9572
|
const deadline = setTimeout(() => {
|
|
9535
9573
|
cleanup();
|
|
9536
|
-
|
|
9574
|
+
const err = new Error(
|
|
9575
|
+
`P2P UID lookup timeout (${dest.host}:${dest.port}) \u2014 sent=${counters.sentBytes}B rx=${counters.rxBytes}B`
|
|
9576
|
+
);
|
|
9577
|
+
err.sentBytes = counters.sentBytes;
|
|
9578
|
+
err.rxBytes = counters.rxBytes;
|
|
9579
|
+
reject(err);
|
|
9537
9580
|
}, timeoutMs);
|
|
9538
9581
|
const onMsg = (msg) => {
|
|
9582
|
+
counters.rxBytes += msg.length;
|
|
9539
9583
|
try {
|
|
9540
9584
|
const p = decodeBcUdpPacket(msg);
|
|
9541
9585
|
if (p.kind !== "discovery") return;
|
|
@@ -9543,13 +9587,19 @@ var BcUdpStream = class extends import_node_events.EventEmitter {
|
|
|
9543
9587
|
const qr = parseM2cQr(p.xml);
|
|
9544
9588
|
if (!qr?.reg || !qr?.relay) return;
|
|
9545
9589
|
cleanup();
|
|
9546
|
-
resolve({
|
|
9590
|
+
resolve({
|
|
9591
|
+
reg: qr.reg,
|
|
9592
|
+
relay: qr.relay,
|
|
9593
|
+
sentBytes: counters.sentBytes,
|
|
9594
|
+
rxBytes: counters.rxBytes
|
|
9595
|
+
});
|
|
9547
9596
|
} catch {
|
|
9548
9597
|
}
|
|
9549
9598
|
};
|
|
9550
9599
|
const send = () => {
|
|
9551
9600
|
try {
|
|
9552
9601
|
sock.send(pkt, dest.port, dest.host);
|
|
9602
|
+
counters.sentBytes += pkt.length;
|
|
9553
9603
|
} catch {
|
|
9554
9604
|
}
|
|
9555
9605
|
};
|