import Foundation public struct Route: Equatable, Sendable { public let destination: MeshAddress public let nextHop: MeshAddress public let hopCount: Int } public final class LinkStateRouter: @unchecked Sendable { private struct Entry { let state: LinkState; var receivedAt: Date } private var database: [MeshAddress: Entry] = [:] private let local: MeshAddress private let lock = NSLock() public init(local: MeshAddress) { self.local = local } @discardableResult public func ingest(_ state: LinkState, now: Date = Date()) -> Bool { guard state.validate(), state.neighbors.count <= 32 else { return false } lock.lock(); defer { lock.unlock() } if let existing = database[state.origin.address], existing.state.sequence >= state.sequence { return false } if database[state.origin.address] == nil, database.count >= 32 { return false } database[state.origin.address] = Entry(state: state, receivedAt: now) return true } public func expire(olderThan seconds: TimeInterval = 30, now: Date = Date()) { lock.lock(); defer { lock.unlock() } database = database.filter { now.timeIntervalSince($0.value.receivedAt) <= seconds || $0.key == local } } public func record(for address: MeshAddress) -> NodeRecord? { lock.lock(); defer { lock.unlock() } return database[address]?.state.origin } public func allRecords() -> [NodeRecord] { lock.lock(); defer { lock.unlock() } return database.values.map(\.state.origin) } public func allStates() -> [LinkState] { lock.lock(); defer { lock.unlock() } return database.values.map(\.state) } public func routes() -> [MeshAddress: Route] { lock.lock(); let snapshot = database; lock.unlock() var graph: [MeshAddress: Set] = [:] for entry in snapshot.values { let origin = entry.state.origin.address for neighbor in entry.state.neighbors { graph[origin, default: []].insert(neighbor) graph[neighbor, default: []].insert(origin) } } var distance: [MeshAddress: Int] = [local: 0] var firstHop: [MeshAddress: MeshAddress] = [:] var queue = [local] while !queue.isEmpty { let current = queue.removeFirst() guard let base = distance[current], base < 16 else { continue } for neighbor in (graph[current] ?? []).sorted() { let candidateFirst = current == local ? neighbor : firstHop[current]! let candidateDistance = base + 1 if distance[neighbor] == nil || candidateDistance < distance[neighbor]! || (candidateDistance == distance[neighbor]! && candidateFirst < firstHop[neighbor]!) { distance[neighbor] = candidateDistance; firstHop[neighbor] = candidateFirst queue.append(neighbor) } } } return Dictionary(uniqueKeysWithValues: distance.compactMap { address, hops in guard address != local, let hop = firstHop[address] else { return nil } return (address, Route(destination: address, nextHop: hop, hopCount: hops)) }) } }