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);
|
||||
}
|
||||
6
electron/node_modules/native-run/dist/ios/lib/index.js
generated
vendored
Normal file
6
electron/node_modules/native-run/dist/ios/lib/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./client"), exports);
|
||||
tslib_1.__exportStar(require("./protocol"), exports);
|
||||
tslib_1.__exportStar(require("./manager"), exports);
|
||||
10
electron/node_modules/native-run/dist/ios/lib/lib-errors.js
generated
vendored
Normal file
10
electron/node_modules/native-run/dist/ios/lib/lib-errors.js
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.IOSLibError = void 0;
|
||||
class IOSLibError extends Error {
|
||||
constructor(message, code) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
exports.IOSLibError = IOSLibError;
|
||||
139
electron/node_modules/native-run/dist/ios/lib/manager.js
generated
vendored
Normal file
139
electron/node_modules/native-run/dist/ios/lib/manager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ClientManager = void 0;
|
||||
const stream_1 = require("stream");
|
||||
const tls = require("tls");
|
||||
const afc_1 = require("./client/afc");
|
||||
const debugserver_1 = require("./client/debugserver");
|
||||
const installation_proxy_1 = require("./client/installation_proxy");
|
||||
const lockdownd_1 = require("./client/lockdownd");
|
||||
const mobile_image_mounter_1 = require("./client/mobile_image_mounter");
|
||||
const usbmuxd_1 = require("./client/usbmuxd");
|
||||
class ClientManager {
|
||||
constructor(pairRecord, device, lockdowndClient) {
|
||||
this.pairRecord = pairRecord;
|
||||
this.device = device;
|
||||
this.lockdowndClient = lockdowndClient;
|
||||
this.connections = [lockdowndClient.socket];
|
||||
}
|
||||
static async create(udid) {
|
||||
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
|
||||
const device = await usbmuxClient.getDevice(udid);
|
||||
const pairRecord = await usbmuxClient.readPairRecord(device.Properties.SerialNumber);
|
||||
const lockdownSocket = await usbmuxClient.connect(device, 62078);
|
||||
const lockdownClient = new lockdownd_1.LockdowndClient(lockdownSocket);
|
||||
await lockdownClient.doHandshake(pairRecord);
|
||||
return new ClientManager(pairRecord, device, lockdownClient);
|
||||
}
|
||||
async getUsbmuxdClient() {
|
||||
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
|
||||
this.connections.push(usbmuxClient.socket);
|
||||
return usbmuxClient;
|
||||
}
|
||||
async getLockdowndClient() {
|
||||
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
|
||||
const lockdownSocket = await usbmuxClient.connect(this.device, 62078);
|
||||
const lockdownClient = new lockdownd_1.LockdowndClient(lockdownSocket);
|
||||
this.connections.push(lockdownClient.socket);
|
||||
return lockdownClient;
|
||||
}
|
||||
async getLockdowndClientWithHandshake() {
|
||||
const lockdownClient = await this.getLockdowndClient();
|
||||
await lockdownClient.doHandshake(this.pairRecord);
|
||||
return lockdownClient;
|
||||
}
|
||||
async getAFCClient() {
|
||||
return this.getServiceClient('com.apple.afc', afc_1.AFCClient);
|
||||
}
|
||||
async getInstallationProxyClient() {
|
||||
return this.getServiceClient('com.apple.mobile.installation_proxy', installation_proxy_1.InstallationProxyClient);
|
||||
}
|
||||
async getMobileImageMounterClient() {
|
||||
return this.getServiceClient('com.apple.mobile.mobile_image_mounter', mobile_image_mounter_1.MobileImageMounterClient);
|
||||
}
|
||||
async getDebugserverClient() {
|
||||
try {
|
||||
// iOS 14 added support for a secure debug service so try to connect to that first
|
||||
return await this.getServiceClient('com.apple.debugserver.DVTSecureSocketProxy', debugserver_1.DebugserverClient);
|
||||
}
|
||||
catch {
|
||||
// otherwise, fall back to the previous implementation
|
||||
return this.getServiceClient('com.apple.debugserver', debugserver_1.DebugserverClient, true);
|
||||
}
|
||||
}
|
||||
async getServiceClient(name, ServiceType, disableSSL = false) {
|
||||
const { port: servicePort, enableServiceSSL } = await this.lockdowndClient.startService(name);
|
||||
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
|
||||
let usbmuxdSocket = await usbmuxClient.connect(this.device, servicePort);
|
||||
if (enableServiceSSL) {
|
||||
const tlsOptions = {
|
||||
rejectUnauthorized: false,
|
||||
secureContext: tls.createSecureContext({
|
||||
secureProtocol: 'TLSv1_2_method',
|
||||
cert: this.pairRecord.RootCertificate,
|
||||
key: this.pairRecord.RootPrivateKey,
|
||||
}),
|
||||
};
|
||||
// Some services seem to not support TLS/SSL after the initial handshake
|
||||
// More info: https://github.com/libimobiledevice/libimobiledevice/issues/793
|
||||
if (disableSSL) {
|
||||
// According to https://nodejs.org/api/tls.html#tls_tls_connect_options_callback we can
|
||||
// pass any Duplex in to tls.connect instead of a Socket. So we'll use our proxy to keep
|
||||
// the TLS wrapper and underlying usbmuxd socket separate.
|
||||
const proxy = new UsbmuxdProxy(usbmuxdSocket);
|
||||
tlsOptions.socket = proxy;
|
||||
await new Promise((res, rej) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
rej('The TLS handshake failed to complete after 5s.');
|
||||
}, 5000);
|
||||
tls.connect(tlsOptions, function () {
|
||||
clearTimeout(timeoutId);
|
||||
// After the handshake, we don't need TLS or the proxy anymore,
|
||||
// since we'll just pass in the naked usbmuxd socket to the service client
|
||||
this.destroy();
|
||||
res();
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
tlsOptions.socket = usbmuxdSocket;
|
||||
usbmuxdSocket = tls.connect(tlsOptions);
|
||||
}
|
||||
}
|
||||
const client = new ServiceType(usbmuxdSocket);
|
||||
this.connections.push(client.socket);
|
||||
return client;
|
||||
}
|
||||
end() {
|
||||
for (const socket of this.connections) {
|
||||
// may already be closed
|
||||
try {
|
||||
socket.end();
|
||||
}
|
||||
catch (err) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ClientManager = ClientManager;
|
||||
class UsbmuxdProxy extends stream_1.Duplex {
|
||||
constructor(usbmuxdSock) {
|
||||
super();
|
||||
this.usbmuxdSock = usbmuxdSock;
|
||||
this.usbmuxdSock.on('data', (data) => {
|
||||
this.push(data);
|
||||
});
|
||||
}
|
||||
_write(chunk, encoding, callback) {
|
||||
this.usbmuxdSock.write(chunk);
|
||||
callback();
|
||||
}
|
||||
_read(size) {
|
||||
// Stub so we don't error, since we push everything we get from usbmuxd as it comes in.
|
||||
// TODO: better way to do this?
|
||||
}
|
||||
_destroy() {
|
||||
this.usbmuxdSock.removeAllListeners();
|
||||
}
|
||||
}
|
||||
373
electron/node_modules/native-run/dist/ios/lib/protocol/afc.js
generated
vendored
Normal file
373
electron/node_modules/native-run/dist/ios/lib/protocol/afc.js
generated
vendored
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AFCProtocolWriter = exports.AFCProtocolReader = exports.AFCProtocolClient = exports.AFCError = exports.AFC_FILE_OPEN_FLAGS = exports.AFC_STATUS = exports.AFC_OPS = exports.AFC_HEADER_SIZE = exports.AFC_MAGIC = void 0;
|
||||
const Debug = require("debug");
|
||||
const protocol_1 = require("./protocol");
|
||||
const debug = Debug('native-run:ios:lib:protocol:afc');
|
||||
exports.AFC_MAGIC = 'CFA6LPAA';
|
||||
exports.AFC_HEADER_SIZE = 40;
|
||||
/**
|
||||
* AFC Operations
|
||||
*/
|
||||
var AFC_OPS;
|
||||
(function (AFC_OPS) {
|
||||
/**
|
||||
* Invalid
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["INVALID"] = 0] = "INVALID";
|
||||
/**
|
||||
* Status
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["STATUS"] = 1] = "STATUS";
|
||||
/**
|
||||
* Data
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["DATA"] = 2] = "DATA";
|
||||
/**
|
||||
* ReadDir
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["READ_DIR"] = 3] = "READ_DIR";
|
||||
/**
|
||||
* ReadFile
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["READ_FILE"] = 4] = "READ_FILE";
|
||||
/**
|
||||
* WriteFile
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["WRITE_FILE"] = 5] = "WRITE_FILE";
|
||||
/**
|
||||
* WritePart
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["WRITE_PART"] = 6] = "WRITE_PART";
|
||||
/**
|
||||
* TruncateFile
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["TRUNCATE"] = 7] = "TRUNCATE";
|
||||
/**
|
||||
* RemovePath
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["REMOVE_PATH"] = 8] = "REMOVE_PATH";
|
||||
/**
|
||||
* MakeDir
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["MAKE_DIR"] = 9] = "MAKE_DIR";
|
||||
/**
|
||||
* GetFileInfo
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["GET_FILE_INFO"] = 10] = "GET_FILE_INFO";
|
||||
/**
|
||||
* GetDeviceInfo
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["GET_DEVINFO"] = 11] = "GET_DEVINFO";
|
||||
/**
|
||||
* WriteFileAtomic (tmp file+rename)
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["WRITE_FILE_ATOM"] = 12] = "WRITE_FILE_ATOM";
|
||||
/**
|
||||
* FileRefOpen
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_OPEN"] = 13] = "FILE_OPEN";
|
||||
/**
|
||||
* FileRefOpenResult
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_OPEN_RES"] = 14] = "FILE_OPEN_RES";
|
||||
/**
|
||||
* FileRefRead
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_READ"] = 15] = "FILE_READ";
|
||||
/**
|
||||
* FileRefWrite
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_WRITE"] = 16] = "FILE_WRITE";
|
||||
/**
|
||||
* FileRefSeek
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_SEEK"] = 17] = "FILE_SEEK";
|
||||
/**
|
||||
* FileRefTell
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_TELL"] = 18] = "FILE_TELL";
|
||||
/**
|
||||
* FileRefTellResult
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_TELL_RES"] = 19] = "FILE_TELL_RES";
|
||||
/**
|
||||
* FileRefClose
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_CLOSE"] = 20] = "FILE_CLOSE";
|
||||
/**
|
||||
* FileRefSetFileSize (ftruncate)
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_SET_SIZE"] = 21] = "FILE_SET_SIZE";
|
||||
/**
|
||||
* GetConnectionInfo
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["GET_CON_INFO"] = 22] = "GET_CON_INFO";
|
||||
/**
|
||||
* SetConnectionOptions
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["SET_CON_OPTIONS"] = 23] = "SET_CON_OPTIONS";
|
||||
/**
|
||||
* RenamePath
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["RENAME_PATH"] = 24] = "RENAME_PATH";
|
||||
/**
|
||||
* SetFSBlockSize (0x800000)
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["SET_FS_BS"] = 25] = "SET_FS_BS";
|
||||
/**
|
||||
* SetSocketBlockSize (0x800000)
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["SET_SOCKET_BS"] = 26] = "SET_SOCKET_BS";
|
||||
/**
|
||||
* FileRefLock
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_LOCK"] = 27] = "FILE_LOCK";
|
||||
/**
|
||||
* MakeLink
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["MAKE_LINK"] = 28] = "MAKE_LINK";
|
||||
/**
|
||||
* GetFileHash
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["GET_FILE_HASH"] = 29] = "GET_FILE_HASH";
|
||||
/**
|
||||
* SetModTime
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["SET_FILE_MOD_TIME"] = 30] = "SET_FILE_MOD_TIME";
|
||||
/**
|
||||
* GetFileHashWithRange
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["GET_FILE_HASH_RANGE"] = 31] = "GET_FILE_HASH_RANGE";
|
||||
// iOS 6+
|
||||
/**
|
||||
* FileRefSetImmutableHint
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_SET_IMMUTABLE_HINT"] = 32] = "FILE_SET_IMMUTABLE_HINT";
|
||||
/**
|
||||
* GetSizeOfPathContents
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["GET_SIZE_OF_PATH_CONTENTS"] = 33] = "GET_SIZE_OF_PATH_CONTENTS";
|
||||
/**
|
||||
* RemovePathAndContents
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["REMOVE_PATH_AND_CONTENTS"] = 34] = "REMOVE_PATH_AND_CONTENTS";
|
||||
/**
|
||||
* DirectoryEnumeratorRefOpen
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["DIR_OPEN"] = 35] = "DIR_OPEN";
|
||||
/**
|
||||
* DirectoryEnumeratorRefOpenResult
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["DIR_OPEN_RESULT"] = 36] = "DIR_OPEN_RESULT";
|
||||
/**
|
||||
* DirectoryEnumeratorRefRead
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["DIR_READ"] = 37] = "DIR_READ";
|
||||
/**
|
||||
* DirectoryEnumeratorRefClose
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["DIR_CLOSE"] = 38] = "DIR_CLOSE";
|
||||
// iOS 7+
|
||||
/**
|
||||
* FileRefReadWithOffset
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_READ_OFFSET"] = 39] = "FILE_READ_OFFSET";
|
||||
/**
|
||||
* FileRefWriteWithOffset
|
||||
*/
|
||||
AFC_OPS[AFC_OPS["FILE_WRITE_OFFSET"] = 40] = "FILE_WRITE_OFFSET";
|
||||
})(AFC_OPS = exports.AFC_OPS || (exports.AFC_OPS = {}));
|
||||
/**
|
||||
* Error Codes
|
||||
*/
|
||||
var AFC_STATUS;
|
||||
(function (AFC_STATUS) {
|
||||
AFC_STATUS[AFC_STATUS["SUCCESS"] = 0] = "SUCCESS";
|
||||
AFC_STATUS[AFC_STATUS["UNKNOWN_ERROR"] = 1] = "UNKNOWN_ERROR";
|
||||
AFC_STATUS[AFC_STATUS["OP_HEADER_INVALID"] = 2] = "OP_HEADER_INVALID";
|
||||
AFC_STATUS[AFC_STATUS["NO_RESOURCES"] = 3] = "NO_RESOURCES";
|
||||
AFC_STATUS[AFC_STATUS["READ_ERROR"] = 4] = "READ_ERROR";
|
||||
AFC_STATUS[AFC_STATUS["WRITE_ERROR"] = 5] = "WRITE_ERROR";
|
||||
AFC_STATUS[AFC_STATUS["UNKNOWN_PACKET_TYPE"] = 6] = "UNKNOWN_PACKET_TYPE";
|
||||
AFC_STATUS[AFC_STATUS["INVALID_ARG"] = 7] = "INVALID_ARG";
|
||||
AFC_STATUS[AFC_STATUS["OBJECT_NOT_FOUND"] = 8] = "OBJECT_NOT_FOUND";
|
||||
AFC_STATUS[AFC_STATUS["OBJECT_IS_DIR"] = 9] = "OBJECT_IS_DIR";
|
||||
AFC_STATUS[AFC_STATUS["PERM_DENIED"] = 10] = "PERM_DENIED";
|
||||
AFC_STATUS[AFC_STATUS["SERVICE_NOT_CONNECTED"] = 11] = "SERVICE_NOT_CONNECTED";
|
||||
AFC_STATUS[AFC_STATUS["OP_TIMEOUT"] = 12] = "OP_TIMEOUT";
|
||||
AFC_STATUS[AFC_STATUS["TOO_MUCH_DATA"] = 13] = "TOO_MUCH_DATA";
|
||||
AFC_STATUS[AFC_STATUS["END_OF_DATA"] = 14] = "END_OF_DATA";
|
||||
AFC_STATUS[AFC_STATUS["OP_NOT_SUPPORTED"] = 15] = "OP_NOT_SUPPORTED";
|
||||
AFC_STATUS[AFC_STATUS["OBJECT_EXISTS"] = 16] = "OBJECT_EXISTS";
|
||||
AFC_STATUS[AFC_STATUS["OBJECT_BUSY"] = 17] = "OBJECT_BUSY";
|
||||
AFC_STATUS[AFC_STATUS["NO_SPACE_LEFT"] = 18] = "NO_SPACE_LEFT";
|
||||
AFC_STATUS[AFC_STATUS["OP_WOULD_BLOCK"] = 19] = "OP_WOULD_BLOCK";
|
||||
AFC_STATUS[AFC_STATUS["IO_ERROR"] = 20] = "IO_ERROR";
|
||||
AFC_STATUS[AFC_STATUS["OP_INTERRUPTED"] = 21] = "OP_INTERRUPTED";
|
||||
AFC_STATUS[AFC_STATUS["OP_IN_PROGRESS"] = 22] = "OP_IN_PROGRESS";
|
||||
AFC_STATUS[AFC_STATUS["INTERNAL_ERROR"] = 23] = "INTERNAL_ERROR";
|
||||
AFC_STATUS[AFC_STATUS["MUX_ERROR"] = 30] = "MUX_ERROR";
|
||||
AFC_STATUS[AFC_STATUS["NO_MEM"] = 31] = "NO_MEM";
|
||||
AFC_STATUS[AFC_STATUS["NOT_ENOUGH_DATA"] = 32] = "NOT_ENOUGH_DATA";
|
||||
AFC_STATUS[AFC_STATUS["DIR_NOT_EMPTY"] = 33] = "DIR_NOT_EMPTY";
|
||||
AFC_STATUS[AFC_STATUS["FORCE_SIGNED_TYPE"] = -1] = "FORCE_SIGNED_TYPE";
|
||||
})(AFC_STATUS = exports.AFC_STATUS || (exports.AFC_STATUS = {}));
|
||||
var AFC_FILE_OPEN_FLAGS;
|
||||
(function (AFC_FILE_OPEN_FLAGS) {
|
||||
/**
|
||||
* r (O_RDONLY)
|
||||
*/
|
||||
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["RDONLY"] = 1] = "RDONLY";
|
||||
/**
|
||||
* r+ (O_RDWR | O_CREAT)
|
||||
*/
|
||||
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["RW"] = 2] = "RW";
|
||||
/**
|
||||
* w (O_WRONLY | O_CREAT | O_TRUNC)
|
||||
*/
|
||||
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["WRONLY"] = 3] = "WRONLY";
|
||||
/**
|
||||
* w+ (O_RDWR | O_CREAT | O_TRUNC)
|
||||
*/
|
||||
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["WR"] = 4] = "WR";
|
||||
/**
|
||||
* a (O_WRONLY | O_APPEND | O_CREAT)
|
||||
*/
|
||||
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["APPEND"] = 5] = "APPEND";
|
||||
/**
|
||||
* a+ (O_RDWR | O_APPEND | O_CREAT)
|
||||
*/
|
||||
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["RDAPPEND"] = 6] = "RDAPPEND";
|
||||
})(AFC_FILE_OPEN_FLAGS = exports.AFC_FILE_OPEN_FLAGS || (exports.AFC_FILE_OPEN_FLAGS = {}));
|
||||
function isAFCResponse(resp) {
|
||||
return AFC_OPS[resp.operation] !== undefined && resp.id !== undefined && resp.data !== undefined;
|
||||
}
|
||||
function isStatusResponse(resp) {
|
||||
return isAFCResponse(resp) && resp.operation === AFC_OPS.STATUS;
|
||||
}
|
||||
function isErrorStatusResponse(resp) {
|
||||
return isStatusResponse(resp) && resp.data !== AFC_STATUS.SUCCESS;
|
||||
}
|
||||
class AFCInternalError extends Error {
|
||||
constructor(msg, requestId) {
|
||||
super(msg);
|
||||
this.requestId = requestId;
|
||||
}
|
||||
}
|
||||
class AFCError extends Error {
|
||||
constructor(msg, status) {
|
||||
super(msg);
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
exports.AFCError = AFCError;
|
||||
class AFCProtocolClient extends protocol_1.ProtocolClient {
|
||||
constructor(socket) {
|
||||
super(socket, new protocol_1.ProtocolReaderFactory(AFCProtocolReader), new AFCProtocolWriter());
|
||||
this.requestId = 0;
|
||||
this.requestCallbacks = {};
|
||||
const reader = this.readerFactory.create((resp, err) => {
|
||||
if (err && err instanceof AFCInternalError) {
|
||||
this.requestCallbacks[err.requestId](resp, err);
|
||||
}
|
||||
else if (isErrorStatusResponse(resp)) {
|
||||
this.requestCallbacks[resp.id](resp, new AFCError(AFC_STATUS[resp.data], resp.data));
|
||||
}
|
||||
else {
|
||||
this.requestCallbacks[resp.id](resp);
|
||||
}
|
||||
});
|
||||
socket.on('data', reader.onData);
|
||||
}
|
||||
sendMessage(msg) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestId = this.requestId++;
|
||||
this.requestCallbacks[requestId] = async (resp, err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
if (isAFCResponse(resp)) {
|
||||
resolve(resp);
|
||||
}
|
||||
else {
|
||||
reject(new Error('Malformed AFC response'));
|
||||
}
|
||||
};
|
||||
this.writer.write(this.socket, { ...msg, requestId });
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.AFCProtocolClient = AFCProtocolClient;
|
||||
class AFCProtocolReader extends protocol_1.ProtocolReader {
|
||||
constructor(callback) {
|
||||
super(exports.AFC_HEADER_SIZE, callback);
|
||||
}
|
||||
parseHeader(data) {
|
||||
const magic = data.slice(0, 8).toString('ascii');
|
||||
if (magic !== exports.AFC_MAGIC) {
|
||||
throw new AFCInternalError(`Invalid AFC packet received (magic != ${exports.AFC_MAGIC})`, data.readUInt32LE(24));
|
||||
}
|
||||
// technically these are uint64
|
||||
this.header = {
|
||||
magic,
|
||||
totalLength: data.readUInt32LE(8),
|
||||
headerLength: data.readUInt32LE(16),
|
||||
requestId: data.readUInt32LE(24),
|
||||
operation: data.readUInt32LE(32),
|
||||
};
|
||||
debug(`parse header: ${JSON.stringify(this.header)}`);
|
||||
if (this.header.headerLength < exports.AFC_HEADER_SIZE) {
|
||||
throw new AFCInternalError('Invalid AFC header', this.header.requestId);
|
||||
}
|
||||
return this.header.totalLength - exports.AFC_HEADER_SIZE;
|
||||
}
|
||||
parseBody(data) {
|
||||
const body = {
|
||||
operation: this.header.operation,
|
||||
id: this.header.requestId,
|
||||
data,
|
||||
};
|
||||
if (isStatusResponse(body)) {
|
||||
const status = data.readUInt32LE(0);
|
||||
debug(`${AFC_OPS[this.header.operation]} response: ${AFC_STATUS[status]}`);
|
||||
body.data = status;
|
||||
}
|
||||
else if (data.length <= 8) {
|
||||
debug(`${AFC_OPS[this.header.operation]} response: ${Array.prototype.toString.call(body)}`);
|
||||
}
|
||||
else {
|
||||
debug(`${AFC_OPS[this.header.operation]} response length: ${data.length} bytes`);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
exports.AFCProtocolReader = AFCProtocolReader;
|
||||
class AFCProtocolWriter {
|
||||
write(socket, msg) {
|
||||
const { data, payload, operation, requestId } = msg;
|
||||
const dataLength = data ? data.length : 0;
|
||||
const payloadLength = payload ? payload.length : 0;
|
||||
const header = Buffer.alloc(exports.AFC_HEADER_SIZE);
|
||||
const magic = Buffer.from(exports.AFC_MAGIC);
|
||||
magic.copy(header);
|
||||
header.writeUInt32LE(exports.AFC_HEADER_SIZE + dataLength + payloadLength, 8);
|
||||
header.writeUInt32LE(exports.AFC_HEADER_SIZE + dataLength, 16);
|
||||
header.writeUInt32LE(requestId, 24);
|
||||
header.writeUInt32LE(operation, 32);
|
||||
socket.write(header);
|
||||
socket.write(data);
|
||||
if (data.length <= 8) {
|
||||
debug(`socket write, header: { requestId: ${requestId}, operation: ${AFC_OPS[operation]}}, body: ${Array.prototype.toString.call(data)}`);
|
||||
}
|
||||
else {
|
||||
debug(`socket write, header: { requestId: ${requestId}, operation: ${AFC_OPS[operation]}}, body: ${data.length} bytes`);
|
||||
}
|
||||
debug(`socket write, bytes written ${header.length} (header), ${data.length} (body)`);
|
||||
if (payload) {
|
||||
socket.write(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AFCProtocolWriter = AFCProtocolWriter;
|
||||
112
electron/node_modules/native-run/dist/ios/lib/protocol/gdb.js
generated
vendored
Normal file
112
electron/node_modules/native-run/dist/ios/lib/protocol/gdb.js
generated
vendored
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.GDBProtocolWriter = exports.GDBProtocolReader = exports.GDBProtocolClient = void 0;
|
||||
const Debug = require("debug");
|
||||
const protocol_1 = require("./protocol");
|
||||
const debug = Debug('native-run:ios:lib:protocol:gdb');
|
||||
const ACK_SUCCESS = '+'.charCodeAt(0);
|
||||
class GDBProtocolClient extends protocol_1.ProtocolClient {
|
||||
constructor(socket) {
|
||||
super(socket, new protocol_1.ProtocolReaderFactory(GDBProtocolReader), new GDBProtocolWriter());
|
||||
}
|
||||
}
|
||||
exports.GDBProtocolClient = GDBProtocolClient;
|
||||
class GDBProtocolReader extends protocol_1.ProtocolReader {
|
||||
constructor(callback) {
|
||||
super(1 /* "Header" is '+' or '-' */, callback);
|
||||
}
|
||||
onData(data) {
|
||||
// the GDB protocol does not support body length in its header so we cannot rely on
|
||||
// the parent implementation to determine when a payload is complete
|
||||
try {
|
||||
// if there's data, add it to the existing buffer
|
||||
this.buffer = data ? Buffer.concat([this.buffer, data]) : this.buffer;
|
||||
// do we have enough bytes to proceed
|
||||
if (this.buffer.length < this.headerSize) {
|
||||
return; // incomplete header, wait for more
|
||||
}
|
||||
// first, check the header
|
||||
if (this.parseHeader(this.buffer) === -1) {
|
||||
// we have a valid header so check the body. GDB packets will always be a leading '$', data bytes,
|
||||
// a trailing '#', and a two digit checksum. minimum valid body is the empty response '$#00'
|
||||
// https://developer.apple.com/library/archive/documentation/DeveloperTools/gdb/gdb/gdb_33.html
|
||||
const packetData = this.buffer.toString().match('\\$.*#[0-9a-f]{2}');
|
||||
if (packetData == null) {
|
||||
return; // incomplete body, wait for more
|
||||
}
|
||||
// extract the body and update the buffer
|
||||
const body = Buffer.from(packetData[0]);
|
||||
this.buffer = this.buffer.slice(this.headerSize + body.length);
|
||||
// parse the payload and recurse if there is more data to process
|
||||
this.callback(this.parseBody(body));
|
||||
if (this.buffer.length) {
|
||||
this.onData();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
this.callback(null, err);
|
||||
}
|
||||
}
|
||||
parseHeader(data) {
|
||||
if (data[0] !== ACK_SUCCESS) {
|
||||
throw new Error('Unsuccessful debugserver response');
|
||||
} // TODO: retry?
|
||||
return -1;
|
||||
}
|
||||
parseBody(buffer) {
|
||||
debug(`Response body: ${buffer.toString()}`);
|
||||
// check for checksum
|
||||
const checksum = buffer.slice(-3).toString();
|
||||
if (checksum.match(/#[0-9a-f]{2}/)) {
|
||||
// remove '$' prefix and checksum
|
||||
const msg = buffer.slice(1, -3).toString();
|
||||
if (validateChecksum(checksum, msg)) {
|
||||
return msg;
|
||||
}
|
||||
else {
|
||||
throw new Error('Invalid checksum received from debugserver');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("Didn't receive checksum");
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.GDBProtocolReader = GDBProtocolReader;
|
||||
class GDBProtocolWriter {
|
||||
write(socket, msg) {
|
||||
const { cmd, args } = msg;
|
||||
debug(`Socket write: ${cmd}, args: ${args}`);
|
||||
// hex encode and concat all args
|
||||
const encodedArgs = args
|
||||
.map((arg) => Buffer.from(arg).toString('hex'))
|
||||
.join()
|
||||
.toUpperCase();
|
||||
const checksumStr = calculateChecksum(cmd + encodedArgs);
|
||||
const formattedCmd = `$${cmd}${encodedArgs}#${checksumStr}`;
|
||||
socket.write(formattedCmd);
|
||||
}
|
||||
}
|
||||
exports.GDBProtocolWriter = GDBProtocolWriter;
|
||||
// hex value of (sum of cmd chars mod 256)
|
||||
function calculateChecksum(cmdStr) {
|
||||
let checksum = 0;
|
||||
for (let i = 0; i < cmdStr.length; i++) {
|
||||
checksum += cmdStr.charCodeAt(i);
|
||||
}
|
||||
let result = (checksum % 256).toString(16);
|
||||
// pad if necessary
|
||||
if (result.length === 1) {
|
||||
result = `0${result}`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function validateChecksum(checksum, msg) {
|
||||
// remove '#' from checksum
|
||||
const checksumVal = checksum.slice(1);
|
||||
// remove '$' from msg and calculate its checksum
|
||||
const computedChecksum = calculateChecksum(msg);
|
||||
debug(`Checksum: ${checksumVal}, computed checksum: ${computedChecksum}`);
|
||||
return checksumVal === computedChecksum;
|
||||
}
|
||||
8
electron/node_modules/native-run/dist/ios/lib/protocol/index.js
generated
vendored
Normal file
8
electron/node_modules/native-run/dist/ios/lib/protocol/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./protocol"), exports);
|
||||
tslib_1.__exportStar(require("./afc"), exports);
|
||||
tslib_1.__exportStar(require("./gdb"), exports);
|
||||
tslib_1.__exportStar(require("./lockdown"), exports);
|
||||
tslib_1.__exportStar(require("./usbmux"), exports);
|
||||
57
electron/node_modules/native-run/dist/ios/lib/protocol/lockdown.js
generated
vendored
Normal file
57
electron/node_modules/native-run/dist/ios/lib/protocol/lockdown.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LockdownProtocolWriter = exports.LockdownProtocolReader = exports.LockdownProtocolClient = exports.isLockdownErrorResponse = exports.isLockdownResponse = exports.LOCKDOWN_HEADER_SIZE = void 0;
|
||||
const Debug = require("debug");
|
||||
const plist = require("plist");
|
||||
const lib_errors_1 = require("../lib-errors");
|
||||
const protocol_1 = require("./protocol");
|
||||
const debug = Debug('native-run:ios:lib:protocol:lockdown');
|
||||
exports.LOCKDOWN_HEADER_SIZE = 4;
|
||||
function isDefined(val) {
|
||||
return typeof val !== 'undefined';
|
||||
}
|
||||
function isLockdownResponse(resp) {
|
||||
return isDefined(resp.Status);
|
||||
}
|
||||
exports.isLockdownResponse = isLockdownResponse;
|
||||
function isLockdownErrorResponse(resp) {
|
||||
return isDefined(resp.Error);
|
||||
}
|
||||
exports.isLockdownErrorResponse = isLockdownErrorResponse;
|
||||
class LockdownProtocolClient extends protocol_1.ProtocolClient {
|
||||
constructor(socket) {
|
||||
super(socket, new protocol_1.ProtocolReaderFactory(LockdownProtocolReader), new LockdownProtocolWriter());
|
||||
}
|
||||
}
|
||||
exports.LockdownProtocolClient = LockdownProtocolClient;
|
||||
class LockdownProtocolReader extends protocol_1.PlistProtocolReader {
|
||||
constructor(callback) {
|
||||
super(exports.LOCKDOWN_HEADER_SIZE, callback);
|
||||
}
|
||||
parseHeader(data) {
|
||||
return data.readUInt32BE(0);
|
||||
}
|
||||
parseBody(data) {
|
||||
const resp = super.parseBody(data);
|
||||
debug(`Response: ${JSON.stringify(resp)}`);
|
||||
if (isLockdownErrorResponse(resp)) {
|
||||
if (resp.Error === 'DeviceLocked') {
|
||||
throw new lib_errors_1.IOSLibError('Device is currently locked.', 'DeviceLocked');
|
||||
}
|
||||
throw new Error(resp.Error);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
exports.LockdownProtocolReader = LockdownProtocolReader;
|
||||
class LockdownProtocolWriter {
|
||||
write(socket, plistData) {
|
||||
debug(`socket write: ${JSON.stringify(plistData)}`);
|
||||
const plistMessage = plist.build(plistData);
|
||||
const header = Buffer.alloc(exports.LOCKDOWN_HEADER_SIZE);
|
||||
header.writeUInt32BE(plistMessage.length, 0);
|
||||
socket.write(header);
|
||||
socket.write(plistMessage);
|
||||
}
|
||||
}
|
||||
exports.LockdownProtocolWriter = LockdownProtocolWriter;
|
||||
111
electron/node_modules/native-run/dist/ios/lib/protocol/protocol.js
generated
vendored
Normal file
111
electron/node_modules/native-run/dist/ios/lib/protocol/protocol.js
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ProtocolClient = exports.PlistProtocolReader = exports.ProtocolReader = exports.ProtocolReaderFactory = void 0;
|
||||
const bplistParser = require("bplist-parser");
|
||||
const plist = require("plist");
|
||||
const BPLIST_MAGIC = Buffer.from('bplist00');
|
||||
class ProtocolReaderFactory {
|
||||
constructor(ProtocolReader) {
|
||||
this.ProtocolReader = ProtocolReader;
|
||||
}
|
||||
create(callback) {
|
||||
return new this.ProtocolReader(callback);
|
||||
}
|
||||
}
|
||||
exports.ProtocolReaderFactory = ProtocolReaderFactory;
|
||||
class ProtocolReader {
|
||||
constructor(headerSize, callback) {
|
||||
this.headerSize = headerSize;
|
||||
this.callback = callback;
|
||||
this.buffer = Buffer.alloc(0);
|
||||
this.onData = this.onData.bind(this);
|
||||
}
|
||||
onData(data) {
|
||||
try {
|
||||
// if there's data, add it on to existing buffer
|
||||
this.buffer = data ? Buffer.concat([this.buffer, data]) : this.buffer;
|
||||
// we haven't gotten the body length from the header yet
|
||||
if (!this.bodyLength) {
|
||||
if (this.buffer.length < this.headerSize) {
|
||||
// partial header, wait for rest
|
||||
return;
|
||||
}
|
||||
this.bodyLength = this.parseHeader(this.buffer);
|
||||
// move on to body
|
||||
this.buffer = this.buffer.slice(this.headerSize);
|
||||
if (!this.buffer.length) {
|
||||
// only got header, wait for body
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.buffer.length < this.bodyLength) {
|
||||
// wait for rest of body
|
||||
return;
|
||||
}
|
||||
if (this.bodyLength === -1) {
|
||||
this.callback(this.parseBody(this.buffer));
|
||||
this.buffer = Buffer.alloc(0);
|
||||
}
|
||||
else {
|
||||
this.body = this.buffer.slice(0, this.bodyLength);
|
||||
this.bodyLength -= this.body.length;
|
||||
if (!this.bodyLength) {
|
||||
this.callback(this.parseBody(this.body));
|
||||
}
|
||||
this.buffer = this.buffer.slice(this.body.length);
|
||||
// There are multiple messages here, call parse again
|
||||
if (this.buffer.length) {
|
||||
this.onData();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
this.callback(null, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ProtocolReader = ProtocolReader;
|
||||
class PlistProtocolReader extends ProtocolReader {
|
||||
parseBody(body) {
|
||||
if (BPLIST_MAGIC.compare(body, 0, 8) === 0) {
|
||||
return bplistParser.parseBuffer(body);
|
||||
}
|
||||
else {
|
||||
return plist.parse(body.toString('utf8'));
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.PlistProtocolReader = PlistProtocolReader;
|
||||
class ProtocolClient {
|
||||
constructor(socket, readerFactory, writer) {
|
||||
this.socket = socket;
|
||||
this.readerFactory = readerFactory;
|
||||
this.writer = writer;
|
||||
}
|
||||
sendMessage(msg, callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = this.readerFactory.create(async (resp, err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
if (callback) {
|
||||
callback(resp, (value) => {
|
||||
this.socket.removeListener('data', reader.onData);
|
||||
resolve(value);
|
||||
}, reject);
|
||||
}
|
||||
else {
|
||||
this.socket.removeListener('data', reader.onData);
|
||||
resolve(resp);
|
||||
}
|
||||
});
|
||||
this.socket.on('error', (err) => {
|
||||
throw err;
|
||||
});
|
||||
this.socket.on('data', reader.onData);
|
||||
this.writer.write(this.socket, msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.ProtocolClient = ProtocolClient;
|
||||
57
electron/node_modules/native-run/dist/ios/lib/protocol/usbmux.js
generated
vendored
Normal file
57
electron/node_modules/native-run/dist/ios/lib/protocol/usbmux.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UsbmuxProtocolWriter = exports.UsbmuxProtocolReader = exports.UsbmuxProtocolClient = exports.USBMUXD_HEADER_SIZE = void 0;
|
||||
const Debug = require("debug");
|
||||
const plist = require("plist");
|
||||
const protocol_1 = require("./protocol");
|
||||
const debug = Debug('native-run:ios:lib:protocol:usbmux');
|
||||
exports.USBMUXD_HEADER_SIZE = 16;
|
||||
class UsbmuxProtocolClient extends protocol_1.ProtocolClient {
|
||||
constructor(socket) {
|
||||
super(socket, new protocol_1.ProtocolReaderFactory(UsbmuxProtocolReader), new UsbmuxProtocolWriter());
|
||||
}
|
||||
}
|
||||
exports.UsbmuxProtocolClient = UsbmuxProtocolClient;
|
||||
class UsbmuxProtocolReader extends protocol_1.PlistProtocolReader {
|
||||
constructor(callback) {
|
||||
super(exports.USBMUXD_HEADER_SIZE, callback);
|
||||
}
|
||||
parseHeader(data) {
|
||||
return data.readUInt32LE(0) - exports.USBMUXD_HEADER_SIZE;
|
||||
}
|
||||
parseBody(data) {
|
||||
const resp = super.parseBody(data);
|
||||
debug(`Response: ${JSON.stringify(resp)}`);
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
exports.UsbmuxProtocolReader = UsbmuxProtocolReader;
|
||||
class UsbmuxProtocolWriter {
|
||||
constructor() {
|
||||
this.useTag = 0;
|
||||
}
|
||||
write(socket, msg) {
|
||||
// TODO Usbmux message type
|
||||
debug(`socket write: ${JSON.stringify(msg)}`);
|
||||
const { messageType, extraFields } = msg;
|
||||
const plistMessage = plist.build({
|
||||
BundleID: 'io.ionic.native-run',
|
||||
ClientVersionString: 'usbmux.js',
|
||||
MessageType: messageType,
|
||||
ProgName: 'native-run',
|
||||
kLibUSBMuxVersion: 3,
|
||||
...extraFields,
|
||||
});
|
||||
const dataSize = plistMessage ? plistMessage.length : 0;
|
||||
const protocolVersion = 1;
|
||||
const messageCode = 8;
|
||||
const header = Buffer.alloc(exports.USBMUXD_HEADER_SIZE);
|
||||
header.writeUInt32LE(exports.USBMUXD_HEADER_SIZE + dataSize, 0);
|
||||
header.writeUInt32LE(protocolVersion, 4);
|
||||
header.writeUInt32LE(messageCode, 8);
|
||||
header.writeUInt32LE(this.useTag++, 12); // TODO
|
||||
socket.write(header);
|
||||
socket.write(plistMessage);
|
||||
}
|
||||
}
|
||||
exports.UsbmuxProtocolWriter = UsbmuxProtocolWriter;
|
||||
Loading…
Add table
Add a link
Reference in a new issue