mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-21 19:35:49 +08:00
refactor(core): replace UDID with Uniq class and implement initial pairing support
This commit is contained in:
+250
-156
@@ -27,6 +27,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
#include <thread>
|
||||
|
||||
AppContext *AppContext::sharedInstance()
|
||||
{
|
||||
@@ -92,7 +93,6 @@ void AppContext::cachePairedDevices()
|
||||
lockdowndir.filePath(fileName);
|
||||
}
|
||||
#else
|
||||
// FIXME: implement caching for macOS
|
||||
/* MacOS */
|
||||
qDebug() << "Caching paired network devices from usbmuxd";
|
||||
auto conn = UsbmuxdConnection::default_new(0);
|
||||
@@ -183,165 +183,286 @@ void AppContext::cachePairedDevices()
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppContext::addDevice(QString udid,
|
||||
void AppContext::addDevice(iDescriptor::Uniq uniq,
|
||||
DeviceMonitorThread::IdeviceConnectionType conn_type,
|
||||
AddType addType, QString wifiMacAddress,
|
||||
QString ipAddress)
|
||||
{
|
||||
|
||||
emit initStarted(udid);
|
||||
emit initStarted(uniq);
|
||||
try {
|
||||
// iDescriptorInitDeviceResult initResult;
|
||||
auto initResult = std::make_shared<iDescriptorInitDeviceResult>();
|
||||
QFuture<void> future = QtConcurrent::run([this, udid, conn_type,
|
||||
|
||||
QFuture<void> future = QtConcurrent::run([this, uniq, conn_type,
|
||||
addType, wifiMacAddress,
|
||||
ipAddress, initResult]() {
|
||||
if (addType == AddType::UpgradeToWireless) {
|
||||
qDebug() << "AddType::UpgradeToWireless";
|
||||
// FIXME: udid is actually macAddress here
|
||||
const QString _pairingFilePath = getCachedPairingFile(udid);
|
||||
const QString _pairingFilePath = getCachedPairingFile(uniq);
|
||||
|
||||
if (_pairingFilePath.isEmpty()) {
|
||||
qDebug() << "Cannot upgrade to wireless, no cached pairing "
|
||||
"file for"
|
||||
<< udid;
|
||||
emitNoPairingFileForWirelessDevice(udid);
|
||||
<< uniq;
|
||||
emitNoPairingFileForWirelessDevice(uniq);
|
||||
return;
|
||||
}
|
||||
|
||||
*initResult = init_idescriptor_device(
|
||||
udid, {ipAddress, _pairingFilePath});
|
||||
init_idescriptor_device(uniq, *initResult,
|
||||
{ipAddress, _pairingFilePath});
|
||||
|
||||
} else if (addType == AddType::Wireless) {
|
||||
qDebug() << "AddType::Wireless";
|
||||
// FIXME: udid is actually macAddress here
|
||||
const QString _pairingFilePath = getCachedPairingFile(udid);
|
||||
const QString _pairingFilePath = getCachedPairingFile(uniq);
|
||||
|
||||
if (_pairingFilePath.isEmpty()) {
|
||||
qDebug() << "Cannot upgrade to wireless, no cached pairing "
|
||||
"file for"
|
||||
<< udid;
|
||||
emitNoPairingFileForWirelessDevice(udid);
|
||||
<< uniq;
|
||||
emitNoPairingFileForWirelessDevice(uniq);
|
||||
return;
|
||||
}
|
||||
|
||||
*initResult = init_idescriptor_device(
|
||||
udid, {ipAddress, _pairingFilePath});
|
||||
init_idescriptor_device(uniq, *initResult,
|
||||
{ipAddress, _pairingFilePath});
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
qDebug() << "AddType::Regular";
|
||||
*initResult = init_idescriptor_device(udid, {nullptr, nullptr});
|
||||
init_idescriptor_device(uniq, *initResult, {nullptr, nullptr});
|
||||
}
|
||||
});
|
||||
QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
|
||||
watcher->setFuture(future);
|
||||
connect(watcher, &QFutureWatcher<void>::finished, this,
|
||||
[this, udid, initResult, addType, conn_type, watcher]() {
|
||||
watcher->deleteLater();
|
||||
qDebug() << "init_idescriptor_device success ?: "
|
||||
<< initResult->success;
|
||||
// qDebug() << "init_idescriptor_device error code: " <<
|
||||
// initResult.error;
|
||||
if (!initResult->success) {
|
||||
qDebug() << "Failed to initialize device with UDID: "
|
||||
<< udid;
|
||||
emit initFailed(udid);
|
||||
return;
|
||||
connect(
|
||||
watcher, &QFutureWatcher<void>::finished, this,
|
||||
[this, uniq, initResult, addType, conn_type, watcher]() {
|
||||
watcher->deleteLater();
|
||||
qDebug() << "init_idescriptor_device success ?: "
|
||||
<< initResult->success;
|
||||
|
||||
if (!initResult->success) {
|
||||
qDebug() << "Failed to initialize device with" << uniq;
|
||||
emit initFailed(uniq);
|
||||
if (initResult->error && initResult->error->code ==
|
||||
PairingDialogResponsePending) {
|
||||
if (addType == AddType::Regular) {
|
||||
m_pendingDevices.append(uniq);
|
||||
emit devicePasswordProtected(uniq);
|
||||
emit deviceChange();
|
||||
QTimer::singleShot(
|
||||
SettingsManager::sharedInstance()
|
||||
->connectionTimeout() *
|
||||
1000,
|
||||
this, [this, uniq]() {
|
||||
if (m_pendingDevices.contains(uniq)) {
|
||||
qDebug() << "Pairing expired for "
|
||||
"device UDID:"
|
||||
<< uniq;
|
||||
m_pendingDevices.removeAll(uniq);
|
||||
emit devicePairingExpired(uniq);
|
||||
emit deviceChange();
|
||||
}
|
||||
});
|
||||
// FIXME: free properly and move to a better place
|
||||
QtConcurrent::run([uniq, this]() {
|
||||
UsbmuxdConnectionHandle *usbmuxd_conn = nullptr;
|
||||
UsbmuxdAddrHandle *addr_handle = nullptr;
|
||||
IdeviceProviderHandle *provider = nullptr;
|
||||
LockdowndClientHandle *lockdown = nullptr;
|
||||
IdevicePairingFile *pairing_file = nullptr;
|
||||
|
||||
IdeviceFfiError *err =
|
||||
idevice_usbmuxd_new_default_connection(
|
||||
0, &usbmuxd_conn);
|
||||
if (err) {
|
||||
// if (!isWireless) {
|
||||
qDebug() << "Failed to connect to usbmuxd";
|
||||
// goto cleanup;
|
||||
return;
|
||||
// }
|
||||
}
|
||||
|
||||
err = idevice_usbmuxd_default_addr_new(
|
||||
&addr_handle);
|
||||
if (err) {
|
||||
qDebug()
|
||||
<< "Failed to create address handle";
|
||||
// goto cleanup;
|
||||
return;
|
||||
}
|
||||
|
||||
UsbmuxdDeviceHandle **devices;
|
||||
int device_count;
|
||||
int actual_device_id = -1;
|
||||
err = idevice_usbmuxd_get_devices(
|
||||
usbmuxd_conn, &devices, &device_count);
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
const char *device_udid =
|
||||
idevice_usbmuxd_device_get_udid(
|
||||
devices[i]);
|
||||
if (strcmp(
|
||||
device_udid,
|
||||
uniq.get().toUtf8().constData()) ==
|
||||
0) {
|
||||
actual_device_id =
|
||||
idevice_usbmuxd_device_get_device_id(
|
||||
devices[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = usbmuxd_provider_new(
|
||||
addr_handle, 0,
|
||||
uniq.get().toUtf8().constData(),
|
||||
actual_device_id, APP_LABEL, &provider);
|
||||
|
||||
err = lockdownd_connect(provider, &lockdown);
|
||||
if (err) {
|
||||
qDebug() << "Failed to connect to lockdown";
|
||||
return;
|
||||
}
|
||||
|
||||
QString hostId = QUuid::createUuid()
|
||||
.toString()
|
||||
.remove("{")
|
||||
.remove("}")
|
||||
.toUpper();
|
||||
char *buid = nullptr;
|
||||
idevice_usbmuxd_get_buid(usbmuxd_conn, &buid);
|
||||
|
||||
bool ok = false;
|
||||
while (true) {
|
||||
// if (const auto dev =
|
||||
// AppContext::sharedInstance()
|
||||
// ->getDevice(
|
||||
// uniq.get().toStdString()))
|
||||
// {
|
||||
|
||||
if (ok) {
|
||||
qDebug() << "Successfully paired with "
|
||||
"device, ";
|
||||
break;
|
||||
};
|
||||
err = lockdownd_pair(
|
||||
lockdown, hostId.toStdString().c_str(),
|
||||
buid, &pairing_file);
|
||||
if (err) {
|
||||
qDebug() << "Failed to pair with device"
|
||||
<< err->message;
|
||||
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::seconds(5));
|
||||
// return;
|
||||
// goto cleanup;
|
||||
} else {
|
||||
|
||||
qDebug()
|
||||
<< "There was no error, pairing "
|
||||
"successful";
|
||||
uint8_t *data = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
// Serialize pairing file to bytes
|
||||
IdeviceFfiError *err =
|
||||
idevice_pairing_file_serialize(
|
||||
pairing_file, &data, &size);
|
||||
if (err) {
|
||||
qDebug() << "Failed to serialize "
|
||||
"pairing file:"
|
||||
<< err->message;
|
||||
// idevice_error_free(err);
|
||||
// goto cleanup;
|
||||
}
|
||||
|
||||
err = idevice_usbmuxd_save_pair_record(
|
||||
usbmuxd_conn,
|
||||
uniq.get().toUtf8().constData(),
|
||||
data, size);
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(),
|
||||
"addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, uniq),
|
||||
Q_ARG(DeviceMonitorThread::
|
||||
IdeviceConnectionType,
|
||||
DeviceMonitorThread::
|
||||
IdeviceConnectionType::
|
||||
CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::Regular));
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (!initResult.success) {
|
||||
// qDebug() << "Failed to initialize device with UDID: "
|
||||
// << udid; if (initResult.error ==
|
||||
// LOCKDOWN_E_PASSWORD_PROTECTED)
|
||||
// {
|
||||
// if (addType == AddType::Regular) {
|
||||
// m_pendingDevices.append(udid);
|
||||
// emit devicePasswordProtected(udid);
|
||||
// emit deviceChange();
|
||||
// QTimer::singleShot(
|
||||
// SettingsManager::sharedInstance()->connectionTimeout()
|
||||
// *
|
||||
// 1000,
|
||||
// this, [this, udid]() {
|
||||
// if (m_pendingDevices.contains(udid))
|
||||
// {
|
||||
// qDebug() << "Pairing expired for
|
||||
// device UDID:
|
||||
// "
|
||||
// << udid;
|
||||
// m_pendingDevices.removeAll(udid);
|
||||
// emit devicePairingExpired(udid);
|
||||
// emit deviceChange();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// } else if (initResult.error ==
|
||||
// LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING
|
||||
// ||
|
||||
// initResult.error ==
|
||||
// LOCKDOWN_E_INVALID_HOST_ID) {
|
||||
// m_pendingDevices.append(udid);
|
||||
// emit devicePairPending(udid);
|
||||
// emit deviceChange();
|
||||
// QTimer::singleShot(
|
||||
// SettingsManager::sharedInstance()->connectionTimeout()
|
||||
// *
|
||||
// 1000,
|
||||
// this, [this, udid]() {
|
||||
|
||||
// else if (initResult.error ==
|
||||
// LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING
|
||||
// ||
|
||||
// initResult.error ==
|
||||
// LOCKDOWN_E_INVALID_HOST_ID) {
|
||||
// m_pendingDevices.append(udid);
|
||||
// emit devicePairPending(udid);
|
||||
// emit deviceChange();
|
||||
// QTimer::singleShot(
|
||||
// SettingsManager::sharedInstance()->connectionTimeout()
|
||||
// *
|
||||
// 1000,
|
||||
// this, [this, udid]() {
|
||||
// qDebug()
|
||||
// << "Pairing timer fired for device
|
||||
// UDID: " << udid;
|
||||
// if (m_pendingDevices.contains(udid)) {
|
||||
// qDebug()
|
||||
// << "Pairing timer fired for device
|
||||
// << "Pairing expired for device
|
||||
// UDID: " << udid;
|
||||
// if (m_pendingDevices.contains(udid)) {
|
||||
// qDebug()
|
||||
// << "Pairing expired for device
|
||||
// UDID: " << udid;
|
||||
// m_pendingDevices.removeAll(udid);
|
||||
// emit devicePairingExpired(udid);
|
||||
// emit deviceChange();
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// qDebug() << "Unhandled error for device UDID: "
|
||||
// << udid
|
||||
// << " Error code: " << initResult.error;
|
||||
// }
|
||||
// return;
|
||||
// m_pendingDevices.removeAll(udid);
|
||||
// emit devicePairingExpired(udid);
|
||||
// emit deviceChange();
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// qDebug() << "Unhandled error for device UDID: "
|
||||
// << udid
|
||||
// << " Error code: " << initResult.error;
|
||||
// }
|
||||
qDebug() << "Device initialized: " << udid;
|
||||
return;
|
||||
}
|
||||
qDebug() << "Device initialized: " << uniq;
|
||||
|
||||
iDescriptorDevice *device = new iDescriptorDevice{
|
||||
.udid = udid.toStdString(),
|
||||
.conn_type = conn_type,
|
||||
.provider = initResult->provider,
|
||||
.deviceInfo = initResult->deviceInfo,
|
||||
.afcClient = initResult->afcClient,
|
||||
.afc2Client = initResult->afc2Client,
|
||||
.lockdown = initResult->lockdown,
|
||||
.imageMounter = initResult->imageMounter,
|
||||
.diagRelay = initResult->diagRelay,
|
||||
.locationSimulation = initResult->locationSimulation,
|
||||
.heartbeatThread = initResult->heartbeatThread};
|
||||
m_devices[device->udid] = device;
|
||||
if (addType == AddType::Regular) {
|
||||
qDebug() << "Regular device added: " << udid;
|
||||
// SettingsManager::sharedInstance()->doIfEnabled(
|
||||
// SettingsManager::Setting::AutoRaiseWindow, []() {
|
||||
// if (MainWindow *mainWindow =
|
||||
// MainWindow::sharedInstance()) {
|
||||
// mainWindow->raise();
|
||||
// mainWindow->activateWindow();
|
||||
// }
|
||||
// });
|
||||
iDescriptorDevice *device = new iDescriptorDevice{
|
||||
.udid = uniq.get().toStdString(),
|
||||
.conn_type = conn_type,
|
||||
.provider = initResult->provider,
|
||||
.deviceInfo = initResult->deviceInfo,
|
||||
.afcClient = initResult->afcClient,
|
||||
.afc2Client = initResult->afc2Client,
|
||||
.lockdown = initResult->lockdown,
|
||||
.diagRelay = initResult->diagRelay,
|
||||
.heartbeatThread = initResult->heartbeatThread};
|
||||
m_devices[device->udid] = device;
|
||||
if (addType == AddType::Regular) {
|
||||
qDebug() << "Regular device added: " << uniq;
|
||||
// SettingsManager::sharedInstance()->doIfEnabled(
|
||||
// SettingsManager::Setting::AutoRaiseWindow, []() {
|
||||
// if (MainWindow *mainWindow =
|
||||
// MainWindow::sharedInstance()) {
|
||||
// mainWindow->raise();
|
||||
// mainWindow->activateWindow();
|
||||
// }
|
||||
// });
|
||||
|
||||
emit deviceAdded(device);
|
||||
emit deviceChange();
|
||||
return;
|
||||
}
|
||||
emit devicePaired(device);
|
||||
emit deviceAdded(device);
|
||||
emit deviceChange();
|
||||
m_pendingDevices.removeAll(udid);
|
||||
});
|
||||
return;
|
||||
}
|
||||
emit devicePaired(device);
|
||||
emit deviceChange();
|
||||
m_pendingDevices.removeAll(uniq);
|
||||
});
|
||||
} catch (const std::exception &e) {
|
||||
qDebug() << "Exception in onDeviceAdded: " << e.what();
|
||||
}
|
||||
@@ -552,31 +673,18 @@ AppContext::getDeviceByMacAddress(const QString &macAddress) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AppContext::cachePairingFile(const QString &udid,
|
||||
void AppContext::cachePairingFile(const QString &uniq,
|
||||
const QString &pairingFilePath)
|
||||
{
|
||||
m_pairingFileCache.insert(udid, pairingFilePath);
|
||||
m_pairingFileCache.insert(uniq, pairingFilePath);
|
||||
}
|
||||
const QString AppContext::getCachedPairingFile(const QString &udid) const
|
||||
const QString AppContext::getCachedPairingFile(const QString &uniq) const
|
||||
{
|
||||
QString pairingFile;
|
||||
|
||||
// Retrieve the pairing file from the cache
|
||||
if (m_pairingFileCache.contains(udid)) {
|
||||
pairingFile = m_pairingFileCache.value(udid);
|
||||
} else {
|
||||
// FIXME: mac support
|
||||
// IdevicePairingFile* pairing_file = nullptr;
|
||||
// const char* file_path = udid.toUtf8().constData();
|
||||
// IdeviceFfiError* err = idevice_pairing_file_read(file_path,
|
||||
// &pairing_file); if (err == nullptr || pairing_file == nullptr) {
|
||||
// pairingFile = QString::fromUtf8(file_path);
|
||||
// } else {
|
||||
// qDebug() << "Failed to read pairing file for UDID:" << udid <<
|
||||
// "Error:" << err->message; idevice_error_free(err);
|
||||
// }
|
||||
if (m_pairingFileCache.contains(uniq)) {
|
||||
pairingFile = m_pairingFileCache.value(uniq);
|
||||
}
|
||||
|
||||
return pairingFile;
|
||||
}
|
||||
|
||||
@@ -585,33 +693,19 @@ void AppContext::heartbeatFailed(const QString &macAddress, int tries)
|
||||
emit deviceHeartbeatFailed(macAddress, tries);
|
||||
}
|
||||
|
||||
void AppContext::tryToConnectToNetworkDevice(const QString &macAddress)
|
||||
void AppContext::tryToConnectToNetworkDevice(const NetworkDevice &device)
|
||||
{
|
||||
|
||||
// force refresh macAddress-udid mapping
|
||||
cachePairedDevices();
|
||||
|
||||
QList<NetworkDevice> networkDevices =
|
||||
NetworkDeviceManager::sharedInstance()
|
||||
->m_networkProvider->getNetworkDevices();
|
||||
|
||||
auto it =
|
||||
std::find_if(networkDevices.constBegin(), networkDevices.constEnd(),
|
||||
[macAddress](const NetworkDevice &device) {
|
||||
return device.macAddress.compare(
|
||||
macAddress, Qt::CaseInsensitive) == 0;
|
||||
});
|
||||
|
||||
if (it != networkDevices.constEnd()) {
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(QString, macAddress),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::Wireless), Q_ARG(QString, macAddress));
|
||||
} else {
|
||||
qDebug() << "No network device found with MAC address:" << macAddress;
|
||||
}
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(device.macAddress, true)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::UpgradeToWireless),
|
||||
Q_ARG(QString, device.macAddress), Q_ARG(QString, device.address));
|
||||
}
|
||||
|
||||
// this is required because cannot emit signals from qfuture
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ public:
|
||||
void cachePairingFile(const QString &udid, const QString &pairingFilePath);
|
||||
const QString getCachedPairingFile(const QString &udid) const;
|
||||
|
||||
void tryToConnectToNetworkDevice(const QString &macAddress);
|
||||
void tryToConnectToNetworkDevice(const NetworkDevice &device);
|
||||
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
// QList<iDescriptorRecoveryDevice *> getAllRecoveryDevices();
|
||||
// #endif
|
||||
@@ -91,7 +91,7 @@ signals:
|
||||
void deviceHeartbeatFailed(const QString &macAddress, int tries);
|
||||
public slots:
|
||||
void removeDevice(QString udid);
|
||||
void addDevice(QString udid,
|
||||
void addDevice(iDescriptor::Uniq udid,
|
||||
DeviceMonitorThread::IdeviceConnectionType connType,
|
||||
AddType addType, QString wifiMacAddress = QString(),
|
||||
QString ipAddress = QString());
|
||||
|
||||
@@ -21,24 +21,33 @@
|
||||
|
||||
MountedImageInfo _get_mounted_image(const iDescriptorDevice *device)
|
||||
{
|
||||
qDebug() << "_get_mounted_image";
|
||||
|
||||
uint8_t *signature = NULL;
|
||||
size_t signature_len = 0;
|
||||
IdeviceFfiError *err = nullptr;
|
||||
qDebug() << "_get_mounted_image";
|
||||
ImageMounterHandle *image_mounter = nullptr;
|
||||
err = image_mounter_connect(device->provider, &image_mounter);
|
||||
if (err) {
|
||||
qDebug() << "Failed to create Image Mounter client";
|
||||
goto leave;
|
||||
}
|
||||
if (err) {
|
||||
qDebug() << "Failed to connect to image mounter:" << err->message;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = image_mounter_lookup_image(device->imageMounter,
|
||||
DISK_IMAGE_TYPE_DEVELOPER, &signature,
|
||||
&signature_len);
|
||||
err = image_mounter_lookup_image(image_mounter, DISK_IMAGE_TYPE_DEVELOPER,
|
||||
&signature, &signature_len);
|
||||
if (err) {
|
||||
qDebug() << "Failed to lookup image:" << err->message
|
||||
<< "Code:" << err->code;
|
||||
}
|
||||
|
||||
leave:
|
||||
if (image_mounter)
|
||||
image_mounter_free(image_mounter);
|
||||
|
||||
return {
|
||||
.err = err,
|
||||
.signature = signature,
|
||||
|
||||
@@ -364,22 +364,29 @@ DeviceInfo fullDeviceInfo(const pugi::xml_document &doc,
|
||||
}
|
||||
}
|
||||
|
||||
iDescriptorInitDeviceResult
|
||||
init_idescriptor_device(const QString &udid,
|
||||
const WirelessInitArgs &wirelessArgs)
|
||||
void init_idescriptor_device(const iDescriptor::Uniq &uniq,
|
||||
iDescriptorInitDeviceResult &result,
|
||||
const WirelessInitArgs &wirelessArgs)
|
||||
{
|
||||
const bool isWireless =
|
||||
!wirelessArgs.ip.isEmpty() && !wirelessArgs.pairing_file.isEmpty();
|
||||
qDebug() << "Initializing iDescriptor device with UDID: " << udid
|
||||
|
||||
/* these should never happen but just to be safe and not to waste any
|
||||
* resources return */
|
||||
if (isWireless && uniq.isUdid())
|
||||
return;
|
||||
if (!isWireless && uniq.isMac())
|
||||
return;
|
||||
|
||||
qDebug() << "Initializing iDescriptor device with"
|
||||
<< (uniq.isUdid() ? "UDID" : "MAC") << uniq
|
||||
<< (isWireless ? "over wireless" : "over USB");
|
||||
|
||||
if (isWireless) {
|
||||
qDebug() << "Wireless args" << "IP:" << wirelessArgs.ip
|
||||
<< "for mac address" << udid;
|
||||
<< "for mac address" << uniq;
|
||||
}
|
||||
|
||||
iDescriptorInitDeviceResult result = {};
|
||||
|
||||
UsbmuxdConnectionHandle *usbmuxd_conn = nullptr;
|
||||
UsbmuxdAddrHandle *addr_handle = nullptr;
|
||||
IdeviceProviderHandle *provider = nullptr;
|
||||
@@ -393,9 +400,7 @@ init_idescriptor_device(const QString &udid,
|
||||
IdeviceHandle *deviceHandle = nullptr;
|
||||
HeartbeatClientHandle *heartbeat = nullptr;
|
||||
HeartbeatThread *heartbeatThread = nullptr;
|
||||
ImageMounterHandle *image_mounter = nullptr;
|
||||
DiagnosticsRelayClientHandle *diagnostics_relay = nullptr;
|
||||
LocationSimulationHandle *location_simulation = nullptr;
|
||||
plist_t val = nullptr;
|
||||
|
||||
IdeviceFfiError *err =
|
||||
@@ -422,7 +427,7 @@ init_idescriptor_device(const QString &udid,
|
||||
inet_pton(AF_INET, wirelessArgs.ip.toUtf8().constData(),
|
||||
&addr_in.sin_addr);
|
||||
qDebug() << "Reading pairing file from" << wirelessArgs.pairing_file
|
||||
<< "for udid" << udid;
|
||||
<< "for" << (uniq.isUdid() ? "UDID" : "MAC") << uniq;
|
||||
err = idevice_pairing_file_read(
|
||||
wirelessArgs.pairing_file.toUtf8().constData(), &pairing_file);
|
||||
if (err) {
|
||||
@@ -443,8 +448,8 @@ init_idescriptor_device(const QString &udid,
|
||||
qDebug() << "Failed to start Heartbeat service";
|
||||
goto cleanup;
|
||||
}
|
||||
// udid is mac address here for wireless
|
||||
heartbeatThread = new HeartbeatThread(heartbeat, udid);
|
||||
|
||||
heartbeatThread = new HeartbeatThread(heartbeat, uniq);
|
||||
heartbeatThread->start();
|
||||
|
||||
while (!heartbeatThread->initialCompleted()) {
|
||||
@@ -458,19 +463,18 @@ init_idescriptor_device(const QString &udid,
|
||||
err =
|
||||
idevice_usbmuxd_get_devices(usbmuxd_conn, &devices, &device_count);
|
||||
|
||||
// Find by UDID and get its device_id
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
const char *device_udid =
|
||||
idevice_usbmuxd_device_get_udid(devices[i]);
|
||||
if (strcmp(device_udid, udid.toUtf8().constData()) == 0) {
|
||||
if (strcmp(device_udid, uniq.get().toUtf8().constData()) == 0) {
|
||||
actual_device_id =
|
||||
idevice_usbmuxd_device_get_device_id(devices[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Create provider for the device (actual function name)
|
||||
err = usbmuxd_provider_new(addr_handle, 0, udid.toUtf8().constData(),
|
||||
err = usbmuxd_provider_new(addr_handle, 0,
|
||||
uniq.get().toUtf8().constData(),
|
||||
actual_device_id, APP_LABEL, &provider);
|
||||
}
|
||||
|
||||
@@ -487,7 +491,11 @@ init_idescriptor_device(const QString &udid,
|
||||
|
||||
err = idevice_provider_get_pairing_file(provider, &pairing_file);
|
||||
if (err) {
|
||||
qDebug() << "Failed to get pairing file";
|
||||
idevice_error_free(err);
|
||||
err = new IdeviceFfiError{.code = PairingDialogResponsePending,
|
||||
.message = "Pairing dialog response pending"};
|
||||
|
||||
qDebug() << "Waiting for user to respond to pairing dialog on device";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -508,12 +516,6 @@ init_idescriptor_device(const QString &udid,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = image_mounter_connect(provider, &image_mounter);
|
||||
if (err) {
|
||||
qDebug() << "Failed to create Image Mounter client";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = diagnostics_relay_client_connect(provider, &diagnostics_relay);
|
||||
|
||||
if (err) {
|
||||
@@ -534,7 +536,7 @@ init_idescriptor_device(const QString &udid,
|
||||
// qDebug() << "Failed to create Location Simulation client";
|
||||
// goto cleanup;
|
||||
// }
|
||||
get_device_info_xml(udid.toUtf8().constData(), lockdown, infoXml);
|
||||
get_device_info_xml(uniq.get().toUtf8().constData(), lockdown, infoXml);
|
||||
|
||||
lockdownd_get_value(lockdown, "EnableWifiConnections",
|
||||
"com.apple.mobile.wireless_lockdown", &val);
|
||||
@@ -546,12 +548,8 @@ init_idescriptor_device(const QString &udid,
|
||||
result.afcClient = afc_client;
|
||||
result.afc2Client = afc2_client;
|
||||
result.lockdown = lockdown;
|
||||
// TODO:remove, not really required to get some stuff going so it can be
|
||||
// optional
|
||||
result.imageMounter = image_mounter;
|
||||
result.diagRelay = std::make_shared<DiagnosticsRelay>(
|
||||
DiagnosticsRelay::adopt(diagnostics_relay));
|
||||
result.locationSimulation = location_simulation;
|
||||
result.heartbeatThread = heartbeatThread;
|
||||
// TODO cache pairing file path
|
||||
result.deviceInfo.isWireless = isWireless;
|
||||
@@ -561,14 +559,16 @@ init_idescriptor_device(const QString &udid,
|
||||
::QObject::connect(heartbeatThread, &HeartbeatThread::heartbeatFailed,
|
||||
AppContext::sharedInstance(),
|
||||
&AppContext::heartbeatFailed);
|
||||
::QObject::connect(
|
||||
heartbeatThread, &HeartbeatThread::heartbeatThreadExited,
|
||||
AppContext::sharedInstance(), &AppContext::removeDevice);
|
||||
::QObject::connect(heartbeatThread,
|
||||
&HeartbeatThread::heartbeatThreadExited,
|
||||
AppContext::sharedInstance(),
|
||||
&AppContext::removeDevice, Qt::SingleShotConnection);
|
||||
}
|
||||
cleanup:
|
||||
// Cleanup on error
|
||||
// FIXME: implement proper cleanup
|
||||
// one of them causes a crash here, needs investigation
|
||||
result.error = err;
|
||||
if (!result.success) {
|
||||
qDebug() << "Initialization failed, cleaning up resources."
|
||||
<< err->message;
|
||||
@@ -585,8 +585,6 @@ cleanup:
|
||||
// if (usbmuxd_conn)
|
||||
// idevice_usbmuxd_connection_free(usbmuxd_conn);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
@@ -649,4 +647,4 @@ cleanup:
|
||||
|
||||
// return result;
|
||||
// }
|
||||
// #endif // ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
// #endif // ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
|
||||
@@ -29,7 +29,7 @@ IdeviceFfiError *mount_dev_image(const iDescriptorDevice *device,
|
||||
const char *signature_file)
|
||||
{
|
||||
|
||||
if (!device || !device->provider || !device->imageMounter) {
|
||||
if (!device || !device->provider) {
|
||||
qDebug()
|
||||
<< "Error: Invalid device or provider passed to mount_dev_image";
|
||||
return new IdeviceFfiError{// FIXME: whats the code ?
|
||||
@@ -43,7 +43,10 @@ IdeviceFfiError *mount_dev_image(const iDescriptorDevice *device,
|
||||
uint8_t *signature_data = nullptr;
|
||||
IdeviceFfiError *err = nullptr;
|
||||
|
||||
ImageMounterHandle *image_mounter = nullptr;
|
||||
err = image_mounter_connect(device->provider, &image_mounter);
|
||||
if (err) {
|
||||
qDebug() << "Failed to create Image Mounter client";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -56,9 +59,9 @@ IdeviceFfiError *mount_dev_image(const iDescriptorDevice *device,
|
||||
.message = "Failed to read signature file"};
|
||||
goto cleanup;
|
||||
} else {
|
||||
err = image_mounter_mount_developer(device->imageMounter, image_data,
|
||||
image_len, signature_data,
|
||||
signature_len);
|
||||
err =
|
||||
image_mounter_mount_developer(image_mounter, image_data, image_len,
|
||||
signature_data, signature_len);
|
||||
if (err == NULL) {
|
||||
printf("Developer image mounted successfully\n");
|
||||
} else {
|
||||
@@ -69,6 +72,8 @@ IdeviceFfiError *mount_dev_image(const iDescriptorDevice *device,
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (image_mounter)
|
||||
image_mounter_free(image_mounter);
|
||||
|
||||
if (image_data)
|
||||
free(image_data);
|
||||
|
||||
+19
-20
@@ -197,28 +197,27 @@ void DeviceManagerWidget::addDevice(iDescriptorDevice *device)
|
||||
// }
|
||||
// #endif
|
||||
|
||||
void DeviceManagerWidget::addPendingDevice(const QString &udid, bool locked)
|
||||
void DeviceManagerWidget::addPendingDevice(const QString &uniq, bool locked)
|
||||
{
|
||||
// qDebug() << "Adding pending device:" << udid;
|
||||
// if (m_pendingDeviceWidgets.contains(udid.toStdString()) && !locked) {
|
||||
// qDebug() << "Pending device already exists, moving to next state:"
|
||||
// << udid;
|
||||
// m_pendingDeviceWidgets[udid.toStdString()].first->next();
|
||||
// return;
|
||||
// } else if (m_pendingDeviceWidgets.contains(udid.toStdString()) && locked)
|
||||
// {
|
||||
// // Already exists and still locked, do nothing
|
||||
// qDebug()
|
||||
// << "Pending device already exists and is locked, doing nothing:"
|
||||
// << udid;
|
||||
// return;
|
||||
// }
|
||||
qDebug() << "Adding pending device:" << uniq;
|
||||
if (m_pendingDeviceWidgets.contains(uniq.toStdString()) && !locked) {
|
||||
qDebug() << "Pending device already exists, moving to next state:"
|
||||
<< uniq;
|
||||
m_pendingDeviceWidgets[uniq.toStdString()].first->next();
|
||||
return;
|
||||
} else if (m_pendingDeviceWidgets.contains(uniq.toStdString()) && locked) {
|
||||
// Already exists and still locked, do nothing
|
||||
qDebug()
|
||||
<< "Pending device already exists and is locked, doing nothing:"
|
||||
<< uniq;
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug() << "Created pending widget for:" << udid << "Locked:" << locked;
|
||||
// DevicePendingWidget *pendingWidget = new DevicePendingWidget(locked,
|
||||
// this); m_stackedWidget->addWidget(pendingWidget);
|
||||
// m_pendingDeviceWidgets[udid.toStdString()] =
|
||||
// std::pair{pendingWidget, m_sidebar->addPendingDevice(udid)};
|
||||
qDebug() << "Created pending widget for:" << uniq << "Locked:" << locked;
|
||||
DevicePendingWidget *pendingWidget = new DevicePendingWidget(locked, this);
|
||||
m_stackedWidget->addWidget(pendingWidget);
|
||||
m_pendingDeviceWidgets[uniq.toStdString()] =
|
||||
std::pair{pendingWidget, m_sidebar->addPendingDevice(uniq)};
|
||||
}
|
||||
|
||||
void DeviceManagerWidget::removePendingDevice(const QString &udid)
|
||||
|
||||
@@ -39,6 +39,34 @@ struct ProductTypeVersion {
|
||||
|
||||
namespace iDescriptor
|
||||
{
|
||||
/*
|
||||
Uniq is just a wrapper to get rid of mac and udid hell
|
||||
*/
|
||||
class Uniq
|
||||
{
|
||||
public:
|
||||
Uniq(const QString &uniq, bool isMac = false)
|
||||
{
|
||||
m_uniq = uniq;
|
||||
m_isMac = isMac;
|
||||
};
|
||||
|
||||
Uniq(const std::string &uniq, bool isMac = false)
|
||||
{
|
||||
m_uniq = QString::fromStdString(uniq);
|
||||
m_isMac = isMac;
|
||||
};
|
||||
|
||||
bool isMac() const { return m_isMac; };
|
||||
bool isUdid() const { return !m_isMac; }
|
||||
const QString &get() const { return m_uniq; }
|
||||
operator QString() const { return m_uniq; }
|
||||
|
||||
private:
|
||||
QString m_uniq;
|
||||
bool m_isMac;
|
||||
};
|
||||
|
||||
class Utils
|
||||
{
|
||||
private:
|
||||
|
||||
+6
-8
@@ -72,6 +72,8 @@
|
||||
#define DeviceLockedMountErrorCode -21
|
||||
#define NotFoundErrorCode -14
|
||||
#define ServiceNotFoundErrorCode -15
|
||||
#define PairingDialogResponsePending -28
|
||||
|
||||
#define DISK_IMAGE_TYPE_DEVELOPER "Developer"
|
||||
|
||||
#define HEARTBEAT_RETRY_LIMIT 2
|
||||
@@ -224,24 +226,20 @@ struct iDescriptorDevice {
|
||||
AfcClientHandle *afc2Client;
|
||||
LockdowndClientHandle *lockdown;
|
||||
mutable std::recursive_mutex mutex;
|
||||
ImageMounterHandle *imageMounter;
|
||||
std::shared_ptr<DiagnosticsRelay> diagRelay;
|
||||
LocationSimulationHandle *locationSimulation;
|
||||
// nullptr on USB devices
|
||||
QThread *heartbeatThread;
|
||||
};
|
||||
|
||||
struct iDescriptorInitDeviceResult {
|
||||
bool success = false;
|
||||
IdeviceFfiError error;
|
||||
IdeviceFfiError *error;
|
||||
IdeviceProviderHandle *provider;
|
||||
DeviceInfo deviceInfo;
|
||||
AfcClientHandle *afcClient;
|
||||
AfcClientHandle *afc2Client;
|
||||
LockdowndClientHandle *lockdown;
|
||||
ImageMounterHandle *imageMounter;
|
||||
std::shared_ptr<DiagnosticsRelay> diagRelay;
|
||||
LocationSimulationHandle *locationSimulation;
|
||||
QThread *heartbeatThread;
|
||||
};
|
||||
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
@@ -438,9 +436,9 @@ struct WirelessInitArgs {
|
||||
const QString ip;
|
||||
const QString pairing_file;
|
||||
};
|
||||
iDescriptorInitDeviceResult
|
||||
init_idescriptor_device(const QString &udid,
|
||||
const WirelessInitArgs &wirelessArgs = {"", ""});
|
||||
void init_idescriptor_device(const iDescriptor::Uniq &uniq,
|
||||
iDescriptorInitDeviceResult &result,
|
||||
const WirelessInitArgs &wirelessArgs = {"", ""});
|
||||
|
||||
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
|
||||
// iDescriptorInitDeviceResultRecovery
|
||||
|
||||
+26
-21
@@ -364,11 +364,12 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
if (conn_type == DeviceMonitorThread::CONNECTION_NETWORK) {
|
||||
return;
|
||||
}
|
||||
qDebug() << "Device added: " << udid;
|
||||
qDebug() << "Device event received: " << udid;
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Qt::QueuedConnection, Q_ARG(QString, udid),
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid)),
|
||||
Q_ARG(
|
||||
DeviceMonitorThread::IdeviceConnectionType,
|
||||
static_cast<DeviceMonitorThread::IdeviceConnectionType>(
|
||||
@@ -414,24 +415,27 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// Upgrade to wireless when a "WIRED" device is removed
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
connect(AppContext::sharedInstance(), &AppContext::deviceRemoved, this,
|
||||
[](const std::string &udid, const std::string &wifiMacAddress,
|
||||
const std::string &ipAddress, bool wasWireless) {
|
||||
if (wasWireless)
|
||||
return;
|
||||
qDebug() << "Upgrading device to wireless connection for UDID"
|
||||
<< QString::fromStdString(udid);
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(QString, QString::fromStdString(udid)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::UpgradeToWireless),
|
||||
Q_ARG(QString, QString::fromStdString(wifiMacAddress)),
|
||||
Q_ARG(QString, QString::fromStdString(ipAddress)));
|
||||
});
|
||||
connect(
|
||||
AppContext::sharedInstance(), &AppContext::deviceRemoved, this,
|
||||
[](const std::string &udid, const std::string &wifiMacAddress,
|
||||
const std::string &ipAddress, bool wasWireless) {
|
||||
if (wasWireless)
|
||||
return;
|
||||
qDebug() << "Upgrading device to wireless connection for UDID"
|
||||
<< QString::fromStdString(udid);
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
|
||||
Q_ARG(iDescriptor::Uniq, iDescriptor::Uniq(udid, wasWireless)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::UpgradeToWireless),
|
||||
Q_ARG(QString, QString::fromStdString(wifiMacAddress)),
|
||||
Q_ARG(QString, QString::fromStdString(ipAddress)));
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// Add a wireless device
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
connect(NetworkDeviceManager::sharedInstance(),
|
||||
&NetworkDeviceManager::deviceAdded, this,
|
||||
[this](const NetworkDevice &device) {
|
||||
@@ -455,7 +459,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
AppContext::sharedInstance(), "addDevice",
|
||||
Qt::QueuedConnection, Q_ARG(QString, device.macAddress),
|
||||
Q_ARG(iDescriptor::Uniq,
|
||||
iDescriptor::Uniq(device.macAddress, true)),
|
||||
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
|
||||
DeviceMonitorThread::CONNECTION_NETWORK),
|
||||
Q_ARG(AddType, AddType::Wireless),
|
||||
@@ -496,7 +501,7 @@ void MainWindow::createMenus()
|
||||
|
||||
void MainWindow::updateNoDevicesConnected()
|
||||
{
|
||||
qDebug() << "Is there no devices connected? "
|
||||
qDebug() << "No devices connected? "
|
||||
<< AppContext::sharedInstance()->noDevicesConnected();
|
||||
if (AppContext::sharedInstance()->noDevicesConnected()) {
|
||||
|
||||
|
||||
@@ -85,8 +85,7 @@ NetworkDeviceCard::NetworkDeviceCard(const NetworkDevice &device,
|
||||
connect(m_connectButton, &QPushButton::clicked, this, [this, device]() {
|
||||
m_connectButton->setText("Connecting...");
|
||||
m_connectButton->setEnabled(false);
|
||||
AppContext::sharedInstance()->tryToConnectToNetworkDevice(
|
||||
device.macAddress);
|
||||
AppContext::sharedInstance()->tryToConnectToNetworkDevice(device);
|
||||
});
|
||||
infoLayout->addWidget(m_connectButton);
|
||||
infoLayout->addSpacing(5);
|
||||
@@ -207,7 +206,7 @@ void NetworkDevicesToConnectWidget::setupUI()
|
||||
// Scroll area
|
||||
m_scrollArea = new QScrollArea();
|
||||
m_scrollArea->setWidgetResizable(true);
|
||||
m_scrollArea->setMinimumHeight(200);
|
||||
m_scrollArea->setMinimumHeight(400);
|
||||
m_scrollArea->setMaximumHeight(400);
|
||||
m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
||||
Reference in New Issue
Block a user