c9-core/plugins/c9.cli.bridge/bridge-service.js

158 wiersze
4.5 KiB
JavaScript

module.exports = function (vfs, options, register) {
var stream;
var net = require("net");
var Stream = require('stream');
var path = require("path");
var SOCKET = process.platform == "win32"
? "\\\\.\\pipe\\.c9\\bridge.socket"
: process.env.HOME + "/.c9/bridge.socket";
function createListenClient(api) {
var client = net.connect(SOCKET, function(data) {
api.onConnect(client);
});
client.setEncoding("utf8");
client.unref();
client.on("data", function(data) {
if (data) api.onData(data);
});
client.on("error", function(err) {
if (err.code == "ECONNREFUSED" && process.platform !== "win32") {
require("fs").unlink(SOCKET, function() {
createListenServer(api);
});
}
else if (err.code == "ENOENT") {
createListenServer(api);
}
else
api.onConnectError(err);
});
client.on("end", function() {
createListenServer(api);
});
api.disconnect = function() {
client.end();
};
return client;
}
function createListenServer(api) {
function broadcast(data, client) {
clients.forEach(function(c) {
if (c != client)
c.write(data);
});
}
function registerClient(client) {
if (client.setEncoding)
client.setEncoding("utf8");
client.on("data", function(data) {
// TODO add a way for sending message to one client
broadcast(data, client);
});
function cleanup(e) {
var i = clients.indexOf(client);
if (i != -1)
clients.splice(i, 1);
client.removeListener("end", cleanup);
client.removeListener("error", cleanup);
}
client.on("end", cleanup);
client.on("error", cleanup);
clients.push(client);
}
var clients = [];
var stream = new Stream();
stream.readable = true;
stream.writable = true;
stream.write = function(e) {
api.onData(e);
};
registerClient(stream);
api.onConnect({ write: function(e) {
stream.emit("data", e); }
});
var unixServer = net.createServer(registerClient);
unixServer.listen(SOCKET);
var socketDirExists = false;
unixServer.on("error", function(err) {
if (err.code == "EADDRINUSE") {
createListenClient(api);
}
else if (err.code == "EACCES" && !socketDirExists) {
vfs.mkdirP(path.dirname(SOCKET), {}, function() {
socketDirExists = true;
unixServer.listen(SOCKET);
});
}
else
api.onConnectError(err);
});
api.disconnect = function() {
unixServer.close();
};
}
register(null, {
connect: function (callback) {
if (stream) return callback(null, { stream: stream });
stream = new Stream();
stream.readable = true;
stream.writable = true;
stream.write = function(data) {
if (client) client.write(data);
};
var client;
var sent = false;
var api = this.api = {
id: Math.random(),
onConnect: function(c) {
client = c;
if (sent) return;
callback(null, { stream: stream });
sent = true;
},
onData: function(data) {
stream && stream.emit("data", data);
},
onConnectError: function(err) {
callback(err);
}
};
// createListenServer
createListenClient(api);
},
disconnect: function() {
try { this.api && this.api.disconnect(); }
catch (e) {}
stream = null;
delete this.api;
},
destroy: function() {
this.disconnect();
}
});
};