Archived
2
0

Automatic SDP negotiation (#103)

This commit is contained in:
Miroslav Šedivý
2021-12-02 23:43:36 +01:00
parent a8542bc222
commit fed6ddbd4e
13 changed files with 232 additions and 47 deletions

View File

@ -2,7 +2,14 @@ import EventEmitter from 'eventemitter3'
import { OPCODE } from './data'
import { EVENT, WebSocketEvents } from './events'
import { WebSocketMessages, WebSocketPayloads, SignalProvidePayload, SignalCandidatePayload } from './messages'
import {
WebSocketMessages,
WebSocketPayloads,
SignalProvidePayload,
SignalCandidatePayload,
SignalOfferPayload,
SignalAnswerMessage,
} from './messages'
export interface BaseEvents {
info: (...message: any[]) => void
@ -180,7 +187,7 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
this._ws!.send(JSON.stringify({ event, ...payload }))
}
public async createPeer(sdp: string, lite: boolean, servers: RTCIceServer[]) {
public async createPeer(lite: boolean, servers: RTCIceServer[]) {
this.emit('debug', `creating peer`)
if (!this.socketOpen) {
this.emit(
@ -243,13 +250,32 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
}
this._peer.ontrack = this.onTrack.bind(this)
this._peer.addTransceiver('audio', { direction: 'recvonly' })
this._peer.addTransceiver('video', { direction: 'recvonly' })
this._peer.onnegotiationneeded = async () => {
this.emit('warn', `negotiation is needed`)
const d = await this._peer!.createOffer()
this._peer!.setLocalDescription(d)
this._ws!.send(
JSON.stringify({
event: EVENT.SIGNAL.OFFER,
sdp: d.sdp,
}),
)
}
this._channel = this._peer.createDataChannel('data')
this._channel.onerror = this.onError.bind(this)
this._channel.onmessage = this.onData.bind(this)
this._channel.onclose = this.onDisconnected.bind(this, new Error('peer data channel closed'))
}
public async setRemoteOffer(sdp: string) {
if (!this._peer) {
this.emit('warn', `attempting to set remote offer while disconnected`)
return
}
this._peer.setRemoteDescription({ type: 'offer', sdp })
@ -274,7 +300,16 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
}
}
private onMessage(e: MessageEvent) {
public async setRemoteAnswer(sdp: string) {
if (!this._peer) {
this.emit('warn', `attempting to set remote answer while disconnected`)
return
}
this._peer.setRemoteDescription({ type: 'answer', sdp })
}
private async onMessage(e: MessageEvent) {
const { event, ...payload } = JSON.parse(e.data) as WebSocketMessages
this.emit('debug', `received websocket event ${event} ${payload ? `with payload: ` : ''}`, payload)
@ -282,7 +317,20 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
if (event === EVENT.SIGNAL.PROVIDE) {
const { sdp, lite, ice, id } = payload as SignalProvidePayload
this._id = id
this.createPeer(sdp, lite, ice)
await this.createPeer(lite, ice)
await this.setRemoteOffer(sdp)
return
}
if (event === EVENT.SIGNAL.OFFER) {
const { sdp } = payload as SignalOfferPayload
await this.setRemoteOffer(sdp)
return
}
if (event === EVENT.SIGNAL.ANSWER) {
const { sdp } = payload as SignalAnswerMessage
await this.setRemoteAnswer(sdp)
return
}

View File

@ -14,6 +14,7 @@ export const EVENT = {
ERROR: 'system/error',
},
SIGNAL: {
OFFER: 'signal/offer',
ANSWER: 'signal/answer',
PROVIDE: 'signal/provide',
CANDIDATE: 'signal/candidate',
@ -81,7 +82,13 @@ export type ControlEvents =
export type SystemEvents = typeof EVENT.SYSTEM.DISCONNECT
export type MemberEvents = typeof EVENT.MEMBER.LIST | typeof EVENT.MEMBER.CONNECTED | typeof EVENT.MEMBER.DISCONNECTED
export type SignalEvents = typeof EVENT.SIGNAL.ANSWER | typeof EVENT.SIGNAL.PROVIDE | typeof EVENT.SIGNAL.CANDIDATE
export type SignalEvents =
| typeof EVENT.SIGNAL.OFFER
| typeof EVENT.SIGNAL.ANSWER
| typeof EVENT.SIGNAL.PROVIDE
| typeof EVENT.SIGNAL.CANDIDATE
export type ChatEvents = typeof EVENT.CHAT.MESSAGE | typeof EVENT.CHAT.EMOTE
export type ScreenEvents = typeof EVENT.SCREEN.CONFIGURATIONS | typeof EVENT.SCREEN.RESOLUTION | typeof EVENT.SCREEN.SET

View File

@ -14,6 +14,7 @@ import { Member, ScreenConfigurations, ScreenResolution } from './types'
export type WebSocketMessages =
| WebSocketMessage
| SignalProvideMessage
| SignalOfferMessage
| SignalAnswerMessage
| SignalCandidateMessage
| MemberListMessage
@ -26,6 +27,7 @@ export type WebSocketMessages =
export type WebSocketPayloads =
| SignalProvidePayload
| SignalOfferPayload
| SignalAnswerPayload
| SignalCandidatePayload
| MemberListPayload
@ -74,6 +76,14 @@ export interface SignalProvidePayload {
sdp: string
}
// signal/offer
export interface SignalOfferMessage extends WebSocketMessage, SignalOfferPayload {
event: typeof EVENT.SIGNAL.OFFER
}
export interface SignalOfferPayload {
sdp: string
}
// signal/answer
export interface SignalAnswerMessage extends WebSocketMessage, SignalAnswerPayload {
event: typeof EVENT.SIGNAL.ANSWER