feat(k1): add local connection matrix
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import CoreWLAN
|
||||
import Foundation
|
||||
|
||||
private struct AssociationRequest: Decodable {
|
||||
let ssid: String
|
||||
let password: String
|
||||
}
|
||||
|
||||
private struct AssociationResponse: Encodable {
|
||||
let ok: Bool
|
||||
let alreadyAssociated: Bool?
|
||||
let reasonCode: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case ok
|
||||
case alreadyAssociated = "already_associated"
|
||||
case reasonCode = "reason_code"
|
||||
}
|
||||
}
|
||||
|
||||
private func emit(_ response: AssociationResponse, exitCode: Int32) -> Never {
|
||||
let encoder = JSONEncoder()
|
||||
if let data = try? encoder.encode(response) {
|
||||
FileHandle.standardOutput.write(data)
|
||||
}
|
||||
exit(exitCode)
|
||||
}
|
||||
|
||||
private let input = FileHandle.standardInput.readDataToEndOfFile()
|
||||
guard input.count <= 1024 else {
|
||||
emit(
|
||||
AssociationResponse(ok: false, alreadyAssociated: nil, reasonCode: "request-too-large"),
|
||||
exitCode: 1
|
||||
)
|
||||
}
|
||||
|
||||
do {
|
||||
let request = try JSONDecoder().decode(AssociationRequest.self, from: input)
|
||||
guard let ssidData = request.ssid.data(using: .utf8),
|
||||
(1 ... 32).contains(ssidData.count),
|
||||
let passwordData = request.password.data(using: .utf8),
|
||||
(1 ... 64).contains(passwordData.count)
|
||||
else {
|
||||
emit(
|
||||
AssociationResponse(ok: false, alreadyAssociated: nil, reasonCode: "credential-bounds"),
|
||||
exitCode: 1
|
||||
)
|
||||
}
|
||||
|
||||
guard let interface = CWWiFiClient.shared().interface() else {
|
||||
emit(
|
||||
AssociationResponse(ok: false, alreadyAssociated: nil, reasonCode: "wifi-interface-unavailable"),
|
||||
exitCode: 1
|
||||
)
|
||||
}
|
||||
|
||||
if interface.ssid() == request.ssid {
|
||||
emit(AssociationResponse(ok: true, alreadyAssociated: true, reasonCode: nil), exitCode: 0)
|
||||
}
|
||||
|
||||
let networks = try interface.scanForNetworks(withSSID: ssidData)
|
||||
guard let network = networks.first(where: { $0.ssid == request.ssid }) else {
|
||||
emit(
|
||||
AssociationResponse(ok: false, alreadyAssociated: nil, reasonCode: "network-not-found"),
|
||||
exitCode: 1
|
||||
)
|
||||
}
|
||||
|
||||
try interface.associate(to: network, password: request.password)
|
||||
// CoreWLAN's synchronous association call throws on failure. Reading the
|
||||
// current SSID again would require Location authorization on recent macOS
|
||||
// versions and could turn a successful association into a false negative.
|
||||
emit(AssociationResponse(ok: true, alreadyAssociated: false, reasonCode: nil), exitCode: 0)
|
||||
} catch {
|
||||
emit(
|
||||
AssociationResponse(ok: false, alreadyAssociated: nil, reasonCode: "corewlan-error"),
|
||||
exitCode: 1
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user