-
Notifications
You must be signed in to change notification settings - Fork 17
/
server.ts
137 lines (115 loc) Β· 3.8 KB
/
server.ts
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// it's easiest to share typedefs as an ambient declaration file
/// <reference path="./messages.d.ts" />
import * as express from "express";
import * as expressWs from "express-ws";
import * as WebSocket from "ws";
import { createServer } from "http";
interface User {
socket: WebSocket;
name: string;
}
// we'll keep a list of our connected users, as we need to send them messages later
let connectedUsers: User[] = [];
/**
* Searches the currently connected users and returns the first one connected to the provided socket.
* @param socket The socket to search for
*/
function findUserBySocket(socket: WebSocket): User | undefined {
return connectedUsers.find((user) => user.socket === socket);
}
/**
* Searches the currently connected users and returns the first one with the provided name.
* @param name The name to search for
*/
function findUserByName(name: string): User | undefined {
return connectedUsers.find((user) => user.name === name);
}
/**
* Forwards this message to the person
* @param sender The person originally sending this message
* @param message The received message
*/
function forwardMessageToOtherPerson(sender: User, message: WebSocketCallMessage): void {
const receiver = findUserByName(message.otherPerson);
if (!receiver) {
// in case this user doesn't exist, don't do anything
return;
}
const json = JSON.stringify({
...message,
otherPerson: sender.name,
});
receiver.socket.send(json);
}
/**
* Processes the incoming message.
* @param socket The socket that sent the message
* @param message The message itself
*/
function handleMessage(socket: WebSocket, message: WebSocketMessage): void {
const sender = findUserBySocket(socket) || {
name: "[unknown]",
socket,
};
switch (message.channel) {
case "login":
console.log(`${message.name} joined`);
connectedUsers.push({ socket, name: message.name });
break;
case "start_call":
console.log(`${sender.name} started a call with ${message.otherPerson}`);
forwardMessageToOtherPerson(sender, message);
break;
case "webrtc_ice_candidate":
console.log(`received ice candidate from ${sender.name}`);
forwardMessageToOtherPerson(sender, message);
break;
case "webrtc_offer":
console.log(`received offer from ${sender.name}`);
forwardMessageToOtherPerson(sender, message);
break;
case "webrtc_answer":
console.log(`received answer from ${sender.name}`);
forwardMessageToOtherPerson(sender, message);
break;
default:
console.log("unknown message", message);
break;
}
}
/**
* Adds event listeners to the incoming socket.
* @param socket The incoming WebSocket
*/
function handleSocketConnection(socket: WebSocket): void {
socket.addEventListener("message", (event) => {
// incoming messages are strings of buffers. we need to convert them
// to objects first using JSON.parse()
// it's safe to assume we'll only receive valid json here though
const json = JSON.parse(event.data.toString());
handleMessage(socket, json);
});
socket.addEventListener("close", () => {
// remove the user from our user list
connectedUsers = connectedUsers.filter((user) => {
if (user.socket === socket) {
console.log(`${user.name} disconnected`);
return false;
}
return true;
});
});
}
// create an express app, using http `createServer`
const app = express();
const server = createServer(app);
// we'll serve our public directory under /
app.use("/", express.static("public"));
// add a websocket listener under /ws
const wsApp = expressWs(app, server).app;
wsApp.ws("/ws", handleSocketConnection);
// start the server
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log(`server started on http://localhost:${port}`);
});