fix: normalize discovered IPv4 Cast receiver addresses

This commit is contained in:
2026-10-24 23:44:57 +02:00
parent f6fe617d92
commit 2391dadc75
3 changed files with 21 additions and 1 deletions
+2
View File
@@ -10,6 +10,8 @@ A requested change of media, playback state, position, or quality that may still
**Cast playback transition**:
A playback transition that transfers playback between this Mac and a Cast receiver. Connection alone does not transfer playback; the destination must acknowledge the handoff, and interruption must preserve the latest playback intent and acknowledged position.
Discovery supplies receiver addresses to both Network.framework and the native media relay's POSIX resolver. IPv4 addresses must omit interface scope suffixes; IPv6 addresses retain their scopes.
**Playback intent**:
The user's latest requested playing or paused state, which can differ from the state playback has acknowledged.
+10
View File
@@ -412,6 +412,16 @@ struct CastSessionCheck {
let fallbackID = discovery.devices.first { $0.name == prefix + "-fallback" }!.id
let device = ownDevices()[0]
require(device.port == second.port?.rawValue, "Discovery preserves the advertised Cast port")
for device in discovery.devices {
guard case .ipv4 = NWEndpoint.Host(device.host) else { continue }
var hints = addrinfo()
hints.ai_family = AF_INET
hints.ai_socktype = SOCK_DGRAM
var addresses: UnsafeMutablePointer<addrinfo>?
let result = getaddrinfo(device.host, "8009", &hints, &addresses)
if let addresses { freeaddrinfo(addresses) }
require(result == 0, "Discovered IPv4 receiver resolves through the native relay's POSIX API")
}
let connection = NWConnection(host: NWEndpoint.Host(device.host),
port: NWEndpoint.Port(rawValue: device.port)!, using: .tcp)
defer { connection.cancel() }
+9 -1
View File
@@ -115,9 +115,17 @@ final class CastDiscovery: ObservableObject {
let value = String(data: data, encoding: .utf8), !value.isEmpty else { return nil }
return value
}
// Network.framework scopes IPv4 to an interface; POSIX getaddrinfo
// rejects that suffix. IPv6 scope identifiers must remain intact.
let address: String
if case .ipv4 = host {
address = String(host.debugDescription.prefix { $0 != "%" })
} else {
address = host.debugDescription
}
resolved[endpoint] = CastDevice(id: text("id") ?? domain + type + name,
name: text("fn") ?? name,
host: host.debugDescription, port: port.rawValue)
host: address, port: port.rawValue)
}
services[endpoint]?.timeout?.cancel()
services[endpoint]?.timeout = nil