core/plugins/c9.ide.run.debug/debuggers/chrome/chrome-debug-proxy.js
2018-02-06 22:57:37 +04:00

201 lines
5.2 KiB
JavaScript

/*
ide1 ide2
| |
vfsServer1 vfsServer2 vfsServer3 ... clients
| |
| | filesocket
| |
chrome-debug-proxy
|
| websocket
|
node-process1 node-process2 ... debuggers
*/
var fs = require("fs");
var net = require("net");
var Debugger = require("./Debugger");
var MessageReader = require("./MessageReader");
var startT = Date.now();
var IS_WINDOWS = process.platform == "win32";
/*** connect to cloud9 ***/
var socketPath = process.env.HOME + "/.c9/chrome.sock";
if (IS_WINDOWS)
socketPath = "\\\\.\\pipe\\" + socketPath.replace(/\//g, "\\");
console.log("Using socket", socketPath);
function checkServer(id) {
var client = net.connect(socketPath, function() {
if (id) return;
console.log("process already exists");
process.exit(0);
});
client.on("data", function(data) {
try {
var msg = JSON.parse(data.toString().slice(0, -1));
} catch (e) {}
if (msg && msg.ping != id)
process.exit(1);
client.destroy();
});
client.on("error", function(err) {
if (!id && err) {
var code = err.code;
if (code == "ECONNREFUSED" || code === "ENOENT" || code === "EAGAIN")
return createServer();
}
process.exit(1);
});
}
var $id = 0;
var server;
var ideClients = {};
var debuggers = {};
function createServer() {
server = net.createServer(function(client) {
var isClosed = false;
client.id = $id++;
ideClients[client.id] = client;
client.send = function(msg) {
if (isClosed)
return;
var strMsg = JSON.stringify(msg);
client.write(strMsg + "\0");
};
client.on("data", onData);
var buff = [];
function onData(data) {
data = data.toString();
var idx;
while (true) {
idx = data.indexOf("\0");
if (idx === -1)
return data && buff.push(data);
buff.push(data.substring(0, idx));
var clientMsg = buff.join("");
data = data.substring(idx + 1);
buff = [];
if (clientMsg[0] == "{") {
try {
var msg = JSON.parse(clientMsg);
} catch (e) {
console.log("error parsing message", clientMsg);
return client.close();
}
} else {
msg = clientMsg;
}
client.emit("message", msg);
}
}
client.on("close", onClose);
client.on("end", onClose);
client.on("message", function(message) {
if (actions[message.$])
actions[message.$](message, client);
else if (client.debugger)
client.debugger.handleMessage(message);
});
function onClose() {
if (isClosed) return;
isClosed = true;
delete ideClients[client.id];
if (client.debugger)
client.debugger.removeClient(client);
client.emit("disconnect");
}
client.on("error", function(err) {
console.log(err);
onClose();
client.destroy();
});
client.send({ ping: process.pid });
});
server.on("error", function(err) {
console.error("server error", err);
throw err;
});
server.on("close", function (e) {
console.log("server closed", e);
process.exit(1);
});
removeStaleSocket();
server.listen(socketPath, function() {
console.log("server listening on ", socketPath);
checkServer(process.pid);
});
}
function removeStaleSocket() {
if (IS_WINDOWS)
return;
try {
fs.unlinkSync(socketPath);
} catch (e) {
if (e.code != "ENOENT")
console.error(e);
}
}
var actions = {
exit: function(message, client) {
process.exit(1);
},
ping: function(message, client) {
message.$ = "pong";
message.t = Date.now();
client.send(message);
},
connect: function(message, client, callback) {
if (!debuggers[message.port]) {
var dbg = debuggers[message.port] = new Debugger();
debuggers[message.port].connect(message);
debuggers[message.port].on("disconnect", function() {
if (debuggers[message.port] == dbg)
delete debuggers[message.port];
});
}
debuggers[message.port].addClient(client);
},
detach: function(message, client, callback) {
if (client.debugger)
client.debugger.disconnect();
},
};
/*** =============== ***/
var idle = 0;
setInterval(function() {
console.log(Object.keys(ideClients), Object.keys(debuggers))
if (!Object.keys(ideClients).length && !Object.keys(debuggers).length) {
idle++;
} else {
idle = 0;
}
if (idle > 2) {
console.log("No open connections, exiting");
process.exit(0);
}
}, 30 * 1000);
checkServer();