@quick-game/cli
Version:
Command line interface for rapid qg development
352 lines (313 loc) • 11.7 kB
JavaScript
"use strict";var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");_Object$defineProperty(exports, "__esModule", { value: true });exports.default = void 0;var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map"));var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));var _from = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/array/from"));
var _adbDevicesEmitter = _interopRequireDefault(require("adb-devices-emitter"));
var _adbCommander = _interopRequireDefault(require("adb-commander"));
var _recordClient = require("../record-client.js");
var _debuglog = _interopRequireDefault(require("./debuglog")); /**
* Copyright (C) 2017, hapjs.org. All rights reserved.
*/const REMOTE_REVERSE_PORT = 12306;
const REMOTE_UP_FORWARD_PORT = 39517;
/**
* ADB Modules
*/
class ADBModule {
/**
* ADBModule constructor
* @param option
* @param option.localReversePort {number} adb reverse命令使用的端口
*/
constructor(option) {
this.option = option;
// 当前连接的设备列表 sn: { upForwardPortPair:[localPort, remotePort], wsPortPair[localPort, remotePort] }
this.currentDeviceMap = new _map.default();
// 用来记录所有当前连接和已拔出的设备列表
this.cachedDeviceMap = new _map.default();
this.DEBUG = (process.env.NODE_DEBUG || '').split(',').includes('adb');
// 记录localUpForwardPort(自增)的端口号, 初始值等于REMOTE_UP_FORWARD_PORT
this._localUpForwardPort = REMOTE_UP_FORWARD_PORT;
this.commander = _adbCommander.default;
this.devicesEmitter = _adbDevicesEmitter.default;
this._lastPromise = null;
this.emulators = new _map.default();
this.init();
}
/**
* 注册事件, 开始查询设备
*/
init() {
(0, _debuglog.default)(`init(): start`);
this.devicesEmitter.addEventListener('deviceAdded', (event) => {
this._listen(event, this.onDeviceAdded.bind(this));
});
this.devicesEmitter.addEventListener('deviceRemoved', (event) => {
this._listen(event, this.onDeviceRemoved.bind(this));
});
this.devicesEmitter.start();
}
/**
* 确保队列式的调用顺序
* @private
*/
_listen(event, callback) {
if (!this._lastPromise) {
this._lastPromise = callback(event);
} else {
this._lastPromise = this._lastPromise.then(
() => {
return callback(event);
},
() => {
return callback(event);
}
);
}
}
/**
* 取得一个_localUpForwardPort端口数字
* @private
*/
_getNextLocalForwardPort() {
return this._localUpForwardPort++;
}
/**
* 处理每个新增设备
* @desc
* 为每一个设备执行以下操作:
* 1. adb reverse tcp:${localReversePort} tcp:REMOTE_REVERSE_PORT,
* 2. adb forward tcp:${localUpForwardPort} tcp:REMOTE_UP_FORWARD_PORT;
* 3. 如果cachedDeviceList中存在当前新增设备, 且状态为已断开, 检查该设备是否
* 已有wsForwardPort端口记录信息, 有则执行adb forward tcp:${wsPair[0]} tcp:${wsPair[1]};
* 4. 为currentList中新增当前设备;
* @param event
* @param event.sn 设备序列号
*/
async onDeviceAdded(event) {
const { sn } = event;
console.info(`### App Server ### 手机设备(${sn})被连入`);
const { result } = await this.commander.getProp(sn);
if (result) {
this.emulators.set(result.trim(), sn);
}
const localReversePort = this.option.localReversePort;
// 建立reverse设定
const reverseResult = await this.establishADBProxyLink('reverse', [
sn,
localReversePort,
REMOTE_REVERSE_PORT]
);
if (reverseResult.err) {
console.error(
`### App Server ### onDeviceAdded(): (${sn})建立adb reverse失败(local port: ${localReversePort}, remote port: ${REMOTE_REVERSE_PORT})`
);
return;
}
// 检查cachedDeviceList中的设备状况
let currentDevice = this.cachedDeviceMap.get(sn);
(0, _debuglog.default)(
`onDeviceAdded():(${sn})\ncachedDevice:\t${(0, _stringify.default)(
currentDevice
)}\ncachedDeviceList:\t${(0, _stringify.default)((0, _from.default)(this.cachedDeviceMap.entries()))}`
);
// 建立forward update port设定
if (!currentDevice || !currentDevice.upForwardPortPair) {
currentDevice = {
upForwardPortPair: [this._getNextLocalForwardPort(), REMOTE_UP_FORWARD_PORT]
};
}
const upForwardResult = await this.establishADBProxyLink(
'forward',
[sn].concat(currentDevice.upForwardPortPair)
);
if (upForwardResult.err) {
console.error(
`### App Server ### onDeviceAdded(): (${sn})建立adb forward失败(local port: ${
currentDevice.upForwardPortPair[0]}, remote port: ${
currentDevice.upForwardPortPair[1]}) `
);
return;
}
// 如果有记录的调试端口 为调试web socket建立forward
if (currentDevice.wsPortPair) {
const debugForwardResult = await this.establishADBProxyLink('forward', [
sn,
currentDevice.wsPortPair[0],
currentDevice.wsPortPair[1]]
);
if (debugForwardResult.err) {
console.info(
`### App Server ### onDeviceAdded():(${sn}) 建立adb forward失败(local port: ${
currentDevice.wsPortPair[0]}, remote port: ${
currentDevice.wsPortPair[1]})`
);
currentDevice.wsPortPair = undefined;
}
}
// 记录当前设备
this.currentDeviceMap.set(sn, currentDevice);
this.cachedDeviceMap.set(sn, currentDevice);
// 记录发送update http请求需要的ip和端口
await this._writeClientLogFile({
sn,
ip: `127.0.0.1`,
port: currentDevice.upForwardPortPair[0]
});
(0, _debuglog.default)(`onDeviceAdded():(${sn}) end`);
}
/**
* 移除设备事件
*/
async onDeviceRemoved(event) {
const { sn } = event;
console.info(`### App Server ### 手机设备(${sn})被拔出`);
this.currentDeviceMap.delete(sn);
if (this.DEBUG) {
(0, _debuglog.default)(
`deviceRemoved():(${sn}) cachedDeviceList: ${(0, _stringify.default)(
(0, _from.default)(this.cachedDeviceMap.entries())
)}`
);
await this.commander.print(`adb -s ${sn} reverse --list`);
await this.commander.print(`adb -s ${sn} forward --list`);
}
await this._removeItemFromClientLogFile(sn);
(0, _debuglog.default)(`deviceRemoved():(${sn}) end`);
}
/**
* 记录一条端口映射条目
*/
async _writeClientLogFile(newClient) {
try {
(0, _recordClient.recordClient)(_recordClient.clientRecordPath, newClient, (msg) => {
(0, _debuglog.default)(msg);
});
} catch (err) {
console.error(
`### App Server ### writeClientLogFile(): 写入client.json文件出错: ${err.message}`
);
}
}
/**
* 从端口映射记录文件中移除一个条目
*/
async _removeItemFromClientLogFile(sn) {
try {
(0, _recordClient.removeClientBySn)(_recordClient.clientRecordPath, sn, (msg) => {
(0, _debuglog.default)(msg);
});
} catch (err) {
console.error(
`### App Server ### _removeItemFromClientLogFile(): 移除client.json设备信息出错: ${err.message}`
);
}
}
/**
* 建立Websocket连接的端口映射
* @param sn 设备序列号
* @param remoteWsPort Websocket连接的远程端口号
* @returns {Promise.<{ localWsPort } | { err }>}
*/
async forwardForWsChannel(sn, remoteWsPort) {
let device = this.currentDeviceMap.get(sn);
// 暂时localWsPort与remoteWsPort一样;
const localWsPort = remoteWsPort;
const localReversePort = this.option.localReversePort;
if (!sn) {
const { err } = await this.setupPortForwarding(localWsPort, remoteWsPort);
if (err) {
console.error(`### AppApp Server ### forwardForWsChannel(): 创建WebSocket端口映射失败`);
return { err };
}
return { localWsPort, localReversePort };
}
if (!device) {
const realSN = this.emulators.get(sn);
console.info(`### App Server ### 通过(${sn})查找到设备${realSN}`);
device = this.currentDeviceMap.get(realSN);
if (device) {
sn = realSN;
}
}
if (!device) {
console.error(`### App Server ### 获取(${sn})设备信息失败`);
return { localWsPort, localReversePort };
}
const wsPortPair = device.wsPortPair;
// 若之前不存在端口, 说明是第一次连接,否则可以不必设定
if (wsPortPair && wsPortPair[0] === localWsPort && wsPortPair[1] === remoteWsPort) {
return { localWsPort, localReversePort };
}
const { err } = await this.establishADBProxyLink('forward', [sn, localWsPort, remoteWsPort]);
if (err) {
console.error(`### AppApp Server ### forwardForWsChannel(): 创建WebSocket端口映射失败`);
device.wsPortPair = undefined;
return { err };
}
device.wsPortPair = [localWsPort, remoteWsPort];
return { localWsPort, localReversePort };
}
/**
* 建立adb reverse/forward通道
* @param type {string} "reverse"|"forward"
* @param args {array} 建立reverse/forward通道所需的参数. e.g. [sn, localPort, devicePort]
*/
async establishADBProxyLink(type, args) {
const result = await this.commander[type](...args);
if (this.DEBUG) {
(0, _debuglog.default)(
`establishADBReverseLink(): (${args[0]}) adb ${type} setup result: ${(0, _stringify.default)(
result
)}`
);
await this.commander.print(`adb -s ${args[0]} ${type} --list`);
}
if (result.err) {
const { err } = await this.setupPortReversing(args[1], args[2]);
if (err) {
console.error(`### AppApp Server ### setupPortReversing(): 创建adb端口映射失败 ${args[1]} ${args[2]} ${err}`);
return { err };
}
return {};
}
return result;
}
// Sample function to set up port forwarding
async setupPortForwarding(localPort, remotePort) {
try {
// Check connected devices
const { deviceList } = await this.commander.deviceList();
// If no devices are connected, handle it
if (deviceList.length === 0) {
console.log('No devices connected.');
return;
}
// Use the first device if multiple are connected
const deviceSerial = deviceList[0];
// Forward the port
const result = await this.commander.forward(deviceSerial, localPort, remotePort);
return result;
} catch (error) {
console.error('Error forwarding port:', error);
}
return { err: 'Port forwarding failed' };
}
// Sample function to set up port forwarding
async setupPortReversing(localPort, remotePort) {
try {
// Check connected devices
const { deviceList } = await this.commander.deviceList();
// If no devices are connected, handle it
if (deviceList.length === 0) {
console.log('No devices connected.');
return;
}
// Use the first device if multiple are connected
const deviceSerial = deviceList[0];
// Forward the port
const result = await this.commander.reverse(deviceSerial, localPort, remotePort);
return result;
} catch (error) {
console.error('Error forwarding port:', error);
}
return { err: 'Port forwarding failed' };
}
}var _default = exports.default =
ADBModule;