mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Treating AltKit as a full module resulted in more complexity than necessary, when we really just wanted to share some files between different targets. Now we can share individual files across modules as-needed without AltKit overhead.
149 lines
4.0 KiB
Swift
149 lines
4.0 KiB
Swift
//
|
|
// WirelessConnectionHandler.swift
|
|
// AltKit
|
|
//
|
|
// Created by Riley Testut on 6/1/20.
|
|
// Copyright © 2020 Riley Testut. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Network
|
|
|
|
extension WirelessConnectionHandler
|
|
{
|
|
public enum State
|
|
{
|
|
case notRunning
|
|
case connecting
|
|
case running(NWListener.Service)
|
|
case failed(Swift.Error)
|
|
}
|
|
}
|
|
|
|
public class WirelessConnectionHandler: ConnectionHandler
|
|
{
|
|
public var connectionHandler: ((Connection) -> Void)?
|
|
public var disconnectionHandler: ((Connection) -> Void)?
|
|
|
|
public var stateUpdateHandler: ((State) -> Void)?
|
|
|
|
public private(set) var state: State = .notRunning {
|
|
didSet {
|
|
self.stateUpdateHandler?(self.state)
|
|
}
|
|
}
|
|
|
|
private lazy var listener = self.makeListener()
|
|
private let dispatchQueue = DispatchQueue(label: "io.altstore.WirelessConnectionListener", qos: .utility)
|
|
|
|
public func startListening()
|
|
{
|
|
switch self.state
|
|
{
|
|
case .notRunning, .failed: self.listener.start(queue: self.dispatchQueue)
|
|
default: break
|
|
}
|
|
}
|
|
|
|
public func stopListening()
|
|
{
|
|
switch self.state
|
|
{
|
|
case .running: self.listener.cancel()
|
|
default: break
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension WirelessConnectionHandler
|
|
{
|
|
func makeListener() -> NWListener
|
|
{
|
|
let listener = try! NWListener(using: .tcp)
|
|
|
|
let service: NWListener.Service
|
|
|
|
if let serverID = UserDefaults.standard.serverID?.data(using: .utf8)
|
|
{
|
|
let txtDictionary = ["serverID": serverID]
|
|
let txtData = NetService.data(fromTXTRecord: txtDictionary)
|
|
|
|
service = NWListener.Service(name: nil, type: ALTServerServiceType, domain: nil, txtRecord: txtData)
|
|
}
|
|
else
|
|
{
|
|
service = NWListener.Service(type: ALTServerServiceType)
|
|
}
|
|
|
|
listener.service = service
|
|
|
|
listener.serviceRegistrationUpdateHandler = { (serviceChange) in
|
|
switch serviceChange
|
|
{
|
|
case .add(.service(let name, let type, let domain, _)):
|
|
let service = NWListener.Service(name: name, type: type, domain: domain, txtRecord: nil)
|
|
self.state = .running(service)
|
|
|
|
default: break
|
|
}
|
|
}
|
|
|
|
listener.stateUpdateHandler = { (state) in
|
|
switch state
|
|
{
|
|
case .ready: break
|
|
case .waiting, .setup: self.state = .connecting
|
|
case .cancelled: self.state = .notRunning
|
|
case .failed(let error): self.state = .failed(error)
|
|
@unknown default: break
|
|
}
|
|
}
|
|
|
|
listener.newConnectionHandler = { [weak self] (connection) in
|
|
self?.prepare(connection)
|
|
}
|
|
|
|
return listener
|
|
}
|
|
|
|
func prepare(_ nwConnection: NWConnection)
|
|
{
|
|
print("Preparing:", 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:", connection)
|
|
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)
|
|
}
|
|
}
|