mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 21:38:15 +00:00
fix local cache loopback port
This commit is contained in:
parent
e7a80df7cc
commit
151ae3ca5b
4 changed files with 77 additions and 15 deletions
|
|
@ -335,29 +335,79 @@ final class ProgressiveHTTPRangeCacheServer {
|
|||
private var listener: NWListener?
|
||||
private var port: UInt16?
|
||||
private var sessions: [String: ProgressiveHTTPRangeCacheSession] = [:]
|
||||
private var startupContinuations: [CheckedContinuation<UInt16, Error>] = []
|
||||
|
||||
func localURL(for session: ProgressiveHTTPRangeCacheSession) throws -> URL {
|
||||
try startIfNeeded()
|
||||
func localURL(for session: ProgressiveHTTPRangeCacheSession) async throws -> URL {
|
||||
let assignedPort = try await startIfNeeded()
|
||||
sessions[session.id] = session
|
||||
guard let port,
|
||||
let url = URL(string: "http://127.0.0.1:\(port)/stream/\(session.id)") else {
|
||||
guard let url = URL(string: "http://127.0.0.1:\(assignedPort)/stream/\(session.id)") else {
|
||||
throw HTTPRangeCacheError.serverUnavailable
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
private func startIfNeeded() throws {
|
||||
guard listener == nil else {
|
||||
return
|
||||
private func startIfNeeded() async throws -> UInt16 {
|
||||
if let port, port > 0 {
|
||||
return port
|
||||
}
|
||||
|
||||
let listener = try NWListener(using: .tcp, on: .any)
|
||||
listener.newConnectionHandler = { [weak self] connection in
|
||||
self?.handle(connection)
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
queue.async { [weak self] in
|
||||
guard let self else {
|
||||
continuation.resume(throwing: HTTPRangeCacheError.serverUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
if let port = self.port, port > 0 {
|
||||
continuation.resume(returning: port)
|
||||
return
|
||||
}
|
||||
|
||||
self.startupContinuations.append(continuation)
|
||||
guard self.listener == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let listener = try NWListener(using: .tcp, on: .any)
|
||||
listener.newConnectionHandler = { [weak self] connection in
|
||||
self?.handle(connection)
|
||||
}
|
||||
listener.stateUpdateHandler = { [weak self] state in
|
||||
self?.handleListenerState(state)
|
||||
}
|
||||
self.listener = listener
|
||||
listener.start(queue: self.queue)
|
||||
} catch {
|
||||
self.finishStartup(with: .failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handleListenerState(_ state: NWListener.State) {
|
||||
switch state {
|
||||
case .ready:
|
||||
guard let rawPort = listener?.port?.rawValue, rawPort > 0 else {
|
||||
finishStartup(with: .failure(HTTPRangeCacheError.serverUnavailable))
|
||||
return
|
||||
}
|
||||
let assignedPort = UInt16(rawPort)
|
||||
port = assignedPort
|
||||
finishStartup(with: .success(assignedPort))
|
||||
case .failed(let error):
|
||||
finishStartup(with: .failure(error))
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func finishStartup(with result: Result<UInt16, Error>) {
|
||||
let continuations = startupContinuations
|
||||
startupContinuations.removeAll()
|
||||
continuations.forEach { continuation in
|
||||
continuation.resume(with: result)
|
||||
}
|
||||
listener.start(queue: queue)
|
||||
self.listener = listener
|
||||
self.port = listener.port.map { UInt16($0.rawValue) }
|
||||
}
|
||||
|
||||
private func handle(_ connection: NWConnection) {
|
||||
|
|
@ -449,6 +499,8 @@ final class ProgressiveHTTPRangeCacheServer {
|
|||
}
|
||||
}
|
||||
|
||||
extension ProgressiveHTTPRangeCacheServer: @unchecked Sendable {}
|
||||
|
||||
private extension NSLock {
|
||||
func withLock<T>(_ body: () -> T) -> T {
|
||||
lock()
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ final class VLCNativePlaybackBackend: NSObject, NativePlaybackBackend {
|
|||
contentLength: contentLength,
|
||||
durationProvider: { [weak self] in self?.duration ?? 0 }
|
||||
)
|
||||
let localURL = try ProgressiveHTTPRangeCacheServer.shared.localURL(for: session)
|
||||
let localURL = try await ProgressiveHTTPRangeCacheServer.shared.localURL(for: session)
|
||||
await MainActor.run {
|
||||
self.rangeCacheSession = session
|
||||
session.prefetch(aroundByteOffset: 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue