|
| 1 | +// |
| 2 | +// PlaceServer+Media.swift |
| 3 | +// allonet2 |
| 4 | +// |
| 5 | +// Created by Nevyn Bengtsson on 2025-08-28. |
| 6 | +// |
| 7 | + |
| 8 | +import Foundation |
| 9 | + |
| 10 | +extension PlaceServer |
| 11 | +{ |
| 12 | + // TODO: Forward audio based on interactions instead of doing everyone-to-everyone |
| 13 | + /// A new incoming stream arrived. Forward it to everyone. |
| 14 | + internal func handle(incoming stream: MediaStream, from sender: ConnectedClient) |
| 15 | + { |
| 16 | + for (cid, receiver) in self.clients |
| 17 | + { |
| 18 | + do { |
| 19 | + try start(forwarding: stream, from: sender, to: receiver) |
| 20 | + } catch let e { |
| 21 | + print("FAILED to forward media stream \(sender.cid).\(stream.mediaId) -> \(receiver.cid): \(e)") |
| 22 | + } |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + /// A new client connected. Forward every existing stream to it. |
| 27 | + internal func start(forwardingTo receiver: ConnectedClient) |
| 28 | + { |
| 29 | + for sender in clients.values where sender !== receiver |
| 30 | + { |
| 31 | + for stream in sender.session.incomingStreams.values |
| 32 | + { |
| 33 | + do { |
| 34 | + try self.start(forwarding: stream, from: sender, to: receiver) |
| 35 | + } catch let e { |
| 36 | + print("FAILED to do initial forwarding of media stream \(sender.cid).\(stream.mediaId) -> \(receiver.cid): \(e)") |
| 37 | + } |
| 38 | + } |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + /// Perform the |
| 43 | + internal func start(forwarding stream: MediaStream, from sender: ConnectedClient, to receiver: ConnectedClient) throws |
| 44 | + { |
| 45 | + // Don't forward the stream back to its source |
| 46 | + if sender.session.clientId == receiver.session.clientId { return } |
| 47 | + |
| 48 | + let transport = receiver.session.transport |
| 49 | + |
| 50 | + let id = SFUIdentifier(fromMediaId: stream.mediaId, toClient: receiver.cid) |
| 51 | + if let existingSfu = sfus[id] |
| 52 | + { |
| 53 | + return |
| 54 | + } |
| 55 | + |
| 56 | + let sfu = try transportClass.forward(mediaStream: stream, to: transport) |
| 57 | + sfus[id] = sfu |
| 58 | + } |
| 59 | + |
| 60 | + internal func stop(forwarding stream: MediaStream, to client: ConnectedClient) |
| 61 | + { |
| 62 | + stop(forwarding: stream, toClientId: client.cid) |
| 63 | + } |
| 64 | + internal func stop(forwarding stream: MediaStream, toClientId: ClientId) |
| 65 | + { |
| 66 | + let id = SFUIdentifier(fromMediaId: stream.mediaId, toClient: toClientId) |
| 67 | + guard let sfu = sfus[id] else { return } |
| 68 | + sfu.stop() |
| 69 | + sfus[id] = nil |
| 70 | + } |
| 71 | + |
| 72 | + public func stop(forwarding stream: MediaStream) |
| 73 | + { |
| 74 | + for id in sfus.keys |
| 75 | + { |
| 76 | + if id.fromMediaId == stream.mediaId |
| 77 | + { |
| 78 | + self.stop(forwarding: stream, toClientId: id.toClient) |
| 79 | + } |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + internal func stop(forwarding client: ConnectedClient) |
| 84 | + { |
| 85 | + for stream in client.session.incomingStreams.values |
| 86 | + { |
| 87 | + self.stop(forwarding: stream) |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + internal struct SFUIdentifier: Equatable, Hashable |
| 92 | + { |
| 93 | + let fromMediaId: String |
| 94 | + let toClient: ClientId |
| 95 | + } |
| 96 | +} |
0 commit comments