Skip to content

Commit 618a4fd

Browse files
authored
Merge branch 'NetrisTV:master' into master
2 parents aecd468 + 4d2c7f6 commit 618a4fd

File tree

11 files changed

+122
-47
lines changed

11 files changed

+122
-47
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,10 @@ established over adb.
159159

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

164-
Parameters explanation: **TBD**.
163+
Configuration file format: [Configuration.d.ts](/src/types/Configuration.d.ts).
164+
165+
Configuration file example: [config.example.yaml](/config.example.yaml).
165166

166167
## Known issues
167168

config.example.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Run configuration example. See full config file spec in src/types/Configuration.d.ts
2+
3+
# Device trackers (default: true)
4+
runGoogTracker: false
5+
runApplTracker: false;
6+
7+
# HTTP[s] servers configuration
8+
server:
9+
- secure: false
10+
port: 8000
11+
redirectToSecure:
12+
port: 8443
13+
host: first-mobile-stand.example.com
14+
- secure: true
15+
port: 8443
16+
options:
17+
certPath: /Users/example/ssl/STAR_example_com.crt
18+
keyPath: /Users/example/ssl/STAR_example_com.key
19+
20+
# Announce remote device trackers. The server doesn't check their availability.
21+
remoteHostList:
22+
- useProxy: true # optional, default: false
23+
type: android # required, "android" | "ios"
24+
secure: true # required, false for HTTP, true for HTTPS
25+
hostname: second-mobile-stand.example.com
26+
port: 8443
27+
- useProxy: true
28+
type: ios
29+
secure: true
30+
hostname: second-mobile-stand.example.com
31+
port: 8443

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"node-pty": "^0.10.1",
2323
"portfinder": "^1.0.28",
2424
"tslib": "^1.9.3",
25-
"ws": "^7.4.6"
25+
"ws": "^7.4.6",
26+
"yaml": "^1.10.2"
2627
},
2728
"devDependencies": {
2829
"@types/bluebird": "^3.5.32",

src/server/Config.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import * as fs from 'fs';
33
import * as path from 'path';
44
import { Configuration, HostItem, ServerItem } from '../types/Configuration';
55
import { EnvName } from './EnvName';
6+
import YAML from 'yaml';
67

78
const DEFAULT_PORT = 8000;
89

10+
const YAML_RE = /^.+\.(yaml|yml)$/i;
11+
const JSON_RE = /^.+\.(json|js)$/i;
12+
913
export class Config {
1014
private static instance?: Config;
1115
public static getInstance(defaultConfig?: Configuration): Config {
@@ -37,7 +41,13 @@ export class Config {
3741
if (!configPath) {
3842
return;
3943
}
40-
this.fullConfig = JSON.parse(this.readFile(configPath));
44+
if (configPath.match(YAML_RE)) {
45+
this.fullConfig = YAML.parse(this.readFile(configPath));
46+
} else if (configPath.match(JSON_RE)) {
47+
this.fullConfig = JSON.parse(this.readFile(configPath));
48+
} else {
49+
throw Error(`Unknown file type: ${configPath}`);
50+
}
4151
}
4252

4353
public readFile(pathString: string): string {
@@ -50,10 +60,10 @@ export class Config {
5060
}
5161

5262
public getHostList(): HostItem[] {
53-
if (!this.fullConfig.hostList || !this.fullConfig.hostList.length) {
63+
if (!this.fullConfig.remoteHostList || !this.fullConfig.remoteHostList.length) {
5464
return [];
5565
}
56-
return this.fullConfig.hostList.splice(0);
66+
return this.fullConfig.remoteHostList.splice(0);
5767
}
5868

5969
public getRunLocalGoogTracker(): boolean {

src/server/appl-device/mw/StreamProxy.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,16 @@ export class StreamProxy extends Mw {
5050
try {
5151
command = ControlCenterCommand.fromJSON(event.data.toString());
5252
} catch (e) {
53-
console.error(`[${StreamProxy.TAG}], Received message: ${event.data}. Error: ${e.message}`);
53+
console.error(`${this.name}, Received message: ${event.data}. Error: ${e.message}`);
5454
return;
5555
}
56-
console.log(`[${StreamProxy.TAG}], Received message: type:"${command.getType()}", data:${command.getData()}.`);
56+
console.log(`${this.name}, Received message: type:"${command.getType()}", data:${command.getData()}.`);
5757
}
5858

5959
protected onSocketClose(): void {
6060
if (this.wsProxy) {
6161
this.wsProxy.release();
62+
delete this.wsProxy;
6263
}
6364
this.release();
6465
}

src/server/appl-device/services/QvhackRunner.ts

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,24 @@ import { ProcessRunner, ProcessRunnerEvents } from '../../services/ProcessRunner
33

44
export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
55
private static instances: Map<string, QvhackRunner> = new Map();
6+
public static SHUTDOWN_TIMEOUT = 15000;
67
public static getInstance(udid: string): QvhackRunner {
78
let instance = this.instances.get(udid);
89
if (!instance) {
910
instance = new QvhackRunner(udid);
1011
this.instances.set(udid, instance);
1112
instance.start();
12-
} else {
13-
if (instance.releaseTimeoutId) {
14-
clearTimeout(instance.releaseTimeoutId);
15-
}
1613
}
17-
instance.holders++;
14+
instance.lock();
1815
return instance;
1916
}
2017
protected TAG = '[QvhackRunner]';
2118
protected name: string;
2219
protected cmd = 'ws-qvh';
23-
protected holders = 0;
2420
protected releaseTimeoutId?: NodeJS.Timeout;
2521
protected address = '';
22+
protected started = false;
23+
private holders = 0;
2624

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

34+
protected lock(): void {
35+
if (this.releaseTimeoutId) {
36+
clearTimeout(this.releaseTimeoutId);
37+
}
38+
this.holders++;
39+
}
40+
41+
protected unlock(): void {
42+
this.holders--;
43+
if (this.holders > 0) {
44+
return;
45+
}
46+
this.releaseTimeoutId = setTimeout(() => {
47+
super.release();
48+
QvhackRunner.instances.delete(this.udid);
49+
}, QvhackRunner.SHUTDOWN_TIMEOUT);
50+
}
51+
3652
protected async getArgs(): Promise<string[]> {
3753
const port = await portfinder.getPortPromise();
3854
const host = `127.0.0.1:${port}`;
@@ -43,9 +59,9 @@ export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
4359
public start(): void {
4460
this.runProcess()
4561
.then(() => {
46-
// FIXME: for some reason `ws-qvh` does not emit `spawn` event
62+
// Wait for server to start listen on a port
4763
this.once('stderr', () => {
48-
this.spawned = true;
64+
this.started = true;
4965
this.emit('started', true);
5066
});
5167
})
@@ -54,15 +70,11 @@ export class QvhackRunner extends ProcessRunner<ProcessRunnerEvents> {
5470
});
5571
}
5672

73+
public isStarted(): boolean {
74+
return this.started;
75+
}
76+
5777
public release(): void {
58-
this.holders--;
59-
if (this.holders > 0) {
60-
return;
61-
}
62-
const TIME = 15000;
63-
this.releaseTimeoutId = setTimeout(() => {
64-
super.release();
65-
QvhackRunner.instances.delete(this.udid);
66-
}, TIME);
78+
this.unlock();
6779
}
6880
}

src/server/appl-device/services/WDARunner.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface WDARunnerEvents {
1313
export class WDARunner extends TypedEmitter<WDARunnerEvents> {
1414
protected static TAG = 'WDARunner';
1515
private static instances: Map<string, WDARunner> = new Map();
16+
public static SHUTDOWN_TIMEOUT = 15000;
1617
private static servers: Map<string, Server> = new Map();
1718
private static cachedScreenInfo: Map<string, any> = new Map();
1819
public static getInstance(udid: string): WDARunner {
@@ -21,10 +22,8 @@ export class WDARunner extends TypedEmitter<WDARunnerEvents> {
2122
instance = new WDARunner(udid);
2223
this.instances.set(udid, instance);
2324
instance.start();
24-
} else if (instance.releaseTimeoutId) {
25-
clearTimeout(instance.releaseTimeoutId);
2625
}
27-
instance.holders++;
26+
instance.lock();
2827
return instance;
2928
}
3029
public static async getServer(udid: string): Promise<Server> {
@@ -59,6 +58,31 @@ export class WDARunner extends TypedEmitter<WDARunnerEvents> {
5958
this.name = `[${WDARunner.TAG}][udid: ${this.udid}]`;
6059
}
6160

61+
protected lock(): void {
62+
if (this.releaseTimeoutId) {
63+
clearTimeout(this.releaseTimeoutId);
64+
}
65+
this.holders++;
66+
}
67+
68+
protected unlock(): void {
69+
this.holders--;
70+
if (this.holders > 0) {
71+
return;
72+
}
73+
this.releaseTimeoutId = setTimeout(async () => {
74+
WDARunner.servers.delete(this.udid);
75+
WDARunner.instances.delete(this.udid);
76+
if (this.server) {
77+
if (this.server.driver) {
78+
await this.server.driver.deleteSession();
79+
}
80+
this.server.close();
81+
delete this.server;
82+
}
83+
}, WDARunner.SHUTDOWN_TIMEOUT);
84+
}
85+
6286
public async request(command: ControlCenterCommand): Promise<any> {
6387
const driver = this.server?.driver;
6488
if (!driver) {
@@ -110,20 +134,6 @@ export class WDARunner extends TypedEmitter<WDARunnerEvents> {
110134
}
111135

112136
public release(): void {
113-
this.holders--;
114-
if (this.holders > 0) {
115-
return;
116-
}
117-
const TIME = 15000;
118-
this.releaseTimeoutId = setTimeout(async () => {
119-
WDARunner.servers.delete(this.udid);
120-
WDARunner.instances.delete(this.udid);
121-
if (this.server) {
122-
if (this.server.driver) {
123-
await this.server.driver.deleteSession();
124-
}
125-
this.server.close();
126-
}
127-
}, TIME);
137+
this.unlock();
128138
}
129139
}

src/server/mw/WebsocketProxy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export class WebsocketProxy extends Mw {
3939
}
4040

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

9192
public release(): void {
93+
if (this.released) {
94+
return;
95+
}
9296
super.release();
9397
this.released = true;
9498
this.flush();

src/server/services/ProcessRunner.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ChildProcessByStdio, spawn } from 'child_process';
44
import { Readable, Writable } from 'stream';
55

66
export interface ProcessRunnerEvents {
7+
spawned: boolean;
78
started: boolean;
89
stdout: string;
910
stderr: string;
@@ -42,11 +43,10 @@ export abstract class ProcessRunner<T extends ProcessRunnerEvents> extends Typed
4243

4344
this.proc.on('spawn', () => {
4445
this.spawned = true;
45-
this.emit('started', true);
46+
this.emit('spawned', true);
4647
});
4748

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

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

5858
this.proc.on('close', (code, signal) => {
59-
console.log(this.name, `"close" event. code ${code}, signal: ${signal}`);
6059
this.emit('close', { code, signal });
6160
});
6261
}

src/types/Configuration.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ export interface ServerItem {
2525
| boolean;
2626
}
2727

28+
// The configuration file must contain a single object with this structure
2829
export interface Configuration {
2930
server?: ServerItem[];
3031
runApplTracker?: boolean;
3132
announceApplTracker?: boolean;
3233
runGoogTracker?: boolean;
3334
announceGoogTracker?: boolean;
34-
hostList?: HostItem[];
35+
remoteHostList?: HostItem[];
3536
}

0 commit comments

Comments
 (0)