Sesame-iOS/Sesame/Client.swift
2022-05-01 14:07:43 +02:00

71 lines
2.3 KiB
Swift

import Foundation
import CryptoKit
struct Client {
let server: URL
private let delegate = NeverCacheDelegate()
init(server: URL) {
self.server = server
}
func deviceStatus(authToken: Data) async -> ClientState {
await send(path: .getDeviceStatus, data: authToken).state
}
func send(_ message: Message, authToken: Data) async -> (state: ClientState, response: Message?) {
let serverMessage = ServerMessage(authToken: authToken, message: message)
return await send(path: .postMessage, data: serverMessage.encoded)
}
private func send(path: RouteAPI, data: Data) async -> (state: ClientState, response: Message?) {
let url = server.appendingPathComponent(path.rawValue)
var request = URLRequest(url: url)
request.httpBody = data
request.httpMethod = "POST"
guard let data = await fulfill(request) else {
return (.deviceNotAvailable(.serverNotReached), nil)
}
guard let byte = data.first else {
return (.internalError("Empty response"), nil)
}
guard let status = MessageResult(rawValue: byte) else {
return (.internalError("Invalid message response: \(byte)"), nil)
}
let result = ClientState(keyResult: status)
guard data.count == Message.length + 1 else {
return (result, nil)
}
let messageData = Array(data.advanced(by: 1))
let message = Message(decodeFrom: messageData)
return (result, message)
}
private func fulfill(_ request: URLRequest) async -> Data? {
do {
let (data, response) = try await URLSession.shared.data(for: request)
guard let code = (response as? HTTPURLResponse)?.statusCode else {
print("No response from server")
return nil
}
guard code == 200 else {
print("Invalid server response \(code)")
return nil
}
return data
} catch {
print("Request failed: \(error)")
return nil
}
}
}
class NeverCacheDelegate: NSObject, NSURLConnectionDataDelegate {
func connection(_ connection: NSURLConnection, willCacheResponse cachedResponse: CachedURLResponse) -> CachedURLResponse? {
return nil
}
}