File size: 3,531 Bytes
4cadbaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createServer = void 0;
const path_1 = __importDefault(require("path"));
const websocket_1 = __importDefault(require("websocket"));
const fileProxy_1 = __importDefault(require("./fileProxy"));
;
const acceptFrontendConnection = (request, options) => {
    const connection = request.accept("editor-frontend", request.origin);
    console.log("[web-editor] frontend accepted:", request.origin, connection.remoteAddress);
    let file = null;
    connection.on("close", (reasonCode, description) => {
        console.log("[web-editor] frontend quit:", connection.remoteAddress, reasonCode, description);
        if (file) {
            file.dispose();
            file = null;
        }
    });
    const sendCommand = (command, data) => connection.sendUTF(JSON.stringify(Object.assign({ command }, data)));
    connection.on("message", message => {
        const json = JSON.parse(message.utf8Data);
        switch (json.command) {
            case "bindFile":
                try {
                    const filePath = path_1.default.resolve(options.rootDir, json.filePath);
                    file = new fileProxy_1.default(filePath);
                    file.on("error", err => sendCommand("failure", err));
                    file.on("fullSync", data => sendCommand("fullSync", data));
                    file.on("increase", data => sendCommand("increase", data));
                }
                catch (err) {
                    console.warn("bindFile failed:", err);
                    connection.sendUTF(JSON.stringify({ command: "failure", description: err.toString() }));
                }
                break;
            case "increase":
                if (!file)
                    sendCommand("failure", { description: "no file bound yet" });
                else {
                    file.increase({
                        timestamp: json.timestamp,
                        fromHash: json.fromHash,
                        toHash: json.toHash,
                        patch: json.patch,
                    });
                }
                break;
            case "requestFullSync":
                if (!file)
                    sendCommand("failure", { description: "no file bound yet" });
                else {
                    console.assert(json.timestamp < file.timestamp, "[web-editor] requestFullSync sent from a newer peer:", new Date(json.timestamp), new Date(file.timestamp));
                    file.fullSync();
                }
                break;
            default:
                console.warn("[web-editor] unexpected frontend command:", json);
        }
    });
    return connection;
};
function createServer(httpServer, options) {
    const server = new websocket_1.default.server({
        httpServer,
        maxReceivedFrameSize: 0x1000000,
        maxReceivedMessageSize: 0x1000000,
        closeTimeout: 30e+3,
    });
    server.on("request", request => {
        //console.log("[Synchronizer] request received:", request.origin);
        if (request.requestedProtocols.includes("editor-frontend"))
            acceptFrontendConnection(request, options);
        else
            console.warn("Unexpected subprotocol request:", request.origin, request.requestedProtocols);
    });
    return server;
}
exports.createServer = createServer;
;