Files
umn/Sources/UltraMeshCore/Framing.swift
T
2026-08-31 16:44:54 -05:00

59 lines
2.2 KiB
Swift

import Foundation
public enum FrameCodec {
public static let maximumFrameSize = 1_200_000
public static func encode<T: Encodable>(_ value: T) throws -> Data {
let encoder = PropertyListEncoder(); encoder.outputFormat = .binary
let body = try encoder.encode(value)
guard body.count <= maximumFrameSize else { throw UMNError.invalidFrame }
var size = UInt32(body.count).bigEndian
return withUnsafeBytes(of: &size) { Data($0) } + body
}
public static func decode<T: Decodable>(_ type: T.Type, body: Data) throws -> T {
guard body.count <= maximumFrameSize else { throw UMNError.invalidFrame }
return try PropertyListDecoder().decode(type, from: body)
}
public static func bodyLength(from prefix: Data) throws -> Int {
guard prefix.count == 4 else { throw UMNError.invalidFrame }
let value = prefix.reduce(UInt32(0)) { ($0 << 8) | UInt32($1) }
guard value > 0, value <= maximumFrameSize else { throw UMNError.invalidFrame }
return Int(value)
}
}
public enum IPCOperation: String, Codable, Sendable {
case status, address, peers, routes, ping, interfaceStatus
case aliasSet, aliasRemove, aliasList
case firewallAllow, firewallRevoke, firewallList
case textSend, bindText, bindStream, openStream, streamData, streamClose
}
public struct IPCMessage: Codable, Sendable {
public var version: UInt16
public var operation: IPCOperation
public var requestID: UUID
public var target: String?
public var source: String?
public var name: String?
public var port: UInt16?
public var firewallProtocol: FirewallProtocol?
public var interfaceName: String?
public var interfaceAddress: String?
public var interfaceMTU: UInt16?
public var helperState: String?
public var synchronizedRouteCount: Int?
public var dnsState: String?
public var streamID: UInt64?
public var data: Data?
public var ok: Bool?
public var message: String?
public var values: [String]?
public init(operation: IPCOperation, requestID: UUID = UUID()) {
self.version = 2; self.operation = operation; self.requestID = requestID
}
}