125 lines
3.4 KiB
Swift
125 lines
3.4 KiB
Swift
|
import Foundation
|
||
|
import WebSocketKit
|
||
|
import Vapor
|
||
|
|
||
|
final class KeyManagement {
|
||
|
|
||
|
/// The security parameter for the keys (in bits)
|
||
|
private static let keySecurity = 128
|
||
|
|
||
|
/// The size of the individual keys in bytes
|
||
|
static let keySize = keySecurity / 8
|
||
|
|
||
|
/// The connection to the device
|
||
|
private var connection: WebSocket?
|
||
|
|
||
|
private let deviceKey: String
|
||
|
|
||
|
var deviceIsAuthenticated = false
|
||
|
|
||
|
/// Indicator for device availability
|
||
|
var deviceIsConnected: Bool {
|
||
|
!(connection?.isClosed ?? true) && deviceIsAuthenticated
|
||
|
}
|
||
|
|
||
|
/// The id of the key which was sent to the device
|
||
|
private var keyInTransit: UInt16?
|
||
|
|
||
|
/// The result transmitted by the device for the sent key
|
||
|
var keyResult: KeyResult = .none
|
||
|
|
||
|
init(deviceKey: String) {
|
||
|
self.deviceKey = deviceKey
|
||
|
}
|
||
|
|
||
|
// MARK: API
|
||
|
|
||
|
var deviceResponse: String {
|
||
|
guard let keyId = keyInTransit else {
|
||
|
return "No key"
|
||
|
}
|
||
|
return "\(keyId):\(keyResult.rawValue)"
|
||
|
}
|
||
|
|
||
|
var deviceStatus: String {
|
||
|
deviceIsConnected ? "1" : "0"
|
||
|
}
|
||
|
|
||
|
func clearClientRequest() {
|
||
|
keyInTransit = nil
|
||
|
keyResult = .none
|
||
|
}
|
||
|
|
||
|
func sendKeyToDevice(_ key: Data, keyId: UInt16) -> KeyPostResponse {
|
||
|
guard key.count == KeyManagement.keySize else {
|
||
|
return .invalidKeySize
|
||
|
}
|
||
|
guard let socket = connection, !socket.isClosed else {
|
||
|
connection = nil
|
||
|
return .deviceNotConnected
|
||
|
}
|
||
|
let keyIdData = [UInt8(keyId >> 8), UInt8(keyId & 0xFF)]
|
||
|
keyInTransit = keyId
|
||
|
socket.send(keyIdData + key, promise: nil)
|
||
|
return .success
|
||
|
}
|
||
|
|
||
|
func authenticateDevice(psk: String) {
|
||
|
guard psk == self.deviceKey else {
|
||
|
print("Invalid device key")
|
||
|
_ = connection?.close()
|
||
|
deviceIsAuthenticated = false
|
||
|
return
|
||
|
}
|
||
|
print("Device authenticated")
|
||
|
deviceIsAuthenticated = true
|
||
|
}
|
||
|
|
||
|
func processDeviceResponse(_ data: ByteBuffer) {
|
||
|
guard data.readableBytes == 1 else {
|
||
|
print("Unexpected number of bytes received from device")
|
||
|
keyInTransit = nil
|
||
|
keyResult = .unexpectedSocketEvent
|
||
|
return
|
||
|
}
|
||
|
guard let rawValue = data.getBytes(at: 0, length: 1)?.first else {
|
||
|
print("Unreadable data received from device")
|
||
|
keyInTransit = nil
|
||
|
keyResult = .unexpectedSocketEvent
|
||
|
return
|
||
|
}
|
||
|
guard let response = KeyResult(rawValue: rawValue) else {
|
||
|
print("Unknown response \(rawValue) received from device")
|
||
|
keyInTransit = nil
|
||
|
keyResult = .unexpectedSocketEvent
|
||
|
return
|
||
|
}
|
||
|
guard keyInTransit != nil else {
|
||
|
print("No key in transit for response \(response)")
|
||
|
return
|
||
|
}
|
||
|
keyResult = response
|
||
|
}
|
||
|
|
||
|
func didCloseDeviceSocket() {
|
||
|
deviceIsAuthenticated = false
|
||
|
guard connection != nil else {
|
||
|
return
|
||
|
}
|
||
|
connection = nil
|
||
|
print("Socket closed")
|
||
|
}
|
||
|
|
||
|
func removeDeviceConnection() {
|
||
|
_ = connection?.close()
|
||
|
connection = nil
|
||
|
}
|
||
|
|
||
|
func createNewDeviceConnection(_ socket: WebSocket) {
|
||
|
removeDeviceConnection()
|
||
|
connection = socket
|
||
|
deviceIsAuthenticated = false
|
||
|
print("Socket connected")
|
||
|
}
|
||
|
}
|