@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.cjs
CHANGED
|
@@ -11318,12 +11318,28 @@ async function getServerBinding(uid, options = {}) {
|
|
|
11318
11318
|
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
11319
11319
|
const logger = options.logger;
|
|
11320
11320
|
if (typeof fetchImpl !== "function") {
|
|
11321
|
-
logger?.
|
|
11321
|
+
logger?.log?.(
|
|
11322
11322
|
`[server-binding] global fetch unavailable; skipping cloud lookup`
|
|
11323
11323
|
);
|
|
11324
11324
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
11325
11325
|
return void 0;
|
|
11326
11326
|
}
|
|
11327
|
+
try {
|
|
11328
|
+
const apiHostname = new URL(baseUrl).hostname;
|
|
11329
|
+
const dns2 = await import("dns/promises");
|
|
11330
|
+
const answers = await dns2.lookup(apiHostname, { family: 4, all: true });
|
|
11331
|
+
const sinkholed = answers.find(
|
|
11332
|
+
(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 ?? "")
|
|
11333
|
+
);
|
|
11334
|
+
if (sinkholed) {
|
|
11335
|
+
logger?.log?.(
|
|
11336
|
+
`[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.`
|
|
11337
|
+
);
|
|
11338
|
+
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
11339
|
+
return void 0;
|
|
11340
|
+
}
|
|
11341
|
+
} catch {
|
|
11342
|
+
}
|
|
11327
11343
|
const url = `${baseUrl}/devices/${encodeURIComponent(uid)}/server-binding?language=${encodeURIComponent(language)}`;
|
|
11328
11344
|
const controller = new AbortController();
|
|
11329
11345
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -11334,8 +11350,8 @@ async function getServerBinding(uid, options = {}) {
|
|
|
11334
11350
|
headers: { Accept: "application/json" }
|
|
11335
11351
|
});
|
|
11336
11352
|
if (!res.ok) {
|
|
11337
|
-
logger?.
|
|
11338
|
-
`[server-binding] ${uid}: HTTP ${res.status} ${res.statusText}`
|
|
11353
|
+
logger?.log?.(
|
|
11354
|
+
`[server-binding] ${uid}: HTTP ${res.status} ${res.statusText} from ${url}`
|
|
11339
11355
|
);
|
|
11340
11356
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
11341
11357
|
return void 0;
|
|
@@ -11343,8 +11359,15 @@ async function getServerBinding(uid, options = {}) {
|
|
|
11343
11359
|
const json = await res.json();
|
|
11344
11360
|
const parsed = parseServerBindingResponse(json);
|
|
11345
11361
|
if (!parsed) {
|
|
11346
|
-
logger?.
|
|
11347
|
-
`[server-binding] ${uid}: response shape did not match expectations`
|
|
11362
|
+
logger?.log?.(
|
|
11363
|
+
`[server-binding] ${uid}: response shape did not match expectations (Reolink schema change?)`
|
|
11364
|
+
);
|
|
11365
|
+
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
11366
|
+
return void 0;
|
|
11367
|
+
}
|
|
11368
|
+
if (parsed.availableZones.length === 0) {
|
|
11369
|
+
logger?.log?.(
|
|
11370
|
+
`[server-binding] ${uid}: cloud returned 0 zones \u2014 UID not registered with Reolink cloud (or wrong region)`
|
|
11348
11371
|
);
|
|
11349
11372
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
11350
11373
|
return void 0;
|
|
@@ -11363,9 +11386,23 @@ async function getServerBinding(uid, options = {}) {
|
|
|
11363
11386
|
);
|
|
11364
11387
|
return parsed;
|
|
11365
11388
|
} catch (e) {
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
)
|
|
11389
|
+
const msg = e?.message ?? String(e);
|
|
11390
|
+
const errName = e?.name;
|
|
11391
|
+
if (errName === "AbortError" || msg.includes("aborted")) {
|
|
11392
|
+
logger?.log?.(
|
|
11393
|
+
`[server-binding] ${uid}: timed out after ${timeoutMs}ms (cloud unreachable)`
|
|
11394
|
+
);
|
|
11395
|
+
} else if (msg.includes("ENOTFOUND") || msg.includes("EAI_AGAIN")) {
|
|
11396
|
+
logger?.log?.(
|
|
11397
|
+
`[server-binding] ${uid}: DNS failed (${msg}) \u2014 apis.reolink.com may be blocked at resolver`
|
|
11398
|
+
);
|
|
11399
|
+
} else if (msg.includes("ECONNREFUSED") || msg.includes("EHOSTUNREACH") || msg.includes("ENETUNREACH")) {
|
|
11400
|
+
logger?.log?.(
|
|
11401
|
+
`[server-binding] ${uid}: network unreachable (${msg}) \u2014 cloud port blocked`
|
|
11402
|
+
);
|
|
11403
|
+
} else {
|
|
11404
|
+
logger?.log?.(`[server-binding] ${uid}: fetch failed \u2014 ${msg}`);
|
|
11405
|
+
}
|
|
11369
11406
|
cache.set(uid, { kind: "err", expires: now + NEGATIVE_TTL_MS });
|
|
11370
11407
|
return void 0;
|
|
11371
11408
|
} finally {
|
|
@@ -11801,12 +11838,19 @@ var BcUdpStream = class extends import_node_events3.EventEmitter {
|
|
|
11801
11838
|
const tid = (Math.floor(Math.random() * 2147483647) | 0) >>> 0;
|
|
11802
11839
|
const xml = buildC2mQ({ uid });
|
|
11803
11840
|
const pkt = encodeDiscoveryPacket(tid, xml);
|
|
11841
|
+
const counters = { sentBytes: 0, rxBytes: 0 };
|
|
11804
11842
|
return await new Promise((resolve, reject) => {
|
|
11805
11843
|
const deadline = setTimeout(() => {
|
|
11806
11844
|
cleanup();
|
|
11807
|
-
|
|
11845
|
+
const err = new Error(
|
|
11846
|
+
`P2P UID lookup timeout (${dest.host}:${dest.port}) \u2014 sent=${counters.sentBytes}B rx=${counters.rxBytes}B`
|
|
11847
|
+
);
|
|
11848
|
+
err.sentBytes = counters.sentBytes;
|
|
11849
|
+
err.rxBytes = counters.rxBytes;
|
|
11850
|
+
reject(err);
|
|
11808
11851
|
}, timeoutMs);
|
|
11809
11852
|
const onMsg = (msg) => {
|
|
11853
|
+
counters.rxBytes += msg.length;
|
|
11810
11854
|
try {
|
|
11811
11855
|
const p = decodeBcUdpPacket(msg);
|
|
11812
11856
|
if (p.kind !== "discovery") return;
|
|
@@ -11814,13 +11858,19 @@ var BcUdpStream = class extends import_node_events3.EventEmitter {
|
|
|
11814
11858
|
const qr = parseM2cQr(p.xml);
|
|
11815
11859
|
if (!qr?.reg || !qr?.relay) return;
|
|
11816
11860
|
cleanup();
|
|
11817
|
-
resolve({
|
|
11861
|
+
resolve({
|
|
11862
|
+
reg: qr.reg,
|
|
11863
|
+
relay: qr.relay,
|
|
11864
|
+
sentBytes: counters.sentBytes,
|
|
11865
|
+
rxBytes: counters.rxBytes
|
|
11866
|
+
});
|
|
11818
11867
|
} catch {
|
|
11819
11868
|
}
|
|
11820
11869
|
};
|
|
11821
11870
|
const send = () => {
|
|
11822
11871
|
try {
|
|
11823
11872
|
sock.send(pkt, dest.port, dest.host);
|
|
11873
|
+
counters.sentBytes += pkt.length;
|
|
11824
11874
|
} catch {
|
|
11825
11875
|
}
|
|
11826
11876
|
};
|