inital commit

This commit is contained in:
Owen Qwen
2026-08-31 15:55:09 -05:00
commit e71b3ada71
22 changed files with 1783 additions and 0 deletions
+188
View File
@@ -0,0 +1,188 @@
import Foundation
import CryptoKit
public enum UMNError: Error, LocalizedError {
case invalidAddress, invalidFrame, invalidIdentity, cryptoFailure
case noRoute, denied, unbound, transferLimit, timeout
case message(String)
public var errorDescription: String? {
switch self {
case .invalidAddress: "invalid mesh address"
case .invalidFrame: "invalid protocol frame"
case .invalidIdentity: "identity verification failed"
case .cryptoFailure: "cryptographic operation failed"
case .noRoute: "no route to destination"
case .denied: "destination firewall denied the connection"
case .unbound: "destination port has no bound service"
case .transferLimit: "the 1 MiB stream limit was exceeded"
case .timeout: "operation timed out"
case .message(let value): value
}
}
}
public struct MeshAddress: Hashable, Codable, Comparable, CustomStringConvertible, Sendable {
public let bytes: Data
public init(bytes: Data) throws {
guard bytes.count == 16, bytes.first == 0xfd else { throw UMNError.invalidAddress }
self.bytes = bytes
}
public init(_ text: String) throws {
var raw = in6_addr()
guard inet_pton(AF_INET6, text, &raw) == 1 else { throw UMNError.invalidAddress }
let data = withUnsafeBytes(of: &raw) { Data($0) }
try self.init(bytes: data)
}
public static func derive(from signingPublicKey: Data) throws -> MeshAddress {
let digest = Data(SHA256.hash(data: signingPublicKey))
return try MeshAddress(bytes: Data([0xfd]) + digest.prefix(15))
}
public var description: String {
var raw = in6_addr()
_ = withUnsafeMutableBytes(of: &raw) { bytes.copyBytes(to: $0) }
var output = [CChar](repeating: 0, count: Int(INET6_ADDRSTRLEN))
guard inet_ntop(AF_INET6, &raw, &output, socklen_t(INET6_ADDRSTRLEN)) != nil else {
return bytes.map { String(format: "%02x", $0) }.joined()
}
return String(cString: output)
}
public static func < (lhs: MeshAddress, rhs: MeshAddress) -> Bool {
lhs.bytes.lexicographicallyPrecedes(rhs.bytes)
}
}
public struct NodeRecord: Codable, Hashable, Sendable {
public let address: MeshAddress
public let signingPublicKey: Data
public let agreementPublicKey: Data
public init(address: MeshAddress, signingPublicKey: Data, agreementPublicKey: Data) {
self.address = address
self.signingPublicKey = signingPublicKey
self.agreementPublicKey = agreementPublicKey
}
public func validate() -> Bool {
guard signingPublicKey.count == 32, agreementPublicKey.count == 32,
let derived = try? MeshAddress.derive(from: signingPublicKey) else { return false }
return derived == address
}
}
public struct LinkState: Codable, Hashable, Sendable {
public let origin: NodeRecord
public let sequence: UInt64
public let neighbors: [MeshAddress]
public let signature: Data
public init(origin: NodeRecord, sequence: UInt64, neighbors: [MeshAddress], signature: Data) {
self.origin = origin
self.sequence = sequence
self.neighbors = neighbors.sorted()
self.signature = signature
}
public func signingBytes() throws -> Data {
struct Unsigned: Codable { let origin: NodeRecord; let sequence: UInt64; let neighbors: [MeshAddress] }
let encoder = PropertyListEncoder(); encoder.outputFormat = .binary
return try encoder.encode(Unsigned(origin: origin, sequence: sequence, neighbors: neighbors.sorted()))
}
public func validate() -> Bool {
guard origin.validate(), let key = try? Curve25519.Signing.PublicKey(rawRepresentation: origin.signingPublicKey),
let bytes = try? signingBytes() else { return false }
return key.isValidSignature(signature, for: bytes)
}
}
public enum PacketKind: String, Codable, Sendable {
case pingRequest, pingReply, text, streamOpen, streamData, streamAck, streamClose, streamReset, error
}
public struct InnerFrame: Codable, Sendable {
public let kind: PacketKind
public let streamID: UInt64
public let port: UInt16?
public let sequence: UInt64
public let acknowledgment: UInt64
public let payload: Data
public let sourceRecord: NodeRecord
public init(kind: PacketKind, streamID: UInt64 = 0, port: UInt16? = nil,
sequence: UInt64 = 0, acknowledgment: UInt64 = 0,
payload: Data = Data(), sourceRecord: NodeRecord) {
self.kind = kind; self.streamID = streamID; self.port = port
self.sequence = sequence; self.acknowledgment = acknowledgment
self.payload = payload; self.sourceRecord = sourceRecord
}
}
public struct SealedPayload: Codable, Sendable {
public let ephemeralPublicKey: Data
public let combinedCiphertext: Data
public init(ephemeralPublicKey: Data, combinedCiphertext: Data) {
self.ephemeralPublicKey = ephemeralPublicKey
self.combinedCiphertext = combinedCiphertext
}
}
public struct RoutedPacket: Codable, Sendable {
public let id: UUID
public let source: MeshAddress
public let destination: MeshAddress
public var hopLimit: UInt8
public let sealed: SealedPayload
public init(id: UUID = UUID(), source: MeshAddress, destination: MeshAddress,
hopLimit: UInt8 = 16, sealed: SealedPayload) {
self.id = id; self.source = source; self.destination = destination
self.hopLimit = hopLimit; self.sealed = sealed
}
}
public enum WireMessage: Codable, Sendable {
case hello(NodeRecord)
case linkState(LinkState)
case packet(RoutedPacket)
case keepalive
private enum CodingKeys: String, CodingKey { case type, payload }
private enum Kind: String, Codable { case hello, linkState, packet, keepalive }
public init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
switch try c.decode(Kind.self, forKey: .type) {
case .hello: self = .hello(try c.decode(NodeRecord.self, forKey: .payload))
case .linkState: self = .linkState(try c.decode(LinkState.self, forKey: .payload))
case .packet: self = .packet(try c.decode(RoutedPacket.self, forKey: .payload))
case .keepalive: self = .keepalive
}
}
public func encode(to encoder: Encoder) throws {
var c = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .hello(let value): try c.encode(Kind.hello, forKey: .type); try c.encode(value, forKey: .payload)
case .linkState(let value): try c.encode(Kind.linkState, forKey: .type); try c.encode(value, forKey: .payload)
case .packet(let value): try c.encode(Kind.packet, forKey: .type); try c.encode(value, forKey: .payload)
case .keepalive: try c.encode(Kind.keepalive, forKey: .type)
}
}
}
public struct WireEnvelope: Codable, Sendable {
public static let currentVersion: UInt16 = 1
public let version: UInt16
public let message: WireMessage
public init(message: WireMessage, version: UInt16 = currentVersion) {
self.version = version; self.message = message
}
}