forked from olcxjas-softworks/LarpixClient
fix gitignore again
This commit is contained in:
parent
ce5a1e330b
commit
5da5c2afe2
3329 changed files with 364540 additions and 3 deletions
164
electron/node_modules/native-run/dist/ios/lib/client/afc.js
generated
vendored
Normal file
164
electron/node_modules/native-run/dist/ios/lib/client/afc.js
generated
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AFCClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const util_1 = require("util");
|
||||
const afc_1 = require("../protocol/afc");
|
||||
const client_1 = require("./client");
|
||||
const debug = Debug('native-run:ios:lib:client:afc');
|
||||
const MAX_OPEN_FILES = 240;
|
||||
class AFCClient extends client_1.ServiceClient {
|
||||
constructor(socket) {
|
||||
super(socket, new afc_1.AFCProtocolClient(socket));
|
||||
this.socket = socket;
|
||||
}
|
||||
async getFileInfo(path) {
|
||||
debug(`getFileInfo: ${path}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
operation: afc_1.AFC_OPS.GET_FILE_INFO,
|
||||
data: toCString(path),
|
||||
});
|
||||
const strings = [];
|
||||
let currentString = '';
|
||||
const tokens = resp.data;
|
||||
tokens.forEach((token) => {
|
||||
if (token === 0) {
|
||||
strings.push(currentString);
|
||||
currentString = '';
|
||||
}
|
||||
else {
|
||||
currentString += String.fromCharCode(token);
|
||||
}
|
||||
});
|
||||
return strings;
|
||||
}
|
||||
async writeFile(fd, data) {
|
||||
debug(`writeFile: ${Array.prototype.toString.call(fd)}`);
|
||||
return this.protocolClient.sendMessage({
|
||||
operation: afc_1.AFC_OPS.FILE_WRITE,
|
||||
data: fd,
|
||||
payload: data,
|
||||
});
|
||||
}
|
||||
async openFile(path) {
|
||||
debug(`openFile: ${path}`);
|
||||
// mode + path + null terminator
|
||||
const data = Buffer.alloc(8 + Buffer.byteLength(path) + 1);
|
||||
// write mode
|
||||
data.writeUInt32LE(afc_1.AFC_FILE_OPEN_FLAGS.WRONLY, 0);
|
||||
// then path to file
|
||||
toCString(path).copy(data, 8);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
operation: afc_1.AFC_OPS.FILE_OPEN,
|
||||
data,
|
||||
});
|
||||
if (resp.operation === afc_1.AFC_OPS.FILE_OPEN_RES) {
|
||||
return resp.data;
|
||||
}
|
||||
throw new Error(`There was an unknown error opening file ${path}, response: ${Array.prototype.toString.call(resp.data)}`);
|
||||
}
|
||||
async closeFile(fd) {
|
||||
debug(`closeFile fd: ${Array.prototype.toString.call(fd)}`);
|
||||
return this.protocolClient.sendMessage({
|
||||
operation: afc_1.AFC_OPS.FILE_CLOSE,
|
||||
data: fd,
|
||||
});
|
||||
}
|
||||
async uploadFile(srcPath, destPath) {
|
||||
debug(`uploadFile: ${srcPath}`);
|
||||
// read local file and get fd of destination
|
||||
const [srcFile, destFile] = await Promise.all([
|
||||
await (0, util_1.promisify)(fs.readFile)(srcPath),
|
||||
await this.openFile(destPath),
|
||||
]);
|
||||
try {
|
||||
await this.writeFile(destFile, srcFile);
|
||||
await this.closeFile(destFile);
|
||||
}
|
||||
catch (err) {
|
||||
await this.closeFile(destFile);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async makeDirectory(path) {
|
||||
debug(`makeDirectory: ${path}`);
|
||||
return this.protocolClient.sendMessage({
|
||||
operation: afc_1.AFC_OPS.MAKE_DIR,
|
||||
data: toCString(path),
|
||||
});
|
||||
}
|
||||
async uploadDirectory(srcPath, destPath) {
|
||||
debug(`uploadDirectory: ${srcPath}`);
|
||||
await this.makeDirectory(destPath);
|
||||
// AFC doesn't seem to give out more than 240 file handles,
|
||||
// so we delay any requests that would push us over until more open up
|
||||
let numOpenFiles = 0;
|
||||
const pendingFileUploads = [];
|
||||
const _this = this;
|
||||
return uploadDir(srcPath);
|
||||
async function uploadDir(dirPath) {
|
||||
const promises = [];
|
||||
for (const file of fs.readdirSync(dirPath)) {
|
||||
const filePath = path.join(dirPath, file);
|
||||
const remotePath = path.join(destPath, path.relative(srcPath, filePath));
|
||||
if (fs.lstatSync(filePath).isDirectory()) {
|
||||
promises.push(_this.makeDirectory(remotePath).then(() => uploadDir(filePath)));
|
||||
}
|
||||
else {
|
||||
// Create promise to add to promises array
|
||||
// this way it can be resolved once a pending upload has finished
|
||||
let resolve;
|
||||
let reject;
|
||||
const promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
promises.push(promise);
|
||||
// wrap upload in a function in case we need to save it for later
|
||||
const uploadFile = (tries = 0) => {
|
||||
numOpenFiles++;
|
||||
_this
|
||||
.uploadFile(filePath, remotePath)
|
||||
.then(() => {
|
||||
resolve();
|
||||
numOpenFiles--;
|
||||
const fn = pendingFileUploads.pop();
|
||||
if (fn) {
|
||||
fn();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
// Couldn't get fd for whatever reason, try again
|
||||
// # of retries is arbitrary and can be adjusted
|
||||
if (err.status === afc_1.AFC_STATUS.NO_RESOURCES && tries < 10) {
|
||||
debug(`Received NO_RESOURCES from AFC, retrying ${filePath} upload. ${tries}`);
|
||||
uploadFile(tries++);
|
||||
}
|
||||
else {
|
||||
numOpenFiles--;
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (numOpenFiles < MAX_OPEN_FILES) {
|
||||
uploadFile();
|
||||
}
|
||||
else {
|
||||
debug(`numOpenFiles >= ${MAX_OPEN_FILES}, adding to pending queue. Length: ${pendingFileUploads.length}`);
|
||||
pendingFileUploads.push(uploadFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AFCClient = AFCClient;
|
||||
function toCString(s) {
|
||||
const buf = Buffer.alloc(Buffer.byteLength(s) + 1);
|
||||
const len = buf.write(s);
|
||||
buf.writeUInt8(0, len);
|
||||
return buf;
|
||||
}
|
||||
17
electron/node_modules/native-run/dist/ios/lib/client/client.js
generated
vendored
Normal file
17
electron/node_modules/native-run/dist/ios/lib/client/client.js
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ResponseError = exports.ServiceClient = void 0;
|
||||
class ServiceClient {
|
||||
constructor(socket, protocolClient) {
|
||||
this.socket = socket;
|
||||
this.protocolClient = protocolClient;
|
||||
}
|
||||
}
|
||||
exports.ServiceClient = ServiceClient;
|
||||
class ResponseError extends Error {
|
||||
constructor(msg, response) {
|
||||
super(msg);
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
exports.ResponseError = ResponseError;
|
||||
66
electron/node_modules/native-run/dist/ios/lib/client/debugserver.js
generated
vendored
Normal file
66
electron/node_modules/native-run/dist/ios/lib/client/debugserver.js
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DebugserverClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const path = require("path");
|
||||
const gdb_1 = require("../protocol/gdb");
|
||||
const client_1 = require("./client");
|
||||
const debug = Debug('native-run:ios:lib:client:debugserver');
|
||||
class DebugserverClient extends client_1.ServiceClient {
|
||||
constructor(socket) {
|
||||
super(socket, new gdb_1.GDBProtocolClient(socket));
|
||||
this.socket = socket;
|
||||
}
|
||||
async setMaxPacketSize(size) {
|
||||
return this.sendCommand('QSetMaxPacketSize:', [size.toString()]);
|
||||
}
|
||||
async setWorkingDir(workingDir) {
|
||||
return this.sendCommand('QSetWorkingDir:', [workingDir]);
|
||||
}
|
||||
async checkLaunchSuccess() {
|
||||
return this.sendCommand('qLaunchSuccess', []);
|
||||
}
|
||||
async attachByName(name) {
|
||||
const hexName = Buffer.from(name).toString('hex');
|
||||
return this.sendCommand(`vAttachName;${hexName}`, []);
|
||||
}
|
||||
async continue() {
|
||||
return this.sendCommand('c', []);
|
||||
}
|
||||
halt() {
|
||||
// ^C
|
||||
debug('Sending ^C to debugserver');
|
||||
return this.protocolClient.socket.write('\u0003');
|
||||
}
|
||||
async kill() {
|
||||
const msg = { cmd: 'k', args: [] };
|
||||
return this.protocolClient.sendMessage(msg, (resp, resolve, reject) => {
|
||||
this.protocolClient.socket.write('+');
|
||||
const parts = resp.split(';');
|
||||
for (const part of parts) {
|
||||
if (part.includes('description')) {
|
||||
// description:{hex encoded message like: "Terminated with signal 9"}
|
||||
resolve(Buffer.from(part.split(':')[1], 'hex').toString('ascii'));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// TODO support app args
|
||||
// https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#Packets
|
||||
// A arglen,argnum,arg,
|
||||
async launchApp(appPath, executableName) {
|
||||
const fullPath = path.join(appPath, executableName);
|
||||
const hexAppPath = Buffer.from(fullPath).toString('hex');
|
||||
const appCommand = `A${hexAppPath.length},0,${hexAppPath}`;
|
||||
return this.sendCommand(appCommand, []);
|
||||
}
|
||||
async sendCommand(cmd, args) {
|
||||
const msg = { cmd, args };
|
||||
debug(`Sending command: ${cmd}, args: ${args}`);
|
||||
const resp = await this.protocolClient.sendMessage(msg);
|
||||
// we need to ACK as well
|
||||
this.protocolClient.socket.write('+');
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
exports.DebugserverClient = DebugserverClient;
|
||||
10
electron/node_modules/native-run/dist/ios/lib/client/index.js
generated
vendored
Normal file
10
electron/node_modules/native-run/dist/ios/lib/client/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./client"), exports);
|
||||
tslib_1.__exportStar(require("./afc"), exports);
|
||||
tslib_1.__exportStar(require("./debugserver"), exports);
|
||||
tslib_1.__exportStar(require("./installation_proxy"), exports);
|
||||
tslib_1.__exportStar(require("./lockdownd"), exports);
|
||||
tslib_1.__exportStar(require("./mobile_image_mounter"), exports);
|
||||
tslib_1.__exportStar(require("./usbmuxd"), exports);
|
||||
72
electron/node_modules/native-run/dist/ios/lib/client/installation_proxy.js
generated
vendored
Normal file
72
electron/node_modules/native-run/dist/ios/lib/client/installation_proxy.js
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InstallationProxyClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const lockdown_1 = require("../protocol/lockdown");
|
||||
const client_1 = require("./client");
|
||||
const debug = Debug('native-run:ios:lib:client:installation_proxy');
|
||||
function isIPLookupResponse(resp) {
|
||||
return resp.length && resp[0].LookupResult !== undefined;
|
||||
}
|
||||
function isIPInstallPercentCompleteResponse(resp) {
|
||||
return resp.length && resp[0].PercentComplete !== undefined;
|
||||
}
|
||||
function isIPInstallCFBundleIdentifierResponse(resp) {
|
||||
return resp.length && resp[0].CFBundleIdentifier !== undefined;
|
||||
}
|
||||
function isIPInstallCompleteResponse(resp) {
|
||||
return resp.length && resp[0].Status === 'Complete';
|
||||
}
|
||||
class InstallationProxyClient extends client_1.ServiceClient {
|
||||
constructor(socket) {
|
||||
super(socket, new lockdown_1.LockdownProtocolClient(socket));
|
||||
this.socket = socket;
|
||||
}
|
||||
async lookupApp(bundleIds, options = {
|
||||
ReturnAttributes: ['Path', 'Container', 'CFBundleExecutable', 'CFBundleIdentifier'],
|
||||
ApplicationsType: 'Any',
|
||||
}) {
|
||||
debug(`lookupApp, options: ${JSON.stringify(options)}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
Command: 'Lookup',
|
||||
ClientOptions: {
|
||||
BundleIDs: bundleIds,
|
||||
...options,
|
||||
},
|
||||
});
|
||||
if (isIPLookupResponse(resp)) {
|
||||
return resp[0].LookupResult;
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError(`There was an error looking up app`, resp);
|
||||
}
|
||||
}
|
||||
async installApp(packagePath, bundleId, options = {
|
||||
ApplicationsType: 'Any',
|
||||
PackageType: 'Developer',
|
||||
}) {
|
||||
debug(`installApp, packagePath: ${packagePath}, bundleId: ${bundleId}`);
|
||||
return this.protocolClient.sendMessage({
|
||||
Command: 'Install',
|
||||
PackagePath: packagePath,
|
||||
ClientOptions: {
|
||||
CFBundleIdentifier: bundleId,
|
||||
...options,
|
||||
},
|
||||
}, (resp, resolve, reject) => {
|
||||
if (isIPInstallCompleteResponse(resp)) {
|
||||
resolve();
|
||||
}
|
||||
else if (isIPInstallPercentCompleteResponse(resp)) {
|
||||
debug(`Installation status: ${resp[0].Status}, %${resp[0].PercentComplete}`);
|
||||
}
|
||||
else if (isIPInstallCFBundleIdentifierResponse(resp)) {
|
||||
debug(`Installed app: ${resp[0].CFBundleIdentifier}`);
|
||||
}
|
||||
else {
|
||||
reject(new client_1.ResponseError('There was an error installing app', resp));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.InstallationProxyClient = InstallationProxyClient;
|
||||
111
electron/node_modules/native-run/dist/ios/lib/client/lockdownd.js
generated
vendored
Normal file
111
electron/node_modules/native-run/dist/ios/lib/client/lockdownd.js
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LockdowndClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const tls = require("tls");
|
||||
const lockdown_1 = require("../protocol/lockdown");
|
||||
const client_1 = require("./client");
|
||||
const debug = Debug('native-run:ios:lib:client:lockdownd');
|
||||
function isLockdowndServiceResponse(resp) {
|
||||
return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;
|
||||
}
|
||||
function isLockdowndSessionResponse(resp) {
|
||||
return resp.Request === 'StartSession';
|
||||
}
|
||||
function isLockdowndAllValuesResponse(resp) {
|
||||
return resp.Request === 'GetValue' && resp.Value !== undefined;
|
||||
}
|
||||
function isLockdowndValueResponse(resp) {
|
||||
return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';
|
||||
}
|
||||
function isLockdowndQueryTypeResponse(resp) {
|
||||
return resp.Request === 'QueryType' && resp.Type !== undefined;
|
||||
}
|
||||
class LockdowndClient extends client_1.ServiceClient {
|
||||
constructor(socket) {
|
||||
super(socket, new lockdown_1.LockdownProtocolClient(socket));
|
||||
this.socket = socket;
|
||||
}
|
||||
async startService(name) {
|
||||
debug(`startService: ${name}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
Request: 'StartService',
|
||||
Service: name,
|
||||
});
|
||||
if (isLockdowndServiceResponse(resp)) {
|
||||
return { port: resp.Port, enableServiceSSL: !!resp.EnableServiceSSL };
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError(`Error starting service ${name}`, resp);
|
||||
}
|
||||
}
|
||||
async startSession(pairRecord) {
|
||||
debug(`startSession: ${pairRecord}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
Request: 'StartSession',
|
||||
HostID: pairRecord.HostID,
|
||||
SystemBUID: pairRecord.SystemBUID,
|
||||
});
|
||||
if (isLockdowndSessionResponse(resp)) {
|
||||
if (resp.EnableSessionSSL) {
|
||||
this.protocolClient.socket = new tls.TLSSocket(this.protocolClient.socket, {
|
||||
secureContext: tls.createSecureContext({
|
||||
secureProtocol: 'TLSv1_2_method',
|
||||
cert: pairRecord.RootCertificate,
|
||||
key: pairRecord.RootPrivateKey,
|
||||
}),
|
||||
});
|
||||
debug(`Socket upgraded to TLS connection`);
|
||||
}
|
||||
// TODO: save sessionID for StopSession?
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError('Error starting session', resp);
|
||||
}
|
||||
}
|
||||
async getAllValues() {
|
||||
debug(`getAllValues`);
|
||||
const resp = await this.protocolClient.sendMessage({ Request: 'GetValue' });
|
||||
if (isLockdowndAllValuesResponse(resp)) {
|
||||
return resp.Value;
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError('Error getting lockdown value', resp);
|
||||
}
|
||||
}
|
||||
async getValue(val) {
|
||||
debug(`getValue: ${val}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
Request: 'GetValue',
|
||||
Key: val,
|
||||
});
|
||||
if (isLockdowndValueResponse(resp)) {
|
||||
return resp.Value;
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError('Error getting lockdown value', resp);
|
||||
}
|
||||
}
|
||||
async queryType() {
|
||||
debug('queryType');
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
Request: 'QueryType',
|
||||
});
|
||||
if (isLockdowndQueryTypeResponse(resp)) {
|
||||
return resp.Type;
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError('Error getting lockdown query type', resp);
|
||||
}
|
||||
}
|
||||
async doHandshake(pairRecord) {
|
||||
debug('doHandshake');
|
||||
// if (await this.lockdownQueryType() !== 'com.apple.mobile.lockdown') {
|
||||
// throw new Error('Invalid type received from lockdown handshake');
|
||||
// }
|
||||
// await this.getLockdownValue('ProductVersion');
|
||||
// TODO: validate pair and pair
|
||||
await this.startSession(pairRecord);
|
||||
}
|
||||
}
|
||||
exports.LockdowndClient = LockdowndClient;
|
||||
61
electron/node_modules/native-run/dist/ios/lib/client/mobile_image_mounter.js
generated
vendored
Normal file
61
electron/node_modules/native-run/dist/ios/lib/client/mobile_image_mounter.js
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MobileImageMounterClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const fs = require("fs");
|
||||
const lockdown_1 = require("../protocol/lockdown");
|
||||
const client_1 = require("./client");
|
||||
const debug = Debug('native-run:ios:lib:client:mobile_image_mounter');
|
||||
function isMIMUploadCompleteResponse(resp) {
|
||||
return resp.Status === 'Complete';
|
||||
}
|
||||
function isMIMUploadReceiveBytesResponse(resp) {
|
||||
return resp.Status === 'ReceiveBytesAck';
|
||||
}
|
||||
class MobileImageMounterClient extends client_1.ServiceClient {
|
||||
constructor(socket) {
|
||||
super(socket, new lockdown_1.LockdownProtocolClient(socket));
|
||||
}
|
||||
async mountImage(imagePath, imageSig) {
|
||||
debug(`mountImage: ${imagePath}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
Command: 'MountImage',
|
||||
ImagePath: imagePath,
|
||||
ImageSignature: imageSig,
|
||||
ImageType: 'Developer',
|
||||
});
|
||||
if (!(0, lockdown_1.isLockdownResponse)(resp) || resp.Status !== 'Complete') {
|
||||
throw new client_1.ResponseError(`There was an error mounting ${imagePath} on device`, resp);
|
||||
}
|
||||
}
|
||||
async uploadImage(imagePath, imageSig) {
|
||||
debug(`uploadImage: ${imagePath}`);
|
||||
const imageSize = fs.statSync(imagePath).size;
|
||||
return this.protocolClient.sendMessage({
|
||||
Command: 'ReceiveBytes',
|
||||
ImageSize: imageSize,
|
||||
ImageSignature: imageSig,
|
||||
ImageType: 'Developer',
|
||||
}, (resp, resolve, reject) => {
|
||||
if (isMIMUploadReceiveBytesResponse(resp)) {
|
||||
const imageStream = fs.createReadStream(imagePath);
|
||||
imageStream.pipe(this.protocolClient.socket, { end: false });
|
||||
imageStream.on('error', (err) => reject(err));
|
||||
}
|
||||
else if (isMIMUploadCompleteResponse(resp)) {
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
reject(new client_1.ResponseError(`There was an error uploading image ${imagePath} to the device`, resp));
|
||||
}
|
||||
});
|
||||
}
|
||||
async lookupImage() {
|
||||
debug('lookupImage');
|
||||
return this.protocolClient.sendMessage({
|
||||
Command: 'LookupImage',
|
||||
ImageType: 'Developer',
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.MobileImageMounterClient = MobileImageMounterClient;
|
||||
103
electron/node_modules/native-run/dist/ios/lib/client/usbmuxd.js
generated
vendored
Normal file
103
electron/node_modules/native-run/dist/ios/lib/client/usbmuxd.js
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UsbmuxdClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const net = require("net");
|
||||
const plist = require("plist");
|
||||
const usbmux_1 = require("../protocol/usbmux");
|
||||
const client_1 = require("./client");
|
||||
const debug = Debug('native-run:ios:lib:client:usbmuxd');
|
||||
function isUsbmuxdConnectResponse(resp) {
|
||||
return resp.MessageType === 'Result' && resp.Number !== undefined;
|
||||
}
|
||||
function isUsbmuxdDeviceResponse(resp) {
|
||||
return resp.DeviceList !== undefined;
|
||||
}
|
||||
function isUsbmuxdPairRecordResponse(resp) {
|
||||
return resp.PairRecordData !== undefined;
|
||||
}
|
||||
class UsbmuxdClient extends client_1.ServiceClient {
|
||||
constructor(socket) {
|
||||
super(socket, new usbmux_1.UsbmuxProtocolClient(socket));
|
||||
this.socket = socket;
|
||||
}
|
||||
static connectUsbmuxdSocket() {
|
||||
debug('connectUsbmuxdSocket');
|
||||
if ('win32' === process.platform) {
|
||||
return net.connect({ port: 27015, host: 'localhost' });
|
||||
}
|
||||
else {
|
||||
return net.connect({ path: '/var/run/usbmuxd' });
|
||||
}
|
||||
}
|
||||
async connect(device, port) {
|
||||
debug(`connect: ${device.DeviceID} on port ${port}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
messageType: 'Connect',
|
||||
extraFields: {
|
||||
DeviceID: device.DeviceID,
|
||||
PortNumber: htons(port),
|
||||
},
|
||||
});
|
||||
if (isUsbmuxdConnectResponse(resp) && resp.Number === 0) {
|
||||
return this.protocolClient.socket;
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError(`There was an error connecting to ${device.DeviceID} on port ${port}`, resp);
|
||||
}
|
||||
}
|
||||
async getDevices() {
|
||||
debug('getDevices');
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
messageType: 'ListDevices',
|
||||
});
|
||||
if (isUsbmuxdDeviceResponse(resp)) {
|
||||
return resp.DeviceList;
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError('Invalid response from getDevices', resp);
|
||||
}
|
||||
}
|
||||
async getDevice(udid) {
|
||||
debug(`getDevice ${udid ? 'udid: ' + udid : ''}`);
|
||||
const devices = await this.getDevices();
|
||||
if (!devices.length) {
|
||||
throw new Error('No devices found');
|
||||
}
|
||||
if (!udid) {
|
||||
return devices[0];
|
||||
}
|
||||
for (const device of devices) {
|
||||
if (device.Properties && device.Properties.SerialNumber === udid) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
throw new Error(`No device with udid ${udid} found`);
|
||||
}
|
||||
async readPairRecord(udid) {
|
||||
debug(`readPairRecord: ${udid}`);
|
||||
const resp = await this.protocolClient.sendMessage({
|
||||
messageType: 'ReadPairRecord',
|
||||
extraFields: { PairRecordID: udid },
|
||||
});
|
||||
if (isUsbmuxdPairRecordResponse(resp)) {
|
||||
// the pair record can be created as a binary plist
|
||||
const BPLIST_MAGIC = Buffer.from('bplist00');
|
||||
if (BPLIST_MAGIC.compare(resp.PairRecordData, 0, 8) === 0) {
|
||||
debug('Binary plist pair record detected.');
|
||||
const bplistParser = await Promise.resolve().then(() => require('bplist-parser'));
|
||||
return bplistParser.parseBuffer(resp.PairRecordData)[0];
|
||||
}
|
||||
else {
|
||||
return plist.parse(resp.PairRecordData.toString()); // TODO: type guard
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new client_1.ResponseError(`There was an error reading pair record for udid: ${udid}`, resp);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.UsbmuxdClient = UsbmuxdClient;
|
||||
function htons(n) {
|
||||
return ((n & 0xff) << 8) | ((n >> 8) & 0xff);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue