@mega-yfue/eufy-sdk 0.3.0-beta.2 → 0.3.0-beta.3
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/index.js +105 -16
- package/dist/index.js.map +2 -2
- package/dist/transport/p2p/p2p-session.d.ts +25 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15141,6 +15141,8 @@ var LIVE_START_ACK_DEADLINE_MS = 3e3;
|
|
|
15141
15141
|
var SEQUENCE_LOOKBACK = 32768;
|
|
15142
15142
|
var STALE_RETRANSMIT_DEPTH = 1024;
|
|
15143
15143
|
var PUNCH_PROBE_SOCKETS = 7;
|
|
15144
|
+
var REORDER_WAIT_MS = 250;
|
|
15145
|
+
var REORDER_MAX_DATAGRAMS = 128;
|
|
15144
15146
|
var MAX_TRACED_DATAGRAM_GAPS = 8;
|
|
15145
15147
|
var CMD_SET_PAYLOAD = 1350;
|
|
15146
15148
|
var CMD_NOTIFY_PAYLOAD = 1351;
|
|
@@ -15210,9 +15212,10 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
15210
15212
|
selfHost;
|
|
15211
15213
|
/** In-flight multi-datagram frame per data channel (see onData). */
|
|
15212
15214
|
pendingByDataType = /* @__PURE__ */ new Map();
|
|
15213
|
-
/** Last datagram sequence number
|
|
15214
|
-
* mid-frame and drop the (now unrecoverable) partial frame instead of splicing wrong bytes. */
|
|
15215
|
+
/** Last delivered datagram sequence number per data type. */
|
|
15215
15216
|
lastSeqByType = /* @__PURE__ */ new Map();
|
|
15217
|
+
/** Held datagrams and their active gap timer, grouped by data type. */
|
|
15218
|
+
reorderByType = /* @__PURE__ */ new Map();
|
|
15216
15219
|
tracedDatagramGaps = 0;
|
|
15217
15220
|
level1Key;
|
|
15218
15221
|
/** Negotiated 32-byte level-2/gateway key (AES-256-GCM). Set via setLevel2Key once known. */
|
|
@@ -16467,8 +16470,7 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16467
16470
|
* Acknowledge and reassemble one DATA datagram, sequenced independently per data type.
|
|
16468
16471
|
*
|
|
16469
16472
|
* The device numbers each data type's datagrams in its own 16-bit space and repeats what it thinks was
|
|
16470
|
-
* lost
|
|
16471
|
-
* retransmission of something already reassembled: it is acknowledged, then ignored. Distance is measured
|
|
16473
|
+
* lost. A repeat of something already delivered is acknowledged, then ignored. Distance is measured
|
|
16472
16474
|
* modulo the sequence space and read as backwards beyond {@link SEQUENCE_LOOKBACK}, which is what lets the
|
|
16473
16475
|
* numbering wrap without the next datagram looking like a jump of nearly a full space.
|
|
16474
16476
|
*
|
|
@@ -16478,9 +16480,13 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16478
16480
|
* numbering and the half-assembled frame goes — because ignoring it would freeze the mark, and every
|
|
16479
16481
|
* datagram of the new numbering would then be read as behind it too, for as long as it took to climb back.
|
|
16480
16482
|
*
|
|
16481
|
-
*
|
|
16482
|
-
*
|
|
16483
|
-
*
|
|
16483
|
+
* A forward gap means a datagram has not arrived YET, which is not the same as lost. The device repeats
|
|
16484
|
+
* unacknowledged datagrams, so successors are held for a bounded wait and delivered strictly in sequence
|
|
16485
|
+
* if the missing one arrives. A logical frame's payload spans datagrams that carry no header of their
|
|
16486
|
+
* own, so reassembling around a hole is impossible; waiting for it is what keeps the frame whole.
|
|
16487
|
+
*
|
|
16488
|
+
* Only once {@link REORDER_WAIT_MS} passes, or {@link REORDER_MAX_DATAGRAMS} pile up, is the datagram
|
|
16489
|
+
* treated as lost: a pending frame is discarded and delivery resumes from the earliest held datagram.
|
|
16484
16490
|
*/
|
|
16485
16491
|
onData(msg, addr) {
|
|
16486
16492
|
const dataTypeBuffer = msg.subarray(4, 6);
|
|
@@ -16491,18 +16497,98 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16491
16497
|
const advance = prevSeq === void 0 ? 1 : seqNo - prevSeq & 65535;
|
|
16492
16498
|
if (advance === 0)
|
|
16493
16499
|
return;
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
}
|
|
16500
|
+
if (advance > SEQUENCE_LOOKBACK) {
|
|
16501
|
+
if (65536 - advance <= STALE_RETRANSMIT_DEPTH)
|
|
16502
|
+
return;
|
|
16503
|
+
if (this.pendingByDataType.has(dataType) && this.tracedDatagramGaps++ < MAX_TRACED_DATAGRAM_GAPS)
|
|
16504
|
+
this.trace({ phase: "sequence-restart", dataType });
|
|
16505
|
+
this.clearReorderTimer(dataType);
|
|
16506
|
+
this.reorderByType.delete(dataType);
|
|
16502
16507
|
this.pendingByDataType.delete(dataType);
|
|
16508
|
+
this.lastSeqByType.set(dataType, seqNo);
|
|
16509
|
+
this.reassemble(dataType, msg.subarray(8));
|
|
16510
|
+
return;
|
|
16511
|
+
}
|
|
16512
|
+
if (advance === 1) {
|
|
16513
|
+
this.lastSeqByType.set(dataType, seqNo);
|
|
16514
|
+
this.reassemble(dataType, msg.subarray(8));
|
|
16515
|
+
this.drainReorder(dataType);
|
|
16516
|
+
return;
|
|
16503
16517
|
}
|
|
16518
|
+
this.holdForRetransmit(dataType, seqNo, msg.subarray(8));
|
|
16519
|
+
}
|
|
16520
|
+
/** Hold a datagram that arrived past a hole, and arm the wait for the missing one to be repeated. */
|
|
16521
|
+
holdForRetransmit(dataType, seqNo, body) {
|
|
16522
|
+
let reorder = this.reorderByType.get(dataType);
|
|
16523
|
+
if (!reorder) {
|
|
16524
|
+
reorder = { held: /* @__PURE__ */ new Map() };
|
|
16525
|
+
this.reorderByType.set(dataType, reorder);
|
|
16526
|
+
}
|
|
16527
|
+
if (!reorder.held.has(seqNo))
|
|
16528
|
+
reorder.held.set(seqNo, body);
|
|
16529
|
+
if (reorder.held.size > REORDER_MAX_DATAGRAMS) {
|
|
16530
|
+
this.abandonHole(dataType);
|
|
16531
|
+
return;
|
|
16532
|
+
}
|
|
16533
|
+
this.armReorderTimer(dataType);
|
|
16534
|
+
}
|
|
16535
|
+
/** Start a full wait for the current hole, leaving an existing wait undisturbed. */
|
|
16536
|
+
armReorderTimer(dataType) {
|
|
16537
|
+
const reorder = this.reorderByType.get(dataType);
|
|
16538
|
+
if (!reorder?.held.size || reorder.timer)
|
|
16539
|
+
return;
|
|
16540
|
+
const timer = setTimeout(() => {
|
|
16541
|
+
reorder.timer = void 0;
|
|
16542
|
+
this.abandonHole(dataType);
|
|
16543
|
+
}, REORDER_WAIT_MS);
|
|
16544
|
+
timer.unref?.();
|
|
16545
|
+
reorder.timer = timer;
|
|
16546
|
+
}
|
|
16547
|
+
/** Deliver held datagrams that now follow directly on from the last one delivered. */
|
|
16548
|
+
drainReorder(dataType) {
|
|
16549
|
+
const reorder = this.reorderByType.get(dataType);
|
|
16550
|
+
if (!reorder?.held.size)
|
|
16551
|
+
return;
|
|
16552
|
+
this.clearReorderTimer(dataType);
|
|
16553
|
+
for (; ; ) {
|
|
16554
|
+
const next = this.lastSeqByType.get(dataType) + 1 & 65535;
|
|
16555
|
+
const body = reorder.held.get(next);
|
|
16556
|
+
if (body === void 0)
|
|
16557
|
+
break;
|
|
16558
|
+
reorder.held.delete(next);
|
|
16559
|
+
this.lastSeqByType.set(dataType, next);
|
|
16560
|
+
this.reassemble(dataType, body);
|
|
16561
|
+
}
|
|
16562
|
+
if (reorder.held.size)
|
|
16563
|
+
this.armReorderTimer(dataType);
|
|
16564
|
+
else
|
|
16565
|
+
this.reorderByType.delete(dataType);
|
|
16566
|
+
}
|
|
16567
|
+
/**
|
|
16568
|
+
* The missing datagram was not repeated in time: report the gap, drop the frame it belonged to, and
|
|
16569
|
+
* resume from the earliest datagram still held so the stream keeps moving.
|
|
16570
|
+
*/
|
|
16571
|
+
abandonHole(dataType) {
|
|
16572
|
+
const held = this.reorderByType.get(dataType).held;
|
|
16573
|
+
if (this.pendingByDataType.has(dataType) && this.tracedDatagramGaps++ < MAX_TRACED_DATAGRAM_GAPS)
|
|
16574
|
+
this.trace({ phase: "datagram-gap", dataType });
|
|
16575
|
+
this.pendingByDataType.delete(dataType);
|
|
16576
|
+
const last = this.lastSeqByType.get(dataType);
|
|
16577
|
+
const earliest = [...held.keys()].sort((a, b) => (a - last & 65535) - (b - last & 65535))[0];
|
|
16578
|
+
this.lastSeqByType.set(dataType, earliest - 1 & 65535);
|
|
16579
|
+
this.drainReorder(dataType);
|
|
16580
|
+
}
|
|
16581
|
+
clearReorderTimer(dataType) {
|
|
16582
|
+
const reorder = this.reorderByType.get(dataType);
|
|
16583
|
+
if (!reorder?.timer)
|
|
16584
|
+
return;
|
|
16585
|
+
clearTimeout(reorder.timer);
|
|
16586
|
+
reorder.timer = void 0;
|
|
16587
|
+
}
|
|
16588
|
+
/** Reassemble one in-sequence datagram body into logical frames. */
|
|
16589
|
+
reassemble(dataType, datagramBody) {
|
|
16504
16590
|
const pending = this.pendingByDataType.get(dataType);
|
|
16505
|
-
let body = pending ? Buffer.concat([pending.buf,
|
|
16591
|
+
let body = pending ? Buffer.concat([pending.buf, datagramBody]) : datagramBody;
|
|
16506
16592
|
const carryHeader = pending?.header;
|
|
16507
16593
|
this.pendingByDataType.delete(dataType);
|
|
16508
16594
|
if (carryHeader) {
|
|
@@ -16533,6 +16619,9 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16533
16619
|
* completed either.
|
|
16534
16620
|
*/
|
|
16535
16621
|
resetInboundSequencing() {
|
|
16622
|
+
for (const dataType of this.reorderByType.keys())
|
|
16623
|
+
this.clearReorderTimer(dataType);
|
|
16624
|
+
this.reorderByType.clear();
|
|
16536
16625
|
this.lastSeqByType.clear();
|
|
16537
16626
|
this.pendingByDataType.clear();
|
|
16538
16627
|
this.tracedDatagramGaps = 0;
|