File size: 3,896 Bytes
58ad246
 
 
 
 
ebf3f0c
cfd4c95
 
2b43822
 
35fc662
a74716b
34ecf0f
cfd4c95
58ad246
a74716b
d32b1fb
 
 
 
cfd4c95
d32b1fb
a74716b
cfd4c95
58ad246
 
 
 
a74716b
c0563d6
 
 
 
 
 
 
d32b1fb
 
 
 
 
 
 
 
 
 
 
 
 
cfd4c95
d32b1fb
 
 
a74716b
58ad246
34ecf0f
 
58ad246
34ecf0f
 
d32b1fb
a74716b
d32b1fb
 
 
 
2b43822
d32b1fb
 
 
c0563d6
d32b1fb
 
cfd4c95
c0563d6
 
d32b1fb
 
 
 
a74716b
c0563d6
 
 
 
 
 
 
58fc009
 
 
 
 
 
d32b1fb
 
 
 
 
 
 
e3cb794
d32b1fb
 
e3cb794
c0563d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d32b1fb
 
 
a74716b
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
/*
Created by Anne Lefebvre and Anuj Panthri - 2023
Handles the HTTP file serving and the WebSocket connect for HapticTouch
*/

import express, { Application, Request, Response } from "express";
import * as http from "http";
import * as WebSocket from "ws";
import { HapticLinkServer } from "./socket/hapticLinkServer";
import { registerRoutes } from "./socket/routes";
import WebSocketWrapper from "./socket/WebSocketAdapter";
import pino from "pino";
import path from "path";

// If started with --silent, then logging will be disabled.
(() => {
    const args = process.argv;
    if (args.includes("--silent")) {
        return main(false);
    }

    return main(true);
})();

/**
 * Starts HTTP(S) and WS server, initializes HapticLinkServer and handles routing.
 * @param {boolean} logging - Defaults true
 */
function main(logging: boolean = true) {

    // Added by Anuj
    const PING_INTERVAL = parseInt(process.env.PING_INTERVAL as string, 10) || 5 * 1000;
    interface LooseWebSocket extends WebSocket {
        isAlive?: boolean
    }

    const port: number = parseInt(process.env.PORT as string, 10) || 3000;
    const logger = pino({
        level: logging ? "info" : "silent",
        formatters: {
            bindings(bindings) {
                return {
                    level: bindings.level,
                    time: bindings.time,
                    msg: bindings.msg,
                };
            },
        },
    });

    const app: Application = express();
    const server = http.createServer(app);
    const wss = new WebSocket.Server({ server });

    // The entire build/web directory is statically served.
    app.use(express.static(path.join(__dirname, "../../client/build/web")));

    // Catch all. If we want to add pages later, then we should probably change this.
    app.get("*", (_req: Request, res: Response) => {
        res.sendFile(path.join(__dirname + "/../../client/build/web/index.html"));
    });

    // Routes are in socket/routes/*.ts
    // registerRoutes imports and adds them all to router
    const hapticLink = new HapticLinkServer();
    registerRoutes(hapticLink);

    // When a user sends a message, the router checks if that route is available
    // and then calls the handler. It also generates a User object for them to store
    // data for later requests such as an ID
    wss.on("connection", (ws: LooseWebSocket) => {
        logger.info("Client Connected");
        const wsw = new WebSocketWrapper(ws);

        ws.isAlive = true;  // Added by Anuj

        ws.on("message", (message: string) => {
            logger.info(`Received Message: ${message}`);
            hapticLink.handleRoute(wsw, message);
        });

        // Added by Anuj
        // When receive pong from a client this is triggered
        ws.on('pong', () => {
            ws.isAlive = true;
            logger.info("received pong");
        });

        // Added by Anuj
        // When receive ping from a client this is triggered
        ws.on('ping', () => {
            logger.info("received ping");
        });

        // When a user disconnects, their account is removed, and they are removed from all groups
        ws.on("close", () => {
            hapticLink.removeUser(wsw);
        });
        ws.on("error", () => {
            hapticLink.removeUser(wsw);
        });

        ws.send("Welcome");
    });


    // Added by Anuj
    const interval = setInterval(function ping() {
        wss.clients.forEach((ws) => {
            const client = ws as LooseWebSocket;
            if (client.isAlive === false) return ws.terminate();

            ws.ping();
            client.isAlive = false;
        });
    }, PING_INTERVAL);

    // Added by Anuj
    wss.on('close', function close() {
        clearInterval(interval);
    });

    server.listen(port, () => {
        logger.info(`Server is running on port ${port}`);
    });
}