diff options
author | metamuffin <metamuffin@yandex.com> | 2022-01-23 14:06:14 +0100 |
---|---|---|
committer | metamuffin <metamuffin@yandex.com> | 2022-01-23 14:06:14 +0100 |
commit | a383c334a2e4ccb246a4a1092b1d053ccad19bd7 (patch) | |
tree | c747e39e25b94944da077df0a3ea20a2465540a8 /source | |
parent | 16fa95ac191287fe7f82b9f37c31342fe3b4b65a (diff) | |
download | keks-meet-a383c334a2e4ccb246a4a1092b1d053ccad19bd7.tar keks-meet-a383c334a2e4ccb246a4a1092b1d053ccad19bd7.tar.bz2 keks-meet-a383c334a2e4ccb246a4a1092b1d053ccad19bd7.tar.zst |
ported everything to deno! yay
Diffstat (limited to 'source')
-rw-r--r-- | source/client/helper.ts | 6 | ||||
-rw-r--r-- | source/client/index.ts | 15 | ||||
-rw-r--r-- | source/client/local_user.ts | 18 | ||||
-rw-r--r-- | source/client/logger.ts | 1 | ||||
-rw-r--r-- | source/client/remote_user.ts | 10 | ||||
-rw-r--r-- | source/client/rnnoise.ts | 11 | ||||
-rw-r--r-- | source/client/room.ts | 13 | ||||
-rw-r--r-- | source/client/types.ts | 16 | ||||
-rw-r--r-- | source/client/user.ts | 9 | ||||
-rw-r--r-- | source/packets.ts | 31 | ||||
-rw-r--r-- | source/server/index.ts | 142 | ||||
-rw-r--r-- | source/server/room.ts | 56 |
12 files changed, 186 insertions, 142 deletions
diff --git a/source/client/helper.ts b/source/client/helper.ts index 9fb4052..c46b169 100644 --- a/source/client/helper.ts +++ b/source/client/helper.ts @@ -1,4 +1,4 @@ -import { parameters } from "." +import { parameters } from "./index.ts" export function get_query_params(): { [key: string]: string } { const q: { [key: string]: string } = {} @@ -9,7 +9,7 @@ export function get_query_params(): { [key: string]: string } { return q } -export function hex_id(len: number = 8): string { +export function hex_id(len = 8): string { if (len > 8) return hex_id() + hex_id(len - 8) return Math.floor(Math.random() * 16 ** len).toString(16).padStart(len, "0") } @@ -21,7 +21,7 @@ export function parameter_bool(name: string, def: boolean): boolean { if (v == "0" || v == "false" || v == "no") return false if (v == "1" || v == "true" || v == "yes") return true alert(`parameter ${name} is invalid`) - return def + return def } export function parameter_number(name: string, def: number): number { diff --git a/source/client/index.ts b/source/client/index.ts index 313cd86..0c7e728 100644 --- a/source/client/index.ts +++ b/source/client/index.ts @@ -1,6 +1,8 @@ -import { get_query_params } from "./helper" -import { log } from "./logger" -import { Room } from "./room" +/// <reference lib="dom" /> + +import { get_query_params } from "./helper.ts" +import { log } from "./logger.ts" +import { Room } from "./room.ts" export const servers = { iceServers: [{ urls: ["stun:stun1.l.google.com:19302", "stun:stun2.l.google.com:19302"] }], @@ -13,14 +15,15 @@ export interface User { } -export var parameters = get_query_params() +export const parameters = get_query_params() window.onload = () => main() -export async function main() { +export function main() { + log("*", "starting up") if (window.location.pathname.startsWith("/room/")) { const room_name = window.location.pathname.substr("/room/".length) - let room = new Room(room_name) + const room = new Room(room_name) document.body.append(room.el) } else { document.body.append(create_start_screen()) diff --git a/source/client/local_user.ts b/source/client/local_user.ts index 7f2327e..540e311 100644 --- a/source/client/local_user.ts +++ b/source/client/local_user.ts @@ -1,9 +1,9 @@ -import { parameter_bool, parameter_number, parameter_string } from "./helper"; -import { log } from "./logger"; -import { RemoteUser } from "./remote_user"; -import { get_rnnoise_node } from "./rnnoise"; -import { Room } from "./room"; -import { User } from "./user"; +import { parameter_bool, parameter_number } from "./helper.ts"; +import { log } from "./logger.ts"; +import { RemoteUser } from "./remote_user.ts"; +import { get_rnnoise_node } from "./rnnoise.ts"; +import { Room } from "./room.ts"; +import { User } from "./user.ts"; export class LocalUser extends User { @@ -74,7 +74,7 @@ export class LocalUser extends User { else this.controls?.video.classList.remove("enabled") } - async add_initial_to_remote(ru: RemoteUser) { + add_initial_to_remote(ru: RemoteUser) { if (this.audio_track) ru.peer.addTrack(this.audio_track) if (this.video_track) ru.peer.addTrack(this.video_track) } @@ -133,7 +133,7 @@ export class LocalUser extends User { this.update_view_w() } - async disable_video() { + disable_video() { if (!this.video_track) return this.room.remote_users.forEach(u => { u.peer.getSenders().forEach(s => { @@ -144,7 +144,7 @@ export class LocalUser extends User { this.update_view_w() this.video_track = undefined } - async disable_audio() { + disable_audio() { if (!this.audio_track) return if (this.audio_disable_cleanup) this.audio_disable_cleanup() this.room.remote_users.forEach(u => { diff --git a/source/client/logger.ts b/source/client/logger.ts index 637f5c0..745ce88 100644 --- a/source/client/logger.ts +++ b/source/client/logger.ts @@ -9,6 +9,7 @@ const log_tag_color: { [key in LogTag]: string } = { } // TODO maybe log time aswell +// deno-lint-ignore no-explicit-any export function log(tag: LogTag, message: string, ...data: any[]) { for (let i = 0; i < data.length; i++) { const e = data[i]; diff --git a/source/client/remote_user.ts b/source/client/remote_user.ts index 6986a11..9e33a09 100644 --- a/source/client/remote_user.ts +++ b/source/client/remote_user.ts @@ -1,13 +1,13 @@ -import { servers } from "." -import { log } from "./logger" -import { Room } from "./room" -import { User } from "./user" +import { servers } from "./index.ts" +import { log } from "./logger.ts" +import { Room } from "./room.ts" +import { User } from "./user.ts" export class RemoteUser extends User { peer: RTCPeerConnection - negotiation_busy: boolean = false + negotiation_busy = false constructor(room: Room, name: string) { super(room, name) diff --git a/source/client/rnnoise.ts b/source/client/rnnoise.ts index c9014ef..0d301c5 100644 --- a/source/client/rnnoise.ts +++ b/source/client/rnnoise.ts @@ -1,9 +1,10 @@ -import { log } from "./logger" +import { log } from "./logger.ts" declare global { class RNNoiseNode extends AudioWorkletNode { static register(context: AudioContext): Promise<void> constructor(context: AudioContext) + // deno-lint-ignore no-explicit-any onstatus: (data: any) => void update(something: boolean): void } @@ -13,19 +14,19 @@ declare global { // TODO fix leak export async function get_rnnoise_node(context: AudioContext): Promise<RNNoiseNode> { log("misc", "rnnoise enabled") - //@ts-ignore + //@ts-ignore asfdasfd let RNNoiseNode: typeof RNNoiseNode = window.RNNoiseNode; let script: HTMLScriptElement; if (!RNNoiseNode) { log("misc", "loading rnnoise...") script = document.createElement("script") - script.src = "/static/rnnoise/rnnoise-runtime.js" + script.src = "/rnnoise/rnnoise-runtime.js" script.defer = true document.head.appendChild(script) - //@ts-ignore + //@ts-ignore asdfsfad while (!window.RNNoiseNode) await new Promise<void>(r => setTimeout(() => r(), 100)) - //@ts-ignore + //@ts-ignore asfdsadfsafd RNNoiseNode = window.RNNoiseNode; log("misc", "rnnoise loaded") } diff --git a/source/client/room.ts b/source/client/room.ts index 6a53a45..de6bff7 100644 --- a/source/client/room.ts +++ b/source/client/room.ts @@ -1,10 +1,9 @@ -import { log } from "./logger"; -import { CSPacket, SCPacket } from "./types"; -import { RemoteUser } from "./remote_user"; -import { User } from "./user"; -import { LocalUser } from "./local_user"; -import { parameters } from "."; -import { hex_id, parameter_string } from "./helper"; +import { log } from "./logger.ts"; +import { RemoteUser } from "./remote_user.ts"; +import { User } from "./user.ts"; +import { LocalUser } from "./local_user.ts"; +import { hex_id, parameter_string } from "./helper.ts"; +import { CSPacket, SCPacket } from "../packets.ts"; export class Room { diff --git a/source/client/types.ts b/source/client/types.ts deleted file mode 100644 index 7ce23ea..0000000 --- a/source/client/types.ts +++ /dev/null @@ -1,16 +0,0 @@ - -export interface SCPacket { - sender: string, - data?: CSPacket, - join?: boolean, // user just joined - leave?: boolean, // user left - stable?: boolean // user "joined" because you joined aka. user was already there -} -export interface CSPacket { - receiver?: string - ice_candiate?: RTCIceCandidateInit - offer?: RTCSessionDescriptionInit - answer?: RTCSessionDescriptionInit -} - - diff --git a/source/client/user.ts b/source/client/user.ts index f4f33e1..ef1449f 100644 --- a/source/client/user.ts +++ b/source/client/user.ts @@ -1,5 +1,6 @@ -import { log } from "./logger" -import { Room } from "./room" + +import { log } from "./logger.ts" +import { Room } from "./room.ts" export abstract class User { @@ -11,7 +12,7 @@ export abstract class User { display?: { audio_status_el: HTMLElement, video_status_el: HTMLElement } - local: boolean = false + local = false stream: MediaStream = new MediaStream() @@ -96,7 +97,7 @@ export abstract class User { const pip_el = document.createElement("input") pip_el.type = "button" pip_el.addEventListener("click", () => { - //@ts-ignore + // @ts-ignore firefox feature media_el.requestPictureInPicture() }) pip_el.value = "Picture-in-Picture" diff --git a/source/packets.ts b/source/packets.ts new file mode 100644 index 0000000..ef65ce7 --- /dev/null +++ b/source/packets.ts @@ -0,0 +1,31 @@ + + +type F_RTCSdpType = "answer" | "offer" | "pranswer" | "rollback"; +interface F_RTCSessionDescriptionInit { + sdp?: string; + type: F_RTCSdpType; +} + +interface F_RTCIceCandidateInit { + candidate?: string; + sdpMLineIndex?: number | null; + sdpMid?: string | null; + usernameFragment?: string | null; +} + + +export interface SCPacket { + sender: string, + data?: CSPacket, + join?: boolean, // user just joined + leave?: boolean, // user left + stable?: boolean // user "joined" because you joined aka. user was already there +} +export interface CSPacket { + receiver?: string + ice_candiate?: F_RTCIceCandidateInit + offer?: F_RTCSessionDescriptionInit + answer?: F_RTCSessionDescriptionInit +} + + diff --git a/source/server/index.ts b/source/server/index.ts index 88c3a66..1ee6bc9 100644 --- a/source/server/index.ts +++ b/source/server/index.ts @@ -1,103 +1,71 @@ -import Express, { static as estatic, json } from "express"; -import { join } from "path"; -import Webpack from "webpack" -import WebpackDevMiddleware from "webpack-dev-middleware" -import { existsSync, readFile, readFileSync } from "fs"; -import http from "http" -import https from "https" -import expressWs from "express-ws"; -import { CSPacket, SCPacket } from "../client/types"; -import * as ws from "ws" +import { Application, Router, RouterContext, send } from "https://deno.land/x/oak/mod.ts"; +import { api } from "./room.ts"; -type Room = Map<string, ws> -const rooms: Map<string, Room> = new Map() +const app = new Application() -function ws_send(ws: ws, data: SCPacket) { - try { ws.send(JSON.stringify(data)) } - catch (e) { console.warn("i hate express-ws") } -} +const root = new Router() + +let bundleFiles: Record<string, string> = {} -async function main() { - const app_e = Express(); - const app = expressWs(app_e).app +root.get("/", async c => { await c.send({ path: "index.html", root: `${Deno.cwd()}/public` }) }) +root.get("/room/:id", async c => { await c.send({ path: "index.html", root: `${Deno.cwd()}/public` }) }) - if (process.env.ENV == "production") { - console.log("PRODUCTION MODE!!!"); - app.use("/scripts", estatic(join(__dirname, "../../public/dist"))) - } else { - console.log("DEVELOPMENT MODE!!!"); - const webpackConfig = require('../../webpack.dev'); - const compiler = Webpack(webpackConfig) - const devMiddleware = WebpackDevMiddleware(compiler, { - publicPath: webpackConfig.output.publicPath - }) - app.use("/scripts", devMiddleware) +// deno-lint-ignore no-explicit-any +function respondWithType(mimeType: string, f: () => string): (c: RouterContext<any, any, any>) => void { + return c => { + c.response.headers.set("Content-Type", mimeType) + c.response.body = f() } +} - app.disable("x-powered-by"); - app.use(json()); +root.get("/bundle.js", respondWithType("application/javascript", () => bundleFiles["deno:///bundle.js"])) +root.get("/bundle.js.map", respondWithType("application/javascript", () => bundleFiles["deno:///bundle.js.map"])) - app.get("/", (req, res) => { - res.sendFile(join(__dirname, "../../public/index.html")); - }); - app.get("/room/:id", (req, res) => { - res.sendFile(join(__dirname, "../../public/index.html")); - }); +function mountFilesystem(r: Router, route: string, path: string) { + r.get(route + "/(.*)", async (context) => { + await send(context, context.request.url.pathname, { root: Deno.cwd() + path }); + }) - app.use("/static", estatic(join(__dirname, "../../public"))); +} - app.ws("/signaling/:id", (ws, req) => { - const room_name = req.params.id - const room: Map<string, ws> = rooms.get(req.params.id) ?? new Map() - let initialized = false - let user_name = "" +mountFilesystem(root, "/style", "/public") +mountFilesystem(root, "/rnnoise", "/public") - const init = (n: string) => { - if (room.get(n)) return ws.close() - initialized = true - user_name = n - rooms.set(req.params.id, room) - room.forEach(uws => ws_send(uws, { sender: user_name, join: true })) - room.forEach((_, uname) => ws_send(ws, { sender: uname, join: true, stable: true })) - room.set(user_name, ws) - console.log(`[${room_name}] ${user_name} joined`) - } - ws.onclose = () => { - room.delete(user_name) - room.forEach(uws => ws_send(uws, { sender: user_name, leave: true })) - if (room.size == 0) rooms.delete(room_name) - console.log(`[${room_name}] ${user_name} left`) - } - ws.onmessage = ev => { - const message = ev.data.toString() - if (!initialized) return init(message) - let in_packet: CSPacket; - try { in_packet = JSON.parse(message) } - catch (e) { return } +root.use(api.routes()) - console.log(`[${room_name}] ${user_name} -> ${in_packet.receiver ?? "*"}: ${message.substr(0, 100)}`) - const out_packet: SCPacket = { sender: user_name, data: in_packet } +app.use(root.routes()) +app.use(root.allowedMethods()) - if (in_packet.receiver) { - const rws = room.get(in_packet.receiver) - if (rws) ws_send(rws, out_packet) - } else { - room.forEach((uws, uname) => { - if (uname != user_name) ws_send(uws, out_packet) - }) - } - } - }) +app.addEventListener("listen", ({ hostname, port, secure }) => { + console.log(`listening on: ${secure ? "https://" : "http://"}${hostname}:${port}`); +}); - app.use((req, res, next) => { - res.status(404); - res.send("This is an error page"); - }); +app.listen({ + hostname: Deno.env.get("HOSTNAME") ?? "127.0.0.1", + port: parseInt(Deno.env.get("PORT") ?? "8080") +}); - const port = parseInt(process.env.PORT ?? "8080") - app.listen(port, process.env.HOST ?? "127.0.0.1", () => { - console.log(`Server listening on ${process.env.HOST ?? "127.0.0.1"}:${port}`); - }) + +let refresh_needed = false +let refresh_pending = false +async function refresh() { + refresh_needed = true + if (refresh_pending) return + refresh_needed = false + refresh_pending = true + + try { + const { files } = await Deno.emit("source/client/index.ts", { bundle: "module", check: false }) + bundleFiles = files + } catch (e) { console.error(e) } + + refresh_pending = false + if (refresh_needed) refresh() } -main();
\ No newline at end of file +refresh() +for await (const event of Deno.watchFs("source/client")) { + if (event.kind == "modify" || event.kind == "create") { + refresh() + } +} diff --git a/source/server/room.ts b/source/server/room.ts new file mode 100644 index 0000000..34d847c --- /dev/null +++ b/source/server/room.ts @@ -0,0 +1,56 @@ +import { Router } from "https://deno.land/x/oak@v10.1.0/router.ts"; +import { CSPacket, SCPacket } from "../packets.ts"; + +export const api = new Router() + +type Room = Map<string, WebSocket> +const rooms: Map<string, Room> = new Map() + +function send_packet(ws: WebSocket, packet: SCPacket) { + ws.send(JSON.stringify(packet)) +} + +api.get("/signaling/:id", c => { + const ws = c.upgrade() + + const room_name = c.params.id + const room: Room = rooms.get(c.params.id) ?? new Map() + let initialized = false + let user_name = "" + + const init = (n: string) => { + if (room.get(n)) return ws.close() + initialized = true + user_name = n + rooms.set(c.params.id, room) + room.forEach(uws => send_packet(uws, { sender: user_name, join: true })) + room.forEach((_, uname) => send_packet(ws, { sender: uname, join: true, stable: true })) + room.set(user_name, ws) + console.log(`[${room_name}] ${user_name} joined`) + } + ws.onclose = () => { + room.delete(user_name) + room.forEach(uws => send_packet(uws, { sender: user_name, leave: true })) + if (room.size == 0) rooms.delete(room_name) + console.log(`[${room_name}] ${user_name} left`) + } + ws.onmessage = ev => { + const message = ev.data.toString() + if (!initialized) return init(message) + let in_packet: CSPacket; + try { in_packet = JSON.parse(message) } + catch (_e) { return } + + console.log(`[${room_name}] ${user_name} -> ${in_packet.receiver ?? "*"}: ${message.substr(0, 100)}`) + const out_packet: SCPacket = { sender: user_name, data: in_packet } + + if (in_packet.receiver) { + const rws = room.get(in_packet.receiver) + if (rws) send_packet(rws, out_packet) + } else { + room.forEach((uws, uname) => { + if (uname != user_name) send_packet(uws, out_packet) + }) + } + } +}) |