2019-09-10 12:19:46 -07:00
//
// F i n d S e r v e r O p e r a t i o n . s w i f t
// A l t S t o r e
//
// C r e a t e d b y R i l e y T e s t u t o n 9 / 8 / 1 9 .
// C o p y r i g h t © 2 0 1 9 R i l e y T e s t u t . A l l r i g h t s r e s e r v e d .
//
import Foundation
2020-08-31 13:58:44 -07:00
2020-09-22 15:11:42 -07:00
import AltStoreCore
2019-09-10 12:19:46 -07:00
import Roxas
2020-06-04 19:53:10 -07:00
private let ReceivedServerConnectionResponse : @ convention ( c ) ( CFNotificationCenter ? , UnsafeMutableRawPointer ? , CFNotificationName ? , UnsafeRawPointer ? , CFDictionary ? ) -> Void =
2020-01-13 10:17:30 -08:00
{ ( center , observer , name , object , userInfo ) in
2020-06-04 19:53:10 -07:00
guard let name = name , let observer = observer else { return }
let operation = unsafeBitCast ( observer , to : FindServerOperation . self )
operation . handle ( name )
2020-01-13 10:17:30 -08:00
}
2019-09-10 12:19:46 -07:00
@objc ( FindServerOperation )
class FindServerOperation : ResultOperation < Server >
{
2020-03-06 17:08:35 -08:00
let context : OperationContext
2019-09-10 12:19:46 -07:00
2020-01-13 10:17:30 -08:00
private var isWiredServerConnectionAvailable = false
2020-09-30 14:42:22 -07:00
private var localServerMachServiceName : String ?
2020-03-06 17:08:35 -08:00
init ( context : OperationContext = OperationContext ( ) )
2019-09-10 12:19:46 -07:00
{
2020-03-06 17:08:35 -08:00
self . context = context
2019-09-10 12:19:46 -07:00
}
2020-06-04 19:53:10 -07:00
2019-09-10 12:19:46 -07:00
override func main ( )
{
super . main ( )
2020-03-06 17:08:35 -08:00
if let error = self . context . error
2019-09-10 12:19:46 -07:00
{
self . finish ( . failure ( error ) )
return
}
2020-03-06 17:08:35 -08:00
if let server = self . context . server
{
self . finish ( . success ( server ) )
return
}
2023-10-18 14:06:10 -05:00
Logger . sideload . notice ( " Discovering AltServers... " )
2020-01-13 10:17:30 -08:00
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter ( )
2020-06-04 19:53:10 -07:00
let observer = Unmanaged . passUnretained ( self ) . toOpaque ( )
2020-01-13 10:17:30 -08:00
2020-06-04 19:53:10 -07:00
// P r e p a r e o b s e r v e r s t o r e c e i v e c a l l b a c k f r o m w i r e d c o n n e c t i o n o r b a c k g r o u n d d a e m o n ( i f a v a i l a b l e ) .
CFNotificationCenterAddObserver ( notificationCenter , observer , ReceivedServerConnectionResponse , CFNotificationName . wiredServerConnectionAvailableResponse . rawValue , nil , . deliverImmediately )
2020-01-13 10:17:30 -08:00
2020-06-04 19:53:10 -07:00
// P o s t n o t i f i c a t i o n s .
2020-01-13 10:17:30 -08:00
CFNotificationCenterPostNotification ( notificationCenter , . wiredServerConnectionAvailableRequest , nil , nil , true )
2020-09-22 15:11:42 -07:00
self . discoverLocalServer ( )
2020-01-13 10:17:30 -08:00
// W a i t f o r e i t h e r c a l l b a c k o r t i m e o u t .
DispatchQueue . global ( ) . asyncAfter ( deadline : . now ( ) + 1.0 ) {
2020-09-30 14:42:22 -07:00
if let machServiceName = self . localServerMachServiceName
2020-06-04 19:53:10 -07:00
{
2023-10-18 14:06:10 -05:00
Logger . sideload . notice ( " Found AltDaemon! " )
2020-06-04 19:53:10 -07:00
// P r e f e r b a c k g r o u n d d a e m o n , i f i t e x i s t s a n d i s r u n n i n g .
2020-09-30 14:42:22 -07:00
let server = Server ( connectionType : . local , machServiceName : machServiceName )
2020-06-04 19:53:10 -07:00
self . finish ( . success ( server ) )
}
else if self . isWiredServerConnectionAvailable
{
2023-10-18 14:06:10 -05:00
Logger . sideload . notice ( " Found AltServer connected via USB! " )
2020-06-04 19:53:10 -07:00
let server = Server ( connectionType : . wired )
self . finish ( . success ( server ) )
}
else if let server = ServerManager . shared . discoveredServers . first ( where : { $0 . isPreferred } )
2020-01-13 10:17:30 -08:00
{
2023-10-18 14:06:10 -05:00
Logger . sideload . notice ( " Found preferred AltServer! \( server . localizedName ? ? " nil " , privacy : . public ) " )
2020-06-04 19:53:10 -07:00
// P r e f e r r e d s e r v e r .
self . finish ( . success ( server ) )
}
else if let server = ServerManager . shared . discoveredServers . first
{
2023-10-18 14:06:10 -05:00
Logger . sideload . notice ( " Found AltServer! \( server . localizedName ? ? " nil " , privacy : . public ) " )
2020-06-04 19:53:10 -07:00
// A n y a v a i l a b l e s e r v e r .
2020-01-13 10:17:30 -08:00
self . finish ( . success ( server ) )
}
else
{
2020-06-04 19:53:10 -07:00
// N o s e r v e r s .
2023-01-24 13:56:41 -06:00
self . finish ( . failure ( OperationError . serverNotFound ) )
2020-01-13 10:17:30 -08:00
}
2019-09-10 12:19:46 -07:00
}
}
2020-06-04 19:53:10 -07:00
override func finish ( _ result : Result < Server , Error > )
{
super . finish ( result )
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter ( )
let observer = Unmanaged . passUnretained ( self ) . toOpaque ( )
CFNotificationCenterRemoveObserver ( notificationCenter , observer , . wiredServerConnectionAvailableResponse , nil )
}
2019-09-10 12:19:46 -07:00
}
2020-06-04 19:53:10 -07:00
fileprivate extension FindServerOperation
2020-01-13 10:17:30 -08:00
{
2020-09-22 15:11:42 -07:00
func discoverLocalServer ( )
{
2020-09-30 14:42:22 -07:00
for machServiceName in XPCConnection . machServiceNames
{
let xpcConnection = NSXPCConnection . makeConnection ( machServiceName : machServiceName )
let connection = XPCConnection ( xpcConnection )
connection . connect { ( result ) in
switch result
{
2023-10-18 14:06:10 -05:00
case . failure ( let error ) : Logger . sideload . notice ( " Could not connect to AltDaemon XPC service \( machServiceName , privacy : . public ) . \( error . localizedDescription , privacy : . public ) " )
2020-09-30 14:42:22 -07:00
case . success : self . localServerMachServiceName = machServiceName
}
2020-09-22 15:11:42 -07:00
}
}
}
2020-06-04 19:53:10 -07:00
func handle ( _ notification : CFNotificationName )
2020-01-13 10:17:30 -08:00
{
2020-06-04 19:53:10 -07:00
switch notification
{
case . wiredServerConnectionAvailableResponse : self . isWiredServerConnectionAvailable = true
default : break
}
2020-01-13 10:17:30 -08:00
}
}