implement basic renegotiation

This commit is contained in:
Bruno Windels 2022-04-21 10:10:49 +02:00
parent 82ffb557e5
commit 99769eb84e
2 changed files with 50 additions and 10 deletions

View file

@ -18,24 +18,24 @@ import {ObservableMap} from "../../observable/map/ObservableMap";
import {recursivelyAssign} from "../../utils/recursivelyAssign"; import {recursivelyAssign} from "../../utils/recursivelyAssign";
import {AsyncQueue} from "../../utils/AsyncQueue"; import {AsyncQueue} from "../../utils/AsyncQueue";
import {Disposables, IDisposable} from "../../utils/Disposables"; import {Disposables, IDisposable} from "../../utils/Disposables";
import type {Room} from "../room/Room";
import type {StateEvent} from "../storage/types";
import type {ILogItem} from "../../logging/types";
import type {TimeoutCreator, Timeout} from "../../platform/types/types";
import {WebRTC, PeerConnection, PeerConnectionHandler, TrackSender, TrackReceiver} from "../../platform/types/WebRTC"; import {WebRTC, PeerConnection, PeerConnectionHandler, TrackSender, TrackReceiver} from "../../platform/types/WebRTC";
import {MediaDevices, Track, AudioTrack, Stream} from "../../platform/types/MediaDevices"; import {MediaDevices, Track, AudioTrack, Stream} from "../../platform/types/MediaDevices";
import type {LocalMedia} from "./LocalMedia";
import { import {
SDPStreamMetadataKey, SDPStreamMetadataKey,
SDPStreamMetadataPurpose, SDPStreamMetadataPurpose,
EventType, EventType,
CallErrorCode, CallErrorCode,
} from "./callEventTypes"; } from "./callEventTypes";
import type {Room} from "../room/Room";
import type {StateEvent} from "../storage/types";
import type {ILogItem} from "../../logging/types";
import type {TimeoutCreator, Timeout} from "../../platform/types/types";
import type {LocalMedia} from "./LocalMedia";
import type { import type {
MCallBase, MCallBase,
MCallInvite, MCallInvite,
MCallNegotiate,
MCallAnswer, MCallAnswer,
MCallSDPStreamMetadataChanged, MCallSDPStreamMetadataChanged,
MCallCandidates, MCallCandidates,
@ -265,6 +265,9 @@ export class PeerCall implements IDisposable {
case EventType.Answer: case EventType.Answer:
await this.handleAnswer(message.content, partyId, log); await this.handleAnswer(message.content, partyId, log);
break; break;
case EventType.Negotiate:
await this.handleRemoteNegotiate(message.content, partyId, log);
break;
case EventType.Candidates: case EventType.Candidates:
await this.handleRemoteIceCandidates(message.content, partyId, log); await this.handleRemoteIceCandidates(message.content, partyId, log);
break; break;
@ -341,10 +344,10 @@ export class PeerCall implements IDisposable {
await this.sendSignallingMessage({type: EventType.Invite, content}, log); await this.sendSignallingMessage({type: EventType.Invite, content}, log);
this.setState(CallState.InviteSent, log); this.setState(CallState.InviteSent, log);
} else if (this._state === CallState.Connected || this._state === CallState.Connecting) { } else if (this._state === CallState.Connected || this._state === CallState.Connecting) {
log.log("would send renegotiation now but not implemented");
// send Negotiate message // send Negotiate message
//await this.sendSignallingMessage({type: EventType.Invite, content}); content.description = content.offer;
//this.setState(CallState.InviteSent); delete content.offer;
await this.sendSignallingMessage({type: EventType.Negotiate, content}, log);
} }
} finally { } finally {
this.makingOffer = false; this.makingOffer = false;
@ -497,6 +500,36 @@ export class PeerCall implements IDisposable {
} }
} }
private async handleRemoteNegotiate(content: MCallNegotiate<MCallBase>, partyId: PartyId, log: ILogItem): Promise<void> {
if (this._state !== CallState.Connected) {
log.log({l: `Ignoring renegotiate because not connected`, status: this._state});
return;
}
if (this.opponentPartyId !== partyId) {
log.log(`Ignoring answer: we already have an answer/reject from ${this.opponentPartyId}`);
return;
}
const sdpStreamMetadata = content[SDPStreamMetadataKey];
if (sdpStreamMetadata) {
this.updateRemoteSDPStreamMetadata(sdpStreamMetadata, log);
} else {
log.log(`Did not get any SDPStreamMetadata! Can not send/receive multiple streams`);
}
try {
await this.peerConnection.setRemoteDescription(content.description);
} catch (e) {
await log.wrap(`Failed to set remote description`, log => {
log.catch(e);
this.terminate(CallParty.Local, CallErrorCode.SetRemoteDescription, log);
});
return;
}
}
private handleIceGatheringState(state: RTCIceGatheringState, log: ILogItem) { private handleIceGatheringState(state: RTCIceGatheringState, log: ILogItem) {
if (state === 'complete' && !this.sentEndOfCandidates) { if (state === 'complete' && !this.sentEndOfCandidates) {
// If we didn't get an empty-string candidate to signal the end of candidates, // If we didn't get an empty-string candidate to signal the end of candidates,

View file

@ -97,6 +97,12 @@ export type MCallInvite<Base extends MCallBase> = Base & {
[SDPStreamMetadataKey]: SDPStreamMetadata; [SDPStreamMetadataKey]: SDPStreamMetadata;
} }
export type MCallNegotiate<Base extends MCallBase> = Base & {
description: SessionDescription;
lifetime: number;
[SDPStreamMetadataKey]: SDPStreamMetadata;
}
export type MCallSDPStreamMetadataChanged<Base extends MCallBase> = Base & { export type MCallSDPStreamMetadataChanged<Base extends MCallBase> = Base & {
[SDPStreamMetadataKey]: SDPStreamMetadata; [SDPStreamMetadataKey]: SDPStreamMetadata;
} }
@ -213,6 +219,7 @@ export enum CallErrorCode {
export type SignallingMessage<Base extends MCallBase> = export type SignallingMessage<Base extends MCallBase> =
{type: EventType.Invite, content: MCallInvite<Base>} | {type: EventType.Invite, content: MCallInvite<Base>} |
{type: EventType.Negotiate, content: MCallNegotiate<Base>} |
{type: EventType.Answer, content: MCallAnswer<Base>} | {type: EventType.Answer, content: MCallAnswer<Base>} |
{type: EventType.SDPStreamMetadataChanged | EventType.SDPStreamMetadataChangedPrefix, content: MCallSDPStreamMetadataChanged<Base>} | {type: EventType.SDPStreamMetadataChanged | EventType.SDPStreamMetadataChangedPrefix, content: MCallSDPStreamMetadataChanged<Base>} |
{type: EventType.Candidates, content: MCallCandidates<Base>} | {type: EventType.Candidates, content: MCallCandidates<Base>} |