@yume-chan/adb 0.0.9 → 0.0.12
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 +55 -0
- package/CHANGELOG.md +35 -0
- package/LICENSE +21 -21
- package/README.md +240 -257
- package/esm/adb.d.ts +48 -0
- package/esm/adb.d.ts.map +1 -0
- package/esm/adb.js +141 -145
- package/esm/adb.js.map +1 -1
- package/{dts → esm}/auth.d.ts +17 -7
- package/esm/auth.d.ts.map +1 -0
- package/esm/auth.js +69 -109
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +9 -0
- package/esm/backend.d.ts.map +1 -0
- package/{dts → esm}/commands/base.d.ts +1 -1
- package/esm/commands/base.d.ts.map +1 -0
- package/esm/commands/base.js +1 -0
- package/esm/commands/base.js.map +1 -1
- package/{dts → esm}/commands/framebuffer.d.ts +3 -3
- package/esm/commands/framebuffer.d.ts.map +1 -0
- package/esm/commands/framebuffer.js +15 -18
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/index.d.ts +9 -0
- package/esm/commands/index.d.ts.map +1 -0
- package/esm/commands/index.js +8 -8
- package/esm/commands/index.js.map +1 -1
- package/esm/commands/install.d.ts +4 -0
- package/esm/commands/install.d.ts.map +1 -0
- package/esm/commands/install.js +21 -13
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +23 -0
- package/esm/commands/power.d.ts.map +1 -0
- package/esm/commands/power.js +45 -0
- package/esm/commands/power.js.map +1 -0
- package/{dts → esm}/commands/reverse.d.ts +3 -3
- package/esm/commands/reverse.d.ts.map +1 -0
- package/esm/commands/reverse.js +50 -60
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/index.d.ts +57 -0
- package/esm/commands/subprocess/index.d.ts.map +1 -0
- package/esm/commands/subprocess/index.js +83 -0
- package/esm/commands/subprocess/index.js.map +1 -0
- package/esm/commands/subprocess/legacy.d.ts +28 -0
- package/esm/commands/subprocess/legacy.d.ts.map +1 -0
- package/esm/commands/subprocess/legacy.js +44 -0
- package/esm/commands/subprocess/legacy.js.map +1 -0
- package/esm/commands/subprocess/protocol.d.ts +38 -0
- package/esm/commands/subprocess/protocol.d.ts.map +1 -0
- package/esm/commands/subprocess/protocol.js +155 -0
- package/esm/commands/subprocess/protocol.js.map +1 -0
- package/esm/commands/subprocess/types.d.ts +47 -0
- package/esm/commands/subprocess/types.d.ts.map +1 -0
- package/esm/commands/{shell → subprocess}/types.js +0 -0
- package/{cjs/commands/shell → esm/commands/subprocess}/types.js.map +1 -1
- package/{dts/commands/shell → esm/commands/subprocess}/utils.d.ts +0 -0
- package/esm/commands/subprocess/utils.d.ts.map +1 -0
- package/esm/commands/{shell → subprocess}/utils.js +0 -0
- package/esm/commands/subprocess/utils.js.map +1 -0
- package/esm/commands/sync/index.d.ts +8 -0
- package/esm/commands/sync/index.d.ts.map +1 -0
- package/esm/commands/sync/index.js +7 -7
- package/esm/commands/sync/index.js.map +1 -1
- package/{dts → esm}/commands/sync/list.d.ts +4 -4
- package/esm/commands/sync/list.d.ts.map +1 -0
- package/esm/commands/sync/list.js +16 -19
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +11 -0
- package/esm/commands/sync/pull.d.ts.map +1 -0
- package/esm/commands/sync/pull.js +17 -11
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +8 -0
- package/esm/commands/sync/push.d.ts.map +1 -0
- package/esm/commands/sync/push.js +19 -37
- package/esm/commands/sync/push.js.map +1 -1
- package/{dts → esm}/commands/sync/request.d.ts +3 -3
- package/esm/commands/sync/request.d.ts.map +1 -0
- package/esm/commands/sync/request.js +24 -26
- package/esm/commands/sync/request.js.map +1 -1
- package/{dts → esm}/commands/sync/response.d.ts +3 -3
- package/esm/commands/sync/response.d.ts.map +1 -0
- package/esm/commands/sync/response.js +16 -19
- package/esm/commands/sync/response.js.map +1 -1
- package/{dts → esm}/commands/sync/stat.d.ts +4 -4
- package/esm/commands/sync/stat.d.ts.map +1 -0
- package/esm/commands/sync/stat.js +22 -27
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +83 -0
- package/esm/commands/sync/sync.d.ts.map +1 -0
- package/esm/commands/sync/sync.js +92 -89
- package/esm/commands/sync/sync.js.map +1 -1
- package/{dts → esm}/commands/tcpip.d.ts +1 -1
- package/{dts → esm}/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +14 -19
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/crypto.d.ts +24 -0
- package/esm/crypto.d.ts.map +1 -0
- package/esm/crypto.js +33 -31
- package/esm/crypto.js.map +1 -1
- package/{dts → esm}/features.d.ts +0 -0
- package/{dts → esm}/features.d.ts.map +0 -0
- package/esm/features.js +1 -1
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +11 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +10 -10
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +28 -0
- package/esm/packet.d.ts.map +1 -0
- package/esm/packet.js +26 -53
- package/esm/packet.js.map +1 -1
- package/esm/socket/controller.d.ts +37 -0
- package/esm/socket/controller.d.ts.map +1 -0
- package/esm/socket/controller.js +52 -66
- package/esm/socket/controller.js.map +1 -1
- package/{dts → esm}/socket/dispatcher.d.ts +10 -23
- package/esm/socket/dispatcher.d.ts.map +1 -0
- package/esm/socket/dispatcher.js +148 -164
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +3 -0
- package/esm/socket/index.d.ts.map +1 -0
- package/esm/socket/index.js +2 -6
- package/esm/socket/index.js.map +1 -1
- package/esm/socket/socket.d.ts +34 -0
- package/esm/socket/socket.d.ts.map +1 -0
- package/esm/socket/socket.js +69 -14
- package/esm/socket/socket.js.map +1 -1
- package/esm/stream/buffered.d.ts +35 -0
- package/esm/stream/buffered.d.ts.map +1 -0
- package/esm/stream/buffered.js +123 -0
- package/esm/stream/buffered.js.map +1 -0
- package/esm/stream/detect.bak.d.ts +240 -0
- package/esm/stream/detect.bak.d.ts.map +1 -0
- package/esm/stream/detect.bak.js +60 -0
- package/esm/stream/detect.bak.js.map +1 -0
- package/esm/stream/detect.d.ts +18 -0
- package/esm/stream/detect.d.ts.map +1 -0
- package/esm/stream/detect.js +6 -0
- package/esm/stream/detect.js.map +1 -0
- package/esm/stream/detect.native.d.ts +240 -0
- package/esm/stream/detect.native.d.ts.map +1 -0
- package/esm/stream/detect.native.js +60 -0
- package/esm/stream/detect.native.js.map +1 -0
- package/esm/stream/detect.polyfill.d.ts +18 -0
- package/esm/stream/detect.polyfill.d.ts.map +1 -0
- package/esm/stream/detect.polyfill.js +6 -0
- package/esm/stream/detect.polyfill.js.map +1 -0
- package/esm/stream/index.d.ts +4 -0
- package/esm/stream/index.d.ts.map +1 -0
- package/esm/stream/index.js +3 -2
- package/esm/stream/index.js.map +1 -1
- package/esm/stream/transform.d.ts +98 -0
- package/esm/stream/transform.d.ts.map +1 -0
- package/esm/stream/transform.js +352 -0
- package/esm/stream/transform.js.map +1 -0
- package/{dts → esm}/utils/auto-reset-event.d.ts +1 -1
- package/esm/utils/auto-reset-event.d.ts.map +1 -0
- package/esm/utils/auto-reset-event.js +2 -1
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.d.ts +5 -0
- package/esm/utils/base64.d.ts.map +1 -0
- package/esm/utils/base64.js +116 -80
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/encoding.d.ts +3 -0
- package/esm/utils/encoding.d.ts.map +1 -0
- package/esm/utils/encoding.js +11 -0
- package/esm/utils/encoding.js.map +1 -0
- package/esm/utils/index.d.ts +4 -0
- package/esm/utils/index.d.ts.map +1 -0
- package/esm/utils/index.js +3 -4
- package/esm/utils/index.js.map +1 -1
- package/package.json +49 -50
- package/src/adb.ts +247 -242
- package/src/auth.ts +170 -156
- package/src/backend.ts +11 -24
- package/src/commands/base.ts +11 -11
- package/src/commands/framebuffer.ts +73 -73
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +32 -21
- package/src/commands/power.ts +54 -0
- package/src/commands/reverse.ts +136 -133
- package/src/commands/subprocess/index.ts +124 -0
- package/src/commands/subprocess/legacy.ts +58 -0
- package/src/commands/subprocess/protocol.ts +185 -0
- package/src/commands/subprocess/types.ts +55 -0
- package/src/commands/{shell → subprocess}/utils.ts +20 -20
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +40 -39
- package/src/commands/sync/pull.ts +43 -34
- package/src/commands/sync/push.ts +41 -46
- package/src/commands/sync/request.ts +49 -48
- package/src/commands/sync/response.ts +58 -57
- package/src/commands/sync/stat.ts +123 -121
- package/src/commands/sync/sync.ts +145 -113
- package/src/commands/tcpip.ts +21 -21
- package/src/crypto.ts +280 -280
- package/src/features.ts +5 -5
- package/src/index.ts +11 -10
- package/src/packet.ts +69 -89
- package/src/socket/dispatcher.ts +256 -269
- package/src/socket/index.ts +2 -6
- package/src/socket/socket.ts +129 -28
- package/src/stream/buffered.ts +147 -0
- package/src/stream/detect.native.ts +362 -0
- package/src/stream/detect.polyfill.ts +25 -0
- package/src/stream/detect.ts +25 -0
- package/src/stream/index.ts +3 -2
- package/src/stream/transform.ts +427 -0
- package/src/utils/auto-reset-event.ts +41 -41
- package/src/utils/base64.ts +306 -274
- package/src/utils/encoding.ts +13 -0
- package/src/utils/index.ts +3 -4
- package/tsconfig.build.json +3 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.test.json +10 -0
- package/cjs/adb.js +0 -205
- package/cjs/adb.js.map +0 -1
- package/cjs/auth.js +0 -141
- package/cjs/auth.js.map +0 -1
- package/cjs/backend.js +0 -3
- package/cjs/backend.js.map +0 -1
- package/cjs/commands/base.js +0 -12
- package/cjs/commands/base.js.map +0 -1
- package/cjs/commands/demo-mode.js +0 -174
- package/cjs/commands/demo-mode.js.map +0 -1
- package/cjs/commands/framebuffer.js +0 -66
- package/cjs/commands/framebuffer.js.map +0 -1
- package/cjs/commands/index.js +0 -12
- package/cjs/commands/index.js.map +0 -1
- package/cjs/commands/install.js +0 -20
- package/cjs/commands/install.js.map +0 -1
- package/cjs/commands/reverse.js +0 -105
- package/cjs/commands/reverse.js.map +0 -1
- package/cjs/commands/shell/index.js +0 -56
- package/cjs/commands/shell/index.js.map +0 -1
- package/cjs/commands/shell/legacy.js +0 -37
- package/cjs/commands/shell/legacy.js.map +0 -1
- package/cjs/commands/shell/protocol.js +0 -83
- package/cjs/commands/shell/protocol.js.map +0 -1
- package/cjs/commands/shell/types.js +0 -3
- package/cjs/commands/shell/utils.js +0 -23
- package/cjs/commands/shell/utils.js.map +0 -1
- package/cjs/commands/sync/index.js +0 -11
- package/cjs/commands/sync/index.js.map +0 -1
- package/cjs/commands/sync/list.js +0 -36
- package/cjs/commands/sync/list.js.map +0 -1
- package/cjs/commands/sync/pull.js +0 -34
- package/cjs/commands/sync/pull.js.map +0 -1
- package/cjs/commands/sync/push.js +0 -49
- package/cjs/commands/sync/push.js.map +0 -1
- package/cjs/commands/sync/request.js +0 -48
- package/cjs/commands/sync/request.js.map +0 -1
- package/cjs/commands/sync/response.js +0 -53
- package/cjs/commands/sync/response.js.map +0 -1
- package/cjs/commands/sync/stat.js +0 -109
- package/cjs/commands/sync/stat.js.map +0 -1
- package/cjs/commands/sync/sync.js +0 -118
- package/cjs/commands/sync/sync.js.map +0 -1
- package/cjs/commands/tcpip.js +0 -28
- package/cjs/commands/tcpip.js.map +0 -1
- package/cjs/crypto.js +0 -231
- package/cjs/crypto.js.map +0 -1
- package/cjs/features.js +0 -10
- package/cjs/features.js.map +0 -1
- package/cjs/index.js +0 -14
- package/cjs/index.js.map +0 -1
- package/cjs/packet.js +0 -77
- package/cjs/packet.js.map +0 -1
- package/cjs/socket/close-event-emitter.js +0 -32
- package/cjs/socket/close-event-emitter.js.map +0 -1
- package/cjs/socket/controller.js +0 -84
- package/cjs/socket/controller.js.map +0 -1
- package/cjs/socket/data-event-emitter.js +0 -29
- package/cjs/socket/data-event-emitter.js.map +0 -1
- package/cjs/socket/dispatcher.js +0 -219
- package/cjs/socket/dispatcher.js.map +0 -1
- package/cjs/socket/index.js +0 -10
- package/cjs/socket/index.js.map +0 -1
- package/cjs/socket/logger.js +0 -3
- package/cjs/socket/logger.js.map +0 -1
- package/cjs/socket/socket.js +0 -24
- package/cjs/socket/socket.js.map +0 -1
- package/cjs/stream/buffered-stream.js +0 -78
- package/cjs/stream/buffered-stream.js.map +0 -1
- package/cjs/stream/index.js +0 -6
- package/cjs/stream/index.js.map +0 -1
- package/cjs/stream/stream.js +0 -45
- package/cjs/stream/stream.js.map +0 -1
- package/cjs/utils/auto-reset-event.js +0 -37
- package/cjs/utils/auto-reset-event.js.map +0 -1
- package/cjs/utils/base64.js +0 -210
- package/cjs/utils/base64.js.map +0 -1
- package/cjs/utils/chunk.js +0 -75
- package/cjs/utils/chunk.js.map +0 -1
- package/cjs/utils/event-queue.js +0 -108
- package/cjs/utils/event-queue.js.map +0 -1
- package/cjs/utils/index.js +0 -8
- package/cjs/utils/index.js.map +0 -1
- package/dts/adb.d.ts +0 -46
- package/dts/adb.d.ts.map +0 -1
- package/dts/auth.d.ts.map +0 -1
- package/dts/backend.d.ts +0 -15
- package/dts/backend.d.ts.map +0 -1
- package/dts/commands/base.d.ts.map +0 -1
- package/dts/commands/demo-mode.d.ts +0 -41
- package/dts/commands/demo-mode.d.ts.map +0 -1
- package/dts/commands/framebuffer.d.ts.map +0 -1
- package/dts/commands/index.d.ts +0 -9
- package/dts/commands/index.d.ts.map +0 -1
- package/dts/commands/install.d.ts +0 -3
- package/dts/commands/install.d.ts.map +0 -1
- package/dts/commands/reverse.d.ts.map +0 -1
- package/dts/commands/shell/index.d.ts +0 -20
- package/dts/commands/shell/index.d.ts.map +0 -1
- package/dts/commands/shell/legacy.d.ts +0 -27
- package/dts/commands/shell/legacy.d.ts.map +0 -1
- package/dts/commands/shell/protocol.d.ts +0 -37
- package/dts/commands/shell/protocol.d.ts.map +0 -1
- package/dts/commands/shell/types.d.ts +0 -15
- package/dts/commands/shell/types.d.ts.map +0 -1
- package/dts/commands/shell/utils.d.ts.map +0 -1
- package/dts/commands/sync/index.d.ts +0 -8
- package/dts/commands/sync/index.d.ts.map +0 -1
- package/dts/commands/sync/list.d.ts.map +0 -1
- package/dts/commands/sync/pull.d.ts +0 -11
- package/dts/commands/sync/pull.d.ts.map +0 -1
- package/dts/commands/sync/push.d.ts +0 -8
- package/dts/commands/sync/push.d.ts.map +0 -1
- package/dts/commands/sync/request.d.ts.map +0 -1
- package/dts/commands/sync/response.d.ts.map +0 -1
- package/dts/commands/sync/stat.d.ts.map +0 -1
- package/dts/commands/sync/sync.d.ts +0 -68
- package/dts/commands/sync/sync.d.ts.map +0 -1
- package/dts/crypto.d.ts +0 -17
- package/dts/crypto.d.ts.map +0 -1
- package/dts/index.d.ts +0 -11
- package/dts/index.d.ts.map +0 -1
- package/dts/packet.d.ts +0 -27
- package/dts/packet.d.ts.map +0 -1
- package/dts/socket/close-event-emitter.d.ts +0 -8
- package/dts/socket/close-event-emitter.d.ts.map +0 -1
- package/dts/socket/controller.d.ts +0 -43
- package/dts/socket/controller.d.ts.map +0 -1
- package/dts/socket/data-event-emitter.d.ts +0 -10
- package/dts/socket/data-event-emitter.d.ts.map +0 -1
- package/dts/socket/dispatcher.d.ts.map +0 -1
- package/dts/socket/index.d.ts +0 -7
- package/dts/socket/index.d.ts.map +0 -1
- package/dts/socket/logger.d.ts +0 -9
- package/dts/socket/logger.d.ts.map +0 -1
- package/dts/socket/socket.d.ts +0 -22
- package/dts/socket/socket.d.ts.map +0 -1
- package/dts/stream/buffered-stream.d.ts +0 -30
- package/dts/stream/buffered-stream.d.ts.map +0 -1
- package/dts/stream/index.d.ts +0 -3
- package/dts/stream/index.d.ts.map +0 -1
- package/dts/stream/stream.d.ts +0 -15
- package/dts/stream/stream.d.ts.map +0 -1
- package/dts/utils/auto-reset-event.d.ts.map +0 -1
- package/dts/utils/base64.d.ts +0 -7
- package/dts/utils/base64.d.ts.map +0 -1
- package/dts/utils/chunk.d.ts +0 -3
- package/dts/utils/chunk.d.ts.map +0 -1
- package/dts/utils/event-queue.d.ts +0 -35
- package/dts/utils/event-queue.d.ts.map +0 -1
- package/dts/utils/index.d.ts +0 -5
- package/dts/utils/index.d.ts.map +0 -1
- package/esm/commands/demo-mode.js +0 -170
- package/esm/commands/demo-mode.js.map +0 -1
- package/esm/commands/shell/index.js +0 -52
- package/esm/commands/shell/index.js.map +0 -1
- package/esm/commands/shell/legacy.js +0 -33
- package/esm/commands/shell/legacy.js.map +0 -1
- package/esm/commands/shell/protocol.js +0 -79
- package/esm/commands/shell/protocol.js.map +0 -1
- package/esm/commands/shell/types.js.map +0 -1
- package/esm/commands/shell/utils.js.map +0 -1
- package/esm/socket/close-event-emitter.js +0 -28
- package/esm/socket/close-event-emitter.js.map +0 -1
- package/esm/socket/data-event-emitter.js +0 -25
- package/esm/socket/data-event-emitter.js.map +0 -1
- package/esm/socket/logger.js +0 -2
- package/esm/socket/logger.js.map +0 -1
- package/esm/stream/buffered-stream.js +0 -73
- package/esm/stream/buffered-stream.js.map +0 -1
- package/esm/stream/stream.js +0 -41
- package/esm/stream/stream.js.map +0 -1
- package/esm/utils/chunk.js +0 -70
- package/esm/utils/chunk.js.map +0 -1
- package/esm/utils/event-queue.js +0 -104
- package/esm/utils/event-queue.js.map +0 -1
- package/src/commands/demo-mode.ts +0 -160
- package/src/commands/shell/index.ts +0 -68
- package/src/commands/shell/legacy.ts +0 -42
- package/src/commands/shell/protocol.ts +0 -94
- package/src/commands/shell/types.ts +0 -21
- package/src/socket/close-event-emitter.ts +0 -28
- package/src/socket/controller.ts +0 -105
- package/src/socket/data-event-emitter.ts +0 -27
- package/src/socket/logger.ts +0 -12
- package/src/stream/buffered-stream.ts +0 -100
- package/src/stream/stream.ts +0 -50
- package/src/utils/chunk.ts +0 -70
- package/src/utils/event-queue.ts +0 -145
- package/tsconfig.cjs.json +0 -11
- package/tsconfig.esm.json +0 -28
- package/tsconfig.esm.tsbuildinfo +0 -1305
- package/tsconfig.json +0 -18
package/src/commands/reverse.ts
CHANGED
|
@@ -1,133 +1,136 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
* @
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
1
|
+
// cspell: ignore killforward
|
|
2
|
+
|
|
3
|
+
import { AutoDisposable } from '@yume-chan/event';
|
|
4
|
+
import Struct from '@yume-chan/struct';
|
|
5
|
+
import type { AdbPacketCore } from '../packet.js';
|
|
6
|
+
import type { AdbIncomingSocketEventArgs, AdbPacketDispatcher, AdbSocket } from '../socket/index.js';
|
|
7
|
+
import { AdbBufferedStream } from '../stream/index.js';
|
|
8
|
+
import { decodeUtf8 } from "../utils/index.js";
|
|
9
|
+
|
|
10
|
+
export interface AdbReverseHandler {
|
|
11
|
+
onSocket(packet: AdbPacketCore, socket: AdbSocket): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AdbForwardListener {
|
|
15
|
+
deviceSerial: string;
|
|
16
|
+
|
|
17
|
+
localName: string;
|
|
18
|
+
|
|
19
|
+
remoteName: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const AdbReverseStringResponse =
|
|
23
|
+
new Struct({ littleEndian: true })
|
|
24
|
+
.string('length', { length: 4 })
|
|
25
|
+
.string('content', { lengthField: 'length', lengthFieldBase: 16 });
|
|
26
|
+
|
|
27
|
+
const AdbReverseErrorResponse =
|
|
28
|
+
new Struct({ littleEndian: true })
|
|
29
|
+
.fields(AdbReverseStringResponse)
|
|
30
|
+
.postDeserialize((value) => {
|
|
31
|
+
throw new Error(value.content);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export class AdbReverseCommand extends AutoDisposable {
|
|
35
|
+
protected localPortToHandler = new Map<number, AdbReverseHandler>();
|
|
36
|
+
|
|
37
|
+
protected deviceAddressToLocalPort = new Map<string, number>();
|
|
38
|
+
|
|
39
|
+
protected dispatcher: AdbPacketDispatcher;
|
|
40
|
+
|
|
41
|
+
protected listening = false;
|
|
42
|
+
|
|
43
|
+
public constructor(dispatcher: AdbPacketDispatcher) {
|
|
44
|
+
super();
|
|
45
|
+
|
|
46
|
+
this.dispatcher = dispatcher;
|
|
47
|
+
this.addDisposable(this.dispatcher.onIncomingSocket(this.handleIncomingSocket, this));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
protected handleIncomingSocket(e: AdbIncomingSocketEventArgs): void {
|
|
51
|
+
if (e.handled) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const address = decodeUtf8(e.packet.payload);
|
|
56
|
+
// Address format: `tcp:12345\0`
|
|
57
|
+
const port = Number.parseInt(address.substring(4));
|
|
58
|
+
if (this.localPortToHandler.has(port)) {
|
|
59
|
+
this.localPortToHandler.get(port)!.onSocket(e.packet, e.socket);
|
|
60
|
+
e.handled = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private async createBufferedStream(service: string) {
|
|
65
|
+
const socket = await this.dispatcher.createSocket(service);
|
|
66
|
+
return new AdbBufferedStream(socket);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private async sendRequest(service: string) {
|
|
70
|
+
const stream = await this.createBufferedStream(service);
|
|
71
|
+
const success = decodeUtf8(await stream.read(4)) === 'OKAY';
|
|
72
|
+
if (!success) {
|
|
73
|
+
await AdbReverseErrorResponse.deserialize(stream);
|
|
74
|
+
}
|
|
75
|
+
return stream;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public async list(): Promise<AdbForwardListener[]> {
|
|
79
|
+
const stream = await this.createBufferedStream('reverse:list-forward');
|
|
80
|
+
|
|
81
|
+
const response = await AdbReverseStringResponse.deserialize(stream);
|
|
82
|
+
return response.content!.split('\n').map(line => {
|
|
83
|
+
const [deviceSerial, localName, remoteName] = line.split(' ') as [string, string, string];
|
|
84
|
+
return { deviceSerial, localName, remoteName };
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// No need to close the stream, device will close it
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param deviceAddress The address adbd on device is listening on. Can be `tcp:0` to let adbd choose an available TCP port by itself.
|
|
92
|
+
* @param localPort Native ADB will open a connection to localPort when reverse connection starts. In webadb, it's only used to uniquely identify a reverse registry, `handler` will be called on connection.
|
|
93
|
+
* @param handler A callback to handle incoming connections
|
|
94
|
+
* @returns If `deviceAddress` is `tcp:0`, return `tcp:{ACTUAL_LISTENING_PORT}`; otherwise, return `deviceAddress`.
|
|
95
|
+
*/
|
|
96
|
+
public async add(
|
|
97
|
+
deviceAddress: string,
|
|
98
|
+
localPort: number,
|
|
99
|
+
handler: AdbReverseHandler,
|
|
100
|
+
): Promise<string> {
|
|
101
|
+
const stream = await this.sendRequest(`reverse:forward:${deviceAddress};tcp:${localPort}`);
|
|
102
|
+
|
|
103
|
+
// `tcp:0` tells the device to pick an available port.
|
|
104
|
+
// However, device will response with the selected port for all `tcp:` requests.
|
|
105
|
+
if (deviceAddress.startsWith('tcp:')) {
|
|
106
|
+
const response = await AdbReverseStringResponse.deserialize(stream);
|
|
107
|
+
deviceAddress = `tcp:${Number.parseInt(response.content!, 10)}`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.localPortToHandler.set(localPort, handler);
|
|
111
|
+
this.deviceAddressToLocalPort.set(deviceAddress, localPort);
|
|
112
|
+
return deviceAddress;
|
|
113
|
+
|
|
114
|
+
// No need to close the stream, device will close it
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public async remove(deviceAddress: string): Promise<void> {
|
|
118
|
+
await this.sendRequest(`reverse:killforward:${deviceAddress}`);
|
|
119
|
+
|
|
120
|
+
if (this.deviceAddressToLocalPort.has(deviceAddress)) {
|
|
121
|
+
this.localPortToHandler.delete(this.deviceAddressToLocalPort.get(deviceAddress)!);
|
|
122
|
+
this.deviceAddressToLocalPort.delete(deviceAddress);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// No need to close the stream, device will close it
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public async removeAll(): Promise<void> {
|
|
129
|
+
await this.sendRequest(`reverse:killforward-all`);
|
|
130
|
+
|
|
131
|
+
this.deviceAddressToLocalPort.clear();
|
|
132
|
+
this.localPortToHandler.clear();
|
|
133
|
+
|
|
134
|
+
// No need to close the stream, device will close it
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Adb } from '../../adb.js';
|
|
2
|
+
import { DecodeUtf8Stream, GatherStringStream } from "../../stream/index.js";
|
|
3
|
+
import { AdbNoneSubprocessProtocol } from './legacy.js';
|
|
4
|
+
import { AdbShellSubprocessProtocol } from './protocol.js';
|
|
5
|
+
import type { AdbSubprocessProtocol, AdbSubprocessProtocolConstructor } from './types.js';
|
|
6
|
+
|
|
7
|
+
export * from './legacy.js';
|
|
8
|
+
export * from './protocol.js';
|
|
9
|
+
export * from './types.js';
|
|
10
|
+
export * from './utils.js';
|
|
11
|
+
|
|
12
|
+
export interface AdbSubprocessOptions {
|
|
13
|
+
/**
|
|
14
|
+
* A list of `AdbShellConstructor`s to be used.
|
|
15
|
+
*
|
|
16
|
+
* Different `AdbShell` has different capabilities, thus requires specific adaptations.
|
|
17
|
+
* Check each `AdbShell`'s documentation for details.
|
|
18
|
+
*
|
|
19
|
+
* The first one whose `isSupported` returns `true` will be used.
|
|
20
|
+
* If no `AdbShell` is supported, an error will be thrown.
|
|
21
|
+
*
|
|
22
|
+
* The default value is `[AdbShellProtocol, AdbLegacyShell]`.
|
|
23
|
+
*/
|
|
24
|
+
protocols: AdbSubprocessProtocolConstructor[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const DefaultOptions: AdbSubprocessOptions = {
|
|
28
|
+
protocols: [AdbShellSubprocessProtocol, AdbNoneSubprocessProtocol],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export interface SubprocessResult {
|
|
32
|
+
stdout: string;
|
|
33
|
+
stderr: string;
|
|
34
|
+
exitCode: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class AdbSubprocess {
|
|
38
|
+
public readonly adb: Adb;
|
|
39
|
+
|
|
40
|
+
public constructor(adb: Adb) {
|
|
41
|
+
this.adb = adb;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private async createProtocol(command: string, options?: Partial<AdbSubprocessOptions>): Promise<AdbSubprocessProtocol> {
|
|
45
|
+
let { protocols } = { ...DefaultOptions, ...options };
|
|
46
|
+
|
|
47
|
+
let Constructor: AdbSubprocessProtocolConstructor | undefined;
|
|
48
|
+
for (const item of protocols) {
|
|
49
|
+
if (await item.isSupported(this.adb)) {
|
|
50
|
+
Constructor = item;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!Constructor) {
|
|
56
|
+
throw new Error('No specified protocol is supported by the device');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return await Constructor.spawn(this.adb, command);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Spawns the default shell in interactive mode.
|
|
64
|
+
* @param options The options for creating the `AdbShell`
|
|
65
|
+
* @returns A new `AdbShell` instance connecting to the spawned shell process.
|
|
66
|
+
*/
|
|
67
|
+
public shell(options?: Partial<AdbSubprocessOptions>): Promise<AdbSubprocessProtocol> {
|
|
68
|
+
return this.createProtocol('', options);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Spawns a new process using the given `command`.
|
|
73
|
+
* @param command The command to run, or an array of strings containing both command and args.
|
|
74
|
+
* @param options The options for creating the `AdbShell`
|
|
75
|
+
* @returns A new `AdbShell` instance connecting to the spawned process.
|
|
76
|
+
*/
|
|
77
|
+
public spawn(command: string | string[], options?: Partial<AdbSubprocessOptions>): Promise<AdbSubprocessProtocol> {
|
|
78
|
+
if (Array.isArray(command)) {
|
|
79
|
+
command = command.join(' ');
|
|
80
|
+
}
|
|
81
|
+
return this.createProtocol(command, options);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Spawns a new process, waits until it exits, and returns the entire output.
|
|
86
|
+
* @param command The command to run
|
|
87
|
+
* @param options The options for creating the `AdbShell`
|
|
88
|
+
* @returns The entire output of the command
|
|
89
|
+
*/
|
|
90
|
+
public async spawnAndWait(
|
|
91
|
+
command: string | string[],
|
|
92
|
+
options?: Partial<AdbSubprocessOptions>
|
|
93
|
+
): Promise<SubprocessResult> {
|
|
94
|
+
const shell = await this.spawn(command, options);
|
|
95
|
+
|
|
96
|
+
const stdout = new GatherStringStream();
|
|
97
|
+
shell.stdout
|
|
98
|
+
.pipeThrough(new DecodeUtf8Stream())
|
|
99
|
+
.pipeThrough(stdout);
|
|
100
|
+
|
|
101
|
+
const stderr = new GatherStringStream();
|
|
102
|
+
shell.stderr
|
|
103
|
+
.pipeThrough(new DecodeUtf8Stream())
|
|
104
|
+
.pipeThrough(stderr);
|
|
105
|
+
|
|
106
|
+
const exitCode = await shell.exit;
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
stdout: stdout.result,
|
|
110
|
+
stderr: stderr.result,
|
|
111
|
+
exitCode,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Spawns a new process, waits until it exits, and returns the entire output.
|
|
117
|
+
* @param command The command to run
|
|
118
|
+
* @returns The entire output of the command
|
|
119
|
+
*/
|
|
120
|
+
public async spawnAndWaitLegacy(command: string | string[]): Promise<string> {
|
|
121
|
+
const { stdout } = await this.spawnAndWait(command, { protocols: [AdbNoneSubprocessProtocol] });
|
|
122
|
+
return stdout;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Adb } from "../../adb.js";
|
|
2
|
+
import type { AdbSocket } from "../../socket/index.js";
|
|
3
|
+
import { DuplexStreamFactory, type ReadableStream } from "../../stream/index.js";
|
|
4
|
+
import type { AdbSubprocessProtocol } from "./types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The legacy shell
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* * `stderr`: No
|
|
11
|
+
* * `exit` exit code: No
|
|
12
|
+
* * `resize`: No
|
|
13
|
+
*/
|
|
14
|
+
export class AdbNoneSubprocessProtocol implements AdbSubprocessProtocol {
|
|
15
|
+
public static isSupported() { return true; }
|
|
16
|
+
|
|
17
|
+
public static async spawn(adb: Adb, command: string) {
|
|
18
|
+
return new AdbNoneSubprocessProtocol(await adb.createSocket(`shell:${command}`));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private readonly socket: AdbSocket;
|
|
22
|
+
|
|
23
|
+
// Legacy shell forwards all data to stdin.
|
|
24
|
+
public get stdin() { return this.socket.writable; }
|
|
25
|
+
|
|
26
|
+
private _stdout: ReadableStream<Uint8Array>;
|
|
27
|
+
// Legacy shell doesn't support splitting output streams.
|
|
28
|
+
public get stdout() { return this._stdout; }
|
|
29
|
+
|
|
30
|
+
// `stderr` of Legacy shell is always empty.
|
|
31
|
+
private _stderr: ReadableStream<Uint8Array>;
|
|
32
|
+
public get stderr() { return this._stderr; }
|
|
33
|
+
|
|
34
|
+
private _exit: Promise<number>;
|
|
35
|
+
public get exit() { return this._exit; }
|
|
36
|
+
|
|
37
|
+
public constructor(socket: AdbSocket) {
|
|
38
|
+
this.socket = socket;
|
|
39
|
+
|
|
40
|
+
const factory = new DuplexStreamFactory<Uint8Array, Uint8Array>({
|
|
41
|
+
close: async () => {
|
|
42
|
+
await this.socket.close();
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this._stdout = factory.createWrapReadable(this.socket.readable);
|
|
47
|
+
this._stderr = factory.createReadable();
|
|
48
|
+
this._exit = factory.closed.then(() => 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public resize() {
|
|
52
|
+
// Not supported
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public kill() {
|
|
56
|
+
return this.socket.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import Struct, { placeholder, type StructValueType } from "@yume-chan/struct";
|
|
3
|
+
import type { Adb } from "../../adb.js";
|
|
4
|
+
import { AdbFeatures } from "../../features.js";
|
|
5
|
+
import type { AdbSocket } from "../../socket/index.js";
|
|
6
|
+
import { PushReadableStream, ReadableStream, StructDeserializeStream, StructSerializeStream, TransformStream, WritableStream, WritableStreamDefaultWriter, type PushReadableStreamController } from "../../stream/index.js";
|
|
7
|
+
import { encodeUtf8 } from "../../utils/index.js";
|
|
8
|
+
import type { AdbSubprocessProtocol } from "./types.js";
|
|
9
|
+
|
|
10
|
+
export enum AdbShellProtocolId {
|
|
11
|
+
Stdin,
|
|
12
|
+
Stdout,
|
|
13
|
+
Stderr,
|
|
14
|
+
Exit,
|
|
15
|
+
CloseStdin,
|
|
16
|
+
WindowSizeChange,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// This packet format is used in both direction.
|
|
20
|
+
const AdbShellProtocolPacket = new Struct({ littleEndian: true })
|
|
21
|
+
.uint8('id', placeholder<AdbShellProtocolId>())
|
|
22
|
+
.uint32('length')
|
|
23
|
+
.uint8Array('data', { lengthField: 'length' });
|
|
24
|
+
|
|
25
|
+
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket['TInit'];
|
|
26
|
+
|
|
27
|
+
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
|
|
28
|
+
|
|
29
|
+
class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolPacketInit>{
|
|
30
|
+
constructor() {
|
|
31
|
+
super({
|
|
32
|
+
transform(chunk, controller) {
|
|
33
|
+
controller.enqueue({
|
|
34
|
+
id: AdbShellProtocolId.Stdin,
|
|
35
|
+
data: chunk,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
flush() {
|
|
39
|
+
// TODO: AdbShellSubprocessProtocol: support closing stdin
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Uint8Array>{
|
|
46
|
+
constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
|
|
47
|
+
super({
|
|
48
|
+
transform(chunk, controller) {
|
|
49
|
+
if (chunk.id === type) {
|
|
50
|
+
controller.enqueue(chunk.data);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class MultiplexStream<T>{
|
|
58
|
+
private _readable: PushReadableStream<T>;
|
|
59
|
+
private _readableController!: PushReadableStreamController<T>;
|
|
60
|
+
public get readable() { return this._readable; }
|
|
61
|
+
|
|
62
|
+
private _activeCount = 0;
|
|
63
|
+
|
|
64
|
+
constructor() {
|
|
65
|
+
this._readable = new PushReadableStream(controller => {
|
|
66
|
+
this._readableController = controller;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public createWriteable() {
|
|
71
|
+
return new WritableStream<T>({
|
|
72
|
+
start: () => {
|
|
73
|
+
this._activeCount += 1;
|
|
74
|
+
},
|
|
75
|
+
write: async (chunk) => {
|
|
76
|
+
await this._readableController.enqueue(chunk);
|
|
77
|
+
},
|
|
78
|
+
abort: async (e) => {
|
|
79
|
+
this._activeCount -= 1;
|
|
80
|
+
if (this._activeCount === 0) {
|
|
81
|
+
this._readableController.close();
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
close: async () => {
|
|
85
|
+
this._activeCount -= 1;
|
|
86
|
+
if (this._activeCount === 0) {
|
|
87
|
+
this._readableController.close();
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Shell v2 a.k.a Shell Protocol
|
|
96
|
+
*
|
|
97
|
+
* Features:
|
|
98
|
+
* * `stderr`: Yes
|
|
99
|
+
* * `exit` exit code: Yes
|
|
100
|
+
* * `resize`: Yes
|
|
101
|
+
*/
|
|
102
|
+
export class AdbShellSubprocessProtocol implements AdbSubprocessProtocol {
|
|
103
|
+
public static isSupported(adb: Adb) {
|
|
104
|
+
return adb.features!.includes(AdbFeatures.ShellV2);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public static async spawn(adb: Adb, command: string) {
|
|
108
|
+
// TODO: AdbShellSubprocessProtocol: Support raw mode
|
|
109
|
+
// TODO: AdbShellSubprocessProtocol: Support setting `XTERM` environment variable
|
|
110
|
+
return new AdbShellSubprocessProtocol(await adb.createSocket(`shell,v2,pty:${command}`));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private readonly _socket: AdbSocket;
|
|
114
|
+
private _socketWriter: WritableStreamDefaultWriter<AdbShellProtocolPacketInit>;
|
|
115
|
+
|
|
116
|
+
private _stdin: WritableStream<Uint8Array>;
|
|
117
|
+
public get stdin() { return this._stdin; }
|
|
118
|
+
|
|
119
|
+
private _stdout: ReadableStream<Uint8Array>;
|
|
120
|
+
public get stdout() { return this._stdout; }
|
|
121
|
+
|
|
122
|
+
private _stderr: ReadableStream<Uint8Array>;
|
|
123
|
+
public get stderr() { return this._stderr; }
|
|
124
|
+
|
|
125
|
+
private readonly _exit = new PromiseResolver<number>();
|
|
126
|
+
public get exit() { return this._exit.promise; }
|
|
127
|
+
|
|
128
|
+
public constructor(socket: AdbSocket) {
|
|
129
|
+
this._socket = socket;
|
|
130
|
+
|
|
131
|
+
// Check this image to help you understand the stream graph
|
|
132
|
+
// cspell: disable-next-line
|
|
133
|
+
// https://www.plantuml.com/plantuml/png/bL91QiCm4Bpx5SAdv90lb1JISmiw5XzaQKf5PIkiLZIqzEyLSg8ks13gYtOykpFhiOw93N6UGjVDqK7rZsxKqNw0U_NTgVAy4empOy2mm4_olC0VEVEE47GUpnGjKdgXoD76q4GIEpyFhOwP_m28hW0NNzxNUig1_JdW0bA7muFIJDco1daJ_1SAX9bgvoPJPyIkSekhNYctvIGXrCH6tIsPL5fs-s6J5yc9BpWXhKtNdF2LgVYPGM_6GlMwfhWUsIt4lbScANrwlgVVUifPSVi__t44qStnwPvZwobdSmHHlL57p2vFuHS0
|
|
134
|
+
|
|
135
|
+
// TODO: AdbShellSubprocessProtocol: Optimize stream graph
|
|
136
|
+
|
|
137
|
+
const [stdout, stderr] = socket.readable
|
|
138
|
+
.pipeThrough(new StructDeserializeStream(AdbShellProtocolPacket))
|
|
139
|
+
.pipeThrough(new TransformStream<AdbShellProtocolPacket, AdbShellProtocolPacket>({
|
|
140
|
+
transform: (chunk, controller) => {
|
|
141
|
+
if (chunk.id === AdbShellProtocolId.Exit) {
|
|
142
|
+
this._exit.resolve(new Uint8Array(chunk.data)[0]!);
|
|
143
|
+
// We can let `StdoutTransformStream` to process `AdbShellProtocolId.Exit`,
|
|
144
|
+
// but since we need this `TransformStream` to capture the exit code anyway,
|
|
145
|
+
// terminating child streams here is killing two birds with one stone.
|
|
146
|
+
controller.terminate();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
controller.enqueue(chunk);
|
|
150
|
+
}
|
|
151
|
+
}))
|
|
152
|
+
.tee();
|
|
153
|
+
this._stdout = stdout
|
|
154
|
+
.pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stdout));
|
|
155
|
+
this._stderr = stderr
|
|
156
|
+
.pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stderr));
|
|
157
|
+
|
|
158
|
+
const multiplexer = new MultiplexStream<AdbShellProtocolPacketInit>();
|
|
159
|
+
multiplexer.readable
|
|
160
|
+
.pipeThrough(new StructSerializeStream(AdbShellProtocolPacket))
|
|
161
|
+
.pipeTo(socket.writable);
|
|
162
|
+
|
|
163
|
+
const { readable, writable } = new StdinSerializeStream();
|
|
164
|
+
this._stdin = writable;
|
|
165
|
+
readable.pipeTo(multiplexer.createWriteable());
|
|
166
|
+
|
|
167
|
+
this._socketWriter = multiplexer.createWriteable().getWriter();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public async resize(rows: number, cols: number) {
|
|
171
|
+
await this._socketWriter.write({
|
|
172
|
+
id: AdbShellProtocolId.WindowSizeChange,
|
|
173
|
+
data: encodeUtf8(
|
|
174
|
+
// The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
|
|
175
|
+
// However, according to https://linux.die.net/man/4/tty_ioctl
|
|
176
|
+
// `x_pixels` and `y_pixels` are not used, so always passing `0` is fine.
|
|
177
|
+
`${rows}x${cols},0x0\0`
|
|
178
|
+
),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public kill() {
|
|
183
|
+
return this._socket.close();
|
|
184
|
+
}
|
|
185
|
+
}
|