diff --git a/bundle/src/Server.ts b/bundle/src/Server.ts index 71a60d49..bc1d7cbc 100644 --- a/bundle/src/Server.ts +++ b/bundle/src/Server.ts @@ -50,20 +50,20 @@ async function main() { endpointPublic: `ws://localhost:${port}`, }), }, - // regions: { - // default: "fosscord", - // useDefaultAsOptimal: true, - // available: [ - // { - // id: "fosscord", - // name: "Fosscord", - // endpoint: "127.0.0.1:3001", - // vip: false, - // custom: false, - // deprecated: false, - // }, - // ], - // }, + regions: { + default: "fosscord", + useDefaultAsOptimal: true, + available: [ + { + id: "fosscord", + name: "Fosscord", + endpoint: "127.0.0.1:3004", + vip: false, + custom: false, + deprecated: false, + }, + ], + }, } as any); //Sentry diff --git a/util/src/util/Constants.ts b/util/src/util/Constants.ts index 5fdf5bc0..a1892105 100644 --- a/util/src/util/Constants.ts +++ b/util/src/util/Constants.ts @@ -73,7 +73,10 @@ export const VoiceOPCodes = { HEARTBEAT: 3, SESSION_DESCRIPTION: 4, SPEAKING: 5, + HEARTBEAT_ACK: 6, + RESUME: 7, HELLO: 8, + RESUMED: 9, CLIENT_CONNECT: 12, CLIENT_DISCONNECT: 13, }; diff --git a/webrtc/.vscode/launch.json b/webrtc/.vscode/launch.json new file mode 100644 index 00000000..92403164 --- /dev/null +++ b/webrtc/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "ts-node", + "type": "node", + "request": "launch", + "args": [ + "src/start.ts" + ], + "runtimeArgs": [ + "-r", + "ts-node/register" + ], + "cwd": "${workspaceRoot}", + "protocol": "inspector", + "internalConsoleOptions": "openOnSessionStart" + } + ] +} \ No newline at end of file diff --git a/webrtc/package-lock.json b/webrtc/package-lock.json index a5db2de1..6c3726dc 100644 Binary files a/webrtc/package-lock.json and b/webrtc/package-lock.json differ diff --git a/webrtc/package.json b/webrtc/package.json index 0f700728..8c66245d 100644 --- a/webrtc/package.json +++ b/webrtc/package.json @@ -14,11 +14,13 @@ "devDependencies": { "@types/node": "^15.6.1", "@types/ws": "^7.4.4", + "ts-node": "^10.4.0", "typescript": "^4.3.2" }, "dependencies": { - "mediasoup": "^3.7.16", + "mediasoup": "^3.9.5", "node-turn": "^0.0.6", + "tsconfig-paths": "^3.12.0", "ws": "^7.4.6" } } diff --git a/webrtc/src/Server.ts b/webrtc/src/Server.ts index 6591691c..06a36df9 100644 --- a/webrtc/src/Server.ts +++ b/webrtc/src/Server.ts @@ -1,5 +1,8 @@ import { Server as WebSocketServer } from "ws"; -import { Config, db } from "@fosscord/util"; +import { WebSocket, CLOSECODES, Payload, OPCODES } from "@fosscord/gateway"; +import { Config, initDatabase } from "@fosscord/util"; +import OPCodeHandlers from "./opcodes"; +import { setHeartbeat } from "./util" import mediasoup from "mediasoup"; var port = Number(process.env.PORT); @@ -7,38 +10,29 @@ if (isNaN(port)) port = 3004; export class Server { public ws: WebSocketServer; - public turn: any; constructor() { this.ws = new WebSocketServer({ port, maxPayload: 4096, }); - this.ws.on("connection", (socket) => { - socket.on("message", (message) => { - socket.emit( - JSON.stringify({ - op: 2, - d: { - ssrc: 1, - ip: "127.0.0.1", - port: 3004, - modes: [ - "xsalsa20_poly1305", - "xsalsa20_poly1305_suffix", - "xsalsa20_poly1305_lite", - ], - heartbeat_interval: 1, - }, - }) - ); + this.ws.on("connection", async (socket: WebSocket) => { + await setHeartbeat(socket); + + socket.on("message", async (message: string) => { + const payload: Payload = JSON.parse(message); + + if (OPCodeHandlers[payload.op]) + await OPCodeHandlers[payload.op](socket, payload); + else + console.error(`Unimplemented`, payload) }); }); } async listen(): Promise { // @ts-ignore - await (db as Promise); + await initDatabase(); await Config.init(); console.log("[DB] connected"); console.log(`[WebRTC] online on 0.0.0.0:${port}`); diff --git a/webrtc/src/opcodes/Connect.ts b/webrtc/src/opcodes/Connect.ts new file mode 100644 index 00000000..5cc66506 --- /dev/null +++ b/webrtc/src/opcodes/Connect.ts @@ -0,0 +1,5 @@ +import { WebSocket } from "@fosscord/gateway"; +import { Payload } from "./index"; + +export async function onConnect(socket: WebSocket, data: Payload) { +} \ No newline at end of file diff --git a/webrtc/src/opcodes/Heartbeat.ts b/webrtc/src/opcodes/Heartbeat.ts new file mode 100644 index 00000000..04150e36 --- /dev/null +++ b/webrtc/src/opcodes/Heartbeat.ts @@ -0,0 +1,7 @@ +import { WebSocket } from "@fosscord/gateway"; +import { Payload } from "./index"; +import { setHeartbeat } from "./../util"; + +export async function onHeartbeat(socket: WebSocket, data: Payload) { + await setHeartbeat(socket); +} \ No newline at end of file diff --git a/webrtc/src/opcodes/Identify.ts b/webrtc/src/opcodes/Identify.ts new file mode 100644 index 00000000..2026d7c9 --- /dev/null +++ b/webrtc/src/opcodes/Identify.ts @@ -0,0 +1,20 @@ +import { WebSocket } from "@fosscord/gateway"; +import { Payload } from "./index" +import { VoiceOPCodes } from "@fosscord/util"; + +export async function onIdentify(socket: WebSocket, data: Payload) { + socket.send(JSON.stringify({ + op: VoiceOPCodes.READY, + d: { + ssrc: 1, + ip: "127.0.0.1", + port: 3005, + modes: [ + "xsalsa20_poly1305", + "xsalsa20_poly1305_suffix", + "xsalsa20_poly1305_lite", + ], + heartbeat_interval: 1, + }, + })); +} \ No newline at end of file diff --git a/webrtc/src/opcodes/Resume.ts b/webrtc/src/opcodes/Resume.ts new file mode 100644 index 00000000..de21eba6 --- /dev/null +++ b/webrtc/src/opcodes/Resume.ts @@ -0,0 +1,5 @@ +import { WebSocket } from "@fosscord/gateway"; +import { Payload } from "./index"; + +export async function onResume(socket: WebSocket, data: Payload) { +} \ No newline at end of file diff --git a/webrtc/src/opcodes/SelectProtocol.ts b/webrtc/src/opcodes/SelectProtocol.ts new file mode 100644 index 00000000..f1732dd9 --- /dev/null +++ b/webrtc/src/opcodes/SelectProtocol.ts @@ -0,0 +1,16 @@ +import { WebSocket } from "@fosscord/gateway"; +import { Payload } from "./index"; +import { VoiceOPCodes } from "@fosscord/util"; + +export async function onSelectProtocol(socket: WebSocket, data: Payload) { + socket.send(JSON.stringify({ + op: VoiceOPCodes.SESSION_DESCRIPTION, + d: { + video_codec: "H264", + secret_key: new Array(32).fill(null).map(x => Math.random() * 256), + mode: "aead_aes256_gcm_rtpsize", + media_session_id: "d8eb5c84d987c6642ec4ce72ffa97f00", + audio_codec: "opus", + } + })); +} \ No newline at end of file diff --git a/webrtc/src/opcodes/Speaking.ts b/webrtc/src/opcodes/Speaking.ts new file mode 100644 index 00000000..14f86b3c --- /dev/null +++ b/webrtc/src/opcodes/Speaking.ts @@ -0,0 +1,6 @@ +import { WebSocket } from "@fosscord/gateway"; +import { Payload } from "./index" +import { VoiceOPCodes } from "@fosscord/util"; + +export async function onSpeaking(socket: WebSocket, data: Payload) { +} \ No newline at end of file diff --git a/webrtc/src/opcodes/index.ts b/webrtc/src/opcodes/index.ts new file mode 100644 index 00000000..2fe69c38 --- /dev/null +++ b/webrtc/src/opcodes/index.ts @@ -0,0 +1,35 @@ +import { WebSocket } from "@fosscord/gateway"; +import { VoiceOPCodes } from "@fosscord/util"; + +export interface Payload { + op: number; + d?: any; + s?: number; + t?: string; +} + +import { onIdentify } from "./Identify"; +import { onSelectProtocol } from "./SelectProtocol"; +import { onHeartbeat } from "./Heartbeat"; +import { onSpeaking } from "./Speaking"; +import { onResume } from "./Resume"; +import { onConnect } from "./Connect"; + +export type OPCodeHandler = (this: WebSocket, data: Payload) => any; + +export default { + [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? +}; \ No newline at end of file diff --git a/webrtc/src/start.ts b/webrtc/src/start.ts index 68867a2c..5614982d 100644 --- a/webrtc/src/start.ts +++ b/webrtc/src/start.ts @@ -1,3 +1,4 @@ import { Server } from "./Server"; const server = new Server(); +server.listen(); \ No newline at end of file diff --git a/webrtc/src/util/Heartbeat.ts b/webrtc/src/util/Heartbeat.ts new file mode 100644 index 00000000..7b5ed9cd --- /dev/null +++ b/webrtc/src/util/Heartbeat.ts @@ -0,0 +1,18 @@ +import { WebSocket, CLOSECODES } from "@fosscord/gateway"; +import { VoiceOPCodes } from "@fosscord/util"; + +export async function setHeartbeat(socket: WebSocket) { + if (socket.heartbeatTimeout) clearTimeout(socket.heartbeatTimeout); + + socket.heartbeatTimeout = setTimeout(() => { + return socket.close(CLOSECODES.Session_timed_out); + }, 1000 * 45); + + socket.send(JSON.stringify({ + op: VoiceOPCodes.HEARTBEAT_ACK, + d: { + v: 6, + heartbeat_interval: 13750, + } + })); +} \ No newline at end of file diff --git a/webrtc/src/util/index.ts b/webrtc/src/util/index.ts new file mode 100644 index 00000000..e8557452 --- /dev/null +++ b/webrtc/src/util/index.ts @@ -0,0 +1 @@ +export * from "./Heartbeat" \ No newline at end of file diff --git a/webrtc/tsconfig.json b/webrtc/tsconfig.json index 77353db0..fb93b0bd 100644 --- a/webrtc/tsconfig.json +++ b/webrtc/tsconfig.json @@ -1,5 +1,8 @@ { "include": ["src/**/*.ts"], + "ts-node": { + "require": ["tsconfig-paths/register"], + }, "compilerOptions": { /* Visit https://aka.ms/tsconfig.json to read more about this file */ @@ -18,7 +21,7 @@ "sourceMap": true /* Generates corresponding '.map' file. */, // "outFile": "./", /* Concatenate and emit output to single file. */ "outDir": "./dist/" /* Redirect output structure to the directory. */, - "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, + "rootDir": "../" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */ @@ -62,11 +65,19 @@ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ + + "baseUrl": "../", + "paths": { + "@fosscord/api": ["api/src/index"], + "@fosscord/gateway": ["gateway/src/index"], + "@fosscord/cdn": ["cdn/src/index"], + "@fosscord/util": ["util/src/index"] + }, } }