import Foundation
import IrdP2PSignaling
public enum SDPType: String, Sendable { case offer, answer }
public enum PeerConnectionState: Sendable, Equatable { case new, connecting, connected, disconnected, failed, closed }
public enum SignalingState: Sendable, Equatable { case stable, haveLocalOffer, haveRemoteOffer, other, closed }
/// Value events from a peer connection, safe to hop between actors.
public enum PeerConnectionEvent: Sendable, Equatable {
case iceCandidate(candidate: String, sdpMid: String?, sdpMLineIndex: Int?)
case iceGatheringComplete
case connectionState(PeerConnectionState)
case dataChannelOpen
case dataChannelClosed
case message(Data, isBinary: Bool)
case bufferedAmountLow
}
/// One WebRTC peer connection with a single negotiated, reliable, ordered data
/// channel (`id 0`, label `ird`) created on both sides up front.
public protocol PeerConnectionHandle: Sendable {
var events: AsyncStream<PeerConnectionEvent> { get }
/// Creates and applies a local offer; returns its SDP.
func createOffer(iceRestart: Bool) async throws -> String
/// Creates and applies a local answer to the current remote offer; returns its SDP.
func createAnswer() async throws -> String
func setRemoteDescription(_ type: SDPType, sdp: String) async throws
/// Rolls back a pending local offer (perfect-negotiation glare handling).
func rollback() async throws
func addIceCandidate(candidate: String, sdpMid: String?, sdpMLineIndex: Int?) async throws
func signalingState() async -> SignalingState
func send(text: String) async throws
func send(data: Data) async throws
func bufferedAmount() async -> Int
func close() async
}
/// Creates peer connections; the WebRTC-backed factory is the default, the in-memory
/// one pairs handles inside one process for tests.
public protocol PeerConnectionFactory: Sendable {
func makePeerConnection(ice: IceConfiguration) async throws -> any PeerConnectionHandle
/// What rooms call, passing `RoomOptions.continualGathering`. Factories that do not
/// gather ICE candidates need not implement it: the default ignores the flag.
func makePeerConnection(ice: IceConfiguration, continualGathering: Bool) async throws -> any PeerConnectionHandle
}
extension PeerConnectionFactory {
public func makePeerConnection(ice: IceConfiguration, continualGathering: Bool) async throws -> any PeerConnectionHandle {
try await makePeerConnection(ice: ice)
}
}