mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-12 00:03:27 +01:00
[AltServer] Improves handling of errors when installing apps
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSErrorDomain const AltServerErrorDomain;
|
||||
extern NSErrorDomain const AltServerInstallationErrorDomain;
|
||||
|
||||
typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
|
||||
{
|
||||
@@ -23,6 +24,8 @@ typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
|
||||
ALTServerErrorInvalidResponse,
|
||||
|
||||
ALTServerErrorInvalidApp,
|
||||
ALTServerErrorInstallationFailed,
|
||||
ALTServerErrorMaximumFreeAppLimitReached,
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -9,6 +9,56 @@
|
||||
#import "NSError+ALTServerError.h"
|
||||
|
||||
NSErrorDomain const AltServerErrorDomain = @"com.rileytestut.AltServer";
|
||||
NSErrorDomain const AltServerInstallationErrorDomain = @"com.rileytestut.AltServer.Installation";
|
||||
|
||||
@implementation NSError (ALTServerError)
|
||||
|
||||
+ (void)load
|
||||
{
|
||||
[NSError setUserInfoValueProviderForDomain:AltServerErrorDomain provider:^id _Nullable(NSError * _Nonnull error, NSErrorUserInfoKey _Nonnull userInfoKey) {
|
||||
if ([userInfoKey isEqualToString:NSLocalizedFailureReasonErrorKey])
|
||||
{
|
||||
return [error alt_localizedDescription];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (nullable NSString *)alt_localizedDescription
|
||||
{
|
||||
switch ((ALTServerError)self.code)
|
||||
{
|
||||
case ALTServerErrorUnknown:
|
||||
return NSLocalizedString(@"An unknown error occured.", @"");
|
||||
|
||||
case ALTServerErrorConnectionFailed:
|
||||
return NSLocalizedString(@"Could not connect to AltServer.", @"");
|
||||
|
||||
case ALTServerErrorLostConnection:
|
||||
return NSLocalizedString(@"Lost connection to AltServer.", @"");
|
||||
|
||||
case ALTServerErrorDeviceNotFound:
|
||||
return NSLocalizedString(@"AltServer could not locate this device", @"");
|
||||
|
||||
case ALTServerErrorDeviceWriteFailed:
|
||||
return NSLocalizedString(@"Failed to write app data to phone.", @"");
|
||||
|
||||
case ALTServerErrorInvalidRequest:
|
||||
return NSLocalizedString(@"AltServer received an invalid request.", @"");
|
||||
|
||||
case ALTServerErrorInvalidResponse:
|
||||
return NSLocalizedString(@"AltServer sent an invalid response.", @"");
|
||||
|
||||
case ALTServerErrorInvalidApp:
|
||||
return NSLocalizedString(@"The app is invalid.", @"");
|
||||
|
||||
case ALTServerErrorInstallationFailed:
|
||||
return NSLocalizedString(@"An error occured while installing the app.", @"");
|
||||
|
||||
case ALTServerErrorMaximumFreeAppLimitReached:
|
||||
return NSLocalizedString(@"You have reached the limit of 3 apps per device.", @"");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,16 +15,14 @@
|
||||
#include <libimobiledevice/notification_proxy.h>
|
||||
#include <libimobiledevice/afc.h>
|
||||
|
||||
void ALTDeviceManagerDidFinishAppInstallation(const char *notification, void *udid);
|
||||
void ALTDeviceManagerUpdateStatus(plist_t command, plist_t status, void *udid);
|
||||
|
||||
NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
|
||||
@interface ALTDeviceManager ()
|
||||
|
||||
@property (nonatomic, readonly) NSMutableDictionary<NSUUID *, void (^)(void)> *installationCompletionHandlers;
|
||||
@property (nonatomic, readonly) NSMutableDictionary<NSUUID *, void (^)(NSError *)> *installationCompletionHandlers;
|
||||
@property (nonatomic, readonly) NSMutableDictionary<NSUUID *, NSProgress *> *installationProgress;
|
||||
@property (nonatomic, readonly) NSMutableDictionary<NSUUID *, NSValue *> *installationClients;
|
||||
@property (nonatomic, readonly) dispatch_queue_t installationQueue;
|
||||
|
||||
@end
|
||||
@@ -49,7 +47,6 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
{
|
||||
_installationCompletionHandlers = [NSMutableDictionary dictionary];
|
||||
_installationProgress = [NSMutableDictionary dictionary];
|
||||
_installationClients = [NSMutableDictionary dictionary];
|
||||
|
||||
_installationQueue = dispatch_queue_create("com.rileytestut.AltServer.InstallationQueue", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
@@ -75,7 +72,7 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
lockdownd_service_descriptor_t service = NULL;
|
||||
|
||||
void (^finish)(NSError *error) = ^(NSError *error) {
|
||||
np_client_free(np);
|
||||
|
||||
instproxy_client_free(ipc);
|
||||
afc_client_free(afc);
|
||||
lockdownd_client_free(client);
|
||||
@@ -138,28 +135,6 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||
}
|
||||
|
||||
/* Connect to Notification Proxy */
|
||||
if ((lockdownd_start_service(client, "com.apple.mobile.notification_proxy", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
||||
{
|
||||
return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||
}
|
||||
|
||||
if (np_client_new(device, service, &np) != NP_E_SUCCESS)
|
||||
{
|
||||
return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||
}
|
||||
|
||||
np_set_notify_callback(np, ALTDeviceManagerDidFinishAppInstallation, uuidString);
|
||||
|
||||
const char *notifications[2] = { NP_APP_INSTALLED, NULL };
|
||||
np_observe_notifications(np, notifications);
|
||||
|
||||
if (service)
|
||||
{
|
||||
lockdownd_service_descriptor_free(service);
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
/* Connect to Installation Proxy */
|
||||
if ((lockdownd_start_service(client, "com.apple.mobile.installation_proxy", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
||||
{
|
||||
@@ -177,18 +152,12 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
lockdownd_service_descriptor_free(service);
|
||||
service = NULL;
|
||||
|
||||
/* Connect to AFC service */
|
||||
if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
||||
{
|
||||
return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||
}
|
||||
|
||||
lockdownd_client_free(client);
|
||||
client = NULL;
|
||||
|
||||
if (afc_client_new(device, service, &afc) != AFC_E_SUCCESS)
|
||||
{
|
||||
return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||
@@ -239,12 +208,11 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
|
||||
NSProgress *installationProgress = [NSProgress progressWithTotalUnitCount:100 parent:progress pendingUnitCount:1];
|
||||
|
||||
NSValue *value = [NSValue valueWithPointer:(const void *)np];
|
||||
NSProgress *installationProgress = [NSProgress progressWithTotalUnitCount:100 parent:progress pendingUnitCount:1];
|
||||
|
||||
self.installationClients[UUID] = value;
|
||||
self.installationProgress[UUID] = installationProgress;
|
||||
self.installationCompletionHandlers[UUID] = ^{
|
||||
finish(nil);
|
||||
self.installationCompletionHandlers[UUID] = ^(NSError *error) {
|
||||
finish(error);
|
||||
|
||||
if (temporaryDirectoryURL != nil)
|
||||
{
|
||||
@@ -470,29 +438,6 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
||||
|
||||
#pragma mark - Callbacks -
|
||||
|
||||
void ALTDeviceManagerDidFinishAppInstallation(const char *notification, void *uuid)
|
||||
{
|
||||
NSUUID *UUID = [[NSUUID alloc] initWithUUIDString:[NSString stringWithUTF8String:(const char *)uuid]];
|
||||
|
||||
void (^completionHandler)(void) = ALTDeviceManager.sharedManager.installationCompletionHandlers[UUID];
|
||||
if (completionHandler != nil)
|
||||
{
|
||||
completionHandler();
|
||||
|
||||
ALTDeviceManager.sharedManager.installationCompletionHandlers[UUID] = nil;
|
||||
ALTDeviceManager.sharedManager.installationProgress[UUID] = nil;
|
||||
}
|
||||
|
||||
NSValue *value = ALTDeviceManager.sharedManager.installationClients[UUID];
|
||||
if (value != nil)
|
||||
{
|
||||
np_client_t np = (np_client_t)value.pointerValue;
|
||||
np_set_notify_callback(np, NULL, uuid);
|
||||
|
||||
ALTDeviceManager.sharedManager.installationClients[UUID] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void ALTDeviceManagerUpdateStatus(plist_t command, plist_t status, void *uuid)
|
||||
{
|
||||
NSUUID *UUID = [[NSUUID alloc] initWithUUIDString:[NSString stringWithUTF8String:(const char *)uuid]];
|
||||
@@ -506,7 +451,46 @@ void ALTDeviceManagerUpdateStatus(plist_t command, plist_t status, void *uuid)
|
||||
int percent = -1;
|
||||
instproxy_status_get_percent_complete(status, &percent);
|
||||
|
||||
if (progress.completedUnitCount < percent)
|
||||
char *name = NULL;
|
||||
char *description = NULL;
|
||||
uint64_t code = 0;
|
||||
instproxy_status_get_error(status, &name, &description, &code);
|
||||
|
||||
if ((percent == -1 && progress.completedUnitCount > 0) || code != 0)
|
||||
{
|
||||
void (^completionHandler)(NSError *) = ALTDeviceManager.sharedManager.installationCompletionHandlers[UUID];
|
||||
if (completionHandler != nil)
|
||||
{
|
||||
if (code != 0)
|
||||
{
|
||||
NSLog(@"Error installing app. %@ (%@). %@", @(code), @(name), @(description));
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
if (code == 3892346913)
|
||||
{
|
||||
error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorMaximumFreeAppLimitReached userInfo:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSError *underlyingError = [NSError errorWithDomain:AltServerInstallationErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: @(description)}];
|
||||
|
||||
error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorInstallationFailed userInfo:@{NSUnderlyingErrorKey: underlyingError}];
|
||||
}
|
||||
|
||||
completionHandler(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Finished installing app!");
|
||||
completionHandler(nil);
|
||||
}
|
||||
|
||||
ALTDeviceManager.sharedManager.installationCompletionHandlers[UUID] = nil;
|
||||
ALTDeviceManager.sharedManager.installationProgress[UUID] = nil;
|
||||
}
|
||||
}
|
||||
else if (progress.completedUnitCount < percent)
|
||||
{
|
||||
progress.completedUnitCount = percent;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user