@yume-chan/adb 0.0.21 → 0.0.23
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 +39 -0
- package/CHANGELOG.md +20 -1
- package/README.md +46 -366
- package/esm/adb.d.ts +9 -5
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +9 -2
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js +1 -0
- package/esm/banner.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +1 -1
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/reverse.js +1 -1
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +2 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +11 -14
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +21 -71
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/utils.js +1 -1
- package/esm/commands/subprocess/utils.js.map +1 -1
- package/esm/commands/sync/list.d.ts +2 -1
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +2 -2
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +4 -0
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +1 -1
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +1 -1
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +1 -0
- package/esm/commands/sync/socket.d.ts.map +1 -1
- package/esm/commands/sync/socket.js +4 -0
- package/esm/commands/sync/socket.js.map +1 -1
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +5 -6
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +21 -0
- package/esm/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +18 -0
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/dispatcher.d.ts +9 -1
- package/esm/daemon/dispatcher.d.ts.map +1 -1
- package/esm/daemon/dispatcher.js +107 -51
- package/esm/daemon/dispatcher.js.map +1 -1
- package/esm/daemon/packet.d.ts +5 -5
- package/esm/daemon/packet.d.ts.map +1 -1
- package/esm/daemon/packet.js +1 -1
- package/esm/daemon/packet.js.map +1 -1
- package/esm/daemon/socket.d.ts +8 -13
- package/esm/daemon/socket.d.ts.map +1 -1
- package/esm/daemon/socket.js +80 -44
- package/esm/daemon/socket.js.map +1 -1
- package/esm/daemon/transport.d.ts +32 -4
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js +61 -31
- package/esm/daemon/transport.js.map +1 -1
- package/esm/features.d.ts +2 -1
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +2 -1
- package/esm/features.js.map +1 -1
- package/esm/server/client.d.ts +14 -8
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +122 -70
- package/esm/server/client.js.map +1 -1
- package/esm/server/transport.d.ts +3 -0
- package/esm/server/transport.d.ts.map +1 -1
- package/esm/server/transport.js +26 -0
- package/esm/server/transport.js.map +1 -1
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/conditional-variable.js.map +1 -1
- package/esm/utils/hex.js.map +1 -1
- package/package.json +14 -14
- package/src/adb.ts +22 -7
- package/src/banner.ts +1 -0
- package/src/commands/framebuffer.ts +1 -1
- package/src/commands/reverse.ts +2 -2
- package/src/commands/subprocess/protocols/none.ts +15 -19
- package/src/commands/subprocess/protocols/shell.ts +28 -98
- package/src/commands/subprocess/utils.ts +1 -1
- package/src/commands/sync/list.ts +6 -2
- package/src/commands/sync/pull.ts +3 -0
- package/src/commands/sync/response.ts +2 -2
- package/src/commands/sync/socket.ts +5 -0
- package/src/commands/sync/sync.ts +5 -6
- package/src/commands/tcpip.ts +44 -0
- package/src/daemon/dispatcher.ts +156 -65
- package/src/daemon/packet.ts +1 -1
- package/src/daemon/socket.ts +104 -86
- package/src/daemon/transport.ts +104 -38
- package/src/features.ts +2 -1
- package/src/server/client.ts +141 -91
- package/src/server/transport.ts +28 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/esm/daemon/socket.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
-
import { ConsumableWritableStream,
|
|
2
|
+
import { ConsumableWritableStream, PushReadableStream, } from "@yume-chan/stream-extra";
|
|
3
3
|
import { AdbCommand } from "./packet.js";
|
|
4
4
|
export class AdbDaemonSocketController {
|
|
5
5
|
#dispatcher;
|
|
@@ -7,82 +7,118 @@ export class AdbDaemonSocketController {
|
|
|
7
7
|
remoteId;
|
|
8
8
|
localCreated;
|
|
9
9
|
service;
|
|
10
|
-
#duplex;
|
|
11
10
|
#readable;
|
|
12
11
|
#readableController;
|
|
13
12
|
get readable() {
|
|
14
13
|
return this.#readable;
|
|
15
14
|
}
|
|
16
|
-
#
|
|
15
|
+
#writableController;
|
|
17
16
|
writable;
|
|
18
17
|
#closed = false;
|
|
19
|
-
|
|
20
|
-
* Whether the socket is half-closed (i.e. the local side initiated the close).
|
|
21
|
-
*
|
|
22
|
-
* It's only used by dispatcher to avoid sending another `CLSE` packet to remote.
|
|
23
|
-
*/
|
|
18
|
+
#closedPromise = new PromiseResolver();
|
|
24
19
|
get closed() {
|
|
25
|
-
return this.#
|
|
20
|
+
return this.#closedPromise.promise;
|
|
26
21
|
}
|
|
27
22
|
#socket;
|
|
28
23
|
get socket() {
|
|
29
24
|
return this.#socket;
|
|
30
25
|
}
|
|
26
|
+
#availableWriteBytesChanged;
|
|
27
|
+
/**
|
|
28
|
+
* When delayed ack is disabled, can be `Infinity` if the socket is ready to write.
|
|
29
|
+
* Exactly one packet can be written no matter how large it is. Or `-1` if the socket
|
|
30
|
+
* is waiting for ack.
|
|
31
|
+
*
|
|
32
|
+
* When delayed ack is enabled, a non-negative finite number indicates the number of
|
|
33
|
+
* bytes that can be written to the socket before receiving an ack.
|
|
34
|
+
*/
|
|
35
|
+
#availableWriteBytes = 0;
|
|
31
36
|
constructor(options) {
|
|
32
37
|
this.#dispatcher = options.dispatcher;
|
|
33
38
|
this.localId = options.localId;
|
|
34
39
|
this.remoteId = options.remoteId;
|
|
35
40
|
this.localCreated = options.localCreated;
|
|
36
41
|
this.service = options.service;
|
|
37
|
-
|
|
38
|
-
// cspell: disable-next-line
|
|
39
|
-
// https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
|
|
40
|
-
this.#duplex = new DuplexStreamFactory({
|
|
41
|
-
close: async () => {
|
|
42
|
-
this.#closed = true;
|
|
43
|
-
await this.#dispatcher.sendPacket(AdbCommand.Close, this.localId, this.remoteId);
|
|
44
|
-
// Don't `dispose` here, we need to wait for `CLSE` response packet.
|
|
45
|
-
return false;
|
|
46
|
-
},
|
|
47
|
-
dispose: () => {
|
|
48
|
-
// Error out the pending writes
|
|
49
|
-
this.#writePromise?.reject(new Error("Socket closed"));
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
this.#readable = this.#duplex.wrapReadable(new PushReadableStream((controller) => {
|
|
42
|
+
this.#readable = new PushReadableStream((controller) => {
|
|
53
43
|
this.#readableController = controller;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
});
|
|
45
|
+
this.writable = new ConsumableWritableStream({
|
|
46
|
+
start: (controller) => {
|
|
47
|
+
this.#writableController = controller;
|
|
58
48
|
},
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
49
|
+
write: async (data, controller) => {
|
|
50
|
+
const size = data.length;
|
|
51
|
+
const chunkSize = this.#dispatcher.options.maxPayloadSize;
|
|
52
|
+
for (let start = 0, end = chunkSize; start < size; start = end, end += chunkSize) {
|
|
53
|
+
const chunk = data.subarray(start, end);
|
|
54
|
+
await this.#writeChunk(chunk, controller.signal);
|
|
55
|
+
}
|
|
66
56
|
},
|
|
67
|
-
})
|
|
57
|
+
});
|
|
68
58
|
this.#socket = new AdbDaemonSocket(this);
|
|
69
59
|
}
|
|
60
|
+
async #writeChunk(data, signal) {
|
|
61
|
+
const length = data.byteLength;
|
|
62
|
+
while (this.#availableWriteBytes < length) {
|
|
63
|
+
// Only one lock is required because Web Streams API guarantees
|
|
64
|
+
// that `write` is not reentrant.
|
|
65
|
+
const resolver = new PromiseResolver();
|
|
66
|
+
signal.addEventListener("abort", () => {
|
|
67
|
+
resolver.reject(signal.reason);
|
|
68
|
+
});
|
|
69
|
+
this.#availableWriteBytesChanged = resolver;
|
|
70
|
+
await resolver.promise;
|
|
71
|
+
}
|
|
72
|
+
if (this.#availableWriteBytes === Infinity) {
|
|
73
|
+
this.#availableWriteBytes = -1;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.#availableWriteBytes -= length;
|
|
77
|
+
}
|
|
78
|
+
await this.#dispatcher.sendPacket(AdbCommand.Write, this.localId, this.remoteId, data);
|
|
79
|
+
}
|
|
70
80
|
async enqueue(data) {
|
|
71
|
-
//
|
|
72
|
-
//
|
|
81
|
+
// Consumers can `cancel` the `readable` if they are not interested in future data.
|
|
82
|
+
// Throw away the data if that happens.
|
|
73
83
|
if (this.#readableController.abortSignal.aborted) {
|
|
74
84
|
return;
|
|
75
85
|
}
|
|
76
|
-
|
|
86
|
+
try {
|
|
87
|
+
await this.#readableController.enqueue(data);
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
if (this.#readableController.abortSignal.aborted) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
throw e;
|
|
94
|
+
}
|
|
77
95
|
}
|
|
78
|
-
ack() {
|
|
79
|
-
this.#
|
|
96
|
+
ack(bytes) {
|
|
97
|
+
this.#availableWriteBytes += bytes;
|
|
98
|
+
this.#availableWriteBytesChanged?.resolve();
|
|
80
99
|
}
|
|
81
100
|
async close() {
|
|
82
|
-
|
|
101
|
+
if (this.#closed) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
this.#closed = true;
|
|
105
|
+
this.#availableWriteBytesChanged?.reject(new Error("Socket closed"));
|
|
106
|
+
try {
|
|
107
|
+
this.#writableController.error(new Error("Socket closed"));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// ignore
|
|
111
|
+
}
|
|
112
|
+
await this.#dispatcher.sendPacket(AdbCommand.Close, this.localId, this.remoteId);
|
|
83
113
|
}
|
|
84
114
|
dispose() {
|
|
85
|
-
|
|
115
|
+
try {
|
|
116
|
+
this.#readableController.close();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// ignore
|
|
120
|
+
}
|
|
121
|
+
this.#closedPromise.resolve();
|
|
86
122
|
}
|
|
87
123
|
}
|
|
88
124
|
/**
|
package/esm/daemon/socket.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/daemon/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/daemon/socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,29 +2,55 @@ import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
|
|
|
2
2
|
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
3
3
|
import type { AdbIncomingSocketHandler, AdbSocket, AdbTransport } from "../adb.js";
|
|
4
4
|
import { AdbBanner } from "../banner.js";
|
|
5
|
+
import { AdbFeature } from "../features.js";
|
|
5
6
|
import type { AdbAuthenticator, AdbCredentialStore } from "./auth.js";
|
|
6
7
|
import type { AdbPacketData, AdbPacketInit } from "./packet.js";
|
|
7
8
|
export declare const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 16777217;
|
|
9
|
+
export declare const ADB_DAEMON_DEFAULT_FEATURES: AdbFeature[];
|
|
10
|
+
export declare const ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE: number;
|
|
11
|
+
export type AdbDaemonConnection = ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>;
|
|
8
12
|
interface AdbDaemonAuthenticationOptions {
|
|
9
13
|
serial: string;
|
|
10
|
-
connection:
|
|
14
|
+
connection: AdbDaemonConnection;
|
|
11
15
|
credentialStore: AdbCredentialStore;
|
|
12
16
|
authenticators?: AdbAuthenticator[];
|
|
17
|
+
features?: readonly AdbFeature[];
|
|
18
|
+
/**
|
|
19
|
+
* The number of bytes the device can send before receiving an ack packet.
|
|
20
|
+
*
|
|
21
|
+
* Set to 0 or any negative value to disable delayed ack in handshake.
|
|
22
|
+
* Otherwise the value must be in the range of unsigned 32-bit integer.
|
|
23
|
+
*
|
|
24
|
+
* Delayed ack requires Android 14, this option is ignored on older versions.
|
|
25
|
+
*/
|
|
26
|
+
initialDelayedAckBytes?: number;
|
|
13
27
|
/**
|
|
14
28
|
* Whether to preserve the connection open after the `AdbDaemonTransport` is closed.
|
|
15
29
|
*/
|
|
16
30
|
preserveConnection?: boolean | undefined;
|
|
31
|
+
debugSlowRead?: boolean | undefined;
|
|
17
32
|
}
|
|
18
33
|
interface AdbDaemonSocketConnectorConstructionOptions {
|
|
19
34
|
serial: string;
|
|
20
|
-
connection:
|
|
35
|
+
connection: AdbDaemonConnection;
|
|
21
36
|
version: number;
|
|
22
37
|
maxPayloadSize: number;
|
|
23
38
|
banner: string;
|
|
39
|
+
features?: readonly AdbFeature[];
|
|
40
|
+
/**
|
|
41
|
+
* The number of bytes the device can send before receiving an ack packet.
|
|
42
|
+
*
|
|
43
|
+
* Set to 0 or any negative value to disable delayed ack in handshake.
|
|
44
|
+
* Otherwise the value must be in the range of unsigned 32-bit integer.
|
|
45
|
+
*
|
|
46
|
+
* Delayed ack requires Android 14, this option is ignored on older versions.
|
|
47
|
+
*/
|
|
48
|
+
initialDelayedAckBytes?: number;
|
|
24
49
|
/**
|
|
25
50
|
* Whether to preserve the connection open after the `AdbDaemonTransport` is closed.
|
|
26
51
|
*/
|
|
27
52
|
preserveConnection?: boolean | undefined;
|
|
53
|
+
debugSlowRead?: boolean | undefined;
|
|
28
54
|
}
|
|
29
55
|
export declare class AdbDaemonTransport implements AdbTransport {
|
|
30
56
|
#private;
|
|
@@ -36,13 +62,15 @@ export declare class AdbDaemonTransport implements AdbTransport {
|
|
|
36
62
|
* on the same connection. Because every time the device receives a `CNXN` packet,
|
|
37
63
|
* it resets all internal state, and starts a new authentication process.
|
|
38
64
|
*/
|
|
39
|
-
static authenticate({ serial, connection, credentialStore, authenticators,
|
|
65
|
+
static authenticate({ serial, connection, credentialStore, authenticators, features, initialDelayedAckBytes, ...options }: AdbDaemonAuthenticationOptions): Promise<AdbDaemonTransport>;
|
|
66
|
+
get connection(): AdbDaemonConnection;
|
|
40
67
|
get serial(): string;
|
|
41
68
|
get protocolVersion(): number;
|
|
42
69
|
get maxPayloadSize(): number;
|
|
43
70
|
get banner(): AdbBanner;
|
|
44
71
|
get disconnected(): Promise<void>;
|
|
45
|
-
|
|
72
|
+
get clientFeatures(): readonly AdbFeature[];
|
|
73
|
+
constructor({ serial, connection, version, banner, features, initialDelayedAckBytes, ...options }: AdbDaemonSocketConnectorConstructionOptions);
|
|
46
74
|
connect(service: string): ValueOrPromise<AdbSocket>;
|
|
47
75
|
addReverseTunnel(handler: AdbIncomingSocketHandler, address?: string): string;
|
|
48
76
|
removeReverseTunnel(address: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/daemon/transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAMhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EACR,wBAAwB,EACxB,SAAS,EACT,YAAY,EACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/daemon/transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAMhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EACR,wBAAwB,EACxB,SAAS,EACT,YAAY,EACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAMtE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGhE,eAAO,MAAM,gCAAgC,WAAa,CAAC;AAG3D,eAAO,MAAM,2BAA2B,cAoBvB,CAAC;AAClB,eAAO,MAAM,uCAAuC,QAAmB,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAClD,aAAa,EACb,UAAU,CAAC,aAAa,CAAC,CAC5B,CAAC;AAEF,UAAU,8BAA8B;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,mBAAmB,CAAC;IAChC,eAAe,EAAE,kBAAkB,CAAC;IACpC,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACjC;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvC;AAED,UAAU,2CAA2C;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,mBAAmB,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACjC;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvC;AAED,qBAAa,kBAAmB,YAAW,YAAY;;IACnD;;;;;;;OAOG;WACU,YAAY,CAAC,EACtB,MAAM,EACN,UAAU,EACV,eAAe,EACf,cAA2C,EAC3C,QAAsC,EACtC,sBAAgE,EAChE,GAAG,OAAO,EACb,EAAE,8BAA8B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAqH/D,IAAI,UAAU,wBAEb;IAKD,IAAI,MAAM,WAET;IAGD,IAAI,eAAe,WAElB;IAED,IAAI,cAAc,WAEjB;IAGD,IAAI,MAAM,cAET;IAED,IAAI,YAAY,kBAEf;IAGD,IAAI,cAAc,0BAEjB;gBAEW,EACR,MAAM,EACN,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsC,EACtC,sBAAgE,EAChE,GAAG,OAAO,EACb,EAAE,2CAA2C;IAwC9C,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC;IAInD,gBAAgB,CACZ,OAAO,EAAE,wBAAwB,EACjC,OAAO,CAAC,EAAE,MAAM,GACjB,MAAM;IAST,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1C,mBAAmB,IAAI,IAAI;IAI3B,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC;CAGhC"}
|
package/esm/daemon/transport.js
CHANGED
|
@@ -7,6 +7,30 @@ import { ADB_DEFAULT_AUTHENTICATORS, AdbAuthenticationProcessor, } from "./auth.
|
|
|
7
7
|
import { AdbPacketDispatcher } from "./dispatcher.js";
|
|
8
8
|
import { AdbCommand, calculateChecksum } from "./packet.js";
|
|
9
9
|
export const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 0x01000001;
|
|
10
|
+
// https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
|
|
11
|
+
// There are some other feature constants, but some of them are only used by ADB server, not devices (daemons).
|
|
12
|
+
export const ADB_DAEMON_DEFAULT_FEATURES = [
|
|
13
|
+
AdbFeature.ShellV2,
|
|
14
|
+
AdbFeature.Cmd,
|
|
15
|
+
AdbFeature.StatV2,
|
|
16
|
+
AdbFeature.ListV2,
|
|
17
|
+
AdbFeature.FixedPushMkdir,
|
|
18
|
+
"apex",
|
|
19
|
+
AdbFeature.Abb,
|
|
20
|
+
// only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
|
|
21
|
+
// No special handling required.
|
|
22
|
+
"fixed_push_symlink_timestamp",
|
|
23
|
+
AdbFeature.AbbExec,
|
|
24
|
+
"remount_shell",
|
|
25
|
+
"track_app",
|
|
26
|
+
AdbFeature.SendReceiveV2,
|
|
27
|
+
"sendrecv_v2_brotli",
|
|
28
|
+
"sendrecv_v2_lz4",
|
|
29
|
+
"sendrecv_v2_zstd",
|
|
30
|
+
"sendrecv_v2_dry_run_send",
|
|
31
|
+
AdbFeature.DelayedAck,
|
|
32
|
+
];
|
|
33
|
+
export const ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE = 32 * 1024 * 1024;
|
|
10
34
|
export class AdbDaemonTransport {
|
|
11
35
|
/**
|
|
12
36
|
* Authenticates the connection and creates an `AdbDaemonTransport` instance
|
|
@@ -16,7 +40,7 @@ export class AdbDaemonTransport {
|
|
|
16
40
|
* on the same connection. Because every time the device receives a `CNXN` packet,
|
|
17
41
|
* it resets all internal state, and starts a new authentication process.
|
|
18
42
|
*/
|
|
19
|
-
static async authenticate({ serial, connection, credentialStore, authenticators = ADB_DEFAULT_AUTHENTICATORS,
|
|
43
|
+
static async authenticate({ serial, connection, credentialStore, authenticators = ADB_DEFAULT_AUTHENTICATORS, features = ADB_DAEMON_DEFAULT_FEATURES, initialDelayedAckBytes = ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE, ...options }) {
|
|
20
44
|
// Initially, set to highest-supported version and payload size.
|
|
21
45
|
let version = 0x01000001;
|
|
22
46
|
// Android 4: 4K, Android 7: 256K, Android 9: 1M
|
|
@@ -69,37 +93,22 @@ export class AdbDaemonTransport {
|
|
|
69
93
|
init.magic = init.command ^ 0xffffffff;
|
|
70
94
|
await ConsumableWritableStream.write(writer, init);
|
|
71
95
|
}
|
|
96
|
+
const actualFeatures = features.slice();
|
|
97
|
+
if (initialDelayedAckBytes <= 0) {
|
|
98
|
+
const index = features.indexOf(AdbFeature.DelayedAck);
|
|
99
|
+
if (index !== -1) {
|
|
100
|
+
actualFeatures.splice(index, 1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
72
103
|
let banner;
|
|
73
104
|
try {
|
|
74
|
-
// https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
|
|
75
|
-
// There are some other feature constants, but some of them are only used by ADB server, not devices (daemons).
|
|
76
|
-
const features = [
|
|
77
|
-
AdbFeature.ShellV2,
|
|
78
|
-
AdbFeature.Cmd,
|
|
79
|
-
AdbFeature.StatV2,
|
|
80
|
-
AdbFeature.ListV2,
|
|
81
|
-
AdbFeature.FixedPushMkdir,
|
|
82
|
-
"apex",
|
|
83
|
-
AdbFeature.Abb,
|
|
84
|
-
// only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
|
|
85
|
-
// No special handling required.
|
|
86
|
-
"fixed_push_symlink_timestamp",
|
|
87
|
-
AdbFeature.AbbExec,
|
|
88
|
-
"remount_shell",
|
|
89
|
-
"track_app",
|
|
90
|
-
AdbFeature.SendReceiveV2,
|
|
91
|
-
"sendrecv_v2_brotli",
|
|
92
|
-
"sendrecv_v2_lz4",
|
|
93
|
-
"sendrecv_v2_zstd",
|
|
94
|
-
"sendrecv_v2_dry_run_send",
|
|
95
|
-
].join(",");
|
|
96
105
|
await sendPacket({
|
|
97
106
|
command: AdbCommand.Connect,
|
|
98
107
|
arg0: version,
|
|
99
108
|
arg1: maxPayloadSize,
|
|
100
109
|
// The terminating `;` is required in formal definition
|
|
101
110
|
// But ADB daemon (all versions) can still work without it
|
|
102
|
-
payload: encodeUtf8(`host::features=${
|
|
111
|
+
payload: encodeUtf8(`host::features=${actualFeatures.join(",")}`),
|
|
103
112
|
});
|
|
104
113
|
banner = await resolver.promise;
|
|
105
114
|
}
|
|
@@ -117,9 +126,15 @@ export class AdbDaemonTransport {
|
|
|
117
126
|
version,
|
|
118
127
|
maxPayloadSize,
|
|
119
128
|
banner,
|
|
120
|
-
|
|
129
|
+
features: actualFeatures,
|
|
130
|
+
initialDelayedAckBytes,
|
|
131
|
+
...options,
|
|
121
132
|
});
|
|
122
133
|
}
|
|
134
|
+
#connection;
|
|
135
|
+
get connection() {
|
|
136
|
+
return this.#connection;
|
|
137
|
+
}
|
|
123
138
|
#dispatcher;
|
|
124
139
|
#serial;
|
|
125
140
|
get serial() {
|
|
@@ -129,9 +144,8 @@ export class AdbDaemonTransport {
|
|
|
129
144
|
get protocolVersion() {
|
|
130
145
|
return this.#protocolVersion;
|
|
131
146
|
}
|
|
132
|
-
#maxPayloadSize;
|
|
133
147
|
get maxPayloadSize() {
|
|
134
|
-
return this.#maxPayloadSize;
|
|
148
|
+
return this.#dispatcher.options.maxPayloadSize;
|
|
135
149
|
}
|
|
136
150
|
#banner;
|
|
137
151
|
get banner() {
|
|
@@ -140,9 +154,26 @@ export class AdbDaemonTransport {
|
|
|
140
154
|
get disconnected() {
|
|
141
155
|
return this.#dispatcher.disconnected;
|
|
142
156
|
}
|
|
143
|
-
|
|
157
|
+
#clientFeatures;
|
|
158
|
+
get clientFeatures() {
|
|
159
|
+
return this.#clientFeatures;
|
|
160
|
+
}
|
|
161
|
+
constructor({ serial, connection, version, banner, features = ADB_DAEMON_DEFAULT_FEATURES, initialDelayedAckBytes = ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE, ...options }) {
|
|
144
162
|
this.#serial = serial;
|
|
163
|
+
this.#connection = connection;
|
|
145
164
|
this.#banner = AdbBanner.parse(banner);
|
|
165
|
+
this.#clientFeatures = features;
|
|
166
|
+
if (features.includes(AdbFeature.DelayedAck)) {
|
|
167
|
+
if (initialDelayedAckBytes <= 0) {
|
|
168
|
+
throw new Error("`initialDelayedAckBytes` must be greater than 0 when DelayedAck feature is enabled.");
|
|
169
|
+
}
|
|
170
|
+
if (!this.#banner.features.includes(AdbFeature.DelayedAck)) {
|
|
171
|
+
initialDelayedAckBytes = 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
initialDelayedAckBytes = 0;
|
|
176
|
+
}
|
|
146
177
|
let calculateChecksum;
|
|
147
178
|
let appendNullToServiceString;
|
|
148
179
|
if (version >= ADB_DAEMON_VERSION_OMIT_CHECKSUM) {
|
|
@@ -156,11 +187,10 @@ export class AdbDaemonTransport {
|
|
|
156
187
|
this.#dispatcher = new AdbPacketDispatcher(connection, {
|
|
157
188
|
calculateChecksum,
|
|
158
189
|
appendNullToServiceString,
|
|
159
|
-
|
|
160
|
-
|
|
190
|
+
initialDelayedAckBytes,
|
|
191
|
+
...options,
|
|
161
192
|
});
|
|
162
193
|
this.#protocolVersion = version;
|
|
163
|
-
this.#maxPayloadSize = maxPayloadSize;
|
|
164
194
|
}
|
|
165
195
|
connect(service) {
|
|
166
196
|
return this.#dispatcher.createSocket(service);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/daemon/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EACH,eAAe,EACf,wBAAwB,EACxB,cAAc,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAO3D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EACH,0BAA0B,EAC1B,0BAA0B,GAC7B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,CAAC,MAAM,gCAAgC,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/daemon/transport.ts"],"names":[],"mappings":"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"}
|
package/esm/features.d.ts
CHANGED
package/esm/features.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAEA,oBAAY,UAAU;IAClB,OAAO,aAAa;IACpB,GAAG,QAAQ;IACX,MAAM,YAAY;IAClB,MAAM,UAAU;IAChB,cAAc,qBAAqB;IACnC,GAAG,QAAQ;IACX,OAAO,aAAa;IACpB,aAAa,gBAAgB;
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAEA,oBAAY,UAAU;IAClB,OAAO,aAAa;IACpB,GAAG,QAAQ;IACX,MAAM,YAAY;IAClB,MAAM,UAAU;IAChB,cAAc,qBAAqB;IACnC,GAAG,QAAQ;IACX,OAAO,aAAa;IACpB,aAAa,gBAAgB;IAC7B,UAAU,gBAAgB;CAC7B"}
|
package/esm/features.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// The order follows
|
|
2
|
-
// https://android.
|
|
2
|
+
// https://cs.android.com/android/platform/superproject/+/master:packages/modules/adb/transport.cpp;l=77;drc=6d14d35d0241f6fee145f8e54ffd77252e8d29fd
|
|
3
3
|
export var AdbFeature;
|
|
4
4
|
(function (AdbFeature) {
|
|
5
5
|
AdbFeature["ShellV2"] = "shell_v2";
|
|
@@ -10,5 +10,6 @@ export var AdbFeature;
|
|
|
10
10
|
AdbFeature["Abb"] = "abb";
|
|
11
11
|
AdbFeature["AbbExec"] = "abb_exec";
|
|
12
12
|
AdbFeature["SendReceiveV2"] = "sendrecv_v2";
|
|
13
|
+
AdbFeature["DelayedAck"] = "delayed_ack";
|
|
13
14
|
})(AdbFeature || (AdbFeature = {}));
|
|
14
15
|
//# sourceMappingURL=features.js.map
|
package/esm/features.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features.js","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB
|
|
1
|
+
{"version":3,"file":"features.js","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,qJAAqJ;AACrJ,MAAM,CAAN,IAAY,UAUX;AAVD,WAAY,UAAU;IAClB,kCAAoB,CAAA;IACpB,yBAAW,CAAA;IACX,gCAAkB,CAAA;IAClB,8BAAgB,CAAA;IAChB,iDAAmC,CAAA;IACnC,yBAAW,CAAA;IACX,kCAAoB,CAAA;IACpB,2CAA6B,CAAA;IAC7B,wCAA0B,CAAA;AAC9B,CAAC,EAVW,UAAU,KAAV,UAAU,QAUrB"}
|
package/esm/server/client.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { AbortSignal, ReadableWritablePair, WritableStreamDefaultWriter } from "@yume-chan/stream-extra";
|
|
2
2
|
import type { AsyncExactReadable, ExactReadable, ValueOrPromise } from "@yume-chan/struct";
|
|
3
|
-
import type { AdbIncomingSocketHandler, AdbSocket } from "../adb.js";
|
|
3
|
+
import type { AdbIncomingSocketHandler, AdbSocket, Closeable } from "../adb.js";
|
|
4
4
|
import type { AdbFeature } from "../features.js";
|
|
5
5
|
import { AdbServerTransport } from "./transport.js";
|
|
6
6
|
export interface AdbServerConnectionOptions {
|
|
7
7
|
unref?: boolean | undefined;
|
|
8
8
|
signal?: AbortSignal | undefined;
|
|
9
9
|
}
|
|
10
|
-
export interface AdbServerConnection {
|
|
11
|
-
|
|
10
|
+
export interface AdbServerConnection extends ReadableWritablePair<Uint8Array, Uint8Array>, Closeable {
|
|
11
|
+
get closed(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface AdbServerConnector {
|
|
14
|
+
connect(options?: AdbServerConnectionOptions): ValueOrPromise<AdbServerConnection>;
|
|
12
15
|
addReverseTunnel(handler: AdbIncomingSocketHandler, address?: string): ValueOrPromise<string>;
|
|
13
16
|
removeReverseTunnel(address: string): ValueOrPromise<void>;
|
|
14
17
|
clearReverseTunnels(): ValueOrPromise<void>;
|
|
@@ -17,9 +20,9 @@ export interface AdbServerSocket extends AdbSocket {
|
|
|
17
20
|
transportId: bigint;
|
|
18
21
|
}
|
|
19
22
|
export type AdbServerDeviceSelector = {
|
|
20
|
-
serial: string;
|
|
21
|
-
} | {
|
|
22
23
|
transportId: bigint;
|
|
24
|
+
} | {
|
|
25
|
+
serial: string;
|
|
23
26
|
} | {
|
|
24
27
|
usb: true;
|
|
25
28
|
} | {
|
|
@@ -34,18 +37,20 @@ export interface AdbServerDevice {
|
|
|
34
37
|
}
|
|
35
38
|
export declare class AdbServerClient {
|
|
36
39
|
static readonly VERSION = 41;
|
|
37
|
-
readonly connection:
|
|
38
|
-
constructor(connection:
|
|
40
|
+
readonly connection: AdbServerConnector;
|
|
41
|
+
constructor(connection: AdbServerConnector);
|
|
39
42
|
static readString(stream: ExactReadable): string;
|
|
40
43
|
static readString(stream: AsyncExactReadable): PromiseLike<string>;
|
|
41
44
|
static writeString(writer: WritableStreamDefaultWriter<Uint8Array>, value: string): Promise<void>;
|
|
42
45
|
static readOkay(stream: ExactReadable | AsyncExactReadable): Promise<void>;
|
|
43
|
-
connect(request: string, options?: AdbServerConnectionOptions): Promise<
|
|
46
|
+
connect(request: string, options?: AdbServerConnectionOptions): Promise<AdbServerConnection>;
|
|
44
47
|
getVersion(): Promise<number>;
|
|
45
48
|
validateVersion(): Promise<void>;
|
|
46
49
|
killServer(): Promise<void>;
|
|
47
50
|
getServerFeatures(): Promise<AdbFeature[]>;
|
|
51
|
+
parseDeviceList(value: string): AdbServerDevice[];
|
|
48
52
|
getDevices(): Promise<AdbServerDevice[]>;
|
|
53
|
+
trackDevices(callback: (devices: AdbServerDevice[]) => void): Promise<() => void>;
|
|
49
54
|
formatDeviceService(device: AdbServerDeviceSelector, command: string): string;
|
|
50
55
|
/**
|
|
51
56
|
* Gets the features supported by the device.
|
|
@@ -75,4 +80,5 @@ export declare class AdbServerClient {
|
|
|
75
80
|
waitFor(device: AdbServerDeviceSelector, state: "device" | "disconnect", options?: AdbServerConnectionOptions): Promise<void>;
|
|
76
81
|
createTransport(device: AdbServerDeviceSelector): Promise<AdbServerTransport>;
|
|
77
82
|
}
|
|
83
|
+
export declare function raceSignal<T>(callback: () => Promise<T>, ...signals: (AbortSignal | undefined)[]): Promise<T>;
|
|
78
84
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/server/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,WAAW,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/server/client.ts"],"names":[],"mappings":"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"}
|