summary refs log tree commit diff
path: root/webrtc/src/opcodes
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--webrtc/src/opcodes/BackendVersion.ts6
-rw-r--r--webrtc/src/opcodes/Connect.ts40
-rw-r--r--webrtc/src/opcodes/Heartbeat.ts13
-rw-r--r--webrtc/src/opcodes/Identify.ts87
-rw-r--r--webrtc/src/opcodes/Resume.ts24
-rw-r--r--webrtc/src/opcodes/SelectProtocol.ts250
-rw-r--r--webrtc/src/opcodes/Speaking.ts25
-rw-r--r--webrtc/src/opcodes/Version.ts14
-rw-r--r--webrtc/src/opcodes/Video.ts118
-rw-r--r--webrtc/src/opcodes/index.ts52
10 files changed, 252 insertions, 377 deletions
diff --git a/webrtc/src/opcodes/BackendVersion.ts b/webrtc/src/opcodes/BackendVersion.ts
new file mode 100644

index 00000000..b4b61c7d --- /dev/null +++ b/webrtc/src/opcodes/BackendVersion.ts
@@ -0,0 +1,6 @@ +import { Payload, Send, WebSocket } from "@fosscord/gateway"; +import { VoiceOPCodes } from "../util"; + +export async function onBackendVersion(this: WebSocket, data: Payload) { + await Send(this, { op: VoiceOPCodes.VOICE_BACKEND_VERSION, d: { voice: "0.8.43", rtc_worker: "0.3.26" } }); +} \ No newline at end of file diff --git a/webrtc/src/opcodes/Connect.ts b/webrtc/src/opcodes/Connect.ts deleted file mode 100644
index 1f874a44..00000000 --- a/webrtc/src/opcodes/Connect.ts +++ /dev/null
@@ -1,40 +0,0 @@ -import { WebSocket } from "@fosscord/gateway"; -import { Payload } from "./index"; -import { Server } from "../Server" - -/* -Sent by client: - -{ - "op": 12, - "d": { - "audio_ssrc": 0, - "video_ssrc": 0, - "rtx_ssrc": 0, - "streams": [ - { - "type": "video", - "rid": "100", - "ssrc": 0, - "active": false, - "quality": 100, - "rtx_ssrc": 0, - "max_bitrate": 2500000, - "max_framerate": 20, - "max_resolution": { - "type": "fixed", - "width": 1280, - "height": 720 - } - } - ] - } -} -*/ - -export async function onConnect(this: Server, socket: WebSocket, data: Payload) { - socket.send(JSON.stringify({ //what is op 15? - op: 15, - d: { any: 100 } - })) -} \ No newline at end of file diff --git a/webrtc/src/opcodes/Heartbeat.ts b/webrtc/src/opcodes/Heartbeat.ts
index 47f33f76..1b6c5bcd 100644 --- a/webrtc/src/opcodes/Heartbeat.ts +++ b/webrtc/src/opcodes/Heartbeat.ts
@@ -1,8 +1,9 @@ -import { WebSocket } from "@fosscord/gateway"; -import { Payload } from "./index"; -import { setHeartbeat } from "../util"; -import { Server } from "../Server" +import { CLOSECODES, Payload, Send, setHeartbeat, WebSocket } from "@fosscord/gateway"; +import { VoiceOPCodes } from "../util"; -export async function onHeartbeat(this: Server, socket: WebSocket, data: Payload) { - await setHeartbeat(socket, data.d); +export async function onHeartbeat(this: WebSocket, data: Payload) { + setHeartbeat(this); + if (isNaN(data.d)) return this.close(CLOSECODES.Decode_error); + + await Send(this, { op: VoiceOPCodes.HEARTBEAT_ACK, d: data.d }); } \ No newline at end of file diff --git a/webrtc/src/opcodes/Identify.ts b/webrtc/src/opcodes/Identify.ts
index 210b5041..4ecec949 100644 --- a/webrtc/src/opcodes/Identify.ts +++ b/webrtc/src/opcodes/Identify.ts
@@ -1,50 +1,50 @@ -import { WebSocket, CLOSECODES } from "@fosscord/gateway"; -import { Payload } from "./index"; -import { VoiceOPCodes, Session, User, Guild } from "@fosscord/util"; -import { Server } from "../Server"; +import { CLOSECODES, Payload, Send, WebSocket } from "@fosscord/gateway"; +import { validateSchema, VoiceIdentifySchema, VoiceState } from "@fosscord/util"; +import { endpoint, getClients, VoiceOPCodes } from "@fosscord/webrtc"; +import SemanticSDP from "semantic-sdp"; +const defaultSDP = require("../../../assets/sdp.json"); -export interface IdentifyPayload extends Payload { - d: { - server_id: string, //guild id - session_id: string, //gateway session - streams: Array<{ - type: string, - rid: string, //number - quality: number, - }>, - token: string, //voice_states token - user_id: string, - video: boolean, - }; -} +export async function onIdentify(this: WebSocket, data: Payload) { + clearTimeout(this.readyTimeout); + const { server_id, user_id, session_id, token, streams, video } = validateSchema("VoiceIdentifySchema", data.d) as VoiceIdentifySchema; -export async function onIdentify(this: Server, socket: WebSocket, data: Payload) { + const voiceState = await VoiceState.findOne({ guild_id: server_id, user_id, token, session_id }); + if (!voiceState) return this.close(CLOSECODES.Authentication_failed); - const session = await Session.findOneOrFail( - { session_id: data.d.session_id, }, - { - where: { user_id: data.d.user_id }, - relations: ["user"] - } - ); - const user = session.user; - const guild = await Guild.findOneOrFail({ id: data.d.server_id }, { relations: ["members"] }); + this.user_id = user_id; + this.session_id = session_id; + const sdp = SemanticSDP.SDPInfo.expand(defaultSDP); + sdp.setDTLS(SemanticSDP.DTLSInfo.expand({ setup: "actpass", hash: "sha-256", fingerprint: endpoint.getDTLSFingerprint() })); + + this.client = { + websocket: this, + out: { + tracks: new Map() + }, + in: { + audio_ssrc: 0, + video_ssrc: 0, + rtx_ssrc: 0 + }, + sdp, + channel_id: voiceState.channel_id + }; - if (!guild.members.find(x => x.id === user.id)) - return socket.close(CLOSECODES.Invalid_intent); + const clients = getClients(voiceState.channel_id)!; + clients.add(this.client); - var transport = this.mediasoupTransports[0] || await this.mediasoupRouters[0].createWebRtcTransport({ - listenIps: [{ ip: "10.22.64.146" }], - enableUdp: true, + this.on("close", () => { + clients.delete(this.client!); }); - socket.send(JSON.stringify({ + await Send(this, { op: VoiceOPCodes.READY, d: { - streams: data.d.streams ? [...data.d.streams.map(x => ({ ...x, rtx_ssrc: Math.floor(Math.random() * 10000), ssrc: Math.floor(Math.random() * 10000), active: true, }))] : undefined, - ssrc: Math.floor(Math.random() * 10000), - ip: transport.iceCandidates[0].ip, - port: transport.iceCandidates[0].port, + streams: [ + // { type: "video", ssrc: this.ssrc + 1, rtx_ssrc: this.ssrc + 2, rid: "100", quality: 100, active: false } + ], + ssrc: -1, + port: endpoint.getLocalPort(), modes: [ "aead_aes256_gcm_rtpsize", "aead_aes256_gcm", @@ -53,11 +53,8 @@ export async function onIdentify(this: Server, socket: WebSocket, data: Payload) "xsalsa20_poly1305_suffix", "xsalsa20_poly1305" ], - experiments: [ - "bwe_conservative_link_estimate", - "bwe_remote_locus_client", - "fixed_keyframe_interval" - ] - }, - })); + ip: "127.0.0.1", + experiments: [] + } + }); } \ No newline at end of file diff --git a/webrtc/src/opcodes/Resume.ts b/webrtc/src/opcodes/Resume.ts deleted file mode 100644
index 856b550c..00000000 --- a/webrtc/src/opcodes/Resume.ts +++ /dev/null
@@ -1,24 +0,0 @@ -import { CLOSECODES, WebSocket } from "@fosscord/gateway"; -import { Payload } from "./index"; -import { Server } from "../Server" -import { Guild, Session, VoiceOPCodes } from "@fosscord/util"; - -export async function onResume(this: Server, socket: WebSocket, data: Payload) { - const session = await Session.findOneOrFail( - { session_id: data.d.session_id, }, - { - where: { user_id: data.d.user_id }, - relations: ["user"] - } - ); - const user = session.user; - const guild = await Guild.findOneOrFail({ id: data.d.server_id }, { relations: ["members"] }); - - if (!guild.members.find(x => x.id === user.id)) - return socket.close(CLOSECODES.Invalid_intent); - - socket.send(JSON.stringify({ - op: VoiceOPCodes.RESUMED, - d: null, - })) -} \ No newline at end of file diff --git a/webrtc/src/opcodes/SelectProtocol.ts b/webrtc/src/opcodes/SelectProtocol.ts
index 71772454..c660c8e2 100644 --- a/webrtc/src/opcodes/SelectProtocol.ts +++ b/webrtc/src/opcodes/SelectProtocol.ts
@@ -1,206 +1,46 @@ -import { WebSocket } from "@fosscord/gateway"; -import { Payload } from "./index"; -import { VoiceOPCodes } from "@fosscord/util"; -import { Server } from "../Server"; -import * as mediasoup from "mediasoup"; -import { RtpCodecCapability } from "mediasoup/node/lib/RtpParameters"; -import * as sdpTransform from 'sdp-transform'; -import sodium from "libsodium-wrappers"; - -export interface CodecPayload { - name: string, - type: "audio" | "video", - priority: number, - payload_type: number, - rtx_payload_type: number | null, -} - -export interface SelectProtocolPayload extends Payload { - d: { - codecs: Array<CodecPayload>, - data: string, // SDP if webrtc - protocol: string, - rtc_connection_id: string, - sdp?: string, // same as data - }; -} - -/* - - Sent by client: -{ - "op": 1, - "d": { - "protocol": "webrtc", - "data": " - a=extmap-allow-mixed - a=ice-ufrag:vNxb - a=ice-pwd:tZvpbVPYEKcnW0gGRPq0OOnh - a=ice-options:trickle - a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level - a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time - a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 - a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid - a=rtpmap:111 opus/48000/2 - a=extmap:14 urn:ietf:params:rtp-hdrext:toffset - a=extmap:13 urn:3gpp:video-orientation - a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay - a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type - a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing - a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space - a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id - a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id - a=rtpmap:96 VP8/90000 - a=rtpmap:97 rtx/90000 - ", - "codecs": [ - { - "name": "opus", - "type": "audio", - "priority": 1000, - "payload_type": 111, - "rtx_payload_type": null - }, - { - "name": "H264", - "type": "video", - "priority": 1000, - "payload_type": 102, - "rtx_payload_type": 121 - }, - { - "name": "VP8", - "type": "video", - "priority": 2000, - "payload_type": 96, - "rtx_payload_type": 97 - }, - { - "name": "VP9", - "type": "video", - "priority": 3000, - "payload_type": 98, - "rtx_payload_type": 99 - } - ], - "rtc_connection_id": "3faa0b80-b3e2-4bae-b291-273801fbb7ab" - } -} -*/ - -export async function onSelectProtocol(this: Server, socket: WebSocket, data: Payload) { - if (data.d.sdp) { - const rtpCapabilities = this.mediasoupRouters[0].rtpCapabilities; - const codecs = rtpCapabilities.codecs as RtpCodecCapability[]; - - const transport = this.mediasoupTransports[0]; //whatever - - const res = sdpTransform.parse(data.d.sdp); - - const videoCodec = this.mediasoupRouters[0].rtpCapabilities.codecs!.find((x: any) => x.kind === "video"); - const audioCodec = this.mediasoupRouters[0].rtpCapabilities.codecs!.find((x: any) => x.kind === "audio"); - - const producer = this.mediasoupProducers[0] || await transport.produce({ - kind: "audio", - rtpParameters: { - mid: "audio", - codecs: [{ - clockRate: audioCodec!.clockRate, - payloadType: audioCodec!.preferredPayloadType as number, - mimeType: audioCodec!.mimeType, - channels: audioCodec?.channels, - }], - headerExtensions: res.ext?.map(x => ({ - id: x.value, - uri: x.uri, - })), - }, - paused: false, - }); - - console.log("can consume: " + this.mediasoupRouters[0].canConsume({ producerId: producer.id, rtpCapabilities: rtpCapabilities })); - - const consumer = this.mediasoupConsumers[0] || await transport.consume({ - producerId: producer.id, - paused: false, - rtpCapabilities, - }); - - transport.connect({ - dtlsParameters: { - fingerprints: transport.dtlsParameters.fingerprints, - role: "server", - } - }); - - socket.send(JSON.stringify({ - op: VoiceOPCodes.SESSION_DESCRIPTION, - d: { - video_codec: videoCodec?.mimeType?.substring(6) || undefined, - // mode: "xsalsa20_poly1305_lite", - media_session_id: transport.id, - audio_codec: audioCodec?.mimeType.substring(6), - secret_key: sodium.from_hex("724b092810ec86d7e35c9d067702b31ef90bc43a7b598626749914d6a3e033ed").buffer, - sdp: `m=audio ${50001} ICE/SDP\n` - + `a=fingerprint:sha-256 ${transport.dtlsParameters.fingerprints.find(x => x.algorithm === "sha-256")?.value}\n` - + `c=IN IP4 ${transport.iceCandidates[0].ip}\n` - + `t=0 0\n` - + `a=ice-lite\n` - + `a=rtcp-mux\n` - + `a=rtcp:${50001}\n` - + `a=ice-ufrag:${transport.iceParameters.usernameFragment}\n` - + `a=ice-pwd:${transport.iceParameters.password}\n` - + `a=fingerprint:sha-256 ${transport.dtlsParameters.fingerprints.find(x => x.algorithm === "sha-256")?.value}\n` - + `a=candidate:1 1 ${transport.iceCandidates[0].protocol.toUpperCase()} ${transport.iceCandidates[0].priority} ${transport.iceCandidates[0].ip} ${50001} typ ${transport.iceCandidates[0].type}` - } - })); - return; - } - else { - /* - { - "video_codec":"H264", - "sdp": - " - m=audio 50010 ICE/SDP - a=fingerprint:sha-256 4A:79:94:16:44:3F:BD:05:41:5A:C7:20:F3:12:54:70:00:73:5D:33:00:2D:2C:80:9B:39:E1:9F:2D:A7:49:87 - c=IN IP4 109.200.214.158 - a=rtcp:50010 - a=ice-ufrag:+npq - a=ice-pwd:+jf7jAesMeHHby43FRqWTy - a=fingerprint:sha-256 4A:79:94:16:44:3F:BD:05:41:5A:C7:20:F3:12:54:70:00:73:5D:33:00:2D:2C:80:9B:39:E1:9F:2D:A7:49:87 - a=candidate:1 1 UDP 4261412862 109.200.214.158 50010 typ host", - "media_session_id":"59265c94fa13e313492c372c4c8da801 - ", - "audio_codec":"opus" - } - */ - - - /* - { - "video_codec": "H264", - "secret_key": [36, 80, 96, 53, 95, 149, 253, 16, 137, 186, 238, 222, 251, 180, 94, 150, 112, 137, 192, 109, 69, 79, 218, 111, 217, 197, 56, 74, 18, 41, 51, 140], - "mode": "aead_aes256_gcm_rtpsize", - "media_session_id": "797575a97a87b63e81e2399348b97ad1", - "audio_codec": "opus" - }; - */ - - this.decryptKey = sodium.randombytes_buf(sodium.crypto_secretbox_KEYBYTES); - - // this.decryptKey = new Array(sodium.crypto_secretbox_KEYBYTES).fill(null).map((x, i) => i + 1); - console.log(this.decryptKey); - - socket.send(JSON.stringify({ - op: VoiceOPCodes.SESSION_DESCRIPTION, - d: { - video_codec: "H264", - secret_key: [...this.decryptKey.values()], - mode: "aead_aes256_gcm_rtpsize", - media_session_id: "blah blah blah", - audio_codec: "opus", - } - })); - } +import { Payload, Send, WebSocket } from "@fosscord/gateway"; +import { SelectProtocolSchema, validateSchema } from "@fosscord/util"; +import { endpoint, PublicIP, VoiceOPCodes } from "@fosscord/webrtc"; +import SemanticSDP from "semantic-sdp"; + +export async function onSelectProtocol(this: WebSocket, payload: Payload) { + if (!this.client) return; + + const data = validateSchema("SelectProtocolSchema", payload.d) as SelectProtocolSchema; + + const offer = SemanticSDP.SDPInfo.parse("m=audio\n" + data.sdp!); + this.client.sdp!.setICE(offer.getICE()); + this.client.sdp!.setDTLS(offer.getDTLS()); + + const transport = endpoint.createTransport(this.client.sdp!); + this.client.transport = transport; + transport.setRemoteProperties(this.client.sdp!); + transport.setLocalProperties(this.client.sdp!); + + const dtls = transport.getLocalDTLSInfo(); + const ice = transport.getLocalICEInfo(); + const port = endpoint.getLocalPort(); + const fingerprint = dtls.getHash() + " " + dtls.getFingerprint(); + const candidates = transport.getLocalCandidates(); + const candidate = candidates[0]; + + const answer = `m=audio ${port} ICE/SDP +a=fingerprint:${fingerprint} +c=IN IP4 ${PublicIP} +a=rtcp:${port} +a=ice-ufrag:${ice.getUfrag()} +a=ice-pwd:${ice.getPwd()} +a=fingerprint:${fingerprint} +a=candidate:1 1 ${candidate.getTransport()} ${candidate.getFoundation()} ${candidate.getAddress()} ${candidate.getPort()} typ host +`; + + await Send(this, { + op: VoiceOPCodes.SELECT_PROTOCOL_ACK, + d: { + video_codec: "H264", + sdp: answer, + media_session_id: this.session_id, + audio_codec: "opus" + } + }); } \ No newline at end of file diff --git a/webrtc/src/opcodes/Speaking.ts b/webrtc/src/opcodes/Speaking.ts
index 861a7c3d..e2227040 100644 --- a/webrtc/src/opcodes/Speaking.ts +++ b/webrtc/src/opcodes/Speaking.ts
@@ -1,7 +1,22 @@ -import { WebSocket } from "@fosscord/gateway"; -import { Payload } from "./index" -import { VoiceOPCodes } from "@fosscord/util"; -import { Server } from "../Server" +import { Payload, Send, WebSocket } from "@fosscord/gateway"; +import { getClients, VoiceOPCodes } from "../util"; -export async function onSpeaking(this: Server, socket: WebSocket, data: Payload) { +// {"speaking":1,"delay":5,"ssrc":2805246727} + +export async function onSpeaking(this: WebSocket, data: Payload) { + if (!this.client) return; + + getClients(this.client.channel_id).forEach((client) => { + if (client === this.client) return; + const ssrc = this.client!.out.tracks.get(client.websocket.user_id); + + Send(client.websocket, { + op: VoiceOPCodes.SPEAKING, + d: { + user_id: client.websocket.user_id, + speaking: data.d.speaking, + ssrc: ssrc?.audio_ssrc || 0 + } + }); + }); } \ No newline at end of file diff --git a/webrtc/src/opcodes/Version.ts b/webrtc/src/opcodes/Version.ts deleted file mode 100644
index 0ea6eb4d..00000000 --- a/webrtc/src/opcodes/Version.ts +++ /dev/null
@@ -1,14 +0,0 @@ -import { WebSocket } from "@fosscord/gateway"; -import { Payload } from "./index"; -import { setHeartbeat } from "../util"; -import { Server } from "../Server" - -export async function onVersion(this: Server, socket: WebSocket, data: Payload) { - socket.send(JSON.stringify({ - op: 16, - d: { - voice: "0.8.31", //version numbers? - rtc_worker: "0.3.18", - } - })) -} \ No newline at end of file diff --git a/webrtc/src/opcodes/Video.ts b/webrtc/src/opcodes/Video.ts new file mode 100644
index 00000000..ff20d5a9 --- /dev/null +++ b/webrtc/src/opcodes/Video.ts
@@ -0,0 +1,118 @@ +import { Payload, Send, WebSocket } from "@fosscord/gateway"; +import { validateSchema, VoiceVideoSchema } from "@fosscord/util"; +import { channels, getClients, VoiceOPCodes } from "@fosscord/webrtc"; +import { IncomingStreamTrack, SSRCs } from "medooze-media-server"; +import SemanticSDP from "semantic-sdp"; + +export async function onVideo(this: WebSocket, payload: Payload) { + if (!this.client) return; + const { transport, channel_id } = this.client; + if (!transport) return; + const d = validateSchema("VoiceVideoSchema", payload.d) as VoiceVideoSchema; + + await Send(this, { op: VoiceOPCodes.MEDIA_SINK_WANTS, d: { any: 100 } }); + + const id = "stream" + this.user_id; + + var stream = this.client.in.stream!; + if (!stream) { + stream = this.client.transport!.createIncomingStream( + // @ts-ignore + SemanticSDP.StreamInfo.expand({ + id, + // @ts-ignore + tracks: [] + }) + ); + this.client.in.stream = stream; + + const interval = setInterval(() => { + for (const track of stream.getTracks()) { + for (const layer of Object.values(track.getStats())) { + console.log(track.getId(), layer.total); + } + } + }, 5000); + + stream.on("stopped", () => { + console.log("stream stopped"); + clearInterval(interval); + }); + this.on("close", () => { + transport!.stop(); + }); + const out = transport.createOutgoingStream( + // @ts-ignore + SemanticSDP.StreamInfo.expand({ + id: "out" + this.user_id, + // @ts-ignore + tracks: [] + }) + ); + this.client.out.stream = out; + + const clients = channels.get(channel_id)!; + + clients.forEach((client) => { + if (client.websocket.user_id === this.user_id) return; + if (!client.in.stream) return; + + client.in.stream?.getTracks().forEach((track) => { + attachTrack.call(this, track, client.websocket.user_id); + }); + }); + } + + if (d.audio_ssrc) { + handleSSRC.call(this, "audio", { media: d.audio_ssrc, rtx: d.audio_ssrc + 1 }); + } + if (d.video_ssrc && d.rtx_ssrc) { + handleSSRC.call(this, "video", { media: d.video_ssrc, rtx: d.rtx_ssrc }); + } +} + +function attachTrack(this: WebSocket, track: IncomingStreamTrack, user_id: string) { + if (!this.client) return; + const outTrack = this.client.transport!.createOutgoingStreamTrack(track.getMedia()); + outTrack.attachTo(track); + this.client.out.stream!.addTrack(outTrack); + var ssrcs = this.client.out.tracks.get(user_id)!; + if (!ssrcs) ssrcs = this.client.out.tracks.set(user_id, { audio_ssrc: 0, rtx_ssrc: 0, video_ssrc: 0 }).get(user_id)!; + + if (track.getMedia() === "audio") { + ssrcs.audio_ssrc = outTrack.getSSRCs().media!; + } else if (track.getMedia() === "video") { + ssrcs.video_ssrc = outTrack.getSSRCs().media!; + ssrcs.rtx_ssrc = outTrack.getSSRCs().rtx!; + } + + Send(this, { + op: VoiceOPCodes.VIDEO, + d: { + user_id: user_id, + ...ssrcs + } as VoiceVideoSchema + }); +} + +function handleSSRC(this: WebSocket, type: "audio" | "video", ssrcs: SSRCs) { + if (!this.client) return; + const stream = this.client.in.stream!; + const transport = this.client.transport!; + + const id = type + ssrcs.media; + var track = stream.getTrack(id); + if (!track) { + console.log("createIncomingStreamTrack", id); + track = transport.createIncomingStreamTrack(type, { id, ssrcs }); + stream.addTrack(track); + + const clients = getClients(this.client.channel_id)!; + clients.forEach((client) => { + if (client.websocket.user_id === this.user_id) return; + if (!client.out.stream) return; + + attachTrack.call(this, track, client.websocket.user_id); + }); + } +} \ No newline at end of file diff --git a/webrtc/src/opcodes/index.ts b/webrtc/src/opcodes/index.ts
index 4d4dbc30..8c664cce 100644 --- a/webrtc/src/opcodes/index.ts +++ b/webrtc/src/opcodes/index.ts
@@ -1,43 +1,19 @@ -import { WebSocket } from "@fosscord/gateway"; -import { VoiceOPCodes } from "@fosscord/util"; -import { Server } from "../Server"; - -export interface Payload { - op: number; - d: any; - s: number; - t: string; -} - +import { Payload, WebSocket } from "@fosscord/gateway"; +import { VoiceOPCodes } from "../util"; +import { onBackendVersion } from "./BackendVersion"; +import { onHeartbeat } from "./Heartbeat"; import { onIdentify } from "./Identify"; import { onSelectProtocol } from "./SelectProtocol"; -import { onHeartbeat } from "./Heartbeat"; import { onSpeaking } from "./Speaking"; -import { onResume } from "./Resume"; -import { onConnect } from "./Connect"; - -import { onVersion } from "./Version"; - -export type OPCodeHandler = (this: Server, socket: WebSocket, data: Payload) => any; +import { onVideo } from "./Video"; -const handlers: { [key: number]: OPCodeHandler } = { - [VoiceOPCodes.IDENTIFY]: onIdentify, //op 0 - [VoiceOPCodes.SELECT_PROTOCOL]: onSelectProtocol, //op 1 - //op 2 voice_ready - [VoiceOPCodes.HEARTBEAT]: onHeartbeat, //op 3 - //op 4 session_description - [VoiceOPCodes.SPEAKING]: onSpeaking, //op 5 - //op 6 heartbeat_ack - [VoiceOPCodes.RESUME]: onResume, //op 7 - //op 8 hello - //op 9 resumed - //op 10? - //op 11? - [VoiceOPCodes.CLIENT_CONNECT]: onConnect, //op 12 - //op 13? - //op 15? - //op 16? empty data on client send but server sends {"voice":"0.8.24+bugfix.voice.streams.opt.branch-ffcefaff7","rtc_worker":"0.3.14-crypto-collision-copy"} - [VoiceOPCodes.VERSION]: onVersion, -}; +export type OPCodeHandler = (this: WebSocket, data: Payload) => any; -export default handlers; \ No newline at end of file +export default { + [VoiceOPCodes.HEARTBEAT]: onHeartbeat, + [VoiceOPCodes.IDENTIFY]: onIdentify, + [VoiceOPCodes.VOICE_BACKEND_VERSION]: onBackendVersion, + [VoiceOPCodes.VIDEO]: onVideo, + [VoiceOPCodes.SPEAKING]: onSpeaking, + [VoiceOPCodes.SELECT_PROTOCOL]: onSelectProtocol +}; \ No newline at end of file