aboutsummaryrefslogtreecommitdiff
path: root/source/server
diff options
context:
space:
mode:
Diffstat (limited to 'source/server')
-rw-r--r--source/server/index.ts142
-rw-r--r--source/server/room.ts56
2 files changed, 111 insertions, 87 deletions
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)
+ })
+ }
+ }
+})