mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-04 18:29:23 +02:00
feat(adb): allow reverse.add
to accept any string local address
ref #410
This commit is contained in:
parent
c3ccd6a1f8
commit
b7c20dbd6f
3 changed files with 64 additions and 20 deletions
44
apps/demo/src/pages/reverse.tsx
Normal file
44
apps/demo/src/pages/reverse.tsx
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { decodeUtf8, WritableStream } from "@yume-chan/adb";
|
||||||
|
import { makeAutoObservable, reaction, runInAction } from "mobx";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { NextPage } from "next";
|
||||||
|
import { GlobalState } from "../state";
|
||||||
|
|
||||||
|
const state = makeAutoObservable({
|
||||||
|
log: [] as string[],
|
||||||
|
});
|
||||||
|
|
||||||
|
reaction(() => GlobalState.device, async device => {
|
||||||
|
if (!device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await device.reverse.remove('tcp:3000').catch(() => { });
|
||||||
|
await device.reverse.add('tcp:3000', 'tcp:1234', socket => {
|
||||||
|
runInAction(() => {
|
||||||
|
state.log.push(`received stream ${socket.localId}`);
|
||||||
|
});
|
||||||
|
socket.readable.pipeTo(new WritableStream({
|
||||||
|
write: chunk => {
|
||||||
|
runInAction(() => {
|
||||||
|
state.log.push(`data from ${socket.localId}: ${decodeUtf8(chunk)}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Return true to accept the connection.
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}, { fireImmediately: true });
|
||||||
|
|
||||||
|
const ReverseTesterPage: NextPage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{state.log.map(line => (
|
||||||
|
<div>{line}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default observer(ReverseTesterPage);
|
|
@ -16,21 +16,21 @@ export interface AdbForwardListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AdbReverseStringResponse =
|
const AdbReverseStringResponse =
|
||||||
new Struct({ littleEndian: true })
|
new Struct()
|
||||||
.string('length', { length: 4 })
|
.string('length', { length: 4 })
|
||||||
.string('content', { lengthField: 'length', lengthFieldBase: 16 });
|
.string('content', { lengthField: 'length', lengthFieldRadix: 16 });
|
||||||
|
|
||||||
const AdbReverseErrorResponse =
|
const AdbReverseErrorResponse =
|
||||||
new Struct({ littleEndian: true })
|
new Struct()
|
||||||
.fields(AdbReverseStringResponse)
|
.fields(AdbReverseStringResponse)
|
||||||
.postDeserialize((value) => {
|
.postDeserialize((value) => {
|
||||||
throw new Error(value.content);
|
throw new Error(value.content);
|
||||||
});
|
});
|
||||||
|
|
||||||
export class AdbReverseCommand extends AutoDisposable {
|
export class AdbReverseCommand extends AutoDisposable {
|
||||||
protected localPortToHandler = new Map<number, AdbIncomingSocketHandler>();
|
protected localAddressToHandler = new Map<string, AdbIncomingSocketHandler>();
|
||||||
|
|
||||||
protected deviceAddressToLocalPort = new Map<string, number>();
|
protected deviceAddressToLocalAddress = new Map<string, string>();
|
||||||
|
|
||||||
protected adb: Adb;
|
protected adb: Adb;
|
||||||
|
|
||||||
|
@ -44,10 +44,10 @@ export class AdbReverseCommand extends AutoDisposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected handleIncomingSocket = async (socket: AdbSocket) => {
|
protected handleIncomingSocket = async (socket: AdbSocket) => {
|
||||||
const address = socket.serviceString;
|
let address = socket.serviceString;
|
||||||
// Address format: `tcp:12345\0`
|
// ADB daemon appends `\0` to the service string
|
||||||
const port = Number.parseInt(address.substring(4));
|
address = address.replace(/\0/g, '');
|
||||||
return !!(await this.localPortToHandler.get(port)?.(socket));
|
return !!(await this.localAddressToHandler.get(address)?.(socket));
|
||||||
};
|
};
|
||||||
|
|
||||||
private async createBufferedStream(service: string) {
|
private async createBufferedStream(service: string) {
|
||||||
|
@ -78,16 +78,16 @@ export class AdbReverseCommand extends AutoDisposable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param deviceAddress The address adbd on device is listening on. Can be `tcp:0` to let adbd choose an available TCP port by itself.
|
* @param deviceAddress The address adbd on device is listening on. Can be `tcp:0` to let adbd choose an available TCP port by itself.
|
||||||
* @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.
|
* @param localAddress Native ADB client will open a connection to this address when reverse connection received. In WebADB, it's only used to uniquely identify a reverse tunnel registry, `handler` will be called to handle the connection.
|
||||||
* @param handler A callback to handle incoming connections
|
* @param handler A callback to handle incoming connections
|
||||||
* @returns If `deviceAddress` is `tcp:0`, return `tcp:{ACTUAL_LISTENING_PORT}`; otherwise, return `deviceAddress`.
|
* @returns If `deviceAddress` is `tcp:0`, return `tcp:{ACTUAL_LISTENING_PORT}`; otherwise, return `deviceAddress`.
|
||||||
*/
|
*/
|
||||||
public async add(
|
public async add(
|
||||||
deviceAddress: string,
|
deviceAddress: string,
|
||||||
localPort: number,
|
localAddress: string,
|
||||||
handler: AdbIncomingSocketHandler,
|
handler: AdbIncomingSocketHandler,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const stream = await this.sendRequest(`reverse:forward:${deviceAddress};tcp:${localPort}`);
|
const stream = await this.sendRequest(`reverse:forward:${deviceAddress};${localAddress}`);
|
||||||
|
|
||||||
// `tcp:0` tells the device to pick an available port.
|
// `tcp:0` tells the device to pick an available port.
|
||||||
// Begin with Android 8, device will respond with the selected port for all `tcp:` requests.
|
// Begin with Android 8, device will respond with the selected port for all `tcp:` requests.
|
||||||
|
@ -111,8 +111,8 @@ export class AdbReverseCommand extends AutoDisposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.localPortToHandler.set(localPort, handler);
|
this.localAddressToHandler.set(localAddress, handler);
|
||||||
this.deviceAddressToLocalPort.set(deviceAddress, localPort);
|
this.deviceAddressToLocalAddress.set(deviceAddress, localAddress);
|
||||||
return deviceAddress;
|
return deviceAddress;
|
||||||
|
|
||||||
// No need to close the stream, device will close it
|
// No need to close the stream, device will close it
|
||||||
|
@ -121,9 +121,9 @@ export class AdbReverseCommand extends AutoDisposable {
|
||||||
public async remove(deviceAddress: string): Promise<void> {
|
public async remove(deviceAddress: string): Promise<void> {
|
||||||
await this.sendRequest(`reverse:killforward:${deviceAddress}`);
|
await this.sendRequest(`reverse:killforward:${deviceAddress}`);
|
||||||
|
|
||||||
if (this.deviceAddressToLocalPort.has(deviceAddress)) {
|
if (this.deviceAddressToLocalAddress.has(deviceAddress)) {
|
||||||
this.localPortToHandler.delete(this.deviceAddressToLocalPort.get(deviceAddress)!);
|
this.localAddressToHandler.delete(this.deviceAddressToLocalAddress.get(deviceAddress)!);
|
||||||
this.deviceAddressToLocalPort.delete(deviceAddress);
|
this.deviceAddressToLocalAddress.delete(deviceAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to close the stream, device will close it
|
// No need to close the stream, device will close it
|
||||||
|
@ -132,8 +132,8 @@ export class AdbReverseCommand extends AutoDisposable {
|
||||||
public async removeAll(): Promise<void> {
|
public async removeAll(): Promise<void> {
|
||||||
await this.sendRequest(`reverse:killforward-all`);
|
await this.sendRequest(`reverse:killforward-all`);
|
||||||
|
|
||||||
this.deviceAddressToLocalPort.clear();
|
this.deviceAddressToLocalAddress.clear();
|
||||||
this.localPortToHandler.clear();
|
this.localAddressToHandler.clear();
|
||||||
|
|
||||||
// No need to close the stream, device will close it
|
// No need to close the stream, device will close it
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ export class ScrcpyClientReverseConnection extends ScrcpyClientConnection {
|
||||||
const writer = queue.writable.getWriter();
|
const writer = queue.writable.getWriter();
|
||||||
this.address = await this.device.reverse.add(
|
this.address = await this.device.reverse.add(
|
||||||
'localabstract:scrcpy',
|
'localabstract:scrcpy',
|
||||||
27183,
|
'tcp:27183',
|
||||||
socket => {
|
socket => {
|
||||||
writer.write(socket);
|
writer.write(socket);
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue