@mega-yfue/eufy-sdk 0.5.0-beta.84 → 0.5.0-beta.85
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 +53 -7
- package/dist/index.js.map +2 -2
- package/dist/transport/p2p/p2p-session.d.ts +21 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16227,6 +16227,10 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16227
16227
|
* change (the level-2 key arrived after an initial level-1 start), otherwise sends the 1139 nudge.
|
|
16228
16228
|
*/
|
|
16229
16229
|
liveStartedChannels = /* @__PURE__ */ new Map();
|
|
16230
|
+
/** The `cipher_id` this connection's `CMD_GATEWAYINFO` reply named, once its negotiation has read it. */
|
|
16231
|
+
gatewayCipherId;
|
|
16232
|
+
/** The `n` of the last `[0x01, n]` header this connection sent in the clear — see {@link nextClearCommandBytes}. */
|
|
16233
|
+
clearCommandCount = 0;
|
|
16230
16234
|
unackedLiveStarts = /* @__PURE__ */ new Map();
|
|
16231
16235
|
liveStartRetransmitTimer;
|
|
16232
16236
|
logger;
|
|
@@ -16424,6 +16428,7 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16424
16428
|
this.level2Negotiating = true;
|
|
16425
16429
|
const generation = this.connectionGeneration;
|
|
16426
16430
|
const cipherId = gatewayInfoCipherId(gwPayload);
|
|
16431
|
+
this.gatewayCipherId = cipherId;
|
|
16427
16432
|
this.trace({ phase: "level2-negotiating", cipherId });
|
|
16428
16433
|
void (async () => {
|
|
16429
16434
|
try {
|
|
@@ -16530,6 +16535,8 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16530
16535
|
this.level2Pending = this.cfg.resolveCipherKey !== void 0;
|
|
16531
16536
|
this.level2Negotiating = false;
|
|
16532
16537
|
this.level2Reprompted = false;
|
|
16538
|
+
this.gatewayCipherId = void 0;
|
|
16539
|
+
this.clearCommandCount = 0;
|
|
16533
16540
|
}
|
|
16534
16541
|
const socket = dgram.createSocket("udp4");
|
|
16535
16542
|
this.socket = socket;
|
|
@@ -16820,7 +16827,7 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16820
16827
|
this.sendMediaPayloadLevel2(CMD_START_REALTIME_MEDIA, channel, accountId, {});
|
|
16821
16828
|
return;
|
|
16822
16829
|
}
|
|
16823
|
-
const want = this.level2Key ? "l2" : "l1";
|
|
16830
|
+
const want = this.level2Key ? "l2" : this.sendsInTheClear() ? "clear" : "l1";
|
|
16824
16831
|
if (opts?.force) {
|
|
16825
16832
|
for (const pending of this.unackedLiveStarts.values())
|
|
16826
16833
|
if (pending.channel === channel)
|
|
@@ -16850,8 +16857,17 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16850
16857
|
* `video_type` is 12, and `transaction` is the millisecond timestamp as a string. The device answers a
|
|
16851
16858
|
* start carrying these values with a keyframe; `encryptkey` is the modulus it RSA-wraps each keyframe's
|
|
16852
16859
|
* AES media key with (unwrapped by {@link decodeVideoFrame}).
|
|
16860
|
+
*
|
|
16861
|
+
* With `clearMsgId`, the body of a start sent in the clear: `{accountId, encryptkey, msg_id, streamtype: 1}`
|
|
16862
|
+
* only, `msg_id` being `clearMsgId`, which changes from one start to the next.
|
|
16853
16863
|
*/
|
|
16854
|
-
startLiveJson(channel, accountId) {
|
|
16864
|
+
startLiveJson(channel, accountId, clearMsgId) {
|
|
16865
|
+
if (clearMsgId !== void 0) {
|
|
16866
|
+
return Buffer.from(JSON.stringify({
|
|
16867
|
+
commandType: CMD_START_LIVE,
|
|
16868
|
+
data: { accountId, encryptkey: this.rsaModulus(), msg_id: clearMsgId, streamtype: 1 }
|
|
16869
|
+
}), "utf-8");
|
|
16870
|
+
}
|
|
16855
16871
|
const now2 = Date.now();
|
|
16856
16872
|
return Buffer.from(JSON.stringify({
|
|
16857
16873
|
commandType: CMD_START_LIVE,
|
|
@@ -16882,25 +16898,31 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16882
16898
|
* (GCM, signCode 8, frame type 10) when the session has a negotiated key, else level-1 (AES-128-ECB,
|
|
16883
16899
|
* signCode 1, frame type 11) — chosen by the session key, not the device family. The camera RSA-wraps
|
|
16884
16900
|
* each keyframe's AES media key with the `encryptkey` modulus (unwrapped by {@link decodeVideoFrame}).
|
|
16901
|
+
* A session that {@link sendsInTheClear} sends it unencrypted instead: signCode 0, frame type 0, header
|
|
16902
|
+
* bytes `[0x01, n]` from {@link nextClearCommandBytes}, and `n` as the body's `msg_id`.
|
|
16885
16903
|
*/
|
|
16886
16904
|
sendStartLiveOwnSession(channel, accountId) {
|
|
16887
16905
|
if (!this.connectAddress)
|
|
16888
16906
|
return;
|
|
16889
|
-
const plain = this.startLiveJson(channel, accountId);
|
|
16890
16907
|
let payload;
|
|
16891
16908
|
let signCode;
|
|
16892
16909
|
let magic;
|
|
16893
16910
|
let frameType;
|
|
16894
16911
|
if (this.level2Key) {
|
|
16895
|
-
const enc2 = this.encryptLevel2(
|
|
16912
|
+
const enc2 = this.encryptLevel2(this.startLiveJson(channel, accountId));
|
|
16896
16913
|
if (!enc2)
|
|
16897
16914
|
return;
|
|
16898
16915
|
payload = enc2;
|
|
16899
16916
|
signCode = 8;
|
|
16900
16917
|
magic = [8, 0];
|
|
16901
16918
|
frameType = START_LIVE_FRAME_TYPE_L2;
|
|
16919
|
+
} else if (this.sendsInTheClear()) {
|
|
16920
|
+
magic = this.nextClearCommandBytes();
|
|
16921
|
+
payload = this.startLiveJson(channel, accountId, magic[1]);
|
|
16922
|
+
signCode = 0;
|
|
16923
|
+
frameType = 0;
|
|
16902
16924
|
} else {
|
|
16903
|
-
payload = encryptP2PData(paddingP2PData(
|
|
16925
|
+
payload = encryptP2PData(paddingP2PData(this.startLiveJson(channel, accountId)), this.level1Key);
|
|
16904
16926
|
signCode = 1;
|
|
16905
16927
|
magic = [1, 0];
|
|
16906
16928
|
frameType = START_LIVE_FRAME_TYPE_L1;
|
|
@@ -16920,6 +16942,21 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16920
16942
|
this.armLiveStartRetransmit();
|
|
16921
16943
|
this.send(this.connectAddress, RequestMessageType.DATA, data);
|
|
16922
16944
|
}
|
|
16945
|
+
/**
|
|
16946
|
+
* Whether this session's own-session start and stop go in the clear: its `CMD_GATEWAYINFO` reply named
|
|
16947
|
+
* `cipher_id` 0.
|
|
16948
|
+
*/
|
|
16949
|
+
sendsInTheClear() {
|
|
16950
|
+
return this.gatewayCipherId === 0;
|
|
16951
|
+
}
|
|
16952
|
+
/**
|
|
16953
|
+
* Header bytes 10-11 of this connection's next command sent in the clear: `[0x01, n]`, with `n` counting
|
|
16954
|
+
* those commands from 1 and never 0. A retransmit repeats its `n`, and the device's reply echoes it.
|
|
16955
|
+
*/
|
|
16956
|
+
nextClearCommandBytes() {
|
|
16957
|
+
this.clearCommandCount = this.clearCommandCount % 255 + 1;
|
|
16958
|
+
return [1, this.clearCommandCount];
|
|
16959
|
+
}
|
|
16923
16960
|
/**
|
|
16924
16961
|
* Repeat unacknowledged own-session live starts until the device takes one. Runs only while a start is
|
|
16925
16962
|
* outstanding.
|
|
@@ -17082,6 +17119,8 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
17082
17119
|
* `uint32`, the same 4-byte body as the attached talkback frames. The app sends this frame on closing
|
|
17083
17120
|
* an own-session camera's live view; the camera stops streaming on it within a second, and keeps
|
|
17084
17121
|
* streaming through the 1350-wrapped form.
|
|
17122
|
+
* - own-session on a session that {@link sendsInTheClear}: the same 4-byte body unencrypted, signCode 0,
|
|
17123
|
+
* header bytes from {@link nextClearCommandBytes}.
|
|
17085
17124
|
* - without a level-2 key: the bare 1004 command.
|
|
17086
17125
|
*/
|
|
17087
17126
|
stopLiveMedia(channel = STATION_CHANNEL3, accountId = "", homeBaseAttached = false) {
|
|
@@ -17094,12 +17133,19 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
17094
17133
|
clearInterval(this.liveStartRetransmitTimer);
|
|
17095
17134
|
this.liveStartRetransmitTimer = void 0;
|
|
17096
17135
|
}
|
|
17136
|
+
const body = Buffer.allocUnsafe(4);
|
|
17137
|
+
body.writeUInt32LE(channel >>> 0, 0);
|
|
17097
17138
|
if (this.level2Key && !homeBaseAttached) {
|
|
17098
|
-
const body = Buffer.allocUnsafe(4);
|
|
17099
|
-
body.writeUInt32LE(channel >>> 0, 0);
|
|
17100
17139
|
this.sendRawLevel2Bytes(body, channel, CMD_STOP_REALTIME_MEDIA, 8);
|
|
17101
17140
|
} else if (this.level2Key) {
|
|
17102
17141
|
this.sendMediaPayloadLevel2(CMD_STOP_REALTIME_MEDIA, channel, accountId, {});
|
|
17142
|
+
} else if (!homeBaseAttached && this.sendsInTheClear() && this.connectAddress) {
|
|
17143
|
+
const data = Buffer.concat([
|
|
17144
|
+
buildCommandHeader(this.seqNumber, CMD_STOP_REALTIME_MEDIA),
|
|
17145
|
+
buildRawCommandPayload(body, channel, 0, this.nextClearCommandBytes(), 0)
|
|
17146
|
+
]);
|
|
17147
|
+
this.seqNumber = this.seqNumber + 1 & 65535;
|
|
17148
|
+
this.send(this.connectAddress, RequestMessageType.DATA, data);
|
|
17103
17149
|
} else {
|
|
17104
17150
|
this.sendCommand(CMD_STOP_REALTIME_MEDIA, channel);
|
|
17105
17151
|
}
|