@yume-chan/adb 0.0.10 → 0.0.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/CHANGELOG.json +26 -0
- package/CHANGELOG.md +15 -1
- package/LICENSE +1 -1
- package/README.md +56 -43
- package/esm/adb.d.ts +48 -0
- package/esm/adb.d.ts.map +1 -0
- package/esm/adb.js +141 -146
- package/esm/adb.js.map +1 -1
- package/{dts → esm}/auth.d.ts +8 -8
- package/esm/auth.d.ts.map +1 -0
- package/esm/auth.js +68 -108
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +9 -0
- package/esm/backend.d.ts.map +1 -0
- package/{dts → esm}/commands/base.d.ts +1 -1
- package/esm/commands/base.d.ts.map +1 -0
- package/esm/commands/base.js +1 -0
- package/esm/commands/base.js.map +1 -1
- package/{dts → esm}/commands/framebuffer.d.ts +3 -3
- package/esm/commands/framebuffer.d.ts.map +1 -0
- package/esm/commands/framebuffer.js +15 -18
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/index.d.ts +9 -0
- package/esm/commands/index.d.ts.map +1 -0
- package/esm/commands/index.js +8 -8
- package/esm/commands/index.js.map +1 -1
- package/esm/commands/install.d.ts +4 -0
- package/esm/commands/install.d.ts.map +1 -0
- package/esm/commands/install.js +21 -13
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +23 -0
- package/esm/commands/power.d.ts.map +1 -0
- package/esm/commands/power.js +45 -0
- package/esm/commands/power.js.map +1 -0
- package/{dts → esm}/commands/reverse.d.ts +3 -3
- package/esm/commands/reverse.d.ts.map +1 -0
- package/esm/commands/reverse.js +49 -60
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/index.d.ts +57 -0
- package/esm/commands/subprocess/index.d.ts.map +1 -0
- package/esm/commands/subprocess/index.js +83 -0
- package/esm/commands/subprocess/index.js.map +1 -0
- package/esm/commands/subprocess/legacy.d.ts +28 -0
- package/esm/commands/subprocess/legacy.d.ts.map +1 -0
- package/esm/commands/subprocess/legacy.js +44 -0
- package/esm/commands/subprocess/legacy.js.map +1 -0
- package/esm/commands/subprocess/protocol.d.ts +38 -0
- package/esm/commands/subprocess/protocol.d.ts.map +1 -0
- package/esm/commands/subprocess/protocol.js +155 -0
- package/esm/commands/subprocess/protocol.js.map +1 -0
- package/esm/commands/subprocess/types.d.ts +47 -0
- package/esm/commands/subprocess/types.d.ts.map +1 -0
- package/esm/commands/{shell → subprocess}/types.js +0 -0
- package/esm/commands/{shell → subprocess}/types.js.map +1 -1
- package/{dts/commands/shell → esm/commands/subprocess}/utils.d.ts +0 -0
- package/esm/commands/subprocess/utils.d.ts.map +1 -0
- package/esm/commands/{shell → subprocess}/utils.js +0 -0
- package/esm/commands/subprocess/utils.js.map +1 -0
- package/esm/commands/sync/index.d.ts +8 -0
- package/esm/commands/sync/index.d.ts.map +1 -0
- package/esm/commands/sync/index.js +7 -7
- package/esm/commands/sync/index.js.map +1 -1
- package/{dts → esm}/commands/sync/list.d.ts +4 -4
- package/esm/commands/sync/list.d.ts.map +1 -0
- package/esm/commands/sync/list.js +16 -19
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +11 -0
- package/esm/commands/sync/pull.d.ts.map +1 -0
- package/esm/commands/sync/pull.js +17 -11
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +8 -0
- package/esm/commands/sync/push.d.ts.map +1 -0
- package/esm/commands/sync/push.js +19 -37
- package/esm/commands/sync/push.js.map +1 -1
- package/{dts → esm}/commands/sync/request.d.ts +3 -3
- package/esm/commands/sync/request.d.ts.map +1 -0
- package/esm/commands/sync/request.js +24 -27
- package/esm/commands/sync/request.js.map +1 -1
- package/{dts → esm}/commands/sync/response.d.ts +2 -2
- package/esm/commands/sync/response.d.ts.map +1 -0
- package/esm/commands/sync/response.js +16 -20
- package/esm/commands/sync/response.js.map +1 -1
- package/{dts → esm}/commands/sync/stat.d.ts +4 -4
- package/esm/commands/sync/stat.d.ts.map +1 -0
- package/esm/commands/sync/stat.js +22 -27
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +83 -0
- package/esm/commands/sync/sync.d.ts.map +1 -0
- package/esm/commands/sync/sync.js +92 -89
- package/esm/commands/sync/sync.js.map +1 -1
- package/{dts → esm}/commands/tcpip.d.ts +1 -1
- package/{dts → esm}/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +14 -19
- package/esm/commands/tcpip.js.map +1 -1
- package/{dts → esm}/crypto.d.ts +7 -7
- package/esm/crypto.d.ts.map +1 -0
- package/esm/crypto.js +26 -29
- package/esm/crypto.js.map +1 -1
- package/{dts → esm}/features.d.ts +0 -0
- package/{dts → esm}/features.d.ts.map +0 -0
- package/esm/features.js +1 -1
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +11 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +10 -10
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +28 -0
- package/esm/packet.d.ts.map +1 -0
- package/esm/packet.js +26 -51
- package/esm/packet.js.map +1 -1
- package/esm/socket/controller.d.ts +37 -0
- package/esm/socket/controller.d.ts.map +1 -0
- package/esm/socket/controller.js +52 -66
- package/esm/socket/controller.js.map +1 -1
- package/{dts → esm}/socket/dispatcher.d.ts +10 -23
- package/esm/socket/dispatcher.d.ts.map +1 -0
- package/esm/socket/dispatcher.js +148 -164
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +3 -0
- package/esm/socket/index.d.ts.map +1 -0
- package/esm/socket/index.js +2 -6
- package/esm/socket/index.js.map +1 -1
- package/esm/socket/socket.d.ts +34 -0
- package/esm/socket/socket.d.ts.map +1 -0
- package/esm/socket/socket.js +69 -14
- package/esm/socket/socket.js.map +1 -1
- package/esm/stream/buffered.d.ts +35 -0
- package/esm/stream/buffered.d.ts.map +1 -0
- package/esm/stream/buffered.js +123 -0
- package/esm/stream/buffered.js.map +1 -0
- package/esm/stream/detect.bak.d.ts +240 -0
- package/esm/stream/detect.bak.d.ts.map +1 -0
- package/esm/stream/detect.bak.js +60 -0
- package/esm/stream/detect.bak.js.map +1 -0
- package/esm/stream/detect.d.ts +18 -0
- package/esm/stream/detect.d.ts.map +1 -0
- package/esm/stream/detect.js +6 -0
- package/esm/stream/detect.js.map +1 -0
- package/esm/stream/detect.native.d.ts +240 -0
- package/esm/stream/detect.native.d.ts.map +1 -0
- package/esm/stream/detect.native.js +60 -0
- package/esm/stream/detect.native.js.map +1 -0
- package/esm/stream/detect.polyfill.d.ts +18 -0
- package/esm/stream/detect.polyfill.d.ts.map +1 -0
- package/esm/stream/detect.polyfill.js +6 -0
- package/esm/stream/detect.polyfill.js.map +1 -0
- package/esm/stream/index.d.ts +4 -0
- package/esm/stream/index.d.ts.map +1 -0
- package/esm/stream/index.js +3 -2
- package/esm/stream/index.js.map +1 -1
- package/esm/stream/transform.d.ts +98 -0
- package/esm/stream/transform.d.ts.map +1 -0
- package/esm/stream/transform.js +352 -0
- package/esm/stream/transform.js.map +1 -0
- package/{dts → esm}/utils/auto-reset-event.d.ts +1 -1
- package/esm/utils/auto-reset-event.d.ts.map +1 -0
- package/esm/utils/auto-reset-event.js +2 -1
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.d.ts +5 -0
- package/esm/utils/base64.d.ts.map +1 -0
- package/esm/utils/base64.js +116 -80
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/encoding.d.ts +3 -0
- package/{dts → esm}/utils/encoding.d.ts.map +1 -1
- package/esm/utils/encoding.js +1 -1
- package/esm/utils/encoding.js.map +1 -1
- package/esm/utils/index.d.ts +4 -0
- package/esm/utils/index.d.ts.map +1 -0
- package/esm/utils/index.js +3 -5
- package/esm/utils/index.js.map +1 -1
- package/package.json +50 -44
- package/src/adb.ts +147 -143
- package/src/auth.ts +23 -19
- package/src/backend.ts +3 -12
- package/src/commands/base.ts +1 -1
- package/src/commands/framebuffer.ts +4 -4
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +26 -15
- package/src/commands/power.ts +54 -0
- package/src/commands/reverse.ts +10 -8
- package/src/commands/subprocess/index.ts +124 -0
- package/src/commands/subprocess/legacy.ts +58 -0
- package/src/commands/subprocess/protocol.ts +185 -0
- package/src/commands/subprocess/types.ts +55 -0
- package/src/commands/{shell → subprocess}/utils.ts +0 -0
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +7 -6
- package/src/commands/sync/pull.ts +27 -18
- package/src/commands/sync/push.ts +25 -30
- package/src/commands/sync/request.ts +7 -7
- package/src/commands/sync/response.ts +4 -4
- package/src/commands/sync/stat.ts +8 -6
- package/src/commands/sync/sync.ts +64 -32
- package/src/commands/tcpip.ts +3 -3
- package/src/crypto.ts +38 -43
- package/src/index.ts +11 -10
- package/src/packet.ts +37 -52
- package/src/socket/dispatcher.ts +90 -103
- package/src/socket/index.ts +2 -6
- package/src/socket/socket.ts +117 -16
- package/src/stream/buffered.ts +147 -0
- package/src/stream/detect.native.ts +362 -0
- package/src/stream/detect.polyfill.ts +25 -0
- package/src/stream/detect.ts +25 -0
- package/src/stream/index.ts +3 -2
- package/src/stream/transform.ts +427 -0
- package/src/utils/auto-reset-event.ts +1 -1
- package/src/utils/base64.ts +161 -129
- package/src/utils/encoding.ts +3 -3
- package/src/utils/index.ts +3 -5
- package/tsconfig.build.json +3 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.test.json +10 -0
- package/dts/adb.d.ts +0 -46
- package/dts/adb.d.ts.map +0 -1
- package/dts/auth.d.ts.map +0 -1
- package/dts/backend.d.ts +0 -13
- package/dts/backend.d.ts.map +0 -1
- package/dts/commands/base.d.ts.map +0 -1
- package/dts/commands/demo-mode.d.ts +0 -41
- package/dts/commands/demo-mode.d.ts.map +0 -1
- package/dts/commands/framebuffer.d.ts.map +0 -1
- package/dts/commands/index.d.ts +0 -9
- package/dts/commands/index.d.ts.map +0 -1
- package/dts/commands/install.d.ts +0 -3
- package/dts/commands/install.d.ts.map +0 -1
- package/dts/commands/reverse.d.ts.map +0 -1
- package/dts/commands/shell/index.d.ts +0 -46
- package/dts/commands/shell/index.d.ts.map +0 -1
- package/dts/commands/shell/legacy.d.ts +0 -38
- package/dts/commands/shell/legacy.d.ts.map +0 -1
- package/dts/commands/shell/protocol.d.ts +0 -45
- package/dts/commands/shell/protocol.d.ts.map +0 -1
- package/dts/commands/shell/types.d.ts +0 -47
- package/dts/commands/shell/types.d.ts.map +0 -1
- package/dts/commands/shell/utils.d.ts.map +0 -1
- package/dts/commands/sync/index.d.ts +0 -8
- package/dts/commands/sync/index.d.ts.map +0 -1
- package/dts/commands/sync/list.d.ts.map +0 -1
- package/dts/commands/sync/pull.d.ts +0 -11
- package/dts/commands/sync/pull.d.ts.map +0 -1
- package/dts/commands/sync/push.d.ts +0 -8
- package/dts/commands/sync/push.d.ts.map +0 -1
- package/dts/commands/sync/request.d.ts.map +0 -1
- package/dts/commands/sync/response.d.ts.map +0 -1
- package/dts/commands/sync/stat.d.ts.map +0 -1
- package/dts/commands/sync/sync.d.ts +0 -68
- package/dts/commands/sync/sync.d.ts.map +0 -1
- package/dts/crypto.d.ts.map +0 -1
- package/dts/index.d.ts +0 -11
- package/dts/index.d.ts.map +0 -1
- package/dts/packet.d.ts +0 -27
- package/dts/packet.d.ts.map +0 -1
- package/dts/socket/close-event-emitter.d.ts +0 -8
- package/dts/socket/close-event-emitter.d.ts.map +0 -1
- package/dts/socket/controller.d.ts +0 -43
- package/dts/socket/controller.d.ts.map +0 -1
- package/dts/socket/data-event-emitter.d.ts +0 -10
- package/dts/socket/data-event-emitter.d.ts.map +0 -1
- package/dts/socket/dispatcher.d.ts.map +0 -1
- package/dts/socket/index.d.ts +0 -7
- package/dts/socket/index.d.ts.map +0 -1
- package/dts/socket/logger.d.ts +0 -9
- package/dts/socket/logger.d.ts.map +0 -1
- package/dts/socket/socket.d.ts +0 -22
- package/dts/socket/socket.d.ts.map +0 -1
- package/dts/stream/buffered-stream.d.ts +0 -28
- package/dts/stream/buffered-stream.d.ts.map +0 -1
- package/dts/stream/index.d.ts +0 -3
- package/dts/stream/index.d.ts.map +0 -1
- package/dts/stream/stream.d.ts +0 -15
- package/dts/stream/stream.d.ts.map +0 -1
- package/dts/utils/auto-reset-event.d.ts.map +0 -1
- package/dts/utils/base64.d.ts +0 -7
- package/dts/utils/base64.d.ts.map +0 -1
- package/dts/utils/chunk.d.ts +0 -3
- package/dts/utils/chunk.d.ts.map +0 -1
- package/dts/utils/encoding.d.ts +0 -3
- package/dts/utils/event-queue.d.ts +0 -35
- package/dts/utils/event-queue.d.ts.map +0 -1
- package/dts/utils/index.d.ts +0 -6
- package/dts/utils/index.d.ts.map +0 -1
- package/esm/commands/demo-mode.js +0 -170
- package/esm/commands/demo-mode.js.map +0 -1
- package/esm/commands/shell/index.js +0 -62
- package/esm/commands/shell/index.js.map +0 -1
- package/esm/commands/shell/legacy.js +0 -49
- package/esm/commands/shell/legacy.js.map +0 -1
- package/esm/commands/shell/protocol.js +0 -106
- package/esm/commands/shell/protocol.js.map +0 -1
- package/esm/commands/shell/utils.js.map +0 -1
- package/esm/socket/close-event-emitter.js +0 -28
- package/esm/socket/close-event-emitter.js.map +0 -1
- package/esm/socket/data-event-emitter.js +0 -25
- package/esm/socket/data-event-emitter.js.map +0 -1
- package/esm/socket/logger.js +0 -2
- package/esm/socket/logger.js.map +0 -1
- package/esm/stream/buffered-stream.js +0 -67
- package/esm/stream/buffered-stream.js.map +0 -1
- package/esm/stream/stream.js +0 -41
- package/esm/stream/stream.js.map +0 -1
- package/esm/utils/chunk.js +0 -70
- package/esm/utils/chunk.js.map +0 -1
- package/esm/utils/event-queue.js +0 -104
- package/esm/utils/event-queue.js.map +0 -1
- package/src/commands/demo-mode.ts +0 -160
- package/src/commands/shell/index.ts +0 -87
- package/src/commands/shell/legacy.ts +0 -59
- package/src/commands/shell/protocol.ts +0 -121
- package/src/commands/shell/types.ts +0 -55
- package/src/socket/close-event-emitter.ts +0 -28
- package/src/socket/controller.ts +0 -105
- package/src/socket/data-event-emitter.ts +0 -27
- package/src/socket/logger.ts +0 -12
- package/src/stream/buffered-stream.ts +0 -92
- package/src/stream/stream.ts +0 -50
- package/src/utils/chunk.ts +0 -70
- package/src/utils/event-queue.ts +0 -145
package/src/socket/dispatcher.ts
CHANGED
|
@@ -1,46 +1,36 @@
|
|
|
1
|
-
import { AsyncOperationManager } from '@yume-chan/async';
|
|
1
|
+
import { AsyncOperationManager, PromiseResolver } from '@yume-chan/async';
|
|
2
2
|
import { AutoDisposable, EventEmitter } from '@yume-chan/event';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { AdbLogger } from './logger';
|
|
8
|
-
import { AdbSocket } from './socket';
|
|
9
|
-
|
|
10
|
-
export interface AdbPacketReceivedEventArgs {
|
|
11
|
-
handled: boolean;
|
|
12
|
-
|
|
13
|
-
packet: AdbPacket;
|
|
14
|
-
}
|
|
3
|
+
import { AdbCommand, calculateChecksum, type AdbPacketCore, type AdbPacketInit } from '../packet.js';
|
|
4
|
+
import { AbortController, WritableStream, WritableStreamDefaultWriter, type ReadableWritablePair } from '../stream/index.js';
|
|
5
|
+
import { decodeUtf8, encodeUtf8 } from '../utils/index.js';
|
|
6
|
+
import { AdbSocket } from './socket.js';
|
|
15
7
|
|
|
16
8
|
export interface AdbIncomingSocketEventArgs {
|
|
17
9
|
handled: boolean;
|
|
18
10
|
|
|
19
|
-
packet:
|
|
11
|
+
packet: AdbPacketCore;
|
|
20
12
|
|
|
21
13
|
serviceString: string;
|
|
22
14
|
|
|
23
15
|
socket: AdbSocket;
|
|
24
16
|
}
|
|
25
17
|
|
|
26
|
-
const
|
|
18
|
+
const EmptyUint8Array = new Uint8Array(0);
|
|
27
19
|
|
|
28
20
|
export class AdbPacketDispatcher extends AutoDisposable {
|
|
29
21
|
// ADB socket id starts from 1
|
|
30
22
|
// (0 means open failed)
|
|
31
23
|
private readonly initializers = new AsyncOperationManager(1);
|
|
32
|
-
private readonly sockets = new Map<number,
|
|
33
|
-
private readonly sendLock = new AutoResetEvent();
|
|
34
|
-
private readonly logger: AdbLogger | undefined;
|
|
24
|
+
private readonly sockets = new Map<number, AdbSocket>();
|
|
35
25
|
|
|
36
|
-
|
|
26
|
+
private _writer!: WritableStreamDefaultWriter<AdbPacketInit>;
|
|
37
27
|
|
|
38
28
|
public maxPayloadSize = 0;
|
|
39
29
|
public calculateChecksum = true;
|
|
40
30
|
public appendNullToServiceString = true;
|
|
41
31
|
|
|
42
|
-
private
|
|
43
|
-
public get
|
|
32
|
+
private _disconnected = new PromiseResolver<void>();
|
|
33
|
+
public get disconnected() { return this._disconnected.promise; }
|
|
44
34
|
|
|
45
35
|
private readonly incomingSocketEvent = this.addDisposable(new EventEmitter<AdbIncomingSocketEventArgs>());
|
|
46
36
|
public get onIncomingSocket() { return this.incomingSocketEvent.event; }
|
|
@@ -48,64 +38,60 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
48
38
|
private readonly errorEvent = this.addDisposable(new EventEmitter<Error>());
|
|
49
39
|
public get onError() { return this.errorEvent.event; }
|
|
50
40
|
|
|
51
|
-
private
|
|
52
|
-
public get running() { return this._running; }
|
|
41
|
+
private _abortController = new AbortController();
|
|
53
42
|
|
|
54
|
-
public constructor(
|
|
43
|
+
public constructor(
|
|
44
|
+
connection: ReadableWritablePair<AdbPacketCore, AdbPacketInit>,
|
|
45
|
+
) {
|
|
55
46
|
super();
|
|
56
47
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
48
|
+
connection.readable
|
|
49
|
+
.pipeTo(new WritableStream({
|
|
50
|
+
write: async (packet) => {
|
|
51
|
+
try {
|
|
52
|
+
switch (packet.command) {
|
|
53
|
+
case AdbCommand.OK:
|
|
54
|
+
this.handleOk(packet);
|
|
55
|
+
return;
|
|
56
|
+
case AdbCommand.Close:
|
|
57
|
+
await this.handleClose(packet);
|
|
58
|
+
return;
|
|
59
|
+
case AdbCommand.Write:
|
|
60
|
+
if (this.sockets.has(packet.arg1)) {
|
|
61
|
+
await this.sockets.get(packet.arg1)!.enqueue(packet.payload);
|
|
62
|
+
await this.sendPacket(AdbCommand.OK, packet.arg1, packet.arg0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Maybe the device is responding to a packet of last connection
|
|
66
|
+
// Just ignore it
|
|
67
|
+
return;
|
|
68
|
+
case AdbCommand.Open:
|
|
69
|
+
await this.handleOpen(packet);
|
|
70
|
+
return;
|
|
78
71
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!this._running) {
|
|
100
|
-
// ignore error
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.errorEvent.fire(e as Error);
|
|
105
|
-
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
this.errorEvent.fire(e as Error);
|
|
74
|
+
|
|
75
|
+
// Throw error here will stop the pipe
|
|
76
|
+
// But won't close `readable` because of `preventCancel: true`
|
|
77
|
+
throw e;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
}), {
|
|
81
|
+
preventCancel: false,
|
|
82
|
+
signal: this._abortController.signal,
|
|
83
|
+
})
|
|
84
|
+
.then(() => {
|
|
85
|
+
this.dispose();
|
|
86
|
+
}, () => {
|
|
87
|
+
// TODO: AdbPacketDispatcher: reject `_disconnected` when pipe errored?
|
|
88
|
+
this.dispose();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
this._writer = connection.writable.getWriter();
|
|
106
92
|
}
|
|
107
93
|
|
|
108
|
-
private handleOk(packet:
|
|
94
|
+
private handleOk(packet: AdbPacketCore) {
|
|
109
95
|
if (this.initializers.resolve(packet.arg1, packet.arg0)) {
|
|
110
96
|
// Device successfully created the socket
|
|
111
97
|
return;
|
|
@@ -123,7 +109,7 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
123
109
|
this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
|
|
124
110
|
}
|
|
125
111
|
|
|
126
|
-
private async handleClose(packet:
|
|
112
|
+
private async handleClose(packet: AdbPacketCore) {
|
|
127
113
|
// From https://android.googlesource.com/platform/packages/modules/adb/+/65d18e2c1cc48b585811954892311b28a4c3d188/adb.cpp#459
|
|
128
114
|
/* According to protocol.txt, p->msg.arg0 might be 0 to indicate
|
|
129
115
|
* a failed OPEN only. However, due to a bug in previous ADB
|
|
@@ -153,23 +139,22 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
153
139
|
// Just ignore it
|
|
154
140
|
}
|
|
155
141
|
|
|
156
|
-
private async handleOpen(packet:
|
|
142
|
+
private async handleOpen(packet: AdbPacketCore) {
|
|
157
143
|
// AsyncOperationManager doesn't support get and skip an ID
|
|
158
144
|
// Use `add` + `resolve` to simulate this behavior
|
|
159
145
|
const [localId] = this.initializers.add<number>();
|
|
160
146
|
this.initializers.resolve(localId, undefined);
|
|
161
147
|
|
|
162
148
|
const remoteId = packet.arg0;
|
|
163
|
-
const serviceString = decodeUtf8(packet.payload
|
|
149
|
+
const serviceString = decodeUtf8(packet.payload);
|
|
164
150
|
|
|
165
|
-
const
|
|
151
|
+
const socket = new AdbSocket({
|
|
166
152
|
dispatcher: this,
|
|
167
153
|
localId,
|
|
168
154
|
remoteId,
|
|
169
155
|
localCreated: false,
|
|
170
156
|
serviceString,
|
|
171
157
|
});
|
|
172
|
-
const socket = new AdbSocket(controller);
|
|
173
158
|
|
|
174
159
|
const args: AdbIncomingSocketEventArgs = {
|
|
175
160
|
handled: false,
|
|
@@ -180,18 +165,13 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
180
165
|
this.incomingSocketEvent.fire(args);
|
|
181
166
|
|
|
182
167
|
if (args.handled) {
|
|
183
|
-
this.sockets.set(localId,
|
|
168
|
+
this.sockets.set(localId, socket);
|
|
184
169
|
await this.sendPacket(AdbCommand.OK, localId, remoteId);
|
|
185
170
|
} else {
|
|
186
171
|
await this.sendPacket(AdbCommand.Close, 0, remoteId);
|
|
187
172
|
}
|
|
188
173
|
}
|
|
189
174
|
|
|
190
|
-
public start() {
|
|
191
|
-
this._running = true;
|
|
192
|
-
this.receiveLoop();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
175
|
public async createSocket(serviceString: string): Promise<AdbSocket> {
|
|
196
176
|
if (this.appendNullToServiceString) {
|
|
197
177
|
serviceString += '\0';
|
|
@@ -201,16 +181,16 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
201
181
|
await this.sendPacket(AdbCommand.Open, localId, 0, serviceString);
|
|
202
182
|
|
|
203
183
|
const remoteId = await initializer;
|
|
204
|
-
const
|
|
184
|
+
const socket = new AdbSocket({
|
|
205
185
|
dispatcher: this,
|
|
206
186
|
localId,
|
|
207
187
|
remoteId,
|
|
208
188
|
localCreated: true,
|
|
209
189
|
serviceString,
|
|
210
190
|
});
|
|
211
|
-
this.sockets.set(
|
|
191
|
+
this.sockets.set(localId, socket);
|
|
212
192
|
|
|
213
|
-
return
|
|
193
|
+
return socket;
|
|
214
194
|
}
|
|
215
195
|
|
|
216
196
|
public sendPacket(packet: AdbPacketInit): Promise<void>;
|
|
@@ -218,23 +198,27 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
218
198
|
command: AdbCommand,
|
|
219
199
|
arg0: number,
|
|
220
200
|
arg1: number,
|
|
221
|
-
payload?: string |
|
|
201
|
+
payload?: string | Uint8Array
|
|
222
202
|
): Promise<void>;
|
|
223
203
|
public async sendPacket(
|
|
224
204
|
packetOrCommand: AdbPacketInit | AdbCommand,
|
|
225
205
|
arg0?: number,
|
|
226
206
|
arg1?: number,
|
|
227
|
-
payload: string |
|
|
207
|
+
payload: string | Uint8Array = EmptyUint8Array,
|
|
228
208
|
): Promise<void> {
|
|
229
|
-
let init:
|
|
209
|
+
let init: AdbPacketCore;
|
|
230
210
|
if (arg0 === undefined) {
|
|
231
211
|
init = packetOrCommand as AdbPacketInit;
|
|
232
212
|
} else {
|
|
213
|
+
if (typeof payload === 'string') {
|
|
214
|
+
payload = encodeUtf8(payload);
|
|
215
|
+
}
|
|
216
|
+
|
|
233
217
|
init = {
|
|
234
218
|
command: packetOrCommand as AdbCommand,
|
|
235
219
|
arg0: arg0 as number,
|
|
236
220
|
arg1: arg1 as number,
|
|
237
|
-
payload
|
|
221
|
+
payload,
|
|
238
222
|
};
|
|
239
223
|
}
|
|
240
224
|
|
|
@@ -243,27 +227,30 @@ export class AdbPacketDispatcher extends AutoDisposable {
|
|
|
243
227
|
throw new Error('payload too large');
|
|
244
228
|
}
|
|
245
229
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
this.logger?.onOutgoingPacket?.(init);
|
|
252
|
-
|
|
253
|
-
await AdbPacket.write(init, this.calculateChecksum, this.backend);
|
|
254
|
-
} finally {
|
|
255
|
-
this.sendLock.notify();
|
|
230
|
+
if (this.calculateChecksum) {
|
|
231
|
+
calculateChecksum(init);
|
|
232
|
+
} else {
|
|
233
|
+
(init as AdbPacketInit).checksum = 0;
|
|
256
234
|
}
|
|
235
|
+
|
|
236
|
+
await this._writer.write(init as AdbPacketInit);
|
|
257
237
|
}
|
|
258
238
|
|
|
259
239
|
public override dispose() {
|
|
260
|
-
this._running = false;
|
|
261
|
-
|
|
262
240
|
for (const socket of this.sockets.values()) {
|
|
263
241
|
socket.dispose();
|
|
264
242
|
}
|
|
265
243
|
this.sockets.clear();
|
|
266
244
|
|
|
245
|
+
try {
|
|
246
|
+
// Stop pipes
|
|
247
|
+
this._abortController.abort();
|
|
248
|
+
} catch { }
|
|
249
|
+
|
|
250
|
+
this._writer.releaseLock();
|
|
251
|
+
|
|
252
|
+
this._disconnected.resolve();
|
|
253
|
+
|
|
267
254
|
super.dispose();
|
|
268
255
|
}
|
|
269
256
|
}
|
package/src/socket/index.ts
CHANGED
package/src/socket/socket.ts
CHANGED
|
@@ -1,28 +1,129 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import { AdbCommand } from '../packet.js';
|
|
3
|
+
import { ChunkStream, DuplexStreamFactory, pipeFrom, ReadableStream, WritableStream, type PushReadableStreamController } from '../stream/index.js';
|
|
4
|
+
import type { AdbPacketDispatcher } from './dispatcher.js';
|
|
5
|
+
|
|
6
|
+
export interface AdbSocketInfo {
|
|
7
|
+
localId: number;
|
|
8
|
+
remoteId: number;
|
|
9
|
+
|
|
10
|
+
localCreated: boolean;
|
|
11
|
+
|
|
12
|
+
serviceString: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AdbSocketConstructionOptions {
|
|
16
|
+
dispatcher: AdbPacketDispatcher;
|
|
17
|
+
|
|
18
|
+
localId: number;
|
|
19
|
+
|
|
20
|
+
remoteId: number;
|
|
21
|
+
|
|
22
|
+
localCreated: boolean;
|
|
23
|
+
|
|
24
|
+
serviceString: string;
|
|
25
|
+
|
|
26
|
+
highWaterMark?: number | undefined;
|
|
27
|
+
}
|
|
2
28
|
|
|
3
29
|
export class AdbSocket implements AdbSocketInfo {
|
|
4
|
-
private readonly
|
|
30
|
+
private readonly dispatcher!: AdbPacketDispatcher;
|
|
31
|
+
|
|
32
|
+
public readonly localId!: number;
|
|
33
|
+
public readonly remoteId!: number;
|
|
34
|
+
public readonly localCreated!: boolean;
|
|
35
|
+
public readonly serviceString!: string;
|
|
36
|
+
|
|
37
|
+
private _factory: DuplexStreamFactory<Uint8Array, Uint8Array>;
|
|
5
38
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
public get
|
|
9
|
-
public get localCreated() { return this.controller.localCreated; }
|
|
10
|
-
public get serviceString() { return this.controller.serviceString; }
|
|
39
|
+
private _readable: ReadableStream<Uint8Array>;
|
|
40
|
+
private _readableController!: PushReadableStreamController<Uint8Array>;
|
|
41
|
+
public get readable() { return this._readable; }
|
|
11
42
|
|
|
12
|
-
|
|
43
|
+
private _writePromise: PromiseResolver<void> | undefined;
|
|
44
|
+
public readonly writable: WritableStream<Uint8Array>;
|
|
13
45
|
|
|
14
|
-
|
|
15
|
-
public get
|
|
46
|
+
private _closed = false;
|
|
47
|
+
public get closed() { return this._closed; }
|
|
16
48
|
|
|
17
|
-
public constructor(
|
|
18
|
-
this
|
|
49
|
+
public constructor(options: AdbSocketConstructionOptions) {
|
|
50
|
+
Object.assign(this, options);
|
|
51
|
+
|
|
52
|
+
// Check this image to help you understand the stream graph
|
|
53
|
+
// cspell: disable-next-line
|
|
54
|
+
// https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
|
|
55
|
+
|
|
56
|
+
this._factory = new DuplexStreamFactory<Uint8Array, Uint8Array>({
|
|
57
|
+
close: async () => {
|
|
58
|
+
await this.close();
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
this._readable = this._factory.createPushReadable(controller => {
|
|
63
|
+
this._readableController = controller;
|
|
64
|
+
}, {
|
|
65
|
+
highWaterMark: options.highWaterMark ?? 16 * 1024,
|
|
66
|
+
size(chunk) { return chunk.byteLength; }
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
this.writable = pipeFrom(
|
|
70
|
+
this._factory.createWritable({
|
|
71
|
+
write: async (chunk) => {
|
|
72
|
+
// Wait for an ack packet
|
|
73
|
+
this._writePromise = new PromiseResolver();
|
|
74
|
+
await this.dispatcher.sendPacket(
|
|
75
|
+
AdbCommand.Write,
|
|
76
|
+
this.localId,
|
|
77
|
+
this.remoteId,
|
|
78
|
+
chunk
|
|
79
|
+
);
|
|
80
|
+
await this._writePromise.promise;
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
new ChunkStream(this.dispatcher.maxPayloadSize)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
public async enqueue(packet: Uint8Array) {
|
|
91
|
+
await this._readableController.enqueue(packet);
|
|
19
92
|
}
|
|
20
93
|
|
|
21
|
-
|
|
22
|
-
|
|
94
|
+
/**
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
97
|
+
public ack() {
|
|
98
|
+
this._writePromise?.resolve();
|
|
23
99
|
}
|
|
24
100
|
|
|
25
|
-
public close(): Promise<void> {
|
|
26
|
-
|
|
101
|
+
public async close(): Promise<void> {
|
|
102
|
+
// Error out the pending writes
|
|
103
|
+
this._writePromise?.reject(new Error('Socket closed'));
|
|
104
|
+
|
|
105
|
+
if (!this._closed) {
|
|
106
|
+
this._closed = true;
|
|
107
|
+
|
|
108
|
+
// Only send close packet when `close` is called before `dispose`
|
|
109
|
+
// (the client initiated the close)
|
|
110
|
+
await this.dispatcher.sendPacket(
|
|
111
|
+
AdbCommand.Close,
|
|
112
|
+
this.localId,
|
|
113
|
+
this.remoteId
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @internal
|
|
120
|
+
*/
|
|
121
|
+
public dispose() {
|
|
122
|
+
this._closed = true;
|
|
123
|
+
|
|
124
|
+
this._factory.close();
|
|
125
|
+
|
|
126
|
+
// Close `writable` side
|
|
127
|
+
this.close();
|
|
27
128
|
}
|
|
28
129
|
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { StructAsyncDeserializeStream } from '@yume-chan/struct';
|
|
2
|
+
import type { AdbSocket, AdbSocketInfo } from '../socket/index.js';
|
|
3
|
+
import type { ReadableStream, ReadableStreamDefaultReader } from './detect.js';
|
|
4
|
+
import { PushReadableStream } from "./transform.js";
|
|
5
|
+
|
|
6
|
+
export class BufferedStreamEndedError extends Error {
|
|
7
|
+
public constructor() {
|
|
8
|
+
super('Stream ended');
|
|
9
|
+
|
|
10
|
+
// Fix Error's prototype chain when compiling to ES5
|
|
11
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class BufferedStream {
|
|
16
|
+
private buffer: Uint8Array | undefined;
|
|
17
|
+
|
|
18
|
+
protected readonly stream: ReadableStream<Uint8Array>;
|
|
19
|
+
|
|
20
|
+
protected readonly reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
21
|
+
|
|
22
|
+
public constructor(stream: ReadableStream<Uint8Array>) {
|
|
23
|
+
this.stream = stream;
|
|
24
|
+
this.reader = stream.getReader();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param length
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
public async read(length: number): Promise<Uint8Array> {
|
|
33
|
+
let array: Uint8Array;
|
|
34
|
+
let index: number;
|
|
35
|
+
if (this.buffer) {
|
|
36
|
+
const buffer = this.buffer;
|
|
37
|
+
if (buffer.byteLength > length) {
|
|
38
|
+
this.buffer = buffer.subarray(length);
|
|
39
|
+
return buffer.subarray(0, length);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
array = new Uint8Array(length);
|
|
43
|
+
array.set(buffer);
|
|
44
|
+
index = buffer.byteLength;
|
|
45
|
+
this.buffer = undefined;
|
|
46
|
+
} else {
|
|
47
|
+
const { done, value } = await this.reader.read();
|
|
48
|
+
if (done) {
|
|
49
|
+
throw new BufferedStreamEndedError();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (value.byteLength === length) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (value.byteLength > length) {
|
|
57
|
+
this.buffer = value.subarray(length);
|
|
58
|
+
return value.subarray(0, length);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
array = new Uint8Array(length);
|
|
62
|
+
array.set(value);
|
|
63
|
+
index = value.byteLength;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
while (index < length) {
|
|
67
|
+
const left = length - index;
|
|
68
|
+
|
|
69
|
+
const { done, value } = await this.reader.read();
|
|
70
|
+
if (done) {
|
|
71
|
+
throw new BufferedStreamEndedError();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (value.byteLength === left) {
|
|
75
|
+
array.set(value, index);
|
|
76
|
+
return array;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (value.byteLength > left) {
|
|
80
|
+
array.set(value.subarray(0, left), index);
|
|
81
|
+
this.buffer = value.subarray(left);
|
|
82
|
+
return array;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
array.set(value, index);
|
|
86
|
+
index += value.byteLength;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return array;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Return a readable stream with unconsumed data (if any) and
|
|
94
|
+
* all data from the wrapped stream.
|
|
95
|
+
* @returns A `ReadableStream`
|
|
96
|
+
*/
|
|
97
|
+
public release(): ReadableStream<Uint8Array> {
|
|
98
|
+
if (this.buffer) {
|
|
99
|
+
return new PushReadableStream<Uint8Array>(async controller => {
|
|
100
|
+
// Put the remaining data back to the stream
|
|
101
|
+
await controller.enqueue(this.buffer!);
|
|
102
|
+
|
|
103
|
+
// Manually pipe the stream
|
|
104
|
+
while (true) {
|
|
105
|
+
try {
|
|
106
|
+
const { done, value } = await this.reader.read();
|
|
107
|
+
if (done) {
|
|
108
|
+
controller.close();
|
|
109
|
+
break;
|
|
110
|
+
} else {
|
|
111
|
+
await controller.enqueue(value);
|
|
112
|
+
}
|
|
113
|
+
} catch (e) {
|
|
114
|
+
controller.error(e);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
} else {
|
|
120
|
+
// Simply release the reader and return the stream
|
|
121
|
+
this.reader.releaseLock();
|
|
122
|
+
return this.stream;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public close() {
|
|
127
|
+
this.reader.cancel();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export class AdbBufferedStream
|
|
132
|
+
extends BufferedStream
|
|
133
|
+
implements AdbSocketInfo, StructAsyncDeserializeStream {
|
|
134
|
+
protected readonly socket: AdbSocket;
|
|
135
|
+
|
|
136
|
+
public get localId() { return this.socket.localId; }
|
|
137
|
+
public get remoteId() { return this.socket.remoteId; }
|
|
138
|
+
public get localCreated() { return this.socket.localCreated; }
|
|
139
|
+
public get serviceString() { return this.socket.serviceString; }
|
|
140
|
+
|
|
141
|
+
public get writable() { return this.socket.writable; }
|
|
142
|
+
|
|
143
|
+
public constructor(socket: AdbSocket) {
|
|
144
|
+
super(socket.readable);
|
|
145
|
+
this.socket = socket;
|
|
146
|
+
}
|
|
147
|
+
}
|