Skip to content

Commit

Permalink
Merge branch 'NetrisTV:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalyrepin authored Nov 1, 2021
2 parents aecd468 + 4d2c7f6 commit 618a4fd
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 47 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,10 @@ established over adb.

You can specify a path to a configuration file in `WS_SCRCPY_CONFIG`
environment variable.
Configuration file format: [source](/src/types/Configuration.d.ts).

Parameters explanation: **TBD**.
Configuration file format: [Configuration.d.ts](/src/types/Configuration.d.ts).

Configuration file example: [config.example.yaml](/config.example.yaml).

## Known issues

Expand Down
31 changes: 31 additions & 0 deletions config.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Run configuration example. See full config file spec in src/types/Configuration.d.ts

# Device trackers (default: true)
runGoogTracker: false
runApplTracker: false;

# HTTP[s] servers configuration
server:
- secure: false
port: 8000
redirectToSecure:
port: 8443
host: first-mobile-stand.example.com
- secure: true
port: 8443
options:
certPath: /Users/example/ssl/STAR_example_com.crt
keyPath: /Users/example/ssl/STAR_example_com.key

# Announce remote device trackers. The server doesn't check their availability.
remoteHostList:
- useProxy: true # optional, default: false
type: android # required, "android" | "ios"
secure: true # required, false for HTTP, true for HTTPS
hostname: second-mobile-stand.example.com
port: 8443
- useProxy: true
type: ios
secure: true
hostname: second-mobile-stand.example.com
port: 8443
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"node-pty": "^0.10.1",
"portfinder": "^1.0.28",
"tslib": "^1.9.3",
"ws": "^7.4.6"
"ws": "^7.4.6",
"yaml": "^1.10.2"
},
"devDependencies": {
"@types/bluebird": "^3.5.32",
Expand Down
16 changes: 13 additions & 3 deletions src/server/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import * as fs from 'fs';
import * as path from 'path';
import { Configuration, HostItem, ServerItem } from '../types/Configuration';
import { EnvName } from './EnvName';
import YAML from 'yaml';

const DEFAULT_PORT = 8000;

const YAML_RE = /^.+\.(yaml|yml)$/i;
const JSON_RE = /^.+\.(json|js)$/i;

export class Config {
private static instance?: Config;
public static getInstance(defaultConfig?: Configuration): Config {
Expand Down Expand Up @@ -37,7 +41,13 @@ export class Config {
if (!configPath) {
return;
}
this.fullConfig = JSON.parse(this.readFile(configPath));
if (configPath.match(YAML_RE)) {
this.fullConfig = YAML.parse(this.readFile(configPath));
} else if (configPath.match(JSON_RE)) {
this.fullConfig = JSON.parse(this.readFile(configPath));
} else {
throw Error(`Unknown file type: ${configPath}`);
}
}

public readFile(pathString: string): string {
Expand All @@ -50,10 +60,10 @@ export class Config {
}

public getHostList(): HostItem[] {
if (!this.fullConfig.hostList || !this.fullConfig.hostList.length) {
if (!this.fullConfig.remoteHostList || !this.fullConfig.remoteHostList.length) {
return [];
}
return this.fullConfig.hostList.splice(0);
return this.fullConfig.remoteHostList.splice(0);
}

public getRunLocalGoogTracker(): boolean {
Expand Down
5 changes: 3 additions & 2 deletions src/server/appl-device/mw/StreamProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,16 @@ export class StreamProxy extends Mw {
try {
command = ControlCenterCommand.fromJSON(event.data.toString());
} catch (e) {
console.error(`[${StreamProxy.TAG}], Received message: ${event.data}. Error: ${e.message}`);
console.error(`${this.name}, Received message: ${event.data}. Error: ${e.message}`);
return;
}
console.log(`[${StreamProxy.TAG}], Received message: type:"${command.getType()}", data:${command.getData()}.`);
console.log(`${this.name}, Received message: type:"${command.getType()}", data:${command.getData()}.`);
}

protected onSocketClose(): void {
if (this.wsProxy) {
this.wsProxy.release();
delete this.wsProxy;
}
this.release();
}
Expand Down
46 changes: 29 additions & 17 deletions src/server/appl-device/services/QvhackRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ import { ProcessRunner, ProcessRunnerEvents } from '../../services/ProcessRunner

export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
private static instances: Map<string, QvhackRunner> = new Map();
public static SHUTDOWN_TIMEOUT = 15000;
public static getInstance(udid: string): QvhackRunner {
let instance = this.instances.get(udid);
if (!instance) {
instance = new QvhackRunner(udid);
this.instances.set(udid, instance);
instance.start();
} else {
if (instance.releaseTimeoutId) {
clearTimeout(instance.releaseTimeoutId);
}
}
instance.holders++;
instance.lock();
return instance;
}
protected TAG = '[QvhackRunner]';
protected name: string;
protected cmd = 'ws-qvh';
protected holders = 0;
protected releaseTimeoutId?: NodeJS.Timeout;
protected address = '';
protected started = false;
private holders = 0;

constructor(private readonly udid: string) {
super();
Expand All @@ -33,6 +31,24 @@ export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
return this.address;
}

protected lock(): void {
if (this.releaseTimeoutId) {
clearTimeout(this.releaseTimeoutId);
}
this.holders++;
}

protected unlock(): void {
this.holders--;
if (this.holders > 0) {
return;
}
this.releaseTimeoutId = setTimeout(() => {
super.release();
QvhackRunner.instances.delete(this.udid);
}, QvhackRunner.SHUTDOWN_TIMEOUT);
}

protected async getArgs(): Promise<string[]> {
const port = await portfinder.getPortPromise();
const host = `127.0.0.1:${port}`;
Expand All @@ -43,9 +59,9 @@ export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
public start(): void {
this.runProcess()
.then(() => {
// FIXME: for some reason `ws-qvh` does not emit `spawn` event
// Wait for server to start listen on a port
this.once('stderr', () => {
this.spawned = true;
this.started = true;
this.emit('started', true);
});
})
Expand All @@ -54,15 +70,11 @@ export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
});
}

public isStarted(): boolean {
return this.started;
}

public release(): void {
this.holders--;
if (this.holders > 0) {
return;
}
const TIME = 15000;
this.releaseTimeoutId = setTimeout(() => {
super.release();
QvhackRunner.instances.delete(this.udid);
}, TIME);
this.unlock();
}
}
46 changes: 28 additions & 18 deletions src/server/appl-device/services/WDARunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface WDARunnerEvents {
export class WDARunner extends TypedEmitter<WDARunnerEvents> {
protected static TAG = 'WDARunner';
private static instances: Map<string, WDARunner> = new Map();
public static SHUTDOWN_TIMEOUT = 15000;
private static servers: Map<string, Server> = new Map();
private static cachedScreenInfo: Map<string, any> = new Map();
public static getInstance(udid: string): WDARunner {
Expand All @@ -21,10 +22,8 @@ export class WDARunner extends TypedEmitter<WDARunnerEvents> {
instance = new WDARunner(udid);
this.instances.set(udid, instance);
instance.start();
} else if (instance.releaseTimeoutId) {
clearTimeout(instance.releaseTimeoutId);
}
instance.holders++;
instance.lock();
return instance;
}
public static async getServer(udid: string): Promise<Server> {
Expand Down Expand Up @@ -59,6 +58,31 @@ export class WDARunner extends TypedEmitter<WDARunnerEvents> {
this.name = `[${WDARunner.TAG}][udid: ${this.udid}]`;
}

protected lock(): void {
if (this.releaseTimeoutId) {
clearTimeout(this.releaseTimeoutId);
}
this.holders++;
}

protected unlock(): void {
this.holders--;
if (this.holders > 0) {
return;
}
this.releaseTimeoutId = setTimeout(async () => {
WDARunner.servers.delete(this.udid);
WDARunner.instances.delete(this.udid);
if (this.server) {
if (this.server.driver) {
await this.server.driver.deleteSession();
}
this.server.close();
delete this.server;
}
}, WDARunner.SHUTDOWN_TIMEOUT);
}

public async request(command: ControlCenterCommand): Promise<any> {
const driver = this.server?.driver;
if (!driver) {
Expand Down Expand Up @@ -110,20 +134,6 @@ export class WDARunner extends TypedEmitter<WDARunnerEvents> {
}

public release(): void {
this.holders--;
if (this.holders > 0) {
return;
}
const TIME = 15000;
this.releaseTimeoutId = setTimeout(async () => {
WDARunner.servers.delete(this.udid);
WDARunner.instances.delete(this.udid);
if (this.server) {
if (this.server.driver) {
await this.server.driver.deleteSession();
}
this.server.close();
}
}, TIME);
this.unlock();
}
}
4 changes: 4 additions & 0 deletions src/server/mw/WebsocketProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class WebsocketProxy extends Mw {
}

public async init(remoteUrl: string): Promise<void> {
this.name = `[${WebsocketProxy.TAG}{$${remoteUrl}}]`;
const remoteSocket = new WS(remoteUrl);
remoteSocket.onopen = () => {
this.remoteSocket = remoteSocket;
Expand Down Expand Up @@ -89,6 +90,9 @@ export class WebsocketProxy extends Mw {
}

public release(): void {
if (this.released) {
return;
}
super.release();
this.released = true;
this.flush();
Expand Down
5 changes: 2 additions & 3 deletions src/server/services/ProcessRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ChildProcessByStdio, spawn } from 'child_process';
import { Readable, Writable } from 'stream';

export interface ProcessRunnerEvents {
spawned: boolean;
started: boolean;
stdout: string;
stderr: string;
Expand Down Expand Up @@ -42,11 +43,10 @@ export abstract class ProcessRunner<T extends ProcessRunnerEvents> extends Typed

this.proc.on('spawn', () => {
this.spawned = true;
this.emit('started', true);
this.emit('spawned', true);
});

this.proc.on('exit', (code, signal) => {
console.log(this.name, `"exit" event. code ${code}, signal: ${signal}`);
this.emit('exit', { code, signal });
});

Expand All @@ -56,7 +56,6 @@ export abstract class ProcessRunner<T extends ProcessRunnerEvents> extends Typed
});

this.proc.on('close', (code, signal) => {
console.log(this.name, `"close" event. code ${code}, signal: ${signal}`);
this.emit('close', { code, signal });
});
}
Expand Down
3 changes: 2 additions & 1 deletion src/types/Configuration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ export interface ServerItem {
| boolean;
}

// The configuration file must contain a single object with this structure
export interface Configuration {
server?: ServerItem[];
runApplTracker?: boolean;
announceApplTracker?: boolean;
runGoogTracker?: boolean;
announceGoogTracker?: boolean;
hostList?: HostItem[];
remoteHostList?: HostItem[];
}

0 comments on commit 618a4fd

Please sign in to comment.