aboutsummaryrefslogtreecommitdiff
path: root/source/server/index.ts
blob: f37a0b90633564318bd0e344ace19c6c64f91545 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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"

type Room = Map<string, ws>
const rooms: Map<string, Room> = new Map()

function ws_send(ws: ws, data: SCPacket) {
    try { ws.send(JSON.stringify(data)) }
    catch (e) { console.warn("i hate express-ws") }
}

async function main() {
    const app_e = Express();
    const app = expressWs(app_e).app

    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)
    }

    app.disable("x-powered-by");
    app.use(json());

    app.get("/", (req, res) => {
        res.sendFile(join(__dirname, "../../public/index.html"));
    });
    app.get("/room/:id", (req, res) => {
        res.sendFile(join(__dirname, "../../public/index.html"));
    });

    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 = ""

        const init = (n: string) => {
            if (room.get(n)) return ws.close(1, "username already taken")
            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 }

            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) ws_send(rws, out_packet)
            } else {
                room.forEach((uws, uname) => {
                    if (uname != user_name) ws_send(uws, out_packet)
                })
            }
        }
    })

    app.use((req, res, next) => {
        res.status(404);
        res.send("This is an error page");
    });

    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}`);
    })
}

main();