mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-12 16:23:32 +01:00
[Both] Adds support for installing apps over USB
This commit is contained in:
@@ -19,11 +19,14 @@ class ServerManager: NSObject
|
||||
private(set) var discoveredServers = [Server]()
|
||||
|
||||
private let serviceBrowser = NetServiceBrowser()
|
||||
|
||||
private var services = Set<NetService>()
|
||||
|
||||
private let dispatchQueue = DispatchQueue(label: "io.altstore.ServerManager")
|
||||
|
||||
private lazy var connectionListener = self.makeListener()
|
||||
private var incomingConnections = [NWConnection]()
|
||||
private let incomingConnectionsSemaphore = DispatchSemaphore(value: 0)
|
||||
|
||||
private override init()
|
||||
{
|
||||
super.init()
|
||||
@@ -41,6 +44,8 @@ extension ServerManager
|
||||
self.isDiscovering = true
|
||||
|
||||
self.serviceBrowser.searchForServices(ofType: ALTServerServiceType, inDomain: "")
|
||||
|
||||
self.connectionListener.start(queue: self.dispatchQueue)
|
||||
}
|
||||
|
||||
func stopDiscovering()
|
||||
@@ -55,30 +60,62 @@ extension ServerManager
|
||||
|
||||
func connect(to server: Server, completion: @escaping (Result<ServerConnection, Error>) -> Void)
|
||||
{
|
||||
let connection = NWConnection(to: .service(name: server.service.name, type: server.service.type, domain: server.service.domain, interface: nil), using: .tcp)
|
||||
|
||||
connection.stateUpdateHandler = { [unowned connection] (state) in
|
||||
switch state
|
||||
DispatchQueue.global().async {
|
||||
func finish(_ result: Result<ServerConnection, Error>)
|
||||
{
|
||||
case .failed(let error):
|
||||
print("Failed to connect to service \(server.service.name).", error)
|
||||
completion(.failure(ConnectionError.connectionFailed))
|
||||
completion(result)
|
||||
}
|
||||
|
||||
func start(_ connection: NWConnection)
|
||||
{
|
||||
connection.stateUpdateHandler = { [unowned connection] (state) in
|
||||
switch state
|
||||
{
|
||||
case .failed(let error):
|
||||
print("Failed to connect to service \(server.service?.name ?? "").", error)
|
||||
finish(.failure(ConnectionError.connectionFailed))
|
||||
|
||||
case .cancelled:
|
||||
finish(.failure(OperationError.cancelled))
|
||||
|
||||
case .ready:
|
||||
let connection = ServerConnection(server: server, connection: connection)
|
||||
finish(.success(connection))
|
||||
|
||||
case .waiting: break
|
||||
case .setup: break
|
||||
case .preparing: break
|
||||
@unknown default: break
|
||||
}
|
||||
}
|
||||
|
||||
case .cancelled:
|
||||
completion(.failure(OperationError.cancelled))
|
||||
connection.start(queue: self.dispatchQueue)
|
||||
}
|
||||
|
||||
if server.isWiredConnection
|
||||
{
|
||||
print("Waiting for new wired connection...")
|
||||
|
||||
case .ready:
|
||||
let connection = ServerConnection(server: server, connection: connection)
|
||||
completion(.success(connection))
|
||||
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
|
||||
CFNotificationCenterPostNotification(notificationCenter, .wiredServerConnectionStartRequest, nil, nil, true)
|
||||
|
||||
case .waiting: break
|
||||
case .setup: break
|
||||
case .preparing: break
|
||||
@unknown default: break
|
||||
_ = self.incomingConnectionsSemaphore.wait(timeout: .now() + 10.0)
|
||||
|
||||
if let connection = self.incomingConnections.popLast()
|
||||
{
|
||||
start(connection)
|
||||
}
|
||||
else
|
||||
{
|
||||
finish(.failure(ALTServerError(.connectionFailed)))
|
||||
}
|
||||
}
|
||||
else if let service = server.service
|
||||
{
|
||||
let connection = NWConnection(to: .service(name: service.name, type: service.type, domain: service.domain, interface: nil), using: .tcp)
|
||||
start(connection)
|
||||
}
|
||||
}
|
||||
|
||||
connection.start(queue: self.dispatchQueue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +130,27 @@ private extension ServerManager
|
||||
|
||||
self.discoveredServers.append(server)
|
||||
}
|
||||
|
||||
func makeListener() -> NWListener
|
||||
{
|
||||
let listener = try! NWListener(using: .tcp, on: NWEndpoint.Port(rawValue: ALTDeviceListeningSocket)!)
|
||||
listener.newConnectionHandler = { [weak self] (connection) in
|
||||
self?.incomingConnections.append(connection)
|
||||
self?.incomingConnectionsSemaphore.signal()
|
||||
}
|
||||
listener.stateUpdateHandler = { (state) in
|
||||
switch state
|
||||
{
|
||||
case .ready: break
|
||||
case .waiting, .setup: print("Listener socket waiting...")
|
||||
case .cancelled: print("Listener socket cancelled.")
|
||||
case .failed(let error): print("Listener socket failed:", error)
|
||||
@unknown default: break
|
||||
}
|
||||
}
|
||||
|
||||
return listener
|
||||
}
|
||||
}
|
||||
|
||||
extension ServerManager: NetServiceBrowserDelegate
|
||||
|
||||
Reference in New Issue
Block a user