mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
AltDaemon allows AltStore to install and refresh apps without a computer on jailbroken devices. AltDaemon has the necessary entitlements to perform the same actions AltServer normally does over WiFi, and uses the same AltServer request logic to handle local requests.
111 lines
3.8 KiB
Swift
111 lines
3.8 KiB
Swift
//
|
|
// LocalConnectionHandler.swift
|
|
// AltDaemon
|
|
//
|
|
// Created by Riley Testut on 6/2/20.
|
|
// Copyright © 2020 Riley Testut. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Network
|
|
|
|
import AltKit
|
|
|
|
private let ReceivedLocalServerConnectionRequest: @convention(c) (CFNotificationCenter?, UnsafeMutableRawPointer?, CFNotificationName?, UnsafeRawPointer?, CFDictionary?) -> Void =
|
|
{ (center, observer, name, object, userInfo) in
|
|
guard let name = name, let observer = observer else { return }
|
|
|
|
let connection = unsafeBitCast(observer, to: LocalConnectionHandler.self)
|
|
connection.handle(name)
|
|
}
|
|
|
|
class LocalConnectionHandler: ConnectionHandler
|
|
{
|
|
var connectionHandler: ((Connection) -> Void)?
|
|
var disconnectionHandler: ((Connection) -> Void)?
|
|
|
|
private let dispatchQueue = DispatchQueue(label: "io.altstore.LocalConnectionListener", qos: .utility)
|
|
|
|
deinit
|
|
{
|
|
self.stopListening()
|
|
}
|
|
|
|
func startListening()
|
|
{
|
|
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
|
|
let observer = Unmanaged.passUnretained(self).toOpaque()
|
|
|
|
CFNotificationCenterAddObserver(notificationCenter, observer, ReceivedLocalServerConnectionRequest, CFNotificationName.localServerConnectionAvailableRequest.rawValue, nil, .deliverImmediately)
|
|
CFNotificationCenterAddObserver(notificationCenter, observer, ReceivedLocalServerConnectionRequest, CFNotificationName.localServerConnectionStartRequest.rawValue, nil, .deliverImmediately)
|
|
}
|
|
|
|
func stopListening()
|
|
{
|
|
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
|
|
let observer = Unmanaged.passUnretained(self).toOpaque()
|
|
|
|
CFNotificationCenterRemoveObserver(notificationCenter, observer, .localServerConnectionAvailableRequest, nil)
|
|
CFNotificationCenterRemoveObserver(notificationCenter, observer, .localServerConnectionStartRequest, nil)
|
|
}
|
|
|
|
fileprivate func handle(_ notification: CFNotificationName)
|
|
{
|
|
switch notification
|
|
{
|
|
case .localServerConnectionAvailableRequest:
|
|
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
|
|
CFNotificationCenterPostNotification(notificationCenter, .localServerConnectionAvailableResponse, nil, nil, true)
|
|
|
|
case .localServerConnectionStartRequest:
|
|
let connection = NWConnection(host: "localhost", port: NWEndpoint.Port(rawValue: ALTDeviceListeningSocket)!, using: .tcp)
|
|
self.start(connection)
|
|
|
|
default: break
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension LocalConnectionHandler
|
|
{
|
|
func start(_ nwConnection: NWConnection)
|
|
{
|
|
print("Starting connection to:", nwConnection)
|
|
|
|
// Use same instance for all callbacks.
|
|
let connection = NetworkConnection(nwConnection)
|
|
|
|
nwConnection.stateUpdateHandler = { [weak self] (state) in
|
|
switch state
|
|
{
|
|
case .setup, .preparing: break
|
|
|
|
case .ready:
|
|
print("Connected to client:", nwConnection.endpoint)
|
|
self?.connectionHandler?(connection)
|
|
|
|
case .waiting:
|
|
print("Waiting for connection...")
|
|
|
|
case .failed(let error):
|
|
print("Failed to connect to service \(nwConnection.endpoint).", error)
|
|
self?.disconnect(connection)
|
|
|
|
case .cancelled:
|
|
self?.disconnect(connection)
|
|
|
|
@unknown default: break
|
|
}
|
|
}
|
|
|
|
nwConnection.start(queue: self.dispatchQueue)
|
|
}
|
|
|
|
func disconnect(_ connection: Connection)
|
|
{
|
|
connection.disconnect()
|
|
|
|
self.disconnectionHandler?(connection)
|
|
}
|
|
}
|