@yume-chan/adb 0.0.18 → 0.0.20

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 (241) hide show
  1. package/CHANGELOG.json +54 -0
  2. package/CHANGELOG.md +25 -1
  3. package/README.md +220 -103
  4. package/esm/adb.d.ts +43 -60
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +68 -249
  7. package/esm/adb.js.map +1 -1
  8. package/esm/banner.d.ts +17 -0
  9. package/esm/banner.d.ts.map +1 -0
  10. package/esm/banner.js +67 -0
  11. package/esm/banner.js.map +1 -0
  12. package/esm/commands/base.d.ts +6 -6
  13. package/esm/commands/base.d.ts.map +1 -1
  14. package/esm/commands/base.js +8 -8
  15. package/esm/commands/framebuffer.d.ts +53 -53
  16. package/esm/commands/framebuffer.d.ts.map +1 -1
  17. package/esm/commands/framebuffer.js +46 -46
  18. package/esm/commands/framebuffer.js.map +1 -1
  19. package/esm/commands/index.d.ts +7 -8
  20. package/esm/commands/index.d.ts.map +1 -1
  21. package/esm/commands/index.js +7 -8
  22. package/esm/commands/index.js.map +1 -1
  23. package/esm/commands/power.d.ts +22 -22
  24. package/esm/commands/power.js +48 -48
  25. package/esm/commands/reverse.d.ts +40 -28
  26. package/esm/commands/reverse.d.ts.map +1 -1
  27. package/esm/commands/reverse.js +130 -100
  28. package/esm/commands/reverse.js.map +1 -1
  29. package/esm/commands/subprocess/command.d.ts +57 -51
  30. package/esm/commands/subprocess/command.d.ts.map +1 -1
  31. package/esm/commands/subprocess/command.js +86 -80
  32. package/esm/commands/subprocess/command.js.map +1 -1
  33. package/esm/commands/subprocess/index.d.ts +3 -3
  34. package/esm/commands/subprocess/index.js +3 -3
  35. package/esm/commands/subprocess/protocols/index.d.ts +3 -3
  36. package/esm/commands/subprocess/protocols/index.js +3 -3
  37. package/esm/commands/subprocess/protocols/none.d.ts +30 -35
  38. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  39. package/esm/commands/subprocess/protocols/none.js +65 -55
  40. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  41. package/esm/commands/subprocess/protocols/shell.d.ts +33 -38
  42. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  43. package/esm/commands/subprocess/protocols/shell.js +172 -162
  44. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  45. package/esm/commands/subprocess/protocols/types.d.ts +48 -49
  46. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/types.js +1 -1
  48. package/esm/commands/subprocess/utils.d.ts +1 -1
  49. package/esm/commands/subprocess/utils.js +18 -18
  50. package/esm/commands/sync/index.d.ts +8 -7
  51. package/esm/commands/sync/index.d.ts.map +1 -1
  52. package/esm/commands/sync/index.js +8 -7
  53. package/esm/commands/sync/index.js.map +1 -1
  54. package/esm/commands/sync/list.d.ts +42 -40
  55. package/esm/commands/sync/list.d.ts.map +1 -1
  56. package/esm/commands/sync/list.js +67 -47
  57. package/esm/commands/sync/list.js.map +1 -1
  58. package/esm/commands/sync/pull.d.ts +13 -11
  59. package/esm/commands/sync/pull.d.ts.map +1 -1
  60. package/esm/commands/sync/pull.js +35 -37
  61. package/esm/commands/sync/pull.js.map +1 -1
  62. package/esm/commands/sync/push.d.ts +57 -7
  63. package/esm/commands/sync/push.d.ts.map +1 -1
  64. package/esm/commands/sync/push.js +89 -22
  65. package/esm/commands/sync/push.js.map +1 -1
  66. package/esm/commands/sync/request.d.ts +26 -23
  67. package/esm/commands/sync/request.d.ts.map +1 -1
  68. package/esm/commands/sync/request.js +40 -42
  69. package/esm/commands/sync/request.js.map +1 -1
  70. package/esm/commands/sync/response.d.ts +19 -19
  71. package/esm/commands/sync/response.d.ts.map +1 -1
  72. package/esm/commands/sync/response.js +54 -54
  73. package/esm/commands/sync/response.js.map +1 -1
  74. package/esm/commands/sync/socket.d.ts +22 -0
  75. package/esm/commands/sync/socket.d.ts.map +1 -0
  76. package/esm/commands/sync/socket.js +69 -0
  77. package/esm/commands/sync/socket.js.map +1 -0
  78. package/esm/commands/sync/stat.d.ts +72 -72
  79. package/esm/commands/sync/stat.d.ts.map +1 -1
  80. package/esm/commands/sync/stat.js +116 -104
  81. package/esm/commands/sync/stat.js.map +1 -1
  82. package/esm/commands/sync/sync.d.ts +65 -60
  83. package/esm/commands/sync/sync.d.ts.map +1 -1
  84. package/esm/commands/sync/sync.js +123 -149
  85. package/esm/commands/sync/sync.js.map +1 -1
  86. package/esm/commands/tcpip.d.ts +5 -5
  87. package/esm/commands/tcpip.d.ts.map +1 -1
  88. package/esm/commands/tcpip.js +20 -18
  89. package/esm/commands/tcpip.js.map +1 -1
  90. package/esm/{auth.d.ts → daemon/auth.d.ts} +50 -51
  91. package/esm/daemon/auth.d.ts.map +1 -0
  92. package/esm/{auth.js → daemon/auth.js} +95 -96
  93. package/esm/daemon/auth.js.map +1 -0
  94. package/esm/daemon/connection.d.ts +11 -0
  95. package/esm/daemon/connection.d.ts.map +1 -0
  96. package/esm/daemon/connection.js +2 -0
  97. package/esm/daemon/connection.js.map +1 -0
  98. package/esm/{crypto.d.ts → daemon/crypto.d.ts} +36 -36
  99. package/esm/daemon/crypto.d.ts.map +1 -0
  100. package/esm/{crypto.js → daemon/crypto.js} +244 -248
  101. package/esm/daemon/crypto.js.map +1 -0
  102. package/esm/daemon/device.d.ts +9 -0
  103. package/esm/daemon/device.d.ts.map +1 -0
  104. package/esm/daemon/device.js +2 -0
  105. package/esm/daemon/device.js.map +1 -0
  106. package/esm/daemon/dispatcher.d.ts +42 -0
  107. package/esm/daemon/dispatcher.d.ts.map +1 -0
  108. package/esm/{socket → daemon}/dispatcher.js +225 -234
  109. package/esm/daemon/dispatcher.js.map +1 -0
  110. package/esm/daemon/index.d.ts +8 -0
  111. package/esm/daemon/index.d.ts.map +1 -0
  112. package/esm/daemon/index.js +8 -0
  113. package/esm/daemon/index.js.map +1 -0
  114. package/esm/{packet.d.ts → daemon/packet.d.ts} +45 -46
  115. package/esm/daemon/packet.d.ts.map +1 -0
  116. package/esm/{packet.js → daemon/packet.js} +43 -48
  117. package/esm/daemon/packet.js.map +1 -0
  118. package/esm/daemon/socket.d.ts +58 -0
  119. package/esm/daemon/socket.d.ts.map +1 -0
  120. package/esm/{socket → daemon}/socket.js +121 -118
  121. package/esm/daemon/socket.js.map +1 -0
  122. package/esm/daemon/transport.d.ts +45 -0
  123. package/esm/daemon/transport.d.ts.map +1 -0
  124. package/esm/daemon/transport.js +184 -0
  125. package/esm/daemon/transport.js.map +1 -0
  126. package/esm/features.d.ts +10 -7
  127. package/esm/features.d.ts.map +1 -1
  128. package/esm/features.js +13 -10
  129. package/esm/features.js.map +1 -1
  130. package/esm/index.d.ts +7 -9
  131. package/esm/index.d.ts.map +1 -1
  132. package/esm/index.js +7 -9
  133. package/esm/index.js.map +1 -1
  134. package/esm/server/client.d.ts +78 -0
  135. package/esm/server/client.d.ts.map +1 -0
  136. package/esm/server/client.js +329 -0
  137. package/esm/server/client.js.map +1 -0
  138. package/esm/server/index.d.ts +3 -0
  139. package/esm/server/index.d.ts.map +1 -0
  140. package/esm/server/index.js +3 -0
  141. package/esm/server/index.js.map +1 -0
  142. package/esm/server/transport.d.ts +19 -0
  143. package/esm/server/transport.d.ts.map +1 -0
  144. package/esm/server/transport.js +44 -0
  145. package/esm/server/transport.js.map +1 -0
  146. package/esm/utils/auto-reset-event.d.ts +8 -9
  147. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  148. package/esm/utils/auto-reset-event.js +33 -33
  149. package/esm/utils/auto-reset-event.js.map +1 -1
  150. package/esm/utils/base64.d.ts +27 -27
  151. package/esm/utils/base64.js +246 -246
  152. package/esm/utils/base64.js.map +1 -1
  153. package/esm/utils/conditional-variable.d.ts +8 -0
  154. package/esm/utils/conditional-variable.d.ts.map +1 -0
  155. package/esm/utils/conditional-variable.js +34 -0
  156. package/esm/utils/conditional-variable.js.map +1 -0
  157. package/esm/utils/hex.d.ts +3 -0
  158. package/esm/utils/hex.d.ts.map +1 -0
  159. package/esm/utils/hex.js +55 -0
  160. package/esm/utils/hex.js.map +1 -0
  161. package/esm/utils/index.d.ts +6 -3
  162. package/esm/utils/index.d.ts.map +1 -1
  163. package/esm/utils/index.js +6 -3
  164. package/esm/utils/index.js.map +1 -1
  165. package/esm/utils/no-op.d.ts +7 -0
  166. package/esm/utils/no-op.d.ts.map +1 -0
  167. package/esm/utils/no-op.js +12 -0
  168. package/esm/utils/no-op.js.map +1 -0
  169. package/package.json +14 -12
  170. package/src/adb.ts +47 -248
  171. package/src/banner.ts +82 -0
  172. package/src/commands/base.ts +1 -1
  173. package/src/commands/framebuffer.ts +4 -4
  174. package/src/commands/index.ts +7 -8
  175. package/src/commands/power.ts +2 -2
  176. package/src/commands/reverse.ts +90 -70
  177. package/src/commands/subprocess/command.ts +12 -4
  178. package/src/commands/subprocess/index.ts +3 -3
  179. package/src/commands/subprocess/protocols/index.ts +3 -3
  180. package/src/commands/subprocess/protocols/none.ts +36 -23
  181. package/src/commands/subprocess/protocols/shell.ts +94 -74
  182. package/src/commands/subprocess/protocols/types.ts +7 -7
  183. package/src/commands/subprocess/utils.ts +1 -1
  184. package/src/commands/sync/index.ts +8 -7
  185. package/src/commands/sync/list.ts +44 -25
  186. package/src/commands/sync/pull.ts +40 -45
  187. package/src/commands/sync/push.ts +158 -39
  188. package/src/commands/sync/request.ts +21 -16
  189. package/src/commands/sync/response.ts +10 -9
  190. package/src/commands/sync/socket.ts +99 -0
  191. package/src/commands/sync/stat.ts +47 -42
  192. package/src/commands/sync/sync.ts +73 -116
  193. package/src/commands/tcpip.ts +9 -7
  194. package/src/{auth.ts → daemon/auth.ts} +24 -23
  195. package/src/{crypto.ts → daemon/crypto.ts} +25 -33
  196. package/src/daemon/device.ts +14 -0
  197. package/src/{socket → daemon}/dispatcher.ts +95 -117
  198. package/src/daemon/index.ts +7 -0
  199. package/src/daemon/packet.ts +75 -0
  200. package/src/{socket → daemon}/socket.ts +71 -56
  201. package/src/daemon/transport.ts +269 -0
  202. package/src/features.ts +9 -6
  203. package/src/index.ts +3 -5
  204. package/src/server/client.ts +476 -0
  205. package/src/server/index.ts +2 -0
  206. package/src/server/transport.ts +77 -0
  207. package/src/utils/auto-reset-event.ts +14 -15
  208. package/src/utils/conditional-variable.ts +45 -0
  209. package/src/utils/hex.ts +58 -0
  210. package/src/utils/index.ts +6 -3
  211. package/src/utils/no-op.ts +12 -0
  212. package/tsconfig.build.json +12 -1
  213. package/tsconfig.build.tsbuildinfo +1 -1
  214. package/esm/auth.d.ts.map +0 -1
  215. package/esm/auth.js.map +0 -1
  216. package/esm/backend.d.ts +0 -9
  217. package/esm/backend.d.ts.map +0 -1
  218. package/esm/backend.js +0 -2
  219. package/esm/backend.js.map +0 -1
  220. package/esm/commands/install.d.ts +0 -4
  221. package/esm/commands/install.d.ts.map +0 -1
  222. package/esm/commands/install.js +0 -29
  223. package/esm/commands/install.js.map +0 -1
  224. package/esm/crypto.d.ts.map +0 -1
  225. package/esm/crypto.js.map +0 -1
  226. package/esm/packet.d.ts.map +0 -1
  227. package/esm/packet.js.map +0 -1
  228. package/esm/socket/dispatcher.d.ts +0 -60
  229. package/esm/socket/dispatcher.d.ts.map +0 -1
  230. package/esm/socket/dispatcher.js.map +0 -1
  231. package/esm/socket/index.d.ts +0 -3
  232. package/esm/socket/index.d.ts.map +0 -1
  233. package/esm/socket/index.js +0 -3
  234. package/esm/socket/index.js.map +0 -1
  235. package/esm/socket/socket.d.ts +0 -60
  236. package/esm/socket/socket.d.ts.map +0 -1
  237. package/esm/socket/socket.js.map +0 -1
  238. package/src/backend.ts +0 -14
  239. package/src/commands/install.ts +0 -40
  240. package/src/packet.ts +0 -90
  241. package/src/socket/index.ts +0 -2
@@ -1,49 +1,44 @@
1
- import { TransformStream } from "@yume-chan/stream-extra";
2
- import Struct from "@yume-chan/struct";
3
- export var AdbCommand;
4
- (function (AdbCommand) {
5
- AdbCommand[AdbCommand["Auth"] = 1213486401] = "Auth";
6
- AdbCommand[AdbCommand["Close"] = 1163086915] = "Close";
7
- AdbCommand[AdbCommand["Connect"] = 1314410051] = "Connect";
8
- AdbCommand[AdbCommand["OK"] = 1497451343] = "OK";
9
- AdbCommand[AdbCommand["Open"] = 1313165391] = "Open";
10
- AdbCommand[AdbCommand["Write"] = 1163154007] = "Write";
11
- })(AdbCommand = AdbCommand || (AdbCommand = {}));
12
- export const AdbPacketHeader = new Struct({ littleEndian: true })
13
- .uint32("command")
14
- .uint32("arg0")
15
- .uint32("arg1")
16
- .uint32("payloadLength")
17
- .uint32("checksum")
18
- .int32("magic");
19
- export const AdbPacket = new Struct({ littleEndian: true })
20
- .fields(AdbPacketHeader)
21
- .uint8Array("payload", { lengthField: "payloadLength" });
22
- export function calculateChecksum(payload) {
23
- if (payload instanceof Uint8Array) {
24
- return payload.reduce((result, item) => result + item, 0);
25
- }
26
- else {
27
- payload.checksum = calculateChecksum(payload.payload);
28
- return payload;
29
- }
30
- }
31
- export class AdbPacketSerializeStream extends TransformStream {
32
- constructor() {
33
- super({
34
- transform: (init, controller) => {
35
- // This syntax is ugly, but I don't want to create a new object.
36
- init.magic =
37
- init.command ^ 0xffffffff;
38
- init.payloadLength =
39
- init.payload.byteLength;
40
- controller.enqueue(AdbPacketHeader.serialize(init));
41
- if (init.payload.byteLength) {
42
- // Enqueue payload separately to avoid copying
43
- controller.enqueue(init.payload);
44
- }
45
- },
46
- });
47
- }
48
- }
1
+ import { ConsumableTransformStream } from "@yume-chan/stream-extra";
2
+ import Struct from "@yume-chan/struct";
3
+ export var AdbCommand;
4
+ (function (AdbCommand) {
5
+ AdbCommand[AdbCommand["Auth"] = 1213486401] = "Auth";
6
+ AdbCommand[AdbCommand["Close"] = 1163086915] = "Close";
7
+ AdbCommand[AdbCommand["Connect"] = 1314410051] = "Connect";
8
+ AdbCommand[AdbCommand["OK"] = 1497451343] = "OK";
9
+ AdbCommand[AdbCommand["Open"] = 1313165391] = "Open";
10
+ AdbCommand[AdbCommand["Write"] = 1163154007] = "Write";
11
+ })(AdbCommand = AdbCommand || (AdbCommand = {}));
12
+ export const AdbPacketHeader = new Struct({ littleEndian: true })
13
+ .uint32("command")
14
+ .uint32("arg0")
15
+ .uint32("arg1")
16
+ .uint32("payloadLength")
17
+ .uint32("checksum")
18
+ .int32("magic");
19
+ export const AdbPacket = new Struct({ littleEndian: true })
20
+ .concat(AdbPacketHeader)
21
+ .uint8Array("payload", { lengthField: "payloadLength" });
22
+ export function calculateChecksum(payload) {
23
+ return payload.reduce((result, item) => result + item, 0);
24
+ }
25
+ export class AdbPacketSerializeStream extends ConsumableTransformStream {
26
+ constructor() {
27
+ const headerBuffer = new Uint8Array(AdbPacketHeader.size);
28
+ super({
29
+ transform: async (chunk, controller) => {
30
+ const init = chunk;
31
+ init.payloadLength = init.payload.byteLength;
32
+ AdbPacketHeader.serialize(init, headerBuffer);
33
+ await controller.enqueue(headerBuffer);
34
+ if (init.payload.byteLength) {
35
+ // USB protocol preserves packet boundaries,
36
+ // so we must write payload separately as native ADB does,
37
+ // otherwise the read operation on device will fail.
38
+ await controller.enqueue(init.payload);
39
+ }
40
+ },
41
+ });
42
+ }
43
+ }
49
44
  //# sourceMappingURL=packet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packet.js","sourceRoot":"","sources":["../../src/daemon/packet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAEvC,MAAM,CAAN,IAAY,UAOX;AAPD,WAAY,UAAU;IAClB,oDAAiB,CAAA;IACjB,sDAAkB,CAAA;IAClB,0DAAoB,CAAA;IACpB,gDAAe,CAAA;IACf,oDAAiB,CAAA;IACjB,sDAAkB,CAAA;AACtB,CAAC,EAPW,UAAU,GAAV,UAAU,KAAV,UAAU,QAOrB;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,MAAM,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;KAC5D,MAAM,CAAC,SAAS,CAAC;KACjB,MAAM,CAAC,MAAM,CAAC;KACd,MAAM,CAAC,MAAM,CAAC;KACd,MAAM,CAAC,eAAe,CAAC;KACvB,MAAM,CAAC,UAAU,CAAC;KAClB,KAAK,CAAC,OAAO,CAAC,CAAC;AAMpB,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;KACtD,MAAM,CAAC,eAAe,CAAC;KACvB,UAAU,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;AAqB7D,MAAM,UAAU,iBAAiB,CAAC,OAAmB;IACjD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,OAAO,wBAAyB,SAAQ,yBAG7C;IACG;QACI,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC1D,KAAK,CAAC;YACF,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACnC,MAAM,IAAI,GAAG,KAA4C,CAAC;gBAC1D,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;gBAE7C,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBAC9C,MAAM,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBAEvC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;oBACzB,4CAA4C;oBAC5C,0DAA0D;oBAC1D,oDAAoD;oBACpD,MAAM,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;iBAC1C;YACL,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ"}
@@ -0,0 +1,58 @@
1
+ import type { Disposable } from "@yume-chan/event";
2
+ import type { Consumable, ReadableStream, ReadableWritablePair, WritableStream } from "@yume-chan/stream-extra";
3
+ import type { Closeable } from "../adb.js";
4
+ import type { AdbPacketDispatcher } from "./dispatcher.js";
5
+ export interface AdbDaemonSocketInfo {
6
+ localId: number;
7
+ remoteId: number;
8
+ localCreated: boolean;
9
+ service: string;
10
+ }
11
+ export interface AdbDaemonSocketConstructionOptions extends AdbDaemonSocketInfo {
12
+ dispatcher: AdbPacketDispatcher;
13
+ highWaterMark?: number | undefined;
14
+ }
15
+ export declare class AdbDaemonSocketController implements AdbDaemonSocketInfo, ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>, Closeable, Disposable {
16
+ #private;
17
+ private readonly dispatcher;
18
+ readonly localId: number;
19
+ readonly remoteId: number;
20
+ readonly localCreated: boolean;
21
+ readonly service: string;
22
+ get readable(): ReadableStream<Uint8Array>;
23
+ readonly writable: WritableStream<Consumable<Uint8Array>>;
24
+ /**
25
+ * Whether the socket is half-closed (i.e. the local side initiated the close).
26
+ *
27
+ * It's only used by dispatcher to avoid sending another `CLSE` packet to remote.
28
+ */
29
+ get closed(): boolean;
30
+ private _socket;
31
+ get socket(): AdbDaemonSocket;
32
+ constructor(options: AdbDaemonSocketConstructionOptions);
33
+ enqueue(data: Uint8Array): Promise<void>;
34
+ ack(): void;
35
+ close(): Promise<void>;
36
+ dispose(): Promise<void>;
37
+ }
38
+ /**
39
+ * A duplex stream representing a socket to ADB daemon.
40
+ *
41
+ * To close it, call either `socket.close()`,
42
+ * `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
43
+ * `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
44
+ * `socket.writable.close()` or `socket.writable.getWriter().close()`.
45
+ */
46
+ export declare class AdbDaemonSocket implements AdbDaemonSocketInfo, ReadableWritablePair<Uint8Array, Consumable<Uint8Array>> {
47
+ #private;
48
+ get localId(): number;
49
+ get remoteId(): number;
50
+ get localCreated(): boolean;
51
+ get service(): string;
52
+ get readable(): ReadableStream<Uint8Array>;
53
+ get writable(): WritableStream<Consumable<Uint8Array>>;
54
+ get closed(): boolean;
55
+ constructor(controller: AdbDaemonSocketController);
56
+ close(): Promise<void>;
57
+ }
58
+ //# sourceMappingURL=socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/daemon/socket.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EACR,UAAU,EAEV,cAAc,EACd,oBAAoB,EACpB,cAAc,EACjB,MAAM,yBAAyB,CAAC;AASjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAG3D,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kCACb,SAAQ,mBAAmB;IAC3B,UAAU,EAAE,mBAAmB,CAAC;IAEhC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED,qBAAa,yBACT,YACI,mBAAmB,EACnB,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,EACxD,SAAS,EACT,UAAU;;IAEd,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD,SAAgB,OAAO,EAAG,MAAM,CAAC;IACjC,SAAgB,QAAQ,EAAG,MAAM,CAAC;IAClC,SAAgB,YAAY,EAAG,OAAO,CAAC;IACvC,SAAgB,OAAO,EAAG,MAAM,CAAC;IAMjC,IAAW,QAAQ,+BAElB;IAGD,SAAgB,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IAGjE;;;;OAIG;IACH,IAAW,MAAM,YAEhB;IAED,OAAO,CAAC,OAAO,CAAkB;IACjC,IAAW,MAAM,oBAEhB;gBAEkB,OAAO,EAAE,kCAAkC;IAiEjD,OAAO,CAAC,IAAI,EAAE,UAAU;IAU9B,GAAG;IAIG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO;CAGjB;AAED;;;;;;;GAOG;AACH,qBAAa,eACT,YACI,mBAAmB,EACnB,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;;IAI5D,IAAW,OAAO,IAAI,MAAM,CAE3B;IACD,IAAW,QAAQ,IAAI,MAAM,CAE5B;IACD,IAAW,YAAY,IAAI,OAAO,CAEjC;IACD,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,QAAQ,IAAI,cAAc,CAAC,UAAU,CAAC,CAEhD;IACD,IAAW,QAAQ,IAAI,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAE5D;IAED,IAAW,MAAM,IAAI,OAAO,CAE3B;gBAEkB,UAAU,EAAE,yBAAyB;IAIjD,KAAK;CAGf"}
@@ -1,119 +1,122 @@
1
- import { PromiseResolver } from "@yume-chan/async";
2
- import { ChunkStream, DuplexStreamFactory, PushReadableStream, WritableStream, pipeFrom, } from "@yume-chan/stream-extra";
3
- import { AdbCommand } from "../packet.js";
4
- export class AdbSocketController {
5
- dispatcher;
6
- localId;
7
- remoteId;
8
- localCreated;
9
- serviceString;
10
- _duplex;
11
- _readable;
12
- _readableController;
13
- get readable() {
14
- return this._readable;
15
- }
16
- _writePromise;
17
- writable;
18
- _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
- */
24
- get closed() {
25
- return this._closed;
26
- }
27
- _socket;
28
- get socket() {
29
- return this._socket;
30
- }
31
- constructor(options) {
32
- Object.assign(this, options);
33
- // Check this image to help you understand the stream graph
34
- // cspell: disable-next-line
35
- // https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
36
- this._duplex = new DuplexStreamFactory({
37
- close: async () => {
38
- this._closed = true;
39
- await this.dispatcher.sendPacket(AdbCommand.Close, this.localId, this.remoteId);
40
- // Don't `dispose` here, we need to wait for `CLSE` response packet.
41
- return false;
42
- },
43
- dispose: () => {
44
- // Error out the pending writes
45
- this._writePromise?.reject(new Error("Socket closed"));
46
- },
47
- });
48
- this._readable = this._duplex.wrapReadable(new PushReadableStream((controller) => {
49
- this._readableController = controller;
50
- }, {
51
- highWaterMark: options.highWaterMark ?? 16 * 1024,
52
- size(chunk) {
53
- return chunk.byteLength;
54
- },
55
- }));
56
- this.writable = pipeFrom(this._duplex.createWritable(new WritableStream({
57
- write: async (chunk) => {
58
- // Wait for an ack packet
59
- this._writePromise = new PromiseResolver();
60
- await this.dispatcher.sendPacket(AdbCommand.Write, this.localId, this.remoteId, chunk);
61
- await this._writePromise.promise;
62
- },
63
- })), new ChunkStream(this.dispatcher.options.maxPayloadSize));
64
- this._socket = new AdbSocket(this);
65
- }
66
- async enqueue(packet) {
67
- // Consumer may abort the `ReadableStream` to close the socket,
68
- // it's OK to throw away further packets in this case.
69
- if (this._readableController.abortSignal.aborted) {
70
- return;
71
- }
72
- await this._readableController.enqueue(packet);
73
- }
74
- ack() {
75
- this._writePromise?.resolve();
76
- }
77
- async close() {
78
- await this._duplex.close();
79
- }
80
- dispose() {
81
- return this._duplex.dispose();
82
- }
83
- }
84
- /**
85
- * A duplex stream representing a socket to ADB daemon.
86
- *
87
- * To close it, call either `socket.close()`,
88
- * `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
89
- * `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
90
- * `socket.writable.close()` or `socket.writable.getWriter().close()`.
91
- */
92
- export class AdbSocket {
93
- _controller;
94
- get localId() {
95
- return this._controller.localId;
96
- }
97
- get remoteId() {
98
- return this._controller.remoteId;
99
- }
100
- get localCreated() {
101
- return this._controller.localCreated;
102
- }
103
- get serviceString() {
104
- return this._controller.serviceString;
105
- }
106
- get readable() {
107
- return this._controller.readable;
108
- }
109
- get writable() {
110
- return this._controller.writable;
111
- }
112
- constructor(controller) {
113
- this._controller = controller;
114
- }
115
- close() {
116
- return this._controller.close();
117
- }
118
- }
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import { ConsumableWritableStream, DistributionStream, DuplexStreamFactory, PushReadableStream, pipeFrom, } from "@yume-chan/stream-extra";
3
+ import { AdbCommand } from "./packet.js";
4
+ export class AdbDaemonSocketController {
5
+ dispatcher;
6
+ localId;
7
+ remoteId;
8
+ localCreated;
9
+ service;
10
+ #duplex;
11
+ #readable;
12
+ #readableController;
13
+ get readable() {
14
+ return this.#readable;
15
+ }
16
+ #writePromise;
17
+ writable;
18
+ #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
+ */
24
+ get closed() {
25
+ return this.#closed;
26
+ }
27
+ _socket;
28
+ get socket() {
29
+ return this._socket;
30
+ }
31
+ constructor(options) {
32
+ Object.assign(this, options);
33
+ // Check this image to help you understand the stream graph
34
+ // cspell: disable-next-line
35
+ // https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
36
+ this.#duplex = new DuplexStreamFactory({
37
+ close: async () => {
38
+ this.#closed = true;
39
+ await this.dispatcher.sendPacket(AdbCommand.Close, this.localId, this.remoteId);
40
+ // Don't `dispose` here, we need to wait for `CLSE` response packet.
41
+ return false;
42
+ },
43
+ dispose: () => {
44
+ // Error out the pending writes
45
+ this.#writePromise?.reject(new Error("Socket closed"));
46
+ },
47
+ });
48
+ this.#readable = this.#duplex.wrapReadable(new PushReadableStream((controller) => {
49
+ this.#readableController = controller;
50
+ }, {
51
+ highWaterMark: options.highWaterMark ?? 16 * 1024,
52
+ size(chunk) {
53
+ return chunk.byteLength;
54
+ },
55
+ }));
56
+ this.writable = pipeFrom(this.#duplex.createWritable(new ConsumableWritableStream({
57
+ write: async (chunk) => {
58
+ // Wait for an ack packet
59
+ this.#writePromise = new PromiseResolver();
60
+ await this.dispatcher.sendPacket(AdbCommand.Write, this.localId, this.remoteId, chunk);
61
+ await this.#writePromise.promise;
62
+ },
63
+ })), new DistributionStream(this.dispatcher.options.maxPayloadSize));
64
+ this._socket = new AdbDaemonSocket(this);
65
+ }
66
+ async enqueue(data) {
67
+ // Consumer may abort the `ReadableStream` to close the socket,
68
+ // it's OK to throw away further packets in this case.
69
+ if (this.#readableController.abortSignal.aborted) {
70
+ return;
71
+ }
72
+ await this.#readableController.enqueue(data);
73
+ }
74
+ ack() {
75
+ this.#writePromise?.resolve();
76
+ }
77
+ async close() {
78
+ await this.#duplex.close();
79
+ }
80
+ dispose() {
81
+ return this.#duplex.dispose();
82
+ }
83
+ }
84
+ /**
85
+ * A duplex stream representing a socket to ADB daemon.
86
+ *
87
+ * To close it, call either `socket.close()`,
88
+ * `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
89
+ * `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
90
+ * `socket.writable.close()` or `socket.writable.getWriter().close()`.
91
+ */
92
+ export class AdbDaemonSocket {
93
+ #controller;
94
+ get localId() {
95
+ return this.#controller.localId;
96
+ }
97
+ get remoteId() {
98
+ return this.#controller.remoteId;
99
+ }
100
+ get localCreated() {
101
+ return this.#controller.localCreated;
102
+ }
103
+ get service() {
104
+ return this.#controller.service;
105
+ }
106
+ get readable() {
107
+ return this.#controller.readable;
108
+ }
109
+ get writable() {
110
+ return this.#controller.writable;
111
+ }
112
+ get closed() {
113
+ return this.#controller.closed;
114
+ }
115
+ constructor(controller) {
116
+ this.#controller = controller;
117
+ }
118
+ close() {
119
+ return this.#controller.close();
120
+ }
121
+ }
119
122
  //# sourceMappingURL=socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/daemon/socket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
2
+ import type { ValueOrPromise } from "@yume-chan/struct";
3
+ import type { AdbIncomingSocketHandler, AdbSocket, AdbTransport } from "../adb.js";
4
+ import { AdbBanner } from "../banner.js";
5
+ import type { AdbAuthenticator, AdbCredentialStore } from "./auth.js";
6
+ import type { AdbPacketData, AdbPacketInit } from "./packet.js";
7
+ export declare const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 16777217;
8
+ interface AdbDaemonAuthenticationOptions {
9
+ serial: string;
10
+ connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>;
11
+ credentialStore: AdbCredentialStore;
12
+ authenticators?: AdbAuthenticator[];
13
+ }
14
+ interface AdbDaemonSocketConnectorConstructionOptions {
15
+ serial: string;
16
+ connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>;
17
+ version: number;
18
+ maxPayloadSize: number;
19
+ banner: string;
20
+ }
21
+ export declare class AdbDaemonTransport implements AdbTransport {
22
+ #private;
23
+ /**
24
+ * Authenticates the connection and creates an `AdbDaemonTransport` instance
25
+ * that can be used by `Adb` class.
26
+ *
27
+ * If an authentication process failed, it's possible to call `authenticate` again
28
+ * on the same connection. Because every time the device receives a `CNXN` packet,
29
+ * it resets all internal state, and starts a new authentication process.
30
+ */
31
+ static authenticate({ serial, connection, credentialStore, authenticators, }: AdbDaemonAuthenticationOptions): Promise<AdbDaemonTransport>;
32
+ get serial(): string;
33
+ get protocolVersion(): number;
34
+ get maxPayloadSize(): number;
35
+ get banner(): AdbBanner;
36
+ get disconnected(): Promise<void>;
37
+ constructor({ serial, connection, version, maxPayloadSize, banner, }: AdbDaemonSocketConnectorConstructionOptions);
38
+ connect(service: string): ValueOrPromise<AdbSocket>;
39
+ addReverseTunnel(handler: AdbIncomingSocketHandler, address?: string): string;
40
+ removeReverseTunnel(address: string): void;
41
+ clearReverseTunnels(): void;
42
+ close(): ValueOrPromise<void>;
43
+ }
44
+ export {};
45
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +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;AAGzC,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;AAE3D,UAAU,8BAA8B;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,oBAAoB,CAAC,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;IAC3E,eAAe,EAAE,kBAAkB,CAAC;IACpC,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACvC;AAED,UAAU,2CAA2C;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,oBAAoB,CAAC,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAmB,YAAW,YAAY;;IACnD;;;;;;;OAOG;WACiB,YAAY,CAAC,EAC7B,MAAM,EACN,UAAU,EACV,eAAe,EACf,cAA2C,GAC9C,EAAE,8BAA8B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkI/D,IAAW,MAAM,WAEhB;IAGD,IAAW,eAAe,WAEzB;IAGD,IAAW,cAAc,WAExB;IAGD,IAAW,MAAM,cAEhB;IAED,IAAW,YAAY,kBAEtB;gBAEkB,EACf,MAAM,EACN,UAAU,EACV,OAAO,EACP,cAAc,EACd,MAAM,GACT,EAAE,2CAA2C;IAwBvC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC;IAInD,gBAAgB,CACnB,OAAO,EAAE,wBAAwB,EACjC,OAAO,CAAC,EAAE,MAAM,GACjB,MAAM;IASF,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1C,mBAAmB,IAAI,IAAI;IAI3B,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC;CAGvC"}
@@ -0,0 +1,184 @@
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import { AbortController, ConsumableWritableStream, WritableStream, } from "@yume-chan/stream-extra";
3
+ import { decodeUtf8, encodeUtf8 } from "@yume-chan/struct";
4
+ import { AdbBanner } from "../banner.js";
5
+ import { AdbFeature } from "../features.js";
6
+ import { ADB_DEFAULT_AUTHENTICATORS, AdbAuthenticationProcessor, } from "./auth.js";
7
+ import { AdbPacketDispatcher } from "./dispatcher.js";
8
+ import { AdbCommand, calculateChecksum } from "./packet.js";
9
+ export const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 0x01000001;
10
+ export class AdbDaemonTransport {
11
+ /**
12
+ * Authenticates the connection and creates an `AdbDaemonTransport` instance
13
+ * that can be used by `Adb` class.
14
+ *
15
+ * If an authentication process failed, it's possible to call `authenticate` again
16
+ * on the same connection. Because every time the device receives a `CNXN` packet,
17
+ * it resets all internal state, and starts a new authentication process.
18
+ */
19
+ static async authenticate({ serial, connection, credentialStore, authenticators = ADB_DEFAULT_AUTHENTICATORS, }) {
20
+ // Initially, set to highest-supported version and payload size.
21
+ let version = 0x01000001;
22
+ // Android 4: 4K, Android 7: 256K, Android 9: 1M
23
+ let maxPayloadSize = 1024 * 1024;
24
+ const resolver = new PromiseResolver();
25
+ const authProcessor = new AdbAuthenticationProcessor(authenticators, credentialStore);
26
+ // Here is similar to `AdbPacketDispatcher`,
27
+ // But the received packet types and send packet processing are different.
28
+ const abortController = new AbortController();
29
+ const pipe = connection.readable
30
+ .pipeTo(new WritableStream({
31
+ async write(packet) {
32
+ switch (packet.command) {
33
+ case AdbCommand.Connect:
34
+ version = Math.min(version, packet.arg0);
35
+ maxPayloadSize = Math.min(maxPayloadSize, packet.arg1);
36
+ resolver.resolve(decodeUtf8(packet.payload));
37
+ break;
38
+ case AdbCommand.Auth: {
39
+ const response = await authProcessor.process(packet);
40
+ await sendPacket(response);
41
+ break;
42
+ }
43
+ default:
44
+ // Maybe the previous ADB client exited without reading all packets,
45
+ // so they are still waiting in OS internal buffer.
46
+ // Just ignore them.
47
+ // Because a `Connect` packet will reset the device,
48
+ // Eventually there will be `Connect` and `Auth` response packets.
49
+ break;
50
+ }
51
+ },
52
+ }), {
53
+ // Don't cancel the source ReadableStream on AbortSignal abort.
54
+ preventCancel: true,
55
+ signal: abortController.signal,
56
+ })
57
+ .then(() => {
58
+ if (resolver.state === "running") {
59
+ resolver.reject(new Error("Connection closed unexpectedly"));
60
+ }
61
+ }, (e) => {
62
+ resolver.reject(e);
63
+ });
64
+ const writer = connection.writable.getWriter();
65
+ async function sendPacket(init) {
66
+ // Always send checksum in auth steps
67
+ // Because we don't know if the device needs it or not.
68
+ init.checksum = calculateChecksum(init.payload);
69
+ init.magic = init.command ^ 0xffffffff;
70
+ await ConsumableWritableStream.write(writer, init);
71
+ }
72
+ let banner;
73
+ 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
+ "sendrecv_v2",
91
+ "sendrecv_v2_brotli",
92
+ "sendrecv_v2_lz4",
93
+ "sendrecv_v2_zstd",
94
+ "sendrecv_v2_dry_run_send",
95
+ ].join(",");
96
+ await sendPacket({
97
+ command: AdbCommand.Connect,
98
+ arg0: version,
99
+ arg1: maxPayloadSize,
100
+ // The terminating `;` is required in formal definition
101
+ // But ADB daemon (all versions) can still work without it
102
+ payload: encodeUtf8(`host::features=${features}`),
103
+ });
104
+ banner = await resolver.promise;
105
+ }
106
+ finally {
107
+ // When failed, release locks on `connection` so the caller can try again.
108
+ // When success, also release locks so `AdbPacketDispatcher` can use them.
109
+ abortController.abort();
110
+ writer.releaseLock();
111
+ // Wait until pipe stops (`ReadableStream` lock released)
112
+ await pipe;
113
+ }
114
+ return new AdbDaemonTransport({
115
+ serial,
116
+ connection,
117
+ version,
118
+ maxPayloadSize,
119
+ banner,
120
+ });
121
+ }
122
+ #dispatcher;
123
+ #serial;
124
+ get serial() {
125
+ return this.#serial;
126
+ }
127
+ #protocolVersion;
128
+ get protocolVersion() {
129
+ return this.#protocolVersion;
130
+ }
131
+ #maxPayloadSize;
132
+ get maxPayloadSize() {
133
+ return this.#maxPayloadSize;
134
+ }
135
+ #banner;
136
+ get banner() {
137
+ return this.#banner;
138
+ }
139
+ get disconnected() {
140
+ return this.#dispatcher.disconnected;
141
+ }
142
+ constructor({ serial, connection, version, maxPayloadSize, banner, }) {
143
+ this.#serial = serial;
144
+ this.#banner = AdbBanner.parse(banner);
145
+ let calculateChecksum;
146
+ let appendNullToServiceString;
147
+ if (version >= ADB_DAEMON_VERSION_OMIT_CHECKSUM) {
148
+ calculateChecksum = false;
149
+ appendNullToServiceString = false;
150
+ }
151
+ else {
152
+ calculateChecksum = true;
153
+ appendNullToServiceString = true;
154
+ }
155
+ this.#dispatcher = new AdbPacketDispatcher(connection, {
156
+ calculateChecksum,
157
+ appendNullToServiceString,
158
+ maxPayloadSize,
159
+ });
160
+ this.#protocolVersion = version;
161
+ this.#maxPayloadSize = maxPayloadSize;
162
+ }
163
+ connect(service) {
164
+ return this.#dispatcher.createSocket(service);
165
+ }
166
+ addReverseTunnel(handler, address) {
167
+ if (!address) {
168
+ const id = Math.random().toString().substring(2);
169
+ address = `localabstract:reverse_${id}`;
170
+ }
171
+ this.#dispatcher.addReverseTunnel(address, handler);
172
+ return address;
173
+ }
174
+ removeReverseTunnel(address) {
175
+ this.#dispatcher.removeReverseTunnel(address);
176
+ }
177
+ clearReverseTunnels() {
178
+ this.#dispatcher.clearReverseTunnels();
179
+ }
180
+ close() {
181
+ return this.#dispatcher.close();
182
+ }
183
+ }
184
+ //# sourceMappingURL=transport.js.map