@yume-chan/adb 0.0.24 → 1.1.0
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.md +42 -1
- package/README.md +4 -1
- package/esm/adb.d.ts +13 -7
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +3 -0
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts +7 -6
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js +6 -7
- package/esm/banner.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +63 -34
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +35 -33
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/reverse.d.ts +12 -12
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +39 -30
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +3 -5
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +20 -12
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +16 -21
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +6 -6
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/sync/list.d.ts +49 -27
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +9 -9
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +7 -6
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +3 -5
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +22 -16
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +12 -16
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +19 -17
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +14 -18
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +18 -18
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +20 -19
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +1 -1
- package/esm/commands/sync/socket.js +2 -2
- package/esm/commands/sync/socket.js.map +1 -1
- package/esm/commands/sync/stat.d.ts +75 -51
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +73 -67
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +14 -14
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +4 -7
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +0 -1
- package/esm/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +8 -8
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/daemon/auth.d.ts +8 -7
- package/esm/daemon/auth.d.ts.map +1 -1
- package/esm/daemon/auth.js +7 -8
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.d.ts +1 -1
- package/esm/daemon/crypto.d.ts.map +1 -1
- package/esm/daemon/crypto.js +1 -0
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/device.d.ts +2 -2
- package/esm/daemon/device.d.ts.map +1 -1
- package/esm/daemon/dispatcher.js +6 -6
- package/esm/daemon/dispatcher.js.map +1 -1
- package/esm/daemon/packet.d.ts +46 -30
- package/esm/daemon/packet.d.ts.map +1 -1
- package/esm/daemon/packet.js +24 -21
- package/esm/daemon/packet.js.map +1 -1
- package/esm/daemon/socket.d.ts +1 -6
- package/esm/daemon/socket.d.ts.map +1 -1
- package/esm/daemon/socket.js +4 -27
- package/esm/daemon/socket.js.map +1 -1
- package/esm/daemon/transport.d.ts +14 -14
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js +6 -8
- package/esm/daemon/transport.js.map +1 -1
- package/esm/device-observer.d.ts +10 -0
- package/esm/device-observer.d.ts.map +1 -0
- package/esm/device-observer.js +2 -0
- package/esm/device-observer.js.map +1 -0
- package/esm/features.d.ts +12 -11
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +11 -12
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/server/client.d.ts +33 -35
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +136 -201
- package/esm/server/client.js.map +1 -1
- package/esm/server/index.d.ts +2 -0
- package/esm/server/index.d.ts.map +1 -1
- package/esm/server/index.js +2 -0
- package/esm/server/index.js.map +1 -1
- package/esm/server/observer.d.ts +8 -0
- package/esm/server/observer.d.ts.map +1 -0
- package/esm/server/observer.js +106 -0
- package/esm/server/observer.js.map +1 -0
- package/esm/server/stream.d.ts +19 -0
- package/esm/server/stream.d.ts.map +1 -0
- package/esm/server/stream.js +77 -0
- package/esm/server/stream.js.map +1 -0
- package/esm/server/transport.d.ts +3 -4
- package/esm/server/transport.d.ts.map +1 -1
- package/esm/server/transport.js +16 -16
- package/esm/server/transport.js.map +1 -1
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +19 -16
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/esm/utils/no-op.d.ts.map +1 -1
- package/esm/utils/no-op.js +1 -0
- package/esm/utils/no-op.js.map +1 -1
- package/esm/utils/ref.d.ts +18 -0
- package/esm/utils/ref.d.ts.map +1 -0
- package/esm/utils/ref.js +29 -0
- package/esm/utils/ref.js.map +1 -0
- package/package.json +13 -16
- package/src/adb.ts +13 -7
- package/src/banner.ts +8 -6
- package/src/commands/framebuffer.ts +44 -35
- package/src/commands/reverse.ts +49 -31
- package/src/commands/subprocess/protocols/none.ts +3 -5
- package/src/commands/subprocess/protocols/shell.ts +26 -24
- package/src/commands/subprocess/protocols/types.ts +6 -6
- package/src/commands/sync/list.ts +20 -13
- package/src/commands/sync/pull.ts +8 -7
- package/src/commands/sync/push.ts +20 -16
- package/src/commands/sync/request.ts +18 -19
- package/src/commands/sync/response.ts +28 -29
- package/src/commands/sync/socket.ts +2 -2
- package/src/commands/sync/stat.ts +93 -71
- package/src/commands/sync/sync.ts +4 -8
- package/src/commands/tcpip.ts +8 -8
- package/src/daemon/auth.ts +11 -9
- package/src/daemon/crypto.ts +2 -0
- package/src/daemon/device.ts +2 -2
- package/src/daemon/dispatcher.ts +6 -6
- package/src/daemon/packet.ts +37 -25
- package/src/daemon/socket.ts +4 -27
- package/src/daemon/transport.ts +36 -35
- package/src/device-observer.ts +10 -0
- package/src/features.ts +13 -11
- package/src/index.ts +1 -0
- package/src/server/client.ts +181 -242
- package/src/server/index.ts +2 -0
- package/src/server/observer.ts +144 -0
- package/src/server/stream.ts +100 -0
- package/src/server/transport.ts +18 -17
- package/src/utils/base64.ts +26 -18
- package/src/utils/index.ts +1 -0
- package/src/utils/no-op.ts +1 -0
- package/src/utils/ref.ts +37 -0
- package/tsconfig.build.json +1 -12
- package/tsconfig.build.tsbuildinfo +1 -1
- package/CHANGELOG.json +0 -298
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { getUint32LittleEndian } from "@yume-chan/no-data-view";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
StructLike,
|
|
5
|
-
StructValueType,
|
|
6
|
-
} from "@yume-chan/struct";
|
|
7
|
-
import Struct, { decodeUtf8 } from "@yume-chan/struct";
|
|
2
|
+
import type { AsyncExactReadable, StructLike } from "@yume-chan/struct";
|
|
3
|
+
import { decodeUtf8, string, struct, u32 } from "@yume-chan/struct";
|
|
8
4
|
|
|
9
5
|
function encodeAsciiUnchecked(value: string): Uint8Array {
|
|
10
6
|
const result = new Uint8Array(value.length);
|
|
@@ -18,32 +14,37 @@ function encodeAsciiUnchecked(value: string): Uint8Array {
|
|
|
18
14
|
* Encode ID to numbers for faster comparison
|
|
19
15
|
* @param value A 4-character string
|
|
20
16
|
* @returns A 32-bit integer by encoding the string as little-endian
|
|
17
|
+
*
|
|
18
|
+
* #__NO_SIDE_EFFECTS__
|
|
21
19
|
*/
|
|
22
20
|
export function adbSyncEncodeId(value: string): number {
|
|
23
21
|
const buffer = encodeAsciiUnchecked(value);
|
|
24
22
|
return getUint32LittleEndian(buffer, 0);
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
25
|
+
export const AdbSyncResponseId = {
|
|
26
|
+
Entry: adbSyncEncodeId("DENT"),
|
|
27
|
+
Entry2: adbSyncEncodeId("DNT2"),
|
|
28
|
+
Lstat: adbSyncEncodeId("STAT"),
|
|
29
|
+
Stat: adbSyncEncodeId("STA2"),
|
|
30
|
+
Lstat2: adbSyncEncodeId("LST2"),
|
|
31
|
+
Done: adbSyncEncodeId("DONE"),
|
|
32
|
+
Data: adbSyncEncodeId("DATA"),
|
|
33
|
+
Ok: adbSyncEncodeId("OKAY"),
|
|
34
|
+
Fail: adbSyncEncodeId("FAIL"),
|
|
35
|
+
};
|
|
38
36
|
|
|
39
37
|
export class AdbSyncError extends Error {}
|
|
40
38
|
|
|
41
|
-
export const AdbSyncFailResponse =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
export const AdbSyncFailResponse = struct(
|
|
40
|
+
{ message: string(u32) },
|
|
41
|
+
{
|
|
42
|
+
littleEndian: true,
|
|
43
|
+
postDeserialize(value) {
|
|
44
|
+
throw new AdbSyncError(value.message);
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
);
|
|
47
48
|
|
|
48
49
|
export async function adbSyncReadResponse<T>(
|
|
49
50
|
stream: AsyncExactReadable,
|
|
@@ -68,13 +69,11 @@ export async function adbSyncReadResponse<T>(
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
export async function* adbSyncReadResponses<
|
|
72
|
-
T extends Struct<object, PropertyKey, object, unknown>,
|
|
73
|
-
>(
|
|
72
|
+
export async function* adbSyncReadResponses<T>(
|
|
74
73
|
stream: AsyncExactReadable,
|
|
75
74
|
id: number | string,
|
|
76
|
-
type: T
|
|
77
|
-
): AsyncGenerator<
|
|
75
|
+
type: StructLike<T>,
|
|
76
|
+
): AsyncGenerator<T, void, void> {
|
|
78
77
|
if (typeof id === "string") {
|
|
79
78
|
id = adbSyncEncodeId(id);
|
|
80
79
|
}
|
|
@@ -93,7 +92,7 @@ export async function* adbSyncReadResponses<
|
|
|
93
92
|
await stream.readExactly(type.size);
|
|
94
93
|
return;
|
|
95
94
|
case id:
|
|
96
|
-
yield
|
|
95
|
+
yield await type.deserialize(stream);
|
|
97
96
|
break;
|
|
98
97
|
default:
|
|
99
98
|
throw new Error(
|
|
@@ -35,9 +35,9 @@ export class AdbSyncSocketLocked implements AsyncExactReadable {
|
|
|
35
35
|
this.#combiner = new BufferCombiner(bufferSize);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
#write(buffer: Uint8Array) {
|
|
39
39
|
// `#combiner` will reuse the buffer, so we need to use the Consumable pattern
|
|
40
|
-
|
|
40
|
+
return Consumable.WritableStream.write(this.#writer, buffer);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async flush() {
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { StructValue } from "@yume-chan/struct";
|
|
2
|
+
import { struct, u32, u64 } from "@yume-chan/struct";
|
|
2
3
|
|
|
3
4
|
import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
|
|
4
5
|
import { AdbSyncResponseId, adbSyncReadResponse } from "./response.js";
|
|
5
6
|
import type { AdbSyncSocket } from "./socket.js";
|
|
6
7
|
|
|
7
8
|
// https://github.com/python/cpython/blob/4e581d64b8aff3e2eda99b12f080c877bb78dfca/Lib/stat.py#L36
|
|
8
|
-
export
|
|
9
|
-
Directory
|
|
10
|
-
File
|
|
11
|
-
Link
|
|
12
|
-
}
|
|
9
|
+
export const LinuxFileType = {
|
|
10
|
+
Directory: 0o04,
|
|
11
|
+
File: 0o10,
|
|
12
|
+
Link: 0o12,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type LinuxFileType = (typeof LinuxFileType)[keyof typeof LinuxFileType];
|
|
13
16
|
|
|
14
17
|
export interface AdbSyncStat {
|
|
15
18
|
mode: number;
|
|
@@ -24,79 +27,98 @@ export interface AdbSyncStat {
|
|
|
24
27
|
ctime?: bigint;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export const AdbSyncLstatResponse =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
export const AdbSyncLstatResponse = struct(
|
|
31
|
+
{ mode: u32, size: u32, mtime: u32 },
|
|
32
|
+
{
|
|
33
|
+
littleEndian: true,
|
|
34
|
+
extra: {
|
|
35
|
+
get type(): LinuxFileType {
|
|
36
|
+
return (this.mode >> 12) as LinuxFileType;
|
|
37
|
+
},
|
|
38
|
+
get permission(): number {
|
|
39
|
+
return this.mode & 0b00001111_11111111;
|
|
40
|
+
},
|
|
34
41
|
},
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
postDeserialize(value) {
|
|
43
|
+
if (value.mode === 0 && value.size === 0 && value.mtime === 0) {
|
|
44
|
+
throw new Error("lstat error");
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
37
47
|
},
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (object.mode === 0 && object.size === 0 && object.mtime === 0) {
|
|
41
|
-
throw new Error("lstat error");
|
|
42
|
-
}
|
|
43
|
-
});
|
|
48
|
+
},
|
|
49
|
+
);
|
|
44
50
|
|
|
45
|
-
export type AdbSyncLstatResponse =
|
|
46
|
-
(typeof AdbSyncLstatResponse)["TDeserializeResult"];
|
|
51
|
+
export type AdbSyncLstatResponse = StructValue<typeof AdbSyncLstatResponse>;
|
|
47
52
|
|
|
48
|
-
export
|
|
49
|
-
SUCCESS
|
|
50
|
-
EACCES
|
|
51
|
-
EEXIST
|
|
52
|
-
EFAULT
|
|
53
|
-
EFBIG
|
|
54
|
-
EINTR
|
|
55
|
-
EINVAL
|
|
56
|
-
EIO
|
|
57
|
-
EISDIR
|
|
58
|
-
ELOOP
|
|
59
|
-
EMFILE
|
|
60
|
-
ENAMETOOLONG
|
|
61
|
-
ENFILE
|
|
62
|
-
ENOENT
|
|
63
|
-
ENOMEM
|
|
64
|
-
ENOSPC
|
|
65
|
-
ENOTDIR
|
|
66
|
-
EOVERFLOW
|
|
67
|
-
EPERM
|
|
68
|
-
EROFS
|
|
69
|
-
ETXTBSY
|
|
70
|
-
}
|
|
53
|
+
export const AdbSyncStatErrorCode = {
|
|
54
|
+
SUCCESS: 0,
|
|
55
|
+
EACCES: 13,
|
|
56
|
+
EEXIST: 17,
|
|
57
|
+
EFAULT: 14,
|
|
58
|
+
EFBIG: 27,
|
|
59
|
+
EINTR: 4,
|
|
60
|
+
EINVAL: 22,
|
|
61
|
+
EIO: 5,
|
|
62
|
+
EISDIR: 21,
|
|
63
|
+
ELOOP: 40,
|
|
64
|
+
EMFILE: 24,
|
|
65
|
+
ENAMETOOLONG: 36,
|
|
66
|
+
ENFILE: 23,
|
|
67
|
+
ENOENT: 2,
|
|
68
|
+
ENOMEM: 12,
|
|
69
|
+
ENOSPC: 28,
|
|
70
|
+
ENOTDIR: 20,
|
|
71
|
+
EOVERFLOW: 75,
|
|
72
|
+
EPERM: 1,
|
|
73
|
+
EROFS: 30,
|
|
74
|
+
ETXTBSY: 26,
|
|
75
|
+
} as const;
|
|
71
76
|
|
|
72
|
-
export
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
export type AdbSyncStatErrorCode =
|
|
78
|
+
(typeof AdbSyncStatErrorCode)[keyof typeof AdbSyncStatErrorCode];
|
|
79
|
+
|
|
80
|
+
const AdbSyncStatErrorName = /* #__PURE__ */ (() =>
|
|
81
|
+
Object.fromEntries(
|
|
82
|
+
Object.entries(AdbSyncStatErrorCode).map(([key, value]) => [
|
|
83
|
+
value,
|
|
84
|
+
key,
|
|
85
|
+
]),
|
|
86
|
+
))();
|
|
87
|
+
|
|
88
|
+
export const AdbSyncStatResponse = struct(
|
|
89
|
+
{
|
|
90
|
+
error: u32<AdbSyncStatErrorCode>(),
|
|
91
|
+
dev: u64,
|
|
92
|
+
ino: u64,
|
|
93
|
+
mode: u32,
|
|
94
|
+
nlink: u32,
|
|
95
|
+
uid: u32,
|
|
96
|
+
gid: u32,
|
|
97
|
+
size: u64,
|
|
98
|
+
atime: u64,
|
|
99
|
+
mtime: u64,
|
|
100
|
+
ctime: u64,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
littleEndian: true,
|
|
104
|
+
extra: {
|
|
105
|
+
get type(): LinuxFileType {
|
|
106
|
+
return (this.mode >> 12) as LinuxFileType;
|
|
107
|
+
},
|
|
108
|
+
get permission(): number {
|
|
109
|
+
return this.mode & 0b00001111_11111111;
|
|
110
|
+
},
|
|
87
111
|
},
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
postDeserialize(value) {
|
|
113
|
+
if (value.error) {
|
|
114
|
+
throw new Error(AdbSyncStatErrorName[value.error]);
|
|
115
|
+
}
|
|
116
|
+
return value;
|
|
90
117
|
},
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (object.error) {
|
|
94
|
-
throw new Error(AdbSyncStatErrorCode[object.error]);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
118
|
+
},
|
|
119
|
+
);
|
|
97
120
|
|
|
98
|
-
export type AdbSyncStatResponse =
|
|
99
|
-
(typeof AdbSyncStatResponse)["TDeserializeResult"];
|
|
121
|
+
export type AdbSyncStatResponse = StructValue<typeof AdbSyncStatResponse>;
|
|
100
122
|
|
|
101
123
|
export async function adbSyncLstat(
|
|
102
124
|
socket: AdbSyncSocket,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AutoDisposable } from "@yume-chan/event";
|
|
2
1
|
import type { MaybeConsumable, ReadableStream } from "@yume-chan/stream-extra";
|
|
3
2
|
|
|
4
3
|
import type { Adb, AdbSocket } from "../../adb.js";
|
|
@@ -39,7 +38,7 @@ export interface AdbSyncWriteOptions {
|
|
|
39
38
|
dryRun?: boolean;
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
export class AdbSync
|
|
41
|
+
export class AdbSync {
|
|
43
42
|
protected _adb: Adb;
|
|
44
43
|
protected _socket: AdbSyncSocket;
|
|
45
44
|
|
|
@@ -70,8 +69,6 @@ export class AdbSync extends AutoDisposable {
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
constructor(adb: Adb, socket: AdbSocket) {
|
|
73
|
-
super();
|
|
74
|
-
|
|
75
72
|
this._adb = adb;
|
|
76
73
|
this._socket = new AdbSyncSocket(socket, adb.maxPayloadSize);
|
|
77
74
|
|
|
@@ -117,7 +114,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
117
114
|
try {
|
|
118
115
|
await this.lstat(path + "/");
|
|
119
116
|
return true;
|
|
120
|
-
} catch
|
|
117
|
+
} catch {
|
|
121
118
|
return false;
|
|
122
119
|
}
|
|
123
120
|
}
|
|
@@ -172,8 +169,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
172
169
|
return this._socket.lock();
|
|
173
170
|
}
|
|
174
171
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
await this._socket.close();
|
|
172
|
+
dispose() {
|
|
173
|
+
return this._socket.close();
|
|
178
174
|
}
|
|
179
175
|
}
|
package/src/commands/tcpip.ts
CHANGED
|
@@ -20,14 +20,14 @@ export interface AdbTcpIpListenAddresses {
|
|
|
20
20
|
persistPort: number | undefined;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
|
-
return Number.parseInt(value, 10);
|
|
23
|
+
function parsePort(value: string): number | undefined {
|
|
24
|
+
if (!value || value === "0") {
|
|
25
|
+
return undefined;
|
|
29
26
|
}
|
|
27
|
+
return Number.parseInt(value, 10);
|
|
28
|
+
}
|
|
30
29
|
|
|
30
|
+
export class AdbTcpIpCommand extends AdbCommandBase {
|
|
31
31
|
async getListenAddresses(): Promise<AdbTcpIpListenAddresses> {
|
|
32
32
|
const serviceListenAddresses = await this.adb.getProp(
|
|
33
33
|
"service.adb.listen_addrs",
|
|
@@ -40,8 +40,8 @@ export class AdbTcpIpCommand extends AdbCommandBase {
|
|
|
40
40
|
serviceListenAddresses != ""
|
|
41
41
|
? serviceListenAddresses.split(",")
|
|
42
42
|
: [],
|
|
43
|
-
servicePort:
|
|
44
|
-
persistPort:
|
|
43
|
+
servicePort: parsePort(servicePort),
|
|
44
|
+
persistPort: parsePort(persistPort),
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
package/src/daemon/auth.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
1
2
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
3
|
import type { Disposable } from "@yume-chan/event";
|
|
3
|
-
import
|
|
4
|
-
import { EMPTY_UINT8_ARRAY } from "@yume-chan/struct";
|
|
4
|
+
import { EmptyUint8Array } from "@yume-chan/struct";
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
calculateBase64EncodedLength,
|
|
@@ -33,7 +33,7 @@ export interface AdbCredentialStore {
|
|
|
33
33
|
/**
|
|
34
34
|
* Generates and stores a RSA private key with modulus length `2048` and public exponent `65537`.
|
|
35
35
|
*/
|
|
36
|
-
generateKey():
|
|
36
|
+
generateKey(): MaybePromiseLike<AdbPrivateKey>;
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Synchronously or asynchronously iterates through all stored RSA private keys.
|
|
@@ -43,11 +43,13 @@ export interface AdbCredentialStore {
|
|
|
43
43
|
iterateKeys(): AdbKeyIterable;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export
|
|
47
|
-
Token
|
|
48
|
-
Signature
|
|
49
|
-
PublicKey
|
|
50
|
-
}
|
|
46
|
+
export const AdbAuthType = {
|
|
47
|
+
Token: 1,
|
|
48
|
+
Signature: 2,
|
|
49
|
+
PublicKey: 3,
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
export type AdbAuthType = (typeof AdbAuthType)[keyof typeof AdbAuthType];
|
|
51
53
|
|
|
52
54
|
export interface AdbAuthenticator {
|
|
53
55
|
/**
|
|
@@ -114,7 +116,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
|
114
116
|
|
|
115
117
|
const nameBuffer = privateKey.name?.length
|
|
116
118
|
? encodeUtf8(privateKey.name)
|
|
117
|
-
:
|
|
119
|
+
: EmptyUint8Array;
|
|
118
120
|
const publicKeyBuffer = new Uint8Array(
|
|
119
121
|
publicKeyBase64Length +
|
|
120
122
|
(nameBuffer.length ? nameBuffer.length + 1 : 0) + // Space character + name
|
package/src/daemon/crypto.ts
CHANGED
|
@@ -38,6 +38,8 @@ export function getBigUint(
|
|
|
38
38
|
* @param littleEndian If `false` or `undefined`, a big-endian value should be written,
|
|
39
39
|
* otherwise a little-endian value should be written.
|
|
40
40
|
*/
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/max-params
|
|
41
43
|
export function setBigUint(
|
|
42
44
|
array: Uint8Array,
|
|
43
45
|
byteOffset: number,
|
package/src/daemon/device.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
1
2
|
import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
|
|
2
|
-
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
3
3
|
|
|
4
4
|
import type { AdbPacketData, AdbPacketInit } from "./packet.js";
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ export interface AdbDaemonDevice {
|
|
|
8
8
|
|
|
9
9
|
readonly name: string | undefined;
|
|
10
10
|
|
|
11
|
-
connect():
|
|
11
|
+
connect(): MaybePromiseLike<
|
|
12
12
|
ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
|
|
13
13
|
>;
|
|
14
14
|
}
|
package/src/daemon/dispatcher.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
Consumable,
|
|
17
17
|
WritableStream,
|
|
18
18
|
} from "@yume-chan/stream-extra";
|
|
19
|
-
import {
|
|
19
|
+
import { EmptyUint8Array, decodeUtf8, encodeUtf8 } from "@yume-chan/struct";
|
|
20
20
|
|
|
21
21
|
import type { AdbIncomingSocketHandler, AdbSocket, Closeable } from "../adb.js";
|
|
22
22
|
|
|
@@ -259,7 +259,7 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
259
259
|
AdbCommand.Close,
|
|
260
260
|
packet.arg1,
|
|
261
261
|
packet.arg0,
|
|
262
|
-
|
|
262
|
+
EmptyUint8Array,
|
|
263
263
|
);
|
|
264
264
|
}
|
|
265
265
|
|
|
@@ -271,7 +271,7 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
271
271
|
payload = new Uint8Array(4);
|
|
272
272
|
setUint32LittleEndian(payload, 0, ackBytes);
|
|
273
273
|
} else {
|
|
274
|
-
payload =
|
|
274
|
+
payload = EmptyUint8Array;
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
return this.sendPacket(AdbCommand.Okay, localId, remoteId, payload);
|
|
@@ -312,7 +312,7 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
312
312
|
AdbCommand.Close,
|
|
313
313
|
0,
|
|
314
314
|
remoteId,
|
|
315
|
-
|
|
315
|
+
EmptyUint8Array,
|
|
316
316
|
);
|
|
317
317
|
return;
|
|
318
318
|
}
|
|
@@ -334,12 +334,12 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
334
334
|
remoteId,
|
|
335
335
|
this.options.initialDelayedAckBytes,
|
|
336
336
|
);
|
|
337
|
-
} catch
|
|
337
|
+
} catch {
|
|
338
338
|
await this.sendPacket(
|
|
339
339
|
AdbCommand.Close,
|
|
340
340
|
0,
|
|
341
341
|
remoteId,
|
|
342
|
-
|
|
342
|
+
EmptyUint8Array,
|
|
343
343
|
);
|
|
344
344
|
}
|
|
345
345
|
}
|
package/src/daemon/packet.ts
CHANGED
|
@@ -1,32 +1,43 @@
|
|
|
1
1
|
import { Consumable, TransformStream } from "@yume-chan/stream-extra";
|
|
2
|
-
import
|
|
2
|
+
import type { StructInit, StructValue } from "@yume-chan/struct";
|
|
3
|
+
import { buffer, s32, struct, u32 } from "@yume-chan/struct";
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
Auth
|
|
6
|
-
Close
|
|
7
|
-
Connect
|
|
8
|
-
Okay
|
|
9
|
-
Open
|
|
10
|
-
Write
|
|
11
|
-
}
|
|
5
|
+
export const AdbCommand = {
|
|
6
|
+
Auth: 0x48545541, // 'AUTH'
|
|
7
|
+
Close: 0x45534c43, // 'CLSE'
|
|
8
|
+
Connect: 0x4e584e43, // 'CNXN'
|
|
9
|
+
Okay: 0x59414b4f, // 'OKAY'
|
|
10
|
+
Open: 0x4e45504f, // 'OPEN'
|
|
11
|
+
Write: 0x45545257, // 'WRTE'
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
export type AdbCommand = (typeof AdbCommand)[keyof typeof AdbCommand];
|
|
12
15
|
|
|
13
|
-
export const AdbPacketHeader =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
export const AdbPacketHeader = struct(
|
|
17
|
+
{
|
|
18
|
+
command: u32,
|
|
19
|
+
arg0: u32,
|
|
20
|
+
arg1: u32,
|
|
21
|
+
payloadLength: u32,
|
|
22
|
+
checksum: u32,
|
|
23
|
+
magic: s32,
|
|
24
|
+
},
|
|
25
|
+
{ littleEndian: true },
|
|
26
|
+
);
|
|
20
27
|
|
|
21
|
-
export type AdbPacketHeader =
|
|
28
|
+
export type AdbPacketHeader = StructValue<typeof AdbPacketHeader>;
|
|
22
29
|
|
|
23
|
-
type AdbPacketHeaderInit =
|
|
30
|
+
type AdbPacketHeaderInit = StructInit<typeof AdbPacketHeader>;
|
|
24
31
|
|
|
25
|
-
export const AdbPacket =
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
export const AdbPacket = struct(
|
|
33
|
+
/* #__PURE__ */ (() => ({
|
|
34
|
+
...AdbPacketHeader.fields,
|
|
35
|
+
payload: buffer("payloadLength"),
|
|
36
|
+
}))(),
|
|
37
|
+
{ littleEndian: true },
|
|
38
|
+
);
|
|
28
39
|
|
|
29
|
-
export type AdbPacket =
|
|
40
|
+
export type AdbPacket = StructValue<typeof AdbPacket>;
|
|
30
41
|
|
|
31
42
|
/**
|
|
32
43
|
* `AdbPacketData` contains all the useful fields of `AdbPacket`.
|
|
@@ -39,11 +50,11 @@ export type AdbPacket = (typeof AdbPacket)["TDeserializeResult"];
|
|
|
39
50
|
* so `AdbSocket#writable#write` only needs `AdbPacketData`.
|
|
40
51
|
*/
|
|
41
52
|
export type AdbPacketData = Omit<
|
|
42
|
-
|
|
53
|
+
StructInit<typeof AdbPacket>,
|
|
43
54
|
"checksum" | "magic"
|
|
44
55
|
>;
|
|
45
56
|
|
|
46
|
-
export type AdbPacketInit =
|
|
57
|
+
export type AdbPacketInit = StructInit<typeof AdbPacket>;
|
|
47
58
|
|
|
48
59
|
export function calculateChecksum(payload: Uint8Array): number {
|
|
49
60
|
return payload.reduce((result, item) => result + item, 0);
|
|
@@ -61,9 +72,10 @@ export class AdbPacketSerializeStream extends TransformStream<
|
|
|
61
72
|
const init = chunk as AdbPacketInit & AdbPacketHeaderInit;
|
|
62
73
|
init.payloadLength = init.payload.length;
|
|
63
74
|
|
|
75
|
+
AdbPacketHeader.serialize(init, headerBuffer);
|
|
64
76
|
await Consumable.ReadableStream.enqueue(
|
|
65
77
|
controller,
|
|
66
|
-
|
|
78
|
+
headerBuffer,
|
|
67
79
|
);
|
|
68
80
|
|
|
69
81
|
if (init.payloadLength) {
|
package/src/daemon/socket.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
WritableStreamDefaultController,
|
|
8
8
|
} from "@yume-chan/stream-extra";
|
|
9
9
|
import { MaybeConsumable, PushReadableStream } from "@yume-chan/stream-extra";
|
|
10
|
-
import {
|
|
10
|
+
import { EmptyUint8Array } from "@yume-chan/struct";
|
|
11
11
|
|
|
12
12
|
import type { AdbSocket } from "../adb.js";
|
|
13
13
|
|
|
@@ -138,20 +138,7 @@ export class AdbDaemonSocketController
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
async enqueue(data: Uint8Array) {
|
|
141
|
-
|
|
142
|
-
// Throw away the data if that happens.
|
|
143
|
-
if (this.#readableController.abortSignal.aborted) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
await this.#readableController.enqueue(data);
|
|
149
|
-
} catch (e) {
|
|
150
|
-
if (this.#readableController.abortSignal.aborted) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
throw e;
|
|
154
|
-
}
|
|
141
|
+
await this.#readableController.enqueue(data);
|
|
155
142
|
}
|
|
156
143
|
|
|
157
144
|
public ack(bytes: number) {
|
|
@@ -177,28 +164,18 @@ export class AdbDaemonSocketController
|
|
|
177
164
|
AdbCommand.Close,
|
|
178
165
|
this.localId,
|
|
179
166
|
this.remoteId,
|
|
180
|
-
|
|
167
|
+
EmptyUint8Array,
|
|
181
168
|
);
|
|
182
169
|
}
|
|
183
170
|
|
|
184
171
|
dispose() {
|
|
185
|
-
|
|
186
|
-
this.#readableController.close();
|
|
187
|
-
} catch {
|
|
188
|
-
// ignore
|
|
189
|
-
}
|
|
190
|
-
|
|
172
|
+
this.#readableController.close();
|
|
191
173
|
this.#closedPromise.resolve();
|
|
192
174
|
}
|
|
193
175
|
}
|
|
194
176
|
|
|
195
177
|
/**
|
|
196
178
|
* A duplex stream representing a socket to ADB daemon.
|
|
197
|
-
*
|
|
198
|
-
* To close it, call either `socket.close()`,
|
|
199
|
-
* `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
|
|
200
|
-
* `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
|
|
201
|
-
* `socket.writable.close()` or `socket.writable.getWriter().close()`.
|
|
202
179
|
*/
|
|
203
180
|
export class AdbDaemonSocket implements AdbDaemonSocketInfo, AdbSocket {
|
|
204
181
|
#controller: AdbDaemonSocketController;
|