@yume-chan/adb 0.0.16 → 0.0.18

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.
Files changed (177) hide show
  1. package/CHANGELOG.json +18 -0
  2. package/CHANGELOG.md +13 -1
  3. package/LICENSE +1 -1
  4. package/esm/adb.d.ts +13 -8
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +63 -38
  7. package/esm/adb.js.map +1 -1
  8. package/esm/auth.d.ts +4 -4
  9. package/esm/auth.d.ts.map +1 -1
  10. package/esm/auth.js +6 -6
  11. package/esm/auth.js.map +1 -1
  12. package/esm/backend.d.ts +3 -3
  13. package/esm/backend.d.ts.map +1 -1
  14. package/esm/commands/base.d.ts +2 -2
  15. package/esm/commands/base.d.ts.map +1 -1
  16. package/esm/commands/base.js +1 -1
  17. package/esm/commands/base.js.map +1 -1
  18. package/esm/commands/framebuffer.d.ts +22 -6
  19. package/esm/commands/framebuffer.d.ts.map +1 -1
  20. package/esm/commands/framebuffer.js +33 -45
  21. package/esm/commands/framebuffer.js.map +1 -1
  22. package/esm/commands/install.d.ts +2 -2
  23. package/esm/commands/install.d.ts.map +1 -1
  24. package/esm/commands/install.js +12 -5
  25. package/esm/commands/install.js.map +1 -1
  26. package/esm/commands/power.d.ts.map +1 -1
  27. package/esm/commands/power.js +13 -9
  28. package/esm/commands/power.js.map +1 -1
  29. package/esm/commands/reverse.d.ts +5 -5
  30. package/esm/commands/reverse.d.ts.map +1 -1
  31. package/esm/commands/reverse.js +20 -18
  32. package/esm/commands/reverse.js.map +1 -1
  33. package/esm/commands/subprocess/command.d.ts +52 -0
  34. package/esm/commands/subprocess/command.d.ts.map +1 -0
  35. package/esm/commands/subprocess/command.js +81 -0
  36. package/esm/commands/subprocess/command.js.map +1 -0
  37. package/esm/commands/subprocess/index.d.ts +1 -53
  38. package/esm/commands/subprocess/index.d.ts.map +1 -1
  39. package/esm/commands/subprocess/index.js +1 -85
  40. package/esm/commands/subprocess/index.js.map +1 -1
  41. package/esm/commands/subprocess/protocols/none.d.ts +5 -5
  42. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  43. package/esm/commands/subprocess/protocols/none.js +5 -3
  44. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  45. package/esm/commands/subprocess/protocols/shell.d.ts +4 -4
  46. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/shell.js +28 -20
  48. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  49. package/esm/commands/subprocess/protocols/types.d.ts +7 -7
  50. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  51. package/esm/commands/sync/index.d.ts +1 -1
  52. package/esm/commands/sync/index.d.ts.map +1 -1
  53. package/esm/commands/sync/index.js +1 -1
  54. package/esm/commands/sync/index.js.map +1 -1
  55. package/esm/commands/sync/list.d.ts +7 -7
  56. package/esm/commands/sync/list.d.ts.map +1 -1
  57. package/esm/commands/sync/list.js +34 -50
  58. package/esm/commands/sync/list.js.map +1 -1
  59. package/esm/commands/sync/pull.d.ts +5 -4
  60. package/esm/commands/sync/pull.d.ts.map +1 -1
  61. package/esm/commands/sync/pull.js +21 -22
  62. package/esm/commands/sync/pull.js.map +1 -1
  63. package/esm/commands/sync/push.d.ts +4 -4
  64. package/esm/commands/sync/push.d.ts.map +1 -1
  65. package/esm/commands/sync/push.js +7 -11
  66. package/esm/commands/sync/push.js.map +1 -1
  67. package/esm/commands/sync/request.d.ts +4 -4
  68. package/esm/commands/sync/request.d.ts.map +1 -1
  69. package/esm/commands/sync/request.js +6 -6
  70. package/esm/commands/sync/request.js.map +1 -1
  71. package/esm/commands/sync/response.d.ts +5 -10
  72. package/esm/commands/sync/response.d.ts.map +1 -1
  73. package/esm/commands/sync/response.js +35 -26
  74. package/esm/commands/sync/response.js.map +1 -1
  75. package/esm/commands/sync/stat.d.ts +7 -7
  76. package/esm/commands/sync/stat.d.ts.map +1 -1
  77. package/esm/commands/sync/stat.js +48 -55
  78. package/esm/commands/sync/stat.js.map +1 -1
  79. package/esm/commands/sync/sync.d.ts +7 -7
  80. package/esm/commands/sync/sync.d.ts.map +1 -1
  81. package/esm/commands/sync/sync.js +25 -22
  82. package/esm/commands/sync/sync.js.map +1 -1
  83. package/esm/crypto.d.ts.map +1 -1
  84. package/esm/crypto.js +26 -16
  85. package/esm/crypto.js.map +1 -1
  86. package/esm/index.d.ts +9 -10
  87. package/esm/index.d.ts.map +1 -1
  88. package/esm/index.js +9 -10
  89. package/esm/index.js.map +1 -1
  90. package/esm/packet.d.ts +8 -8
  91. package/esm/packet.d.ts.map +1 -1
  92. package/esm/packet.js +14 -12
  93. package/esm/packet.js.map +1 -1
  94. package/esm/socket/dispatcher.d.ts +11 -6
  95. package/esm/socket/dispatcher.d.ts.map +1 -1
  96. package/esm/socket/dispatcher.js +28 -20
  97. package/esm/socket/dispatcher.js.map +1 -1
  98. package/esm/socket/index.d.ts +1 -1
  99. package/esm/socket/index.d.ts.map +1 -1
  100. package/esm/socket/index.js +1 -1
  101. package/esm/socket/index.js.map +1 -1
  102. package/esm/socket/socket.d.ts +5 -5
  103. package/esm/socket/socket.d.ts.map +1 -1
  104. package/esm/socket/socket.js +37 -17
  105. package/esm/socket/socket.js.map +1 -1
  106. package/esm/utils/auto-reset-event.d.ts +1 -1
  107. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  108. package/esm/utils/auto-reset-event.js +2 -2
  109. package/esm/utils/base64.d.ts +23 -0
  110. package/esm/utils/base64.d.ts.map +1 -1
  111. package/esm/utils/base64.js +36 -29
  112. package/esm/utils/base64.js.map +1 -1
  113. package/package.json +19 -17
  114. package/src/adb.ts +140 -86
  115. package/src/auth.ts +27 -18
  116. package/src/backend.ts +7 -4
  117. package/src/commands/base.ts +3 -2
  118. package/src/commands/framebuffer.ts +48 -47
  119. package/src/commands/install.ts +20 -10
  120. package/src/commands/power.ts +14 -10
  121. package/src/commands/reverse.ts +53 -33
  122. package/src/commands/subprocess/command.ts +134 -0
  123. package/src/commands/subprocess/index.ts +1 -137
  124. package/src/commands/subprocess/protocols/none.ts +10 -6
  125. package/src/commands/subprocess/protocols/shell.ts +72 -39
  126. package/src/commands/subprocess/protocols/types.ts +12 -8
  127. package/src/commands/sync/index.ts +1 -1
  128. package/src/commands/sync/list.ts +63 -68
  129. package/src/commands/sync/pull.ts +53 -37
  130. package/src/commands/sync/push.ts +26 -15
  131. package/src/commands/sync/request.ts +20 -21
  132. package/src/commands/sync/response.ts +63 -53
  133. package/src/commands/sync/stat.ts +91 -90
  134. package/src/commands/sync/sync.ts +56 -34
  135. package/src/crypto.ts +61 -33
  136. package/src/features.ts +1 -1
  137. package/src/index.ts +9 -11
  138. package/src/packet.ts +40 -30
  139. package/src/socket/dispatcher.ts +119 -77
  140. package/src/socket/index.ts +1 -1
  141. package/src/socket/socket.ts +68 -26
  142. package/src/utils/auto-reset-event.ts +3 -3
  143. package/src/utils/base64.ts +75 -42
  144. package/tsconfig.build.json +1 -1
  145. package/tsconfig.build.tsbuildinfo +1 -1
  146. package/esm/stream/buffered.d.ts +0 -39
  147. package/esm/stream/buffered.d.ts.map +0 -1
  148. package/esm/stream/buffered.js +0 -143
  149. package/esm/stream/buffered.js.map +0 -1
  150. package/esm/stream/detect.d.ts +0 -2
  151. package/esm/stream/detect.d.ts.map +0 -1
  152. package/esm/stream/detect.js +0 -6
  153. package/esm/stream/detect.js.map +0 -1
  154. package/esm/stream/detect.native.d.ts +0 -240
  155. package/esm/stream/detect.native.d.ts.map +0 -1
  156. package/esm/stream/detect.native.js +0 -60
  157. package/esm/stream/detect.native.js.map +0 -1
  158. package/esm/stream/detect.polyfill.d.ts +0 -18
  159. package/esm/stream/detect.polyfill.d.ts.map +0 -1
  160. package/esm/stream/detect.polyfill.js +0 -4
  161. package/esm/stream/detect.polyfill.js.map +0 -1
  162. package/esm/stream/index.d.ts +0 -4
  163. package/esm/stream/index.d.ts.map +0 -1
  164. package/esm/stream/index.js +0 -4
  165. package/esm/stream/index.js.map +0 -1
  166. package/esm/stream/transform.d.ts +0 -124
  167. package/esm/stream/transform.d.ts.map +0 -1
  168. package/esm/stream/transform.js +0 -379
  169. package/esm/stream/transform.js.map +0 -1
  170. package/src/stream/buffered.ts +0 -168
  171. package/src/stream/detect.native.ts +0 -362
  172. package/src/stream/detect.polyfill.ts +0 -22
  173. package/src/stream/detect.ts +0 -7
  174. package/src/stream/index.ts +0 -3
  175. package/src/stream/transform.ts +0 -474
  176. package/tsconfig.test.json +0 -9
  177. package/web-streams-polyfill-4.0.0-beta.2.tgz +0 -0
package/src/crypto.ts CHANGED
@@ -1,4 +1,7 @@
1
- import { getBigUint64, setBigUint64 } from '@yume-chan/dataview-bigint-polyfill/esm/fallback.js';
1
+ import {
2
+ getBigUint64,
3
+ setBigUint64,
4
+ } from "@yume-chan/dataview-bigint-polyfill/esm/fallback.js";
2
5
 
3
6
  const BigInt0 = BigInt(0);
4
7
  const BigInt1 = BigInt(1);
@@ -12,7 +15,11 @@ const BigInt64 = BigInt(64);
12
15
  * Only supports Big-Endian, because that's what ADB uses.
13
16
  * @param byteOffset The place in the buffer at which the value should be retrieved.
14
17
  */
15
- export function getBigUint(dataView: DataView, byteOffset: number, length: number): bigint {
18
+ export function getBigUint(
19
+ dataView: DataView,
20
+ byteOffset: number,
21
+ length: number
22
+ ): bigint {
16
23
  let result = BigInt0;
17
24
 
18
25
  // Currently `length` must be a multiplication of 8
@@ -34,7 +41,12 @@ export function getBigUint(dataView: DataView, byteOffset: number, length: numbe
34
41
  * @param littleEndian If `false` or `undefined`, a big-endian value should be written,
35
42
  * otherwise a little-endian value should be written.
36
43
  */
37
- export function setBigUint(dataView: DataView, byteOffset: number, value: bigint, littleEndian?: boolean) {
44
+ export function setBigUint(
45
+ dataView: DataView,
46
+ byteOffset: number,
47
+ value: bigint,
48
+ littleEndian?: boolean
49
+ ) {
38
50
  const start = byteOffset;
39
51
 
40
52
  if (littleEndian) {
@@ -96,9 +108,9 @@ export function parsePrivateKey(key: Uint8Array): [n: bigint, d: bigint] {
96
108
 
97
109
  // Taken from https://stackoverflow.com/a/51562038
98
110
  // I can't understand, but it does work
99
- // Only used with numbers less than 2^32 so doesn't need BigInt
111
+ // Only used with numbers smaller than 2^32 so doesn't need BigInt
100
112
  export function modInverse(a: number, m: number) {
101
- a = (a % m + m) % m;
113
+ a = ((a % m) + m) % m;
102
114
  if (!a || m < 2) {
103
115
  return NaN; // invalid input
104
116
  }
@@ -115,26 +127,24 @@ export function modInverse(a: number, m: number) {
115
127
  // find the inverse
116
128
  let x = 1;
117
129
  let y = 0;
118
- for (let i = s.length - 2; i >= 0; --i) {
130
+ for (let i = s.length - 2; i >= 0; i -= 1) {
119
131
  [x, y] = [y, x - y * Math.floor(s[i]!.a / s[i]!.b)];
120
132
  }
121
- return (y % m + m) % m;
133
+ return ((y % m) + m) % m;
122
134
  }
123
135
 
124
136
  export function calculatePublicKeyLength() {
125
137
  return 4 + 4 + 2048 / 8 + 2048 / 8 + 4;
126
138
  }
127
139
 
128
- export function calculatePublicKey(
129
- privateKey: Uint8Array
130
- ): Uint8Array;
140
+ export function calculatePublicKey(privateKey: Uint8Array): Uint8Array;
131
141
  export function calculatePublicKey(
132
142
  privateKey: Uint8Array,
133
- output: Uint8Array,
143
+ output: Uint8Array
134
144
  ): number;
135
145
  export function calculatePublicKey(
136
146
  privateKey: Uint8Array,
137
- output?: Uint8Array,
147
+ output?: Uint8Array
138
148
  ): Uint8Array | number {
139
149
  // Android has its own public key generation algorithm
140
150
  // See https://android.googlesource.com/platform/system/core.git/+/91784040db2b9273687f88d8b95f729d4a61ecc2/libcrypto_utils/android_pubkey.cpp#111
@@ -156,20 +166,24 @@ export function calculatePublicKey(
156
166
  // extract `n` from private key
157
167
  const [n] = parsePrivateKey(privateKey);
158
168
 
159
- let outputType: 'Uint8Array' | 'number';
169
+ let outputType: "Uint8Array" | "number";
160
170
  const outputLength = calculatePublicKeyLength();
161
171
  if (!output) {
162
172
  output = new Uint8Array(outputLength);
163
- outputType = 'Uint8Array';
173
+ outputType = "Uint8Array";
164
174
  } else {
165
175
  if (output.byteLength < outputLength) {
166
- throw new Error('output buffer is too small');
176
+ throw new Error("output buffer is too small");
167
177
  }
168
178
 
169
- outputType = 'number';
179
+ outputType = "number";
170
180
  }
171
181
 
172
- const outputView = new DataView(output.buffer, output.byteOffset, output.byteLength);
182
+ const outputView = new DataView(
183
+ output.buffer,
184
+ output.byteOffset,
185
+ output.byteLength
186
+ );
173
187
  let outputOffset = 0;
174
188
 
175
189
  // modulusLengthInWords
@@ -179,7 +193,10 @@ export function calculatePublicKey(
179
193
  // Calculate `n0inv`
180
194
  // Don't know why need to multiple -1
181
195
  // Didn't exist in Android codebase
182
- const n0inv = modInverse(Number(BigInt.asUintN(32, n) * BigInt(-1)), 2 ** 32);
196
+ const n0inv = modInverse(
197
+ Number(BigInt.asUintN(32, n) * BigInt(-1)),
198
+ 2 ** 32
199
+ );
183
200
  outputView.setUint32(outputOffset, n0inv, true);
184
201
  outputOffset += 4;
185
202
 
@@ -188,14 +205,14 @@ export function calculatePublicKey(
188
205
  outputOffset += 256;
189
206
 
190
207
  // Calculate rr = (2^(rsa_size)) ^ 2 mod n
191
- let rr = BigInt(2) ** BigInt(4096) % n;
208
+ const rr = BigInt(2) ** BigInt(4096) % n;
192
209
  outputOffset += setBigUint(outputView, outputOffset, rr, true);
193
210
 
194
211
  // exponent
195
212
  outputView.setUint32(outputOffset, 65537, true);
196
213
  outputOffset += 4;
197
214
 
198
- if (outputType === 'Uint8Array') {
215
+ if (outputType === "Uint8Array") {
199
216
  return output;
200
217
  } else {
201
218
  return outputLength;
@@ -209,7 +226,11 @@ export function calculatePublicKey(
209
226
  *
210
227
  * See https://en.wikipedia.org/wiki/Modular_exponentiation#Implementation_in_Lua
211
228
  */
212
- export function powMod(base: bigint, exponent: bigint, modulus: bigint): bigint {
229
+ export function powMod(
230
+ base: bigint,
231
+ exponent: bigint,
232
+ modulus: bigint
233
+ ): bigint {
213
234
  if (modulus === BigInt1) {
214
235
  return BigInt0;
215
236
  }
@@ -219,7 +240,7 @@ export function powMod(base: bigint, exponent: bigint, modulus: bigint): bigint
219
240
 
220
241
  while (exponent > BigInt0) {
221
242
  if (BigInt.asUintN(1, exponent) === BigInt1) {
222
- r = r * base % modulus;
243
+ r = (r * base) % modulus;
223
244
  }
224
245
 
225
246
  exponent >>= BigInt1;
@@ -238,12 +259,22 @@ export const ASN1_OID = 0x06;
238
259
 
239
260
  // PKCS#1 SHA-1 hash digest info
240
261
  export const SHA1_DIGEST_INFO = new Uint8Array([
241
- ASN1_SEQUENCE, 0x0d + SHA1_DIGEST_LENGTH,
242
- ASN1_SEQUENCE, 0x09,
262
+ ASN1_SEQUENCE,
263
+ 0x0d + SHA1_DIGEST_LENGTH,
264
+ ASN1_SEQUENCE,
265
+ 0x09,
243
266
  // SHA-1 (1 3 14 3 2 26)
244
- ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, 26,
245
- ASN1_NULL, 0x00,
246
- ASN1_OCTET_STRING, SHA1_DIGEST_LENGTH
267
+ ASN1_OID,
268
+ 0x05,
269
+ 1 * 40 + 3,
270
+ 14,
271
+ 3,
272
+ 2,
273
+ 26,
274
+ ASN1_NULL,
275
+ 0x00,
276
+ ASN1_OCTET_STRING,
277
+ SHA1_DIGEST_LENGTH,
247
278
  ]);
248
279
 
249
280
  // SubtleCrypto.sign() will hash the given data and sign the hash
@@ -265,7 +296,8 @@ export function sign(privateKey: Uint8Array, data: Uint8Array): Uint8Array {
265
296
  padded[index] = 1;
266
297
  index += 1;
267
298
 
268
- const fillLength = padded.length - SHA1_DIGEST_INFO.length - data.length - 1;
299
+ const fillLength =
300
+ padded.length - SHA1_DIGEST_INFO.length - data.length - 1;
269
301
  while (index < fillLength) {
270
302
  padded[index] = 0xff;
271
303
  index += 1;
@@ -282,11 +314,7 @@ export function sign(privateKey: Uint8Array, data: Uint8Array): Uint8Array {
282
314
  // Encryption
283
315
  // signature = padded ** d % n
284
316
  const view = new DataView(padded.buffer);
285
- const signature = powMod(
286
- getBigUint(view, 0, view.byteLength),
287
- d,
288
- n
289
- );
317
+ const signature = powMod(getBigUint(view, 0, view.byteLength), d, n);
290
318
 
291
319
  // `padded` is not used anymore,
292
320
  // re-use the buffer to store the result
package/src/features.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // The order follows
2
2
  // https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
3
3
  export enum AdbFeatures {
4
- ShellV2 = "shell_v2",
4
+ ShellV2 = 'shell_v2',
5
5
  Cmd = 'cmd',
6
6
  StatV2 = 'stat_v2',
7
7
  ListV2 = 'ls_v2',
package/src/index.ts CHANGED
@@ -1,11 +1,9 @@
1
-
2
- export * from './adb.js';
3
- export * from './auth.js';
4
- export * from './backend.js';
5
- export * from './commands/index.js';
6
- export * from './crypto.js';
7
- export * from './features.js';
8
- export * from './packet.js';
9
- export * from './socket/index.js';
10
- export * from './stream/index.js';
11
- export * from './utils/index.js';
1
+ export * from "./adb.js";
2
+ export * from "./auth.js";
3
+ export * from "./backend.js";
4
+ export * from "./commands/index.js";
5
+ export * from "./crypto.js";
6
+ export * from "./features.js";
7
+ export * from "./packet.js";
8
+ export * from "./socket/index.js";
9
+ export * from "./utils/index.js";
package/src/packet.ts CHANGED
@@ -1,34 +1,32 @@
1
- import Struct from '@yume-chan/struct';
2
- import { TransformStream } from "./stream/index.js";
1
+ import { TransformStream } from "@yume-chan/stream-extra";
2
+ import Struct from "@yume-chan/struct";
3
3
 
4
4
  export enum AdbCommand {
5
- Auth = 0x48545541, // 'AUTH'
6
- Close = 0x45534c43, // 'CLSE'
5
+ Auth = 0x48545541, // 'AUTH'
6
+ Close = 0x45534c43, // 'CLSE'
7
7
  Connect = 0x4e584e43, // 'CNXN'
8
- OK = 0x59414b4f, // 'OKAY'
9
- Open = 0x4e45504f, // 'OPEN'
10
- Write = 0x45545257, // 'WRTE'
8
+ OK = 0x59414b4f, // 'OKAY'
9
+ Open = 0x4e45504f, // 'OPEN'
10
+ Write = 0x45545257, // 'WRTE'
11
11
  }
12
12
 
13
- export const AdbPacketHeader =
14
- new Struct({ littleEndian: true })
15
- .uint32('command')
16
- .uint32('arg0')
17
- .uint32('arg1')
18
- .uint32('payloadLength')
19
- .uint32('checksum')
20
- .int32('magic');
13
+ export const AdbPacketHeader = new Struct({ littleEndian: true })
14
+ .uint32("command")
15
+ .uint32("arg0")
16
+ .uint32("arg1")
17
+ .uint32("payloadLength")
18
+ .uint32("checksum")
19
+ .int32("magic");
21
20
 
22
- export type AdbPacketHeader = typeof AdbPacketHeader['TDeserializeResult'];
21
+ export type AdbPacketHeader = typeof AdbPacketHeader["TDeserializeResult"];
23
22
 
24
- type AdbPacketHeaderInit = typeof AdbPacketHeader['TInit'];
23
+ type AdbPacketHeaderInit = typeof AdbPacketHeader["TInit"];
25
24
 
26
- export const AdbPacket =
27
- new Struct({ littleEndian: true })
28
- .fields(AdbPacketHeader)
29
- .uint8Array('payload', { lengthField: 'payloadLength' });
25
+ export const AdbPacket = new Struct({ littleEndian: true })
26
+ .fields(AdbPacketHeader)
27
+ .uint8Array("payload", { lengthField: "payloadLength" });
30
28
 
31
- export type AdbPacket = typeof AdbPacket['TDeserializeResult'];
29
+ export type AdbPacket = typeof AdbPacket["TDeserializeResult"];
32
30
 
33
31
  /**
34
32
  * `AdbPacketData` contains all the useful fields of `AdbPacket`.
@@ -40,29 +38,41 @@ export type AdbPacket = typeof AdbPacket['TDeserializeResult'];
40
38
  * however, `AdbPacketDispatcher` will transform `AdbPacketData` to `AdbPacketInit` for you,
41
39
  * so `AdbSocket#writable#write` only needs `AdbPacketData`.
42
40
  */
43
- export type AdbPacketData = Omit<typeof AdbPacket['TInit'], 'checksum' | 'magic'>;
41
+ export type AdbPacketData = Omit<
42
+ typeof AdbPacket["TInit"],
43
+ "checksum" | "magic"
44
+ >;
44
45
 
45
46
  // All fields except `magic`, which can be calculated in `AdbPacketSerializeStream`
46
- export type AdbPacketInit = Omit<typeof AdbPacket['TInit'], 'magic'>;
47
+ export type AdbPacketInit = Omit<typeof AdbPacket["TInit"], "magic">;
47
48
 
48
49
  export function calculateChecksum(payload: Uint8Array): number;
49
50
  export function calculateChecksum(init: AdbPacketData): AdbPacketInit;
50
- export function calculateChecksum(payload: Uint8Array | AdbPacketData): number | AdbPacketInit {
51
+ export function calculateChecksum(
52
+ payload: Uint8Array | AdbPacketData
53
+ ): number | AdbPacketInit {
51
54
  if (payload instanceof Uint8Array) {
52
55
  return payload.reduce((result, item) => result + item, 0);
53
56
  } else {
54
- (payload as AdbPacketInit).checksum = calculateChecksum(payload.payload);
57
+ (payload as AdbPacketInit).checksum = calculateChecksum(
58
+ payload.payload
59
+ );
55
60
  return payload as AdbPacketInit;
56
61
  }
57
62
  }
58
63
 
59
- export class AdbPacketSerializeStream extends TransformStream<AdbPacketInit, Uint8Array>{
64
+ export class AdbPacketSerializeStream extends TransformStream<
65
+ AdbPacketInit,
66
+ Uint8Array
67
+ > {
60
68
  public constructor() {
61
69
  super({
62
- transform: async (init, controller) => {
70
+ transform: (init, controller) => {
63
71
  // This syntax is ugly, but I don't want to create a new object.
64
- (init as unknown as AdbPacketHeaderInit).magic = init.command ^ 0xFFFFFFFF;
65
- (init as unknown as AdbPacketHeaderInit).payloadLength = init.payload.byteLength;
72
+ (init as unknown as AdbPacketHeaderInit).magic =
73
+ init.command ^ 0xffffffff;
74
+ (init as unknown as AdbPacketHeaderInit).payloadLength =
75
+ init.payload.byteLength;
66
76
 
67
77
  controller.enqueue(
68
78
  AdbPacketHeader.serialize(
@@ -1,11 +1,22 @@
1
- import { AsyncOperationManager, PromiseResolver } from '@yume-chan/async';
2
- import type { RemoveEventListener } from '@yume-chan/event';
1
+ import { AsyncOperationManager, PromiseResolver } from "@yume-chan/async";
2
+ import { type RemoveEventListener } from "@yume-chan/event";
3
+ import {
4
+ AbortController,
5
+ WritableStream,
6
+ type ReadableWritablePair,
7
+ type WritableStreamDefaultWriter,
8
+ } from "@yume-chan/stream-extra";
3
9
  import { EMPTY_UINT8_ARRAY, type ValueOrPromise } from "@yume-chan/struct";
4
10
 
5
- import { AdbCommand, calculateChecksum, type AdbPacketData, type AdbPacketInit } from '../packet.js';
6
- import { AbortController, WritableStream, WritableStreamDefaultWriter, type ReadableWritablePair } from '../stream/index.js';
7
- import { decodeUtf8, encodeUtf8 } from '../utils/index.js';
8
- import { AdbSocket, AdbSocketController } from './socket.js';
11
+ import {
12
+ AdbCommand,
13
+ calculateChecksum,
14
+ type AdbPacketData,
15
+ type AdbPacketInit,
16
+ } from "../packet.js";
17
+ import { decodeUtf8, encodeUtf8 } from "../utils/index.js";
18
+
19
+ import { AdbSocketController, type AdbSocket } from "./socket.js";
9
20
 
10
21
  export interface AdbPacketDispatcherOptions {
11
22
  calculateChecksum: boolean;
@@ -19,7 +30,9 @@ export interface AdbPacketDispatcherOptions {
19
30
  maxPayloadSize: number;
20
31
  }
21
32
 
22
- export type AdbIncomingSocketHandler = (socket: AdbSocket) => ValueOrPromise<boolean>;
33
+ export type AdbIncomingSocketHandler = (
34
+ socket: AdbSocket
35
+ ) => ValueOrPromise<boolean>;
23
36
 
24
37
  export interface Closeable {
25
38
  close(): ValueOrPromise<void>;
@@ -50,7 +63,9 @@ export class AdbPacketDispatcher implements Closeable {
50
63
 
51
64
  private _closed = false;
52
65
  private _disconnected = new PromiseResolver<void>();
53
- public get disconnected() { return this._disconnected.promise; }
66
+ public get disconnected() {
67
+ return this._disconnected.promise;
68
+ }
54
69
 
55
70
  private _incomingSocketHandlers: Set<AdbIncomingSocketHandler> = new Set();
56
71
 
@@ -63,53 +78,68 @@ export class AdbPacketDispatcher implements Closeable {
63
78
  this.options = options;
64
79
 
65
80
  connection.readable
66
- .pipeTo(new WritableStream({
67
- write: async (packet) => {
68
- switch (packet.command) {
69
- case AdbCommand.OK:
70
- this.handleOk(packet);
71
- break;
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);
81
+ .pipeTo(
82
+ new WritableStream({
83
+ write: async (packet) => {
84
+ switch (packet.command) {
85
+ case AdbCommand.OK:
86
+ this.handleOk(packet);
79
87
  break;
80
- }
81
- throw new Error(`Unknown local socket id: ${packet.arg1}`);
82
- case AdbCommand.Open:
83
- await this.handleOpen(packet);
84
- break;
85
- default:
86
- // Junk data may only appear in the authentication phase,
87
- // since the dispatcher only works after authentication,
88
- // all packets should have a valid command.
89
- // (although it's possible that Adb added new commands in the future)
90
- throw new Error(`Unknown command: ${packet.command.toString(16)}`);
91
- }
88
+ case AdbCommand.Close:
89
+ await this.handleClose(packet);
90
+ break;
91
+ case AdbCommand.Write:
92
+ if (this.sockets.has(packet.arg1)) {
93
+ await this.sockets
94
+ .get(packet.arg1)!
95
+ .enqueue(packet.payload);
96
+ await this.sendPacket(
97
+ AdbCommand.OK,
98
+ packet.arg1,
99
+ packet.arg0
100
+ );
101
+ break;
102
+ }
103
+ throw new Error(
104
+ `Unknown local socket id: ${packet.arg1}`
105
+ );
106
+ case AdbCommand.Open:
107
+ await this.handleOpen(packet);
108
+ break;
109
+ default:
110
+ // Junk data may only appear in the authentication phase,
111
+ // since the dispatcher only works after authentication,
112
+ // all packets should have a valid command.
113
+ // (although it's possible that Adb added new commands in the future)
114
+ throw new Error(
115
+ `Unknown command: ${packet.command.toString(
116
+ 16
117
+ )}`
118
+ );
119
+ }
120
+ },
121
+ }),
122
+ {
123
+ // There are multiple reasons for the pipe to stop,
124
+ // (device disconnection, protocol error, or user abortion)
125
+ // if the underlying streams are still open,
126
+ // it's still possible to create another ADB connection.
127
+ // So don't close `readable` here.
128
+ preventCancel: true,
129
+ signal: this._abortController.signal,
130
+ }
131
+ )
132
+ .then(
133
+ () => {
134
+ this.dispose();
92
135
  },
93
- }), {
94
- // There are multiple reasons for the pipe to stop,
95
- // (device disconnection, protocol error, or user abortion)
96
- // if the underlying streams are still open,
97
- // it's still possible to create another ADB connection.
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);
136
+ (e) => {
137
+ if (!this._closed) {
138
+ this._disconnected.reject(e);
139
+ }
140
+ this.dispose();
110
141
  }
111
- this.dispose();
112
- });
142
+ );
113
143
 
114
144
  this._writer = connection.writable.getWriter();
115
145
  }
@@ -129,13 +159,18 @@ export class AdbPacketDispatcher implements Closeable {
129
159
 
130
160
  // Maybe the device is responding to a packet of last connection
131
161
  // Tell the device to close the socket
132
- this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
162
+ void this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
133
163
  }
134
164
 
135
165
  private async handleClose(packet: AdbPacketData) {
136
166
  // If the socket is still pending
137
- if (packet.arg0 === 0 &&
138
- this.initializers.reject(packet.arg1, new Error('Socket open failed'))) {
167
+ if (
168
+ packet.arg0 === 0 &&
169
+ this.initializers.reject(
170
+ packet.arg1,
171
+ new Error("Socket open failed")
172
+ )
173
+ ) {
139
174
  // Device failed to create the socket
140
175
  // (unknown service string, failed to execute command, etc.)
141
176
  // it doesn't break the connection,
@@ -156,9 +191,13 @@ export class AdbPacketDispatcher implements Closeable {
156
191
  if (socket) {
157
192
  // The device want to close the socket
158
193
  if (!socket.closed) {
159
- await this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
194
+ await this.sendPacket(
195
+ AdbCommand.Close,
196
+ packet.arg1,
197
+ packet.arg0
198
+ );
160
199
  }
161
- socket.dispose();
200
+ await socket.dispose();
162
201
  this.sockets.delete(packet.arg1);
163
202
  return;
164
203
  }
@@ -168,7 +207,14 @@ export class AdbPacketDispatcher implements Closeable {
168
207
  // the device may also respond with two `CLSE` packets.
169
208
  }
170
209
 
171
- public addIncomingSocketHandler(handler: AdbIncomingSocketHandler): RemoveEventListener {
210
+ /**
211
+ * Add a handler for incoming socket.
212
+ * @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.
213
+ * @returns A function to remove the handler.
214
+ */
215
+ public onIncomingSocket(
216
+ handler: AdbIncomingSocketHandler
217
+ ): RemoveEventListener {
172
218
  this._incomingSocketHandlers.add(handler);
173
219
  const remove = () => {
174
220
  this._incomingSocketHandlers.delete(handler);
@@ -178,7 +224,7 @@ export class AdbPacketDispatcher implements Closeable {
178
224
  }
179
225
 
180
226
  private async handleOpen(packet: AdbPacketData) {
181
- // AsyncOperationManager doesn't support get and skip an ID
227
+ // `AsyncOperationManager` doesn't support skipping IDs
182
228
  // Use `add` + `resolve` to simulate this behavior
183
229
  const [localId] = this.initializers.add<number>();
184
230
  this.initializers.resolve(localId, undefined);
@@ -207,16 +253,11 @@ export class AdbPacketDispatcher implements Closeable {
207
253
 
208
254
  public async createSocket(serviceString: string): Promise<AdbSocket> {
209
255
  if (this.options.appendNullToServiceString) {
210
- serviceString += '\0';
256
+ serviceString += "\0";
211
257
  }
212
258
 
213
259
  const [localId, initializer] = this.initializers.add<number>();
214
- await this.sendPacket(
215
- AdbCommand.Open,
216
- localId,
217
- 0,
218
- serviceString
219
- );
260
+ await this.sendPacket(AdbCommand.Open, localId, 0, serviceString);
220
261
 
221
262
  // Fulfilled by `handleOk`
222
263
  const remoteId = await initializer;
@@ -243,27 +284,29 @@ export class AdbPacketDispatcher implements Closeable {
243
284
  packetOrCommand: AdbPacketInit | AdbCommand,
244
285
  arg0?: number,
245
286
  arg1?: number,
246
- payload: string | Uint8Array = EMPTY_UINT8_ARRAY,
287
+ payload: string | Uint8Array = EMPTY_UINT8_ARRAY
247
288
  ): Promise<void> {
248
289
  let init: AdbPacketData;
249
290
  if (arg0 === undefined) {
250
291
  init = packetOrCommand as AdbPacketInit;
251
292
  } else {
252
- if (typeof payload === 'string') {
293
+ if (typeof payload === "string") {
253
294
  payload = encodeUtf8(payload);
254
295
  }
255
296
 
256
297
  init = {
257
298
  command: packetOrCommand as AdbCommand,
258
- arg0: arg0 as number,
299
+ arg0: arg0,
259
300
  arg1: arg1 as number,
260
301
  payload,
261
302
  };
262
303
  }
263
304
 
264
- if (init.payload &&
265
- init.payload.byteLength > this.options.maxPayloadSize) {
266
- throw new Error('payload too large');
305
+ if (
306
+ init.payload &&
307
+ init.payload.byteLength > this.options.maxPayloadSize
308
+ ) {
309
+ throw new Error("payload too large");
267
310
  }
268
311
 
269
312
  if (this.options.calculateChecksum) {
@@ -279,10 +322,7 @@ export class AdbPacketDispatcher implements Closeable {
279
322
  public async close() {
280
323
  // Send `CLSE` packets for all sockets
281
324
  await Promise.all(
282
- Array.from(
283
- this.sockets.values(),
284
- socket => socket.close(),
285
- )
325
+ Array.from(this.sockets.values(), (socket) => socket.close())
286
326
  );
287
327
 
288
328
  // Stop receiving
@@ -297,7 +337,9 @@ export class AdbPacketDispatcher implements Closeable {
297
337
 
298
338
  private dispose() {
299
339
  for (const socket of this.sockets.values()) {
300
- socket.dispose();
340
+ socket.dispose().catch((e) => {
341
+ void e;
342
+ });
301
343
  }
302
344
 
303
345
  this._disconnected.resolve();
@@ -1,2 +1,2 @@
1
- export * from './socket.js';
2
1
  export * from './dispatcher.js';
2
+ export * from './socket.js';