@yume-chan/adb 0.0.17 → 0.0.19
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 +27 -0
- package/CHANGELOG.md +16 -1
- package/LICENSE +1 -1
- package/esm/adb.d.ts +63 -60
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +257 -229
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts +51 -51
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js +95 -96
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +8 -8
- package/esm/backend.d.ts.map +1 -1
- package/esm/backend.js +1 -1
- package/esm/commands/base.d.ts +6 -6
- package/esm/commands/base.js +8 -8
- package/esm/commands/framebuffer.d.ts +53 -53
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +46 -47
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/index.d.ts +7 -8
- package/esm/commands/index.d.ts.map +1 -1
- package/esm/commands/index.js +7 -8
- package/esm/commands/index.js.map +1 -1
- package/esm/commands/install.d.ts +9 -3
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +27 -21
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +22 -22
- package/esm/commands/power.d.ts.map +1 -1
- package/esm/commands/power.js +48 -44
- package/esm/commands/power.js.map +1 -1
- package/esm/commands/reverse.d.ts +41 -28
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +125 -98
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +57 -51
- package/esm/commands/subprocess/command.d.ts.map +1 -1
- package/esm/commands/subprocess/command.js +86 -82
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/index.d.ts +3 -3
- package/esm/commands/subprocess/index.js +3 -3
- package/esm/commands/subprocess/protocols/index.d.ts +3 -3
- package/esm/commands/subprocess/protocols/index.js +3 -3
- package/esm/commands/subprocess/protocols/none.d.ts +35 -35
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +65 -55
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +39 -38
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +166 -154
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +49 -49
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/types.js +1 -1
- package/esm/commands/subprocess/utils.d.ts +1 -1
- package/esm/commands/subprocess/utils.js +18 -18
- package/esm/commands/sync/index.d.ts +8 -7
- package/esm/commands/sync/index.d.ts.map +1 -1
- package/esm/commands/sync/index.js +8 -7
- package/esm/commands/sync/index.js.map +1 -1
- package/esm/commands/sync/list.d.ts +42 -40
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +67 -35
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +13 -11
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +35 -36
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +46 -7
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +89 -23
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +26 -23
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +40 -42
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +19 -19
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +54 -54
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +27 -0
- package/esm/commands/sync/socket.d.ts.map +1 -0
- package/esm/commands/sync/socket.js +66 -0
- package/esm/commands/sync/socket.js.map +1 -0
- package/esm/commands/sync/stat.d.ts +72 -72
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +116 -94
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +72 -60
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +127 -148
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +5 -5
- package/esm/commands/tcpip.js +18 -18
- package/esm/crypto.d.ts +36 -36
- package/esm/crypto.d.ts.map +1 -1
- package/esm/crypto.js +248 -238
- package/esm/crypto.js.map +1 -1
- package/esm/features.d.ts +10 -7
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +13 -10
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +9 -9
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +9 -9
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +45 -46
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +43 -46
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +59 -59
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +223 -231
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +2 -2
- package/esm/socket/index.js +2 -2
- package/esm/socket/socket.d.ts +59 -59
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +118 -98
- package/esm/socket/socket.js.map +1 -1
- package/esm/utils/auto-reset-event.d.ts +9 -9
- package/esm/utils/auto-reset-event.d.ts.map +1 -1
- package/esm/utils/auto-reset-event.js +33 -33
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.d.ts +27 -27
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +246 -245
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/conditional-variable.d.ts +9 -0
- package/esm/utils/conditional-variable.d.ts.map +1 -0
- package/esm/utils/conditional-variable.js +34 -0
- package/esm/utils/conditional-variable.js.map +1 -0
- package/esm/utils/index.d.ts +4 -3
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +4 -3
- package/esm/utils/index.js.map +1 -1
- package/package.json +17 -13
- package/src/adb.ts +160 -101
- package/src/auth.ts +31 -22
- package/src/backend.ts +6 -4
- package/src/commands/base.ts +2 -2
- package/src/commands/framebuffer.ts +37 -41
- package/src/commands/index.ts +7 -8
- package/src/commands/power.ts +15 -11
- package/src/commands/reverse.ts +74 -30
- package/src/commands/subprocess/command.ts +34 -23
- package/src/commands/subprocess/index.ts +3 -3
- package/src/commands/subprocess/protocols/index.ts +3 -3
- package/src/commands/subprocess/protocols/none.ts +26 -11
- package/src/commands/subprocess/protocols/shell.ts +110 -56
- package/src/commands/subprocess/protocols/types.ts +10 -6
- package/src/commands/subprocess/utils.ts +1 -1
- package/src/commands/sync/index.ts +8 -7
- package/src/commands/sync/list.ts +74 -28
- package/src/commands/sync/pull.ts +49 -37
- package/src/commands/sync/push.ts +153 -32
- package/src/commands/sync/request.ts +37 -34
- package/src/commands/sync/response.ts +34 -27
- package/src/commands/sync/socket.ts +97 -0
- package/src/commands/sync/stat.ts +98 -70
- package/src/commands/sync/sync.ts +78 -97
- package/src/commands/tcpip.ts +5 -5
- package/src/crypto.ts +60 -32
- package/src/features.ts +9 -6
- package/src/index.ts +9 -10
- package/src/packet.ts +41 -46
- package/src/socket/dispatcher.ts +130 -108
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +84 -34
- package/src/utils/auto-reset-event.ts +16 -17
- package/src/utils/base64.ts +51 -41
- package/src/utils/conditional-variable.ts +45 -0
- package/src/utils/index.ts +4 -3
- package/tsconfig.build.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/src/commands/install.ts +0 -32
package/src/socket/dispatcher.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
-
import { AsyncOperationManager, PromiseResolver } from
|
|
2
|
-
import type { RemoveEventListener } from
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
1
|
+
import { AsyncOperationManager, PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type { RemoveEventListener } from "@yume-chan/event";
|
|
3
|
+
import type {
|
|
4
|
+
Consumable,
|
|
5
|
+
ReadableWritablePair,
|
|
6
|
+
WritableStreamDefaultWriter,
|
|
7
|
+
} from "@yume-chan/stream-extra";
|
|
8
|
+
import {
|
|
9
|
+
AbortController,
|
|
10
|
+
ConsumableWritableStream,
|
|
11
|
+
WritableStream,
|
|
12
|
+
} from "@yume-chan/stream-extra";
|
|
13
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
14
|
+
import { EMPTY_UINT8_ARRAY } from "@yume-chan/struct";
|
|
15
|
+
|
|
16
|
+
import type { AdbPacketData, AdbPacketInit } from "../packet.js";
|
|
17
|
+
import { AdbCommand, calculateChecksum } from "../packet.js";
|
|
18
|
+
import { decodeUtf8, encodeUtf8 } from "../utils/index.js";
|
|
19
|
+
|
|
20
|
+
import type { AdbSocket } from "./socket.js";
|
|
21
|
+
import { AdbSocketController } from "./socket.js";
|
|
9
22
|
|
|
10
23
|
export interface AdbPacketDispatcherOptions {
|
|
11
24
|
calculateChecksum: boolean;
|
|
@@ -19,7 +32,9 @@ export interface AdbPacketDispatcherOptions {
|
|
|
19
32
|
maxPayloadSize: number;
|
|
20
33
|
}
|
|
21
34
|
|
|
22
|
-
export type AdbIncomingSocketHandler = (
|
|
35
|
+
export type AdbIncomingSocketHandler = (
|
|
36
|
+
socket: AdbSocket
|
|
37
|
+
) => ValueOrPromise<boolean>;
|
|
23
38
|
|
|
24
39
|
export interface Closeable {
|
|
25
40
|
close(): ValueOrPromise<void>;
|
|
@@ -44,72 +59,92 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
44
59
|
*/
|
|
45
60
|
private readonly sockets = new Map<number, AdbSocketController>();
|
|
46
61
|
|
|
47
|
-
private _writer
|
|
62
|
+
private _writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>;
|
|
48
63
|
|
|
49
64
|
public readonly options: AdbPacketDispatcherOptions;
|
|
50
65
|
|
|
51
66
|
private _closed = false;
|
|
52
67
|
private _disconnected = new PromiseResolver<void>();
|
|
53
|
-
public get disconnected() {
|
|
68
|
+
public get disconnected() {
|
|
69
|
+
return this._disconnected.promise;
|
|
70
|
+
}
|
|
54
71
|
|
|
55
72
|
private _incomingSocketHandlers: Set<AdbIncomingSocketHandler> = new Set();
|
|
56
73
|
|
|
57
74
|
private _abortController = new AbortController();
|
|
58
75
|
|
|
59
76
|
public constructor(
|
|
60
|
-
connection: ReadableWritablePair<
|
|
77
|
+
connection: ReadableWritablePair<
|
|
78
|
+
AdbPacketData,
|
|
79
|
+
Consumable<AdbPacketInit>
|
|
80
|
+
>,
|
|
61
81
|
options: AdbPacketDispatcherOptions
|
|
62
82
|
) {
|
|
63
83
|
this.options = options;
|
|
64
84
|
|
|
65
85
|
connection.readable
|
|
66
|
-
.pipeTo(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
case AdbCommand.Close:
|
|
73
|
-
await this.handleClose(packet);
|
|
74
|
-
break;
|
|
75
|
-
case AdbCommand.Write:
|
|
76
|
-
if (this.sockets.has(packet.arg1)) {
|
|
77
|
-
await this.sockets.get(packet.arg1)!.enqueue(packet.payload);
|
|
78
|
-
await this.sendPacket(AdbCommand.OK, packet.arg1, packet.arg0);
|
|
86
|
+
.pipeTo(
|
|
87
|
+
new WritableStream({
|
|
88
|
+
write: async (packet) => {
|
|
89
|
+
switch (packet.command) {
|
|
90
|
+
case AdbCommand.OK:
|
|
91
|
+
this.handleOk(packet);
|
|
79
92
|
break;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
case AdbCommand.Close:
|
|
94
|
+
await this.handleClose(packet);
|
|
95
|
+
break;
|
|
96
|
+
case AdbCommand.Write:
|
|
97
|
+
if (this.sockets.has(packet.arg1)) {
|
|
98
|
+
await this.sockets
|
|
99
|
+
.get(packet.arg1)!
|
|
100
|
+
.enqueue(packet.payload);
|
|
101
|
+
await this.sendPacket(
|
|
102
|
+
AdbCommand.OK,
|
|
103
|
+
packet.arg1,
|
|
104
|
+
packet.arg0
|
|
105
|
+
);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Unknown local socket id: ${packet.arg1}`
|
|
110
|
+
);
|
|
111
|
+
case AdbCommand.Open:
|
|
112
|
+
await this.handleOpen(packet);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
// Junk data may only appear in the authentication phase,
|
|
116
|
+
// since the dispatcher only works after authentication,
|
|
117
|
+
// all packets should have a valid command.
|
|
118
|
+
// (although it's possible that Adb added new commands in the future)
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Unknown command: ${packet.command.toString(
|
|
121
|
+
16
|
|
122
|
+
)}`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
}),
|
|
127
|
+
{
|
|
128
|
+
// There are multiple reasons for the pipe to stop,
|
|
129
|
+
// (device disconnection, protocol error, or user abortion)
|
|
130
|
+
// if the underlying streams are still open,
|
|
131
|
+
// it's still possible to create another ADB connection.
|
|
132
|
+
// So don't close `readable` here.
|
|
133
|
+
preventCancel: true,
|
|
134
|
+
signal: this._abortController.signal,
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
.then(
|
|
138
|
+
() => {
|
|
139
|
+
this.dispose();
|
|
92
140
|
},
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// So don't close `readable` here.
|
|
99
|
-
preventCancel: true,
|
|
100
|
-
signal: this._abortController.signal,
|
|
101
|
-
})
|
|
102
|
-
.then(() => {
|
|
103
|
-
this.dispose();
|
|
104
|
-
}, (e) => {
|
|
105
|
-
// https://github.com/MattiasBuelens/web-streams-polyfill/issues/115
|
|
106
|
-
// `e` is always `AbortError` (instead of what I give in `abortController.abort()`)
|
|
107
|
-
// so we can't check if `e` is a real error.
|
|
108
|
-
if (!this._closed) {
|
|
109
|
-
this._disconnected.reject(e);
|
|
141
|
+
(e) => {
|
|
142
|
+
if (!this._closed) {
|
|
143
|
+
this._disconnected.reject(e);
|
|
144
|
+
}
|
|
145
|
+
this.dispose();
|
|
110
146
|
}
|
|
111
|
-
|
|
112
|
-
});
|
|
147
|
+
);
|
|
113
148
|
|
|
114
149
|
this._writer = connection.writable.getWriter();
|
|
115
150
|
}
|
|
@@ -129,13 +164,18 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
129
164
|
|
|
130
165
|
// Maybe the device is responding to a packet of last connection
|
|
131
166
|
// Tell the device to close the socket
|
|
132
|
-
this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
|
|
167
|
+
void this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
|
|
133
168
|
}
|
|
134
169
|
|
|
135
170
|
private async handleClose(packet: AdbPacketData) {
|
|
136
171
|
// If the socket is still pending
|
|
137
|
-
if (
|
|
138
|
-
|
|
172
|
+
if (
|
|
173
|
+
packet.arg0 === 0 &&
|
|
174
|
+
this.initializers.reject(
|
|
175
|
+
packet.arg1,
|
|
176
|
+
new Error("Socket open failed")
|
|
177
|
+
)
|
|
178
|
+
) {
|
|
139
179
|
// Device failed to create the socket
|
|
140
180
|
// (unknown service string, failed to execute command, etc.)
|
|
141
181
|
// it doesn't break the connection,
|
|
@@ -156,9 +196,13 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
156
196
|
if (socket) {
|
|
157
197
|
// The device want to close the socket
|
|
158
198
|
if (!socket.closed) {
|
|
159
|
-
await this.sendPacket(
|
|
199
|
+
await this.sendPacket(
|
|
200
|
+
AdbCommand.Close,
|
|
201
|
+
packet.arg1,
|
|
202
|
+
packet.arg0
|
|
203
|
+
);
|
|
160
204
|
}
|
|
161
|
-
socket.dispose();
|
|
205
|
+
await socket.dispose();
|
|
162
206
|
this.sockets.delete(packet.arg1);
|
|
163
207
|
return;
|
|
164
208
|
}
|
|
@@ -173,7 +217,9 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
173
217
|
* @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.
|
|
174
218
|
* @returns A function to remove the handler.
|
|
175
219
|
*/
|
|
176
|
-
public onIncomingSocket(
|
|
220
|
+
public onIncomingSocket(
|
|
221
|
+
handler: AdbIncomingSocketHandler
|
|
222
|
+
): RemoveEventListener {
|
|
177
223
|
this._incomingSocketHandlers.add(handler);
|
|
178
224
|
const remove = () => {
|
|
179
225
|
this._incomingSocketHandlers.delete(handler);
|
|
@@ -212,16 +258,11 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
212
258
|
|
|
213
259
|
public async createSocket(serviceString: string): Promise<AdbSocket> {
|
|
214
260
|
if (this.options.appendNullToServiceString) {
|
|
215
|
-
serviceString +=
|
|
261
|
+
serviceString += "\0";
|
|
216
262
|
}
|
|
217
263
|
|
|
218
264
|
const [localId, initializer] = this.initializers.add<number>();
|
|
219
|
-
await this.sendPacket(
|
|
220
|
-
AdbCommand.Open,
|
|
221
|
-
localId,
|
|
222
|
-
0,
|
|
223
|
-
serviceString
|
|
224
|
-
);
|
|
265
|
+
await this.sendPacket(AdbCommand.Open, localId, 0, serviceString);
|
|
225
266
|
|
|
226
267
|
// Fulfilled by `handleOk`
|
|
227
268
|
const remoteId = await initializer;
|
|
@@ -237,57 +278,36 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
237
278
|
return controller.socket;
|
|
238
279
|
}
|
|
239
280
|
|
|
240
|
-
public sendPacket(
|
|
241
|
-
public sendPacket(
|
|
281
|
+
public async sendPacket(
|
|
242
282
|
command: AdbCommand,
|
|
243
283
|
arg0: number,
|
|
244
284
|
arg1: number,
|
|
245
|
-
payload
|
|
246
|
-
): Promise<void>;
|
|
247
|
-
public async sendPacket(
|
|
248
|
-
packetOrCommand: AdbPacketInit | AdbCommand,
|
|
249
|
-
arg0?: number,
|
|
250
|
-
arg1?: number,
|
|
251
|
-
payload: string | Uint8Array = EMPTY_UINT8_ARRAY,
|
|
285
|
+
payload: string | Uint8Array = EMPTY_UINT8_ARRAY
|
|
252
286
|
): Promise<void> {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
init = packetOrCommand as AdbPacketInit;
|
|
256
|
-
} else {
|
|
257
|
-
if (typeof payload === 'string') {
|
|
258
|
-
payload = encodeUtf8(payload);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
init = {
|
|
262
|
-
command: packetOrCommand as AdbCommand,
|
|
263
|
-
arg0: arg0 as number,
|
|
264
|
-
arg1: arg1 as number,
|
|
265
|
-
payload,
|
|
266
|
-
};
|
|
287
|
+
if (typeof payload === "string") {
|
|
288
|
+
payload = encodeUtf8(payload);
|
|
267
289
|
}
|
|
268
290
|
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
throw new Error('payload too large');
|
|
291
|
+
if (payload.byteLength > this.options.maxPayloadSize) {
|
|
292
|
+
throw new Error("payload too large");
|
|
272
293
|
}
|
|
273
294
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
295
|
+
await ConsumableWritableStream.write(this._writer, {
|
|
296
|
+
command,
|
|
297
|
+
arg0,
|
|
298
|
+
arg1,
|
|
299
|
+
payload,
|
|
300
|
+
checksum: this.options.calculateChecksum
|
|
301
|
+
? calculateChecksum(payload)
|
|
302
|
+
: 0,
|
|
303
|
+
magic: command ^ 0xffffffff,
|
|
304
|
+
});
|
|
282
305
|
}
|
|
283
306
|
|
|
284
307
|
public async close() {
|
|
285
308
|
// Send `CLSE` packets for all sockets
|
|
286
309
|
await Promise.all(
|
|
287
|
-
Array.from(
|
|
288
|
-
this.sockets.values(),
|
|
289
|
-
socket => socket.close(),
|
|
290
|
-
)
|
|
310
|
+
Array.from(this.sockets.values(), (socket) => socket.close())
|
|
291
311
|
);
|
|
292
312
|
|
|
293
313
|
// Stop receiving
|
|
@@ -302,7 +322,9 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
302
322
|
|
|
303
323
|
private dispose() {
|
|
304
324
|
for (const socket of this.sockets.values()) {
|
|
305
|
-
socket.dispose()
|
|
325
|
+
socket.dispose().catch((e) => {
|
|
326
|
+
void e;
|
|
327
|
+
});
|
|
306
328
|
}
|
|
307
329
|
|
|
308
330
|
this._disconnected.resolve();
|
package/src/socket/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./dispatcher.js";
|
|
2
|
+
export * from "./socket.js";
|
package/src/socket/socket.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import { PromiseResolver } from
|
|
2
|
-
import type { Disposable } from
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type { Disposable } from "@yume-chan/event";
|
|
3
|
+
import type {
|
|
4
|
+
Consumable,
|
|
5
|
+
PushReadableStreamController,
|
|
6
|
+
ReadableStream,
|
|
7
|
+
ReadableWritablePair,
|
|
8
|
+
WritableStream,
|
|
9
|
+
} from "@yume-chan/stream-extra";
|
|
10
|
+
import {
|
|
11
|
+
ConsumableWritableStream,
|
|
12
|
+
DistributionStream,
|
|
13
|
+
DuplexStreamFactory,
|
|
14
|
+
PushReadableStream,
|
|
15
|
+
pipeFrom,
|
|
16
|
+
} from "@yume-chan/stream-extra";
|
|
17
|
+
|
|
18
|
+
import { AdbCommand } from "../packet.js";
|
|
19
|
+
|
|
20
|
+
import type { AdbPacketDispatcher, Closeable } from "./dispatcher.js";
|
|
7
21
|
|
|
8
22
|
export interface AdbSocketInfo {
|
|
9
23
|
localId: number;
|
|
@@ -19,7 +33,13 @@ export interface AdbSocketConstructionOptions extends AdbSocketInfo {
|
|
|
19
33
|
highWaterMark?: number | undefined;
|
|
20
34
|
}
|
|
21
35
|
|
|
22
|
-
export class AdbSocketController
|
|
36
|
+
export class AdbSocketController
|
|
37
|
+
implements
|
|
38
|
+
AdbSocketInfo,
|
|
39
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>,
|
|
40
|
+
Closeable,
|
|
41
|
+
Disposable
|
|
42
|
+
{
|
|
23
43
|
private readonly dispatcher!: AdbPacketDispatcher;
|
|
24
44
|
|
|
25
45
|
public readonly localId!: number;
|
|
@@ -27,14 +47,16 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
27
47
|
public readonly localCreated!: boolean;
|
|
28
48
|
public readonly serviceString!: string;
|
|
29
49
|
|
|
30
|
-
private _duplex: DuplexStreamFactory<Uint8Array, Uint8Array
|
|
50
|
+
private _duplex: DuplexStreamFactory<Uint8Array, Consumable<Uint8Array>>;
|
|
31
51
|
|
|
32
52
|
private _readable: ReadableStream<Uint8Array>;
|
|
33
53
|
private _readableController!: PushReadableStreamController<Uint8Array>;
|
|
34
|
-
public get readable() {
|
|
54
|
+
public get readable() {
|
|
55
|
+
return this._readable;
|
|
56
|
+
}
|
|
35
57
|
|
|
36
58
|
private _writePromise: PromiseResolver<void> | undefined;
|
|
37
|
-
public readonly writable: WritableStream<Uint8Array
|
|
59
|
+
public readonly writable: WritableStream<Consumable<Uint8Array>>;
|
|
38
60
|
|
|
39
61
|
private _closed = false;
|
|
40
62
|
/**
|
|
@@ -42,10 +64,14 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
42
64
|
*
|
|
43
65
|
* It's only used by dispatcher to avoid sending another `CLSE` packet to remote.
|
|
44
66
|
*/
|
|
45
|
-
public get closed() {
|
|
67
|
+
public get closed() {
|
|
68
|
+
return this._closed;
|
|
69
|
+
}
|
|
46
70
|
|
|
47
71
|
private _socket: AdbSocket;
|
|
48
|
-
public get socket() {
|
|
72
|
+
public get socket() {
|
|
73
|
+
return this._socket;
|
|
74
|
+
}
|
|
49
75
|
|
|
50
76
|
public constructor(options: AdbSocketConstructionOptions) {
|
|
51
77
|
Object.assign(this, options);
|
|
@@ -54,7 +80,10 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
54
80
|
// cspell: disable-next-line
|
|
55
81
|
// https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
|
|
56
82
|
|
|
57
|
-
this._duplex = new DuplexStreamFactory<
|
|
83
|
+
this._duplex = new DuplexStreamFactory<
|
|
84
|
+
Uint8Array,
|
|
85
|
+
Consumable<Uint8Array>
|
|
86
|
+
>({
|
|
58
87
|
close: async () => {
|
|
59
88
|
this._closed = true;
|
|
60
89
|
|
|
@@ -69,22 +98,27 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
69
98
|
},
|
|
70
99
|
dispose: () => {
|
|
71
100
|
// Error out the pending writes
|
|
72
|
-
this._writePromise?.reject(new Error(
|
|
101
|
+
this._writePromise?.reject(new Error("Socket closed"));
|
|
73
102
|
},
|
|
74
103
|
});
|
|
75
104
|
|
|
76
105
|
this._readable = this._duplex.wrapReadable(
|
|
77
|
-
new PushReadableStream(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
106
|
+
new PushReadableStream(
|
|
107
|
+
(controller) => {
|
|
108
|
+
this._readableController = controller;
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
highWaterMark: options.highWaterMark ?? 16 * 1024,
|
|
112
|
+
size(chunk) {
|
|
113
|
+
return chunk.byteLength;
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
)
|
|
83
117
|
);
|
|
84
118
|
|
|
85
119
|
this.writable = pipeFrom(
|
|
86
120
|
this._duplex.createWritable(
|
|
87
|
-
new
|
|
121
|
+
new ConsumableWritableStream<Uint8Array>({
|
|
88
122
|
write: async (chunk) => {
|
|
89
123
|
// Wait for an ack packet
|
|
90
124
|
this._writePromise = new PromiseResolver();
|
|
@@ -95,23 +129,23 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
95
129
|
chunk
|
|
96
130
|
);
|
|
97
131
|
await this._writePromise.promise;
|
|
98
|
-
}
|
|
99
|
-
})
|
|
132
|
+
},
|
|
133
|
+
})
|
|
100
134
|
),
|
|
101
|
-
new
|
|
135
|
+
new DistributionStream(this.dispatcher.options.maxPayloadSize)
|
|
102
136
|
);
|
|
103
137
|
|
|
104
138
|
this._socket = new AdbSocket(this);
|
|
105
139
|
}
|
|
106
140
|
|
|
107
|
-
public async enqueue(
|
|
141
|
+
public async enqueue(data: Uint8Array) {
|
|
108
142
|
// Consumer may abort the `ReadableStream` to close the socket,
|
|
109
143
|
// it's OK to throw away further packets in this case.
|
|
110
144
|
if (this._readableController.abortSignal.aborted) {
|
|
111
145
|
return;
|
|
112
146
|
}
|
|
113
147
|
|
|
114
|
-
await this._readableController.enqueue(
|
|
148
|
+
await this._readableController.enqueue(data);
|
|
115
149
|
}
|
|
116
150
|
|
|
117
151
|
public ack() {
|
|
@@ -123,7 +157,7 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
123
157
|
}
|
|
124
158
|
|
|
125
159
|
public dispose() {
|
|
126
|
-
this._duplex.dispose();
|
|
160
|
+
return this._duplex.dispose();
|
|
127
161
|
}
|
|
128
162
|
}
|
|
129
163
|
|
|
@@ -135,16 +169,32 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
|
|
|
135
169
|
* `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
|
|
136
170
|
* `socket.writable.close()` or `socket.writable.getWriter().close()`.
|
|
137
171
|
*/
|
|
138
|
-
export class AdbSocket
|
|
172
|
+
export class AdbSocket
|
|
173
|
+
implements
|
|
174
|
+
AdbSocketInfo,
|
|
175
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
176
|
+
{
|
|
139
177
|
private _controller: AdbSocketController;
|
|
140
178
|
|
|
141
|
-
public get localId(): number {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
public get
|
|
179
|
+
public get localId(): number {
|
|
180
|
+
return this._controller.localId;
|
|
181
|
+
}
|
|
182
|
+
public get remoteId(): number {
|
|
183
|
+
return this._controller.remoteId;
|
|
184
|
+
}
|
|
185
|
+
public get localCreated(): boolean {
|
|
186
|
+
return this._controller.localCreated;
|
|
187
|
+
}
|
|
188
|
+
public get serviceString(): string {
|
|
189
|
+
return this._controller.serviceString;
|
|
190
|
+
}
|
|
145
191
|
|
|
146
|
-
public get readable(): ReadableStream<Uint8Array> {
|
|
147
|
-
|
|
192
|
+
public get readable(): ReadableStream<Uint8Array> {
|
|
193
|
+
return this._controller.readable;
|
|
194
|
+
}
|
|
195
|
+
public get writable(): WritableStream<Consumable<Uint8Array>> {
|
|
196
|
+
return this._controller.writable;
|
|
197
|
+
}
|
|
148
198
|
|
|
149
199
|
public constructor(controller: AdbSocketController) {
|
|
150
200
|
this._controller = controller;
|
|
@@ -1,41 +1,40 @@
|
|
|
1
|
-
import { PromiseResolver } from
|
|
2
|
-
import type { Disposable } from
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type { Disposable } from "@yume-chan/event";
|
|
3
3
|
|
|
4
4
|
export class AutoResetEvent implements Disposable {
|
|
5
|
-
private
|
|
6
|
-
|
|
7
|
-
private blocking: boolean;
|
|
5
|
+
private _set: boolean;
|
|
6
|
+
private readonly _queue: PromiseResolver<void>[] = [];
|
|
8
7
|
|
|
9
8
|
public constructor(initialSet = false) {
|
|
10
|
-
this.
|
|
9
|
+
this._set = initialSet;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
public wait(): Promise<void> {
|
|
14
|
-
if (!this.
|
|
15
|
-
this.
|
|
13
|
+
if (!this._set) {
|
|
14
|
+
this._set = true;
|
|
16
15
|
|
|
17
|
-
if (this.
|
|
16
|
+
if (this._queue.length === 0) {
|
|
18
17
|
return Promise.resolve();
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
const resolver = new PromiseResolver<void>();
|
|
23
|
-
this.
|
|
22
|
+
this._queue.push(resolver);
|
|
24
23
|
return resolver.promise;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
public
|
|
28
|
-
if (this.
|
|
29
|
-
this.
|
|
26
|
+
public notifyOne() {
|
|
27
|
+
if (this._queue.length !== 0) {
|
|
28
|
+
this._queue.pop()!.resolve();
|
|
30
29
|
} else {
|
|
31
|
-
this.
|
|
30
|
+
this._set = false;
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
public dispose() {
|
|
36
|
-
for (const item of this.
|
|
37
|
-
item.reject(new Error(
|
|
35
|
+
for (const item of this._queue) {
|
|
36
|
+
item.reject(new Error("The AutoResetEvent has been disposed"));
|
|
38
37
|
}
|
|
39
|
-
this.
|
|
38
|
+
this._queue.length = 0;
|
|
40
39
|
}
|
|
41
40
|
}
|