···991010 // MARK: - mDNS
1111 static let bonjourServiceType = "_serviceberry._tcp"
1212- static let bonjourDomain = "local."
1212+ static let bonjourDomain = "local." // trailing dot is standard DNS format
13131414 // MARK: - Server
1515 static let serverPort: UInt16 = 8080
+45-9
serviceberry/Services/MDNSDiscovery.swift
···1111 @Published var discoveredServers: [ServerInfo] = []
1212 @Published var isSearching = false
1313 @Published var lastError: Error?
1414+ @Published var debugState: String = "idle"
14151516 /// Start browsing for Serviceberry servers
1617 func startBrowsing() {
1718 stopBrowsing()
1819 discoveredServers = []
1920 isSearching = true
2121+ debugState = "starting"
20222323+ // Use "local." domain with trailing dot (standard DNS format)
2124 let descriptor = NWBrowser.Descriptor.bonjour(
2225 type: Constants.bonjourServiceType,
2326 domain: Constants.bonjourDomain
2427 )
25282929+ // Configure parameters for local network discovery
2630 let parameters = NWParameters()
2727- parameters.includePeerToPeer = true
3131+ parameters.allowLocalEndpointReuse = true
3232+ parameters.acceptLocalOnly = true
3333+ parameters.allowFastOpen = true
28343535+ print("[mDNS] Creating browser for type: \(Constants.bonjourServiceType)")
2936 browser = NWBrowser(for: descriptor, using: parameters)
30373138 browser?.stateUpdateHandler = { [weak self] state in
···3340 guard let self else { return }
3441 switch state {
3542 case .ready:
3636- break
4343+ print("[mDNS] ✅ Browser ready, searching for \(Constants.bonjourServiceType)")
4444+ self.debugState = "ready"
3745 case .failed(let error):
4646+ print("[mDNS] ❌ Browser failed: \(error)")
4747+ print("[mDNS] ❌ Error code: \(error.debugDescription)")
4848+ self.debugState = "failed: \(error.localizedDescription)"
3849 self.lastError = error
3950 self.isSearching = false
4051 case .cancelled:
5252+ print("[mDNS] Browser cancelled")
5353+ self.debugState = "cancelled"
4154 self.isSearching = false
4242- default:
4343- break
5555+ case .waiting(let error):
5656+ print("[mDNS] ⏳ Browser waiting: \(error)")
5757+ self.debugState = "waiting: \(error.localizedDescription)"
5858+ case .setup:
5959+ print("[mDNS] Browser setup...")
6060+ self.debugState = "setup"
6161+ @unknown default:
6262+ print("[mDNS] Browser unknown state: \(state)")
6363+ self.debugState = "unknown"
4464 }
4565 }
4666 }
···4868 browser?.browseResultsChangedHandler = { [weak self] results, _ in
4969 Task { @MainActor [weak self] in
5070 guard let self else { return }
7171+ print("[mDNS] Found \(results.count) service(s)")
5172 self.processBrowseResults(results)
5273 }
5374 }
···6485 }
6586 connections = []
6687 isSearching = false
8888+ debugState = "stopped"
6789 }
68906991 private func processBrowseResults(_ results: Set<NWBrowser.Result>) {
7092 for result in results {
7193 guard case .service(let name, let type, let domain, _) = result.endpoint else { continue }
9494+ print("[mDNS] Service: '\(name)' type: '\(type)' domain: '\(domain)'")
72957396 // Extract TXT records from metadata
7497 var version = "unknown"
···159182 // Use the resolved hostname (e.g., "turtle.local")
160183 host = hostname
161184 case .ipv4(let addr):
162162- // Use IPv4 address
163163- host = "\(addr)"
185185+ // Use IPv4 address, strip any interface suffix (e.g., %en0)
186186+ var ipStr = "\(addr)"
187187+ if let percentIndex = ipStr.firstIndex(of: "%") {
188188+ ipStr = String(ipStr[..<percentIndex])
189189+ }
190190+ host = ipStr
164191 case .ipv6(let addr):
165165- // Use IPv6 address
166166- host = "[\(addr)]"
192192+ // Use IPv6 address, strip any interface suffix
193193+ var ipStr = "\(addr)"
194194+ if let percentIndex = ipStr.firstIndex(of: "%") {
195195+ ipStr = String(ipStr[..<percentIndex])
196196+ }
197197+ host = "[\(ipStr)]"
167198 @unknown default:
168199 break
169200 }
···172203 break
173204 }
174205175175- guard !host.isEmpty else { return }
206206+ guard !host.isEmpty else {
207207+ print("[mDNS] Failed to resolve host for '\(serviceName)'")
208208+ return
209209+ }
210210+211211+ print("[mDNS] Resolved '\(serviceName)' -> \(host):\(port)")
176212177213 let serverInfo = ServerInfo(
178214 name: serviceName,