Skip to content

Commit

Permalink
feat(adb): support connect to adb server (#549)
Browse files Browse the repository at this point in the history
  • Loading branch information
yume-chan authored May 13, 2023
1 parent 3075d88 commit 43db8a1
Show file tree
Hide file tree
Showing 30 changed files with 850 additions and 278 deletions.
11 changes: 11 additions & 0 deletions packages/adb-daemon-direct-sockets/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
"extends": [
"@yume-chan"
],
parserOptions: {
tsconfigRootDir: __dirname,
project: [
"./tsconfig.build.json"
],
},
}
16 changes: 16 additions & 0 deletions packages/adb-daemon-direct-sockets/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.rush

# Test
coverage
**/*.spec.ts
**/*.spec.js
**/*.spec.js.map
**/__helpers__
jest.config.js

.eslintrc.cjs
tsconfig.json
tsconfig.test.json

# Logs
*.log
5 changes: 5 additions & 0 deletions packages/adb-daemon-direct-sockets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `@yume-chan/adb-daemon-direct-sockets`

Use [Direct Sockets API](https://wicg.github.io/direct-sockets/) for plugin-free ADB over WiFi connection.

Note: Direct Sockets API is still under development. Currently it's only available in Chrome and requires extra command line arguments to enable. This package is not ready to be used in production, thus not published to NPM registry.
46 changes: 46 additions & 0 deletions packages/adb-daemon-direct-sockets/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "@yume-chan/adb-daemon-direct-sockets",
"private": true,
"version": "0.0.9",
"description": "ADB daemon transport connection for `@yume-chan/adb` using Direct Sockets API.",
"keywords": [
"adb",
"direct-sockets"
],
"author": {
"name": "Simon Chan",
"email": "cnsimonchan@live.com",
"url": "https://chensi.moe/blog"
},
"homepage": "https://github.com/yume-chan/ya-webadb/tree/main/libraries/adb-daemon-direct-sockets#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/yume-chan/ya-webadb.git",
"directory": "libraries/adb-daemon-direct-sockets"
},
"bugs": {
"url": "https://github.com/yume-chan/ya-webadb/issues"
},
"license": "MIT",
"type": "module",
"main": "esm/index.js",
"types": "esm/index.d.ts",
"scripts": {
"build": "tsc -b tsconfig.build.json",
"build:watch": "tsc -b tsconfig.build.json",
"lint": "eslint src/**/*.ts --fix && prettier src/**/*.ts --write --tab-width 4",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@yume-chan/adb": "workspace:^0.0.19",
"@yume-chan/stream-extra": "workspace:^0.0.19",
"tslib": "^2.5.0"
},
"devDependencies": {
"@yume-chan/eslint-config": "workspace:^1.0.0",
"@yume-chan/tsconfig": "workspace:^1.0.0",
"eslint": "^8.39.0",
"prettier": "^2.8.8",
"typescript": "^5.0.3"
}
}
84 changes: 84 additions & 0 deletions packages/adb-daemon-direct-sockets/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { AdbDaemonConnection } from "@yume-chan/adb";
import { AdbPacket, AdbPacketSerializeStream } from "@yume-chan/adb";
import type { ReadableStream, WritableStream } from "@yume-chan/stream-extra";
import {
StructDeserializeStream,
UnwrapConsumableStream,
WrapReadableStream,
WrapWritableStream,
} from "@yume-chan/stream-extra";

declare global {
interface TCPSocketOpenInfo {
readable: ReadableStream<Uint8Array>;
writable: WritableStream<Uint8Array>;

remoteAddress: string;
remotePort: number;

localAddress: string;
localPort: number;
}

class TCPSocket {
constructor(
remoteAddress: string,
remotePort: number,
options?: TCPSocketOptions
);

opened: Promise<TCPSocketOpenInfo>;
closed: Promise<void>;

close(): Promise<void>;
}

interface TCPSocketOptions {
sendBufferSize?: number;
receiveBufferSize?: number;

noDelay?: boolean;
keepAliveDelay?: number;
}

interface Window {
TCPSocket: typeof TCPSocket;
}
}

export default class AdbDaemonDirectSocketsConnection
implements AdbDaemonConnection
{
public static isSupported(): boolean {
return typeof window !== "undefined" && !!window.TCPSocket;
}

public readonly serial: string;

public readonly host: string;

public readonly port: number;

public name: string | undefined;

public constructor(host: string, port = 5555, name?: string) {
this.host = host;
this.port = port;
this.serial = `${host}:${port}`;
this.name = name;
}

public async connect() {
const socket = new TCPSocket(this.host, this.port, { noDelay: true });
const { readable, writable } = await socket.opened;

return {
readable: new WrapReadableStream(readable).pipeThrough(
new StructDeserializeStream(AdbPacket)
),
writable: new WrapWritableStream(writable)
.bePipedThroughFrom(new UnwrapConsumableStream())
.bePipedThroughFrom(new AdbPacketSerializeStream()),
};
}
}
9 changes: 9 additions & 0 deletions packages/adb-daemon-direct-sockets/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./node_modules/@yume-chan/tsconfig/tsconfig.base.json",
"compilerOptions": {
"lib": [
"ESNext",
"DOM"
],
}
}
13 changes: 13 additions & 0 deletions packages/adb-daemon-direct-sockets/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"references": [
{
"path": "../adb/tsconfig.build.json"
},
{
"path": "../stream-extra/tsconfig.build.json"
},
{
"path": "./tsconfig.build.json"
},
]
}
11 changes: 11 additions & 0 deletions packages/adb-daemon-ws/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
"extends": [
"@yume-chan"
],
parserOptions: {
tsconfigRootDir: __dirname,
project: [
"./tsconfig.build.json"
],
},
}
16 changes: 16 additions & 0 deletions packages/adb-daemon-ws/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.rush

# Test
coverage
**/*.spec.ts
**/*.spec.js
**/*.spec.js.map
**/__helpers__
jest.config.js

.eslintrc.cjs
tsconfig.json
tsconfig.test.json

# Logs
*.log
9 changes: 9 additions & 0 deletions packages/adb-daemon-ws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# `@yume-chan/adb-daemon-ws`

ADB daemon transport connection for `@yume-chan/adb` using WebSocket API.

Requires WebSockify softwares to bridge the connection between TCP (ADB over Wi-Fi) and WebSocket.

**WARNING:** WebSocket is an unreliable protocol! When send buffer is full, it will throw away any new-coming data, or even cut the connection completely.

Note: This package only demonstrate the possibility. It's not intended to be used in production, thus not published to NPM registry.
46 changes: 46 additions & 0 deletions packages/adb-daemon-ws/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "@yume-chan/adb-daemon-ws",
"private": true,
"version": "0.0.9",
"description": "ADB daemon transport connection for `@yume-chan/adb` using WebSocket API.",
"keywords": [
"websocket",
"adb"
],
"license": "MIT",
"author": {
"name": "Simon Chan",
"email": "cnsimonchan@live.com",
"url": "https://chensi.moe/blog"
},
"homepage": "https://github.com/yume-chan/ya-webadb/tree/main/libraries/adb-daemon-ws#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/yume-chan/ya-webadb.git",
"directory": "libraries/adb-daemon-ws"
},
"bugs": {
"url": "https://github.com/yume-chan/ya-webadb/issues"
},
"type": "module",
"main": "esm/index.js",
"types": "esm/index.d.ts",
"scripts": {
"build": "tsc -b tsconfig.build.json",
"build:watch": "tsc -b tsconfig.build.json",
"lint": "eslint src/**/*.ts --fix"
},
"dependencies": {
"@yume-chan/adb": "workspace:^0.0.19",
"@yume-chan/stream-extra": "workspace:^0.0.19",
"tslib": "^2.5.0"
},
"devDependencies": {
"@yume-chan/eslint-config": "workspace:^1.0.0",
"@yume-chan/tsconfig": "workspace:^1.0.0",
"eslint": "^8.39.0",
"jest": "^29.5.0",
"prettier": "^2.8.8",
"typescript": "^5.0.3"
}
}
89 changes: 89 additions & 0 deletions packages/adb-daemon-ws/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import type { AdbDaemonConnection } from "@yume-chan/adb";
import {
AdbPacket,
AdbPacketSerializeStream,
unreachable,
} from "@yume-chan/adb";
import type { Consumable } from "@yume-chan/stream-extra";
import {
ConsumableWritableStream,
DuplexStreamFactory,
ReadableStream,
StructDeserializeStream,
pipeFrom,
} from "@yume-chan/stream-extra";

export default class AdbDaemonWebSocketConnection
implements AdbDaemonConnection
{
public readonly serial: string;

public name: string | undefined;

public constructor(url: string, name?: string) {
this.serial = url;
this.name = name;
}

public async connect() {
const socket = new WebSocket(this.serial);
socket.binaryType = "arraybuffer";

await new Promise((resolve, reject) => {
socket.onopen = resolve;
socket.onerror = () => {
reject(new Error("WebSocket connect failed"));
};
});

const duplex = new DuplexStreamFactory<
Uint8Array,
Consumable<Uint8Array>
>({
close: () => {
socket.close();
},
});

socket.onclose = () => {
duplex.dispose().catch(unreachable);
};

const readable = duplex.wrapReadable(
new ReadableStream(
{
start: (controller) => {
socket.onmessage = ({
data,
}: {
data: ArrayBuffer;
}) => {
controller.enqueue(new Uint8Array(data));
};
},
},
{
highWaterMark: 16 * 1024,
size(chunk) {
return chunk.byteLength;
},
}
)
);

const writable = duplex.createWritable(
new ConsumableWritableStream({
write(chunk) {
socket.send(chunk);
},
})
);

return {
readable: readable.pipeThrough(
new StructDeserializeStream(AdbPacket)
),
writable: pipeFrom(writable, new AdbPacketSerializeStream()),
};
}
}
9 changes: 9 additions & 0 deletions packages/adb-daemon-ws/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./node_modules/@yume-chan/tsconfig/tsconfig.base.json",
"compilerOptions": {
"lib": [
"ESNext",
"DOM"
]
},
}
13 changes: 13 additions & 0 deletions packages/adb-daemon-ws/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"references": [
{
"path": "../adb/tsconfig.build.json"
},
{
"path": "../stream-extra/tsconfig.build.json"
},
{
"path": "./tsconfig.build.json"
},
]
}
Loading

0 comments on commit 43db8a1

Please sign in to comment.