@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/commands/reverse.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
// cspell: ignore killforward
|
|
2
|
+
|
|
1
3
|
import { AutoDisposable } from '@yume-chan/event';
|
|
2
4
|
import Struct from '@yume-chan/struct';
|
|
3
|
-
import type {
|
|
4
|
-
import type { AdbIncomingSocketEventArgs, AdbPacketDispatcher, AdbSocket } from '../socket';
|
|
5
|
-
import { AdbBufferedStream } from '../stream';
|
|
6
|
-
import { decodeUtf8 } from "../utils";
|
|
5
|
+
import type { AdbPacketCore } from '../packet.js';
|
|
6
|
+
import type { AdbIncomingSocketEventArgs, AdbPacketDispatcher, AdbSocket } from '../socket/index.js';
|
|
7
|
+
import { AdbBufferedStream } from '../stream/index.js';
|
|
8
|
+
import { decodeUtf8 } from "../utils/index.js";
|
|
7
9
|
|
|
8
10
|
export interface AdbReverseHandler {
|
|
9
|
-
onSocket(packet:
|
|
11
|
+
onSocket(packet: AdbPacketCore, socket: AdbSocket): void;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export interface AdbForwardListener {
|
|
@@ -50,8 +52,8 @@ export class AdbReverseCommand extends AutoDisposable {
|
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
const address = decodeUtf8(e.packet.payload
|
|
54
|
-
// tcp:
|
|
55
|
+
const address = decodeUtf8(e.packet.payload);
|
|
56
|
+
// Address format: `tcp:12345\0`
|
|
55
57
|
const port = Number.parseInt(address.substring(4));
|
|
56
58
|
if (this.localPortToHandler.has(port)) {
|
|
57
59
|
this.localPortToHandler.get(port)!.onSocket(e.packet, e.socket);
|
|
@@ -78,7 +80,7 @@ export class AdbReverseCommand extends AutoDisposable {
|
|
|
78
80
|
|
|
79
81
|
const response = await AdbReverseStringResponse.deserialize(stream);
|
|
80
82
|
return response.content!.split('\n').map(line => {
|
|
81
|
-
const [deviceSerial, localName, remoteName] = line.split(' ');
|
|
83
|
+
const [deviceSerial, localName, remoteName] = line.split(' ') as [string, string, string];
|
|
82
84
|
return { deviceSerial, localName, remoteName };
|
|
83
85
|
});
|
|
84
86
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Adb } from '../../adb.js';
|
|
2
|
+
import { DecodeUtf8Stream, GatherStringStream } from "../../stream/index.js";
|
|
3
|
+
import { AdbNoneSubprocessProtocol } from './legacy.js';
|
|
4
|
+
import { AdbShellSubprocessProtocol } from './protocol.js';
|
|
5
|
+
import type { AdbSubprocessProtocol, AdbSubprocessProtocolConstructor } from './types.js';
|
|
6
|
+
|
|
7
|
+
export * from './legacy.js';
|
|
8
|
+
export * from './protocol.js';
|
|
9
|
+
export * from './types.js';
|
|
10
|
+
export * from './utils.js';
|
|
11
|
+
|
|
12
|
+
export interface AdbSubprocessOptions {
|
|
13
|
+
/**
|
|
14
|
+
* A list of `AdbShellConstructor`s to be used.
|
|
15
|
+
*
|
|
16
|
+
* Different `AdbShell` has different capabilities, thus requires specific adaptations.
|
|
17
|
+
* Check each `AdbShell`'s documentation for details.
|
|
18
|
+
*
|
|
19
|
+
* The first one whose `isSupported` returns `true` will be used.
|
|
20
|
+
* If no `AdbShell` is supported, an error will be thrown.
|
|
21
|
+
*
|
|
22
|
+
* The default value is `[AdbShellProtocol, AdbLegacyShell]`.
|
|
23
|
+
*/
|
|
24
|
+
protocols: AdbSubprocessProtocolConstructor[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const DefaultOptions: AdbSubprocessOptions = {
|
|
28
|
+
protocols: [AdbShellSubprocessProtocol, AdbNoneSubprocessProtocol],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export interface SubprocessResult {
|
|
32
|
+
stdout: string;
|
|
33
|
+
stderr: string;
|
|
34
|
+
exitCode: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class AdbSubprocess {
|
|
38
|
+
public readonly adb: Adb;
|
|
39
|
+
|
|
40
|
+
public constructor(adb: Adb) {
|
|
41
|
+
this.adb = adb;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private async createProtocol(command: string, options?: Partial<AdbSubprocessOptions>): Promise<AdbSubprocessProtocol> {
|
|
45
|
+
let { protocols } = { ...DefaultOptions, ...options };
|
|
46
|
+
|
|
47
|
+
let Constructor: AdbSubprocessProtocolConstructor | undefined;
|
|
48
|
+
for (const item of protocols) {
|
|
49
|
+
if (await item.isSupported(this.adb)) {
|
|
50
|
+
Constructor = item;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!Constructor) {
|
|
56
|
+
throw new Error('No specified protocol is supported by the device');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return await Constructor.spawn(this.adb, command);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Spawns the default shell in interactive mode.
|
|
64
|
+
* @param options The options for creating the `AdbShell`
|
|
65
|
+
* @returns A new `AdbShell` instance connecting to the spawned shell process.
|
|
66
|
+
*/
|
|
67
|
+
public shell(options?: Partial<AdbSubprocessOptions>): Promise<AdbSubprocessProtocol> {
|
|
68
|
+
return this.createProtocol('', options);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Spawns a new process using the given `command`.
|
|
73
|
+
* @param command The command to run, or an array of strings containing both command and args.
|
|
74
|
+
* @param options The options for creating the `AdbShell`
|
|
75
|
+
* @returns A new `AdbShell` instance connecting to the spawned process.
|
|
76
|
+
*/
|
|
77
|
+
public spawn(command: string | string[], options?: Partial<AdbSubprocessOptions>): Promise<AdbSubprocessProtocol> {
|
|
78
|
+
if (Array.isArray(command)) {
|
|
79
|
+
command = command.join(' ');
|
|
80
|
+
}
|
|
81
|
+
return this.createProtocol(command, options);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Spawns a new process, waits until it exits, and returns the entire output.
|
|
86
|
+
* @param command The command to run
|
|
87
|
+
* @param options The options for creating the `AdbShell`
|
|
88
|
+
* @returns The entire output of the command
|
|
89
|
+
*/
|
|
90
|
+
public async spawnAndWait(
|
|
91
|
+
command: string | string[],
|
|
92
|
+
options?: Partial<AdbSubprocessOptions>
|
|
93
|
+
): Promise<SubprocessResult> {
|
|
94
|
+
const shell = await this.spawn(command, options);
|
|
95
|
+
|
|
96
|
+
const stdout = new GatherStringStream();
|
|
97
|
+
shell.stdout
|
|
98
|
+
.pipeThrough(new DecodeUtf8Stream())
|
|
99
|
+
.pipeThrough(stdout);
|
|
100
|
+
|
|
101
|
+
const stderr = new GatherStringStream();
|
|
102
|
+
shell.stderr
|
|
103
|
+
.pipeThrough(new DecodeUtf8Stream())
|
|
104
|
+
.pipeThrough(stderr);
|
|
105
|
+
|
|
106
|
+
const exitCode = await shell.exit;
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
stdout: stdout.result,
|
|
110
|
+
stderr: stderr.result,
|
|
111
|
+
exitCode,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Spawns a new process, waits until it exits, and returns the entire output.
|
|
117
|
+
* @param command The command to run
|
|
118
|
+
* @returns The entire output of the command
|
|
119
|
+
*/
|
|
120
|
+
public async spawnAndWaitLegacy(command: string | string[]): Promise<string> {
|
|
121
|
+
const { stdout } = await this.spawnAndWait(command, { protocols: [AdbNoneSubprocessProtocol] });
|
|
122
|
+
return stdout;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Adb } from "../../adb.js";
|
|
2
|
+
import type { AdbSocket } from "../../socket/index.js";
|
|
3
|
+
import { DuplexStreamFactory, type ReadableStream } from "../../stream/index.js";
|
|
4
|
+
import type { AdbSubprocessProtocol } from "./types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The legacy shell
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* * `stderr`: No
|
|
11
|
+
* * `exit` exit code: No
|
|
12
|
+
* * `resize`: No
|
|
13
|
+
*/
|
|
14
|
+
export class AdbNoneSubprocessProtocol implements AdbSubprocessProtocol {
|
|
15
|
+
public static isSupported() { return true; }
|
|
16
|
+
|
|
17
|
+
public static async spawn(adb: Adb, command: string) {
|
|
18
|
+
return new AdbNoneSubprocessProtocol(await adb.createSocket(`shell:${command}`));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private readonly socket: AdbSocket;
|
|
22
|
+
|
|
23
|
+
// Legacy shell forwards all data to stdin.
|
|
24
|
+
public get stdin() { return this.socket.writable; }
|
|
25
|
+
|
|
26
|
+
private _stdout: ReadableStream<Uint8Array>;
|
|
27
|
+
// Legacy shell doesn't support splitting output streams.
|
|
28
|
+
public get stdout() { return this._stdout; }
|
|
29
|
+
|
|
30
|
+
// `stderr` of Legacy shell is always empty.
|
|
31
|
+
private _stderr: ReadableStream<Uint8Array>;
|
|
32
|
+
public get stderr() { return this._stderr; }
|
|
33
|
+
|
|
34
|
+
private _exit: Promise<number>;
|
|
35
|
+
public get exit() { return this._exit; }
|
|
36
|
+
|
|
37
|
+
public constructor(socket: AdbSocket) {
|
|
38
|
+
this.socket = socket;
|
|
39
|
+
|
|
40
|
+
const factory = new DuplexStreamFactory<Uint8Array, Uint8Array>({
|
|
41
|
+
close: async () => {
|
|
42
|
+
await this.socket.close();
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this._stdout = factory.createWrapReadable(this.socket.readable);
|
|
47
|
+
this._stderr = factory.createReadable();
|
|
48
|
+
this._exit = factory.closed.then(() => 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public resize() {
|
|
52
|
+
// Not supported
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public kill() {
|
|
56
|
+
return this.socket.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import Struct, { placeholder, type StructValueType } from "@yume-chan/struct";
|
|
3
|
+
import type { Adb } from "../../adb.js";
|
|
4
|
+
import { AdbFeatures } from "../../features.js";
|
|
5
|
+
import type { AdbSocket } from "../../socket/index.js";
|
|
6
|
+
import { PushReadableStream, ReadableStream, StructDeserializeStream, StructSerializeStream, TransformStream, WritableStream, WritableStreamDefaultWriter, type PushReadableStreamController } from "../../stream/index.js";
|
|
7
|
+
import { encodeUtf8 } from "../../utils/index.js";
|
|
8
|
+
import type { AdbSubprocessProtocol } from "./types.js";
|
|
9
|
+
|
|
10
|
+
export enum AdbShellProtocolId {
|
|
11
|
+
Stdin,
|
|
12
|
+
Stdout,
|
|
13
|
+
Stderr,
|
|
14
|
+
Exit,
|
|
15
|
+
CloseStdin,
|
|
16
|
+
WindowSizeChange,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// This packet format is used in both direction.
|
|
20
|
+
const AdbShellProtocolPacket = new Struct({ littleEndian: true })
|
|
21
|
+
.uint8('id', placeholder<AdbShellProtocolId>())
|
|
22
|
+
.uint32('length')
|
|
23
|
+
.uint8Array('data', { lengthField: 'length' });
|
|
24
|
+
|
|
25
|
+
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket['TInit'];
|
|
26
|
+
|
|
27
|
+
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
|
|
28
|
+
|
|
29
|
+
class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolPacketInit>{
|
|
30
|
+
constructor() {
|
|
31
|
+
super({
|
|
32
|
+
transform(chunk, controller) {
|
|
33
|
+
controller.enqueue({
|
|
34
|
+
id: AdbShellProtocolId.Stdin,
|
|
35
|
+
data: chunk,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
flush() {
|
|
39
|
+
// TODO: AdbShellSubprocessProtocol: support closing stdin
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Uint8Array>{
|
|
46
|
+
constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
|
|
47
|
+
super({
|
|
48
|
+
transform(chunk, controller) {
|
|
49
|
+
if (chunk.id === type) {
|
|
50
|
+
controller.enqueue(chunk.data);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class MultiplexStream<T>{
|
|
58
|
+
private _readable: PushReadableStream<T>;
|
|
59
|
+
private _readableController!: PushReadableStreamController<T>;
|
|
60
|
+
public get readable() { return this._readable; }
|
|
61
|
+
|
|
62
|
+
private _activeCount = 0;
|
|
63
|
+
|
|
64
|
+
constructor() {
|
|
65
|
+
this._readable = new PushReadableStream(controller => {
|
|
66
|
+
this._readableController = controller;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public createWriteable() {
|
|
71
|
+
return new WritableStream<T>({
|
|
72
|
+
start: () => {
|
|
73
|
+
this._activeCount += 1;
|
|
74
|
+
},
|
|
75
|
+
write: async (chunk) => {
|
|
76
|
+
await this._readableController.enqueue(chunk);
|
|
77
|
+
},
|
|
78
|
+
abort: async (e) => {
|
|
79
|
+
this._activeCount -= 1;
|
|
80
|
+
if (this._activeCount === 0) {
|
|
81
|
+
this._readableController.close();
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
close: async () => {
|
|
85
|
+
this._activeCount -= 1;
|
|
86
|
+
if (this._activeCount === 0) {
|
|
87
|
+
this._readableController.close();
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Shell v2 a.k.a Shell Protocol
|
|
96
|
+
*
|
|
97
|
+
* Features:
|
|
98
|
+
* * `stderr`: Yes
|
|
99
|
+
* * `exit` exit code: Yes
|
|
100
|
+
* * `resize`: Yes
|
|
101
|
+
*/
|
|
102
|
+
export class AdbShellSubprocessProtocol implements AdbSubprocessProtocol {
|
|
103
|
+
public static isSupported(adb: Adb) {
|
|
104
|
+
return adb.features!.includes(AdbFeatures.ShellV2);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public static async spawn(adb: Adb, command: string) {
|
|
108
|
+
// TODO: AdbShellSubprocessProtocol: Support raw mode
|
|
109
|
+
// TODO: AdbShellSubprocessProtocol: Support setting `XTERM` environment variable
|
|
110
|
+
return new AdbShellSubprocessProtocol(await adb.createSocket(`shell,v2,pty:${command}`));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private readonly _socket: AdbSocket;
|
|
114
|
+
private _socketWriter: WritableStreamDefaultWriter<AdbShellProtocolPacketInit>;
|
|
115
|
+
|
|
116
|
+
private _stdin: WritableStream<Uint8Array>;
|
|
117
|
+
public get stdin() { return this._stdin; }
|
|
118
|
+
|
|
119
|
+
private _stdout: ReadableStream<Uint8Array>;
|
|
120
|
+
public get stdout() { return this._stdout; }
|
|
121
|
+
|
|
122
|
+
private _stderr: ReadableStream<Uint8Array>;
|
|
123
|
+
public get stderr() { return this._stderr; }
|
|
124
|
+
|
|
125
|
+
private readonly _exit = new PromiseResolver<number>();
|
|
126
|
+
public get exit() { return this._exit.promise; }
|
|
127
|
+
|
|
128
|
+
public constructor(socket: AdbSocket) {
|
|
129
|
+
this._socket = socket;
|
|
130
|
+
|
|
131
|
+
// Check this image to help you understand the stream graph
|
|
132
|
+
// cspell: disable-next-line
|
|
133
|
+
// https://www.plantuml.com/plantuml/png/bL91QiCm4Bpx5SAdv90lb1JISmiw5XzaQKf5PIkiLZIqzEyLSg8ks13gYtOykpFhiOw93N6UGjVDqK7rZsxKqNw0U_NTgVAy4empOy2mm4_olC0VEVEE47GUpnGjKdgXoD76q4GIEpyFhOwP_m28hW0NNzxNUig1_JdW0bA7muFIJDco1daJ_1SAX9bgvoPJPyIkSekhNYctvIGXrCH6tIsPL5fs-s6J5yc9BpWXhKtNdF2LgVYPGM_6GlMwfhWUsIt4lbScANrwlgVVUifPSVi__t44qStnwPvZwobdSmHHlL57p2vFuHS0
|
|
134
|
+
|
|
135
|
+
// TODO: AdbShellSubprocessProtocol: Optimize stream graph
|
|
136
|
+
|
|
137
|
+
const [stdout, stderr] = socket.readable
|
|
138
|
+
.pipeThrough(new StructDeserializeStream(AdbShellProtocolPacket))
|
|
139
|
+
.pipeThrough(new TransformStream<AdbShellProtocolPacket, AdbShellProtocolPacket>({
|
|
140
|
+
transform: (chunk, controller) => {
|
|
141
|
+
if (chunk.id === AdbShellProtocolId.Exit) {
|
|
142
|
+
this._exit.resolve(new Uint8Array(chunk.data)[0]!);
|
|
143
|
+
// We can let `StdoutTransformStream` to process `AdbShellProtocolId.Exit`,
|
|
144
|
+
// but since we need this `TransformStream` to capture the exit code anyway,
|
|
145
|
+
// terminating child streams here is killing two birds with one stone.
|
|
146
|
+
controller.terminate();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
controller.enqueue(chunk);
|
|
150
|
+
}
|
|
151
|
+
}))
|
|
152
|
+
.tee();
|
|
153
|
+
this._stdout = stdout
|
|
154
|
+
.pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stdout));
|
|
155
|
+
this._stderr = stderr
|
|
156
|
+
.pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stderr));
|
|
157
|
+
|
|
158
|
+
const multiplexer = new MultiplexStream<AdbShellProtocolPacketInit>();
|
|
159
|
+
multiplexer.readable
|
|
160
|
+
.pipeThrough(new StructSerializeStream(AdbShellProtocolPacket))
|
|
161
|
+
.pipeTo(socket.writable);
|
|
162
|
+
|
|
163
|
+
const { readable, writable } = new StdinSerializeStream();
|
|
164
|
+
this._stdin = writable;
|
|
165
|
+
readable.pipeTo(multiplexer.createWriteable());
|
|
166
|
+
|
|
167
|
+
this._socketWriter = multiplexer.createWriteable().getWriter();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public async resize(rows: number, cols: number) {
|
|
171
|
+
await this._socketWriter.write({
|
|
172
|
+
id: AdbShellProtocolId.WindowSizeChange,
|
|
173
|
+
data: encodeUtf8(
|
|
174
|
+
// The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
|
|
175
|
+
// However, according to https://linux.die.net/man/4/tty_ioctl
|
|
176
|
+
// `x_pixels` and `y_pixels` are not used, so always passing `0` is fine.
|
|
177
|
+
`${rows}x${cols},0x0\0`
|
|
178
|
+
),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public kill() {
|
|
183
|
+
return this._socket.close();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
2
|
+
import type { Adb } from "../../adb.js";
|
|
3
|
+
import type { AdbSocket } from "../../socket/index.js";
|
|
4
|
+
import type { ReadableStream, WritableStream } from "../../stream/index.js";
|
|
5
|
+
|
|
6
|
+
export interface AdbSubprocessProtocol {
|
|
7
|
+
/**
|
|
8
|
+
* A WritableStream that writes to the `stdin` pipe.
|
|
9
|
+
*/
|
|
10
|
+
readonly stdin: WritableStream<Uint8Array>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The `stdout` pipe of the process.
|
|
14
|
+
*/
|
|
15
|
+
readonly stdout: ReadableStream<Uint8Array>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The `stderr` pipe of the process.
|
|
19
|
+
*
|
|
20
|
+
* Note: Some `AdbShell` doesn't separate `stdout` and `stderr`,
|
|
21
|
+
* All output will be sent to `stdout`.
|
|
22
|
+
*/
|
|
23
|
+
readonly stderr: ReadableStream<Uint8Array>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A `Promise` that resolves to the exit code of the process.
|
|
27
|
+
*
|
|
28
|
+
* Note: Some `AdbShell` doesn't support exit code,
|
|
29
|
+
* They will always resolve with `0`.
|
|
30
|
+
*/
|
|
31
|
+
readonly exit: Promise<number>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Resizes the current shell.
|
|
35
|
+
*
|
|
36
|
+
* Some `AdbShell`s may not support resizing and will always ignore calls to this method.
|
|
37
|
+
*/
|
|
38
|
+
resize(rows: number, cols: number): ValueOrPromise<void>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Kills the current process.
|
|
42
|
+
*/
|
|
43
|
+
kill(): ValueOrPromise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface AdbSubprocessProtocolConstructor {
|
|
47
|
+
/** Returns `true` if the `adb` instance supports this shell */
|
|
48
|
+
isSupported(adb: Adb): ValueOrPromise<boolean>;
|
|
49
|
+
|
|
50
|
+
/** Creates a new `AdbShell` using the specified `Adb` and `command` */
|
|
51
|
+
spawn(adb: Adb, command: string): ValueOrPromise<AdbSubprocessProtocol>;
|
|
52
|
+
|
|
53
|
+
/** Creates a new `AdbShell` by attaching to an exist `AdbSocket` */
|
|
54
|
+
new(socket: AdbSocket): AdbSubprocessProtocol;
|
|
55
|
+
}
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './list';
|
|
2
|
-
export * from './pull';
|
|
3
|
-
export * from './request';
|
|
4
|
-
export * from './response';
|
|
5
|
-
export * from './push';
|
|
6
|
-
export * from './stat';
|
|
7
|
-
export * from './sync';
|
|
1
|
+
export * from './list.js';
|
|
2
|
+
export * from './pull.js';
|
|
3
|
+
export * from './request.js';
|
|
4
|
+
export * from './response.js';
|
|
5
|
+
export * from './push.js';
|
|
6
|
+
export * from './stat.js';
|
|
7
|
+
export * from './sync.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Struct from '@yume-chan/struct';
|
|
2
|
-
import { AdbBufferedStream } from '../../stream';
|
|
3
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from './request';
|
|
4
|
-
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response';
|
|
5
|
-
import { AdbSyncLstatResponse } from './stat';
|
|
2
|
+
import type { AdbBufferedStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
+
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
+
import { AdbSyncLstatResponse } from './stat.js';
|
|
6
6
|
|
|
7
7
|
export const AdbSyncEntryResponse =
|
|
8
8
|
new Struct({ littleEndian: true })
|
|
@@ -20,9 +20,10 @@ const ResponseTypes = {
|
|
|
20
20
|
|
|
21
21
|
export async function* adbSyncOpenDir(
|
|
22
22
|
stream: AdbBufferedStream,
|
|
23
|
-
|
|
23
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
24
|
+
path: string,
|
|
24
25
|
): AsyncGenerator<AdbSyncEntryResponse, void, void> {
|
|
25
|
-
await adbSyncWriteRequest(
|
|
26
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.List, path);
|
|
26
27
|
|
|
27
28
|
while (true) {
|
|
28
29
|
const response = await adbSyncReadResponse(stream, ResponseTypes);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import Struct from '@yume-chan/struct';
|
|
2
|
-
import { AdbBufferedStream } from '../../stream';
|
|
3
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from './request';
|
|
4
|
-
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response';
|
|
2
|
+
import { AdbBufferedStream, ReadableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
+
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
5
|
|
|
6
6
|
export const AdbSyncDataResponse =
|
|
7
7
|
new Struct({ littleEndian: true })
|
|
8
8
|
.uint32('dataLength')
|
|
9
|
-
.
|
|
9
|
+
.uint8Array('data', { lengthField: 'dataLength' })
|
|
10
10
|
.extra({ id: AdbSyncResponseId.Data as const });
|
|
11
11
|
|
|
12
12
|
const ResponseTypes = {
|
|
@@ -14,21 +14,30 @@ const ResponseTypes = {
|
|
|
14
14
|
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncDataResponse.size),
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export
|
|
17
|
+
export function adbSyncPull(
|
|
18
18
|
stream: AdbBufferedStream,
|
|
19
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
19
20
|
path: string,
|
|
20
|
-
):
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
): ReadableStream<Uint8Array> {
|
|
22
|
+
return new ReadableStream<Uint8Array>({
|
|
23
|
+
async start() {
|
|
24
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Receive, path);
|
|
25
|
+
},
|
|
26
|
+
async pull(controller) {
|
|
27
|
+
const response = await adbSyncReadResponse(stream, ResponseTypes);
|
|
28
|
+
switch (response.id) {
|
|
29
|
+
case AdbSyncResponseId.Data:
|
|
30
|
+
controller.enqueue(response.data!);
|
|
31
|
+
break;
|
|
32
|
+
case AdbSyncResponseId.Done:
|
|
33
|
+
controller.close();
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
throw new Error('Unexpected response id');
|
|
37
|
+
}
|
|
32
38
|
}
|
|
33
|
-
}
|
|
39
|
+
}, {
|
|
40
|
+
highWaterMark: 16 * 1024,
|
|
41
|
+
size(chunk) { return chunk.byteLength; }
|
|
42
|
+
});
|
|
34
43
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import Struct from '@yume-chan/struct';
|
|
2
|
-
import { AdbBufferedStream } from '../../stream';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { LinuxFileType } from './stat';
|
|
2
|
+
import { AdbBufferedStream, ChunkStream, pipeFrom, WritableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
+
import { adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
+
import { LinuxFileType } from './stat.js';
|
|
7
6
|
|
|
8
7
|
export const AdbSyncOkResponse =
|
|
9
8
|
new Struct({ littleEndian: true })
|
|
@@ -13,34 +12,30 @@ const ResponseTypes = {
|
|
|
13
12
|
[AdbSyncResponseId.Ok]: AdbSyncOkResponse,
|
|
14
13
|
};
|
|
15
14
|
|
|
16
|
-
export const
|
|
15
|
+
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
|
|
17
16
|
|
|
18
|
-
export
|
|
17
|
+
export function adbSyncPush(
|
|
19
18
|
stream: AdbBufferedStream,
|
|
19
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
20
20
|
filename: string,
|
|
21
|
-
content: ArrayLike<number> | ArrayBufferLike | AsyncIterable<ArrayBuffer>,
|
|
22
21
|
mode: number = (LinuxFileType.File << 12) | 0o666,
|
|
23
22
|
mtime: number = (Date.now() / 1000) | 0,
|
|
24
|
-
packetSize: number =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await adbSyncWriteRequest(stream, AdbSyncRequestId.Done, mtime);
|
|
45
|
-
await adbSyncReadResponse(stream, ResponseTypes);
|
|
23
|
+
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE,
|
|
24
|
+
): WritableStream<Uint8Array> {
|
|
25
|
+
return pipeFrom(
|
|
26
|
+
new WritableStream<Uint8Array>({
|
|
27
|
+
async start() {
|
|
28
|
+
const pathAndMode = `${filename},${mode.toString()}`;
|
|
29
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Send, pathAndMode);
|
|
30
|
+
},
|
|
31
|
+
async write(chunk) {
|
|
32
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Data, chunk);
|
|
33
|
+
},
|
|
34
|
+
async close() {
|
|
35
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Done, mtime);
|
|
36
|
+
await adbSyncReadResponse(stream, ResponseTypes);
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
new ChunkStream(packetSize)
|
|
40
|
+
);
|
|
46
41
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Struct from '@yume-chan/struct';
|
|
2
|
-
import type {
|
|
3
|
-
import { encodeUtf8 } from "../../utils";
|
|
2
|
+
import type { WritableStreamDefaultWriter } from "../../stream/index.js";
|
|
3
|
+
import { encodeUtf8 } from "../../utils/index.js";
|
|
4
4
|
|
|
5
5
|
export enum AdbSyncRequestId {
|
|
6
6
|
List = 'LIST',
|
|
@@ -21,14 +21,14 @@ export const AdbSyncNumberRequest =
|
|
|
21
21
|
export const AdbSyncDataRequest =
|
|
22
22
|
new Struct({ littleEndian: true })
|
|
23
23
|
.fields(AdbSyncNumberRequest)
|
|
24
|
-
.
|
|
24
|
+
.uint8Array('data', { lengthField: 'arg' });
|
|
25
25
|
|
|
26
26
|
export async function adbSyncWriteRequest(
|
|
27
|
-
|
|
27
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
28
28
|
id: AdbSyncRequestId | string,
|
|
29
|
-
value: number | string |
|
|
29
|
+
value: number | string | Uint8Array
|
|
30
30
|
): Promise<void> {
|
|
31
|
-
let buffer:
|
|
31
|
+
let buffer: Uint8Array;
|
|
32
32
|
if (typeof value === 'number') {
|
|
33
33
|
buffer = AdbSyncNumberRequest.serialize({
|
|
34
34
|
id,
|
|
@@ -45,5 +45,5 @@ export async function adbSyncWriteRequest(
|
|
|
45
45
|
data: value,
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
await
|
|
48
|
+
await writer.write(buffer);
|
|
49
49
|
}
|