Archived
2
0

server -> client signaling

This commit is contained in:
Craig
2020-02-12 23:13:33 +00:00
parent 1f8b4d44c7
commit d5bff32302
17 changed files with 181 additions and 286 deletions

View File

@ -2,15 +2,7 @@ import EventEmitter from 'eventemitter3'
import { OPCODE } from './data'
import { EVENT, WebSocketEvents } from './events'
import {
WebSocketMessages,
WebSocketPayloads,
IdentityPayload,
SignalPayload,
MemberListPayload,
MemberPayload,
ControlPayload,
} from './messages'
import { WebSocketMessages, WebSocketPayloads, SignalProvidePayload } from './messages'
export interface BaseEvents {
info: (...message: any[]) => void
@ -26,6 +18,11 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
protected _timeout?: NodeJS.Timeout
protected _username?: string
protected _state: RTCIceConnectionState = 'disconnected'
protected _id = ''
get id() {
return this._id
}
get supported() {
return typeof RTCPeerConnection !== 'undefined' && typeof RTCPeerConnection.prototype.addTransceiver !== 'undefined'
@ -93,6 +90,8 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
}
this._state = 'disconnected'
this._username = undefined
this._id = ''
}
public sendData(event: 'wheel' | 'mousemove', data: { x: number; y: number }): void
@ -157,7 +156,7 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
this._ws!.send(JSON.stringify({ event, ...payload }))
}
public createPeer() {
public createPeer(sdp: string) {
this.emit('debug', `creating peer`)
if (!this.socketOpen) {
this.emit(
@ -175,18 +174,6 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
this._peer = new RTCPeerConnection()
this._peer.onicecandidate = event => {
if (event.candidate === null && this._peer!.localDescription) {
this.emit('debug', `sending event '${EVENT.SIGNAL.PROVIDE}' with payload`, this._peer!.localDescription.sdp)
this._ws!.send(
JSON.stringify({
event: EVENT.SIGNAL.PROVIDE,
sdp: this._peer!.localDescription.sdp,
}),
)
}
}
this._peer.onconnectionstatechange = event => {
this.emit('debug', `peer connection state chagned`, this._peer ? this._peer.connectionState : undefined)
}
@ -227,43 +214,40 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
this._channel.onmessage = this.onData.bind(this)
this._channel.onclose = this.onDisconnected.bind(this, new Error('peer data channel closed'))
this._peer.setRemoteDescription({ type: 'offer', sdp })
this._peer
.createOffer()
.then(d => this._peer!.setLocalDescription(d))
.createAnswer()
.then(d => {
this._peer!.setLocalDescription(d)
this._ws!.send(
JSON.stringify({
event: EVENT.SIGNAL.ANSWER,
sdp: d.sdp,
username: this._username,
}),
)
})
.catch(err => this.emit('error', err))
}
private setRemoteDescription(payload: SignalPayload) {
if (this.peerConnected) {
this.emit('warn', `attempting to set remote description while peer connected`, payload)
return
}
this.emit('debug', `remote description recieved: \n`, payload.sdp)
this._peer!.setRemoteDescription({ type: 'answer', sdp: payload.sdp })
}
private onMessage(e: MessageEvent) {
const { event, ...payload } = JSON.parse(e.data) as WebSocketMessages
this.emit('debug', `received websocket event ${event} ${payload ? `with payload: ` : ''}`, payload)
switch (event) {
case EVENT.IDENTITY.PROVIDE:
this[EVENT.IDENTITY.PROVIDE](payload as IdentityPayload)
this.createPeer()
break
case EVENT.SIGNAL.ANSWER:
this.setRemoteDescription(payload as SignalPayload)
break
default:
// @ts-ignore
if (typeof this[event] === 'function') {
// @ts-ignore
this[event](payload)
} else {
this[EVENT.MESSAGE](event, payload)
}
if (event === EVENT.SIGNAL.PROVIDE) {
const { sdp, id } = payload as SignalProvidePayload
this._id = id
this.createPeer(sdp)
return
}
// @ts-ignore
if (typeof this[event] === 'function') {
// @ts-ignore
this[event](payload)
} else {
this[EVENT.MESSAGE](event, payload)
}
}
@ -295,14 +279,6 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
return
}
this.emit('debug', `sending event '${EVENT.IDENTITY.DETAILS}' with payload`, { username: this._username })
this._ws!.send(
JSON.stringify({
event: EVENT.IDENTITY.DETAILS,
username: this._username,
}),
)
this.emit('debug', `connected`)
this[EVENT.CONNECTED]()
}
@ -330,5 +306,4 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
protected abstract [EVENT.DISCONNECTED](reason?: Error): void
protected abstract [EVENT.TRACK](event: RTCTrackEvent): void
protected abstract [EVENT.DATA](data: any): void
protected abstract [EVENT.IDENTITY.PROVIDE](payload: IdentityPayload): void
}

View File

@ -15,10 +15,6 @@ export const EVENT = {
ANSWER: 'signal/answer',
PROVIDE: 'signal/provide',
},
IDENTITY: {
PROVIDE: 'identity/provide',
DETAILS: 'identity/details',
},
MEMBER: {
LIST: 'member/list',
CONNECTED: 'member/connected',
@ -59,7 +55,6 @@ export type Events = typeof EVENT
export type WebSocketEvents =
| SystemEvents
| ControlEvents
| IdentityEvents
| MemberEvents
| SignalEvents
| ChatEvents
@ -74,7 +69,6 @@ export type ControlEvents =
| typeof EVENT.CONTROL.CLIPBOARD
export type SystemEvents = typeof EVENT.SYSTEM.DISCONNECT
export type IdentityEvents = typeof EVENT.IDENTITY.PROVIDE | typeof EVENT.IDENTITY.DETAILS
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
export type ChatEvents = typeof EVENT.CHAT.MESSAGE | typeof EVENT.CHAT.EMOTE

View File

@ -7,7 +7,7 @@ import { accessor } from '~/store'
import {
DisconnectPayload,
IdentityPayload,
SignalProvidePayload,
MemberListPayload,
MemberDisconnectPayload,
MemberPayload,
@ -28,10 +28,6 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
private $vue!: Vue
private $accessor!: typeof accessor
private get id() {
return this.$accessor.user.id
}
init(vue: Vue) {
this.$vue = vue
this.$accessor = vue.$accessor
@ -72,6 +68,7 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
}
protected [EVENT.CONNECTED]() {
this.$accessor.user.setMember(this.id)
this.$accessor.setConnected(true)
this.$accessor.setConnected(true)
@ -121,13 +118,6 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
})
}
/////////////////////////////
// Identity Events
/////////////////////////////
protected [EVENT.IDENTITY.PROVIDE]({ id }: IdentityPayload) {
this.$accessor.user.setMember(id)
}
/////////////////////////////
// Member Events
/////////////////////////////

View File

@ -3,7 +3,6 @@ import {
WebSocketEvents,
SystemEvents,
ControlEvents,
IdentityEvents,
MemberEvents,
SignalEvents,
ChatEvents,
@ -14,8 +13,8 @@ import { Member, ScreenConfigurations, ScreenResolution } from './types'
export type WebSocketMessages =
| WebSocketMessage
| IdentityMessage
| SignalMessage
| SignalProvideMessage
| SignalAnswerMessage
| MemberListMessage
| MembeConnectMessage
| MembeDisconnectMessage
@ -25,8 +24,8 @@ export type WebSocketMessages =
| ChatMessage
export type WebSocketPayloads =
| IdentityPayload
| SignalPayload
| SignalProvidePayload
| SignalAnswerPayload
| MemberListPayload
| Member
| ControlPayload
@ -53,26 +52,25 @@ export interface DisconnectPayload {
message: string
}
/*
IDENTITY MESSAGES/PAYLOADS
*/
// identity/provide
export interface IdentityMessage extends WebSocketMessage, IdentityPayload {
event: typeof EVENT.IDENTITY.PROVIDE
}
export interface IdentityPayload {
id: string
}
/*
SIGNAL MESSAGES/PAYLOADS
*/
// signal/provide
export interface SignalProvideMessage extends WebSocketMessage, SignalProvidePayload {
event: typeof EVENT.SIGNAL.PROVIDE
}
export interface SignalProvidePayload {
id: string
sdp: string
}
// signal/answer
export interface SignalMessage extends WebSocketMessage, SignalPayload {
export interface SignalAnswerMessage extends WebSocketMessage, SignalAnswerPayload {
event: typeof EVENT.SIGNAL.ANSWER
}
export interface SignalPayload {
export interface SignalAnswerPayload {
sdp: string
username: string
}
/*