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
104
105
106
107
108
|
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 { CallDocModel } from "../models";
const call_docs: Map<String, CallDocModel> = new Map()
async function main() {
const app_e = Express();
const app = expressWs(app_e).app
const webpackConfig = require('../../webpack.config');
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.use("/static", estatic(join(__dirname, "../../public")));
app.get("/favicon.ico", (req, res) => {
res.sendFile(join(__dirname, "../../public/favicon.ico"));
});
app.ws("/offer/:id", (ws, req) => {
const id = req.params.id
if (call_docs.get(id)) return ws.close(0, "call already running")
console.log(`[${id}] offer websocket open`);
ws.onclose = () => console.log(`[${id}] offer websocket close`);
const doc: CallDocModel = {
answered: false,
offer_candidates: [],
offer: undefined,
on_answer: () => { },
on_answer_candidate: () => { },
on_offer_candidate: () => { },
}
ws.onmessage = ev => {
const s = JSON.parse(ev.data.toString())
if (s.offer) {
console.log(`[${id}] offer`);
doc.offer = s.offer
call_docs.set(id, doc)
}
if (s.candidate) {
console.log(`[${id}] offer candidate`);
if (doc.answered) doc.on_offer_candidate(s.candidate)
else doc.offer_candidates.push(s.candidate)
}
}
doc.on_answer = answer => ws.send(JSON.stringify({ answer }))
doc.on_answer_candidate = candidate => ws.send(JSON.stringify({ candidate }))
})
app.ws("/answer/:id", (ws, req) => {
const id = req.params.id
console.log(`[${id}] answer websocket open`);
ws.onclose = () => console.log(`[${id}] answer websocket close`);
const doc = call_docs.get(id)
if (!doc) return ws.close(0, "call not found")
if (doc.answered) return ws.close(0, "call already answered")
ws.onmessage = ev => {
const s = JSON.parse(ev.data.toString())
if (s.answer) {
console.log(`[${id}] answer`);
doc.on_answer(s.answer)
}
if (s.candidate) {
console.log(`[${id}] answer candidate`);
doc.on_answer_candidate(s.candidate)
}
}
doc.on_offer_candidate = candidate => ws.send(JSON.stringify({ candidate }))
// TODO this is evil
setTimeout(() => {
ws.send(JSON.stringify({ offer: doc.offer }))
for (const candidate of doc.offer_candidates) {
ws.send(JSON.stringify({ candidate }))
}
doc.offer_candidates = []
}, 100)
})
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 127.0.0.1:${port}`);
})
}
main();
|