@yume-chan/adb 0.0.20 → 0.0.21
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 +24 -0
- package/CHANGELOG.md +12 -1
- package/README.md +5 -3
- package/esm/adb.d.ts +4 -1
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +21 -11
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js +1 -1
- package/esm/banner.js.map +1 -1
- package/esm/commands/base.d.ts.map +1 -1
- package/esm/commands/base.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +9 -0
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +27 -3
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/power.d.ts.map +1 -1
- package/esm/commands/power.js.map +1 -1
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +1 -1
- package/esm/commands/subprocess/command.d.ts.map +1 -1
- package/esm/commands/subprocess/command.js +15 -13
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- 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 +15 -15
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/sync/push.js +1 -1
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.js +1 -1
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +2 -0
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +4 -2
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +0 -1
- package/esm/commands/sync/socket.d.ts.map +1 -1
- package/esm/commands/sync/socket.js +3 -3
- package/esm/commands/sync/socket.js.map +1 -1
- package/esm/commands/sync/stat.js +2 -2
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +15 -0
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +17 -2
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/daemon/auth.d.ts +11 -9
- package/esm/daemon/auth.d.ts.map +1 -1
- package/esm/daemon/auth.js +21 -12
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.js +2 -2
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/dispatcher.d.ts +4 -4
- package/esm/daemon/dispatcher.d.ts.map +1 -1
- package/esm/daemon/dispatcher.js +16 -16
- package/esm/daemon/dispatcher.js.map +1 -1
- package/esm/daemon/packet.js +1 -1
- package/esm/daemon/packet.js.map +1 -1
- package/esm/daemon/socket.d.ts +0 -2
- package/esm/daemon/socket.d.ts.map +1 -1
- package/esm/daemon/socket.js +12 -8
- package/esm/daemon/socket.js.map +1 -1
- package/esm/daemon/transport.d.ts +10 -2
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js +5 -3
- package/esm/daemon/transport.js.map +1 -1
- package/esm/features.js +1 -1
- package/esm/features.js.map +1 -1
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +1 -2
- package/esm/server/client.js.map +1 -1
- package/esm/server/transport.d.ts.map +1 -1
- package/esm/server/transport.js.map +1 -1
- package/esm/utils/auto-reset-event.d.ts.map +1 -1
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/conditional-variable.d.ts.map +1 -1
- package/esm/utils/conditional-variable.js.map +1 -1
- package/package.json +12 -13
- package/src/adb.ts +42 -30
- package/src/banner.ts +7 -7
- package/src/commands/base.ts +1 -1
- package/src/commands/framebuffer.ts +31 -3
- package/src/commands/power.ts +9 -9
- package/src/commands/reverse.ts +13 -13
- package/src/commands/subprocess/command.ts +24 -25
- package/src/commands/subprocess/protocols/none.ts +12 -12
- package/src/commands/subprocess/protocols/shell.ts +35 -35
- package/src/commands/sync/list.ts +5 -5
- package/src/commands/sync/pull.ts +4 -4
- package/src/commands/sync/push.ts +6 -6
- package/src/commands/sync/request.ts +3 -3
- package/src/commands/sync/response.ts +7 -5
- package/src/commands/sync/socket.ts +14 -14
- package/src/commands/sync/stat.ts +5 -5
- package/src/commands/sync/sync.ts +32 -17
- package/src/commands/tcpip.ts +2 -2
- package/src/daemon/auth.ts +49 -30
- package/src/daemon/crypto.ts +9 -9
- package/src/daemon/dispatcher.ts +40 -39
- package/src/daemon/packet.ts +1 -1
- package/src/daemon/socket.ts +34 -30
- package/src/daemon/transport.ts +32 -20
- package/src/server/client.ts +38 -41
- package/src/server/transport.ts +13 -13
- package/src/utils/auto-reset-event.ts +4 -4
- package/src/utils/base64.ts +5 -5
- package/src/utils/conditional-variable.ts +4 -4
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/daemon/connection.d.ts +0 -11
- package/esm/daemon/connection.d.ts.map +0 -1
- package/esm/daemon/connection.js +0 -2
- package/esm/daemon/connection.js.map +0 -1
package/src/daemon/dispatcher.ts
CHANGED
|
@@ -28,6 +28,10 @@ export interface AdbPacketDispatcherOptions {
|
|
|
28
28
|
*/
|
|
29
29
|
appendNullToServiceString: boolean;
|
|
30
30
|
maxPayloadSize: number;
|
|
31
|
+
/**
|
|
32
|
+
* Whether to preserve the connection open after the `AdbPacketDispatcher` is closed.
|
|
33
|
+
*/
|
|
34
|
+
preserveConnection?: boolean | undefined;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
/**
|
|
@@ -51,23 +55,23 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
51
55
|
|
|
52
56
|
#writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>;
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
readonly options: AdbPacketDispatcherOptions;
|
|
55
59
|
|
|
56
60
|
#closed = false;
|
|
57
61
|
#disconnected = new PromiseResolver<void>();
|
|
58
|
-
|
|
62
|
+
get disconnected() {
|
|
59
63
|
return this.#disconnected.promise;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
#incomingSocketHandlers = new Map<string, AdbIncomingSocketHandler>();
|
|
63
67
|
#readAbortController = new AbortController();
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
constructor(
|
|
66
70
|
connection: ReadableWritablePair<
|
|
67
71
|
AdbPacketData,
|
|
68
72
|
Consumable<AdbPacketInit>
|
|
69
73
|
>,
|
|
70
|
-
options: AdbPacketDispatcherOptions
|
|
74
|
+
options: AdbPacketDispatcherOptions,
|
|
71
75
|
) {
|
|
72
76
|
this.options = options;
|
|
73
77
|
|
|
@@ -77,10 +81,10 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
77
81
|
write: async (packet) => {
|
|
78
82
|
switch (packet.command) {
|
|
79
83
|
case AdbCommand.OK:
|
|
80
|
-
this
|
|
84
|
+
this.#handleOk(packet);
|
|
81
85
|
break;
|
|
82
86
|
case AdbCommand.Close:
|
|
83
|
-
await this
|
|
87
|
+
await this.#handleClose(packet);
|
|
84
88
|
break;
|
|
85
89
|
case AdbCommand.Write:
|
|
86
90
|
if (this.#sockets.has(packet.arg1)) {
|
|
@@ -90,15 +94,15 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
90
94
|
await this.sendPacket(
|
|
91
95
|
AdbCommand.OK,
|
|
92
96
|
packet.arg1,
|
|
93
|
-
packet.arg0
|
|
97
|
+
packet.arg0,
|
|
94
98
|
);
|
|
95
99
|
break;
|
|
96
100
|
}
|
|
97
101
|
throw new Error(
|
|
98
|
-
`Unknown local socket id: ${packet.arg1}
|
|
102
|
+
`Unknown local socket id: ${packet.arg1}`,
|
|
99
103
|
);
|
|
100
104
|
case AdbCommand.Open:
|
|
101
|
-
await this
|
|
105
|
+
await this.#handleOpen(packet);
|
|
102
106
|
break;
|
|
103
107
|
default:
|
|
104
108
|
// Junk data may only appear in the authentication phase,
|
|
@@ -107,38 +111,33 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
107
111
|
// (although it's possible that Adb added new commands in the future)
|
|
108
112
|
throw new Error(
|
|
109
113
|
`Unknown command: ${packet.command.toString(
|
|
110
|
-
16
|
|
111
|
-
)}
|
|
114
|
+
16,
|
|
115
|
+
)}`,
|
|
112
116
|
);
|
|
113
117
|
}
|
|
114
118
|
},
|
|
115
119
|
}),
|
|
116
120
|
{
|
|
117
|
-
|
|
118
|
-
// (device disconnection, protocol error, or user abortion)
|
|
119
|
-
// if the underlying streams are still open,
|
|
120
|
-
// it's still possible to create another ADB connection.
|
|
121
|
-
// So don't close `readable` here.
|
|
122
|
-
preventCancel: true,
|
|
121
|
+
preventCancel: options.preserveConnection ?? false,
|
|
123
122
|
signal: this.#readAbortController.signal,
|
|
124
|
-
}
|
|
123
|
+
},
|
|
125
124
|
)
|
|
126
125
|
.then(
|
|
127
126
|
() => {
|
|
128
|
-
this
|
|
127
|
+
this.#dispose();
|
|
129
128
|
},
|
|
130
129
|
(e) => {
|
|
131
130
|
if (!this.#closed) {
|
|
132
131
|
this.#disconnected.reject(e);
|
|
133
132
|
}
|
|
134
|
-
this
|
|
135
|
-
}
|
|
133
|
+
this.#dispose();
|
|
134
|
+
},
|
|
136
135
|
);
|
|
137
136
|
|
|
138
137
|
this.#writer = connection.writable.getWriter();
|
|
139
138
|
}
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
#handleOk(packet: AdbPacketData) {
|
|
142
141
|
if (this.#initializers.resolve(packet.arg1, packet.arg0)) {
|
|
143
142
|
// Device successfully created the socket
|
|
144
143
|
return;
|
|
@@ -156,13 +155,13 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
156
155
|
void this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
|
|
158
|
+
async #handleClose(packet: AdbPacketData) {
|
|
160
159
|
// If the socket is still pending
|
|
161
160
|
if (
|
|
162
161
|
packet.arg0 === 0 &&
|
|
163
162
|
this.#initializers.reject(
|
|
164
163
|
packet.arg1,
|
|
165
|
-
new Error("Socket open failed")
|
|
164
|
+
new Error("Socket open failed"),
|
|
166
165
|
)
|
|
167
166
|
) {
|
|
168
167
|
// Device failed to create the socket
|
|
@@ -188,7 +187,7 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
188
187
|
await this.sendPacket(
|
|
189
188
|
AdbCommand.Close,
|
|
190
189
|
packet.arg1,
|
|
191
|
-
packet.arg0
|
|
190
|
+
packet.arg0,
|
|
192
191
|
);
|
|
193
192
|
}
|
|
194
193
|
await socket.dispose();
|
|
@@ -201,22 +200,19 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
201
200
|
// the device may also respond with two `CLSE` packets.
|
|
202
201
|
}
|
|
203
202
|
|
|
204
|
-
|
|
205
|
-
service: string,
|
|
206
|
-
handler: AdbIncomingSocketHandler
|
|
207
|
-
) {
|
|
203
|
+
addReverseTunnel(service: string, handler: AdbIncomingSocketHandler) {
|
|
208
204
|
this.#incomingSocketHandlers.set(service, handler);
|
|
209
205
|
}
|
|
210
206
|
|
|
211
|
-
|
|
207
|
+
removeReverseTunnel(address: string) {
|
|
212
208
|
this.#incomingSocketHandlers.delete(address);
|
|
213
209
|
}
|
|
214
210
|
|
|
215
|
-
|
|
211
|
+
clearReverseTunnels() {
|
|
216
212
|
this.#incomingSocketHandlers.clear();
|
|
217
213
|
}
|
|
218
214
|
|
|
219
|
-
|
|
215
|
+
async #handleOpen(packet: AdbPacketData) {
|
|
220
216
|
// `AsyncOperationManager` doesn't support skipping IDs
|
|
221
217
|
// Use `add` + `resolve` to simulate this behavior
|
|
222
218
|
const [localId] = this.#initializers.add<number>();
|
|
@@ -251,7 +247,7 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
251
247
|
}
|
|
252
248
|
}
|
|
253
249
|
|
|
254
|
-
|
|
250
|
+
async createSocket(service: string): Promise<AdbSocket> {
|
|
255
251
|
if (this.options.appendNullToServiceString) {
|
|
256
252
|
service += "\0";
|
|
257
253
|
}
|
|
@@ -273,11 +269,11 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
273
269
|
return controller.socket;
|
|
274
270
|
}
|
|
275
271
|
|
|
276
|
-
|
|
272
|
+
async sendPacket(
|
|
277
273
|
command: AdbCommand,
|
|
278
274
|
arg0: number,
|
|
279
275
|
arg1: number,
|
|
280
|
-
payload: string | Uint8Array = EMPTY_UINT8_ARRAY
|
|
276
|
+
payload: string | Uint8Array = EMPTY_UINT8_ARRAY,
|
|
281
277
|
): Promise<void> {
|
|
282
278
|
if (typeof payload === "string") {
|
|
283
279
|
payload = encodeUtf8(payload);
|
|
@@ -299,23 +295,28 @@ export class AdbPacketDispatcher implements Closeable {
|
|
|
299
295
|
});
|
|
300
296
|
}
|
|
301
297
|
|
|
302
|
-
|
|
298
|
+
async close() {
|
|
303
299
|
// Send `CLSE` packets for all sockets
|
|
304
300
|
await Promise.all(
|
|
305
|
-
Array.from(this.#sockets.values(), (socket) => socket.close())
|
|
301
|
+
Array.from(this.#sockets.values(), (socket) => socket.close()),
|
|
306
302
|
);
|
|
307
303
|
|
|
308
304
|
// Stop receiving
|
|
309
305
|
// It's possible that we haven't received all `CLSE` confirm packets,
|
|
310
306
|
// but it doesn't matter, the next connection can cope with them.
|
|
311
307
|
this.#closed = true;
|
|
308
|
+
|
|
312
309
|
this.#readAbortController.abort();
|
|
313
|
-
this
|
|
310
|
+
if (this.options.preserveConnection ?? false) {
|
|
311
|
+
this.#writer.releaseLock();
|
|
312
|
+
} else {
|
|
313
|
+
await this.#writer.close();
|
|
314
|
+
}
|
|
314
315
|
|
|
315
316
|
// `pipe().then()` will call `dispose`
|
|
316
317
|
}
|
|
317
318
|
|
|
318
|
-
|
|
319
|
+
#dispose() {
|
|
319
320
|
for (const socket of this.#sockets.values()) {
|
|
320
321
|
socket.dispose().catch(unreachable);
|
|
321
322
|
}
|
package/src/daemon/packet.ts
CHANGED
|
@@ -53,7 +53,7 @@ export class AdbPacketSerializeStream extends ConsumableTransformStream<
|
|
|
53
53
|
AdbPacketInit,
|
|
54
54
|
Uint8Array
|
|
55
55
|
> {
|
|
56
|
-
|
|
56
|
+
constructor() {
|
|
57
57
|
const headerBuffer = new Uint8Array(AdbPacketHeader.size);
|
|
58
58
|
super({
|
|
59
59
|
transform: async (chunk, controller) => {
|
package/src/daemon/socket.ts
CHANGED
|
@@ -42,23 +42,23 @@ export class AdbDaemonSocketController
|
|
|
42
42
|
Closeable,
|
|
43
43
|
Disposable
|
|
44
44
|
{
|
|
45
|
-
|
|
45
|
+
readonly #dispatcher!: AdbPacketDispatcher;
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
readonly localId!: number;
|
|
48
|
+
readonly remoteId!: number;
|
|
49
|
+
readonly localCreated!: boolean;
|
|
50
|
+
readonly service!: string;
|
|
51
51
|
|
|
52
52
|
#duplex: DuplexStreamFactory<Uint8Array, Consumable<Uint8Array>>;
|
|
53
53
|
|
|
54
54
|
#readable: ReadableStream<Uint8Array>;
|
|
55
55
|
#readableController!: PushReadableStreamController<Uint8Array>;
|
|
56
|
-
|
|
56
|
+
get readable() {
|
|
57
57
|
return this.#readable;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
#writePromise: PromiseResolver<void> | undefined;
|
|
61
|
-
|
|
61
|
+
readonly writable: WritableStream<Consumable<Uint8Array>>;
|
|
62
62
|
|
|
63
63
|
#closed = false;
|
|
64
64
|
/**
|
|
@@ -66,17 +66,21 @@ export class AdbDaemonSocketController
|
|
|
66
66
|
*
|
|
67
67
|
* It's only used by dispatcher to avoid sending another `CLSE` packet to remote.
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
get closed() {
|
|
70
70
|
return this.#closed;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return this
|
|
73
|
+
#socket: AdbDaemonSocket;
|
|
74
|
+
get socket() {
|
|
75
|
+
return this.#socket;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
constructor(options: AdbDaemonSocketConstructionOptions) {
|
|
79
|
+
this.#dispatcher = options.dispatcher;
|
|
80
|
+
this.localId = options.localId;
|
|
81
|
+
this.remoteId = options.remoteId;
|
|
82
|
+
this.localCreated = options.localCreated;
|
|
83
|
+
this.service = options.service;
|
|
80
84
|
|
|
81
85
|
// Check this image to help you understand the stream graph
|
|
82
86
|
// cspell: disable-next-line
|
|
@@ -89,7 +93,7 @@ export class AdbDaemonSocketController
|
|
|
89
93
|
close: async () => {
|
|
90
94
|
this.#closed = true;
|
|
91
95
|
|
|
92
|
-
await this
|
|
96
|
+
await this.#dispatcher.sendPacket(
|
|
93
97
|
AdbCommand.Close,
|
|
94
98
|
this.localId,
|
|
95
99
|
this.remoteId
|
|
@@ -124,7 +128,7 @@ export class AdbDaemonSocketController
|
|
|
124
128
|
write: async (chunk) => {
|
|
125
129
|
// Wait for an ack packet
|
|
126
130
|
this.#writePromise = new PromiseResolver();
|
|
127
|
-
await this
|
|
131
|
+
await this.#dispatcher.sendPacket(
|
|
128
132
|
AdbCommand.Write,
|
|
129
133
|
this.localId,
|
|
130
134
|
this.remoteId,
|
|
@@ -134,13 +138,13 @@ export class AdbDaemonSocketController
|
|
|
134
138
|
},
|
|
135
139
|
})
|
|
136
140
|
),
|
|
137
|
-
new DistributionStream(this
|
|
141
|
+
new DistributionStream(this.#dispatcher.options.maxPayloadSize)
|
|
138
142
|
);
|
|
139
143
|
|
|
140
|
-
this
|
|
144
|
+
this.#socket = new AdbDaemonSocket(this);
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
async enqueue(data: Uint8Array) {
|
|
144
148
|
// Consumer may abort the `ReadableStream` to close the socket,
|
|
145
149
|
// it's OK to throw away further packets in this case.
|
|
146
150
|
if (this.#readableController.abortSignal.aborted) {
|
|
@@ -150,15 +154,15 @@ export class AdbDaemonSocketController
|
|
|
150
154
|
await this.#readableController.enqueue(data);
|
|
151
155
|
}
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
ack() {
|
|
154
158
|
this.#writePromise?.resolve();
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
|
|
161
|
+
async close(): Promise<void> {
|
|
158
162
|
await this.#duplex.close();
|
|
159
163
|
}
|
|
160
164
|
|
|
161
|
-
|
|
165
|
+
dispose() {
|
|
162
166
|
return this.#duplex.dispose();
|
|
163
167
|
}
|
|
164
168
|
}
|
|
@@ -178,35 +182,35 @@ export class AdbDaemonSocket
|
|
|
178
182
|
{
|
|
179
183
|
#controller: AdbDaemonSocketController;
|
|
180
184
|
|
|
181
|
-
|
|
185
|
+
get localId(): number {
|
|
182
186
|
return this.#controller.localId;
|
|
183
187
|
}
|
|
184
|
-
|
|
188
|
+
get remoteId(): number {
|
|
185
189
|
return this.#controller.remoteId;
|
|
186
190
|
}
|
|
187
|
-
|
|
191
|
+
get localCreated(): boolean {
|
|
188
192
|
return this.#controller.localCreated;
|
|
189
193
|
}
|
|
190
|
-
|
|
194
|
+
get service(): string {
|
|
191
195
|
return this.#controller.service;
|
|
192
196
|
}
|
|
193
197
|
|
|
194
|
-
|
|
198
|
+
get readable(): ReadableStream<Uint8Array> {
|
|
195
199
|
return this.#controller.readable;
|
|
196
200
|
}
|
|
197
|
-
|
|
201
|
+
get writable(): WritableStream<Consumable<Uint8Array>> {
|
|
198
202
|
return this.#controller.writable;
|
|
199
203
|
}
|
|
200
204
|
|
|
201
|
-
|
|
205
|
+
get closed(): boolean {
|
|
202
206
|
return this.#controller.closed;
|
|
203
207
|
}
|
|
204
208
|
|
|
205
|
-
|
|
209
|
+
constructor(controller: AdbDaemonSocketController) {
|
|
206
210
|
this.#controller = controller;
|
|
207
211
|
}
|
|
208
212
|
|
|
209
|
-
|
|
213
|
+
close() {
|
|
210
214
|
return this.#controller.close();
|
|
211
215
|
}
|
|
212
216
|
}
|
package/src/daemon/transport.ts
CHANGED
|
@@ -32,6 +32,10 @@ interface AdbDaemonAuthenticationOptions {
|
|
|
32
32
|
connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>;
|
|
33
33
|
credentialStore: AdbCredentialStore;
|
|
34
34
|
authenticators?: AdbAuthenticator[];
|
|
35
|
+
/**
|
|
36
|
+
* Whether to preserve the connection open after the `AdbDaemonTransport` is closed.
|
|
37
|
+
*/
|
|
38
|
+
preserveConnection?: boolean | undefined;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
interface AdbDaemonSocketConnectorConstructionOptions {
|
|
@@ -40,6 +44,10 @@ interface AdbDaemonSocketConnectorConstructionOptions {
|
|
|
40
44
|
version: number;
|
|
41
45
|
maxPayloadSize: number;
|
|
42
46
|
banner: string;
|
|
47
|
+
/**
|
|
48
|
+
* Whether to preserve the connection open after the `AdbDaemonTransport` is closed.
|
|
49
|
+
*/
|
|
50
|
+
preserveConnection?: boolean | undefined;
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
export class AdbDaemonTransport implements AdbTransport {
|
|
@@ -51,11 +59,12 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
51
59
|
* on the same connection. Because every time the device receives a `CNXN` packet,
|
|
52
60
|
* it resets all internal state, and starts a new authentication process.
|
|
53
61
|
*/
|
|
54
|
-
|
|
62
|
+
static async authenticate({
|
|
55
63
|
serial,
|
|
56
64
|
connection,
|
|
57
65
|
credentialStore,
|
|
58
66
|
authenticators = ADB_DEFAULT_AUTHENTICATORS,
|
|
67
|
+
preserveConnection,
|
|
59
68
|
}: AdbDaemonAuthenticationOptions): Promise<AdbDaemonTransport> {
|
|
60
69
|
// Initially, set to highest-supported version and payload size.
|
|
61
70
|
let version = 0x01000001;
|
|
@@ -65,7 +74,7 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
65
74
|
const resolver = new PromiseResolver<string>();
|
|
66
75
|
const authProcessor = new AdbAuthenticationProcessor(
|
|
67
76
|
authenticators,
|
|
68
|
-
credentialStore
|
|
77
|
+
credentialStore,
|
|
69
78
|
);
|
|
70
79
|
|
|
71
80
|
// Here is similar to `AdbPacketDispatcher`,
|
|
@@ -80,13 +89,13 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
80
89
|
version = Math.min(version, packet.arg0);
|
|
81
90
|
maxPayloadSize = Math.min(
|
|
82
91
|
maxPayloadSize,
|
|
83
|
-
packet.arg1
|
|
92
|
+
packet.arg1,
|
|
84
93
|
);
|
|
85
94
|
resolver.resolve(decodeUtf8(packet.payload));
|
|
86
95
|
break;
|
|
87
96
|
case AdbCommand.Auth: {
|
|
88
97
|
const response = await authProcessor.process(
|
|
89
|
-
packet
|
|
98
|
+
packet,
|
|
90
99
|
);
|
|
91
100
|
await sendPacket(response);
|
|
92
101
|
break;
|
|
@@ -105,19 +114,19 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
105
114
|
// Don't cancel the source ReadableStream on AbortSignal abort.
|
|
106
115
|
preventCancel: true,
|
|
107
116
|
signal: abortController.signal,
|
|
108
|
-
}
|
|
117
|
+
},
|
|
109
118
|
)
|
|
110
119
|
.then(
|
|
111
120
|
() => {
|
|
112
121
|
if (resolver.state === "running") {
|
|
113
122
|
resolver.reject(
|
|
114
|
-
new Error("Connection closed unexpectedly")
|
|
123
|
+
new Error("Connection closed unexpectedly"),
|
|
115
124
|
);
|
|
116
125
|
}
|
|
117
126
|
},
|
|
118
127
|
(e) => {
|
|
119
128
|
resolver.reject(e);
|
|
120
|
-
}
|
|
129
|
+
},
|
|
121
130
|
);
|
|
122
131
|
|
|
123
132
|
const writer = connection.writable.getWriter();
|
|
@@ -147,7 +156,7 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
147
156
|
AdbFeature.AbbExec,
|
|
148
157
|
"remount_shell",
|
|
149
158
|
"track_app",
|
|
150
|
-
|
|
159
|
+
AdbFeature.SendReceiveV2,
|
|
151
160
|
"sendrecv_v2_brotli",
|
|
152
161
|
"sendrecv_v2_lz4",
|
|
153
162
|
"sendrecv_v2_zstd",
|
|
@@ -180,41 +189,43 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
180
189
|
version,
|
|
181
190
|
maxPayloadSize,
|
|
182
191
|
banner,
|
|
192
|
+
preserveConnection,
|
|
183
193
|
});
|
|
184
194
|
}
|
|
185
195
|
|
|
186
196
|
readonly #dispatcher: AdbPacketDispatcher;
|
|
187
197
|
|
|
188
198
|
#serial: string;
|
|
189
|
-
|
|
199
|
+
get serial() {
|
|
190
200
|
return this.#serial;
|
|
191
201
|
}
|
|
192
202
|
|
|
193
203
|
#protocolVersion: number;
|
|
194
|
-
|
|
204
|
+
get protocolVersion() {
|
|
195
205
|
return this.#protocolVersion;
|
|
196
206
|
}
|
|
197
207
|
|
|
198
208
|
#maxPayloadSize: number;
|
|
199
|
-
|
|
209
|
+
get maxPayloadSize() {
|
|
200
210
|
return this.#maxPayloadSize;
|
|
201
211
|
}
|
|
202
212
|
|
|
203
213
|
#banner: AdbBanner;
|
|
204
|
-
|
|
214
|
+
get banner() {
|
|
205
215
|
return this.#banner;
|
|
206
216
|
}
|
|
207
217
|
|
|
208
|
-
|
|
218
|
+
get disconnected() {
|
|
209
219
|
return this.#dispatcher.disconnected;
|
|
210
220
|
}
|
|
211
221
|
|
|
212
|
-
|
|
222
|
+
constructor({
|
|
213
223
|
serial,
|
|
214
224
|
connection,
|
|
215
225
|
version,
|
|
216
226
|
maxPayloadSize,
|
|
217
227
|
banner,
|
|
228
|
+
preserveConnection,
|
|
218
229
|
}: AdbDaemonSocketConnectorConstructionOptions) {
|
|
219
230
|
this.#serial = serial;
|
|
220
231
|
this.#banner = AdbBanner.parse(banner);
|
|
@@ -233,19 +244,20 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
233
244
|
calculateChecksum,
|
|
234
245
|
appendNullToServiceString,
|
|
235
246
|
maxPayloadSize,
|
|
247
|
+
preserveConnection,
|
|
236
248
|
});
|
|
237
249
|
|
|
238
250
|
this.#protocolVersion = version;
|
|
239
251
|
this.#maxPayloadSize = maxPayloadSize;
|
|
240
252
|
}
|
|
241
253
|
|
|
242
|
-
|
|
254
|
+
connect(service: string): ValueOrPromise<AdbSocket> {
|
|
243
255
|
return this.#dispatcher.createSocket(service);
|
|
244
256
|
}
|
|
245
257
|
|
|
246
|
-
|
|
258
|
+
addReverseTunnel(
|
|
247
259
|
handler: AdbIncomingSocketHandler,
|
|
248
|
-
address?: string
|
|
260
|
+
address?: string,
|
|
249
261
|
): string {
|
|
250
262
|
if (!address) {
|
|
251
263
|
const id = Math.random().toString().substring(2);
|
|
@@ -255,15 +267,15 @@ export class AdbDaemonTransport implements AdbTransport {
|
|
|
255
267
|
return address;
|
|
256
268
|
}
|
|
257
269
|
|
|
258
|
-
|
|
270
|
+
removeReverseTunnel(address: string): void {
|
|
259
271
|
this.#dispatcher.removeReverseTunnel(address);
|
|
260
272
|
}
|
|
261
273
|
|
|
262
|
-
|
|
274
|
+
clearReverseTunnels(): void {
|
|
263
275
|
this.#dispatcher.clearReverseTunnels();
|
|
264
276
|
}
|
|
265
277
|
|
|
266
|
-
|
|
278
|
+
close(): ValueOrPromise<void> {
|
|
267
279
|
return this.#dispatcher.close();
|
|
268
280
|
}
|
|
269
281
|
}
|