From 6c4931b0ba1663adb09819cb717fed9ffac94216 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Thu, 3 Dec 2020 12:11:06 -0600 Subject: [PATCH] [AltXPC] Initial version AltXPC uses the private com.apple.authkit.client.internal entitlement to retrieve anisette data. --- AltStore.xcodeproj/project.pbxproj | 174 ++++++++++++++++++ .../xcshareddata/xcschemes/AltXPC.xcscheme | 77 ++++++++ AltXPC/AltXPC-Bridging-Header.h | 7 + AltXPC/AltXPC.entitlements | 8 + AltXPC/AltXPC.swift | 24 +++ AltXPC/Info.plist | 31 ++++ AltXPC/main.swift | 31 ++++ Shared/XPC/AltXPCProtocol.h | 18 ++ 8 files changed, 370 insertions(+) create mode 100644 AltStore.xcodeproj/xcshareddata/xcschemes/AltXPC.xcscheme create mode 100644 AltXPC/AltXPC-Bridging-Header.h create mode 100644 AltXPC/AltXPC.entitlements create mode 100644 AltXPC/AltXPC.swift create mode 100644 AltXPC/Info.plist create mode 100644 AltXPC/main.swift create mode 100644 Shared/XPC/AltXPCProtocol.h diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index b0887892..5b383bc9 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -188,6 +188,8 @@ BF770E5822BC3D0F002A40FE /* RefreshGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF770E5722BC3D0F002A40FE /* RefreshGroup.swift */; }; BF770E6722BD57C4002A40FE /* BackgroundTaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF770E6622BD57C3002A40FE /* BackgroundTaskManager.swift */; }; BF770E6922BD57DD002A40FE /* Silence.m4a in Resources */ = {isa = PBXBuildFile; fileRef = BF770E6822BD57DD002A40FE /* Silence.m4a */; }; + BF77A67025795A5600BFE477 /* AltXPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF77A66F25795A5600BFE477 /* AltXPC.swift */; }; + BF77A67E25795BBE00BFE477 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF77A67D25795BBE00BFE477 /* main.swift */; }; BF88F97224F8727D00BB75DF /* AppManagerErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF88F97124F8727D00BB75DF /* AppManagerErrors.swift */; }; BF8B17EB250AC40000F8157F /* FileManager+SharedDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6A531F246DC1B0004F59C8 /* FileManager+SharedDirectories.swift */; }; BF8CAE452489E772004D6CCE /* AnisetteDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8CAE422489E772004D6CCE /* AnisetteDataManager.swift */; }; @@ -335,6 +337,9 @@ BFF0B69A2322D7D0007A79E1 /* UIScreen+CompactHeight.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF0B6992322D7D0007A79E1 /* UIScreen+CompactHeight.swift */; }; BFF615A82510042B00484D3B /* AltStoreCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF66EE7E2501AE50007EE018 /* AltStoreCore.framework */; }; BFF767C82489A74E0097E58C /* WirelessConnectionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF767C72489A74E0097E58C /* WirelessConnectionHandler.swift */; }; + BFF7C90F257844C900E55F36 /* AltXPC.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = BFF7C904257844C900E55F36 /* AltXPC.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + BFF7C920257844FA00E55F36 /* ALTPluginService.m in Sources */ = {isa = PBXBuildFile; fileRef = BF5C5FCE237DF69100EDD0C6 /* ALTPluginService.m */; }; + BFF7C9342578492100E55F36 /* ALTAnisetteData.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB49AA823834CF900D542D9 /* ALTAnisetteData.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -366,6 +371,13 @@ remoteGlobalIDString = BF66EE7D2501AE50007EE018; remoteInfo = AltStoreCore; }; + BFF7C90D257844C900E55F36 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFD247622284B9A500981D42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = BFF7C903257844C900E55F36; + remoteInfo = AltXPC; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -415,6 +427,17 @@ name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; }; + BFF7C910257844C900E55F36 /* Embed XPC Services */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices"; + dstSubfolderSpec = 16; + files = ( + BFF7C90F257844C900E55F36 /* AltXPC.xpc in Embed XPC Services */, + ); + name = "Embed XPC Services"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -625,6 +648,9 @@ BF770E5722BC3D0F002A40FE /* RefreshGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshGroup.swift; sourceTree = ""; }; BF770E6622BD57C3002A40FE /* BackgroundTaskManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundTaskManager.swift; sourceTree = ""; }; BF770E6822BD57DD002A40FE /* Silence.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Silence.m4a; sourceTree = ""; }; + BF77A66E25795A5600BFE477 /* AltXPC-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AltXPC-Bridging-Header.h"; sourceTree = ""; }; + BF77A66F25795A5600BFE477 /* AltXPC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltXPC.swift; sourceTree = ""; }; + BF77A67D25795BBE00BFE477 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; BF88F97124F8727D00BB75DF /* AppManagerErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManagerErrors.swift; sourceTree = ""; }; BF8B17F0250AC62400F8157F /* AltWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AltWidgetExtension.entitlements; sourceTree = ""; }; BF8CAE422489E772004D6CCE /* AnisetteDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnisetteDataManager.swift; sourceTree = ""; }; @@ -746,6 +772,10 @@ BFF767C72489A74E0097E58C /* WirelessConnectionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WirelessConnectionHandler.swift; sourceTree = ""; }; BFF767CB2489AB5C0097E58C /* ALTServerError+Conveniences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ALTServerError+Conveniences.swift"; sourceTree = ""; }; BFF767CD2489ABE90097E58C /* NetworkConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkConnection.swift; sourceTree = ""; }; + BFF7C904257844C900E55F36 /* AltXPC.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = AltXPC.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; + BFF7C906257844C900E55F36 /* AltXPCProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AltXPCProtocol.h; sourceTree = ""; }; + BFF7C90C257844C900E55F36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + BFF7C93B257849C600E55F36 /* AltXPC.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AltXPC.entitlements; sourceTree = ""; }; BFF7EC4C25081E9300BDE521 /* AltStore 8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 8.xcdatamodel"; sourceTree = ""; }; BFFCFA45248835530077BFCE /* AltDaemon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AltDaemon.entitlements; sourceTree = ""; }; C9EEAA842DA87A88A870053B /* Pods_AltStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AltStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -826,6 +856,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + BFF7C901257844C900E55F36 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -888,6 +925,7 @@ BF718BD723C93DB700A89F2D /* ALTConstants.m */, BF18BFFF2485A75F00DD5981 /* Server Protocol */, BFF767CF2489AC240097E58C /* Connections */, + BFF7C92D2578464D00E55F36 /* XPC */, BFF767C32489A6800097E58C /* Extensions */, BFF767C42489A6980097E58C /* Categories */, ); @@ -1372,6 +1410,7 @@ BF58047C246A28F7008AE704 /* AltBackup */, BF18BFE824857D7900DD5981 /* AltDaemon */, BF98916C250AABF3002ACF50 /* AltWidget */, + BFF7C905257844C900E55F36 /* AltXPC */, BFD247852284BB3300981D42 /* Frameworks */, BFD2476B2284B9A500981D42 /* Products */, 4460E048E3AC1C9708C4FA33 /* Pods */, @@ -1389,6 +1428,7 @@ BF18BFE724857D7900DD5981 /* AltDaemon */, BF66EE7E2501AE50007EE018 /* AltStoreCore.framework */, BF989167250AABF3002ACF50 /* AltWidgetExtension.appex */, + BFF7C904257844C900E55F36 /* AltXPC.xpc */, ); name = Products; sourceTree = ""; @@ -1616,6 +1656,26 @@ path = Connections; sourceTree = ""; }; + BFF7C905257844C900E55F36 /* AltXPC */ = { + isa = PBXGroup; + children = ( + BFF7C93B257849C600E55F36 /* AltXPC.entitlements */, + BF77A67D25795BBE00BFE477 /* main.swift */, + BF77A66F25795A5600BFE477 /* AltXPC.swift */, + BF77A66E25795A5600BFE477 /* AltXPC-Bridging-Header.h */, + BFF7C90C257844C900E55F36 /* Info.plist */, + ); + path = AltXPC; + sourceTree = ""; + }; + BFF7C92D2578464D00E55F36 /* XPC */ = { + isa = PBXGroup; + children = ( + BFF7C906257844C900E55F36 /* AltXPCProtocol.h */, + ); + path = XPC; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1713,11 +1773,13 @@ BF7FDA2C23203B6B00B5D3A4 /* Copy Launcher App */, 98BF22D155DBAEA97544E3E6 /* [CP] Embed Pods Frameworks */, BF914C242383659400E713BA /* Sign Frameworks */, + BFF7C910257844C900E55F36 /* Embed XPC Services */, ); buildRules = ( ); dependencies = ( BF4588452298D48B00BD7491 /* PBXTargetDependency */, + BFF7C90E257844C900E55F36 /* PBXTargetDependency */, ); name = AltServer; packageProductDependencies = ( @@ -1842,6 +1904,23 @@ productReference = BFD2476A2284B9A500981D42 /* AltStore.app */; productType = "com.apple.product-type.application"; }; + BFF7C903257844C900E55F36 /* AltXPC */ = { + isa = PBXNativeTarget; + buildConfigurationList = BFF7C913257844C900E55F36 /* Build configuration list for PBXNativeTarget "AltXPC" */; + buildPhases = ( + BFF7C900257844C900E55F36 /* Sources */, + BFF7C901257844C900E55F36 /* Frameworks */, + BFF7C902257844C900E55F36 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AltXPC; + productName = AltXPC; + productReference = BFF7C904257844C900E55F36 /* AltXPC.xpc */; + productType = "com.apple.product-type.xpc-service"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1897,6 +1976,10 @@ }; }; }; + BFF7C903257844C900E55F36 = { + CreatedOnToolsVersion = 12.3; + LastSwiftMigration = 1230; + }; }; }; buildConfigurationList = BFD247652284B9A500981D42 /* Build configuration list for PBXProject "AltStore" */; @@ -1920,6 +2003,7 @@ BF18BFE624857D7900DD5981 /* AltDaemon */, BF66EE7D2501AE50007EE018 /* AltStoreCore */, BF989166250AABF3002ACF50 /* AltWidgetExtension */, + BFF7C903257844C900E55F36 /* AltXPC */, ); }; /* End PBXProject section */ @@ -1988,6 +2072,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + BFF7C902257844C900E55F36 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -2424,6 +2515,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + BFF7C900257844C900E55F36 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BFF7C9342578492100E55F36 /* ALTAnisetteData.m in Sources */, + BFF7C920257844FA00E55F36 /* ALTPluginService.m in Sources */, + BF77A67E25795BBE00BFE477 /* main.swift in Sources */, + BF77A67025795A5600BFE477 /* AltXPC.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -2447,6 +2549,11 @@ target = BF66EE7D2501AE50007EE018 /* AltStoreCore */; targetProxy = BFF615AA2510042B00484D3B /* PBXContainerItemProxy */; }; + BFF7C90E257844C900E55F36 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BFF7C903257844C900E55F36 /* AltXPC */; + targetProxy = BFF7C90D257844C900E55F36 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -3167,6 +3274,64 @@ }; name = Release; }; + BFF7C911257844C900E55F36 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_ENTITLEMENTS = AltXPC/AltXPC.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 6XVY5G3U44; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = AltXPC/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14.4; + PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltXPC; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "AltXPC/AltXPC-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + BFF7C912257844C900E55F36 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_ENTITLEMENTS = AltXPC/AltXPC.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 6XVY5G3U44; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = AltXPC/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14.4; + PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltXPC; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "AltXPC/AltXPC-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -3251,6 +3416,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + BFF7C913257844C900E55F36 /* Build configuration list for PBXNativeTarget "AltXPC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BFF7C911257844C900E55F36 /* Debug */, + BFF7C912257844C900E55F36 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCSwiftPackageProductDependency section */ diff --git a/AltStore.xcodeproj/xcshareddata/xcschemes/AltXPC.xcscheme b/AltStore.xcodeproj/xcshareddata/xcschemes/AltXPC.xcscheme new file mode 100644 index 00000000..4aca1860 --- /dev/null +++ b/AltStore.xcodeproj/xcshareddata/xcschemes/AltXPC.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AltXPC/AltXPC-Bridging-Header.h b/AltXPC/AltXPC-Bridging-Header.h new file mode 100644 index 00000000..8d7fdbf3 --- /dev/null +++ b/AltXPC/AltXPC-Bridging-Header.h @@ -0,0 +1,7 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "ALTAnisetteData.h" +#import "AltXPCProtocol.h" +#import "ALTPluginService.h" diff --git a/AltXPC/AltXPC.entitlements b/AltXPC/AltXPC.entitlements new file mode 100644 index 00000000..760f348f --- /dev/null +++ b/AltXPC/AltXPC.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.authkit.client.internal + + + diff --git a/AltXPC/AltXPC.swift b/AltXPC/AltXPC.swift new file mode 100644 index 00000000..c91b65d7 --- /dev/null +++ b/AltXPC/AltXPC.swift @@ -0,0 +1,24 @@ +// +// AltXPC.swift +// AltXPC +// +// Created by Riley Testut on 12/3/20. +// Copyright © 2020 Riley Testut. All rights reserved. +// + +import Foundation + +@objc(AltXPC) +class AltXPC: NSObject, AltXPCProtocol +{ + func ping(_ completionHandler: @escaping () -> Void) + { + completionHandler() + } + + func requestAnisetteData(completionHandler: @escaping (ALTAnisetteData?, Error?) -> Void) + { + let anisetteData = ALTPluginService.shared.requestAnisetteData() + completionHandler(anisetteData, nil) + } +} diff --git a/AltXPC/Info.plist b/AltXPC/Info.plist new file mode 100644 index 00000000..5e394254 --- /dev/null +++ b/AltXPC/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + AltXPC + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2020 Riley Testut. All rights reserved. + XPCService + + ServiceType + Application + + + diff --git a/AltXPC/main.swift b/AltXPC/main.swift new file mode 100644 index 00000000..42c0ad36 --- /dev/null +++ b/AltXPC/main.swift @@ -0,0 +1,31 @@ +// +// main.swift +// AltXPC +// +// Created by Riley Testut on 12/3/20. +// Copyright © 2020 Riley Testut. All rights reserved. +// + +import Foundation + +class ServiceDelegate : NSObject, NSXPCListenerDelegate +{ + func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool + { + newConnection.exportedInterface = NSXPCInterface(with: AltXPCProtocol.self) + + let exportedObject = AltXPC() + newConnection.exportedObject = exportedObject + newConnection.resume() + return true + } +} + +let serviceDelegate = ServiceDelegate() + +let listener = NSXPCListener.service() +listener.delegate = serviceDelegate +listener.resume() + +RunLoop.main.run() + diff --git a/Shared/XPC/AltXPCProtocol.h b/Shared/XPC/AltXPCProtocol.h new file mode 100644 index 00000000..629e1f42 --- /dev/null +++ b/Shared/XPC/AltXPCProtocol.h @@ -0,0 +1,18 @@ +// +// AltXPCProtocol.h +// AltXPC +// +// Created by Riley Testut on 12/2/20. +// Copyright © 2020 Riley Testut. All rights reserved. +// + +#import + +@class ALTAnisetteData; + +@protocol AltXPCProtocol + +- (void)ping:(void (^_Nonnull)(void))completionHandler; +- (void)requestAnisetteDataWithCompletionHandler:(void (^_Nonnull)(ALTAnisetteData *_Nullable anisetteData, NSError *_Nullable error))completionHandler; + +@end